diff options
Diffstat (limited to 'arch/mips/au1000/common/dbdma.c')
-rw-r--r-- | arch/mips/au1000/common/dbdma.c | 319 |
1 files changed, 236 insertions, 83 deletions
diff --git a/arch/mips/au1000/common/dbdma.c b/arch/mips/au1000/common/dbdma.c index adfc3172aace..d00e8247d6c2 100644 --- a/arch/mips/au1000/common/dbdma.c +++ b/arch/mips/au1000/common/dbdma.c | |||
@@ -29,6 +29,7 @@ | |||
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | 29 | * 675 Mass Ave, Cambridge, MA 02139, USA. |
30 | * | 30 | * |
31 | */ | 31 | */ |
32 | |||
32 | #include <linux/config.h> | 33 | #include <linux/config.h> |
33 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
34 | #include <linux/errno.h> | 35 | #include <linux/errno.h> |
@@ -38,10 +39,12 @@ | |||
38 | #include <linux/string.h> | 39 | #include <linux/string.h> |
39 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
40 | #include <linux/interrupt.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/module.h> | ||
41 | #include <asm/mach-au1x00/au1000.h> | 43 | #include <asm/mach-au1x00/au1000.h> |
42 | #include <asm/mach-au1x00/au1xxx_dbdma.h> | 44 | #include <asm/mach-au1x00/au1xxx_dbdma.h> |
43 | #include <asm/system.h> | 45 | #include <asm/system.h> |
44 | 46 | ||
47 | |||
45 | #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) | 48 | #if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) |
46 | 49 | ||
47 | /* | 50 | /* |
@@ -61,37 +64,10 @@ static DEFINE_SPINLOCK(au1xxx_dbdma_spin_lock); | |||
61 | */ | 64 | */ |
62 | #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) | 65 | #define ALIGN_ADDR(x, a) ((((u32)(x)) + (a-1)) & ~(a-1)) |
63 | 66 | ||
64 | static volatile dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; | 67 | static dbdma_global_t *dbdma_gptr = (dbdma_global_t *)DDMA_GLOBAL_BASE; |
65 | static int dbdma_initialized; | 68 | static int dbdma_initialized=0; |
66 | static void au1xxx_dbdma_init(void); | 69 | static void au1xxx_dbdma_init(void); |
67 | 70 | ||
68 | typedef struct dbdma_device_table { | ||
69 | u32 dev_id; | ||
70 | u32 dev_flags; | ||
71 | u32 dev_tsize; | ||
72 | u32 dev_devwidth; | ||
73 | u32 dev_physaddr; /* If FIFO */ | ||
74 | u32 dev_intlevel; | ||
75 | u32 dev_intpolarity; | ||
76 | } dbdev_tab_t; | ||
77 | |||
78 | typedef struct dbdma_chan_config { | ||
79 | u32 chan_flags; | ||
80 | u32 chan_index; | ||
81 | dbdev_tab_t *chan_src; | ||
82 | dbdev_tab_t *chan_dest; | ||
83 | au1x_dma_chan_t *chan_ptr; | ||
84 | au1x_ddma_desc_t *chan_desc_base; | ||
85 | au1x_ddma_desc_t *get_ptr, *put_ptr, *cur_ptr; | ||
86 | void *chan_callparam; | ||
87 | void (*chan_callback)(int, void *, struct pt_regs *); | ||
88 | } chan_tab_t; | ||
89 | |||
90 | #define DEV_FLAGS_INUSE (1 << 0) | ||
91 | #define DEV_FLAGS_ANYUSE (1 << 1) | ||
92 | #define DEV_FLAGS_OUT (1 << 2) | ||
93 | #define DEV_FLAGS_IN (1 << 3) | ||
94 | |||
95 | static dbdev_tab_t dbdev_tab[] = { | 71 | static dbdev_tab_t dbdev_tab[] = { |
96 | #ifdef CONFIG_SOC_AU1550 | 72 | #ifdef CONFIG_SOC_AU1550 |
97 | /* UARTS */ | 73 | /* UARTS */ |
@@ -157,25 +133,25 @@ static dbdev_tab_t dbdev_tab[] = { | |||
157 | { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, | 133 | { DSCR_CMD0_MAE_BOTH, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, |
158 | { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, | 134 | { DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, |
159 | 135 | ||
160 | { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, | 136 | { DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 }, |
161 | { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, | 137 | { DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 }, |
162 | { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, | 138 | { DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 4, 8, 0x10680000, 0, 0 }, |
163 | { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, | 139 | { DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 4, 8, 0x10680004, 0, 0 }, |
164 | 140 | ||
165 | { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 0, 0, 0x00000000, 0, 0 }, | 141 | { DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 }, |
166 | { DSCR_CMD0_AES_RX, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, | 142 | { DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 }, |
167 | 143 | ||
168 | { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 0, 0x11a0001c, 0, 0 }, | 144 | { DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 16, 0x11a0001c, 0, 0 }, |
169 | { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 0, 0x11a0001c, 0, 0 }, | 145 | { DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 16, 0x11a0001c, 0, 0 }, |
170 | { DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, | 146 | { DSCR_CMD0_PSC0_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, |
171 | 147 | ||
172 | { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 0, 0x11b0001c, 0, 0 }, | 148 | { DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 16, 0x11b0001c, 0, 0 }, |
173 | { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 0, 0x11b0001c, 0, 0 }, | 149 | { DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 16, 0x11b0001c, 0, 0 }, |
174 | { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, | 150 | { DSCR_CMD0_PSC1_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, |
175 | 151 | ||
176 | { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, | 152 | { DSCR_CMD0_CIM_RXA, DEV_FLAGS_IN, 0, 32, 0x14004020, 0, 0 }, |
177 | { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, | 153 | { DSCR_CMD0_CIM_RXB, DEV_FLAGS_IN, 0, 32, 0x14004040, 0, 0 }, |
178 | { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, | 154 | { DSCR_CMD0_CIM_RXC, DEV_FLAGS_IN, 0, 32, 0x14004060, 0, 0 }, |
179 | { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, | 155 | { DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, |
180 | 156 | ||
181 | { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, | 157 | { DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 }, |
@@ -184,6 +160,24 @@ static dbdev_tab_t dbdev_tab[] = { | |||
184 | 160 | ||
185 | { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, | 161 | { DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, |
186 | { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, | 162 | { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, |
163 | |||
164 | /* Provide 16 user definable device types */ | ||
165 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
166 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
167 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
168 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
169 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
170 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
171 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
172 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
173 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
174 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
175 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
176 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
177 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
178 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
179 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
180 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
187 | }; | 181 | }; |
188 | 182 | ||
189 | #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) | 183 | #define DBDEV_TAB_SIZE (sizeof(dbdev_tab) / sizeof(dbdev_tab_t)) |
@@ -203,6 +197,36 @@ find_dbdev_id (u32 id) | |||
203 | return NULL; | 197 | return NULL; |
204 | } | 198 | } |
205 | 199 | ||
200 | void * au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp) | ||
201 | { | ||
202 | return phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); | ||
203 | } | ||
204 | EXPORT_SYMBOL(au1xxx_ddma_get_nextptr_virt); | ||
205 | |||
206 | u32 | ||
207 | au1xxx_ddma_add_device(dbdev_tab_t *dev) | ||
208 | { | ||
209 | u32 ret = 0; | ||
210 | dbdev_tab_t *p=NULL; | ||
211 | static u16 new_id=0x1000; | ||
212 | |||
213 | p = find_dbdev_id(0); | ||
214 | if ( NULL != p ) | ||
215 | { | ||
216 | memcpy(p, dev, sizeof(dbdev_tab_t)); | ||
217 | p->dev_id = DSCR_DEV2CUSTOM_ID(new_id,dev->dev_id); | ||
218 | ret = p->dev_id; | ||
219 | new_id++; | ||
220 | #if 0 | ||
221 | printk("add_device: id:%x flags:%x padd:%x\n", | ||
222 | p->dev_id, p->dev_flags, p->dev_physaddr ); | ||
223 | #endif | ||
224 | } | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | EXPORT_SYMBOL(au1xxx_ddma_add_device); | ||
229 | |||
206 | /* Allocate a channel and return a non-zero descriptor if successful. | 230 | /* Allocate a channel and return a non-zero descriptor if successful. |
207 | */ | 231 | */ |
208 | u32 | 232 | u32 |
@@ -215,7 +239,7 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
215 | int i; | 239 | int i; |
216 | dbdev_tab_t *stp, *dtp; | 240 | dbdev_tab_t *stp, *dtp; |
217 | chan_tab_t *ctp; | 241 | chan_tab_t *ctp; |
218 | volatile au1x_dma_chan_t *cp; | 242 | au1x_dma_chan_t *cp; |
219 | 243 | ||
220 | /* We do the intialization on the first channel allocation. | 244 | /* We do the intialization on the first channel allocation. |
221 | * We have to wait because of the interrupt handler initialization | 245 | * We have to wait because of the interrupt handler initialization |
@@ -225,9 +249,6 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
225 | au1xxx_dbdma_init(); | 249 | au1xxx_dbdma_init(); |
226 | dbdma_initialized = 1; | 250 | dbdma_initialized = 1; |
227 | 251 | ||
228 | if ((srcid > DSCR_NDEV_IDS) || (destid > DSCR_NDEV_IDS)) | ||
229 | return 0; | ||
230 | |||
231 | if ((stp = find_dbdev_id(srcid)) == NULL) return 0; | 252 | if ((stp = find_dbdev_id(srcid)) == NULL) return 0; |
232 | if ((dtp = find_dbdev_id(destid)) == NULL) return 0; | 253 | if ((dtp = find_dbdev_id(destid)) == NULL) return 0; |
233 | 254 | ||
@@ -271,7 +292,6 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
271 | */ | 292 | */ |
272 | ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL); | 293 | ctp = kmalloc(sizeof(chan_tab_t), GFP_KERNEL); |
273 | chan_tab_ptr[i] = ctp; | 294 | chan_tab_ptr[i] = ctp; |
274 | ctp->chan_index = chan = i; | ||
275 | break; | 295 | break; |
276 | } | 296 | } |
277 | } | 297 | } |
@@ -279,10 +299,11 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
279 | 299 | ||
280 | if (ctp != NULL) { | 300 | if (ctp != NULL) { |
281 | memset(ctp, 0, sizeof(chan_tab_t)); | 301 | memset(ctp, 0, sizeof(chan_tab_t)); |
302 | ctp->chan_index = chan = i; | ||
282 | dcp = DDMA_CHANNEL_BASE; | 303 | dcp = DDMA_CHANNEL_BASE; |
283 | dcp += (0x0100 * chan); | 304 | dcp += (0x0100 * chan); |
284 | ctp->chan_ptr = (au1x_dma_chan_t *)dcp; | 305 | ctp->chan_ptr = (au1x_dma_chan_t *)dcp; |
285 | cp = (volatile au1x_dma_chan_t *)dcp; | 306 | cp = (au1x_dma_chan_t *)dcp; |
286 | ctp->chan_src = stp; | 307 | ctp->chan_src = stp; |
287 | ctp->chan_dest = dtp; | 308 | ctp->chan_dest = dtp; |
288 | ctp->chan_callback = callback; | 309 | ctp->chan_callback = callback; |
@@ -299,6 +320,9 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
299 | i |= DDMA_CFG_DED; | 320 | i |= DDMA_CFG_DED; |
300 | if (dtp->dev_intpolarity) | 321 | if (dtp->dev_intpolarity) |
301 | i |= DDMA_CFG_DP; | 322 | i |= DDMA_CFG_DP; |
323 | if ((stp->dev_flags & DEV_FLAGS_SYNC) || | ||
324 | (dtp->dev_flags & DEV_FLAGS_SYNC)) | ||
325 | i |= DDMA_CFG_SYNC; | ||
302 | cp->ddma_cfg = i; | 326 | cp->ddma_cfg = i; |
303 | au_sync(); | 327 | au_sync(); |
304 | 328 | ||
@@ -309,14 +333,14 @@ au1xxx_dbdma_chan_alloc(u32 srcid, u32 destid, | |||
309 | rv = (u32)(&chan_tab_ptr[chan]); | 333 | rv = (u32)(&chan_tab_ptr[chan]); |
310 | } | 334 | } |
311 | else { | 335 | else { |
312 | /* Release devices. | 336 | /* Release devices */ |
313 | */ | ||
314 | stp->dev_flags &= ~DEV_FLAGS_INUSE; | 337 | stp->dev_flags &= ~DEV_FLAGS_INUSE; |
315 | dtp->dev_flags &= ~DEV_FLAGS_INUSE; | 338 | dtp->dev_flags &= ~DEV_FLAGS_INUSE; |
316 | } | 339 | } |
317 | } | 340 | } |
318 | return rv; | 341 | return rv; |
319 | } | 342 | } |
343 | EXPORT_SYMBOL(au1xxx_dbdma_chan_alloc); | ||
320 | 344 | ||
321 | /* Set the device width if source or destination is a FIFO. | 345 | /* Set the device width if source or destination is a FIFO. |
322 | * Should be 8, 16, or 32 bits. | 346 | * Should be 8, 16, or 32 bits. |
@@ -344,6 +368,7 @@ au1xxx_dbdma_set_devwidth(u32 chanid, int bits) | |||
344 | 368 | ||
345 | return rv; | 369 | return rv; |
346 | } | 370 | } |
371 | EXPORT_SYMBOL(au1xxx_dbdma_set_devwidth); | ||
347 | 372 | ||
348 | /* Allocate a descriptor ring, initializing as much as possible. | 373 | /* Allocate a descriptor ring, initializing as much as possible. |
349 | */ | 374 | */ |
@@ -370,7 +395,8 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) | |||
370 | * and if we try that first we are likely to not waste larger | 395 | * and if we try that first we are likely to not waste larger |
371 | * slabs of memory. | 396 | * slabs of memory. |
372 | */ | 397 | */ |
373 | desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), GFP_KERNEL); | 398 | desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t), |
399 | GFP_KERNEL|GFP_DMA); | ||
374 | if (desc_base == 0) | 400 | if (desc_base == 0) |
375 | return 0; | 401 | return 0; |
376 | 402 | ||
@@ -381,7 +407,7 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) | |||
381 | kfree((const void *)desc_base); | 407 | kfree((const void *)desc_base); |
382 | i = entries * sizeof(au1x_ddma_desc_t); | 408 | i = entries * sizeof(au1x_ddma_desc_t); |
383 | i += (sizeof(au1x_ddma_desc_t) - 1); | 409 | i += (sizeof(au1x_ddma_desc_t) - 1); |
384 | if ((desc_base = (u32)kmalloc(i, GFP_KERNEL)) == 0) | 410 | if ((desc_base = (u32)kmalloc(i, GFP_KERNEL|GFP_DMA)) == 0) |
385 | return 0; | 411 | return 0; |
386 | 412 | ||
387 | desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); | 413 | desc_base = ALIGN_ADDR(desc_base, sizeof(au1x_ddma_desc_t)); |
@@ -403,7 +429,13 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) | |||
403 | cmd0 |= DSCR_CMD0_SID(srcid); | 429 | cmd0 |= DSCR_CMD0_SID(srcid); |
404 | cmd0 |= DSCR_CMD0_DID(destid); | 430 | cmd0 |= DSCR_CMD0_DID(destid); |
405 | cmd0 |= DSCR_CMD0_IE | DSCR_CMD0_CV; | 431 | cmd0 |= DSCR_CMD0_IE | DSCR_CMD0_CV; |
406 | cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_CURRENT); | 432 | cmd0 |= DSCR_CMD0_ST(DSCR_CMD0_ST_NOCHANGE); |
433 | |||
434 | /* is it mem to mem transfer? */ | ||
435 | if(((DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_THROTTLE) || (DSCR_CUSTOM2DEV_ID(srcid) == DSCR_CMD0_ALWAYS)) && | ||
436 | ((DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_THROTTLE) || (DSCR_CUSTOM2DEV_ID(destid) == DSCR_CMD0_ALWAYS))) { | ||
437 | cmd0 |= DSCR_CMD0_MEM; | ||
438 | } | ||
407 | 439 | ||
408 | switch (stp->dev_devwidth) { | 440 | switch (stp->dev_devwidth) { |
409 | case 8: | 441 | case 8: |
@@ -461,9 +493,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) | |||
461 | /* If source input is fifo, set static address. | 493 | /* If source input is fifo, set static address. |
462 | */ | 494 | */ |
463 | if (stp->dev_flags & DEV_FLAGS_IN) { | 495 | if (stp->dev_flags & DEV_FLAGS_IN) { |
464 | src0 = stp->dev_physaddr; | 496 | if ( stp->dev_flags & DEV_FLAGS_BURSTABLE ) |
497 | src1 |= DSCR_SRC1_SAM(DSCR_xAM_BURST); | ||
498 | else | ||
465 | src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); | 499 | src1 |= DSCR_SRC1_SAM(DSCR_xAM_STATIC); |
500 | |||
466 | } | 501 | } |
502 | if (stp->dev_physaddr) | ||
503 | src0 = stp->dev_physaddr; | ||
467 | 504 | ||
468 | /* Set up dest1. For now, assume no stride and increment. | 505 | /* Set up dest1. For now, assume no stride and increment. |
469 | * A channel attribute update can change this later. | 506 | * A channel attribute update can change this later. |
@@ -487,10 +524,18 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) | |||
487 | /* If destination output is fifo, set static address. | 524 | /* If destination output is fifo, set static address. |
488 | */ | 525 | */ |
489 | if (dtp->dev_flags & DEV_FLAGS_OUT) { | 526 | if (dtp->dev_flags & DEV_FLAGS_OUT) { |
490 | dest0 = dtp->dev_physaddr; | 527 | if ( dtp->dev_flags & DEV_FLAGS_BURSTABLE ) |
528 | dest1 |= DSCR_DEST1_DAM(DSCR_xAM_BURST); | ||
529 | else | ||
491 | dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); | 530 | dest1 |= DSCR_DEST1_DAM(DSCR_xAM_STATIC); |
492 | } | 531 | } |
532 | if (dtp->dev_physaddr) | ||
533 | dest0 = dtp->dev_physaddr; | ||
493 | 534 | ||
535 | #if 0 | ||
536 | printk("did:%x sid:%x cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", | ||
537 | dtp->dev_id, stp->dev_id, cmd0, cmd1, src0, src1, dest0, dest1 ); | ||
538 | #endif | ||
494 | for (i=0; i<entries; i++) { | 539 | for (i=0; i<entries; i++) { |
495 | dp->dscr_cmd0 = cmd0; | 540 | dp->dscr_cmd0 = cmd0; |
496 | dp->dscr_cmd1 = cmd1; | 541 | dp->dscr_cmd1 = cmd1; |
@@ -499,6 +544,8 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) | |||
499 | dp->dscr_dest0 = dest0; | 544 | dp->dscr_dest0 = dest0; |
500 | dp->dscr_dest1 = dest1; | 545 | dp->dscr_dest1 = dest1; |
501 | dp->dscr_stat = 0; | 546 | dp->dscr_stat = 0; |
547 | dp->sw_context = 0; | ||
548 | dp->sw_status = 0; | ||
502 | dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); | 549 | dp->dscr_nxtptr = DSCR_NXTPTR(virt_to_phys(dp + 1)); |
503 | dp++; | 550 | dp++; |
504 | } | 551 | } |
@@ -511,13 +558,14 @@ au1xxx_dbdma_ring_alloc(u32 chanid, int entries) | |||
511 | 558 | ||
512 | return (u32)(ctp->chan_desc_base); | 559 | return (u32)(ctp->chan_desc_base); |
513 | } | 560 | } |
561 | EXPORT_SYMBOL(au1xxx_dbdma_ring_alloc); | ||
514 | 562 | ||
515 | /* Put a source buffer into the DMA ring. | 563 | /* Put a source buffer into the DMA ring. |
516 | * This updates the source pointer and byte count. Normally used | 564 | * This updates the source pointer and byte count. Normally used |
517 | * for memory to fifo transfers. | 565 | * for memory to fifo transfers. |
518 | */ | 566 | */ |
519 | u32 | 567 | u32 |
520 | au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes) | 568 | _au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes, u32 flags) |
521 | { | 569 | { |
522 | chan_tab_t *ctp; | 570 | chan_tab_t *ctp; |
523 | au1x_ddma_desc_t *dp; | 571 | au1x_ddma_desc_t *dp; |
@@ -544,8 +592,24 @@ au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes) | |||
544 | */ | 592 | */ |
545 | dp->dscr_source0 = virt_to_phys(buf); | 593 | dp->dscr_source0 = virt_to_phys(buf); |
546 | dp->dscr_cmd1 = nbytes; | 594 | dp->dscr_cmd1 = nbytes; |
547 | dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ | 595 | /* Check flags */ |
548 | ctp->chan_ptr->ddma_dbell = 0xffffffff; /* Make it go */ | 596 | if (flags & DDMA_FLAGS_IE) |
597 | dp->dscr_cmd0 |= DSCR_CMD0_IE; | ||
598 | if (flags & DDMA_FLAGS_NOIE) | ||
599 | dp->dscr_cmd0 &= ~DSCR_CMD0_IE; | ||
600 | |||
601 | /* | ||
602 | * There is an errata on the Au1200/Au1550 parts that could result | ||
603 | * in "stale" data being DMA'd. It has to do with the snoop logic on | ||
604 | * the dache eviction buffer. NONCOHERENT_IO is on by default for | ||
605 | * these parts. If it is fixedin the future, these dma_cache_inv will | ||
606 | * just be nothing more than empty macros. See io.h. | ||
607 | * */ | ||
608 | dma_cache_wback_inv((unsigned long)buf, nbytes); | ||
609 | dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ | ||
610 | au_sync(); | ||
611 | dma_cache_wback_inv((unsigned long)dp, sizeof(dp)); | ||
612 | ctp->chan_ptr->ddma_dbell = 0; | ||
549 | 613 | ||
550 | /* Get next descriptor pointer. | 614 | /* Get next descriptor pointer. |
551 | */ | 615 | */ |
@@ -555,13 +619,14 @@ au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes) | |||
555 | */ | 619 | */ |
556 | return nbytes; | 620 | return nbytes; |
557 | } | 621 | } |
622 | EXPORT_SYMBOL(_au1xxx_dbdma_put_source); | ||
558 | 623 | ||
559 | /* Put a destination buffer into the DMA ring. | 624 | /* Put a destination buffer into the DMA ring. |
560 | * This updates the destination pointer and byte count. Normally used | 625 | * This updates the destination pointer and byte count. Normally used |
561 | * to place an empty buffer into the ring for fifo to memory transfers. | 626 | * to place an empty buffer into the ring for fifo to memory transfers. |
562 | */ | 627 | */ |
563 | u32 | 628 | u32 |
564 | au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) | 629 | _au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags) |
565 | { | 630 | { |
566 | chan_tab_t *ctp; | 631 | chan_tab_t *ctp; |
567 | au1x_ddma_desc_t *dp; | 632 | au1x_ddma_desc_t *dp; |
@@ -583,11 +648,33 @@ au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) | |||
583 | if (dp->dscr_cmd0 & DSCR_CMD0_V) | 648 | if (dp->dscr_cmd0 & DSCR_CMD0_V) |
584 | return 0; | 649 | return 0; |
585 | 650 | ||
586 | /* Load up buffer address and byte count. | 651 | /* Load up buffer address and byte count */ |
587 | */ | 652 | |
653 | /* Check flags */ | ||
654 | if (flags & DDMA_FLAGS_IE) | ||
655 | dp->dscr_cmd0 |= DSCR_CMD0_IE; | ||
656 | if (flags & DDMA_FLAGS_NOIE) | ||
657 | dp->dscr_cmd0 &= ~DSCR_CMD0_IE; | ||
658 | |||
588 | dp->dscr_dest0 = virt_to_phys(buf); | 659 | dp->dscr_dest0 = virt_to_phys(buf); |
589 | dp->dscr_cmd1 = nbytes; | 660 | dp->dscr_cmd1 = nbytes; |
661 | #if 0 | ||
662 | printk("cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n", | ||
663 | dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0, | ||
664 | dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1 ); | ||
665 | #endif | ||
666 | /* | ||
667 | * There is an errata on the Au1200/Au1550 parts that could result in | ||
668 | * "stale" data being DMA'd. It has to do with the snoop logic on the | ||
669 | * dache eviction buffer. NONCOHERENT_IO is on by default for these | ||
670 | * parts. If it is fixedin the future, these dma_cache_inv will just | ||
671 | * be nothing more than empty macros. See io.h. | ||
672 | * */ | ||
673 | dma_cache_inv((unsigned long)buf,nbytes); | ||
590 | dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ | 674 | dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ |
675 | au_sync(); | ||
676 | dma_cache_wback_inv((unsigned long)dp, sizeof(dp)); | ||
677 | ctp->chan_ptr->ddma_dbell = 0; | ||
591 | 678 | ||
592 | /* Get next descriptor pointer. | 679 | /* Get next descriptor pointer. |
593 | */ | 680 | */ |
@@ -597,6 +684,7 @@ au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes) | |||
597 | */ | 684 | */ |
598 | return nbytes; | 685 | return nbytes; |
599 | } | 686 | } |
687 | EXPORT_SYMBOL(_au1xxx_dbdma_put_dest); | ||
600 | 688 | ||
601 | /* Get a destination buffer into the DMA ring. | 689 | /* Get a destination buffer into the DMA ring. |
602 | * Normally used to get a full buffer from the ring during fifo | 690 | * Normally used to get a full buffer from the ring during fifo |
@@ -646,7 +734,7 @@ void | |||
646 | au1xxx_dbdma_stop(u32 chanid) | 734 | au1xxx_dbdma_stop(u32 chanid) |
647 | { | 735 | { |
648 | chan_tab_t *ctp; | 736 | chan_tab_t *ctp; |
649 | volatile au1x_dma_chan_t *cp; | 737 | au1x_dma_chan_t *cp; |
650 | int halt_timeout = 0; | 738 | int halt_timeout = 0; |
651 | 739 | ||
652 | ctp = *((chan_tab_t **)chanid); | 740 | ctp = *((chan_tab_t **)chanid); |
@@ -666,6 +754,7 @@ au1xxx_dbdma_stop(u32 chanid) | |||
666 | cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); | 754 | cp->ddma_stat |= (DDMA_STAT_DB | DDMA_STAT_V); |
667 | au_sync(); | 755 | au_sync(); |
668 | } | 756 | } |
757 | EXPORT_SYMBOL(au1xxx_dbdma_stop); | ||
669 | 758 | ||
670 | /* Start using the current descriptor pointer. If the dbdma encounters | 759 | /* Start using the current descriptor pointer. If the dbdma encounters |
671 | * a not valid descriptor, it will stop. In this case, we can just | 760 | * a not valid descriptor, it will stop. In this case, we can just |
@@ -675,17 +764,17 @@ void | |||
675 | au1xxx_dbdma_start(u32 chanid) | 764 | au1xxx_dbdma_start(u32 chanid) |
676 | { | 765 | { |
677 | chan_tab_t *ctp; | 766 | chan_tab_t *ctp; |
678 | volatile au1x_dma_chan_t *cp; | 767 | au1x_dma_chan_t *cp; |
679 | 768 | ||
680 | ctp = *((chan_tab_t **)chanid); | 769 | ctp = *((chan_tab_t **)chanid); |
681 | |||
682 | cp = ctp->chan_ptr; | 770 | cp = ctp->chan_ptr; |
683 | cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); | 771 | cp->ddma_desptr = virt_to_phys(ctp->cur_ptr); |
684 | cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ | 772 | cp->ddma_cfg |= DDMA_CFG_EN; /* Enable channel */ |
685 | au_sync(); | 773 | au_sync(); |
686 | cp->ddma_dbell = 0xffffffff; /* Make it go */ | 774 | cp->ddma_dbell = 0; |
687 | au_sync(); | 775 | au_sync(); |
688 | } | 776 | } |
777 | EXPORT_SYMBOL(au1xxx_dbdma_start); | ||
689 | 778 | ||
690 | void | 779 | void |
691 | au1xxx_dbdma_reset(u32 chanid) | 780 | au1xxx_dbdma_reset(u32 chanid) |
@@ -704,15 +793,21 @@ au1xxx_dbdma_reset(u32 chanid) | |||
704 | 793 | ||
705 | do { | 794 | do { |
706 | dp->dscr_cmd0 &= ~DSCR_CMD0_V; | 795 | dp->dscr_cmd0 &= ~DSCR_CMD0_V; |
796 | /* reset our SW status -- this is used to determine | ||
797 | * if a descriptor is in use by upper level SW. Since | ||
798 | * posting can reset 'V' bit. | ||
799 | */ | ||
800 | dp->sw_status = 0; | ||
707 | dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); | 801 | dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); |
708 | } while (dp != ctp->chan_desc_base); | 802 | } while (dp != ctp->chan_desc_base); |
709 | } | 803 | } |
804 | EXPORT_SYMBOL(au1xxx_dbdma_reset); | ||
710 | 805 | ||
711 | u32 | 806 | u32 |
712 | au1xxx_get_dma_residue(u32 chanid) | 807 | au1xxx_get_dma_residue(u32 chanid) |
713 | { | 808 | { |
714 | chan_tab_t *ctp; | 809 | chan_tab_t *ctp; |
715 | volatile au1x_dma_chan_t *cp; | 810 | au1x_dma_chan_t *cp; |
716 | u32 rv; | 811 | u32 rv; |
717 | 812 | ||
718 | ctp = *((chan_tab_t **)chanid); | 813 | ctp = *((chan_tab_t **)chanid); |
@@ -738,8 +833,7 @@ au1xxx_dbdma_chan_free(u32 chanid) | |||
738 | 833 | ||
739 | au1xxx_dbdma_stop(chanid); | 834 | au1xxx_dbdma_stop(chanid); |
740 | 835 | ||
741 | if (ctp->chan_desc_base != NULL) | 836 | kfree((void *)ctp->chan_desc_base); |
742 | kfree(ctp->chan_desc_base); | ||
743 | 837 | ||
744 | stp->dev_flags &= ~DEV_FLAGS_INUSE; | 838 | stp->dev_flags &= ~DEV_FLAGS_INUSE; |
745 | dtp->dev_flags &= ~DEV_FLAGS_INUSE; | 839 | dtp->dev_flags &= ~DEV_FLAGS_INUSE; |
@@ -747,15 +841,16 @@ au1xxx_dbdma_chan_free(u32 chanid) | |||
747 | 841 | ||
748 | kfree(ctp); | 842 | kfree(ctp); |
749 | } | 843 | } |
844 | EXPORT_SYMBOL(au1xxx_dbdma_chan_free); | ||
750 | 845 | ||
751 | static irqreturn_t | 846 | static irqreturn_t |
752 | dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 847 | dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
753 | { | 848 | { |
754 | u32 intstat; | 849 | u32 intstat; |
755 | u32 chan_index; | 850 | u32 chan_index; |
756 | chan_tab_t *ctp; | 851 | chan_tab_t *ctp; |
757 | au1x_ddma_desc_t *dp; | 852 | au1x_ddma_desc_t *dp; |
758 | volatile au1x_dma_chan_t *cp; | 853 | au1x_dma_chan_t *cp; |
759 | 854 | ||
760 | intstat = dbdma_gptr->ddma_intstat; | 855 | intstat = dbdma_gptr->ddma_intstat; |
761 | au_sync(); | 856 | au_sync(); |
@@ -774,19 +869,27 @@ dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
774 | (ctp->chan_callback)(irq, ctp->chan_callparam, regs); | 869 | (ctp->chan_callback)(irq, ctp->chan_callparam, regs); |
775 | 870 | ||
776 | ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); | 871 | ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); |
777 | 872 | return IRQ_RETVAL(1); | |
778 | return IRQ_HANDLED; | ||
779 | } | 873 | } |
780 | 874 | ||
781 | static void | 875 | static void au1xxx_dbdma_init(void) |
782 | au1xxx_dbdma_init(void) | ||
783 | { | 876 | { |
877 | int irq_nr; | ||
878 | |||
784 | dbdma_gptr->ddma_config = 0; | 879 | dbdma_gptr->ddma_config = 0; |
785 | dbdma_gptr->ddma_throttle = 0; | 880 | dbdma_gptr->ddma_throttle = 0; |
786 | dbdma_gptr->ddma_inten = 0xffff; | 881 | dbdma_gptr->ddma_inten = 0xffff; |
787 | au_sync(); | 882 | au_sync(); |
788 | 883 | ||
789 | if (request_irq(AU1550_DDMA_INT, dbdma_interrupt, SA_INTERRUPT, | 884 | #if defined(CONFIG_SOC_AU1550) |
885 | irq_nr = AU1550_DDMA_INT; | ||
886 | #elif defined(CONFIG_SOC_AU1200) | ||
887 | irq_nr = AU1200_DDMA_INT; | ||
888 | #else | ||
889 | #error Unknown Au1x00 SOC | ||
890 | #endif | ||
891 | |||
892 | if (request_irq(irq_nr, dbdma_interrupt, SA_INTERRUPT, | ||
790 | "Au1xxx dbdma", (void *)dbdma_gptr)) | 893 | "Au1xxx dbdma", (void *)dbdma_gptr)) |
791 | printk("Can't get 1550 dbdma irq"); | 894 | printk("Can't get 1550 dbdma irq"); |
792 | } | 895 | } |
@@ -797,7 +900,8 @@ au1xxx_dbdma_dump(u32 chanid) | |||
797 | chan_tab_t *ctp; | 900 | chan_tab_t *ctp; |
798 | au1x_ddma_desc_t *dp; | 901 | au1x_ddma_desc_t *dp; |
799 | dbdev_tab_t *stp, *dtp; | 902 | dbdev_tab_t *stp, *dtp; |
800 | volatile au1x_dma_chan_t *cp; | 903 | au1x_dma_chan_t *cp; |
904 | u32 i = 0; | ||
801 | 905 | ||
802 | ctp = *((chan_tab_t **)chanid); | 906 | ctp = *((chan_tab_t **)chanid); |
803 | stp = ctp->chan_src; | 907 | stp = ctp->chan_src; |
@@ -822,15 +926,64 @@ au1xxx_dbdma_dump(u32 chanid) | |||
822 | dp = ctp->chan_desc_base; | 926 | dp = ctp->chan_desc_base; |
823 | 927 | ||
824 | do { | 928 | do { |
825 | printk("dp %08x, cmd0 %08x, cmd1 %08x\n", | 929 | printk("Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n", |
826 | (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); | 930 | i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1); |
827 | printk("src0 %08x, src1 %08x, dest0 %08x\n", | 931 | printk("src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n", |
828 | dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0); | 932 | dp->dscr_source0, dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); |
829 | printk("dest1 %08x, stat %08x, nxtptr %08x\n", | 933 | printk("stat %08x, nxtptr %08x\n", |
830 | dp->dscr_dest1, dp->dscr_stat, dp->dscr_nxtptr); | 934 | dp->dscr_stat, dp->dscr_nxtptr); |
831 | dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); | 935 | dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); |
832 | } while (dp != ctp->chan_desc_base); | 936 | } while (dp != ctp->chan_desc_base); |
833 | } | 937 | } |
834 | 938 | ||
939 | /* Put a descriptor into the DMA ring. | ||
940 | * This updates the source/destination pointers and byte count. | ||
941 | */ | ||
942 | u32 | ||
943 | au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr ) | ||
944 | { | ||
945 | chan_tab_t *ctp; | ||
946 | au1x_ddma_desc_t *dp; | ||
947 | u32 nbytes=0; | ||
948 | |||
949 | /* I guess we could check this to be within the | ||
950 | * range of the table...... | ||
951 | */ | ||
952 | ctp = *((chan_tab_t **)chanid); | ||
953 | |||
954 | /* We should have multiple callers for a particular channel, | ||
955 | * an interrupt doesn't affect this pointer nor the descriptor, | ||
956 | * so no locking should be needed. | ||
957 | */ | ||
958 | dp = ctp->put_ptr; | ||
959 | |||
960 | /* If the descriptor is valid, we are way ahead of the DMA | ||
961 | * engine, so just return an error condition. | ||
962 | */ | ||
963 | if (dp->dscr_cmd0 & DSCR_CMD0_V) | ||
964 | return 0; | ||
965 | |||
966 | /* Load up buffer addresses and byte count. | ||
967 | */ | ||
968 | dp->dscr_dest0 = dscr->dscr_dest0; | ||
969 | dp->dscr_source0 = dscr->dscr_source0; | ||
970 | dp->dscr_dest1 = dscr->dscr_dest1; | ||
971 | dp->dscr_source1 = dscr->dscr_source1; | ||
972 | dp->dscr_cmd1 = dscr->dscr_cmd1; | ||
973 | nbytes = dscr->dscr_cmd1; | ||
974 | /* Allow the caller to specifiy if an interrupt is generated */ | ||
975 | dp->dscr_cmd0 &= ~DSCR_CMD0_IE; | ||
976 | dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V; | ||
977 | ctp->chan_ptr->ddma_dbell = 0; | ||
978 | |||
979 | /* Get next descriptor pointer. | ||
980 | */ | ||
981 | ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); | ||
982 | |||
983 | /* return something not zero. | ||
984 | */ | ||
985 | return nbytes; | ||
986 | } | ||
987 | |||
835 | #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ | 988 | #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */ |
836 | 989 | ||