From c140d27900b95ceed867ef36102fcdeaa91a5cc8 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 8 Aug 2013 15:51:16 -0600 Subject: SAMA5: Use RDR/TDR registers for DMA, not FIFO registers; change DMA bit settings to match Atmel example. Still no DMA --- nuttx/arch/arm/src/sam34/sam3u_dmac.c | 10 ++++++++-- nuttx/arch/arm/src/sam34/sam_hsmci.c | 4 ++-- nuttx/arch/arm/src/sama5/chip/sam_dmac.h | 9 +++++---- nuttx/arch/arm/src/sama5/sam_dmac.c | 18 +++++++++++++----- nuttx/arch/arm/src/sama5/sam_hsmci.c | 30 ++++++++++++++++++++---------- 5 files changed, 48 insertions(+), 23 deletions(-) diff --git a/nuttx/arch/arm/src/sam34/sam3u_dmac.c b/nuttx/arch/arm/src/sam34/sam3u_dmac.c index ef598d01b..43d725b0d 100644 --- a/nuttx/arch/arm/src/sam34/sam3u_dmac.c +++ b/nuttx/arch/arm/src/sam34/sam3u_dmac.c @@ -308,7 +308,8 @@ static inline uint32_t sam_txcfg(struct sam_dma_s *dmach) /* Set transfer (memory to peripheral) DMA channel configuration register */ - regval = (((dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT); + regval = DMACHAN_CFG_SOD; + regval |= (((dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT); regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ? DMACHAN_CFG_SRCH2SEL : 0; regval |= (((dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT) << DMACHAN_CFG_DSTPER_SHIFT); regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ? DMACHAN_CFG_DSTH2SEL : 0; @@ -331,7 +332,8 @@ static inline uint32_t sam_rxcfg(struct sam_dma_s *dmach) /* Set received (peripheral to memory) DMA channel config */ - regval = (((dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT); + regval = DMACHAN_CFG_SOD; + regval |= (((dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT) << DMACHAN_CFG_SRCPER_SHIFT); regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ? DMACHAN_CFG_SRCH2SEL : 0; regval |= (((dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT) << DMACHAN_CFG_DSTPER_SHIFT); regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ? DMACHAN_CFG_DSTH2SEL : 0; @@ -949,6 +951,10 @@ static inline int sam_single(struct sam_dma_s *dmach) putreg32(llhead->dest, dmach->base + SAM_DMACHAN_DADDR_OFFSET); + /* Clear the next descriptor address register */ + + putreg32(0, dmach->base + SAM_DMACHAN_DSCR_OFFSET); + /* Set up the CTRLA register */ putreg32(llhead->ctrla, dmach->base + SAM_DMACHAN_CTRLA_OFFSET); diff --git a/nuttx/arch/arm/src/sam34/sam_hsmci.c b/nuttx/arch/arm/src/sam34/sam_hsmci.c index ee252e578..e5fca7f0d 100644 --- a/nuttx/arch/arm/src/sam34/sam_hsmci.c +++ b/nuttx/arch/arm/src/sam34/sam_hsmci.c @@ -2217,7 +2217,7 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, /* Configure the RX DMA */ sam_enablexfrints(priv, HSMCI_DMARECV_INTS); - sam_dmarxsetup(priv->dma, SAM_HSMCI_FIFO, (uint32_t)buffer, buflen); + sam_dmarxsetup(priv->dma, SAM_HSMCI_RDR, (uint32_t)buffer, buflen); /* Enable DMA handshaking */ @@ -2265,7 +2265,7 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev, /* Configure the TX DMA */ - sam_dmatxsetup(priv->dma, SAM_HSMCI_FIFO, (uint32_t)buffer, buflen); + sam_dmatxsetup(priv->dma, SAM_HSMCI_TDR, (uint32_t)buffer, buflen); /* Enable DMA handshaking */ diff --git a/nuttx/arch/arm/src/sama5/chip/sam_dmac.h b/nuttx/arch/arm/src/sama5/chip/sam_dmac.h index fbcd6b651..6e4cf51a2 100755 --- a/nuttx/arch/arm/src/sama5/chip/sam_dmac.h +++ b/nuttx/arch/arm/src/sama5/chip/sam_dmac.h @@ -507,11 +507,12 @@ # define DMAC_EBC_DICERR4 (1 << (DMAC_EBC_DICERR_SHIFT+4)) # define DMAC_EBC_DICERR5 (1 << (DMAC_EBC_DICERR_SHIFT+5)) # define DMAC_EBC_DICERR6 (1 << (DMAC_EBC_DICERR_SHIFT+6)) -# define DMAC_EBC_DICERR7 (1 << (DMAC_EBC_DICERR_SHIFT+7)) +# define DMAC_EBC_DICERR7 (1 << (DMAC_EBC_DICERR_SHIFT+7)) -#define DMAC_EBC_BTCINTS(n) (0x01010001 << (n)) /* BTC + ERR interrupts */ -#define DMAC_EBC_CBTCINTS(n) (0x01010100 << (n)) /* CBT + ERR interrupts */ -#define DMAC_EBC_CHANINTS(n) (0x01010101 << (n)) /* All channel interrupts */ +#define DMAC_EBC_BTCINTS(n) (0x00010001 << (n)) /* BTC+ERR interrupts */ +#define DMAC_EBC_CBTCINTS(n) (0x00010100 << (n)) /* CBT+ERR interrupts */ +#define DMAC_EBC_CHANINTS(n) (0x00010101 << (n)) /* BTC+CBT+ERR interrupts */ +#define DMAC_EBC_ALLCHANINTS(n) (0x01010101 << (n)) /* All channel interrupts */ #define DMAC_EBC_ALLINTS (0xffffffff) /* All interrupts */ /* DMAC Channel Handler Enable Register */ diff --git a/nuttx/arch/arm/src/sama5/sam_dmac.c b/nuttx/arch/arm/src/sama5/sam_dmac.c index 90b6fee6f..e595afde5 100644 --- a/nuttx/arch/arm/src/sama5/sam_dmac.c +++ b/nuttx/arch/arm/src/sama5/sam_dmac.c @@ -759,11 +759,13 @@ static inline uint32_t sam_txcfg(struct sam_dmach_s *dmach) /* Set transfer (memory to peripheral) DMA channel configuration register */ + regval = DMAC_CH_CFG_SOD; + pid = (dmach->flags & DMACH_FLAG_MEMPID_MASK) >> DMACH_FLAG_MEMPID_SHIFT; isperiph = ((dmach->flags & DMACH_FLAG_MEMISPERIPH) != 0); pchan = sam_source_channel(dmach, pid, isperiph); - regval = ((pchan & 0x0f) << DMAC_CH_CFG_SRCPER_SHIFT); + regval |= ((pchan & 0x0f) << DMAC_CH_CFG_SRCPER_SHIFT); regval |= ((pchan & 0x30) << (DMAC_CH_CFG_SRCPERMSB_SHIFT-4)); regval |= (dmach->flags & DMACH_FLAG_MEMH2SEL) != 0 ? DMAC_CH_CFG_SRCH2SEL : 0; @@ -797,11 +799,13 @@ static inline uint32_t sam_rxcfg(struct sam_dmach_s *dmach) /* Set received (peripheral to memory) DMA channel config */ + regval = DMAC_CH_CFG_SOD; + pid = (dmach->flags & DMACH_FLAG_PERIPHPID_MASK) >> DMACH_FLAG_PERIPHPID_SHIFT; isperiph = ((dmach->flags & DMACH_FLAG_PERIPHISPERIPH) != 0); pchan = sam_source_channel(dmach, pid, isperiph); - regval = ((pchan & 0x0f) << DMAC_CH_CFG_SRCPER_SHIFT); + regval |= ((pchan & 0x0f) << DMAC_CH_CFG_SRCPER_SHIFT); regval |= ((pchan & 0x30) << (DMAC_CH_CFG_SRCPERMSB_SHIFT-4)); regval |= (dmach->flags & DMACH_FLAG_PERIPHH2SEL) != 0 ? DMAC_CH_CFG_SRCH2SEL : 0; @@ -1167,7 +1171,7 @@ static inline uint32_t sam_txctrlb(struct sam_dmach_s *dmach) * and destination descriptors. The default will be single transfer mode. */ - regval = DMAC_CH_CTRLB_BOTHDSCR; + regval = DMAC_CH_CTRLB_BOTHDSCR | DMAC_CH_CTRLB_IEN; /* Select flow control (even if the channel doesn't support it). The * naming convention from TX is memory to peripheral, but that is really @@ -1258,7 +1262,7 @@ static inline uint32_t sam_rxctrlb(struct sam_dmach_s *dmach) * and destination descriptors. The default will be single transfer mode. */ - regval = DMAC_CH_CTRLB_BOTHDSCR; + regval = DMAC_CH_CTRLB_BOTHDSCR | DMAC_CH_CTRLB_IEN; /* Select flow control (even if the channel doesn't support it). The * naming convention from RX is peripheral to memory, but that is really @@ -1605,6 +1609,10 @@ static inline int sam_single(struct sam_dmach_s *dmach) sam_putdmach(dmach, llhead->daddr, SAM_DMAC_CH_DADDR_OFFSET); + /* Clear the next descriptor address */ + + sam_putdmach(dmach, 0, SAM_DMAC_CH_DSCR_OFFSET); + /* Set up the CTRLA register */ sam_putdmach(dmach, llhead->ctrla, SAM_DMAC_CH_CTRLA_OFFSET); @@ -1628,7 +1636,7 @@ static inline int sam_single(struct sam_dmach_s *dmach) /* The DMA has been started. Once the transfer completes, hardware sets * the interrupts and disables the channel. We will received buffer - * complete and* transfer complete interrupts. + * complete and transfer complete interrupts. * * Enable error, buffer complete and transfer complete interrupts. * (Since there is only a single buffer, we don't need the buffer diff --git a/nuttx/arch/arm/src/sama5/sam_hsmci.c b/nuttx/arch/arm/src/sama5/sam_hsmci.c index 42558048a..7d5fe09e5 100644 --- a/nuttx/arch/arm/src/sama5/sam_hsmci.c +++ b/nuttx/arch/arm/src/sama5/sam_hsmci.c @@ -420,7 +420,7 @@ static void sam_cmddump(struct sam_dev_s *priv); /* DMA Helpers **************************************************************/ static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result); -static uint32_t sam_pfifo(struct sam_dev_s *priv); +static uint32_t sam_dmaregister(struct sam_dev_s *priv, unsigned int offset); /* Data Transfer Helpers ****************************************************/ @@ -1074,21 +1074,21 @@ static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result) } /**************************************************************************** - * Name: sam_pfifo + * Name: sam_dmaregister * * Description: - * Return the physical address of a FIFO + * Return the physical address of an HSMCI register * ****************************************************************************/ -static uint32_t sam_pfifo(struct sam_dev_s *priv) +static uint32_t sam_dmaregister(struct sam_dev_s *priv, unsigned int offset) { /* Get the offset into the 1MB section containing the HSMCI registers */ uint32_t pbase = priv->base & 0xfff00000; #ifdef CONFIG_HSMCI_HSMCI0 - /* Add in the physcal base for HSMCI0 + /* Add in the physical base for HSMCI0 * * We only have to check if this is HSMCI0 if either HSMCI1 or HSMCI2 are * enabled. @@ -1106,7 +1106,7 @@ static uint32_t sam_pfifo(struct sam_dev_s *priv) #endif #ifdef CONFIG_HSMCI_HSMCI1 - /* Add in the physcal base for HSMCI1 + /* Add in the physical base for HSMCI1 * * We only have to check if this is HSCMCi1 if HSMCI2 is enabled. */ @@ -1122,7 +1122,7 @@ static uint32_t sam_pfifo(struct sam_dev_s *priv) #endif #endif - /* Add in the physcal base for HSMCI2. + /* Add in the physical base for HSMCI2. * * If we get here, we con't have to check. */ @@ -1133,7 +1133,7 @@ static uint32_t sam_pfifo(struct sam_dev_s *priv) } #endif - return pbase + SAM_HSMCI_FIFO_OFFSET; + return pbase + offset; } /**************************************************************************** @@ -2505,10 +2505,15 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, size_t buflen) { struct sam_dev_s *priv = (struct sam_dev_s *)dev; + uint32_t rdr; DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); DEBUGASSERT(((uint32_t)buffer & 3) == 0); + /* Physical address of the HSCMI RDR registr */ + + rdr = sam_dmaregister(priv, SAM_HSMCI_RDR_OFFSET); + /* Setup register sampling */ sam_xfrsampleinit(priv); @@ -2517,7 +2522,7 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, /* Configure the RX DMA */ sam_enablexfrints(priv, HSMCI_DMARECV_INTS); - sam_dmarxsetup(priv->dma, sam_pfifo(priv), (uint32_t)buffer, buflen); + sam_dmarxsetup(priv->dma, rdr, (uint32_t)buffer, buflen); /* Enable DMA handshaking */ @@ -2554,10 +2559,15 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, size_t buflen) { struct sam_dev_s *priv = (struct sam_dev_s *)dev; + uint32_t tdr; DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); DEBUGASSERT(((uint32_t)buffer & 3) == 0); + /* Physical address of the HSCMI TDR registr */ + + tdr = sam_dmaregister(priv, SAM_HSMCI_TDR_OFFSET); + /* Setup register sampling */ sam_xfrsampleinit(priv); @@ -2565,7 +2575,7 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev, /* Configure the TX DMA */ - sam_dmatxsetup(priv->dma, sam_pfifo(priv), (uint32_t)buffer, buflen); + sam_dmatxsetup(priv->dma, tdr, (uint32_t)buffer, buflen); /* Enable DMA handshaking */ -- cgit v1.2.3