* [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle
@ 2025-10-21 20:45 Tanmay Kathpalia
2025-10-22 3:16 ` Peng Fan
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Tanmay Kathpalia @ 2025-10-21 20:45 UTC (permalink / raw)
To: u-boot; +Cc: trini, peng.fan, jh80.chung, marex, tien.fong.chee,
tanmay.kathpalia
Some boards have SD card connectors where the power rail cannot be switched
off by the driver. However there are various circumstances when a card
might be re-initialized, such as after system resume, warm re-boot, or
error handling. However, a UHS card will continue to use 1.8V signaling
unless it is power cycled.
If the card has not been power cycled, it may still be using 1.8V
signaling. According to the SD spec., the Bus Speed Mode (function group 1)
bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus
they can be used to determine if the card has already switched to 1.8V
signaling. Detect that situation and try to initialize a UHS-I (1.8V)
transfer mode.
Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com>
---
drivers/mmc/mmc.c | 55 ++++++++++++++++++++++++++++++++++++++---------
include/mmc.h | 3 +++
2 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index ec61ed92e86..e1f62a5d0ad 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage)
return 0;
}
+
+static bool mmc_sd_card_using_v18(struct mmc *mmc)
+{
+ /*
+ * According to the SD spec., the Bus Speed Mode (function group 1) bits
+ * 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus
+ * they can be used to determine if the card has already switched to
+ * 1.8V signaling.
+ */
+ bool volt = mmc->sd3_bus_mode &
+ (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50);
+ return volt;
+}
#endif
static int sd_send_op_cond(struct mmc *mmc, bool uhs_en)
@@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc *mmc)
ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16);
struct mmc_data data;
int timeout;
-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
- u32 sd3_bus_mode;
-#endif
mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
@@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc *mmc)
if (mmc->version < SD_VERSION_3)
return 0;
- sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
- if (sd3_bus_mode & SD_MODE_UHS_SDR104)
+ mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f;
+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104)
mmc->card_caps |= MMC_CAP(UHS_SDR104);
- if (sd3_bus_mode & SD_MODE_UHS_SDR50)
+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50)
mmc->card_caps |= MMC_CAP(UHS_SDR50);
- if (sd3_bus_mode & SD_MODE_UHS_SDR25)
+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25)
mmc->card_caps |= MMC_CAP(UHS_SDR25);
- if (sd3_bus_mode & SD_MODE_UHS_SDR12)
+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12)
mmc->card_caps |= MMC_CAP(UHS_SDR12);
- if (sd3_bus_mode & SD_MODE_UHS_DDR50)
+ if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50)
mmc->card_caps |= MMC_CAP(UHS_DDR50);
#endif
@@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT};
const struct mode_width_tuning *mwt;
#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
- bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false;
+ /*
+ * Enable UHS mode if the card advertises 1.8V support (S18R in OCR)
+ * or is already operating at 1.8V signaling.
+ */
+ bool uhs_en = (mmc->ocr & OCR_S18R) || mmc_sd_card_using_v18(mmc);
#else
bool uhs_en = false;
#endif
@@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc)
err = sd_get_capabilities(mmc);
if (err)
return err;
+
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+ /*
+ * If the card has already switched to 1.8V signaling, then
+ * set the signal voltage to 1.8V.
+ */
+ if (mmc_sd_card_using_v18(mmc)) {
+ /*
+ * During a signal voltage level switch, the clock must be gated
+ * for 5 ms according to the SD spec.
+ */
+ mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE);
+ err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180);
+ if (err)
+ return err;
+ /* Keep clock gated for at least 10 ms, though spec only says 5 ms */
+ mdelay(10);
+ mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE);
+ }
+#endif
+
err = sd_select_mode_and_width(mmc, mmc->card_caps);
} else {
err = mmc_get_capabilities(mmc);
diff --git a/include/mmc.h b/include/mmc.h
index c6b2ab4a29f..51d3f2f8dd5 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -759,6 +759,9 @@ struct mmc {
#endif
u8 *ext_csd;
u32 cardtype; /* cardtype read from the MMC */
+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT)
+ u32 sd3_bus_mode; /* Supported UHS-I bus speed modes */
+#endif
enum mmc_voltage current_voltage;
enum bus_mode selected_mode; /* mode currently used */
enum bus_mode best_mode; /* best mode is the supported mode with the
--
2.43.7
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2025-10-21 20:45 [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle Tanmay Kathpalia @ 2025-10-22 3:16 ` Peng Fan 2025-10-22 14:06 ` Tanmay Kathpalia 2025-10-23 8:46 ` Peng Fan (OSS) ` (2 subsequent siblings) 3 siblings, 1 reply; 17+ messages in thread From: Peng Fan @ 2025-10-22 3:16 UTC (permalink / raw) To: Tanmay Kathpalia Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Tanmay, On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >Some boards have SD card connectors where the power rail cannot be switched >off by the driver. However there are various circumstances when a card >might be re-initialized, such as after system resume, warm re-boot, or >error handling. However, a UHS card will continue to use 1.8V signaling >unless it is power cycled. > >If the card has not been power cycled, it may still be using 1.8V >signaling. According to the SD spec., the Bus Speed Mode (function group 1) >bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >they can be used to determine if the card has already switched to 1.8V >signaling. Detect that situation and try to initialize a UHS-I (1.8V) >transfer mode. Actually a power cycle or reset is required to make sure SD card to work correctly. Some SD cards may work in your case, some SD cards might not work, without a power cycle or reset. Thanks, Peng > >Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2025-10-22 3:16 ` Peng Fan @ 2025-10-22 14:06 ` Tanmay Kathpalia 0 siblings, 0 replies; 17+ messages in thread From: Tanmay Kathpalia @ 2025-10-22 14:06 UTC (permalink / raw) To: Peng Fan; +Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Peng, Thank you for your feedback. On 10/22/2025 8:46 AM, Peng Fan wrote: > Hi Tanmay, > > On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >> Some boards have SD card connectors where the power rail cannot be switched >> off by the driver. However there are various circumstances when a card >> might be re-initialized, such as after system resume, warm re-boot, or >> error handling. However, a UHS card will continue to use 1.8V signaling >> unless it is power cycled. >> >> If the card has not been power cycled, it may still be using 1.8V >> signaling. According to the SD spec., the Bus Speed Mode (function group 1) >> bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >> they can be used to determine if the card has already switched to 1.8V >> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >> transfer mode. > > Actually a power cycle or reset is required to make sure SD card to work > correctly. Some SD cards may work in your case, some SD cards might not work, > without a power cycle or reset. > > Thanks, > Peng > According to the SD specification for the Switch Function command (CMD6): "If the card is initialized in 3.3V signal level, Default Speed and High Speed are assigned to function 0 and 1. Then support bits of function 2 to 4 (SDR50, SDR104 and DDR50) are set to 0. If the card is initialized in 1.8V signal level, SDR and DDR modes are assigned from function 0 to function 4." This allows the host to detect if the card is already operating at 1.8V signaling and proceed accordingly. I have tested this approach with multiple SD cards from different vendors and capacities, including: - Kingston Canvas Select Plus 16GB SDR104 - Samsung EVO Select 128GB SDR104 - Samsung Evo Plus 128GB SDR104 All of these cards worked reliably in my tests. For further reference, similar discussions and solutions have been proposed in the Linux community: https://lore.kernel.org/linux-mmc/a367a679-28f7-898a-c043-27df8c9c9aba@intel.com/ https://lore.kernel.org/linux-mmc/1506328144-13666-1-git-send-email-adrian.hunter@intel.com/ Thanks, Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2025-10-21 20:45 [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle Tanmay Kathpalia 2025-10-22 3:16 ` Peng Fan @ 2025-10-23 8:46 ` Peng Fan (OSS) 2026-05-13 23:39 ` Judith Mendez 2026-05-16 9:44 ` Peng Fan 3 siblings, 0 replies; 17+ messages in thread From: Peng Fan (OSS) @ 2025-10-23 8:46 UTC (permalink / raw) To: u-boot, Tanmay Kathpalia Cc: Peng Fan, trini, jh80.chung, marex, tien.fong.chee From: Peng Fan <peng.fan@nxp.com> On Tue, 21 Oct 2025 13:45:26 -0700, Tanmay Kathpalia wrote: > Some boards have SD card connectors where the power rail cannot be switched > off by the driver. However there are various circumstances when a card > might be re-initialized, such as after system resume, warm re-boot, or > error handling. However, a UHS card will continue to use 1.8V signaling > unless it is power cycled. > > If the card has not been power cycled, it may still be using 1.8V > signaling. According to the SD spec., the Bus Speed Mode (function group 1) > bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus > they can be used to determine if the card has already switched to 1.8V > signaling. Detect that situation and try to initialize a UHS-I (1.8V) > transfer mode. > > [...] Applied to mmc/next, thanks! [1/1] mmc: sd: Handle UHS-I voltage signaling without power cycle commit: a9797a8a057b408e9c26f69d5e1d651285bf81c0 Best regards, -- Peng Fan <peng.fan@nxp.com> ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2025-10-21 20:45 [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle Tanmay Kathpalia 2025-10-22 3:16 ` Peng Fan 2025-10-23 8:46 ` Peng Fan (OSS) @ 2026-05-13 23:39 ` Judith Mendez 2026-05-14 18:50 ` Kathpalia, Tanmay 2026-05-16 9:44 ` Peng Fan 3 siblings, 1 reply; 17+ messages in thread From: Judith Mendez @ 2026-05-13 23:39 UTC (permalink / raw) To: Tanmay Kathpalia, u-boot Cc: trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Tanmay, all, On 10/21/25 3:45 PM, Tanmay Kathpalia wrote: > Some boards have SD card connectors where the power rail cannot be switched > off by the driver. However there are various circumstances when a card > might be re-initialized, such as after system resume, warm re-boot, or > error handling. However, a UHS card will continue to use 1.8V signaling > unless it is power cycled. > > If the card has not been power cycled, it may still be using 1.8V > signaling. According to the SD spec., the Bus Speed Mode (function group 1) > bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus > they can be used to determine if the card has already switched to 1.8V > signaling. Detect that situation and try to initialize a UHS-I (1.8V) > transfer mode. This implementation broke am65 IDK board SD card boot, I have still to check why this breaks only one board, potentially there might be a quirk only for this board... But for now sending the question in case anyone might have an idea what is going on & save me some time. ~ Judith ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-05-13 23:39 ` Judith Mendez @ 2026-05-14 18:50 ` Kathpalia, Tanmay 2026-05-14 22:21 ` Judith Mendez 0 siblings, 1 reply; 17+ messages in thread From: Kathpalia, Tanmay @ 2026-05-14 18:50 UTC (permalink / raw) To: Judith Mendez, u-boot; +Cc: trini, peng.fan, jh80.chung, marex, tien.fong.chee On 5/14/2026 5:09 AM, Judith Mendez wrote: > Hi Tanmay, all, > > On 10/21/25 3:45 PM, Tanmay Kathpalia wrote: >> Some boards have SD card connectors where the power rail cannot be >> switched >> off by the driver. However there are various circumstances when a card >> might be re-initialized, such as after system resume, warm re-boot, or >> error handling. However, a UHS card will continue to use 1.8V signaling >> unless it is power cycled. >> >> If the card has not been power cycled, it may still be using 1.8V >> signaling. According to the SD spec., the Bus Speed Mode (function >> group 1) >> bits 2 to 4 are zero if the card is initialized at 3.3V signal level. >> Thus >> they can be used to determine if the card has already switched to 1.8V >> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >> transfer mode. > > This implementation broke am65 IDK board SD card boot, I have still > to check why this breaks only one board, potentially there might > be a quirk only for this board... But for now sending the question > in case anyone might have an idea what is going on & save me some > time. > > Thanks for reporting this. I had a deeper look at the code and found an issue that is likely the root cause of the failure on am65 IDK. During a normal cold boot with a UHS-capable host and UHS card, the voltage switch to 1.8V is already performed inside sd_send_op_cond() as part of the ACMD41 handshake, and this is recorded in mmc->ocr via the S18R bit. By the time mmc_startup() calls sd_get_capabilities(), the card is already operating at 1.8V and reports UHS bus speed modes, causing mmc_sd_card_using_v18() to return true. The warm-reboot recovery path then fires unconditionally and switches the host voltage a second time, which on boards like am65 IDK can leave the controller in a bad state. The fix is to guard the recovery path so it only activates when the voltage switch was not already performed during the current session: - if (mmc_sd_card_using_v18(mmc)) { + if (!(mmc->ocr & OCR_S18R) && mmc_sd_card_using_v18(mmc)) { Could you please try this change and let me know if it resolves the failure on am65 IDK? I will send the patch for review on the mailing list. Regards, Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-05-14 18:50 ` Kathpalia, Tanmay @ 2026-05-14 22:21 ` Judith Mendez 0 siblings, 0 replies; 17+ messages in thread From: Judith Mendez @ 2026-05-14 22:21 UTC (permalink / raw) To: Kathpalia, Tanmay, u-boot Cc: trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi, On 5/14/26 1:50 PM, Kathpalia, Tanmay wrote: > > On 5/14/2026 5:09 AM, Judith Mendez wrote: >> Hi Tanmay, all, >> >> On 10/21/25 3:45 PM, Tanmay Kathpalia wrote: >>> Some boards have SD card connectors where the power rail cannot be >>> switched >>> off by the driver. However there are various circumstances when a card >>> might be re-initialized, such as after system resume, warm re-boot, or >>> error handling. However, a UHS card will continue to use 1.8V signaling >>> unless it is power cycled. >>> >>> If the card has not been power cycled, it may still be using 1.8V >>> signaling. According to the SD spec., the Bus Speed Mode (function >>> group 1) >>> bits 2 to 4 are zero if the card is initialized at 3.3V signal level. >>> Thus >>> they can be used to determine if the card has already switched to 1.8V >>> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >>> transfer mode. >> >> This implementation broke am65 IDK board SD card boot, I have still >> to check why this breaks only one board, potentially there might >> be a quirk only for this board... But for now sending the question >> in case anyone might have an idea what is going on & save me some >> time. >> >> > > Thanks for reporting this. I had a deeper look at the code and found > an issue that is likely the root cause of the failure on am65 IDK. > > During a normal cold boot with a UHS-capable host and UHS card, the > voltage switch to 1.8V is already performed inside sd_send_op_cond() > as part of the ACMD41 handshake, and this is recorded in mmc->ocr via > the S18R bit. By the time mmc_startup() calls sd_get_capabilities(), > the card is already operating at 1.8V and reports UHS bus speed modes, > causing mmc_sd_card_using_v18() to return true. The warm-reboot > recovery path then fires unconditionally and switches the host voltage > a second time, which on boards like am65 IDK can leave the controller > in a bad state. > > The fix is to guard the recovery path so it only activates when the > voltage switch was not already performed during the current session: > > - if (mmc_sd_card_using_v18(mmc)) { > + if (!(mmc->ocr & OCR_S18R) && mmc_sd_card_using_v18(mmc)) { > > Could you please try this change and let me know if it resolves the > failure on am65 IDK? > > I will send the patch for review on the mailing list. > Seems like that did not work for me [0] :( [0] https://gist.github.com/jmenti/bb2dfc93630219a4d137edf2e20ce66c I might not have a chance to debug/respond here soon since ill be out until may 25, so until then, happy hacking :D ~ Judith ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2025-10-21 20:45 [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle Tanmay Kathpalia ` (2 preceding siblings ...) 2026-05-13 23:39 ` Judith Mendez @ 2026-05-16 9:44 ` Peng Fan 2026-05-16 9:43 ` Kathpalia, Tanmay 2026-05-16 11:44 ` Kathpalia, Tanmay 3 siblings, 2 replies; 17+ messages in thread From: Peng Fan @ 2026-05-16 9:44 UTC (permalink / raw) To: Tanmay Kathpalia, Judith Mendez Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Revisit this patch, since it break one board [1]. [1] https://lore.kernel.org/all/52ec8007-ce50-4f12-b796-4b8c2aa1822e@ti.com/ On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >Some boards have SD card connectors where the power rail cannot be switched >off by the driver. However there are various circumstances when a card >might be re-initialized, such as after system resume, warm re-boot, or >error handling. However, a UHS card will continue to use 1.8V signaling >unless it is power cycled. > >If the card has not been power cycled, it may still be using 1.8V >signaling. According to the SD spec., the Bus Speed Mode (function group 1) >bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >they can be used to determine if the card has already switched to 1.8V >signaling. Detect that situation and try to initialize a UHS-I (1.8V) >transfer mode. > >Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >--- > drivers/mmc/mmc.c | 55 ++++++++++++++++++++++++++++++++++++++--------- > include/mmc.h | 3 +++ > 2 files changed, 48 insertions(+), 10 deletions(-) > >diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >index ec61ed92e86..e1f62a5d0ad 100644 >--- a/drivers/mmc/mmc.c >+++ b/drivers/mmc/mmc.c >@@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) > > return 0; > } >+ >+static bool mmc_sd_card_using_v18(struct mmc *mmc) >+{ >+ /* >+ * According to the SD spec., the Bus Speed Mode (function group 1) bits >+ * 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >+ * they can be used to determine if the card has already switched to >+ * 1.8V signaling. >+ */ >+ bool volt = mmc->sd3_bus_mode & >+ (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); This is wrong. sd3_bus_mode is sd supported bits, not the current running bits. To detect the sd card running bits, need to use: (__be32_to_cpu(switch_status[4]) >> 24) & 0xF >+ return volt; >+} > #endif > > static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >@@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc *mmc) > ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); > struct mmc_data data; > int timeout; >-#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >- u32 sd3_bus_mode; >-#endif > > mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); > >@@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc *mmc) > if (mmc->version < SD_VERSION_3) > return 0; > >- sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >- if (sd3_bus_mode & SD_MODE_UHS_SDR104) >+ mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) > mmc->card_caps |= MMC_CAP(UHS_SDR104); >- if (sd3_bus_mode & SD_MODE_UHS_SDR50) >+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) > mmc->card_caps |= MMC_CAP(UHS_SDR50); >- if (sd3_bus_mode & SD_MODE_UHS_SDR25) >+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) > mmc->card_caps |= MMC_CAP(UHS_SDR25); >- if (sd3_bus_mode & SD_MODE_UHS_SDR12) >+ if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) > mmc->card_caps |= MMC_CAP(UHS_SDR12); >- if (sd3_bus_mode & SD_MODE_UHS_DDR50) >+ if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) > mmc->card_caps |= MMC_CAP(UHS_DDR50); > #endif > >@@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) > uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; > const struct mode_width_tuning *mwt; > #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >- bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >+ /* >+ * Enable UHS mode if the card advertises 1.8V support (S18R in OCR) >+ * or is already operating at 1.8V signaling. >+ */ >+ bool uhs_en = (mmc->ocr & OCR_S18R) || mmc_sd_card_using_v18(mmc); In theory, bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. OCR (including S18R/S18A) only reflects voltage switch negotiation capability and intent, not the current signaling voltage. So your sd card should have OCR_S18R returned per my understanding. > #else > bool uhs_en = false; > #endif >@@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) > err = sd_get_capabilities(mmc); > if (err) > return err; >+ >+#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >+ /* >+ * If the card has already switched to 1.8V signaling, then >+ * set the signal voltage to 1.8V. >+ */ >+ if (mmc_sd_card_using_v18(mmc)) { To switch voltage, ACMD41 is required, see mmc_switch_voltage. Forcing switch to 1.8 here has some risk. >+ /* >+ * During a signal voltage level switch, the clock must be gated >+ * for 5 ms according to the SD spec. >+ */ >+ mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >+ err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180); >+ if (err) >+ return err; >+ /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ >+ mdelay(10); >+ mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >+ } >+#endif A proper redesign is required. So I am going to revert this patch. Thanks Peng ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-05-16 9:44 ` Peng Fan @ 2026-05-16 9:43 ` Kathpalia, Tanmay 2026-05-16 11:44 ` Kathpalia, Tanmay 1 sibling, 0 replies; 17+ messages in thread From: Kathpalia, Tanmay @ 2026-05-16 9:43 UTC (permalink / raw) To: Peng Fan, Judith Mendez Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Peng, Thank you for reviewing and for the detailed feedback. On 5/16/2026 3:14 PM, Peng Fan wrote: > Revisit this patch, since it break one board [1]. > > [1] https://lore.kernel.org/all/52ec8007-ce50-4f12-b796-4b8c2aa1822e@ti.com/ > > On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >> Some boards have SD card connectors where the power rail cannot be switched >> off by the driver. However there are various circumstances when a card >> might be re-initialized, such as after system resume, warm re-boot, or >> error handling. However, a UHS card will continue to use 1.8V signaling >> unless it is power cycled. >> >> If the card has not been power cycled, it may still be using 1.8V >> signaling. According to the SD spec., the Bus Speed Mode (function group 1) >> bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >> they can be used to determine if the card has already switched to 1.8V >> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >> transfer mode. >> >> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >> --- >> drivers/mmc/mmc.c | 55 ++++++++++++++++++++++++++++++++++++++--------- >> include/mmc.h | 3 +++ >> 2 files changed, 48 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >> index ec61ed92e86..e1f62a5d0ad 100644 >> --- a/drivers/mmc/mmc.c >> +++ b/drivers/mmc/mmc.c >> @@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) >> >> return 0; >> } >> + >> +static bool mmc_sd_card_using_v18(struct mmc *mmc) >> +{ >> + /* >> + * According to the SD spec., the Bus Speed Mode (function group 1) bits >> + * 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >> + * they can be used to determine if the card has already switched to >> + * 1.8V signaling. >> + */ >> + bool volt = mmc->sd3_bus_mode & >> + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); > This is wrong. > sd3_bus_mode is sd supported bits, not the current running bits. > > To detect the sd card running bits, need to use: > (__be32_to_cpu(switch_status[4]) >> 24) & 0xF You are correct that sd3_bus_mode stores the supported bits - as can be seen in sd_get_capabilities() where it is filled from the CMD6 status response: mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; However, the intent here is not to read the currently active function code, but to use the supported bits as a proxy for the signaling voltage level. According to the SD Physical Layer Simplified Specification v9.0, Section 4.3.10.4 (Switch Function Command, CMD6): the UHS-I speed modes SDR50, SDR104, and DDR50 (function group 1 bits 2–4) are only available when the card is operating at 1.8V signaling. When the card is initialized at 3.3V, those bits read as zero. Therefore, if any of bits 2-4 are set in the supported field, we can safely infer the card is a UHS-I card and, when not power cycled, retains 1.8V signaling. Using switch_status[4] to read the currently active function would actually NOT work for this scenario. After a warm reboot, the card receives CMD0 (GO_IDLE_STATE), which resets the card's selected function back to 0 (SDR12/default) — even though the 1.8V signaling level is retained. So switch_status[4] would always return 0 in this path, making it unsuitable as a 1.8V indicator here. >> + return volt; >> +} >> #endif >> >> static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >> @@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc *mmc) >> ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); >> struct mmc_data data; >> int timeout; >> -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >> - u32 sd3_bus_mode; >> -#endif >> >> mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); >> >> @@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc *mmc) >> if (mmc->version < SD_VERSION_3) >> return 0; >> >> - sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >> - if (sd3_bus_mode & SD_MODE_UHS_SDR104) >> + mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) >> mmc->card_caps |= MMC_CAP(UHS_SDR104); >> - if (sd3_bus_mode & SD_MODE_UHS_SDR50) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) >> mmc->card_caps |= MMC_CAP(UHS_SDR50); >> - if (sd3_bus_mode & SD_MODE_UHS_SDR25) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) >> mmc->card_caps |= MMC_CAP(UHS_SDR25); >> - if (sd3_bus_mode & SD_MODE_UHS_SDR12) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) >> mmc->card_caps |= MMC_CAP(UHS_SDR12); >> - if (sd3_bus_mode & SD_MODE_UHS_DDR50) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) >> mmc->card_caps |= MMC_CAP(UHS_DDR50); >> #endif >> >> @@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) >> uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; >> const struct mode_width_tuning *mwt; >> #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >> - bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >> + /* >> + * Enable UHS mode if the card advertises 1.8V support (S18R in OCR) >> + * or is already operating at 1.8V signaling. >> + */ >> + bool uhs_en = (mmc->ocr & OCR_S18R) || mmc_sd_card_using_v18(mmc); > In theory, > > bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. > > OCR (including S18R/S18A) only reflects voltage switch negotiation > capability and intent, not the current signaling voltage. So your sd card > should have OCR_S18R returned per my understanding. I think there is a gap in understanding here. The scenario this patch targets is warm reboot or system resume - the card was never power cycled, so it is still operating at 1.8V signaling. In that situation, when ACMD41 is re-issued, the card will NOT assert S18A (Switching to 1.8V Accepted) in the OCR response, because the voltage negotiation already happened in the previous session and the card has no need to re-negotiate. Per the SD Physical Layer Simplified Specification v9.0, S18A is set only during the initial 1.8V request handshake. A card already running at 1.8V will not set S18A again on a subsequent ACMD41 after warm reset. This is exactly the corner case: OCR_S18R/S18A will be zero, yet the card is already at 1.8V. The existing code misses this entirely. >> #else >> bool uhs_en = false; >> #endif >> @@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) >> err = sd_get_capabilities(mmc); >> if (err) >> return err; >> + >> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >> + /* >> + * If the card has already switched to 1.8V signaling, then >> + * set the signal voltage to 1.8V. >> + */ >> + if (mmc_sd_card_using_v18(mmc)) { > To switch voltage, ACMD41 is required, see mmc_switch_voltage. > Forcing switch to 1.8 here has some risk. Agreed - ACMD41 is required to initiate a voltage switch on a card that is currently at 3.3V. However, in this path the card has already completed the voltage switch in a prior session and is still running at 1.8V. There is no card-side voltage transition happening; only the host controller needs to be reconfigured to match the 1.8V signaling level the card retained. Sending ACMD41 again in this context would be incorrect, as the card is not in a state to re-negotiate voltage. >> + /* >> + * During a signal voltage level switch, the clock must be gated >> + * for 5 ms according to the SD spec. >> + */ >> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >> + err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180); >> + if (err) >> + return err; >> + /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ >> + mdelay(10); >> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >> + } >> +#endif > A proper redesign is required. So I am going to revert this patch. > I would respectfully ask to reconsider before reverting. This patch is specifically targeted at the warm reboot / system resume / error recovery scenario where the card is not power cycled. The check in mmc_sd_card_using_v18() acts as a guard - it only triggers when the card is already at 1.8V and the normal OCR path did not catch it. On a cold boot with a fresh 3.3V card, the UHS supported bits will be zero and this path is never entered, so it cannot regress cold-boot behavior for any board. Regarding the reported regression [1], Judith mentioned that he will debug once he is back. If possible, let us wait for him to conclude before deciding to revert. This problem is not unique to U-Boot. Similar discussions and solutions have been proposed in the Linux community: https://lore.kernel.org/linux-mmc/a367a679-28f7-898a-c043-27df8c9c9aba@intel.com/ https://lore.kernel.org/linux-mmc/1506328144-13666-1-git-send-email-adrian.hunter@intel.com/ I am happy to rework this in v2 with a tighter guard condition (already addressed in [2]) once we have more information from the regression report. Please let me know your thoughts. Thanks, Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-05-16 9:44 ` Peng Fan 2026-05-16 9:43 ` Kathpalia, Tanmay @ 2026-05-16 11:44 ` Kathpalia, Tanmay 2026-05-27 23:22 ` Judith Mendez 1 sibling, 1 reply; 17+ messages in thread From: Kathpalia, Tanmay @ 2026-05-16 11:44 UTC (permalink / raw) To: Peng Fan, Judith Mendez Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Peng, Thank you for reviewing and for the detailed feedback. Apologies for the resend — my previous reply had an incorrect timestamp due to a timezone misconfiguration, which caused it to appear out of order in the thread. On 5/16/2026 3:14 PM, Peng Fan wrote: > Revisit this patch, since it break one board [1]. > > [1] https://lore.kernel.org/all/52ec8007-ce50-4f12-b796-4b8c2aa1822e@ti.com/ > > On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >> Some boards have SD card connectors where the power rail cannot be switched >> off by the driver. However there are various circumstances when a card >> might be re-initialized, such as after system resume, warm re-boot, or >> error handling. However, a UHS card will continue to use 1.8V signaling >> unless it is power cycled. >> >> If the card has not been power cycled, it may still be using 1.8V >> signaling. According to the SD spec., the Bus Speed Mode (function group 1) >> bits 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >> they can be used to determine if the card has already switched to 1.8V >> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >> transfer mode. >> >> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >> --- >> drivers/mmc/mmc.c | 55 ++++++++++++++++++++++++++++++++++++++--------- >> include/mmc.h | 3 +++ >> 2 files changed, 48 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >> index ec61ed92e86..e1f62a5d0ad 100644 >> --- a/drivers/mmc/mmc.c >> +++ b/drivers/mmc/mmc.c >> @@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc *mmc, int signal_voltage) >> >> return 0; >> } >> + >> +static bool mmc_sd_card_using_v18(struct mmc *mmc) >> +{ >> + /* >> + * According to the SD spec., the Bus Speed Mode (function group 1) bits >> + * 2 to 4 are zero if the card is initialized at 3.3V signal level. Thus >> + * they can be used to determine if the card has already switched to >> + * 1.8V signaling. >> + */ >> + bool volt = mmc->sd3_bus_mode & >> + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); > This is wrong. > sd3_bus_mode is sd supported bits, not the current running bits. > > To detect the sd card running bits, need to use: > (__be32_to_cpu(switch_status[4]) >> 24) & 0xF You are correct that sd3_bus_mode stores the supported bits - as can be seen in sd_get_capabilities() where it is filled from the CMD6 status response: mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; However, the intent here is not to read the currently active function code, but to use the supported bits as a proxy for the signaling voltage level. According to the SD Physical Layer Simplified Specification v9.0, Section 4.3.10.4 (Switch Function Command, CMD6): the UHS-I speed modes SDR50, SDR104, and DDR50 (function group 1 bits 2–4) are only available when the card is operating at 1.8V signaling. When the card is initialized at 3.3V, those bits read as zero. Therefore, if any of bits 2-4 are set in the supported field, we can safely infer the card is a UHS-I card and, when not power cycled, retains 1.8V signaling. Using switch_status[4] to read the currently active function would actually NOT work for this scenario. After a warm reboot, the card receives CMD0 (GO_IDLE_STATE), which resets the card's selected function back to 0 (SDR12/default) — even though the 1.8V signaling level is retained. So switch_status[4] would always return 0 in this path, making it unsuitable as a 1.8V indicator here. >> + return volt; >> +} >> #endif >> >> static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >> @@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc *mmc) >> ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); >> struct mmc_data data; >> int timeout; >> -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >> - u32 sd3_bus_mode; >> -#endif >> >> mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); >> >> @@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc *mmc) >> if (mmc->version < SD_VERSION_3) >> return 0; >> >> - sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >> - if (sd3_bus_mode & SD_MODE_UHS_SDR104) >> + mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) >> mmc->card_caps |= MMC_CAP(UHS_SDR104); >> - if (sd3_bus_mode & SD_MODE_UHS_SDR50) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) >> mmc->card_caps |= MMC_CAP(UHS_SDR50); >> - if (sd3_bus_mode & SD_MODE_UHS_SDR25) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) >> mmc->card_caps |= MMC_CAP(UHS_SDR25); >> - if (sd3_bus_mode & SD_MODE_UHS_SDR12) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) >> mmc->card_caps |= MMC_CAP(UHS_SDR12); >> - if (sd3_bus_mode & SD_MODE_UHS_DDR50) >> + if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) >> mmc->card_caps |= MMC_CAP(UHS_DDR50); >> #endif >> >> @@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) >> uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; >> const struct mode_width_tuning *mwt; >> #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >> - bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >> + /* >> + * Enable UHS mode if the card advertises 1.8V support (S18R in OCR) >> + * or is already operating at 1.8V signaling. >> + */ >> + bool uhs_en = (mmc->ocr & OCR_S18R) || mmc_sd_card_using_v18(mmc); > In theory, > > bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. > > OCR (including S18R/S18A) only reflects voltage switch negotiation > capability and intent, not the current signaling voltage. So your sd card > should have OCR_S18R returned per my understanding. I think there is a gap in understanding here. The scenario this patch targets is warm reboot or system resume - the card was never power cycled, so it is still operating at 1.8V signaling. In that situation, when ACMD41 is re-issued, the card will NOT assert S18A (Switching to 1.8V Accepted) in the OCR response, because the voltage negotiation already happened in the previous session and the card has no need to re-negotiate. Per the SD Physical Layer Simplified Specification v9.0, S18A is set only during the initial 1.8V request handshake. A card already running at 1.8V will not set S18A again on a subsequent ACMD41 after warm reset. This is exactly the corner case: OCR_S18R/S18A will be zero, yet the card is already at 1.8V. The existing code misses this entirely. >> #else >> bool uhs_en = false; >> #endif >> @@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) >> err = sd_get_capabilities(mmc); >> if (err) >> return err; >> + >> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >> + /* >> + * If the card has already switched to 1.8V signaling, then >> + * set the signal voltage to 1.8V. >> + */ >> + if (mmc_sd_card_using_v18(mmc)) { > To switch voltage, ACMD41 is required, see mmc_switch_voltage. > Forcing switch to 1.8 here has some risk. Agreed - ACMD41 is required to initiate a voltage switch on a card that is currently at 3.3V. However, in this path the card has already completed the voltage switch in a prior session and is still running at 1.8V. There is no card-side voltage transition happening; only the host controller needs to be reconfigured to match the 1.8V signaling level the card retained. Sending ACMD41 again in this context would be incorrect, as the card is not in a state to re-negotiate voltage. >> + /* >> + * During a signal voltage level switch, the clock must be gated >> + * for 5 ms according to the SD spec. >> + */ >> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >> + err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180); >> + if (err) >> + return err; >> + /* Keep clock gated for at least 10 ms, though spec only says 5 ms */ >> + mdelay(10); >> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >> + } >> +#endif > A proper redesign is required. So I am going to revert this patch. > I would respectfully ask to reconsider before reverting. This patch is specifically targeted at the warm reboot / system resume / error recovery scenario where the card is not power cycled. The check in mmc_sd_card_using_v18() acts as a guard - it only triggers when the card is already at 1.8V and the normal OCR path did not catch it. On a cold boot with a fresh 3.3V card, the UHS supported bits will be zero and this path is never entered, so it cannot regress cold-boot behavior for any board. Regarding the reported regression [1], Judith mentioned that he will debug once he is back. If possible, let us wait for him to conclude before deciding to revert. This problem is not unique to U-Boot. Similar discussions and solutions have been proposed in the Linux community: https://lore.kernel.org/linux-mmc/a367a679-28f7-898a-c043-27df8c9c9aba@intel.com/ https://lore.kernel.org/linux-mmc/1506328144-13666-1-git-send-email-adrian.hunter@intel.com/ I am happy to rework this in v2 with a tighter guard condition (already addressed in [2]) once we have more information from the regression report. Please let me know your thoughts. Thanks, Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-05-16 11:44 ` Kathpalia, Tanmay @ 2026-05-27 23:22 ` Judith Mendez 2026-05-29 17:21 ` Kathpalia, Tanmay 0 siblings, 1 reply; 17+ messages in thread From: Judith Mendez @ 2026-05-27 23:22 UTC (permalink / raw) To: Kathpalia, Tanmay, Peng Fan Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Kathpalia, On 5/16/26 6:44 AM, Kathpalia, Tanmay wrote: > Hi Peng, > Thank you for reviewing and for the detailed feedback. Apologies for > the resend — my previous reply had an incorrect timestamp due to a > timezone misconfiguration, which caused it to appear out of order in > the thread. > > On 5/16/2026 3:14 PM, Peng Fan wrote: >> Revisit this patch, since it break one board [1]. >> >> [1] https://lore.kernel.org/all/52ec8007-ce50-4f12- >> b796-4b8c2aa1822e@ti.com/ >> >> On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >>> Some boards have SD card connectors where the power rail cannot be >>> switched >>> off by the driver. However there are various circumstances when a card >>> might be re-initialized, such as after system resume, warm re-boot, or >>> error handling. However, a UHS card will continue to use 1.8V signaling >>> unless it is power cycled. >>> >>> If the card has not been power cycled, it may still be using 1.8V >>> signaling. According to the SD spec., the Bus Speed Mode (function >>> group 1) >>> bits 2 to 4 are zero if the card is initialized at 3.3V signal level. >>> Thus >>> they can be used to determine if the card has already switched to 1.8V >>> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >>> transfer mode. >>> >>> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>> --- >>> drivers/mmc/mmc.c | 55 ++++++++++++++++++++++++++++++++++++++--------- >>> include/mmc.h | 3 +++ >>> 2 files changed, 48 insertions(+), 10 deletions(-) >>> >>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >>> index ec61ed92e86..e1f62a5d0ad 100644 >>> --- a/drivers/mmc/mmc.c >>> +++ b/drivers/mmc/mmc.c >>> @@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc *mmc, >>> int signal_voltage) >>> >>> return 0; >>> } >>> + >>> +static bool mmc_sd_card_using_v18(struct mmc *mmc) >>> +{ >>> + /* >>> + * According to the SD spec., the Bus Speed Mode (function group >>> 1) bits >>> + * 2 to 4 are zero if the card is initialized at 3.3V signal >>> level. Thus >>> + * they can be used to determine if the card has already >>> switched to >>> + * 1.8V signaling. >>> + */ >>> + bool volt = mmc->sd3_bus_mode & >>> + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | >>> SD_MODE_UHS_DDR50); >> This is wrong. >> sd3_bus_mode is sd supported bits, not the current running bits. >> >> To detect the sd card running bits, need to use: >> (__be32_to_cpu(switch_status[4]) >> 24) & 0xF > > You are correct that sd3_bus_mode stores the supported bits - as can be > seen in sd_get_capabilities() where it is filled from the CMD6 status > response: > > mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; > > However, the intent here is not to read the currently active function > code, but to use the supported bits as a proxy for the signaling voltage > level. > > According to the SD Physical Layer Simplified Specification v9.0, > Section 4.3.10.4 (Switch Function Command, CMD6): the UHS-I speed modes > SDR50, SDR104, and DDR50 (function group 1 bits 2–4) are only available > when the card is operating at 1.8V signaling. When the card is > initialized at 3.3V, those bits read as zero. Therefore, if any of bits > 2-4 are set in the supported field, we can safely infer the card is a > UHS-I card and, when not power cycled, retains 1.8V signaling. > > Using switch_status[4] to read the currently active function would > actually NOT work for this scenario. After a warm reboot, the card > receives CMD0 (GO_IDLE_STATE), which resets the card's selected function > back to 0 (SDR12/default) — even though the 1.8V signaling level is > retained. So switch_status[4] would always return 0 in this path, > making it unsuitable as a 1.8V indicator here. > >>> + return volt; >>> +} >>> #endif >>> >>> static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >>> @@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc *mmc) >>> ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); >>> struct mmc_data data; >>> int timeout; >>> -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>> - u32 sd3_bus_mode; >>> -#endif >>> >>> mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); >>> >>> @@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc *mmc) >>> if (mmc->version < SD_VERSION_3) >>> return 0; >>> >>> - sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>> - if (sd3_bus_mode & SD_MODE_UHS_SDR104) >>> + mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) >>> mmc->card_caps |= MMC_CAP(UHS_SDR104); >>> - if (sd3_bus_mode & SD_MODE_UHS_SDR50) >>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) >>> mmc->card_caps |= MMC_CAP(UHS_SDR50); >>> - if (sd3_bus_mode & SD_MODE_UHS_SDR25) >>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) >>> mmc->card_caps |= MMC_CAP(UHS_SDR25); >>> - if (sd3_bus_mode & SD_MODE_UHS_SDR12) >>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) >>> mmc->card_caps |= MMC_CAP(UHS_SDR12); >>> - if (sd3_bus_mode & SD_MODE_UHS_DDR50) >>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) >>> mmc->card_caps |= MMC_CAP(UHS_DDR50); >>> #endif >>> >>> @@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct mmc >>> *mmc, uint card_caps) >>> uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; >>> const struct mode_width_tuning *mwt; >>> #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>> - bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >>> + /* >>> + * Enable UHS mode if the card advertises 1.8V support (S18R in >>> OCR) >>> + * or is already operating at 1.8V signaling. >>> + */ >>> + bool uhs_en = (mmc->ocr & OCR_S18R) || mmc_sd_card_using_v18(mmc); >> In theory, >> >> bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. >> >> OCR (including S18R/S18A) only reflects voltage switch negotiation >> capability and intent, not the current signaling voltage. So your sd card >> should have OCR_S18R returned per my understanding. > > I think there is a gap in understanding here. The scenario this patch > targets is warm reboot or system resume - the card was never power cycled, > so it is still operating at 1.8V signaling. > > In that situation, when ACMD41 is re-issued, the card will NOT assert > S18A (Switching to 1.8V Accepted) in the OCR response, because the > voltage negotiation already happened in the previous session and the card > has no need to re-negotiate. Per the SD Physical Layer Simplified > Specification v9.0, S18A is set only during the initial 1.8V request > handshake. A card already running at 1.8V will not set S18A again on a > subsequent ACMD41 after warm reset. > > This is exactly the corner case: OCR_S18R/S18A will be zero, yet the card > is already at 1.8V. The existing code misses this entirely. > >>> #else >>> bool uhs_en = false; >>> #endif >>> @@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) >>> err = sd_get_capabilities(mmc); >>> if (err) >>> return err; >>> + >>> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>> + /* >>> + * If the card has already switched to 1.8V signaling, then >>> + * set the signal voltage to 1.8V. >>> + */ >>> + if (mmc_sd_card_using_v18(mmc)) { >> To switch voltage, ACMD41 is required, see mmc_switch_voltage. >> Forcing switch to 1.8 here has some risk. > > Agreed - ACMD41 is required to initiate a voltage switch on a card that is > currently at 3.3V. However, in this path the card has already completed > the voltage switch in a prior session and is still running at 1.8V. There > is no card-side voltage transition happening; only the host controller > needs to be reconfigured to match the 1.8V signaling level the card > retained. Sending ACMD41 again in this context would be incorrect, as the > card is not in a state to re-negotiate voltage. > >>> + /* >>> + * During a signal voltage level switch, the clock must >>> be gated >>> + * for 5 ms according to the SD spec. >>> + */ >>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >>> + err = mmc_set_signal_voltage(mmc, MMC_SIGNAL_VOLTAGE_180); >>> + if (err) >>> + return err; >>> + /* Keep clock gated for at least 10 ms, though spec only >>> says 5 ms */ >>> + mdelay(10); >>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >>> + } >>> +#endif >> A proper redesign is required. So I am going to revert this patch. >> > > I would respectfully ask to reconsider before reverting. This patch is > specifically targeted at the warm reboot / system resume / error recovery > scenario where the card is not power cycled. The check in > mmc_sd_card_using_v18() acts as a guard - it only triggers when the > card is already at 1.8V and the normal OCR path did not catch it. On > a cold boot with a fresh 3.3V card, the UHS supported bits will be zero > and this path is never entered, so it cannot regress cold-boot behavior > for any board. > > Regarding the reported regression [1], Judith mentioned that he will > debug once he is back. If possible, let us wait for him to conclude > before deciding to revert. So I started looking at this. So far, I have found that on AM65 u-boot, we had been enumerating to SDR104 mode once during boot and finally resolve to HS mode right before loading the kernel. Also, sd3_bus_mode=0x1f at u-boot stage. Something weird: from the schematics, its does not seem like the IOs are switching to 1.8V with on board hardware PMIC. It seems like the call stack has changed where previously uhs_en=0 in u-boot and now with your commit uhs_en=1, right before loading the kernel. After this, we call am654_sdhci_set_ios_post multiple times at mode=0 & signal_voltage=0x2 until mmc_init failure. I realize this is not the most stable platform and there could be hardware issues for SD. Perhaps it is a good idea to create a quirk to skip over this section for these kinds of platforms? What are your thoughts? I will continue on this debug and come back if I find more useful information. ~ Judith > > This problem is not unique to U-Boot. Similar discussions and solutions > have been proposed in the Linux community: > > https://lore.kernel.org/linux-mmc/a367a679-28f7-898a- > c043-27df8c9c9aba@intel.com/ > https://lore.kernel.org/linux-mmc/1506328144-13666-1-git-send-email- > adrian.hunter@intel.com/ > > I am happy to rework this in v2 with a tighter guard condition (already > addressed in [2]) once we have more information from the regression > report. > > Please let me know your thoughts. > > Thanks, > Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-05-27 23:22 ` Judith Mendez @ 2026-05-29 17:21 ` Kathpalia, Tanmay 2026-06-08 15:19 ` Judith Mendez 0 siblings, 1 reply; 17+ messages in thread From: Kathpalia, Tanmay @ 2026-05-29 17:21 UTC (permalink / raw) To: Judith Mendez, Peng Fan Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Judith, Thank you for the information. Let me share my analysis based on what you have described. On 5/28/2026 4:52 AM, Judith Mendez wrote: > Hi Kathpalia, > > On 5/16/26 6:44 AM, Kathpalia, Tanmay wrote: >> Hi Peng, >> Thank you for reviewing and for the detailed feedback. Apologies for >> the resend — my previous reply had an incorrect timestamp due to a >> timezone misconfiguration, which caused it to appear out of order in >> the thread. >> >> On 5/16/2026 3:14 PM, Peng Fan wrote: >>> Revisit this patch, since it break one board [1]. >>> >>> [1] https://lore.kernel.org/all/52ec8007-ce50-4f12- >>> b796-4b8c2aa1822e@ti.com/ >>> >>> On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >>>> Some boards have SD card connectors where the power rail cannot be >>>> switched >>>> off by the driver. However there are various circumstances when a card >>>> might be re-initialized, such as after system resume, warm re-boot, or >>>> error handling. However, a UHS card will continue to use 1.8V >>>> signaling >>>> unless it is power cycled. >>>> >>>> If the card has not been power cycled, it may still be using 1.8V >>>> signaling. According to the SD spec., the Bus Speed Mode (function >>>> group 1) >>>> bits 2 to 4 are zero if the card is initialized at 3.3V signal >>>> level. Thus >>>> they can be used to determine if the card has already switched to 1.8V >>>> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >>>> transfer mode. >>>> >>>> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>>> --- >>>> drivers/mmc/mmc.c | 55 ++++++++++++++++++++++++++++++++++++++--------- >>>> include/mmc.h | 3 +++ >>>> 2 files changed, 48 insertions(+), 10 deletions(-) >>>> >>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >>>> index ec61ed92e86..e1f62a5d0ad 100644 >>>> --- a/drivers/mmc/mmc.c >>>> +++ b/drivers/mmc/mmc.c >>>> @@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc *mmc, >>>> int signal_voltage) >>>> >>>> return 0; >>>> } >>>> + >>>> +static bool mmc_sd_card_using_v18(struct mmc *mmc) >>>> +{ >>>> + /* >>>> + * According to the SD spec., the Bus Speed Mode (function >>>> group 1) bits >>>> + * 2 to 4 are zero if the card is initialized at 3.3V signal >>>> level. Thus >>>> + * they can be used to determine if the card has already >>>> switched to >>>> + * 1.8V signaling. >>>> + */ >>>> + bool volt = mmc->sd3_bus_mode & >>>> + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | >>>> SD_MODE_UHS_DDR50); >>> This is wrong. >>> sd3_bus_mode is sd supported bits, not the current running bits. >>> >>> To detect the sd card running bits, need to use: >>> (__be32_to_cpu(switch_status[4]) >> 24) & 0xF >> >> You are correct that sd3_bus_mode stores the supported bits - as can be >> seen in sd_get_capabilities() where it is filled from the CMD6 status >> response: >> >> mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >> >> However, the intent here is not to read the currently active function >> code, but to use the supported bits as a proxy for the signaling voltage >> level. >> >> According to the SD Physical Layer Simplified Specification v9.0, >> Section 4.3.10.4 (Switch Function Command, CMD6): the UHS-I speed modes >> SDR50, SDR104, and DDR50 (function group 1 bits 2–4) are only available >> when the card is operating at 1.8V signaling. When the card is >> initialized at 3.3V, those bits read as zero. Therefore, if any of bits >> 2-4 are set in the supported field, we can safely infer the card is a >> UHS-I card and, when not power cycled, retains 1.8V signaling. >> >> Using switch_status[4] to read the currently active function would >> actually NOT work for this scenario. After a warm reboot, the card >> receives CMD0 (GO_IDLE_STATE), which resets the card's selected function >> back to 0 (SDR12/default) — even though the 1.8V signaling level is >> retained. So switch_status[4] would always return 0 in this path, >> making it unsuitable as a 1.8V indicator here. >> >>>> + return volt; >>>> +} >>>> #endif >>>> >>>> static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >>>> @@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc *mmc) >>>> ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); >>>> struct mmc_data data; >>>> int timeout; >>>> -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>> - u32 sd3_bus_mode; >>>> -#endif >>>> >>>> mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); >>>> >>>> @@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc >>>> *mmc) >>>> if (mmc->version < SD_VERSION_3) >>>> return 0; >>>> >>>> - sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR104) >>>> + mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) >>>> mmc->card_caps |= MMC_CAP(UHS_SDR104); >>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR50) >>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) >>>> mmc->card_caps |= MMC_CAP(UHS_SDR50); >>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR25) >>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) >>>> mmc->card_caps |= MMC_CAP(UHS_SDR25); >>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR12) >>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) >>>> mmc->card_caps |= MMC_CAP(UHS_SDR12); >>>> - if (sd3_bus_mode & SD_MODE_UHS_DDR50) >>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) >>>> mmc->card_caps |= MMC_CAP(UHS_DDR50); >>>> #endif >>>> >>>> @@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct >>>> mmc *mmc, uint card_caps) >>>> uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; >>>> const struct mode_width_tuning *mwt; >>>> #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>> - bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >>>> + /* >>>> + * Enable UHS mode if the card advertises 1.8V support (S18R >>>> in OCR) >>>> + * or is already operating at 1.8V signaling. >>>> + */ >>>> + bool uhs_en = (mmc->ocr & OCR_S18R) || >>>> mmc_sd_card_using_v18(mmc); >>> In theory, >>> >>> bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. >>> >>> OCR (including S18R/S18A) only reflects voltage switch negotiation >>> capability and intent, not the current signaling voltage. So your sd >>> card >>> should have OCR_S18R returned per my understanding. >> >> I think there is a gap in understanding here. The scenario this patch >> targets is warm reboot or system resume - the card was never power >> cycled, >> so it is still operating at 1.8V signaling. >> >> In that situation, when ACMD41 is re-issued, the card will NOT assert >> S18A (Switching to 1.8V Accepted) in the OCR response, because the >> voltage negotiation already happened in the previous session and the >> card >> has no need to re-negotiate. Per the SD Physical Layer Simplified >> Specification v9.0, S18A is set only during the initial 1.8V request >> handshake. A card already running at 1.8V will not set S18A again on a >> subsequent ACMD41 after warm reset. >> >> This is exactly the corner case: OCR_S18R/S18A will be zero, yet the >> card >> is already at 1.8V. The existing code misses this entirely. >> >>>> #else >>>> bool uhs_en = false; >>>> #endif >>>> @@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) >>>> err = sd_get_capabilities(mmc); >>>> if (err) >>>> return err; >>>> + >>>> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>> + /* >>>> + * If the card has already switched to 1.8V signaling, then >>>> + * set the signal voltage to 1.8V. >>>> + */ >>>> + if (mmc_sd_card_using_v18(mmc)) { >>> To switch voltage, ACMD41 is required, see mmc_switch_voltage. >>> Forcing switch to 1.8 here has some risk. >> >> Agreed - ACMD41 is required to initiate a voltage switch on a card >> that is >> currently at 3.3V. However, in this path the card has already completed >> the voltage switch in a prior session and is still running at 1.8V. >> There >> is no card-side voltage transition happening; only the host controller >> needs to be reconfigured to match the 1.8V signaling level the card >> retained. Sending ACMD41 again in this context would be incorrect, as >> the >> card is not in a state to re-negotiate voltage. >> >>>> + /* >>>> + * During a signal voltage level switch, the clock >>>> must be gated >>>> + * for 5 ms according to the SD spec. >>>> + */ >>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >>>> + err = mmc_set_signal_voltage(mmc, >>>> MMC_SIGNAL_VOLTAGE_180); >>>> + if (err) >>>> + return err; >>>> + /* Keep clock gated for at least 10 ms, though spec >>>> only says 5 ms */ >>>> + mdelay(10); >>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >>>> + } >>>> +#endif >>> A proper redesign is required. So I am going to revert this patch. >>> >> >> I would respectfully ask to reconsider before reverting. This patch is >> specifically targeted at the warm reboot / system resume / error >> recovery >> scenario where the card is not power cycled. The check in >> mmc_sd_card_using_v18() acts as a guard - it only triggers when the >> card is already at 1.8V and the normal OCR path did not catch it. On >> a cold boot with a fresh 3.3V card, the UHS supported bits will be zero >> and this path is never entered, so it cannot regress cold-boot behavior >> for any board. >> >> Regarding the reported regression [1], Judith mentioned that he will >> debug once he is back. If possible, let us wait for him to conclude >> before deciding to revert. > > So I started looking at this. So far, I have found that on AM65 u-boot, > we had been enumerating to SDR104 mode once during boot and finally > resolve to HS mode right before loading the kernel. This seems to be the root of the issue. Entering SDR104 mode transitions the SD card, the IO signal lines, and the host controller all to 1.8V signaling. Once that transition happens, attempting to switch back to HS mode (which requires 3.3V) is not possible without a full power cycle of the card. This is explicitly stated in the SD Physical Layer Simplified Specification, Section "UHS-I Bus Speed Modes Selection Sequence": "Once the card enters 1.8V signaling mode, the card cannot be switched to SPI mode or 3.3V signaling without power cycle. If the card receives CMD0, card returns to Idle state but still works with SDR12 timing." So the failure you are seeing is not introduced by my patch — the card was already non-recoverable to 3.3V from the moment it entered SDR104 earlier in the boot. > > Also, sd3_bus_mode=0x1f at u-boot stage. This confirms the card was already operating in 1.8V signaling when your debug point was reached. For reference, on a fresh cold boot at 3.3V, the CMD6 available functions table shows sd3_bus_mode should read 0x07 (only SDR12/SDR25/HS bits set). The value 0x1f means bits for SDR50, SDR104, and DDR50 are also set, which per the spec only happens when the card is initialized at 1.8V signaling. This is exactly what mmc_sd_card_using_v18() is designed to detect. > > Something weird: from the schematics, its does not seem like the IOs are > switching to 1.8V with on board hardware PMIC. This is worth investigating further. If the IO lines are confirmed to be stuck at 3.3V while the card is operating at 1.8V signaling, that would itself be a pre-existing hardware or driver issue — the IO voltage and the card signaling voltage must always be in sync. I would suggest: 1. Verify the voltage regulator driving the IO lines (Vccq) and confirm whether am654_sdhci_set_ios_post correctly switches it to 1.8V when UHS modes are selected. If Vccq is not switching, that is a separate bug in the am654 driver or the regulator configuration. 2. Try using UHS_SDR12 or UHS_SDR25 as the operating mode instead of HS. Since the card has already transitioned to 1.8V, the UHS-I modes are the correct and spec-compliant modes to use. Running HS mode at 1.8V is not a valid combination. > > It seems like the call stack has changed where previously > uhs_en=0 in u-boot and now with your commit uhs_en=1, right before > loading the kernel. Correct. Previously, even though the card was operating at 1.8V (as evidenced by sd3_bus_mode=0x1f), the code was not checking the card's function group 1 to detect this. So the host stayed at 3.3V while the card was at 1.8V — an incorrect but silently failing combination on platforms where the mismatch happens to be tolerated. With the patch, we correctly detect the 1.8V state and instruct the host to match. The subsequent failure you observe is because the host-side IO voltage switch (Vccq) appears to not be working. > After this, we call am654_sdhci_set_ios_post > multiple times at mode=0 & signal_voltage=0x2 until mmc_init failure. mode=0 corresponds to MMC_LEGACY, which is a 3.3V mode. Having signal_voltage=0x2 (1.8V) alongside MMC_LEGACY is not a valid combination. This suggests the mode selection logic is landing on MMC_LEGACY while the voltage has already been switched to 1.8V, which will always fail. The fix should be to ensure the card operates in a UHS-I mode when at 1.8V, not fall back to MMC_LEGACY. > > I realize this is not the most stable platform and there could > be hardware issues for SD. Perhaps it is a good idea to create > a quirk to skip over this section for these kinds of platforms? I would prefer to avoid a quirk at this stage, as the underlying behavior — the card being at 1.8V after a prior boot — is spec-compliant and real. A quirk would just mask the issue on AM65 rather than fix the actual IO voltage switching problem. > > What are your thoughts? I will continue on this debug > and come back if I find more useful information. > > ~ Judith > Hope this helps, looking forward to your further findings. Thanks, Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-05-29 17:21 ` Kathpalia, Tanmay @ 2026-06-08 15:19 ` Judith Mendez 2026-06-09 7:51 ` Kathpalia, Tanmay 2026-07-13 9:45 ` Kathpalia, Tanmay 0 siblings, 2 replies; 17+ messages in thread From: Judith Mendez @ 2026-06-08 15:19 UTC (permalink / raw) To: Kathpalia, Tanmay, Peng Fan Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Tanmay, On 5/29/26 12:21 PM, Kathpalia, Tanmay wrote: > Hi Judith, > > Thank you for the information. Let me share my analysis based on > what you have described. > > On 5/28/2026 4:52 AM, Judith Mendez wrote: >> Hi Kathpalia, >> >> On 5/16/26 6:44 AM, Kathpalia, Tanmay wrote: >>> Hi Peng, >>> Thank you for reviewing and for the detailed feedback. Apologies for >>> the resend — my previous reply had an incorrect timestamp due to a >>> timezone misconfiguration, which caused it to appear out of order in >>> the thread. >>> >>> On 5/16/2026 3:14 PM, Peng Fan wrote: >>>> Revisit this patch, since it break one board [1]. >>>> >>>> [1] https://lore.kernel.org/all/52ec8007-ce50-4f12- >>>> b796-4b8c2aa1822e@ti.com/ >>>> >>>> On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >>>>> Some boards have SD card connectors where the power rail cannot be >>>>> switched >>>>> off by the driver. However there are various circumstances when a card >>>>> might be re-initialized, such as after system resume, warm re-boot, or >>>>> error handling. However, a UHS card will continue to use 1.8V >>>>> signaling >>>>> unless it is power cycled. >>>>> >>>>> If the card has not been power cycled, it may still be using 1.8V >>>>> signaling. According to the SD spec., the Bus Speed Mode (function >>>>> group 1) >>>>> bits 2 to 4 are zero if the card is initialized at 3.3V signal >>>>> level. Thus >>>>> they can be used to determine if the card has already switched to 1.8V >>>>> signaling. Detect that situation and try to initialize a UHS-I (1.8V) >>>>> transfer mode. >>>>> >>>>> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>>>> --- >>>>> drivers/mmc/mmc.c | 55 ++++++++++++++++++++++++++++++++++++++--------- >>>>> include/mmc.h | 3 +++ >>>>> 2 files changed, 48 insertions(+), 10 deletions(-) >>>>> >>>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >>>>> index ec61ed92e86..e1f62a5d0ad 100644 >>>>> --- a/drivers/mmc/mmc.c >>>>> +++ b/drivers/mmc/mmc.c >>>>> @@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc *mmc, >>>>> int signal_voltage) >>>>> >>>>> return 0; >>>>> } >>>>> + >>>>> +static bool mmc_sd_card_using_v18(struct mmc *mmc) >>>>> +{ >>>>> + /* >>>>> + * According to the SD spec., the Bus Speed Mode (function >>>>> group 1) bits >>>>> + * 2 to 4 are zero if the card is initialized at 3.3V signal >>>>> level. Thus >>>>> + * they can be used to determine if the card has already >>>>> switched to >>>>> + * 1.8V signaling. >>>>> + */ >>>>> + bool volt = mmc->sd3_bus_mode & >>>>> + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | >>>>> SD_MODE_UHS_DDR50); >>>> This is wrong. >>>> sd3_bus_mode is sd supported bits, not the current running bits. >>>> >>>> To detect the sd card running bits, need to use: >>>> (__be32_to_cpu(switch_status[4]) >> 24) & 0xF >>> >>> You are correct that sd3_bus_mode stores the supported bits - as can be >>> seen in sd_get_capabilities() where it is filled from the CMD6 status >>> response: >>> >>> mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>> >>> However, the intent here is not to read the currently active function >>> code, but to use the supported bits as a proxy for the signaling voltage >>> level. >>> >>> According to the SD Physical Layer Simplified Specification v9.0, >>> Section 4.3.10.4 (Switch Function Command, CMD6): the UHS-I speed modes >>> SDR50, SDR104, and DDR50 (function group 1 bits 2–4) are only available >>> when the card is operating at 1.8V signaling. When the card is >>> initialized at 3.3V, those bits read as zero. Therefore, if any of bits >>> 2-4 are set in the supported field, we can safely infer the card is a >>> UHS-I card and, when not power cycled, retains 1.8V signaling. >>> >>> Using switch_status[4] to read the currently active function would >>> actually NOT work for this scenario. After a warm reboot, the card >>> receives CMD0 (GO_IDLE_STATE), which resets the card's selected function >>> back to 0 (SDR12/default) — even though the 1.8V signaling level is >>> retained. So switch_status[4] would always return 0 in this path, >>> making it unsuitable as a 1.8V indicator here. >>> >>>>> + return volt; >>>>> +} >>>>> #endif >>>>> >>>>> static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >>>>> @@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc *mmc) >>>>> ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); >>>>> struct mmc_data data; >>>>> int timeout; >>>>> -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>> - u32 sd3_bus_mode; >>>>> -#endif >>>>> >>>>> mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); >>>>> >>>>> @@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc >>>>> *mmc) >>>>> if (mmc->version < SD_VERSION_3) >>>>> return 0; >>>>> >>>>> - sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR104) >>>>> + mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) >>>>> mmc->card_caps |= MMC_CAP(UHS_SDR104); >>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR50) >>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) >>>>> mmc->card_caps |= MMC_CAP(UHS_SDR50); >>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR25) >>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) >>>>> mmc->card_caps |= MMC_CAP(UHS_SDR25); >>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR12) >>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) >>>>> mmc->card_caps |= MMC_CAP(UHS_SDR12); >>>>> - if (sd3_bus_mode & SD_MODE_UHS_DDR50) >>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) >>>>> mmc->card_caps |= MMC_CAP(UHS_DDR50); >>>>> #endif >>>>> >>>>> @@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct >>>>> mmc *mmc, uint card_caps) >>>>> uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; >>>>> const struct mode_width_tuning *mwt; >>>>> #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>> - bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >>>>> + /* >>>>> + * Enable UHS mode if the card advertises 1.8V support (S18R >>>>> in OCR) >>>>> + * or is already operating at 1.8V signaling. >>>>> + */ >>>>> + bool uhs_en = (mmc->ocr & OCR_S18R) || >>>>> mmc_sd_card_using_v18(mmc); >>>> In theory, >>>> >>>> bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. >>>> >>>> OCR (including S18R/S18A) only reflects voltage switch negotiation >>>> capability and intent, not the current signaling voltage. So your sd >>>> card >>>> should have OCR_S18R returned per my understanding. >>> >>> I think there is a gap in understanding here. The scenario this patch >>> targets is warm reboot or system resume - the card was never power >>> cycled, >>> so it is still operating at 1.8V signaling. >>> >>> In that situation, when ACMD41 is re-issued, the card will NOT assert >>> S18A (Switching to 1.8V Accepted) in the OCR response, because the >>> voltage negotiation already happened in the previous session and the >>> card >>> has no need to re-negotiate. Per the SD Physical Layer Simplified >>> Specification v9.0, S18A is set only during the initial 1.8V request >>> handshake. A card already running at 1.8V will not set S18A again on a >>> subsequent ACMD41 after warm reset. >>> >>> This is exactly the corner case: OCR_S18R/S18A will be zero, yet the >>> card >>> is already at 1.8V. The existing code misses this entirely. >>> >>>>> #else >>>>> bool uhs_en = false; >>>>> #endif >>>>> @@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) >>>>> err = sd_get_capabilities(mmc); >>>>> if (err) >>>>> return err; >>>>> + >>>>> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>> + /* >>>>> + * If the card has already switched to 1.8V signaling, then >>>>> + * set the signal voltage to 1.8V. >>>>> + */ >>>>> + if (mmc_sd_card_using_v18(mmc)) { >>>> To switch voltage, ACMD41 is required, see mmc_switch_voltage. >>>> Forcing switch to 1.8 here has some risk. >>> >>> Agreed - ACMD41 is required to initiate a voltage switch on a card >>> that is >>> currently at 3.3V. However, in this path the card has already completed >>> the voltage switch in a prior session and is still running at 1.8V. >>> There >>> is no card-side voltage transition happening; only the host controller >>> needs to be reconfigured to match the 1.8V signaling level the card >>> retained. Sending ACMD41 again in this context would be incorrect, as >>> the >>> card is not in a state to re-negotiate voltage. >>> >>>>> + /* >>>>> + * During a signal voltage level switch, the clock >>>>> must be gated >>>>> + * for 5 ms according to the SD spec. >>>>> + */ >>>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >>>>> + err = mmc_set_signal_voltage(mmc, >>>>> MMC_SIGNAL_VOLTAGE_180); >>>>> + if (err) >>>>> + return err; >>>>> + /* Keep clock gated for at least 10 ms, though spec >>>>> only says 5 ms */ >>>>> + mdelay(10); >>>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >>>>> + } >>>>> +#endif >>>> A proper redesign is required. So I am going to revert this patch. >>>> >>> >>> I would respectfully ask to reconsider before reverting. This patch is >>> specifically targeted at the warm reboot / system resume / error >>> recovery >>> scenario where the card is not power cycled. The check in >>> mmc_sd_card_using_v18() acts as a guard - it only triggers when the >>> card is already at 1.8V and the normal OCR path did not catch it. On >>> a cold boot with a fresh 3.3V card, the UHS supported bits will be zero >>> and this path is never entered, so it cannot regress cold-boot behavior >>> for any board. >>> >>> Regarding the reported regression [1], Judith mentioned that he will >>> debug once he is back. If possible, let us wait for him to conclude >>> before deciding to revert. >> >> So I started looking at this. So far, I have found that on AM65 u-boot, >> we had been enumerating to SDR104 mode once during boot and finally >> resolve to HS mode right before loading the kernel. > > This seems to be the root of the issue. Entering SDR104 mode transitions > the SD card, the IO signal lines, and the host controller all to 1.8V > signaling. > Once that transition happens, attempting to switch back to HS mode (which > requires 3.3V) is not possible without a full power cycle of the card. > > This is explicitly stated in the SD Physical Layer Simplified > Specification, > Section "UHS-I Bus Speed Modes Selection Sequence": > > "Once the card enters 1.8V signaling mode, the card cannot be switched > to SPI mode or 3.3V signaling without power cycle. If the card receives > CMD0, card returns to Idle state but still works with SDR12 timing." > > So the failure you are seeing is not introduced by my patch — the card > was already non-recoverable to 3.3V from the moment it entered SDR104 > earlier in the boot. I agree there is an issue with this board, but still this implementation breaks am65 further and causes mmc_init failure now. > >> >> Also, sd3_bus_mode=0x1f at u-boot stage. > > This confirms the card was already operating in 1.8V signaling when your > debug point was reached. For reference, on a fresh cold boot at 3.3V, the > CMD6 available functions table shows sd3_bus_mode should read 0x07 > (only SDR12/SDR25/HS bits set). The value 0x1f means bits for SDR50, > SDR104, and DDR50 are also set, which per the spec only happens when the > card is initialized at 1.8V signaling. This is exactly what > mmc_sd_card_using_v18() is designed to detect. > >> >> Something weird: from the schematics, its does not seem like the IOs are >> switching to 1.8V with on board hardware PMIC. > > This is worth investigating further. If the IO lines are confirmed to be > stuck at 3.3V while the card is operating at 1.8V signaling, that would > itself be a pre-existing hardware or driver issue — the IO voltage and the > card signaling voltage must always be in sync. I would suggest: > > 1. Verify the voltage regulator driving the IO lines (Vccq) and confirm > whether am654_sdhci_set_ios_post correctly switches it to 1.8V when > UHS modes are selected. If Vccq is not switching, that is a separate > bug in the am654 driver or the regulator configuration. > > 2. Try using UHS_SDR12 or UHS_SDR25 as the operating mode instead > of HS. Since the card has already transitioned to 1.8V, the UHS-I modes > are the correct and spec-compliant modes to use. Running HS mode at > 1.8V is not a valid combination. Ok So, I dug further and found that AM65 also has an internal LDO, so Host side voltage switch happens with V1p8 bit. It switches voltage as expected. > >> >> It seems like the call stack has changed where previously >> uhs_en=0 in u-boot and now with your commit uhs_en=1, right before >> loading the kernel. > > Correct. Previously, even though the card was operating at 1.8V (as > evidenced by sd3_bus_mode=0x1f), the code was not checking the card's > function group 1 to detect this. So the host stayed at 3.3V while the > card was at 1.8V — an incorrect but silently failing combination on > platforms where the mismatch happens to be tolerated. > > With the patch, we correctly detect the 1.8V state and instruct the host > to match. The subsequent failure you observe is because the host-side > IO voltage switch (Vccq) appears to not be working. Wrong info here from my part, voltage switch does happen. > >> After this, we call am654_sdhci_set_ios_post >> multiple times at mode=0 & signal_voltage=0x2 until mmc_init failure. > > mode=0 corresponds to MMC_LEGACY, which is a 3.3V mode. Having > signal_voltage=0x2 (1.8V) alongside MMC_LEGACY is not a valid > combination. This suggests the mode selection logic is landing on > MMC_LEGACY while the voltage has already been switched to 1.8V, which > will always fail. The fix should be to ensure the card operates in a > UHS-I mode when at 1.8V, not fall back to MMC_LEGACY. > >> >> I realize this is not the most stable platform and there could >> be hardware issues for SD. Perhaps it is a good idea to create >> a quirk to skip over this section for these kinds of platforms? > > I would prefer to avoid a quirk at this stage, as the underlying behavior > — the card being at 1.8V after a prior boot — is spec-compliant and > real. A quirk would just mask the issue on AM65 rather than fix the actual > IO voltage switching problem. > >> >> What are your thoughts? I will continue on this debug >> and come back if I find more useful information. >> >> ~ Judith >> > > Hope this helps, looking forward to your further findings. > Sorry for my late response, I had to drop this debug for a while and actually will not be able to return to this debug in a week or two. I found something interesting while debugging on SD card reset line, but I am tracking down different am65 board versions to further investigate this. Ill let you know if I find anything. Meanwhile, if you would like to sync offline on anything, feel free to ping my email address. ~ judith ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-06-08 15:19 ` Judith Mendez @ 2026-06-09 7:51 ` Kathpalia, Tanmay 2026-07-13 9:45 ` Kathpalia, Tanmay 1 sibling, 0 replies; 17+ messages in thread From: Kathpalia, Tanmay @ 2026-06-09 7:51 UTC (permalink / raw) To: Judith Mendez, Peng Fan Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi Judith, Thank you for the update. On 6/8/2026 8:49 PM, Judith Mendez wrote: > Hi Tanmay, > > On 5/29/26 12:21 PM, Kathpalia, Tanmay wrote: >> Hi Judith, >> >> Thank you for the information. Let me share my analysis based on >> what you have described. >> >> On 5/28/2026 4:52 AM, Judith Mendez wrote: >>> Hi Kathpalia, >>> >>> On 5/16/26 6:44 AM, Kathpalia, Tanmay wrote: >>>> Hi Peng, >>>> Thank you for reviewing and for the detailed feedback. Apologies for >>>> the resend — my previous reply had an incorrect timestamp due to a >>>> timezone misconfiguration, which caused it to appear out of order in >>>> the thread. >>>> >>>> On 5/16/2026 3:14 PM, Peng Fan wrote: >>>>> Revisit this patch, since it break one board [1]. >>>>> >>>>> [1] https://lore.kernel.org/all/52ec8007-ce50-4f12- >>>>> b796-4b8c2aa1822e@ti.com/ >>>>> >>>>> On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >>>>>> Some boards have SD card connectors where the power rail cannot >>>>>> be switched >>>>>> off by the driver. However there are various circumstances when a >>>>>> card >>>>>> might be re-initialized, such as after system resume, warm >>>>>> re-boot, or >>>>>> error handling. However, a UHS card will continue to use 1.8V >>>>>> signaling >>>>>> unless it is power cycled. >>>>>> >>>>>> If the card has not been power cycled, it may still be using 1.8V >>>>>> signaling. According to the SD spec., the Bus Speed Mode >>>>>> (function group 1) >>>>>> bits 2 to 4 are zero if the card is initialized at 3.3V signal >>>>>> level. Thus >>>>>> they can be used to determine if the card has already switched to >>>>>> 1.8V >>>>>> signaling. Detect that situation and try to initialize a UHS-I >>>>>> (1.8V) >>>>>> transfer mode. >>>>>> >>>>>> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>>>>> --- >>>>>> drivers/mmc/mmc.c | 55 >>>>>> ++++++++++++++++++++++++++++++++++++++--------- >>>>>> include/mmc.h | 3 +++ >>>>>> 2 files changed, 48 insertions(+), 10 deletions(-) >>>>>> >>>>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >>>>>> index ec61ed92e86..e1f62a5d0ad 100644 >>>>>> --- a/drivers/mmc/mmc.c >>>>>> +++ b/drivers/mmc/mmc.c >>>>>> @@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc >>>>>> *mmc, int signal_voltage) >>>>>> >>>>>> return 0; >>>>>> } >>>>>> + >>>>>> +static bool mmc_sd_card_using_v18(struct mmc *mmc) >>>>>> +{ >>>>>> + /* >>>>>> + * According to the SD spec., the Bus Speed Mode (function >>>>>> group 1) bits >>>>>> + * 2 to 4 are zero if the card is initialized at 3.3V signal >>>>>> level. Thus >>>>>> + * they can be used to determine if the card has already >>>>>> switched to >>>>>> + * 1.8V signaling. >>>>>> + */ >>>>>> + bool volt = mmc->sd3_bus_mode & >>>>>> + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | >>>>>> SD_MODE_UHS_DDR50); >>>>> This is wrong. >>>>> sd3_bus_mode is sd supported bits, not the current running bits. >>>>> >>>>> To detect the sd card running bits, need to use: >>>>> (__be32_to_cpu(switch_status[4]) >> 24) & 0xF >>>> >>>> You are correct that sd3_bus_mode stores the supported bits - as >>>> can be >>>> seen in sd_get_capabilities() where it is filled from the CMD6 status >>>> response: >>>> >>>> mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>> >>>> However, the intent here is not to read the currently active function >>>> code, but to use the supported bits as a proxy for the signaling >>>> voltage >>>> level. >>>> >>>> According to the SD Physical Layer Simplified Specification v9.0, >>>> Section 4.3.10.4 (Switch Function Command, CMD6): the UHS-I speed >>>> modes >>>> SDR50, SDR104, and DDR50 (function group 1 bits 2–4) are only >>>> available >>>> when the card is operating at 1.8V signaling. When the card is >>>> initialized at 3.3V, those bits read as zero. Therefore, if any of >>>> bits >>>> 2-4 are set in the supported field, we can safely infer the card is a >>>> UHS-I card and, when not power cycled, retains 1.8V signaling. >>>> >>>> Using switch_status[4] to read the currently active function would >>>> actually NOT work for this scenario. After a warm reboot, the card >>>> receives CMD0 (GO_IDLE_STATE), which resets the card's selected >>>> function >>>> back to 0 (SDR12/default) — even though the 1.8V signaling level is >>>> retained. So switch_status[4] would always return 0 in this path, >>>> making it unsuitable as a 1.8V indicator here. >>>> >>>>>> + return volt; >>>>>> +} >>>>>> #endif >>>>>> >>>>>> static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >>>>>> @@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc >>>>>> *mmc) >>>>>> ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); >>>>>> struct mmc_data data; >>>>>> int timeout; >>>>>> -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>>> - u32 sd3_bus_mode; >>>>>> -#endif >>>>>> >>>>>> mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); >>>>>> >>>>>> @@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc >>>>>> *mmc) >>>>>> if (mmc->version < SD_VERSION_3) >>>>>> return 0; >>>>>> >>>>>> - sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR104) >>>>>> + mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & >>>>>> 0x1f; >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR104); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR50) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR50); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR25) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR25); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR12) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR12); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_DDR50) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) >>>>>> mmc->card_caps |= MMC_CAP(UHS_DDR50); >>>>>> #endif >>>>>> >>>>>> @@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct >>>>>> mmc *mmc, uint card_caps) >>>>>> uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; >>>>>> const struct mode_width_tuning *mwt; >>>>>> #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>>> - bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >>>>>> + /* >>>>>> + * Enable UHS mode if the card advertises 1.8V support (S18R >>>>>> in OCR) >>>>>> + * or is already operating at 1.8V signaling. >>>>>> + */ >>>>>> + bool uhs_en = (mmc->ocr & OCR_S18R) || >>>>>> mmc_sd_card_using_v18(mmc); >>>>> In theory, >>>>> >>>>> bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. >>>>> >>>>> OCR (including S18R/S18A) only reflects voltage switch negotiation >>>>> capability and intent, not the current signaling voltage. So your >>>>> sd card >>>>> should have OCR_S18R returned per my understanding. >>>> >>>> I think there is a gap in understanding here. The scenario this patch >>>> targets is warm reboot or system resume - the card was never power >>>> cycled, >>>> so it is still operating at 1.8V signaling. >>>> >>>> In that situation, when ACMD41 is re-issued, the card will NOT assert >>>> S18A (Switching to 1.8V Accepted) in the OCR response, because the >>>> voltage negotiation already happened in the previous session and >>>> the card >>>> has no need to re-negotiate. Per the SD Physical Layer Simplified >>>> Specification v9.0, S18A is set only during the initial 1.8V request >>>> handshake. A card already running at 1.8V will not set S18A again on a >>>> subsequent ACMD41 after warm reset. >>>> >>>> This is exactly the corner case: OCR_S18R/S18A will be zero, yet >>>> the card >>>> is already at 1.8V. The existing code misses this entirely. >>>> >>>>>> #else >>>>>> bool uhs_en = false; >>>>>> #endif >>>>>> @@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) >>>>>> err = sd_get_capabilities(mmc); >>>>>> if (err) >>>>>> return err; >>>>>> + >>>>>> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>>> + /* >>>>>> + * If the card has already switched to 1.8V signaling, then >>>>>> + * set the signal voltage to 1.8V. >>>>>> + */ >>>>>> + if (mmc_sd_card_using_v18(mmc)) { >>>>> To switch voltage, ACMD41 is required, see mmc_switch_voltage. >>>>> Forcing switch to 1.8 here has some risk. >>>> >>>> Agreed - ACMD41 is required to initiate a voltage switch on a card >>>> that is >>>> currently at 3.3V. However, in this path the card has already >>>> completed >>>> the voltage switch in a prior session and is still running at 1.8V. >>>> There >>>> is no card-side voltage transition happening; only the host controller >>>> needs to be reconfigured to match the 1.8V signaling level the card >>>> retained. Sending ACMD41 again in this context would be incorrect, >>>> as the >>>> card is not in a state to re-negotiate voltage. >>>> >>>>>> + /* >>>>>> + * During a signal voltage level switch, the clock >>>>>> must be gated >>>>>> + * for 5 ms according to the SD spec. >>>>>> + */ >>>>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >>>>>> + err = mmc_set_signal_voltage(mmc, >>>>>> MMC_SIGNAL_VOLTAGE_180); >>>>>> + if (err) >>>>>> + return err; >>>>>> + /* Keep clock gated for at least 10 ms, though spec >>>>>> only says 5 ms */ >>>>>> + mdelay(10); >>>>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >>>>>> + } >>>>>> +#endif >>>>> A proper redesign is required. So I am going to revert this patch. >>>>> >>>> >>>> I would respectfully ask to reconsider before reverting. This patch is >>>> specifically targeted at the warm reboot / system resume / error >>>> recovery >>>> scenario where the card is not power cycled. The check in >>>> mmc_sd_card_using_v18() acts as a guard - it only triggers when the >>>> card is already at 1.8V and the normal OCR path did not catch it. On >>>> a cold boot with a fresh 3.3V card, the UHS supported bits will be >>>> zero >>>> and this path is never entered, so it cannot regress cold-boot >>>> behavior >>>> for any board. >>>> >>>> Regarding the reported regression [1], Judith mentioned that he will >>>> debug once he is back. If possible, let us wait for him to conclude >>>> before deciding to revert. >>> >>> So I started looking at this. So far, I have found that on AM65 u-boot, >>> we had been enumerating to SDR104 mode once during boot and finally >>> resolve to HS mode right before loading the kernel. >> >> This seems to be the root of the issue. Entering SDR104 mode transitions >> the SD card, the IO signal lines, and the host controller all to 1.8V >> signaling. >> Once that transition happens, attempting to switch back to HS mode >> (which >> requires 3.3V) is not possible without a full power cycle of the card. >> >> This is explicitly stated in the SD Physical Layer Simplified >> Specification, >> Section "UHS-I Bus Speed Modes Selection Sequence": >> >> "Once the card enters 1.8V signaling mode, the card cannot be >> switched >> to SPI mode or 3.3V signaling without power cycle. If the card >> receives >> CMD0, card returns to Idle state but still works with SDR12 timing." >> >> So the failure you are seeing is not introduced by my patch — the card >> was already non-recoverable to 3.3V from the moment it entered SDR104 >> earlier in the boot. > > I agree there is an issue with this board, but still this implementation > breaks am65 further and causes mmc_init failure now. Understood. To clarify my position: I believe what the patch has done is surface a pre-existing condition - the card being at 1.8V signaling after a prior boot - rather than introduce a new failure. The mmc_init failure is a consequence of that state not being handled correctly downstream, not of the 1.8V detection itself. > >> >>> >>> Also, sd3_bus_mode=0x1f at u-boot stage. >> >> This confirms the card was already operating in 1.8V signaling when your >> debug point was reached. For reference, on a fresh cold boot at 3.3V, >> the >> CMD6 available functions table shows sd3_bus_mode should read 0x07 >> (only SDR12/SDR25/HS bits set). The value 0x1f means bits for SDR50, >> SDR104, and DDR50 are also set, which per the spec only happens when the >> card is initialized at 1.8V signaling. This is exactly what >> mmc_sd_card_using_v18() is designed to detect. >> >>> >>> Something weird: from the schematics, its does not seem like the IOs >>> are >>> switching to 1.8V with on board hardware PMIC. >> >> This is worth investigating further. If the IO lines are confirmed to be >> stuck at 3.3V while the card is operating at 1.8V signaling, that would >> itself be a pre-existing hardware or driver issue — the IO voltage >> and the >> card signaling voltage must always be in sync. I would suggest: >> >> 1. Verify the voltage regulator driving the IO lines (Vccq) and confirm >> whether am654_sdhci_set_ios_post correctly switches it to 1.8V when >> UHS modes are selected. If Vccq is not switching, that is a separate >> bug in the am654 driver or the regulator configuration. >> >> 2. Try using UHS_SDR12 or UHS_SDR25 as the operating mode instead >> of HS. Since the card has already transitioned to 1.8V, the UHS-I modes >> are the correct and spec-compliant modes to use. Running HS mode at >> 1.8V is not a valid combination. > > Ok So, I dug further and found that AM65 also has an internal LDO, so > Host side voltage switch happens with V1p8 bit. It switches voltage > as expected. So to confirm my understanding: you have verified both (1) the IO signal lines are switching to 1.8V via the internal LDO, and (2) the host controller registers are being configured for 1.8V signaling. With both of those confirmed, the next question would be whether the mode selected after the voltage switch is a valid UHS-I mode - as running MMC_LEGACY at 1.8V is not a legal combination and would explain the subsequent failure. > >> >>> >>> It seems like the call stack has changed where previously >>> uhs_en=0 in u-boot and now with your commit uhs_en=1, right before >>> loading the kernel. >> >> Correct. Previously, even though the card was operating at 1.8V (as >> evidenced by sd3_bus_mode=0x1f), the code was not checking the card's >> function group 1 to detect this. So the host stayed at 3.3V while the >> card was at 1.8V — an incorrect but silently failing combination on >> platforms where the mismatch happens to be tolerated. >> >> With the patch, we correctly detect the 1.8V state and instruct the host >> to match. The subsequent failure you observe is because the host-side >> IO voltage switch (Vccq) appears to not be working. > > Wrong info here from my part, voltage switch does happen. > >> >>> After this, we call am654_sdhci_set_ios_post >>> multiple times at mode=0 & signal_voltage=0x2 until mmc_init failure. >> >> mode=0 corresponds to MMC_LEGACY, which is a 3.3V mode. Having >> signal_voltage=0x2 (1.8V) alongside MMC_LEGACY is not a valid >> combination. This suggests the mode selection logic is landing on >> MMC_LEGACY while the voltage has already been switched to 1.8V, which >> will always fail. The fix should be to ensure the card operates in a >> UHS-I mode when at 1.8V, not fall back to MMC_LEGACY. >> >>> >>> I realize this is not the most stable platform and there could >>> be hardware issues for SD. Perhaps it is a good idea to create >>> a quirk to skip over this section for these kinds of platforms? >> >> I would prefer to avoid a quirk at this stage, as the underlying >> behavior >> — the card being at 1.8V after a prior boot — is spec-compliant and >> real. A quirk would just mask the issue on AM65 rather than fix the >> actual >> IO voltage switching problem. >> >>> >>> What are your thoughts? I will continue on this debug >>> and come back if I find more useful information. >>> >>> ~ Judith >>> >> >> Hope this helps, looking forward to your further findings. >> > > Sorry for my late response, I had to drop this debug for a while and > actually will not be able to return to this debug in a week or two. > > I found something interesting while debugging on SD card reset line, > but I am tracking down different am65 board versions to further > investigate this. Ill let you know if I find anything. Meanwhile, > if you would like to sync offline on anything, feel free to ping my > email address. No worries at all - priorities shift and that is completely understood. Testing across different AM65 board versions sounds like a right step and could help isolate whether this is board-revision-specific. I agree syncing offline would be the most efficient way to root cause this together rather than going back and forth over email. Let us plan a sync once you are back on this debug. Regards, Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-06-08 15:19 ` Judith Mendez 2026-06-09 7:51 ` Kathpalia, Tanmay @ 2026-07-13 9:45 ` Kathpalia, Tanmay 2026-07-13 10:21 ` Peng Fan 1 sibling, 1 reply; 17+ messages in thread From: Kathpalia, Tanmay @ 2026-07-13 9:45 UTC (permalink / raw) To: Judith Mendez, Peng Fan Cc: u-boot, trini, peng.fan, jh80.chung, marex, tien.fong.chee Hi all, Following up on this thread regarding the reported regression on the AM65 IDK board. On 6/8/2026 8:49 PM, Judith Mendez wrote: > Hi Tanmay, > > On 5/29/26 12:21 PM, Kathpalia, Tanmay wrote: >> Hi Judith, >> >> Thank you for the information. Let me share my analysis based on >> what you have described. >> >> On 5/28/2026 4:52 AM, Judith Mendez wrote: >>> Hi Kathpalia, >>> >>> On 5/16/26 6:44 AM, Kathpalia, Tanmay wrote: >>>> Hi Peng, >>>> Thank you for reviewing and for the detailed feedback. Apologies for >>>> the resend — my previous reply had an incorrect timestamp due to a >>>> timezone misconfiguration, which caused it to appear out of order in >>>> the thread. >>>> >>>> On 5/16/2026 3:14 PM, Peng Fan wrote: >>>>> Revisit this patch, since it break one board [1]. >>>>> >>>>> [1] https://lore.kernel.org/all/52ec8007-ce50-4f12- >>>>> b796-4b8c2aa1822e@ti.com/ >>>>> >>>>> On Tue, Oct 21, 2025 at 01:45:26PM -0700, Tanmay Kathpalia wrote: >>>>>> Some boards have SD card connectors where the power rail cannot >>>>>> be switched >>>>>> off by the driver. However there are various circumstances when a >>>>>> card >>>>>> might be re-initialized, such as after system resume, warm >>>>>> re-boot, or >>>>>> error handling. However, a UHS card will continue to use 1.8V >>>>>> signaling >>>>>> unless it is power cycled. >>>>>> >>>>>> If the card has not been power cycled, it may still be using 1.8V >>>>>> signaling. According to the SD spec., the Bus Speed Mode >>>>>> (function group 1) >>>>>> bits 2 to 4 are zero if the card is initialized at 3.3V signal >>>>>> level. Thus >>>>>> they can be used to determine if the card has already switched to >>>>>> 1.8V >>>>>> signaling. Detect that situation and try to initialize a UHS-I >>>>>> (1.8V) >>>>>> transfer mode. >>>>>> >>>>>> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>>>>> --- >>>>>> drivers/mmc/mmc.c | 55 >>>>>> ++++++++++++++++++++++++++++++++++++++--------- >>>>>> include/mmc.h | 3 +++ >>>>>> 2 files changed, 48 insertions(+), 10 deletions(-) >>>>>> >>>>>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >>>>>> index ec61ed92e86..e1f62a5d0ad 100644 >>>>>> --- a/drivers/mmc/mmc.c >>>>>> +++ b/drivers/mmc/mmc.c >>>>>> @@ -643,6 +643,19 @@ static int mmc_switch_voltage(struct mmc >>>>>> *mmc, int signal_voltage) >>>>>> >>>>>> return 0; >>>>>> } >>>>>> + >>>>>> +static bool mmc_sd_card_using_v18(struct mmc *mmc) >>>>>> +{ >>>>>> + /* >>>>>> + * According to the SD spec., the Bus Speed Mode (function >>>>>> group 1) bits >>>>>> + * 2 to 4 are zero if the card is initialized at 3.3V signal >>>>>> level. Thus >>>>>> + * they can be used to determine if the card has already >>>>>> switched to >>>>>> + * 1.8V signaling. >>>>>> + */ >>>>>> + bool volt = mmc->sd3_bus_mode & >>>>>> + (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | >>>>>> SD_MODE_UHS_DDR50); >>>>> This is wrong. >>>>> sd3_bus_mode is sd supported bits, not the current running bits. >>>>> >>>>> To detect the sd card running bits, need to use: >>>>> (__be32_to_cpu(switch_status[4]) >> 24) & 0xF >>>> >>>> You are correct that sd3_bus_mode stores the supported bits - as >>>> can be >>>> seen in sd_get_capabilities() where it is filled from the CMD6 status >>>> response: >>>> >>>> mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>> >>>> However, the intent here is not to read the currently active function >>>> code, but to use the supported bits as a proxy for the signaling >>>> voltage >>>> level. >>>> >>>> According to the SD Physical Layer Simplified Specification v9.0, >>>> Section 4.3.10.4 (Switch Function Command, CMD6): the UHS-I speed >>>> modes >>>> SDR50, SDR104, and DDR50 (function group 1 bits 2–4) are only >>>> available >>>> when the card is operating at 1.8V signaling. When the card is >>>> initialized at 3.3V, those bits read as zero. Therefore, if any of >>>> bits >>>> 2-4 are set in the supported field, we can safely infer the card is a >>>> UHS-I card and, when not power cycled, retains 1.8V signaling. >>>> >>>> Using switch_status[4] to read the currently active function would >>>> actually NOT work for this scenario. After a warm reboot, the card >>>> receives CMD0 (GO_IDLE_STATE), which resets the card's selected >>>> function >>>> back to 0 (SDR12/default) — even though the 1.8V signaling level is >>>> retained. So switch_status[4] would always return 0 in this path, >>>> making it unsuitable as a 1.8V indicator here. >>>> >>>>>> + return volt; >>>>>> +} >>>>>> #endif >>>>>> >>>>>> static int sd_send_op_cond(struct mmc *mmc, bool uhs_en) >>>>>> @@ -1369,9 +1382,6 @@ static int sd_get_capabilities(struct mmc >>>>>> *mmc) >>>>>> ALLOC_CACHE_ALIGN_BUFFER(__be32, switch_status, 16); >>>>>> struct mmc_data data; >>>>>> int timeout; >>>>>> -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>>> - u32 sd3_bus_mode; >>>>>> -#endif >>>>>> >>>>>> mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY); >>>>>> >>>>>> @@ -1451,16 +1461,16 @@ static int sd_get_capabilities(struct mmc >>>>>> *mmc) >>>>>> if (mmc->version < SD_VERSION_3) >>>>>> return 0; >>>>>> >>>>>> - sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & 0x1f; >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR104) >>>>>> + mmc->sd3_bus_mode = __be32_to_cpu(switch_status[3]) >> 16 & >>>>>> 0x1f; >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR104) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR104); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR50) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR50) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR50); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR25) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR25) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR25); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_SDR12) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_SDR12) >>>>>> mmc->card_caps |= MMC_CAP(UHS_SDR12); >>>>>> - if (sd3_bus_mode & SD_MODE_UHS_DDR50) >>>>>> + if (mmc->sd3_bus_mode & SD_MODE_UHS_DDR50) >>>>>> mmc->card_caps |= MMC_CAP(UHS_DDR50); >>>>>> #endif >>>>>> >>>>>> @@ -1830,7 +1840,11 @@ static int sd_select_mode_and_width(struct >>>>>> mmc *mmc, uint card_caps) >>>>>> uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; >>>>>> const struct mode_width_tuning *mwt; >>>>>> #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>>> - bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; >>>>>> + /* >>>>>> + * Enable UHS mode if the card advertises 1.8V support (S18R >>>>>> in OCR) >>>>>> + * or is already operating at 1.8V signaling. >>>>>> + */ >>>>>> + bool uhs_en = (mmc->ocr & OCR_S18R) || >>>>>> mmc_sd_card_using_v18(mmc); >>>>> In theory, >>>>> >>>>> bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; is correct. >>>>> >>>>> OCR (including S18R/S18A) only reflects voltage switch negotiation >>>>> capability and intent, not the current signaling voltage. So your >>>>> sd card >>>>> should have OCR_S18R returned per my understanding. >>>> >>>> I think there is a gap in understanding here. The scenario this patch >>>> targets is warm reboot or system resume - the card was never power >>>> cycled, >>>> so it is still operating at 1.8V signaling. >>>> >>>> In that situation, when ACMD41 is re-issued, the card will NOT assert >>>> S18A (Switching to 1.8V Accepted) in the OCR response, because the >>>> voltage negotiation already happened in the previous session and >>>> the card >>>> has no need to re-negotiate. Per the SD Physical Layer Simplified >>>> Specification v9.0, S18A is set only during the initial 1.8V request >>>> handshake. A card already running at 1.8V will not set S18A again on a >>>> subsequent ACMD41 after warm reset. >>>> >>>> This is exactly the corner case: OCR_S18R/S18A will be zero, yet >>>> the card >>>> is already at 1.8V. The existing code misses this entirely. >>>> >>>>>> #else >>>>>> bool uhs_en = false; >>>>>> #endif >>>>>> @@ -2701,6 +2715,27 @@ static int mmc_startup(struct mmc *mmc) >>>>>> err = sd_get_capabilities(mmc); >>>>>> if (err) >>>>>> return err; >>>>>> + >>>>>> +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) >>>>>> + /* >>>>>> + * If the card has already switched to 1.8V signaling, then >>>>>> + * set the signal voltage to 1.8V. >>>>>> + */ >>>>>> + if (mmc_sd_card_using_v18(mmc)) { >>>>> To switch voltage, ACMD41 is required, see mmc_switch_voltage. >>>>> Forcing switch to 1.8 here has some risk. >>>> >>>> Agreed - ACMD41 is required to initiate a voltage switch on a card >>>> that is >>>> currently at 3.3V. However, in this path the card has already >>>> completed >>>> the voltage switch in a prior session and is still running at 1.8V. >>>> There >>>> is no card-side voltage transition happening; only the host controller >>>> needs to be reconfigured to match the 1.8V signaling level the card >>>> retained. Sending ACMD41 again in this context would be incorrect, >>>> as the >>>> card is not in a state to re-negotiate voltage. >>>> >>>>>> + /* >>>>>> + * During a signal voltage level switch, the clock >>>>>> must be gated >>>>>> + * for 5 ms according to the SD spec. >>>>>> + */ >>>>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_DISABLE); >>>>>> + err = mmc_set_signal_voltage(mmc, >>>>>> MMC_SIGNAL_VOLTAGE_180); >>>>>> + if (err) >>>>>> + return err; >>>>>> + /* Keep clock gated for at least 10 ms, though spec >>>>>> only says 5 ms */ >>>>>> + mdelay(10); >>>>>> + mmc_set_clock(mmc, mmc->clock, MMC_CLK_ENABLE); >>>>>> + } >>>>>> +#endif >>>>> A proper redesign is required. So I am going to revert this patch. >>>>> >>>> >>>> I would respectfully ask to reconsider before reverting. This patch is >>>> specifically targeted at the warm reboot / system resume / error >>>> recovery >>>> scenario where the card is not power cycled. The check in >>>> mmc_sd_card_using_v18() acts as a guard - it only triggers when the >>>> card is already at 1.8V and the normal OCR path did not catch it. On >>>> a cold boot with a fresh 3.3V card, the UHS supported bits will be >>>> zero >>>> and this path is never entered, so it cannot regress cold-boot >>>> behavior >>>> for any board. >>>> >>>> Regarding the reported regression [1], Judith mentioned that he will >>>> debug once he is back. If possible, let us wait for him to conclude >>>> before deciding to revert. >>> >>> So I started looking at this. So far, I have found that on AM65 u-boot, >>> we had been enumerating to SDR104 mode once during boot and finally >>> resolve to HS mode right before loading the kernel. >> >> This seems to be the root of the issue. Entering SDR104 mode transitions >> the SD card, the IO signal lines, and the host controller all to 1.8V >> signaling. >> Once that transition happens, attempting to switch back to HS mode >> (which >> requires 3.3V) is not possible without a full power cycle of the card. >> >> This is explicitly stated in the SD Physical Layer Simplified >> Specification, >> Section "UHS-I Bus Speed Modes Selection Sequence": >> >> "Once the card enters 1.8V signaling mode, the card cannot be >> switched >> to SPI mode or 3.3V signaling without power cycle. If the card >> receives >> CMD0, card returns to Idle state but still works with SDR12 timing." >> >> So the failure you are seeing is not introduced by my patch — the card >> was already non-recoverable to 3.3V from the moment it entered SDR104 >> earlier in the boot. > > I agree there is an issue with this board, but still this implementation > breaks am65 further and causes mmc_init failure now. > >> >>> >>> Also, sd3_bus_mode=0x1f at u-boot stage. >> >> This confirms the card was already operating in 1.8V signaling when your >> debug point was reached. For reference, on a fresh cold boot at 3.3V, >> the >> CMD6 available functions table shows sd3_bus_mode should read 0x07 >> (only SDR12/SDR25/HS bits set). The value 0x1f means bits for SDR50, >> SDR104, and DDR50 are also set, which per the spec only happens when the >> card is initialized at 1.8V signaling. This is exactly what >> mmc_sd_card_using_v18() is designed to detect. >> >>> >>> Something weird: from the schematics, its does not seem like the IOs >>> are >>> switching to 1.8V with on board hardware PMIC. >> >> This is worth investigating further. If the IO lines are confirmed to be >> stuck at 3.3V while the card is operating at 1.8V signaling, that would >> itself be a pre-existing hardware or driver issue — the IO voltage >> and the >> card signaling voltage must always be in sync. I would suggest: >> >> 1. Verify the voltage regulator driving the IO lines (Vccq) and confirm >> whether am654_sdhci_set_ios_post correctly switches it to 1.8V when >> UHS modes are selected. If Vccq is not switching, that is a separate >> bug in the am654 driver or the regulator configuration. >> >> 2. Try using UHS_SDR12 or UHS_SDR25 as the operating mode instead >> of HS. Since the card has already transitioned to 1.8V, the UHS-I modes >> are the correct and spec-compliant modes to use. Running HS mode at >> 1.8V is not a valid combination. > > Ok So, I dug further and found that AM65 also has an internal LDO, so > Host side voltage switch happens with V1p8 bit. It switches voltage > as expected. > >> >>> >>> It seems like the call stack has changed where previously >>> uhs_en=0 in u-boot and now with your commit uhs_en=1, right before >>> loading the kernel. >> >> Correct. Previously, even though the card was operating at 1.8V (as >> evidenced by sd3_bus_mode=0x1f), the code was not checking the card's >> function group 1 to detect this. So the host stayed at 3.3V while the >> card was at 1.8V — an incorrect but silently failing combination on >> platforms where the mismatch happens to be tolerated. >> >> With the patch, we correctly detect the 1.8V state and instruct the host >> to match. The subsequent failure you observe is because the host-side >> IO voltage switch (Vccq) appears to not be working. > > Wrong info here from my part, voltage switch does happen. > >> >>> After this, we call am654_sdhci_set_ios_post >>> multiple times at mode=0 & signal_voltage=0x2 until mmc_init failure. >> >> mode=0 corresponds to MMC_LEGACY, which is a 3.3V mode. Having >> signal_voltage=0x2 (1.8V) alongside MMC_LEGACY is not a valid >> combination. This suggests the mode selection logic is landing on >> MMC_LEGACY while the voltage has already been switched to 1.8V, which >> will always fail. The fix should be to ensure the card operates in a >> UHS-I mode when at 1.8V, not fall back to MMC_LEGACY. >> >>> >>> I realize this is not the most stable platform and there could >>> be hardware issues for SD. Perhaps it is a good idea to create >>> a quirk to skip over this section for these kinds of platforms? >> >> I would prefer to avoid a quirk at this stage, as the underlying >> behavior >> — the card being at 1.8V after a prior boot — is spec-compliant and >> real. A quirk would just mask the issue on AM65 rather than fix the >> actual >> IO voltage switching problem. >> >>> >>> What are your thoughts? I will continue on this debug >>> and come back if I find more useful information. >>> >>> ~ Judith >>> >> >> Hope this helps, looking forward to your further findings. >> > > Sorry for my late response, I had to drop this debug for a while and > actually will not be able to return to this debug in a week or two. > > I found something interesting while debugging on SD card reset line, > but I am tracking down different am65 board versions to further > investigate this. Ill let you know if I find anything. Meanwhile, > if you would like to sync offline on anything, feel free to ping my > email address. > > > I worked with Judith Mendez to get to the bottom of this - she shared logs from the AM65 IDK board and we went back and forth analyzing them, which pointed to a board-level power sequencing problem on AM65x rather than an issue with this patch. In her words: "So it is truly a power issue, I have a patch to fix the issue on am65x. There is nothing wrong with your patch, coincidentally my power issue caused am65x to fall into a weird state and your commit caught that. So actually, thanks. I can now send my proper fix to the u-boot mailing list." So this patch did not introduce a regression - it actually helped uncover a latent power-sequencing issue on the AM65x board that was independent of this change. Judith will be sending a separate fix for the AM65x board issue. I'd consider this matter closed with respect to this patch. Thanks Judith for digging into this and confirming the root cause. Regards, Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-07-13 9:45 ` Kathpalia, Tanmay @ 2026-07-13 10:21 ` Peng Fan 2026-07-14 1:37 ` Mendez, Judith 0 siblings, 1 reply; 17+ messages in thread From: Peng Fan @ 2026-07-13 10:21 UTC (permalink / raw) To: Kathpalia, Tanmay, Judith Mendez, Peng Fan (OSS) Cc: u-boot@lists.denx.de, trini@konsulko.com, jh80.chung@samsung.com, marex@denx.de, tien.fong.chee@altera.com Hi Tanmay, > Subject: Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without > power cycle > .... > > I worked with Judith Mendez to get to the bottom of this - she shared > logs from the AM65 IDK board and we went back and forth analyzing > them, which pointed to a board-level power sequencing problem on > AM65x rather than an issue with this patch. In her words: > "So it is truly a power issue, I have a patch to fix the issue on am65x. > There is nothing wrong with your patch, coincidentally my power issue > caused am65x to fall into a weird state and your commit caught that. > So actually, thanks. I can now send my proper fix to the u-boot mailing > list." > > So this patch did not introduce a regression - it actually helped uncover > a latent power-sequencing issue on the AM65x board that was > independent of this change. Judith will be sending a separate fix for the > AM65x board issue. Thanks for the updating. Thanks, Peng > > I'd consider this matter closed with respect to this patch. Thanks Judith > for digging into this and confirming the root cause. > > Regards, > Tanmay ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle 2026-07-13 10:21 ` Peng Fan @ 2026-07-14 1:37 ` Mendez, Judith 0 siblings, 0 replies; 17+ messages in thread From: Mendez, Judith @ 2026-07-14 1:37 UTC (permalink / raw) To: Peng Fan, Kathpalia, Tanmay, Peng Fan (OSS) Cc: u-boot@lists.denx.de, trini@konsulko.com, jh80.chung@samsung.com, marex@denx.de, tien.fong.chee@altera.com Hi Peng, Tanmay, On 7/13/2026 5:21 AM, Peng Fan wrote: > Hi Tanmay, > >> Subject: Re: [PATCH] mmc: sd: Handle UHS-I voltage signaling without >> power cycle >> > .... >> >> I worked with Judith Mendez to get to the bottom of this - she shared >> logs from the AM65 IDK board and we went back and forth analyzing >> them, which pointed to a board-level power sequencing problem on >> AM65x rather than an issue with this patch. In her words: >> "So it is truly a power issue, I have a patch to fix the issue on am65x. >> There is nothing wrong with your patch, coincidentally my power issue >> caused am65x to fall into a weird state and your commit caught that. >> So actually, thanks. I can now send my proper fix to the u-boot mailing >> list." >> >> So this patch did not introduce a regression - it actually helped uncover >> a latent power-sequencing issue on the AM65x board that was >> independent of this change. Judith will be sending a separate fix for the >> AM65x board issue. > > Thanks for the updating. > > Thanks, > Peng > >> >> I'd consider this matter closed with respect to this patch. Thanks Judith >> for digging into this and confirming the root cause. >> Confirm on the above. No problem, thanks to you for the collab (: ~ Judith ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-07-14 1:37 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-10-21 20:45 [PATCH] mmc: sd: Handle UHS-I voltage signaling without power cycle Tanmay Kathpalia 2025-10-22 3:16 ` Peng Fan 2025-10-22 14:06 ` Tanmay Kathpalia 2025-10-23 8:46 ` Peng Fan (OSS) 2026-05-13 23:39 ` Judith Mendez 2026-05-14 18:50 ` Kathpalia, Tanmay 2026-05-14 22:21 ` Judith Mendez 2026-05-16 9:44 ` Peng Fan 2026-05-16 9:43 ` Kathpalia, Tanmay 2026-05-16 11:44 ` Kathpalia, Tanmay 2026-05-27 23:22 ` Judith Mendez 2026-05-29 17:21 ` Kathpalia, Tanmay 2026-06-08 15:19 ` Judith Mendez 2026-06-09 7:51 ` Kathpalia, Tanmay 2026-07-13 9:45 ` Kathpalia, Tanmay 2026-07-13 10:21 ` Peng Fan 2026-07-14 1:37 ` Mendez, Judith
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox