public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Validate and clean up UHS/DDR/HS200 timing checks
@ 2026-03-06 12:48 Shawn Lin
  2026-03-06 12:48 ` [PATCH 1/2] mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width Shawn Lin
  2026-03-06 12:48 ` [PATCH 2/2] mmc: core: Remove checking MMC_CAP_4_BIT_DATA from mmc_host_can_uhs() Shawn Lin
  0 siblings, 2 replies; 5+ messages in thread
From: Shawn Lin @ 2026-03-06 12:48 UTC (permalink / raw)
  To: Ulf Hansson; +Cc: linux-mmc, linux-kernel, Shawn Lin


This series adds validation for UHS/DDR/HS200 timing modes when the host
only supports 1-bit bus width which also fixes a real performance drop issue
due to incorrect hs200 mode switch code. And then cleans up the check in
mmc_host_can_uhs().


Luke Wang (1):
  mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width

Shawn Lin (1):
  mmc: core: Remove checking MMC_CAP_4_BIT_DATA from mmc_host_can_uhs()

 drivers/mmc/core/host.c | 9 +++++++++
 drivers/mmc/core/host.h | 6 +-----
 2 files changed, 10 insertions(+), 5 deletions(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/2] mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width
  2026-03-06 12:48 [PATCH 0/2] Validate and clean up UHS/DDR/HS200 timing checks Shawn Lin
@ 2026-03-06 12:48 ` Shawn Lin
  2026-03-09 14:57   ` Ulf Hansson
  2026-03-06 12:48 ` [PATCH 2/2] mmc: core: Remove checking MMC_CAP_4_BIT_DATA from mmc_host_can_uhs() Shawn Lin
  1 sibling, 1 reply; 5+ messages in thread
From: Shawn Lin @ 2026-03-06 12:48 UTC (permalink / raw)
  To: Ulf Hansson; +Cc: linux-mmc, linux-kernel, Luke Wang, Shawn Lin

From: Luke Wang <ziniu.wang_1@nxp.com>

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 drop HS400 change]
Signed-off-by: Shawn Lin <shawn.lin@linux.dev>
---

 drivers/mmc/core/host.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 88c95db..d1d4870 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -624,6 +624,15 @@ 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");
+		host->caps = caps = caps & ~(MMC_CAP_UHS | MMC_CAP_DDR);
+		host->caps2 = caps2 = 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");
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/2] mmc: core: Remove checking MMC_CAP_4_BIT_DATA from mmc_host_can_uhs()
  2026-03-06 12:48 [PATCH 0/2] Validate and clean up UHS/DDR/HS200 timing checks Shawn Lin
  2026-03-06 12:48 ` [PATCH 1/2] mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width Shawn Lin
@ 2026-03-06 12:48 ` Shawn Lin
  1 sibling, 0 replies; 5+ messages in thread
From: Shawn Lin @ 2026-03-06 12:48 UTC (permalink / raw)
  To: Ulf Hansson; +Cc: linux-mmc, linux-kernel, Shawn Lin

The bus width support for UHS mode is now validated in mmc_validate_host_caps().
Therefore, we can safely remove the explicit MMC_CAP_4_BIT_DATA check from
mmc_host_can_uhs(). As part of this cleanup, simplify the condition by using the
consolidated MMC_CAP_UHS flag.

Signed-off-by: Shawn Lin <shawn.lin@linux.dev>
---

 drivers/mmc/core/host.h | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index 5941d68..6bce5a4 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -56,11 +56,7 @@ static inline int mmc_host_can_access_boot(struct mmc_host *host)
 
 static inline int mmc_host_can_uhs(struct mmc_host *host)
 {
-	return host->caps &
-		(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 |
-		 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 |
-		 MMC_CAP_UHS_DDR50) &&
-	       host->caps & MMC_CAP_4_BIT_DATA;
+	return host->caps & MMC_CAP_UHS;
 }
 
 static inline bool mmc_card_hs200(struct mmc_card *card)
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width
  2026-03-06 12:48 ` [PATCH 1/2] mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width Shawn Lin
