diff --git a/drivers/mmcsd/mmcsd_sdio.c b/drivers/mmcsd/mmcsd_sdio.c index c034f48fef5e2..f81412704d444 100644 --- a/drivers/mmcsd/mmcsd_sdio.c +++ b/drivers/mmcsd/mmcsd_sdio.c @@ -2848,8 +2848,17 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv) { /* Configuring MMC - Use MMC_SWITCH access modes. * Select 8-bit if host supports it, otherwise 4-bit. + * + * Switch the host to wide bus operation before issuing the + * SWITCH command: on hosts that program the bus width in the + * widebus callback, switching the card first leaves the switch + * unfinished and all following transfers fail. */ + SDIO_WIDEBUS(priv->dev, true); + priv->widebus = true; + MMCSD_USLEEP(MMCSD_CLK_DELAY); + if (priv->caps & SDIO_CAPS_8BIT) { mmcsd_sendcmdpoll(priv, MMCSD_CMD6, @@ -2936,7 +2945,13 @@ static int mmcsd_widebus(FAR struct mmcsd_state_s *priv) priv->mode = EXT_CSD_HS_TIMING_HS; } - SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER); + /* Select the MMC transfer clocking according to the negotiated + * bus width, mirroring the SD card path above, so that a later + * clock selection cannot revert the host to 1-bit operation. + */ + + SDIO_CLOCK(priv->dev, priv->widebus ? CLOCK_MMC_TRANSFER_4BIT : + CLOCK_MMC_TRANSFER); } #endif /* #ifdef CONFIG_MMCSD_MMCSUPPORT */ @@ -3171,6 +3186,15 @@ static int mmcsd_mmcinitialize(FAR struct mmcsd_state_s *priv) mmcsd_decode_csd(priv, priv->csd); + /* Select high speed MMC clocking (which may depend on the DSR setting) + * before switching the bus width: on hosts that program the bus width + * in the clock callback, the transfer clock must already be in place + * before the switch sequence starts. + */ + + SDIO_CLOCK(priv->dev, CLOCK_MMC_TRANSFER); + MMCSD_USLEEP(MMCSD_CLK_DELAY); + /* It's up to the driver to act on the widebus request. mmcsd_widebus() * enables the CLOCK_MMC_TRANSFER, so call it here always. */