From ddf9bd4089b549ff7be3f4d0dbf19d4b9267d679 Mon Sep 17 00:00:00 2001 From: M'boumba Cedric Madianga Date: Tue, 13 Dec 2016 14:40:44 +0100 Subject: dmaengine: stm32-dma: Fix typo in Kconfig As STM32 DMA driver is only used as buit-in driver, it couldn't be used as module. Signed-off-by: M'boumba Cedric Madianga Reviewed-by: Ludovic BARRE Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 263495d0adbd..96da57aeaa4d 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -458,7 +458,7 @@ config STM32_DMA help Enable support for the on-chip DMA controller on STMicroelectronics STM32 MCUs. - If you have a board based on such a MCU and wish to use DMA say Y or M + If you have a board based on such a MCU and wish to use DMA say Y here. config S3C24XX_DMAC -- cgit v1.2.3 From 16545502d70641af0fc4d2cc0b2789cf27d9ca9d Mon Sep 17 00:00:00 2001 From: M'boumba Cedric Madianga Date: Tue, 13 Dec 2016 14:40:45 +0100 Subject: dt-bindings: stm32-dma: Fix typo regarding DMA client binding Only four cells are required for dma client binding not five. Signed-off-by: M'boumba Cedric Madianga Reviewed-by: Ludovic BARRE Acked-by: Rob Herring Signed-off-by: Vinod Koul --- Documentation/devicetree/bindings/dma/stm32-dma.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/dma/stm32-dma.txt b/Documentation/devicetree/bindings/dma/stm32-dma.txt index 70cd13f1588a..4408af693d0c 100644 --- a/Documentation/devicetree/bindings/dma/stm32-dma.txt +++ b/Documentation/devicetree/bindings/dma/stm32-dma.txt @@ -40,8 +40,7 @@ Example: DMA clients connected to the STM32 DMA controller must use the format described in the dma.txt file, using a five-cell specifier for each -channel: a phandle plus four integer cells. -The four cells in order are: +channel: a phandle to the DMA controller plus the following four integer cells: 1. The channel id 2. The request line number @@ -61,7 +60,7 @@ The four cells in order are: 0x1: medium 0x2: high 0x3: very high -5. A 32bit mask specifying the DMA FIFO threshold configuration which are device +4. A 32bit mask specifying the DMA FIFO threshold configuration which are device dependent: -bit 0-1: Fifo threshold 0x0: 1/4 full FIFO -- cgit v1.2.3 From 8d1b76f031ce60c50d03674e6d1db0c5e5f55945 Mon Sep 17 00:00:00 2001 From: M'boumba Cedric Madianga Date: Tue, 13 Dec 2016 14:40:47 +0100 Subject: dmaengine: stm32-dma: Rework starting transfer management This patch reworks the way to manage transfer starting. Now, starting DMA is only allowed when the channel is not busy. Then, stm32_dma_start_transfer is declared as void. At least, after each transfer completion, we start the next transfer if a new descriptor as been queued in the issued list during an ongoing transfer. Signed-off-by: M'boumba Cedric Madianga Reviewed-by: Ludovic BARRE Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 3688d0873a3e..a8c2ad686173 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -421,7 +421,7 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr); } -static int stm32_dma_start_transfer(struct stm32_dma_chan *chan) +static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) { struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); struct virt_dma_desc *vdesc; @@ -432,12 +432,12 @@ static int stm32_dma_start_transfer(struct stm32_dma_chan *chan) ret = stm32_dma_disable_chan(chan); if (ret < 0) - return ret; + return; if (!chan->desc) { vdesc = vchan_next_desc(&chan->vchan); if (!vdesc) - return -EPERM; + return; chan->desc = to_stm32_dma_desc(vdesc); chan->next_sg = 0; @@ -471,7 +471,7 @@ static int stm32_dma_start_transfer(struct stm32_dma_chan *chan) chan->busy = true; - return 0; + dev_dbg(chan2dev(chan), "vchan %p: started\n", &chan->vchan); } static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) @@ -552,15 +552,13 @@ static void stm32_dma_issue_pending(struct dma_chan *c) { struct stm32_dma_chan *chan = to_stm32_dma_chan(c); unsigned long flags; - int ret; spin_lock_irqsave(&chan->vchan.lock, flags); - if (!chan->busy) { - if (vchan_issue_pending(&chan->vchan) && !chan->desc) { - ret = stm32_dma_start_transfer(chan); - if ((!ret) && (chan->desc->cyclic)) - stm32_dma_configure_next_sg(chan); - } + if (vchan_issue_pending(&chan->vchan) && !chan->desc && !chan->busy) { + dev_dbg(chan2dev(chan), "vchan %p: issued\n", &chan->vchan); + stm32_dma_start_transfer(chan); + if (chan->desc->cyclic) + stm32_dma_configure_next_sg(chan); } spin_unlock_irqrestore(&chan->vchan.lock, flags); } -- cgit v1.2.3 From 2b12c5580e0a4c0ffd513d1522dd39b2464fb207 Mon Sep 17 00:00:00 2001 From: M'boumba Cedric Madianga Date: Tue, 13 Dec 2016 14:40:48 +0100 Subject: dmaengine: stm32-dma: Fix residue computation issue in cyclic mode This patch resolves the residue computation issue detected in cyclic mode. Now, in cyclic mode, we increment next_sg variable as soon as a period is transferred instead of after pushing a new sg request. Then, we take into account that after transferring a complete buffer, the next_sg variable is equal to 0. Signed-off-by: M'boumba Cedric Madianga Reviewed-by: Ludovic BARRE Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index a8c2ad686173..8a29b028d39e 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -500,8 +500,6 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n", stm32_dma_read(dmadev, STM32_DMA_SM1AR(id))); } - - chan->next_sg++; } } @@ -510,6 +508,7 @@ static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan) if (chan->desc) { if (chan->desc->cyclic) { vchan_cyclic_callback(&chan->desc->vdesc); + chan->next_sg++; stm32_dma_configure_next_sg(chan); } else { chan->busy = false; @@ -846,26 +845,40 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy( return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); } +static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan) +{ + u32 dma_scr, width, ndtr; + struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); + + dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); + width = STM32_DMA_SCR_PSIZE_GET(dma_scr); + ndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id)); + + return ndtr << width; +} + static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, struct stm32_dma_desc *desc, u32 next_sg) { - struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); - u32 dma_scr, width, residue, count; + u32 residue = 0; int i; - residue = 0; + /* + * In cyclic mode, for the last period, residue = remaining bytes from + * NDTR + */ + if (chan->desc->cyclic && next_sg == 0) + return stm32_dma_get_remaining_bytes(chan); + /* + * For all other periods in cyclic mode, and in sg mode, + * residue = remaining bytes from NDTR + remaining periods/sg to be + * transferred + */ for (i = next_sg; i < desc->num_sgs; i++) residue += desc->sg_req[i].len; - - if (next_sg != 0) { - dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); - width = STM32_DMA_SCR_PSIZE_GET(dma_scr); - count = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id)); - - residue += count << width; - } + residue += stm32_dma_get_remaining_bytes(chan); return residue; } -- cgit v1.2.3 From dc808675104b920f2be1ac4bf1e9aa57680f0699 Mon Sep 17 00:00:00 2001 From: M'boumba Cedric Madianga Date: Tue, 13 Dec 2016 14:40:50 +0100 Subject: dmaengine: stm32-dma: Add synchronization support Implement the new device_synchronize() callback to allow proper synchronization when stopping a channel. Signed-off-by: M'boumba Cedric Madianga Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 8a29b028d39e..53b2ee79cc0e 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -403,6 +403,13 @@ static int stm32_dma_terminate_all(struct dma_chan *c) return 0; } +static void stm32_dma_synchronize(struct dma_chan *c) +{ + struct stm32_dma_chan *chan = to_stm32_dma_chan(c); + + vchan_synchronize(&chan->vchan); +} + static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) { struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); @@ -1066,6 +1073,7 @@ static int stm32_dma_probe(struct platform_device *pdev) dd->device_prep_dma_cyclic = stm32_dma_prep_dma_cyclic; dd->device_config = stm32_dma_slave_config; dd->device_terminate_all = stm32_dma_terminate_all; + dd->device_synchronize = stm32_dma_synchronize; dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); -- cgit v1.2.3 From 276b0046ff7765c1d42ed48c67b4b5f3b50ea461 Mon Sep 17 00:00:00 2001 From: M'boumba Cedric Madianga Date: Tue, 13 Dec 2016 14:40:51 +0100 Subject: dmaengine: stm32-dma: Add max_burst support This patch sets the max_burst value supported by the STM32 DMA Signed-off-by: M'boumba Cedric Madianga Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index 53b2ee79cc0e..fc9738e0f3a3 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -114,6 +114,7 @@ #define STM32_DMA_MAX_CHANNELS 0x08 #define STM32_DMA_MAX_REQUEST_ID 0x08 #define STM32_DMA_MAX_DATA_PARAM 0x03 +#define STM32_DMA_MAX_BURST 16 enum stm32_dma_width { STM32_DMA_BYTE, @@ -1082,6 +1083,7 @@ static int stm32_dma_probe(struct platform_device *pdev) BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; + dd->max_burst = STM32_DMA_MAX_BURST; dd->dev = &pdev->dev; INIT_LIST_HEAD(&dd->channels); -- cgit v1.2.3 From 5df4eb453cbdad34ea55c0ce984a376b33442aa1 Mon Sep 17 00:00:00 2001 From: M'boumba Cedric Madianga Date: Thu, 5 Jan 2017 09:09:40 +0100 Subject: dmaengine: stm32-dma: Add error messages if xlate fails This patch adds some error messages when a slave device fails to request a channel. Signed-off-by: M'boumba Cedric Madianga Reviewed-by: Ludovic BARRE Signed-off-by: Vinod Koul --- drivers/dma/stm32-dma.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/dma/stm32-dma.c b/drivers/dma/stm32-dma.c index fc9738e0f3a3..4eacd9dd5710 100644 --- a/drivers/dma/stm32-dma.c +++ b/drivers/dma/stm32-dma.c @@ -987,30 +987,36 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec, struct of_dma *ofdma) { struct stm32_dma_device *dmadev = ofdma->of_dma_data; + struct device *dev = dmadev->ddev.dev; struct stm32_dma_cfg cfg; struct stm32_dma_chan *chan; struct dma_chan *c; - if (dma_spec->args_count < 3) + if (dma_spec->args_count < 4) { + dev_err(dev, "Bad number of cells\n"); return NULL; + } cfg.channel_id = dma_spec->args[0]; cfg.request_line = dma_spec->args[1]; cfg.stream_config = dma_spec->args[2]; - cfg.threshold = 0; + cfg.threshold = dma_spec->args[3]; - if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >= - STM32_DMA_MAX_REQUEST_ID)) + if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || + (cfg.request_line >= STM32_DMA_MAX_REQUEST_ID)) { + dev_err(dev, "Bad channel and/or request id\n"); return NULL; - - if (dma_spec->args_count > 3) - cfg.threshold = dma_spec->args[3]; + } chan = &dmadev->chan[cfg.channel_id]; c = dma_get_slave_channel(&chan->vchan.chan); - if (c) - stm32_dma_set_config(chan, &cfg); + if (!c) { + dev_err(dev, "No more channel avalaible\n"); + return NULL; + } + + stm32_dma_set_config(chan, &cfg); return c; } -- cgit v1.2.3