diff --git a/arch/arm/src/imxrt/imxrt_usdhc.c b/arch/arm/src/imxrt/imxrt_usdhc.c index ef6065349b6..26286d9fec3 100644 --- a/arch/arm/src/imxrt/imxrt_usdhc.c +++ b/arch/arm/src/imxrt/imxrt_usdhc.c @@ -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 */ diff --git a/configs/imxrt1050-evk/include/board.h b/configs/imxrt1050-evk/include/board.h index af41390d697..a674e623dd8 100644 --- a/configs/imxrt1050-evk/include/board.h +++ b/configs/imxrt1050-evk/include/board.h @@ -4,6 +4,7 @@ * Copyright (C) 2018 Gregory Nutt. All rights reserved. * Authors: Gregory Nutt * David Sidrane + * Dave Marples * * 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 ***************************************************************/ diff --git a/include/stdbool.h b/include/stdbool.h index 7a2b80a2a0c..7cd2df07e6c 100644 --- a/include/stdbool.h +++ b/include/stdbool.h @@ -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. */