From 2a710b1372badaa64664685a5bf15d3a3bcc0f93 Mon Sep 17 00:00:00 2001 From: Stephanos Ioannidis Date: Wed, 22 Apr 2020 14:59:06 +0900 Subject: [PATCH] Revert "drivers: dma: sam0: fix DMA to peripheral transfer on SAMD5x" This reverts commit 90cc723e65c480459a20270993340cf221d94fcb. Using `DMAC_CHCTRLA_TRIGACT_BLOCK` breaks SERCOM UART peripheral DMA operations (DMA-based asynchronous UART transmit operation only sends the first byte and does not proceed any further). The `DMAC_CHCTRLA_TRIGACT_BURST` with `DMAC_CHCTRLA_BURSTLEN(0)` is a special case utilising the "internal FIFO", according to the datasheet (see DS60001507E; 22.6.2.8), and should always be specified for peripheral data transfer operations. Also it is worth noting that Atmel and other third-party drivers use the aforementioned "internal FIFO" configuration for peripheral data transfers as well. Signed-off-by: Stephanos Ioannidis --- drivers/dma/dma_sam0.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dma_sam0.c b/drivers/dma/dma_sam0.c index 643f94e91f9..3b4d3fc588d 100644 --- a/drivers/dma/dma_sam0.c +++ b/drivers/dma/dma_sam0.c @@ -151,7 +151,7 @@ static int dma_sam0_config(struct device *dev, u32_t channel, DMAC_CHCTRLA_TRIGSRC(config->dma_slot); } else { /* One peripheral trigger per beat */ - chcfg->CHCTRLA.reg = DMAC_CHCTRLA_TRIGACT_BLOCK | + chcfg->CHCTRLA.reg = DMAC_CHCTRLA_TRIGACT_BURST | DMAC_CHCTRLA_TRIGSRC(config->dma_slot); } @@ -163,6 +163,22 @@ static int dma_sam0_config(struct device *dev, u32_t channel, chcfg->CHPRILVL.bit.PRILVL = config->channel_priority; + /* Set the burst length */ + if (config->source_burst_length != config->dest_burst_length) { + LOG_ERR("Source and destination burst lengths must be equal"); + goto inval; + } + + if (config->source_burst_length > 16U) { + LOG_ERR("Invalid burst length"); + goto inval; + } + + if (config->source_burst_length > 0U) { + chcfg->CHCTRLA.reg |= DMAC_CHCTRLA_BURSTLEN( + config->source_burst_length - 1U); + } + /* Enable the interrupts */ chcfg->CHINTENSET.reg = DMAC_CHINTENSET_TCMPL; if (!config->error_callback_en) {