diff options
-rw-r--r-- | arch/arm/plat-omap/dma.c | 36 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/dma.h | 3 |
2 files changed, 37 insertions, 2 deletions
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 420cef370b33..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> |
@@ -1024,8 +1025,39 @@ void omap_stop_dma(int lch) | |||
1024 | dma_write(0, CICR(lch)); | 1025 | dma_write(0, CICR(lch)); |
1025 | 1026 | ||
1026 | l = dma_read(CCR(lch)); | 1027 | l = dma_read(CCR(lch)); |
1027 | l &= ~OMAP_DMA_CCR_EN; | 1028 | /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ |
1028 | 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 | } | ||
1029 | 1061 | ||
1030 | 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) { |
1031 | int next_lch, cur_lch = lch; | 1063 | int next_lch, cur_lch = lch; |
diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 6f70f7cfe91d..0cce4ca83aa0 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h | |||
@@ -337,6 +337,9 @@ | |||
337 | #define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11) | 337 | #define OMAP2_DMA_MISALIGNED_ERR_IRQ (1 << 11) |
338 | 338 | ||
339 | #define OMAP_DMA_CCR_EN (1 << 7) | 339 | #define OMAP_DMA_CCR_EN (1 << 7) |
340 | #define OMAP_DMA_CCR_RD_ACTIVE (1 << 9) | ||
341 | #define OMAP_DMA_CCR_WR_ACTIVE (1 << 10) | ||
342 | #define OMAP_DMA_CCR_SEL_SRC_DST_SYNC (1 << 24) | ||
340 | #define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25) | 343 | #define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25) |
341 | 344 | ||
342 | #define OMAP_DMA_DATA_TYPE_S8 0x00 | 345 | #define OMAP_DMA_DATA_TYPE_S8 0x00 |