From: Luke Wang Date: Tue, 10 Mar 2026 01:35:52 +0000 (+0800) Subject: mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e98f926e5a2d8023a74ec2ba7a973b5d76610f4e;p=thirdparty%2Fkernel%2Fstable.git mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width UHS/DDR/HS200 modes require at least 4-bit bus support. Host controllers that lack relevant capability registers rely on paring properties provided by firmware, which may incorrectly set these modes. Now that mmc_validate_host_caps() has been introduced to validate such configuration violations, let's also add checks for UHS/DDR/HS200 modes. This fixes an issue where, if the HS200/HS400 property is set while only a 1-bit bus width is used, mmc_select_hs200() returns 0 without actually performing the mode switch. Consequently, mmc_select_timing() proceeds without falling back to mmc_select_hs(), leaving the eMMC device operating in legacy mode (26 MHz) instead of switching to High Speed mode (52 MHz). Signed-off-by: Luke Wang [Shawn: reword the commit msg and rework the code] Signed-off-by: Shawn Lin Signed-off-by: Ulf Hansson --- diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 88c95dbfd9cf..a457c88fdcbc 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -624,12 +624,24 @@ static int mmc_validate_host_caps(struct mmc_host *host) return -EINVAL; } + /* UHS/DDR/HS200 modes require at least 4-bit bus */ + if (!(caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) && + ((caps & (MMC_CAP_UHS | MMC_CAP_DDR)) || (caps2 & MMC_CAP2_HS200))) { + dev_warn(dev, "drop UHS/DDR/HS200 support since 1-bit bus only\n"); + caps &= ~(MMC_CAP_UHS | MMC_CAP_DDR); + caps2 &= ~MMC_CAP2_HS200; + } + + /* HS400 and HS400ES modes require 8-bit bus */ if (caps2 & (MMC_CAP2_HS400_ES | MMC_CAP2_HS400) && !(caps & MMC_CAP_8_BIT_DATA) && !(caps2 & MMC_CAP2_NO_MMC)) { dev_warn(dev, "drop HS400 support since no 8-bit bus\n"); - host->caps2 = caps2 & ~MMC_CAP2_HS400_ES & ~MMC_CAP2_HS400; + caps2 &= ~(MMC_CAP2_HS400_ES | MMC_CAP2_HS400); } + host->caps = caps; + host->caps2 = caps2; + return 0; }