diff options
author | Kedareswara rao Appana <appana.durga.rao@xilinx.com> | 2016-07-01 07:37:06 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2016-07-08 01:55:34 -0400 |
commit | b0cc417c1637192be658e68a74c8d1568e3d35f6 (patch) | |
tree | 1ad03ac982bc0e17c3a34b0b2ce0bf30999145d7 | |
parent | 805abc5f2f5d374086114f941e5bb6cb02e0c955 (diff) |
dmaengine: Add Xilinx zynqmp dma engine driver support
Added the driver for zynqmp dma engine used in Zynq
UltraScale+ MPSoC. This dma controller supports memory to memory
and I/O to I/O buffer transfers.
Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r-- | drivers/dma/Kconfig | 7 | ||||
-rw-r--r-- | drivers/dma/xilinx/Makefile | 1 | ||||
-rw-r--r-- | drivers/dma/xilinx/zynqmp_dma.c | 1145 |
3 files changed, 1153 insertions, 0 deletions
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 1f39f3ef6c8d..cde83f41d874 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -538,6 +538,13 @@ config XILINX_DMA | |||
538 | AXI DMA engine provides high-bandwidth one dimensional direct | 538 | AXI DMA engine provides high-bandwidth one dimensional direct |
539 | memory access between memory and AXI4-Stream target peripherals. | 539 | memory access between memory and AXI4-Stream target peripherals. |
540 | 540 | ||
541 | config XILINX_ZYNQMP_DMA | ||
542 | tristate "Xilinx ZynqMP DMA Engine" | ||
543 | depends on (ARCH_ZYNQ || MICROBLAZE || ARM64) | ||
544 | select DMA_ENGINE | ||
545 | help | ||
546 | Enable support for Xilinx ZynqMP DMA controller. | ||
547 | |||
541 | config ZX_DMA | 548 | config ZX_DMA |
542 | tristate "ZTE ZX296702 DMA support" | 549 | tristate "ZTE ZX296702 DMA support" |
543 | depends on ARCH_ZX | 550 | depends on ARCH_ZX |
diff --git a/drivers/dma/xilinx/Makefile b/drivers/dma/xilinx/Makefile index af9e69a41f8f..9e91f8f5b087 100644 --- a/drivers/dma/xilinx/Makefile +++ b/drivers/dma/xilinx/Makefile | |||
@@ -1 +1,2 @@ | |||
1 | obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o | 1 | obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o |
2 | obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o | ||
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c new file mode 100644 index 000000000000..59bc1f730a48 --- /dev/null +++ b/drivers/dma/xilinx/zynqmp_dma.c | |||
@@ -0,0 +1,1145 @@ | |||
1 | /* | ||
2 | * DMA driver for Xilinx ZynqMP DMA Engine | ||
3 | * | ||
4 | * Copyright (C) 2016 Xilinx, Inc. All rights reserved. | ||
5 | * | ||
6 | * This program is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation, either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/bitops.h> | ||
13 | #include <linux/dmapool.h> | ||
14 | #include <linux/dma/xilinx_dma.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of_address.h> | ||
20 | #include <linux/of_dma.h> | ||
21 | #include <linux/of_irq.h> | ||
22 | #include <linux/of_platform.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/io-64-nonatomic-lo-hi.h> | ||
26 | |||
27 | #include "../dmaengine.h" | ||
28 | |||
29 | /* Register Offsets */ | ||
30 | #define ZYNQMP_DMA_ISR 0x100 | ||
31 | #define ZYNQMP_DMA_IMR 0x104 | ||
32 | #define ZYNQMP_DMA_IER 0x108 | ||
33 | #define ZYNQMP_DMA_IDS 0x10C | ||
34 | #define ZYNQMP_DMA_CTRL0 0x110 | ||
35 | #define ZYNQMP_DMA_CTRL1 0x114 | ||
36 | #define ZYNQMP_DMA_DATA_ATTR 0x120 | ||
37 | #define ZYNQMP_DMA_DSCR_ATTR 0x124 | ||
38 | #define ZYNQMP_DMA_SRC_DSCR_WRD0 0x128 | ||
39 | #define ZYNQMP_DMA_SRC_DSCR_WRD1 0x12C | ||
40 | #define ZYNQMP_DMA_SRC_DSCR_WRD2 0x130 | ||
41 | #define ZYNQMP_DMA_SRC_DSCR_WRD3 0x134 | ||
42 | #define ZYNQMP_DMA_DST_DSCR_WRD0 0x138 | ||
43 | #define ZYNQMP_DMA_DST_DSCR_WRD1 0x13C | ||
44 | #define ZYNQMP_DMA_DST_DSCR_WRD2 0x140 | ||
45 | #define ZYNQMP_DMA_DST_DSCR_WRD3 0x144 | ||
46 | #define ZYNQMP_DMA_SRC_START_LSB 0x158 | ||
47 | #define ZYNQMP_DMA_SRC_START_MSB 0x15C | ||
48 | #define ZYNQMP_DMA_DST_START_LSB 0x160 | ||
49 | #define ZYNQMP_DMA_DST_START_MSB 0x164 | ||
50 | #define ZYNQMP_DMA_RATE_CTRL 0x18C | ||
51 | #define ZYNQMP_DMA_IRQ_SRC_ACCT 0x190 | ||
52 | #define ZYNQMP_DMA_IRQ_DST_ACCT 0x194 | ||
53 | #define ZYNQMP_DMA_CTRL2 0x200 | ||
54 | |||
55 | /* Interrupt registers bit field definitions */ | ||
56 | #define ZYNQMP_DMA_DONE BIT(10) | ||
57 | #define ZYNQMP_DMA_AXI_WR_DATA BIT(9) | ||
58 | #define ZYNQMP_DMA_AXI_RD_DATA BIT(8) | ||
59 | #define ZYNQMP_DMA_AXI_RD_DST_DSCR BIT(7) | ||
60 | #define ZYNQMP_DMA_AXI_RD_SRC_DSCR BIT(6) | ||
61 | #define ZYNQMP_DMA_IRQ_DST_ACCT_ERR BIT(5) | ||
62 | #define ZYNQMP_DMA_IRQ_SRC_ACCT_ERR BIT(4) | ||
63 | #define ZYNQMP_DMA_BYTE_CNT_OVRFL BIT(3) | ||
64 | #define ZYNQMP_DMA_DST_DSCR_DONE BIT(2) | ||
65 | #define ZYNQMP_DMA_INV_APB BIT(0) | ||
66 | |||
67 | /* Control 0 register bit field definitions */ | ||
68 | #define ZYNQMP_DMA_OVR_FETCH BIT(7) | ||
69 | #define ZYNQMP_DMA_POINT_TYPE_SG BIT(6) | ||
70 | #define ZYNQMP_DMA_RATE_CTRL_EN BIT(3) | ||
71 | |||
72 | /* Control 1 register bit field definitions */ | ||
73 | #define ZYNQMP_DMA_SRC_ISSUE GENMASK(4, 0) | ||
74 | |||
75 | /* Data Attribute register bit field definitions */ | ||
76 | #define ZYNQMP_DMA_ARBURST GENMASK(27, 26) | ||
77 | #define ZYNQMP_DMA_ARCACHE GENMASK(25, 22) | ||
78 | #define ZYNQMP_DMA_ARCACHE_OFST 22 | ||
79 | #define ZYNQMP_DMA_ARQOS GENMASK(21, 18) | ||
80 | #define ZYNQMP_DMA_ARQOS_OFST 18 | ||
81 | #define ZYNQMP_DMA_ARLEN GENMASK(17, 14) | ||
82 | #define ZYNQMP_DMA_ARLEN_OFST 14 | ||
83 | #define ZYNQMP_DMA_AWBURST GENMASK(13, 12) | ||
84 | #define ZYNQMP_DMA_AWCACHE GENMASK(11, 8) | ||
85 | #define ZYNQMP_DMA_AWCACHE_OFST 8 | ||
86 | #define ZYNQMP_DMA_AWQOS GENMASK(7, 4) | ||
87 | #define ZYNQMP_DMA_AWQOS_OFST 4 | ||
88 | #define ZYNQMP_DMA_AWLEN GENMASK(3, 0) | ||
89 | #define ZYNQMP_DMA_AWLEN_OFST 0 | ||
90 | |||
91 | /* Descriptor Attribute register bit field definitions */ | ||
92 | #define ZYNQMP_DMA_AXCOHRNT BIT(8) | ||
93 | #define ZYNQMP_DMA_AXCACHE GENMASK(7, 4) | ||
94 | #define ZYNQMP_DMA_AXCACHE_OFST 4 | ||
95 | #define ZYNQMP_DMA_AXQOS GENMASK(3, 0) | ||
96 | #define ZYNQMP_DMA_AXQOS_OFST 0 | ||
97 | |||
98 | /* Control register 2 bit field definitions */ | ||
99 | #define ZYNQMP_DMA_ENABLE BIT(0) | ||
100 | |||
101 | /* Buffer Descriptor definitions */ | ||
102 | #define ZYNQMP_DMA_DESC_CTRL_STOP 0x10 | ||
103 | #define ZYNQMP_DMA_DESC_CTRL_COMP_INT 0x4 | ||
104 | #define ZYNQMP_DMA_DESC_CTRL_SIZE_256 0x2 | ||
105 | #define ZYNQMP_DMA_DESC_CTRL_COHRNT 0x1 | ||
106 | |||
107 | /* Interrupt Mask specific definitions */ | ||
108 | #define ZYNQMP_DMA_INT_ERR (ZYNQMP_DMA_AXI_RD_DATA | \ | ||
109 | ZYNQMP_DMA_AXI_WR_DATA | \ | ||
110 | ZYNQMP_DMA_AXI_RD_DST_DSCR | \ | ||
111 | ZYNQMP_DMA_AXI_RD_SRC_DSCR | \ | ||
112 | ZYNQMP_DMA_INV_APB) | ||
113 | #define ZYNQMP_DMA_INT_OVRFL (ZYNQMP_DMA_BYTE_CNT_OVRFL | \ | ||
114 | ZYNQMP_DMA_IRQ_SRC_ACCT_ERR | \ | ||
115 | ZYNQMP_DMA_IRQ_DST_ACCT_ERR) | ||
116 | #define ZYNQMP_DMA_INT_DONE (ZYNQMP_DMA_DONE | ZYNQMP_DMA_DST_DSCR_DONE) | ||
117 | #define ZYNQMP_DMA_INT_EN_DEFAULT_MASK (ZYNQMP_DMA_INT_DONE | \ | ||
118 | ZYNQMP_DMA_INT_ERR | \ | ||
119 | ZYNQMP_DMA_INT_OVRFL | \ | ||
120 | ZYNQMP_DMA_DST_DSCR_DONE) | ||
121 | |||
122 | /* Max number of descriptors per channel */ | ||
123 | #define ZYNQMP_DMA_NUM_DESCS 32 | ||
124 | |||
125 | /* Max transfer size per descriptor */ | ||
126 | #define ZYNQMP_DMA_MAX_TRANS_LEN 0x40000000 | ||
127 | |||
128 | /* Reset values for data attributes */ | ||
129 | #define ZYNQMP_DMA_AXCACHE_VAL 0xF | ||
130 | #define ZYNQMP_DMA_ARLEN_RST_VAL 0xF | ||
131 | #define ZYNQMP_DMA_AWLEN_RST_VAL 0xF | ||
132 | |||
133 | #define ZYNQMP_DMA_SRC_ISSUE_RST_VAL 0x1F | ||
134 | |||
135 | #define ZYNQMP_DMA_IDS_DEFAULT_MASK 0xFFF | ||
136 | |||
137 | /* Bus width in bits */ | ||
138 | #define ZYNQMP_DMA_BUS_WIDTH_64 64 | ||
139 | #define ZYNQMP_DMA_BUS_WIDTH_128 128 | ||
140 | |||
141 | #define ZYNQMP_DMA_DESC_SIZE(chan) (chan->desc_size) | ||
142 | |||
143 | #define to_chan(chan) container_of(chan, struct zynqmp_dma_chan, \ | ||
144 | common) | ||
145 | #define tx_to_desc(tx) container_of(tx, struct zynqmp_dma_desc_sw, \ | ||
146 | async_tx) | ||
147 | |||
148 | /** | ||
149 | * struct zynqmp_dma_desc_ll - Hw linked list descriptor | ||
150 | * @addr: Buffer address | ||
151 | * @size: Size of the buffer | ||
152 | * @ctrl: Control word | ||
153 | * @nxtdscraddr: Next descriptor base address | ||
154 | * @rsvd: Reserved field and for Hw internal use. | ||
155 | */ | ||
156 | struct zynqmp_dma_desc_ll { | ||
157 | u64 addr; | ||
158 | u32 size; | ||
159 | u32 ctrl; | ||
160 | u64 nxtdscraddr; | ||
161 | u64 rsvd; | ||
162 | }; __aligned(64) | ||
163 | |||
164 | /** | ||
165 | * struct zynqmp_dma_desc_sw - Per Transaction structure | ||
166 | * @src: Source address for simple mode dma | ||
167 | * @dst: Destination address for simple mode dma | ||
168 | * @len: Transfer length for simple mode dma | ||
169 | * @node: Node in the channel descriptor list | ||
170 | * @tx_list: List head for the current transfer | ||
171 | * @async_tx: Async transaction descriptor | ||
172 | * @src_v: Virtual address of the src descriptor | ||
173 | * @src_p: Physical address of the src descriptor | ||
174 | * @dst_v: Virtual address of the dst descriptor | ||
175 | * @dst_p: Physical address of the dst descriptor | ||
176 | */ | ||
177 | struct zynqmp_dma_desc_sw { | ||
178 | u64 src; | ||
179 | u64 dst; | ||
180 | u32 len; | ||
181 | struct list_head node; | ||
182 | struct list_head tx_list; | ||
183 | struct dma_async_tx_descriptor async_tx; | ||
184 | struct zynqmp_dma_desc_ll *src_v; | ||
185 | dma_addr_t src_p; | ||
186 | struct zynqmp_dma_desc_ll *dst_v; | ||
187 | dma_addr_t dst_p; | ||
188 | }; | ||
189 | |||
190 | /** | ||
191 | * struct zynqmp_dma_chan - Driver specific DMA channel structure | ||
192 | * @zdev: Driver specific device structure | ||
193 | * @regs: Control registers offset | ||
194 | * @lock: Descriptor operation lock | ||
195 | * @pending_list: Descriptors waiting | ||
196 | * @free_list: Descriptors free | ||
197 | * @active_list: Descriptors active | ||
198 | * @sw_desc_pool: SW descriptor pool | ||
199 | * @done_list: Complete descriptors | ||
200 | * @common: DMA common channel | ||
201 | * @desc_pool_v: Statically allocated descriptor base | ||
202 | * @desc_pool_p: Physical allocated descriptor base | ||
203 | * @desc_free_cnt: Descriptor available count | ||
204 | * @dev: The dma device | ||
205 | * @irq: Channel IRQ | ||
206 | * @is_dmacoherent: Tells whether dma operations are coherent or not | ||
207 | * @tasklet: Cleanup work after irq | ||
208 | * @idle : Channel status; | ||
209 | * @desc_size: Size of the low level descriptor | ||
210 | * @err: Channel has errors | ||
211 | * @bus_width: Bus width | ||
212 | * @src_burst_len: Source burst length | ||
213 | * @dst_burst_len: Dest burst length | ||
214 | * @clk_main: Pointer to main clock | ||
215 | * @clk_apb: Pointer to apb clock | ||
216 | */ | ||
217 | struct zynqmp_dma_chan { | ||
218 | struct zynqmp_dma_device *zdev; | ||
219 | void __iomem *regs; | ||
220 | spinlock_t lock; | ||
221 | struct list_head pending_list; | ||
222 | struct list_head free_list; | ||
223 | struct list_head active_list; | ||
224 | struct zynqmp_dma_desc_sw *sw_desc_pool; | ||
225 | struct list_head done_list; | ||
226 | struct dma_chan common; | ||
227 | void *desc_pool_v; | ||
228 | dma_addr_t desc_pool_p; | ||
229 | u32 desc_free_cnt; | ||
230 | struct device *dev; | ||
231 | int irq; | ||
232 | bool is_dmacoherent; | ||
233 | struct tasklet_struct tasklet; | ||
234 | bool idle; | ||
235 | u32 desc_size; | ||
236 | bool err; | ||
237 | u32 bus_width; | ||
238 | u32 src_burst_len; | ||
239 | u32 dst_burst_len; | ||
240 | struct clk *clk_main; | ||
241 | struct clk *clk_apb; | ||
242 | }; | ||
243 | |||
244 | /** | ||
245 | * struct zynqmp_dma_device - DMA device structure | ||
246 | * @dev: Device Structure | ||
247 | * @common: DMA device structure | ||
248 | * @chan: Driver specific DMA channel | ||
249 | */ | ||
250 | struct zynqmp_dma_device { | ||
251 | struct device *dev; | ||
252 | struct dma_device common; | ||
253 | struct zynqmp_dma_chan *chan; | ||
254 | }; | ||
255 | |||
256 | static inline void zynqmp_dma_writeq(struct zynqmp_dma_chan *chan, u32 reg, | ||
257 | u64 value) | ||
258 | { | ||
259 | lo_hi_writeq(value, chan->regs + reg); | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * zynqmp_dma_update_desc_to_ctrlr - Updates descriptor to the controller | ||
264 | * @chan: ZynqMP DMA DMA channel pointer | ||
265 | * @desc: Transaction descriptor pointer | ||
266 | */ | ||
267 | static void zynqmp_dma_update_desc_to_ctrlr(struct zynqmp_dma_chan *chan, | ||
268 | struct zynqmp_dma_desc_sw *desc) | ||
269 | { | ||
270 | dma_addr_t addr; | ||
271 | |||
272 | addr = desc->src_p; | ||
273 | zynqmp_dma_writeq(chan, ZYNQMP_DMA_SRC_START_LSB, addr); | ||
274 | addr = desc->dst_p; | ||
275 | zynqmp_dma_writeq(chan, ZYNQMP_DMA_DST_START_LSB, addr); | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * zynqmp_dma_desc_config_eod - Mark the descriptor as end descriptor | ||
280 | * @chan: ZynqMP DMA channel pointer | ||
281 | * @desc: Hw descriptor pointer | ||
282 | */ | ||
283 | static void zynqmp_dma_desc_config_eod(struct zynqmp_dma_chan *chan, | ||
284 | void *desc) | ||
285 | { | ||
286 | struct zynqmp_dma_desc_ll *hw = (struct zynqmp_dma_desc_ll *)desc; | ||
287 | |||
288 | hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_STOP; | ||
289 | hw++; | ||
290 | hw->ctrl |= ZYNQMP_DMA_DESC_CTRL_COMP_INT | ZYNQMP_DMA_DESC_CTRL_STOP; | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * zynqmp_dma_config_sg_ll_desc - Configure the linked list descriptor | ||
295 | * @chan: ZynqMP DMA channel pointer | ||
296 | * @sdesc: Hw descriptor pointer | ||
297 | * @src: Source buffer address | ||
298 | * @dst: Destination buffer address | ||
299 | * @len: Transfer length | ||
300 | * @prev: Previous hw descriptor pointer | ||
301 | */ | ||
302 | static void zynqmp_dma_config_sg_ll_desc(struct zynqmp_dma_chan *chan, | ||
303 | struct zynqmp_dma_desc_ll *sdesc, | ||
304 | dma_addr_t src, dma_addr_t dst, size_t len, | ||
305 | struct zynqmp_dma_desc_ll *prev) | ||
306 | { | ||
307 | struct zynqmp_dma_desc_ll *ddesc = sdesc + 1; | ||
308 | |||
309 | sdesc->size = ddesc->size = len; | ||
310 | sdesc->addr = src; | ||
311 | ddesc->addr = dst; | ||
312 | |||
313 | sdesc->ctrl = ddesc->ctrl = ZYNQMP_DMA_DESC_CTRL_SIZE_256; | ||
314 | if (chan->is_dmacoherent) { | ||
315 | sdesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT; | ||
316 | ddesc->ctrl |= ZYNQMP_DMA_DESC_CTRL_COHRNT; | ||
317 | } | ||
318 | |||
319 | if (prev) { | ||
320 | dma_addr_t addr = chan->desc_pool_p + | ||
321 | ((dma_addr_t)sdesc - (dma_addr_t)chan->desc_pool_v); | ||
322 | ddesc = prev + 1; | ||
323 | prev->nxtdscraddr = addr; | ||
324 | ddesc->nxtdscraddr = addr + ZYNQMP_DMA_DESC_SIZE(chan); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | /** | ||
329 | * zynqmp_dma_init - Initialize the channel | ||
330 | * @chan: ZynqMP DMA channel pointer | ||
331 | */ | ||
332 | static void zynqmp_dma_init(struct zynqmp_dma_chan *chan) | ||
333 | { | ||
334 | u32 val; | ||
335 | |||
336 | writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS); | ||
337 | val = readl(chan->regs + ZYNQMP_DMA_ISR); | ||
338 | writel(val, chan->regs + ZYNQMP_DMA_ISR); | ||
339 | |||
340 | if (chan->is_dmacoherent) { | ||
341 | val = ZYNQMP_DMA_AXCOHRNT; | ||
342 | val = (val & ~ZYNQMP_DMA_AXCACHE) | | ||
343 | (ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_AXCACHE_OFST); | ||
344 | writel(val, chan->regs + ZYNQMP_DMA_DSCR_ATTR); | ||
345 | } | ||
346 | |||
347 | val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR); | ||
348 | if (chan->is_dmacoherent) { | ||
349 | val = (val & ~ZYNQMP_DMA_ARCACHE) | | ||
350 | (ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_ARCACHE_OFST); | ||
351 | val = (val & ~ZYNQMP_DMA_AWCACHE) | | ||
352 | (ZYNQMP_DMA_AXCACHE_VAL << ZYNQMP_DMA_AWCACHE_OFST); | ||
353 | } | ||
354 | writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR); | ||
355 | |||
356 | /* Clearing the interrupt account rgisters */ | ||
357 | val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT); | ||
358 | val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT); | ||
359 | |||
360 | chan->idle = true; | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * zynqmp_dma_tx_submit - Submit DMA transaction | ||
365 | * @tx: Async transaction descriptor pointer | ||
366 | * | ||
367 | * Return: cookie value | ||
368 | */ | ||
369 | static dma_cookie_t zynqmp_dma_tx_submit(struct dma_async_tx_descriptor *tx) | ||
370 | { | ||
371 | struct zynqmp_dma_chan *chan = to_chan(tx->chan); | ||
372 | struct zynqmp_dma_desc_sw *desc, *new; | ||
373 | dma_cookie_t cookie; | ||
374 | |||
375 | new = tx_to_desc(tx); | ||
376 | spin_lock_bh(&chan->lock); | ||
377 | cookie = dma_cookie_assign(tx); | ||
378 | |||
379 | if (!list_empty(&chan->pending_list)) { | ||
380 | desc = list_last_entry(&chan->pending_list, | ||
381 | struct zynqmp_dma_desc_sw, node); | ||
382 | if (!list_empty(&desc->tx_list)) | ||
383 | desc = list_last_entry(&desc->tx_list, | ||
384 | struct zynqmp_dma_desc_sw, node); | ||
385 | desc->src_v->nxtdscraddr = new->src_p; | ||
386 | desc->src_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP; | ||
387 | desc->dst_v->nxtdscraddr = new->dst_p; | ||
388 | desc->dst_v->ctrl &= ~ZYNQMP_DMA_DESC_CTRL_STOP; | ||
389 | } | ||
390 | |||
391 | list_add_tail(&new->node, &chan->pending_list); | ||
392 | spin_unlock_bh(&chan->lock); | ||
393 | |||
394 | return cookie; | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * zynqmp_dma_get_descriptor - Get the sw descriptor from the pool | ||
399 | * @chan: ZynqMP DMA channel pointer | ||
400 | * | ||
401 | * Return: The sw descriptor | ||
402 | */ | ||
403 | static struct zynqmp_dma_desc_sw * | ||
404 | zynqmp_dma_get_descriptor(struct zynqmp_dma_chan *chan) | ||
405 | { | ||
406 | struct zynqmp_dma_desc_sw *desc; | ||
407 | |||
408 | spin_lock_bh(&chan->lock); | ||
409 | desc = list_first_entry(&chan->free_list, | ||
410 | struct zynqmp_dma_desc_sw, node); | ||
411 | list_del(&desc->node); | ||
412 | spin_unlock_bh(&chan->lock); | ||
413 | |||
414 | INIT_LIST_HEAD(&desc->tx_list); | ||
415 | /* Clear the src and dst descriptor memory */ | ||
416 | memset((void *)desc->src_v, 0, ZYNQMP_DMA_DESC_SIZE(chan)); | ||
417 | memset((void *)desc->dst_v, 0, ZYNQMP_DMA_DESC_SIZE(chan)); | ||
418 | |||
419 | return desc; | ||
420 | } | ||
421 | |||
422 | /** | ||
423 | * zynqmp_dma_free_descriptor - Issue pending transactions | ||
424 | * @chan: ZynqMP DMA channel pointer | ||
425 | * @sdesc: Transaction descriptor pointer | ||
426 | */ | ||
427 | static void zynqmp_dma_free_descriptor(struct zynqmp_dma_chan *chan, | ||
428 | struct zynqmp_dma_desc_sw *sdesc) | ||
429 | { | ||
430 | struct zynqmp_dma_desc_sw *child, *next; | ||
431 | |||
432 | chan->desc_free_cnt++; | ||
433 | list_add_tail(&sdesc->node, &chan->free_list); | ||
434 | list_for_each_entry_safe(child, next, &sdesc->tx_list, node) { | ||
435 | chan->desc_free_cnt++; | ||
436 | list_move_tail(&child->node, &chan->free_list); | ||
437 | } | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * zynqmp_dma_free_desc_list - Free descriptors list | ||
442 | * @chan: ZynqMP DMA channel pointer | ||
443 | * @list: List to parse and delete the descriptor | ||
444 | */ | ||
445 | static void zynqmp_dma_free_desc_list(struct zynqmp_dma_chan *chan, | ||
446 | struct list_head *list) | ||
447 | { | ||
448 | struct zynqmp_dma_desc_sw *desc, *next; | ||
449 | |||
450 | list_for_each_entry_safe(desc, next, list, node) | ||
451 | zynqmp_dma_free_descriptor(chan, desc); | ||
452 | } | ||
453 | |||
454 | /** | ||
455 | * zynqmp_dma_alloc_chan_resources - Allocate channel resources | ||
456 | * @dchan: DMA channel | ||
457 | * | ||
458 | * Return: Number of descriptors on success and failure value on error | ||
459 | */ | ||
460 | static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) | ||
461 | { | ||
462 | struct zynqmp_dma_chan *chan = to_chan(dchan); | ||
463 | struct zynqmp_dma_desc_sw *desc; | ||
464 | int i; | ||
465 | |||
466 | chan->sw_desc_pool = kzalloc(sizeof(*desc) * ZYNQMP_DMA_NUM_DESCS, | ||
467 | GFP_KERNEL); | ||
468 | if (!chan->sw_desc_pool) | ||
469 | return -ENOMEM; | ||
470 | |||
471 | chan->idle = true; | ||
472 | chan->desc_free_cnt = ZYNQMP_DMA_NUM_DESCS; | ||
473 | |||
474 | INIT_LIST_HEAD(&chan->free_list); | ||
475 | |||
476 | for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) { | ||
477 | desc = chan->sw_desc_pool + i; | ||
478 | dma_async_tx_descriptor_init(&desc->async_tx, &chan->common); | ||
479 | desc->async_tx.tx_submit = zynqmp_dma_tx_submit; | ||
480 | list_add_tail(&desc->node, &chan->free_list); | ||
481 | } | ||
482 | |||
483 | chan->desc_pool_v = dma_zalloc_coherent(chan->dev, | ||
484 | (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS), | ||
485 | &chan->desc_pool_p, GFP_KERNEL); | ||
486 | if (!chan->desc_pool_v) | ||
487 | return -ENOMEM; | ||
488 | |||
489 | for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) { | ||
490 | desc = chan->sw_desc_pool + i; | ||
491 | desc->src_v = (struct zynqmp_dma_desc_ll *) (chan->desc_pool_v + | ||
492 | (i * ZYNQMP_DMA_DESC_SIZE(chan) * 2)); | ||
493 | desc->dst_v = (struct zynqmp_dma_desc_ll *) (desc->src_v + 1); | ||
494 | desc->src_p = chan->desc_pool_p + | ||
495 | (i * ZYNQMP_DMA_DESC_SIZE(chan) * 2); | ||
496 | desc->dst_p = desc->src_p + ZYNQMP_DMA_DESC_SIZE(chan); | ||
497 | } | ||
498 | |||
499 | return ZYNQMP_DMA_NUM_DESCS; | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * zynqmp_dma_start - Start DMA channel | ||
504 | * @chan: ZynqMP DMA channel pointer | ||
505 | */ | ||
506 | static void zynqmp_dma_start(struct zynqmp_dma_chan *chan) | ||
507 | { | ||
508 | writel(ZYNQMP_DMA_INT_EN_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IER); | ||
509 | chan->idle = false; | ||
510 | writel(ZYNQMP_DMA_ENABLE, chan->regs + ZYNQMP_DMA_CTRL2); | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * zynqmp_dma_handle_ovfl_int - Process the overflow interrupt | ||
515 | * @chan: ZynqMP DMA channel pointer | ||
516 | * @status: Interrupt status value | ||
517 | */ | ||
518 | static void zynqmp_dma_handle_ovfl_int(struct zynqmp_dma_chan *chan, u32 status) | ||
519 | { | ||
520 | u32 val; | ||
521 | |||
522 | if (status & ZYNQMP_DMA_IRQ_DST_ACCT_ERR) | ||
523 | val = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT); | ||
524 | if (status & ZYNQMP_DMA_IRQ_SRC_ACCT_ERR) | ||
525 | val = readl(chan->regs + ZYNQMP_DMA_IRQ_SRC_ACCT); | ||
526 | } | ||
527 | |||
528 | static void zynqmp_dma_config(struct zynqmp_dma_chan *chan) | ||
529 | { | ||
530 | u32 val; | ||
531 | |||
532 | val = readl(chan->regs + ZYNQMP_DMA_CTRL0); | ||
533 | val |= ZYNQMP_DMA_POINT_TYPE_SG; | ||
534 | writel(val, chan->regs + ZYNQMP_DMA_CTRL0); | ||
535 | |||
536 | val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR); | ||
537 | val = (val & ~ZYNQMP_DMA_ARLEN) | | ||
538 | (chan->src_burst_len << ZYNQMP_DMA_ARLEN_OFST); | ||
539 | val = (val & ~ZYNQMP_DMA_AWLEN) | | ||
540 | (chan->dst_burst_len << ZYNQMP_DMA_AWLEN_OFST); | ||
541 | writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR); | ||
542 | } | ||
543 | |||
544 | /** | ||
545 | * zynqmp_dma_device_config - Zynqmp dma device configuration | ||
546 | * @dchan: DMA channel | ||
547 | * @config: DMA device config | ||
548 | */ | ||
549 | static int zynqmp_dma_device_config(struct dma_chan *dchan, | ||
550 | struct dma_slave_config *config) | ||
551 | { | ||
552 | struct zynqmp_dma_chan *chan = to_chan(dchan); | ||
553 | |||
554 | chan->src_burst_len = config->src_maxburst; | ||
555 | chan->dst_burst_len = config->dst_maxburst; | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * zynqmp_dma_start_transfer - Initiate the new transfer | ||
562 | * @chan: ZynqMP DMA channel pointer | ||
563 | */ | ||
564 | static void zynqmp_dma_start_transfer(struct zynqmp_dma_chan *chan) | ||
565 | { | ||
566 | struct zynqmp_dma_desc_sw *desc; | ||
567 | |||
568 | if (!chan->idle) | ||
569 | return; | ||
570 | |||
571 | zynqmp_dma_config(chan); | ||
572 | |||
573 | desc = list_first_entry_or_null(&chan->pending_list, | ||
574 | struct zynqmp_dma_desc_sw, node); | ||
575 | if (!desc) | ||
576 | return; | ||
577 | |||
578 | list_splice_tail_init(&chan->pending_list, &chan->active_list); | ||
579 | zynqmp_dma_update_desc_to_ctrlr(chan, desc); | ||
580 | zynqmp_dma_start(chan); | ||
581 | } | ||
582 | |||
583 | |||
584 | /** | ||
585 | * zynqmp_dma_chan_desc_cleanup - Cleanup the completed descriptors | ||
586 | * @chan: ZynqMP DMA channel | ||
587 | */ | ||
588 | static void zynqmp_dma_chan_desc_cleanup(struct zynqmp_dma_chan *chan) | ||
589 | { | ||
590 | struct zynqmp_dma_desc_sw *desc, *next; | ||
591 | |||
592 | list_for_each_entry_safe(desc, next, &chan->done_list, node) { | ||
593 | dma_async_tx_callback callback; | ||
594 | void *callback_param; | ||
595 | |||
596 | list_del(&desc->node); | ||
597 | |||
598 | callback = desc->async_tx.callback; | ||
599 | callback_param = desc->async_tx.callback_param; | ||
600 | if (callback) { | ||
601 | spin_unlock(&chan->lock); | ||
602 | callback(callback_param); | ||
603 | spin_lock(&chan->lock); | ||
604 | } | ||
605 | |||
606 | /* Run any dependencies, then free the descriptor */ | ||
607 | zynqmp_dma_free_descriptor(chan, desc); | ||
608 | } | ||
609 | } | ||
610 | |||
611 | /** | ||
612 | * zynqmp_dma_complete_descriptor - Mark the active descriptor as complete | ||
613 | * @chan: ZynqMP DMA channel pointer | ||
614 | */ | ||
615 | static void zynqmp_dma_complete_descriptor(struct zynqmp_dma_chan *chan) | ||
616 | { | ||
617 | struct zynqmp_dma_desc_sw *desc; | ||
618 | |||
619 | desc = list_first_entry_or_null(&chan->active_list, | ||
620 | struct zynqmp_dma_desc_sw, node); | ||
621 | if (!desc) | ||
622 | return; | ||
623 | list_del(&desc->node); | ||
624 | dma_cookie_complete(&desc->async_tx); | ||
625 | list_add_tail(&desc->node, &chan->done_list); | ||
626 | } | ||
627 | |||
628 | /** | ||
629 | * zynqmp_dma_issue_pending - Issue pending transactions | ||
630 | * @dchan: DMA channel pointer | ||
631 | */ | ||
632 | static void zynqmp_dma_issue_pending(struct dma_chan *dchan) | ||
633 | { | ||
634 | struct zynqmp_dma_chan *chan = to_chan(dchan); | ||
635 | |||
636 | spin_lock_bh(&chan->lock); | ||
637 | zynqmp_dma_start_transfer(chan); | ||
638 | spin_unlock_bh(&chan->lock); | ||
639 | } | ||
640 | |||
641 | /** | ||
642 | * zynqmp_dma_free_descriptors - Free channel descriptors | ||
643 | * @dchan: DMA channel pointer | ||
644 | */ | ||
645 | static void zynqmp_dma_free_descriptors(struct zynqmp_dma_chan *chan) | ||
646 | { | ||
647 | zynqmp_dma_free_desc_list(chan, &chan->active_list); | ||
648 | zynqmp_dma_free_desc_list(chan, &chan->pending_list); | ||
649 | zynqmp_dma_free_desc_list(chan, &chan->done_list); | ||
650 | } | ||
651 | |||
652 | /** | ||
653 | * zynqmp_dma_free_chan_resources - Free channel resources | ||
654 | * @dchan: DMA channel pointer | ||
655 | */ | ||
656 | static void zynqmp_dma_free_chan_resources(struct dma_chan *dchan) | ||
657 | { | ||
658 | struct zynqmp_dma_chan *chan = to_chan(dchan); | ||
659 | |||
660 | spin_lock_bh(&chan->lock); | ||
661 | zynqmp_dma_free_descriptors(chan); | ||
662 | spin_unlock_bh(&chan->lock); | ||
663 | dma_free_coherent(chan->dev, | ||
664 | (2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS), | ||
665 | chan->desc_pool_v, chan->desc_pool_p); | ||
666 | kfree(chan->sw_desc_pool); | ||
667 | } | ||
668 | |||
669 | /** | ||
670 | * zynqmp_dma_reset - Reset the channel | ||
671 | * @chan: ZynqMP DMA channel pointer | ||
672 | */ | ||
673 | static void zynqmp_dma_reset(struct zynqmp_dma_chan *chan) | ||
674 | { | ||
675 | writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS); | ||
676 | |||
677 | zynqmp_dma_complete_descriptor(chan); | ||
678 | zynqmp_dma_chan_desc_cleanup(chan); | ||
679 | zynqmp_dma_free_descriptors(chan); | ||
680 | zynqmp_dma_init(chan); | ||
681 | } | ||
682 | |||
683 | /** | ||
684 | * zynqmp_dma_irq_handler - ZynqMP DMA Interrupt handler | ||
685 | * @irq: IRQ number | ||
686 | * @data: Pointer to the ZynqMP DMA channel structure | ||
687 | * | ||
688 | * Return: IRQ_HANDLED/IRQ_NONE | ||
689 | */ | ||
690 | static irqreturn_t zynqmp_dma_irq_handler(int irq, void *data) | ||
691 | { | ||
692 | struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data; | ||
693 | u32 isr, imr, status; | ||
694 | irqreturn_t ret = IRQ_NONE; | ||
695 | |||
696 | isr = readl(chan->regs + ZYNQMP_DMA_ISR); | ||
697 | imr = readl(chan->regs + ZYNQMP_DMA_IMR); | ||
698 | status = isr & ~imr; | ||
699 | |||
700 | writel(isr, chan->regs + ZYNQMP_DMA_ISR); | ||
701 | if (status & ZYNQMP_DMA_INT_DONE) { | ||
702 | tasklet_schedule(&chan->tasklet); | ||
703 | ret = IRQ_HANDLED; | ||
704 | } | ||
705 | |||
706 | if (status & ZYNQMP_DMA_DONE) | ||
707 | chan->idle = true; | ||
708 | |||
709 | if (status & ZYNQMP_DMA_INT_ERR) { | ||
710 | chan->err = true; | ||
711 | tasklet_schedule(&chan->tasklet); | ||
712 | dev_err(chan->dev, "Channel %p has errors\n", chan); | ||
713 | ret = IRQ_HANDLED; | ||
714 | } | ||
715 | |||
716 | if (status & ZYNQMP_DMA_INT_OVRFL) { | ||
717 | zynqmp_dma_handle_ovfl_int(chan, status); | ||
718 | dev_info(chan->dev, "Channel %p overflow interrupt\n", chan); | ||
719 | ret = IRQ_HANDLED; | ||
720 | } | ||
721 | |||
722 | return ret; | ||
723 | } | ||
724 | |||
725 | /** | ||
726 | * zynqmp_dma_do_tasklet - Schedule completion tasklet | ||
727 | * @data: Pointer to the ZynqMP DMA channel structure | ||
728 | */ | ||
729 | static void zynqmp_dma_do_tasklet(unsigned long data) | ||
730 | { | ||
731 | struct zynqmp_dma_chan *chan = (struct zynqmp_dma_chan *)data; | ||
732 | u32 count; | ||
733 | |||
734 | spin_lock(&chan->lock); | ||
735 | |||
736 | if (chan->err) { | ||
737 | zynqmp_dma_reset(chan); | ||
738 | chan->err = false; | ||
739 | goto unlock; | ||
740 | } | ||
741 | |||
742 | count = readl(chan->regs + ZYNQMP_DMA_IRQ_DST_ACCT); | ||
743 | |||
744 | while (count) { | ||
745 | zynqmp_dma_complete_descriptor(chan); | ||
746 | zynqmp_dma_chan_desc_cleanup(chan); | ||
747 | count--; | ||
748 | } | ||
749 | |||
750 | if (chan->idle) | ||
751 | zynqmp_dma_start_transfer(chan); | ||
752 | |||
753 | unlock: | ||
754 | spin_unlock(&chan->lock); | ||
755 | } | ||
756 | |||
757 | /** | ||
758 | * zynqmp_dma_device_terminate_all - Aborts all transfers on a channel | ||
759 | * @dchan: DMA channel pointer | ||
760 | * | ||
761 | * Return: Always '0' | ||
762 | */ | ||
763 | static int zynqmp_dma_device_terminate_all(struct dma_chan *dchan) | ||
764 | { | ||
765 | struct zynqmp_dma_chan *chan = to_chan(dchan); | ||
766 | |||
767 | spin_lock_bh(&chan->lock); | ||
768 | writel(ZYNQMP_DMA_IDS_DEFAULT_MASK, chan->regs + ZYNQMP_DMA_IDS); | ||
769 | zynqmp_dma_free_descriptors(chan); | ||
770 | spin_unlock_bh(&chan->lock); | ||
771 | |||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | /** | ||
776 | * zynqmp_dma_prep_memcpy - prepare descriptors for memcpy transaction | ||
777 | * @dchan: DMA channel | ||
778 | * @dma_dst: Destination buffer address | ||
779 | * @dma_src: Source buffer address | ||
780 | * @len: Transfer length | ||
781 | * @flags: transfer ack flags | ||
782 | * | ||
783 | * Return: Async transaction descriptor on success and NULL on failure | ||
784 | */ | ||
785 | static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy( | ||
786 | struct dma_chan *dchan, dma_addr_t dma_dst, | ||
787 | dma_addr_t dma_src, size_t len, ulong flags) | ||
788 | { | ||
789 | struct zynqmp_dma_chan *chan; | ||
790 | struct zynqmp_dma_desc_sw *new, *first = NULL; | ||
791 | void *desc = NULL, *prev = NULL; | ||
792 | size_t copy; | ||
793 | u32 desc_cnt; | ||
794 | |||
795 | chan = to_chan(dchan); | ||
796 | |||
797 | if (len > ZYNQMP_DMA_MAX_TRANS_LEN) | ||
798 | return NULL; | ||
799 | |||
800 | desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN); | ||
801 | |||
802 | spin_lock_bh(&chan->lock); | ||
803 | if (desc_cnt > chan->desc_free_cnt) { | ||
804 | spin_unlock_bh(&chan->lock); | ||
805 | dev_dbg(chan->dev, "chan %p descs are not available\n", chan); | ||
806 | return NULL; | ||
807 | } | ||
808 | chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt; | ||
809 | spin_unlock_bh(&chan->lock); | ||
810 | |||
811 | do { | ||
812 | /* Allocate and populate the descriptor */ | ||
813 | new = zynqmp_dma_get_descriptor(chan); | ||
814 | |||
815 | copy = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN); | ||
816 | desc = (struct zynqmp_dma_desc_ll *)new->src_v; | ||
817 | zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src, | ||
818 | dma_dst, copy, prev); | ||
819 | prev = desc; | ||
820 | len -= copy; | ||
821 | dma_src += copy; | ||
822 | dma_dst += copy; | ||
823 | if (!first) | ||
824 | first = new; | ||
825 | else | ||
826 | list_add_tail(&new->node, &first->tx_list); | ||
827 | } while (len); | ||
828 | |||
829 | zynqmp_dma_desc_config_eod(chan, desc); | ||
830 | async_tx_ack(&first->async_tx); | ||
831 | first->async_tx.flags = flags; | ||
832 | return &first->async_tx; | ||
833 | } | ||
834 | |||
835 | /** | ||
836 | * zynqmp_dma_prep_slave_sg - prepare descriptors for a memory sg transaction | ||
837 | * @dchan: DMA channel | ||
838 | * @dst_sg: Destination scatter list | ||
839 | * @dst_sg_len: Number of entries in destination scatter list | ||
840 | * @src_sg: Source scatter list | ||
841 | * @src_sg_len: Number of entries in source scatter list | ||
842 | * @flags: transfer ack flags | ||
843 | * | ||
844 | * Return: Async transaction descriptor on success and NULL on failure | ||
845 | */ | ||
846 | static struct dma_async_tx_descriptor *zynqmp_dma_prep_sg( | ||
847 | struct dma_chan *dchan, struct scatterlist *dst_sg, | ||
848 | unsigned int dst_sg_len, struct scatterlist *src_sg, | ||
849 | unsigned int src_sg_len, unsigned long flags) | ||
850 | { | ||
851 | struct zynqmp_dma_desc_sw *new, *first = NULL; | ||
852 | struct zynqmp_dma_chan *chan = to_chan(dchan); | ||
853 | void *desc = NULL, *prev = NULL; | ||
854 | size_t len, dst_avail, src_avail; | ||
855 | dma_addr_t dma_dst, dma_src; | ||
856 | u32 desc_cnt = 0, i; | ||
857 | struct scatterlist *sg; | ||
858 | |||
859 | for_each_sg(src_sg, sg, src_sg_len, i) | ||
860 | desc_cnt += DIV_ROUND_UP(sg_dma_len(sg), | ||
861 | ZYNQMP_DMA_MAX_TRANS_LEN); | ||
862 | |||
863 | spin_lock_bh(&chan->lock); | ||
864 | if (desc_cnt > chan->desc_free_cnt) { | ||
865 | spin_unlock_bh(&chan->lock); | ||
866 | dev_dbg(chan->dev, "chan %p descs are not available\n", chan); | ||
867 | return NULL; | ||
868 | } | ||
869 | chan->desc_free_cnt = chan->desc_free_cnt - desc_cnt; | ||
870 | spin_unlock_bh(&chan->lock); | ||
871 | |||
872 | dst_avail = sg_dma_len(dst_sg); | ||
873 | src_avail = sg_dma_len(src_sg); | ||
874 | |||
875 | /* Run until we are out of scatterlist entries */ | ||
876 | while (true) { | ||
877 | /* Allocate and populate the descriptor */ | ||
878 | new = zynqmp_dma_get_descriptor(chan); | ||
879 | desc = (struct zynqmp_dma_desc_ll *)new->src_v; | ||
880 | len = min_t(size_t, src_avail, dst_avail); | ||
881 | len = min_t(size_t, len, ZYNQMP_DMA_MAX_TRANS_LEN); | ||
882 | if (len == 0) | ||
883 | goto fetch; | ||
884 | dma_dst = sg_dma_address(dst_sg) + sg_dma_len(dst_sg) - | ||
885 | dst_avail; | ||
886 | dma_src = sg_dma_address(src_sg) + sg_dma_len(src_sg) - | ||
887 | src_avail; | ||
888 | |||
889 | zynqmp_dma_config_sg_ll_desc(chan, desc, dma_src, dma_dst, | ||
890 | len, prev); | ||
891 | prev = desc; | ||
892 | dst_avail -= len; | ||
893 | src_avail -= len; | ||
894 | |||
895 | if (!first) | ||
896 | first = new; | ||
897 | else | ||
898 | list_add_tail(&new->node, &first->tx_list); | ||
899 | fetch: | ||
900 | /* Fetch the next dst scatterlist entry */ | ||
901 | if (dst_avail == 0) { | ||
902 | if (dst_sg_len == 0) | ||
903 | break; | ||
904 | dst_sg = sg_next(dst_sg); | ||
905 | if (dst_sg == NULL) | ||
906 | break; | ||
907 | dst_sg_len--; | ||
908 | dst_avail = sg_dma_len(dst_sg); | ||
909 | } | ||
910 | /* Fetch the next src scatterlist entry */ | ||
911 | if (src_avail == 0) { | ||
912 | if (src_sg_len == 0) | ||
913 | break; | ||
914 | src_sg = sg_next(src_sg); | ||
915 | if (src_sg == NULL) | ||
916 | break; | ||
917 | src_sg_len--; | ||
918 | src_avail = sg_dma_len(src_sg); | ||
919 | } | ||
920 | } | ||
921 | |||
922 | zynqmp_dma_desc_config_eod(chan, desc); | ||
923 | first->async_tx.flags = flags; | ||
924 | return &first->async_tx; | ||
925 | } | ||
926 | |||
927 | /** | ||
928 | * zynqmp_dma_chan_remove - Channel remove function | ||
929 | * @chan: ZynqMP DMA channel pointer | ||
930 | */ | ||
931 | static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan) | ||
932 | { | ||
933 | if (!chan) | ||
934 | return; | ||
935 | |||
936 | devm_free_irq(chan->zdev->dev, chan->irq, chan); | ||
937 | tasklet_kill(&chan->tasklet); | ||
938 | list_del(&chan->common.device_node); | ||
939 | clk_disable_unprepare(chan->clk_apb); | ||
940 | clk_disable_unprepare(chan->clk_main); | ||
941 | } | ||
942 | |||
943 | /** | ||
944 | * zynqmp_dma_chan_probe - Per Channel Probing | ||
945 | * @zdev: Driver specific device structure | ||
946 | * @pdev: Pointer to the platform_device structure | ||
947 | * | ||
948 | * Return: '0' on success and failure value on error | ||
949 | */ | ||
950 | static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, | ||
951 | struct platform_device *pdev) | ||
952 | { | ||
953 | struct zynqmp_dma_chan *chan; | ||
954 | struct resource *res; | ||
955 | struct device_node *node = pdev->dev.of_node; | ||
956 | int err; | ||
957 | |||
958 | chan = devm_kzalloc(zdev->dev, sizeof(*chan), GFP_KERNEL); | ||
959 | if (!chan) | ||
960 | return -ENOMEM; | ||
961 | chan->dev = zdev->dev; | ||
962 | chan->zdev = zdev; | ||
963 | |||
964 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
965 | chan->regs = devm_ioremap_resource(&pdev->dev, res); | ||
966 | if (IS_ERR(chan->regs)) | ||
967 | return PTR_ERR(chan->regs); | ||
968 | |||
969 | chan->bus_width = ZYNQMP_DMA_BUS_WIDTH_64; | ||
970 | chan->dst_burst_len = ZYNQMP_DMA_AWLEN_RST_VAL; | ||
971 | chan->src_burst_len = ZYNQMP_DMA_ARLEN_RST_VAL; | ||
972 | err = of_property_read_u32(node, "xlnx,bus-width", &chan->bus_width); | ||
973 | if ((err < 0) && ((chan->bus_width != ZYNQMP_DMA_BUS_WIDTH_64) || | ||
974 | (chan->bus_width != ZYNQMP_DMA_BUS_WIDTH_128))) { | ||
975 | dev_err(zdev->dev, "invalid bus-width value"); | ||
976 | return err; | ||
977 | } | ||
978 | |||
979 | chan->is_dmacoherent = of_property_read_bool(node, "dma-coherent"); | ||
980 | zdev->chan = chan; | ||
981 | tasklet_init(&chan->tasklet, zynqmp_dma_do_tasklet, (ulong)chan); | ||
982 | spin_lock_init(&chan->lock); | ||
983 | INIT_LIST_HEAD(&chan->active_list); | ||
984 | INIT_LIST_HEAD(&chan->pending_list); | ||
985 | INIT_LIST_HEAD(&chan->done_list); | ||
986 | INIT_LIST_HEAD(&chan->free_list); | ||
987 | |||
988 | dma_cookie_init(&chan->common); | ||
989 | chan->common.device = &zdev->common; | ||
990 | list_add_tail(&chan->common.device_node, &zdev->common.channels); | ||
991 | |||
992 | zynqmp_dma_init(chan); | ||
993 | chan->irq = platform_get_irq(pdev, 0); | ||
994 | if (chan->irq < 0) | ||
995 | return -ENXIO; | ||
996 | err = devm_request_irq(&pdev->dev, chan->irq, zynqmp_dma_irq_handler, 0, | ||
997 | "zynqmp-dma", chan); | ||
998 | if (err) | ||
999 | return err; | ||
1000 | chan->clk_main = devm_clk_get(&pdev->dev, "clk_main"); | ||
1001 | if (IS_ERR(chan->clk_main)) { | ||
1002 | dev_err(&pdev->dev, "main clock not found.\n"); | ||
1003 | return PTR_ERR(chan->clk_main); | ||
1004 | } | ||
1005 | |||
1006 | chan->clk_apb = devm_clk_get(&pdev->dev, "clk_apb"); | ||
1007 | if (IS_ERR(chan->clk_apb)) { | ||
1008 | dev_err(&pdev->dev, "apb clock not found.\n"); | ||
1009 | return PTR_ERR(chan->clk_apb); | ||
1010 | } | ||
1011 | |||
1012 | err = clk_prepare_enable(chan->clk_main); | ||
1013 | if (err) { | ||
1014 | dev_err(&pdev->dev, "Unable to enable main clock.\n"); | ||
1015 | return err; | ||
1016 | } | ||
1017 | |||
1018 | err = clk_prepare_enable(chan->clk_apb); | ||
1019 | if (err) { | ||
1020 | clk_disable_unprepare(chan->clk_main); | ||
1021 | dev_err(&pdev->dev, "Unable to enable apb clock.\n"); | ||
1022 | return err; | ||
1023 | } | ||
1024 | |||
1025 | chan->desc_size = sizeof(struct zynqmp_dma_desc_ll); | ||
1026 | chan->idle = true; | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | /** | ||
1031 | * of_zynqmp_dma_xlate - Translation function | ||
1032 | * @dma_spec: Pointer to DMA specifier as found in the device tree | ||
1033 | * @ofdma: Pointer to DMA controller data | ||
1034 | * | ||
1035 | * Return: DMA channel pointer on success and NULL on error | ||
1036 | */ | ||
1037 | static struct dma_chan *of_zynqmp_dma_xlate(struct of_phandle_args *dma_spec, | ||
1038 | struct of_dma *ofdma) | ||
1039 | { | ||
1040 | struct zynqmp_dma_device *zdev = ofdma->of_dma_data; | ||
1041 | |||
1042 | return dma_get_slave_channel(&zdev->chan->common); | ||
1043 | } | ||
1044 | |||
1045 | /** | ||
1046 | * zynqmp_dma_probe - Driver probe function | ||
1047 | * @pdev: Pointer to the platform_device structure | ||
1048 | * | ||
1049 | * Return: '0' on success and failure value on error | ||
1050 | */ | ||
1051 | static int zynqmp_dma_probe(struct platform_device *pdev) | ||
1052 | { | ||
1053 | struct zynqmp_dma_device *zdev; | ||
1054 | struct dma_device *p; | ||
1055 | int ret; | ||
1056 | |||
1057 | zdev = devm_kzalloc(&pdev->dev, sizeof(*zdev), GFP_KERNEL); | ||
1058 | if (!zdev) | ||
1059 | return -ENOMEM; | ||
1060 | |||
1061 | zdev->dev = &pdev->dev; | ||
1062 | INIT_LIST_HEAD(&zdev->common.channels); | ||
1063 | |||
1064 | dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); | ||
1065 | dma_cap_set(DMA_SG, zdev->common.cap_mask); | ||
1066 | dma_cap_set(DMA_MEMCPY, zdev->common.cap_mask); | ||
1067 | |||
1068 | p = &zdev->common; | ||
1069 | p->device_prep_dma_sg = zynqmp_dma_prep_sg; | ||
1070 | p->device_prep_dma_memcpy = zynqmp_dma_prep_memcpy; | ||
1071 | p->device_terminate_all = zynqmp_dma_device_terminate_all; | ||
1072 | p->device_issue_pending = zynqmp_dma_issue_pending; | ||
1073 | p->device_alloc_chan_resources = zynqmp_dma_alloc_chan_resources; | ||
1074 | p->device_free_chan_resources = zynqmp_dma_free_chan_resources; | ||
1075 | p->device_tx_status = dma_cookie_status; | ||
1076 | p->device_config = zynqmp_dma_device_config; | ||
1077 | p->dev = &pdev->dev; | ||
1078 | |||
1079 | platform_set_drvdata(pdev, zdev); | ||
1080 | |||
1081 | ret = zynqmp_dma_chan_probe(zdev, pdev); | ||
1082 | if (ret) { | ||
1083 | dev_err(&pdev->dev, "Probing channel failed\n"); | ||
1084 | goto free_chan_resources; | ||
1085 | } | ||
1086 | |||
1087 | p->dst_addr_widths = BIT(zdev->chan->bus_width / 8); | ||
1088 | p->src_addr_widths = BIT(zdev->chan->bus_width / 8); | ||
1089 | |||
1090 | dma_async_device_register(&zdev->common); | ||
1091 | |||
1092 | ret = of_dma_controller_register(pdev->dev.of_node, | ||
1093 | of_zynqmp_dma_xlate, zdev); | ||
1094 | if (ret) { | ||
1095 | dev_err(&pdev->dev, "Unable to register DMA to DT\n"); | ||
1096 | dma_async_device_unregister(&zdev->common); | ||
1097 | goto free_chan_resources; | ||
1098 | } | ||
1099 | |||
1100 | dev_info(&pdev->dev, "ZynqMP DMA driver Probe success\n"); | ||
1101 | |||
1102 | return 0; | ||
1103 | |||
1104 | free_chan_resources: | ||
1105 | zynqmp_dma_chan_remove(zdev->chan); | ||
1106 | return ret; | ||
1107 | } | ||
1108 | |||
1109 | /** | ||
1110 | * zynqmp_dma_remove - Driver remove function | ||
1111 | * @pdev: Pointer to the platform_device structure | ||
1112 | * | ||
1113 | * Return: Always '0' | ||
1114 | */ | ||
1115 | static int zynqmp_dma_remove(struct platform_device *pdev) | ||
1116 | { | ||
1117 | struct zynqmp_dma_device *zdev = platform_get_drvdata(pdev); | ||
1118 | |||
1119 | of_dma_controller_free(pdev->dev.of_node); | ||
1120 | dma_async_device_unregister(&zdev->common); | ||
1121 | |||
1122 | zynqmp_dma_chan_remove(zdev->chan); | ||
1123 | |||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | static const struct of_device_id zynqmp_dma_of_match[] = { | ||
1128 | { .compatible = "xlnx,zynqmp-dma-1.0", }, | ||
1129 | {} | ||
1130 | }; | ||
1131 | MODULE_DEVICE_TABLE(of, zynqmp_dma_of_match); | ||
1132 | |||
1133 | static struct platform_driver zynqmp_dma_driver = { | ||
1134 | .driver = { | ||
1135 | .name = "xilinx-zynqmp-dma", | ||
1136 | .of_match_table = zynqmp_dma_of_match, | ||
1137 | }, | ||
1138 | .probe = zynqmp_dma_probe, | ||
1139 | .remove = zynqmp_dma_remove, | ||
1140 | }; | ||
1141 | |||
1142 | module_platform_driver(zynqmp_dma_driver); | ||
1143 | |||
1144 | MODULE_AUTHOR("Xilinx, Inc."); | ||
1145 | MODULE_DESCRIPTION("Xilinx ZynqMP DMA driver"); | ||