aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-omap/dma.c844
-rw-r--r--include/asm-arm/arch-omap/dma.h135
2 files changed, 905 insertions, 74 deletions
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index dcbba07cf98a..a46676db8113 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -6,7 +6,7 @@
6 * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> 6 * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com>
7 * Graphics DMA and LCD DMA graphics tranformations 7 * Graphics DMA and LCD DMA graphics tranformations
8 * by Imre Deak <imre.deak@nokia.com> 8 * by Imre Deak <imre.deak@nokia.com>
9 * OMAP2 support Copyright (C) 2004-2005 Texas Instruments, Inc. 9 * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc.
10 * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com> 10 * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com>
11 * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. 11 * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc.
12 * 12 *
@@ -33,12 +33,14 @@
33 33
34#include <asm/arch/tc.h> 34#include <asm/arch/tc.h>
35 35
36#define DEBUG_PRINTS 36#undef DEBUG
37#undef DEBUG_PRINTS 37
38#ifdef DEBUG_PRINTS 38#ifndef CONFIG_ARCH_OMAP1
39#define debug_printk(x) printk x 39enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED,
40#else 40 DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED
41#define debug_printk(x) 41};
42
43enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
42#endif 44#endif
43 45
44#define OMAP_DMA_ACTIVE 0x01 46#define OMAP_DMA_ACTIVE 0x01
@@ -57,9 +59,66 @@ struct omap_dma_lch {
57 const char *dev_name; 59 const char *dev_name;
58 void (* callback)(int lch, u16 ch_status, void *data); 60 void (* callback)(int lch, u16 ch_status, void *data);
59 void *data; 61 void *data;
62
63#ifndef CONFIG_ARCH_OMAP1
64 /* required for Dynamic chaining */
65 int prev_linked_ch;
66 int next_linked_ch;
67 int state;
68 int chain_id;
69
70 int status;
71#endif
60 long flags; 72 long flags;
61}; 73};
62 74
75#ifndef CONFIG_ARCH_OMAP1
76struct dma_link_info {
77 int *linked_dmach_q;
78 int no_of_lchs_linked;
79
80 int q_count;
81 int q_tail;
82 int q_head;
83
84 int chain_state;
85 int chain_mode;
86
87};
88
89static struct dma_link_info dma_linked_lch[OMAP_LOGICAL_DMA_CH_COUNT];
90
91/* Chain handling macros */
92#define OMAP_DMA_CHAIN_QINIT(chain_id) \
93 do { \
94 dma_linked_lch[chain_id].q_head = \
95 dma_linked_lch[chain_id].q_tail = \
96 dma_linked_lch[chain_id].q_count = 0; \
97 } while (0)
98#define OMAP_DMA_CHAIN_QFULL(chain_id) \
99 (dma_linked_lch[chain_id].no_of_lchs_linked == \
100 dma_linked_lch[chain_id].q_count)
101#define OMAP_DMA_CHAIN_QLAST(chain_id) \
102 do { \
103 ((dma_linked_lch[chain_id].no_of_lchs_linked-1) == \
104 dma_linked_lch[chain_id].q_count) \
105 } while (0)
106#define OMAP_DMA_CHAIN_QEMPTY(chain_id) \
107 (0 == dma_linked_lch[chain_id].q_count)
108#define __OMAP_DMA_CHAIN_INCQ(end) \
109 ((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked)
110#define OMAP_DMA_CHAIN_INCQHEAD(chain_id) \
111 do { \
112 __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head); \
113 dma_linked_lch[chain_id].q_count--; \
114 } while (0)
115
116#define OMAP_DMA_CHAIN_INCQTAIL(chain_id) \
117 do { \
118 __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_tail); \
119 dma_linked_lch[chain_id].q_count++; \
120 } while (0)
121#endif
63static int dma_chan_count; 122static int dma_chan_count;
64 123
65static spinlock_t dma_chan_lock; 124static spinlock_t dma_chan_lock;
@@ -73,6 +132,10 @@ static const u8 omap1_dma_irq[OMAP_LOGICAL_DMA_CH_COUNT] = {
73 INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD 132 INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD
74}; 133};
75 134
135static inline void disable_lnk(int lch);
136static void omap_disable_channel_irq(int lch);
137static inline void omap_enable_channel_irq(int lch);
138
76#define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \ 139#define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \
77 __FUNCTION__); 140 __FUNCTION__);
78 141
@@ -148,7 +211,7 @@ void omap_set_dma_priority(int lch, int dst_port, int priority)
148 omap_writel(l, reg); 211 omap_writel(l, reg);
149 } 212 }
150 213
151 if (cpu_is_omap24xx()) { 214 if (cpu_class_is_omap2()) {
152 if (priority) 215 if (priority)
153 OMAP_DMA_CCR_REG(lch) |= (1 << 6); 216 OMAP_DMA_CCR_REG(lch) |= (1 << 6);
154 else 217 else
@@ -173,7 +236,7 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
173 OMAP1_DMA_CCR2_REG(lch) |= 1 << 2; 236 OMAP1_DMA_CCR2_REG(lch) |= 1 << 2;
174 } 237 }
175 238
176 if (cpu_is_omap24xx() && dma_trigger) { 239 if (cpu_class_is_omap2() && dma_trigger) {
177 u32 val = OMAP_DMA_CCR_REG(lch); 240 u32 val = OMAP_DMA_CCR_REG(lch);
178 241
179 val &= ~(3 << 19); 242 val &= ~(3 << 19);
@@ -213,7 +276,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
213 276
214 BUG_ON(omap_dma_in_1510_mode()); 277 BUG_ON(omap_dma_in_1510_mode());
215 278
216 if (cpu_is_omap24xx()) { 279 if (cpu_class_is_omap2()) {
217 REVISIT_24XX(); 280 REVISIT_24XX();
218 return; 281 return;
219 } 282 }
@@ -245,7 +308,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
245 308
246void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) 309void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
247{ 310{
248 if (cpu_is_omap24xx()) { 311 if (cpu_class_is_omap2()) {
249 OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16); 312 OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16);
250 OMAP_DMA_CSDP_REG(lch) |= (mode << 16); 313 OMAP_DMA_CSDP_REG(lch) |= (mode << 16);
251 } 314 }
@@ -269,7 +332,7 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode,
269 OMAP1_DMA_CSSA_L_REG(lch) = src_start; 332 OMAP1_DMA_CSSA_L_REG(lch) = src_start;
270 } 333 }
271 334
272 if (cpu_is_omap24xx()) 335 if (cpu_class_is_omap2())
273 OMAP2_DMA_CSSA_REG(lch) = src_start; 336 OMAP2_DMA_CSSA_REG(lch) = src_start;
274 337
275 OMAP_DMA_CSEI_REG(lch) = src_ei; 338 OMAP_DMA_CSEI_REG(lch) = src_ei;
@@ -289,11 +352,14 @@ void omap_set_dma_params(int lch, struct omap_dma_channel_params * params)
289 omap_set_dma_dest_params(lch, params->dst_port, 352 omap_set_dma_dest_params(lch, params->dst_port,
290 params->dst_amode, params->dst_start, 353 params->dst_amode, params->dst_start,
291 params->dst_ei, params->dst_fi); 354 params->dst_ei, params->dst_fi);
355 if (params->read_prio || params->write_prio)
356 omap_dma_set_prio_lch(lch, params->read_prio,
357 params->write_prio);
292} 358}
293 359
294void omap_set_dma_src_index(int lch, int eidx, int fidx) 360void omap_set_dma_src_index(int lch, int eidx, int fidx)
295{ 361{
296 if (cpu_is_omap24xx()) { 362 if (cpu_class_is_omap2()) {
297 REVISIT_24XX(); 363 REVISIT_24XX();
298 return; 364 return;
299 } 365 }
@@ -317,13 +383,13 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
317 case OMAP_DMA_DATA_BURST_DIS: 383 case OMAP_DMA_DATA_BURST_DIS:
318 break; 384 break;
319 case OMAP_DMA_DATA_BURST_4: 385 case OMAP_DMA_DATA_BURST_4:
320 if (cpu_is_omap24xx()) 386 if (cpu_class_is_omap2())
321 burst = 0x1; 387 burst = 0x1;
322 else 388 else
323 burst = 0x2; 389 burst = 0x2;
324 break; 390 break;
325 case OMAP_DMA_DATA_BURST_8: 391 case OMAP_DMA_DATA_BURST_8:
326 if (cpu_is_omap24xx()) { 392 if (cpu_class_is_omap2()) {
327 burst = 0x2; 393 burst = 0x2;
328 break; 394 break;
329 } 395 }
@@ -332,7 +398,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
332 * fall through 398 * fall through
333 */ 399 */
334 case OMAP_DMA_DATA_BURST_16: 400 case OMAP_DMA_DATA_BURST_16:
335 if (cpu_is_omap24xx()) { 401 if (cpu_class_is_omap2()) {
336 burst = 0x3; 402 burst = 0x3;
337 break; 403 break;
338 } 404 }
@@ -363,7 +429,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
363 OMAP1_DMA_CDSA_L_REG(lch) = dest_start; 429 OMAP1_DMA_CDSA_L_REG(lch) = dest_start;
364 } 430 }
365 431
366 if (cpu_is_omap24xx()) 432 if (cpu_class_is_omap2())
367 OMAP2_DMA_CDSA_REG(lch) = dest_start; 433 OMAP2_DMA_CDSA_REG(lch) = dest_start;
368 434
369 OMAP_DMA_CDEI_REG(lch) = dst_ei; 435 OMAP_DMA_CDEI_REG(lch) = dst_ei;
@@ -372,7 +438,7 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode,
372 438
373void omap_set_dma_dest_index(int lch, int eidx, int fidx) 439void omap_set_dma_dest_index(int lch, int eidx, int fidx)
374{ 440{
375 if (cpu_is_omap24xx()) { 441 if (cpu_class_is_omap2()) {
376 REVISIT_24XX(); 442 REVISIT_24XX();
377 return; 443 return;
378 } 444 }
@@ -396,19 +462,19 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode)
396 case OMAP_DMA_DATA_BURST_DIS: 462 case OMAP_DMA_DATA_BURST_DIS:
397 break; 463 break;
398 case OMAP_DMA_DATA_BURST_4: 464 case OMAP_DMA_DATA_BURST_4:
399 if (cpu_is_omap24xx()) 465 if (cpu_class_is_omap2())
400 burst = 0x1; 466 burst = 0x1;
401 else 467 else
402 burst = 0x2; 468 burst = 0x2;
403 break; 469 break;
404 case OMAP_DMA_DATA_BURST_8: 470 case OMAP_DMA_DATA_BURST_8:
405 if (cpu_is_omap24xx()) 471 if (cpu_class_is_omap2())
406 burst = 0x2; 472 burst = 0x2;
407 else 473 else
408 burst = 0x3; 474 burst = 0x3;
409 break; 475 break;
410 case OMAP_DMA_DATA_BURST_16: 476 case OMAP_DMA_DATA_BURST_16:
411 if (cpu_is_omap24xx()) { 477 if (cpu_class_is_omap2()) {
412 burst = 0x3; 478 burst = 0x3;
413 break; 479 break;
414 } 480 }
@@ -430,7 +496,7 @@ static inline void omap_enable_channel_irq(int lch)
430 /* Clear CSR */ 496 /* Clear CSR */
431 if (cpu_class_is_omap1()) 497 if (cpu_class_is_omap1())
432 status = OMAP_DMA_CSR_REG(lch); 498 status = OMAP_DMA_CSR_REG(lch);
433 else if (cpu_is_omap24xx()) 499 else if (cpu_class_is_omap2())
434 OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK; 500 OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK;
435 501
436 /* Enable some nice interrupts. */ 502 /* Enable some nice interrupts. */
@@ -441,7 +507,7 @@ static inline void omap_enable_channel_irq(int lch)
441 507
442static void omap_disable_channel_irq(int lch) 508static void omap_disable_channel_irq(int lch)
443{ 509{
444 if (cpu_is_omap24xx()) 510 if (cpu_class_is_omap2())
445 OMAP_DMA_CICR_REG(lch) = 0; 511 OMAP_DMA_CICR_REG(lch) = 0;
446} 512}
447 513
@@ -464,6 +530,12 @@ static inline void enable_lnk(int lch)
464 if (dma_chan[lch].next_lch != -1) 530 if (dma_chan[lch].next_lch != -1)
465 OMAP_DMA_CLNK_CTRL_REG(lch) = 531 OMAP_DMA_CLNK_CTRL_REG(lch) =
466 dma_chan[lch].next_lch | (1 << 15); 532 dma_chan[lch].next_lch | (1 << 15);
533
534#ifndef CONFIG_ARCH_OMAP1
535 if (dma_chan[lch].next_linked_ch != -1)
536 OMAP_DMA_CLNK_CTRL_REG(lch) =
537 dma_chan[lch].next_linked_ch | (1 << 15);
538#endif
467} 539}
468 540
469static inline void disable_lnk(int lch) 541static inline void disable_lnk(int lch)
@@ -475,7 +547,7 @@ static inline void disable_lnk(int lch)
475 OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14; 547 OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14;
476 } 548 }
477 549
478 if (cpu_is_omap24xx()) { 550 if (cpu_class_is_omap2()) {
479 omap_disable_channel_irq(lch); 551 omap_disable_channel_irq(lch);
480 /* Clear the ENABLE_LNK bit */ 552 /* Clear the ENABLE_LNK bit */
481 OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15); 553 OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15);
@@ -488,7 +560,7 @@ static inline void omap2_enable_irq_lch(int lch)
488{ 560{
489 u32 val; 561 u32 val;
490 562
491 if (!cpu_is_omap24xx()) 563 if (!cpu_class_is_omap2())
492 return; 564 return;
493 565
494 val = omap_readl(OMAP_DMA4_IRQENABLE_L0); 566 val = omap_readl(OMAP_DMA4_IRQENABLE_L0);
@@ -522,7 +594,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
522 if (cpu_class_is_omap1()) 594 if (cpu_class_is_omap1())
523 clear_lch_regs(free_ch); 595 clear_lch_regs(free_ch);
524 596
525 if (cpu_is_omap24xx()) 597 if (cpu_class_is_omap2())
526 omap_clear_dma(free_ch); 598 omap_clear_dma(free_ch);
527 599
528 spin_unlock_irqrestore(&dma_chan_lock, flags); 600 spin_unlock_irqrestore(&dma_chan_lock, flags);
@@ -530,11 +602,14 @@ int omap_request_dma(int dev_id, const char *dev_name,
530 chan->dev_name = dev_name; 602 chan->dev_name = dev_name;
531 chan->callback = callback; 603 chan->callback = callback;
532 chan->data = data; 604 chan->data = data;
605#ifndef CONFIG_ARCH_OMAP1
606 chan->chain_id = -1;
607#endif
533 chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; 608 chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ;
534 609
535 if (cpu_class_is_omap1()) 610 if (cpu_class_is_omap1())
536 chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ; 611 chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ;
537 else if (cpu_is_omap24xx()) 612 else if (cpu_class_is_omap2())
538 chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ | 613 chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ |
539 OMAP2_DMA_TRANS_ERR_IRQ; 614 OMAP2_DMA_TRANS_ERR_IRQ;
540 615
@@ -551,7 +626,7 @@ int omap_request_dma(int dev_id, const char *dev_name,
551 OMAP_DMA_CCR_REG(free_ch) = dev_id; 626 OMAP_DMA_CCR_REG(free_ch) = dev_id;
552 } 627 }
553 628
554 if (cpu_is_omap24xx()) { 629 if (cpu_class_is_omap2()) {
555 omap2_enable_irq_lch(free_ch); 630 omap2_enable_irq_lch(free_ch);
556 631
557 omap_enable_channel_irq(free_ch); 632 omap_enable_channel_irq(free_ch);
@@ -588,7 +663,7 @@ void omap_free_dma(int lch)
588 OMAP_DMA_CCR_REG(lch) = 0; 663 OMAP_DMA_CCR_REG(lch) = 0;
589 } 664 }
590 665
591 if (cpu_is_omap24xx()) { 666 if (cpu_class_is_omap2()) {
592 u32 val; 667 u32 val;
593 /* Disable interrupts */ 668 /* Disable interrupts */
594 val = omap_readl(OMAP_DMA4_IRQENABLE_L0); 669 val = omap_readl(OMAP_DMA4_IRQENABLE_L0);
@@ -608,6 +683,67 @@ void omap_free_dma(int lch)
608 } 683 }
609} 684}
610 685
686/**
687 * @brief omap_dma_set_global_params : Set global priority settings for dma
688 *
689 * @param arb_rate
690 * @param max_fifo_depth
691 * @param tparams - Number of thereads to reserve : DMA_THREAD_RESERVE_NORM
692 * DMA_THREAD_RESERVE_ONET
693 * DMA_THREAD_RESERVE_TWOT
694 * DMA_THREAD_RESERVE_THREET
695 */
696void
697omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams)
698{
699 u32 reg;
700
701 if (!cpu_class_is_omap2()) {
702 printk(KERN_ERR "FIXME: no %s on 15xx/16xx\n", __FUNCTION__);
703 return;
704 }
705
706 if (arb_rate == 0)
707 arb_rate = 1;
708
709 reg = (arb_rate & 0xff) << 16;
710 reg |= (0xff & max_fifo_depth);
711
712 omap_writel(reg, OMAP_DMA4_GCR_REG);
713}
714EXPORT_SYMBOL(omap_dma_set_global_params);
715
716/**
717 * @brief omap_dma_set_prio_lch : Set channel wise priority settings
718 *
719 * @param lch
720 * @param read_prio - Read priority
721 * @param write_prio - Write priority
722 * Both of the above can be set with one of the following values :
723 * DMA_CH_PRIO_HIGH/DMA_CH_PRIO_LOW
724 */
725int
726omap_dma_set_prio_lch(int lch, unsigned char read_prio,
727 unsigned char write_prio)
728{
729 u32 w;
730
731 if (unlikely((lch < 0 || lch >= OMAP_LOGICAL_DMA_CH_COUNT))) {
732 printk(KERN_ERR "Invalid channel id\n");
733 return -EINVAL;
734 }
735 w = OMAP_DMA_CCR_REG(lch);
736 w &= ~((1 << 6) | (1 << 26));
737 if (cpu_is_omap2430() || cpu_is_omap34xx())
738 w |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26);
739 else
740 w |= ((read_prio & 0x1) << 6);
741
742 OMAP_DMA_CCR_REG(lch) = w;
743 return 0;
744}
745EXPORT_SYMBOL(omap_dma_set_prio_lch);
746
611/* 747/*
612 * Clears any DMA state so the DMA engine is ready to restart with new buffers 748 * Clears any DMA state so the DMA engine is ready to restart with new buffers
613 * through omap_start_dma(). Any buffers in flight are discarded. 749 * through omap_start_dma(). Any buffers in flight are discarded.
@@ -626,9 +762,9 @@ void omap_clear_dma(int lch)
626 status = OMAP_DMA_CSR_REG(lch); 762 status = OMAP_DMA_CSR_REG(lch);
627 } 763 }
628 764
629 if (cpu_is_omap24xx()) { 765 if (cpu_class_is_omap2()) {
630 int i; 766 int i;
631 u32 lch_base = OMAP24XX_DMA_BASE + lch * 0x60 + 0x80; 767 u32 lch_base = OMAP_DMA4_BASE + lch * 0x60 + 0x80;
632 for (i = 0; i < 0x44; i += 4) 768 for (i = 0; i < 0x44; i += 4)
633 omap_writel(0, lch_base + i); 769 omap_writel(0, lch_base + i);
634 } 770 }
@@ -662,7 +798,7 @@ void omap_start_dma(int lch)
662 798
663 cur_lch = next_lch; 799 cur_lch = next_lch;
664 } while (next_lch != -1); 800 } while (next_lch != -1);
665 } else if (cpu_is_omap24xx()) { 801 } else if (cpu_class_is_omap2()) {
666 /* Errata: Need to write lch even if not using chaining */ 802 /* Errata: Need to write lch even if not using chaining */
667 OMAP_DMA_CLNK_CTRL_REG(lch) = lch; 803 OMAP_DMA_CLNK_CTRL_REG(lch) = lch;
668 } 804 }
@@ -753,7 +889,7 @@ dma_addr_t omap_get_dma_src_pos(int lch)
753 offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) | 889 offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) |
754 (OMAP1_DMA_CSSA_U_REG(lch) << 16)); 890 (OMAP1_DMA_CSSA_U_REG(lch) << 16));
755 891
756 if (cpu_is_omap24xx()) 892 if (cpu_class_is_omap2())
757 offset = OMAP_DMA_CSAC_REG(lch); 893 offset = OMAP_DMA_CSAC_REG(lch);
758 894
759 return offset; 895 return offset;
@@ -775,8 +911,8 @@ dma_addr_t omap_get_dma_dst_pos(int lch)
775 offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) | 911 offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) |
776 (OMAP1_DMA_CDSA_U_REG(lch) << 16)); 912 (OMAP1_DMA_CDSA_U_REG(lch) << 16));
777 913
778 if (cpu_is_omap24xx()) 914 if (cpu_class_is_omap2())
779 offset = OMAP2_DMA_CDSA_REG(lch); 915 offset = OMAP_DMA_CDAC_REG(lch);
780 916
781 return offset; 917 return offset;
782} 918}
@@ -859,6 +995,605 @@ void omap_dma_unlink_lch (int lch_head, int lch_queue)
859 dma_chan[lch_head].next_lch = -1; 995 dma_chan[lch_head].next_lch = -1;
860} 996}
861 997
998#ifndef CONFIG_ARCH_OMAP1
999/* Create chain of DMA channesls */
1000static void create_dma_lch_chain(int lch_head, int lch_queue)
1001{
1002 u32 w;
1003
1004 /* Check if this is the first link in chain */
1005 if (dma_chan[lch_head].next_linked_ch == -1) {
1006 dma_chan[lch_head].next_linked_ch = lch_queue;
1007 dma_chan[lch_head].prev_linked_ch = lch_queue;
1008 dma_chan[lch_queue].next_linked_ch = lch_head;
1009 dma_chan[lch_queue].prev_linked_ch = lch_head;
1010 }
1011
1012 /* a link exists, link the new channel in circular chain */
1013 else {
1014 dma_chan[lch_queue].next_linked_ch =
1015 dma_chan[lch_head].next_linked_ch;
1016 dma_chan[lch_queue].prev_linked_ch = lch_head;
1017 dma_chan[lch_head].next_linked_ch = lch_queue;
1018 dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch =
1019 lch_queue;
1020 }
1021
1022 w = OMAP_DMA_CLNK_CTRL_REG(lch_head);
1023 w &= ~(0x0f);
1024 w |= lch_queue;
1025 OMAP_DMA_CLNK_CTRL_REG(lch_head) = w;
1026
1027 w = OMAP_DMA_CLNK_CTRL_REG(lch_queue);
1028 w &= ~(0x0f);
1029 w |= (dma_chan[lch_queue].next_linked_ch);
1030 OMAP_DMA_CLNK_CTRL_REG(lch_queue) = w;
1031}
1032
1033/**
1034 * @brief omap_request_dma_chain : Request a chain of DMA channels
1035 *
1036 * @param dev_id - Device id using the dma channel
1037 * @param dev_name - Device name
1038 * @param callback - Call back function
1039 * @chain_id -
1040 * @no_of_chans - Number of channels requested
1041 * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN
1042 * OMAP_DMA_DYNAMIC_CHAIN
1043 * @params - Channel parameters
1044 *
1045 * @return - Succes : 0
1046 * Failure: -EINVAL/-ENOMEM
1047 */
1048int omap_request_dma_chain(int dev_id, const char *dev_name,
1049 void (*callback) (int chain_id, u16 ch_status,
1050 void *data),
1051 int *chain_id, int no_of_chans, int chain_mode,
1052 struct omap_dma_channel_params params)
1053{
1054 int *channels;
1055 int i, err;
1056
1057 /* Is the chain mode valid ? */
1058 if (chain_mode != OMAP_DMA_STATIC_CHAIN
1059 && chain_mode != OMAP_DMA_DYNAMIC_CHAIN) {
1060 printk(KERN_ERR "Invalid chain mode requested\n");
1061 return -EINVAL;
1062 }
1063
1064 if (unlikely((no_of_chans < 1
1065 || no_of_chans > OMAP_LOGICAL_DMA_CH_COUNT))) {
1066 printk(KERN_ERR "Invalid Number of channels requested\n");
1067 return -EINVAL;
1068 }
1069
1070 /* Allocate a queue to maintain the status of the channels
1071 * in the chain */
1072 channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL);
1073 if (channels == NULL) {
1074 printk(KERN_ERR "omap_dma: No memory for channel queue\n");
1075 return -ENOMEM;
1076 }
1077
1078 /* request and reserve DMA channels for the chain */
1079 for (i = 0; i < no_of_chans; i++) {
1080 err = omap_request_dma(dev_id, dev_name,
1081 callback, 0, &channels[i]);
1082 if (err < 0) {
1083 int j;
1084 for (j = 0; j < i; j++)
1085 omap_free_dma(channels[j]);
1086 kfree(channels);
1087 printk(KERN_ERR "omap_dma: Request failed %d\n", err);
1088 return err;
1089 }
1090 dma_chan[channels[i]].next_linked_ch = -1;
1091 dma_chan[channels[i]].prev_linked_ch = -1;
1092 dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
1093
1094 /*
1095 * Allowing client drivers to set common parameters now,
1096 * so that later only relevant (src_start, dest_start
1097 * and element count) can be set
1098 */
1099 omap_set_dma_params(channels[i], &params);
1100 }
1101
1102 *chain_id = channels[0];
1103 dma_linked_lch[*chain_id].linked_dmach_q = channels;
1104 dma_linked_lch[*chain_id].chain_mode = chain_mode;
1105 dma_linked_lch[*chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
1106 dma_linked_lch[*chain_id].no_of_lchs_linked = no_of_chans;
1107
1108 for (i = 0; i < no_of_chans; i++)
1109 dma_chan[channels[i]].chain_id = *chain_id;
1110
1111 /* Reset the Queue pointers */
1112 OMAP_DMA_CHAIN_QINIT(*chain_id);
1113
1114 /* Set up the chain */
1115 if (no_of_chans == 1)
1116 create_dma_lch_chain(channels[0], channels[0]);
1117 else {
1118 for (i = 0; i < (no_of_chans - 1); i++)
1119 create_dma_lch_chain(channels[i], channels[i + 1]);
1120 }
1121 return 0;
1122}
1123EXPORT_SYMBOL(omap_request_dma_chain);
1124
1125/**
1126 * @brief omap_modify_dma_chain_param : Modify the chain's params - Modify the
1127 * params after setting it. Dont do this while dma is running!!
1128 *
1129 * @param chain_id - Chained logical channel id.
1130 * @param params
1131 *
1132 * @return - Success : 0
1133 * Failure : -EINVAL
1134 */
1135int omap_modify_dma_chain_params(int chain_id,
1136 struct omap_dma_channel_params params)
1137{
1138 int *channels;
1139 u32 i;
1140
1141 /* Check for input params */
1142 if (unlikely((chain_id < 0
1143 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1144 printk(KERN_ERR "Invalid chain id\n");
1145 return -EINVAL;
1146 }
1147
1148 /* Check if the chain exists */
1149 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1150 printk(KERN_ERR "Chain doesn't exists\n");
1151 return -EINVAL;
1152 }
1153 channels = dma_linked_lch[chain_id].linked_dmach_q;
1154
1155 for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
1156 /*
1157 * Allowing client drivers to set common parameters now,
1158 * so that later only relevant (src_start, dest_start
1159 * and element count) can be set
1160 */
1161 omap_set_dma_params(channels[i], &params);
1162 }
1163 return 0;
1164}
1165EXPORT_SYMBOL(omap_modify_dma_chain_params);
1166
1167/**
1168 * @brief omap_free_dma_chain - Free all the logical channels in a chain.
1169 *
1170 * @param chain_id
1171 *
1172 * @return - Success : 0
1173 * Failure : -EINVAL
1174 */
1175int omap_free_dma_chain(int chain_id)
1176{
1177 int *channels;
1178 u32 i;
1179
1180 /* Check for input params */
1181 if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1182 printk(KERN_ERR "Invalid chain id\n");
1183 return -EINVAL;
1184 }
1185
1186 /* Check if the chain exists */
1187 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1188 printk(KERN_ERR "Chain doesn't exists\n");
1189 return -EINVAL;
1190 }
1191
1192 channels = dma_linked_lch[chain_id].linked_dmach_q;
1193 for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
1194 dma_chan[channels[i]].next_linked_ch = -1;
1195 dma_chan[channels[i]].prev_linked_ch = -1;
1196 dma_chan[channels[i]].chain_id = -1;
1197 dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
1198 omap_free_dma(channels[i]);
1199 }
1200
1201 kfree(channels);
1202
1203 dma_linked_lch[chain_id].linked_dmach_q = NULL;
1204 dma_linked_lch[chain_id].chain_mode = -1;
1205 dma_linked_lch[chain_id].chain_state = -1;
1206 return (0);
1207}
1208EXPORT_SYMBOL(omap_free_dma_chain);
1209
1210/**
1211 * @brief omap_dma_chain_status - Check if the chain is in
1212 * active / inactive state.
1213 * @param chain_id
1214 *
1215 * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE
1216 * Failure : -EINVAL
1217 */
1218int omap_dma_chain_status(int chain_id)
1219{
1220 /* Check for input params */
1221 if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1222 printk(KERN_ERR "Invalid chain id\n");
1223 return -EINVAL;
1224 }
1225
1226 /* Check if the chain exists */
1227 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1228 printk(KERN_ERR "Chain doesn't exists\n");
1229 return -EINVAL;
1230 }
1231 pr_debug("CHAINID=%d, qcnt=%d\n", chain_id,
1232 dma_linked_lch[chain_id].q_count);
1233
1234 if (OMAP_DMA_CHAIN_QEMPTY(chain_id))
1235 return OMAP_DMA_CHAIN_INACTIVE;
1236 return OMAP_DMA_CHAIN_ACTIVE;
1237}
1238EXPORT_SYMBOL(omap_dma_chain_status);
1239
1240/**
1241 * @brief omap_dma_chain_a_transfer - Get a free channel from a chain,
1242 * set the params and start the transfer.
1243 *
1244 * @param chain_id
1245 * @param src_start - buffer start address
1246 * @param dest_start - Dest address
1247 * @param elem_count
1248 * @param frame_count
1249 * @param callbk_data - channel callback parameter data.
1250 *
1251 * @return - Success : start_dma status
1252 * Failure: -EINVAL/-EBUSY
1253 */
1254int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start,
1255 int elem_count, int frame_count, void *callbk_data)
1256{
1257 int *channels;
1258 u32 w, lch;
1259 int start_dma = 0;
1260
1261 /* if buffer size is less than 1 then there is
1262 * no use of starting the chain */
1263 if (elem_count < 1) {
1264 printk(KERN_ERR "Invalid buffer size\n");
1265 return -EINVAL;
1266 }
1267
1268 /* Check for input params */
1269 if (unlikely((chain_id < 0
1270 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1271 printk(KERN_ERR "Invalid chain id\n");
1272 return -EINVAL;
1273 }
1274
1275 /* Check if the chain exists */
1276 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1277 printk(KERN_ERR "Chain doesn't exist\n");
1278 return -EINVAL;
1279 }
1280
1281 /* Check if all the channels in chain are in use */
1282 if (OMAP_DMA_CHAIN_QFULL(chain_id))
1283 return -EBUSY;
1284
1285 /* Frame count may be negative in case of indexed transfers */
1286 channels = dma_linked_lch[chain_id].linked_dmach_q;
1287
1288 /* Get a free channel */
1289 lch = channels[dma_linked_lch[chain_id].q_tail];
1290
1291 /* Store the callback data */
1292 dma_chan[lch].data = callbk_data;
1293
1294 /* Increment the q_tail */
1295 OMAP_DMA_CHAIN_INCQTAIL(chain_id);
1296
1297 /* Set the params to the free channel */
1298 if (src_start != 0)
1299 OMAP2_DMA_CSSA_REG(lch) = src_start;
1300 if (dest_start != 0)
1301 OMAP2_DMA_CDSA_REG(lch) = dest_start;
1302
1303 /* Write the buffer size */
1304 OMAP_DMA_CEN_REG(lch) = elem_count;
1305 OMAP_DMA_CFN_REG(lch) = frame_count;
1306
1307 /* If the chain is dynamically linked,
1308 * then we may have to start the chain if its not active */
1309 if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) {
1310
1311 /* In Dynamic chain, if the chain is not started,
1312 * queue the channel */
1313 if (dma_linked_lch[chain_id].chain_state ==
1314 DMA_CHAIN_NOTSTARTED) {
1315 /* Enable the link in previous channel */
1316 if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
1317 DMA_CH_QUEUED)
1318 enable_lnk(dma_chan[lch].prev_linked_ch);
1319 dma_chan[lch].state = DMA_CH_QUEUED;
1320 }
1321
1322 /* Chain is already started, make sure its active,
1323 * if not then start the chain */
1324 else {
1325 start_dma = 1;
1326
1327 if (dma_chan[dma_chan[lch].prev_linked_ch].state ==
1328 DMA_CH_STARTED) {
1329 enable_lnk(dma_chan[lch].prev_linked_ch);
1330 dma_chan[lch].state = DMA_CH_QUEUED;
1331 start_dma = 0;
1332 if (0 == ((1 << 7) & (OMAP_DMA_CCR_REG
1333 (dma_chan[lch].prev_linked_ch)))) {
1334 disable_lnk(dma_chan[lch].
1335 prev_linked_ch);
1336 pr_debug("\n prev ch is stopped\n");
1337 start_dma = 1;
1338 }
1339 }
1340
1341 else if (dma_chan[dma_chan[lch].prev_linked_ch].state
1342 == DMA_CH_QUEUED) {
1343 enable_lnk(dma_chan[lch].prev_linked_ch);
1344 dma_chan[lch].state = DMA_CH_QUEUED;
1345 start_dma = 0;
1346 }
1347 omap_enable_channel_irq(lch);
1348
1349 w = OMAP_DMA_CCR_REG(lch);
1350
1351 if ((0 == (w & (1 << 24))))
1352 w &= ~(1 << 25);
1353 else
1354 w |= (1 << 25);
1355 if (start_dma == 1) {
1356 if (0 == (w & (1 << 7))) {
1357 w |= (1 << 7);
1358 dma_chan[lch].state = DMA_CH_STARTED;
1359 pr_debug("starting %d\n", lch);
1360 OMAP_DMA_CCR_REG(lch) = w;
1361 } else
1362 start_dma = 0;
1363 } else {
1364 if (0 == (w & (1 << 7)))
1365 OMAP_DMA_CCR_REG(lch) = w;
1366 }
1367 dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
1368 }
1369 }
1370 return start_dma;
1371}
1372EXPORT_SYMBOL(omap_dma_chain_a_transfer);
1373
1374/**
1375 * @brief omap_start_dma_chain_transfers - Start the chain
1376 *
1377 * @param chain_id
1378 *
1379 * @return - Success : 0
1380 * Failure : -EINVAL/-EBUSY
1381 */
1382int omap_start_dma_chain_transfers(int chain_id)
1383{
1384 int *channels;
1385 u32 w, i;
1386
1387 if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1388 printk(KERN_ERR "Invalid chain id\n");
1389 return -EINVAL;
1390 }
1391
1392 channels = dma_linked_lch[chain_id].linked_dmach_q;
1393
1394 if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) {
1395 printk(KERN_ERR "Chain is already started\n");
1396 return -EBUSY;
1397 }
1398
1399 if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) {
1400 for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked;
1401 i++) {
1402 enable_lnk(channels[i]);
1403 omap_enable_channel_irq(channels[i]);
1404 }
1405 } else {
1406 omap_enable_channel_irq(channels[0]);
1407 }
1408
1409 w = OMAP_DMA_CCR_REG(channels[0]);
1410 w |= (1 << 7);
1411 dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED;
1412 dma_chan[channels[0]].state = DMA_CH_STARTED;
1413
1414 if ((0 == (w & (1 << 24))))
1415 w &= ~(1 << 25);
1416 else
1417 w |= (1 << 25);
1418 OMAP_DMA_CCR_REG(channels[0]) = w;
1419
1420 dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE;
1421 return 0;
1422}
1423EXPORT_SYMBOL(omap_start_dma_chain_transfers);
1424
1425/**
1426 * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain.
1427 *
1428 * @param chain_id
1429 *
1430 * @return - Success : 0
1431 * Failure : EINVAL
1432 */
1433int omap_stop_dma_chain_transfers(int chain_id)
1434{
1435 int *channels;
1436 u32 w, i;
1437 u32 sys_cf;
1438
1439 /* Check for input params */
1440 if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1441 printk(KERN_ERR "Invalid chain id\n");
1442 return -EINVAL;
1443 }
1444
1445 /* Check if the chain exists */
1446 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1447 printk(KERN_ERR "Chain doesn't exists\n");
1448 return -EINVAL;
1449 }
1450 channels = dma_linked_lch[chain_id].linked_dmach_q;
1451
1452 /* DMA Errata:
1453 * Special programming model needed to disable DMA before end of block
1454 */
1455 sys_cf = omap_readl(OMAP_DMA4_OCP_SYSCONFIG);
1456 w = sys_cf;
1457 /* Middle mode reg set no Standby */
1458 w &= ~((1 << 12)|(1 << 13));
1459 omap_writel(w, OMAP_DMA4_OCP_SYSCONFIG);
1460
1461 for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
1462
1463 /* Stop the Channel transmission */
1464 w = OMAP_DMA_CCR_REG(channels[i]);
1465 w &= ~(1 << 7);
1466 OMAP_DMA_CCR_REG(channels[i]) = w;
1467
1468 /* Disable the link in all the channels */
1469 disable_lnk(channels[i]);
1470 dma_chan[channels[i]].state = DMA_CH_NOTSTARTED;
1471
1472 }
1473 dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED;
1474
1475 /* Reset the Queue pointers */
1476 OMAP_DMA_CHAIN_QINIT(chain_id);
1477
1478 /* Errata - put in the old value */
1479 omap_writel(sys_cf, OMAP_DMA4_OCP_SYSCONFIG);
1480 return 0;
1481}
1482EXPORT_SYMBOL(omap_stop_dma_chain_transfers);
1483
1484/* Get the index of the ongoing DMA in chain */
1485/**
1486 * @brief omap_get_dma_chain_index - Get the element and frame index
1487 * of the ongoing DMA in chain
1488 *
1489 * @param chain_id
1490 * @param ei - Element index
1491 * @param fi - Frame index
1492 *
1493 * @return - Success : 0
1494 * Failure : -EINVAL
1495 */
1496int omap_get_dma_chain_index(int chain_id, int *ei, int *fi)
1497{
1498 int lch;
1499 int *channels;
1500
1501 /* Check for input params */
1502 if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1503 printk(KERN_ERR "Invalid chain id\n");
1504 return -EINVAL;
1505 }
1506
1507 /* Check if the chain exists */
1508 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1509 printk(KERN_ERR "Chain doesn't exists\n");
1510 return -EINVAL;
1511 }
1512 if ((!ei) || (!fi))
1513 return -EINVAL;
1514
1515 channels = dma_linked_lch[chain_id].linked_dmach_q;
1516
1517 /* Get the current channel */
1518 lch = channels[dma_linked_lch[chain_id].q_head];
1519
1520 *ei = OMAP2_DMA_CCEN_REG(lch);
1521 *fi = OMAP2_DMA_CCFN_REG(lch);
1522
1523 return 0;
1524}
1525EXPORT_SYMBOL(omap_get_dma_chain_index);
1526
1527/**
1528 * @brief omap_get_dma_chain_dst_pos - Get the destination position of the
1529 * ongoing DMA in chain
1530 *
1531 * @param chain_id
1532 *
1533 * @return - Success : Destination position
1534 * Failure : -EINVAL
1535 */
1536int omap_get_dma_chain_dst_pos(int chain_id)
1537{
1538 int lch;
1539 int *channels;
1540
1541 /* Check for input params */
1542 if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1543 printk(KERN_ERR "Invalid chain id\n");
1544 return -EINVAL;
1545 }
1546
1547 /* Check if the chain exists */
1548 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1549 printk(KERN_ERR "Chain doesn't exists\n");
1550 return -EINVAL;
1551 }
1552
1553 channels = dma_linked_lch[chain_id].linked_dmach_q;
1554
1555 /* Get the current channel */
1556 lch = channels[dma_linked_lch[chain_id].q_head];
1557
1558 return (OMAP_DMA_CDAC_REG(lch));
1559}
1560EXPORT_SYMBOL(omap_get_dma_chain_dst_pos);
1561
1562/**
1563 * @brief omap_get_dma_chain_src_pos - Get the source position
1564 * of the ongoing DMA in chain
1565 * @param chain_id
1566 *
1567 * @return - Success : Destination position
1568 * Failure : -EINVAL
1569 */
1570int omap_get_dma_chain_src_pos(int chain_id)
1571{
1572 int lch;
1573 int *channels;
1574
1575 /* Check for input params */
1576 if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) {
1577 printk(KERN_ERR "Invalid chain id\n");
1578 return -EINVAL;
1579 }
1580
1581 /* Check if the chain exists */
1582 if (dma_linked_lch[chain_id].linked_dmach_q == NULL) {
1583 printk(KERN_ERR "Chain doesn't exists\n");
1584 return -EINVAL;
1585 }
1586
1587 channels = dma_linked_lch[chain_id].linked_dmach_q;
1588
1589 /* Get the current channel */
1590 lch = channels[dma_linked_lch[chain_id].q_head];
1591
1592 return (OMAP_DMA_CSAC_REG(lch));
1593}
1594EXPORT_SYMBOL(omap_get_dma_chain_src_pos);
1595#endif
1596
862/*----------------------------------------------------------------------------*/ 1597/*----------------------------------------------------------------------------*/
863 1598
864#ifdef CONFIG_ARCH_OMAP1 1599#ifdef CONFIG_ARCH_OMAP1
@@ -919,7 +1654,7 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id)
919#define omap1_dma_irq_handler NULL 1654#define omap1_dma_irq_handler NULL
920#endif 1655#endif
921 1656
922#ifdef CONFIG_ARCH_OMAP2 1657#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
923 1658
924static int omap2_dma_handle_ch(int ch) 1659static int omap2_dma_handle_ch(int ch)
925{ 1660{
@@ -953,8 +1688,33 @@ static int omap2_dma_handle_ch(int ch)
953 OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK; 1688 OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK;
954 omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0); 1689 omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0);
955 1690
956 if (likely(dma_chan[ch].callback != NULL)) 1691 /* If the ch is not chained then chain_id will be -1 */
957 dma_chan[ch].callback(ch, status, dma_chan[ch].data); 1692 if (dma_chan[ch].chain_id != -1) {
1693 int chain_id = dma_chan[ch].chain_id;
1694 dma_chan[ch].state = DMA_CH_NOTSTARTED;
1695 if (OMAP_DMA_CLNK_CTRL_REG(ch) & (1 << 15))
1696 dma_chan[dma_chan[ch].next_linked_ch].state =
1697 DMA_CH_STARTED;
1698 if (dma_linked_lch[chain_id].chain_mode ==
1699 OMAP_DMA_DYNAMIC_CHAIN)
1700 disable_lnk(ch);
1701
1702 if (!OMAP_DMA_CHAIN_QEMPTY(chain_id))
1703 OMAP_DMA_CHAIN_INCQHEAD(chain_id);
1704
1705 status = OMAP_DMA_CSR_REG(ch);
1706 }
1707
1708 if (likely(dma_chan[ch].callback != NULL)) {
1709 if (dma_chan[ch].chain_id != -1)
1710 dma_chan[ch].callback(dma_chan[ch].chain_id, status,
1711 dma_chan[ch].data);
1712 else
1713 dma_chan[ch].callback(ch, status, dma_chan[ch].data);
1714
1715 }
1716
1717 OMAP_DMA_CSR_REG(ch) = status;
958 1718
959 return 0; 1719 return 0;
960} 1720}
@@ -1385,7 +2145,7 @@ static int __init omap_init_dma(void)
1385 w &= ~(1 << 8); 2145 w &= ~(1 << 8);
1386 omap_writew(w, OMAP1610_DMA_LCD_CTRL); 2146 omap_writew(w, OMAP1610_DMA_LCD_CTRL);
1387 } 2147 }
1388 } else if (cpu_is_omap24xx()) { 2148 } else if (cpu_class_is_omap2()) {
1389 u8 revision = omap_readb(OMAP_DMA4_REVISION); 2149 u8 revision = omap_readb(OMAP_DMA4_REVISION);
1390 printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", 2150 printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n",
1391 revision >> 4, revision & 0xf); 2151 revision >> 4, revision & 0xf);
@@ -1428,7 +2188,11 @@ static int __init omap_init_dma(void)
1428 } 2188 }
1429 } 2189 }
1430 2190
1431 if (cpu_is_omap24xx()) 2191 if (cpu_is_omap2430() || cpu_is_omap34xx())
2192 omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE,
2193 DMA_DEFAULT_FIFO_DEPTH, 0);
2194
2195 if (cpu_class_is_omap2())
1432 setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq); 2196 setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq);
1433 2197
1434 /* FIXME: Update LCD DMA to work on 24xx */ 2198 /* FIXME: Update LCD DMA to work on 24xx */
diff --git a/include/asm-arm/arch-omap/dma.h b/include/asm-arm/arch-omap/dma.h
index f33b467fddb7..24acf090030d 100644
--- a/include/asm-arm/arch-omap/dma.h
+++ b/include/asm-arm/arch-omap/dma.h
@@ -45,22 +45,28 @@
45#define OMAP_DMA_PCHD_SR (OMAP_DMA_BASE + 0x4c0) 45#define OMAP_DMA_PCHD_SR (OMAP_DMA_BASE + 0x4c0)
46 46
47/* Hardware registers for omap2 */ 47/* Hardware registers for omap2 */
48#define OMAP24XX_DMA_BASE (L4_24XX_BASE + 0x56000) 48#if defined(CONFIG_ARCH_OMAP3)
49#define OMAP_DMA4_REVISION (OMAP24XX_DMA_BASE + 0x00) 49#define OMAP_DMA4_BASE (L4_34XX_BASE + 0x56000)
50#define OMAP_DMA4_GCR_REG (OMAP24XX_DMA_BASE + 0x78) 50#else /* CONFIG_ARCH_OMAP2 */
51#define OMAP_DMA4_IRQSTATUS_L0 (OMAP24XX_DMA_BASE + 0x08) 51#define OMAP_DMA4_BASE (L4_24XX_BASE + 0x56000)
52#define OMAP_DMA4_IRQSTATUS_L1 (OMAP24XX_DMA_BASE + 0x0c) 52#endif
53#define OMAP_DMA4_IRQSTATUS_L2 (OMAP24XX_DMA_BASE + 0x10) 53
54#define OMAP_DMA4_IRQSTATUS_L3 (OMAP24XX_DMA_BASE + 0x14) 54#define OMAP_DMA4_REVISION (OMAP_DMA4_BASE + 0x00)
55#define OMAP_DMA4_IRQENABLE_L0 (OMAP24XX_DMA_BASE + 0x18) 55#define OMAP_DMA4_GCR_REG (OMAP_DMA4_BASE + 0x78)
56#define OMAP_DMA4_IRQENABLE_L1 (OMAP24XX_DMA_BASE + 0x1c) 56#define OMAP_DMA4_IRQSTATUS_L0 (OMAP_DMA4_BASE + 0x08)
57#define OMAP_DMA4_IRQENABLE_L2 (OMAP24XX_DMA_BASE + 0x20) 57#define OMAP_DMA4_IRQSTATUS_L1 (OMAP_DMA4_BASE + 0x0c)
58#define OMAP_DMA4_IRQENABLE_L3 (OMAP24XX_DMA_BASE + 0x24) 58#define OMAP_DMA4_IRQSTATUS_L2 (OMAP_DMA4_BASE + 0x10)
59#define OMAP_DMA4_SYSSTATUS (OMAP24XX_DMA_BASE + 0x28) 59#define OMAP_DMA4_IRQSTATUS_L3 (OMAP_DMA4_BASE + 0x14)
60#define OMAP_DMA4_CAPS_0 (OMAP24XX_DMA_BASE + 0x64) 60#define OMAP_DMA4_IRQENABLE_L0 (OMAP_DMA4_BASE + 0x18)
61#define OMAP_DMA4_CAPS_2 (OMAP24XX_DMA_BASE + 0x6c) 61#define OMAP_DMA4_IRQENABLE_L1 (OMAP_DMA4_BASE + 0x1c)
62#define OMAP_DMA4_CAPS_3 (OMAP24XX_DMA_BASE + 0x70) 62#define OMAP_DMA4_IRQENABLE_L2 (OMAP_DMA4_BASE + 0x20)
63#define OMAP_DMA4_CAPS_4 (OMAP24XX_DMA_BASE + 0x74) 63#define OMAP_DMA4_IRQENABLE_L3 (OMAP_DMA4_BASE + 0x24)
64#define OMAP_DMA4_SYSSTATUS (OMAP_DMA4_BASE + 0x28)
65#define OMAP_DMA4_OCP_SYSCONFIG (OMAP_DMA4_BASE + 0x2c)
66#define OMAP_DMA4_CAPS_0 (OMAP_DMA4_BASE + 0x64)
67#define OMAP_DMA4_CAPS_2 (OMAP_DMA4_BASE + 0x6c)
68#define OMAP_DMA4_CAPS_3 (OMAP_DMA4_BASE + 0x70)
69#define OMAP_DMA4_CAPS_4 (OMAP_DMA4_BASE + 0x74)
64 70
65#ifdef CONFIG_ARCH_OMAP1 71#ifdef CONFIG_ARCH_OMAP1
66 72
@@ -86,19 +92,19 @@
86#define OMAP_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ 92#define OMAP_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */
87 93
88/* Common channel specific registers for omap2 */ 94/* Common channel specific registers for omap2 */
89#define OMAP_DMA_CCR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x80) 95#define OMAP_DMA_CCR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x80)
90#define OMAP_DMA_CLNK_CTRL_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x84) 96#define OMAP_DMA_CLNK_CTRL_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x84)
91#define OMAP_DMA_CICR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x88) 97#define OMAP_DMA_CICR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x88)
92#define OMAP_DMA_CSR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x8c) 98#define OMAP_DMA_CSR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x8c)
93#define OMAP_DMA_CSDP_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x90) 99#define OMAP_DMA_CSDP_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x90)
94#define OMAP_DMA_CEN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x94) 100#define OMAP_DMA_CEN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x94)
95#define OMAP_DMA_CFN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x98) 101#define OMAP_DMA_CFN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x98)
96#define OMAP_DMA_CSEI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa4) 102#define OMAP_DMA_CSEI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xa4)
97#define OMAP_DMA_CSFI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa8) 103#define OMAP_DMA_CSFI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xa8)
98#define OMAP_DMA_CDEI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xac) 104#define OMAP_DMA_CDEI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xac)
99#define OMAP_DMA_CDFI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb0) 105#define OMAP_DMA_CDFI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xb0)
100#define OMAP_DMA_CSAC_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb4) 106#define OMAP_DMA_CSAC_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xb4)
101#define OMAP_DMA_CDAC_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb8) 107#define OMAP_DMA_CDAC_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xb8)
102 108
103#endif 109#endif
104 110
@@ -113,11 +119,11 @@
113#define OMAP1_DMA_LCH_CTRL_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x2a) 119#define OMAP1_DMA_LCH_CTRL_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x2a)
114 120
115/* Channel specific registers only on omap2 */ 121/* Channel specific registers only on omap2 */
116#define OMAP2_DMA_CSSA_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x9c) 122#define OMAP2_DMA_CSSA_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x9c)
117#define OMAP2_DMA_CDSA_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa0) 123#define OMAP2_DMA_CDSA_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xa0)
118#define OMAP2_DMA_CCEN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xbc) 124#define OMAP2_DMA_CCEN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xbc)
119#define OMAP2_DMA_CCFN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc0) 125#define OMAP2_DMA_CCFN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xc0)
120#define OMAP2_DMA_COLOR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc4) 126#define OMAP2_DMA_COLOR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xc4)
121 127
122/*----------------------------------------------------------------------------*/ 128/*----------------------------------------------------------------------------*/
123 129
@@ -297,6 +303,10 @@
297#define OMAP_DMA_SYNC_ELEMENT 0x00 303#define OMAP_DMA_SYNC_ELEMENT 0x00
298#define OMAP_DMA_SYNC_FRAME 0x01 304#define OMAP_DMA_SYNC_FRAME 0x01
299#define OMAP_DMA_SYNC_BLOCK 0x02 305#define OMAP_DMA_SYNC_BLOCK 0x02
306#define OMAP_DMA_SYNC_PACKET 0x03
307
308#define OMAP_DMA_SRC_SYNC 0x01
309#define OMAP_DMA_DST_SYNC 0x00
300 310
301#define OMAP_DMA_PORT_EMIFF 0x00 311#define OMAP_DMA_PORT_EMIFF 0x00
302#define OMAP_DMA_PORT_EMIFS 0x01 312#define OMAP_DMA_PORT_EMIFS 0x01
@@ -310,6 +320,29 @@
310#define OMAP_DMA_AMODE_SINGLE_IDX 0x02 320#define OMAP_DMA_AMODE_SINGLE_IDX 0x02
311#define OMAP_DMA_AMODE_DOUBLE_IDX 0x03 321#define OMAP_DMA_AMODE_DOUBLE_IDX 0x03
312 322
323#define DMA_DEFAULT_FIFO_DEPTH 0x10
324#define DMA_DEFAULT_ARB_RATE 0x01
325/* Pass THREAD_RESERVE ORed with THREAD_FIFO for tparams */
326#define DMA_THREAD_RESERVE_NORM (0x00 << 12) /* Def */
327#define DMA_THREAD_RESERVE_ONET (0x01 << 12)
328#define DMA_THREAD_RESERVE_TWOT (0x02 << 12)
329#define DMA_THREAD_RESERVE_THREET (0x03 << 12)
330#define DMA_THREAD_FIFO_NONE (0x00 << 14) /* Def */
331#define DMA_THREAD_FIFO_75 (0x01 << 14)
332#define DMA_THREAD_FIFO_25 (0x02 << 14)
333#define DMA_THREAD_FIFO_50 (0x03 << 14)
334
335/* Chaining modes*/
336#ifndef CONFIG_ARCH_OMAP1
337#define OMAP_DMA_STATIC_CHAIN 0x1
338#define OMAP_DMA_DYNAMIC_CHAIN 0x2
339#define OMAP_DMA_CHAIN_ACTIVE 0x1
340#define OMAP_DMA_CHAIN_INACTIVE 0x0
341#endif
342
343#define DMA_CH_PRIO_HIGH 0x1
344#define DMA_CH_PRIO_LOW 0x0 /* Def */
345
313/* LCD DMA block numbers */ 346/* LCD DMA block numbers */
314enum { 347enum {
315 OMAP_LCD_DMA_B1_TOP, 348 OMAP_LCD_DMA_B1_TOP,
@@ -359,6 +392,13 @@ struct omap_dma_channel_params {
359 int src_or_dst_synch; /* source synch(1) or destination synch(0) */ 392 int src_or_dst_synch; /* source synch(1) or destination synch(0) */
360 393
361 int ie; /* interrupt enabled */ 394 int ie; /* interrupt enabled */
395
396 unsigned char read_prio;/* read priority */
397 unsigned char write_prio;/* write priority */
398
399#ifndef CONFIG_ARCH_OMAP1
400 enum omap_dma_burst_mode burst_mode; /* Burst mode 4/8/16 words */
401#endif
362}; 402};
363 403
364 404
@@ -409,6 +449,33 @@ extern dma_addr_t omap_get_dma_dst_pos(int lch);
409extern int omap_get_dma_src_addr_counter(int lch); 449extern int omap_get_dma_src_addr_counter(int lch);
410extern void omap_clear_dma(int lch); 450extern void omap_clear_dma(int lch);
411extern int omap_dma_running(void); 451extern int omap_dma_running(void);
452extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth,
453 int tparams);
454extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio,
455 unsigned char write_prio);
456
457/* Chaining APIs */
458#ifndef CONFIG_ARCH_OMAP1
459extern int omap_request_dma_chain(int dev_id, const char *dev_name,
460 void (*callback) (int chain_id, u16 ch_status,
461 void *data),
462 int *chain_id, int no_of_chans,
463 int chain_mode,
464 struct omap_dma_channel_params params);
465extern int omap_free_dma_chain(int chain_id);
466extern int omap_dma_chain_a_transfer(int chain_id, int src_start,
467 int dest_start, int elem_count,
468 int frame_count, void *callbk_data);
469extern int omap_start_dma_chain_transfers(int chain_id);
470extern int omap_stop_dma_chain_transfers(int chain_id);
471extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi);
472extern int omap_get_dma_chain_dst_pos(int chain_id);
473extern int omap_get_dma_chain_src_pos(int chain_id);
474
475extern int omap_modify_dma_chain_params(int chain_id,
476 struct omap_dma_channel_params params);
477extern int omap_dma_chain_status(int chain_id);
478#endif
412 479
413/* LCD DMA functions */ 480/* LCD DMA functions */
414extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data), 481extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data),