SAM3/4: Support for PDC based HSMCI ADMA from Bob Doiron
This commit is contained in:
parent
b0f4941c77
commit
5eadd8df7a
@ -43,6 +43,7 @@
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#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 */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user