summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-08-06 13:27:48 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-08-06 13:27:48 -0600
commit8b15e9a5eddd764f9eaefd87aa6fcc2c5bf843d5 (patch)
tree146e1f37ca32def1d83e8f5a1e28e3161b44a750
parentd337863e6e7c89fac3891c5a63b09720f07c6aea (diff)
downloadnuttx-8b15e9a5eddd764f9eaefd87aa6fcc2c5bf843d5.tar.gz
nuttx-8b15e9a5eddd764f9eaefd87aa6fcc2c5bf843d5.tar.bz2
nuttx-8b15e9a5eddd764f9eaefd87aa6fcc2c5bf843d5.zip
SAM3,4,A5 DMAC driver fixes
-rw-r--r--nuttx/ChangeLog5
-rw-r--r--nuttx/arch/arm/src/sam34/sam3u_dmac.c29
-rw-r--r--nuttx/arch/arm/src/sama5/sam_dmac.c33
-rw-r--r--nuttx/arch/arm/src/sama5/sam_hsmci.c4
4 files changed, 58 insertions, 13 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index e297eee09..af29cb919 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5319,4 +5319,7 @@
* arch/arm/src/sam34/sam_hsmci.c and sama5/sam_hsmci.c: Fix handling
of some masked status conditions that can cause false-alarm errors
(2013-8-6).
-
+ * arch/arm/src/sama5/sam_dmac.c and sam34/sam34_dmac.c: For SAMA5,
+ correct some bad register address and some bad assertions that caused
+ false alarms. These latter were backported to the SAM34 DMAC driver
+ as well (2013-8-6).
diff --git a/nuttx/arch/arm/src/sam34/sam3u_dmac.c b/nuttx/arch/arm/src/sam34/sam3u_dmac.c
index 71ed102f3..3d9708cb7 100644
--- a/nuttx/arch/arm/src/sam34/sam3u_dmac.c
+++ b/nuttx/arch/arm/src/sam34/sam3u_dmac.c
@@ -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);
diff --git a/nuttx/arch/arm/src/sama5/sam_dmac.c b/nuttx/arch/arm/src/sama5/sam_dmac.c
index 27b23bfc3..4495209c1 100644
--- a/nuttx/arch/arm/src/sama5/sam_dmac.c
+++ b/nuttx/arch/arm/src/sama5/sam_dmac.c
@@ -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);
diff --git a/nuttx/arch/arm/src/sama5/sam_hsmci.c b/nuttx/arch/arm/src/sama5/sam_hsmci.c
index f9bf9e3e1..482a7b0e4 100644
--- a/nuttx/arch/arm/src/sama5/sam_hsmci.c
+++ b/nuttx/arch/arm/src/sama5/sam_hsmci.c
@@ -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);
}