diff --git a/arch/arm/src/stm32/stm32_sdio.c b/arch/arm/src/stm32/stm32_sdio.c index 58a028fe5b8..7c7b48c0d40 100644 --- a/arch/arm/src/stm32/stm32_sdio.c +++ b/arch/arm/src/stm32/stm32_sdio.c @@ -428,6 +428,11 @@ static void stm32_configwaitints(struct stm32_dev_s *priv, uint32 waitmask, sdio_eventset_t wkupevent) { irqstate_t flags; + + /* Save all of the data and set the new interrupt mask in one, atomic + * operation. + */ + flags = irqsave(); priv->waitevents = waitevents; priv->wkupevent = wkupevent; @@ -1152,35 +1157,39 @@ static void stm32_widebus(FAR struct sdio_dev_s *dev, boolean wide) static void stm32_clock(FAR struct sdio_dev_s *dev, enum sdio_clock_e rate) { uint32 clckr; + uint32 enable = 1; switch (rate) { - case CLOCK_SDIO_DISABLED: /* Clock is disabled */ - putreg32(0, SDIO_CLKCR_CLKEN_BB); - break; - default: + case CLOCK_SDIO_DISABLED: /* Clock is disabled */ + clckr = STM32_CLCKCR_INIT; + enable = 0; + return; + case CLOCK_IDMODE: /* Initial ID mode clocking (<400KHz) */ - clckr = STM32_CLCKCR_INIT; + clckr = STM32_CLCKCR_INIT; break; case CLOCK_MMC_TRANSFER: /* MMC normal operation clocking */ - clckr = SDIO_CLKCR_MMCXFR; + clckr = SDIO_CLKCR_MMCXFR; break; case CLOCK_SD_TRANSFER_1BIT: /* SD normal operation clocking (narrow 1-bit mode) */ - clckr = SDIO_CLCKR_SDXFR; + clckr = SDIO_CLCKR_SDXFR; break; case CLOCK_SD_TRANSFER_4BIT: /* SD normal operation clocking (wide 4-bit mode) */ - clckr = SDIO_CLCKR_SDWIDEXFR; + clckr = SDIO_CLCKR_SDWIDEXFR; break; }; - /* Set the new clock frequency and make sure that the clock is enabled */ + /* Set the new clock frequency and make sure that the clock is enabled or + * disabled, whatever the case. + */ - stm32_setclkcr(STM32_CLCKCR_INIT); - putreg32(1, SDIO_CLKCR_CLKEN_BB); + stm32_setclkcr(clckr); + putreg32(enable, SDIO_CLKCR_CLKEN_BB); } /**************************************************************************** @@ -1773,7 +1782,13 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, sdio_eventset_t wkupevent = 0; int ret; - DEBUGASSERT(priv->waitevents != 0); + /* There is a race condition here... the event may have completed before + * we get here. In this case waitevents will be zero, but wkupevents will + * be non-zero (and, hopefully, the semaphore count will also be non-zero. + */ + + DEBUGASSERT((priv->waitevents != 0 && priv->wkupevent == 0) || + (priv->waitevents == 0 && priv->wkupevent != 0)); /* Check if the timeout event is specified in the event set */ @@ -1814,10 +1829,11 @@ static sdio_eventset_t stm32_eventwait(FAR struct sdio_dev_s *dev, stm32_takesem(priv); - /* Check if the event has occurred. */ + /* Check if the event has occurred. When the event has occurred, then + * evenset will be set to 0 and wkupevent will be set to a nonzero value. + */ - wkupevent = (ubyte)(priv->wkupevent & priv->waitevents); - if (wkupevent != 0) + if (priv->wkupevent != 0) { /* Yes... break out of the loop with wkupevent non-zero */ diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c index 69a92496652..152a2bee35f 100644 --- a/drivers/mmcsd/mmcsd_sdio.c +++ b/drivers/mmcsd/mmcsd_sdio.c @@ -824,8 +824,6 @@ struct mmcsd_scr_s decoded; * SD_SECURITY 54:52 3-bit SD security support level * SD_BUS_WIDTHS 51:48 4-bit bus width indicator * Reserved 47:32 16-bit SD reserved space - * usage. - * */ priv->buswidth = (scr[0] >> 16) & 15; @@ -839,9 +837,7 @@ struct mmcsd_scr_s decoded; #endif /* Word 1, bits 63:32 - * Reserved 31:0 32-bits reserved for manufacturing - * usage. - * + * Reserved 31:0 32-bits reserved for manufacturing usage. */ #if defined(CONFIG_DEBUG) && defined (CONFIG_DEBUG_VERBOSE) && defined(CONFIG_DEBUG_FS) @@ -1134,7 +1130,7 @@ static int mmcsd_setblocklen(FAR struct mmcsd_state_s *priv, uint32 blocklen) * block length is specified in the CSD. */ - mmcsd_sendcmdpoll(priv, MMCSD_CMD16, priv->blocksize); + mmcsd_sendcmdpoll(priv, MMCSD_CMD16, blocklen); ret = mmcsd_recvR1(priv, MMCSD_CMD16); if (ret == OK) { @@ -2238,6 +2234,19 @@ static int mmcsd_sdinitialize(FAR struct mmcsd_state_s *priv) } mmcsd_decodeCSD(priv, csd); + /* Send CMD7 with the argument == RCA in order to select the card. + * Since we are supporting only a single card, we just leave the + * card selected all of the time. + */ + + mmcsd_sendcmdpoll(priv, MMCSD_CMD7S, priv->rca << 16); + ret = mmcsd_recvR1(priv, MMCSD_CMD7S); + if (ret != OK) + { + fdbg("ERROR: mmcsd_recvR1 for CMD7 failed: %d\n", ret); + return ret; + } + /* Set the Driver Stage Register (DSR) if (1) a CONFIG_MMCSD_DSR has been * provided and (2) the card supports a DSR register. If no DSR value * the card default value (0x0404) will be used.