@ 2026-03-09 14:57   ` Ulf Hansson
  2026-03-10  0:37     ` Shawn Lin
  0 siblings, 1 reply; 5+ messages in thread
From: Ulf Hansson @ 2026-03-09 14:57 UTC (permalink / raw)
  To: Shawn Lin; +Cc: linux-mmc, linux-kernel, Luke Wang

On Fri, 6 Mar 2026 at 13:48, Shawn Lin <shawn.lin@linux.dev> wrote:
>
> From: Luke Wang <ziniu.wang_1@nxp.com>
>
> 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 drop HS400 change]
> Signed-off-by: Shawn Lin <shawn.lin@linux.dev>
> ---
>
>  drivers/mmc/core/host.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
> index 88c95db..d1d4870 100644
> --- a/drivers/mmc/core/host.c
> +++ b/drivers/mmc/core/host.c
> @@ -624,6 +624,15 @@ 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");
> +               host->caps = caps = caps & ~(MMC_CAP_UHS | MMC_CAP_DDR);
> +               host->caps2 = caps2 = caps2 & ~MMC_CAP2_HS200;

Hmm.

How about just updating the temporary variables, caps and caps2, here?

Then at the end of the function when we have validated all "caps", we
can update the variables in the host, like:
host->caps = caps;
host->caps2 = caps2;

> +       }
> +
> +       /* 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");
> --
> 2.7.4
>

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/2] mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width
  2026-03-09 14:57   ` Ulf Hansson
@ 2026-03-10  0:37     ` Shawn Lin
  0 siblings, 0 replies; 5+ messages in thread
From: Shawn Lin @ 2026-03-10  0:37 UTC (permalink / raw)
  To: Ulf Hansson; +Cc: shawn.lin, linux-mmc, linux-kernel, Luke Wang

Hi Ulf,

在 2026/03/09 星期一 22:57, Ulf Hansson 写道:
> On Fri, 6 Mar 2026 at 13:48, Shawn Lin <shawn.lin@linux.dev> wrote:
>>
>> From: Luke Wang <ziniu.wang_1@nxp.com>
>>
>> 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 drop HS400 change]
>> Signed-off-by: Shawn Lin <shawn.lin@linux.dev>
>> ---
>>
>>   drivers/mmc/core/host.c | 9 +++++++++
>>   1 file changed, 9 insertions(+)
>>
>> diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
>> index 88c95db..d1d4870 100644
>> --- a/drivers/mmc/core/host.c
>> +++ b/drivers/mmc/core/host.c
>> @@ -624,6 +624,15 @@ 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");
>> +               host->caps = caps = caps & ~(MMC_CAP_UHS | MMC_CAP_DDR);
>> +               host->caps2 = caps2 = caps2 & ~MMC_CAP2_HS200;
> 
> Hmm.
> 
> How about just updating the temporary variables, caps and caps2, here?
> 
> Then at the end of the function when we have validated all "caps", we
> can update the variables in the host, like:
> host->caps = caps;
> host->caps2 = caps2;

It looks better. Will update v2 based on your suggestion.

> 
>> +       }
>> +
>> +       /* 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");
>> --
>> 2.7.4
>>
> 
> Kind regards
> Uffe
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-03-10  0:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-06 12:48 [PATCH 0/2] Validate and clean up UHS/DDR/HS200 timing checks Shawn Lin
2026-03-06 12:48 ` [PATCH 1/2] mmc: core: Validate UHS/DDR/HS200 timing selection for 1-bit bus width Shawn Lin
2026-03-09 14:57   ` Ulf Hansson
2026-03-10  0:37     ` Shawn Lin
2026-03-06 12:48 ` [PATCH 2/2] mmc: core: Remove checking MMC_CAP_4_BIT_DATA from mmc_host_can_uhs() Shawn Lin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox