ARM: OMAP: Add DMA support for chaining and 3430

Add DMA support for chaining and 3430.

Also remove old DEBUG_PRINTS as noted by Russell King.

Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>

authored by Anand Gadiyar and committed by Tony Lindgren f8151e5c 5eb3bb9c

+905 -74
+804 -40
arch/arm/plat-omap/dma.c
··· 6 * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> 7 * Graphics DMA and LCD DMA graphics tranformations 8 * by Imre Deak <imre.deak@nokia.com> 9 - * OMAP2 support Copyright (C) 2004-2005 Texas Instruments, Inc. 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. 12 * ··· 33 34 #include <asm/arch/tc.h> 35 36 - #define DEBUG_PRINTS 37 - #undef DEBUG_PRINTS 38 - #ifdef DEBUG_PRINTS 39 - #define debug_printk(x) printk x 40 - #else 41 - #define debug_printk(x) 42 #endif 43 44 #define OMAP_DMA_ACTIVE 0x01 ··· 59 const char *dev_name; 60 void (* callback)(int lch, u16 ch_status, void *data); 61 void *data; 62 long flags; 63 }; 64 65 static int dma_chan_count; 66 67 static spinlock_t dma_chan_lock; ··· 131 INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13, 132 INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD 133 }; 134 135 #define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \ 136 __FUNCTION__); ··· 211 omap_writel(l, reg); 212 } 213 214 - if (cpu_is_omap24xx()) { 215 if (priority) 216 OMAP_DMA_CCR_REG(lch) |= (1 << 6); 217 else ··· 236 OMAP1_DMA_CCR2_REG(lch) |= 1 << 2; 237 } 238 239 - if (cpu_is_omap24xx() && dma_trigger) { 240 u32 val = OMAP_DMA_CCR_REG(lch); 241 242 val &= ~(3 << 19); ··· 276 277 BUG_ON(omap_dma_in_1510_mode()); 278 279 - if (cpu_is_omap24xx()) { 280 REVISIT_24XX(); 281 return; 282 } ··· 308 309 void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) 310 { 311 - if (cpu_is_omap24xx()) { 312 OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16); 313 OMAP_DMA_CSDP_REG(lch) |= (mode << 16); 314 } ··· 332 OMAP1_DMA_CSSA_L_REG(lch) = src_start; 333 } 334 335 - if (cpu_is_omap24xx()) 336 OMAP2_DMA_CSSA_REG(lch) = src_start; 337 338 OMAP_DMA_CSEI_REG(lch) = src_ei; ··· 352 omap_set_dma_dest_params(lch, params->dst_port, 353 params->dst_amode, params->dst_start, 354 params->dst_ei, params->dst_fi); 355 } 356 357 void omap_set_dma_src_index(int lch, int eidx, int fidx) 358 { 359 - if (cpu_is_omap24xx()) { 360 REVISIT_24XX(); 361 return; 362 } ··· 383 case OMAP_DMA_DATA_BURST_DIS: 384 break; 385 case OMAP_DMA_DATA_BURST_4: 386 - if (cpu_is_omap24xx()) 387 burst = 0x1; 388 else 389 burst = 0x2; 390 break; 391 case OMAP_DMA_DATA_BURST_8: 392 - if (cpu_is_omap24xx()) { 393 burst = 0x2; 394 break; 395 } ··· 398 * fall through 399 */ 400 case OMAP_DMA_DATA_BURST_16: 401 - if (cpu_is_omap24xx()) { 402 burst = 0x3; 403 break; 404 } ··· 429 OMAP1_DMA_CDSA_L_REG(lch) = dest_start; 430 } 431 432 - if (cpu_is_omap24xx()) 433 OMAP2_DMA_CDSA_REG(lch) = dest_start; 434 435 OMAP_DMA_CDEI_REG(lch) = dst_ei; ··· 438 439 void omap_set_dma_dest_index(int lch, int eidx, int fidx) 440 { 441 - if (cpu_is_omap24xx()) { 442 REVISIT_24XX(); 443 return; 444 } ··· 462 case OMAP_DMA_DATA_BURST_DIS: 463 break; 464 case OMAP_DMA_DATA_BURST_4: 465 - if (cpu_is_omap24xx()) 466 burst = 0x1; 467 else 468 burst = 0x2; 469 break; 470 case OMAP_DMA_DATA_BURST_8: 471 - if (cpu_is_omap24xx()) 472 burst = 0x2; 473 else 474 burst = 0x3; 475 break; 476 case OMAP_DMA_DATA_BURST_16: 477 - if (cpu_is_omap24xx()) { 478 burst = 0x3; 479 break; 480 } ··· 496 /* Clear CSR */ 497 if (cpu_class_is_omap1()) 498 status = OMAP_DMA_CSR_REG(lch); 499 - else if (cpu_is_omap24xx()) 500 OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK; 501 502 /* Enable some nice interrupts. */ ··· 507 508 static void omap_disable_channel_irq(int lch) 509 { 510 - if (cpu_is_omap24xx()) 511 OMAP_DMA_CICR_REG(lch) = 0; 512 } 513 ··· 530 if (dma_chan[lch].next_lch != -1) 531 OMAP_DMA_CLNK_CTRL_REG(lch) = 532 dma_chan[lch].next_lch | (1 << 15); 533 } 534 535 static inline void disable_lnk(int lch) ··· 547 OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14; 548 } 549 550 - if (cpu_is_omap24xx()) { 551 omap_disable_channel_irq(lch); 552 /* Clear the ENABLE_LNK bit */ 553 OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15); ··· 560 { 561 u32 val; 562 563 - if (!cpu_is_omap24xx()) 564 return; 565 566 val = omap_readl(OMAP_DMA4_IRQENABLE_L0); ··· 594 if (cpu_class_is_omap1()) 595 clear_lch_regs(free_ch); 596 597 - if (cpu_is_omap24xx()) 598 omap_clear_dma(free_ch); 599 600 spin_unlock_irqrestore(&dma_chan_lock, flags); ··· 602 chan->dev_name = dev_name; 603 chan->callback = callback; 604 chan->data = data; 605 chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; 606 607 if (cpu_class_is_omap1()) 608 chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ; 609 - else if (cpu_is_omap24xx()) 610 chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ | 611 OMAP2_DMA_TRANS_ERR_IRQ; 612 ··· 626 OMAP_DMA_CCR_REG(free_ch) = dev_id; 627 } 628 629 - if (cpu_is_omap24xx()) { 630 omap2_enable_irq_lch(free_ch); 631 632 omap_enable_channel_irq(free_ch); ··· 663 OMAP_DMA_CCR_REG(lch) = 0; 664 } 665 666 - if (cpu_is_omap24xx()) { 667 u32 val; 668 /* Disable interrupts */ 669 val = omap_readl(OMAP_DMA4_IRQENABLE_L0); ··· 683 } 684 } 685 686 /* 687 * Clears any DMA state so the DMA engine is ready to restart with new buffers 688 * through omap_start_dma(). Any buffers in flight are discarded. ··· 762 status = OMAP_DMA_CSR_REG(lch); 763 } 764 765 - if (cpu_is_omap24xx()) { 766 int i; 767 - u32 lch_base = OMAP24XX_DMA_BASE + lch * 0x60 + 0x80; 768 for (i = 0; i < 0x44; i += 4) 769 omap_writel(0, lch_base + i); 770 } ··· 798 799 cur_lch = next_lch; 800 } while (next_lch != -1); 801 - } else if (cpu_is_omap24xx()) { 802 /* Errata: Need to write lch even if not using chaining */ 803 OMAP_DMA_CLNK_CTRL_REG(lch) = lch; 804 } ··· 889 offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) | 890 (OMAP1_DMA_CSSA_U_REG(lch) << 16)); 891 892 - if (cpu_is_omap24xx()) 893 offset = OMAP_DMA_CSAC_REG(lch); 894 895 return offset; ··· 911 offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) | 912 (OMAP1_DMA_CDSA_U_REG(lch) << 16)); 913 914 - if (cpu_is_omap24xx()) 915 - offset = OMAP2_DMA_CDSA_REG(lch); 916 917 return offset; 918 } ··· 995 dma_chan[lch_head].next_lch = -1; 996 } 997 998 /*----------------------------------------------------------------------------*/ 999 1000 #ifdef CONFIG_ARCH_OMAP1 ··· 1654 #define omap1_dma_irq_handler NULL 1655 #endif 1656 1657 - #ifdef CONFIG_ARCH_OMAP2 1658 1659 static int omap2_dma_handle_ch(int ch) 1660 { ··· 1688 OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK; 1689 omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0); 1690 1691 - if (likely(dma_chan[ch].callback != NULL)) 1692 - dma_chan[ch].callback(ch, status, dma_chan[ch].data); 1693 1694 return 0; 1695 } ··· 2145 w &= ~(1 << 8); 2146 omap_writew(w, OMAP1610_DMA_LCD_CTRL); 2147 } 2148 - } else if (cpu_is_omap24xx()) { 2149 u8 revision = omap_readb(OMAP_DMA4_REVISION); 2150 printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", 2151 revision >> 4, revision & 0xf); ··· 2188 } 2189 } 2190 2191 - if (cpu_is_omap24xx()) 2192 setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq); 2193 2194 /* FIXME: Update LCD DMA to work on 24xx */
··· 6 * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> 7 * Graphics DMA and LCD DMA graphics tranformations 8 * by Imre Deak <imre.deak@nokia.com> 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> 11 * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. 12 * ··· 33 34 #include <asm/arch/tc.h> 35 36 + #undef DEBUG 37 + 38 + #ifndef CONFIG_ARCH_OMAP1 39 + enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED, 40 + DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED 41 + }; 42 + 43 + enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; 44 #endif 45 46 #define OMAP_DMA_ACTIVE 0x01 ··· 57 const char *dev_name; 58 void (* callback)(int lch, u16 ch_status, void *data); 59 void *data; 60 + 61 + #ifndef CONFIG_ARCH_OMAP1 62 + /* required for Dynamic chaining */ 63 + int prev_linked_ch; 64 + int next_linked_ch; 65 + int state; 66 + int chain_id; 67 + 68 + int status; 69 + #endif 70 long flags; 71 }; 72 73 + #ifndef CONFIG_ARCH_OMAP1 74 + struct dma_link_info { 75 + int *linked_dmach_q; 76 + int no_of_lchs_linked; 77 + 78 + int q_count; 79 + int q_tail; 80 + int q_head; 81 + 82 + int chain_state; 83 + int chain_mode; 84 + 85 + }; 86 + 87 + static struct dma_link_info dma_linked_lch[OMAP_LOGICAL_DMA_CH_COUNT]; 88 + 89 + /* Chain handling macros */ 90 + #define OMAP_DMA_CHAIN_QINIT(chain_id) \ 91 + do { \ 92 + dma_linked_lch[chain_id].q_head = \ 93 + dma_linked_lch[chain_id].q_tail = \ 94 + dma_linked_lch[chain_id].q_count = 0; \ 95 + } while (0) 96 + #define OMAP_DMA_CHAIN_QFULL(chain_id) \ 97 + (dma_linked_lch[chain_id].no_of_lchs_linked == \ 98 + dma_linked_lch[chain_id].q_count) 99 + #define OMAP_DMA_CHAIN_QLAST(chain_id) \ 100 + do { \ 101 + ((dma_linked_lch[chain_id].no_of_lchs_linked-1) == \ 102 + dma_linked_lch[chain_id].q_count) \ 103 + } while (0) 104 + #define OMAP_DMA_CHAIN_QEMPTY(chain_id) \ 105 + (0 == dma_linked_lch[chain_id].q_count) 106 + #define __OMAP_DMA_CHAIN_INCQ(end) \ 107 + ((end) = ((end)+1) % dma_linked_lch[chain_id].no_of_lchs_linked) 108 + #define OMAP_DMA_CHAIN_INCQHEAD(chain_id) \ 109 + do { \ 110 + __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_head); \ 111 + dma_linked_lch[chain_id].q_count--; \ 112 + } while (0) 113 + 114 + #define OMAP_DMA_CHAIN_INCQTAIL(chain_id) \ 115 + do { \ 116 + __OMAP_DMA_CHAIN_INCQ(dma_linked_lch[chain_id].q_tail); \ 117 + dma_linked_lch[chain_id].q_count++; \ 118 + } while (0) 119 + #endif 120 static int dma_chan_count; 121 122 static spinlock_t dma_chan_lock; ··· 72 INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13, 73 INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD 74 }; 75 + 76 + static inline void disable_lnk(int lch); 77 + static void omap_disable_channel_irq(int lch); 78 + static inline void omap_enable_channel_irq(int lch); 79 80 #define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \ 81 __FUNCTION__); ··· 148 omap_writel(l, reg); 149 } 150 151 + if (cpu_class_is_omap2()) { 152 if (priority) 153 OMAP_DMA_CCR_REG(lch) |= (1 << 6); 154 else ··· 173 OMAP1_DMA_CCR2_REG(lch) |= 1 << 2; 174 } 175 176 + if (cpu_class_is_omap2() && dma_trigger) { 177 u32 val = OMAP_DMA_CCR_REG(lch); 178 179 val &= ~(3 << 19); ··· 213 214 BUG_ON(omap_dma_in_1510_mode()); 215 216 + if (cpu_class_is_omap2()) { 217 REVISIT_24XX(); 218 return; 219 } ··· 245 246 void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) 247 { 248 + if (cpu_class_is_omap2()) { 249 OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16); 250 OMAP_DMA_CSDP_REG(lch) |= (mode << 16); 251 } ··· 269 OMAP1_DMA_CSSA_L_REG(lch) = src_start; 270 } 271 272 + if (cpu_class_is_omap2()) 273 OMAP2_DMA_CSSA_REG(lch) = src_start; 274 275 OMAP_DMA_CSEI_REG(lch) = src_ei; ··· 289 omap_set_dma_dest_params(lch, params->dst_port, 290 params->dst_amode, params->dst_start, 291 params->dst_ei, params->dst_fi); 292 + if (params->read_prio || params->write_prio) 293 + omap_dma_set_prio_lch(lch, params->read_prio, 294 + params->write_prio); 295 } 296 297 void omap_set_dma_src_index(int lch, int eidx, int fidx) 298 { 299 + if (cpu_class_is_omap2()) { 300 REVISIT_24XX(); 301 return; 302 } ··· 317 case OMAP_DMA_DATA_BURST_DIS: 318 break; 319 case OMAP_DMA_DATA_BURST_4: 320 + if (cpu_class_is_omap2()) 321 burst = 0x1; 322 else 323 burst = 0x2; 324 break; 325 case OMAP_DMA_DATA_BURST_8: 326 + if (cpu_class_is_omap2()) { 327 burst = 0x2; 328 break; 329 } ··· 332 * fall through 333 */ 334 case OMAP_DMA_DATA_BURST_16: 335 + if (cpu_class_is_omap2()) { 336 burst = 0x3; 337 break; 338 } ··· 363 OMAP1_DMA_CDSA_L_REG(lch) = dest_start; 364 } 365 366 + if (cpu_class_is_omap2()) 367 OMAP2_DMA_CDSA_REG(lch) = dest_start; 368 369 OMAP_DMA_CDEI_REG(lch) = dst_ei; ··· 372 373 void omap_set_dma_dest_index(int lch, int eidx, int fidx) 374 { 375 + if (cpu_class_is_omap2()) { 376 REVISIT_24XX(); 377 return; 378 } ··· 396 case OMAP_DMA_DATA_BURST_DIS: 397 break; 398 case OMAP_DMA_DATA_BURST_4: 399 + if (cpu_class_is_omap2()) 400 burst = 0x1; 401 else 402 burst = 0x2; 403 break; 404 case OMAP_DMA_DATA_BURST_8: 405 + if (cpu_class_is_omap2()) 406 burst = 0x2; 407 else 408 burst = 0x3; 409 break; 410 case OMAP_DMA_DATA_BURST_16: 411 + if (cpu_class_is_omap2()) { 412 burst = 0x3; 413 break; 414 } ··· 430 /* Clear CSR */ 431 if (cpu_class_is_omap1()) 432 status = OMAP_DMA_CSR_REG(lch); 433 + else if (cpu_class_is_omap2()) 434 OMAP_DMA_CSR_REG(lch) = OMAP2_DMA_CSR_CLEAR_MASK; 435 436 /* Enable some nice interrupts. */ ··· 441 442 static void omap_disable_channel_irq(int lch) 443 { 444 + if (cpu_class_is_omap2()) 445 OMAP_DMA_CICR_REG(lch) = 0; 446 } 447 ··· 464 if (dma_chan[lch].next_lch != -1) 465 OMAP_DMA_CLNK_CTRL_REG(lch) = 466 dma_chan[lch].next_lch | (1 << 15); 467 + 468 + #ifndef CONFIG_ARCH_OMAP1 469 + if (dma_chan[lch].next_linked_ch != -1) 470 + OMAP_DMA_CLNK_CTRL_REG(lch) = 471 + dma_chan[lch].next_linked_ch | (1 << 15); 472 + #endif 473 } 474 475 static inline void disable_lnk(int lch) ··· 475 OMAP_DMA_CLNK_CTRL_REG(lch) |= 1 << 14; 476 } 477 478 + if (cpu_class_is_omap2()) { 479 omap_disable_channel_irq(lch); 480 /* Clear the ENABLE_LNK bit */ 481 OMAP_DMA_CLNK_CTRL_REG(lch) &= ~(1 << 15); ··· 488 { 489 u32 val; 490 491 + if (!cpu_class_is_omap2()) 492 return; 493 494 val = omap_readl(OMAP_DMA4_IRQENABLE_L0); ··· 522 if (cpu_class_is_omap1()) 523 clear_lch_regs(free_ch); 524 525 + if (cpu_class_is_omap2()) 526 omap_clear_dma(free_ch); 527 528 spin_unlock_irqrestore(&dma_chan_lock, flags); ··· 530 chan->dev_name = dev_name; 531 chan->callback = callback; 532 chan->data = data; 533 + #ifndef CONFIG_ARCH_OMAP1 534 + chan->chain_id = -1; 535 + #endif 536 chan->enabled_irqs = OMAP_DMA_DROP_IRQ | OMAP_DMA_BLOCK_IRQ; 537 538 if (cpu_class_is_omap1()) 539 chan->enabled_irqs |= OMAP1_DMA_TOUT_IRQ; 540 + else if (cpu_class_is_omap2()) 541 chan->enabled_irqs |= OMAP2_DMA_MISALIGNED_ERR_IRQ | 542 OMAP2_DMA_TRANS_ERR_IRQ; 543 ··· 551 OMAP_DMA_CCR_REG(free_ch) = dev_id; 552 } 553 554 + if (cpu_class_is_omap2()) { 555 omap2_enable_irq_lch(free_ch); 556 557 omap_enable_channel_irq(free_ch); ··· 588 OMAP_DMA_CCR_REG(lch) = 0; 589 } 590 591 + if (cpu_class_is_omap2()) { 592 u32 val; 593 /* Disable interrupts */ 594 val = omap_readl(OMAP_DMA4_IRQENABLE_L0); ··· 608 } 609 } 610 611 + /** 612 + * @brief omap_dma_set_global_params : Set global priority settings for dma 613 + * 614 + * @param arb_rate 615 + * @param max_fifo_depth 616 + * @param tparams - Number of thereads to reserve : DMA_THREAD_RESERVE_NORM 617 + * DMA_THREAD_RESERVE_ONET 618 + * DMA_THREAD_RESERVE_TWOT 619 + * DMA_THREAD_RESERVE_THREET 620 + */ 621 + void 622 + omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) 623 + { 624 + u32 reg; 625 + 626 + if (!cpu_class_is_omap2()) { 627 + printk(KERN_ERR "FIXME: no %s on 15xx/16xx\n", __FUNCTION__); 628 + return; 629 + } 630 + 631 + if (arb_rate == 0) 632 + arb_rate = 1; 633 + 634 + reg = (arb_rate & 0xff) << 16; 635 + reg |= (0xff & max_fifo_depth); 636 + 637 + omap_writel(reg, OMAP_DMA4_GCR_REG); 638 + } 639 + EXPORT_SYMBOL(omap_dma_set_global_params); 640 + 641 + /** 642 + * @brief omap_dma_set_prio_lch : Set channel wise priority settings 643 + * 644 + * @param lch 645 + * @param read_prio - Read priority 646 + * @param write_prio - Write priority 647 + * Both of the above can be set with one of the following values : 648 + * DMA_CH_PRIO_HIGH/DMA_CH_PRIO_LOW 649 + */ 650 + int 651 + omap_dma_set_prio_lch(int lch, unsigned char read_prio, 652 + unsigned char write_prio) 653 + { 654 + u32 w; 655 + 656 + if (unlikely((lch < 0 || lch >= OMAP_LOGICAL_DMA_CH_COUNT))) { 657 + printk(KERN_ERR "Invalid channel id\n"); 658 + return -EINVAL; 659 + } 660 + w = OMAP_DMA_CCR_REG(lch); 661 + w &= ~((1 << 6) | (1 << 26)); 662 + if (cpu_is_omap2430() || cpu_is_omap34xx()) 663 + w |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); 664 + else 665 + w |= ((read_prio & 0x1) << 6); 666 + 667 + OMAP_DMA_CCR_REG(lch) = w; 668 + return 0; 669 + } 670 + EXPORT_SYMBOL(omap_dma_set_prio_lch); 671 + 672 /* 673 * Clears any DMA state so the DMA engine is ready to restart with new buffers 674 * through omap_start_dma(). Any buffers in flight are discarded. ··· 626 status = OMAP_DMA_CSR_REG(lch); 627 } 628 629 + if (cpu_class_is_omap2()) { 630 int i; 631 + u32 lch_base = OMAP_DMA4_BASE + lch * 0x60 + 0x80; 632 for (i = 0; i < 0x44; i += 4) 633 omap_writel(0, lch_base + i); 634 } ··· 662 663 cur_lch = next_lch; 664 } while (next_lch != -1); 665 + } else if (cpu_class_is_omap2()) { 666 /* Errata: Need to write lch even if not using chaining */ 667 OMAP_DMA_CLNK_CTRL_REG(lch) = lch; 668 } ··· 753 offset = (dma_addr_t) (OMAP1_DMA_CSSA_L_REG(lch) | 754 (OMAP1_DMA_CSSA_U_REG(lch) << 16)); 755 756 + if (cpu_class_is_omap2()) 757 offset = OMAP_DMA_CSAC_REG(lch); 758 759 return offset; ··· 775 offset = (dma_addr_t) (OMAP1_DMA_CDSA_L_REG(lch) | 776 (OMAP1_DMA_CDSA_U_REG(lch) << 16)); 777 778 + if (cpu_class_is_omap2()) 779 + offset = OMAP_DMA_CDAC_REG(lch); 780 781 return offset; 782 } ··· 859 dma_chan[lch_head].next_lch = -1; 860 } 861 862 + #ifndef CONFIG_ARCH_OMAP1 863 + /* Create chain of DMA channesls */ 864 + static void create_dma_lch_chain(int lch_head, int lch_queue) 865 + { 866 + u32 w; 867 + 868 + /* Check if this is the first link in chain */ 869 + if (dma_chan[lch_head].next_linked_ch == -1) { 870 + dma_chan[lch_head].next_linked_ch = lch_queue; 871 + dma_chan[lch_head].prev_linked_ch = lch_queue; 872 + dma_chan[lch_queue].next_linked_ch = lch_head; 873 + dma_chan[lch_queue].prev_linked_ch = lch_head; 874 + } 875 + 876 + /* a link exists, link the new channel in circular chain */ 877 + else { 878 + dma_chan[lch_queue].next_linked_ch = 879 + dma_chan[lch_head].next_linked_ch; 880 + dma_chan[lch_queue].prev_linked_ch = lch_head; 881 + dma_chan[lch_head].next_linked_ch = lch_queue; 882 + dma_chan[dma_chan[lch_queue].next_linked_ch].prev_linked_ch = 883 + lch_queue; 884 + } 885 + 886 + w = OMAP_DMA_CLNK_CTRL_REG(lch_head); 887 + w &= ~(0x0f); 888 + w |= lch_queue; 889 + OMAP_DMA_CLNK_CTRL_REG(lch_head) = w; 890 + 891 + w = OMAP_DMA_CLNK_CTRL_REG(lch_queue); 892 + w &= ~(0x0f); 893 + w |= (dma_chan[lch_queue].next_linked_ch); 894 + OMAP_DMA_CLNK_CTRL_REG(lch_queue) = w; 895 + } 896 + 897 + /** 898 + * @brief omap_request_dma_chain : Request a chain of DMA channels 899 + * 900 + * @param dev_id - Device id using the dma channel 901 + * @param dev_name - Device name 902 + * @param callback - Call back function 903 + * @chain_id - 904 + * @no_of_chans - Number of channels requested 905 + * @chain_mode - Dynamic or static chaining : OMAP_DMA_STATIC_CHAIN 906 + * OMAP_DMA_DYNAMIC_CHAIN 907 + * @params - Channel parameters 908 + * 909 + * @return - Succes : 0 910 + * Failure: -EINVAL/-ENOMEM 911 + */ 912 + int omap_request_dma_chain(int dev_id, const char *dev_name, 913 + void (*callback) (int chain_id, u16 ch_status, 914 + void *data), 915 + int *chain_id, int no_of_chans, int chain_mode, 916 + struct omap_dma_channel_params params) 917 + { 918 + int *channels; 919 + int i, err; 920 + 921 + /* Is the chain mode valid ? */ 922 + if (chain_mode != OMAP_DMA_STATIC_CHAIN 923 + && chain_mode != OMAP_DMA_DYNAMIC_CHAIN) { 924 + printk(KERN_ERR "Invalid chain mode requested\n"); 925 + return -EINVAL; 926 + } 927 + 928 + if (unlikely((no_of_chans < 1 929 + || no_of_chans > OMAP_LOGICAL_DMA_CH_COUNT))) { 930 + printk(KERN_ERR "Invalid Number of channels requested\n"); 931 + return -EINVAL; 932 + } 933 + 934 + /* Allocate a queue to maintain the status of the channels 935 + * in the chain */ 936 + channels = kmalloc(sizeof(*channels) * no_of_chans, GFP_KERNEL); 937 + if (channels == NULL) { 938 + printk(KERN_ERR "omap_dma: No memory for channel queue\n"); 939 + return -ENOMEM; 940 + } 941 + 942 + /* request and reserve DMA channels for the chain */ 943 + for (i = 0; i < no_of_chans; i++) { 944 + err = omap_request_dma(dev_id, dev_name, 945 + callback, 0, &channels[i]); 946 + if (err < 0) { 947 + int j; 948 + for (j = 0; j < i; j++) 949 + omap_free_dma(channels[j]); 950 + kfree(channels); 951 + printk(KERN_ERR "omap_dma: Request failed %d\n", err); 952 + return err; 953 + } 954 + dma_chan[channels[i]].next_linked_ch = -1; 955 + dma_chan[channels[i]].prev_linked_ch = -1; 956 + dma_chan[channels[i]].state = DMA_CH_NOTSTARTED; 957 + 958 + /* 959 + * Allowing client drivers to set common parameters now, 960 + * so that later only relevant (src_start, dest_start 961 + * and element count) can be set 962 + */ 963 + omap_set_dma_params(channels[i], &params); 964 + } 965 + 966 + *chain_id = channels[0]; 967 + dma_linked_lch[*chain_id].linked_dmach_q = channels; 968 + dma_linked_lch[*chain_id].chain_mode = chain_mode; 969 + dma_linked_lch[*chain_id].chain_state = DMA_CHAIN_NOTSTARTED; 970 + dma_linked_lch[*chain_id].no_of_lchs_linked = no_of_chans; 971 + 972 + for (i = 0; i < no_of_chans; i++) 973 + dma_chan[channels[i]].chain_id = *chain_id; 974 + 975 + /* Reset the Queue pointers */ 976 + OMAP_DMA_CHAIN_QINIT(*chain_id); 977 + 978 + /* Set up the chain */ 979 + if (no_of_chans == 1) 980 + create_dma_lch_chain(channels[0], channels[0]); 981 + else { 982 + for (i = 0; i < (no_of_chans - 1); i++) 983 + create_dma_lch_chain(channels[i], channels[i + 1]); 984 + } 985 + return 0; 986 + } 987 + EXPORT_SYMBOL(omap_request_dma_chain); 988 + 989 + /** 990 + * @brief omap_modify_dma_chain_param : Modify the chain's params - Modify the 991 + * params after setting it. Dont do this while dma is running!! 992 + * 993 + * @param chain_id - Chained logical channel id. 994 + * @param params 995 + * 996 + * @return - Success : 0 997 + * Failure : -EINVAL 998 + */ 999 + int omap_modify_dma_chain_params(int chain_id, 1000 + struct omap_dma_channel_params params) 1001 + { 1002 + int *channels; 1003 + u32 i; 1004 + 1005 + /* Check for input params */ 1006 + if (unlikely((chain_id < 0 1007 + || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1008 + printk(KERN_ERR "Invalid chain id\n"); 1009 + return -EINVAL; 1010 + } 1011 + 1012 + /* Check if the chain exists */ 1013 + if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { 1014 + printk(KERN_ERR "Chain doesn't exists\n"); 1015 + return -EINVAL; 1016 + } 1017 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1018 + 1019 + for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { 1020 + /* 1021 + * Allowing client drivers to set common parameters now, 1022 + * so that later only relevant (src_start, dest_start 1023 + * and element count) can be set 1024 + */ 1025 + omap_set_dma_params(channels[i], &params); 1026 + } 1027 + return 0; 1028 + } 1029 + EXPORT_SYMBOL(omap_modify_dma_chain_params); 1030 + 1031 + /** 1032 + * @brief omap_free_dma_chain - Free all the logical channels in a chain. 1033 + * 1034 + * @param chain_id 1035 + * 1036 + * @return - Success : 0 1037 + * Failure : -EINVAL 1038 + */ 1039 + int omap_free_dma_chain(int chain_id) 1040 + { 1041 + int *channels; 1042 + u32 i; 1043 + 1044 + /* Check for input params */ 1045 + if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1046 + printk(KERN_ERR "Invalid chain id\n"); 1047 + return -EINVAL; 1048 + } 1049 + 1050 + /* Check if the chain exists */ 1051 + if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { 1052 + printk(KERN_ERR "Chain doesn't exists\n"); 1053 + return -EINVAL; 1054 + } 1055 + 1056 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1057 + for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { 1058 + dma_chan[channels[i]].next_linked_ch = -1; 1059 + dma_chan[channels[i]].prev_linked_ch = -1; 1060 + dma_chan[channels[i]].chain_id = -1; 1061 + dma_chan[channels[i]].state = DMA_CH_NOTSTARTED; 1062 + omap_free_dma(channels[i]); 1063 + } 1064 + 1065 + kfree(channels); 1066 + 1067 + dma_linked_lch[chain_id].linked_dmach_q = NULL; 1068 + dma_linked_lch[chain_id].chain_mode = -1; 1069 + dma_linked_lch[chain_id].chain_state = -1; 1070 + return (0); 1071 + } 1072 + EXPORT_SYMBOL(omap_free_dma_chain); 1073 + 1074 + /** 1075 + * @brief omap_dma_chain_status - Check if the chain is in 1076 + * active / inactive state. 1077 + * @param chain_id 1078 + * 1079 + * @return - Success : OMAP_DMA_CHAIN_ACTIVE/OMAP_DMA_CHAIN_INACTIVE 1080 + * Failure : -EINVAL 1081 + */ 1082 + int omap_dma_chain_status(int chain_id) 1083 + { 1084 + /* Check for input params */ 1085 + if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1086 + printk(KERN_ERR "Invalid chain id\n"); 1087 + return -EINVAL; 1088 + } 1089 + 1090 + /* Check if the chain exists */ 1091 + if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { 1092 + printk(KERN_ERR "Chain doesn't exists\n"); 1093 + return -EINVAL; 1094 + } 1095 + pr_debug("CHAINID=%d, qcnt=%d\n", chain_id, 1096 + dma_linked_lch[chain_id].q_count); 1097 + 1098 + if (OMAP_DMA_CHAIN_QEMPTY(chain_id)) 1099 + return OMAP_DMA_CHAIN_INACTIVE; 1100 + return OMAP_DMA_CHAIN_ACTIVE; 1101 + } 1102 + EXPORT_SYMBOL(omap_dma_chain_status); 1103 + 1104 + /** 1105 + * @brief omap_dma_chain_a_transfer - Get a free channel from a chain, 1106 + * set the params and start the transfer. 1107 + * 1108 + * @param chain_id 1109 + * @param src_start - buffer start address 1110 + * @param dest_start - Dest address 1111 + * @param elem_count 1112 + * @param frame_count 1113 + * @param callbk_data - channel callback parameter data. 1114 + * 1115 + * @return - Success : start_dma status 1116 + * Failure: -EINVAL/-EBUSY 1117 + */ 1118 + int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, 1119 + int elem_count, int frame_count, void *callbk_data) 1120 + { 1121 + int *channels; 1122 + u32 w, lch; 1123 + int start_dma = 0; 1124 + 1125 + /* if buffer size is less than 1 then there is 1126 + * no use of starting the chain */ 1127 + if (elem_count < 1) { 1128 + printk(KERN_ERR "Invalid buffer size\n"); 1129 + return -EINVAL; 1130 + } 1131 + 1132 + /* Check for input params */ 1133 + if (unlikely((chain_id < 0 1134 + || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1135 + printk(KERN_ERR "Invalid chain id\n"); 1136 + return -EINVAL; 1137 + } 1138 + 1139 + /* Check if the chain exists */ 1140 + if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { 1141 + printk(KERN_ERR "Chain doesn't exist\n"); 1142 + return -EINVAL; 1143 + } 1144 + 1145 + /* Check if all the channels in chain are in use */ 1146 + if (OMAP_DMA_CHAIN_QFULL(chain_id)) 1147 + return -EBUSY; 1148 + 1149 + /* Frame count may be negative in case of indexed transfers */ 1150 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1151 + 1152 + /* Get a free channel */ 1153 + lch = channels[dma_linked_lch[chain_id].q_tail]; 1154 + 1155 + /* Store the callback data */ 1156 + dma_chan[lch].data = callbk_data; 1157 + 1158 + /* Increment the q_tail */ 1159 + OMAP_DMA_CHAIN_INCQTAIL(chain_id); 1160 + 1161 + /* Set the params to the free channel */ 1162 + if (src_start != 0) 1163 + OMAP2_DMA_CSSA_REG(lch) = src_start; 1164 + if (dest_start != 0) 1165 + OMAP2_DMA_CDSA_REG(lch) = dest_start; 1166 + 1167 + /* Write the buffer size */ 1168 + OMAP_DMA_CEN_REG(lch) = elem_count; 1169 + OMAP_DMA_CFN_REG(lch) = frame_count; 1170 + 1171 + /* If the chain is dynamically linked, 1172 + * then we may have to start the chain if its not active */ 1173 + if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_DYNAMIC_CHAIN) { 1174 + 1175 + /* In Dynamic chain, if the chain is not started, 1176 + * queue the channel */ 1177 + if (dma_linked_lch[chain_id].chain_state == 1178 + DMA_CHAIN_NOTSTARTED) { 1179 + /* Enable the link in previous channel */ 1180 + if (dma_chan[dma_chan[lch].prev_linked_ch].state == 1181 + DMA_CH_QUEUED) 1182 + enable_lnk(dma_chan[lch].prev_linked_ch); 1183 + dma_chan[lch].state = DMA_CH_QUEUED; 1184 + } 1185 + 1186 + /* Chain is already started, make sure its active, 1187 + * if not then start the chain */ 1188 + else { 1189 + start_dma = 1; 1190 + 1191 + if (dma_chan[dma_chan[lch].prev_linked_ch].state == 1192 + DMA_CH_STARTED) { 1193 + enable_lnk(dma_chan[lch].prev_linked_ch); 1194 + dma_chan[lch].state = DMA_CH_QUEUED; 1195 + start_dma = 0; 1196 + if (0 == ((1 << 7) & (OMAP_DMA_CCR_REG 1197 + (dma_chan[lch].prev_linked_ch)))) { 1198 + disable_lnk(dma_chan[lch]. 1199 + prev_linked_ch); 1200 + pr_debug("\n prev ch is stopped\n"); 1201 + start_dma = 1; 1202 + } 1203 + } 1204 + 1205 + else if (dma_chan[dma_chan[lch].prev_linked_ch].state 1206 + == DMA_CH_QUEUED) { 1207 + enable_lnk(dma_chan[lch].prev_linked_ch); 1208 + dma_chan[lch].state = DMA_CH_QUEUED; 1209 + start_dma = 0; 1210 + } 1211 + omap_enable_channel_irq(lch); 1212 + 1213 + w = OMAP_DMA_CCR_REG(lch); 1214 + 1215 + if ((0 == (w & (1 << 24)))) 1216 + w &= ~(1 << 25); 1217 + else 1218 + w |= (1 << 25); 1219 + if (start_dma == 1) { 1220 + if (0 == (w & (1 << 7))) { 1221 + w |= (1 << 7); 1222 + dma_chan[lch].state = DMA_CH_STARTED; 1223 + pr_debug("starting %d\n", lch); 1224 + OMAP_DMA_CCR_REG(lch) = w; 1225 + } else 1226 + start_dma = 0; 1227 + } else { 1228 + if (0 == (w & (1 << 7))) 1229 + OMAP_DMA_CCR_REG(lch) = w; 1230 + } 1231 + dma_chan[lch].flags |= OMAP_DMA_ACTIVE; 1232 + } 1233 + } 1234 + return start_dma; 1235 + } 1236 + EXPORT_SYMBOL(omap_dma_chain_a_transfer); 1237 + 1238 + /** 1239 + * @brief omap_start_dma_chain_transfers - Start the chain 1240 + * 1241 + * @param chain_id 1242 + * 1243 + * @return - Success : 0 1244 + * Failure : -EINVAL/-EBUSY 1245 + */ 1246 + int omap_start_dma_chain_transfers(int chain_id) 1247 + { 1248 + int *channels; 1249 + u32 w, i; 1250 + 1251 + if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1252 + printk(KERN_ERR "Invalid chain id\n"); 1253 + return -EINVAL; 1254 + } 1255 + 1256 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1257 + 1258 + if (dma_linked_lch[channels[0]].chain_state == DMA_CHAIN_STARTED) { 1259 + printk(KERN_ERR "Chain is already started\n"); 1260 + return -EBUSY; 1261 + } 1262 + 1263 + if (dma_linked_lch[chain_id].chain_mode == OMAP_DMA_STATIC_CHAIN) { 1264 + for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; 1265 + i++) { 1266 + enable_lnk(channels[i]); 1267 + omap_enable_channel_irq(channels[i]); 1268 + } 1269 + } else { 1270 + omap_enable_channel_irq(channels[0]); 1271 + } 1272 + 1273 + w = OMAP_DMA_CCR_REG(channels[0]); 1274 + w |= (1 << 7); 1275 + dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED; 1276 + dma_chan[channels[0]].state = DMA_CH_STARTED; 1277 + 1278 + if ((0 == (w & (1 << 24)))) 1279 + w &= ~(1 << 25); 1280 + else 1281 + w |= (1 << 25); 1282 + OMAP_DMA_CCR_REG(channels[0]) = w; 1283 + 1284 + dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; 1285 + return 0; 1286 + } 1287 + EXPORT_SYMBOL(omap_start_dma_chain_transfers); 1288 + 1289 + /** 1290 + * @brief omap_stop_dma_chain_transfers - Stop the dma transfer of a chain. 1291 + * 1292 + * @param chain_id 1293 + * 1294 + * @return - Success : 0 1295 + * Failure : EINVAL 1296 + */ 1297 + int omap_stop_dma_chain_transfers(int chain_id) 1298 + { 1299 + int *channels; 1300 + u32 w, i; 1301 + u32 sys_cf; 1302 + 1303 + /* Check for input params */ 1304 + if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1305 + printk(KERN_ERR "Invalid chain id\n"); 1306 + return -EINVAL; 1307 + } 1308 + 1309 + /* Check if the chain exists */ 1310 + if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { 1311 + printk(KERN_ERR "Chain doesn't exists\n"); 1312 + return -EINVAL; 1313 + } 1314 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1315 + 1316 + /* DMA Errata: 1317 + * Special programming model needed to disable DMA before end of block 1318 + */ 1319 + sys_cf = omap_readl(OMAP_DMA4_OCP_SYSCONFIG); 1320 + w = sys_cf; 1321 + /* Middle mode reg set no Standby */ 1322 + w &= ~((1 << 12)|(1 << 13)); 1323 + omap_writel(w, OMAP_DMA4_OCP_SYSCONFIG); 1324 + 1325 + for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { 1326 + 1327 + /* Stop the Channel transmission */ 1328 + w = OMAP_DMA_CCR_REG(channels[i]); 1329 + w &= ~(1 << 7); 1330 + OMAP_DMA_CCR_REG(channels[i]) = w; 1331 + 1332 + /* Disable the link in all the channels */ 1333 + disable_lnk(channels[i]); 1334 + dma_chan[channels[i]].state = DMA_CH_NOTSTARTED; 1335 + 1336 + } 1337 + dma_linked_lch[chain_id].chain_state = DMA_CHAIN_NOTSTARTED; 1338 + 1339 + /* Reset the Queue pointers */ 1340 + OMAP_DMA_CHAIN_QINIT(chain_id); 1341 + 1342 + /* Errata - put in the old value */ 1343 + omap_writel(sys_cf, OMAP_DMA4_OCP_SYSCONFIG); 1344 + return 0; 1345 + } 1346 + EXPORT_SYMBOL(omap_stop_dma_chain_transfers); 1347 + 1348 + /* Get the index of the ongoing DMA in chain */ 1349 + /** 1350 + * @brief omap_get_dma_chain_index - Get the element and frame index 1351 + * of the ongoing DMA in chain 1352 + * 1353 + * @param chain_id 1354 + * @param ei - Element index 1355 + * @param fi - Frame index 1356 + * 1357 + * @return - Success : 0 1358 + * Failure : -EINVAL 1359 + */ 1360 + int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) 1361 + { 1362 + int lch; 1363 + int *channels; 1364 + 1365 + /* Check for input params */ 1366 + if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1367 + printk(KERN_ERR "Invalid chain id\n"); 1368 + return -EINVAL; 1369 + } 1370 + 1371 + /* Check if the chain exists */ 1372 + if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { 1373 + printk(KERN_ERR "Chain doesn't exists\n"); 1374 + return -EINVAL; 1375 + } 1376 + if ((!ei) || (!fi)) 1377 + return -EINVAL; 1378 + 1379 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1380 + 1381 + /* Get the current channel */ 1382 + lch = channels[dma_linked_lch[chain_id].q_head]; 1383 + 1384 + *ei = OMAP2_DMA_CCEN_REG(lch); 1385 + *fi = OMAP2_DMA_CCFN_REG(lch); 1386 + 1387 + return 0; 1388 + } 1389 + EXPORT_SYMBOL(omap_get_dma_chain_index); 1390 + 1391 + /** 1392 + * @brief omap_get_dma_chain_dst_pos - Get the destination position of the 1393 + * ongoing DMA in chain 1394 + * 1395 + * @param chain_id 1396 + * 1397 + * @return - Success : Destination position 1398 + * Failure : -EINVAL 1399 + */ 1400 + int omap_get_dma_chain_dst_pos(int chain_id) 1401 + { 1402 + int lch; 1403 + int *channels; 1404 + 1405 + /* Check for input params */ 1406 + if (unlikely((chain_id < 0 || chain_id >= OMAP_LOGICAL_DMA_CH_COUNT))) { 1407 + printk(KERN_ERR "Invalid chain id\n"); 1408 + return -EINVAL; 1409 + } 1410 + 1411 + /* Check if the chain exists */ 1412 + if (dma_linked_lch[chain_id].linked_dmach_q == NULL) { 1413 + printk(KERN_ERR "Chain doesn't exists\n"); 1414 + return -EINVAL; 1415 + } 1416 + 1417 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1418 + 1419 + /* Get the current channel */ 1420 + lch = channels[dma_linked_lch[chain_id].q_head]; 1421 + 1422 + return (OMAP_DMA_CDAC_REG(lch)); 1423 + } 1424 + EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); 1425 + 1426 + /** 1427 + * @brief omap_get_dma_chain_src_pos - Get the source position 1428 + * of the ongoing DMA in chain 1429 + * @param chain_id 1430 + * 1431 + * @return - Success : Destination position 1432 + * Failure : -EINVAL 1433 + */ 1434 + int omap_get_dma_chain_src_pos(int chain_id) 1435 + { 1436 + int lch; 1437 + int *channels; 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 + 1451 + channels = dma_linked_lch[chain_id].linked_dmach_q; 1452 + 1453 + /* Get the current channel */ 1454 + lch = channels[dma_linked_lch[chain_id].q_head]; 1455 + 1456 + return (OMAP_DMA_CSAC_REG(lch)); 1457 + } 1458 + EXPORT_SYMBOL(omap_get_dma_chain_src_pos); 1459 + #endif 1460 + 1461 /*----------------------------------------------------------------------------*/ 1462 1463 #ifdef CONFIG_ARCH_OMAP1 ··· 919 #define omap1_dma_irq_handler NULL 920 #endif 921 922 + #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) 923 924 static int omap2_dma_handle_ch(int ch) 925 { ··· 953 OMAP_DMA_CSR_REG(ch) = OMAP2_DMA_CSR_CLEAR_MASK; 954 omap_writel(1 << ch, OMAP_DMA4_IRQSTATUS_L0); 955 956 + /* If the ch is not chained then chain_id will be -1 */ 957 + if (dma_chan[ch].chain_id != -1) { 958 + int chain_id = dma_chan[ch].chain_id; 959 + dma_chan[ch].state = DMA_CH_NOTSTARTED; 960 + if (OMAP_DMA_CLNK_CTRL_REG(ch) & (1 << 15)) 961 + dma_chan[dma_chan[ch].next_linked_ch].state = 962 + DMA_CH_STARTED; 963 + if (dma_linked_lch[chain_id].chain_mode == 964 + OMAP_DMA_DYNAMIC_CHAIN) 965 + disable_lnk(ch); 966 + 967 + if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) 968 + OMAP_DMA_CHAIN_INCQHEAD(chain_id); 969 + 970 + status = OMAP_DMA_CSR_REG(ch); 971 + } 972 + 973 + if (likely(dma_chan[ch].callback != NULL)) { 974 + if (dma_chan[ch].chain_id != -1) 975 + dma_chan[ch].callback(dma_chan[ch].chain_id, status, 976 + dma_chan[ch].data); 977 + else 978 + dma_chan[ch].callback(ch, status, dma_chan[ch].data); 979 + 980 + } 981 + 982 + OMAP_DMA_CSR_REG(ch) = status; 983 984 return 0; 985 } ··· 1385 w &= ~(1 << 8); 1386 omap_writew(w, OMAP1610_DMA_LCD_CTRL); 1387 } 1388 + } else if (cpu_class_is_omap2()) { 1389 u8 revision = omap_readb(OMAP_DMA4_REVISION); 1390 printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", 1391 revision >> 4, revision & 0xf); ··· 1428 } 1429 } 1430 1431 + if (cpu_is_omap2430() || cpu_is_omap34xx()) 1432 + omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 1433 + DMA_DEFAULT_FIFO_DEPTH, 0); 1434 + 1435 + if (cpu_class_is_omap2()) 1436 setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq); 1437 1438 /* FIXME: Update LCD DMA to work on 24xx */
+101 -34
include/asm-arm/arch-omap/dma.h
··· 45 #define OMAP_DMA_PCHD_SR (OMAP_DMA_BASE + 0x4c0) 46 47 /* Hardware registers for omap2 */ 48 - #define OMAP24XX_DMA_BASE (L4_24XX_BASE + 0x56000) 49 - #define OMAP_DMA4_REVISION (OMAP24XX_DMA_BASE + 0x00) 50 - #define OMAP_DMA4_GCR_REG (OMAP24XX_DMA_BASE + 0x78) 51 - #define OMAP_DMA4_IRQSTATUS_L0 (OMAP24XX_DMA_BASE + 0x08) 52 - #define OMAP_DMA4_IRQSTATUS_L1 (OMAP24XX_DMA_BASE + 0x0c) 53 - #define OMAP_DMA4_IRQSTATUS_L2 (OMAP24XX_DMA_BASE + 0x10) 54 - #define OMAP_DMA4_IRQSTATUS_L3 (OMAP24XX_DMA_BASE + 0x14) 55 - #define OMAP_DMA4_IRQENABLE_L0 (OMAP24XX_DMA_BASE + 0x18) 56 - #define OMAP_DMA4_IRQENABLE_L1 (OMAP24XX_DMA_BASE + 0x1c) 57 - #define OMAP_DMA4_IRQENABLE_L2 (OMAP24XX_DMA_BASE + 0x20) 58 - #define OMAP_DMA4_IRQENABLE_L3 (OMAP24XX_DMA_BASE + 0x24) 59 - #define OMAP_DMA4_SYSSTATUS (OMAP24XX_DMA_BASE + 0x28) 60 - #define OMAP_DMA4_CAPS_0 (OMAP24XX_DMA_BASE + 0x64) 61 - #define OMAP_DMA4_CAPS_2 (OMAP24XX_DMA_BASE + 0x6c) 62 - #define OMAP_DMA4_CAPS_3 (OMAP24XX_DMA_BASE + 0x70) 63 - #define OMAP_DMA4_CAPS_4 (OMAP24XX_DMA_BASE + 0x74) 64 65 #ifdef CONFIG_ARCH_OMAP1 66 ··· 92 #define OMAP_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ 93 94 /* Common channel specific registers for omap2 */ 95 - #define OMAP_DMA_CCR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x80) 96 - #define OMAP_DMA_CLNK_CTRL_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x84) 97 - #define OMAP_DMA_CICR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x88) 98 - #define OMAP_DMA_CSR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x8c) 99 - #define OMAP_DMA_CSDP_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x90) 100 - #define OMAP_DMA_CEN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x94) 101 - #define OMAP_DMA_CFN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x98) 102 - #define OMAP_DMA_CSEI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa4) 103 - #define OMAP_DMA_CSFI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa8) 104 - #define OMAP_DMA_CDEI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xac) 105 - #define OMAP_DMA_CDFI_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb0) 106 - #define OMAP_DMA_CSAC_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb4) 107 - #define OMAP_DMA_CDAC_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xb8) 108 109 #endif 110 ··· 119 #define OMAP1_DMA_LCH_CTRL_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x2a) 120 121 /* Channel specific registers only on omap2 */ 122 - #define OMAP2_DMA_CSSA_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0x9c) 123 - #define OMAP2_DMA_CDSA_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xa0) 124 - #define OMAP2_DMA_CCEN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xbc) 125 - #define OMAP2_DMA_CCFN_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc0) 126 - #define OMAP2_DMA_COLOR_REG(n) __REG32(OMAP24XX_DMA_BASE + 0x60 * (n) + 0xc4) 127 128 /*----------------------------------------------------------------------------*/ 129 ··· 303 #define OMAP_DMA_SYNC_ELEMENT 0x00 304 #define OMAP_DMA_SYNC_FRAME 0x01 305 #define OMAP_DMA_SYNC_BLOCK 0x02 306 307 #define OMAP_DMA_PORT_EMIFF 0x00 308 #define OMAP_DMA_PORT_EMIFS 0x01 ··· 319 #define OMAP_DMA_AMODE_POST_INC 0x01 320 #define OMAP_DMA_AMODE_SINGLE_IDX 0x02 321 #define OMAP_DMA_AMODE_DOUBLE_IDX 0x03 322 323 /* LCD DMA block numbers */ 324 enum { ··· 392 int src_or_dst_synch; /* source synch(1) or destination synch(0) */ 393 394 int ie; /* interrupt enabled */ 395 }; 396 397 ··· 449 extern int omap_get_dma_src_addr_counter(int lch); 450 extern void omap_clear_dma(int lch); 451 extern int omap_dma_running(void); 452 453 /* LCD DMA functions */ 454 extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data),
··· 45 #define OMAP_DMA_PCHD_SR (OMAP_DMA_BASE + 0x4c0) 46 47 /* Hardware registers for omap2 */ 48 + #if defined(CONFIG_ARCH_OMAP3) 49 + #define OMAP_DMA4_BASE (L4_34XX_BASE + 0x56000) 50 + #else /* CONFIG_ARCH_OMAP2 */ 51 + #define OMAP_DMA4_BASE (L4_24XX_BASE + 0x56000) 52 + #endif 53 + 54 + #define OMAP_DMA4_REVISION (OMAP_DMA4_BASE + 0x00) 55 + #define OMAP_DMA4_GCR_REG (OMAP_DMA4_BASE + 0x78) 56 + #define OMAP_DMA4_IRQSTATUS_L0 (OMAP_DMA4_BASE + 0x08) 57 + #define OMAP_DMA4_IRQSTATUS_L1 (OMAP_DMA4_BASE + 0x0c) 58 + #define OMAP_DMA4_IRQSTATUS_L2 (OMAP_DMA4_BASE + 0x10) 59 + #define OMAP_DMA4_IRQSTATUS_L3 (OMAP_DMA4_BASE + 0x14) 60 + #define OMAP_DMA4_IRQENABLE_L0 (OMAP_DMA4_BASE + 0x18) 61 + #define OMAP_DMA4_IRQENABLE_L1 (OMAP_DMA4_BASE + 0x1c) 62 + #define OMAP_DMA4_IRQENABLE_L2 (OMAP_DMA4_BASE + 0x20) 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) 70 71 #ifdef CONFIG_ARCH_OMAP1 72 ··· 86 #define OMAP_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ 87 88 /* Common channel specific registers for omap2 */ 89 + #define OMAP_DMA_CCR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x80) 90 + #define OMAP_DMA_CLNK_CTRL_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x84) 91 + #define OMAP_DMA_CICR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x88) 92 + #define OMAP_DMA_CSR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x8c) 93 + #define OMAP_DMA_CSDP_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x90) 94 + #define OMAP_DMA_CEN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x94) 95 + #define OMAP_DMA_CFN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x98) 96 + #define OMAP_DMA_CSEI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xa4) 97 + #define OMAP_DMA_CSFI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xa8) 98 + #define OMAP_DMA_CDEI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xac) 99 + #define OMAP_DMA_CDFI_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xb0) 100 + #define OMAP_DMA_CSAC_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xb4) 101 + #define OMAP_DMA_CDAC_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xb8) 102 103 #endif 104 ··· 113 #define OMAP1_DMA_LCH_CTRL_REG(n) __REG16(OMAP_DMA_BASE + 0x40 * (n) + 0x2a) 114 115 /* Channel specific registers only on omap2 */ 116 + #define OMAP2_DMA_CSSA_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0x9c) 117 + #define OMAP2_DMA_CDSA_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xa0) 118 + #define OMAP2_DMA_CCEN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xbc) 119 + #define OMAP2_DMA_CCFN_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xc0) 120 + #define OMAP2_DMA_COLOR_REG(n) __REG32(OMAP_DMA4_BASE + 0x60 * (n) + 0xc4) 121 122 /*----------------------------------------------------------------------------*/ 123 ··· 297 #define OMAP_DMA_SYNC_ELEMENT 0x00 298 #define OMAP_DMA_SYNC_FRAME 0x01 299 #define OMAP_DMA_SYNC_BLOCK 0x02 300 + #define OMAP_DMA_SYNC_PACKET 0x03 301 + 302 + #define OMAP_DMA_SRC_SYNC 0x01 303 + #define OMAP_DMA_DST_SYNC 0x00 304 305 #define OMAP_DMA_PORT_EMIFF 0x00 306 #define OMAP_DMA_PORT_EMIFS 0x01 ··· 309 #define OMAP_DMA_AMODE_POST_INC 0x01 310 #define OMAP_DMA_AMODE_SINGLE_IDX 0x02 311 #define OMAP_DMA_AMODE_DOUBLE_IDX 0x03 312 + 313 + #define DMA_DEFAULT_FIFO_DEPTH 0x10 314 + #define DMA_DEFAULT_ARB_RATE 0x01 315 + /* Pass THREAD_RESERVE ORed with THREAD_FIFO for tparams */ 316 + #define DMA_THREAD_RESERVE_NORM (0x00 << 12) /* Def */ 317 + #define DMA_THREAD_RESERVE_ONET (0x01 << 12) 318 + #define DMA_THREAD_RESERVE_TWOT (0x02 << 12) 319 + #define DMA_THREAD_RESERVE_THREET (0x03 << 12) 320 + #define DMA_THREAD_FIFO_NONE (0x00 << 14) /* Def */ 321 + #define DMA_THREAD_FIFO_75 (0x01 << 14) 322 + #define DMA_THREAD_FIFO_25 (0x02 << 14) 323 + #define DMA_THREAD_FIFO_50 (0x03 << 14) 324 + 325 + /* Chaining modes*/ 326 + #ifndef CONFIG_ARCH_OMAP1 327 + #define OMAP_DMA_STATIC_CHAIN 0x1 328 + #define OMAP_DMA_DYNAMIC_CHAIN 0x2 329 + #define OMAP_DMA_CHAIN_ACTIVE 0x1 330 + #define OMAP_DMA_CHAIN_INACTIVE 0x0 331 + #endif 332 + 333 + #define DMA_CH_PRIO_HIGH 0x1 334 + #define DMA_CH_PRIO_LOW 0x0 /* Def */ 335 336 /* LCD DMA block numbers */ 337 enum { ··· 359 int src_or_dst_synch; /* source synch(1) or destination synch(0) */ 360 361 int ie; /* interrupt enabled */ 362 + 363 + unsigned char read_prio;/* read priority */ 364 + unsigned char write_prio;/* write priority */ 365 + 366 + #ifndef CONFIG_ARCH_OMAP1 367 + enum omap_dma_burst_mode burst_mode; /* Burst mode 4/8/16 words */ 368 + #endif 369 }; 370 371 ··· 409 extern int omap_get_dma_src_addr_counter(int lch); 410 extern void omap_clear_dma(int lch); 411 extern int omap_dma_running(void); 412 + extern void omap_dma_set_global_params(int arb_rate, int max_fifo_depth, 413 + int tparams); 414 + extern int omap_dma_set_prio_lch(int lch, unsigned char read_prio, 415 + unsigned char write_prio); 416 + 417 + /* Chaining APIs */ 418 + #ifndef CONFIG_ARCH_OMAP1 419 + extern int omap_request_dma_chain(int dev_id, const char *dev_name, 420 + void (*callback) (int chain_id, u16 ch_status, 421 + void *data), 422 + int *chain_id, int no_of_chans, 423 + int chain_mode, 424 + struct omap_dma_channel_params params); 425 + extern int omap_free_dma_chain(int chain_id); 426 + extern int omap_dma_chain_a_transfer(int chain_id, int src_start, 427 + int dest_start, int elem_count, 428 + int frame_count, void *callbk_data); 429 + extern int omap_start_dma_chain_transfers(int chain_id); 430 + extern int omap_stop_dma_chain_transfers(int chain_id); 431 + extern int omap_get_dma_chain_index(int chain_id, int *ei, int *fi); 432 + extern int omap_get_dma_chain_dst_pos(int chain_id); 433 + extern int omap_get_dma_chain_src_pos(int chain_id); 434 + 435 + extern int omap_modify_dma_chain_params(int chain_id, 436 + struct omap_dma_channel_params params); 437 + extern int omap_dma_chain_status(int chain_id); 438 + #endif 439 440 /* LCD DMA functions */ 441 extern int omap_request_lcd_dma(void (* callback)(u16 status, void *data),