summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Halpin <jack.halpin@gmail.com>2009-11-23 19:44:13 +0000
committerJack Halpin <jack.halpin@gmail.com>2009-11-23 19:44:13 +0000
commitf5b59cdf5e6974ea2b23babfc7aa326df6f8a49e (patch)
treef02d02bd191bf5e2ced4d65d4e48ef9f944aa814
parentae22ef13edf317137504770aadac429df3b0d53f (diff)
AMS Sansa: dma-pl081.c: dma_enable_channel() Add step to clear pending interrupts from the previous operation. Add comments and make construction
of the CH_CONTROL and CH_CONFIGURATION registers easier to follow. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23725 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/dma-pl081.c66
1 files changed, 36 insertions, 30 deletions
diff --git a/firmware/target/arm/as3525/dma-pl081.c b/firmware/target/arm/as3525/dma-pl081.c
index 52fd90f940..5bde46565b 100644
--- a/firmware/target/arm/as3525/dma-pl081.c
+++ b/firmware/target/arm/as3525/dma-pl081.c
@@ -63,41 +63,47 @@ void dma_enable_channel(int channel, void *src, void *dst, int peri,
{
dma_callback[channel] = callback;
- int control = 0;
+ /* Clear any pending interrupts leftover from previous operation */
+ DMAC_INT_TC_CLEAR = (1<<channel);
+ DMAC_INT_ERR_CLEAR = (1<<channel);
DMAC_CH_SRC_ADDR(channel) = (int)src;
DMAC_CH_DST_ADDR(channel) = (int)dst;
- DMAC_CH_LLI(channel) = 0; /* we use contigous memory, so don't use the LLI */
-
- /* specify address increment */
- if(src_inc)
- control |= (1<<26);
-
- if(dst_inc)
- control |= (1<<27);
-
- /* OF use transfers of 4 * 32 bits words on memory, i2sin, i2sout */
- /* OF use transfers of 8 * 32 bits words on SD */
-
- control |= (2<<21) | (2<<18); /* dst/src width = word, 32bit */
- control |= (nwords<<15) | (nwords<<12); /* dst/src size */
- control |= (size & 0x7ff); /* transfer size */
-
- control |= (1<<31); /* current LLI is expected to trigger terminal count interrupt */
-
- DMAC_CH_CONTROL(channel) = control;
-
- /* we set the same peripheral as source and destination because we always
- * use memory-to-peripheral or peripheral-to-memory transfers */
+ /* When LLI is 0 channel is disabled upon transfer completion */
+ DMAC_CH_LLI(channel) = 0;
+
+ /* Channel Control Register */
+ DMAC_CH_CONTROL(channel) =
+ ((1<<31) /* LLI triggers terminal count interrupt */
+ /* | (1<<30) */ /* cacheable = 1, non = 0 */
+ /* | (1<<29) */ /* bufferable = 1, non = 0 */
+ /* | (1<<28) */ /* privileged = 1, user = 0 */
+ | (dst_inc? (1<<27): 0) /* specify address increment */
+ | (src_inc? (1<<26): 0) /* specify address increment */
+ /* [25:24] */ /* undefined */
+ | (2<<21) /* dst width = word, 32bit */
+ | (2<<18) /* src width = word, 32bit */
+ /* OF uses transfers of 4 * 32 bits words on memory, i2sin, i2sout */
+ /* OF uses transfers of 8 * 32 bits words on SD */
+ | (nwords<<15) /* dst size */
+ | (nwords<<12) /* src size */
+ | ((size & 0x7ff)<<0)); /* transfer size */
+
+ /* Channel Config Register */
DMAC_CH_CONFIGURATION(channel) =
- (flow_controller<<11) /* flow controller is peripheral */
- | (1<<15) /* terminal count interrupt mask */
- | (1<<14) /* interrupt error mask */
- | (peri<<6) /* dst peripheral */
- | (peri<<1) /* src peripheral */
- | (1<<0) /* enable channel */
- ;
+ /* [31:19] */ /* Read undefined. Write as zero */
+ /* (0<<18) */ /* Halt Bit */
+ /* (0<<17) */ /* Active Bit */
+ /* (0<<16) */ /* Lock Bit */
+ (1<<15) /* terminal count interrupt mask */
+ | (1<<14) /* interrupt error mask */
+ | (flow_controller<<11) /* flow controller is peripheral or SDMAC */
+ /* we set the same peripheral as source and destination because we
+ * always use memory-to-peripheral or peripheral-to-memory transfers */
+ | (peri<<6) /* dst peripheral */
+ | (peri<<1) /* src peripheral */
+ | (1<<0); /* enable channel */
}
/* isr */