From d1da100cf01f38ab201132333048f80a9288c558 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 6 Aug 2013 13:27:48 -0600 Subject: [PATCH] SAM3,4,A5 DMAC driver fixes --- arch/arm/src/sam34/sam3u_dmac.c | 29 +++++++++++++++++++++++++---- arch/arm/src/sama5/sam_dmac.c | 33 +++++++++++++++++++++++++++------ arch/arm/src/sama5/sam_hsmci.c | 4 ++-- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/arch/arm/src/sam34/sam3u_dmac.c b/arch/arm/src/sam34/sam3u_dmac.c index 71ed102f30..3d9708cb70 100644 --- a/arch/arm/src/sam34/sam3u_dmac.c +++ b/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/arch/arm/src/sama5/sam_dmac.c b/arch/arm/src/sama5/sam_dmac.c index 27b23bfc3d..4495209c14 100644 --- a/arch/arm/src/sama5/sam_dmac.c +++ b/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/arch/arm/src/sama5/sam_hsmci.c b/arch/arm/src/sama5/sam_hsmci.c index f9bf9e3e11..482a7b0e4b 100644 --- a/arch/arm/src/sama5/sam_hsmci.c +++ b/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); }