blob: 06d97955c544547190e1e8620edd0cc0aafbda90 [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#include <mach/coh901318.h>
Linus Walleij24dbcd82013-01-04 13:38:18 +010026#include <mach/u300-regs.h>
Linus Walleij61f135b2009-11-19 19:49:17 +010027
28#include "coh901318_lli.h"
Russell King - ARM Linuxd2ebfb32012-03-06 22:34:26 +000029#include "dmaengine.h"
Linus Walleij61f135b2009-11-19 19:49:17 +010030
Linus Walleij24dbcd82013-01-04 13:38:18 +010031/* points out all dma slave channels.
32 * Syntax is [A1, B1, A2, B2, .... ,-1,-1]
33 * Select all channels from A to B, end of list is marked with -1,-1
34 */
35static int dma_slave_channels[] = {
36 U300_DMA_MSL_TX_0, U300_DMA_SPI_RX,
37 U300_DMA_UART1_TX, U300_DMA_UART1_RX, -1, -1};
38
39/* points out all dma memcpy channels. */
40static int dma_memcpy_channels[] = {
41 U300_DMA_GENERAL_PURPOSE_0, U300_DMA_GENERAL_PURPOSE_8, -1, -1};
42
43/** register dma for memory access
44 *
45 * active 1 means dma intends to access memory
46 * 0 means dma wont access memory
47 */
48static void coh901318_access_memory_state(struct device *dev, bool active)
49{
50}
51
52#define flags_memcpy_config (COH901318_CX_CFG_CH_DISABLE | \
53 COH901318_CX_CFG_RM_MEMORY_TO_MEMORY | \
54 COH901318_CX_CFG_LCR_DISABLE | \
55 COH901318_CX_CFG_TC_IRQ_ENABLE | \
56 COH901318_CX_CFG_BE_IRQ_ENABLE)
57#define flags_memcpy_lli_chained (COH901318_CX_CTRL_TC_ENABLE | \
58 COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \
59 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \
60 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \
61 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \
62 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \
63 COH901318_CX_CTRL_MASTER_MODE_M1RW | \
64 COH901318_CX_CTRL_TCP_DISABLE | \
65 COH901318_CX_CTRL_TC_IRQ_DISABLE | \
66 COH901318_CX_CTRL_HSP_DISABLE | \
67 COH901318_CX_CTRL_HSS_DISABLE | \
68 COH901318_CX_CTRL_DDMA_LEGACY | \
69 COH901318_CX_CTRL_PRDD_SOURCE)
70#define flags_memcpy_lli (COH901318_CX_CTRL_TC_ENABLE | \
71 COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \
72 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \
73 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \
74 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \
75 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \
76 COH901318_CX_CTRL_MASTER_MODE_M1RW | \
77 COH901318_CX_CTRL_TCP_DISABLE | \
78 COH901318_CX_CTRL_TC_IRQ_DISABLE | \
79 COH901318_CX_CTRL_HSP_DISABLE | \
80 COH901318_CX_CTRL_HSS_DISABLE | \
81 COH901318_CX_CTRL_DDMA_LEGACY | \
82 COH901318_CX_CTRL_PRDD_SOURCE)
83#define flags_memcpy_lli_last (COH901318_CX_CTRL_TC_ENABLE | \
84 COH901318_CX_CTRL_BURST_COUNT_32_BYTES | \
85 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | \
86 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE | \
87 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | \
88 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE | \
89 COH901318_CX_CTRL_MASTER_MODE_M1RW | \
90 COH901318_CX_CTRL_TCP_DISABLE | \
91 COH901318_CX_CTRL_TC_IRQ_ENABLE | \
92 COH901318_CX_CTRL_HSP_DISABLE | \
93 COH901318_CX_CTRL_HSS_DISABLE | \
94 COH901318_CX_CTRL_DDMA_LEGACY | \
95 COH901318_CX_CTRL_PRDD_SOURCE)
96
97const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
98 {
99 .number = U300_DMA_MSL_TX_0,
100 .name = "MSL TX 0",
101 .priority_high = 0,
102 .dev_addr = U300_MSL_BASE + 0 * 0x40 + 0x20,
103 },
104 {
105 .number = U300_DMA_MSL_TX_1,
106 .name = "MSL TX 1",
107 .priority_high = 0,
108 .dev_addr = U300_MSL_BASE + 1 * 0x40 + 0x20,
109 .param.config = COH901318_CX_CFG_CH_DISABLE |
110 COH901318_CX_CFG_LCR_DISABLE |
111 COH901318_CX_CFG_TC_IRQ_ENABLE |
112 COH901318_CX_CFG_BE_IRQ_ENABLE,
113 .param.ctrl_lli_chained = 0 |
114 COH901318_CX_CTRL_TC_ENABLE |
115 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
116 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
117 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
118 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
119 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
120 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
121 COH901318_CX_CTRL_TCP_DISABLE |
122 COH901318_CX_CTRL_TC_IRQ_DISABLE |
123 COH901318_CX_CTRL_HSP_ENABLE |
124 COH901318_CX_CTRL_HSS_DISABLE |
125 COH901318_CX_CTRL_DDMA_LEGACY |
126 COH901318_CX_CTRL_PRDD_SOURCE,
127 .param.ctrl_lli = 0 |
128 COH901318_CX_CTRL_TC_ENABLE |
129 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
130 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
131 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
132 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
133 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
134 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
135 COH901318_CX_CTRL_TCP_ENABLE |
136 COH901318_CX_CTRL_TC_IRQ_DISABLE |
137 COH901318_CX_CTRL_HSP_ENABLE |
138 COH901318_CX_CTRL_HSS_DISABLE |
139 COH901318_CX_CTRL_DDMA_LEGACY |
140 COH901318_CX_CTRL_PRDD_SOURCE,
141 .param.ctrl_lli_last = 0 |
142 COH901318_CX_CTRL_TC_ENABLE |
143 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
144 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
145 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
146 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
147 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
148 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
149 COH901318_CX_CTRL_TCP_ENABLE |
150 COH901318_CX_CTRL_TC_IRQ_ENABLE |
151 COH901318_CX_CTRL_HSP_ENABLE |
152 COH901318_CX_CTRL_HSS_DISABLE |
153 COH901318_CX_CTRL_DDMA_LEGACY |
154 COH901318_CX_CTRL_PRDD_SOURCE,
155 },
156 {
157 .number = U300_DMA_MSL_TX_2,
158 .name = "MSL TX 2",
159 .priority_high = 0,
160 .dev_addr = U300_MSL_BASE + 2 * 0x40 + 0x20,
161 .param.config = COH901318_CX_CFG_CH_DISABLE |
162 COH901318_CX_CFG_LCR_DISABLE |
163 COH901318_CX_CFG_TC_IRQ_ENABLE |
164 COH901318_CX_CFG_BE_IRQ_ENABLE,
165 .param.ctrl_lli_chained = 0 |
166 COH901318_CX_CTRL_TC_ENABLE |
167 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
168 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
169 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
170 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
171 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
172 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
173 COH901318_CX_CTRL_TCP_DISABLE |
174 COH901318_CX_CTRL_TC_IRQ_DISABLE |
175 COH901318_CX_CTRL_HSP_ENABLE |
176 COH901318_CX_CTRL_HSS_DISABLE |
177 COH901318_CX_CTRL_DDMA_LEGACY |
178 COH901318_CX_CTRL_PRDD_SOURCE,
179 .param.ctrl_lli = 0 |
180 COH901318_CX_CTRL_TC_ENABLE |
181 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
182 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
183 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
184 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
185 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
186 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
187 COH901318_CX_CTRL_TCP_ENABLE |
188 COH901318_CX_CTRL_TC_IRQ_DISABLE |
189 COH901318_CX_CTRL_HSP_ENABLE |
190 COH901318_CX_CTRL_HSS_DISABLE |
191 COH901318_CX_CTRL_DDMA_LEGACY |
192 COH901318_CX_CTRL_PRDD_SOURCE,
193 .param.ctrl_lli_last = 0 |
194 COH901318_CX_CTRL_TC_ENABLE |
195 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
196 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
197 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
198 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
199 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
200 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
201 COH901318_CX_CTRL_TCP_ENABLE |
202 COH901318_CX_CTRL_TC_IRQ_ENABLE |
203 COH901318_CX_CTRL_HSP_ENABLE |
204 COH901318_CX_CTRL_HSS_DISABLE |
205 COH901318_CX_CTRL_DDMA_LEGACY |
206 COH901318_CX_CTRL_PRDD_SOURCE,
207 .desc_nbr_max = 10,
208 },
209 {
210 .number = U300_DMA_MSL_TX_3,
211 .name = "MSL TX 3",
212 .priority_high = 0,
213 .dev_addr = U300_MSL_BASE + 3 * 0x40 + 0x20,
214 .param.config = COH901318_CX_CFG_CH_DISABLE |
215 COH901318_CX_CFG_LCR_DISABLE |
216 COH901318_CX_CFG_TC_IRQ_ENABLE |
217 COH901318_CX_CFG_BE_IRQ_ENABLE,
218 .param.ctrl_lli_chained = 0 |
219 COH901318_CX_CTRL_TC_ENABLE |
220 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
221 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
222 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
223 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
224 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
225 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
226 COH901318_CX_CTRL_TCP_DISABLE |
227 COH901318_CX_CTRL_TC_IRQ_DISABLE |
228 COH901318_CX_CTRL_HSP_ENABLE |
229 COH901318_CX_CTRL_HSS_DISABLE |
230 COH901318_CX_CTRL_DDMA_LEGACY |
231 COH901318_CX_CTRL_PRDD_SOURCE,
232 .param.ctrl_lli = 0 |
233 COH901318_CX_CTRL_TC_ENABLE |
234 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
235 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
236 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
237 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
238 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
239 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
240 COH901318_CX_CTRL_TCP_ENABLE |
241 COH901318_CX_CTRL_TC_IRQ_DISABLE |
242 COH901318_CX_CTRL_HSP_ENABLE |
243 COH901318_CX_CTRL_HSS_DISABLE |
244 COH901318_CX_CTRL_DDMA_LEGACY |
245 COH901318_CX_CTRL_PRDD_SOURCE,
246 .param.ctrl_lli_last = 0 |
247 COH901318_CX_CTRL_TC_ENABLE |
248 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
249 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
250 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
251 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
252 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
253 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
254 COH901318_CX_CTRL_TCP_ENABLE |
255 COH901318_CX_CTRL_TC_IRQ_ENABLE |
256 COH901318_CX_CTRL_HSP_ENABLE |
257 COH901318_CX_CTRL_HSS_DISABLE |
258 COH901318_CX_CTRL_DDMA_LEGACY |
259 COH901318_CX_CTRL_PRDD_SOURCE,
260 },
261 {
262 .number = U300_DMA_MSL_TX_4,
263 .name = "MSL TX 4",
264 .priority_high = 0,
265 .dev_addr = U300_MSL_BASE + 4 * 0x40 + 0x20,
266 .param.config = COH901318_CX_CFG_CH_DISABLE |
267 COH901318_CX_CFG_LCR_DISABLE |
268 COH901318_CX_CFG_TC_IRQ_ENABLE |
269 COH901318_CX_CFG_BE_IRQ_ENABLE,
270 .param.ctrl_lli_chained = 0 |
271 COH901318_CX_CTRL_TC_ENABLE |
272 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
273 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
274 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
275 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
276 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
277 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
278 COH901318_CX_CTRL_TCP_DISABLE |
279 COH901318_CX_CTRL_TC_IRQ_DISABLE |
280 COH901318_CX_CTRL_HSP_ENABLE |
281 COH901318_CX_CTRL_HSS_DISABLE |
282 COH901318_CX_CTRL_DDMA_LEGACY |
283 COH901318_CX_CTRL_PRDD_SOURCE,
284 .param.ctrl_lli = 0 |
285 COH901318_CX_CTRL_TC_ENABLE |
286 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
287 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
288 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
289 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
290 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
291 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
292 COH901318_CX_CTRL_TCP_ENABLE |
293 COH901318_CX_CTRL_TC_IRQ_DISABLE |
294 COH901318_CX_CTRL_HSP_ENABLE |
295 COH901318_CX_CTRL_HSS_DISABLE |
296 COH901318_CX_CTRL_DDMA_LEGACY |
297 COH901318_CX_CTRL_PRDD_SOURCE,
298 .param.ctrl_lli_last = 0 |
299 COH901318_CX_CTRL_TC_ENABLE |
300 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
301 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
302 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
303 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
304 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
305 COH901318_CX_CTRL_MASTER_MODE_M1R_M2W |
306 COH901318_CX_CTRL_TCP_ENABLE |
307 COH901318_CX_CTRL_TC_IRQ_ENABLE |
308 COH901318_CX_CTRL_HSP_ENABLE |
309 COH901318_CX_CTRL_HSS_DISABLE |
310 COH901318_CX_CTRL_DDMA_LEGACY |
311 COH901318_CX_CTRL_PRDD_SOURCE,
312 },
313 {
314 .number = U300_DMA_MSL_TX_5,
315 .name = "MSL TX 5",
316 .priority_high = 0,
317 .dev_addr = U300_MSL_BASE + 5 * 0x40 + 0x20,
318 },
319 {
320 .number = U300_DMA_MSL_TX_6,
321 .name = "MSL TX 6",
322 .priority_high = 0,
323 .dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x20,
324 },
325 {
326 .number = U300_DMA_MSL_RX_0,
327 .name = "MSL RX 0",
328 .priority_high = 0,
329 .dev_addr = U300_MSL_BASE + 0 * 0x40 + 0x220,
330 },
331 {
332 .number = U300_DMA_MSL_RX_1,
333 .name = "MSL RX 1",
334 .priority_high = 0,
335 .dev_addr = U300_MSL_BASE + 1 * 0x40 + 0x220,
336 .param.config = COH901318_CX_CFG_CH_DISABLE |
337 COH901318_CX_CFG_LCR_DISABLE |
338 COH901318_CX_CFG_TC_IRQ_ENABLE |
339 COH901318_CX_CFG_BE_IRQ_ENABLE,
340 .param.ctrl_lli_chained = 0 |
341 COH901318_CX_CTRL_TC_ENABLE |
342 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
343 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
344 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
345 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
346 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
347 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
348 COH901318_CX_CTRL_TCP_DISABLE |
349 COH901318_CX_CTRL_TC_IRQ_DISABLE |
350 COH901318_CX_CTRL_HSP_ENABLE |
351 COH901318_CX_CTRL_HSS_DISABLE |
352 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
353 COH901318_CX_CTRL_PRDD_DEST,
354 .param.ctrl_lli = 0,
355 .param.ctrl_lli_last = 0 |
356 COH901318_CX_CTRL_TC_ENABLE |
357 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
358 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
359 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
360 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
361 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
362 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
363 COH901318_CX_CTRL_TCP_DISABLE |
364 COH901318_CX_CTRL_TC_IRQ_ENABLE |
365 COH901318_CX_CTRL_HSP_ENABLE |
366 COH901318_CX_CTRL_HSS_DISABLE |
367 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
368 COH901318_CX_CTRL_PRDD_DEST,
369 },
370 {
371 .number = U300_DMA_MSL_RX_2,
372 .name = "MSL RX 2",
373 .priority_high = 0,
374 .dev_addr = U300_MSL_BASE + 2 * 0x40 + 0x220,
375 .param.config = COH901318_CX_CFG_CH_DISABLE |
376 COH901318_CX_CFG_LCR_DISABLE |
377 COH901318_CX_CFG_TC_IRQ_ENABLE |
378 COH901318_CX_CFG_BE_IRQ_ENABLE,
379 .param.ctrl_lli_chained = 0 |
380 COH901318_CX_CTRL_TC_ENABLE |
381 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
382 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
383 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
384 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
385 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
386 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
387 COH901318_CX_CTRL_TCP_DISABLE |
388 COH901318_CX_CTRL_TC_IRQ_DISABLE |
389 COH901318_CX_CTRL_HSP_ENABLE |
390 COH901318_CX_CTRL_HSS_DISABLE |
391 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
392 COH901318_CX_CTRL_PRDD_DEST,
393 .param.ctrl_lli = 0 |
394 COH901318_CX_CTRL_TC_ENABLE |
395 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
396 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
397 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
398 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
399 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
400 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
401 COH901318_CX_CTRL_TCP_DISABLE |
402 COH901318_CX_CTRL_TC_IRQ_ENABLE |
403 COH901318_CX_CTRL_HSP_ENABLE |
404 COH901318_CX_CTRL_HSS_DISABLE |
405 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
406 COH901318_CX_CTRL_PRDD_DEST,
407 .param.ctrl_lli_last = 0 |
408 COH901318_CX_CTRL_TC_ENABLE |
409 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
410 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
411 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
412 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
413 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
414 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
415 COH901318_CX_CTRL_TCP_DISABLE |
416 COH901318_CX_CTRL_TC_IRQ_ENABLE |
417 COH901318_CX_CTRL_HSP_ENABLE |
418 COH901318_CX_CTRL_HSS_DISABLE |
419 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
420 COH901318_CX_CTRL_PRDD_DEST,
421 },
422 {
423 .number = U300_DMA_MSL_RX_3,
424 .name = "MSL RX 3",
425 .priority_high = 0,
426 .dev_addr = U300_MSL_BASE + 3 * 0x40 + 0x220,
427 .param.config = COH901318_CX_CFG_CH_DISABLE |
428 COH901318_CX_CFG_LCR_DISABLE |
429 COH901318_CX_CFG_TC_IRQ_ENABLE |
430 COH901318_CX_CFG_BE_IRQ_ENABLE,
431 .param.ctrl_lli_chained = 0 |
432 COH901318_CX_CTRL_TC_ENABLE |
433 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
434 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
435 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
436 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
437 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
438 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
439 COH901318_CX_CTRL_TCP_DISABLE |
440 COH901318_CX_CTRL_TC_IRQ_DISABLE |
441 COH901318_CX_CTRL_HSP_ENABLE |
442 COH901318_CX_CTRL_HSS_DISABLE |
443 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
444 COH901318_CX_CTRL_PRDD_DEST,
445 .param.ctrl_lli = 0 |
446 COH901318_CX_CTRL_TC_ENABLE |
447 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
448 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
449 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
450 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
451 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
452 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
453 COH901318_CX_CTRL_TCP_DISABLE |
454 COH901318_CX_CTRL_TC_IRQ_ENABLE |
455 COH901318_CX_CTRL_HSP_ENABLE |
456 COH901318_CX_CTRL_HSS_DISABLE |
457 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
458 COH901318_CX_CTRL_PRDD_DEST,
459 .param.ctrl_lli_last = 0 |
460 COH901318_CX_CTRL_TC_ENABLE |
461 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
462 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
463 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
464 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
465 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
466 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
467 COH901318_CX_CTRL_TCP_DISABLE |
468 COH901318_CX_CTRL_TC_IRQ_ENABLE |
469 COH901318_CX_CTRL_HSP_ENABLE |
470 COH901318_CX_CTRL_HSS_DISABLE |
471 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
472 COH901318_CX_CTRL_PRDD_DEST,
473 },
474 {
475 .number = U300_DMA_MSL_RX_4,
476 .name = "MSL RX 4",
477 .priority_high = 0,
478 .dev_addr = U300_MSL_BASE + 4 * 0x40 + 0x220,
479 .param.config = COH901318_CX_CFG_CH_DISABLE |
480 COH901318_CX_CFG_LCR_DISABLE |
481 COH901318_CX_CFG_TC_IRQ_ENABLE |
482 COH901318_CX_CFG_BE_IRQ_ENABLE,
483 .param.ctrl_lli_chained = 0 |
484 COH901318_CX_CTRL_TC_ENABLE |
485 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
486 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
487 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
488 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
489 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
490 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
491 COH901318_CX_CTRL_TCP_DISABLE |
492 COH901318_CX_CTRL_TC_IRQ_DISABLE |
493 COH901318_CX_CTRL_HSP_ENABLE |
494 COH901318_CX_CTRL_HSS_DISABLE |
495 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
496 COH901318_CX_CTRL_PRDD_DEST,
497 .param.ctrl_lli = 0 |
498 COH901318_CX_CTRL_TC_ENABLE |
499 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
500 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
501 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
502 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
503 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
504 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
505 COH901318_CX_CTRL_TCP_DISABLE |
506 COH901318_CX_CTRL_TC_IRQ_ENABLE |
507 COH901318_CX_CTRL_HSP_ENABLE |
508 COH901318_CX_CTRL_HSS_DISABLE |
509 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
510 COH901318_CX_CTRL_PRDD_DEST,
511 .param.ctrl_lli_last = 0 |
512 COH901318_CX_CTRL_TC_ENABLE |
513 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
514 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
515 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
516 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
517 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
518 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
519 COH901318_CX_CTRL_TCP_DISABLE |
520 COH901318_CX_CTRL_TC_IRQ_ENABLE |
521 COH901318_CX_CTRL_HSP_ENABLE |
522 COH901318_CX_CTRL_HSS_DISABLE |
523 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
524 COH901318_CX_CTRL_PRDD_DEST,
525 },
526 {
527 .number = U300_DMA_MSL_RX_5,
528 .name = "MSL RX 5",
529 .priority_high = 0,
530 .dev_addr = U300_MSL_BASE + 5 * 0x40 + 0x220,
531 .param.config = COH901318_CX_CFG_CH_DISABLE |
532 COH901318_CX_CFG_LCR_DISABLE |
533 COH901318_CX_CFG_TC_IRQ_ENABLE |
534 COH901318_CX_CFG_BE_IRQ_ENABLE,
535 .param.ctrl_lli_chained = 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_DISABLE |
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 = 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 .param.ctrl_lli_last = 0 |
564 COH901318_CX_CTRL_TC_ENABLE |
565 COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
566 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
567 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
568 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
569 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
570 COH901318_CX_CTRL_MASTER_MODE_M2R_M1W |
571 COH901318_CX_CTRL_TCP_DISABLE |
572 COH901318_CX_CTRL_TC_IRQ_ENABLE |
573 COH901318_CX_CTRL_HSP_ENABLE |
574 COH901318_CX_CTRL_HSS_DISABLE |
575 COH901318_CX_CTRL_DDMA_DEMAND_DMA1 |
576 COH901318_CX_CTRL_PRDD_DEST,
577 },
578 {
579 .number = U300_DMA_MSL_RX_6,
580 .name = "MSL RX 6",
581 .priority_high = 0,
582 .dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220,
583 },
584 /*
585 * Don't set up device address, burst count or size of src
586 * or dst bus for this peripheral - handled by PrimeCell
587 * DMA extension.
588 */
589 {
590 .number = U300_DMA_MMCSD_RX_TX,
591 .name = "MMCSD RX TX",
592 .priority_high = 0,
593 .param.config = COH901318_CX_CFG_CH_DISABLE |
594 COH901318_CX_CFG_LCR_DISABLE |
595 COH901318_CX_CFG_TC_IRQ_ENABLE |
596 COH901318_CX_CFG_BE_IRQ_ENABLE,
597 .param.ctrl_lli_chained = 0 |
598 COH901318_CX_CTRL_TC_ENABLE |
599 COH901318_CX_CTRL_MASTER_MODE_M1RW |
600 COH901318_CX_CTRL_TCP_ENABLE |
601 COH901318_CX_CTRL_TC_IRQ_DISABLE |
602 COH901318_CX_CTRL_HSP_ENABLE |
603 COH901318_CX_CTRL_HSS_DISABLE |
604 COH901318_CX_CTRL_DDMA_LEGACY,
605 .param.ctrl_lli = 0 |
606 COH901318_CX_CTRL_TC_ENABLE |
607 COH901318_CX_CTRL_MASTER_MODE_M1RW |
608 COH901318_CX_CTRL_TCP_ENABLE |
609 COH901318_CX_CTRL_TC_IRQ_DISABLE |
610 COH901318_CX_CTRL_HSP_ENABLE |
611 COH901318_CX_CTRL_HSS_DISABLE |
612 COH901318_CX_CTRL_DDMA_LEGACY,
613 .param.ctrl_lli_last = 0 |
614 COH901318_CX_CTRL_TC_ENABLE |
615 COH901318_CX_CTRL_MASTER_MODE_M1RW |
616 COH901318_CX_CTRL_TCP_DISABLE |
617 COH901318_CX_CTRL_TC_IRQ_ENABLE |
618 COH901318_CX_CTRL_HSP_ENABLE |
619 COH901318_CX_CTRL_HSS_DISABLE |
620 COH901318_CX_CTRL_DDMA_LEGACY,
621
622 },
623 {
624 .number = U300_DMA_MSPRO_TX,
625 .name = "MSPRO TX",
626 .priority_high = 0,
627 },
628 {
629 .number = U300_DMA_MSPRO_RX,
630 .name = "MSPRO RX",
631 .priority_high = 0,
632 },
633 /*
634 * Don't set up device address, burst count or size of src
635 * or dst bus for this peripheral - handled by PrimeCell
636 * DMA extension.
637 */
638 {
639 .number = U300_DMA_UART0_TX,
640 .name = "UART0 TX",
641 .priority_high = 0,
642 .param.config = COH901318_CX_CFG_CH_DISABLE |
643 COH901318_CX_CFG_LCR_DISABLE |
644 COH901318_CX_CFG_TC_IRQ_ENABLE |
645 COH901318_CX_CFG_BE_IRQ_ENABLE,
646 .param.ctrl_lli_chained = 0 |
647 COH901318_CX_CTRL_TC_ENABLE |
648 COH901318_CX_CTRL_MASTER_MODE_M1RW |
649 COH901318_CX_CTRL_TCP_ENABLE |
650 COH901318_CX_CTRL_TC_IRQ_DISABLE |
651 COH901318_CX_CTRL_HSP_ENABLE |
652 COH901318_CX_CTRL_HSS_DISABLE |
653 COH901318_CX_CTRL_DDMA_LEGACY,
654 .param.ctrl_lli = 0 |
655 COH901318_CX_CTRL_TC_ENABLE |
656 COH901318_CX_CTRL_MASTER_MODE_M1RW |
657 COH901318_CX_CTRL_TCP_ENABLE |
658 COH901318_CX_CTRL_TC_IRQ_ENABLE |
659 COH901318_CX_CTRL_HSP_ENABLE |
660 COH901318_CX_CTRL_HSS_DISABLE |
661 COH901318_CX_CTRL_DDMA_LEGACY,
662 .param.ctrl_lli_last = 0 |
663 COH901318_CX_CTRL_TC_ENABLE |
664 COH901318_CX_CTRL_MASTER_MODE_M1RW |
665 COH901318_CX_CTRL_TCP_ENABLE |
666 COH901318_CX_CTRL_TC_IRQ_ENABLE |
667 COH901318_CX_CTRL_HSP_ENABLE |
668 COH901318_CX_CTRL_HSS_DISABLE |
669 COH901318_CX_CTRL_DDMA_LEGACY,
670 },
671 {
672 .number = U300_DMA_UART0_RX,
673 .name = "UART0 RX",
674 .priority_high = 0,
675 .param.config = COH901318_CX_CFG_CH_DISABLE |
676 COH901318_CX_CFG_LCR_DISABLE |
677 COH901318_CX_CFG_TC_IRQ_ENABLE |
678 COH901318_CX_CFG_BE_IRQ_ENABLE,
679 .param.ctrl_lli_chained = 0 |
680 COH901318_CX_CTRL_TC_ENABLE |
681 COH901318_CX_CTRL_MASTER_MODE_M1RW |
682 COH901318_CX_CTRL_TCP_ENABLE |
683 COH901318_CX_CTRL_TC_IRQ_DISABLE |
684 COH901318_CX_CTRL_HSP_ENABLE |
685 COH901318_CX_CTRL_HSS_DISABLE |
686 COH901318_CX_CTRL_DDMA_LEGACY,
687 .param.ctrl_lli = 0 |
688 COH901318_CX_CTRL_TC_ENABLE |
689 COH901318_CX_CTRL_MASTER_MODE_M1RW |
690 COH901318_CX_CTRL_TCP_ENABLE |
691 COH901318_CX_CTRL_TC_IRQ_ENABLE |
692 COH901318_CX_CTRL_HSP_ENABLE |
693 COH901318_CX_CTRL_HSS_DISABLE |
694 COH901318_CX_CTRL_DDMA_LEGACY,
695 .param.ctrl_lli_last = 0 |
696 COH901318_CX_CTRL_TC_ENABLE |
697 COH901318_CX_CTRL_MASTER_MODE_M1RW |
698 COH901318_CX_CTRL_TCP_ENABLE |
699 COH901318_CX_CTRL_TC_IRQ_ENABLE |
700 COH901318_CX_CTRL_HSP_ENABLE |
701 COH901318_CX_CTRL_HSS_DISABLE |
702 COH901318_CX_CTRL_DDMA_LEGACY,
703 },
704 {
705 .number = U300_DMA_APEX_TX,
706 .name = "APEX TX",
707 .priority_high = 0,
708 },
709 {
710 .number = U300_DMA_APEX_RX,
711 .name = "APEX RX",
712 .priority_high = 0,
713 },
714 {
715 .number = U300_DMA_PCM_I2S0_TX,
716 .name = "PCM I2S0 TX",
717 .priority_high = 1,
718 .dev_addr = U300_PCM_I2S0_BASE + 0x14,
719 .param.config = COH901318_CX_CFG_CH_DISABLE |
720 COH901318_CX_CFG_LCR_DISABLE |
721 COH901318_CX_CFG_TC_IRQ_ENABLE |
722 COH901318_CX_CFG_BE_IRQ_ENABLE,
723 .param.ctrl_lli_chained = 0 |
724 COH901318_CX_CTRL_TC_ENABLE |
725 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
726 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
727 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
728 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
729 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
730 COH901318_CX_CTRL_MASTER_MODE_M1RW |
731 COH901318_CX_CTRL_TCP_DISABLE |
732 COH901318_CX_CTRL_TC_IRQ_DISABLE |
733 COH901318_CX_CTRL_HSP_ENABLE |
734 COH901318_CX_CTRL_HSS_DISABLE |
735 COH901318_CX_CTRL_DDMA_LEGACY |
736 COH901318_CX_CTRL_PRDD_SOURCE,
737 .param.ctrl_lli = 0 |
738 COH901318_CX_CTRL_TC_ENABLE |
739 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
740 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
741 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
742 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
743 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
744 COH901318_CX_CTRL_MASTER_MODE_M1RW |
745 COH901318_CX_CTRL_TCP_ENABLE |
746 COH901318_CX_CTRL_TC_IRQ_DISABLE |
747 COH901318_CX_CTRL_HSP_ENABLE |
748 COH901318_CX_CTRL_HSS_DISABLE |
749 COH901318_CX_CTRL_DDMA_LEGACY |
750 COH901318_CX_CTRL_PRDD_SOURCE,
751 .param.ctrl_lli_last = 0 |
752 COH901318_CX_CTRL_TC_ENABLE |
753 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
754 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
755 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
756 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
757 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
758 COH901318_CX_CTRL_MASTER_MODE_M1RW |
759 COH901318_CX_CTRL_TCP_ENABLE |
760 COH901318_CX_CTRL_TC_IRQ_DISABLE |
761 COH901318_CX_CTRL_HSP_ENABLE |
762 COH901318_CX_CTRL_HSS_DISABLE |
763 COH901318_CX_CTRL_DDMA_LEGACY |
764 COH901318_CX_CTRL_PRDD_SOURCE,
765 },
766 {
767 .number = U300_DMA_PCM_I2S0_RX,
768 .name = "PCM I2S0 RX",
769 .priority_high = 1,
770 .dev_addr = U300_PCM_I2S0_BASE + 0x10,
771 .param.config = COH901318_CX_CFG_CH_DISABLE |
772 COH901318_CX_CFG_LCR_DISABLE |
773 COH901318_CX_CFG_TC_IRQ_ENABLE |
774 COH901318_CX_CFG_BE_IRQ_ENABLE,
775 .param.ctrl_lli_chained = 0 |
776 COH901318_CX_CTRL_TC_ENABLE |
777 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
778 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
779 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
780 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
781 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
782 COH901318_CX_CTRL_MASTER_MODE_M1RW |
783 COH901318_CX_CTRL_TCP_DISABLE |
784 COH901318_CX_CTRL_TC_IRQ_DISABLE |
785 COH901318_CX_CTRL_HSP_ENABLE |
786 COH901318_CX_CTRL_HSS_DISABLE |
787 COH901318_CX_CTRL_DDMA_LEGACY |
788 COH901318_CX_CTRL_PRDD_DEST,
789 .param.ctrl_lli = 0 |
790 COH901318_CX_CTRL_TC_ENABLE |
791 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
792 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
793 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
794 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
795 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
796 COH901318_CX_CTRL_MASTER_MODE_M1RW |
797 COH901318_CX_CTRL_TCP_ENABLE |
798 COH901318_CX_CTRL_TC_IRQ_DISABLE |
799 COH901318_CX_CTRL_HSP_ENABLE |
800 COH901318_CX_CTRL_HSS_DISABLE |
801 COH901318_CX_CTRL_DDMA_LEGACY |
802 COH901318_CX_CTRL_PRDD_DEST,
803 .param.ctrl_lli_last = 0 |
804 COH901318_CX_CTRL_TC_ENABLE |
805 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
806 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
807 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
808 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
809 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
810 COH901318_CX_CTRL_MASTER_MODE_M1RW |
811 COH901318_CX_CTRL_TCP_ENABLE |
812 COH901318_CX_CTRL_TC_IRQ_ENABLE |
813 COH901318_CX_CTRL_HSP_ENABLE |
814 COH901318_CX_CTRL_HSS_DISABLE |
815 COH901318_CX_CTRL_DDMA_LEGACY |
816 COH901318_CX_CTRL_PRDD_DEST,
817 },
818 {
819 .number = U300_DMA_PCM_I2S1_TX,
820 .name = "PCM I2S1 TX",
821 .priority_high = 1,
822 .dev_addr = U300_PCM_I2S1_BASE + 0x14,
823 .param.config = COH901318_CX_CFG_CH_DISABLE |
824 COH901318_CX_CFG_LCR_DISABLE |
825 COH901318_CX_CFG_TC_IRQ_ENABLE |
826 COH901318_CX_CFG_BE_IRQ_ENABLE,
827 .param.ctrl_lli_chained = 0 |
828 COH901318_CX_CTRL_TC_ENABLE |
829 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
830 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
831 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
832 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
833 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
834 COH901318_CX_CTRL_MASTER_MODE_M1RW |
835 COH901318_CX_CTRL_TCP_DISABLE |
836 COH901318_CX_CTRL_TC_IRQ_DISABLE |
837 COH901318_CX_CTRL_HSP_ENABLE |
838 COH901318_CX_CTRL_HSS_DISABLE |
839 COH901318_CX_CTRL_DDMA_LEGACY |
840 COH901318_CX_CTRL_PRDD_SOURCE,
841 .param.ctrl_lli = 0 |
842 COH901318_CX_CTRL_TC_ENABLE |
843 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
844 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
845 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
846 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
847 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
848 COH901318_CX_CTRL_MASTER_MODE_M1RW |
849 COH901318_CX_CTRL_TCP_ENABLE |
850 COH901318_CX_CTRL_TC_IRQ_DISABLE |
851 COH901318_CX_CTRL_HSP_ENABLE |
852 COH901318_CX_CTRL_HSS_DISABLE |
853 COH901318_CX_CTRL_DDMA_LEGACY |
854 COH901318_CX_CTRL_PRDD_SOURCE,
855 .param.ctrl_lli_last = 0 |
856 COH901318_CX_CTRL_TC_ENABLE |
857 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
858 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
859 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE |
860 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
861 COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
862 COH901318_CX_CTRL_MASTER_MODE_M1RW |
863 COH901318_CX_CTRL_TCP_ENABLE |
864 COH901318_CX_CTRL_TC_IRQ_ENABLE |
865 COH901318_CX_CTRL_HSP_ENABLE |
866 COH901318_CX_CTRL_HSS_DISABLE |
867 COH901318_CX_CTRL_DDMA_LEGACY |
868 COH901318_CX_CTRL_PRDD_SOURCE,
869 },
870 {
871 .number = U300_DMA_PCM_I2S1_RX,
872 .name = "PCM I2S1 RX",
873 .priority_high = 1,
874 .dev_addr = U300_PCM_I2S1_BASE + 0x10,
875 .param.config = COH901318_CX_CFG_CH_DISABLE |
876 COH901318_CX_CFG_LCR_DISABLE |
877 COH901318_CX_CFG_TC_IRQ_ENABLE |
878 COH901318_CX_CFG_BE_IRQ_ENABLE,
879 .param.ctrl_lli_chained = 0 |
880 COH901318_CX_CTRL_TC_ENABLE |
881 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
882 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
883 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
884 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
885 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
886 COH901318_CX_CTRL_MASTER_MODE_M1RW |
887 COH901318_CX_CTRL_TCP_DISABLE |
888 COH901318_CX_CTRL_TC_IRQ_DISABLE |
889 COH901318_CX_CTRL_HSP_ENABLE |
890 COH901318_CX_CTRL_HSS_DISABLE |
891 COH901318_CX_CTRL_DDMA_LEGACY |
892 COH901318_CX_CTRL_PRDD_DEST,
893 .param.ctrl_lli = 0 |
894 COH901318_CX_CTRL_TC_ENABLE |
895 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
896 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
897 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
898 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
899 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
900 COH901318_CX_CTRL_MASTER_MODE_M1RW |
901 COH901318_CX_CTRL_TCP_ENABLE |
902 COH901318_CX_CTRL_TC_IRQ_DISABLE |
903 COH901318_CX_CTRL_HSP_ENABLE |
904 COH901318_CX_CTRL_HSS_DISABLE |
905 COH901318_CX_CTRL_DDMA_LEGACY |
906 COH901318_CX_CTRL_PRDD_DEST,
907 .param.ctrl_lli_last = 0 |
908 COH901318_CX_CTRL_TC_ENABLE |
909 COH901318_CX_CTRL_BURST_COUNT_16_BYTES |
910 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
911 COH901318_CX_CTRL_SRC_ADDR_INC_DISABLE |
912 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
913 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE |
914 COH901318_CX_CTRL_MASTER_MODE_M1RW |
915 COH901318_CX_CTRL_TCP_ENABLE |
916 COH901318_CX_CTRL_TC_IRQ_ENABLE |
917 COH901318_CX_CTRL_HSP_ENABLE |
918 COH901318_CX_CTRL_HSS_DISABLE |
919 COH901318_CX_CTRL_DDMA_LEGACY |
920 COH901318_CX_CTRL_PRDD_DEST,
921 },
922 {
923 .number = U300_DMA_XGAM_CDI,
924 .name = "XGAM CDI",
925 .priority_high = 0,
926 },
927 {
928 .number = U300_DMA_XGAM_PDI,
929 .name = "XGAM PDI",
930 .priority_high = 0,
931 },
932 /*
933 * Don't set up device address, burst count or size of src
934 * or dst bus for this peripheral - handled by PrimeCell
935 * DMA extension.
936 */
937 {
938 .number = U300_DMA_SPI_TX,
939 .name = "SPI TX",
940 .priority_high = 0,
941 .param.config = COH901318_CX_CFG_CH_DISABLE |
942 COH901318_CX_CFG_LCR_DISABLE |
943 COH901318_CX_CFG_TC_IRQ_ENABLE |
944 COH901318_CX_CFG_BE_IRQ_ENABLE,
945 .param.ctrl_lli_chained = 0 |
946 COH901318_CX_CTRL_TC_ENABLE |
947 COH901318_CX_CTRL_MASTER_MODE_M1RW |
948 COH901318_CX_CTRL_TCP_DISABLE |
949 COH901318_CX_CTRL_TC_IRQ_DISABLE |
950 COH901318_CX_CTRL_HSP_ENABLE |
951 COH901318_CX_CTRL_HSS_DISABLE |
952 COH901318_CX_CTRL_DDMA_LEGACY,
953 .param.ctrl_lli = 0 |
954 COH901318_CX_CTRL_TC_ENABLE |
955 COH901318_CX_CTRL_MASTER_MODE_M1RW |
956 COH901318_CX_CTRL_TCP_DISABLE |
957 COH901318_CX_CTRL_TC_IRQ_ENABLE |
958 COH901318_CX_CTRL_HSP_ENABLE |
959 COH901318_CX_CTRL_HSS_DISABLE |
960 COH901318_CX_CTRL_DDMA_LEGACY,
961 .param.ctrl_lli_last = 0 |
962 COH901318_CX_CTRL_TC_ENABLE |
963 COH901318_CX_CTRL_MASTER_MODE_M1RW |
964 COH901318_CX_CTRL_TCP_DISABLE |
965 COH901318_CX_CTRL_TC_IRQ_ENABLE |
966 COH901318_CX_CTRL_HSP_ENABLE |
967 COH901318_CX_CTRL_HSS_DISABLE |
968 COH901318_CX_CTRL_DDMA_LEGACY,
969 },
970 {
971 .number = U300_DMA_SPI_RX,
972 .name = "SPI RX",
973 .priority_high = 0,
974 .param.config = COH901318_CX_CFG_CH_DISABLE |
975 COH901318_CX_CFG_LCR_DISABLE |
976 COH901318_CX_CFG_TC_IRQ_ENABLE |
977 COH901318_CX_CFG_BE_IRQ_ENABLE,
978 .param.ctrl_lli_chained = 0 |
979 COH901318_CX_CTRL_TC_ENABLE |
980 COH901318_CX_CTRL_MASTER_MODE_M1RW |
981 COH901318_CX_CTRL_TCP_DISABLE |
982 COH901318_CX_CTRL_TC_IRQ_DISABLE |
983 COH901318_CX_CTRL_HSP_ENABLE |
984 COH901318_CX_CTRL_HSS_DISABLE |
985 COH901318_CX_CTRL_DDMA_LEGACY,
986 .param.ctrl_lli = 0 |
987 COH901318_CX_CTRL_TC_ENABLE |
988 COH901318_CX_CTRL_MASTER_MODE_M1RW |
989 COH901318_CX_CTRL_TCP_DISABLE |
990 COH901318_CX_CTRL_TC_IRQ_ENABLE |
991 COH901318_CX_CTRL_HSP_ENABLE |
992 COH901318_CX_CTRL_HSS_DISABLE |
993 COH901318_CX_CTRL_DDMA_LEGACY,
994 .param.ctrl_lli_last = 0 |
995 COH901318_CX_CTRL_TC_ENABLE |
996 COH901318_CX_CTRL_MASTER_MODE_M1RW |
997 COH901318_CX_CTRL_TCP_DISABLE |
998 COH901318_CX_CTRL_TC_IRQ_ENABLE |
999 COH901318_CX_CTRL_HSP_ENABLE |
1000 COH901318_CX_CTRL_HSS_DISABLE |
1001 COH901318_CX_CTRL_DDMA_LEGACY,
1002
1003 },
1004 {
1005 .number = U300_DMA_GENERAL_PURPOSE_0,
1006 .name = "GENERAL 00",
1007 .priority_high = 0,
1008
1009 .param.config = flags_memcpy_config,
1010 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1011 .param.ctrl_lli = flags_memcpy_lli,
1012 .param.ctrl_lli_last = flags_memcpy_lli_last,
1013 },
1014 {
1015 .number = U300_DMA_GENERAL_PURPOSE_1,
1016 .name = "GENERAL 01",
1017 .priority_high = 0,
1018
1019 .param.config = flags_memcpy_config,
1020 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1021 .param.ctrl_lli = flags_memcpy_lli,
1022 .param.ctrl_lli_last = flags_memcpy_lli_last,
1023 },
1024 {
1025 .number = U300_DMA_GENERAL_PURPOSE_2,
1026 .name = "GENERAL 02",
1027 .priority_high = 0,
1028
1029 .param.config = flags_memcpy_config,
1030 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1031 .param.ctrl_lli = flags_memcpy_lli,
1032 .param.ctrl_lli_last = flags_memcpy_lli_last,
1033 },
1034 {
1035 .number = U300_DMA_GENERAL_PURPOSE_3,
1036 .name = "GENERAL 03",
1037 .priority_high = 0,
1038
1039 .param.config = flags_memcpy_config,
1040 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1041 .param.ctrl_lli = flags_memcpy_lli,
1042 .param.ctrl_lli_last = flags_memcpy_lli_last,
1043 },
1044 {
1045 .number = U300_DMA_GENERAL_PURPOSE_4,
1046 .name = "GENERAL 04",
1047 .priority_high = 0,
1048
1049 .param.config = flags_memcpy_config,
1050 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1051 .param.ctrl_lli = flags_memcpy_lli,
1052 .param.ctrl_lli_last = flags_memcpy_lli_last,
1053 },
1054 {
1055 .number = U300_DMA_GENERAL_PURPOSE_5,
1056 .name = "GENERAL 05",
1057 .priority_high = 0,
1058
1059 .param.config = flags_memcpy_config,
1060 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1061 .param.ctrl_lli = flags_memcpy_lli,
1062 .param.ctrl_lli_last = flags_memcpy_lli_last,
1063 },
1064 {
1065 .number = U300_DMA_GENERAL_PURPOSE_6,
1066 .name = "GENERAL 06",
1067 .priority_high = 0,
1068
1069 .param.config = flags_memcpy_config,
1070 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1071 .param.ctrl_lli = flags_memcpy_lli,
1072 .param.ctrl_lli_last = flags_memcpy_lli_last,
1073 },
1074 {
1075 .number = U300_DMA_GENERAL_PURPOSE_7,
1076 .name = "GENERAL 07",
1077 .priority_high = 0,
1078
1079 .param.config = flags_memcpy_config,
1080 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1081 .param.ctrl_lli = flags_memcpy_lli,
1082 .param.ctrl_lli_last = flags_memcpy_lli_last,
1083 },
1084 {
1085 .number = U300_DMA_GENERAL_PURPOSE_8,
1086 .name = "GENERAL 08",
1087 .priority_high = 0,
1088
1089 .param.config = flags_memcpy_config,
1090 .param.ctrl_lli_chained = flags_memcpy_lli_chained,
1091 .param.ctrl_lli = flags_memcpy_lli,
1092 .param.ctrl_lli_last = flags_memcpy_lli_last,
1093 },
1094 {
1095 .number = U300_DMA_UART1_TX,
1096 .name = "UART1 TX",
1097 .priority_high = 0,
1098 },
1099 {
1100 .number = U300_DMA_UART1_RX,
1101 .name = "UART1 RX",
1102 .priority_high = 0,
1103 }
1104};
1105
1106static struct coh901318_platform coh901318_platform = {
1107 .chans_slave = dma_slave_channels,
1108 .chans_memcpy = dma_memcpy_channels,
1109 .access_memory_state = coh901318_access_memory_state,
1110 .chan_conf = chan_config,
1111 .max_channels = U300_DMA_CHANNELS,
1112};
1113
Linus Walleij61f135b2009-11-19 19:49:17 +01001114#define COHC_2_DEV(cohc) (&cohc->chan.dev->device)
1115
1116#ifdef VERBOSE_DEBUG
1117#define COH_DBG(x) ({ if (1) x; 0; })
1118#else
1119#define COH_DBG(x) ({ if (0) x; 0; })
1120#endif
1121
1122struct coh901318_desc {
1123 struct dma_async_tx_descriptor desc;
1124 struct list_head node;
1125 struct scatterlist *sg;
1126 unsigned int sg_len;
Linus Walleijcecd87d2010-03-04 14:31:47 +01001127 struct coh901318_lli *lli;
Vinod Kouldb8196d2011-10-13 22:34:23 +05301128 enum dma_transfer_direction dir;
Linus Walleij61f135b2009-11-19 19:49:17 +01001129 unsigned long flags;
Linus Walleijb89243d2011-07-01 16:47:28 +02001130 u32 head_config;
1131 u32 head_ctrl;
Linus Walleij61f135b2009-11-19 19:49:17 +01001132};
1133
1134struct coh901318_base {
1135 struct device *dev;
1136 void __iomem *virtbase;
1137 struct coh901318_pool pool;
1138 struct powersave pm;
1139 struct dma_device dma_slave;
1140 struct dma_device dma_memcpy;
1141 struct coh901318_chan *chans;
1142 struct coh901318_platform *platform;
1143};
1144
1145struct coh901318_chan {
1146 spinlock_t lock;
1147 int allocated;
Linus Walleij61f135b2009-11-19 19:49:17 +01001148 int id;
1149 int stopped;
1150
1151 struct work_struct free_work;
1152 struct dma_chan chan;
1153
1154 struct tasklet_struct tasklet;
1155
1156 struct list_head active;
1157 struct list_head queue;
1158 struct list_head free;
1159
1160 unsigned long nbr_active_done;
1161 unsigned long busy;
Linus Walleij61f135b2009-11-19 19:49:17 +01001162
Linus Walleij128f9042010-08-04 13:37:53 +02001163 u32 runtime_addr;
1164 u32 runtime_ctrl;
1165
Linus Walleij61f135b2009-11-19 19:49:17 +01001166 struct coh901318_base *base;
1167};
1168
1169static void coh901318_list_print(struct coh901318_chan *cohc,
1170 struct coh901318_lli *lli)
1171{
Linus Walleij848ad122010-03-02 14:17:15 -07001172 struct coh901318_lli *l = lli;
Linus Walleij61f135b2009-11-19 19:49:17 +01001173 int i = 0;
1174
Linus Walleij848ad122010-03-02 14:17:15 -07001175 while (l) {
Linus Walleij61f135b2009-11-19 19:49:17 +01001176 dev_vdbg(COHC_2_DEV(cohc), "i %d, lli %p, ctrl 0x%x, src 0x%x"
Linus Walleij848ad122010-03-02 14:17:15 -07001177 ", dst 0x%x, link 0x%x virt_link_addr 0x%p\n",
Linus Walleij61f135b2009-11-19 19:49:17 +01001178 i, l, l->control, l->src_addr, l->dst_addr,
Linus Walleij848ad122010-03-02 14:17:15 -07001179 l->link_addr, l->virt_link_addr);
Linus Walleij61f135b2009-11-19 19:49:17 +01001180 i++;
Linus Walleij848ad122010-03-02 14:17:15 -07001181 l = l->virt_link_addr;
Linus Walleij61f135b2009-11-19 19:49:17 +01001182 }
1183}
1184
1185#ifdef CONFIG_DEBUG_FS
1186
1187#define COH901318_DEBUGFS_ASSIGN(x, y) (x = y)
1188
1189static struct coh901318_base *debugfs_dma_base;
1190static struct dentry *dma_dentry;
1191
Linus Walleij61f135b2009-11-19 19:49:17 +01001192static int coh901318_debugfs_read(struct file *file, char __user *buf,
1193 size_t count, loff_t *f_pos)
1194{
1195 u64 started_channels = debugfs_dma_base->pm.started_channels;
1196 int pool_count = debugfs_dma_base->pool.debugfs_pool_counter;
1197 int i;
1198 int ret = 0;
1199 char *dev_buf;
1200 char *tmp;
1201 int dev_size;
1202
1203 dev_buf = kmalloc(4*1024, GFP_KERNEL);
1204 if (dev_buf == NULL)
1205 goto err_kmalloc;
1206 tmp = dev_buf;
1207
Linus Walleij848ad122010-03-02 14:17:15 -07001208 tmp += sprintf(tmp, "DMA -- enabled dma channels\n");
Linus Walleij61f135b2009-11-19 19:49:17 +01001209
1210 for (i = 0; i < debugfs_dma_base->platform->max_channels; i++)
1211 if (started_channels & (1 << i))
1212 tmp += sprintf(tmp, "channel %d\n", i);
1213
1214 tmp += sprintf(tmp, "Pool alloc nbr %d\n", pool_count);
1215 dev_size = tmp - dev_buf;
1216
1217 /* No more to read if offset != 0 */
1218 if (*f_pos > dev_size)
1219 goto out;
1220
1221 if (count > dev_size - *f_pos)
1222 count = dev_size - *f_pos;
1223
1224 if (copy_to_user(buf, dev_buf + *f_pos, count))
1225 ret = -EINVAL;
1226 ret = count;
1227 *f_pos += count;
1228
1229 out:
1230 kfree(dev_buf);
1231 return ret;
1232
1233 err_kmalloc:
1234 return 0;
1235}
1236
1237static const struct file_operations coh901318_debugfs_status_operations = {
1238 .owner = THIS_MODULE,
Stephen Boyd234e3402012-04-05 14:25:11 -07001239 .open = simple_open,
Linus Walleij61f135b2009-11-19 19:49:17 +01001240 .read = coh901318_debugfs_read,
Arnd Bergmann6038f372010-08-15 18:52:59 +02001241 .llseek = default_llseek,
Linus Walleij61f135b2009-11-19 19:49:17 +01001242};
1243
1244
1245static int __init init_coh901318_debugfs(void)
1246{
1247
1248 dma_dentry = debugfs_create_dir("dma", NULL);
1249
1250 (void) debugfs_create_file("status",
1251 S_IFREG | S_IRUGO,
1252 dma_dentry, NULL,
1253 &coh901318_debugfs_status_operations);
1254 return 0;
1255}
1256
1257static void __exit exit_coh901318_debugfs(void)
1258{
1259 debugfs_remove_recursive(dma_dentry);
1260}
1261
1262module_init(init_coh901318_debugfs);
1263module_exit(exit_coh901318_debugfs);
1264#else
1265
1266#define COH901318_DEBUGFS_ASSIGN(x, y)
1267
1268#endif /* CONFIG_DEBUG_FS */
1269
1270static inline struct coh901318_chan *to_coh901318_chan(struct dma_chan *chan)
1271{
1272 return container_of(chan, struct coh901318_chan, chan);
1273}
1274
1275static inline dma_addr_t
1276cohc_dev_addr(struct coh901318_chan *cohc)
1277{
Linus Walleij128f9042010-08-04 13:37:53 +02001278 /* Runtime supplied address will take precedence */
1279 if (cohc->runtime_addr)
1280 return cohc->runtime_addr;
Linus Walleij61f135b2009-11-19 19:49:17 +01001281 return cohc->base->platform->chan_conf[cohc->id].dev_addr;
1282}
1283
1284static inline const struct coh901318_params *
1285cohc_chan_param(struct coh901318_chan *cohc)
1286{
1287 return &cohc->base->platform->chan_conf[cohc->id].param;
1288}
1289
1290static inline const struct coh_dma_channel *
1291cohc_chan_conf(struct coh901318_chan *cohc)
1292{
1293 return &cohc->base->platform->chan_conf[cohc->id];
1294}
1295
1296static void enable_powersave(struct coh901318_chan *cohc)
1297{
1298 unsigned long flags;
1299 struct powersave *pm = &cohc->base->pm;
1300
1301 spin_lock_irqsave(&pm->lock, flags);
1302
1303 pm->started_channels &= ~(1ULL << cohc->id);
1304
1305 if (!pm->started_channels) {
1306 /* DMA no longer intends to access memory */
1307 cohc->base->platform->access_memory_state(cohc->base->dev,
1308 false);
1309 }
1310
1311 spin_unlock_irqrestore(&pm->lock, flags);
1312}
1313static void disable_powersave(struct coh901318_chan *cohc)
1314{
1315 unsigned long flags;
1316 struct powersave *pm = &cohc->base->pm;
1317
1318 spin_lock_irqsave(&pm->lock, flags);
1319
1320 if (!pm->started_channels) {
1321 /* DMA intends to access memory */
1322 cohc->base->platform->access_memory_state(cohc->base->dev,
1323 true);
1324 }
1325
1326 pm->started_channels |= (1ULL << cohc->id);
1327
1328 spin_unlock_irqrestore(&pm->lock, flags);
1329}
1330
1331static inline int coh901318_set_ctrl(struct coh901318_chan *cohc, u32 control)
1332{
1333 int channel = cohc->id;
1334 void __iomem *virtbase = cohc->base->virtbase;
1335
1336 writel(control,
1337 virtbase + COH901318_CX_CTRL +
1338 COH901318_CX_CTRL_SPACING * channel);
1339 return 0;
1340}
1341
1342static inline int coh901318_set_conf(struct coh901318_chan *cohc, u32 conf)
1343{
1344 int channel = cohc->id;
1345 void __iomem *virtbase = cohc->base->virtbase;
1346
1347 writel(conf,
1348 virtbase + COH901318_CX_CFG +
1349 COH901318_CX_CFG_SPACING*channel);
1350 return 0;
1351}
1352
1353
1354static int coh901318_start(struct coh901318_chan *cohc)
1355{
1356 u32 val;
1357 int channel = cohc->id;
1358 void __iomem *virtbase = cohc->base->virtbase;
1359
1360 disable_powersave(cohc);
1361
1362 val = readl(virtbase + COH901318_CX_CFG +
1363 COH901318_CX_CFG_SPACING * channel);
1364
1365 /* Enable channel */
1366 val |= COH901318_CX_CFG_CH_ENABLE;
1367 writel(val, virtbase + COH901318_CX_CFG +
1368 COH901318_CX_CFG_SPACING * channel);
1369
1370 return 0;
1371}
1372
1373static int coh901318_prep_linked_list(struct coh901318_chan *cohc,
Linus Walleijcecd87d2010-03-04 14:31:47 +01001374 struct coh901318_lli *lli)
Linus Walleij61f135b2009-11-19 19:49:17 +01001375{
1376 int channel = cohc->id;
1377 void __iomem *virtbase = cohc->base->virtbase;
1378
1379 BUG_ON(readl(virtbase + COH901318_CX_STAT +
1380 COH901318_CX_STAT_SPACING*channel) &
1381 COH901318_CX_STAT_ACTIVE);
1382
Linus Walleijcecd87d2010-03-04 14:31:47 +01001383 writel(lli->src_addr,
Linus Walleij61f135b2009-11-19 19:49:17 +01001384 virtbase + COH901318_CX_SRC_ADDR +
1385 COH901318_CX_SRC_ADDR_SPACING * channel);
1386
Linus Walleijcecd87d2010-03-04 14:31:47 +01001387 writel(lli->dst_addr, virtbase +
Linus Walleij61f135b2009-11-19 19:49:17 +01001388 COH901318_CX_DST_ADDR +
1389 COH901318_CX_DST_ADDR_SPACING * channel);
1390
Linus Walleijcecd87d2010-03-04 14:31:47 +01001391 writel(lli->link_addr, virtbase + COH901318_CX_LNK_ADDR +
Linus Walleij61f135b2009-11-19 19:49:17 +01001392 COH901318_CX_LNK_ADDR_SPACING * channel);
1393
Linus Walleijcecd87d2010-03-04 14:31:47 +01001394 writel(lli->control, virtbase + COH901318_CX_CTRL +
Linus Walleij61f135b2009-11-19 19:49:17 +01001395 COH901318_CX_CTRL_SPACING * channel);
1396
1397 return 0;
1398}
Linus Walleij61f135b2009-11-19 19:49:17 +01001399
1400static struct coh901318_desc *
1401coh901318_desc_get(struct coh901318_chan *cohc)
1402{
1403 struct coh901318_desc *desc;
1404
1405 if (list_empty(&cohc->free)) {
1406 /* alloc new desc because we're out of used ones
1407 * TODO: alloc a pile of descs instead of just one,
1408 * avoid many small allocations.
1409 */
Linus Walleijb87108a2010-03-02 14:17:20 -07001410 desc = kzalloc(sizeof(struct coh901318_desc), GFP_NOWAIT);
Linus Walleij61f135b2009-11-19 19:49:17 +01001411 if (desc == NULL)
1412 goto out;
1413 INIT_LIST_HEAD(&desc->node);
Linus Walleijb87108a2010-03-02 14:17:20 -07001414 dma_async_tx_descriptor_init(&desc->desc, &cohc->chan);
Linus Walleij61f135b2009-11-19 19:49:17 +01001415 } else {
1416 /* Reuse an old desc. */
1417 desc = list_first_entry(&cohc->free,
1418 struct coh901318_desc,
1419 node);
1420 list_del(&desc->node);
Linus Walleijb87108a2010-03-02 14:17:20 -07001421 /* Initialize it a bit so it's not insane */
1422 desc->sg = NULL;
1423 desc->sg_len = 0;
1424 desc->desc.callback = NULL;
1425 desc->desc.callback_param = NULL;
Linus Walleij61f135b2009-11-19 19:49:17 +01001426 }
1427
1428 out:
1429 return desc;
1430}
1431
1432static void
1433coh901318_desc_free(struct coh901318_chan *cohc, struct coh901318_desc *cohd)
1434{
1435 list_add_tail(&cohd->node, &cohc->free);
1436}
1437
1438/* call with irq lock held */
1439static void
1440coh901318_desc_submit(struct coh901318_chan *cohc, struct coh901318_desc *desc)
1441{
1442 list_add_tail(&desc->node, &cohc->active);
Linus Walleij61f135b2009-11-19 19:49:17 +01001443}
1444
1445static struct coh901318_desc *
1446coh901318_first_active_get(struct coh901318_chan *cohc)
1447{
1448 struct coh901318_desc *d;
1449
1450 if (list_empty(&cohc->active))
1451 return NULL;
1452
1453 d = list_first_entry(&cohc->active,
1454 struct coh901318_desc,
1455 node);
1456 return d;
1457}
1458
1459static void
1460coh901318_desc_remove(struct coh901318_desc *cohd)
1461{
1462 list_del(&cohd->node);
1463}
1464
1465static void
1466coh901318_desc_queue(struct coh901318_chan *cohc, struct coh901318_desc *desc)
1467{
1468 list_add_tail(&desc->node, &cohc->queue);
1469}
1470
1471static struct coh901318_desc *
1472coh901318_first_queued(struct coh901318_chan *cohc)
1473{
1474 struct coh901318_desc *d;
1475
1476 if (list_empty(&cohc->queue))
1477 return NULL;
1478
1479 d = list_first_entry(&cohc->queue,
1480 struct coh901318_desc,
1481 node);
1482 return d;
1483}
1484
Linus Walleij84c84472010-03-04 14:40:30 +01001485static inline u32 coh901318_get_bytes_in_lli(struct coh901318_lli *in_lli)
1486{
1487 struct coh901318_lli *lli = in_lli;
1488 u32 bytes = 0;
1489
1490 while (lli) {
1491 bytes += lli->control & COH901318_CX_CTRL_TC_VALUE_MASK;
1492 lli = lli->virt_link_addr;
1493 }
1494 return bytes;
1495}
1496
Linus Walleij61f135b2009-11-19 19:49:17 +01001497/*
Linus Walleij84c84472010-03-04 14:40:30 +01001498 * Get the number of bytes left to transfer on this channel,
1499 * it is unwise to call this before stopping the channel for
1500 * absolute measures, but for a rough guess you can still call
1501 * it.
Linus Walleij61f135b2009-11-19 19:49:17 +01001502 */
Linus Walleij07934482010-03-26 16:50:49 -07001503static u32 coh901318_get_bytes_left(struct dma_chan *chan)
Linus Walleij61f135b2009-11-19 19:49:17 +01001504{
Linus Walleij61f135b2009-11-19 19:49:17 +01001505 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Linus Walleij84c84472010-03-04 14:40:30 +01001506 struct coh901318_desc *cohd;
1507 struct list_head *pos;
1508 unsigned long flags;
1509 u32 left = 0;
1510 int i = 0;
Linus Walleij61f135b2009-11-19 19:49:17 +01001511
1512 spin_lock_irqsave(&cohc->lock, flags);
1513
Linus Walleij84c84472010-03-04 14:40:30 +01001514 /*
1515 * If there are many queued jobs, we iterate and add the
1516 * size of them all. We take a special look on the first
1517 * job though, since it is probably active.
1518 */
1519 list_for_each(pos, &cohc->active) {
1520 /*
1521 * The first job in the list will be working on the
1522 * hardware. The job can be stopped but still active,
1523 * so that the transfer counter is somewhere inside
1524 * the buffer.
1525 */
1526 cohd = list_entry(pos, struct coh901318_desc, node);
1527
1528 if (i == 0) {
1529 struct coh901318_lli *lli;
1530 dma_addr_t ladd;
1531
1532 /* Read current transfer count value */
1533 left = readl(cohc->base->virtbase +
1534 COH901318_CX_CTRL +
1535 COH901318_CX_CTRL_SPACING * cohc->id) &
1536 COH901318_CX_CTRL_TC_VALUE_MASK;
1537
1538 /* See if the transfer is linked... */
1539 ladd = readl(cohc->base->virtbase +
1540 COH901318_CX_LNK_ADDR +
1541 COH901318_CX_LNK_ADDR_SPACING *
1542 cohc->id) &
1543 ~COH901318_CX_LNK_LINK_IMMEDIATE;
1544 /* Single transaction */
1545 if (!ladd)
1546 continue;
1547
1548 /*
1549 * Linked transaction, follow the lli, find the
1550 * currently processing lli, and proceed to the next
1551 */
1552 lli = cohd->lli;
1553 while (lli && lli->link_addr != ladd)
1554 lli = lli->virt_link_addr;
1555
1556 if (lli)
1557 lli = lli->virt_link_addr;
1558
1559 /*
1560 * Follow remaining lli links around to count the total
1561 * number of bytes left
1562 */
1563 left += coh901318_get_bytes_in_lli(lli);
1564 } else {
1565 left += coh901318_get_bytes_in_lli(cohd->lli);
1566 }
1567 i++;
1568 }
1569
1570 /* Also count bytes in the queued jobs */
1571 list_for_each(pos, &cohc->queue) {
1572 cohd = list_entry(pos, struct coh901318_desc, node);
1573 left += coh901318_get_bytes_in_lli(cohd->lli);
1574 }
Linus Walleij61f135b2009-11-19 19:49:17 +01001575
1576 spin_unlock_irqrestore(&cohc->lock, flags);
1577
Linus Walleij84c84472010-03-04 14:40:30 +01001578 return left;
Linus Walleij61f135b2009-11-19 19:49:17 +01001579}
Linus Walleij61f135b2009-11-19 19:49:17 +01001580
Linus Walleijc3635c72010-03-26 16:44:01 -07001581/*
1582 * Pauses a transfer without losing data. Enables power save.
1583 * Use this function in conjunction with coh901318_resume.
1584 */
1585static void coh901318_pause(struct dma_chan *chan)
Linus Walleij61f135b2009-11-19 19:49:17 +01001586{
1587 u32 val;
1588 unsigned long flags;
1589 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1590 int channel = cohc->id;
1591 void __iomem *virtbase = cohc->base->virtbase;
1592
1593 spin_lock_irqsave(&cohc->lock, flags);
1594
1595 /* Disable channel in HW */
1596 val = readl(virtbase + COH901318_CX_CFG +
1597 COH901318_CX_CFG_SPACING * channel);
1598
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001599 /* Stopping infinite transfer */
Linus Walleij61f135b2009-11-19 19:49:17 +01001600 if ((val & COH901318_CX_CTRL_TC_ENABLE) == 0 &&
1601 (val & COH901318_CX_CFG_CH_ENABLE))
1602 cohc->stopped = 1;
1603
1604
1605 val &= ~COH901318_CX_CFG_CH_ENABLE;
1606 /* Enable twice, HW bug work around */
1607 writel(val, virtbase + COH901318_CX_CFG +
1608 COH901318_CX_CFG_SPACING * channel);
1609 writel(val, virtbase + COH901318_CX_CFG +
1610 COH901318_CX_CFG_SPACING * channel);
1611
1612 /* Spin-wait for it to actually go inactive */
1613 while (readl(virtbase + COH901318_CX_STAT+COH901318_CX_STAT_SPACING *
1614 channel) & COH901318_CX_STAT_ACTIVE)
1615 cpu_relax();
1616
1617 /* Check if we stopped an active job */
1618 if ((readl(virtbase + COH901318_CX_CTRL+COH901318_CX_CTRL_SPACING *
1619 channel) & COH901318_CX_CTRL_TC_VALUE_MASK) > 0)
1620 cohc->stopped = 1;
1621
1622 enable_powersave(cohc);
1623
1624 spin_unlock_irqrestore(&cohc->lock, flags);
1625}
Linus Walleij61f135b2009-11-19 19:49:17 +01001626
Linus Walleijc3635c72010-03-26 16:44:01 -07001627/* Resumes a transfer that has been stopped via 300_dma_stop(..).
Linus Walleij61f135b2009-11-19 19:49:17 +01001628 Power save is handled.
1629*/
Linus Walleijc3635c72010-03-26 16:44:01 -07001630static void coh901318_resume(struct dma_chan *chan)
Linus Walleij61f135b2009-11-19 19:49:17 +01001631{
1632 u32 val;
1633 unsigned long flags;
1634 struct coh901318_chan *cohc = to_coh901318_chan(chan);
1635 int channel = cohc->id;
1636
1637 spin_lock_irqsave(&cohc->lock, flags);
1638
1639 disable_powersave(cohc);
1640
1641 if (cohc->stopped) {
1642 /* Enable channel in HW */
1643 val = readl(cohc->base->virtbase + COH901318_CX_CFG +
1644 COH901318_CX_CFG_SPACING * channel);
1645
1646 val |= COH901318_CX_CFG_CH_ENABLE;
1647
1648 writel(val, cohc->base->virtbase + COH901318_CX_CFG +
1649 COH901318_CX_CFG_SPACING*channel);
1650
1651 cohc->stopped = 0;
1652 }
1653
1654 spin_unlock_irqrestore(&cohc->lock, flags);
1655}
Linus Walleij61f135b2009-11-19 19:49:17 +01001656
1657bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
1658{
1659 unsigned int ch_nr = (unsigned int) chan_id;
1660
1661 if (ch_nr == to_coh901318_chan(chan)->id)
1662 return true;
1663
1664 return false;
1665}
1666EXPORT_SYMBOL(coh901318_filter_id);
1667
1668/*
1669 * DMA channel allocation
1670 */
1671static int coh901318_config(struct coh901318_chan *cohc,
1672 struct coh901318_params *param)
1673{
1674 unsigned long flags;
1675 const struct coh901318_params *p;
1676 int channel = cohc->id;
1677 void __iomem *virtbase = cohc->base->virtbase;
1678
1679 spin_lock_irqsave(&cohc->lock, flags);
1680
1681 if (param)
1682 p = param;
1683 else
1684 p = &cohc->base->platform->chan_conf[channel].param;
1685
1686 /* Clear any pending BE or TC interrupt */
1687 if (channel < 32) {
1688 writel(1 << channel, virtbase + COH901318_BE_INT_CLEAR1);
1689 writel(1 << channel, virtbase + COH901318_TC_INT_CLEAR1);
1690 } else {
1691 writel(1 << (channel - 32), virtbase +
1692 COH901318_BE_INT_CLEAR2);
1693 writel(1 << (channel - 32), virtbase +
1694 COH901318_TC_INT_CLEAR2);
1695 }
1696
1697 coh901318_set_conf(cohc, p->config);
1698 coh901318_set_ctrl(cohc, p->ctrl_lli_last);
1699
1700 spin_unlock_irqrestore(&cohc->lock, flags);
1701
1702 return 0;
1703}
1704
1705/* must lock when calling this function
1706 * start queued jobs, if any
1707 * TODO: start all queued jobs in one go
1708 *
1709 * Returns descriptor if queued job is started otherwise NULL.
1710 * If the queue is empty NULL is returned.
1711 */
1712static struct coh901318_desc *coh901318_queue_start(struct coh901318_chan *cohc)
1713{
Linus Walleijcecd87d2010-03-04 14:31:47 +01001714 struct coh901318_desc *cohd;
Linus Walleij61f135b2009-11-19 19:49:17 +01001715
Linus Walleijcecd87d2010-03-04 14:31:47 +01001716 /*
1717 * start queued jobs, if any
Linus Walleij61f135b2009-11-19 19:49:17 +01001718 * TODO: transmit all queued jobs in one go
1719 */
Linus Walleijcecd87d2010-03-04 14:31:47 +01001720 cohd = coh901318_first_queued(cohc);
Linus Walleij61f135b2009-11-19 19:49:17 +01001721
Linus Walleijcecd87d2010-03-04 14:31:47 +01001722 if (cohd != NULL) {
Linus Walleij61f135b2009-11-19 19:49:17 +01001723 /* Remove from queue */
Linus Walleijcecd87d2010-03-04 14:31:47 +01001724 coh901318_desc_remove(cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01001725 /* initiate DMA job */
1726 cohc->busy = 1;
1727
Linus Walleijcecd87d2010-03-04 14:31:47 +01001728 coh901318_desc_submit(cohc, cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01001729
Linus Walleijb89243d2011-07-01 16:47:28 +02001730 /* Program the transaction head */
1731 coh901318_set_conf(cohc, cohd->head_config);
1732 coh901318_set_ctrl(cohc, cohd->head_ctrl);
Linus Walleijcecd87d2010-03-04 14:31:47 +01001733 coh901318_prep_linked_list(cohc, cohd->lli);
Linus Walleij61f135b2009-11-19 19:49:17 +01001734
Linus Walleijcecd87d2010-03-04 14:31:47 +01001735 /* start dma job on this channel */
Linus Walleij61f135b2009-11-19 19:49:17 +01001736 coh901318_start(cohc);
1737
1738 }
1739
Linus Walleijcecd87d2010-03-04 14:31:47 +01001740 return cohd;
Linus Walleij61f135b2009-11-19 19:49:17 +01001741}
1742
Linus Walleij848ad122010-03-02 14:17:15 -07001743/*
1744 * This tasklet is called from the interrupt handler to
1745 * handle each descriptor (DMA job) that is sent to a channel.
1746 */
Linus Walleij61f135b2009-11-19 19:49:17 +01001747static void dma_tasklet(unsigned long data)
1748{
1749 struct coh901318_chan *cohc = (struct coh901318_chan *) data;
1750 struct coh901318_desc *cohd_fin;
1751 unsigned long flags;
1752 dma_async_tx_callback callback;
1753 void *callback_param;
1754
Linus Walleij848ad122010-03-02 14:17:15 -07001755 dev_vdbg(COHC_2_DEV(cohc), "[%s] chan_id %d"
1756 " nbr_active_done %ld\n", __func__,
1757 cohc->id, cohc->nbr_active_done);
1758
Linus Walleij61f135b2009-11-19 19:49:17 +01001759 spin_lock_irqsave(&cohc->lock, flags);
1760
Linus Walleij848ad122010-03-02 14:17:15 -07001761 /* get first active descriptor entry from list */
Linus Walleij61f135b2009-11-19 19:49:17 +01001762 cohd_fin = coh901318_first_active_get(cohc);
1763
Linus Walleij61f135b2009-11-19 19:49:17 +01001764 if (cohd_fin == NULL)
1765 goto err;
1766
Linus Walleij0b588282010-03-02 14:17:44 -07001767 /* locate callback to client */
Linus Walleij61f135b2009-11-19 19:49:17 +01001768 callback = cohd_fin->desc.callback;
1769 callback_param = cohd_fin->desc.callback_param;
1770
Linus Walleij0b588282010-03-02 14:17:44 -07001771 /* sign this job as completed on the channel */
Russell King - ARM Linuxf7fbce02012-03-06 22:35:07 +00001772 dma_cookie_complete(&cohd_fin->desc);
Linus Walleij61f135b2009-11-19 19:49:17 +01001773
Linus Walleij0b588282010-03-02 14:17:44 -07001774 /* release the lli allocation and remove the descriptor */
Linus Walleijcecd87d2010-03-04 14:31:47 +01001775 coh901318_lli_free(&cohc->base->pool, &cohd_fin->lli);
Linus Walleij0b588282010-03-02 14:17:44 -07001776
1777 /* return desc to free-list */
1778 coh901318_desc_remove(cohd_fin);
1779 coh901318_desc_free(cohc, cohd_fin);
1780
1781 spin_unlock_irqrestore(&cohc->lock, flags);
1782
1783 /* Call the callback when we're done */
1784 if (callback)
1785 callback(callback_param);
1786
1787 spin_lock_irqsave(&cohc->lock, flags);
Linus Walleij61f135b2009-11-19 19:49:17 +01001788
Linus Walleij848ad122010-03-02 14:17:15 -07001789 /*
1790 * If another interrupt fired while the tasklet was scheduling,
1791 * we don't get called twice, so we have this number of active
1792 * counter that keep track of the number of IRQs expected to
1793 * be handled for this channel. If there happen to be more than
1794 * one IRQ to be ack:ed, we simply schedule this tasklet again.
1795 */
Linus Walleij0b588282010-03-02 14:17:44 -07001796 cohc->nbr_active_done--;
Linus Walleij61f135b2009-11-19 19:49:17 +01001797 if (cohc->nbr_active_done) {
Linus Walleij848ad122010-03-02 14:17:15 -07001798 dev_dbg(COHC_2_DEV(cohc), "scheduling tasklet again, new IRQs "
1799 "came in while we were scheduling this tasklet\n");
Linus Walleij61f135b2009-11-19 19:49:17 +01001800 if (cohc_chan_conf(cohc)->priority_high)
1801 tasklet_hi_schedule(&cohc->tasklet);
1802 else
1803 tasklet_schedule(&cohc->tasklet);
1804 }
Linus Walleij61f135b2009-11-19 19:49:17 +01001805
Linus Walleij0b588282010-03-02 14:17:44 -07001806 spin_unlock_irqrestore(&cohc->lock, flags);
Linus Walleij61f135b2009-11-19 19:49:17 +01001807
1808 return;
1809
1810 err:
1811 spin_unlock_irqrestore(&cohc->lock, flags);
1812 dev_err(COHC_2_DEV(cohc), "[%s] No active dma desc\n", __func__);
1813}
1814
1815
1816/* called from interrupt context */
1817static void dma_tc_handle(struct coh901318_chan *cohc)
1818{
Linus Walleijcecd87d2010-03-04 14:31:47 +01001819 /*
1820 * If the channel is not allocated, then we shouldn't have
1821 * any TC interrupts on it.
1822 */
1823 if (!cohc->allocated) {
1824 dev_err(COHC_2_DEV(cohc), "spurious interrupt from "
1825 "unallocated channel\n");
Linus Walleij61f135b2009-11-19 19:49:17 +01001826 return;
Linus Walleijcecd87d2010-03-04 14:31:47 +01001827 }
Linus Walleij61f135b2009-11-19 19:49:17 +01001828
Linus Walleij0b588282010-03-02 14:17:44 -07001829 spin_lock(&cohc->lock);
Linus Walleij61f135b2009-11-19 19:49:17 +01001830
Linus Walleijcecd87d2010-03-04 14:31:47 +01001831 /*
1832 * When we reach this point, at least one queue item
1833 * should have been moved over from cohc->queue to
1834 * cohc->active and run to completion, that is why we're
1835 * getting a terminal count interrupt is it not?
1836 * If you get this BUG() the most probable cause is that
1837 * the individual nodes in the lli chain have IRQ enabled,
1838 * so check your platform config for lli chain ctrl.
1839 */
1840 BUG_ON(list_empty(&cohc->active));
1841
Linus Walleij61f135b2009-11-19 19:49:17 +01001842 cohc->nbr_active_done++;
1843
Linus Walleijcecd87d2010-03-04 14:31:47 +01001844 /*
1845 * This attempt to take a job from cohc->queue, put it
1846 * into cohc->active and start it.
1847 */
Linus Walleij0b588282010-03-02 14:17:44 -07001848 if (coh901318_queue_start(cohc) == NULL)
Linus Walleij61f135b2009-11-19 19:49:17 +01001849 cohc->busy = 0;
1850
Linus Walleij0b588282010-03-02 14:17:44 -07001851 spin_unlock(&cohc->lock);
1852
Linus Walleijcecd87d2010-03-04 14:31:47 +01001853 /*
1854 * This tasklet will remove items from cohc->active
1855 * and thus terminates them.
1856 */
Linus Walleij61f135b2009-11-19 19:49:17 +01001857 if (cohc_chan_conf(cohc)->priority_high)
1858 tasklet_hi_schedule(&cohc->tasklet);
1859 else
1860 tasklet_schedule(&cohc->tasklet);
1861}
1862
1863
1864static irqreturn_t dma_irq_handler(int irq, void *dev_id)
1865{
1866 u32 status1;
1867 u32 status2;
1868 int i;
1869 int ch;
1870 struct coh901318_base *base = dev_id;
1871 struct coh901318_chan *cohc;
1872 void __iomem *virtbase = base->virtbase;
1873
1874 status1 = readl(virtbase + COH901318_INT_STATUS1);
1875 status2 = readl(virtbase + COH901318_INT_STATUS2);
1876
1877 if (unlikely(status1 == 0 && status2 == 0)) {
1878 dev_warn(base->dev, "spurious DMA IRQ from no channel!\n");
1879 return IRQ_HANDLED;
1880 }
1881
1882 /* TODO: consider handle IRQ in tasklet here to
1883 * minimize interrupt latency */
1884
1885 /* Check the first 32 DMA channels for IRQ */
1886 while (status1) {
1887 /* Find first bit set, return as a number. */
1888 i = ffs(status1) - 1;
1889 ch = i;
1890
1891 cohc = &base->chans[ch];
1892 spin_lock(&cohc->lock);
1893
1894 /* Mask off this bit */
1895 status1 &= ~(1 << i);
1896 /* Check the individual channel bits */
1897 if (test_bit(i, virtbase + COH901318_BE_INT_STATUS1)) {
1898 dev_crit(COHC_2_DEV(cohc),
1899 "DMA bus error on channel %d!\n", ch);
1900 BUG_ON(1);
1901 /* Clear BE interrupt */
1902 __set_bit(i, virtbase + COH901318_BE_INT_CLEAR1);
1903 } else {
1904 /* Caused by TC, really? */
1905 if (unlikely(!test_bit(i, virtbase +
1906 COH901318_TC_INT_STATUS1))) {
1907 dev_warn(COHC_2_DEV(cohc),
1908 "ignoring interrupt not caused by terminal count on channel %d\n", ch);
1909 /* Clear TC interrupt */
1910 BUG_ON(1);
1911 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
1912 } else {
1913 /* Enable powersave if transfer has finished */
1914 if (!(readl(virtbase + COH901318_CX_STAT +
1915 COH901318_CX_STAT_SPACING*ch) &
1916 COH901318_CX_STAT_ENABLED)) {
1917 enable_powersave(cohc);
1918 }
1919
1920 /* Must clear TC interrupt before calling
1921 * dma_tc_handle
Justin P. Mattockbc0b44c2011-01-28 11:48:18 -08001922 * in case tc_handle initiate a new dma job
Linus Walleij61f135b2009-11-19 19:49:17 +01001923 */
1924 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
1925
1926 dma_tc_handle(cohc);
1927 }
1928 }
1929 spin_unlock(&cohc->lock);
1930 }
1931
1932 /* Check the remaining 32 DMA channels for IRQ */
1933 while (status2) {
1934 /* Find first bit set, return as a number. */
1935 i = ffs(status2) - 1;
1936 ch = i + 32;
1937 cohc = &base->chans[ch];
1938 spin_lock(&cohc->lock);
1939
1940 /* Mask off this bit */
1941 status2 &= ~(1 << i);
1942 /* Check the individual channel bits */
1943 if (test_bit(i, virtbase + COH901318_BE_INT_STATUS2)) {
1944 dev_crit(COHC_2_DEV(cohc),
1945 "DMA bus error on channel %d!\n", ch);
1946 /* Clear BE interrupt */
1947 BUG_ON(1);
1948 __set_bit(i, virtbase + COH901318_BE_INT_CLEAR2);
1949 } else {
1950 /* Caused by TC, really? */
1951 if (unlikely(!test_bit(i, virtbase +
1952 COH901318_TC_INT_STATUS2))) {
1953 dev_warn(COHC_2_DEV(cohc),
1954 "ignoring interrupt not caused by terminal count on channel %d\n", ch);
1955 /* Clear TC interrupt */
1956 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
1957 BUG_ON(1);
1958 } else {
1959 /* Enable powersave if transfer has finished */
1960 if (!(readl(virtbase + COH901318_CX_STAT +
1961 COH901318_CX_STAT_SPACING*ch) &
1962 COH901318_CX_STAT_ENABLED)) {
1963 enable_powersave(cohc);
1964 }
1965 /* Must clear TC interrupt before calling
1966 * dma_tc_handle
Justin P. Mattockbc0b44c2011-01-28 11:48:18 -08001967 * in case tc_handle initiate a new dma job
Linus Walleij61f135b2009-11-19 19:49:17 +01001968 */
1969 __set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
1970
1971 dma_tc_handle(cohc);
1972 }
1973 }
1974 spin_unlock(&cohc->lock);
1975 }
1976
1977 return IRQ_HANDLED;
1978}
1979
1980static int coh901318_alloc_chan_resources(struct dma_chan *chan)
1981{
1982 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Linus Walleij84c84472010-03-04 14:40:30 +01001983 unsigned long flags;
Linus Walleij61f135b2009-11-19 19:49:17 +01001984
1985 dev_vdbg(COHC_2_DEV(cohc), "[%s] DMA channel %d\n",
1986 __func__, cohc->id);
1987
1988 if (chan->client_count > 1)
1989 return -EBUSY;
1990
Linus Walleij84c84472010-03-04 14:40:30 +01001991 spin_lock_irqsave(&cohc->lock, flags);
1992
Linus Walleij61f135b2009-11-19 19:49:17 +01001993 coh901318_config(cohc, NULL);
1994
1995 cohc->allocated = 1;
Russell King - ARM Linuxd3ee98cdc2012-03-06 22:35:47 +00001996 dma_cookie_init(chan);
Linus Walleij61f135b2009-11-19 19:49:17 +01001997
Linus Walleij84c84472010-03-04 14:40:30 +01001998 spin_unlock_irqrestore(&cohc->lock, flags);
1999
Linus Walleij61f135b2009-11-19 19:49:17 +01002000 return 1;
2001}
2002
2003static void
2004coh901318_free_chan_resources(struct dma_chan *chan)
2005{
2006 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2007 int channel = cohc->id;
2008 unsigned long flags;
2009
2010 spin_lock_irqsave(&cohc->lock, flags);
2011
2012 /* Disable HW */
2013 writel(0x00000000U, cohc->base->virtbase + COH901318_CX_CFG +
2014 COH901318_CX_CFG_SPACING*channel);
2015 writel(0x00000000U, cohc->base->virtbase + COH901318_CX_CTRL +
2016 COH901318_CX_CTRL_SPACING*channel);
2017
2018 cohc->allocated = 0;
2019
2020 spin_unlock_irqrestore(&cohc->lock, flags);
2021
Linus Walleij05827632010-05-17 16:30:42 -07002022 chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
Linus Walleij61f135b2009-11-19 19:49:17 +01002023}
2024
2025
2026static dma_cookie_t
2027coh901318_tx_submit(struct dma_async_tx_descriptor *tx)
2028{
2029 struct coh901318_desc *cohd = container_of(tx, struct coh901318_desc,
2030 desc);
2031 struct coh901318_chan *cohc = to_coh901318_chan(tx->chan);
2032 unsigned long flags;
Russell King - ARM Linux884485e2012-03-06 22:34:46 +00002033 dma_cookie_t cookie;
Linus Walleij61f135b2009-11-19 19:49:17 +01002034
2035 spin_lock_irqsave(&cohc->lock, flags);
Russell King - ARM Linux884485e2012-03-06 22:34:46 +00002036 cookie = dma_cookie_assign(tx);
Linus Walleij61f135b2009-11-19 19:49:17 +01002037
2038 coh901318_desc_queue(cohc, cohd);
2039
2040 spin_unlock_irqrestore(&cohc->lock, flags);
2041
Russell King - ARM Linux884485e2012-03-06 22:34:46 +00002042 return cookie;
Linus Walleij61f135b2009-11-19 19:49:17 +01002043}
2044
2045static struct dma_async_tx_descriptor *
2046coh901318_prep_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
2047 size_t size, unsigned long flags)
2048{
Linus Walleijcecd87d2010-03-04 14:31:47 +01002049 struct coh901318_lli *lli;
Linus Walleij61f135b2009-11-19 19:49:17 +01002050 struct coh901318_desc *cohd;
2051 unsigned long flg;
2052 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2053 int lli_len;
2054 u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
Linus Walleijb87108a2010-03-02 14:17:20 -07002055 int ret;
Linus Walleij61f135b2009-11-19 19:49:17 +01002056
2057 spin_lock_irqsave(&cohc->lock, flg);
2058
2059 dev_vdbg(COHC_2_DEV(cohc),
2060 "[%s] channel %d src 0x%x dest 0x%x size %d\n",
2061 __func__, cohc->id, src, dest, size);
2062
2063 if (flags & DMA_PREP_INTERRUPT)
2064 /* Trigger interrupt after last lli */
2065 ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
2066
2067 lli_len = size >> MAX_DMA_PACKET_SIZE_SHIFT;
2068 if ((lli_len << MAX_DMA_PACKET_SIZE_SHIFT) < size)
2069 lli_len++;
2070
Linus Walleijcecd87d2010-03-04 14:31:47 +01002071 lli = coh901318_lli_alloc(&cohc->base->pool, lli_len);
Linus Walleij61f135b2009-11-19 19:49:17 +01002072
Linus Walleijcecd87d2010-03-04 14:31:47 +01002073 if (lli == NULL)
Linus Walleij61f135b2009-11-19 19:49:17 +01002074 goto err;
2075
Linus Walleijb87108a2010-03-02 14:17:20 -07002076 ret = coh901318_lli_fill_memcpy(
Linus Walleijcecd87d2010-03-04 14:31:47 +01002077 &cohc->base->pool, lli, src, size, dest,
Linus Walleijb87108a2010-03-02 14:17:20 -07002078 cohc_chan_param(cohc)->ctrl_lli_chained,
2079 ctrl_last);
2080 if (ret)
2081 goto err;
Linus Walleij61f135b2009-11-19 19:49:17 +01002082
Linus Walleijcecd87d2010-03-04 14:31:47 +01002083 COH_DBG(coh901318_list_print(cohc, lli));
Linus Walleij61f135b2009-11-19 19:49:17 +01002084
Linus Walleijb87108a2010-03-02 14:17:20 -07002085 /* Pick a descriptor to handle this transfer */
2086 cohd = coh901318_desc_get(cohc);
Linus Walleijcecd87d2010-03-04 14:31:47 +01002087 cohd->lli = lli;
Linus Walleijb87108a2010-03-02 14:17:20 -07002088 cohd->flags = flags;
Linus Walleij61f135b2009-11-19 19:49:17 +01002089 cohd->desc.tx_submit = coh901318_tx_submit;
2090
2091 spin_unlock_irqrestore(&cohc->lock, flg);
2092
2093 return &cohd->desc;
2094 err:
2095 spin_unlock_irqrestore(&cohc->lock, flg);
2096 return NULL;
2097}
2098
2099static struct dma_async_tx_descriptor *
2100coh901318_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
Vinod Kouldb8196d2011-10-13 22:34:23 +05302101 unsigned int sg_len, enum dma_transfer_direction direction,
Alexandre Bounine185ecb52012-03-08 15:35:13 -05002102 unsigned long flags, void *context)
Linus Walleij61f135b2009-11-19 19:49:17 +01002103{
2104 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Linus Walleijcecd87d2010-03-04 14:31:47 +01002105 struct coh901318_lli *lli;
Linus Walleij61f135b2009-11-19 19:49:17 +01002106 struct coh901318_desc *cohd;
Linus Walleij516fd432010-03-02 20:12:46 +01002107 const struct coh901318_params *params;
Linus Walleij61f135b2009-11-19 19:49:17 +01002108 struct scatterlist *sg;
2109 int len = 0;
2110 int size;
2111 int i;
2112 u32 ctrl_chained = cohc_chan_param(cohc)->ctrl_lli_chained;
2113 u32 ctrl = cohc_chan_param(cohc)->ctrl_lli;
2114 u32 ctrl_last = cohc_chan_param(cohc)->ctrl_lli_last;
Linus Walleij516fd432010-03-02 20:12:46 +01002115 u32 config;
Linus Walleij61f135b2009-11-19 19:49:17 +01002116 unsigned long flg;
Linus Walleij0b588282010-03-02 14:17:44 -07002117 int ret;
Linus Walleij61f135b2009-11-19 19:49:17 +01002118
2119 if (!sgl)
2120 goto out;
Lars-Peter Clausenfdaf9c42012-04-25 20:50:52 +02002121 if (sg_dma_len(sgl) == 0)
Linus Walleij61f135b2009-11-19 19:49:17 +01002122 goto out;
2123
2124 spin_lock_irqsave(&cohc->lock, flg);
2125
2126 dev_vdbg(COHC_2_DEV(cohc), "[%s] sg_len %d dir %d\n",
2127 __func__, sg_len, direction);
2128
2129 if (flags & DMA_PREP_INTERRUPT)
2130 /* Trigger interrupt after last lli */
2131 ctrl_last |= COH901318_CX_CTRL_TC_IRQ_ENABLE;
2132
Linus Walleij516fd432010-03-02 20:12:46 +01002133 params = cohc_chan_param(cohc);
2134 config = params->config;
Linus Walleij128f9042010-08-04 13:37:53 +02002135 /*
2136 * Add runtime-specific control on top, make
2137 * sure the bits you set per peripheral channel are
2138 * cleared in the default config from the platform.
2139 */
2140 ctrl_chained |= cohc->runtime_ctrl;
2141 ctrl_last |= cohc->runtime_ctrl;
2142 ctrl |= cohc->runtime_ctrl;
Linus Walleij516fd432010-03-02 20:12:46 +01002143
Vinod Kouldb8196d2011-10-13 22:34:23 +05302144 if (direction == DMA_MEM_TO_DEV) {
Linus Walleij61f135b2009-11-19 19:49:17 +01002145 u32 tx_flags = COH901318_CX_CTRL_PRDD_SOURCE |
2146 COH901318_CX_CTRL_SRC_ADDR_INC_ENABLE;
2147
Linus Walleij516fd432010-03-02 20:12:46 +01002148 config |= COH901318_CX_CFG_RM_MEMORY_TO_PRIMARY;
Linus Walleij61f135b2009-11-19 19:49:17 +01002149 ctrl_chained |= tx_flags;
2150 ctrl_last |= tx_flags;
2151 ctrl |= tx_flags;
Vinod Kouldb8196d2011-10-13 22:34:23 +05302152 } else if (direction == DMA_DEV_TO_MEM) {
Linus Walleij61f135b2009-11-19 19:49:17 +01002153 u32 rx_flags = COH901318_CX_CTRL_PRDD_DEST |
2154 COH901318_CX_CTRL_DST_ADDR_INC_ENABLE;
2155
Linus Walleij516fd432010-03-02 20:12:46 +01002156 config |= COH901318_CX_CFG_RM_PRIMARY_TO_MEMORY;
Linus Walleij61f135b2009-11-19 19:49:17 +01002157 ctrl_chained |= rx_flags;
2158 ctrl_last |= rx_flags;
2159 ctrl |= rx_flags;
2160 } else
2161 goto err_direction;
2162
Linus Walleij61f135b2009-11-19 19:49:17 +01002163 /* The dma only supports transmitting packages up to
2164 * MAX_DMA_PACKET_SIZE. Calculate to total number of
2165 * dma elemts required to send the entire sg list
2166 */
2167 for_each_sg(sgl, sg, sg_len, i) {
2168 unsigned int factor;
2169 size = sg_dma_len(sg);
2170
2171 if (size <= MAX_DMA_PACKET_SIZE) {
2172 len++;
2173 continue;
2174 }
2175
2176 factor = size >> MAX_DMA_PACKET_SIZE_SHIFT;
2177 if ((factor << MAX_DMA_PACKET_SIZE_SHIFT) < size)
2178 factor++;
2179
2180 len += factor;
2181 }
2182
Linus Walleij848ad122010-03-02 14:17:15 -07002183 pr_debug("Allocate %d lli:s for this transfer\n", len);
Linus Walleijcecd87d2010-03-04 14:31:47 +01002184 lli = coh901318_lli_alloc(&cohc->base->pool, len);
Linus Walleij61f135b2009-11-19 19:49:17 +01002185
Linus Walleijcecd87d2010-03-04 14:31:47 +01002186 if (lli == NULL)
Linus Walleij61f135b2009-11-19 19:49:17 +01002187 goto err_dma_alloc;
2188
Linus Walleijcecd87d2010-03-04 14:31:47 +01002189 /* initiate allocated lli list */
2190 ret = coh901318_lli_fill_sg(&cohc->base->pool, lli, sgl, sg_len,
Linus Walleij0b588282010-03-02 14:17:44 -07002191 cohc_dev_addr(cohc),
2192 ctrl_chained,
2193 ctrl,
2194 ctrl_last,
2195 direction, COH901318_CX_CTRL_TC_IRQ_ENABLE);
2196 if (ret)
2197 goto err_lli_fill;
Linus Walleij61f135b2009-11-19 19:49:17 +01002198
Linus Walleij128f9042010-08-04 13:37:53 +02002199
Linus Walleijcecd87d2010-03-04 14:31:47 +01002200 COH_DBG(coh901318_list_print(cohc, lli));
Linus Walleij61f135b2009-11-19 19:49:17 +01002201
Linus Walleijb87108a2010-03-02 14:17:20 -07002202 /* Pick a descriptor to handle this transfer */
2203 cohd = coh901318_desc_get(cohc);
Linus Walleijb89243d2011-07-01 16:47:28 +02002204 cohd->head_config = config;
2205 /*
2206 * Set the default head ctrl for the channel to the one from the
2207 * lli, things may have changed due to odd buffer alignment
2208 * etc.
2209 */
2210 cohd->head_ctrl = lli->control;
Linus Walleijb87108a2010-03-02 14:17:20 -07002211 cohd->dir = direction;
2212 cohd->flags = flags;
2213 cohd->desc.tx_submit = coh901318_tx_submit;
Linus Walleijcecd87d2010-03-04 14:31:47 +01002214 cohd->lli = lli;
Linus Walleijb87108a2010-03-02 14:17:20 -07002215
Linus Walleij61f135b2009-11-19 19:49:17 +01002216 spin_unlock_irqrestore(&cohc->lock, flg);
2217
2218 return &cohd->desc;
Linus Walleij0b588282010-03-02 14:17:44 -07002219 err_lli_fill:
Linus Walleij61f135b2009-11-19 19:49:17 +01002220 err_dma_alloc:
2221 err_direction:
Linus Walleij61f135b2009-11-19 19:49:17 +01002222 spin_unlock_irqrestore(&cohc->lock, flg);
2223 out:
2224 return NULL;
2225}
2226
2227static enum dma_status
Linus Walleij07934482010-03-26 16:50:49 -07002228coh901318_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
2229 struct dma_tx_state *txstate)
Linus Walleij61f135b2009-11-19 19:49:17 +01002230{
2231 struct coh901318_chan *cohc = to_coh901318_chan(chan);
Russell King - ARM Linux96a2af42012-03-06 22:35:27 +00002232 enum dma_status ret;
Linus Walleij61f135b2009-11-19 19:49:17 +01002233
Russell King - ARM Linux96a2af42012-03-06 22:35:27 +00002234 ret = dma_cookie_status(chan, cookie, txstate);
2235 /* FIXME: should be conditional on ret != DMA_SUCCESS? */
2236 dma_set_residue(txstate, coh901318_get_bytes_left(chan));
Linus Walleij61f135b2009-11-19 19:49:17 +01002237
Linus Walleij07934482010-03-26 16:50:49 -07002238 if (ret == DMA_IN_PROGRESS && cohc->stopped)
2239 ret = DMA_PAUSED;
Linus Walleij61f135b2009-11-19 19:49:17 +01002240
2241 return ret;
2242}
2243
2244static void
2245coh901318_issue_pending(struct dma_chan *chan)
2246{
2247 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2248 unsigned long flags;
2249
2250 spin_lock_irqsave(&cohc->lock, flags);
2251
Linus Walleijcecd87d2010-03-04 14:31:47 +01002252 /*
2253 * Busy means that pending jobs are already being processed,
2254 * and then there is no point in starting the queue: the
2255 * terminal count interrupt on the channel will take the next
2256 * job on the queue and execute it anyway.
2257 */
Linus Walleij61f135b2009-11-19 19:49:17 +01002258 if (!cohc->busy)
2259 coh901318_queue_start(cohc);
2260
2261 spin_unlock_irqrestore(&cohc->lock, flags);
2262}
2263
Linus Walleij128f9042010-08-04 13:37:53 +02002264/*
2265 * Here we wrap in the runtime dma control interface
2266 */
2267struct burst_table {
2268 int burst_8bit;
2269 int burst_16bit;
2270 int burst_32bit;
2271 u32 reg;
2272};
2273
2274static const struct burst_table burst_sizes[] = {
2275 {
2276 .burst_8bit = 64,
2277 .burst_16bit = 32,
2278 .burst_32bit = 16,
2279 .reg = COH901318_CX_CTRL_BURST_COUNT_64_BYTES,
2280 },
2281 {
2282 .burst_8bit = 48,
2283 .burst_16bit = 24,
2284 .burst_32bit = 12,
2285 .reg = COH901318_CX_CTRL_BURST_COUNT_48_BYTES,
2286 },
2287 {
2288 .burst_8bit = 32,
2289 .burst_16bit = 16,
2290 .burst_32bit = 8,
2291 .reg = COH901318_CX_CTRL_BURST_COUNT_32_BYTES,
2292 },
2293 {
2294 .burst_8bit = 16,
2295 .burst_16bit = 8,
2296 .burst_32bit = 4,
2297 .reg = COH901318_CX_CTRL_BURST_COUNT_16_BYTES,
2298 },
2299 {
2300 .burst_8bit = 8,
2301 .burst_16bit = 4,
2302 .burst_32bit = 2,
2303 .reg = COH901318_CX_CTRL_BURST_COUNT_8_BYTES,
2304 },
2305 {
2306 .burst_8bit = 4,
2307 .burst_16bit = 2,
2308 .burst_32bit = 1,
2309 .reg = COH901318_CX_CTRL_BURST_COUNT_4_BYTES,
2310 },
2311 {
2312 .burst_8bit = 2,
2313 .burst_16bit = 1,
2314 .burst_32bit = 0,
2315 .reg = COH901318_CX_CTRL_BURST_COUNT_2_BYTES,
2316 },
2317 {
2318 .burst_8bit = 1,
2319 .burst_16bit = 0,
2320 .burst_32bit = 0,
2321 .reg = COH901318_CX_CTRL_BURST_COUNT_1_BYTE,
2322 },
2323};
2324
2325static void coh901318_dma_set_runtimeconfig(struct dma_chan *chan,
2326 struct dma_slave_config *config)
2327{
2328 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2329 dma_addr_t addr;
2330 enum dma_slave_buswidth addr_width;
2331 u32 maxburst;
2332 u32 runtime_ctrl = 0;
2333 int i = 0;
2334
2335 /* We only support mem to per or per to mem transfers */
Vinod Kouldb8196d2011-10-13 22:34:23 +05302336 if (config->direction == DMA_DEV_TO_MEM) {
Linus Walleij128f9042010-08-04 13:37:53 +02002337 addr = config->src_addr;
2338 addr_width = config->src_addr_width;
2339 maxburst = config->src_maxburst;
Vinod Kouldb8196d2011-10-13 22:34:23 +05302340 } else if (config->direction == DMA_MEM_TO_DEV) {
Linus Walleij128f9042010-08-04 13:37:53 +02002341 addr = config->dst_addr;
2342 addr_width = config->dst_addr_width;
2343 maxburst = config->dst_maxburst;
2344 } else {
2345 dev_err(COHC_2_DEV(cohc), "illegal channel mode\n");
2346 return;
2347 }
2348
2349 dev_dbg(COHC_2_DEV(cohc), "configure channel for %d byte transfers\n",
2350 addr_width);
2351 switch (addr_width) {
2352 case DMA_SLAVE_BUSWIDTH_1_BYTE:
2353 runtime_ctrl |=
2354 COH901318_CX_CTRL_SRC_BUS_SIZE_8_BITS |
2355 COH901318_CX_CTRL_DST_BUS_SIZE_8_BITS;
2356
2357 while (i < ARRAY_SIZE(burst_sizes)) {
2358 if (burst_sizes[i].burst_8bit <= maxburst)
2359 break;
2360 i++;
2361 }
2362
2363 break;
2364 case DMA_SLAVE_BUSWIDTH_2_BYTES:
2365 runtime_ctrl |=
2366 COH901318_CX_CTRL_SRC_BUS_SIZE_16_BITS |
2367 COH901318_CX_CTRL_DST_BUS_SIZE_16_BITS;
2368
2369 while (i < ARRAY_SIZE(burst_sizes)) {
2370 if (burst_sizes[i].burst_16bit <= maxburst)
2371 break;
2372 i++;
2373 }
2374
2375 break;
2376 case DMA_SLAVE_BUSWIDTH_4_BYTES:
2377 /* Direction doesn't matter here, it's 32/32 bits */
2378 runtime_ctrl |=
2379 COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
2380 COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS;
2381
2382 while (i < ARRAY_SIZE(burst_sizes)) {
2383 if (burst_sizes[i].burst_32bit <= maxburst)
2384 break;
2385 i++;
2386 }
2387
2388 break;
2389 default:
2390 dev_err(COHC_2_DEV(cohc),
2391 "bad runtimeconfig: alien address width\n");
2392 return;
2393 }
2394
2395 runtime_ctrl |= burst_sizes[i].reg;
2396 dev_dbg(COHC_2_DEV(cohc),
2397 "selected burst size %d bytes for address width %d bytes, maxburst %d\n",
2398 burst_sizes[i].burst_8bit, addr_width, maxburst);
2399
2400 cohc->runtime_addr = addr;
2401 cohc->runtime_ctrl = runtime_ctrl;
2402}
2403
Linus Walleijc3635c72010-03-26 16:44:01 -07002404static int
Linus Walleij05827632010-05-17 16:30:42 -07002405coh901318_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
2406 unsigned long arg)
Linus Walleij61f135b2009-11-19 19:49:17 +01002407{
2408 unsigned long flags;
2409 struct coh901318_chan *cohc = to_coh901318_chan(chan);
2410 struct coh901318_desc *cohd;
2411 void __iomem *virtbase = cohc->base->virtbase;
2412
Linus Walleij128f9042010-08-04 13:37:53 +02002413 if (cmd == DMA_SLAVE_CONFIG) {
2414 struct dma_slave_config *config =
2415 (struct dma_slave_config *) arg;
2416
2417 coh901318_dma_set_runtimeconfig(chan, config);
2418 return 0;
2419 }
2420
Linus Walleijc3635c72010-03-26 16:44:01 -07002421 if (cmd == DMA_PAUSE) {
2422 coh901318_pause(chan);
2423 return 0;
2424 }
Linus Walleij61f135b2009-11-19 19:49:17 +01002425
Linus Walleijc3635c72010-03-26 16:44:01 -07002426 if (cmd == DMA_RESUME) {
2427 coh901318_resume(chan);
2428 return 0;
2429 }
2430
2431 if (cmd != DMA_TERMINATE_ALL)
2432 return -ENXIO;
2433
2434 /* The remainder of this function terminates the transfer */
2435 coh901318_pause(chan);
Linus Walleij61f135b2009-11-19 19:49:17 +01002436 spin_lock_irqsave(&cohc->lock, flags);
2437
2438 /* Clear any pending BE or TC interrupt */
2439 if (cohc->id < 32) {
2440 writel(1 << cohc->id, virtbase + COH901318_BE_INT_CLEAR1);
2441 writel(1 << cohc->id, virtbase + COH901318_TC_INT_CLEAR1);
2442 } else {
2443 writel(1 << (cohc->id - 32), virtbase +
2444 COH901318_BE_INT_CLEAR2);
2445 writel(1 << (cohc->id - 32), virtbase +
2446 COH901318_TC_INT_CLEAR2);
2447 }
2448
2449 enable_powersave(cohc);
2450
2451 while ((cohd = coh901318_first_active_get(cohc))) {
2452 /* release the lli allocation*/
Linus Walleijcecd87d2010-03-04 14:31:47 +01002453 coh901318_lli_free(&cohc->base->pool, &cohd->lli);
Linus Walleij61f135b2009-11-19 19:49:17 +01002454
Linus Walleij61f135b2009-11-19 19:49:17 +01002455 /* return desc to free-list */
Linus Walleij848ad122010-03-02 14:17:15 -07002456 coh901318_desc_remove(cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01002457 coh901318_desc_free(cohc, cohd);
2458 }
2459
2460 while ((cohd = coh901318_first_queued(cohc))) {
2461 /* release the lli allocation*/
Linus Walleijcecd87d2010-03-04 14:31:47 +01002462 coh901318_lli_free(&cohc->base->pool, &cohd->lli);
Linus Walleij61f135b2009-11-19 19:49:17 +01002463
Linus Walleij61f135b2009-11-19 19:49:17 +01002464 /* return desc to free-list */
Linus Walleij848ad122010-03-02 14:17:15 -07002465 coh901318_desc_remove(cohd);
Linus Walleij61f135b2009-11-19 19:49:17 +01002466 coh901318_desc_free(cohc, cohd);
2467 }
2468
2469
2470 cohc->nbr_active_done = 0;
2471 cohc->busy = 0;
Linus Walleij61f135b2009-11-19 19:49:17 +01002472
2473 spin_unlock_irqrestore(&cohc->lock, flags);
Linus Walleijc3635c72010-03-26 16:44:01 -07002474
2475 return 0;
Linus Walleij61f135b2009-11-19 19:49:17 +01002476}
Linus Walleij128f9042010-08-04 13:37:53 +02002477
Linus Walleij61f135b2009-11-19 19:49:17 +01002478void coh901318_base_init(struct dma_device *dma, const int *pick_chans,
2479 struct coh901318_base *base)
2480{
2481 int chans_i;
2482 int i = 0;
2483 struct coh901318_chan *cohc;
2484
2485 INIT_LIST_HEAD(&dma->channels);
2486
2487 for (chans_i = 0; pick_chans[chans_i] != -1; chans_i += 2) {
2488 for (i = pick_chans[chans_i]; i <= pick_chans[chans_i+1]; i++) {
2489 cohc = &base->chans[i];
2490
2491 cohc->base = base;
2492 cohc->chan.device = dma;
2493 cohc->id = i;
2494
2495 /* TODO: do we really need this lock if only one
2496 * client is connected to each channel?
2497 */
2498
2499 spin_lock_init(&cohc->lock);
2500
Linus Walleij61f135b2009-11-19 19:49:17 +01002501 cohc->nbr_active_done = 0;
2502 cohc->busy = 0;
2503 INIT_LIST_HEAD(&cohc->free);
2504 INIT_LIST_HEAD(&cohc->active);
2505 INIT_LIST_HEAD(&cohc->queue);
2506
2507 tasklet_init(&cohc->tasklet, dma_tasklet,
2508 (unsigned long) cohc);
2509
2510 list_add_tail(&cohc->chan.device_node,
2511 &dma->channels);
2512 }
2513 }
2514}
2515
2516static int __init coh901318_probe(struct platform_device *pdev)
2517{
2518 int err = 0;
2519 struct coh901318_platform *pdata;
2520 struct coh901318_base *base;
2521 int irq;
2522 struct resource *io;
2523
2524 io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2525 if (!io)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002526 return -ENODEV;
Linus Walleij61f135b2009-11-19 19:49:17 +01002527
2528 /* Map DMA controller registers to virtual memory */
Linus Walleijf7ceb362012-06-12 20:19:24 +02002529 if (devm_request_mem_region(&pdev->dev,
2530 io->start,
2531 resource_size(io),
2532 pdev->dev.driver->name) == NULL)
2533 return -ENOMEM;
Linus Walleij61f135b2009-11-19 19:49:17 +01002534
Linus Walleij24dbcd82013-01-04 13:38:18 +01002535 pdata = &coh901318_platform,
Linus Walleij61f135b2009-11-19 19:49:17 +01002536
Linus Walleijf7ceb362012-06-12 20:19:24 +02002537 base = devm_kzalloc(&pdev->dev,
2538 ALIGN(sizeof(struct coh901318_base), 4) +
2539 pdata->max_channels *
2540 sizeof(struct coh901318_chan),
2541 GFP_KERNEL);
Linus Walleij61f135b2009-11-19 19:49:17 +01002542 if (!base)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002543 return -ENOMEM;
Linus Walleij61f135b2009-11-19 19:49:17 +01002544
2545 base->chans = ((void *)base) + ALIGN(sizeof(struct coh901318_base), 4);
2546
Linus Walleijf7ceb362012-06-12 20:19:24 +02002547 base->virtbase = devm_ioremap(&pdev->dev, io->start, resource_size(io));
2548 if (!base->virtbase)
2549 return -ENOMEM;
Linus Walleij61f135b2009-11-19 19:49:17 +01002550
2551 base->dev = &pdev->dev;
2552 base->platform = pdata;
2553 spin_lock_init(&base->pm.lock);
2554 base->pm.started_channels = 0;
2555
2556 COH901318_DEBUGFS_ASSIGN(debugfs_dma_base, base);
2557
Linus Walleij61f135b2009-11-19 19:49:17 +01002558 irq = platform_get_irq(pdev, 0);
2559 if (irq < 0)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002560 return irq;
Linus Walleij61f135b2009-11-19 19:49:17 +01002561
Linus Walleijf7ceb362012-06-12 20:19:24 +02002562 err = devm_request_irq(&pdev->dev, irq, dma_irq_handler, IRQF_DISABLED,
2563 "coh901318", base);
2564 if (err)
2565 return err;
Linus Walleij61f135b2009-11-19 19:49:17 +01002566
2567 err = coh901318_pool_create(&base->pool, &pdev->dev,
2568 sizeof(struct coh901318_lli),
2569 32);
2570 if (err)
Linus Walleijf7ceb362012-06-12 20:19:24 +02002571 return err;
Linus Walleij61f135b2009-11-19 19:49:17 +01002572
2573 /* init channels for device transfers */
2574 coh901318_base_init(&base->dma_slave, base->platform->chans_slave,
2575 base);
2576
2577 dma_cap_zero(base->dma_slave.cap_mask);
2578 dma_cap_set(DMA_SLAVE, base->dma_slave.cap_mask);
2579
2580 base->dma_slave.device_alloc_chan_resources = coh901318_alloc_chan_resources;
2581 base->dma_slave.device_free_chan_resources = coh901318_free_chan_resources;
2582 base->dma_slave.device_prep_slave_sg = coh901318_prep_slave_sg;
Linus Walleij07934482010-03-26 16:50:49 -07002583 base->dma_slave.device_tx_status = coh901318_tx_status;
Linus Walleij61f135b2009-11-19 19:49:17 +01002584 base->dma_slave.device_issue_pending = coh901318_issue_pending;
Linus Walleijc3635c72010-03-26 16:44:01 -07002585 base->dma_slave.device_control = coh901318_control;
Linus Walleij61f135b2009-11-19 19:49:17 +01002586 base->dma_slave.dev = &pdev->dev;
2587
2588 err = dma_async_device_register(&base->dma_slave);
2589
2590 if (err)
2591 goto err_register_slave;
2592
2593 /* init channels for memcpy */
2594 coh901318_base_init(&base->dma_memcpy, base->platform->chans_memcpy,
2595 base);
2596
2597 dma_cap_zero(base->dma_memcpy.cap_mask);
2598 dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask);
2599
2600 base->dma_memcpy.device_alloc_chan_resources = coh901318_alloc_chan_resources;
2601 base->dma_memcpy.device_free_chan_resources = coh901318_free_chan_resources;
2602 base->dma_memcpy.device_prep_dma_memcpy = coh901318_prep_memcpy;
Linus Walleij07934482010-03-26 16:50:49 -07002603 base->dma_memcpy.device_tx_status = coh901318_tx_status;
Linus Walleij61f135b2009-11-19 19:49:17 +01002604 base->dma_memcpy.device_issue_pending = coh901318_issue_pending;
Linus Walleijc3635c72010-03-26 16:44:01 -07002605 base->dma_memcpy.device_control = coh901318_control;
Linus Walleij61f135b2009-11-19 19:49:17 +01002606 base->dma_memcpy.dev = &pdev->dev;
Linus Walleij516fd432010-03-02 20:12:46 +01002607 /*
2608 * This controller can only access address at even 32bit boundaries,
2609 * i.e. 2^2
2610 */
2611 base->dma_memcpy.copy_align = 2;
Linus Walleij61f135b2009-11-19 19:49:17 +01002612 err = dma_async_device_register(&base->dma_memcpy);
2613
2614 if (err)
2615 goto err_register_memcpy;
2616
Linus Walleijf7ceb362012-06-12 20:19:24 +02002617 platform_set_drvdata(pdev, base);
Linus Walleij848ad122010-03-02 14:17:15 -07002618 dev_info(&pdev->dev, "Initialized COH901318 DMA on virtual base 0x%08x\n",
Linus Walleij61f135b2009-11-19 19:49:17 +01002619 (u32) base->virtbase);
2620
2621 return err;
2622
2623 err_register_memcpy:
2624 dma_async_device_unregister(&base->dma_slave);
2625 err_register_slave:
2626 coh901318_pool_destroy(&base->pool);
Linus Walleij61f135b2009-11-19 19:49:17 +01002627 return err;
2628}
2629
2630static int __exit coh901318_remove(struct platform_device *pdev)
2631{
2632 struct coh901318_base *base = platform_get_drvdata(pdev);
2633
2634 dma_async_device_unregister(&base->dma_memcpy);
2635 dma_async_device_unregister(&base->dma_slave);
2636 coh901318_pool_destroy(&base->pool);
Linus Walleij61f135b2009-11-19 19:49:17 +01002637 return 0;
2638}
2639
2640
2641static struct platform_driver coh901318_driver = {
2642 .remove = __exit_p(coh901318_remove),
2643 .driver = {
2644 .name = "coh901318",
2645 },
2646};
2647
2648int __init coh901318_init(void)
2649{
2650 return platform_driver_probe(&coh901318_driver, coh901318_probe);
2651}
Linus Walleija0eb2212011-05-18 14:18:57 +02002652subsys_initcall(coh901318_init);
Linus Walleij61f135b2009-11-19 19:49:17 +01002653
2654void __exit coh901318_exit(void)
2655{
2656 platform_driver_unregister(&coh901318_driver);
2657}
2658module_exit(coh901318_exit);
2659
2660MODULE_LICENSE("GPL");
2661MODULE_AUTHOR("Per Friden");