blob: 1be69b87a9130b9413b89514a8460cb58e8413e0 [file] [log] [blame]
Linus Walleij61f135b2009-11-19 19:49:17 +01001/*
2 * driver/dma/coh901318.c
3 *
4 * Copyright (C) 2007-2009 ST-Ericsson
5 * License terms: GNU General Public License (GPL) version 2
6 * DMA driver for COH 901 318
7 * Author: Per Friden <per.friden@stericsson.com>
8 */
9
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/kernel.h> /* printk() */
13#include <linux/fs.h> /* everything... */
Alexey Dobriyanb7f080c2011-06-16 11:01:34 +000014#include <linux/scatterlist.h>
Linus Walleij61f135b2009-11-19 19:49:17 +010015#include <linux/slab.h> /* kmalloc() */
16#include <linux/dmaengine.h>
17#include <linux/platform_device.h>
18#include <linux/device.h>
19#include <linux/irqreturn.h>
20#include <linux/interrupt.h>
21#include <linux/io.h>
22#include <linux/uaccess.h>
23#include <linux/debugfs.h>
Linus Walleij9f575d92013-01-04 10:35:06 +010024#include <linux/platform_data/dma-coh901318.h>
Linus Walleij61f135b2009-11-19 19:49:17 +010025
Linus Walleij2b9277a2013-01-04 13:56:16 +010026#include "coh901318.h"
Linus Walleij61f135b2009-11-19 19:49:17 +010027#include "coh901318_lli.h"
Russell King - ARM Linuxd2ebfb32012-03-06 22:34:26 +000028#include "dmaengine.h"
Linus Walleij61f135b2009-11-19 19:49:17 +010029
Linus Walleij24dbcd82013-01-04 13:38:18 +010030/* points out all dma slave channels.
31 * Syntax is [A1, B1, A2, B2, .... ,-1,-1]
32 * Select all channels from A to B, end of list is marked with -1,-1
33 */
34static int dma_slave_channels[] = {
35 U300_DMA_MSL_TX_0, U300_DMA_SPI_RX,
36 U300_DMA_UART1_TX, U300_DMA_UART1_RX, -1, -1};
37
38/* points out all dma memcpy channels. */
39static int dma_memcpy_channels[] = {
40 U300_DMA_GENERAL_PURPOSE_0, U300_DMA_GENERAL_PURPOSE_8, -1, -1};
41
42/** register dma for memory access
43 *
44 * active 1 means dma intends to access memory
45 * 0 means dma wont access memory
46 */
47static void coh901318_access_memory_state(struct device *dev, bool active)
48{
49}
50
51#define flags_memcpy_config (COH901318_CX_CFG_CH_DISABLE | \
52 COH901318_CX_CFG_RM_MEMORY_TO_MEMORY | \
53 COH901318_CX_CFG_LCR_DISABLE | \
54 COH901318_CX_CFG_TC_IRQ_ENABLE | \
55 COH901318_CX_CFG_BE_IRQ_ENABLE)
56#define flags_memcpy_lli_chained (COH901318_CX_CTRL_TC_ENABLE | \
57 COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \
58 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \
59 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \
60 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \
61 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \
62 COH901318_CX_CTRL_MASTER_MODE_M1RW | \
63 COH901318_CX_CTRL_TCP_DISABLE | \
64 COH901318_CX_CTRL_TC_IRQ_DISABLE | \
65 COH901318_CX_CTRL_HSP_DISABLE | \
66 COH901318_CX_CTRL_HSS_DISABLE | \
67 COH901318_CX_CTRL_DDMA_LEGACY | \
68 COH901318_CX_CTRL_PRDD_SOURCE)
69#define flags_memcpy_lli (COH901318_CX_CTRL_TC_ENABLE | \
70 COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \
71 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \
72 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \
73 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \
74 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \
75 COH901318_CX_CTRL_MASTER_MODE_M1RW | \
76 COH901318_CX_CTRL_TCP_DISABLE | \
77 COH901318_CX_CTRL_TC_IRQ_DISABLE | \
78 COH901318_CX_CTRL_HSP_DISABLE | \
79 COH901318_CX_CTRL_HSS_DISABLE | \
80 COH901318_CX_CTRL_DDMA_LEGACY | \
81 COH901318_CX_CTRL_PRDD_SOURCE)
82#define flags_memcpy_lli_last (COH901318_CX_CTRL_TC_ENABLE | \
83 COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \
84 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \
85 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \
86 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \
87 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \
88 COH901318_CX_CTRL_MASTER_MODE_M1RW | \
89 COH901318_CX_CTRL_TCP_DISABLE | \
90 COH901318_CX_CTRL_TC_IRQ_ENABLE | \
91 COH901318_CX_CTRL_HSP_DISABLE | \
92 COH901318_CX_CTRL_HSS_DISABLE | \
93 COH901318_CX_CTRL_DDMA_LEGACY | \
94 COH901318_CX_CTRL_PRDD_SOURCE)
95
96const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
97 {
98 .number = U300_DMA_MSL_TX_0,
99 .name = "MSL TX 0",
100 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100101 },
102 {
103 .number = U300_DMA_MSL_TX_1,
104 .name = "MSL TX 1",
105 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100106 .param.config = COH901318_CX_CFG_CH_DISABLE |
107 COH901318_CX_CFG_LCR_DISABLE |
108 COH901318_CX_CFG_TC_IRQ_ENABLE |
109 COH901318_CX_CFG_BE_IRQ_ENABLE,
110 .param.ctrl_lli_chained = 0 |
111 COH901318_CX_CTRL_TC_ENABLE |
112 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
113 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
114 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
115 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
116 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
117 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
118 COH901318_CX_CTRL_TCP_DISABLE |
119 COH901318_CX_CTRL_TC_IRQ_DISABLE |
120 COH901318_CX_CTRL_HSP_ENABLE |
121 COH901318_CX_CTRL_HSS_DISABLE |
122 COH901318_CX_CTRL_DDMA_LEGACY |
123 COH901318_CX_CTRL_PRDD_SOURCE,
124 .param.ctrl_lli = 0 |
125 COH901318_CX_CTRL_TC_ENABLE |
126 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
127 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
128 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
129 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
130 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
131 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
132 COH901318_CX_CTRL_TCP_ENABLE |
133 COH901318_CX_CTRL_TC_IRQ_DISABLE |
134 COH901318_CX_CTRL_HSP_ENABLE |
135 COH901318_CX_CTRL_HSS_DISABLE |
136 COH901318_CX_CTRL_DDMA_LEGACY |
137 COH901318_CX_CTRL_PRDD_SOURCE,
138 .param.ctrl_lli_last = 0 |
139 COH901318_CX_CTRL_TC_ENABLE |
140 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
141 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
142 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
143 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
144 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
145 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
146 COH901318_CX_CTRL_TCP_ENABLE |
147 COH901318_CX_CTRL_TC_IRQ_ENABLE |
148 COH901318_CX_CTRL_HSP_ENABLE |
149 COH901318_CX_CTRL_HSS_DISABLE |
150 COH901318_CX_CTRL_DDMA_LEGACY |
151 COH901318_CX_CTRL_PRDD_SOURCE,
152 },
153 {
154 .number = U300_DMA_MSL_TX_2,
155 .name = "MSL TX 2",
156 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100157 .param.config = COH901318_CX_CFG_CH_DISABLE |
158 COH901318_CX_CFG_LCR_DISABLE |
159 COH901318_CX_CFG_TC_IRQ_ENABLE |
160 COH901318_CX_CFG_BE_IRQ_ENABLE,
161 .param.ctrl_lli_chained = 0 |
162 COH901318_CX_CTRL_TC_ENABLE |
163 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
164 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
165 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
166 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
167 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
168 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
169 COH901318_CX_CTRL_TCP_DISABLE |
170 COH901318_CX_CTRL_TC_IRQ_DISABLE |
171 COH901318_CX_CTRL_HSP_ENABLE |
172 COH901318_CX_CTRL_HSS_DISABLE |
173 COH901318_CX_CTRL_DDMA_LEGACY |
174 COH901318_CX_CTRL_PRDD_SOURCE,
175 .param.ctrl_lli = 0 |
176 COH901318_CX_CTRL_TC_ENABLE |
177 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
178 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
179 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
180 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
181 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
182 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
183 COH901318_CX_CTRL_TCP_ENABLE |
184 COH901318_CX_CTRL_TC_IRQ_DISABLE |
185 COH901318_CX_CTRL_HSP_ENABLE |
186 COH901318_CX_CTRL_HSS_DISABLE |
187 COH901318_CX_CTRL_DDMA_LEGACY |
188 COH901318_CX_CTRL_PRDD_SOURCE,
189 .param.ctrl_lli_last = 0 |
190 COH901318_CX_CTRL_TC_ENABLE |
191 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
192 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
193 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
194 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
195 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
196 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
197 COH901318_CX_CTRL_TCP_ENABLE |
198 COH901318_CX_CTRL_TC_IRQ_ENABLE |
199 COH901318_CX_CTRL_HSP_ENABLE |
200 COH901318_CX_CTRL_HSS_DISABLE |
201 COH901318_CX_CTRL_DDMA_LEGACY |
202 COH901318_CX_CTRL_PRDD_SOURCE,
203 .desc_nbr_max = 10,
204 },
205 {
206 .number = U300_DMA_MSL_TX_3,
207 .name = "MSL TX 3",
208 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100209 .param.config = COH901318_CX_CFG_CH_DISABLE |
210 COH901318_CX_CFG_LCR_DISABLE |
211 COH901318_CX_CFG_TC_IRQ_ENABLE |
212 COH901318_CX_CFG_BE_IRQ_ENABLE,
213 .param.ctrl_lli_chained = 0 |
214 COH901318_CX_CTRL_TC_ENABLE |
215 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
216 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
217 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
218 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
219 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
220 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
221 COH901318_CX_CTRL_TCP_DISABLE |
222 COH901318_CX_CTRL_TC_IRQ_DISABLE |
223 COH901318_CX_CTRL_HSP_ENABLE |
224 COH901318_CX_CTRL_HSS_DISABLE |
225 COH901318_CX_CTRL_DDMA_LEGACY |
226 COH901318_CX_CTRL_PRDD_SOURCE,
227 .param.ctrl_lli = 0 |
228 COH901318_CX_CTRL_TC_ENABLE |
229 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
230 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
231 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
232 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
233 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
234 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
235 COH901318_CX_CTRL_TCP_ENABLE |
236 COH901318_CX_CTRL_TC_IRQ_DISABLE |
237 COH901318_CX_CTRL_HSP_ENABLE |
238 COH901318_CX_CTRL_HSS_DISABLE |
239 COH901318_CX_CTRL_DDMA_LEGACY |
240 COH901318_CX_CTRL_PRDD_SOURCE,
241 .param.ctrl_lli_last = 0 |
242 COH901318_CX_CTRL_TC_ENABLE |
243 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
244 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
245 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
246 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
247 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
248 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
249 COH901318_CX_CTRL_TCP_ENABLE |
250 COH901318_CX_CTRL_TC_IRQ_ENABLE |
251 COH901318_CX_CTRL_HSP_ENABLE |
252 COH901318_CX_CTRL_HSS_DISABLE |
253 COH901318_CX_CTRL_DDMA_LEGACY |
254 COH901318_CX_CTRL_PRDD_SOURCE,
255 },
256 {
257 .number = U300_DMA_MSL_TX_4,
258 .name = "MSL TX 4",
259 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100260 .param.config = COH901318_CX_CFG_CH_DISABLE |
261 COH901318_CX_CFG_LCR_DISABLE |
262 COH901318_CX_CFG_TC_IRQ_ENABLE |
263 COH901318_CX_CFG_BE_IRQ_ENABLE,
264 .param.ctrl_lli_chained = 0 |
265 COH901318_CX_CTRL_TC_ENABLE |
266 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
267 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
268 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
269 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
270 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
271 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
272 COH901318_CX_CTRL_TCP_DISABLE |
273 COH901318_CX_CTRL_TC_IRQ_DISABLE |
274 COH901318_CX_CTRL_HSP_ENABLE |
275 COH901318_CX_CTRL_HSS_DISABLE |
276 COH901318_CX_CTRL_DDMA_LEGACY |
277 COH901318_CX_CTRL_PRDD_SOURCE,
278 .param.ctrl_lli = 0 |
279 COH901318_CX_CTRL_TC_ENABLE |
280 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
281 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
282 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
283 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
284 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
285 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
286 COH901318_CX_CTRL_TCP_ENABLE |
287 COH901318_CX_CTRL_TC_IRQ_DISABLE |
288 COH901318_CX_CTRL_HSP_ENABLE |
289 COH901318_CX_CTRL_HSS_DISABLE |
290 COH901318_CX_CTRL_DDMA_LEGACY |
291 COH901318_CX_CTRL_PRDD_SOURCE,
292 .param.ctrl_lli_last = 0 |
293 COH901318_CX_CTRL_TC_ENABLE |
294 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
295 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
296 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
297 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
298 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
299 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
300 COH901318_CX_CTRL_TCP_ENABLE |
301 COH901318_CX_CTRL_TC_IRQ_ENABLE |
302 COH901318_CX_CTRL_HSP_ENABLE |
303 COH901318_CX_CTRL_HSS_DISABLE |
304 COH901318_CX_CTRL_DDMA_LEGACY |
305 COH901318_CX_CTRL_PRDD_SOURCE,
306 },
307 {
308 .number = U300_DMA_MSL_TX_5,
309 .name = "MSL TX 5",
310 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100311 },
312 {
313 .number = U300_DMA_MSL_TX_6,
314 .name = "MSL TX 6",
315 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100316 },
317 {
318 .number = U300_DMA_MSL_RX_0,
319 .name = "MSL RX 0",
320 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100321 },
322 {
323 .number = U300_DMA_MSL_RX_1,
324 .name = "MSL RX 1",
325 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100326 .param.config = COH901318_CX_CFG_CH_DISABLE |
327 COH901318_CX_CFG_LCR_DISABLE |
328 COH901318_CX_CFG_TC_IRQ_ENABLE |
329 COH901318_CX_CFG_BE_IRQ_ENABLE,
330 .param.ctrl_lli_chained = 0 |
331 COH901318_CX_CTRL_TC_ENABLE |
332 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
333 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
334 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
335 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
336 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
337 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
338 COH901318_CX_CTRL_TCP_DISABLE |
339 COH901318_CX_CTRL_TC_IRQ_DISABLE |
340 COH901318_CX_CTRL_HSP_ENABLE |
341 COH901318_CX_CTRL_HSS_DISABLE |
342 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
343 COH901318_CX_CTRL_PRDD_DEST,
344 .param.ctrl_lli = 0,
345 .param.ctrl_lli_last = 0 |
346 COH901318_CX_CTRL_TC_ENABLE |
347 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
348 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
349 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
350 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
351 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
352 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
353 COH901318_CX_CTRL_TCP_DISABLE |
354 COH901318_CX_CTRL_TC_IRQ_ENABLE |
355 COH901318_CX_CTRL_HSP_ENABLE |
356 COH901318_CX_CTRL_HSS_DISABLE |
357 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
358 COH901318_CX_CTRL_PRDD_DEST,
359 },
360 {
361 .number = U300_DMA_MSL_RX_2,
362 .name = "MSL RX 2",
363 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100364 .param.config = COH901318_CX_CFG_CH_DISABLE |
365 COH901318_CX_CFG_LCR_DISABLE |
366 COH901318_CX_CFG_TC_IRQ_ENABLE |
367 COH901318_CX_CFG_BE_IRQ_ENABLE,
368 .param.ctrl_lli_chained = 0 |
369 COH901318_CX_CTRL_TC_ENABLE |
370 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
371 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
372 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
373 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
374 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
375 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
376 COH901318_CX_CTRL_TCP_DISABLE |
377 COH901318_CX_CTRL_TC_IRQ_DISABLE |
378 COH901318_CX_CTRL_HSP_ENABLE |
379 COH901318_CX_CTRL_HSS_DISABLE |
380 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
381 COH901318_CX_CTRL_PRDD_DEST,
382 .param.ctrl_lli = 0 |
383 COH901318_CX_CTRL_TC_ENABLE |
384 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
385 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
386 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
387 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
388 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
389 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
390 COH901318_CX_CTRL_TCP_DISABLE |
391 COH901318_CX_CTRL_TC_IRQ_ENABLE |
392 COH901318_CX_CTRL_HSP_ENABLE |
393 COH901318_CX_CTRL_HSS_DISABLE |
394 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
395 COH901318_CX_CTRL_PRDD_DEST,
396 .param.ctrl_lli_last = 0 |
397 COH901318_CX_CTRL_TC_ENABLE |
398 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
399 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
400 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
401 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
402 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
403 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
404 COH901318_CX_CTRL_TCP_DISABLE |
405 COH901318_CX_CTRL_TC_IRQ_ENABLE |
406 COH901318_CX_CTRL_HSP_ENABLE |
407 COH901318_CX_CTRL_HSS_DISABLE |
408 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
409 COH901318_CX_CTRL_PRDD_DEST,
410 },
411 {
412 .number = U300_DMA_MSL_RX_3,
413 .name = "MSL RX 3",
414 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100415 .param.config = COH901318_CX_CFG_CH_DISABLE |
416 COH901318_CX_CFG_LCR_DISABLE |
417 COH901318_CX_CFG_TC_IRQ_ENABLE |
418 COH901318_CX_CFG_BE_IRQ_ENABLE,
419 .param.ctrl_lli_chained = 0 |
420 COH901318_CX_CTRL_TC_ENABLE |
421 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
422 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
423 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
424 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
425 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
426 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
427 COH901318_CX_CTRL_TCP_DISABLE |
428 COH901318_CX_CTRL_TC_IRQ_DISABLE |
429 COH901318_CX_CTRL_HSP_ENABLE |
430 COH901318_CX_CTRL_HSS_DISABLE |
431 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
432 COH901318_CX_CTRL_PRDD_DEST,
433 .param.ctrl_lli = 0 |
434 COH901318_CX_CTRL_TC_ENABLE |
435 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
436 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
437 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
438 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
439 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
440 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
441 COH901318_CX_CTRL_TCP_DISABLE |
442 COH901318_CX_CTRL_TC_IRQ_ENABLE |
443 COH901318_CX_CTRL_HSP_ENABLE |
444 COH901318_CX_CTRL_HSS_DISABLE |
445 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
446 COH901318_CX_CTRL_PRDD_DEST,
447 .param.ctrl_lli_last = 0 |
448 COH901318_CX_CTRL_TC_ENABLE |
449 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
450 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
451 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
452 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
453 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
454 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
455 COH901318_CX_CTRL_TCP_DISABLE |
456 COH901318_CX_CTRL_TC_IRQ_ENABLE |
457 COH901318_CX_CTRL_HSP_ENABLE |
458 COH901318_CX_CTRL_HSS_DISABLE |
459 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
460 COH901318_CX_CTRL_PRDD_DEST,
461 },
462 {
463 .number = U300_DMA_MSL_RX_4,
464 .name = "MSL RX 4",
465 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100466 .param.config = COH901318_CX_CFG_CH_DISABLE |
467 COH901318_CX_CFG_LCR_DISABLE |
468 COH901318_CX_CFG_TC_IRQ_ENABLE |
469 COH901318_CX_CFG_BE_IRQ_ENABLE,
470 .param.ctrl_lli_chained = 0 |
471 COH901318_CX_CTRL_TC_ENABLE |
472 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
473 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
474 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
475 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
476 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
477 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
478 COH901318_CX_CTRL_TCP_DISABLE |
479 COH901318_CX_CTRL_TC_IRQ_DISABLE |
480 COH901318_CX_CTRL_HSP_ENABLE |
481 COH901318_CX_CTRL_HSS_DISABLE |
482 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
483 COH901318_CX_CTRL_PRDD_DEST,
484 .param.ctrl_lli = 0 |
485 COH901318_CX_CTRL_TC_ENABLE |
486 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
487 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
488 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
489 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
490 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
491 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
492 COH901318_CX_CTRL_TCP_DISABLE |
493 COH901318_CX_CTRL_TC_IRQ_ENABLE |
494 COH901318_CX_CTRL_HSP_ENABLE |
495 COH901318_CX_CTRL_HSS_DISABLE |
496 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
497 COH901318_CX_CTRL_PRDD_DEST,
498 .param.ctrl_lli_last = 0 |
499 COH901318_CX_CTRL_TC_ENABLE |
500 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
501 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
502 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
503 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
504 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
505 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
506 COH901318_CX_CTRL_TCP_DISABLE |
507 COH901318_CX_CTRL_TC_IRQ_ENABLE |
508 COH901318_CX_CTRL_HSP_ENABLE |
509 COH901318_CX_CTRL_HSS_DISABLE |
510 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
511 COH901318_CX_CTRL_PRDD_DEST,
512 },
513 {
514 .number = U300_DMA_MSL_RX_5,
515 .name = "MSL RX 5",
516 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100517 .param.config = COH901318_CX_CFG_CH_DISABLE |
518 COH901318_CX_CFG_LCR_DISABLE |
519 COH901318_CX_CFG_TC_IRQ_ENABLE |
520 COH901318_CX_CFG_BE_IRQ_ENABLE,
521 .param.ctrl_lli_chained = 0 |
522 COH901318_CX_CTRL_TC_ENABLE |
523 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
524 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
525 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
526 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
527 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
528 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
529 COH901318_CX_CTRL_TCP_DISABLE |
530 COH901318_CX_CTRL_TC_IRQ_DISABLE |
531 COH901318_CX_CTRL_HSP_ENABLE |
532 COH901318_CX_CTRL_HSS_DISABLE |
533 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
534 COH901318_CX_CTRL_PRDD_DEST,
535 .param.ctrl_lli = 0 |
536 COH901318_CX_CTRL_TC_ENABLE |
537 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
538 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
539 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
540 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
541 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
542 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
543 COH901318_CX_CTRL_TCP_DISABLE |
544 COH901318_CX_CTRL_TC_IRQ_ENABLE |
545 COH901318_CX_CTRL_HSP_ENABLE |
546 COH901318_CX_CTRL_HSS_DISABLE |
547 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
548 COH901318_CX_CTRL_PRDD_DEST,
549 .param.ctrl_lli_last = 0 |
550 COH901318_CX_CTRL_TC_ENABLE |
551 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
552 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
553 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
554 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
555 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
556 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
557 COH901318_CX_CTRL_TCP_DISABLE |
558 COH901318_CX_CTRL_TC_IRQ_ENABLE |
559 COH901318_CX_CTRL_HSP_ENABLE |
560 COH901318_CX_CTRL_HSS_DISABLE |
561 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
562 COH901318_CX_CTRL_PRDD_DEST,
563 },
564 {
565 .number = U300_DMA_MSL_RX_6,
566 .name = "MSL RX 6",
567 .priority_high = 0,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100568 },
569 /*
570 * Don't set up device address, burst count or size of src
571 * or dst bus for this peripheral - handled by PrimeCell
572 * DMA extension.
573 */
574 {
575 .number = U300_DMA_MMCSD_RX_TX,
576 .name = "MMCSD RX TX",
577 .priority_high = 0,
578 .param.config = COH901318_CX_CFG_CH_DISABLE |
579 COH901318_CX_CFG_LCR_DISABLE |
580 COH901318_CX_CFG_TC_IRQ_ENABLE |
581 COH901318_CX_CFG_BE_IRQ_ENABLE,
582 .param.ctrl_lli_chained = 0 |
583 COH901318_CX_CTRL_TC_ENABLE |
584 COH901318_CX_CTRL_MASTER_MODE_M1RW |
585 COH901318_CX_CTRL_TCP_ENABLE |
586 COH901318_CX_CTRL_TC_IRQ_DISABLE |
587 COH901318_CX_CTRL_HSP_ENABLE |
588 COH901318_CX_CTRL_HSS_DISABLE |
589 COH901318_CX_CTRL_DDMA_LEGACY,
590 .param.ctrl_lli = 0 |
591 COH901318_CX_CTRL_TC_ENABLE |
592 COH901318_CX_CTRL_MASTER_MODE_M1RW |
593 COH901318_CX_CTRL_TCP_ENABLE |
594 COH901318_CX_CTRL_TC_IRQ_DISABLE |
595 COH901318_CX_CTRL_HSP_ENABLE |
596 COH901318_CX_CTRL_HSS_DISABLE |
597 COH901318_CX_CTRL_DDMA_LEGACY,
598 .param.ctrl_lli_last = 0 |
599 COH901318_CX_CTRL_TC_ENABLE |
600 COH901318_CX_CTRL_MASTER_MODE_M1RW |
601 COH901318_CX_CTRL_TCP_DISABLE |
602 COH901318_CX_CTRL_TC_IRQ_ENABLE |
603 COH901318_CX_CTRL_HSP_ENABLE |
604 COH901318_CX_CTRL_HSS_DISABLE |
605 COH901318_CX_CTRL_DDMA_LEGACY,
606
607 },
608 {
609 .number = U300_DMA_MSPRO_TX,
610 .name = "MSPRO TX",
611 .priority_high = 0,
612 },
613 {
614 .number = U300_DMA_MSPRO_RX,
615 .name = "MSPRO RX",
616 .priority_high = 0,
617 },
618 /*
619 * Don't set up device address, burst count or size of src
620 * or dst bus for this peripheral - handled by PrimeCell
621 * DMA extension.
622 */
623 {
624 .number = U300_DMA_UART0_TX,
625 .name = "UART0 TX",
626 .priority_high = 0,
627 .param.config = COH901318_CX_CFG_CH_DISABLE |
628 COH901318_CX_CFG_LCR_DISABLE |
629 COH901318_CX_CFG_TC_IRQ_ENABLE |
630 COH901318_CX_CFG_BE_IRQ_ENABLE,
631 .param.ctrl_lli_chained = 0 |
632 COH901318_CX_CTRL_TC_ENABLE |
633 COH901318_CX_CTRL_MASTER_MODE_M1RW |
634 COH901318_CX_CTRL_TCP_ENABLE |
635 COH901318_CX_CTRL_TC_IRQ_DISABLE |
636 COH901318_CX_CTRL_HSP_ENABLE |
637 COH901318_CX_CTRL_HSS_DISABLE |
638 COH901318_CX_CTRL_DDMA_LEGACY,
639 .param.ctrl_lli = 0 |
640 COH901318_CX_CTRL_TC_ENABLE |
641 COH901318_CX_CTRL_MASTER_MODE_M1RW |
642 COH901318_CX_CTRL_TCP_ENABLE |
643 COH901318_CX_CTRL_TC_IRQ_ENABLE |
644 COH901318_CX_CTRL_HSP_ENABLE |
645 COH901318_CX_CTRL_HSS_DISABLE |
646 COH901318_CX_CTRL_DDMA_LEGACY,
647 .param.ctrl_lli_last = 0 |
648 COH901318_CX_CTRL_TC_ENABLE |
649 COH901318_CX_CTRL_MASTER_MODE_M1RW |
650 COH901318_CX_CTRL_TCP_ENABLE |
651 COH901318_CX_CTRL_TC_IRQ_ENABLE |
652 COH901318_CX_CTRL_HSP_ENABLE |
653 COH901318_CX_CTRL_HSS_DISABLE |
654 COH901318_CX_CTRL_DDMA_LEGACY,
655 },
656 {
657 .number = U300_DMA_UART0_RX,
658 .name = "UART0 RX",
659 .priority_high = 0,
660 .param.config = COH901318_CX_CFG_CH_DISABLE |
661 COH901318_CX_CFG_LCR_DISABLE |
662 COH901318_CX_CFG_TC_IRQ_ENABLE |
663 COH901318_CX_CFG_BE_IRQ_ENABLE,
664 .param.ctrl_lli_chained = 0 |
665 COH901318_CX_CTRL_TC_ENABLE |
666 COH901318_CX_CTRL_MASTER_MODE_M1RW |
667 COH901318_CX_CTRL_TCP_ENABLE |
668 COH901318_CX_CTRL_TC_IRQ_DISABLE |
669 COH901318_CX_CTRL_HSP_ENABLE |
670 COH901318_CX_CTRL_HSS_DISABLE |
671 COH901318_CX_CTRL_DDMA_LEGACY,
672 .param.ctrl_lli = 0 |
673 COH901318_CX_CTRL_TC_ENABLE |
674 COH901318_CX_CTRL_MASTER_MODE_M1RW |
675 COH901318_CX_CTRL_TCP_ENABLE |
676 COH901318_CX_CTRL_TC_IRQ_ENABLE |
677 COH901318_CX_CTRL_HSP_ENABLE |
678 COH901318_CX_CTRL_HSS_DISABLE |
679 COH901318_CX_CTRL_DDMA_LEGACY,
680 .param.ctrl_lli_last = 0 |
681 COH901318_CX_CTRL_TC_ENABLE |
682 COH901318_CX_CTRL_MASTER_MODE_M1RW |
683 COH901318_CX_CTRL_TCP_ENABLE |
684 COH901318_CX_CTRL_TC_IRQ_ENABLE |
685 COH901318_CX_CTRL_HSP_ENABLE |
686 COH901318_CX_CTRL_HSS_DISABLE |
687 COH901318_CX_CTRL_DDMA_LEGACY,
688 },
689 {
690 .number = U300_DMA_APEX_TX,
691 .name = "APEX TX",
692 .priority_high = 0,
693 },
694 {
695 .number = U300_DMA_APEX_RX,
696 .name = "APEX RX",
697 .priority_high = 0,
698 },
699 {
700 .number = U300_DMA_PCM_I2S0_TX,
701 .name = "PCM I2S0 TX",
702 .priority_high = 1,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100703 .param.config = COH901318_CX_CFG_CH_DISABLE |
704 COH901318_CX_CFG_LCR_DISABLE |
705 COH901318_CX_CFG_TC_IRQ_ENABLE |
706 COH901318_CX_CFG_BE_IRQ_ENABLE,
707 .param.ctrl_lli_chained = 0 |
708 COH901318_CX_CTRL_TC_ENABLE |
709 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
710 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
711 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
712 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
713 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
714 COH901318_CX_CTRL_MASTER_MODE_M1RW |
715 COH901318_CX_CTRL_TCP_DISABLE |
716 COH901318_CX_CTRL_TC_IRQ_DISABLE |
717 COH901318_CX_CTRL_HSP_ENABLE |
718 COH901318_CX_CTRL_HSS_DISABLE |
719 COH901318_CX_CTRL_DDMA_LEGACY |
720 COH901318_CX_CTRL_PRDD_SOURCE,
721 .param.ctrl_lli = 0 |
722 COH901318_CX_CTRL_TC_ENABLE |
723 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
724 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
725 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
726 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
727 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
728 COH901318_CX_CTRL_MASTER_MODE_M1RW |
729 COH901318_CX_CTRL_TCP_ENABLE |
730 COH901318_CX_CTRL_TC_IRQ_DISABLE |
731 COH901318_CX_CTRL_HSP_ENABLE |
732 COH901318_CX_CTRL_HSS_DISABLE |
733 COH901318_CX_CTRL_DDMA_LEGACY |
734 COH901318_CX_CTRL_PRDD_SOURCE,
735 .param.ctrl_lli_last = 0 |
736 COH901318_CX_CTRL_TC_ENABLE |
737 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
738 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
739 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
740 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
741 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
742 COH901318_CX_CTRL_MASTER_MODE_M1RW |
743 COH901318_CX_CTRL_TCP_ENABLE |
744 COH901318_CX_CTRL_TC_IRQ_DISABLE |
745 COH901318_CX_CTRL_HSP_ENABLE |
746 COH901318_CX_CTRL_HSS_DISABLE |
747 COH901318_CX_CTRL_DDMA_LEGACY |
748 COH901318_CX_CTRL_PRDD_SOURCE,
749 },
750 {
751 .number = U300_DMA_PCM_I2S0_RX,
752 .name = "PCM I2S0 RX",
753 .priority_high = 1,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100754 .param.config = COH901318_CX_CFG_CH_DISABLE |
755 COH901318_CX_CFG_LCR_DISABLE |
756 COH901318_CX_CFG_TC_IRQ_ENABLE |
757 COH901318_CX_CFG_BE_IRQ_ENABLE,
758 .param.ctrl_lli_chained = 0 |
759 COH901318_CX_CTRL_TC_ENABLE |
760 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
761 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
762 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
763 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
764 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
765 COH901318_CX_CTRL_MASTER_MODE_M1RW |
766 COH901318_CX_CTRL_TCP_DISABLE |
767 COH901318_CX_CTRL_TC_IRQ_DISABLE |
768 COH901318_CX_CTRL_HSP_ENABLE |
769 COH901318_CX_CTRL_HSS_DISABLE |
770 COH901318_CX_CTRL_DDMA_LEGACY |
771 COH901318_CX_CTRL_PRDD_DEST,
772 .param.ctrl_lli = 0 |
773 COH901318_CX_CTRL_TC_ENABLE |
774 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
775 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
776 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
777 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
778 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
779 COH901318_CX_CTRL_MASTER_MODE_M1RW |
780 COH901318_CX_CTRL_TCP_ENABLE |
781 COH901318_CX_CTRL_TC_IRQ_DISABLE |
782 COH901318_CX_CTRL_HSP_ENABLE |
783 COH901318_CX_CTRL_HSS_DISABLE |
784 COH901318_CX_CTRL_DDMA_LEGACY |
785 COH901318_CX_CTRL_PRDD_DEST,
786 .param.ctrl_lli_last = 0 |
787 COH901318_CX_CTRL_TC_ENABLE |
788 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
789 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
790 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
791 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
792 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
793 COH901318_CX_CTRL_MASTER_MODE_M1RW |
794 COH901318_CX_CTRL_TCP_ENABLE |
795 COH901318_CX_CTRL_TC_IRQ_ENABLE |
796 COH901318_CX_CTRL_HSP_ENABLE |
797 COH901318_CX_CTRL_HSS_DISABLE |
798 COH901318_CX_CTRL_DDMA_LEGACY |
799 COH901318_CX_CTRL_PRDD_DEST,
800 },
801 {
802 .number = U300_DMA_PCM_I2S1_TX,
803 .name = "PCM I2S1 TX",
804 .priority_high = 1,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100805 .param.config = COH901318_CX_CFG_CH_DISABLE |
806 COH901318_CX_CFG_LCR_DISABLE |
807 COH901318_CX_CFG_TC_IRQ_ENABLE |
808 COH901318_CX_CFG_BE_IRQ_ENABLE,
809 .param.ctrl_lli_chained = 0 |
810 COH901318_CX_CTRL_TC_ENABLE |
811 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
812 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
813 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
814 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
815 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
816 COH901318_CX_CTRL_MASTER_MODE_M1RW |
817 COH901318_CX_CTRL_TCP_DISABLE |
818 COH901318_CX_CTRL_TC_IRQ_DISABLE |
819 COH901318_CX_CTRL_HSP_ENABLE |
820 COH901318_CX_CTRL_HSS_DISABLE |
821 COH901318_CX_CTRL_DDMA_LEGACY |
822 COH901318_CX_CTRL_PRDD_SOURCE,
823 .param.ctrl_lli = 0 |
824 COH901318_CX_CTRL_TC_ENABLE |
825 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
826 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
827 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
828 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
829 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
830 COH901318_CX_CTRL_MASTER_MODE_M1RW |
831 COH901318_CX_CTRL_TCP_ENABLE |
832 COH901318_CX_CTRL_TC_IRQ_DISABLE |
833 COH901318_CX_CTRL_HSP_ENABLE |
834 COH901318_CX_CTRL_HSS_DISABLE |
835 COH901318_CX_CTRL_DDMA_LEGACY |
836 COH901318_CX_CTRL_PRDD_SOURCE,
837 .param.ctrl_lli_last = 0 |
838 COH901318_CX_CTRL_TC_ENABLE |
839 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
840 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
841 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
842 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
843 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
844 COH901318_CX_CTRL_MASTER_MODE_M1RW |
845 COH901318_CX_CTRL_TCP_ENABLE |
846 COH901318_CX_CTRL_TC_IRQ_ENABLE |
847 COH901318_CX_CTRL_HSP_ENABLE |
848 COH901318_CX_CTRL_HSS_DISABLE |
849 COH901318_CX_CTRL_DDMA_LEGACY |
850 COH901318_CX_CTRL_PRDD_SOURCE,
851 },
852 {
853 .number = U300_DMA_PCM_I2S1_RX,
854 .name = "PCM I2S1 RX",
855 .priority_high = 1,
Linus Walleij24dbcd82013-01-04 13:38:18 +0100856 .param.config = COH901318_CX_CFG_CH_DISABLE |
857 COH901318_CX_CFG_LCR_DISABLE |
858 COH901318_CX_CFG_TC_IRQ_ENABLE |
859 COH901318_CX_CFG_BE_IRQ_ENABLE,
860 .param.ctrl_lli_chained = 0 |
861 COH901318_CX_CTRL_TC_ENABLE |
862 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
863 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
864 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
865 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
866 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
867 COH901318_CX_CTRL_MASTER_MODE_M1RW |
868 COH901318_CX_CTRL_TCP_DISABLE |
869 COH901318_CX_CTRL_TC_IRQ_DISABLE |
870 COH901318_CX_CTRL_HSP_ENABLE |
871 COH901318_CX_CTRL_HSS_DISABLE |
872 COH901318_CX_CTRL_DDMA_LEGACY |
873 COH901318_CX_CTRL_PRDD_DEST,
874 .param.ctrl_lli = 0 |
875 COH901318_CX_CTRL_TC_ENABLE |
876 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
877 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
878 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
879 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
880 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
881 COH901318_CX_CTRL_MASTER_MODE_M1RW |
882 COH901318_CX_CTRL_TCP_ENABLE |
883 COH901318_CX_CTRL_TC_IRQ_DISABLE |
884 COH901318_CX_CTRL_HSP_ENABLE |
885 COH901318_CX_CTRL_HSS_DISABLE |
886 COH901318_CX_CTRL_DDMA_LEGACY |
887 COH901318_CX_CTRL_PRDD_DEST,
888 .param.ctrl_lli_last = 0 |
889 COH901318_CX_CTRL_TC_ENABLE |
890 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
891 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
892 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
893 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
894 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
895 COH901318_CX_CTRL_MASTER_MODE_M1RW |
896 COH901318_CX_CTRL_TCP_ENABLE |
897 COH901318_CX_CTRL_TC_IRQ_ENABLE |
898 COH901318_CX_CTRL_HSP_ENABLE |
899 COH901318_CX_CTRL_HSS_DISABLE |
900 COH901318_CX_CTRL_DDMA_LEGACY |
901 COH901318_CX_CTRL_PRDD_DEST,
902 },
903 {
904 .number = U300_DMA_XGAM_CDI,
905 .name = "XGAM CDI",
906 .priority_high = 0,
907 },
908 {
909 .number = U300_DMA_XGAM_PDI,
910 .name = "XGAM PDI",
911 .priority_high = 0,
912 },
913 /*
914 * Don't set up device address, burst count or size of src
915 * or dst bus for this peripheral - handled by PrimeCell
916 * DMA extension.
917 */
918 {
919 .number = U300_DMA_SPI_TX,
920 .name = "SPI TX",
921 .priority_high = 0,
922 .param.config = COH901318_CX_CFG_CH_DISABLE |
923 COH901318_CX_CFG_LCR_DISABLE |
924 COH901318_CX_CFG_TC_IRQ_ENABLE |
925 COH901318_CX_CFG_BE_IRQ_ENABLE,
926 .param.ctrl_lli_chained = 0 |
927 COH901318_CX_CTRL_TC_ENABLE |
928 COH901318_CX_CTRL_MASTER_MODE_M1RW |
929 COH901318_CX_CTRL_TCP_DISABLE |
930 COH901318_CX_CTRL_TC_IRQ_DISABLE |
931 COH901318_CX_CTRL_HSP_ENABLE |
932 COH901318_CX_CTRL_HSS_DISABLE |
933 COH901318_CX_CTRL_DDMA_LEGACY,
934 .param.ctrl_lli = 0 |
935 COH901318_CX_CTRL_TC_ENABLE |
936 COH901318_CX_CTRL_MASTER_MODE_M1RW |
937 COH901318_CX_CTRL_TCP_DISABLE |
938 COH901318_CX_CTRL_TC_IRQ_ENABLE |
939 COH901318_CX_CTRL_HSP_ENABLE |
940 COH901318_CX_CTRL_HSS_DISABLE |
941 COH901318_CX_CTRL_DDMA_LEGACY,
942 .param.ctrl_lli_last = 0 |
943 COH901318_CX_CTRL_TC_ENABLE |
944 COH901318_CX_CTRL_MASTER_MODE_M1RW |
945 COH901318_CX_CTRL_TCP_DISABLE |
946 COH901318_CX_CTRL_TC_IRQ_ENABLE |
947 COH901318_CX_CTRL_HSP_ENABLE |
948 COH901318_CX_CTRL_HSS_DISABLE |
949 COH901318_CX_CTRL_DDMA_LEGACY,
950 },
951 {
952 .number = U300_DMA_SPI_RX,
953 .name = "SPI RX",
954 .priority_high = 0,
955 .param.config = COH901318_CX_CFG_CH_DISABLE |
956 COH901318_CX_CFG_LCR_DISABLE |
957 COH901318_CX_CFG_TC_IRQ_ENABLE |
958 COH901318_CX_CFG_BE_IRQ_ENABLE,
959 .param.ctrl_lli_chained = 0 |
960 COH901318_CX_CTRL_TC_ENABLE |
961 COH901318_CX_CTRL_MASTER_MODE_M1RW |
962 COH901318_CX_CTRL_TCP_DISABLE |
963 COH901318_CX_CTRL_TC_IRQ_DISABLE |
964 COH901318_CX_CTRL_HSP_ENABLE |
965 COH901318_CX_CTRL_HSS_DISABLE |
966 COH901318_CX_CTRL_DDMA_LEGACY,
967 .param.ctrl_lli = 0 |
968 COH901318_CX_CTRL_TC_ENABLE |
969 COH901318_CX_CTRL_MASTER_MODE_M1RW |
970 COH901318_CX_CTRL_TCP_DISABLE |
971 COH901318_CX_CTRL_TC_IRQ_ENABLE |
972 COH901318_CX_CTRL_HSP_ENABLE |
973 COH901318_CX_CTRL_HSS_DISABLE |
974 COH901318_CX_CTRL_DDMA_LEGACY,
975 .param.ctrl_lli_last = 0 |
976 COH901318_CX_CTRL_TC_ENABLE |
977 COH901318_CX_CTRL_MASTER_MODE_M1RW |
978 COH901318_CX_CTRL_TCP_DISABLE |
979 COH901318_CX_CTRL_TC_IRQ_ENABLE |
980 COH901318_CX_CTRL_HSP_ENABLE |
981 COH901318_CX_CTRL_HSS_DISABLE |
982 COH901318_CX_CTRL_DDMA_LEGACY,
983
984 },
985 {
986 .number = U300_DMA_GENERAL_PURPOSE_0,
987 .name = "GENERAL 00",
988 .priority_high = 0,
989
990 .param.config = flags_memcpy_config,
991 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
992 .param.ctrl_lli = flags_memcpy_lli,
993 .param.ctrl_lli_last = flags_memcpy_lli_last,
994 },
995 {
996 .number = U300_DMA_GENERAL_PURPOSE_1,
997 .name = "GENERAL 01",
998 .priority_high = 0,
999
1000 .param.config = flags_memcpy_config,
1001 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1002 .param.ctrl_lli = flags_memcpy_lli,
1003 .param.ctrl_lli_last = flags_memcpy_lli_last,
1004 },
1005 {
1006 .number = U300_DMA_GENERAL_PURPOSE_2,
1007 .name = "GENERAL 02",
1008 .priority_high = 0,
1009
1010 .param.config = flags_memcpy_config,
1011 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1012 .param.ctrl_lli = flags_memcpy_lli,
1013 .param.ctrl_lli_last = flags_memcpy_lli_last,
1014 },
1015 {
1016 .number = U300_DMA_GENERAL_PURPOSE_3,
1017 .name = "GENERAL 03",
1018 .priority_high = 0,
1019
1020 .param.config = flags_memcpy_config,
1021 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1022 .param.ctrl_lli = flags_memcpy_lli,
1023 .param.ctrl_lli_last = flags_memcpy_lli_last,
1024 },
1025 {
1026 .number = U300_DMA_GENERAL_PURPOSE_4,
1027 .name = "GENERAL 04",
1028 .priority_high = 0,
1029
1030 .param.config = flags_memcpy_config,
1031 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1032 .param.ctrl_lli = flags_memcpy_lli,
1033 .param.ctrl_lli_last = flags_memcpy_lli_last,
1034 },
1035 {
1036 .number = U300_DMA_GENERAL_PURPOSE_5,
1037 .name = "GENERAL 05",
1038 .priority_high = 0,
1039
1040 .param.config = flags_memcpy_config,
1041 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1042 .param.ctrl_lli = flags_memcpy_lli,
1043 .param.ctrl_lli_last = flags_memcpy_lli_last,
1044 },
1045 {
1046 .number = U300_DMA_GENERAL_PURPOSE_6,
1047 .name = "GENERAL 06",
1048 .priority_high = 0,
1049
1050 .param.config = flags_memcpy_config,
1051 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1052 .param.ctrl_lli = flags_memcpy_lli,
1053 .param.ctrl_lli_last = flags_memcpy_lli_last,
1054 },
1055 {
1056 .number = U300_DMA_GENERAL_PURPOSE_7,
1057 .name = "GENERAL 07",
1058 .priority_high = 0,
1059
1060 .param.config = flags_memcpy_config,
1061 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1062 .param.ctrl_lli = flags_memcpy_lli,
1063 .param.ctrl_lli_last = flags_memcpy_lli_last,
1064 },
1065 {
1066 .number = U300_DMA_GENERAL_PURPOSE_8,
1067 .name = "GENERAL 08",
1068 .priority_high = 0,
1069
1070 .param.config = flags_memcpy_config,
1071 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1072 .param.ctrl_lli = flags_memcpy_lli,
1073 .param.ctrl_lli_last = flags_memcpy_lli_last,
1074 },
1075 {
1076 .number = U300_DMA_UART1_TX,
1077 .name = "UART1 TX",
1078 .priority_high = 0,
1079 },
1080 {
1081 .number = U300_DMA_UART1_RX,
1082 .name = "UART1 RX",
1083 .priority_high = 0,
1084 }
1085};
1086
1087static struct coh901318_platform coh901318_platform = {
1088 .chans_slave = dma_slave_channels,
1089 .chans_memcpy = dma_memcpy_channels,
1090 .access_memory_state = coh901318_access_memory_state,
1091 .chan_conf = chan_config,
1092 .max_channels = U300_DMA_CHANNELS,
1093};
1094
Linus Walleij61f135b2009-11-19 19:49:17 +01001095#define COHC_2_DEV(cohc) (&cohc->chan.dev->device)
1096
1097#ifdef VERBOSE_DEBUG
1098#define COH_DBG(x) ({ if (1) x; 0; })
1099#else
1100#define COH_DBG(x) ({ if (0) x; 0; })
1101#endif
1102
1103struct coh901318_desc {
1104 struct dma_async_tx_descriptor desc;
1105 struct list_head node;
1106 struct scatterlist *sg;
1107 unsigned int sg_len;
Linus Walleijcecd87d2010-03-04 14:31:47 +01001108 struct coh901318_lli *lli;
Vinod Kouldb8196d2011-10-13 22:34:23 +05301109 enum dma_transfer_direction dir;
Linus Walleij61f135b2009-11-19 19:49:17 +01001110 unsigned long flags;
Linus Walleijb89243d2011-07-01 16:47:28 +02001111 u32 head_config;
1112 u32 head_ctrl;
Linus Walleij61f135b2009-11-19 19:49:17 +01001113};
1114
1115struct coh901318_base {
1116 struct device *dev;
1117 void __iomem *virtbase;
1118 struct coh901318_pool pool;
1119 struct powersave pm;
1120 struct dma_device dma_slave;
1121 struct dma_device dma_memcpy;
1122 struct coh901318_chan *chans;
1123 struct coh901318_platform *platform;
1124};
1125
1126struct coh901318_chan {
1127 spinlock_t lock;
1128 int allocated;
Linus Walleij61f135b2009-11-19 19:49:17 +01001129 int id;
1130 int stopped;
1131
1132 struct work_struct free_work;
1133 struct dma_chan chan;
1134
1135 struct tasklet_struct tasklet;
1136
1137 struct list_head active;
1138 struct list_head queue;
1139 struct list_head free;
1140
1141 unsigned long nbr_active_done;
1142 unsigned long busy;
Linus Walleij61f135b2009-11-19 19:49:17 +01001143
Linus Walleij9aab4d62013-01-04 13:50:49 +01001144 u32 addr;
1145 u32 ctrl;
Linus Walleij128f9042010-08-04 13:37:53 +02001146
Linus Walleij61f135b2009-11-19 19:49:17 +01001147 struct coh901318_base *base;
1148};
1149
1150static void coh901318_list_print(struct coh901318_chan *cohc,
1151 struct coh901318_lli *lli)
1152{
Linus Walleij848ad122010-03-02 14:17:15 -07001153 struct coh901318_lli *l = lli;
Linus Walleij61f135b2009-11-19 19:49:17 +01001154 int i = 0;
1155
Linus Walleij848ad122010-03-02 14:17:15 -07001156 while (l) {
Linus Walleij61f135b2009-11-19 19:49:17 +01001157 dev_vdbg(COHC_2_DEV(cohc), "i %d, lli %p, ctrl 0x%x, src 0x%x"
Linus Walleij848ad122010-03-02 14:17:15 -07001158 ", dst 0x%x, link 0x%x virt_link_addr 0x%p\n",
Linus Walleij61f135b2009-11-19 19:49:17 +01001159 i, l, l->control, l->src_addr, l->dst_addr,
Linus Walleij848ad122010-03-02 14:17:15 -07001160 l->link_addr, l->virt_link_addr);
Linus Walleij61f135b2009-11-19 19:49:17 +01001161 i++;
Linus Walleij848ad122010-03-02 14:17:15 -07001162 l = l->virt_link_addr;
Linus Walleij61f135b2009-11-19 19:49:17 +01001163 }
1164}
1165
1166#ifdef CONFIG_DEBUG_FS
1167
1168#define COH901318_DEBUGFS_ASSIGN(x, y) (x = y)
1169
1170static struct coh901318_base *debugfs_dma_base;
1171static struct dentry *dma_dentry;
1172
Linus Walleij61f135b2009-11-19 19:49:17 +01001173static int coh901318_debugfs_read(struct file *file, char __user *buf,
1174 size_t count, loff_t *f_pos)
1175{
1176 u64 started_channels = debugfs_dma_base->pm.started_channels;
1177 int pool_count = debugfs_dma_base->pool.debugfs_pool_counter;
1178 int i;
1179 int ret = 0;
1180 char *dev_buf;
1181 char *tmp;
1182 int dev_size;
1183
1184 dev_buf = kmalloc(4*1024, GFP_KERNEL);
1185 if (dev_buf == NULL)
1186 goto err_kmalloc;
1187 tmp = dev_buf;
1188
Linus Walleij848ad122010-03-02 14:17:15 -07001189 tmp += sprintf(tmp, "DMA -- enabled dma channels\n");
Linus Walleij61f135b2009-11-19 19:49:17 +01001190
1191 for (i = 0; i < debugfs_dma_base->platform->max_channels; i++)
1192 if (started_channels & (1 << i))
1193 tmp += sprintf(tmp, "channel %d\n", i);
1194
1195 tmp += sprintf(tmp, "Pool alloc nbr %d\n", pool_count);
1196 dev_size = tmp - dev_buf;
1197
1198 /* No more to read if offset != 0 */
1199 if (*f_pos > dev_size)
1200 goto out;
1201
1202 if (count > dev_size - *f_pos)
1203 count = dev_size - *f_pos;
1204
1205 if (copy_to_user(buf, dev_buf + *f_pos, count))
1206 ret = -EINVAL;
1207 ret = count;
1208 *f_pos += count;
1209
1210 out:
1211 kfree(dev_buf);
1212 return ret;
1213
1214 err_kmalloc:
1215 return 0;
1216}
1217
1218static const struct file_operations coh901318_debugfs_status_operations = {
1219 .owner = THIS_MODULE,
Stephen Boyd234e3402012-04-05 14:25:11 -07001220 .open = simple_open,
Linus Walleij61f135b2009-11-19 19:49:17 +01001221 .read = coh901318_debugfs_read,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001222 .llseek = default_llseek,
Linus Walleij61f135b2009-11-19 19:49:17 +01001223};
1224
1225
1226static int __init init_coh901318_debugfs(void)
1227{
1228
1229 dma_dentry = debugfs_create_dir("dma", NULL);
1230
1231 (void) debugfs_create_file("status",
1232 S_IFREG | S_IRUGO,
1233 dma_dentry, NULL,
1234 &coh901318_debugfs_status_operations);
1235 return 0;
1236}
1237
1238static void __exit exit_coh901318_debugfs(void)
1239{
1240 debugfs_remove_recursive(dma_dentry);
1241}
1242
1243module_init(init_coh901318_debugfs);
1244module_exit(exit_coh901318_debugfs);
1245#else
1246
1247#define COH901318_DEBUGFS_ASSIGN(x, y)
1248
1249#endif /* CONFIG_DEBUG_FS */
1250
1251static inline struct coh901318_chan *to_coh901318_chan(struct dma_chan *chan)
1252{
1253 return container_of(chan, struct coh901318_chan, chan);
1254}
1255
Linus Walleij61f135b2009-11-19 19:49:17 +01001256static inline const struct coh901318_params *
1257cohc_chan_param(struct coh901318_chan *cohc)
1258{
1259 return &cohc->base->platform->chan_conf[cohc->id].param;
1260}
1261
1262static inline const struct coh_dma_channel *
1263cohc_chan_conf(struct coh901318_chan *cohc)
1264{
1265 return &cohc->base->platform->chan_conf[cohc->id];
1266}
1267
1268static void enable_powersave(struct coh901318_chan *cohc)
1269{
1270 unsigned long flags;
1271 struct powersave *pm = &cohc->base->pm;
1272
1273 spin_lock_irqsave(&pm->lock, flags);
1274
1275 pm->started_channels &= ~(1ULL << cohc->id);
1276
1277 if (!pm->started_channels) {
1278 /* DMA no longer intends to access memory */
1279 cohc->base->platform->access_memory_state(cohc->base->dev,
1280 false);
1281 }
1282
1283 spin_unlock_irqrestore(&pm->lock, flags);
1284}
1285static void disable_powersave(struct coh901318_chan *cohc)
1286{
1287 unsigned long flags;
1288 struct powersave *pm = &cohc->base->pm;
1289
1290 spin_lock_irqsave(&pm->lock, flags);
1291
1292 if (!pm->started_channels) {
1293 /* DMA intends to access memory */
1294 cohc->base->platform->access_memory_state(cohc->base->dev,
1295 true);
1296 }
1297
1298 pm->started_channels |= (1ULL << cohc->id);
1299
1300 spin_unlock_irqrestore(&pm->lock, flags);
1301}
1302
1303static inline int coh901318_set_ctrl(struct coh901318_chan *cohc, u32 control)
1304{
1305 int channel = cohc->id;
1306 void __iomem *virtbase = cohc->base->virtbase;
1307
1308 writel(control,
1309 virtbase + COH901318_CX_CTRL +
1310 COH901318_CX_CTRL_SPACING * channel);
1311 return 0;
1312}
1313
1314static inline int coh901318_set_conf(struct coh901318_chan *cohc, u32 conf)
1315{
1316 int channel = cohc->id;
1317 void __iomem *virtbase = cohc->base->virtbase;
1318
1319 writel(conf,
1320 virtbase + COH901318_CX_CFG +
1321 COH901318_CX_CFG_SPACING*channel);
1322 return 0;
1323}
1324
1325
1326static int coh901318_start(struct coh901318_chan *cohc)
1327{
1328 u32 val;
1329 int channel = cohc->id;
1330 void __iomem *virtbase = cohc->base->virtbase;
1331
1332 disable_powersave(cohc);
1333
1334 val = readl(virtbase + COH901318_CX_CFG +
1335 COH901318_CX_CFG_SPACING * channel);
1336
1337 /* Enable channel */
1338 val |= COH901318_CX_CFG_CH_ENABLE;
1339 writel(val, virtbase + COH901318_CX_CFG +
1340 COH901318_CX_CFG_SPACING * channel);
1341
1342 return 0;
1343}
1344
1345static int coh901318_prep_linked_list(struct coh901318_chan *cohc,
Linus Walleijcecd87d2010-03-04 14:31:47 +01001346 struct coh901318_lli *lli)
Linus Walleij61f135b2009-11-19 19:49:17 +01001347{
1348 int channel = cohc->id;
1349 void __iomem *virtbase = cohc->base->virtbase;
1350
1351 BUG_ON(readl(virtbase + COH901318_CX_STAT +
1352 COH901318_CX_STAT_SPACING*channel) &
1353 COH901318_CX_STAT_ACTIVE);
1354
Linus Walleijcecd87d2010-03-04 14:31:47 +01001355 writel(lli->src_addr,
Linus Walleij61f135b2009-11-19 19:49:17 +01001356 virtbase + COH901318_CX_SRC_ADDR +
1357 COH901318_CX_SRC_ADDR_SPACING * channel);
1358
Linus Walleijcecd87d2010-03-04 14:31:47 +01001359 writel(lli->dst_addr, virtbase +
Linus Walleij61f135b2009-11-19 19:49:17 +01001360 COH901318_CX_DST_ADDR +
1361 COH901318_CX_DST_ADDR_SPACING * channel);
1362
Linus Walleijcecd87d2010-03-04 14:31:47 +01001363 writel(lli->link_addr, virtbase + COH901318_CX_LNK_ADDR +
Linus Walleij61f135b2009-11-19 19:49:17 +01001364 COH901318_CX_LNK_ADDR_SPACING * channel);
1365
Linus Walleijcecd87d2010-03-04 14:31:47 +01001366 writel(lli->control, virtbase + COH901318_CX_CTRL +
Linus Walleij61f135b2009-11-19 19:49:17 +01001367 COH901318_CX_CTRL_SPACING * channel);
1368
1369 return 0;
1370}
Linus Walleij61f135b2009-11-19 19:49:17 +01001371
1372static struct coh901318_desc *
1373coh901318_desc_get(struct coh901318_chan *cohc)
1374{
1375 struct coh901318_desc *desc;
1376
1377 if (list_empty(&cohc->free)) {
1378 /* alloc new desc because we're out of used ones
1379 * TODO: alloc a pile of descs instead of just one,
1380 * avoid many small allocations.
1381 */
Linus Walleijb87108a2010-03-02 14:17:20 -07001382 desc = kzalloc(sizeof(struct coh901318_desc), GFP_NOWAIT);
Linus Walleij61f135b2009-11-19 19:49:17 +01001383 if (desc == NULL)
1384 goto out;
1385 INIT_LIST_HEAD(&desc->node);
Linus Walleijb87108a2010-03-02 14:17:20 -07001386 dma_async_tx_descriptor_init(&desc->desc, &cohc->chan);
Linus Walleij61f135b2009-11-19 19:49:17 +01001387 } else {
1388 /* Reuse an old desc. */
1389 desc = list_first_entry(&cohc->free,
1390 struct coh901318_desc,
1391 node);
1392 list_del(&desc->node);
Linus Walleijb87108a2010-03-02 14:17:20 -07001393 /* Initialize it a bit so it's not insane */
1394 desc->sg = NULL;
1395 desc->sg_len = 0;
1396 desc->desc.callback = NULL;
1397 desc->desc.callback_param = NULL;
Linus Walleij61f135b2009-11-19 19:49:17 +01001398 }
1399
1400 out:
1401 return desc;
1402}
1403
1404static void
1405coh901318_desc_free(struct coh901318_chan *cohc, struct coh901318_desc *cohd)
1406{
1407 list_add_tail(&cohd->node, &cohc->free);
1408}
1409
1410/* call with irq lock held */
1411static void
1412coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc)
1413{
1414 list_add_tail(&desc->node, &cohc->active);
Linus Walleij61f135b2009-11-19 19:49:17 +01001415}
1416
1417static struct coh901318_desc *
1418coh901318_first_active_get(struct coh901318_chan *cohc)
1419{
1420 struct coh901318_desc *d;
1421
1422 if (list_empty(&cohc->active))
1423 return NULL;
1424
1425 d = list_first_entry(&cohc->active,
1426 struct coh901318_desc,
1427 node);
1428 return d;
1429}
1430
1431static void
1432coh901318_desc_remove(struct coh901318_desc *cohd)
1433{
1434 list_del(&cohd->node);
1435}
1436
1437static void
1438coh901318_desc_queue(struct coh901318_chan *cohc, struct coh901318_desc *desc)
1439{
1440 list_add_tail(&desc->node, &cohc->queue);
1441}
1442
1443static struct coh901318_desc *
1444coh901318_first_queued(struct coh901318_chan *cohc)
1445{
1446 struct coh901318_desc *d;
1447
1448 if (list_empty(&cohc->queue))
1449 return NULL;
1450
1451 d = list_first_entry(&cohc->queue,
1452 struct coh901318_desc,
1453 node);
1454 return d;
1455}
1456
Linus Walleij84c84472010-03-04 14:40:30 +01001457static inline u32 coh901318_get_bytes_in_lli(struct coh901318_lli *in_lli)
1458{
1459 struct coh901318_lli *lli = in_lli;
1460 u32 bytes = 0;
1461
1462 while (lli) {
1463 bytes += lli->control & COH901318_CX_CTRL_TC_VALUE_MASK;
1464 lli = lli->virt_link_addr;
1465 }
1466 return bytes;
1467}
1468
Linus Walleij61f135b2009-11-19 19:49:17 +01001469/*
Linus Walleij84c84472010-03-04 14:40:30 +01001470 * Get the number of bytes left to transfer on this channel,
1471 * it is unwise to call this before stopping the channel for
1472 * absolute measures, but for a rough guess you can still call
1473 * it.
Linus Walleij61f135b2009-11-19 19:49:17 +01001474 */
Linus Walleij07934482010-03-26 16:50:49 -07001475static u32 coh901318_get_bytes_left(struct dma_chan *chan)
Linus Walleij61f135b2009-11-19 19:49:17 +01001476{
Linus Walleij61f135b2009-11-19 19:49:17 +01001477 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Linus Walleij84c84472010-03-04 14:40:30 +01001478 struct coh901318_desc *cohd;
1479 struct list_head *pos;
1480 unsigned long flags;
1481 u32 left = 0;
1482 int i = 0;
Linus Walleij61f135b2009-11-19 19:49:17 +01001483
1484 spin_lock_irqsave(&cohc->lock, flags);
1485
Linus Walleij84c84472010-03-04 14:40:30 +01001486 /*
1487 * If there are many queued jobs, we iterate and add the
1488 * size of them all. We take a special look on the first
1489 * job though, since it is probably active.
1490 */
1491 list_for_each(pos, &cohc->active) {
1492 /*
1493 * The first job in the list will be working on the
1494 * hardware. The job can be stopped but still active,
1495 * so that the transfer counter is somewhere inside
1496 * the buffer.
1497 */
1498 cohd = list_entry(pos, struct coh901318_desc, node);
1499
1500 if (i == 0) {
1501 struct coh901318_lli *lli;
1502 dma_addr_t ladd;
1503
1504 /* Read current transfer count value */
1505 left = readl(cohc->base->virtbase +
1506 COH901318_CX_CTRL +
1507 COH901318_CX_CTRL_SPACING * cohc->id) &
1508 COH901318_CX_CTRL_TC_VALUE_MASK;
1509
1510 /* See if the transfer is linked... */
1511 ladd = readl(cohc->base->virtbase +
1512 COH901318_CX_LNK_ADDR +
1513 COH901318_CX_LNK_ADDR_SPACING *
1514 cohc->id) &
1515 ~COH901318_CX_LNK_LINK_IMMEDIATE;
1516 /* Single transaction */
1517 if (!ladd)
1518 continue;
1519
1520 /*
1521 * Linked transaction, follow the lli, find the
1522 * currently processing lli, and proceed to the next
1523 */
1524 lli = cohd->lli;
1525 while (lli && lli->link_addr != ladd)
1526 lli = lli->virt_link_addr;
1527
1528 if (lli)
1529 lli = lli->virt_link_addr;
1530
1531 /*
1532 * Follow remaining lli links around to count the total
1533 * number of bytes left
1534 */
1535 left += coh901318_get_bytes_in_lli(lli);
1536 } else {
1537 left += coh901318_get_bytes_in_lli(cohd->lli);
1538 }
1539 i++;
1540 }
1541
1542 /* Also count bytes in the queued jobs */
1543 list_for_each(pos, &cohc->queue) {
1544 cohd = list_entry(pos, struct coh901318_desc, node);
1545 left += coh901318_get_bytes_in_lli(cohd->lli);
1546 }
Linus Walleij61f135b2009-11-19 19:49:17 +01001547
1548 spin_unlock_irqrestore(&cohc->lock, flags);
1549
Linus Walleij84c84472010-03-04 14:40:30 +01001550 return left;
Linus Walleij61f135b2009-11-19 19:49:17 +01001551}
Linus Walleij61f135b2009-11-19 19:49:17 +01001552
Linus Walleijc3635c72010-03-26 16:44:01 -07001553/*
1554 * Pauses a transfer without losing data. Enables power save.
1555 * Use this function in conjunction with coh901318_resume.
1556 */
1557static void coh901318_pause(struct dma_chan *chan)
Linus Walleij61f135b2009-11-19 19:49:17 +01001558{
1559 u32 val;
1560 unsigned long flags;
1561 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1562 int channel = cohc->id;
1563 void __iomem *virtbase = cohc->base->virtbase;
1564
1565 spin_lock_irqsave(&cohc->lock, flags);
1566
1567 /* Disable channel in HW */
1568 val = readl(virtbase + COH901318_CX_CFG +
1569 COH901318_CX_CFG_SPACING * channel);
1570
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001571 /* Stopping infinite transfer */
Linus Walleij61f135b2009-11-19 19:49:17 +01001572 if ((val & COH901318_CX_CTRL_TC_ENABLE) == 0 &&
1573 (val & COH901318_CX_CFG_CH_ENABLE))
1574 cohc->stopped = 1;
1575
1576
1577 val &= ~COH901318_CX_CFG_CH_ENABLE;
1578 /* Enable twice, HW bug work around */
1579 writel(val, virtbase + COH901318_CX_CFG +
1580 COH901318_CX_CFG_SPACING * channel);
1581 writel(val, virtbase + COH901318_CX_CFG +
1582 COH901318_CX_CFG_SPACING * channel);
1583
1584 /* Spin-wait for it to actually go inactive */
1585 while (readl(virtbase + COH901318_CX_STAT+COH901318_CX_STAT_SPACING *
1586 channel) & COH901318_CX_STAT_ACTIVE)
1587 cpu_relax();
1588
1589 /* Check if we stopped an active job */
1590 if ((readl(virtbase + COH901318_CX_CTRL+COH901318_CX_CTRL_SPACING *
1591 channel) & COH901318_CX_CTRL_TC_VALUE_MASK) > 0)
1592 cohc->stopped = 1;
1593
1594 enable_powersave(cohc);
1595
1596 spin_unlock_irqrestore(&cohc->lock, flags);
1597}
Linus Walleij61f135b2009-11-19 19:49:17 +01001598
Linus Walleijc3635c72010-03-26 16:44:01 -07001599/* Resumes a transfer that has been stopped via 300_dma_stop(..).
Linus Walleij61f135b2009-11-19 19:49:17 +01001600 Power save is handled.
1601*/
Linus Walleijc3635c72010-03-26 16:44:01 -07001602static void coh901318_resume(struct dma_chan *chan)
Linus Walleij61f135b2009-11-19 19:49:17 +01001603{
1604 u32 val;
1605 unsigned long flags;
1606 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1607 int channel = cohc->id;
1608
1609 spin_lock_irqsave(&cohc->lock, flags);
1610
1611 disable_powersave(cohc);
1612
1613 if (cohc->stopped) {
1614 /* Enable channel in HW */
1615 val = readl(cohc->base->virtbase + COH901318_CX_CFG +
1616 COH901318_CX_CFG_SPACING * channel);
1617
1618 val |= COH901318_CX_CFG_CH_ENABLE;
1619
1620 writel(val, cohc->base->virtbase + COH901318_CX_CFG +
1621 COH901318_CX_CFG_SPACING*channel);
1622
1623 cohc->stopped = 0;
1624 }
1625
1626 spin_unlock_irqrestore(&cohc->lock, flags);
1627}
Linus Walleij61f135b2009-11-19 19:49:17 +01001628
1629bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
1630{
1631 unsigned int ch_nr = (unsigned int) chan_id;
1632
1633 if (ch_nr == to_coh901318_chan(chan)->id)
1634 return true;
1635
1636 return false;
1637}
1638EXPORT_SYMBOL(coh901318_filter_id);
1639
1640/*
1641 * DMA channel allocation
1642 */
1643static int coh901318_config(struct coh901318_chan *cohc,
1644 struct coh901318_params *param)
1645{
1646 unsigned long flags;
1647 const struct coh901318_params *p;
1648 int channel = cohc->id;
1649 void __iomem *virtbase = cohc->base->virtbase;
1650
1651 spin_lock_irqsave(&cohc->lock, flags);
1652
1653 if (param)
1654 p = param;
1655 else
1656 p = &cohc->base->platform->chan_conf[channel].param;
1657
1658 /* Clear any pending BE or TC interrupt */
1659 if (channel < 32) {
1660 writel(1 << channel, virtbase + COH901318_BE_INT_CLEAR1);
1661 writel(1 << channel, virtbase + COH901318_TC_INT_CLEAR1);
1662 } else {
1663 writel(1 << (channel - 32), virtbase +
1664 COH901318_BE_INT_CLEAR2);
1665 writel(1 << (channel - 32), virtbase +
1666 COH901318_TC_INT_CLEAR2);
1667 }
1668
1669 coh901318_set_conf(cohc, p->config);
1670 coh901318_set_ctrl(cohc, p->ctrl_lli_last);
1671
1672 spin_unlock_irqrestore(&cohc->lock, flags);
1673
1674 return 0;
1675}
1676
1677/* must lock when calling this function
1678 * start queued jobs, if any
1679 * TODO: start all queued jobs in one go
1680 *
1681 * Returns descriptor if queued job is started otherwise NULL.
1682 * If the queue is empty NULL is returned.
1683 */
1684static struct coh901318_desc *coh901318_queue_start(struct coh901318_chan *cohc)
1685{
Linus Walleijcecd87d2010-03-04 14:31:47 +01001686 struct coh901318_desc *cohd;
Linus Walleij61f135b2009-11-19 19:49:17 +01001687
Linus Walleijcecd87d2010-03-04 14:31:47 +01001688 /*
1689 * start queued jobs, if any
Linus Walleij61f135b2009-11-19 19:49:17 +01001690 * TODO: transmit all queued jobs in one go
1691 */
Linus Walleijcecd87d2010-03-04 14:31:47 +01001692 cohd = coh901318_first_queued(cohc);
Linus Walleij61f135b2009-11-19 19:49:17 +01001693
Linus Walleijcecd87d2010-03-04 14:31:47 +01001694 if (cohd != NULL) {
Linus Walleij61f135b2009-11-19 19:49:17 +01001695 /* Remove from queue */
Linus Walleijcecd87d2010-03-04 14:31:47 +01001696 coh901318_desc_remove(cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01001697 /* initiate DMA job */
1698 cohc->busy = 1;
1699
Linus Walleijcecd87d2010-03-04 14:31:47 +01001700 coh901318_desc_submit(cohc, cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01001701
Linus Walleijb89243d2011-07-01 16:47:28 +02001702 /* Program the transaction head */
1703 coh901318_set_conf(cohc, cohd->head_config);
1704 coh901318_set_ctrl(cohc, cohd->head_ctrl);
Linus Walleijcecd87d2010-03-04 14:31:47 +01001705 coh901318_prep_linked_list(cohc, cohd->lli);
Linus Walleij61f135b2009-11-19 19:49:17 +01001706
Linus Walleijcecd87d2010-03-04 14:31:47 +01001707 /* start dma job on this channel */
Linus Walleij61f135b2009-11-19 19:49:17 +01001708 coh901318_start(cohc);
1709
1710 }
1711
Linus Walleijcecd87d2010-03-04 14:31:47 +01001712 return cohd;
Linus Walleij61f135b2009-11-19 19:49:17 +01001713}
1714
Linus Walleij848ad122010-03-02 14:17:15 -07001715/*
1716 * This tasklet is called from the interrupt handler to
1717 * handle each descriptor (DMA job) that is sent to a channel.
1718 */
Linus Walleij61f135b2009-11-19 19:49:17 +01001719static void dma_tasklet(unsigned long data)
1720{
1721 struct coh901318_chan *cohc = (struct coh901318_chan *) data;
1722 struct coh901318_desc *cohd_fin;
1723 unsigned long flags;
1724 dma_async_tx_callback callback;
1725 void *callback_param;
1726
Linus Walleij848ad122010-03-02 14:17:15 -07001727 dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d"
1728 " nbr_active_done %ld\n", __func__,
1729 cohc->id, cohc->nbr_active_done);
1730
Linus Walleij61f135b2009-11-19 19:49:17 +01001731 spin_lock_irqsave(&cohc->lock, flags);
1732
Linus Walleij848ad122010-03-02 14:17:15 -07001733 /* get first active descriptor entry from list */
Linus Walleij61f135b2009-11-19 19:49:17 +01001734 cohd_fin = coh901318_first_active_get(cohc);
1735
Linus Walleij61f135b2009-11-19 19:49:17 +01001736 if (cohd_fin == NULL)
1737 goto err;
1738
Linus Walleij0b588282010-03-02 14:17:44 -07001739 /* locate callback to client */
Linus Walleij61f135b2009-11-19 19:49:17 +01001740 callback = cohd_fin->desc.callback;
1741 callback_param = cohd_fin->desc.callback_param;
1742
Linus Walleij0b588282010-03-02 14:17:44 -07001743 /* sign this job as completed on the channel */
Russell King - ARM Linuxf7fbce02012-03-06 22:35:07 +00001744 dma_cookie_complete(&cohd_fin->desc);
Linus Walleij61f135b2009-11-19 19:49:17 +01001745
Linus Walleij0b588282010-03-02 14:17:44 -07001746 /* release the lli allocation and remove the descriptor */
Linus Walleijcecd87d2010-03-04 14:31:47 +01001747 coh901318_lli_free(&cohc->base->pool, &cohd_fin->lli);
Linus Walleij0b588282010-03-02 14:17:44 -07001748
1749 /* return desc to free-list */
1750 coh901318_desc_remove(cohd_fin);
1751 coh901318_desc_free(cohc, cohd_fin);
1752
1753 spin_unlock_irqrestore(&cohc->lock, flags);
1754
1755 /* Call the callback when we're done */
1756 if (callback)
1757 callback(callback_param);
1758
1759 spin_lock_irqsave(&cohc->lock, flags);
Linus Walleij61f135b2009-11-19 19:49:17 +01001760
Linus Walleij848ad122010-03-02 14:17:15 -07001761 /*
1762 * If another interrupt fired while the tasklet was scheduling,
1763 * we don't get called twice, so we have this number of active
1764 * counter that keep track of the number of IRQs expected to
1765 * be handled for this channel. If there happen to be more than
1766 * one IRQ to be ack:ed, we simply schedule this tasklet again.
1767 */
Linus Walleij0b588282010-03-02 14:17:44 -07001768 cohc->nbr_active_done--;
Linus Walleij61f135b2009-11-19 19:49:17 +01001769 if (cohc->nbr_active_done) {
Linus Walleij848ad122010-03-02 14:17:15 -07001770 dev_dbg(COHC_2_DEV(cohc), "scheduling tasklet again, new IRQs "
1771 "came in while we were scheduling this tasklet\n");
Linus Walleij61f135b2009-11-19 19:49:17 +01001772 if (cohc_chan_conf(cohc)->priority_high)
1773 tasklet_hi_schedule(&cohc->tasklet);
1774 else
1775 tasklet_schedule(&cohc->tasklet);
1776 }
Linus Walleij61f135b2009-11-19 19:49:17 +01001777
Linus Walleij0b588282010-03-02 14:17:44 -07001778 spin_unlock_irqrestore(&cohc->lock, flags);
Linus Walleij61f135b2009-11-19 19:49:17 +01001779
1780 return;
1781
1782 err:
1783 spin_unlock_irqrestore(&cohc->lock, flags);
1784 dev_err(COHC_2_DEV(cohc), "[%s] No active dma desc\n", __func__);
1785}
1786
1787
1788/* called from interrupt context */
1789static void dma_tc_handle(struct coh901318_chan *cohc)
1790{
Linus Walleijcecd87d2010-03-04 14:31:47 +01001791 /*
1792 * If the channel is not allocated, then we shouldn't have
1793 * any TC interrupts on it.
1794 */
1795 if (!cohc->allocated) {
1796 dev_err(COHC_2_DEV(cohc), "spurious interrupt from "
1797 "unallocated channel\n");
Linus Walleij61f135b2009-11-19 19:49:17 +01001798 return;
Linus Walleijcecd87d2010-03-04 14:31:47 +01001799 }
Linus Walleij61f135b2009-11-19 19:49:17 +01001800
Linus Walleij0b588282010-03-02 14:17:44 -07001801 spin_lock(&cohc->lock);
Linus Walleij61f135b2009-11-19 19:49:17 +01001802
Linus Walleijcecd87d2010-03-04 14:31:47 +01001803 /*
1804 * When we reach this point, at least one queue item
1805 * should have been moved over from cohc->queue to
1806 * cohc->active and run to completion, that is why we're
1807 * getting a terminal count interrupt is it not?
1808 * If you get this BUG() the most probable cause is that
1809 * the individual nodes in the lli chain have IRQ enabled,
1810 * so check your platform config for lli chain ctrl.
1811 */
1812 BUG_ON(list_empty(&cohc->active));
1813
Linus Walleij61f135b2009-11-19 19:49:17 +01001814 cohc->nbr_active_done++;
1815
Linus Walleijcecd87d2010-03-04 14:31:47 +01001816 /*
1817 * This attempt to take a job from cohc->queue, put it
1818 * into cohc->active and start it.
1819 */
Linus Walleij0b588282010-03-02 14:17:44 -07001820 if (coh901318_queue_start(cohc) == NULL)
Linus Walleij61f135b2009-11-19 19:49:17 +01001821 cohc->busy = 0;
1822
Linus Walleij0b588282010-03-02 14:17:44 -07001823 spin_unlock(&cohc->lock);
1824
Linus Walleijcecd87d2010-03-04 14:31:47 +01001825 /*
1826 * This tasklet will remove items from cohc->active
1827 * and thus terminates them.
1828 */
Linus Walleij61f135b2009-11-19 19:49:17 +01001829 if (cohc_chan_conf(cohc)->priority_high)
1830 tasklet_hi_schedule(&cohc->tasklet);
1831 else
1832 tasklet_schedule(&cohc->tasklet);
1833}
1834
1835
1836static irqreturn_t dma_irq_handler(int irq, void *dev_id)
1837{
1838 u32 status1;
1839 u32 status2;
1840 int i;
1841 int ch;
1842 struct coh901318_base *base = dev_id;
1843 struct coh901318_chan *cohc;
1844 void __iomem *virtbase = base->virtbase;
1845
1846 status1 = readl(virtbase + COH901318_INT_STATUS1);
1847 status2 = readl(virtbase + COH901318_INT_STATUS2);
1848
1849 if (unlikely(status1 == 0 && status2 == 0)) {
1850 dev_warn(base->dev, "spurious DMA IRQ from no channel!\n");
1851 return IRQ_HANDLED;
1852 }
1853
1854 /* TODO: consider handle IRQ in tasklet here to
1855 * minimize interrupt latency */
1856
1857 /* Check the first 32 DMA channels for IRQ */
1858 while (status1) {
1859 /* Find first bit set, return as a number. */
1860 i = ffs(status1) - 1;
1861 ch = i;
1862
1863 cohc = &base->chans[ch];
1864 spin_lock(&cohc->lock);
1865
1866 /* Mask off this bit */
1867 status1 &= ~(1 << i);
1868 /* Check the individual channel bits */
1869 if (test_bit(i, virtbase + COH901318_BE_INT_STATUS1)) {
1870 dev_crit(COHC_2_DEV(cohc),
1871 "DMA bus error on channel %d!\n", ch);
1872 BUG_ON(1);
1873 /* Clear BE interrupt */
1874 __set_bit(i, virtbase + COH901318_BE_INT_CLEAR1);
1875 } else {
1876 /* Caused by TC, really? */
1877 if (unlikely(!test_bit(i, virtbase +
1878 COH901318_TC_INT_STATUS1))) {
1879 dev_warn(COHC_2_DEV(cohc),
1880 "ignoring interrupt not caused by terminal count on channel %d\n", ch);
1881 /* Clear TC interrupt */
1882 BUG_ON(1);
1883 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
1884 } else {
1885 /* Enable powersave if transfer has finished */
1886 if (!(readl(virtbase + COH901318_CX_STAT +
1887 COH901318_CX_STAT_SPACING*ch) &
1888 COH901318_CX_STAT_ENABLED)) {
1889 enable_powersave(cohc);
1890 }
1891
1892 /* Must clear TC interrupt before calling
1893 * dma_tc_handle
Justin P. Mattockbc0b44c2011-01-28 11:48:18 -08001894 * in case tc_handle initiate a new dma job
Linus Walleij61f135b2009-11-19 19:49:17 +01001895 */
1896 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
1897
1898 dma_tc_handle(cohc);
1899 }
1900 }
1901 spin_unlock(&cohc->lock);
1902 }
1903
1904 /* Check the remaining 32 DMA channels for IRQ */
1905 while (status2) {
1906 /* Find first bit set, return as a number. */
1907 i = ffs(status2) - 1;
1908 ch = i + 32;
1909 cohc = &base->chans[ch];
1910 spin_lock(&cohc->lock);
1911
1912 /* Mask off this bit */
1913 status2 &= ~(1 << i);
1914 /* Check the individual channel bits */
1915 if (test_bit(i, virtbase + COH901318_BE_INT_STATUS2)) {
1916 dev_crit(COHC_2_DEV(cohc),
1917 "DMA bus error on channel %d!\n", ch);
1918 /* Clear BE interrupt */
1919 BUG_ON(1);
1920 __set_bit(i, virtbase + COH901318_BE_INT_CLEAR2);
1921 } else {
1922 /* Caused by TC, really? */
1923 if (unlikely(!test_bit(i, virtbase +
1924 COH901318_TC_INT_STATUS2))) {
1925 dev_warn(COHC_2_DEV(cohc),
1926 "ignoring interrupt not caused by terminal count on channel %d\n", ch);
1927 /* Clear TC interrupt */
1928 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
1929 BUG_ON(1);
1930 } else {
1931 /* Enable powersave if transfer has finished */
1932 if (!(readl(virtbase + COH901318_CX_STAT +
1933 COH901318_CX_STAT_SPACING*ch) &
1934 COH901318_CX_STAT_ENABLED)) {
1935 enable_powersave(cohc);
1936 }
1937 /* Must clear TC interrupt before calling
1938 * dma_tc_handle
Justin P. Mattockbc0b44c2011-01-28 11:48:18 -08001939 * in case tc_handle initiate a new dma job
Linus Walleij61f135b2009-11-19 19:49:17 +01001940 */
1941 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
1942
1943 dma_tc_handle(cohc);
1944 }
1945 }
1946 spin_unlock(&cohc->lock);
1947 }
1948
1949 return IRQ_HANDLED;
1950}
1951
1952static int coh901318_alloc_chan_resources(struct dma_chan *chan)
1953{
1954 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Linus Walleij84c84472010-03-04 14:40:30 +01001955 unsigned long flags;
Linus Walleij61f135b2009-11-19 19:49:17 +01001956
1957 dev_vdbg(COHC_2_DEV(cohc), "[%s] DMA channel %d\n",
1958 __func__, cohc->id);
1959
1960 if (chan->client_count > 1)
1961 return -EBUSY;
1962
Linus Walleij84c84472010-03-04 14:40:30 +01001963 spin_lock_irqsave(&cohc->lock, flags);
1964
Linus Walleij61f135b2009-11-19 19:49:17 +01001965 coh901318_config(cohc, NULL);
1966
1967 cohc->allocated = 1;
Russell King - ARM Linuxd3ee98cdc2012-03-06 22:35:47 +00001968 dma_cookie_init(chan);
Linus Walleij61f135b2009-11-19 19:49:17 +01001969
Linus Walleij84c84472010-03-04 14:40:30 +01001970 spin_unlock_irqrestore(&cohc->lock, flags);
1971
Linus Walleij61f135b2009-11-19 19:49:17 +01001972 return 1;
1973}
1974
1975static void
1976coh901318_free_chan_resources(struct dma_chan *chan)
1977{
1978 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1979 int channel = cohc->id;
1980 unsigned long flags;
1981
1982 spin_lock_irqsave(&cohc->lock, flags);
1983
1984 /* Disable HW */
1985 writel(0x00000000U, cohc->base->virtbase + COH901318_CX_CFG +
1986 COH901318_CX_CFG_SPACING*channel);
1987 writel(0x00000000U, cohc->base->virtbase + COH901318_CX_CTRL +
1988 COH901318_CX_CTRL_SPACING*channel);
1989
1990 cohc->allocated = 0;
1991
1992 spin_unlock_irqrestore(&cohc->lock, flags);
1993
Linus Walleij05827632010-05-17 16:30:42 -07001994 chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
Linus Walleij61f135b2009-11-19 19:49:17 +01001995}
1996
1997
1998static dma_cookie_t
1999coh901318_tx_submit(struct dma_async_tx_descriptor *tx)
2000{
2001 struct coh901318_desc *cohd = container_of(tx, struct coh901318_desc,
2002 desc);
2003 struct coh901318_chan *cohc = to_coh901318_chan(tx->chan);
2004 unsigned long flags;
Russell King - ARM Linux884485e2012-03-06 22:34:46 +00002005 dma_cookie_t cookie;
Linus Walleij61f135b2009-11-19 19:49:17 +01002006
2007 spin_lock_irqsave(&cohc->lock, flags);
Russell King - ARM Linux884485e2012-03-06 22:34:46 +00002008 cookie = dma_cookie_assign(tx);
Linus Walleij61f135b2009-11-19 19:49:17 +01002009
2010 coh901318_desc_queue(cohc, cohd);
2011
2012 spin_unlock_irqrestore(&cohc->lock, flags);
2013
Russell King - ARM Linux884485e2012-03-06 22:34:46 +00002014 return cookie;
Linus Walleij61f135b2009-11-19 19:49:17 +01002015}
2016
2017static struct dma_async_tx_descriptor *
2018coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
2019 size_t size, unsigned long flags)
2020{
Linus Walleijcecd87d2010-03-04 14:31:47 +01002021 struct coh901318_lli *lli;
Linus Walleij61f135b2009-11-19 19:49:17 +01002022 struct coh901318_desc *cohd;
2023 unsigned long flg;
2024 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2025 int lli_len;
2026 u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
Linus Walleijb87108a2010-03-02 14:17:20 -07002027 int ret;
Linus Walleij61f135b2009-11-19 19:49:17 +01002028
2029 spin_lock_irqsave(&cohc->lock, flg);
2030
2031 dev_vdbg(COHC_2_DEV(cohc),
2032 "[%s] channel %d src 0x%x dest 0x%x size %d\n",
2033 __func__, cohc->id, src, dest, size);
2034
2035 if (flags & DMA_PREP_INTERRUPT)
2036 /* Trigger interrupt after last lli */
2037 ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
2038
2039 lli_len = size >> MAX_DMA_PACKET_SIZE_SHIFT;
2040 if ((lli_len << MAX_DMA_PACKET_SIZE_SHIFT) < size)
2041 lli_len++;
2042
Linus Walleijcecd87d2010-03-04 14:31:47 +01002043 lli = coh901318_lli_alloc(&cohc->base->pool, lli_len);
Linus Walleij61f135b2009-11-19 19:49:17 +01002044
Linus Walleijcecd87d2010-03-04 14:31:47 +01002045 if (lli == NULL)
Linus Walleij61f135b2009-11-19 19:49:17 +01002046 goto err;
2047
Linus Walleijb87108a2010-03-02 14:17:20 -07002048 ret = coh901318_lli_fill_memcpy(
Linus Walleijcecd87d2010-03-04 14:31:47 +01002049 &cohc->base->pool, lli, src, size, dest,
Linus Walleijb87108a2010-03-02 14:17:20 -07002050 cohc_chan_param(cohc)->ctrl_lli_chained,
2051 ctrl_last);
2052 if (ret)
2053 goto err;
Linus Walleij61f135b2009-11-19 19:49:17 +01002054
Linus Walleijcecd87d2010-03-04 14:31:47 +01002055 COH_DBG(coh901318_list_print(cohc, lli));
Linus Walleij61f135b2009-11-19 19:49:17 +01002056
Linus Walleijb87108a2010-03-02 14:17:20 -07002057 /* Pick a descriptor to handle this transfer */
2058 cohd = coh901318_desc_get(cohc);
Linus Walleijcecd87d2010-03-04 14:31:47 +01002059 cohd->lli = lli;
Linus Walleijb87108a2010-03-02 14:17:20 -07002060 cohd->flags = flags;
Linus Walleij61f135b2009-11-19 19:49:17 +01002061 cohd->desc.tx_submit = coh901318_tx_submit;
2062
2063 spin_unlock_irqrestore(&cohc->lock, flg);
2064
2065 return &cohd->desc;
2066 err:
2067 spin_unlock_irqrestore(&cohc->lock, flg);
2068 return NULL;
2069}
2070
2071static struct dma_async_tx_descriptor *
2072coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
Vinod Kouldb8196d2011-10-13 22:34:23 +05302073 unsigned int sg_len, enum dma_transfer_direction direction,
Alexandre Bounine185ecb52012-03-08 15:35:13 -05002074 unsigned long flags, void *context)
Linus Walleij61f135b2009-11-19 19:49:17 +01002075{
2076 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Linus Walleijcecd87d2010-03-04 14:31:47 +01002077 struct coh901318_lli *lli;
Linus Walleij61f135b2009-11-19 19:49:17 +01002078 struct coh901318_desc *cohd;
Linus Walleij516fd432010-03-02 20:12:46 +01002079 const struct coh901318_params *params;
Linus Walleij61f135b2009-11-19 19:49:17 +01002080 struct scatterlist *sg;
2081 int len = 0;
2082 int size;
2083 int i;
2084 u32 ctrl_chained = cohc_chan_param(cohc)->ctrl_lli_chained;
2085 u32 ctrl = cohc_chan_param(cohc)->ctrl_lli;
2086 u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
Linus Walleij516fd432010-03-02 20:12:46 +01002087 u32 config;
Linus Walleij61f135b2009-11-19 19:49:17 +01002088 unsigned long flg;
Linus Walleij0b588282010-03-02 14:17:44 -07002089 int ret;
Linus Walleij61f135b2009-11-19 19:49:17 +01002090
2091 if (!sgl)
2092 goto out;
Lars-Peter Clausenfdaf9c42012-04-25 20:50:52 +02002093 if (sg_dma_len(sgl) == 0)
Linus Walleij61f135b2009-11-19 19:49:17 +01002094 goto out;
2095
2096 spin_lock_irqsave(&cohc->lock, flg);
2097
2098 dev_vdbg(COHC_2_DEV(cohc), "[%s] sg_len %d dir %d\n",
2099 __func__, sg_len, direction);
2100
2101 if (flags & DMA_PREP_INTERRUPT)
2102 /* Trigger interrupt after last lli */
2103 ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
2104
Linus Walleij516fd432010-03-02 20:12:46 +01002105 params = cohc_chan_param(cohc);
2106 config = params->config;
Linus Walleij128f9042010-08-04 13:37:53 +02002107 /*
2108 * Add runtime-specific control on top, make
2109 * sure the bits you set per peripheral channel are
2110 * cleared in the default config from the platform.
2111 */
Linus Walleij9aab4d62013-01-04 13:50:49 +01002112 ctrl_chained |= cohc->ctrl;
2113 ctrl_last |= cohc->ctrl;
2114 ctrl |= cohc->ctrl;
Linus Walleij516fd432010-03-02 20:12:46 +01002115
Vinod Kouldb8196d2011-10-13 22:34:23 +05302116 if (direction == DMA_MEM_TO_DEV) {
Linus Walleij61f135b2009-11-19 19:49:17 +01002117 u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
2118 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
2119
Linus Walleij516fd432010-03-02 20:12:46 +01002120 config |= COH901318_CX_CFG_RM_MEMORY_TO_PRIMARY;
Linus Walleij61f135b2009-11-19 19:49:17 +01002121 ctrl_chained |= tx_flags;
2122 ctrl_last |= tx_flags;
2123 ctrl |= tx_flags;
Vinod Kouldb8196d2011-10-13 22:34:23 +05302124 } else if (direction == DMA_DEV_TO_MEM) {
Linus Walleij61f135b2009-11-19 19:49:17 +01002125 u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
2126 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
2127
Linus Walleij516fd432010-03-02 20:12:46 +01002128 config |= COH901318_CX_CFG_RM_PRIMARY_TO_MEMORY;
Linus Walleij61f135b2009-11-19 19:49:17 +01002129 ctrl_chained |= rx_flags;
2130 ctrl_last |= rx_flags;
2131 ctrl |= rx_flags;
2132 } else
2133 goto err_direction;
2134
Linus Walleij61f135b2009-11-19 19:49:17 +01002135 /* The dma only supports transmitting packages up to
2136 * MAX_DMA_PACKET_SIZE. Calculate to total number of
2137 * dma elemts required to send the entire sg list
2138 */
2139 for_each_sg(sgl, sg, sg_len, i) {
2140 unsigned int factor;
2141 size = sg_dma_len(sg);
2142
2143 if (size <= MAX_DMA_PACKET_SIZE) {
2144 len++;
2145 continue;
2146 }
2147
2148 factor = size >> MAX_DMA_PACKET_SIZE_SHIFT;
2149 if ((factor << MAX_DMA_PACKET_SIZE_SHIFT) < size)
2150 factor++;
2151
2152 len += factor;
2153 }
2154
Linus Walleij848ad122010-03-02 14:17:15 -07002155 pr_debug("Allocate %d lli:s for this transfer\n", len);
Linus Walleijcecd87d2010-03-04 14:31:47 +01002156 lli = coh901318_lli_alloc(&cohc->base->pool, len);
Linus Walleij61f135b2009-11-19 19:49:17 +01002157
Linus Walleijcecd87d2010-03-04 14:31:47 +01002158 if (lli == NULL)
Linus Walleij61f135b2009-11-19 19:49:17 +01002159 goto err_dma_alloc;
2160
Linus Walleijcecd87d2010-03-04 14:31:47 +01002161 /* initiate allocated lli list */
2162 ret = coh901318_lli_fill_sg(&cohc->base->pool, lli, sgl, sg_len,
Linus Walleij9aab4d62013-01-04 13:50:49 +01002163 cohc->addr,
Linus Walleij0b588282010-03-02 14:17:44 -07002164 ctrl_chained,
2165 ctrl,
2166 ctrl_last,
2167 direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
2168 if (ret)
2169 goto err_lli_fill;
Linus Walleij61f135b2009-11-19 19:49:17 +01002170
Linus Walleij128f9042010-08-04 13:37:53 +02002171
Linus Walleijcecd87d2010-03-04 14:31:47 +01002172 COH_DBG(coh901318_list_print(cohc, lli));
Linus Walleij61f135b2009-11-19 19:49:17 +01002173
Linus Walleijb87108a2010-03-02 14:17:20 -07002174 /* Pick a descriptor to handle this transfer */
2175 cohd = coh901318_desc_get(cohc);
Linus Walleijb89243d2011-07-01 16:47:28 +02002176 cohd->head_config = config;
2177 /*
2178 * Set the default head ctrl for the channel to the one from the
2179 * lli, things may have changed due to odd buffer alignment
2180 * etc.
2181 */
2182 cohd->head_ctrl = lli->control;
Linus Walleijb87108a2010-03-02 14:17:20 -07002183 cohd->dir = direction;
2184 cohd->flags = flags;
2185 cohd->desc.tx_submit = coh901318_tx_submit;
Linus Walleijcecd87d2010-03-04 14:31:47 +01002186 cohd->lli = lli;
Linus Walleijb87108a2010-03-02 14:17:20 -07002187
Linus Walleij61f135b2009-11-19 19:49:17 +01002188 spin_unlock_irqrestore(&cohc->lock, flg);
2189
2190 return &cohd->desc;
Linus Walleij0b588282010-03-02 14:17:44 -07002191 err_lli_fill:
Linus Walleij61f135b2009-11-19 19:49:17 +01002192 err_dma_alloc:
2193 err_direction:
Linus Walleij61f135b2009-11-19 19:49:17 +01002194 spin_unlock_irqrestore(&cohc->lock, flg);
2195 out:
2196 return NULL;
2197}
2198
2199static enum dma_status
Linus Walleij07934482010-03-26 16:50:49 -07002200coh901318_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
2201 struct dma_tx_state *txstate)
Linus Walleij61f135b2009-11-19 19:49:17 +01002202{
2203 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Russell King - ARM Linux96a2af42012-03-06 22:35:27 +00002204 enum dma_status ret;
Linus Walleij61f135b2009-11-19 19:49:17 +01002205
Russell King - ARM Linux96a2af42012-03-06 22:35:27 +00002206 ret = dma_cookie_status(chan, cookie, txstate);
2207 /* FIXME: should be conditional on ret != DMA_SUCCESS? */
2208 dma_set_residue(txstate, coh901318_get_bytes_left(chan));
Linus Walleij61f135b2009-11-19 19:49:17 +01002209
Linus Walleij07934482010-03-26 16:50:49 -07002210 if (ret == DMA_IN_PROGRESS && cohc->stopped)
2211 ret = DMA_PAUSED;
Linus Walleij61f135b2009-11-19 19:49:17 +01002212
2213 return ret;
2214}
2215
2216static void
2217coh901318_issue_pending(struct dma_chan *chan)
2218{
2219 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2220 unsigned long flags;
2221
2222 spin_lock_irqsave(&cohc->lock, flags);
2223
Linus Walleijcecd87d2010-03-04 14:31:47 +01002224 /*
2225 * Busy means that pending jobs are already being processed,
2226 * and then there is no point in starting the queue: the
2227 * terminal count interrupt on the channel will take the next
2228 * job on the queue and execute it anyway.
2229 */
Linus Walleij61f135b2009-11-19 19:49:17 +01002230 if (!cohc->busy)
2231 coh901318_queue_start(cohc);
2232
2233 spin_unlock_irqrestore(&cohc->lock, flags);
2234}
2235
Linus Walleij128f9042010-08-04 13:37:53 +02002236/*
2237 * Here we wrap in the runtime dma control interface
2238 */
2239struct burst_table {
2240 int burst_8bit;
2241 int burst_16bit;
2242 int burst_32bit;
2243 u32 reg;
2244};
2245
2246static const struct burst_table burst_sizes[] = {
2247 {
2248 .burst_8bit = 64,
2249 .burst_16bit = 32,
2250 .burst_32bit = 16,
2251 .reg = COH901318_CX_CTRL_BURST_COUNT_64_BYTES,
2252 },
2253 {
2254 .burst_8bit = 48,
2255 .burst_16bit = 24,
2256 .burst_32bit = 12,
2257 .reg = COH901318_CX_CTRL_BURST_COUNT_48_BYTES,
2258 },
2259 {
2260 .burst_8bit = 32,
2261 .burst_16bit = 16,
2262 .burst_32bit = 8,
2263 .reg = COH901318_CX_CTRL_BURST_COUNT_32_BYTES,
2264 },
2265 {
2266 .burst_8bit = 16,
2267 .burst_16bit = 8,
2268 .burst_32bit = 4,
2269 .reg = COH901318_CX_CTRL_BURST_COUNT_16_BYTES,
2270 },
2271 {
2272 .burst_8bit = 8,
2273 .burst_16bit = 4,
2274 .burst_32bit = 2,
2275 .reg = COH901318_CX_CTRL_BURST_COUNT_8_BYTES,
2276 },
2277 {
2278 .burst_8bit = 4,
2279 .burst_16bit = 2,
2280 .burst_32bit = 1,
2281 .reg = COH901318_CX_CTRL_BURST_COUNT_4_BYTES,
2282 },
2283 {
2284 .burst_8bit = 2,
2285 .burst_16bit = 1,
2286 .burst_32bit = 0,
2287 .reg = COH901318_CX_CTRL_BURST_COUNT_2_BYTES,
2288 },
2289 {
2290 .burst_8bit = 1,
2291 .burst_16bit = 0,
2292 .burst_32bit = 0,
2293 .reg = COH901318_CX_CTRL_BURST_COUNT_1_BYTE,
2294 },
2295};
2296
2297static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan,
2298 struct dma_slave_config *config)
2299{
2300 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2301 dma_addr_t addr;
2302 enum dma_slave_buswidth addr_width;
2303 u32 maxburst;
Linus Walleij9aab4d62013-01-04 13:50:49 +01002304 u32 ctrl = 0;
Linus Walleij128f9042010-08-04 13:37:53 +02002305 int i = 0;
2306
2307 /* We only support mem to per or per to mem transfers */
Vinod Kouldb8196d2011-10-13 22:34:23 +05302308 if (config->direction == DMA_DEV_TO_MEM) {
Linus Walleij128f9042010-08-04 13:37:53 +02002309 addr = config->src_addr;
2310 addr_width = config->src_addr_width;
2311 maxburst = config->src_maxburst;
Vinod Kouldb8196d2011-10-13 22:34:23 +05302312 } else if (config->direction == DMA_MEM_TO_DEV) {
Linus Walleij128f9042010-08-04 13:37:53 +02002313 addr = config->dst_addr;
2314 addr_width = config->dst_addr_width;
2315 maxburst = config->dst_maxburst;
2316 } else {
2317 dev_err(COHC_2_DEV(cohc), "illegal channel mode\n");
2318 return;
2319 }
2320
2321 dev_dbg(COHC_2_DEV(cohc), "configure channel for %d byte transfers\n",
2322 addr_width);
2323 switch (addr_width) {
2324 case DMA_SLAVE_BUSWIDTH_1_BYTE:
Linus Walleij9aab4d62013-01-04 13:50:49 +01002325 ctrl |=
Linus Walleij128f9042010-08-04 13:37:53 +02002326 COH901318_CX_CTRL_SRC_BUS_SIZE_8_BITS |
2327 COH901318_CX_CTRL_DST_BUS_SIZE_8_BITS;
2328
2329 while (i < ARRAY_SIZE(burst_sizes)) {
2330 if (burst_sizes[i].burst_8bit <= maxburst)
2331 break;
2332 i++;
2333 }
2334
2335 break;
2336 case DMA_SLAVE_BUSWIDTH_2_BYTES:
Linus Walleij9aab4d62013-01-04 13:50:49 +01002337 ctrl |=
Linus Walleij128f9042010-08-04 13:37:53 +02002338 COH901318_CX_CTRL_SRC_BUS_SIZE_16_BITS |
2339 COH901318_CX_CTRL_DST_BUS_SIZE_16_BITS;
2340
2341 while (i < ARRAY_SIZE(burst_sizes)) {
2342 if (burst_sizes[i].burst_16bit <= maxburst)
2343 break;
2344 i++;
2345 }
2346
2347 break;
2348 case DMA_SLAVE_BUSWIDTH_4_BYTES:
2349 /* Direction doesn't matter here, it's 32/32 bits */
Linus Walleij9aab4d62013-01-04 13:50:49 +01002350 ctrl |=
Linus Walleij128f9042010-08-04 13:37:53 +02002351 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
2352 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS;
2353
2354 while (i < ARRAY_SIZE(burst_sizes)) {
2355 if (burst_sizes[i].burst_32bit <= maxburst)
2356 break;
2357 i++;
2358 }
2359
2360 break;
2361 default:
2362 dev_err(COHC_2_DEV(cohc),
2363 "bad runtimeconfig: alien address width\n");
2364 return;
2365 }
2366
Linus Walleij9aab4d62013-01-04 13:50:49 +01002367 ctrl |= burst_sizes[i].reg;
Linus Walleij128f9042010-08-04 13:37:53 +02002368 dev_dbg(COHC_2_DEV(cohc),
2369 "selected burst size %d bytes for address width %d bytes, maxburst %d\n",
2370 burst_sizes[i].burst_8bit, addr_width, maxburst);
2371
Linus Walleij9aab4d62013-01-04 13:50:49 +01002372 cohc->addr = addr;
2373 cohc->ctrl = ctrl;
Linus Walleij128f9042010-08-04 13:37:53 +02002374}
2375
Linus Walleijc3635c72010-03-26 16:44:01 -07002376static int
Linus Walleij05827632010-05-17 16:30:42 -07002377coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
2378 unsigned long arg)
Linus Walleij61f135b2009-11-19 19:49:17 +01002379{
2380 unsigned long flags;
2381 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2382 struct coh901318_desc *cohd;
2383 void __iomem *virtbase = cohc->base->virtbase;
2384
Linus Walleij128f9042010-08-04 13:37:53 +02002385 if (cmd == DMA_SLAVE_CONFIG) {
2386 struct dma_slave_config *config =
2387 (struct dma_slave_config *) arg;
2388
2389 coh901318_dma_set_runtimeconfig(chan, config);
2390 return 0;
2391 }
2392
Linus Walleijc3635c72010-03-26 16:44:01 -07002393 if (cmd == DMA_PAUSE) {
2394 coh901318_pause(chan);
2395 return 0;
2396 }
Linus Walleij61f135b2009-11-19 19:49:17 +01002397
Linus Walleijc3635c72010-03-26 16:44:01 -07002398 if (cmd == DMA_RESUME) {
2399 coh901318_resume(chan);
2400 return 0;
2401 }
2402
2403 if (cmd != DMA_TERMINATE_ALL)
2404 return -ENXIO;
2405
2406 /* The remainder of this function terminates the transfer */
2407 coh901318_pause(chan);
Linus Walleij61f135b2009-11-19 19:49:17 +01002408 spin_lock_irqsave(&cohc->lock, flags);
2409
2410 /* Clear any pending BE or TC interrupt */
2411 if (cohc->id < 32) {
2412 writel(1 << cohc->id, virtbase + COH901318_BE_INT_CLEAR1);
2413 writel(1 << cohc->id, virtbase + COH901318_TC_INT_CLEAR1);
2414 } else {
2415 writel(1 << (cohc->id - 32), virtbase +
2416 COH901318_BE_INT_CLEAR2);
2417 writel(1 << (cohc->id - 32), virtbase +
2418 COH901318_TC_INT_CLEAR2);
2419 }
2420
2421 enable_powersave(cohc);
2422
2423 while ((cohd = coh901318_first_active_get(cohc))) {
2424 /* release the lli allocation*/
Linus Walleijcecd87d2010-03-04 14:31:47 +01002425 coh901318_lli_free(&cohc->base->pool, &cohd->lli);
Linus Walleij61f135b2009-11-19 19:49:17 +01002426
Linus Walleij61f135b2009-11-19 19:49:17 +01002427 /* return desc to free-list */
Linus Walleij848ad122010-03-02 14:17:15 -07002428 coh901318_desc_remove(cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01002429 coh901318_desc_free(cohc, cohd);
2430 }
2431
2432 while ((cohd = coh901318_first_queued(cohc))) {
2433 /* release the lli allocation*/
Linus Walleijcecd87d2010-03-04 14:31:47 +01002434 coh901318_lli_free(&cohc->base->pool, &cohd->lli);
Linus Walleij61f135b2009-11-19 19:49:17 +01002435
Linus Walleij61f135b2009-11-19 19:49:17 +01002436 /* return desc to free-list */
Linus Walleij848ad122010-03-02 14:17:15 -07002437 coh901318_desc_remove(cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01002438 coh901318_desc_free(cohc, cohd);
2439 }
2440
2441
2442 cohc->nbr_active_done = 0;
2443 cohc->busy = 0;
Linus Walleij61f135b2009-11-19 19:49:17 +01002444
2445 spin_unlock_irqrestore(&cohc->lock, flags);
Linus Walleijc3635c72010-03-26 16:44:01 -07002446
2447 return 0;
Linus Walleij61f135b2009-11-19 19:49:17 +01002448}
Linus Walleij128f9042010-08-04 13:37:53 +02002449
Linus Walleij61f135b2009-11-19 19:49:17 +01002450void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
2451 struct coh901318_base *base)
2452{
2453 int chans_i;
2454 int i = 0;
2455 struct coh901318_chan *cohc;
2456
2457 INIT_LIST_HEAD(&dma->channels);
2458
2459 for (chans_i = 0; pick_chans[chans_i] != -1; chans_i += 2) {
2460 for (i = pick_chans[chans_i]; i <= pick_chans[chans_i+1]; i++) {
2461 cohc = &base->chans[i];
2462
2463 cohc->base = base;
2464 cohc->chan.device = dma;
2465 cohc->id = i;
2466
2467 /* TODO: do we really need this lock if only one
2468 * client is connected to each channel?
2469 */
2470
2471 spin_lock_init(&cohc->lock);
2472
Linus Walleij61f135b2009-11-19 19:49:17 +01002473 cohc->nbr_active_done = 0;
2474 cohc->busy = 0;
2475 INIT_LIST_HEAD(&cohc->free);
2476 INIT_LIST_HEAD(&cohc->active);
2477 INIT_LIST_HEAD(&cohc->queue);
2478
2479 tasklet_init(&cohc->tasklet, dma_tasklet,
2480 (unsigned long) cohc);
2481
2482 list_add_tail(&cohc->chan.device_node,
2483 &dma->channels);
2484 }
2485 }
2486}
2487
2488static int __init coh901318_probe(struct platform_device *pdev)
2489{
2490 int err = 0;
2491 struct coh901318_platform *pdata;
2492 struct coh901318_base *base;
2493 int irq;
2494 struct resource *io;
2495
2496 io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2497 if (!io)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002498 return -ENODEV;
Linus Walleij61f135b2009-11-19 19:49:17 +01002499
2500 /* Map DMA controller registers to virtual memory */
Linus Walleijf7ceb362012-06-12 20:19:24 +02002501 if (devm_request_mem_region(&pdev->dev,
2502 io->start,
2503 resource_size(io),
2504 pdev->dev.driver->name) == NULL)
2505 return -ENOMEM;
Linus Walleij61f135b2009-11-19 19:49:17 +01002506
Linus Walleij24dbcd82013-01-04 13:38:18 +01002507 pdata = &coh901318_platform,
Linus Walleij61f135b2009-11-19 19:49:17 +01002508
Linus Walleijf7ceb362012-06-12 20:19:24 +02002509 base = devm_kzalloc(&pdev->dev,
2510 ALIGN(sizeof(struct coh901318_base), 4) +
2511 pdata->max_channels *
2512 sizeof(struct coh901318_chan),
2513 GFP_KERNEL);
Linus Walleij61f135b2009-11-19 19:49:17 +01002514 if (!base)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002515 return -ENOMEM;
Linus Walleij61f135b2009-11-19 19:49:17 +01002516
2517 base->chans = ((void *)base) + ALIGN(sizeof(struct coh901318_base), 4);
2518
Linus Walleijf7ceb362012-06-12 20:19:24 +02002519 base->virtbase = devm_ioremap(&pdev->dev, io->start, resource_size(io));
2520 if (!base->virtbase)
2521 return -ENOMEM;
Linus Walleij61f135b2009-11-19 19:49:17 +01002522
2523 base->dev = &pdev->dev;
2524 base->platform = pdata;
2525 spin_lock_init(&base->pm.lock);
2526 base->pm.started_channels = 0;
2527
2528 COH901318_DEBUGFS_ASSIGN(debugfs_dma_base, base);
2529
Linus Walleij61f135b2009-11-19 19:49:17 +01002530 irq = platform_get_irq(pdev, 0);
2531 if (irq < 0)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002532 return irq;
Linus Walleij61f135b2009-11-19 19:49:17 +01002533
Linus Walleijf7ceb362012-06-12 20:19:24 +02002534 err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, IRQF_DISABLED,
2535 "coh901318", base);
2536 if (err)
2537 return err;
Linus Walleij61f135b2009-11-19 19:49:17 +01002538
2539 err = coh901318_pool_create(&base->pool, &pdev->dev,
2540 sizeof(struct coh901318_lli),
2541 32);
2542 if (err)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002543 return err;
Linus Walleij61f135b2009-11-19 19:49:17 +01002544
2545 /* init channels for device transfers */
2546 coh901318_base_init(&base->dma_slave, base->platform->chans_slave,
2547 base);
2548
2549 dma_cap_zero(base->dma_slave.cap_mask);
2550 dma_cap_set(DMA_SLAVE, base->dma_slave.cap_mask);
2551
2552 base->dma_slave.device_alloc_chan_resources = coh901318_alloc_chan_resources;
2553 base->dma_slave.device_free_chan_resources = coh901318_free_chan_resources;
2554 base->dma_slave.device_prep_slave_sg = coh901318_prep_slave_sg;
Linus Walleij07934482010-03-26 16:50:49 -07002555 base->dma_slave.device_tx_status = coh901318_tx_status;
Linus Walleij61f135b2009-11-19 19:49:17 +01002556 base->dma_slave.device_issue_pending = coh901318_issue_pending;
Linus Walleijc3635c72010-03-26 16:44:01 -07002557 base->dma_slave.device_control = coh901318_control;
Linus Walleij61f135b2009-11-19 19:49:17 +01002558 base->dma_slave.dev = &pdev->dev;
2559
2560 err = dma_async_device_register(&base->dma_slave);
2561
2562 if (err)
2563 goto err_register_slave;
2564
2565 /* init channels for memcpy */
2566 coh901318_base_init(&base->dma_memcpy, base->platform->chans_memcpy,
2567 base);
2568
2569 dma_cap_zero(base->dma_memcpy.cap_mask);
2570 dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask);
2571
2572 base->dma_memcpy.device_alloc_chan_resources = coh901318_alloc_chan_resources;
2573 base->dma_memcpy.device_free_chan_resources = coh901318_free_chan_resources;
2574 base->dma_memcpy.device_prep_dma_memcpy = coh901318_prep_memcpy;
Linus Walleij07934482010-03-26 16:50:49 -07002575 base->dma_memcpy.device_tx_status = coh901318_tx_status;
Linus Walleij61f135b2009-11-19 19:49:17 +01002576 base->dma_memcpy.device_issue_pending = coh901318_issue_pending;
Linus Walleijc3635c72010-03-26 16:44:01 -07002577 base->dma_memcpy.device_control = coh901318_control;
Linus Walleij61f135b2009-11-19 19:49:17 +01002578 base->dma_memcpy.dev = &pdev->dev;
Linus Walleij516fd432010-03-02 20:12:46 +01002579 /*
2580 * This controller can only access address at even 32bit boundaries,
2581 * i.e. 2^2
2582 */
2583 base->dma_memcpy.copy_align = 2;
Linus Walleij61f135b2009-11-19 19:49:17 +01002584 err = dma_async_device_register(&base->dma_memcpy);
2585
2586 if (err)
2587 goto err_register_memcpy;
2588
Linus Walleijf7ceb362012-06-12 20:19:24 +02002589 platform_set_drvdata(pdev, base);
Linus Walleij848ad122010-03-02 14:17:15 -07002590 dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
Linus Walleij61f135b2009-11-19 19:49:17 +01002591 (u32) base->virtbase);
2592
2593 return err;
2594
2595 err_register_memcpy:
2596 dma_async_device_unregister(&base->dma_slave);
2597 err_register_slave:
2598 coh901318_pool_destroy(&base->pool);
Linus Walleij61f135b2009-11-19 19:49:17 +01002599 return err;
2600}
2601
2602static int __exit coh901318_remove(struct platform_device *pdev)
2603{
2604 struct coh901318_base *base = platform_get_drvdata(pdev);
2605
2606 dma_async_device_unregister(&base->dma_memcpy);
2607 dma_async_device_unregister(&base->dma_slave);
2608 coh901318_pool_destroy(&base->pool);
Linus Walleij61f135b2009-11-19 19:49:17 +01002609 return 0;
2610}
2611
2612
2613static struct platform_driver coh901318_driver = {
2614 .remove = __exit_p(coh901318_remove),
2615 .driver = {
2616 .name = "coh901318",
2617 },
2618};
2619
2620int __init coh901318_init(void)
2621{
2622 return platform_driver_probe(&coh901318_driver, coh901318_probe);
2623}
Linus Walleija0eb2212011-05-18 14:18:57 +02002624subsys_initcall(coh901318_init);
Linus Walleij61f135b2009-11-19 19:49:17 +01002625
2626void __exit coh901318_exit(void)
2627{
2628 platform_driver_unregister(&coh901318_driver);
2629}
2630module_exit(coh901318_exit);
2631
2632MODULE_LICENSE("GPL");
2633MODULE_AUTHOR("Per Friden");