SAMA5 DMA: Need to flush caches; DMA channel depends upon direction of DMA; the maximum transfer size in bytes depends on the number of bytes per transfer

This commit is contained in:
Gregory Nutt
2013-08-08 13:15:52 -06:00
parent 9d81d4727c
commit 83cbd61c8c
4 changed files with 498 additions and 92 deletions
+40 -12
View File
@@ -424,7 +424,7 @@ static inline uint32_t sam_txctrla(struct sam_dma_s *dmach,
if ((dmach->flags & DMACH_FLAG_MEMCHUNKSIZE) == DMACH_FLAG_MEMCHUNKSIZE_4)
{
dmasize >>= 2;
dmasize = (dmasize + 3) >> 2;
}
DEBUGASSERT(dmasize <= DMACHAN_CTRLA_BTSIZE_MAX);
@@ -516,7 +516,7 @@ static inline uint32_t sam_rxctrla(struct sam_dma_s *dmach,
if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) == DMACH_FLAG_PERIPHCHUNKSIZE_4)
{
dmasize >>= 2;
dmasize = (dmasize + 3) >> 2;
}
DEBUGASSERT(dmasize <= DMACHAN_CTRLA_BTSIZE_MAX);
@@ -1311,6 +1311,7 @@ void sam_dmafree(DMA_HANDLE handle)
int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nbytes)
{
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
size_t maxtransfer;
int ret = OK;
dmavdbg("dmach: %p paddr: %08x maddr: %08x nbytes: %d\n",
@@ -1318,18 +1319,31 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
DEBUGASSERT(dmach);
dmavdbg("llhead: %p lltail: %p\n", dmach->llhead, dmach->lltail);
/* The maximum transfer size in bytes depends upon the maximum number of
* transfers and the number of bytes per transfer.
*/
if ((dmach->flags & DMACH_FLAG_MEMCHUNKSIZE) == DMACH_FLAG_MEMCHUNKSIZE_4)
{
maxtransfer = 4 * DMACHAN_CTRLA_BTSIZE_MAX;
}
else
{
maxtransfer = DMACHAN_CTRLA_BTSIZE_MAX;
}
/* If this is a large transfer, break it up into smaller buffers */
while (nbytes > DMACHAN_CTRLA_BTSIZE_MAX)
while (nbytes > maxtransfer)
{
/* Set up the maximum size transfer */
ret = sam_txbuffer(dmach, paddr, maddr, DMACHAN_CTRLA_BTSIZE_MAX);
ret = sam_txbuffer(dmach, paddr, maddr, maxtransfer);
if (ret == OK);
{
/* Decrement the number of bytes left to transfer */
nbytes -= DMACHAN_CTRLA_BTSIZE_MAX;
nbytes -= maxtransfer;
/* Increment the memory & peripheral address (if it is appropriate to
* do do).
@@ -1337,12 +1351,12 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
if ((dmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
{
paddr += DMACHAN_CTRLA_BTSIZE_MAX;
paddr += maxtransfer;
}
if ((dmach->flags & DMACH_FLAG_MEMINCREMENT) != 0)
{
maddr += DMACHAN_CTRLA_BTSIZE_MAX;
maddr += maxtransfer;
}
}
}
@@ -1371,6 +1385,7 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nbytes)
{
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
size_t maxtransfer;
int ret = OK;
dmavdbg("dmach: %p paddr: %08x maddr: %08x nbytes: %d\n",
@@ -1378,18 +1393,31 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
DEBUGASSERT(dmach);
dmavdbg("llhead: %p lltail: %p\n", dmach->llhead, dmach->lltail);
/* The maximum transfer size in bytes depends upon the maximum number of
* transfers and the number of bytes per transfer.
*/
if ((dmach->flags & DMACH_FLAG_PERIPHCHUNKSIZE) == DMACH_FLAG_PERIPHCHUNKSIZE_4)
{
maxtransfer = 4 * DMACHAN_CTRLA_BTSIZE_MAX;
}
else
{
maxtransfer = DMACHAN_CTRLA_BTSIZE_MAX;
}
/* If this is a large transfer, break it up into smaller buffers */
while (nbytes > DMACHAN_CTRLA_BTSIZE_MAX)
while (nbytes > maxtransfer)
{
/* Set up the maximum size transfer */
ret = sam_rxbuffer(dmach, paddr, maddr, DMACHAN_CTRLA_BTSIZE_MAX);
ret = sam_rxbuffer(dmach, paddr, maddr, maxtransfer);
if (ret == OK);
{
/* Decrement the number of bytes left to transfer */
nbytes -= DMACHAN_CTRLA_BTSIZE_MAX;
nbytes -= maxtransfer;
/* Increment the memory & peripheral address (if it is appropriate to
* do do).
@@ -1397,12 +1425,12 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
if ((dmach->flags & DMACH_FLAG_PERIPHINCREMENT) != 0)
{
paddr += DMACHAN_CTRLA_BTSIZE_MAX;
paddr += maxtransfer;
}
if ((dmach->flags & DMACH_FLAG_MEMINCREMENT) != 0)
{
maddr += DMACHAN_CTRLA_BTSIZE_MAX;
maddr += maxtransfer;
}
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -104,7 +104,7 @@
/* Memory endpoint characteristics */
#define DMACH_FLAG_MEMPID_SHIFT (17) /* Bits 17-22: Memory PID */
#define DMACH_FLAG_MEMPID_MASK (63 << DMACH_FLAG_PERIPHPID_SHIFT)
#define DMACH_FLAG_MEMPID_MASK (63 << DMACH_FLAG_MEMPID_SHIFT)
#define DMACH_FLAG_MEMH2SEL (1 << 23) /* Bits 23: HW handshaking */
#define DMACH_FLAG_MEMISPERIPH (1 << 24) /* Bits 24: 0=memory; 1=peripheral */
#define DMACH_FLAG_MEMAHB_SHIFT (25) /* Bits 25-26: Peripheral ABH layer number */
+6 -8
View File
@@ -175,7 +175,7 @@
( HSMCI_INT_CSTOE | HSMCI_INT_RTOE | HSMCI_INT_RENDE | HSMCI_INT_RDIRE | \
HSMCI_INT_RINDE )
#define HSMCI_RESPONSE_TIMEOUT_ERRORS \
( HSMCI_INT_CSTOE | HSMCI_INT_RTOE )
( HSMCI_INT_CSTOE | HSMCI_INT_RTOE )
/* Data transfer errors:
*
@@ -261,7 +261,6 @@
/****************************************************************************
* Private Types
****************************************************************************/
/* Register logging support */
#if defined(CONFIG_SAMA5_HSMCI_XFRDEBUG) || defined(CONFIG_SAMA5_HSMCI_CMDDEBUG)
@@ -432,7 +431,7 @@ static void sam_notransfer(struct sam_dev_s *priv);
/* Interrupt Handling *******************************************************/
static int sam_hsmci_interrupt(struct sam_dev_s *priv);
static int sam_hsmci_interrupt(struct sam_dev_s *priv);
#ifdef CONFIG_SAMA5_HSMCI0
static int sam_hsmci0_interrupt(int irq, void *context);
#endif
@@ -497,7 +496,6 @@ static void sam_callback(void *arg);
/****************************************************************************
* Private Data
****************************************************************************/
/* Callbacks */
static const struct sdio_dev_s g_callbacks =
@@ -2733,7 +2731,7 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
/* For DMA channel selection */
dmac = 0;
pid = DMAC0_CH_HSMCI0;
pid = SAM_PID_HSMCI0;
}
else
#endif
@@ -2770,7 +2768,7 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
/* For DMA channel selection */
dmac = 1;
pid = DMAC1_CH_HSMCI1;
pid = SAM_PID_HSMCI1;
}
else
#endif
@@ -2807,7 +2805,7 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
/* For DMA channel selection */
dmac = 1;
pid = DMAC1_CH_HSMCI2;
pid = SAM_PID_HSMCI2;
}
else
#endif
@@ -2827,7 +2825,7 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno)
/* Initialize the callbacks */
memcpy(&priv->dev, &g_callbacks, sizeof(struct sdio_dev_s ));
memcpy(&priv->dev, &g_callbacks, sizeof(struct sdio_dev_s));
/* Allocate a DMA channel */