SAM3,4,A5 DMAC driver fixes

This commit is contained in:
Gregory Nutt 2013-08-06 13:27:48 -06:00
parent 03f24c7a1d
commit d1da100cf0
3 changed files with 54 additions and 12 deletions

View File

@ -902,6 +902,7 @@ static int sam_rxbuffer(struct sam_dma_s *dmach, uint32_t paddr,
regval = sam_rxctrlabits(dmach);
ctrlb = sam_rxctrlb(dmach);
}
ctrla = sam_rxctrla(dmach, regval, nbytes);
/* Add the new link list entry */
@ -1158,6 +1159,8 @@ static int sam_dmainterrupt(int irq, void *context)
void weak_function up_dmainitialize(void)
{
dmallvdbg("Iinitialize DMAC0\n");
/* Enable peripheral clock */
sam_dmac_enableclk();
@ -1224,6 +1227,7 @@ DMA_HANDLE sam_dmachannel(uint32_t dmach_flags)
dmach = NULL;
sam_takechsem();
for (chndx = 0; chndx < SAM34_NDMACHAN; chndx++)
{
struct sam_dma_s *candidate = &g_dma[chndx];
@ -1256,7 +1260,10 @@ DMA_HANDLE sam_dmachannel(uint32_t dmach_flags)
break;
}
}
sam_givechsem();
dmavdbg("dmach_flags: %08x returning dmach: %p\n", (int)dmach_flags, dmach);
return (DMA_HANDLE)dmach;
}
@ -1277,11 +1284,13 @@ void sam_dmafree(DMA_HANDLE handle)
{
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
dmavdbg("dmach: %p\n", dmach);
DEBUGASSERT((dmach != NULL) && (dmach->inuse));
/* Mark the channel no longer in use. Clearing the inuse flag is an atomic
* operation and so should be safe.
*/
DEBUGASSERT((dmach != NULL) && (dmach->inuse));
dmach->flags &= (DMACH_FLAG_FLOWCONTROL | DMACH_FLAG_FIFOSIZE_MASK);
dmach->inuse = false; /* No longer in use */
}
@ -1302,7 +1311,10 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
int ret = OK;
DEBUGASSERT(dmach && dmach->llhead != NULL && dmach->lltail != 0);
dmavdbg("dmach: %p paddr: %08x maddr: %08x nbytes: %d\n",
dmach, (int)paddr, (int)maddr, (int)nbytes);
DEBUGASSERT(dmach);
dmavdbg("llhead: %p lltail: %p\n", dmach->llhead, dmach->lltail);
/* If this is a large transfer, break it up into smaller buffers */
@ -1339,6 +1351,7 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
{
ret = sam_txbuffer(dmach, paddr, maddr, nbytes);
}
return ret;
}
@ -1358,7 +1371,10 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
int ret = OK;
DEBUGASSERT(dmach && dmach->llhead != NULL && dmach->lltail != 0);
dmavdbg("dmach: %p paddr: %08x maddr: %08x nbytes: %d\n",
dmach, (int)paddr, (int)maddr, (int)nbytes);
DEBUGASSERT(dmach);
dmavdbg("llhead: %p lltail: %p\n", dmach->llhead, dmach->lltail);
/* If this is a large transfer, break it up into smaller buffers */
@ -1395,6 +1411,7 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
{
ret = sam_rxbuffer(dmach, paddr, maddr, nbytes);
}
return ret;
}
@ -1411,11 +1428,13 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
int ret = -EINVAL;
dmavdbg("dmach: %p callback: %p arg: %p\n", dmach, callback, arg);
DEBUGASSERT(dmach != NULL);
/* Verify that the DMA has been setup (i.e., at least one entry in the
* link list).
*/
DEBUGASSERT(dmach != NULL);
if (dmach->llhead)
{
/* Save the callback info. This will be invoked whent the DMA commpletes */
@ -1452,7 +1471,9 @@ void sam_dmastop(DMA_HANDLE handle)
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
irqstate_t flags;
dmavdbg("dmach: %p\n", dmach);
DEBUGASSERT(dmach != NULL);
flags = irqsave();
sam_dmaterminate(dmach, -EINTR);
irqrestore(flags);

View File

@ -1157,6 +1157,7 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
regval = sam_rxctrlabits(dmach);
ctrlb = sam_rxctrlb(dmach);
}
ctrla = sam_rxctrla(dmach, regval, nbytes);
/* Add the new link list entry */
@ -1479,6 +1480,8 @@ void sam_dmainitialize(struct sam_dmac_s *dmac)
void weak_function up_dmainitialize(void)
{
#ifdef CONFIG_SAMA5_DMAC0
dmallvdbg("Iinitialize DMAC0\n");
/* Enable peripheral clock */
sam_dmac0_enableclk();
@ -1497,6 +1500,8 @@ void weak_function up_dmainitialize(void)
#endif
#ifdef CONFIG_SAMA5_DMAC1
dmallvdbg("Iinitialize DMAC1\n");
/* Enable peripheral clock */
sam_dmac1_enableclk();
@ -1560,7 +1565,7 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
#endif
{
fdbg("Bad DMAC number: %d\n", dmacno);
dmadbg("Bad DMAC number: %d\n", dmacno);
DEBUGPANIC();
return (DMA_HANDLE)NULL;
}
@ -1599,6 +1604,9 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
}
sam_givechsem(dmac);
dmavdbg("dmacno: %d chflags: %08x returning dmach: %p\n",
(int)dmacno, (int)chflags, dmach);
return (DMA_HANDLE)dmach;
}
@ -1619,11 +1627,13 @@ void sam_dmafree(DMA_HANDLE handle)
{
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
dmavdbg("dmach: %p\n", dmach);
DEBUGASSERT((dmach != NULL) && (dmach->inuse));
/* Mark the channel no longer in use. Clearing the inuse flag is an atomic
* operation and so should be safe.
*/
DEBUGASSERT((dmach != NULL) && (dmach->inuse));
dmach->flags = 0;
dmach->inuse = false; /* No longer in use */
}
@ -1644,7 +1654,10 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr, size_t nby
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
int ret = OK;
DEBUGASSERT(dmach && dmach->llhead != NULL && dmach->lltail != 0);
dmavdbg("dmach: %p paddr: %08x maddr: %08x nbytes: %d\n",
dmach, (int)paddr, (int)maddr, (int)nbytes);
DEBUGASSERT(dmach);
dmavdbg("llhead: %p lltail: %p\n", dmach->llhead, dmach->lltail);
/* If this is a large transfer, break it up into smaller buffers */
@ -1696,12 +1709,16 @@ 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)
int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
size_t nbytes)
{
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
int ret = OK;
DEBUGASSERT(dmach && dmach->llhead != NULL && dmach->lltail != 0);
dmavdbg("dmach: %p paddr: %08x maddr: %08x nbytes: %d\n",
dmach, (int)paddr, (int)maddr, (int)nbytes);
DEBUGASSERT(dmach);
dmavdbg("llhead: %p lltail: %p\n", dmach->llhead, dmach->lltail);
/* If this is a large transfer, break it up into smaller buffers */
@ -1755,11 +1772,13 @@ int sam_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
int ret = -EINVAL;
dmavdbg("dmach: %p callback: %p arg: %p\n", dmach, callback, arg);
DEBUGASSERT(dmach != NULL);
/* Verify that the DMA has been setup (i.e., at least one entry in the
* link list).
*/
DEBUGASSERT(dmach != NULL);
if (dmach->llhead)
{
/* Save the callback info. This will be invoked whent the DMA commpletes */
@ -1797,7 +1816,9 @@ void sam_dmastop(DMA_HANDLE handle)
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
irqstate_t flags;
dmavdbg("dmach: %p\n", dmach);
DEBUGASSERT(dmach != NULL);
flags = irqsave();
sam_dmaterminate(dmach, -EINTR);
irqrestore(flags);

View File

@ -736,7 +736,7 @@ static void sam_disablewaitints(struct sam_dev_s *priv,
priv->waitevents = 0;
priv->wkupevent = wkupevent;
priv->waitmask = 0;
putreg32(~priv->xfrmask, SAM_HSMCI_IDR_OFFSET);
sam_putreg(priv, ~priv->xfrmask, SAM_HSMCI_IDR_OFFSET);
irqrestore(flags);
}
@ -782,7 +782,7 @@ static void sam_disablexfrints(struct sam_dev_s *priv)
{
irqstate_t flags = irqsave();
priv->xfrmask = 0;
putreg32(~priv->waitmask, SAM_HSMCI_IDR_OFFSET);
sam_putreg(priv, ~priv->waitmask, SAM_HSMCI_IDR_OFFSET);
irqrestore(flags);
}