1d8b46839SM'boumba Cedric Madianga /* 2d8b46839SM'boumba Cedric Madianga * Driver for STM32 DMA controller 3d8b46839SM'boumba Cedric Madianga * 4d8b46839SM'boumba Cedric Madianga * Inspired by dma-jz4740.c and tegra20-apb-dma.c 5d8b46839SM'boumba Cedric Madianga * 6d8b46839SM'boumba Cedric Madianga * Copyright (C) M'boumba Cedric Madianga 2015 7d8b46839SM'boumba Cedric Madianga * Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com> 8d8b46839SM'boumba Cedric Madianga * 9d8b46839SM'boumba Cedric Madianga * License terms: GNU General Public License (GPL), version 2 10d8b46839SM'boumba Cedric Madianga */ 11d8b46839SM'boumba Cedric Madianga 12d8b46839SM'boumba Cedric Madianga #include <linux/clk.h> 13d8b46839SM'boumba Cedric Madianga #include <linux/delay.h> 14d8b46839SM'boumba Cedric Madianga #include <linux/dmaengine.h> 15d8b46839SM'boumba Cedric Madianga #include <linux/dma-mapping.h> 16d8b46839SM'boumba Cedric Madianga #include <linux/err.h> 17d8b46839SM'boumba Cedric Madianga #include <linux/init.h> 18d8b46839SM'boumba Cedric Madianga #include <linux/jiffies.h> 19d8b46839SM'boumba Cedric Madianga #include <linux/list.h> 20d8b46839SM'boumba Cedric Madianga #include <linux/module.h> 21d8b46839SM'boumba Cedric Madianga #include <linux/of.h> 22d8b46839SM'boumba Cedric Madianga #include <linux/of_device.h> 23d8b46839SM'boumba Cedric Madianga #include <linux/of_dma.h> 24d8b46839SM'boumba Cedric Madianga #include <linux/platform_device.h> 25d8b46839SM'boumba Cedric Madianga #include <linux/reset.h> 26d8b46839SM'boumba Cedric Madianga #include <linux/sched.h> 27d8b46839SM'boumba Cedric Madianga #include <linux/slab.h> 28d8b46839SM'boumba Cedric Madianga 29d8b46839SM'boumba Cedric Madianga #include "virt-dma.h" 30d8b46839SM'boumba Cedric Madianga 31d8b46839SM'boumba Cedric Madianga #define STM32_DMA_LISR 0x0000 /* DMA Low Int Status Reg */ 32d8b46839SM'boumba Cedric Madianga #define STM32_DMA_HISR 0x0004 /* DMA High Int Status Reg */ 33d8b46839SM'boumba Cedric Madianga #define STM32_DMA_LIFCR 0x0008 /* DMA Low Int Flag Clear Reg */ 34d8b46839SM'boumba Cedric Madianga #define STM32_DMA_HIFCR 0x000c /* DMA High Int Flag Clear Reg */ 35d8b46839SM'boumba Cedric Madianga #define STM32_DMA_TCI BIT(5) /* Transfer Complete Interrupt */ 36d8b46839SM'boumba Cedric Madianga #define STM32_DMA_TEI BIT(3) /* Transfer Error Interrupt */ 37d8b46839SM'boumba Cedric Madianga #define STM32_DMA_DMEI BIT(2) /* Direct Mode Error Interrupt */ 38d8b46839SM'boumba Cedric Madianga #define STM32_DMA_FEI BIT(0) /* FIFO Error Interrupt */ 39d8b46839SM'boumba Cedric Madianga 40d8b46839SM'boumba Cedric Madianga /* DMA Stream x Configuration Register */ 41d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR(x) (0x0010 + 0x18 * (x)) /* x = 0..7 */ 42d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_REQ(n) ((n & 0x7) << 25) 43d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_MBURST_MASK GENMASK(24, 23) 44d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_MBURST(n) ((n & 0x3) << 23) 45d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PBURST_MASK GENMASK(22, 21) 46d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PBURST(n) ((n & 0x3) << 21) 47d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PL_MASK GENMASK(17, 16) 48d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PL(n) ((n & 0x3) << 16) 49d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_MSIZE_MASK GENMASK(14, 13) 50d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_MSIZE(n) ((n & 0x3) << 13) 51d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PSIZE_MASK GENMASK(12, 11) 52d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PSIZE(n) ((n & 0x3) << 11) 53d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PSIZE_GET(n) ((n & STM32_DMA_SCR_PSIZE_MASK) >> 11) 54d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_DIR_MASK GENMASK(7, 6) 55d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_DIR(n) ((n & 0x3) << 6) 56d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_CT BIT(19) /* Target in double buffer */ 57d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_DBM BIT(18) /* Double Buffer Mode */ 58d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PINCOS BIT(15) /* Peripheral inc offset size */ 59d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_MINC BIT(10) /* Memory increment mode */ 60d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PINC BIT(9) /* Peripheral increment mode */ 61d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_CIRC BIT(8) /* Circular mode */ 62d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_PFCTRL BIT(5) /* Peripheral Flow Controller */ 63d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_TCIE BIT(4) /* Transfer Cplete Int Enable*/ 64d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_TEIE BIT(2) /* Transfer Error Int Enable */ 65d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_DMEIE BIT(1) /* Direct Mode Err Int Enable */ 66d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_EN BIT(0) /* Stream Enable */ 67d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_CFG_MASK (STM32_DMA_SCR_PINC \ 68d8b46839SM'boumba Cedric Madianga | STM32_DMA_SCR_MINC \ 69d8b46839SM'boumba Cedric Madianga | STM32_DMA_SCR_PINCOS \ 70d8b46839SM'boumba Cedric Madianga | STM32_DMA_SCR_PL_MASK) 71d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SCR_IRQ_MASK (STM32_DMA_SCR_TCIE \ 72d8b46839SM'boumba Cedric Madianga | STM32_DMA_SCR_TEIE \ 73d8b46839SM'boumba Cedric Madianga | STM32_DMA_SCR_DMEIE) 74d8b46839SM'boumba Cedric Madianga 75d8b46839SM'boumba Cedric Madianga /* DMA Stream x number of data register */ 76d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SNDTR(x) (0x0014 + 0x18 * (x)) 77d8b46839SM'boumba Cedric Madianga 78d8b46839SM'boumba Cedric Madianga /* DMA stream peripheral address register */ 79d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SPAR(x) (0x0018 + 0x18 * (x)) 80d8b46839SM'boumba Cedric Madianga 81d8b46839SM'boumba Cedric Madianga /* DMA stream x memory 0 address register */ 82d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SM0AR(x) (0x001c + 0x18 * (x)) 83d8b46839SM'boumba Cedric Madianga 84d8b46839SM'boumba Cedric Madianga /* DMA stream x memory 1 address register */ 85d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SM1AR(x) (0x0020 + 0x18 * (x)) 86d8b46839SM'boumba Cedric Madianga 87d8b46839SM'boumba Cedric Madianga /* DMA stream x FIFO control register */ 88d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SFCR(x) (0x0024 + 0x18 * (x)) 89d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SFCR_FTH_MASK GENMASK(1, 0) 90d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SFCR_FTH(n) (n & STM32_DMA_SFCR_FTH_MASK) 91d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SFCR_FEIE BIT(7) /* FIFO error interrupt enable */ 92d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SFCR_DMDIS BIT(2) /* Direct mode disable */ 93d8b46839SM'boumba Cedric Madianga #define STM32_DMA_SFCR_MASK (STM32_DMA_SFCR_FEIE \ 94d8b46839SM'boumba Cedric Madianga | STM32_DMA_SFCR_DMDIS) 95d8b46839SM'boumba Cedric Madianga 96d8b46839SM'boumba Cedric Madianga /* DMA direction */ 97d8b46839SM'boumba Cedric Madianga #define STM32_DMA_DEV_TO_MEM 0x00 98d8b46839SM'boumba Cedric Madianga #define STM32_DMA_MEM_TO_DEV 0x01 99d8b46839SM'boumba Cedric Madianga #define STM32_DMA_MEM_TO_MEM 0x02 100d8b46839SM'boumba Cedric Madianga 101d8b46839SM'boumba Cedric Madianga /* DMA priority level */ 102d8b46839SM'boumba Cedric Madianga #define STM32_DMA_PRIORITY_LOW 0x00 103d8b46839SM'boumba Cedric Madianga #define STM32_DMA_PRIORITY_MEDIUM 0x01 104d8b46839SM'boumba Cedric Madianga #define STM32_DMA_PRIORITY_HIGH 0x02 105d8b46839SM'boumba Cedric Madianga #define STM32_DMA_PRIORITY_VERY_HIGH 0x03 106d8b46839SM'boumba Cedric Madianga 107d8b46839SM'boumba Cedric Madianga /* DMA FIFO threshold selection */ 108d8b46839SM'boumba Cedric Madianga #define STM32_DMA_FIFO_THRESHOLD_1QUARTERFULL 0x00 109d8b46839SM'boumba Cedric Madianga #define STM32_DMA_FIFO_THRESHOLD_HALFFULL 0x01 110d8b46839SM'boumba Cedric Madianga #define STM32_DMA_FIFO_THRESHOLD_3QUARTERSFULL 0x02 111d8b46839SM'boumba Cedric Madianga #define STM32_DMA_FIFO_THRESHOLD_FULL 0x03 112d8b46839SM'boumba Cedric Madianga 113d8b46839SM'boumba Cedric Madianga #define STM32_DMA_MAX_DATA_ITEMS 0xffff 114d8b46839SM'boumba Cedric Madianga #define STM32_DMA_MAX_CHANNELS 0x08 115d8b46839SM'boumba Cedric Madianga #define STM32_DMA_MAX_REQUEST_ID 0x08 116d8b46839SM'boumba Cedric Madianga #define STM32_DMA_MAX_DATA_PARAM 0x03 117d8b46839SM'boumba Cedric Madianga 118d8b46839SM'boumba Cedric Madianga enum stm32_dma_width { 119d8b46839SM'boumba Cedric Madianga STM32_DMA_BYTE, 120d8b46839SM'boumba Cedric Madianga STM32_DMA_HALF_WORD, 121d8b46839SM'boumba Cedric Madianga STM32_DMA_WORD, 122d8b46839SM'boumba Cedric Madianga }; 123d8b46839SM'boumba Cedric Madianga 124d8b46839SM'boumba Cedric Madianga enum stm32_dma_burst_size { 125d8b46839SM'boumba Cedric Madianga STM32_DMA_BURST_SINGLE, 126d8b46839SM'boumba Cedric Madianga STM32_DMA_BURST_INCR4, 127d8b46839SM'boumba Cedric Madianga STM32_DMA_BURST_INCR8, 128d8b46839SM'boumba Cedric Madianga STM32_DMA_BURST_INCR16, 129d8b46839SM'boumba Cedric Madianga }; 130d8b46839SM'boumba Cedric Madianga 131d8b46839SM'boumba Cedric Madianga struct stm32_dma_cfg { 132d8b46839SM'boumba Cedric Madianga u32 channel_id; 133d8b46839SM'boumba Cedric Madianga u32 request_line; 134d8b46839SM'boumba Cedric Madianga u32 stream_config; 135d8b46839SM'boumba Cedric Madianga u32 threshold; 136d8b46839SM'boumba Cedric Madianga }; 137d8b46839SM'boumba Cedric Madianga 138d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan_reg { 139d8b46839SM'boumba Cedric Madianga u32 dma_lisr; 140d8b46839SM'boumba Cedric Madianga u32 dma_hisr; 141d8b46839SM'boumba Cedric Madianga u32 dma_lifcr; 142d8b46839SM'boumba Cedric Madianga u32 dma_hifcr; 143d8b46839SM'boumba Cedric Madianga u32 dma_scr; 144d8b46839SM'boumba Cedric Madianga u32 dma_sndtr; 145d8b46839SM'boumba Cedric Madianga u32 dma_spar; 146d8b46839SM'boumba Cedric Madianga u32 dma_sm0ar; 147d8b46839SM'boumba Cedric Madianga u32 dma_sm1ar; 148d8b46839SM'boumba Cedric Madianga u32 dma_sfcr; 149d8b46839SM'boumba Cedric Madianga }; 150d8b46839SM'boumba Cedric Madianga 151d8b46839SM'boumba Cedric Madianga struct stm32_dma_sg_req { 152d8b46839SM'boumba Cedric Madianga u32 len; 153d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan_reg chan_reg; 154d8b46839SM'boumba Cedric Madianga }; 155d8b46839SM'boumba Cedric Madianga 156d8b46839SM'boumba Cedric Madianga struct stm32_dma_desc { 157d8b46839SM'boumba Cedric Madianga struct virt_dma_desc vdesc; 158d8b46839SM'boumba Cedric Madianga bool cyclic; 159d8b46839SM'boumba Cedric Madianga u32 num_sgs; 160d8b46839SM'boumba Cedric Madianga struct stm32_dma_sg_req sg_req[]; 161d8b46839SM'boumba Cedric Madianga }; 162d8b46839SM'boumba Cedric Madianga 163d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan { 164d8b46839SM'boumba Cedric Madianga struct virt_dma_chan vchan; 165d8b46839SM'boumba Cedric Madianga bool config_init; 166d8b46839SM'boumba Cedric Madianga bool busy; 167d8b46839SM'boumba Cedric Madianga u32 id; 168d8b46839SM'boumba Cedric Madianga u32 irq; 169d8b46839SM'boumba Cedric Madianga struct stm32_dma_desc *desc; 170d8b46839SM'boumba Cedric Madianga u32 next_sg; 171d8b46839SM'boumba Cedric Madianga struct dma_slave_config dma_sconfig; 172d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan_reg chan_reg; 173d8b46839SM'boumba Cedric Madianga }; 174d8b46839SM'boumba Cedric Madianga 175d8b46839SM'boumba Cedric Madianga struct stm32_dma_device { 176d8b46839SM'boumba Cedric Madianga struct dma_device ddev; 177d8b46839SM'boumba Cedric Madianga void __iomem *base; 178d8b46839SM'boumba Cedric Madianga struct clk *clk; 179d8b46839SM'boumba Cedric Madianga struct reset_control *rst; 180d8b46839SM'boumba Cedric Madianga bool mem2mem; 181d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan chan[STM32_DMA_MAX_CHANNELS]; 182d8b46839SM'boumba Cedric Madianga }; 183d8b46839SM'boumba Cedric Madianga 184d8b46839SM'boumba Cedric Madianga static struct stm32_dma_device *stm32_dma_get_dev(struct stm32_dma_chan *chan) 185d8b46839SM'boumba Cedric Madianga { 186d8b46839SM'boumba Cedric Madianga return container_of(chan->vchan.chan.device, struct stm32_dma_device, 187d8b46839SM'boumba Cedric Madianga ddev); 188d8b46839SM'boumba Cedric Madianga } 189d8b46839SM'boumba Cedric Madianga 190d8b46839SM'boumba Cedric Madianga static struct stm32_dma_chan *to_stm32_dma_chan(struct dma_chan *c) 191d8b46839SM'boumba Cedric Madianga { 192d8b46839SM'boumba Cedric Madianga return container_of(c, struct stm32_dma_chan, vchan.chan); 193d8b46839SM'boumba Cedric Madianga } 194d8b46839SM'boumba Cedric Madianga 195d8b46839SM'boumba Cedric Madianga static struct stm32_dma_desc *to_stm32_dma_desc(struct virt_dma_desc *vdesc) 196d8b46839SM'boumba Cedric Madianga { 197d8b46839SM'boumba Cedric Madianga return container_of(vdesc, struct stm32_dma_desc, vdesc); 198d8b46839SM'boumba Cedric Madianga } 199d8b46839SM'boumba Cedric Madianga 200d8b46839SM'boumba Cedric Madianga static struct device *chan2dev(struct stm32_dma_chan *chan) 201d8b46839SM'boumba Cedric Madianga { 202d8b46839SM'boumba Cedric Madianga return &chan->vchan.chan.dev->device; 203d8b46839SM'boumba Cedric Madianga } 204d8b46839SM'boumba Cedric Madianga 205d8b46839SM'boumba Cedric Madianga static u32 stm32_dma_read(struct stm32_dma_device *dmadev, u32 reg) 206d8b46839SM'boumba Cedric Madianga { 207d8b46839SM'boumba Cedric Madianga return readl_relaxed(dmadev->base + reg); 208d8b46839SM'boumba Cedric Madianga } 209d8b46839SM'boumba Cedric Madianga 210d8b46839SM'boumba Cedric Madianga static void stm32_dma_write(struct stm32_dma_device *dmadev, u32 reg, u32 val) 211d8b46839SM'boumba Cedric Madianga { 212d8b46839SM'boumba Cedric Madianga writel_relaxed(val, dmadev->base + reg); 213d8b46839SM'boumba Cedric Madianga } 214d8b46839SM'boumba Cedric Madianga 215d8b46839SM'boumba Cedric Madianga static struct stm32_dma_desc *stm32_dma_alloc_desc(u32 num_sgs) 216d8b46839SM'boumba Cedric Madianga { 217d8b46839SM'boumba Cedric Madianga return kzalloc(sizeof(struct stm32_dma_desc) + 218d8b46839SM'boumba Cedric Madianga sizeof(struct stm32_dma_sg_req) * num_sgs, GFP_NOWAIT); 219d8b46839SM'boumba Cedric Madianga } 220d8b46839SM'boumba Cedric Madianga 221d8b46839SM'boumba Cedric Madianga static int stm32_dma_get_width(struct stm32_dma_chan *chan, 222d8b46839SM'boumba Cedric Madianga enum dma_slave_buswidth width) 223d8b46839SM'boumba Cedric Madianga { 224d8b46839SM'boumba Cedric Madianga switch (width) { 225d8b46839SM'boumba Cedric Madianga case DMA_SLAVE_BUSWIDTH_1_BYTE: 226d8b46839SM'boumba Cedric Madianga return STM32_DMA_BYTE; 227d8b46839SM'boumba Cedric Madianga case DMA_SLAVE_BUSWIDTH_2_BYTES: 228d8b46839SM'boumba Cedric Madianga return STM32_DMA_HALF_WORD; 229d8b46839SM'boumba Cedric Madianga case DMA_SLAVE_BUSWIDTH_4_BYTES: 230d8b46839SM'boumba Cedric Madianga return STM32_DMA_WORD; 231d8b46839SM'boumba Cedric Madianga default: 232d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "Dma bus width not supported\n"); 233d8b46839SM'boumba Cedric Madianga return -EINVAL; 234d8b46839SM'boumba Cedric Madianga } 235d8b46839SM'boumba Cedric Madianga } 236d8b46839SM'boumba Cedric Madianga 237d8b46839SM'boumba Cedric Madianga static int stm32_dma_get_burst(struct stm32_dma_chan *chan, u32 maxburst) 238d8b46839SM'boumba Cedric Madianga { 239d8b46839SM'boumba Cedric Madianga switch (maxburst) { 240d8b46839SM'boumba Cedric Madianga case 0: 241d8b46839SM'boumba Cedric Madianga case 1: 242d8b46839SM'boumba Cedric Madianga return STM32_DMA_BURST_SINGLE; 243d8b46839SM'boumba Cedric Madianga case 4: 244d8b46839SM'boumba Cedric Madianga return STM32_DMA_BURST_INCR4; 245d8b46839SM'boumba Cedric Madianga case 8: 246d8b46839SM'boumba Cedric Madianga return STM32_DMA_BURST_INCR8; 247d8b46839SM'boumba Cedric Madianga case 16: 248d8b46839SM'boumba Cedric Madianga return STM32_DMA_BURST_INCR16; 249d8b46839SM'boumba Cedric Madianga default: 250d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "Dma burst size not supported\n"); 251d8b46839SM'boumba Cedric Madianga return -EINVAL; 252d8b46839SM'boumba Cedric Madianga } 253d8b46839SM'boumba Cedric Madianga } 254d8b46839SM'boumba Cedric Madianga 255d8b46839SM'boumba Cedric Madianga static void stm32_dma_set_fifo_config(struct stm32_dma_chan *chan, 256d8b46839SM'boumba Cedric Madianga u32 src_maxburst, u32 dst_maxburst) 257d8b46839SM'boumba Cedric Madianga { 258d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_sfcr &= ~STM32_DMA_SFCR_MASK; 259d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_DMEIE; 260d8b46839SM'boumba Cedric Madianga 261d8b46839SM'boumba Cedric Madianga if ((!src_maxburst) && (!dst_maxburst)) { 262d8b46839SM'boumba Cedric Madianga /* Using direct mode */ 263d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr |= STM32_DMA_SCR_DMEIE; 264d8b46839SM'boumba Cedric Madianga } else { 265d8b46839SM'boumba Cedric Madianga /* Using FIFO mode */ 266d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_sfcr |= STM32_DMA_SFCR_MASK; 267d8b46839SM'boumba Cedric Madianga } 268d8b46839SM'boumba Cedric Madianga } 269d8b46839SM'boumba Cedric Madianga 270d8b46839SM'boumba Cedric Madianga static int stm32_dma_slave_config(struct dma_chan *c, 271d8b46839SM'boumba Cedric Madianga struct dma_slave_config *config) 272d8b46839SM'boumba Cedric Madianga { 273d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 274d8b46839SM'boumba Cedric Madianga 275d8b46839SM'boumba Cedric Madianga memcpy(&chan->dma_sconfig, config, sizeof(*config)); 276d8b46839SM'boumba Cedric Madianga 277d8b46839SM'boumba Cedric Madianga chan->config_init = true; 278d8b46839SM'boumba Cedric Madianga 279d8b46839SM'boumba Cedric Madianga return 0; 280d8b46839SM'boumba Cedric Madianga } 281d8b46839SM'boumba Cedric Madianga 282d8b46839SM'boumba Cedric Madianga static u32 stm32_dma_irq_status(struct stm32_dma_chan *chan) 283d8b46839SM'boumba Cedric Madianga { 284d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 285d8b46839SM'boumba Cedric Madianga u32 flags, dma_isr; 286d8b46839SM'boumba Cedric Madianga 287d8b46839SM'boumba Cedric Madianga /* 288d8b46839SM'boumba Cedric Madianga * Read "flags" from DMA_xISR register corresponding to the selected 289d8b46839SM'boumba Cedric Madianga * DMA channel at the correct bit offset inside that register. 290d8b46839SM'boumba Cedric Madianga * 291d8b46839SM'boumba Cedric Madianga * If (ch % 4) is 2 or 3, left shift the mask by 16 bits. 292d8b46839SM'boumba Cedric Madianga * If (ch % 4) is 1 or 3, additionally left shift the mask by 6 bits. 293d8b46839SM'boumba Cedric Madianga */ 294d8b46839SM'boumba Cedric Madianga 295d8b46839SM'boumba Cedric Madianga if (chan->id & 4) 296d8b46839SM'boumba Cedric Madianga dma_isr = stm32_dma_read(dmadev, STM32_DMA_HISR); 297d8b46839SM'boumba Cedric Madianga else 298d8b46839SM'boumba Cedric Madianga dma_isr = stm32_dma_read(dmadev, STM32_DMA_LISR); 299d8b46839SM'boumba Cedric Madianga 300d8b46839SM'boumba Cedric Madianga flags = dma_isr >> (((chan->id & 2) << 3) | ((chan->id & 1) * 6)); 301d8b46839SM'boumba Cedric Madianga 302d8b46839SM'boumba Cedric Madianga return flags; 303d8b46839SM'boumba Cedric Madianga } 304d8b46839SM'boumba Cedric Madianga 305d8b46839SM'boumba Cedric Madianga static void stm32_dma_irq_clear(struct stm32_dma_chan *chan, u32 flags) 306d8b46839SM'boumba Cedric Madianga { 307d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 308d8b46839SM'boumba Cedric Madianga u32 dma_ifcr; 309d8b46839SM'boumba Cedric Madianga 310d8b46839SM'boumba Cedric Madianga /* 311d8b46839SM'boumba Cedric Madianga * Write "flags" to the DMA_xIFCR register corresponding to the selected 312d8b46839SM'boumba Cedric Madianga * DMA channel at the correct bit offset inside that register. 313d8b46839SM'boumba Cedric Madianga * 314d8b46839SM'boumba Cedric Madianga * If (ch % 4) is 2 or 3, left shift the mask by 16 bits. 315d8b46839SM'boumba Cedric Madianga * If (ch % 4) is 1 or 3, additionally left shift the mask by 6 bits. 316d8b46839SM'boumba Cedric Madianga */ 317d8b46839SM'boumba Cedric Madianga dma_ifcr = flags << (((chan->id & 2) << 3) | ((chan->id & 1) * 6)); 318d8b46839SM'boumba Cedric Madianga 319d8b46839SM'boumba Cedric Madianga if (chan->id & 4) 320d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_HIFCR, dma_ifcr); 321d8b46839SM'boumba Cedric Madianga else 322d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_LIFCR, dma_ifcr); 323d8b46839SM'boumba Cedric Madianga } 324d8b46839SM'boumba Cedric Madianga 325d8b46839SM'boumba Cedric Madianga static int stm32_dma_disable_chan(struct stm32_dma_chan *chan) 326d8b46839SM'boumba Cedric Madianga { 327d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 328d8b46839SM'boumba Cedric Madianga unsigned long timeout = jiffies + msecs_to_jiffies(5000); 329d8b46839SM'boumba Cedric Madianga u32 dma_scr, id; 330d8b46839SM'boumba Cedric Madianga 331d8b46839SM'boumba Cedric Madianga id = chan->id; 332d8b46839SM'boumba Cedric Madianga dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); 333d8b46839SM'boumba Cedric Madianga 334d8b46839SM'boumba Cedric Madianga if (dma_scr & STM32_DMA_SCR_EN) { 335d8b46839SM'boumba Cedric Madianga dma_scr &= ~STM32_DMA_SCR_EN; 336d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SCR(id), dma_scr); 337d8b46839SM'boumba Cedric Madianga 338d8b46839SM'boumba Cedric Madianga do { 339d8b46839SM'boumba Cedric Madianga dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); 340d8b46839SM'boumba Cedric Madianga dma_scr &= STM32_DMA_SCR_EN; 341d8b46839SM'boumba Cedric Madianga if (!dma_scr) 342d8b46839SM'boumba Cedric Madianga break; 343d8b46839SM'boumba Cedric Madianga 344d8b46839SM'boumba Cedric Madianga if (time_after_eq(jiffies, timeout)) { 345d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "%s: timeout!\n", 346d8b46839SM'boumba Cedric Madianga __func__); 347d8b46839SM'boumba Cedric Madianga return -EBUSY; 348d8b46839SM'boumba Cedric Madianga } 349d8b46839SM'boumba Cedric Madianga cond_resched(); 350d8b46839SM'boumba Cedric Madianga } while (1); 351d8b46839SM'boumba Cedric Madianga } 352d8b46839SM'boumba Cedric Madianga 353d8b46839SM'boumba Cedric Madianga return 0; 354d8b46839SM'boumba Cedric Madianga } 355d8b46839SM'boumba Cedric Madianga 356d8b46839SM'boumba Cedric Madianga static void stm32_dma_stop(struct stm32_dma_chan *chan) 357d8b46839SM'boumba Cedric Madianga { 358d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 359d8b46839SM'boumba Cedric Madianga u32 dma_scr, dma_sfcr, status; 360d8b46839SM'boumba Cedric Madianga int ret; 361d8b46839SM'boumba Cedric Madianga 362d8b46839SM'boumba Cedric Madianga /* Disable interrupts */ 363d8b46839SM'boumba Cedric Madianga dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); 364d8b46839SM'boumba Cedric Madianga dma_scr &= ~STM32_DMA_SCR_IRQ_MASK; 365d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), dma_scr); 366d8b46839SM'boumba Cedric Madianga dma_sfcr = stm32_dma_read(dmadev, STM32_DMA_SFCR(chan->id)); 367d8b46839SM'boumba Cedric Madianga dma_sfcr &= ~STM32_DMA_SFCR_FEIE; 368d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SFCR(chan->id), dma_sfcr); 369d8b46839SM'boumba Cedric Madianga 370d8b46839SM'boumba Cedric Madianga /* Disable DMA */ 371d8b46839SM'boumba Cedric Madianga ret = stm32_dma_disable_chan(chan); 372d8b46839SM'boumba Cedric Madianga if (ret < 0) 373d8b46839SM'boumba Cedric Madianga return; 374d8b46839SM'boumba Cedric Madianga 375d8b46839SM'boumba Cedric Madianga /* Clear interrupt status if it is there */ 376d8b46839SM'boumba Cedric Madianga status = stm32_dma_irq_status(chan); 377d8b46839SM'boumba Cedric Madianga if (status) { 378d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "%s(): clearing interrupt: 0x%08x\n", 379d8b46839SM'boumba Cedric Madianga __func__, status); 380d8b46839SM'boumba Cedric Madianga stm32_dma_irq_clear(chan, status); 381d8b46839SM'boumba Cedric Madianga } 382d8b46839SM'boumba Cedric Madianga 383d8b46839SM'boumba Cedric Madianga chan->busy = false; 384d8b46839SM'boumba Cedric Madianga } 385d8b46839SM'boumba Cedric Madianga 386d8b46839SM'boumba Cedric Madianga static int stm32_dma_terminate_all(struct dma_chan *c) 387d8b46839SM'boumba Cedric Madianga { 388d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 389d8b46839SM'boumba Cedric Madianga unsigned long flags; 390d8b46839SM'boumba Cedric Madianga LIST_HEAD(head); 391d8b46839SM'boumba Cedric Madianga 392d8b46839SM'boumba Cedric Madianga spin_lock_irqsave(&chan->vchan.lock, flags); 393d8b46839SM'boumba Cedric Madianga 394d8b46839SM'boumba Cedric Madianga if (chan->busy) { 395d8b46839SM'boumba Cedric Madianga stm32_dma_stop(chan); 396d8b46839SM'boumba Cedric Madianga chan->desc = NULL; 397d8b46839SM'boumba Cedric Madianga } 398d8b46839SM'boumba Cedric Madianga 399d8b46839SM'boumba Cedric Madianga vchan_get_all_descriptors(&chan->vchan, &head); 400d8b46839SM'boumba Cedric Madianga spin_unlock_irqrestore(&chan->vchan.lock, flags); 401d8b46839SM'boumba Cedric Madianga vchan_dma_desc_free_list(&chan->vchan, &head); 402d8b46839SM'boumba Cedric Madianga 403d8b46839SM'boumba Cedric Madianga return 0; 404d8b46839SM'boumba Cedric Madianga } 405d8b46839SM'boumba Cedric Madianga 406d8b46839SM'boumba Cedric Madianga static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) 407d8b46839SM'boumba Cedric Madianga { 408d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 409d8b46839SM'boumba Cedric Madianga u32 scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); 410d8b46839SM'boumba Cedric Madianga u32 ndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id)); 411d8b46839SM'boumba Cedric Madianga u32 spar = stm32_dma_read(dmadev, STM32_DMA_SPAR(chan->id)); 412d8b46839SM'boumba Cedric Madianga u32 sm0ar = stm32_dma_read(dmadev, STM32_DMA_SM0AR(chan->id)); 413d8b46839SM'boumba Cedric Madianga u32 sm1ar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(chan->id)); 414d8b46839SM'boumba Cedric Madianga u32 sfcr = stm32_dma_read(dmadev, STM32_DMA_SFCR(chan->id)); 415d8b46839SM'boumba Cedric Madianga 416d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "SCR: 0x%08x\n", scr); 417d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "NDTR: 0x%08x\n", ndtr); 418d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "SPAR: 0x%08x\n", spar); 419d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "SM0AR: 0x%08x\n", sm0ar); 420d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "SM1AR: 0x%08x\n", sm1ar); 421d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr); 422d8b46839SM'boumba Cedric Madianga } 423d8b46839SM'boumba Cedric Madianga 4248d1b76f0SM'boumba Cedric Madianga static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) 425d8b46839SM'boumba Cedric Madianga { 426d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 427d8b46839SM'boumba Cedric Madianga struct virt_dma_desc *vdesc; 428d8b46839SM'boumba Cedric Madianga struct stm32_dma_sg_req *sg_req; 429d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan_reg *reg; 430d8b46839SM'boumba Cedric Madianga u32 status; 431d8b46839SM'boumba Cedric Madianga int ret; 432d8b46839SM'boumba Cedric Madianga 433d8b46839SM'boumba Cedric Madianga ret = stm32_dma_disable_chan(chan); 434d8b46839SM'boumba Cedric Madianga if (ret < 0) 4358d1b76f0SM'boumba Cedric Madianga return; 436d8b46839SM'boumba Cedric Madianga 437d8b46839SM'boumba Cedric Madianga if (!chan->desc) { 438d8b46839SM'boumba Cedric Madianga vdesc = vchan_next_desc(&chan->vchan); 439d8b46839SM'boumba Cedric Madianga if (!vdesc) 4408d1b76f0SM'boumba Cedric Madianga return; 441d8b46839SM'boumba Cedric Madianga 442d8b46839SM'boumba Cedric Madianga chan->desc = to_stm32_dma_desc(vdesc); 443d8b46839SM'boumba Cedric Madianga chan->next_sg = 0; 444d8b46839SM'boumba Cedric Madianga } 445d8b46839SM'boumba Cedric Madianga 446d8b46839SM'boumba Cedric Madianga if (chan->next_sg == chan->desc->num_sgs) 447d8b46839SM'boumba Cedric Madianga chan->next_sg = 0; 448d8b46839SM'boumba Cedric Madianga 449d8b46839SM'boumba Cedric Madianga sg_req = &chan->desc->sg_req[chan->next_sg]; 450d8b46839SM'boumba Cedric Madianga reg = &sg_req->chan_reg; 451d8b46839SM'boumba Cedric Madianga 452d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), reg->dma_scr); 453d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SPAR(chan->id), reg->dma_spar); 454d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SM0AR(chan->id), reg->dma_sm0ar); 455d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SFCR(chan->id), reg->dma_sfcr); 456d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SM1AR(chan->id), reg->dma_sm1ar); 457d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SNDTR(chan->id), reg->dma_sndtr); 458d8b46839SM'boumba Cedric Madianga 459d8b46839SM'boumba Cedric Madianga chan->next_sg++; 460d8b46839SM'boumba Cedric Madianga 461d8b46839SM'boumba Cedric Madianga /* Clear interrupt status if it is there */ 462d8b46839SM'boumba Cedric Madianga status = stm32_dma_irq_status(chan); 463d8b46839SM'boumba Cedric Madianga if (status) 464d8b46839SM'boumba Cedric Madianga stm32_dma_irq_clear(chan, status); 465d8b46839SM'boumba Cedric Madianga 466d8b46839SM'boumba Cedric Madianga stm32_dma_dump_reg(chan); 467d8b46839SM'boumba Cedric Madianga 468d8b46839SM'boumba Cedric Madianga /* Start DMA */ 469d8b46839SM'boumba Cedric Madianga reg->dma_scr |= STM32_DMA_SCR_EN; 470d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), reg->dma_scr); 471d8b46839SM'boumba Cedric Madianga 472d8b46839SM'boumba Cedric Madianga chan->busy = true; 473d8b46839SM'boumba Cedric Madianga 4748d1b76f0SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "vchan %p: started\n", &chan->vchan); 475d8b46839SM'boumba Cedric Madianga } 476d8b46839SM'boumba Cedric Madianga 477d8b46839SM'boumba Cedric Madianga static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) 478d8b46839SM'boumba Cedric Madianga { 479d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 480d8b46839SM'boumba Cedric Madianga struct stm32_dma_sg_req *sg_req; 481d8b46839SM'boumba Cedric Madianga u32 dma_scr, dma_sm0ar, dma_sm1ar, id; 482d8b46839SM'boumba Cedric Madianga 483d8b46839SM'boumba Cedric Madianga id = chan->id; 484d8b46839SM'boumba Cedric Madianga dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(id)); 485d8b46839SM'boumba Cedric Madianga 486d8b46839SM'boumba Cedric Madianga if (dma_scr & STM32_DMA_SCR_DBM) { 487d8b46839SM'boumba Cedric Madianga if (chan->next_sg == chan->desc->num_sgs) 488d8b46839SM'boumba Cedric Madianga chan->next_sg = 0; 489d8b46839SM'boumba Cedric Madianga 490d8b46839SM'boumba Cedric Madianga sg_req = &chan->desc->sg_req[chan->next_sg]; 491d8b46839SM'boumba Cedric Madianga 492d8b46839SM'boumba Cedric Madianga if (dma_scr & STM32_DMA_SCR_CT) { 493d8b46839SM'boumba Cedric Madianga dma_sm0ar = sg_req->chan_reg.dma_sm0ar; 494d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SM0AR(id), dma_sm0ar); 495d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "CT=1 <=> SM0AR: 0x%08x\n", 496d8b46839SM'boumba Cedric Madianga stm32_dma_read(dmadev, STM32_DMA_SM0AR(id))); 497d8b46839SM'boumba Cedric Madianga } else { 498d8b46839SM'boumba Cedric Madianga dma_sm1ar = sg_req->chan_reg.dma_sm1ar; 499d8b46839SM'boumba Cedric Madianga stm32_dma_write(dmadev, STM32_DMA_SM1AR(id), dma_sm1ar); 500d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n", 501d8b46839SM'boumba Cedric Madianga stm32_dma_read(dmadev, STM32_DMA_SM1AR(id))); 502d8b46839SM'boumba Cedric Madianga } 503d8b46839SM'boumba Cedric Madianga } 504d8b46839SM'boumba Cedric Madianga } 505d8b46839SM'boumba Cedric Madianga 506d8b46839SM'boumba Cedric Madianga static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan) 507d8b46839SM'boumba Cedric Madianga { 508d8b46839SM'boumba Cedric Madianga if (chan->desc) { 509d8b46839SM'boumba Cedric Madianga if (chan->desc->cyclic) { 510d8b46839SM'boumba Cedric Madianga vchan_cyclic_callback(&chan->desc->vdesc); 5112b12c558SM'boumba Cedric Madianga chan->next_sg++; 512d8b46839SM'boumba Cedric Madianga stm32_dma_configure_next_sg(chan); 513d8b46839SM'boumba Cedric Madianga } else { 514d8b46839SM'boumba Cedric Madianga chan->busy = false; 515d8b46839SM'boumba Cedric Madianga if (chan->next_sg == chan->desc->num_sgs) { 516d8b46839SM'boumba Cedric Madianga list_del(&chan->desc->vdesc.node); 517d8b46839SM'boumba Cedric Madianga vchan_cookie_complete(&chan->desc->vdesc); 518d8b46839SM'boumba Cedric Madianga chan->desc = NULL; 519d8b46839SM'boumba Cedric Madianga } 520d8b46839SM'boumba Cedric Madianga stm32_dma_start_transfer(chan); 521d8b46839SM'boumba Cedric Madianga } 522d8b46839SM'boumba Cedric Madianga } 523d8b46839SM'boumba Cedric Madianga } 524d8b46839SM'boumba Cedric Madianga 525d8b46839SM'boumba Cedric Madianga static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) 526d8b46839SM'boumba Cedric Madianga { 527d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = devid; 528d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 5291bc4f06cSVinod Koul u32 status, scr; 530d8b46839SM'boumba Cedric Madianga 531d8b46839SM'boumba Cedric Madianga spin_lock(&chan->vchan.lock); 532d8b46839SM'boumba Cedric Madianga 533d8b46839SM'boumba Cedric Madianga status = stm32_dma_irq_status(chan); 534d8b46839SM'boumba Cedric Madianga scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); 535d8b46839SM'boumba Cedric Madianga 536d8b46839SM'boumba Cedric Madianga if ((status & STM32_DMA_TCI) && (scr & STM32_DMA_SCR_TCIE)) { 537d8b46839SM'boumba Cedric Madianga stm32_dma_irq_clear(chan, STM32_DMA_TCI); 538d8b46839SM'boumba Cedric Madianga stm32_dma_handle_chan_done(chan); 539d8b46839SM'boumba Cedric Madianga 540d8b46839SM'boumba Cedric Madianga } else { 541d8b46839SM'boumba Cedric Madianga stm32_dma_irq_clear(chan, status); 542d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status); 543d8b46839SM'boumba Cedric Madianga } 544d8b46839SM'boumba Cedric Madianga 545d8b46839SM'boumba Cedric Madianga spin_unlock(&chan->vchan.lock); 546d8b46839SM'boumba Cedric Madianga 547d8b46839SM'boumba Cedric Madianga return IRQ_HANDLED; 548d8b46839SM'boumba Cedric Madianga } 549d8b46839SM'boumba Cedric Madianga 550d8b46839SM'boumba Cedric Madianga static void stm32_dma_issue_pending(struct dma_chan *c) 551d8b46839SM'boumba Cedric Madianga { 552d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 553d8b46839SM'boumba Cedric Madianga unsigned long flags; 554d8b46839SM'boumba Cedric Madianga 555d8b46839SM'boumba Cedric Madianga spin_lock_irqsave(&chan->vchan.lock, flags); 5568d1b76f0SM'boumba Cedric Madianga if (vchan_issue_pending(&chan->vchan) && !chan->desc && !chan->busy) { 5578d1b76f0SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "vchan %p: issued\n", &chan->vchan); 5588d1b76f0SM'boumba Cedric Madianga stm32_dma_start_transfer(chan); 5598d1b76f0SM'boumba Cedric Madianga if (chan->desc->cyclic) 560d8b46839SM'boumba Cedric Madianga stm32_dma_configure_next_sg(chan); 561d8b46839SM'boumba Cedric Madianga } 562d8b46839SM'boumba Cedric Madianga spin_unlock_irqrestore(&chan->vchan.lock, flags); 563d8b46839SM'boumba Cedric Madianga } 564d8b46839SM'boumba Cedric Madianga 565d8b46839SM'boumba Cedric Madianga static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, 566d8b46839SM'boumba Cedric Madianga enum dma_transfer_direction direction, 567d8b46839SM'boumba Cedric Madianga enum dma_slave_buswidth *buswidth) 568d8b46839SM'boumba Cedric Madianga { 569d8b46839SM'boumba Cedric Madianga enum dma_slave_buswidth src_addr_width, dst_addr_width; 570d8b46839SM'boumba Cedric Madianga int src_bus_width, dst_bus_width; 571d8b46839SM'boumba Cedric Madianga int src_burst_size, dst_burst_size; 572d8b46839SM'boumba Cedric Madianga u32 src_maxburst, dst_maxburst; 573d8b46839SM'boumba Cedric Madianga u32 dma_scr = 0; 574d8b46839SM'boumba Cedric Madianga 575d8b46839SM'boumba Cedric Madianga src_addr_width = chan->dma_sconfig.src_addr_width; 576d8b46839SM'boumba Cedric Madianga dst_addr_width = chan->dma_sconfig.dst_addr_width; 577d8b46839SM'boumba Cedric Madianga src_maxburst = chan->dma_sconfig.src_maxburst; 578d8b46839SM'boumba Cedric Madianga dst_maxburst = chan->dma_sconfig.dst_maxburst; 579d8b46839SM'boumba Cedric Madianga 580d8b46839SM'boumba Cedric Madianga switch (direction) { 581d8b46839SM'boumba Cedric Madianga case DMA_MEM_TO_DEV: 582d8b46839SM'boumba Cedric Madianga dst_bus_width = stm32_dma_get_width(chan, dst_addr_width); 583d8b46839SM'boumba Cedric Madianga if (dst_bus_width < 0) 584d8b46839SM'boumba Cedric Madianga return dst_bus_width; 585d8b46839SM'boumba Cedric Madianga 586d8b46839SM'boumba Cedric Madianga dst_burst_size = stm32_dma_get_burst(chan, dst_maxburst); 587d8b46839SM'boumba Cedric Madianga if (dst_burst_size < 0) 588d8b46839SM'boumba Cedric Madianga return dst_burst_size; 589d8b46839SM'boumba Cedric Madianga 590d8b46839SM'boumba Cedric Madianga if (!src_addr_width) 591d8b46839SM'boumba Cedric Madianga src_addr_width = dst_addr_width; 592d8b46839SM'boumba Cedric Madianga 593d8b46839SM'boumba Cedric Madianga src_bus_width = stm32_dma_get_width(chan, src_addr_width); 594d8b46839SM'boumba Cedric Madianga if (src_bus_width < 0) 595d8b46839SM'boumba Cedric Madianga return src_bus_width; 596d8b46839SM'boumba Cedric Madianga 597d8b46839SM'boumba Cedric Madianga src_burst_size = stm32_dma_get_burst(chan, src_maxburst); 598d8b46839SM'boumba Cedric Madianga if (src_burst_size < 0) 599d8b46839SM'boumba Cedric Madianga return src_burst_size; 600d8b46839SM'boumba Cedric Madianga 601d8b46839SM'boumba Cedric Madianga dma_scr = STM32_DMA_SCR_DIR(STM32_DMA_MEM_TO_DEV) | 602d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_PSIZE(dst_bus_width) | 603d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_MSIZE(src_bus_width) | 604d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_PBURST(dst_burst_size) | 605d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_MBURST(src_burst_size); 606d8b46839SM'boumba Cedric Madianga 607d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_spar = chan->dma_sconfig.dst_addr; 608d8b46839SM'boumba Cedric Madianga *buswidth = dst_addr_width; 609d8b46839SM'boumba Cedric Madianga break; 610d8b46839SM'boumba Cedric Madianga 611d8b46839SM'boumba Cedric Madianga case DMA_DEV_TO_MEM: 612d8b46839SM'boumba Cedric Madianga src_bus_width = stm32_dma_get_width(chan, src_addr_width); 613d8b46839SM'boumba Cedric Madianga if (src_bus_width < 0) 614d8b46839SM'boumba Cedric Madianga return src_bus_width; 615d8b46839SM'boumba Cedric Madianga 616d8b46839SM'boumba Cedric Madianga src_burst_size = stm32_dma_get_burst(chan, src_maxburst); 617d8b46839SM'boumba Cedric Madianga if (src_burst_size < 0) 618d8b46839SM'boumba Cedric Madianga return src_burst_size; 619d8b46839SM'boumba Cedric Madianga 620d8b46839SM'boumba Cedric Madianga if (!dst_addr_width) 621d8b46839SM'boumba Cedric Madianga dst_addr_width = src_addr_width; 622d8b46839SM'boumba Cedric Madianga 623d8b46839SM'boumba Cedric Madianga dst_bus_width = stm32_dma_get_width(chan, dst_addr_width); 624d8b46839SM'boumba Cedric Madianga if (dst_bus_width < 0) 625d8b46839SM'boumba Cedric Madianga return dst_bus_width; 626d8b46839SM'boumba Cedric Madianga 627d8b46839SM'boumba Cedric Madianga dst_burst_size = stm32_dma_get_burst(chan, dst_maxburst); 628d8b46839SM'boumba Cedric Madianga if (dst_burst_size < 0) 629d8b46839SM'boumba Cedric Madianga return dst_burst_size; 630d8b46839SM'boumba Cedric Madianga 631d8b46839SM'boumba Cedric Madianga dma_scr = STM32_DMA_SCR_DIR(STM32_DMA_DEV_TO_MEM) | 632d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_PSIZE(src_bus_width) | 633d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_MSIZE(dst_bus_width) | 634d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_PBURST(src_burst_size) | 635d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_MBURST(dst_burst_size); 636d8b46839SM'boumba Cedric Madianga 637d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_spar = chan->dma_sconfig.src_addr; 638d8b46839SM'boumba Cedric Madianga *buswidth = chan->dma_sconfig.src_addr_width; 639d8b46839SM'boumba Cedric Madianga break; 640d8b46839SM'boumba Cedric Madianga 641d8b46839SM'boumba Cedric Madianga default: 642d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "Dma direction is not supported\n"); 643d8b46839SM'boumba Cedric Madianga return -EINVAL; 644d8b46839SM'boumba Cedric Madianga } 645d8b46839SM'boumba Cedric Madianga 646d8b46839SM'boumba Cedric Madianga stm32_dma_set_fifo_config(chan, src_maxburst, dst_maxburst); 647d8b46839SM'boumba Cedric Madianga 648d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr &= ~(STM32_DMA_SCR_DIR_MASK | 649d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_PSIZE_MASK | STM32_DMA_SCR_MSIZE_MASK | 650d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_PBURST_MASK | STM32_DMA_SCR_MBURST_MASK); 651d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr |= dma_scr; 652d8b46839SM'boumba Cedric Madianga 653d8b46839SM'boumba Cedric Madianga return 0; 654d8b46839SM'boumba Cedric Madianga } 655d8b46839SM'boumba Cedric Madianga 656d8b46839SM'boumba Cedric Madianga static void stm32_dma_clear_reg(struct stm32_dma_chan_reg *regs) 657d8b46839SM'boumba Cedric Madianga { 658d8b46839SM'boumba Cedric Madianga memset(regs, 0, sizeof(struct stm32_dma_chan_reg)); 659d8b46839SM'boumba Cedric Madianga } 660d8b46839SM'boumba Cedric Madianga 661d8b46839SM'boumba Cedric Madianga static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( 662d8b46839SM'boumba Cedric Madianga struct dma_chan *c, struct scatterlist *sgl, 663d8b46839SM'boumba Cedric Madianga u32 sg_len, enum dma_transfer_direction direction, 664d8b46839SM'boumba Cedric Madianga unsigned long flags, void *context) 665d8b46839SM'boumba Cedric Madianga { 666d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 667d8b46839SM'boumba Cedric Madianga struct stm32_dma_desc *desc; 668d8b46839SM'boumba Cedric Madianga struct scatterlist *sg; 669d8b46839SM'boumba Cedric Madianga enum dma_slave_buswidth buswidth; 670d8b46839SM'boumba Cedric Madianga u32 nb_data_items; 671d8b46839SM'boumba Cedric Madianga int i, ret; 672d8b46839SM'boumba Cedric Madianga 673d8b46839SM'boumba Cedric Madianga if (!chan->config_init) { 674d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "dma channel is not configured\n"); 675d8b46839SM'boumba Cedric Madianga return NULL; 676d8b46839SM'boumba Cedric Madianga } 677d8b46839SM'boumba Cedric Madianga 678d8b46839SM'boumba Cedric Madianga if (sg_len < 1) { 679d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "Invalid segment length %d\n", sg_len); 680d8b46839SM'boumba Cedric Madianga return NULL; 681d8b46839SM'boumba Cedric Madianga } 682d8b46839SM'boumba Cedric Madianga 683d8b46839SM'boumba Cedric Madianga desc = stm32_dma_alloc_desc(sg_len); 684d8b46839SM'boumba Cedric Madianga if (!desc) 685d8b46839SM'boumba Cedric Madianga return NULL; 686d8b46839SM'boumba Cedric Madianga 687d8b46839SM'boumba Cedric Madianga ret = stm32_dma_set_xfer_param(chan, direction, &buswidth); 688d8b46839SM'boumba Cedric Madianga if (ret < 0) 689d8b46839SM'boumba Cedric Madianga goto err; 690d8b46839SM'boumba Cedric Madianga 691d8b46839SM'boumba Cedric Madianga /* Set peripheral flow controller */ 692d8b46839SM'boumba Cedric Madianga if (chan->dma_sconfig.device_fc) 693d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr |= STM32_DMA_SCR_PFCTRL; 694d8b46839SM'boumba Cedric Madianga else 695d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; 696d8b46839SM'boumba Cedric Madianga 697d8b46839SM'boumba Cedric Madianga for_each_sg(sgl, sg, sg_len, i) { 698d8b46839SM'boumba Cedric Madianga desc->sg_req[i].len = sg_dma_len(sg); 699d8b46839SM'boumba Cedric Madianga 700d8b46839SM'boumba Cedric Madianga nb_data_items = desc->sg_req[i].len / buswidth; 701d8b46839SM'boumba Cedric Madianga if (nb_data_items > STM32_DMA_MAX_DATA_ITEMS) { 702d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "nb items not supported\n"); 703d8b46839SM'boumba Cedric Madianga goto err; 704d8b46839SM'boumba Cedric Madianga } 705d8b46839SM'boumba Cedric Madianga 706d8b46839SM'boumba Cedric Madianga stm32_dma_clear_reg(&desc->sg_req[i].chan_reg); 707d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_scr = chan->chan_reg.dma_scr; 708d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sfcr = chan->chan_reg.dma_sfcr; 709d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_spar = chan->chan_reg.dma_spar; 710d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sm0ar = sg_dma_address(sg); 711d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sm1ar = sg_dma_address(sg); 712d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sndtr = nb_data_items; 713d8b46839SM'boumba Cedric Madianga } 714d8b46839SM'boumba Cedric Madianga 715d8b46839SM'boumba Cedric Madianga desc->num_sgs = sg_len; 716d8b46839SM'boumba Cedric Madianga desc->cyclic = false; 717d8b46839SM'boumba Cedric Madianga 718d8b46839SM'boumba Cedric Madianga return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); 719d8b46839SM'boumba Cedric Madianga 720d8b46839SM'boumba Cedric Madianga err: 721d8b46839SM'boumba Cedric Madianga kfree(desc); 722d8b46839SM'boumba Cedric Madianga return NULL; 723d8b46839SM'boumba Cedric Madianga } 724d8b46839SM'boumba Cedric Madianga 725d8b46839SM'boumba Cedric Madianga static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( 726d8b46839SM'boumba Cedric Madianga struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len, 727d8b46839SM'boumba Cedric Madianga size_t period_len, enum dma_transfer_direction direction, 728d8b46839SM'boumba Cedric Madianga unsigned long flags) 729d8b46839SM'boumba Cedric Madianga { 730d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 731d8b46839SM'boumba Cedric Madianga struct stm32_dma_desc *desc; 732d8b46839SM'boumba Cedric Madianga enum dma_slave_buswidth buswidth; 733d8b46839SM'boumba Cedric Madianga u32 num_periods, nb_data_items; 734d8b46839SM'boumba Cedric Madianga int i, ret; 735d8b46839SM'boumba Cedric Madianga 736d8b46839SM'boumba Cedric Madianga if (!buf_len || !period_len) { 737d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "Invalid buffer/period len\n"); 738d8b46839SM'boumba Cedric Madianga return NULL; 739d8b46839SM'boumba Cedric Madianga } 740d8b46839SM'boumba Cedric Madianga 741d8b46839SM'boumba Cedric Madianga if (!chan->config_init) { 742d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "dma channel is not configured\n"); 743d8b46839SM'boumba Cedric Madianga return NULL; 744d8b46839SM'boumba Cedric Madianga } 745d8b46839SM'boumba Cedric Madianga 746d8b46839SM'boumba Cedric Madianga if (buf_len % period_len) { 747d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "buf_len not multiple of period_len\n"); 748d8b46839SM'boumba Cedric Madianga return NULL; 749d8b46839SM'boumba Cedric Madianga } 750d8b46839SM'boumba Cedric Madianga 751d8b46839SM'boumba Cedric Madianga /* 752d8b46839SM'boumba Cedric Madianga * We allow to take more number of requests till DMA is 753d8b46839SM'boumba Cedric Madianga * not started. The driver will loop over all requests. 754d8b46839SM'boumba Cedric Madianga * Once DMA is started then new requests can be queued only after 755d8b46839SM'boumba Cedric Madianga * terminating the DMA. 756d8b46839SM'boumba Cedric Madianga */ 757d8b46839SM'boumba Cedric Madianga if (chan->busy) { 758d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "Request not allowed when dma busy\n"); 759d8b46839SM'boumba Cedric Madianga return NULL; 760d8b46839SM'boumba Cedric Madianga } 761d8b46839SM'boumba Cedric Madianga 762d8b46839SM'boumba Cedric Madianga ret = stm32_dma_set_xfer_param(chan, direction, &buswidth); 763d8b46839SM'boumba Cedric Madianga if (ret < 0) 764d8b46839SM'boumba Cedric Madianga return NULL; 765d8b46839SM'boumba Cedric Madianga 766d8b46839SM'boumba Cedric Madianga nb_data_items = period_len / buswidth; 767d8b46839SM'boumba Cedric Madianga if (nb_data_items > STM32_DMA_MAX_DATA_ITEMS) { 768d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "number of items not supported\n"); 769d8b46839SM'boumba Cedric Madianga return NULL; 770d8b46839SM'boumba Cedric Madianga } 771d8b46839SM'boumba Cedric Madianga 772d8b46839SM'boumba Cedric Madianga /* Enable Circular mode or double buffer mode */ 773d8b46839SM'boumba Cedric Madianga if (buf_len == period_len) 774d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr |= STM32_DMA_SCR_CIRC; 775d8b46839SM'boumba Cedric Madianga else 776d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr |= STM32_DMA_SCR_DBM; 777d8b46839SM'boumba Cedric Madianga 778d8b46839SM'boumba Cedric Madianga /* Clear periph ctrl if client set it */ 779d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; 780d8b46839SM'boumba Cedric Madianga 781d8b46839SM'boumba Cedric Madianga num_periods = buf_len / period_len; 782d8b46839SM'boumba Cedric Madianga 783d8b46839SM'boumba Cedric Madianga desc = stm32_dma_alloc_desc(num_periods); 784d8b46839SM'boumba Cedric Madianga if (!desc) 785d8b46839SM'boumba Cedric Madianga return NULL; 786d8b46839SM'boumba Cedric Madianga 787d8b46839SM'boumba Cedric Madianga for (i = 0; i < num_periods; i++) { 788d8b46839SM'boumba Cedric Madianga desc->sg_req[i].len = period_len; 789d8b46839SM'boumba Cedric Madianga 790d8b46839SM'boumba Cedric Madianga stm32_dma_clear_reg(&desc->sg_req[i].chan_reg); 791d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_scr = chan->chan_reg.dma_scr; 792d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sfcr = chan->chan_reg.dma_sfcr; 793d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_spar = chan->chan_reg.dma_spar; 794d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sm0ar = buf_addr; 795d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sm1ar = buf_addr; 796d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sndtr = nb_data_items; 797d8b46839SM'boumba Cedric Madianga buf_addr += period_len; 798d8b46839SM'boumba Cedric Madianga } 799d8b46839SM'boumba Cedric Madianga 800d8b46839SM'boumba Cedric Madianga desc->num_sgs = num_periods; 801d8b46839SM'boumba Cedric Madianga desc->cyclic = true; 802d8b46839SM'boumba Cedric Madianga 803d8b46839SM'boumba Cedric Madianga return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); 804d8b46839SM'boumba Cedric Madianga } 805d8b46839SM'boumba Cedric Madianga 806d8b46839SM'boumba Cedric Madianga static struct dma_async_tx_descriptor *stm32_dma_prep_dma_memcpy( 807d8b46839SM'boumba Cedric Madianga struct dma_chan *c, dma_addr_t dest, 808d8b46839SM'boumba Cedric Madianga dma_addr_t src, size_t len, unsigned long flags) 809d8b46839SM'boumba Cedric Madianga { 810d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 811d8b46839SM'boumba Cedric Madianga u32 num_sgs; 812d8b46839SM'boumba Cedric Madianga struct stm32_dma_desc *desc; 813d8b46839SM'boumba Cedric Madianga size_t xfer_count, offset; 814d8b46839SM'boumba Cedric Madianga int i; 815d8b46839SM'boumba Cedric Madianga 816d8b46839SM'boumba Cedric Madianga num_sgs = DIV_ROUND_UP(len, STM32_DMA_MAX_DATA_ITEMS); 817d8b46839SM'boumba Cedric Madianga desc = stm32_dma_alloc_desc(num_sgs); 818d8b46839SM'boumba Cedric Madianga if (!desc) 819d8b46839SM'boumba Cedric Madianga return NULL; 820d8b46839SM'boumba Cedric Madianga 821d8b46839SM'boumba Cedric Madianga for (offset = 0, i = 0; offset < len; offset += xfer_count, i++) { 822d8b46839SM'boumba Cedric Madianga xfer_count = min_t(size_t, len - offset, 823d8b46839SM'boumba Cedric Madianga STM32_DMA_MAX_DATA_ITEMS); 824d8b46839SM'boumba Cedric Madianga 825d8b46839SM'boumba Cedric Madianga desc->sg_req[i].len = xfer_count; 826d8b46839SM'boumba Cedric Madianga 827d8b46839SM'boumba Cedric Madianga stm32_dma_clear_reg(&desc->sg_req[i].chan_reg); 828d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_scr = 829d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_DIR(STM32_DMA_MEM_TO_MEM) | 830d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_MINC | 831d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_PINC | 832d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_TCIE | 833d8b46839SM'boumba Cedric Madianga STM32_DMA_SCR_TEIE; 834d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sfcr = STM32_DMA_SFCR_DMDIS | 835d8b46839SM'boumba Cedric Madianga STM32_DMA_SFCR_FTH(STM32_DMA_FIFO_THRESHOLD_FULL) | 836d8b46839SM'boumba Cedric Madianga STM32_DMA_SFCR_FEIE; 837d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_spar = src + offset; 838d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sm0ar = dest + offset; 839d8b46839SM'boumba Cedric Madianga desc->sg_req[i].chan_reg.dma_sndtr = xfer_count; 840d8b46839SM'boumba Cedric Madianga } 841d8b46839SM'boumba Cedric Madianga 842d8b46839SM'boumba Cedric Madianga desc->num_sgs = num_sgs; 843d8b46839SM'boumba Cedric Madianga desc->cyclic = false; 844d8b46839SM'boumba Cedric Madianga 845d8b46839SM'boumba Cedric Madianga return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags); 846d8b46839SM'boumba Cedric Madianga } 847d8b46839SM'boumba Cedric Madianga 8482b12c558SM'boumba Cedric Madianga static u32 stm32_dma_get_remaining_bytes(struct stm32_dma_chan *chan) 8492b12c558SM'boumba Cedric Madianga { 8502b12c558SM'boumba Cedric Madianga u32 dma_scr, width, ndtr; 8512b12c558SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 8522b12c558SM'boumba Cedric Madianga 8532b12c558SM'boumba Cedric Madianga dma_scr = stm32_dma_read(dmadev, STM32_DMA_SCR(chan->id)); 8542b12c558SM'boumba Cedric Madianga width = STM32_DMA_SCR_PSIZE_GET(dma_scr); 8552b12c558SM'boumba Cedric Madianga ndtr = stm32_dma_read(dmadev, STM32_DMA_SNDTR(chan->id)); 8562b12c558SM'boumba Cedric Madianga 8572b12c558SM'boumba Cedric Madianga return ndtr << width; 8582b12c558SM'boumba Cedric Madianga } 8592b12c558SM'boumba Cedric Madianga 860d8b46839SM'boumba Cedric Madianga static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, 861d8b46839SM'boumba Cedric Madianga struct stm32_dma_desc *desc, 862d8b46839SM'boumba Cedric Madianga u32 next_sg) 863d8b46839SM'boumba Cedric Madianga { 8642b12c558SM'boumba Cedric Madianga u32 residue = 0; 865d8b46839SM'boumba Cedric Madianga int i; 866d8b46839SM'boumba Cedric Madianga 8672b12c558SM'boumba Cedric Madianga /* 8682b12c558SM'boumba Cedric Madianga * In cyclic mode, for the last period, residue = remaining bytes from 8692b12c558SM'boumba Cedric Madianga * NDTR 8702b12c558SM'boumba Cedric Madianga */ 8712b12c558SM'boumba Cedric Madianga if (chan->desc->cyclic && next_sg == 0) 8722b12c558SM'boumba Cedric Madianga return stm32_dma_get_remaining_bytes(chan); 873d8b46839SM'boumba Cedric Madianga 8742b12c558SM'boumba Cedric Madianga /* 8752b12c558SM'boumba Cedric Madianga * For all other periods in cyclic mode, and in sg mode, 8762b12c558SM'boumba Cedric Madianga * residue = remaining bytes from NDTR + remaining periods/sg to be 8772b12c558SM'boumba Cedric Madianga * transferred 8782b12c558SM'boumba Cedric Madianga */ 879d8b46839SM'boumba Cedric Madianga for (i = next_sg; i < desc->num_sgs; i++) 880d8b46839SM'boumba Cedric Madianga residue += desc->sg_req[i].len; 8812b12c558SM'boumba Cedric Madianga residue += stm32_dma_get_remaining_bytes(chan); 882d8b46839SM'boumba Cedric Madianga 883d8b46839SM'boumba Cedric Madianga return residue; 884d8b46839SM'boumba Cedric Madianga } 885d8b46839SM'boumba Cedric Madianga 886d8b46839SM'boumba Cedric Madianga static enum dma_status stm32_dma_tx_status(struct dma_chan *c, 887d8b46839SM'boumba Cedric Madianga dma_cookie_t cookie, 888d8b46839SM'boumba Cedric Madianga struct dma_tx_state *state) 889d8b46839SM'boumba Cedric Madianga { 890d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 891d8b46839SM'boumba Cedric Madianga struct virt_dma_desc *vdesc; 892d8b46839SM'boumba Cedric Madianga enum dma_status status; 893d8b46839SM'boumba Cedric Madianga unsigned long flags; 894d8b46839SM'boumba Cedric Madianga u32 residue; 895d8b46839SM'boumba Cedric Madianga 896d8b46839SM'boumba Cedric Madianga status = dma_cookie_status(c, cookie, state); 897d8b46839SM'boumba Cedric Madianga if ((status == DMA_COMPLETE) || (!state)) 898d8b46839SM'boumba Cedric Madianga return status; 899d8b46839SM'boumba Cedric Madianga 900d8b46839SM'boumba Cedric Madianga spin_lock_irqsave(&chan->vchan.lock, flags); 901d8b46839SM'boumba Cedric Madianga vdesc = vchan_find_desc(&chan->vchan, cookie); 902d8b46839SM'boumba Cedric Madianga if (cookie == chan->desc->vdesc.tx.cookie) { 903d8b46839SM'boumba Cedric Madianga residue = stm32_dma_desc_residue(chan, chan->desc, 904d8b46839SM'boumba Cedric Madianga chan->next_sg); 905d8b46839SM'boumba Cedric Madianga } else if (vdesc) { 906d8b46839SM'boumba Cedric Madianga residue = stm32_dma_desc_residue(chan, 907d8b46839SM'boumba Cedric Madianga to_stm32_dma_desc(vdesc), 0); 908d8b46839SM'boumba Cedric Madianga } else { 909d8b46839SM'boumba Cedric Madianga residue = 0; 910d8b46839SM'boumba Cedric Madianga } 911d8b46839SM'boumba Cedric Madianga 912d8b46839SM'boumba Cedric Madianga dma_set_residue(state, residue); 913d8b46839SM'boumba Cedric Madianga 914d8b46839SM'boumba Cedric Madianga spin_unlock_irqrestore(&chan->vchan.lock, flags); 915d8b46839SM'boumba Cedric Madianga 916d8b46839SM'boumba Cedric Madianga return status; 917d8b46839SM'boumba Cedric Madianga } 918d8b46839SM'boumba Cedric Madianga 919d8b46839SM'boumba Cedric Madianga static int stm32_dma_alloc_chan_resources(struct dma_chan *c) 920d8b46839SM'boumba Cedric Madianga { 921d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 922d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 923d8b46839SM'boumba Cedric Madianga int ret; 924d8b46839SM'boumba Cedric Madianga 925d8b46839SM'boumba Cedric Madianga chan->config_init = false; 926d8b46839SM'boumba Cedric Madianga ret = clk_prepare_enable(dmadev->clk); 927d8b46839SM'boumba Cedric Madianga if (ret < 0) { 928d8b46839SM'boumba Cedric Madianga dev_err(chan2dev(chan), "clk_prepare_enable failed: %d\n", ret); 929d8b46839SM'boumba Cedric Madianga return ret; 930d8b46839SM'boumba Cedric Madianga } 931d8b46839SM'boumba Cedric Madianga 932d8b46839SM'boumba Cedric Madianga ret = stm32_dma_disable_chan(chan); 933d8b46839SM'boumba Cedric Madianga if (ret < 0) 934d8b46839SM'boumba Cedric Madianga clk_disable_unprepare(dmadev->clk); 935d8b46839SM'boumba Cedric Madianga 936d8b46839SM'boumba Cedric Madianga return ret; 937d8b46839SM'boumba Cedric Madianga } 938d8b46839SM'boumba Cedric Madianga 939d8b46839SM'boumba Cedric Madianga static void stm32_dma_free_chan_resources(struct dma_chan *c) 940d8b46839SM'boumba Cedric Madianga { 941d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan = to_stm32_dma_chan(c); 942d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); 943d8b46839SM'boumba Cedric Madianga unsigned long flags; 944d8b46839SM'boumba Cedric Madianga 945d8b46839SM'boumba Cedric Madianga dev_dbg(chan2dev(chan), "Freeing channel %d\n", chan->id); 946d8b46839SM'boumba Cedric Madianga 947d8b46839SM'boumba Cedric Madianga if (chan->busy) { 948d8b46839SM'boumba Cedric Madianga spin_lock_irqsave(&chan->vchan.lock, flags); 949d8b46839SM'boumba Cedric Madianga stm32_dma_stop(chan); 950d8b46839SM'boumba Cedric Madianga chan->desc = NULL; 951d8b46839SM'boumba Cedric Madianga spin_unlock_irqrestore(&chan->vchan.lock, flags); 952d8b46839SM'boumba Cedric Madianga } 953d8b46839SM'boumba Cedric Madianga 954d8b46839SM'boumba Cedric Madianga clk_disable_unprepare(dmadev->clk); 955d8b46839SM'boumba Cedric Madianga 956d8b46839SM'boumba Cedric Madianga vchan_free_chan_resources(to_virt_chan(c)); 957d8b46839SM'boumba Cedric Madianga } 958d8b46839SM'boumba Cedric Madianga 959d8b46839SM'boumba Cedric Madianga static void stm32_dma_desc_free(struct virt_dma_desc *vdesc) 960d8b46839SM'boumba Cedric Madianga { 961d8b46839SM'boumba Cedric Madianga kfree(container_of(vdesc, struct stm32_dma_desc, vdesc)); 962d8b46839SM'boumba Cedric Madianga } 963d8b46839SM'boumba Cedric Madianga 964e97adb49SVinod Koul static void stm32_dma_set_config(struct stm32_dma_chan *chan, 965d8b46839SM'boumba Cedric Madianga struct stm32_dma_cfg *cfg) 966d8b46839SM'boumba Cedric Madianga { 967d8b46839SM'boumba Cedric Madianga stm32_dma_clear_reg(&chan->chan_reg); 968d8b46839SM'boumba Cedric Madianga 969d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr = cfg->stream_config & STM32_DMA_SCR_CFG_MASK; 970d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr |= STM32_DMA_SCR_REQ(cfg->request_line); 971d8b46839SM'boumba Cedric Madianga 972d8b46839SM'boumba Cedric Madianga /* Enable Interrupts */ 973d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_scr |= STM32_DMA_SCR_TEIE | STM32_DMA_SCR_TCIE; 974d8b46839SM'boumba Cedric Madianga 975d8b46839SM'boumba Cedric Madianga chan->chan_reg.dma_sfcr = cfg->threshold & STM32_DMA_SFCR_FTH_MASK; 976d8b46839SM'boumba Cedric Madianga } 977d8b46839SM'boumba Cedric Madianga 978d8b46839SM'boumba Cedric Madianga static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec, 979d8b46839SM'boumba Cedric Madianga struct of_dma *ofdma) 980d8b46839SM'boumba Cedric Madianga { 981d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev = ofdma->of_dma_data; 982d8b46839SM'boumba Cedric Madianga struct stm32_dma_cfg cfg; 983d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan; 984d8b46839SM'boumba Cedric Madianga struct dma_chan *c; 985d8b46839SM'boumba Cedric Madianga 986d8b46839SM'boumba Cedric Madianga if (dma_spec->args_count < 3) 987d8b46839SM'boumba Cedric Madianga return NULL; 988d8b46839SM'boumba Cedric Madianga 989d8b46839SM'boumba Cedric Madianga cfg.channel_id = dma_spec->args[0]; 990d8b46839SM'boumba Cedric Madianga cfg.request_line = dma_spec->args[1]; 991d8b46839SM'boumba Cedric Madianga cfg.stream_config = dma_spec->args[2]; 992d8b46839SM'boumba Cedric Madianga cfg.threshold = 0; 993d8b46839SM'boumba Cedric Madianga 994d8b46839SM'boumba Cedric Madianga if ((cfg.channel_id >= STM32_DMA_MAX_CHANNELS) || (cfg.request_line >= 995d8b46839SM'boumba Cedric Madianga STM32_DMA_MAX_REQUEST_ID)) 996d8b46839SM'boumba Cedric Madianga return NULL; 997d8b46839SM'boumba Cedric Madianga 998d8b46839SM'boumba Cedric Madianga if (dma_spec->args_count > 3) 999d8b46839SM'boumba Cedric Madianga cfg.threshold = dma_spec->args[3]; 1000d8b46839SM'boumba Cedric Madianga 1001d8b46839SM'boumba Cedric Madianga chan = &dmadev->chan[cfg.channel_id]; 1002d8b46839SM'boumba Cedric Madianga 1003d8b46839SM'boumba Cedric Madianga c = dma_get_slave_channel(&chan->vchan.chan); 1004d8b46839SM'boumba Cedric Madianga if (c) 1005d8b46839SM'boumba Cedric Madianga stm32_dma_set_config(chan, &cfg); 1006d8b46839SM'boumba Cedric Madianga 1007d8b46839SM'boumba Cedric Madianga return c; 1008d8b46839SM'boumba Cedric Madianga } 1009d8b46839SM'boumba Cedric Madianga 1010d8b46839SM'boumba Cedric Madianga static const struct of_device_id stm32_dma_of_match[] = { 1011d8b46839SM'boumba Cedric Madianga { .compatible = "st,stm32-dma", }, 1012d8b46839SM'boumba Cedric Madianga { /* sentinel */ }, 1013d8b46839SM'boumba Cedric Madianga }; 1014d8b46839SM'boumba Cedric Madianga MODULE_DEVICE_TABLE(of, stm32_dma_of_match); 1015d8b46839SM'boumba Cedric Madianga 1016d8b46839SM'boumba Cedric Madianga static int stm32_dma_probe(struct platform_device *pdev) 1017d8b46839SM'boumba Cedric Madianga { 1018d8b46839SM'boumba Cedric Madianga struct stm32_dma_chan *chan; 1019d8b46839SM'boumba Cedric Madianga struct stm32_dma_device *dmadev; 1020d8b46839SM'boumba Cedric Madianga struct dma_device *dd; 1021d8b46839SM'boumba Cedric Madianga const struct of_device_id *match; 1022d8b46839SM'boumba Cedric Madianga struct resource *res; 1023d8b46839SM'boumba Cedric Madianga int i, ret; 1024d8b46839SM'boumba Cedric Madianga 1025d8b46839SM'boumba Cedric Madianga match = of_match_device(stm32_dma_of_match, &pdev->dev); 1026d8b46839SM'boumba Cedric Madianga if (!match) { 1027d8b46839SM'boumba Cedric Madianga dev_err(&pdev->dev, "Error: No device match found\n"); 1028d8b46839SM'boumba Cedric Madianga return -ENODEV; 1029d8b46839SM'boumba Cedric Madianga } 1030d8b46839SM'boumba Cedric Madianga 1031d8b46839SM'boumba Cedric Madianga dmadev = devm_kzalloc(&pdev->dev, sizeof(*dmadev), GFP_KERNEL); 1032d8b46839SM'boumba Cedric Madianga if (!dmadev) 1033d8b46839SM'boumba Cedric Madianga return -ENOMEM; 1034d8b46839SM'boumba Cedric Madianga 1035d8b46839SM'boumba Cedric Madianga dd = &dmadev->ddev; 1036d8b46839SM'boumba Cedric Madianga 1037d8b46839SM'boumba Cedric Madianga res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1038d8b46839SM'boumba Cedric Madianga dmadev->base = devm_ioremap_resource(&pdev->dev, res); 1039d8b46839SM'boumba Cedric Madianga if (IS_ERR(dmadev->base)) 1040d8b46839SM'boumba Cedric Madianga return PTR_ERR(dmadev->base); 1041d8b46839SM'boumba Cedric Madianga 1042d8b46839SM'boumba Cedric Madianga dmadev->clk = devm_clk_get(&pdev->dev, NULL); 1043d8b46839SM'boumba Cedric Madianga if (IS_ERR(dmadev->clk)) { 1044d8b46839SM'boumba Cedric Madianga dev_err(&pdev->dev, "Error: Missing controller clock\n"); 1045d8b46839SM'boumba Cedric Madianga return PTR_ERR(dmadev->clk); 1046d8b46839SM'boumba Cedric Madianga } 1047d8b46839SM'boumba Cedric Madianga 1048d8b46839SM'boumba Cedric Madianga dmadev->mem2mem = of_property_read_bool(pdev->dev.of_node, 1049d8b46839SM'boumba Cedric Madianga "st,mem2mem"); 1050d8b46839SM'boumba Cedric Madianga 1051d8b46839SM'boumba Cedric Madianga dmadev->rst = devm_reset_control_get(&pdev->dev, NULL); 1052d8b46839SM'boumba Cedric Madianga if (!IS_ERR(dmadev->rst)) { 1053d8b46839SM'boumba Cedric Madianga reset_control_assert(dmadev->rst); 1054d8b46839SM'boumba Cedric Madianga udelay(2); 1055d8b46839SM'boumba Cedric Madianga reset_control_deassert(dmadev->rst); 1056d8b46839SM'boumba Cedric Madianga } 1057d8b46839SM'boumba Cedric Madianga 1058d8b46839SM'boumba Cedric Madianga dma_cap_set(DMA_SLAVE, dd->cap_mask); 1059d8b46839SM'boumba Cedric Madianga dma_cap_set(DMA_PRIVATE, dd->cap_mask); 1060d8b46839SM'boumba Cedric Madianga dma_cap_set(DMA_CYCLIC, dd->cap_mask); 1061d8b46839SM'boumba Cedric Madianga dd->device_alloc_chan_resources = stm32_dma_alloc_chan_resources; 1062d8b46839SM'boumba Cedric Madianga dd->device_free_chan_resources = stm32_dma_free_chan_resources; 1063d8b46839SM'boumba Cedric Madianga dd->device_tx_status = stm32_dma_tx_status; 1064d8b46839SM'boumba Cedric Madianga dd->device_issue_pending = stm32_dma_issue_pending; 1065d8b46839SM'boumba Cedric Madianga dd->device_prep_slave_sg = stm32_dma_prep_slave_sg; 1066d8b46839SM'boumba Cedric Madianga dd->device_prep_dma_cyclic = stm32_dma_prep_dma_cyclic; 1067d8b46839SM'boumba Cedric Madianga dd->device_config = stm32_dma_slave_config; 1068d8b46839SM'boumba Cedric Madianga dd->device_terminate_all = stm32_dma_terminate_all; 1069d8b46839SM'boumba Cedric Madianga dd->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | 1070d8b46839SM'boumba Cedric Madianga BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | 1071d8b46839SM'boumba Cedric Madianga BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); 1072d8b46839SM'boumba Cedric Madianga dd->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | 1073d8b46839SM'boumba Cedric Madianga BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | 1074d8b46839SM'boumba Cedric Madianga BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); 1075d8b46839SM'boumba Cedric Madianga dd->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); 1076d8b46839SM'boumba Cedric Madianga dd->residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; 1077d8b46839SM'boumba Cedric Madianga dd->dev = &pdev->dev; 1078d8b46839SM'boumba Cedric Madianga INIT_LIST_HEAD(&dd->channels); 1079d8b46839SM'boumba Cedric Madianga 1080d8b46839SM'boumba Cedric Madianga if (dmadev->mem2mem) { 1081d8b46839SM'boumba Cedric Madianga dma_cap_set(DMA_MEMCPY, dd->cap_mask); 1082d8b46839SM'boumba Cedric Madianga dd->device_prep_dma_memcpy = stm32_dma_prep_dma_memcpy; 1083d8b46839SM'boumba Cedric Madianga dd->directions |= BIT(DMA_MEM_TO_MEM); 1084d8b46839SM'boumba Cedric Madianga } 1085d8b46839SM'boumba Cedric Madianga 1086d8b46839SM'boumba Cedric Madianga for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) { 1087d8b46839SM'boumba Cedric Madianga chan = &dmadev->chan[i]; 1088d8b46839SM'boumba Cedric Madianga chan->id = i; 1089d8b46839SM'boumba Cedric Madianga chan->vchan.desc_free = stm32_dma_desc_free; 1090d8b46839SM'boumba Cedric Madianga vchan_init(&chan->vchan, dd); 1091d8b46839SM'boumba Cedric Madianga } 1092d8b46839SM'boumba Cedric Madianga 1093d8b46839SM'boumba Cedric Madianga ret = dma_async_device_register(dd); 1094d8b46839SM'boumba Cedric Madianga if (ret) 1095d8b46839SM'boumba Cedric Madianga return ret; 1096d8b46839SM'boumba Cedric Madianga 1097d8b46839SM'boumba Cedric Madianga for (i = 0; i < STM32_DMA_MAX_CHANNELS; i++) { 1098d8b46839SM'boumba Cedric Madianga chan = &dmadev->chan[i]; 1099d8b46839SM'boumba Cedric Madianga res = platform_get_resource(pdev, IORESOURCE_IRQ, i); 1100d8b46839SM'boumba Cedric Madianga if (!res) { 1101d8b46839SM'boumba Cedric Madianga ret = -EINVAL; 1102d8b46839SM'boumba Cedric Madianga dev_err(&pdev->dev, "No irq resource for chan %d\n", i); 1103d8b46839SM'boumba Cedric Madianga goto err_unregister; 1104d8b46839SM'boumba Cedric Madianga } 1105d8b46839SM'boumba Cedric Madianga chan->irq = res->start; 1106d8b46839SM'boumba Cedric Madianga ret = devm_request_irq(&pdev->dev, chan->irq, 1107d8b46839SM'boumba Cedric Madianga stm32_dma_chan_irq, 0, 1108d8b46839SM'boumba Cedric Madianga dev_name(chan2dev(chan)), chan); 1109d8b46839SM'boumba Cedric Madianga if (ret) { 1110d8b46839SM'boumba Cedric Madianga dev_err(&pdev->dev, 1111d8b46839SM'boumba Cedric Madianga "request_irq failed with err %d channel %d\n", 1112d8b46839SM'boumba Cedric Madianga ret, i); 1113d8b46839SM'boumba Cedric Madianga goto err_unregister; 1114d8b46839SM'boumba Cedric Madianga } 1115d8b46839SM'boumba Cedric Madianga } 1116d8b46839SM'boumba Cedric Madianga 1117d8b46839SM'boumba Cedric Madianga ret = of_dma_controller_register(pdev->dev.of_node, 1118d8b46839SM'boumba Cedric Madianga stm32_dma_of_xlate, dmadev); 1119d8b46839SM'boumba Cedric Madianga if (ret < 0) { 1120d8b46839SM'boumba Cedric Madianga dev_err(&pdev->dev, 1121d8b46839SM'boumba Cedric Madianga "STM32 DMA DMA OF registration failed %d\n", ret); 1122d8b46839SM'boumba Cedric Madianga goto err_unregister; 1123d8b46839SM'boumba Cedric Madianga } 1124d8b46839SM'boumba Cedric Madianga 1125d8b46839SM'boumba Cedric Madianga platform_set_drvdata(pdev, dmadev); 1126d8b46839SM'boumba Cedric Madianga 1127d8b46839SM'boumba Cedric Madianga dev_info(&pdev->dev, "STM32 DMA driver registered\n"); 1128d8b46839SM'boumba Cedric Madianga 1129d8b46839SM'boumba Cedric Madianga return 0; 1130d8b46839SM'boumba Cedric Madianga 1131d8b46839SM'boumba Cedric Madianga err_unregister: 1132d8b46839SM'boumba Cedric Madianga dma_async_device_unregister(dd); 1133d8b46839SM'boumba Cedric Madianga 1134d8b46839SM'boumba Cedric Madianga return ret; 1135d8b46839SM'boumba Cedric Madianga } 1136d8b46839SM'boumba Cedric Madianga 1137d8b46839SM'boumba Cedric Madianga static struct platform_driver stm32_dma_driver = { 1138d8b46839SM'boumba Cedric Madianga .driver = { 1139d8b46839SM'boumba Cedric Madianga .name = "stm32-dma", 1140d8b46839SM'boumba Cedric Madianga .of_match_table = stm32_dma_of_match, 1141d8b46839SM'boumba Cedric Madianga }, 1142d8b46839SM'boumba Cedric Madianga }; 1143d8b46839SM'boumba Cedric Madianga 1144d8b46839SM'boumba Cedric Madianga static int __init stm32_dma_init(void) 1145d8b46839SM'boumba Cedric Madianga { 1146d8b46839SM'boumba Cedric Madianga return platform_driver_probe(&stm32_dma_driver, stm32_dma_probe); 1147d8b46839SM'boumba Cedric Madianga } 1148d8b46839SM'boumba Cedric Madianga subsys_initcall(stm32_dma_init); 1149