[PATCH 5/5] mmc: fix mmc_deinit regression when card is at 1.8V signaling
Kathpalia, Tanmay
tanmay.kathpalia at altera.com
Sun Jul 12 20:20:27 CEST 2026
Hi Peng,
A few comments.
On 7/12/2026 6:37 PM, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan at nxp.com>
>
> Commit 906ee6785b1c ("mmc: sd: Handle UHS-I voltage signaling without
> power cycle") added detection of cards already operating at 1.8V
> signaling via mmc_sd_card_using_v18(). This correctly handles the
> warm-reboot scenario in mmc_startup(), but causes a regression in
> mmc_deinit().
>
> The problem: mmc_deinit() strips ALL UHS capabilities from the card
> caps and calls sd_select_mode_and_width() to downgrade the card before
> kernel handoff. But sd_select_mode_and_width() now checks
> mmc_sd_card_using_v18(), sees the card is at 1.8V, sets uhs_en=true,
> and tries to use UHS modes -- which were just stripped from the caps.
Even before 906ee6785b1c, sd_select_mode_and_width() computed:
bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
For a card that has switched to 1.8V, OCR_S18R (S18A) is already set in
mmc->ocr, so uhs_en was already true in this path before the commit.
So sd_select_mode_and_width() did not newly set uhs_en=true because
of this commit; that was already the case. Could you reword the
attribution to reflect that?
> The fallback modes (SD_HS, MMC_LEGACY) all fail because they require
> 3.3V signaling, which the card cannot revert to without a power cycle.
I think CMD6 switches speed over whatever signaling is already active,
so this doesn't necessarily fail outright - it likely leaves the card
in an invalid/inconsistent state (a 3.3V speed mode while signaling at
1.8V). Might be worth softening "all fail" to that wording, but I'll
leave it to your judgment/testing.
>
> Per SD Physical Layer Specification: "Once the card enters 1.8V
> signaling mode, the card cannot be switched to 3.3V signaling without
> power cycle. If the card receives CMD0, card returns to Idle state but
> still works with SDR12 timing."
>
> Fix this by preserving UHS_SDR12 in the filtered caps when the card is
> operating at 1.8V. SDR12 is the minimum valid UHS-I mode and is always
> available at 1.8V signaling per the SD specification.
>
> Fixes: 906ee6785b1c ("mmc: sd: Handle UHS-I voltage signaling without power cycle")
> Signed-off-by: Peng Fan <peng.fan at nxp.com>
> ---
> drivers/mmc/mmc.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
> index 5fd12d21f92..809d7b6b578 100644
> --- a/drivers/mmc/mmc.c
> +++ b/drivers/mmc/mmc.c
> @@ -3178,6 +3178,17 @@ int mmc_deinit(struct mmc *mmc)
> MMC_CAP(UHS_SDR50) | MMC_CAP(UHS_DDR50) |
> MMC_CAP(UHS_SDR104));
>
> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
> + /*
> + * Per SD spec, once a card enters 1.8V signaling it
> + * cannot revert to 3.3V without a power cycle.
> + * If the card is operating at 1.8V, keep UHS_SDR12
> + * as the minimum fallback mode.
> + */
> + if (mmc_sd_card_using_v18(mmc))
> + caps_filtered |= MMC_CAP(UHS_SDR12);
> +#endif
> +
> return sd_select_mode_and_width(mmc, caps_filtered);
> } else {
> caps_filtered = mmc->card_caps &
Cleaner to decide the mask up front instead of stripping then adding
back, and reuse UHS_CAPS instead of re-listing the bits:
if (IS_SD(mmc)) {
u32 uhs_mask = UHS_CAPS;
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
/*
* Per SD spec, once a card enters 1.8V signaling it cannot
* revert to 3.3V without a power cycle. If the card is operating
* at 1.8V, keep UHS_SDR12 as the minimum fallback mode so the
* card is left in a consistent (1.8V) state at a low, safe speed.
*/
if (mmc_sd_card_using_v18(mmc))
uhs_mask &= ~MMC_CAP(UHS_SDR12);
#endif
caps_filtered = mmc->card_caps & ~uhs_mask;
Regards,
Tanmay
More information about the U-Boot
mailing list