Hi Peng,

A few comments.


On 7/12/2026 6:37 PM, Peng Fan (OSS) wrote:
From: Peng Fan <[email protected]>

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 <[email protected]>
---
  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

Reply via email to