diff options
Diffstat (limited to 'arch/arm/plat-omap/dma.c')
-rw-r--r-- | arch/arm/plat-omap/dma.c | 50 |
1 files changed, 44 insertions, 6 deletions
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index ec7eddf9e525..f5c5b8da9a87 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/irq.h> | 30 | #include <linux/irq.h> |
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/delay.h> | ||
33 | 34 | ||
34 | #include <asm/system.h> | 35 | #include <asm/system.h> |
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
@@ -996,11 +997,17 @@ void omap_start_dma(int lch) | |||
996 | l = dma_read(CCR(lch)); | 997 | l = dma_read(CCR(lch)); |
997 | 998 | ||
998 | /* | 999 | /* |
999 | * Errata: On ES2.0 BUFFERING disable must be set. | 1000 | * Errata: Inter Frame DMA buffering issue (All OMAP2420 and |
1000 | * This will always fail on ES1.0 | 1001 | * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and |
1002 | * bursting is enabled. This might result in data gets stalled in | ||
1003 | * FIFO at the end of the block. | ||
1004 | * Workaround: DMA channels must have BUFFERING_DISABLED bit set to | ||
1005 | * guarantee no data will stay in the DMA FIFO in case inter frame | ||
1006 | * buffering occurs. | ||
1001 | */ | 1007 | */ |
1002 | if (cpu_is_omap24xx()) | 1008 | if (cpu_is_omap2420() || |
1003 | l |= OMAP_DMA_CCR_EN; | 1009 | (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0))) |
1010 | l |= OMAP_DMA_CCR_BUFFERING_DISABLE; | ||
1004 | 1011 | ||
1005 | l |= OMAP_DMA_CCR_EN; | 1012 | l |= OMAP_DMA_CCR_EN; |
1006 | dma_write(l, CCR(lch)); | 1013 | dma_write(l, CCR(lch)); |
@@ -1018,8 +1025,39 @@ void omap_stop_dma(int lch) | |||
1018 | dma_write(0, CICR(lch)); | 1025 | dma_write(0, CICR(lch)); |
1019 | 1026 | ||
1020 | l = dma_read(CCR(lch)); | 1027 | l = dma_read(CCR(lch)); |
1021 | l &= ~OMAP_DMA_CCR_EN; | 1028 | /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ |
1022 | dma_write(l, CCR(lch)); | 1029 | if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { |
1030 | int i = 0; | ||
1031 | u32 sys_cf; | ||
1032 | |||
1033 | /* Configure No-Standby */ | ||
1034 | l = dma_read(OCP_SYSCONFIG); | ||
1035 | sys_cf = l; | ||
1036 | l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; | ||
1037 | l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); | ||
1038 | dma_write(l , OCP_SYSCONFIG); | ||
1039 | |||
1040 | l = dma_read(CCR(lch)); | ||
1041 | l &= ~OMAP_DMA_CCR_EN; | ||
1042 | dma_write(l, CCR(lch)); | ||
1043 | |||
1044 | /* Wait for sDMA FIFO drain */ | ||
1045 | l = dma_read(CCR(lch)); | ||
1046 | while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | | ||
1047 | OMAP_DMA_CCR_WR_ACTIVE))) { | ||
1048 | udelay(5); | ||
1049 | i++; | ||
1050 | l = dma_read(CCR(lch)); | ||
1051 | } | ||
1052 | if (i >= 100) | ||
1053 | printk(KERN_ERR "DMA drain did not complete on " | ||
1054 | "lch %d\n", lch); | ||
1055 | /* Restore OCP_SYSCONFIG */ | ||
1056 | dma_write(sys_cf, OCP_SYSCONFIG); | ||
1057 | } else { | ||
1058 | l &= ~OMAP_DMA_CCR_EN; | ||
1059 | dma_write(l, CCR(lch)); | ||
1060 | } | ||
1023 | 1061 | ||
1024 | if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { | 1062 | if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { |
1025 | int next_lch, cur_lch = lch; | 1063 | int next_lch, cur_lch = lch; |