[PATCH v2 2/2] mmc: core: Add MMC_CAP2_NO_SLEEP_CMD host capability
Kamal Dasu <[email protected]> Fri, 17 Jul 2026 14:05:36 -0400
| Newsgroups | org.kernel.vger.linux-mmc,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Some (e)MMC devices take longer to exit the SLEEP (CMD5) state than their advertised S_A_TIMEOUT allows for. On platforms where a boot ROM sends CMD0 and reads boot code from the card immediately on resume, a card still asleep at that point causes the ROM to treat it as fatal and reset. Add MMC_CAP2_NO_SLEEP_CMD, settable via the new "no-mmc-sleep" DT property, so affected hosts can tell mmc_card_can_sleep() to never put the card to sleep, regardless of ext_csd revision. This is a host-level capability rather than a card quirk so it also covers cards whose bug can't be identified by CID/ext_csd matching alone, and it is resolved before the card even exists, avoiding any ordering dependency on when a card-quirk table would be applied. Reported-by: Florian Fainelli <[email protected]> Closes: https://lore.kernel.org/r/[email protected]/ Signed-off-by: Kamal Dasu <[email protected]> --- Changes in v2: - Replaced the card-level MMC_QUIRK_BROKEN_SLEEP quirk (keyed off CID) with a host capability, MMC_CAP2_NO_SLEEP_CMD, set from the new "no-mmc-sleep" DT property, per Ulf's suggestion that this generalize beyond one device's CID. - Resolving the capability in mmc_of_parse(), before any card exists, also addresses Oleksij's concern that a quirk registered in mmc_blk_fixups[] (applied at mmc_block probe time) could lose a race against an earlier SLEEP/poweroff on an under-voltage path. - Added Reported-by/Closes tags crediting Florian for the original bug report. drivers/mmc/core/host.c | 2 ++ drivers/mmc/core/mmc.c | 3 +++ include/linux/mmc/host.h | 1 + 3 files changed, 6 insertions(+) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index b7ce3137d452..3bc19645ea96 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -400,6 +400,8 @@ int mmc_of_parse(struct mmc_host *host) if (device_property_read_bool(dev, "no-mmc-hs400")) host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | MMC_CAP2_HS400_ES); + if (device_property_read_bool(dev, "no-mmc-sleep")) + host->caps2 |= MMC_CAP2_NO_SLEEP_CMD; /* Must be after "non-removable" check */ if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 05444ecf3909..5e80fa5c1a28 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1972,6 +1972,9 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, static bool mmc_card_can_sleep(struct mmc_card *card) { + if (card->host->caps2 & MMC_CAP2_NO_SLEEP_CMD) + return false; + return card->ext_csd.rev >= 3; } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ba84f02c2a10..0447a8efed50 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -463,6 +463,7 @@ struct mmc_host { #define MMC_CAP2_CRYPTO 0 #endif #define MMC_CAP2_ALT_GPT_TEGRA (1 << 28) /* Host with eMMC that has GPT entry at a non-standard location */ +#define MMC_CAP2_NO_SLEEP_CMD (1 << 29) /* Card can't reliably wake from CMD5 SLEEP */ bool uhs2_sd_tran; /* UHS-II flag for SD_TRAN state */ bool uhs2_app_cmd; /* UHS-II flag for APP command */ -- 2.34.1