mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 13:27:01 +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_CMDTIMEOUT MSEC2TICK(100)
|
||||||
#define USDHC_LONGTIMEOUT MSEC2TICK(500)
|
#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)
|
#define USDHC_DTOCV_MAXTIMEOUT (15)
|
||||||
|
|
||||||
@@ -110,20 +110,26 @@
|
|||||||
|
|
||||||
/* Data transfer / Event waiting interrupt mask bits */
|
/* 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_RESPERR_INTS (USDHC_INT_CCE | USDHC_INT_CTOE | \
|
||||||
#define USDHC_RESPDONE_INTS (USDHC_RESPERR_INTS|USDHC_INT_CC)
|
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_XFRERR_INTS (USDHC_INT_DCE | USDHC_INT_DTOE | \
|
||||||
#define USDHC_RCVDONE_INTS (USDHC_XFRERR_INTS|USDHC_INT_BRR|USDHC_INT_TC)
|
USDHC_INT_DEBE)
|
||||||
#define USDHC_SNDDONE_INTS (USDHC_XFRERR_INTS|USDHC_INT_BWR|USDHC_INT_TC)
|
#define USDHC_RCVDONE_INTS (USDHC_XFRERR_INTS | USDHC_INT_BRR | \
|
||||||
#define USDHC_XFRDONE_INTS (USDHC_XFRERR_INTS|USDHC_INT_BRR|USDHC_INT_BWR|USDHC_INT_TC)
|
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 */
|
/* For DMA operations DINT is not interesting TC will indicate completions */
|
||||||
|
|
||||||
#define USDHC_DMAERR_INTS (USDHC_XFRERR_INTS|USDHC_INT_DMAE)
|
#define USDHC_DMAERR_INTS (USDHC_XFRERR_INTS | USDHC_INT_DMAE)
|
||||||
#define USDHC_DMADONE_INTS (USDHC_DMAERR_INTS|USDHC_INT_TC)
|
#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 */
|
/* Register logging support */
|
||||||
|
|
||||||
@@ -170,7 +176,10 @@ struct imxrt_dev_s
|
|||||||
/* DMA data transfer support */
|
/* DMA data transfer support */
|
||||||
|
|
||||||
#ifdef CONFIG_IMXRT_USDHC_DMA
|
#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
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -251,8 +260,10 @@ static void imxrt_transmit(struct imxrt_dev_s *priv);
|
|||||||
static void imxrt_receive(struct imxrt_dev_s *priv);
|
static void imxrt_receive(struct imxrt_dev_s *priv);
|
||||||
#endif
|
#endif
|
||||||
static void imxrt_eventtimeout(int argc, uint32_t arg);
|
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,
|
||||||
static void imxrt_endtransfer(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent);
|
sdio_eventset_t wkupevent);
|
||||||
|
static void imxrt_endtransfer(struct imxrt_dev_s *priv,
|
||||||
|
sdio_eventset_t wkupevent);
|
||||||
|
|
||||||
/* Interrupt Handling *******************************************************/
|
/* Interrupt Handling *******************************************************/
|
||||||
|
|
||||||
@@ -604,9 +615,12 @@ static void imxrt_dumpsample(struct imxrt_dev_s *priv,
|
|||||||
#ifdef CONFIG_SDIO_XFRDEBUG
|
#ifdef CONFIG_SDIO_XFRDEBUG
|
||||||
static void imxrt_dumpsamples(struct imxrt_dev_s *priv)
|
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_BEFORE_SETUP],
|
||||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP], "After setup");
|
"Before setup");
|
||||||
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER], "End of transfer");
|
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_AFTER_SETUP],
|
||||||
|
"After setup");
|
||||||
|
imxrt_dumpsample(priv, &g_sampleregs[SAMPLENDX_END_TRANSFER],
|
||||||
|
"End of transfer");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -646,7 +660,9 @@ static void imxrt_dataconfig(struct imxrt_dev_s *priv, bool bwrite,
|
|||||||
unsigned int watermark;
|
unsigned int watermark;
|
||||||
uint32_t regval = 0;
|
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 = getreg32(IMXRT_USDHC1_SYSCTL);
|
||||||
regval &= ~USDHC_SYSCTL_DTOCV_MASK;
|
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 */
|
/* Cancel the watchdog timeout */
|
||||||
|
|
||||||
@@ -949,7 +966,7 @@ static void imxrt_endwait(struct imxrt_dev_s *priv, sdio_eventset_t wkupevent)
|
|||||||
* are detected.
|
* are detected.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* 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
|
* wkupevent - The event that caused the transfer to end
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* 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
|
#ifdef CONFIG_IMXRT_USDHC_DMA
|
||||||
uint32_t regval;
|
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 */
|
/* Clearing pending interrupt status on all transfer related interrupts */
|
||||||
|
|
||||||
putreg32(USDHC_XFRDONE_INTS, IMXRT_USDHC1_IRQSTAT);
|
putreg32(USDHC_XFRDONE_INTS | USDHC_DMADONE_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
|
|
||||||
|
|
||||||
/* Mark the transfer finished */
|
/* Mark the transfer finished */
|
||||||
|
|
||||||
priv->remaining = 0;
|
priv->remaining = 0;
|
||||||
|
|
||||||
|
/* DMA modified the buffer, so we need to flush its cache lines. */
|
||||||
|
|
||||||
|
arch_invalidate_dcache(priv->buffer, priv->bufferend);
|
||||||
|
|
||||||
/* Debug instrumentation */
|
/* Debug instrumentation */
|
||||||
|
|
||||||
imxrt_sample(priv, SAMPLENDX_END_TRANSFER);
|
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->waitints = 0; /* Interrupt enables for event waiting */
|
||||||
priv->wkupevent = 0; /* The event that caused the wakeup */
|
priv->wkupevent = 0; /* The event that caused the wakeup */
|
||||||
#ifdef CONFIG_IMXRT_USDHC_DMA
|
#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
|
#endif
|
||||||
|
|
||||||
wd_cancel(priv->waitwdog); /* Cancel any timeouts */
|
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.
|
* Get SDIO status.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* dev - Device-specific state data
|
* dev - Device-specific state data
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Returns a bitset of status values (see imxrt_status_* defines)
|
* 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_R4_RESPONSE:
|
||||||
case MMCSD_R7_RESPONSE:
|
case MMCSD_R7_RESPONSE:
|
||||||
regval |= USDHC_XFERTYP_RSPTYP_LEN48;
|
regval |= USDHC_XFERTYP_RSPTYP_LEN48;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable DMA */
|
/* Enable DMA */
|
||||||
@@ -1840,7 +1848,9 @@ static int imxrt_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
|
|||||||
imxrt_sampleinit();
|
imxrt_sampleinit();
|
||||||
imxrt_sample(priv, SAMPLENDX_BEFORE_SETUP);
|
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->buffer = (uint32_t *)buffer;
|
||||||
priv->remaining = nbytes;
|
priv->remaining = nbytes;
|
||||||
@@ -2318,7 +2328,12 @@ static void imxrt_waitenable(FAR struct sdio_dev_s *dev,
|
|||||||
|
|
||||||
if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
|
if ((eventset & SDIOWAIT_TRANSFERDONE) != 0)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_IMXRT_USDHC_DMA
|
||||||
|
|
||||||
|
waitints |= USDHC_DMADONE_INTS;
|
||||||
|
#else
|
||||||
waitints |= USDHC_XFRDONE_INTS;
|
waitints |= USDHC_XFRDONE_INTS;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable event-related interrupts */
|
/* 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
|
* are enabled via a call to SDIO_CALLBACKENABLE
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* dev - Device-specific state data
|
* dev - Device-specific state data
|
||||||
* callback - The function to call on the media change
|
* 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:
|
* Returned Value:
|
||||||
* 0 on success; negated errno on failure.
|
* 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->buffer = (uint32_t *)buffer;
|
||||||
priv->remaining = buflen;
|
priv->remaining = buflen;
|
||||||
|
priv->bufferend = (uint32_t *)(buffer + buflen);
|
||||||
|
|
||||||
/* Then set up the SDIO data path */
|
/* Then set up the SDIO data path */
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||||
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
* Authors: Gregory Nutt <gnutt@nuttx.org>
|
||||||
* David Sidrane <david_s5@nscdg.com>
|
* David Sidrane <david_s5@nscdg.com>
|
||||||
|
* Dave Marples <dave@marples.net>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@@ -170,13 +171,14 @@
|
|||||||
/* SDIO *****************************************************************************/
|
/* SDIO *****************************************************************************/
|
||||||
|
|
||||||
/* Pin drive characteristics - drive strength in particular may need tuning for
|
/* 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)
|
IOMUX_PULL_UP_47K | IOMUX_SCHMITT_TRIGGER)
|
||||||
#define PINSET_USDHC1_CMD (PINSET_USDHC1_DATAX)
|
#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 PINSET_USDHC1_CD (0)
|
||||||
|
|
||||||
#define PIN_USDHC1_D0 GPIO_USDHC1_DATA0
|
#define PIN_USDHC1_D0 GPIO_USDHC1_DATA0
|
||||||
@@ -195,13 +197,13 @@
|
|||||||
/* 24.8MHz for other modes */
|
/* 24.8MHz for other modes */
|
||||||
|
|
||||||
#define BOARD_USDHC_MMCMODE_PRESCALER USDHC_SYSCTL_SDCLKFS_DIV8
|
#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_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_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 ***************************************************************/
|
/* PIO Disambiguation ***************************************************************/
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -58,7 +58,7 @@
|
|||||||
* configuration for better standards compatibility.
|
* configuration for better standards compatibility.
|
||||||
*
|
*
|
||||||
* CONFIG_C99_BOOL8 - Means (1) your C++ compiler has sizeof(_Bool) == 8,
|
* 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.
|
* the C99 _Bool type also has size 1.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user