SAM3,4,A5 DMAC driver fixes
This commit is contained in:
parent
03f24c7a1d
commit
d1da100cf0
@ -902,6 +902,7 @@ static int sam_rxbuffer(struct sam_dma_s *dmach, uint32_t paddr,
|
|||||||
regval = sam_rxctrlabits(dmach);
|
regval = sam_rxctrlabits(dmach);
|
||||||
ctrlb = sam_rxctrlb(dmach);
|
ctrlb = sam_rxctrlb(dmach);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrla = sam_rxctrla(dmach, regval, nbytes);
|
ctrla = sam_rxctrla(dmach, regval, nbytes);
|
||||||
|
|
||||||
/* Add the new link list entry */
|
/* Add the new link list entry */
|
||||||
@ -1158,6 +1159,8 @@ static int sam_dmainterrupt(int irq, void *context)
|
|||||||
|
|
||||||
void weak_function up_dmainitialize(void)
|
void weak_function up_dmainitialize(void)
|
||||||
{
|
{
|
||||||
|
dmallvdbg("Iinitialize DMAC0\n");
|
||||||
|
|
||||||
/* Enable peripheral clock */
|
/* Enable peripheral clock */
|
||||||
|
|
||||||
sam_dmac_enableclk();
|
sam_dmac_enableclk();
|
||||||
@ -1224,6 +1227,7 @@ DMA_HANDLE sam_dmachannel(uint32_t dmach_flags)
|
|||||||
|
|
||||||
dmach = NULL;
|
dmach = NULL;
|
||||||
sam_takechsem();
|
sam_takechsem();
|
||||||
|
|
||||||
for (chndx = 0; chndx < SAM34_NDMACHAN; chndx++)
|
for (chndx = 0; chndx < SAM34_NDMACHAN; chndx++)
|
||||||
{
|
{
|
||||||
struct sam_dma_s *candidate = &g_dma[chndx];
|
struct sam_dma_s *candidate = &g_dma[chndx];
|
||||||
@ -1256,7 +1260,10 @@ DMA_HANDLE sam_dmachannel(uint32_t dmach_flags)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sam_givechsem();
|
sam_givechsem();
|
||||||
|
|
||||||
|
dmavdbg("dmach_flags: %08x returning dmach: %p\n", (int)dmach_flags, dmach);
|
||||||
return (DMA_HANDLE)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;
|
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
|
/* Mark the channel no longer in use. Clearing the inuse flag is an atomic
|
||||||
* operation and so should be safe.
|
* operation and so should be safe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT((dmach != NULL) && (dmach->inuse));
|
|
||||||
dmach->flags &= (DMACH_FLAG_FLOWCONTROL | DMACH_FLAG_FIFOSIZE_MASK);
|
dmach->flags &= (DMACH_FLAG_FLOWCONTROL | DMACH_FLAG_FIFOSIZE_MASK);
|
||||||
dmach->inuse = false; /* No longer in use */
|
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;
|
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
|
||||||
int ret = OK;
|
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 */
|
/* 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);
|
ret = sam_txbuffer(dmach, paddr, maddr, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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;
|
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
|
||||||
int ret = OK;
|
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 */
|
/* 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);
|
ret = sam_rxbuffer(dmach, paddr, maddr, nbytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
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;
|
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
|
||||||
int ret = -EINVAL;
|
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
|
/* Verify that the DMA has been setup (i.e., at least one entry in the
|
||||||
* link list).
|
* link list).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(dmach != NULL);
|
|
||||||
if (dmach->llhead)
|
if (dmach->llhead)
|
||||||
{
|
{
|
||||||
/* Save the callback info. This will be invoked whent the DMA commpletes */
|
/* 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;
|
struct sam_dma_s *dmach = (struct sam_dma_s *)handle;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
|
dmavdbg("dmach: %p\n", dmach);
|
||||||
DEBUGASSERT(dmach != NULL);
|
DEBUGASSERT(dmach != NULL);
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
sam_dmaterminate(dmach, -EINTR);
|
sam_dmaterminate(dmach, -EINTR);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
@ -1157,6 +1157,7 @@ static int sam_rxbuffer(struct sam_dmach_s *dmach, uint32_t paddr,
|
|||||||
regval = sam_rxctrlabits(dmach);
|
regval = sam_rxctrlabits(dmach);
|
||||||
ctrlb = sam_rxctrlb(dmach);
|
ctrlb = sam_rxctrlb(dmach);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctrla = sam_rxctrla(dmach, regval, nbytes);
|
ctrla = sam_rxctrla(dmach, regval, nbytes);
|
||||||
|
|
||||||
/* Add the new link list entry */
|
/* Add the new link list entry */
|
||||||
@ -1479,6 +1480,8 @@ void sam_dmainitialize(struct sam_dmac_s *dmac)
|
|||||||
void weak_function up_dmainitialize(void)
|
void weak_function up_dmainitialize(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SAMA5_DMAC0
|
#ifdef CONFIG_SAMA5_DMAC0
|
||||||
|
dmallvdbg("Iinitialize DMAC0\n");
|
||||||
|
|
||||||
/* Enable peripheral clock */
|
/* Enable peripheral clock */
|
||||||
|
|
||||||
sam_dmac0_enableclk();
|
sam_dmac0_enableclk();
|
||||||
@ -1497,6 +1500,8 @@ void weak_function up_dmainitialize(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SAMA5_DMAC1
|
#ifdef CONFIG_SAMA5_DMAC1
|
||||||
|
dmallvdbg("Iinitialize DMAC1\n");
|
||||||
|
|
||||||
/* Enable peripheral clock */
|
/* Enable peripheral clock */
|
||||||
|
|
||||||
sam_dmac1_enableclk();
|
sam_dmac1_enableclk();
|
||||||
@ -1560,7 +1565,7 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
fdbg("Bad DMAC number: %d\n", dmacno);
|
dmadbg("Bad DMAC number: %d\n", dmacno);
|
||||||
DEBUGPANIC();
|
DEBUGPANIC();
|
||||||
return (DMA_HANDLE)NULL;
|
return (DMA_HANDLE)NULL;
|
||||||
}
|
}
|
||||||
@ -1599,6 +1604,9 @@ DMA_HANDLE sam_dmachannel(uint8_t dmacno, uint32_t chflags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sam_givechsem(dmac);
|
sam_givechsem(dmac);
|
||||||
|
|
||||||
|
dmavdbg("dmacno: %d chflags: %08x returning dmach: %p\n",
|
||||||
|
(int)dmacno, (int)chflags, dmach);
|
||||||
return (DMA_HANDLE)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;
|
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
|
/* Mark the channel no longer in use. Clearing the inuse flag is an atomic
|
||||||
* operation and so should be safe.
|
* operation and so should be safe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT((dmach != NULL) && (dmach->inuse));
|
|
||||||
dmach->flags = 0;
|
dmach->flags = 0;
|
||||||
dmach->inuse = false; /* No longer in use */
|
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;
|
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
|
||||||
int ret = OK;
|
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 */
|
/* 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;
|
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
|
||||||
int ret = OK;
|
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 */
|
/* 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;
|
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
|
||||||
int ret = -EINVAL;
|
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
|
/* Verify that the DMA has been setup (i.e., at least one entry in the
|
||||||
* link list).
|
* link list).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(dmach != NULL);
|
|
||||||
if (dmach->llhead)
|
if (dmach->llhead)
|
||||||
{
|
{
|
||||||
/* Save the callback info. This will be invoked whent the DMA commpletes */
|
/* 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;
|
struct sam_dmach_s *dmach = (struct sam_dmach_s *)handle;
|
||||||
irqstate_t flags;
|
irqstate_t flags;
|
||||||
|
|
||||||
|
dmavdbg("dmach: %p\n", dmach);
|
||||||
DEBUGASSERT(dmach != NULL);
|
DEBUGASSERT(dmach != NULL);
|
||||||
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
sam_dmaterminate(dmach, -EINTR);
|
sam_dmaterminate(dmach, -EINTR);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
|
@ -736,7 +736,7 @@ static void sam_disablewaitints(struct sam_dev_s *priv,
|
|||||||
priv->waitevents = 0;
|
priv->waitevents = 0;
|
||||||
priv->wkupevent = wkupevent;
|
priv->wkupevent = wkupevent;
|
||||||
priv->waitmask = 0;
|
priv->waitmask = 0;
|
||||||
putreg32(~priv->xfrmask, SAM_HSMCI_IDR_OFFSET);
|
sam_putreg(priv, ~priv->xfrmask, SAM_HSMCI_IDR_OFFSET);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,7 +782,7 @@ static void sam_disablexfrints(struct sam_dev_s *priv)
|
|||||||
{
|
{
|
||||||
irqstate_t flags = irqsave();
|
irqstate_t flags = irqsave();
|
||||||
priv->xfrmask = 0;
|
priv->xfrmask = 0;
|
||||||
putreg32(~priv->waitmask, SAM_HSMCI_IDR_OFFSET);
|
sam_putreg(priv, ~priv->waitmask, SAM_HSMCI_IDR_OFFSET);
|
||||||
irqrestore(flags);
|
irqrestore(flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user