SAMA5: Use RDR/TDR registers for DMA, not FIFO registers; change DMA bit settings to match Atmel example. Still no DMA

This commit is contained in:
Gregory Nutt 2013-08-08 15:51:16 -06:00
parent 53c4a1e647
commit 2b36e7e266
5 changed files with 48 additions and 23 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */