mirror of
https://github.com/apache/nuttx.git
synced 2026-05-24 07:46:16 +08:00
arch/arm/src/imxrt/imxrt_usdhc.c: Improve SD card handling in the DMA case. For now I think we can consider this complete for both Interrupt and DMA transfers. There is other stuff to add (high speed, low voltage, DDR etc.) later,
This commit is contained in:
committed by
Gregory Nutt
parent
50a1b9eddf
commit
9b68efe251
@@ -100,7 +100,7 @@
|
||||
#define USDHC_CMDTIMEOUT MSEC2TICK(100)
|
||||
#define USDHC_LONGTIMEOUT MSEC2TICK(500)
|
||||
|
||||
/* Big DTOCV setting. Range is 0=SDCLK*2^13 through 15=SDCLK*2^29 */
|
||||
/* Big DTOCV setting. Range is 0 = SDCLK * 2^13 through 15 = SDCLK * 2^29 */
|
||||
|
||||
#define USDHC_DTOCV_MAXTIMEOUT (15)
|
||||
|
||||
@@ -110,20 +110,26 @@
|
||||
|
||||
/* Data transfer / Event waiting interrupt mask bits */
|
||||
|
||||
#define USDHC_RESPERR_INTS (USDHC_INT_CCE|USDHC_INT_CTOE|USDHC_INT_CEBE|USDHC_INT_CIE)
|
||||
#define USDHC_RESPDONE_INTS (USDHC_RESPERR_INTS|USDHC_INT_CC)
|
||||
#define USDHC_RESPERR_INTS (USDHC_INT_CCE | USDHC_INT_CTOE | \
|
||||
USDHC_INT_CEBE | USDHC_INT_CIE)
|
||||
#define USDHC_RESPDONE_INTS (USDHC_RESPERR_INTS | USDHC_INT_CC)
|
||||
|
||||
#define USDHC_XFRERR_INTS (USDHC_INT_DCE|USDHC_INT_DTOE|USDHC_INT_DEBE)
|
||||
#define USDHC_RCVDONE_INTS (USDHC_XFRERR_INTS|USDHC_INT_BRR|USDHC_INT_TC)
|
||||
#define USDHC_SNDDONE_INTS (USDHC_XFRERR_INTS|USDHC_INT_BWR|USDHC_INT_TC)
|
||||
#define USDHC_XFRDONE_INTS (USDHC_XFRERR_INTS|USDHC_INT_BRR|USDHC_INT_BWR|USDHC_INT_TC)
|
||||
#define USDHC_XFRERR_INTS (USDHC_INT_DCE | USDHC_INT_DTOE | \
|
||||
USDHC_INT_DEBE)
|
||||
#define USDHC_RCVDONE_INTS (USDHC_XFRERR_INTS | USDHC_INT_BRR | \
|
||||
USDHC_INT_TC)
|
||||
#define USDHC_SNDDONE_INTS (USDHC_XFRERR_INTS | USDHC_INT_BWR | \
|
||||
USDHC_INT_TC)
|
||||
#define USDHC_XFRDONE_INTS (USDHC_XFRERR_INTS | USDHC_INT_BRR | \
|
||||
USDHC_INT_BWR | USDHC_INT_TC)
|
||||
|
||||
/* For DMA operations DINT is not interesting TC will indicate completions */
|
||||
|
||||
#define USDHC_DMAERR_INTS (USDHC_XFRERR_INTS|USDHC_INT_DMAE)
|
||||
#define USDHC_DMADONE_INTS (USDHC_DMAERR_INTS|USDHC_INT_TC)
|
||||
#define USDHC_DMAERR_INTS (USDHC_XFRERR_INTS | USDHC_INT_DMAE)
|
||||
#define USDHC_DMADONE_INTS (USDHC_DMAERR_INTS | USDHC_INT_TC)
|
||||
|
||||
#define USDHC_WAITALL_INTS (USDHC_RESPDONE_INTS|USDHC_XFRDONE_INTS|USDHC_DMADONE_INTS)
|
||||
#define USDHC_WAITALL_INTS (USDHC_RESPDONE_INTS | USDHC_XFRDONE_INTS | \
|
||||
USDHC_DMADONE_INTS)
|
||||
|
||||
/* Register logging support */
|
||||
|
||||
@@ -170,7 +176,10 @@ struct imxrt_dev_s
|
||||
/* DMA data transfer support */
|
||||
|
||||
#ifdef CONFIG_IMXRT_USDHC_DMA
|
||||
volatile uint8_t xfrflags; /* Used to synchronize SDIO and DMA completion events */
|
||||
volatile uint8_t xfrflags; /* Used to synchronize SDIO and DMA
|
||||
* completion events */
|
||||
uint32_t *bufferend; /* Far end of R/W buffer for cache
|
||||
* invalidation purposes */
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -251,8 +260,10 @@ static void imxrt_transmit(struct imxrt_dev_s *priv);
|
||||
static void imxrt_receive(struct imxrt_dev_s *priv);
|
||||
#endif
|
||||
static void imxrt_eventtimeout(int argc, uint32_t arg);
|
||||
static void imxrt_endwait(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent);
|
||||
static void imxrt_endtransfer(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent);
|
||||
static void imxrt_endwait(struct imxrt_dev_s *priv,
|
||||
sdio_eventset_t wkupevent);
|
||||
static void imxrt_endtransfer(struct imxrt_dev_s *priv,
|
||||
sdio_eventset_t wkupevent);
|
||||
|
||||
/* Interrupt Handling *******************************************************/
|
||||
|
||||
@@ -604,9 +615,12 @@ static void imxrt_dumpsample(struct imxrt_dev_s *priv,
|
||||
#ifdef CONFIG_SDIO_XFRDEBUG
|
||||
static void imxrt_dumpsamples(struct imxrt_dev_s *priv)
|
||||
{
|
||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP], "Before setup");
|
||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup");
|
||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer");
|
||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_BEFORE_SETUP],
|
||||
"Before setup");
|
||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP],
|
||||
"After setup");
|
||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER],
|
||||
"End of transfer");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -646,7 +660,9 @@ static void imxrt_dataconfig(struct imxrt_dev_s *priv, bool bwrite,
|
||||
unsigned int watermark;
|
||||
uint32_t regval = 0;
|
||||
|
||||
/* Set the data timeout value in the USDHC_SYSCTL field to the selected value */
|
||||
/* Set the data timeout value in the USDHC_SYSCTL field to the selected
|
||||
* value.
|
||||
*/
|
||||
|
||||
regval = getreg32(IMXRT_USDHC1_SYSCTL);
|
||||
regval &= ~USDHC_SYSCTL_DTOCV_MASK;
|
||||
@@ -925,7 +941,8 @@ static void imxrt_eventtimeout(int argc, uint32_t arg)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void imxrt_endwait(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent)
|
||||
static void imxrt_endwait(struct imxrt_dev_s *priv,
|
||||
sdio_eventset_t wkupevent)
|
||||
{
|
||||
/* Cancel the watchdog timeout */
|
||||
|
||||
@@ -949,7 +966,7 @@ static void imxrt_endwait(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent)
|
||||
* are detected.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - An instance of the SDIO device interface
|
||||
* priv - An instance of the SDIO device interface
|
||||
* wkupevent - The event that caused the transfer to end
|
||||
*
|
||||
* Returned Value:
|
||||
@@ -960,7 +977,8 @@ static void imxrt_endwait(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void imxrt_endtransfer(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent)
|
||||
static void imxrt_endtransfer(struct imxrt_dev_s *priv,
|
||||
sdio_eventset_t wkupevent)
|
||||
{
|
||||
#ifdef CONFIG_IMXRT_USDHC_DMA
|
||||
uint32_t regval;
|
||||
@@ -973,27 +991,16 @@ static void imxrt_endtransfer(struct imxrt_dev_s *priv, sdio_eventset_t wkupeven
|
||||
|
||||
/* Clearing pending interrupt status on all transfer related interrupts */
|
||||
|
||||
putreg32(USDHC_XFRDONE_INTS, IMXRT_USDHC1_IRQSTAT);
|
||||
|
||||
/* If this was a DMA transfer, make sure that DMA is stopped */
|
||||
|
||||
#ifdef CONFIG_IMXRT_USDHC_DMA
|
||||
/* Stop the DMA by resetting the data path but first save the
|
||||
* state of the USDHC_PROCTL as it will be reset (in bits 24-0)
|
||||
* and we will loose the DTW (4bit mode) setting
|
||||
*/
|
||||
|
||||
proctl = getreg32(IMXRT_USDHC1_PROCTL);
|
||||
regval = getreg32(IMXRT_USDHC1_SYSCTL);
|
||||
regval |= USDHC_SYSCTL_RSTD;
|
||||
putreg32(regval, IMXRT_USDHC1_SYSCTL);
|
||||
putreg32(proctl, IMXRT_USDHC1_PROCTL);
|
||||
#endif
|
||||
putreg32(USDHC_XFRDONE_INTS | USDHC_DMADONE_INTS, IMXRT_USDHC1_IRQSTAT);
|
||||
|
||||
/* Mark the transfer finished */
|
||||
|
||||
priv->remaining = 0;
|
||||
|
||||
/* DMA modified the buffer, so we need to flush its cache lines. */
|
||||
|
||||
arch_invalidate_dcache(priv->buffer, priv->bufferend);
|
||||
|
||||
/* Debug instrumentation */
|
||||
|
||||
imxrt_sample(priv, SAMPLENDX_END_TRANSFER);
|
||||
@@ -1230,7 +1237,8 @@ static void imxrt_reset(FAR struct sdio_dev_s *dev)
|
||||
priv->waitints = 0; /* Interrupt enables for event waiting */
|
||||
priv->wkupevent = 0; /* The event that caused the wakeup */
|
||||
#ifdef CONFIG_IMXRT_USDHC_DMA
|
||||
priv->xfrflags = 0; /* Used to synchronize SDIO and DMA completion events */
|
||||
priv->xfrflags = 0; /* Used to synchronize SDIO and DMA completion
|
||||
* events */
|
||||
#endif
|
||||
|
||||
wd_cancel(priv->waitwdog); /* Cancel any timeouts */
|
||||
@@ -1278,7 +1286,7 @@ static sdio_capset_t imxrt_capabilities(FAR struct sdio_dev_s *dev)
|
||||
* Get SDIO status.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
* dev - Device-specific state data
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns a bitset of status values (see imxrt_status_* defines)
|
||||
@@ -1719,7 +1727,7 @@ static int imxrt_sendcmd(FAR struct sdio_dev_s *dev, uint32_t cmd,
|
||||
case MMCSD_R4_RESPONSE:
|
||||
case MMCSD_R7_RESPONSE:
|
||||
regval |= USDHC_XFERTYP_RSPTYP_LEN48;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable DMA */
|
||||
@@ -1840,7 +1848,9 @@ static int imxrt_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
imxrt_sampleinit();
|
||||
imxrt_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
||||
|
||||
/* Save the destination buffer information for use by the interrupt handler */
|
||||
/* Save the destination buffer information for use by the interrupt handler
|
||||
* and DMA memory invalidation.
|
||||
*/
|
||||
|
||||
priv->buffer = (uint32_t *)buffer;
|
||||
priv->remaining = nbytes;
|
||||
@@ -2318,7 +2328,12 @@ static void imxrt_waitenable(FAR struct sdio_dev_s *dev,
|
||||
|
||||
if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
|
||||
{
|
||||
#ifdef CONFIG_IMXRT_USDHC_DMA
|
||||
|
||||
waitints |= USDHC_DMADONE_INTS;
|
||||
#else
|
||||
waitints |= USDHC_XFRDONE_INTS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Enable event-related interrupts */
|
||||
@@ -2472,9 +2487,9 @@ static void imxrt_callbackenable(FAR struct sdio_dev_s *dev,
|
||||
* are enabled via a call to SDIO_CALLBACKENABLE
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - Device-specific state data
|
||||
* dev - Device-specific state data
|
||||
* callback - The function to call on the media change
|
||||
* arg - A caller provided value to return with the callback
|
||||
* arg - A caller provided value to return with the callback
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; negated errno on failure.
|
||||
@@ -2534,6 +2549,7 @@ static int imxrt_dmarecvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
||||
|
||||
priv->buffer = (uint32_t *)buffer;
|
||||
priv->remaining = buflen;
|
||||
priv->bufferend = (uint32_t *)(buffer + buflen);
|
||||
|
||||
/* Then set up the SDIO data path */
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||
* David Sidrane <david_s5@nscdg.com>
|
||||
* Dave Marples <dave@marples.net>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -170,13 +171,14 @@
|
||||
/* SDIO *****************************************************************************/
|
||||
|
||||
/* Pin drive characteristics - drive strength in particular may need tuning for
|
||||
* specific boards.
|
||||
* specific boards, but has been checked by scope on the EVKB to make sure shapes
|
||||
* are square with minimal ringing.
|
||||
*/
|
||||
|
||||
#define PINSET_USDHC1_DATAX (IOMUX_SLEW_FAST | IOMUX_DRIVE_60OHM | \
|
||||
#define PINSET_USDHC1_DATAX (IOMUX_SLEW_FAST | IOMUX_DRIVE_130OHM | \
|
||||
IOMUX_PULL_UP_47K | IOMUX_SCHMITT_TRIGGER)
|
||||
#define PINSET_USDHC1_CMD (PINSET_USDHC1_DATAX)
|
||||
#define PINSET_USDHC1_CLK (IOMUX_SLEW_FAST | IOMUX_DRIVE_60OHM | IOMUX_SPEED_MAX)
|
||||
#define PINSET_USDHC1_CLK (IOMUX_SLEW_FAST | IOMUX_DRIVE_130OHM | IOMUX_SPEED_MAX)
|
||||
#define PINSET_USDHC1_CD (0)
|
||||
|
||||
#define PIN_USDHC1_D0 GPIO_USDHC1_DATA0
|
||||
@@ -195,13 +197,13 @@
|
||||
/* 24.8MHz for other modes */
|
||||
|
||||
#define BOARD_USDHC_MMCMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_MMCMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(4) // FIXME 1
|
||||
#define BOARD_USDHC_MMCMODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
|
||||
#define BOARD_USDHC_SD1MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_SD1MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(4) // FIXME 1
|
||||
#define BOARD_USDHC_SD1MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
|
||||
#define BOARD_USDHC_SD4MODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
||||
#define BOARD_USDHC_SD4MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(4) // FIXME 1
|
||||
#define BOARD_USDHC_SD4MODE_DIVISOR USDHC_SYSCTL_DVS_DIV(1)
|
||||
|
||||
/* PIO Disambiguation ***************************************************************/
|
||||
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@
|
||||
* configuration for better standards compatibility.
|
||||
*
|
||||
* CONFIG_C99_BOOL8 - Means (1) your C++ compiler has sizeof(_Bool) == 8,
|
||||
* (2) your C compiler supports the C99 _Bool intrinsic type, and (2) that
|
||||
* (2) your C compiler supports the C99 _Bool intrinsic type, and (3) that
|
||||
* the C99 _Bool type also has size 1.
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user