diff options
| author | Luke Wang <ziniu.wang_1@nxp.com> | 2026-03-10 09:35:52 +0800 |
|---|---|---|
| committer | Ulf Hansson <ulf.hansson@linaro.org> | 2026-03-16 15:46:58 +0100 |
| commit | e98f926e5a2d8023a74ec2ba7a973b5d76610f4e (patch) | |
| tree | 68ae28ffa3bb63d5fd08c52021609230a6fef4ab /drivers/mmc/core | |
| parent | cc1060a18e0464a7b03c06fb64889935d27acee0 (diff) | |
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 <ziniu.wang_1@nxp.com>
[Shawn: reword the commit msg and rework the code]
Signed-off-by: Shawn Lin <shawn.lin@linux.dev>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/core')
| -rw-r--r-- | drivers/mmc/core/host.c | 14 |
1 files changed, 13 insertions, 1 deletions
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; } |
