From 5eadd8df7a68e072456b821f32597482b0632217 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 21 Apr 2014 17:18:30 -0600 Subject: [PATCH] SAM3/4: Support for PDC based HSMCI ADMA from Bob Doiron --- arch/arm/src/sam34/chip/sam_hsmci.h | 14 ++ arch/arm/src/sam34/sam_hsmci.c | 323 +++++++++++++++++++--------- 2 files changed, 236 insertions(+), 101 deletions(-) diff --git a/arch/arm/src/sam34/chip/sam_hsmci.h b/arch/arm/src/sam34/chip/sam_hsmci.h index ad71f8fe49..fa3b375b7a 100644 --- a/arch/arm/src/sam34/chip/sam_hsmci.h +++ b/arch/arm/src/sam34/chip/sam_hsmci.h @@ -43,6 +43,7 @@ #include #include "chip.h" +#include "chip/sam_pdc.h" #include "chip/sam_memorymap.h" /**************************************************************************************** @@ -113,6 +114,19 @@ #define SAM_HSMCI_WPSR (SAM_HSMCI_BASE+SAM_HSMCI_WPSR_OFFSET) #define SAM_HSMCI_FIFO (SAM_HSMCI_BASE+SAM_HSMCI_FIFO_OFFSET) +#if (defined(CONFIG_ARCH_CHIP_SAM4S) && defined(CONFIG_SAM34_PDCA)) +# define SAM_HSMCI_PDC_RPR (SAM_HSMCI_BASE+SAM_PDC_RPR_OFFSET) +# define SAM_HSMCI_PDC_RCR (SAM_HSMCI_BASE+SAM_PDC_RCR_OFFSET) +# define SAM_HSMCI_PDC_TPR (SAM_HSMCI_BASE+SAM_PDC_TPR_OFFSET) +# define SAM_HSMCI_PDC_TCR (SAM_HSMCI_BASE+SAM_PDC_TCR_OFFSET) +# define SAM_HSMCI_PDC_RNPR (SAM_HSMCI_BASE+SAM_PDC_RNPR_OFFSET) +# define SAM_HSMCI_PDC_RNCR (SAM_HSMCI_BASE+SAM_PDC_RNCR_OFFSET) +# define SAM_HSMCI_PDC_TNPR (SAM_HSMCI_BASE+SAM_PDC_TNPR_OFFSET) +# define SAM_HSMCI_PDC_TNCR (SAM_HSMCI_BASE+SAM_PDC_TNCR_OFFSET) +# define SAM_HSMCI_PDC_PTCR (SAM_HSMCI_BASE+SAM_PDC_PTCR_OFFSET) +# define SAM_HSMCI_PDC_PTSR (SAM_HSMCI_BASE+SAM_PDC_PTSR_OFFSET) +#endif + /* HSMCI register bit definitions *******************************************************/ /* HSMCI Control Register */ diff --git a/arch/arm/src/sam34/sam_hsmci.c b/arch/arm/src/sam34/sam_hsmci.c index 488ccdc955..728bc0e04f 100644 --- a/arch/arm/src/sam34/sam_hsmci.c +++ b/arch/arm/src/sam34/sam_hsmci.c @@ -61,15 +61,25 @@ #include "up_arch.h" #include "sam_gpio.h" -#include "sam_dmac.h" #include "sam_cmcc.h" #include "sam_hsmci.h" #include "sam_periphclks.h" -#include "chip/sam_dmac.h" + +#ifdef CONFIG_SAM34_DMAC +# include "sam_dmac.h" +#endif + #include "chip/sam_pmc.h" #include "chip/sam_hsmci.h" #include "chip/sam_pinmap.h" +#ifdef CONFIG_SAM34_DMAC +# include "chip/sam_dmac.h" +#endif +#ifdef CONFIG_SAM34_PDCA +# include "chip/sam_pdc.h" +#endif + #if CONFIG_SAM34_HSMCI /**************************************************************************** @@ -78,8 +88,8 @@ /* Configuration ************************************************************/ -#ifndef CONFIG_SAM34_DMAC0 -# warning "HSMCI driver requires CONFIG_SAM34_DMAC0" +#if !(defined(CONFIG_SAM34_DMAC0) || defined(CONFIG_SAM34_PDCA)) +# warning "HSMCI driver requires CONFIG_SAM34_DMAC0 or CONFIG_SAM34_PDCA" #endif #ifndef CONFIG_SCHED_WORKQUEUE @@ -122,6 +132,7 @@ #define HSMCI_DTIMER_DATATIMEOUT (0x000fffff) +#ifdef CONFIG_SAM34_DMAC0 /* DMA configuration flags */ #define DMA_FLAGS \ @@ -131,6 +142,7 @@ DMACH_FLAG_PERIPHWIDTH_32BITS | DMACH_FLAG_PERIPHCHUNKSIZE_1 | \ DMACH_FLAG_MEMWIDTH_32BITS | DMACH_FLAG_MEMINCREMENT | \ DMACH_FLAG_MEMCHUNKSIZE_4) +#endif /* Status errors: * @@ -147,11 +159,6 @@ * HSMCI_INT_RINDE Response Index Error */ -#define HSMCI_STATUS_ERRORS \ - (HSMCI_INT_UNRE | HSMCI_INT_OVRE | HSMCI_INT_BLKOVRE | HSMCI_INT_CSTOE | \ - HSMCI_INT_DTOE | HSMCI_INT_DCRCE | HSMCI_INT_RTOE | HSMCI_INT_RENDE | \ - HSMCI_INT_RCRCE | HSMCI_INT_RDIRE | HSMCI_INT_RINDE) - /* Response errors: * * HSMCI_INT_CSTOE Completion signal time-out error (see HSMCI_CSTOR) @@ -183,30 +190,43 @@ * HSMCI_INT_DCRCE Data CRC Error */ -#if defined(CONFIG_ARCH_CHIP_SAM3U) -# define HSMCI_DATA_ERRORS \ - (HSMCI_INT_UNRE | HSMCI_INT_OVRE | HSMCI_INT_BLKOVRE | HSMCI_INT_CSTOE | \ - HSMCI_INT_DTOE | HSMCI_INT_DCRCE) +#ifdef CONFIG_SAM34_DMAC0 +# if defined(CONFIG_ARCH_CHIP_SAM3U) +# define HSMCI_DATA_ERRORS \ + (HSMCI_INT_UNRE | HSMCI_INT_OVRE | HSMCI_INT_BLKOVRE | HSMCI_INT_CSTOE | \ + HSMCI_INT_DTOE | HSMCI_INT_DCRCE) +# else +# define HSMCI_DATA_ERRORS \ + (HSMCI_INT_UNRE | HSMCI_INT_OVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | \ + HSMCI_INT_DCRCE) +# endif #else -# define HSMCI_DATA_ERRORS \ - (HSMCI_INT_UNRE | HSMCI_INT_OVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | \ - HSMCI_INT_DCRCE) + #define HSMCI_DATA_ERRORS \ + (HSMCI_INT_UNRE | HSMCI_INT_OVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | \ + HSMCI_INT_DCRCE) #endif #define HSMCI_DATA_TIMEOUT_ERRORS \ (HSMCI_INT_CSTOE | HSMCI_INT_DTOE) -#if defined(CONFIG_ARCH_CHIP_SAM3U) +#ifdef CONFIG_SAM34_DMAC0 +# if defined(CONFIG_ARCH_CHIP_SAM3U) +# define HSMCI_DATA_DMARECV_ERRORS \ + (HSMCI_INT_OVRE | HSMCI_INT_BLKOVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | \ + HSMCI_INT_DCRCE) +# else +# define HSMCI_DATA_DMARECV_ERRORS \ + (HSMCI_INT_OVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | HSMCI_INT_DCRCE) +# endif +#endif + +#ifdef CONFIG_SAM34_PDCA # define HSMCI_DATA_DMARECV_ERRORS \ - (HSMCI_INT_OVRE | HSMCI_INT_BLKOVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | \ - HSMCI_INT_DCRCE) -#else -# define HSMCI_DATA_DMARECV_ERRORS \ - (HSMCI_INT_OVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | HSMCI_INT_DCRCE) + (HSMCI_INT_OVRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | HSMCI_INT_DCRCE) #endif #define HSMCI_DATA_DMASEND_ERRORS \ - (HSMCI_INT_UNRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | HSMCI_INT_DCRCE) + (HSMCI_INT_UNRE | HSMCI_INT_CSTOE | HSMCI_INT_DTOE | HSMCI_INT_DCRCE) /* Data transfer status and interrupt mask bits. * @@ -222,10 +242,19 @@ * 1: DMA buffer transfer has completed. */ -#define HSMCI_DMARECV_INTS \ - (HSMCI_DATA_DMARECV_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */) -#define HSMCI_DMASEND_INTS \ - (HSMCI_DATA_DMASEND_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */) +#ifdef CONFIG_SAM34_DMAC0 +# define HSMCI_DMARECV_INTS \ + (HSMCI_DATA_DMARECV_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */) +# define HSMCI_DMASEND_INTS \ + (HSMCI_DATA_DMASEND_ERRORS | HSMCI_INT_XFRDONE /* | HSMCI_INT_DMADONE */) +#endif + +#ifdef CONFIG_SAM34_PDCA + #define HSMCI_DMARECV_INTS \ + (HSMCI_DATA_DMARECV_ERRORS | HSMCI_INT_ENDRX) + #define HSMCI_DMASEND_INTS \ + (HSMCI_DATA_DMASEND_ERRORS | HSMCI_INT_ENDTX) +#endif /* Event waiting interrupt mask bits. * @@ -284,7 +313,9 @@ struct sam_dev_s uint32_t cmdrmask; /* Interrupt enables for this particular cmd/response */ volatile sdio_eventset_t wkupevent; /* The event that caused the wakeup */ WDOG_ID waitwdog; /* Watchdog that handles event timeouts */ +#ifdef CONFIG_SAM34_DMAC0 bool dmabusy; /* TRUE: DMA is in progress */ +#endif /* Callback support */ @@ -301,7 +332,9 @@ struct sam_dev_s /* DMA data transfer support */ bool widebus; /* Required for DMA support */ +#ifdef CONFIG_SAM34_DMAC0 DMA_HANDLE dma; /* Handle for DMA channel */ +#endif }; /* Register logging support */ @@ -309,24 +342,37 @@ struct sam_dev_s #if defined(CONFIG_SAM34_HSMCI_XFRDEBUG) || defined(CONFIG_SAM34_HSMCI_CMDDEBUG) struct sam_hsmciregs_s { - uint32_t mr; /* Mode Register */ - uint32_t dtor; /* Data Timeout Register */ - uint32_t sdcr; /* SD/SDIO Card Register */ - uint32_t argr; /* Argument Register */ - uint32_t blkr; /* Block Register */ - uint32_t cstor; /* Completion Signal Timeout Register */ - uint32_t rsp0; /* Response Register 0 */ - uint32_t rsp1; /* Response Register 1 */ - uint32_t rsp2; /* Response Register 2 */ - uint32_t rsp3; /* Response Register 3 */ - uint32_t sr; /* Status Register */ - uint32_t imr; /* Interrupt Mask Register */ + uint32_t mr; /* Mode Register */ + uint32_t dtor; /* Data Timeout Register */ + uint32_t sdcr; /* SD/SDIO Card Register */ + uint32_t argr; /* Argument Register */ + uint32_t blkr; /* Block Register */ + uint32_t cstor; /* Completion Signal Timeout Register */ + uint32_t rsp0; /* Response Register 0 */ + uint32_t rsp1; /* Response Register 1 */ + uint32_t rsp2; /* Response Register 2 */ + uint32_t rsp3; /* Response Register 3 */ + uint32_t sr; /* Status Register */ + uint32_t imr; /* Interrupt Mask Register */ #if defined(CONFIG_ARCH_CHIP_SAM3U) - uint32_t dma; /* DMA Configuration Register */ + uint32_t dma; /* DMA Configuration Register */ +#endif + uint32_t cfg; /* Configuration Register */ + uint32_t wpmr; /* Write Protection Mode Register */ + uint32_t wpsr; /* Write Protection Status Register */ + +#ifdef CONFIG_SAM34_PDCA + uint32_t pdc_rpr; /* Receive Pointer Register */ + uint32_t pdc_rcr; /* Receive Counter Register */ + uint32_t pdc_tpr; /* Transmit Pointer Register */ + uint32_t pdc_tcr; /* Transmit Counter Register */ + uint32_t pdc_rnpr; /* Receive Next Pointer Register */ + uint32_t pdc_rncr; /* Receive Next Counter Register */ + uint32_t pdc_tnpr; /* Transmit Next Pointer Register */ + uint32_t pdc_tncr; /* Transmit Next Counter Register */ +//uint32_t pdc_ptcr; /* Transfer Control Register */ + uint32_t pdc_ptsr; /* Transfer Status Register */ #endif - uint32_t cfg; /* Configuration Register */ - uint32_t wpmr; /* Write Protection Mode Register */ - uint32_t wpsr; /* Write Protection Status Register */ }; #endif @@ -334,7 +380,7 @@ struct sam_hsmciregs_s struct sam_xfrregs_s { struct sam_hsmciregs_s hsmci; -#ifdef CONFIG_DEBUG_DMA +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SAM34_DMAC0) struct sam_dmaregs_s dma; #endif }; @@ -390,9 +436,11 @@ static void sam_cmddump(void); # define sam_cmddump() #endif +#ifdef CONFIG_SAM34_DMAC0 /* DMA Helpers **************************************************************/ static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result); +#endif /* Data Transfer Helpers ****************************************************/ @@ -733,24 +781,37 @@ static inline void sam_enable(void) #if defined(CONFIG_SAM34_HSMCI_XFRDEBUG) || defined(CONFIG_SAM34_HSMCI_CMDDEBUG) static void sam_hsmcisample(struct sam_hsmciregs_s *regs) { - regs->mr = getreg32(SAM_HSMCI_MR); - regs->dtor = getreg32(SAM_HSMCI_DTOR); - regs->sdcr = getreg32(SAM_HSMCI_SDCR); - regs->argr = getreg32(SAM_HSMCI_ARGR); - regs->blkr = getreg32(SAM_HSMCI_BLKR); - regs->cstor = getreg32(SAM_HSMCI_CSTOR); - regs->rsp0 = getreg32(SAM_HSMCI_RSPR0); - regs->rsp1 = getreg32(SAM_HSMCI_RSPR1); - regs->rsp2 = getreg32(SAM_HSMCI_RSPR2); - regs->rsp3 = getreg32(SAM_HSMCI_RSPR3); - regs->sr = getreg32(SAM_HSMCI_SR); - regs->imr = getreg32(SAM_HSMCI_IMR); + regs->mr = getreg32(SAM_HSMCI_MR); + regs->dtor = getreg32(SAM_HSMCI_DTOR); + regs->sdcr = getreg32(SAM_HSMCI_SDCR); + regs->argr = getreg32(SAM_HSMCI_ARGR); + regs->blkr = getreg32(SAM_HSMCI_BLKR); + regs->cstor = getreg32(SAM_HSMCI_CSTOR); + regs->rsp0 = getreg32(SAM_HSMCI_RSPR0); + regs->rsp1 = getreg32(SAM_HSMCI_RSPR1); + regs->rsp2 = getreg32(SAM_HSMCI_RSPR2); + regs->rsp3 = getreg32(SAM_HSMCI_RSPR3); + regs->sr = getreg32(SAM_HSMCI_SR); + regs->imr = getreg32(SAM_HSMCI_IMR); #if defined(CONFIG_ARCH_CHIP_SAM3U) - regs->dma = getreg32(SAM_HSMCI_DMA); + regs->dma = getreg32(SAM_HSMCI_DMA); +#endif + regs->cfg = getreg32(SAM_HSMCI_CFG); + regs->wpmr = getreg32(SAM_HSMCI_WPMR); + regs->wpsr = getreg32(SAM_HSMCI_WPSR); + +#ifdef CONFIG_SAM34_PDCA + regs->pdc_rpr = getreg32(SAM_HSMCI_PDC_RPR); + regs->pdc_rcr = getreg32(SAM_HSMCI_PDC_RCR); + regs->pdc_tpr = getreg32(SAM_HSMCI_PDC_TPR); + regs->pdc_tcr = getreg32(SAM_HSMCI_PDC_TCR); + regs->pdc_rnpr = getreg32(SAM_HSMCI_PDC_RNPR); + regs->pdc_rncr = getreg32(SAM_HSMCI_PDC_RNCR); + regs->pdc_tnpr = getreg32(SAM_HSMCI_PDC_TNPR); + regs->pdc_tncr = getreg32(SAM_HSMCI_PDC_TNCR); +//regs->pdc_ptcr = getreg32(SAM_HSMCI_PDC_PTCR); + regs->pdc_ptsr = getreg32(SAM_HSMCI_PDC_PTSR); #endif - regs->cfg = getreg32(SAM_HSMCI_CFG); - regs->wpmr = getreg32(SAM_HSMCI_WPMR); - regs->wpsr = getreg32(SAM_HSMCI_WPSR); } #endif @@ -766,24 +827,38 @@ static void sam_hsmcisample(struct sam_hsmciregs_s *regs) static void sam_hsmcidump(struct sam_hsmciregs_s *regs, const char *msg) { fdbg("HSMCI Registers: %s\n", msg); - fdbg(" MR[%08x]: %08x\n", SAM_HSMCI_MR, regs->mr); - fdbg(" DTOR[%08x]: %08x\n", SAM_HSMCI_DTOR, regs->dtor); - fdbg(" SDCR[%08x]: %08x\n", SAM_HSMCI_SDCR, regs->sdcr); - fdbg(" ARGR[%08x]: %08x\n", SAM_HSMCI_ARGR, regs->argr); - fdbg(" BLKR[%08x]: %08x\n", SAM_HSMCI_BLKR, regs->blkr); - fdbg(" CSTOR[%08x]: %08x\n", SAM_HSMCI_CSTOR, regs->cstor); - fdbg(" RSPR0[%08x]: %08x\n", SAM_HSMCI_RSPR0, regs->rsp0); - fdbg(" RSPR1[%08x]: %08x\n", SAM_HSMCI_RSPR1, regs->rsp1); - fdbg(" RSPR2[%08x]: %08x\n", SAM_HSMCI_RSPR2, regs->rsp2); - fdbg(" RSPR3[%08x]: %08x\n", SAM_HSMCI_RSPR3, regs->rsp3); - fdbg(" SR[%08x]: %08x\n", SAM_HSMCI_SR, regs->sr); - fdbg(" IMR[%08x]: %08x\n", SAM_HSMCI_IMR, regs->imr); + fdbg(" MR[%08x]: %08x\n", SAM_HSMCI_MR, regs->mr); + fdbg(" DTOR[%08x]: %08x\n", SAM_HSMCI_DTOR, regs->dtor); + fdbg(" SDCR[%08x]: %08x\n", SAM_HSMCI_SDCR, regs->sdcr); + fdbg(" ARGR[%08x]: %08x\n", SAM_HSMCI_ARGR, regs->argr); + fdbg(" BLKR[%08x]: %08x\n", SAM_HSMCI_BLKR, regs->blkr); + fdbg(" CSTOR[%08x]: %08x\n", SAM_HSMCI_CSTOR, regs->cstor); + fdbg(" RSPR0[%08x]: %08x\n", SAM_HSMCI_RSPR0, regs->rsp0); + fdbg(" RSPR1[%08x]: %08x\n", SAM_HSMCI_RSPR1, regs->rsp1); + fdbg(" RSPR2[%08x]: %08x\n", SAM_HSMCI_RSPR2, regs->rsp2); + fdbg(" RSPR3[%08x]: %08x\n", SAM_HSMCI_RSPR3, regs->rsp3); + fdbg(" SR[%08x]: %08x\n", SAM_HSMCI_SR, regs->sr); + fdbg(" IMR[%08x]: %08x\n", SAM_HSMCI_IMR, regs->imr); #if defined(CONFIG_ARCH_CHIP_SAM3U) - fdbg(" DMA[%08x]: %08x\n", SAM_HSMCI_DMA, regs->dma); + fdbg(" DMA[%08x]: %08x\n", SAM_HSMCI_DMA, regs->dma); +#endif + fdbg(" CFG[%08x]: %08x\n", SAM_HSMCI_CFG, regs->cfg); + fdbg(" WPMR[%08x]: %08x\n", SAM_HSMCI_WPMR, regs->wpmr); + fdbg(" WPSR[%08x]: %08x\n", SAM_HSMCI_WPSR, regs->wpsr); + +#ifdef CONFIG_SAM34_PDCA + fdbg("HSMCI PDC Registers:\n"); + fdbg(" RPR[%08x]: %08x\n", SAM_HSMCI_PDC_RPR, regs->pdc_rpr); + fdbg(" RCR[%08x]: %08x\n", SAM_HSMCI_PDC_RCR, regs->pdc_rcr); + fdbg(" TPR[%08x]: %08x\n", SAM_HSMCI_PDC_TPR, regs->pdc_tpr); + fdbg(" TCR[%08x]: %08x\n", SAM_HSMCI_PDC_TCR, regs->pdc_tcr); + fdbg(" RNPR[%08x]: %08x\n", SAM_HSMCI_PDC_RNPR, regs->pdc_rnpr); + fdbg(" RNCR[%08x]: %08x\n", SAM_HSMCI_PDC_RNCR, regs->pdc_rncr); + fdbg(" TNPR[%08x]: %08x\n", SAM_HSMCI_PDC_TNPR, regs->pdc_tnpr); + fdbg(" TNCR[%08x]: %08x\n", SAM_HSMCI_PDC_TNCR, regs->pdc_tncr); +//fdbg(" TCR[%08x]: %08x\n", SAM_HSMCI_PDC_PTCR, regs->pdc_ptcr); + fdbg(" PTSR[%08x]: %08x\n", SAM_HSMCI_PDC_PTSR, regs->pdc_ptsr); #endif - fdbg(" CFG[%08x]: %08x\n", SAM_HSMCI_CFG, regs->cfg); - fdbg(" WPMR[%08x]: %08x\n", SAM_HSMCI_WPMR, regs->wpmr); - fdbg(" WPSR[%08x]: %08x\n", SAM_HSMCI_WPSR, regs->wpsr); } #endif @@ -799,7 +874,7 @@ static void sam_hsmcidump(struct sam_hsmciregs_s *regs, const char *msg) static void sam_xfrsample(struct sam_dev_s *priv, int index) { struct sam_xfrregs_s *regs = &g_xfrsamples[index]; -#ifdef CONFIG_DEBUG_DMA +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SAM34_DMAC0) sam_dmasample(priv->dma, ®s->dma); #endif sam_hsmcisample(®s->hsmci); @@ -836,7 +911,7 @@ static void sam_xfrsampleinit(void) static void sam_xfrdumpone(struct sam_dev_s *priv, struct sam_xfrregs_s *regs, const char *msg) { -#ifdef CONFIG_DEBUG_DMA +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SAM34_DMAC0) sam_dmadump(priv->dma, ®s->dma, msg); #endif sam_hsmcidump(®s->hsmci, msg); @@ -864,7 +939,7 @@ static void sam_xfrdump(struct sam_dev_s *priv) #endif sam_xfrdumpone(priv, &g_xfrsamples[SAMPLENDX_AFTER_SETUP], "After setup"); sam_xfrdumpone(priv, &g_xfrsamples[SAMPLENDX_END_TRANSFER], "End of transfer"); -#ifdef CONFIG_DEBUG_DMA +#if defined(CONFIG_DEBUG_DMA) && defined(CONFIG_SAM34_DMAC0) sam_xfrdumpone(priv, &g_xfrsamples[SAMPLENDX_DMA_CALLBACK], "DMA Callback"); #endif #ifdef CONFIG_SAM34_HSMCI_CMDDEBUG @@ -949,6 +1024,7 @@ static void sam_cmddump(void) * ****************************************************************************/ +#ifdef CONFIG_SAM34_DMAC0 static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result) { struct sam_dev_s *priv = (struct sam_dev_s *)arg; @@ -963,6 +1039,7 @@ static void sam_dmacallback(DMA_HANDLE handle, void *arg, int result) sam_xfrsample((struct sam_dev_s*)arg, SAMPLENDX_DMA_CALLBACK); } +#endif /**************************************************************************** * Data Transfer Helpers @@ -1073,6 +1150,7 @@ static void sam_endtransfer(struct sam_dev_s *priv, sam_xfrsample(priv, SAMPLENDX_END_TRANSFER); +#ifdef CONFIG_SAM34_DMAC0 /* Make sure that the DMA is stopped (it will be stopped automatically * on normal transfers, but not necessarily when the transfer terminates * on an error condition. @@ -1086,6 +1164,11 @@ static void sam_endtransfer(struct sam_dev_s *priv, putreg32(0, SAM_HSMCI_DMA); #endif +#endif + +#ifdef CONFIG_SAM34_PDCA + putreg32(PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS, SAM_HSMCI_PDC_PTCR); +#endif /* Is a thread wait for these data transfer complete events? */ @@ -1114,19 +1197,28 @@ static void sam_endtransfer(struct sam_dev_s *priv, static void sam_notransfer(struct sam_dev_s *priv) { +#ifdef CONFIG_SAM34_DMAC0 uint32_t regval; regval = getreg32(SAM_HSMCI_MR); + #if defined(CONFIG_ARCH_CHIP_SAM3U) regval &= ~(HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF | HSMCI_MR_BLKLEN_MASK); #else regval &= ~(HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF); #endif + putreg32(regval, SAM_HSMCI_MR); +#endif + +#ifdef CONFIG_SAM34_PDCA + modifyreg32(SAM_HSMCI_MR, HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF | + HSMCI_MR_PDCMODE, 0); +#endif } /**************************************************************************** - * Interrrupt Handling + * Interrupt Handling ****************************************************************************/ /**************************************************************************** @@ -1311,18 +1403,22 @@ static void sam_reset(FAR struct sdio_dev_s *dev) /* Set the SDCard Register */ - putreg32(HSMCI_SDCR_SDCSEL_SLOTA | HSMCI_SDCR_SDCBUS_4BIT, SAM_HSMCI_SDCR); + putreg32(HSMCI_SDCR_SDCSEL_SLOTA | HSMCI_SDCR_SDCBUS_1BIT, SAM_HSMCI_SDCR); /* Enable the MCI controller */ putreg32(HSMCI_CR_MCIEN, SAM_HSMCI_CR); -#if defined(CONFIG_ARCH_CHIP_SAM3U) /* Disable the DMA interface */ +#if defined(CONFIG_ARCH_CHIP_SAM3U) putreg32(0, SAM_HSMCI_DMA); #endif +#ifdef CONFIG_SAM34_PDCA + putreg32(PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS, SAM_HSMCI_PDC_PTCR); +#endif + /* Configure MCI */ putreg32(HSMCI_CFG_FIFOMODE, SAM_HSMCI_CFG); @@ -1336,7 +1432,10 @@ static void sam_reset(FAR struct sdio_dev_s *dev) priv->waitevents = 0; /* Set of events to be waited for */ priv->waitmask = 0; /* Interrupt enables for event waiting */ priv->wkupevent = 0; /* The event that caused the wakeup */ +#ifdef CONFIG_SAM34_DMAC0 priv->dmabusy = false; /* No DMA in progress */ +#endif + wd_cancel(priv->waitwdog); /* Cancel any timeouts */ /* Interrupt mode data transfer support */ @@ -1345,7 +1444,7 @@ static void sam_reset(FAR struct sdio_dev_s *dev) /* DMA data transfer support */ - priv->widebus = false; /* Required for DMA support */ + priv->widebus = false; irqrestore(flags); } @@ -1604,7 +1703,7 @@ static int sam_sendcmd(FAR struct sdio_dev_s *dev, break; } - /* 'OR' in data transer related bits */ + /* 'OR' in data transfer related bits */ switch (cmd & MMCSD_DATAXFR_MASK) { @@ -1676,9 +1775,14 @@ static void sam_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen, DEBUGASSERT(dev != NULL && nblocks > 0 && nblocks < 65535 && blocklen < 65535); - /* Set the block size */ + /* When TRTYP - Single or Multi, blocklen must be 1-511, 0-512 */ + + DEBUGASSERT(blocklen <= 512); + + /* Set the block size. Clear bits followed by set */ regval = getreg32(SAM_HSMCI_MR); + #if defined(CONFIG_ARCH_CHIP_SAM3U) regval &= ~(HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF | HSMCI_MR_BLKLEN_MASK); regval |= HSMCU_PROOF_BITS; @@ -1687,13 +1791,12 @@ static void sam_blocksetup(FAR struct sdio_dev_s *dev, unsigned int blocklen, regval &= ~(HSMCI_MR_RDPROOF | HSMCI_MR_WRPROOF); regval |= HSMCU_PROOF_BITS; #endif + putreg32(regval, SAM_HSMCI_MR); - /* Set the block count */ + /* Set the block count register */ - regval = getreg32(SAM_HSMCI_BLKR); - regval &= ~HSMCI_BLKR_BCNT_MASK; - regval |= (nblocks << HSMCI_BLKR_BCNT_SHIFT); + regval = HSMCI_BLKR_BLKLEN(blocklen) | HSMCI_BLKR_BCNT(nblocks); putreg32(regval, SAM_HSMCI_BLKR); } @@ -1740,8 +1843,10 @@ static int sam_cancel(FAR struct sdio_dev_s *dev) * on an error condition. */ +#ifdef CONFIG_SAM34_DMAC0 sam_dmastop(priv->dma); priv->dmabusy = false; +#endif #if defined(CONFIG_ARCH_CHIP_SAM3U) /* Disable the DMA handshaking */ @@ -1749,6 +1854,10 @@ static int sam_cancel(FAR struct sdio_dev_s *dev) putreg32(0, SAM_HSMCI_DMA); #endif +#ifdef CONFIG_SAM34_PDCA + putreg32(PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS, SAM_HSMCI_PDC_PTCR); +#endif + return OK; } @@ -2157,18 +2266,6 @@ static sdio_eventset_t sam_eventwait(FAR struct sdio_dev_s *dev, return SDIOWAIT_TIMEOUT; } -#if 0 - /* I am not sure why this is, but I am currently seeing some - * additional delays when DMA is used (On the SAMA5, might - * not be necessary for SAM3/4). - */ - - if (priv->dmabusy) - { - timeout += 500; - } -#endif - /* Start the watchdog timer */ delay = (timeout + (MSEC_PER_TICK-1)) / MSEC_PER_TICK; @@ -2340,6 +2437,7 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, sam_xfrsampleinit(); sam_xfrsample(priv, SAMPLENDX_BEFORE_SETUP); +#ifdef CONFIG_SAM34_DMAC0 /* Configure the RX DMA */ sam_dmarxsetup(priv->dma, SAM_HSMCI_RDR, (uint32_t)buffer, buflen); @@ -2361,6 +2459,16 @@ static int sam_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer, priv->dmabusy = true; sam_dmastart(priv->dma, sam_dmacallback, priv); +#endif + +#ifdef CONFIG_SAM34_PDCA + modifyreg32(SAM_HSMCI_MR, 0, HSMCI_MR_PDCMODE); + fdbg("SAM_HSMCI_MR = 0x%08X\n", getreg32(SAM_HSMCI_MR)); + putreg32((uint32_t)buffer, SAM_HSMCI_PDC_RPR); + putreg32(buflen/4, SAM_HSMCI_PDC_RCR); + putreg32(PDC_PTCR_RXTEN, SAM_HSMCI_PDC_PTCR); + sam_xfrsample(priv, SAMPLENDX_BEFORE_ENABLE); +#endif /* Configure transfer-related interrupts. Transfer interrupts are not * enabled until after the transfer is stard with an SD command (i.e., @@ -2404,6 +2512,7 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev, sam_xfrsampleinit(); sam_xfrsample(priv, SAMPLENDX_BEFORE_SETUP); +#ifdef CONFIG_SAM34_DMAC0 /* Configure the TX DMA */ sam_dmatxsetup(priv->dma, SAM_HSMCI_TDR, (uint32_t)buffer, buflen); @@ -2419,6 +2528,16 @@ static int sam_dmasendsetup(FAR struct sdio_dev_s *dev, priv->dmabusy = true; sam_dmastart(priv->dma, sam_dmacallback, priv); +#endif + +#ifdef CONFIG_SAM34_PDCA + modifyreg32(SAM_HSMCI_MR, 0, HSMCI_MR_PDCMODE); + fdbg("SAM_HSMCI_MR = 0x%08X\n", getreg32(SAM_HSMCI_MR)); + putreg32((uint32_t)buffer, SAM_HSMCI_PDC_TPR); + putreg32(buflen/4, SAM_HSMCI_PDC_TCR); + putreg32(PDC_PTCR_TXTEN, SAM_HSMCI_PDC_PTCR); + sam_xfrsample(priv, SAMPLENDX_BEFORE_ENABLE); +#endif /* Configure transfer-related interrupts. Transfer interrupts are not * enabled until after the transfer is stard with an SD command (i.e., @@ -2543,10 +2662,12 @@ FAR struct sdio_dev_s *sdio_initialize(int slotno) priv->waitwdog = wd_create(); DEBUGASSERT(priv->waitwdog); +#ifdef CONFIG_SAM34_DMAC0 /* Allocate a DMA channel. A FIFO size of 8 is sufficient. */ priv->dma = sam_dmachannel(DMA_FLAGS); DEBUGASSERT(priv->dma); +#endif /* Configure GPIOs for 4-bit, wide-bus operation. NOTE: (1) the chip is capable of * 8-bit wide bus operation but D4-D7 are not configured, (2) any card detection