* [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver
@ 2026-10-02 21:29 Dave Klotz
2026-10-02 21:29 ` [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz
` (4 more replies)
0 siblings, 5 replies; 33+ messages in thread
From: Dave Klotz @ 2026-10-02 21:29 UTC (permalink / raw)
To: u-boot
Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Tanmay Kathpalia,
Yixun Lan, Tom Rini, u-boot-spacemit
Three fixes for the K1 SDHCI driver that went into next with
"mmc: k1: add sdhci platform driver":
1. A node without max-frequency asks the clock framework for 0 Hz and
then fails in sdhci_setup_cfg(), and any non-zero return from
clk_set_rate() is treated as an error although it returns the rate.
2. The SPL reads SD cards one block per command, about 2000 commands
for a 1 MiB u-boot.itb. Multi-block PIO reads work in the SPL.
3. A failed probe releases the clock and reset bulks, whose first
entries are the SDH AXI clock and reset shared by all three
controllers. One controller failing then hangs the next access to
another. Patch 1 removes the trigger I hit, but the error path
should not stop the other controllers either way.
Tested on an OrangePi RV2 (upstream k1-orangepi-rv2.dts plus a board
-u-boot.dtsi and defconfig I will post separately): SPL boot from
microSD with multi-block reads, both SDHCI controllers probing in
U-Boot proper, and an EFI boot of FreeBSD from there. Before patch 3,
with the RV2's eMMC node lacking max-frequency, U-Boot hung at "MMC:".
On an OrangePi R2S booting from eMMC, the io clock change in probe
only takes effect with "clk: spacemit: ccu_mix: fix inverted condition
in ccu_mix_trigger_fc()" from the K3 clock series applied.
Dave Klotz (3):
mmc: k1: handle a missing max-frequency and clk_set_rate()'s return
value
mmc: k1: let the SPL read SD cards more than one block at a time
mmc: k1: do not release the shared AXI clock and reset on probe
failure
drivers/mmc/spacemit_sdhci.c | 45 ++++++++++++++++++++++--------------
1 file changed, 28 insertions(+), 17 deletions(-)
base-commit: a000f2af240eaa996cec92f8d44bad96fdf3f898
--
2.55.0
^ permalink raw reply [flat|nested] 33+ messages in thread* [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 2026-10-02 21:29 [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz @ 2026-10-02 21:29 ` Dave Klotz 2026-10-04 9:14 ` Kathpalia, Tanmay 2026-10-04 9:30 ` Kathpalia, Tanmay 2026-10-02 21:29 ` [PATCH 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz ` (3 subsequent siblings) 4 siblings, 2 replies; 33+ messages in thread From: Dave Klotz @ 2026-10-02 21:29 UTC (permalink / raw) To: u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Tanmay Kathpalia, Yixun Lan, Tom Rini, u-boot-spacemit The driver sets the io clock to the max-frequency the device tree gives and fails the probe on any non-zero return from clk_set_rate(). Two problems follow: - clk_set_rate() returns the new rate on success and a negative error code on failure. The SpacemiT clock driver happens to return 0, but any clock driver that reports the rate makes the probe fail. - A node without max-frequency asks for 0 Hz. On the K1 clock driver that picks no divider at all and writes whatever the calculation left behind into the io clock's divider field; host->max_clk is then 0, the capabilities register gives no base clock either, and the probe fails in sdhci_setup_cfg(). Treat only a negative return as an error. Without max-frequency, leave the io clock as an earlier stage set it and run from its current rate. Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> --- drivers/mmc/spacemit_sdhci.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index f5578f38bd..bbd49b76c6 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -606,10 +606,28 @@ static int spacemit_sdhci_probe(struct udevice *dev) goto err_reset; } - ret = clk_set_rate(&clk, plat->cfg.f_max); - if (ret) { - log_err("Failed to set io clk: %d\n", ret); - goto err_reset; + /* + * Without max-frequency there is no rate to ask for: leave the io + * clock as an earlier stage set it and run from its current rate. The + * capabilities register gives no base clock on the K1, so it cannot + * stand in. clk_set_rate() returns the new rate on success, so only a + * negative value is an error. + */ + if (plat->cfg.f_max) { + long rate = clk_set_rate(&clk, plat->cfg.f_max); + + if (rate < 0) { + ret = rate; + log_err("Failed to set io clk: %d\n", ret); + goto err_reset; + } + } else { + plat->cfg.f_max = clk_get_rate(&clk); + if (IS_ERR_VALUE(plat->cfg.f_max) || !plat->cfg.f_max) { + ret = -EINVAL; + log_err("No max-frequency and no io clk rate\n"); + goto err_reset; + } } /* Set quirks */ -- 2.55.0 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 2026-10-02 21:29 ` [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz @ 2026-10-04 9:14 ` Kathpalia, Tanmay 2026-10-04 9:30 ` Kathpalia, Tanmay 1 sibling, 0 replies; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-04 9:14 UTC (permalink / raw) To: Dave Klotz, u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Yixun Lan, Tom Rini, u-boot-spacemit On 03-10-2026 02:59, Dave Klotz wrote: > The driver sets the io clock to the max-frequency the device tree gives > and fails the probe on any non-zero return from clk_set_rate(). Two > problems follow: > > - clk_set_rate() returns the new rate on success and a negative error > code on failure. The SpacemiT clock driver happens to return 0, but > any clock driver that reports the rate makes the probe fail. > - A node without max-frequency asks for 0 Hz. On the K1 clock driver > that picks no divider at all and writes whatever the calculation left > behind into the io clock's divider field; host->max_clk is then 0, > the capabilities register gives no base clock either, and the probe > fails in sdhci_setup_cfg(). > > Treat only a negative return as an error. Without max-frequency, leave > the io clock as an earlier stage set it and run from its current rate. > > Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> > --- > drivers/mmc/spacemit_sdhci.c | 26 ++++++++++++++++++++++---- > 1 file changed, 22 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index f5578f38bd..bbd49b76c6 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -606,10 +606,28 @@ static int spacemit_sdhci_probe(struct udevice *dev) > goto err_reset; > } > > - ret = clk_set_rate(&clk, plat->cfg.f_max); > - if (ret) { > - log_err("Failed to set io clk: %d\n", ret); > - goto err_reset; > + /* > + * Without max-frequency there is no rate to ask for: leave the io > + * clock as an earlier stage set it and run from its current rate. The > + * capabilities register gives no base clock on the K1, so it cannot > + * stand in. clk_set_rate() returns the new rate on success, so only a > + * negative value is an error. > + */ > + if (plat->cfg.f_max) { > + long rate = clk_set_rate(&clk, plat->cfg.f_max); The clock API returns ulong; please use ulong rate with IS_ERR_VALUE(rate) for consistency. > + > + if (rate < 0) { > + ret = rate; > + log_err("Failed to set io clk: %d\n", ret); > + goto err_reset; > + } > + } else { > + plat->cfg.f_max = clk_get_rate(&clk); clk_get_rate() returns ulong, but f_max is uint. On RV64, assigning a negative error first truncates it, so IS_ERR_VALUE(f_max) no longer detects the error. Please validate the ulong rate before assigning it: rate = clk_get_rate(&clk); if (IS_ERR_VALUE(rate) || !rate) { ret = rate ? (int)rate : -EINVAL; goto err_reset; } plat->cfg.f_max = rate; ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 2026-10-02 21:29 ` [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz 2026-10-04 9:14 ` Kathpalia, Tanmay @ 2026-10-04 9:30 ` Kathpalia, Tanmay 2026-10-05 17:46 ` Dave Klotz 1 sibling, 1 reply; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-04 9:30 UTC (permalink / raw) To: Dave Klotz, u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Yixun Lan, Tom Rini, u-boot-spacemit On 03-10-2026 02:59, Dave Klotz wrote: > The driver sets the io clock to the max-frequency the device tree gives > and fails the probe on any non-zero return from clk_set_rate(). Two > problems follow: > > - clk_set_rate() returns the new rate on success and a negative error > code on failure. The SpacemiT clock driver happens to return 0, but > any clock driver that reports the rate makes the probe fail. > - A node without max-frequency asks for 0 Hz. On the K1 clock driver > that picks no divider at all and writes whatever the calculation left > behind into the io clock's divider field; host->max_clk is then 0, > the capabilities register gives no base clock either, and the probe > fails in sdhci_setup_cfg(). > > Treat only a negative return as an error. Without max-frequency, leave > the io clock as an earlier stage set it and run from its current rate. > > Signed-off-by: Dave Klotz<DaveWK225@protonmail.com> > --- > drivers/mmc/spacemit_sdhci.c | 26 ++++++++++++++++++++++---- > 1 file changed, 22 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index f5578f38bd..bbd49b76c6 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -606,10 +606,28 @@ static int spacemit_sdhci_probe(struct udevice *dev) > goto err_reset; > } > > - ret = clk_set_rate(&clk, plat->cfg.f_max); > - if (ret) { > - log_err("Failed to set io clk: %d\n", ret); > - goto err_reset; > + /* > + * Without max-frequency there is no rate to ask for: leave the io > + * clock as an earlier stage set it and run from its current rate. The > + * capabilities register gives no base clock on the K1, so it cannot > + * stand in. clk_set_rate() returns the new rate on success, so only a > + * negative value is an error. > + */ > + if (plat->cfg.f_max) { > + long rate = clk_set_rate(&clk, plat->cfg.f_max); The clock API returns ulong; please use ulong rate with IS_ERR_VALUE(rate) for consistency. > + > + if (rate < 0) { > + ret = rate; > + log_err("Failed to set io clk: %d\n", ret); > + goto err_reset; > + } > + } else { > + plat->cfg.f_max = clk_get_rate(&clk); clk_get_rate() returns ulong, but f_max is uint. On RV64, assigning a negative error first truncates it, so IS_ERR_VALUE(f_max) no longer detects the error. Please validate the ulong rate before assigning it: rate = clk_get_rate(&clk); if (IS_ERR_VALUE(rate) || !rate) { ret = rate ? (int)rate : -EINVAL; goto err_reset; } plat->cfg.f_max = rate; ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 2026-10-04 9:30 ` Kathpalia, Tanmay @ 2026-10-05 17:46 ` Dave Klotz 0 siblings, 0 replies; 33+ messages in thread From: Dave Klotz @ 2026-10-05 17:46 UTC (permalink / raw) To: Tanmay Kathpalia Cc: Yixun Lan, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini Hi Tanmay, Thanks for the review. I've updated v2 patch 1/3 to keep the clock API return values in ulong and test IS_ERR_VALUE(). The missing-max-frequency path now checks clk_get_rate() before assigning it to cfg.f_max, rejects a zero rate, and preserves the clock API's error code. I've retained your Reviewed-by on patches 2/3 and 3/3. Patch 2/3 now explains the intentional reversal of the driver's v9 single-block SPL policy and the MMC core's CMD12 path; its code is unchanged from v1. The revised three-patch stack replays cleanly on its exact base and passes checkpatch. Both R2S and RV2 configurations build successfully. With the separate DDR firmware overlap fix included, the combined firmware passed DDR initialization, FIT verification and automatic EFI/FreeBSD boot on the 2 GiB R2S and the 4 GiB RV2. These are combined-firmware warm-boot results, not isolated tests of this series. Cold boot of the corrected firmware, alternate cards, missing-frequency/error paths and error recovery remain untested. Thanks, Dave ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-02 21:29 [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz 2026-10-02 21:29 ` [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz @ 2026-10-02 21:29 ` Dave Klotz 2026-10-04 9:28 ` Kathpalia, Tanmay 2026-10-02 21:29 ` [PATCH 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz ` (2 subsequent siblings) 4 siblings, 1 reply; 33+ messages in thread From: Dave Klotz @ 2026-10-02 21:29 UTC (permalink / raw) To: u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Tanmay Kathpalia, Yixun Lan, Tom Rini, u-boot-spacemit spacemit_sdhci_get_b_max() limits every SD read in the SPL to a single block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 separate commands. The controller handles multi-block PIO reads in the SPL: the OrangePi RV2 has loaded U-Boot from microSD with them through the v2026.07 and v2026.10 trees. Drop the limit and use the host's b_max. Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> --- drivers/mmc/spacemit_sdhci.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index bbd49b76c6..fec95e3bd7 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -324,16 +324,6 @@ static int spacemit_sdhci_wait_dat0(struct udevice *dev, int state, return 0; } -static int spacemit_sdhci_get_b_max(struct udevice *dev, void *dst, - lbaint_t blkcnt) -{ - struct mmc *mmc = mmc_get_mmc_dev(dev); - - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) - return 1; - return mmc->cfg->b_max; -} - static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) { struct mmc *mmc = host->mmc; @@ -574,7 +564,6 @@ static int spacemit_sdhci_probe(struct udevice *dev) spacemit_mmc_ops = sdhci_ops; spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; ret = clk_get_bulk(dev, &plat->clks); if (ret) { -- 2.55.0 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-02 21:29 ` [PATCH 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz @ 2026-10-04 9:28 ` Kathpalia, Tanmay 0 siblings, 0 replies; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-04 9:28 UTC (permalink / raw) To: Dave Klotz, u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Yixun Lan, Tom Rini, u-boot-spacemit On 03-10-2026 02:59, Dave Klotz wrote: > spacemit_sdhci_get_b_max() limits every SD read in the SPL to a single > block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 > separate commands. The controller handles multi-block PIO reads in the > SPL: the OrangePi RV2 has loaded U-Boot from microSD with them through > the v2026.07 and v2026.10 trees. > > Drop the limit and use the host's b_max. > > Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure 2026-10-02 21:29 [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz 2026-10-02 21:29 ` [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz 2026-10-02 21:29 ` [PATCH 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz @ 2026-10-02 21:29 ` Dave Klotz 2026-10-04 9:28 ` Kathpalia, Tanmay 2026-10-02 22:06 ` [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz 2026-10-05 17:50 ` [PATCH v2 " Dave Klotz 4 siblings, 1 reply; 33+ messages in thread From: Dave Klotz @ 2026-10-02 21:29 UTC (permalink / raw) To: u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Tanmay Kathpalia, Yixun Lan, Tom Rini, u-boot-spacemit When the probe fails, the driver releases its clock and reset bulks. clk_release_bulk() disables every clock and reset_release_bulk() asserts every reset, and the first entry of each is the SDH AXI bus clock and reset, which all three SDHCI controllers of the K1 share. One controller failing to probe therefore stops the bus of the others, and the next register access to any of them hangs the hart. On an OrangePi RV2, whose device tree enables the eMMC controller without a max-frequency, the eMMC probe failed in sdhci_setup_cfg() and U-Boot then hung at "MMC:" probing the microSD controller. Keep the clocks running and the resets deasserted on failure. Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> --- drivers/mmc/spacemit_sdhci.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index fec95e3bd7..c191d78067 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -640,10 +640,14 @@ static int spacemit_sdhci_probe(struct udevice *dev) spacemit_sdhci_phy_init(dev, host); return 0; + /* + * Leave the clocks and resets alone on failure. The "core" clock and + * the "axi" reset are the AXI clock and reset that every SDHCI + * controller of the K1 shares: releasing them would gate the bus of + * the other controllers, and the next access to one of them hangs. + */ err_reset: - reset_release_bulk(&plat->resets); err_clk: - clk_release_bulk(&plat->clks); return ret; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure 2026-10-02 21:29 ` [PATCH 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz @ 2026-10-04 9:28 ` Kathpalia, Tanmay 0 siblings, 0 replies; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-04 9:28 UTC (permalink / raw) To: Dave Klotz, u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Yixun Lan, Tom Rini, u-boot-spacemit On 03-10-2026 02:59, Dave Klotz wrote: > When the probe fails, the driver releases its clock and reset bulks. > clk_release_bulk() disables every clock and reset_release_bulk() > asserts every reset, and the first entry of each is the SDH AXI bus > clock and reset, which all three SDHCI controllers of the K1 share. > > One controller failing to probe therefore stops the bus of the others, > and the next register access to any of them hangs the hart. On an > OrangePi RV2, whose device tree enables the eMMC controller without a > max-frequency, the eMMC probe failed in sdhci_setup_cfg() and U-Boot > then hung at "MMC:" probing the microSD controller. > > Keep the clocks running and the resets deasserted on failure. > > Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver 2026-10-02 21:29 [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz ` (2 preceding siblings ...) 2026-10-02 21:29 ` [PATCH 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz @ 2026-10-02 22:06 ` Dave Klotz 2026-10-05 17:50 ` [PATCH v2 " Dave Klotz 4 siblings, 0 replies; 33+ messages in thread From: Dave Klotz @ 2026-10-02 22:06 UTC (permalink / raw) To: u-boot Cc: Huan Zhou, Eric Chung, Peng Fan, Jaehoon Chung, Tanmay Kathpalia, Yixun Lan, Tom Rini Also tested on an OrangePi R2S (K1, 2 GiB, boots from eMMC), with the same tree as the RV2 runs (upstream next plus these series and board support that is not posted yet): - the SPL starts the eMMC (SDH2, io clock moved from the BootROM's 409.6 MHz to 204.8 MHz through max-frequency) and loads U-Boot; - U-Boot proper runs the eMMC in HS200 with tuning ("Mode: HS200 (200MHz)"), finds the EFI system partition and boots FreeBSD; - FreeBSD then runs the eMMC at 200 MHz, 8-bit, without errors. Patch 2 (SD only) and the failure path of patch 3 are not exercised on this board. ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v2 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver 2026-10-02 21:29 [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz ` (3 preceding siblings ...) 2026-10-02 22:06 ` [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz @ 2026-10-05 17:50 ` Dave Klotz 2026-10-05 17:55 ` [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz ` (2 more replies) 4 siblings, 3 replies; 33+ messages in thread From: Dave Klotz @ 2026-10-05 17:50 UTC (permalink / raw) To: Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tanmay Kathpalia, Tom Rini This revision addresses Tanmay Kathpalia's review of patch 1/3: use ulong and IS_ERR_VALUE() for clock API results, and validate the current clock rate before narrowing it to cfg.f_max. Preserve the actual error code and reject a zero current rate. Patches 2/3 and 3/3 retain Tanmay's Reviewed-by. Patch 2/3 also explains the intentional reversal of the driver's v9 single-block SPL policy and the MMC core's CMD12 path; its executable change is unchanged from v1. Patch 3/3's executable change is unchanged from v1. Exact-base source replay and checkpatch pass for all three revised patches. Both R2S and RV2 configurations build successfully. An integration containing this series, the clock-mux rename and a separate DDR firmware overlap fix passed warm-boot tests on a 2 GiB OrangePi R2S and a 4 GiB OrangePi RV2. Both reached DDR/SPL, FIT verification and automatic EFI boot to their existing FreeBSD 16 installation, with the expected memory and eight CPUs. These are combined-integration results, not isolated tests of this series. Cold boot of the corrected firmware, alternate cards, missing-frequency/ clock error paths and error recovery remain untested. Dave Klotz (3): mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value mmc: k1: let the SPL read SD cards more than one block at a time mmc: k1: do not release the shared AXI clock and reset on probe failure ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 2026-10-05 17:50 ` [PATCH v2 " Dave Klotz @ 2026-10-05 17:55 ` Dave Klotz 2026-10-06 5:40 ` Kathpalia, Tanmay 2026-10-10 8:45 ` Yixun Lan 2026-10-05 18:01 ` [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz 2026-10-05 18:11 ` [PATCH v2 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz 2 siblings, 2 replies; 33+ messages in thread From: Dave Klotz @ 2026-10-05 17:55 UTC (permalink / raw) To: Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tanmay Kathpalia, Tom Rini The driver sets the io clock to the max-frequency the device tree gives and fails the probe on any non-zero return from clk_set_rate(). Two problems follow: - clk_set_rate() returns the new rate on success and a negative error code on failure. The SpacemiT clock driver happens to return 0, but any clock driver that reports the rate makes the probe fail. - A node without max-frequency asks for 0 Hz. On the K1 clock driver that picks no divider at all and writes whatever the calculation left behind into the io clock's divider field; host->max_clk is then 0, the capabilities register gives no base clock either, and the probe fails in sdhci_setup_cfg(). Treat only a negative return as an error. Without max-frequency, leave the io clock as an earlier stage set it and run from its current rate. Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> Changes in v2: - Use ulong and IS_ERR_VALUE() for the clock API return values. - Validate clk_get_rate() before narrowing to cfg.f_max and retain the error. --- drivers/mmc/spacemit_sdhci.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index f5578f38bd..6488ae0fdb 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -606,10 +606,30 @@ goto err_reset; } - ret = clk_set_rate(&clk, plat->cfg.f_max); - if (ret) { - log_err("Failed to set io clk: %d\n", ret); - goto err_reset; + /* + * Without max-frequency there is no rate to ask for: leave the io + * clock as an earlier stage set it and run from its current rate. The + * capabilities register gives no base clock on the K1, so it cannot + * stand in. clk_set_rate() returns the new rate on success, so only a + * negative value is an error. + */ + if (plat->cfg.f_max) { + ulong rate = clk_set_rate(&clk, plat->cfg.f_max); + + if (IS_ERR_VALUE(rate)) { + ret = (int)rate; + log_err("Failed to set io clk: %d\n", ret); + goto err_reset; + } + } else { + ulong rate = clk_get_rate(&clk); + + if (IS_ERR_VALUE(rate) || !rate) { + ret = rate ? (int)rate : -EINVAL; + log_err("No max-frequency and no io clk rate\n"); + goto err_reset; + } + plat->cfg.f_max = rate; } /* Set quirks */ -- 2.55.0 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 2026-10-05 17:55 ` [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz @ 2026-10-06 5:40 ` Kathpalia, Tanmay 2026-10-10 8:45 ` Yixun Lan 1 sibling, 0 replies; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-06 5:40 UTC (permalink / raw) To: Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tom Rini On 05-10-2026 23:25, Dave Klotz wrote: > The driver sets the io clock to the max-frequency the device tree gives > and fails the probe on any non-zero return from clk_set_rate(). Two > problems follow: > > - clk_set_rate() returns the new rate on success and a negative error > code on failure. The SpacemiT clock driver happens to return 0, but > any clock driver that reports the rate makes the probe fail. > - A node without max-frequency asks for 0 Hz. On the K1 clock driver > that picks no divider at all and writes whatever the calculation left > behind into the io clock's divider field; host->max_clk is then 0, > the capabilities register gives no base clock either, and the probe > fails in sdhci_setup_cfg(). > > Treat only a negative return as an error. Without max-frequency, leave > the io clock as an earlier stage set it and run from its current rate. > > Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> > Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 2026-10-05 17:55 ` [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz 2026-10-06 5:40 ` Kathpalia, Tanmay @ 2026-10-10 8:45 ` Yixun Lan 1 sibling, 0 replies; 33+ messages in thread From: Yixun Lan @ 2026-10-10 8:45 UTC (permalink / raw) To: Dave Klotz Cc: Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tanmay Kathpalia, Tom Rini Hi Dave, On 17:55 Mon 05 Oct , Dave Klotz wrote: > The driver sets the io clock to the max-frequency the device tree gives > and fails the probe on any non-zero return from clk_set_rate(). Two > problems follow: > I can understand your problem and what to solve.. but wouldn't it be a more simpler way to just setting max-frequency? currently, only two boards are supported in mainline uboot: k1-bananapi-f3 k1-musepi-pro so, you likely also need to add a customized u-boot dtsi file for supporting OrangePi R2S, something as file below, where setting the max-frequency property arch/riscv/dts/k1-bananapi-f3-u-boot.dtsi > - clk_set_rate() returns the new rate on success and a negative error > code on failure. The SpacemiT clock driver happens to return 0, but > any clock driver that reports the rate makes the probe fail. Could you elaborate a bit "happens to return 0, ..probe fail" ? > - A node without max-frequency asks for 0 Hz. On the K1 clock driver A node with DT property get 0 Hz - that's expected behavior > that picks no divider at all and writes whatever the calculation left > behind into the io clock's divider field; host->max_clk is then 0, > the capabilities register gives no base clock either, and the probe > fails in sdhci_setup_cfg(). I occur to me, we should further check these logic, like a rate = 0 input for clk subsystem - clk_set_rate(, 0) is actually a valid case? also if need to set host->max_clk .. > > Treat only a negative return as an error. Without max-frequency, leave > the io clock as an earlier stage set it and run from its current rate. > > Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> > > Changes in v2: > - Use ulong and IS_ERR_VALUE() for the clock API return values. > - Validate clk_get_rate() before narrowing to cfg.f_max and retain the error. > > --- > drivers/mmc/spacemit_sdhci.c | 28 ++++++++++++++++++++++++---- > 1 file changed, 24 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index f5578f38bd..6488ae0fdb 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -606,10 +606,30 @@ > goto err_reset; > } > > - ret = clk_set_rate(&clk, plat->cfg.f_max); > - if (ret) { > - log_err("Failed to set io clk: %d\n", ret); > - goto err_reset; > + /* > + * Without max-frequency there is no rate to ask for: leave the io > + * clock as an earlier stage set it and run from its current rate. The I'm wondering if we could set a sane default max-frequency if no DT property provided? as we can't always trust previous earlier stage which may in an undetermined state, it will be fragile and easy to fail.. > + * capabilities register gives no base clock on the K1, so it cannot > + * stand in. clk_set_rate() returns the new rate on success, so only a > + * negative value is an error. > + */ > + if (plat->cfg.f_max) { > + ulong rate = clk_set_rate(&clk, plat->cfg.f_max); > + > + if (IS_ERR_VALUE(rate)) { > + ret = (int)rate; > + log_err("Failed to set io clk: %d\n", ret); > + goto err_reset; > + } > + } else { > + ulong rate = clk_get_rate(&clk); > + > + if (IS_ERR_VALUE(rate) || !rate) { > + ret = rate ? (int)rate : -EINVAL; > + log_err("No max-frequency and no io clk rate\n"); > + goto err_reset; > + } > + plat->cfg.f_max = rate; > } > > /* Set quirks */ > -- > 2.55.0 > -- Yixun Lan (dlan) ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-05 17:50 ` [PATCH v2 " Dave Klotz 2026-10-05 17:55 ` [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz @ 2026-10-05 18:01 ` Dave Klotz 2026-10-10 6:17 ` Zixian Zeng 2026-10-05 18:11 ` [PATCH v2 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz 2 siblings, 1 reply; 33+ messages in thread From: Dave Klotz @ 2026-10-05 18:01 UTC (permalink / raw) To: Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tanmay Kathpalia, Tom Rini spacemit_sdhci_get_b_max() limits every SD read in the SPL to a single block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 separate commands. The controller handles multi-block PIO reads in the SPL: the OrangePi RV2 has loaded U-Boot from microSD with them through the v2026.07 and v2026.10 trees. Drop the limit and use the host's b_max. The merged v13 cover retains the v9 changelog entry choosing single- block SD reads in SPL. This reverses that deliberate policy for the recorded RV2 SPL boot use case; no general multi-card reliability claim is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends CMD12 after a multi-block read rather than requiring CMD23. Additional card models, cold boots and transfer-error recovery remain required. Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> --- Validation: unchanged executable change from v1; exact-base source replay and checkpatch pass. The corrected combined integration, with separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. This is an integration result, not an isolated test of this patch. drivers/mmc/spacemit_sdhci.c | 11 ----------- 1 file changed, 0 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index 6488ae0fdb..4284553177 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -324,16 +324,6 @@ return 0; } -static int spacemit_sdhci_get_b_max(struct udevice *dev, void *dst, - lbaint_t blkcnt) -{ - struct mmc *mmc = mmc_get_mmc_dev(dev); - - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) - return 1; - return mmc->cfg->b_max; -} - static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) { struct mmc *mmc = host->mmc; @@ -574,7 +564,6 @@ spacemit_mmc_ops = sdhci_ops; spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; ret = clk_get_bulk(dev, &plat->clks); if (ret) { -- 2.55.0 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-05 18:01 ` [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz @ 2026-10-10 6:17 ` Zixian Zeng 2026-10-10 19:02 ` Kathpalia, Tanmay 0 siblings, 1 reply; 33+ messages in thread From: Zixian Zeng @ 2026-10-10 6:17 UTC (permalink / raw) To: Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tanmay Kathpalia, Tom Rini, u-boot-spacemit Hi, Dave: On 2026/10/6 02:01, Dave Klotz wrote: > spacemit_sdhci_get_b_max() limits every SD read in the SPL to a single > block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 > separate commands. The controller handles multi-block PIO reads in the > SPL: the OrangePi RV2 has loaded U-Boot from microSD with them through > the v2026.07 and v2026.10 trees. > > Drop the limit and use the host's b_max. > > The merged v13 cover retains the v9 changelog entry choosing single- > block SD reads in SPL. This reverses that deliberate policy for the > recorded RV2 SPL boot use case; no general multi-card reliability claim > is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends > CMD12 after a multi-block read rather than requiring CMD23. Additional > card models, cold boots and transfer-error recovery remain required. > > Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> > Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> > --- > Validation: unchanged executable change from v1; exact-base source > replay and checkpatch pass. The corrected combined integration, with > separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and > automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. This is > an integration result, not an isolated test of this patch. > > drivers/mmc/spacemit_sdhci.c | 11 ----------- > 1 file changed, 0 insertions(+), 11 deletions(-) > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index 6488ae0fdb..4284553177 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -324,16 +324,6 @@ > return 0; > } > > -static int spacemit_sdhci_get_b_max(struct udevice *dev, void *dst, > - lbaint_t blkcnt) > -{ > - struct mmc *mmc = mmc_get_mmc_dev(dev); > - > - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) > - return 1; > - return mmc->cfg->b_max; > -} > - > static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) > { > struct mmc *mmc = host->mmc; > @@ -574,7 +564,6 @@ > > spacemit_mmc_ops = sdhci_ops; > spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; > - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; > > ret = clk_get_bulk(dev, &plat->clks); > if (ret) { Using the current version of the next branch u-boot (ed869863c7), with your MMC patch series applied. Since the SPI controller is not enabled by default on the BananaPi-F3, I also applied another patch series: Link: https://lore.kernel.org/u-boot/cover.1790976767.git.DaveWK225@protonmail.com/ I tested u-boot SPL with three SD cards on a BananaPi-F3 and found a reproducible issue, the specific error I encountered is spl: partition error (Error: -38) At the meantime, when i was revert the commit: mmc: k1: let the SPL read SD cards more than one block at a time the error has gone. Same SD card, same operation steps. Maybe BananaPi-F3 do not support read SD cards more than one block at a time? The issue logs are as follows: ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ↑ git log --oneline origin/next..HEAD 6b4af8b1dd8 (HEAD -> k1-dave-mmc) mmc: k1: do not release the shared AXI clock and reset on probe failure 4114764d716 mmc: k1: let the SPL read SD cards more than one block at a time 6676ce89521 mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller in SPL ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ↑ export CROSS_COMPILE=riscv64-linux-gnu- ARCH=riscv export DDR=/home/hack/k1/spacemit-firmware/k1/v0.2/ddr_fw.bin export SBI=/home/hack/k1/opensbi/build/platform/generic/firmware/fw_dynamic.bin ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ↑ make O=build-fix spacemit_k1_defconfig make O=build-fix DDR_FW_FILE=$DDR OPENSBI=$SBI DEVICE_TREE=spacemit/k1-bananapi-f3 -j"$(nproc)" GEN Makefile # # configuration written to .config # GEN Makefile scripts/kconfig/conf --syncconfig Kconfig CFG u-boot.cfg GEN include/autoconf.mk.dep CFG spl/u-boot.cfg GEN include/autoconf.mk GEN spl/include/autoconf.mk GEN Makefile UPD include/generated/timestamp_autogenerated.h ENVC include/generated/env.txt Using .. as source for U-Boot ENVP include/generated/env.in ENVT include/generated/environment.h PYMOD rebuild LDS u-boot.lds CC common/version.o AR common/built-in.a CC env/common.o AR env/built-in.a LD u-boot OBJCOPY u-boot.srec OBJCOPY u-boot-nodtb.bin SYM u-boot.sym MKIMAGE fit-dtb.blob MKIMAGE u-boot.img CC spl/common/spl/spl.o MKIMAGE u-boot-dtb.img CAT u-boot-fit-dtb.bin COPY u-boot.bin AR spl/common/spl/built-in.a LD spl/u-boot-spl OBJCOPY spl/u-boot-spl-nodtb.bin SYM spl/u-boot-spl.sym CAT spl/u-boot-spl-dtb.bin COPY spl/u-boot-spl.bin BINMAN .binman_stamp OFCHK .config ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ↑ cd ~/k1/uboot-2022.10/ ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ cat mainline-fsbl.sh SPL=$1 FSBL=$2 cd /home/hack/k1/uboot-2022.10 cp "$SPL" board/spacemit/k1-x/ python3 tools/build_binary_file.py \ -c board/spacemit/k1-x/configs/fsbl_ddr.json \ -o "$FSBL" rm -f board/spacemit/k1-x/u-boot-spl-ddr.bin echo "Mainline SPL is included in $FSBL" ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ bash mainline-fsbl.sh /home/hack/k1/u-boot/build-fix/u-boot-spl-ddr.bin /home/hack/k1/uboot-2022.10/mainline-spl/FSBL-dave.bin (2026-10-09 21:37:10,279) arch : RISCV64 (2026-10-09 21:37:10,279) description : spacemit k1x fsbl image writing RSA key writing RSA key Mainline SPL is included in /home/hack/k1/uboot-2022.10/mainline-spl/FSBL-dave.bin ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ lsblk /dev/mmcblk0 NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS mmcblk0 179:0 0 29.7G 0 disk ├─mmcblk0p1 179:1 0 256K 0 part ├─mmcblk0p2 179:2 0 64K 0 part ├─mmcblk0p3 179:3 0 1M 0 part ├─mmcblk0p4 179:4 0 2M 0 part ├─mmcblk0p5 179:5 0 256M 0 part └─mmcblk0p6 179:6 0 29.5G 0 part ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ sudo dd if=/home/hack/k1/flash-dir/factory/bootinfo_sd.bin of=/dev/mmcblk0 bs=512 seek=0 count=1 conv=notrunc status=progress 0+1 records in 0+1 records out 80 bytes copied, 0.685238 s, 0.1 kB/s ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ sudo dd if=/home/hack/k1/uboot-2022.10/mainline-spl/FSBL-dave.bin of=/dev/mmcblk0 bs=512 seek=256 conv=notrunc status=progress 304+1 records in 304+1 records out 156128 bytes (156 kB, 152 KiB) copied, 0.72263 s, 216 kB/s ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ sudo dd if=/home/hack/k1/u-boot/build-fix/u-boot.itb of=/dev/mmcblk0 bs=512 seek=4096 conv=notrunc status=progress 1953+1 records in 1953+1 records out 1000145 bytes (1.0 MB, 977 KiB) copied, 0.818001 s, 1.2 MB/s ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ sync ⋊> hack@morise ⋊> ~/k/uboot-2022.10 on k1-bl-v2.2.y ◦ picocom -b 115200 /dev/ttyUSB1 picocom v3.1 port is : /dev/ttyUSB1 flowcontrol : none baudrate is : 115200 parity is : none databits are : 8 stopbits are : 1 escape is : C-a local echo is : no noinit is : no noreset is : no hangup is : no nolock is : no send_cmd is : sz -vv receive_cmd is : rz -vv -E imap is : omap is : emap is : crcrlf,delbs, logfile is : none initstring : none exit_after is : not set exit is : no Type [C-a] [C-h] to see available commands Terminal ready sys: 0x0 try sd... bm:3 j... <debug_uart> U-Boot SPL 2026.10-rc5-00639-g6b4af8b1dd89 (Oct 09 2026 - 21:36:48 +0800) Fail to detect board:-2 vdd_core, value:900000 vdd_1v8, value:1800000 vdd_1v8_mmc, value:1800000 DDR firmware: [0xc081d340]:0xf0227179, size:0x8d98 DDR is ready No SPI controller (-19) Trying to boot from MMC2 spl: partition error Error: -38 SPL: Unsupported Boot Device! Trying to boot from MMC1 alloc space exhausted ptr 104380 limit 100000 Aligned buffer alloc failed spl: could not find mmc device 0. error: -19 Error: -19 SPL: Unsupported Boot Device! Trying to boot from SPI Invalid bus 0 (err=-19) SPI probe failed. Error: -19 SPL: Unsupported Boot Device! SPL: Unsupported Boot Device! SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### Reported-by: Zixian Zeng <sycamoremoon376@gmail.com> ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-10 6:17 ` Zixian Zeng @ 2026-10-10 19:02 ` Kathpalia, Tanmay 2026-10-10 19:16 ` Kathpalia, Tanmay 0 siblings, 1 reply; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-10 19:02 UTC (permalink / raw) To: Zixian Zeng, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit On 10-10-2026 11:47, Zixian Zeng wrote: > Hi, Dave: > > On 2026/10/6 02:01, Dave Klotz wrote: >> spacemit_sdhci_get_b_max() limits every SD read in the SPL to a single >> block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 >> separate commands. The controller handles multi-block PIO reads in the >> SPL: the OrangePi RV2 has loaded U-Boot from microSD with them through >> the v2026.07 and v2026.10 trees. >> >> Drop the limit and use the host's b_max. >> >> The merged v13 cover retains the v9 changelog entry choosing single- >> block SD reads in SPL. This reverses that deliberate policy for the >> recorded RV2 SPL boot use case; no general multi-card reliability claim >> is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends >> CMD12 after a multi-block read rather than requiring CMD23. Additional >> card models, cold boots and transfer-error recovery remain required. >> >> Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> >> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >> --- >> Validation: unchanged executable change from v1; exact-base source >> replay and checkpatch pass. The corrected combined integration, with >> separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and >> automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. This is >> an integration result, not an isolated test of this patch. >> >> drivers/mmc/spacemit_sdhci.c | 11 ----------- >> 1 file changed, 0 insertions(+), 11 deletions(-) >> >> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c >> index 6488ae0fdb..4284553177 100644 >> --- a/drivers/mmc/spacemit_sdhci.c >> +++ b/drivers/mmc/spacemit_sdhci.c >> @@ -324,16 +324,6 @@ >> return 0; >> } >> -static int spacemit_sdhci_get_b_max(struct udevice *dev, void *dst, >> - lbaint_t blkcnt) >> -{ >> - struct mmc *mmc = mmc_get_mmc_dev(dev); >> - >> - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) >> - return 1; >> - return mmc->cfg->b_max; >> -} >> - >> static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) >> { >> struct mmc *mmc = host->mmc; >> @@ -574,7 +564,6 @@ >> spacemit_mmc_ops = sdhci_ops; >> spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; >> - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; >> ret = clk_get_bulk(dev, &plat->clks); >> if (ret) { > Using the current version of the next branch u-boot (ed869863c7), > with your MMC patch series applied. > Since the SPI controller is not enabled by default on the BananaPi-F3, > I also applied another patch series: > Link: > https://lore.kernel.org/u-boot/cover.1790976767.git.DaveWK225@protonmail.com/ > > > I tested u-boot SPL with three SD cards on a BananaPi-F3 and found > a reproducible issue, the specific error I encountered is spl: > partition error (Error: -38) > At the meantime, when i was revert the commit: > mmc: k1: let the SPL read SD cards more than one block at a time > the error has gone. Same SD card, same operation steps. > Maybe BananaPi-F3 do not support read SD cards more than one block at > a time? > > Hi Zixian, Thanks for testing this on the BananaPi-F3 and reporting this. The same cards and steps failing only with this patch shows that multi-block SD reads in the SPL are not reliable yet. I would request to try one more experiment before dropping it. Please add MMC_CAP_CMD23 to host->host_caps and boot the same cards again. CMD23 (SET_BLOCK_COUNT) tells the card how many blocks to transfer. mmc_read_blocks() then uses CMD23 plus CMD18, and it does not send CMD12 afterwards. The current driver does not set MMC_CAP_CMD23, so a multi-block read is CMD18 followed by CMD12. After the SCR is read, the MMC core clears MMC_CAP_CMD23 when the card does not advertise SD_SCR_CMD23_SUPPORT. Those cards stay on CMD18 plus CMD12. This also matches Eric's earlier note that on K1 ADMA depends on CMD23: https://patchwork.ozlabs.org/project/uboot/patch/20260707-m4-v4-3-dbd01185f911@riscstar.com/ If the CMD23 test also fails, I agree that this patch should be dropped. Regards, Tanmay ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-10 19:02 ` Kathpalia, Tanmay @ 2026-10-10 19:16 ` Kathpalia, Tanmay 2026-10-11 3:38 ` Zixian Zeng 0 siblings, 1 reply; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-10 19:16 UTC (permalink / raw) To: Zixian Zeng, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit On 11-10-2026 00:32, Kathpalia, Tanmay wrote: > > On 10-10-2026 11:47, Zixian Zeng wrote: >> Hi, Dave: >> >> On 2026/10/6 02:01, Dave Klotz wrote: >>> spacemit_sdhci_get_b_max() limits every SD read in the SPL to a single >>> block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 >>> separate commands. The controller handles multi-block PIO reads in the >>> SPL: the OrangePi RV2 has loaded U-Boot from microSD with them through >>> the v2026.07 and v2026.10 trees. >>> >>> Drop the limit and use the host's b_max. >>> >>> The merged v13 cover retains the v9 changelog entry choosing single- >>> block SD reads in SPL. This reverses that deliberate policy for the >>> recorded RV2 SPL boot use case; no general multi-card reliability claim >>> is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends >>> CMD12 after a multi-block read rather than requiring CMD23. Additional >>> card models, cold boots and transfer-error recovery remain required. >>> >>> Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> >>> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>> --- >>> Validation: unchanged executable change from v1; exact-base source >>> replay and checkpatch pass. The corrected combined integration, with >>> separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and >>> automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. This is >>> an integration result, not an isolated test of this patch. >>> >>> drivers/mmc/spacemit_sdhci.c | 11 ----------- >>> 1 file changed, 0 insertions(+), 11 deletions(-) >>> >>> diff --git a/drivers/mmc/spacemit_sdhci.c >>> b/drivers/mmc/spacemit_sdhci.c >>> index 6488ae0fdb..4284553177 100644 >>> --- a/drivers/mmc/spacemit_sdhci.c >>> +++ b/drivers/mmc/spacemit_sdhci.c >>> @@ -324,16 +324,6 @@ >>> return 0; >>> } >>> -static int spacemit_sdhci_get_b_max(struct udevice *dev, void *dst, >>> - lbaint_t blkcnt) >>> -{ >>> - struct mmc *mmc = mmc_get_mmc_dev(dev); >>> - >>> - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) >>> - return 1; >>> - return mmc->cfg->b_max; >>> -} >>> - >>> static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) >>> { >>> struct mmc *mmc = host->mmc; >>> @@ -574,7 +564,6 @@ >>> spacemit_mmc_ops = sdhci_ops; >>> spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; >>> - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; >>> ret = clk_get_bulk(dev, &plat->clks); >>> if (ret) { >> Using the current version of the next branch u-boot (ed869863c7), >> with your MMC patch series applied. >> Since the SPI controller is not enabled by default on the BananaPi-F3, >> I also applied another patch series: >> Link: >> https://lore.kernel.org/u-boot/cover.1790976767.git.DaveWK225@protonmail.com/ >> >> >> I tested u-boot SPL with three SD cards on a BananaPi-F3 and found >> a reproducible issue, the specific error I encountered is spl: >> partition error (Error: -38) >> At the meantime, when i was revert the commit: >> mmc: k1: let the SPL read SD cards more than one block at a time >> the error has gone. Same SD card, same operation steps. >> Maybe BananaPi-F3 do not support read SD cards more than one block at >> a time? >> >> > > Hi Zixian, > > Thanks for testing this on the BananaPi-F3 and reporting this. The > same cards and steps failing only with this patch shows that > multi-block SD reads in the SPL are not reliable yet. > > I would request to try one more experiment before dropping it. > Please add MMC_CAP_CMD23 to host->host_caps and boot the same cards > again. CMD23 (SET_BLOCK_COUNT) tells the card how many blocks to > transfer. mmc_read_blocks() then uses CMD23 plus CMD18, and it does > not send CMD12 afterwards. The current driver does not set > MMC_CAP_CMD23, so a multi-block read is CMD18 followed by CMD12. > > After the SCR is read, the MMC core clears MMC_CAP_CMD23 when the card > does not advertise SD_SCR_CMD23_SUPPORT. Those cards stay on CMD18 > plus CMD12. > > This also matches Eric's earlier note that on K1 ADMA depends on CMD23: > https://patchwork.ozlabs.org/project/uboot/patch/20260707-m4-v4-3-dbd01185f911@riscstar.com/ > > > If the CMD23 test also fails, I agree that this patch should be > dropped. > Hi Zixian, A few follow-up questions about the SPL-only failure: The callback limits reads only when CONFIG_SPL_BUILD is enabled. U-Boot proper already uses mmc->cfg->b_max, even without this patch. Therefore, multi-block SD reads should already be used in U-Boot proper. Could you please boot U-Boot proper from another device and test a multi-block read from the same SD cards? Could you also compare the following between SPL and U-Boot proper? - selected SD timing mode - card clock frequency - bus width - PIO, SDMA, or ADMA transfer path - whether the card advertises CMD23 support Although both stages use the same driver source, they may use different configuration options, transfer paths, clocks, and timing modes. This could explain why CMD18 works in U-Boot proper but fails in SPL. Regards, Tanmay ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-10 19:16 ` Kathpalia, Tanmay @ 2026-10-11 3:38 ` Zixian Zeng 2026-10-11 14:31 ` Kathpalia, Tanmay 0 siblings, 1 reply; 33+ messages in thread From: Zixian Zeng @ 2026-10-11 3:38 UTC (permalink / raw) To: Kathpalia, Tanmay, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit On 2026/10/11 03:16, Kathpalia, Tanmay wrote: > > On 11-10-2026 00:32, Kathpalia, Tanmay wrote: >> >> On 10-10-2026 11:47, Zixian Zeng wrote: >>> Hi, Dave: >>> >>> On 2026/10/6 02:01, Dave Klotz wrote: >>>> spacemit_sdhci_get_b_max() limits every SD read in the SPL to a single >>>> block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 >>>> separate commands. The controller handles multi-block PIO reads in the >>>> SPL: the OrangePi RV2 has loaded U-Boot from microSD with them through >>>> the v2026.07 and v2026.10 trees. >>>> >>>> Drop the limit and use the host's b_max. >>>> >>>> The merged v13 cover retains the v9 changelog entry choosing single- >>>> block SD reads in SPL. This reverses that deliberate policy for the >>>> recorded RV2 SPL boot use case; no general multi-card reliability claim >>>> is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends >>>> CMD12 after a multi-block read rather than requiring CMD23. Additional >>>> card models, cold boots and transfer-error recovery remain required. >>>> >>>> Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> >>>> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>>> --- >>>> Validation: unchanged executable change from v1; exact-base source >>>> replay and checkpatch pass. The corrected combined integration, with >>>> separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and >>>> automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. This is >>>> an integration result, not an isolated test of this patch. >>>> >>>> drivers/mmc/spacemit_sdhci.c | 11 ----------- >>>> 1 file changed, 0 insertions(+), 11 deletions(-) >>>> >>>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/ >>>> spacemit_sdhci.c >>>> index 6488ae0fdb..4284553177 100644 >>>> --- a/drivers/mmc/spacemit_sdhci.c >>>> +++ b/drivers/mmc/spacemit_sdhci.c >>>> @@ -324,16 +324,6 @@ >>>> return 0; >>>> } >>>> -static int spacemit_sdhci_get_b_max(struct udevice *dev, void *dst, >>>> - lbaint_t blkcnt) >>>> -{ >>>> - struct mmc *mmc = mmc_get_mmc_dev(dev); >>>> - >>>> - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) >>>> - return 1; >>>> - return mmc->cfg->b_max; >>>> -} >>>> - >>>> static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) >>>> { >>>> struct mmc *mmc = host->mmc; >>>> @@ -574,7 +564,6 @@ >>>> spacemit_mmc_ops = sdhci_ops; >>>> spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; >>>> - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; >>>> ret = clk_get_bulk(dev, &plat->clks); >>>> if (ret) { >>> Using the current version of the next branch u-boot (ed869863c7), >>> with your MMC patch series applied. >>> Since the SPI controller is not enabled by default on the BananaPi-F3, >>> I also applied another patch series: >>> Link: https://lore.kernel.org/u-boot/ >>> cover.1790976767.git.DaveWK225@protonmail.com/ >>> >>> I tested u-boot SPL with three SD cards on a BananaPi-F3 and found >>> a reproducible issue, the specific error I encountered is spl: >>> partition error (Error: -38) >>> At the meantime, when i was revert the commit: >>> mmc: k1: let the SPL read SD cards more than one block at a time >>> the error has gone. Same SD card, same operation steps. >>> Maybe BananaPi-F3 do not support read SD cards more than one block at >>> a time? >>> >>> >> >> Hi Zixian, >> >> Thanks for testing this on the BananaPi-F3 and reporting this. The >> same cards and steps failing only with this patch shows that >> multi-block SD reads in the SPL are not reliable yet. >> >> I would request to try one more experiment before dropping it. >> Please add MMC_CAP_CMD23 to host->host_caps and boot the same cards >> again. CMD23 (SET_BLOCK_COUNT) tells the card how many blocks to >> transfer. mmc_read_blocks() then uses CMD23 plus CMD18, and it does >> not send CMD12 afterwards. The current driver does not set >> MMC_CAP_CMD23, so a multi-block read is CMD18 followed by CMD12. >> >> After the SCR is read, the MMC core clears MMC_CAP_CMD23 when the card >> does not advertise SD_SCR_CMD23_SUPPORT. Those cards stay on CMD18 >> plus CMD12. >> >> This also matches Eric's earlier note that on K1 ADMA depends on CMD23: >> https://patchwork.ozlabs.org/project/uboot/patch/20260707-m4-v4-3- >> dbd01185f911@riscstar.com/ >> >> If the CMD23 test also fails, I agree that this patch should be >> dropped. >> > > Hi Zixian, > > A few follow-up questions about the SPL-only failure: > > The callback limits reads only when CONFIG_SPL_BUILD is enabled. U-Boot > proper already uses mmc->cfg->b_max, even without this patch. > Therefore, multi-block SD reads should already be used in U-Boot proper. > > Could you please boot U-Boot proper from another device and test a > multi-block read from the same SD cards? > Could you also compare the following between SPL and U-Boot proper? > > - selected SD timing mode > - card clock frequency > - bus width > - PIO, SDMA, or ADMA transfer path > - whether the card advertises CMD23 support > > Although both stages use the same driver source, they may use different > configuration options, transfer paths, clocks, and timing modes. This > could explain why CMD18 works in U-Boot proper but fails in SPL. > > Regards, > Tanmay Hi, Tanmay, Sure, I've added some print logs, which you can see below: commit 53c0ff5f65b0c7c4ae9f4563265741cd0ca23a0c Author: Zixian Zeng <sycamoremoon376@gmail.com> Date: Sun Oct 11 09:34:03 2026 +0800 Add mmc debug log Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index a619440fc4c..6e18d13884a 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -458,6 +458,13 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, struct mmc_cmd cmd; struct mmc_data data; + if (blkcnt > 1) + printf("mmc: multi-blk blkcnt=%lu clk=%u mode=%u width=%u caps=%x cmd23_host=%u scr0=%x cmd23_card=%u\n", + (ulong)blkcnt, mmc->clock, + (unsigned)mmc->selected_mode, mmc->bus_width, + mmc->host_caps, !!(mmc->host_caps & MMC_CAP_CMD23), + mmc->scr[0], !!(mmc->scr[0] & SD_SCR_CMD23_SUPPORT)); + if (blkcnt > 1 && (mmc->host_caps & MMC_CAP_CMD23)) { cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT; cmd.cmdarg = blkcnt & 0x0000ffff; @@ -483,8 +490,12 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, data.blocksize = mmc->read_bl_len; data.flags = MMC_DATA_READ; - if (mmc_send_cmd(mmc, &cmd, &data)) + if (mmc_send_cmd(mmc, &cmd, &data)) { + log_err("mmc: cmd%u read failed: blks=%lu blksz=%lu arg=%lx\n", + cmd.cmdidx, (ulong)blkcnt, (ulong)mmc->read_bl_len, + (ulong)cmd.cmdarg); return 0; + } if (blkcnt > 1 && !(mmc->host_caps & MMC_CAP_CMD23)) { if (mmc_send_stop_transmission(mmc, false)) { @@ -547,6 +558,8 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, } if (mmc_set_blocklen(mmc, mmc->read_bl_len)) { + log_err("mmc: CMD16 blocklen=%lu failed, read of %lu blocks aborted\n", + (ulong)mmc->read_bl_len, (ulong)blkcnt); pr_debug("%s: Failed to set blocklen\n", __func__); return 0; } @@ -556,6 +569,8 @@ ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, do { cur = (blocks_todo > b_max) ? b_max : blocks_todo; if (mmc_read_blocks(mmc, dst, start, cur) != cur) { + log_err("mmc: read of %lu blocks at lba %lx failed (b_max=%u)\n", + (ulong)cur, (ulong)start, b_max); pr_debug("%s: Failed to read blocks\n", __func__); return 0; } diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 962a99cd05a..339b222bb68 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -131,6 +131,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data) dma_addr_t start_addr = host->start_addr; unsigned int stat, rdy, mask, timeout, block = 0; bool transfer_done = false; + ulong t0 = get_timer(0); timeout = 1000000; rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL; @@ -138,6 +139,13 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data) do { stat = sdhci_readl(host, SDHCI_INT_STATUS); if (stat & SDHCI_INT_ERROR) { + log_err("sdhci: data err irq=%x present=%x mode=%x blksz=%x blkcnt=%x blocks=%u/%u t=%lums\n", + stat, + sdhci_readl(host, SDHCI_PRESENT_STATE), + sdhci_readw(host, SDHCI_TRANSFER_MODE), + sdhci_readw(host, SDHCI_BLOCK_SIZE), + sdhci_readw(host, SDHCI_BLOCK_COUNT), + block, data->blocks, get_timer(t0)); log_debug("Error detected in status(%#x)!\n", stat); return -EIO; } @@ -294,6 +302,11 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, SDHCI_BLOCK_SIZE); sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); + if (data->blocks > 1) + printf("sdhci: multi cmd%u arg=%lx blks=%u blksz=%u mode=%x dma=%u\n", + cmd->cmdidx, (ulong)cmd->cmdarg, data->blocks, + data->blocksize, mode, + !!(host->flags & USE_DMA)); } else if (cmd->resp_type & MMC_RSP_BUSY) { sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); } @@ -325,8 +338,12 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, if ((stat & (SDHCI_INT_ERROR | mask)) == mask) { sdhci_cmd_done(host, cmd); sdhci_writel(host, mask, SDHCI_INT_STATUS); - } else + } else { + log_err("sdhci: cmd%u status mismatch irq=%x mask=%x present=%x\n", + cmd->cmdidx, stat, mask, + sdhci_readl(host, SDHCI_PRESENT_STATE)); ret = -1; + } if (!ret && data) ret = sdhci_transfer_data(host, data); diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index 13bf6bf6000..23c655c6def 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -640,6 +640,19 @@ static int spacemit_sdhci_probe(struct udevice *dev) goto err_reset; spacemit_sdhci_phy_init(dev, host); + + { + u32 caps = sdhci_readl(host, SDHCI_CAPABILITIES); + const char *path = (host->flags & USE_ADMA64) ? "ADMA64" : + (host->flags & USE_ADMA) ? "ADMA" : + (host->flags & USE_SDMA) ? "SDMA" : "PIO"; + + printf("sdhci: %s path=%s flags=%x caps_sdma=%u caps_adma2=%u max_clk=%u\n", + dev->name, path, host->flags, + !!(caps & SDHCI_CAN_DO_SDMA), + !!(caps & SDHCI_CAN_DO_ADMA2), + host->max_clk); + } return 0; /* commit 75d6b28ba7b020d3100586f586ee6d1a4488ac84 Author: Zixian Zeng <sycamoremoon376@gmail.com> Date: Sun Oct 11 09:33:20 2026 +0800 debug: Add MMC_CAPS_CMD23 Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index 88e06a681ca..13bf6bf6000 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -624,7 +624,7 @@ static int spacemit_sdhci_probe(struct udevice *dev) /* Set quirks */ host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR; - host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; + host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_CAP_CMD23; host->max_clk = plat->cfg.f_max; plat->cfg.f_min = SDHC_MIN_CLOCK; With appling these two commits, Debug logs as follows: ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline origin/next..HEAD 53c0ff5f65b (HEAD -> k1-dave-mmc) Add mmc debug log 75d6b28ba7b debug: Add MMC_CAPS_CMD23 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on probe failure 4114764d716 mmc: k1: let the SPL read SD cards more than one block at a time 6676ce89521 mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller in SPL U-Boot SPL 2026.10-rc5-00641-g53c0ff5f65b0 (Oct 11 2026 - 10:31:28 +0800) Fail to detect board:-2 vdd_core, value:900000 vdd_1v8, value:1800000 vdd_1v8_mmc, value:1800000 DDR firmware: [0xc081d700]:0xf0227179, size:0x8d98 DDR is ready No SPI controller (-19) Trying to boot from MMC2 sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef cmd23_host=1 scr0=2358043 cmd23_card=1 sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 sdhci: data err irq=408020 present=1070800 mode=32 blksz=7200 blkcnt=12 blocks=12/32 t=2ms mmc: cmd18 read failed: blks=32 blksz=512 arg=2 mmc: read of 32 blocks at lba 2 failed (b_max=65535) sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 mmc: CMD16 blocklen=512 failed, read of 1 blocks aborted spl: partition error Error: -38 SPL: Unsupported Boot Device! Trying to boot from MMC1 alloc space exhausted ptr 104380 limit 100000 Aligned buffer alloc failed spl: could not find mmc device 0. error: -19 Error: -19 SPL: Unsupported Boot Device! Trying to boot from SPI Invalid bus 0 (err=-19) SPI probe failed. Error: -19 SPL: Unsupported Boot Device! SPL: Unsupported Boot Device! SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### After I revert the multi-block SD read commit, I booted into u-boot proper. Debug logs as follows: ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline origin/next..HEAD 55e8da25a70 (HEAD -> k1-dave-mmc) Revert "mmc: k1: let the SPL read SD cards more than one block at a time" 53c0ff5f65b Add mmc debug log 75d6b28ba7b debug: Add MMC_CAPS_CMD23 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on probe failure 4114764d716 mmc: k1: let the SPL read SD cards more than one block at a time 6676ce89521 mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller in SPL U-Boot SPL 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) Fail to detect board:-2 vdd_core, value:900000 vdd_1v8, value:1800000 vdd_1v8_mmc, value:1800000 DDR firmware: [0xc081d740]:0xf0227179, size:0x8d98 DDR is ready No SPI controller (-19) Trying to boot from MMC2 sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 <debug_uart> U-Boot 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) DRAM: 4 GiB Core: 339 devices, 23 uclasses, devicetree: separate MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 mmc@d4280000: 1, mmc@d4281000: 0 Loading Environment from nowhere... OK In: serial@d4017000 Out: serial@d4017000 Err: serial@d4017000 Net: No ethernet found. => mmc dev 1 mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef cmd23_host=1 scr0=2358043 cmd23_card=1 sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef cmd23_host=1 scr0=2358043 cmd23_card=1 sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 ... omit duplicate logs mmc: multi-blk blkcnt=2 clk=50000000 mode=2 width=4 caps=300207ef cmd23_host=1 scr0=2358043 cmd23_card=1 sdhci: multi cmd18 arg=82002 blks=2 blksz=512 mode=32 dma=0 switch to partitions #0, OK mmc1 is current device => => mmc list mmc@d4280000: 1 (SD) mmc@d4281000: 0 => => mmc info Device: mmc@d4280000 Manufacturer ID: 3 OEM: 5344 Name: SD32G Bus Speed: 50000000 Mode: SD High Speed (50MHz) Rd Block Len: 512 SD version 3.0 High Capacity: Yes Capacity: 29.7 GiB Bus Width: 4-bit Erase Group Size: 512 Bytes I enabled MMC_CAP_CMD23 and the card does support it (SCR bit 1, cmd23_host=1 and cmd23_card=1 in the log above), so the SPL really used SET_BLOCK_COUNT + CMD18 without CMD12 - and it still aborts the data phase with SDHCI_INT_DATA_END_BIT after ~20 of 32 blocks. Booting U-Boot proper and issuing the same 32 block CMD18 from the same card succeeds, with the same PIO path (flags=0, dma=0), the same SD_HS mode, the same 4-bit bus and the same CMD23 usage. So I think CMD23 is not the trigger, the SPL fails with the FIFO permanently backed up (it drains slower than card delivers, so the controller has to stop the SD clock inside a block). Now answering your questions: mode : mode=2 = SD_HS, in both stages clock : requested 50 MHz (SD_HS) in both stages bus : 4-bit bus, in both stages path : PIO in both stages CMD23 : the card supports it and both stages use CMD23 + CMD18 Best regards, Zixian ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-11 3:38 ` Zixian Zeng @ 2026-10-11 14:31 ` Kathpalia, Tanmay 2026-10-11 15:33 ` Anand Moon 2026-10-12 13:15 ` Zixian Zeng 0 siblings, 2 replies; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-11 14:31 UTC (permalink / raw) To: Zixian Zeng, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit On 11-10-2026 09:08, Zixian Zeng wrote: > On 2026/10/11 03:16, Kathpalia, Tanmay wrote: >> >> On 11-10-2026 00:32, Kathpalia, Tanmay wrote: >>> >>> On 10-10-2026 11:47, Zixian Zeng wrote: >>>> Hi, Dave: >>>> >>>> On 2026/10/6 02:01, Dave Klotz wrote: >>>>> spacemit_sdhci_get_b_max() limits every SD read in the SPL to a >>>>> single >>>>> block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 >>>>> separate commands. The controller handles multi-block PIO reads in >>>>> the >>>>> SPL: the OrangePi RV2 has loaded U-Boot from microSD with them >>>>> through >>>>> the v2026.07 and v2026.10 trees. >>>>> >>>>> Drop the limit and use the host's b_max. >>>>> >>>>> The merged v13 cover retains the v9 changelog entry choosing single- >>>>> block SD reads in SPL. This reverses that deliberate policy for the >>>>> recorded RV2 SPL boot use case; no general multi-card reliability >>>>> claim >>>>> is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends >>>>> CMD12 after a multi-block read rather than requiring CMD23. >>>>> Additional >>>>> card models, cold boots and transfer-error recovery remain required. >>>>> >>>>> Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> >>>>> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>>>> --- >>>>> Validation: unchanged executable change from v1; exact-base source >>>>> replay and checkpatch pass. The corrected combined integration, with >>>>> separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and >>>>> automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. >>>>> This is >>>>> an integration result, not an isolated test of this patch. >>>>> >>>>> drivers/mmc/spacemit_sdhci.c | 11 ----------- >>>>> 1 file changed, 0 insertions(+), 11 deletions(-) >>>>> >>>>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/ >>>>> spacemit_sdhci.c >>>>> index 6488ae0fdb..4284553177 100644 >>>>> --- a/drivers/mmc/spacemit_sdhci.c >>>>> +++ b/drivers/mmc/spacemit_sdhci.c >>>>> @@ -324,16 +324,6 @@ >>>>> return 0; >>>>> } >>>>> -static int spacemit_sdhci_get_b_max(struct udevice *dev, void >>>>> *dst, >>>>> - lbaint_t blkcnt) >>>>> -{ >>>>> - struct mmc *mmc = mmc_get_mmc_dev(dev); >>>>> - >>>>> - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) >>>>> - return 1; >>>>> - return mmc->cfg->b_max; >>>>> -} >>>>> - >>>>> static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) >>>>> { >>>>> struct mmc *mmc = host->mmc; >>>>> @@ -574,7 +564,6 @@ >>>>> spacemit_mmc_ops = sdhci_ops; >>>>> spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; >>>>> - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; >>>>> ret = clk_get_bulk(dev, &plat->clks); >>>>> if (ret) { >>>> Using the current version of the next branch u-boot (ed869863c7), >>>> with your MMC patch series applied. >>>> Since the SPI controller is not enabled by default on the BananaPi-F3, >>>> I also applied another patch series: >>>> Link: https://lore.kernel.org/u-boot/ >>>> cover.1790976767.git.DaveWK225@protonmail.com/ >>>> >>>> I tested u-boot SPL with three SD cards on a BananaPi-F3 and found >>>> a reproducible issue, the specific error I encountered is spl: >>>> partition error (Error: -38) >>>> At the meantime, when i was revert the commit: >>>> mmc: k1: let the SPL read SD cards more than one block at a time >>>> the error has gone. Same SD card, same operation steps. >>>> Maybe BananaPi-F3 do not support read SD cards more than one block >>>> at a time? >>>> >>>> >>> >>> Hi Zixian, >>> >>> Thanks for testing this on the BananaPi-F3 and reporting this. The >>> same cards and steps failing only with this patch shows that >>> multi-block SD reads in the SPL are not reliable yet. >>> >>> I would request to try one more experiment before dropping it. >>> Please add MMC_CAP_CMD23 to host->host_caps and boot the same cards >>> again. CMD23 (SET_BLOCK_COUNT) tells the card how many blocks to >>> transfer. mmc_read_blocks() then uses CMD23 plus CMD18, and it does >>> not send CMD12 afterwards. The current driver does not set >>> MMC_CAP_CMD23, so a multi-block read is CMD18 followed by CMD12. >>> >>> After the SCR is read, the MMC core clears MMC_CAP_CMD23 when the card >>> does not advertise SD_SCR_CMD23_SUPPORT. Those cards stay on CMD18 >>> plus CMD12. >>> >>> This also matches Eric's earlier note that on K1 ADMA depends on CMD23: >>> https://patchwork.ozlabs.org/project/uboot/patch/20260707-m4-v4-3- >>> dbd01185f911@riscstar.com/ >>> >>> If the CMD23 test also fails, I agree that this patch should be >>> dropped. >>> >> >> Hi Zixian, >> >> A few follow-up questions about the SPL-only failure: >> >> The callback limits reads only when CONFIG_SPL_BUILD is enabled. U-Boot >> proper already uses mmc->cfg->b_max, even without this patch. >> Therefore, multi-block SD reads should already be used in U-Boot proper. >> >> Could you please boot U-Boot proper from another device and test a >> multi-block read from the same SD cards? >> Could you also compare the following between SPL and U-Boot proper? >> >> - selected SD timing mode >> - card clock frequency >> - bus width >> - PIO, SDMA, or ADMA transfer path >> - whether the card advertises CMD23 support >> >> Although both stages use the same driver source, they may use different >> configuration options, transfer paths, clocks, and timing modes. This >> could explain why CMD18 works in U-Boot proper but fails in SPL. >> >> Regards, >> Tanmay > > Hi, Tanmay, > > Sure, I've added some print logs, which you can see below: > > commit 53c0ff5f65b0c7c4ae9f4563265741cd0ca23a0c > Author: Zixian Zeng <sycamoremoon376@gmail.com> > Date: Sun Oct 11 09:34:03 2026 +0800 > > Add mmc debug log > > Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> > > diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c > index a619440fc4c..6e18d13884a 100644 > --- a/drivers/mmc/mmc.c > +++ b/drivers/mmc/mmc.c > @@ -458,6 +458,13 @@ static int mmc_read_blocks(struct mmc *mmc, void > *dst, lbaint_t start, > struct mmc_cmd cmd; > struct mmc_data data; > > + if (blkcnt > 1) > + printf("mmc: multi-blk blkcnt=%lu clk=%u mode=%u > width=%u caps=%x cmd23_host=%u scr0=%x cmd23_card=%u\n", > + (ulong)blkcnt, mmc->clock, > + (unsigned)mmc->selected_mode, mmc->bus_width, > + mmc->host_caps, !!(mmc->host_caps & > MMC_CAP_CMD23), > + mmc->scr[0], !!(mmc->scr[0] & > SD_SCR_CMD23_SUPPORT)); > + > if (blkcnt > 1 && (mmc->host_caps & MMC_CAP_CMD23)) { > cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT; > cmd.cmdarg = blkcnt & 0x0000ffff; > @@ -483,8 +490,12 @@ static int mmc_read_blocks(struct mmc *mmc, void > *dst, lbaint_t start, > data.blocksize = mmc->read_bl_len; > data.flags = MMC_DATA_READ; > > - if (mmc_send_cmd(mmc, &cmd, &data)) > + if (mmc_send_cmd(mmc, &cmd, &data)) { > + log_err("mmc: cmd%u read failed: blks=%lu blksz=%lu > arg=%lx\n", > + cmd.cmdidx, (ulong)blkcnt, > (ulong)mmc->read_bl_len, > + (ulong)cmd.cmdarg); > return 0; > + } > > if (blkcnt > 1 && !(mmc->host_caps & MMC_CAP_CMD23)) { > if (mmc_send_stop_transmission(mmc, false)) { > @@ -547,6 +558,8 @@ ulong mmc_bread(struct blk_desc *block_dev, > lbaint_t start, lbaint_t blkcnt, > } > > if (mmc_set_blocklen(mmc, mmc->read_bl_len)) { > + log_err("mmc: CMD16 blocklen=%lu failed, read of %lu > blocks aborted\n", > + (ulong)mmc->read_bl_len, (ulong)blkcnt); > pr_debug("%s: Failed to set blocklen\n", __func__); > return 0; > } > @@ -556,6 +569,8 @@ ulong mmc_bread(struct blk_desc *block_dev, > lbaint_t start, lbaint_t blkcnt, > do { > cur = (blocks_todo > b_max) ? b_max : blocks_todo; > if (mmc_read_blocks(mmc, dst, start, cur) != cur) { > + log_err("mmc: read of %lu blocks at lba %lx > failed (b_max=%u)\n", > + (ulong)cur, (ulong)start, b_max); > pr_debug("%s: Failed to read blocks\n", > __func__); > return 0; > } > diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c > index 962a99cd05a..339b222bb68 100644 > --- a/drivers/mmc/sdhci.c > +++ b/drivers/mmc/sdhci.c > @@ -131,6 +131,7 @@ static int sdhci_transfer_data(struct sdhci_host > *host, struct mmc_data *data) > dma_addr_t start_addr = host->start_addr; > unsigned int stat, rdy, mask, timeout, block = 0; > bool transfer_done = false; > + ulong t0 = get_timer(0); > > timeout = 1000000; > rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL; > @@ -138,6 +139,13 @@ static int sdhci_transfer_data(struct sdhci_host > *host, struct mmc_data *data) > do { > stat = sdhci_readl(host, SDHCI_INT_STATUS); > if (stat & SDHCI_INT_ERROR) { > + log_err("sdhci: data err irq=%x present=%x > mode=%x blksz=%x blkcnt=%x blocks=%u/%u t=%lums\n", > + stat, > + sdhci_readl(host, SDHCI_PRESENT_STATE), > + sdhci_readw(host, SDHCI_TRANSFER_MODE), > + sdhci_readw(host, SDHCI_BLOCK_SIZE), > + sdhci_readw(host, SDHCI_BLOCK_COUNT), > + block, data->blocks, get_timer(t0)); > log_debug("Error detected in status(%#x)!\n", > stat); > return -EIO; > } > @@ -294,6 +302,11 @@ static int sdhci_send_command(struct mmc *mmc, > struct mmc_cmd *cmd, > SDHCI_BLOCK_SIZE); > sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); > sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); > + if (data->blocks > 1) > + printf("sdhci: multi cmd%u arg=%lx blks=%u > blksz=%u mode=%x dma=%u\n", > + cmd->cmdidx, (ulong)cmd->cmdarg, > data->blocks, > + data->blocksize, mode, > + !!(host->flags & USE_DMA)); > } else if (cmd->resp_type & MMC_RSP_BUSY) { > sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); > } > @@ -325,8 +338,12 @@ static int sdhci_send_command(struct mmc *mmc, > struct mmc_cmd *cmd, > if ((stat & (SDHCI_INT_ERROR | mask)) == mask) { > sdhci_cmd_done(host, cmd); > sdhci_writel(host, mask, SDHCI_INT_STATUS); > - } else > + } else { > + log_err("sdhci: cmd%u status mismatch irq=%x mask=%x > present=%x\n", > + cmd->cmdidx, stat, mask, > + sdhci_readl(host, SDHCI_PRESENT_STATE)); > ret = -1; > + } > > if (!ret && data) > ret = sdhci_transfer_data(host, data); > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index 13bf6bf6000..23c655c6def 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -640,6 +640,19 @@ static int spacemit_sdhci_probe(struct udevice *dev) > goto err_reset; > > spacemit_sdhci_phy_init(dev, host); > + > + { > + u32 caps = sdhci_readl(host, SDHCI_CAPABILITIES); > + const char *path = (host->flags & USE_ADMA64) ? > "ADMA64" : > + (host->flags & USE_ADMA) ? "ADMA" : > + (host->flags & USE_SDMA) ? "SDMA" : > "PIO"; > + > + printf("sdhci: %s path=%s flags=%x caps_sdma=%u > caps_adma2=%u max_clk=%u\n", > + dev->name, path, host->flags, > + !!(caps & SDHCI_CAN_DO_SDMA), > + !!(caps & SDHCI_CAN_DO_ADMA2), > + host->max_clk); > + } > return 0; > > /* > > > commit 75d6b28ba7b020d3100586f586ee6d1a4488ac84 > Author: Zixian Zeng <sycamoremoon376@gmail.com> > Date: Sun Oct 11 09:33:20 2026 +0800 > > debug: Add MMC_CAPS_CMD23 > > Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index 88e06a681ca..13bf6bf6000 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -624,7 +624,7 @@ static int spacemit_sdhci_probe(struct udevice *dev) > /* Set quirks */ > host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | > SDHCI_QUIRK_32BIT_DMA_ADDR; > - host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; > + host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | > MMC_CAP_CMD23; > host->max_clk = plat->cfg.f_max; > > plat->cfg.f_min = SDHC_MIN_CLOCK; > > > With appling these two commits, Debug logs as follows: > > ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline > origin/next..HEAD > 53c0ff5f65b (HEAD -> k1-dave-mmc) Add mmc debug log > 75d6b28ba7b debug: Add MMC_CAPS_CMD23 > 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on > probe failure > 4114764d716 mmc: k1: let the SPL read SD cards more than one block at > a time > 6676ce89521 mmc: k1: handle a missing max-frequency and > clk_set_rate()'s return value > 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL > b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller > in SPL > > U-Boot SPL 2026.10-rc5-00641-g53c0ff5f65b0 (Oct 11 2026 - 10:31:28 +0800) > Fail to detect board:-2 > vdd_core, value:900000 > vdd_1v8, value:1800000 > vdd_1v8_mmc, value:1800000 > DDR firmware: [0xc081d700]:0xf0227179, size:0x8d98 > DDR is ready > No SPI controller (-19) > Trying to boot from MMC2 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > sdhci: data err irq=408020 present=1070800 mode=32 blksz=7200 > blkcnt=12 blocks=12/32 t=2ms > mmc: cmd18 read failed: blks=32 blksz=512 arg=2 > mmc: read of 32 blocks at lba 2 failed (b_max=65535) > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > mmc: CMD16 blocklen=512 failed, read of 1 blocks aborted > spl: partition error > Error: -38 > SPL: Unsupported Boot Device! > Trying to boot from MMC1 > alloc space exhausted ptr 104380 limit 100000 > Aligned buffer alloc failed > spl: could not find mmc device 0. error: -19 > Error: -19 > SPL: Unsupported Boot Device! > Trying to boot from SPI > Invalid bus 0 (err=-19) > SPI probe failed. > Error: -19 > SPL: Unsupported Boot Device! > SPL: Unsupported Boot Device! > SPL: failed to boot from all boot devices > ### ERROR ### Please RESET the board ### > > > After I revert the multi-block SD read commit, > I booted into u-boot proper. Debug logs as follows: > > ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline > origin/next..HEAD > 55e8da25a70 (HEAD -> k1-dave-mmc) Revert "mmc: k1: let the SPL read SD > cards more than one block at a time" > 53c0ff5f65b Add mmc debug log > 75d6b28ba7b debug: Add MMC_CAPS_CMD23 > 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on > probe failure > 4114764d716 mmc: k1: let the SPL read SD cards more than one block at > a time > 6676ce89521 mmc: k1: handle a missing max-frequency and > clk_set_rate()'s return value > 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL > b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller > in SPL > > > U-Boot SPL 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) > Fail to detect board:-2 > vdd_core, value:900000 > vdd_1v8, value:1800000 > vdd_1v8_mmc, value:1800000 > DDR firmware: [0xc081d740]:0xf0227179, size:0x8d98 > DDR is ready > No SPI controller (-19) > Trying to boot from MMC2 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > > <debug_uart> > > > U-Boot 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) > > DRAM: 4 GiB > Core: 339 devices, 23 uclasses, devicetree: separate > MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > mmc@d4280000: 1, mmc@d4281000: 0 > Loading Environment from nowhere... OK > In: serial@d4017000 > Out: serial@d4017000 > Err: serial@d4017000 > Net: No ethernet found. > => mmc dev 1 > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > ... omit duplicate logs > mmc: multi-blk blkcnt=2 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=82002 blks=2 blksz=512 mode=32 dma=0 > switch to partitions #0, OK > mmc1 is current device > => > => mmc list > mmc@d4280000: 1 (SD) > mmc@d4281000: 0 > => > => mmc info > Device: mmc@d4280000 > Manufacturer ID: 3 > OEM: 5344 > Name: SD32G > Bus Speed: 50000000 > Mode: SD High Speed (50MHz) > Rd Block Len: 512 > SD version 3.0 > High Capacity: Yes > Capacity: 29.7 GiB > Bus Width: 4-bit > Erase Group Size: 512 Bytes > > I enabled MMC_CAP_CMD23 and the card does support it (SCR bit 1, > cmd23_host=1 and cmd23_card=1 in the log above), so the SPL really > used SET_BLOCK_COUNT + CMD18 without CMD12 - and it still aborts the > data phase with SDHCI_INT_DATA_END_BIT after ~20 of 32 blocks. > Booting U-Boot proper and issuing the same 32 block CMD18 from the same > card succeeds, with the same PIO path (flags=0, dma=0), the same SD_HS > mode, the same 4-bit bus and the same CMD23 usage. > So I think CMD23 is not the trigger, the SPL fails with the FIFO > permanently backed up (it drains slower than card delivers, so the > controller has to stop the SD clock inside a block). > > Now answering your questions: > mode : mode=2 = SD_HS, in both stages > clock : requested 50 MHz (SD_HS) in both stages > bus : 4-bit bus, in both stages > path : PIO in both stages > CMD23 : the card supports it and both stages use CMD23 + CMD18 > > Hi Zixian, Thanks for the logs. I hit the same pattern while testing the Cadence SD6HC driver. Multi-block reads failed and single-block reads worked. On that board the host and the card were in 1.8 V mode, but the I/O supply had been left at 3.3 V. A short transfer got through; a longer one failed on the data lines. Both stages on K1 use the same PIO loop, so a FIFO that drains slower than the card delivers would show up in U-Boot proper as well. Your SPL/proper split fits an electrical setup difference. The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, SD mode only): the controller detected 0 at the end-bit position of read data on DAT, or of the write CRC status. That is a bad edge on the data line during the transfer. On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, called from board_init_f(), writes 1800000. The dts leaves aldo1 at 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is only after a UHS switch. mmc1_cfg is power-source 3300, and mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer that succeeds. CONFIG_SPL_PINCTRL is not set either. The driver calls pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return is ignored. SPL never applies mmc1_cfg. Proper selects "default" for SD_HS, which is that state. Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read succeed, this is the F3 failure. Regards, Tanmay ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-11 14:31 ` Kathpalia, Tanmay @ 2026-10-11 15:33 ` Anand Moon 2026-10-11 19:41 ` Kathpalia, Tanmay 2026-10-12 13:15 ` Zixian Zeng 1 sibling, 1 reply; 33+ messages in thread From: Anand Moon @ 2026-10-11 15:33 UTC (permalink / raw) To: Kathpalia, Tanmay Cc: Zixian Zeng, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit Hi Al,L On Sun, 11 Oct 2026 at 20:07, Kathpalia, Tanmay <tanmay.kathpalia@altera.com> wrote: > > > On 11-10-2026 09:08, Zixian Zeng wrote: > > On 2026/10/11 03:16, Kathpalia, Tanmay wrote: > >> > >> On 11-10-2026 00:32, Kathpalia, Tanmay wrote: > >>> > >>> On 10-10-2026 11:47, Zixian Zeng wrote: > >>>> Hi, Dave: > >>>> > >>>> On 2026/10/6 02:01, Dave Klotz wrote: > >>>>> spacemit_sdhci_get_b_max() limits every SD read in the SPL to a > >>>>> single > >>>>> block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 > >>>>> separate commands. The controller handles multi-block PIO reads in > >>>>> the > >>>>> SPL: the OrangePi RV2 has loaded U-Boot from microSD with them > >>>>> through > >>>>> the v2026.07 and v2026.10 trees. > >>>>> > >>>>> Drop the limit and use the host's b_max. > >>>>> > >>>>> The merged v13 cover retains the v9 changelog entry choosing single- > >>>>> block SD reads in SPL. This reverses that deliberate policy for the > >>>>> recorded RV2 SPL boot use case; no general multi-card reliability > >>>>> claim > >>>>> is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends > >>>>> CMD12 after a multi-block read rather than requiring CMD23. > >>>>> Additional > >>>>> card models, cold boots and transfer-error recovery remain required. > >>>>> > >>>>> Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> > >>>>> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> > >>>>> --- > >>>>> Validation: unchanged executable change from v1; exact-base source > >>>>> replay and checkpatch pass. The corrected combined integration, with > >>>>> separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and > >>>>> automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. > >>>>> This is > >>>>> an integration result, not an isolated test of this patch. > >>>>> > >>>>> drivers/mmc/spacemit_sdhci.c | 11 ----------- > >>>>> 1 file changed, 0 insertions(+), 11 deletions(-) > >>>>> > >>>>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/ > >>>>> spacemit_sdhci.c > >>>>> index 6488ae0fdb..4284553177 100644 > >>>>> --- a/drivers/mmc/spacemit_sdhci.c > >>>>> +++ b/drivers/mmc/spacemit_sdhci.c > >>>>> @@ -324,16 +324,6 @@ > >>>>> return 0; > >>>>> } > >>>>> -static int spacemit_sdhci_get_b_max(struct udevice *dev, void > >>>>> *dst, > >>>>> - lbaint_t blkcnt) > >>>>> -{ > >>>>> - struct mmc *mmc = mmc_get_mmc_dev(dev); > >>>>> - > >>>>> - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) > >>>>> - return 1; > >>>>> - return mmc->cfg->b_max; > >>>>> -} > >>>>> - > >>>>> static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) > >>>>> { > >>>>> struct mmc *mmc = host->mmc; > >>>>> @@ -574,7 +564,6 @@ > >>>>> spacemit_mmc_ops = sdhci_ops; > >>>>> spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; > >>>>> - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; > >>>>> ret = clk_get_bulk(dev, &plat->clks); > >>>>> if (ret) { > >>>> Using the current version of the next branch u-boot (ed869863c7), > >>>> with your MMC patch series applied. > >>>> Since the SPI controller is not enabled by default on the BananaPi-F3, > >>>> I also applied another patch series: > >>>> Link: https://lore.kernel.org/u-boot/ > >>>> cover.1790976767.git.DaveWK225@protonmail.com/ > >>>> > >>>> I tested u-boot SPL with three SD cards on a BananaPi-F3 and found > >>>> a reproducible issue, the specific error I encountered is spl: > >>>> partition error (Error: -38) > >>>> At the meantime, when i was revert the commit: > >>>> mmc: k1: let the SPL read SD cards more than one block at a time > >>>> the error has gone. Same SD card, same operation steps. > >>>> Maybe BananaPi-F3 do not support read SD cards more than one block > >>>> at a time? > >>>> > >>>> > >>> > >>> Hi Zixian, > >>> > >>> Thanks for testing this on the BananaPi-F3 and reporting this. The > >>> same cards and steps failing only with this patch shows that > >>> multi-block SD reads in the SPL are not reliable yet. > >>> > >>> I would request to try one more experiment before dropping it. > >>> Please add MMC_CAP_CMD23 to host->host_caps and boot the same cards > >>> again. CMD23 (SET_BLOCK_COUNT) tells the card how many blocks to > >>> transfer. mmc_read_blocks() then uses CMD23 plus CMD18, and it does > >>> not send CMD12 afterwards. The current driver does not set > >>> MMC_CAP_CMD23, so a multi-block read is CMD18 followed by CMD12. > >>> > >>> After the SCR is read, the MMC core clears MMC_CAP_CMD23 when the card > >>> does not advertise SD_SCR_CMD23_SUPPORT. Those cards stay on CMD18 > >>> plus CMD12. > >>> > >>> This also matches Eric's earlier note that on K1 ADMA depends on CMD23: > >>> https://patchwork.ozlabs.org/project/uboot/patch/20260707-m4-v4-3- > >>> dbd01185f911@riscstar.com/ > >>> > >>> If the CMD23 test also fails, I agree that this patch should be > >>> dropped. > >>> > >> > >> Hi Zixian, > >> > >> A few follow-up questions about the SPL-only failure: > >> > >> The callback limits reads only when CONFIG_SPL_BUILD is enabled. U-Boot > >> proper already uses mmc->cfg->b_max, even without this patch. > >> Therefore, multi-block SD reads should already be used in U-Boot proper. > >> > >> Could you please boot U-Boot proper from another device and test a > >> multi-block read from the same SD cards? > >> Could you also compare the following between SPL and U-Boot proper? > >> > >> - selected SD timing mode > >> - card clock frequency > >> - bus width > >> - PIO, SDMA, or ADMA transfer path > >> - whether the card advertises CMD23 support > >> > >> Although both stages use the same driver source, they may use different > >> configuration options, transfer paths, clocks, and timing modes. This > >> could explain why CMD18 works in U-Boot proper but fails in SPL. > >> > >> Regards, > >> Tanmay > > > > Hi, Tanmay, > > > > Sure, I've added some print logs, which you can see below: > > > > commit 53c0ff5f65b0c7c4ae9f4563265741cd0ca23a0c > > Author: Zixian Zeng <sycamoremoon376@gmail.com> > > Date: Sun Oct 11 09:34:03 2026 +0800 > > > > Add mmc debug log > > > > Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> > > > > diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c > > index a619440fc4c..6e18d13884a 100644 > > --- a/drivers/mmc/mmc.c > > +++ b/drivers/mmc/mmc.c > > @@ -458,6 +458,13 @@ static int mmc_read_blocks(struct mmc *mmc, void > > *dst, lbaint_t start, > > struct mmc_cmd cmd; > > struct mmc_data data; > > > > + if (blkcnt > 1) > > + printf("mmc: multi-blk blkcnt=%lu clk=%u mode=%u > > width=%u caps=%x cmd23_host=%u scr0=%x cmd23_card=%u\n", > > + (ulong)blkcnt, mmc->clock, > > + (unsigned)mmc->selected_mode, mmc->bus_width, > > + mmc->host_caps, !!(mmc->host_caps & > > MMC_CAP_CMD23), > > + mmc->scr[0], !!(mmc->scr[0] & > > SD_SCR_CMD23_SUPPORT)); > > + > > if (blkcnt > 1 && (mmc->host_caps & MMC_CAP_CMD23)) { > > cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT; > > cmd.cmdarg = blkcnt & 0x0000ffff; > > @@ -483,8 +490,12 @@ static int mmc_read_blocks(struct mmc *mmc, void > > *dst, lbaint_t start, > > data.blocksize = mmc->read_bl_len; > > data.flags = MMC_DATA_READ; > > > > - if (mmc_send_cmd(mmc, &cmd, &data)) > > + if (mmc_send_cmd(mmc, &cmd, &data)) { > > + log_err("mmc: cmd%u read failed: blks=%lu blksz=%lu > > arg=%lx\n", > > + cmd.cmdidx, (ulong)blkcnt, > > (ulong)mmc->read_bl_len, > > + (ulong)cmd.cmdarg); > > return 0; > > + } > > > > if (blkcnt > 1 && !(mmc->host_caps & MMC_CAP_CMD23)) { > > if (mmc_send_stop_transmission(mmc, false)) { > > @@ -547,6 +558,8 @@ ulong mmc_bread(struct blk_desc *block_dev, > > lbaint_t start, lbaint_t blkcnt, > > } > > > > if (mmc_set_blocklen(mmc, mmc->read_bl_len)) { > > + log_err("mmc: CMD16 blocklen=%lu failed, read of %lu > > blocks aborted\n", > > + (ulong)mmc->read_bl_len, (ulong)blkcnt); > > pr_debug("%s: Failed to set blocklen\n", __func__); > > return 0; > > } > > @@ -556,6 +569,8 @@ ulong mmc_bread(struct blk_desc *block_dev, > > lbaint_t start, lbaint_t blkcnt, > > do { > > cur = (blocks_todo > b_max) ? b_max : blocks_todo; > > if (mmc_read_blocks(mmc, dst, start, cur) != cur) { > > + log_err("mmc: read of %lu blocks at lba %lx > > failed (b_max=%u)\n", > > + (ulong)cur, (ulong)start, b_max); > > pr_debug("%s: Failed to read blocks\n", > > __func__); > > return 0; > > } > > diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c > > index 962a99cd05a..339b222bb68 100644 > > --- a/drivers/mmc/sdhci.c > > +++ b/drivers/mmc/sdhci.c > > @@ -131,6 +131,7 @@ static int sdhci_transfer_data(struct sdhci_host > > *host, struct mmc_data *data) > > dma_addr_t start_addr = host->start_addr; > > unsigned int stat, rdy, mask, timeout, block = 0; > > bool transfer_done = false; > > + ulong t0 = get_timer(0); > > > > timeout = 1000000; > > rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL; > > @@ -138,6 +139,13 @@ static int sdhci_transfer_data(struct sdhci_host > > *host, struct mmc_data *data) > > do { > > stat = sdhci_readl(host, SDHCI_INT_STATUS); > > if (stat & SDHCI_INT_ERROR) { > > + log_err("sdhci: data err irq=%x present=%x > > mode=%x blksz=%x blkcnt=%x blocks=%u/%u t=%lums\n", > > + stat, > > + sdhci_readl(host, SDHCI_PRESENT_STATE), > > + sdhci_readw(host, SDHCI_TRANSFER_MODE), > > + sdhci_readw(host, SDHCI_BLOCK_SIZE), > > + sdhci_readw(host, SDHCI_BLOCK_COUNT), > > + block, data->blocks, get_timer(t0)); > > log_debug("Error detected in status(%#x)!\n", > > stat); > > return -EIO; > > } > > @@ -294,6 +302,11 @@ static int sdhci_send_command(struct mmc *mmc, > > struct mmc_cmd *cmd, > > SDHCI_BLOCK_SIZE); > > sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); > > sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); > > + if (data->blocks > 1) > > + printf("sdhci: multi cmd%u arg=%lx blks=%u > > blksz=%u mode=%x dma=%u\n", > > + cmd->cmdidx, (ulong)cmd->cmdarg, > > data->blocks, > > + data->blocksize, mode, > > + !!(host->flags & USE_DMA)); > > } else if (cmd->resp_type & MMC_RSP_BUSY) { > > sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); > > } > > @@ -325,8 +338,12 @@ static int sdhci_send_command(struct mmc *mmc, > > struct mmc_cmd *cmd, > > if ((stat & (SDHCI_INT_ERROR | mask)) == mask) { > > sdhci_cmd_done(host, cmd); > > sdhci_writel(host, mask, SDHCI_INT_STATUS); > > - } else > > + } else { > > + log_err("sdhci: cmd%u status mismatch irq=%x mask=%x > > present=%x\n", > > + cmd->cmdidx, stat, mask, > > + sdhci_readl(host, SDHCI_PRESENT_STATE)); > > ret = -1; > > + } > > > > if (!ret && data) > > ret = sdhci_transfer_data(host, data); > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > > index 13bf6bf6000..23c655c6def 100644 > > --- a/drivers/mmc/spacemit_sdhci.c > > +++ b/drivers/mmc/spacemit_sdhci.c > > @@ -640,6 +640,19 @@ static int spacemit_sdhci_probe(struct udevice *dev) > > goto err_reset; > > > > spacemit_sdhci_phy_init(dev, host); > > + > > + { > > + u32 caps = sdhci_readl(host, SDHCI_CAPABILITIES); > > + const char *path = (host->flags & USE_ADMA64) ? > > "ADMA64" : > > + (host->flags & USE_ADMA) ? "ADMA" : > > + (host->flags & USE_SDMA) ? "SDMA" : > > "PIO"; > > + > > + printf("sdhci: %s path=%s flags=%x caps_sdma=%u > > caps_adma2=%u max_clk=%u\n", > > + dev->name, path, host->flags, > > + !!(caps & SDHCI_CAN_DO_SDMA), > > + !!(caps & SDHCI_CAN_DO_ADMA2), > > + host->max_clk); > > + } > > return 0; > > > > /* > > > > > > commit 75d6b28ba7b020d3100586f586ee6d1a4488ac84 > > Author: Zixian Zeng <sycamoremoon376@gmail.com> > > Date: Sun Oct 11 09:33:20 2026 +0800 > > > > debug: Add MMC_CAPS_CMD23 > > > > Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> > > > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > > index 88e06a681ca..13bf6bf6000 100644 > > --- a/drivers/mmc/spacemit_sdhci.c > > +++ b/drivers/mmc/spacemit_sdhci.c > > @@ -624,7 +624,7 @@ static int spacemit_sdhci_probe(struct udevice *dev) > > /* Set quirks */ > > host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | > > SDHCI_QUIRK_32BIT_DMA_ADDR; > > - host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; > > + host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | > > MMC_CAP_CMD23; > > host->max_clk = plat->cfg.f_max; > > > > plat->cfg.f_min = SDHC_MIN_CLOCK; > > > > > > With appling these two commits, Debug logs as follows: > > > > ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline > > origin/next..HEAD > > 53c0ff5f65b (HEAD -> k1-dave-mmc) Add mmc debug log > > 75d6b28ba7b debug: Add MMC_CAPS_CMD23 > > 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on > > probe failure > > 4114764d716 mmc: k1: let the SPL read SD cards more than one block at > > a time > > 6676ce89521 mmc: k1: handle a missing max-frequency and > > clk_set_rate()'s return value > > 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL > > b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller > > in SPL > > > > U-Boot SPL 2026.10-rc5-00641-g53c0ff5f65b0 (Oct 11 2026 - 10:31:28 +0800) > > Fail to detect board:-2 > > vdd_core, value:900000 > > vdd_1v8, value:1800000 > > vdd_1v8_mmc, value:1800000 > > DDR firmware: [0xc081d700]:0xf0227179, size:0x8d98 > > DDR is ready > > No SPI controller (-19) > > Trying to boot from MMC2 > > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > > max_clk=204800000 > > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > > cmd23_host=1 scr0=2358043 cmd23_card=1 > > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > > sdhci: data err irq=408020 present=1070800 mode=32 blksz=7200 > > blkcnt=12 blocks=12/32 t=2ms > > mmc: cmd18 read failed: blks=32 blksz=512 arg=2 > > mmc: read of 32 blocks at lba 2 failed (b_max=65535) > > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > > sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 > > mmc: CMD16 blocklen=512 failed, read of 1 blocks aborted > > spl: partition error > > Error: -38 > > SPL: Unsupported Boot Device! > > Trying to boot from MMC1 > > alloc space exhausted ptr 104380 limit 100000 > > Aligned buffer alloc failed > > spl: could not find mmc device 0. error: -19 > > Error: -19 > > SPL: Unsupported Boot Device! > > Trying to boot from SPI > > Invalid bus 0 (err=-19) > > SPI probe failed. > > Error: -19 > > SPL: Unsupported Boot Device! > > SPL: Unsupported Boot Device! > > SPL: failed to boot from all boot devices > > ### ERROR ### Please RESET the board ### > > > > > > After I revert the multi-block SD read commit, > > I booted into u-boot proper. Debug logs as follows: > > > > ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline > > origin/next..HEAD > > 55e8da25a70 (HEAD -> k1-dave-mmc) Revert "mmc: k1: let the SPL read SD > > cards more than one block at a time" > > 53c0ff5f65b Add mmc debug log > > 75d6b28ba7b debug: Add MMC_CAPS_CMD23 > > 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on > > probe failure > > 4114764d716 mmc: k1: let the SPL read SD cards more than one block at > > a time > > 6676ce89521 mmc: k1: handle a missing max-frequency and > > clk_set_rate()'s return value > > 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL > > b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller > > in SPL > > > > > > U-Boot SPL 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) > > Fail to detect board:-2 > > vdd_core, value:900000 > > vdd_1v8, value:1800000 > > vdd_1v8_mmc, value:1800000 > > DDR firmware: [0xc081d740]:0xf0227179, size:0x8d98 > > DDR is ready > > No SPI controller (-19) > > Trying to boot from MMC2 > > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > > max_clk=204800000 > > > > <debug_uart> > > > > > > U-Boot 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) > > > > DRAM: 4 GiB > > Core: 339 devices, 23 uclasses, devicetree: separate > > MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > > max_clk=204800000 > > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > > max_clk=204800000 > > mmc@d4280000: 1, mmc@d4281000: 0 > > Loading Environment from nowhere... OK > > In: serial@d4017000 > > Out: serial@d4017000 > > Err: serial@d4017000 > > Net: No ethernet found. > > => mmc dev 1 > > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > > cmd23_host=1 scr0=2358043 cmd23_card=1 > > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > > cmd23_host=1 scr0=2358043 cmd23_card=1 > > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > > ... omit duplicate logs > > mmc: multi-blk blkcnt=2 clk=50000000 mode=2 width=4 caps=300207ef > > cmd23_host=1 scr0=2358043 cmd23_card=1 > > sdhci: multi cmd18 arg=82002 blks=2 blksz=512 mode=32 dma=0 > > switch to partitions #0, OK > > mmc1 is current device > > => > > => mmc list > > mmc@d4280000: 1 (SD) > > mmc@d4281000: 0 > > => > > => mmc info > > Device: mmc@d4280000 > > Manufacturer ID: 3 > > OEM: 5344 > > Name: SD32G > > Bus Speed: 50000000 > > Mode: SD High Speed (50MHz) > > Rd Block Len: 512 > > SD version 3.0 > > High Capacity: Yes > > Capacity: 29.7 GiB > > Bus Width: 4-bit > > Erase Group Size: 512 Bytes > > > > I enabled MMC_CAP_CMD23 and the card does support it (SCR bit 1, > > cmd23_host=1 and cmd23_card=1 in the log above), so the SPL really > > used SET_BLOCK_COUNT + CMD18 without CMD12 - and it still aborts the > > data phase with SDHCI_INT_DATA_END_BIT after ~20 of 32 blocks. > > Booting U-Boot proper and issuing the same 32 block CMD18 from the same > > card succeeds, with the same PIO path (flags=0, dma=0), the same SD_HS > > mode, the same 4-bit bus and the same CMD23 usage. > > So I think CMD23 is not the trigger, the SPL fails with the FIFO > > permanently backed up (it drains slower than card delivers, so the > > controller has to stop the SD clock inside a block). > > > > Now answering your questions: > > mode : mode=2 = SD_HS, in both stages > > clock : requested 50 MHz (SD_HS) in both stages > > bus : 4-bit bus, in both stages > > path : PIO in both stages > > CMD23 : the card supports it and both stages use CMD23 + CMD18 > > > > > > Hi Zixian, > > Thanks for the logs. > > I hit the same pattern while testing the Cadence SD6HC driver. > Multi-block reads failed and single-block reads worked. On that board > the host and the card were in 1.8 V mode, but the I/O supply had been > left at 3.3 V. A short transfer got through; a longer one failed on the > data lines. > Both stages on K1 use the same PIO loop, so a FIFO that drains slower > than the card delivers would show up in U-Boot proper as well. Your > SPL/proper split fits an electrical setup difference. > > The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, > SD mode only): the controller detected 0 at the end-bit position of > read data on DAT, or of the write CRC status. That is a bad edge on > the data line during the transfer. > > On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot > dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, > value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, > called from board_init_f(), writes 1800000. The dts leaves aldo1 at > 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is > only after a UHS switch. mmc1_cfg is power-source 3300, and > mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. > > CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a > stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at > 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() > requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the > same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer > that succeeds. > > CONFIG_SPL_PINCTRL is not set either. The driver calls > pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that > function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return > is ignored. SPL never applies mmc1_cfg. Proper selects "default" for > SD_HS, which is that state. > > Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable > CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable > CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read > succeed, this is the F3 failure. > We need to enable CONFIG_SPL_SPACEMIT_GPIO? Thanks. I am seeing the same issue on the F3 board. Since spacemit/k1-musepi-pro is configured as the default device tree, do we also need to make similar changes to k1-bananapi-f3-u-boot.dtsi? $ grep spacemit configs/spacemit_k1_defconfig CONFIG_DEFAULT_DEVICE_TREE="spacemit/k1-musepi-pro" CONFIG_OF_LIST="spacemit/k1-bananapi-f3 spacemit/k1-musepi-pro" On my board, the system fails with the following error: Unhandled exception: Illegal instruction Could this be caused by k1-bananapi-f3-u-boot.dtsi not being updated in the same way as spacemit/k1-musepi-pro? sys: 0x2 try sd... bm:3 j... <debug_uart> U-Boot SPL 2026.10-00722-g6eaefa1cf807-dirty (Oct 11 2026 - 18:36:52 +0530) Fail to detect board:-2 vdd_core, value:900000 vdd_1v8, value:1800000 vdd_1v8_mmc, value:1800000 DDR firmware: [0xc081dc80]:0xf0227179, size:0x8d98 DDR is ready jedec_spi_nor flash@0: unrecognized JEDEC id bytes: 00, 00, 00 Fail to detect spi nor flash. Trying to boot from MMC2 sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 Unhandled exception: Illegal instruction EPC: 0000000000200000 RA: 00000000c08017fa TVAL: 000000006d9058eb Code: 0001 0006 0000 0000 0000 0000 0000 0000 (58eb 6d90) resetting ... reset not supported yet ### ERROR ### Please RESET the board ### > Regards, > Tanmay > Thanks -Anand ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-11 15:33 ` Anand Moon @ 2026-10-11 19:41 ` Kathpalia, Tanmay 0 siblings, 0 replies; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-11 19:41 UTC (permalink / raw) To: Anand Moon Cc: Zixian Zeng, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit On 11-10-2026 21:03, Anand Moon wrote: > Hi Al,L > > On Sun, 11 Oct 2026 at 20:07, Kathpalia, Tanmay > <tanmay.kathpalia@altera.com> wrote: >> >> On 11-10-2026 09:08, Zixian Zeng wrote: >>> On 2026/10/11 03:16, Kathpalia, Tanmay wrote: >>>> On 11-10-2026 00:32, Kathpalia, Tanmay wrote: >>>>> On 10-10-2026 11:47, Zixian Zeng wrote: >>>>>> Hi, Dave: >>>>>> >>>>>> On 2026/10/6 02:01, Dave Klotz wrote: >>>>>>> spacemit_sdhci_get_b_max() limits every SD read in the SPL to a >>>>>>> single >>>>>>> block, so loading a ~1 MiB u-boot.itb from a card takes about 2000 >>>>>>> separate commands. The controller handles multi-block PIO reads in >>>>>>> the >>>>>>> SPL: the OrangePi RV2 has loaded U-Boot from microSD with them >>>>>>> through >>>>>>> the v2026.07 and v2026.10 trees. >>>>>>> >>>>>>> Drop the limit and use the host's b_max. >>>>>>> >>>>>>> The merged v13 cover retains the v9 changelog entry choosing single- >>>>>>> block SD reads in SPL. This reverses that deliberate policy for the >>>>>>> recorded RV2 SPL boot use case; no general multi-card reliability >>>>>>> claim >>>>>>> is made. K1 does not advertise MMC_CAP_CMD23, so the MMC core sends >>>>>>> CMD12 after a multi-block read rather than requiring CMD23. >>>>>>> Additional >>>>>>> card models, cold boots and transfer-error recovery remain required. >>>>>>> >>>>>>> Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> >>>>>>> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >>>>>>> --- >>>>>>> Validation: unchanged executable change from v1; exact-base source >>>>>>> replay and checkpatch pass. The corrected combined integration, with >>>>>>> separate clock/MMC and DDR relocation fixes, passed SD SPL/FIT and >>>>>>> automatic NVMe EFI boot on the 4 GiB RV2 in a warm-boot trial. >>>>>>> This is >>>>>>> an integration result, not an isolated test of this patch. >>>>>>> >>>>>>> drivers/mmc/spacemit_sdhci.c | 11 ----------- >>>>>>> 1 file changed, 0 insertions(+), 11 deletions(-) >>>>>>> >>>>>>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/ >>>>>>> spacemit_sdhci.c >>>>>>> index 6488ae0fdb..4284553177 100644 >>>>>>> --- a/drivers/mmc/spacemit_sdhci.c >>>>>>> +++ b/drivers/mmc/spacemit_sdhci.c >>>>>>> @@ -324,16 +324,6 @@ >>>>>>> return 0; >>>>>>> } >>>>>>> -static int spacemit_sdhci_get_b_max(struct udevice *dev, void >>>>>>> *dst, >>>>>>> - lbaint_t blkcnt) >>>>>>> -{ >>>>>>> - struct mmc *mmc = mmc_get_mmc_dev(dev); >>>>>>> - >>>>>>> - if (IS_ENABLED(CONFIG_SPL_BUILD) && mmc && IS_SD(mmc)) >>>>>>> - return 1; >>>>>>> - return mmc->cfg->b_max; >>>>>>> -} >>>>>>> - >>>>>>> static void spacemit_sdhci_set_control_reg(struct sdhci_host *host) >>>>>>> { >>>>>>> struct mmc *mmc = host->mmc; >>>>>>> @@ -574,7 +564,6 @@ >>>>>>> spacemit_mmc_ops = sdhci_ops; >>>>>>> spacemit_mmc_ops.wait_dat0 = spacemit_sdhci_wait_dat0; >>>>>>> - spacemit_mmc_ops.get_b_max = spacemit_sdhci_get_b_max; >>>>>>> ret = clk_get_bulk(dev, &plat->clks); >>>>>>> if (ret) { >>>>>> Using the current version of the next branch u-boot (ed869863c7), >>>>>> with your MMC patch series applied. >>>>>> Since the SPI controller is not enabled by default on the BananaPi-F3, >>>>>> I also applied another patch series: >>>>>> Link: https://lore.kernel.org/u-boot/ >>>>>> cover.1790976767.git.DaveWK225@protonmail.com/ >>>>>> >>>>>> I tested u-boot SPL with three SD cards on a BananaPi-F3 and found >>>>>> a reproducible issue, the specific error I encountered is spl: >>>>>> partition error (Error: -38) >>>>>> At the meantime, when i was revert the commit: >>>>>> mmc: k1: let the SPL read SD cards more than one block at a time >>>>>> the error has gone. Same SD card, same operation steps. >>>>>> Maybe BananaPi-F3 do not support read SD cards more than one block >>>>>> at a time? >>>>>> >>>>>> >>>>> Hi Zixian, >>>>> >>>>> Thanks for testing this on the BananaPi-F3 and reporting this. The >>>>> same cards and steps failing only with this patch shows that >>>>> multi-block SD reads in the SPL are not reliable yet. >>>>> >>>>> I would request to try one more experiment before dropping it. >>>>> Please add MMC_CAP_CMD23 to host->host_caps and boot the same cards >>>>> again. CMD23 (SET_BLOCK_COUNT) tells the card how many blocks to >>>>> transfer. mmc_read_blocks() then uses CMD23 plus CMD18, and it does >>>>> not send CMD12 afterwards. The current driver does not set >>>>> MMC_CAP_CMD23, so a multi-block read is CMD18 followed by CMD12. >>>>> >>>>> After the SCR is read, the MMC core clears MMC_CAP_CMD23 when the card >>>>> does not advertise SD_SCR_CMD23_SUPPORT. Those cards stay on CMD18 >>>>> plus CMD12. >>>>> >>>>> This also matches Eric's earlier note that on K1 ADMA depends on CMD23: >>>>> https://patchwork.ozlabs.org/project/uboot/patch/20260707-m4-v4-3- >>>>> dbd01185f911@riscstar.com/ >>>>> >>>>> If the CMD23 test also fails, I agree that this patch should be >>>>> dropped. >>>>> >>>> Hi Zixian, >>>> >>>> A few follow-up questions about the SPL-only failure: >>>> >>>> The callback limits reads only when CONFIG_SPL_BUILD is enabled. U-Boot >>>> proper already uses mmc->cfg->b_max, even without this patch. >>>> Therefore, multi-block SD reads should already be used in U-Boot proper. >>>> >>>> Could you please boot U-Boot proper from another device and test a >>>> multi-block read from the same SD cards? >>>> Could you also compare the following between SPL and U-Boot proper? >>>> >>>> - selected SD timing mode >>>> - card clock frequency >>>> - bus width >>>> - PIO, SDMA, or ADMA transfer path >>>> - whether the card advertises CMD23 support >>>> >>>> Although both stages use the same driver source, they may use different >>>> configuration options, transfer paths, clocks, and timing modes. This >>>> could explain why CMD18 works in U-Boot proper but fails in SPL. >>>> >>>> Regards, >>>> Tanmay >>> Hi, Tanmay, >>> >>> Sure, I've added some print logs, which you can see below: >>> >>> commit 53c0ff5f65b0c7c4ae9f4563265741cd0ca23a0c >>> Author: Zixian Zeng <sycamoremoon376@gmail.com> >>> Date: Sun Oct 11 09:34:03 2026 +0800 >>> >>> Add mmc debug log >>> >>> Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> >>> >>> diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c >>> index a619440fc4c..6e18d13884a 100644 >>> --- a/drivers/mmc/mmc.c >>> +++ b/drivers/mmc/mmc.c >>> @@ -458,6 +458,13 @@ static int mmc_read_blocks(struct mmc *mmc, void >>> *dst, lbaint_t start, >>> struct mmc_cmd cmd; >>> struct mmc_data data; >>> >>> + if (blkcnt > 1) >>> + printf("mmc: multi-blk blkcnt=%lu clk=%u mode=%u >>> width=%u caps=%x cmd23_host=%u scr0=%x cmd23_card=%u\n", >>> + (ulong)blkcnt, mmc->clock, >>> + (unsigned)mmc->selected_mode, mmc->bus_width, >>> + mmc->host_caps, !!(mmc->host_caps & >>> MMC_CAP_CMD23), >>> + mmc->scr[0], !!(mmc->scr[0] & >>> SD_SCR_CMD23_SUPPORT)); >>> + >>> if (blkcnt > 1 && (mmc->host_caps & MMC_CAP_CMD23)) { >>> cmd.cmdidx = MMC_CMD_SET_BLOCK_COUNT; >>> cmd.cmdarg = blkcnt & 0x0000ffff; >>> @@ -483,8 +490,12 @@ static int mmc_read_blocks(struct mmc *mmc, void >>> *dst, lbaint_t start, >>> data.blocksize = mmc->read_bl_len; >>> data.flags = MMC_DATA_READ; >>> >>> - if (mmc_send_cmd(mmc, &cmd, &data)) >>> + if (mmc_send_cmd(mmc, &cmd, &data)) { >>> + log_err("mmc: cmd%u read failed: blks=%lu blksz=%lu >>> arg=%lx\n", >>> + cmd.cmdidx, (ulong)blkcnt, >>> (ulong)mmc->read_bl_len, >>> + (ulong)cmd.cmdarg); >>> return 0; >>> + } >>> >>> if (blkcnt > 1 && !(mmc->host_caps & MMC_CAP_CMD23)) { >>> if (mmc_send_stop_transmission(mmc, false)) { >>> @@ -547,6 +558,8 @@ ulong mmc_bread(struct blk_desc *block_dev, >>> lbaint_t start, lbaint_t blkcnt, >>> } >>> >>> if (mmc_set_blocklen(mmc, mmc->read_bl_len)) { >>> + log_err("mmc: CMD16 blocklen=%lu failed, read of %lu >>> blocks aborted\n", >>> + (ulong)mmc->read_bl_len, (ulong)blkcnt); >>> pr_debug("%s: Failed to set blocklen\n", __func__); >>> return 0; >>> } >>> @@ -556,6 +569,8 @@ ulong mmc_bread(struct blk_desc *block_dev, >>> lbaint_t start, lbaint_t blkcnt, >>> do { >>> cur = (blocks_todo > b_max) ? b_max : blocks_todo; >>> if (mmc_read_blocks(mmc, dst, start, cur) != cur) { >>> + log_err("mmc: read of %lu blocks at lba %lx >>> failed (b_max=%u)\n", >>> + (ulong)cur, (ulong)start, b_max); >>> pr_debug("%s: Failed to read blocks\n", >>> __func__); >>> return 0; >>> } >>> diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c >>> index 962a99cd05a..339b222bb68 100644 >>> --- a/drivers/mmc/sdhci.c >>> +++ b/drivers/mmc/sdhci.c >>> @@ -131,6 +131,7 @@ static int sdhci_transfer_data(struct sdhci_host >>> *host, struct mmc_data *data) >>> dma_addr_t start_addr = host->start_addr; >>> unsigned int stat, rdy, mask, timeout, block = 0; >>> bool transfer_done = false; >>> + ulong t0 = get_timer(0); >>> >>> timeout = 1000000; >>> rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL; >>> @@ -138,6 +139,13 @@ static int sdhci_transfer_data(struct sdhci_host >>> *host, struct mmc_data *data) >>> do { >>> stat = sdhci_readl(host, SDHCI_INT_STATUS); >>> if (stat & SDHCI_INT_ERROR) { >>> + log_err("sdhci: data err irq=%x present=%x >>> mode=%x blksz=%x blkcnt=%x blocks=%u/%u t=%lums\n", >>> + stat, >>> + sdhci_readl(host, SDHCI_PRESENT_STATE), >>> + sdhci_readw(host, SDHCI_TRANSFER_MODE), >>> + sdhci_readw(host, SDHCI_BLOCK_SIZE), >>> + sdhci_readw(host, SDHCI_BLOCK_COUNT), >>> + block, data->blocks, get_timer(t0)); >>> log_debug("Error detected in status(%#x)!\n", >>> stat); >>> return -EIO; >>> } >>> @@ -294,6 +302,11 @@ static int sdhci_send_command(struct mmc *mmc, >>> struct mmc_cmd *cmd, >>> SDHCI_BLOCK_SIZE); >>> sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); >>> sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); >>> + if (data->blocks > 1) >>> + printf("sdhci: multi cmd%u arg=%lx blks=%u >>> blksz=%u mode=%x dma=%u\n", >>> + cmd->cmdidx, (ulong)cmd->cmdarg, >>> data->blocks, >>> + data->blocksize, mode, >>> + !!(host->flags & USE_DMA)); >>> } else if (cmd->resp_type & MMC_RSP_BUSY) { >>> sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); >>> } >>> @@ -325,8 +338,12 @@ static int sdhci_send_command(struct mmc *mmc, >>> struct mmc_cmd *cmd, >>> if ((stat & (SDHCI_INT_ERROR | mask)) == mask) { >>> sdhci_cmd_done(host, cmd); >>> sdhci_writel(host, mask, SDHCI_INT_STATUS); >>> - } else >>> + } else { >>> + log_err("sdhci: cmd%u status mismatch irq=%x mask=%x >>> present=%x\n", >>> + cmd->cmdidx, stat, mask, >>> + sdhci_readl(host, SDHCI_PRESENT_STATE)); >>> ret = -1; >>> + } >>> >>> if (!ret && data) >>> ret = sdhci_transfer_data(host, data); >>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c >>> index 13bf6bf6000..23c655c6def 100644 >>> --- a/drivers/mmc/spacemit_sdhci.c >>> +++ b/drivers/mmc/spacemit_sdhci.c >>> @@ -640,6 +640,19 @@ static int spacemit_sdhci_probe(struct udevice *dev) >>> goto err_reset; >>> >>> spacemit_sdhci_phy_init(dev, host); >>> + >>> + { >>> + u32 caps = sdhci_readl(host, SDHCI_CAPABILITIES); >>> + const char *path = (host->flags & USE_ADMA64) ? >>> "ADMA64" : >>> + (host->flags & USE_ADMA) ? "ADMA" : >>> + (host->flags & USE_SDMA) ? "SDMA" : >>> "PIO"; >>> + >>> + printf("sdhci: %s path=%s flags=%x caps_sdma=%u >>> caps_adma2=%u max_clk=%u\n", >>> + dev->name, path, host->flags, >>> + !!(caps & SDHCI_CAN_DO_SDMA), >>> + !!(caps & SDHCI_CAN_DO_ADMA2), >>> + host->max_clk); >>> + } >>> return 0; >>> >>> /* >>> >>> >>> commit 75d6b28ba7b020d3100586f586ee6d1a4488ac84 >>> Author: Zixian Zeng <sycamoremoon376@gmail.com> >>> Date: Sun Oct 11 09:33:20 2026 +0800 >>> >>> debug: Add MMC_CAPS_CMD23 >>> >>> Signed-off-by: Zixian Zeng <sycamoremoon376@gmail.com> >>> >>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c >>> index 88e06a681ca..13bf6bf6000 100644 >>> --- a/drivers/mmc/spacemit_sdhci.c >>> +++ b/drivers/mmc/spacemit_sdhci.c >>> @@ -624,7 +624,7 @@ static int spacemit_sdhci_probe(struct udevice *dev) >>> /* Set quirks */ >>> host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | >>> SDHCI_QUIRK_32BIT_DMA_ADDR; >>> - host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz; >>> + host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | >>> MMC_CAP_CMD23; >>> host->max_clk = plat->cfg.f_max; >>> >>> plat->cfg.f_min = SDHC_MIN_CLOCK; >>> >>> >>> With appling these two commits, Debug logs as follows: >>> >>> ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline >>> origin/next..HEAD >>> 53c0ff5f65b (HEAD -> k1-dave-mmc) Add mmc debug log >>> 75d6b28ba7b debug: Add MMC_CAPS_CMD23 >>> 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on >>> probe failure >>> 4114764d716 mmc: k1: let the SPL read SD cards more than one block at >>> a time >>> 6676ce89521 mmc: k1: handle a missing max-frequency and >>> clk_set_rate()'s return value >>> 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL >>> b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller >>> in SPL >>> >>> U-Boot SPL 2026.10-rc5-00641-g53c0ff5f65b0 (Oct 11 2026 - 10:31:28 +0800) >>> Fail to detect board:-2 >>> vdd_core, value:900000 >>> vdd_1v8, value:1800000 >>> vdd_1v8_mmc, value:1800000 >>> DDR firmware: [0xc081d700]:0xf0227179, size:0x8d98 >>> DDR is ready >>> No SPI controller (-19) >>> Trying to boot from MMC2 >>> sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 >>> max_clk=204800000 >>> mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef >>> cmd23_host=1 scr0=2358043 cmd23_card=1 >>> sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 >>> sdhci: data err irq=408020 present=1070800 mode=32 blksz=7200 >>> blkcnt=12 blocks=12/32 t=2ms >>> mmc: cmd18 read failed: blks=32 blksz=512 arg=2 >>> mmc: read of 32 blocks at lba 2 failed (b_max=65535) >>> sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 >>> sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 >>> sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 >>> sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 >>> sdhci: cmd16 status mismatch irq=18000 mask=1 present=1070000 >>> mmc: CMD16 blocklen=512 failed, read of 1 blocks aborted >>> spl: partition error >>> Error: -38 >>> SPL: Unsupported Boot Device! >>> Trying to boot from MMC1 >>> alloc space exhausted ptr 104380 limit 100000 >>> Aligned buffer alloc failed >>> spl: could not find mmc device 0. error: -19 >>> Error: -19 >>> SPL: Unsupported Boot Device! >>> Trying to boot from SPI >>> Invalid bus 0 (err=-19) >>> SPI probe failed. >>> Error: -19 >>> SPL: Unsupported Boot Device! >>> SPL: Unsupported Boot Device! >>> SPL: failed to boot from all boot devices >>> ### ERROR ### Please RESET the board ### >>> >>> >>> After I revert the multi-block SD read commit, >>> I booted into u-boot proper. Debug logs as follows: >>> >>> ⋊> hack@morise ⋊> ~/k/u-boot on k1-dave-mmc ⥄ git log --oneline >>> origin/next..HEAD >>> 55e8da25a70 (HEAD -> k1-dave-mmc) Revert "mmc: k1: let the SPL read SD >>> cards more than one block at a time" >>> 53c0ff5f65b Add mmc debug log >>> 75d6b28ba7b debug: Add MMC_CAPS_CMD23 >>> 6b4af8b1dd8 mmc: k1: do not release the shared AXI clock and reset on >>> probe failure >>> 4114764d716 mmc: k1: let the SPL read SD cards more than one block at >>> a time >>> 6676ce89521 mmc: k1: handle a missing max-frequency and >>> clk_set_rate()'s return value >>> 6427189ef33 spacemit: k1: fall back to the other boot devices in SPL >>> b58a31797d7 spacemit: k1: do not require a PMIC or an SPI controller >>> in SPL >>> >>> >>> U-Boot SPL 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) >>> Fail to detect board:-2 >>> vdd_core, value:900000 >>> vdd_1v8, value:1800000 >>> vdd_1v8_mmc, value:1800000 >>> DDR firmware: [0xc081d740]:0xf0227179, size:0x8d98 >>> DDR is ready >>> No SPI controller (-19) >>> Trying to boot from MMC2 >>> sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 >>> max_clk=204800000 >>> >>> <debug_uart> >>> >>> >>> U-Boot 2026.10-rc5-00642-g55e8da25a70c (Oct 11 2026 - 10:38:42 +0800) >>> >>> DRAM: 4 GiB >>> Core: 339 devices, 23 uclasses, devicetree: separate >>> MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 >>> max_clk=204800000 >>> sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 >>> max_clk=204800000 >>> mmc@d4280000: 1, mmc@d4281000: 0 >>> Loading Environment from nowhere... OK >>> In: serial@d4017000 >>> Out: serial@d4017000 >>> Err: serial@d4017000 >>> Net: No ethernet found. >>> => mmc dev 1 >>> mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef >>> cmd23_host=1 scr0=2358043 cmd23_card=1 >>> sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 >>> mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef >>> cmd23_host=1 scr0=2358043 cmd23_card=1 >>> sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 >>> ... omit duplicate logs >>> mmc: multi-blk blkcnt=2 clk=50000000 mode=2 width=4 caps=300207ef >>> cmd23_host=1 scr0=2358043 cmd23_card=1 >>> sdhci: multi cmd18 arg=82002 blks=2 blksz=512 mode=32 dma=0 >>> switch to partitions #0, OK >>> mmc1 is current device >>> => >>> => mmc list >>> mmc@d4280000: 1 (SD) >>> mmc@d4281000: 0 >>> => >>> => mmc info >>> Device: mmc@d4280000 >>> Manufacturer ID: 3 >>> OEM: 5344 >>> Name: SD32G >>> Bus Speed: 50000000 >>> Mode: SD High Speed (50MHz) >>> Rd Block Len: 512 >>> SD version 3.0 >>> High Capacity: Yes >>> Capacity: 29.7 GiB >>> Bus Width: 4-bit >>> Erase Group Size: 512 Bytes >>> >>> I enabled MMC_CAP_CMD23 and the card does support it (SCR bit 1, >>> cmd23_host=1 and cmd23_card=1 in the log above), so the SPL really >>> used SET_BLOCK_COUNT + CMD18 without CMD12 - and it still aborts the >>> data phase with SDHCI_INT_DATA_END_BIT after ~20 of 32 blocks. >>> Booting U-Boot proper and issuing the same 32 block CMD18 from the same >>> card succeeds, with the same PIO path (flags=0, dma=0), the same SD_HS >>> mode, the same 4-bit bus and the same CMD23 usage. >>> So I think CMD23 is not the trigger, the SPL fails with the FIFO >>> permanently backed up (it drains slower than card delivers, so the >>> controller has to stop the SD clock inside a block). >>> >>> Now answering your questions: >>> mode : mode=2 = SD_HS, in both stages >>> clock : requested 50 MHz (SD_HS) in both stages >>> bus : 4-bit bus, in both stages >>> path : PIO in both stages >>> CMD23 : the card supports it and both stages use CMD23 + CMD18 >>> >>> >> Hi Zixian, >> >> Thanks for the logs. >> >> I hit the same pattern while testing the Cadence SD6HC driver. >> Multi-block reads failed and single-block reads worked. On that board >> the host and the card were in 1.8 V mode, but the I/O supply had been >> left at 3.3 V. A short transfer got through; a longer one failed on the >> data lines. >> Both stages on K1 use the same PIO loop, so a FIFO that drains slower >> than the card delivers would show up in U-Boot proper as well. Your >> SPL/proper split fits an electrical setup difference. >> >> The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, >> SD mode only): the controller detected 0 at the end-bit position of >> read data on DAT, or of the write CRC status. That is a bad edge on >> the data line during the transfer. >> >> On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot >> dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, >> value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, >> called from board_init_f(), writes 1800000. The dts leaves aldo1 at >> 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is >> only after a UHS switch. mmc1_cfg is power-source 3300, and >> mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. >> >> CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a >> stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at >> 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() >> requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the >> same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer >> that succeeds. >> >> CONFIG_SPL_PINCTRL is not set either. The driver calls >> pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that >> function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return >> is ignored. SPL never applies mmc1_cfg. Proper selects "default" for >> SD_HS, which is that state. >> >> Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable >> CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable >> CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read >> succeed, this is the F3 failure. >> > We need to enable CONFIG_SPL_SPACEMIT_GPIO? > > Thanks. I am seeing the same issue on the F3 board. > Since spacemit/k1-musepi-pro is configured as the default device tree, > do we also need to make similar changes to k1-bananapi-f3-u-boot.dtsi? > > $ grep spacemit configs/spacemit_k1_defconfig > CONFIG_DEFAULT_DEVICE_TREE="spacemit/k1-musepi-pro" > CONFIG_OF_LIST="spacemit/k1-bananapi-f3 spacemit/k1-musepi-pro" > > On my board, the system fails with the following error: Unhandled > exception: Illegal instruction > Could this be caused by k1-bananapi-f3-u-boot.dtsi not being updated > in the same way as > spacemit/k1-musepi-pro? > > sys: 0x2 > try sd... > bm:3 > j... > > <debug_uart> > > U-Boot SPL 2026.10-00722-g6eaefa1cf807-dirty (Oct 11 2026 - 18:36:52 +0530) > Fail to detect board:-2 > vdd_core, value:900000 > vdd_1v8, value:1800000 > vdd_1v8_mmc, value:1800000 > DDR firmware: [0xc081dc80]:0xf0227179, size:0x8d98 > DDR is ready > jedec_spi_nor flash@0: unrecognized JEDEC id bytes: 00, 00, 00 > Fail to detect spi nor flash. > Trying to boot from MMC2 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 > Unhandled exception: Illegal instruction > EPC: 0000000000200000 RA: 00000000c08017fa TVAL: 000000006d9058eb > > Code: 0001 0006 0000 0000 0000 0000 0000 0000 (58eb 6d90) > > > resetting ... > reset not supported yet > ### ERROR ### Please RESET the board ### Hi Anand, The illegal instruction at EPC 0x200000 could mean that SPL loaded a corrupted U-Boot image and then jumped to its load address. Therefore, it may be related to the multi-block failure, but the current log does not confirm that. Could you first try the options suggested above: set the SPL SD I/O supply to 3.3 V, or enable CONFIG_SPL_MMC_IO_VOLTAGE, followed by CONFIG_SPL_PINCTRL if needed? CONFIG_SPL_SPACEMIT_GPIO is related to the card-detect GPIO and is separate from the voltage and pinctrl setup. If the illegal instruction remains after the SD transfer issue is resolved, let us start a separate thread for it. Regards, Tanmay ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-11 14:31 ` Kathpalia, Tanmay 2026-10-11 15:33 ` Anand Moon @ 2026-10-12 13:15 ` Zixian Zeng 2026-10-12 14:00 ` Kathpalia, Tanmay 2026-10-12 16:07 ` Anand Moon 1 sibling, 2 replies; 33+ messages in thread From: Zixian Zeng @ 2026-10-12 13:15 UTC (permalink / raw) To: Kathpalia, Tanmay, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit On 2026/10/11 22:31, Kathpalia, Tanmay wrote: > Hi Zixian, > > Thanks for the logs. > > I hit the same pattern while testing the Cadence SD6HC driver. > Multi-block reads failed and single-block reads worked. On that board > the host and the card were in 1.8 V mode, but the I/O supply had been > left at 3.3 V. A short transfer got through; a longer one failed on the > data lines. > Both stages on K1 use the same PIO loop, so a FIFO that drains slower > than the card delivers would show up in U-Boot proper as well. Your > SPL/proper split fits an electrical setup difference. > > The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, > SD mode only): the controller detected 0 at the end-bit position of > read data on DAT, or of the write CRC status. That is a bad edge on > the data line during the transfer. > > On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot > dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, > value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, > called from board_init_f(), writes 1800000. The dts leaves aldo1 at > 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is > only after a UHS switch. mmc1_cfg is power-source 3300, and > mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. > > CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a > stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at > 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() > requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the > same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer > that succeeds. > > CONFIG_SPL_PINCTRL is not set either. The driver calls > pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that > function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return > is ignored. SPL never applies mmc1_cfg. Proper selects "default" for > SD_HS, which is that state. > > Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable > CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable > CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read > succeed, this is the F3 failure. > > Regards, > Tanmay Hi Tanmay, Your diagnosis was right - it is the I/O voltage. Enabling CONFIG_SPL_MMC_IO_VOLTAGE makes the multi-block read work on the Banana Pi-F3: Based on previous commit, I patched the following changes: diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig index 9c15d96eae2..f5c717e5965 100644 --- a/configs/spacemit_k1_defconfig +++ b/configs/spacemit_k1_defconfig @@ -95,6 +95,7 @@ CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SPACEMIT=y CONFIG_MMC_IO_VOLTAGE=y +CONFIG_SPL_MMC_IO_VOLTAGE=y CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_HS400_SUPPORT=y CONFIG_MMC_HS400_ES_SUPPORT=y diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index 23c655c6def..58374c482b3 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -251,6 +251,10 @@ static void spacemit_sdhci_set_voltage(struct sdhci_host *host) bool ok; int voltage_mv = to_180 ? 1800000 : 3300000; + printf("sdhci: voltage signal_voltage=%u vqmmc=%s -> %dmV\n", + mmc->signal_voltage, + mmc->vqmmc_supply ? mmc->vqmmc_supply->name : "none", + voltage_mv); if (spacemit_sdhci_set_vqmmc_voltage(mmc, voltage_mv)) return; if (!IS_SD(mmc)) @@ -274,7 +278,8 @@ static void spacemit_sdhci_set_voltage(struct sdhci_host *host) break; } default: - /* No signal voltage switch required */ + printf("sdhci: voltage signal_voltage=%u -> no switch\n", + mmc->signal_voltage); return; } } Booting logs as follows: U-Boot SPL 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) Fail to detect board:-2 vdd_core, value:900000 vdd_1v8, value:1800000 vdd_1v8_mmc, value:1800000 DDR firmware: [0xc081d880]:0xf0227179, size:0x8d98 DDR is ready No SPI controller (-19) Trying to boot from MMC2 sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 sdhci: voltage signal_voltage=0 -> no switch sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef cmd23_host=1 scr0=2358043 cmd23_card=1 sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 mmc: multi-blk blkcnt=1956 clk=50000000 mode=2 width=4 caps=300207ef cmd23_host=1 scr0=2358043 cmd23_card=1 sdhci: multi cmd18 arg=1000 blks=1956 blksz=512 mode=32 dma=0 <debug_uart> U-Boot 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) DRAM: 4 GiB Core: 338 devices, 22 uclasses, devicetree: separate MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 max_clk=204800000 mmc@d4280000: 1, mmc@d4281000: 0 Loading Environment from nowhere... OK In: serial@d4017000 Out: serial@d4017000 Err: serial@d4017000 Net: No ethernet found. => With the voltage corrected, a single 1956 block PIO CMD18 loads the whole FIT,so the controller is fine with the FIFO back pressure, the slow SPL drain was a symptom, not the cause :-). Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed "sdhci: voltage signal_voltage=0 -> no switch". Since mmc_set_signWith the voltage corrected, a single 1956 block PIO CMD18 loads the whole FIT,so the controller is fine with the FIFO back pressure, the slow SPL drain was a symptom, not the cause :-). Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed "sdhci: voltage signal_voltage=0 -> no switch". Since mmc_set_signal_voltage() is a stub in SPL, so mmc->signal_voltage stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the "no switch required" path, and aldo1 stayed at the initial 1800000 that set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is what hid it. On the pinctrl side I had already run the SPL with standalone CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and mmc1_uhs_cfg plus their pin groups. I confirmed that pinctrl_select_state() return successfully. The multi-block read still failed the same way with the rail at 1.8V. Therefore, I suspect that configuring the MMC signal voltage to 1.8V in pmic_init() may need to be modified. Thanks for your suggestions and guidance. Best regards, Zixianal_voltage() is a stub in SPL, so mmc->signal_voltage stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the "no switch required" path, and aldo1 stayed at the initial 1800000 that set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is what hid it. On the pinctrl side I had already run the SPL with standalone CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and mmc1_uhs_cfg plus their pin groups. I confirmed that pinctrl_select_state() return successfully. The multi-block read still failed the same way with the rail at 1.8V. Therefore, I suspect that configuring the MMC signal voltage to 1.8V in pmic_init() may need to be modified. Thanks for your suggestions and guidance. Best regards, Zixian ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-12 13:15 ` Zixian Zeng @ 2026-10-12 14:00 ` Kathpalia, Tanmay 2026-10-12 14:30 ` Yixun Lan 2026-10-12 16:07 ` Anand Moon 1 sibling, 1 reply; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-12 14:00 UTC (permalink / raw) To: Zixian Zeng, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit On 12-10-2026 18:45, Zixian Zeng wrote: > On 2026/10/11 22:31, Kathpalia, Tanmay wrote: >> Hi Zixian, >> >> Thanks for the logs. >> >> I hit the same pattern while testing the Cadence SD6HC driver. >> Multi-block reads failed and single-block reads worked. On that board >> the host and the card were in 1.8 V mode, but the I/O supply had been >> left at 3.3 V. A short transfer got through; a longer one failed on the >> data lines. >> Both stages on K1 use the same PIO loop, so a FIFO that drains slower >> than the card delivers would show up in U-Boot proper as well. Your >> SPL/proper split fits an electrical setup difference. >> >> The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, >> SD mode only): the controller detected 0 at the end-bit position of >> read data on DAT, or of the write CRC status. That is a bad edge on >> the data line during the transfer. >> >> On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot >> dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, >> value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, >> called from board_init_f(), writes 1800000. The dts leaves aldo1 at >> 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is >> only after a UHS switch. mmc1_cfg is power-source 3300, and >> mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. >> >> CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a >> stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at >> 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() >> requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the >> same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer >> that succeeds. >> >> CONFIG_SPL_PINCTRL is not set either. The driver calls >> pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that >> function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return >> is ignored. SPL never applies mmc1_cfg. Proper selects "default" for >> SD_HS, which is that state. >> >> Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable >> CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable >> CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read >> succeed, this is the F3 failure. >> >> Regards, >> Tanmay > > Hi Tanmay, > > Your diagnosis was right - it is the I/O voltage. > Enabling CONFIG_SPL_MMC_IO_VOLTAGE makes > the multi-block read work on the Banana Pi-F3: > > Based on previous commit, I patched the following changes: > > diff --git a/configs/spacemit_k1_defconfig > b/configs/spacemit_k1_defconfig > index 9c15d96eae2..f5c717e5965 100644 > --- a/configs/spacemit_k1_defconfig > +++ b/configs/spacemit_k1_defconfig > @@ -95,6 +95,7 @@ CONFIG_MMC=y > CONFIG_MMC_SDHCI=y > CONFIG_MMC_SDHCI_SPACEMIT=y > CONFIG_MMC_IO_VOLTAGE=y > +CONFIG_SPL_MMC_IO_VOLTAGE=y > CONFIG_MMC_HS200_SUPPORT=y > CONFIG_MMC_HS400_SUPPORT=y > CONFIG_MMC_HS400_ES_SUPPORT=y > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index 23c655c6def..58374c482b3 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -251,6 +251,10 @@ static void spacemit_sdhci_set_voltage(struct > sdhci_host *host) > bool ok; > int voltage_mv = to_180 ? 1800000 : 3300000; > > + printf("sdhci: voltage signal_voltage=%u > vqmmc=%s -> %dmV\n", > + mmc->signal_voltage, > + mmc->vqmmc_supply ? > mmc->vqmmc_supply->name : "none", > + voltage_mv); > if (spacemit_sdhci_set_vqmmc_voltage(mmc, > voltage_mv)) > return; > if (!IS_SD(mmc)) > @@ -274,7 +278,8 @@ static void spacemit_sdhci_set_voltage(struct > sdhci_host *host) > break; > } > default: > - /* No signal voltage switch required */ > + printf("sdhci: voltage signal_voltage=%u -> no > switch\n", > + mmc->signal_voltage); > return; > } > } > > Booting logs as follows: > > U-Boot SPL 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > Fail to detect board:-2 > vdd_core, value:900000 > vdd_1v8, value:1800000 > vdd_1v8_mmc, value:1800000 > DDR firmware: [0xc081d880]:0xf0227179, size:0x8d98 > DDR is ready > No SPI controller (-19) > Trying to boot from MMC2 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > sdhci: voltage signal_voltage=0 -> no switch > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > mmc: multi-blk blkcnt=1956 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=1000 blks=1956 blksz=512 mode=32 dma=0 > > <debug_uart> > > > U-Boot 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > > DRAM: 4 GiB > Core: 338 devices, 22 uclasses, devicetree: separate > MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > mmc@d4280000: 1, mmc@d4281000: 0 > Loading Environment from nowhere... OK > In: serial@d4017000 > Out: serial@d4017000 > Err: serial@d4017000 > Net: No ethernet found. > => > > With the voltage corrected, a single 1956 block PIO CMD18 loads > the whole FIT,so the controller is fine with the FIFO back pressure, > the slow SPL drain was a symptom, not the cause :-). > > Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > "sdhci: voltage signal_voltage=0 -> no switch". > Since mmc_set_signWith the voltage corrected, a single 1956 block PIO > CMD18 loads > the whole FIT,so the controller is fine with the FIFO back pressure, > the slow SPL drain was a symptom, not the cause :-). > > Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > "sdhci: voltage signal_voltage=0 -> no switch". > Since mmc_set_signal_voltage() is a stub in SPL, so mmc->signal_voltage > stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > "no switch required" path, and aldo1 stayed at the initial 1800000 that > set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > what hid it. > > On the pinctrl side I had already run the SPL with standalone > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > mmc1_uhs_cfg plus their pin groups. I confirmed that > pinctrl_select_state() return successfully. The multi-block read still > failed the same way with the rail at 1.8V. > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > in pmic_init() may need to be modified. > > Thanks for your suggestions and guidance. > > Best regards, > Zixianal_voltage() is a stub in SPL, so mmc->signal_voltage > stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > "no switch required" path, and aldo1 stayed at the initial 1800000 that > set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > what hid it. > > On the pinctrl side I had already run the SPL with standalone > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > mmc1_uhs_cfg plus their pin groups. I confirmed that > pinctrl_select_state() return successfully. The multi-block read still > failed the same way with the rail at 1.8V. > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > in pmic_init() may need to be modified. > > Thanks for your suggestions and guidance. > > Hi Zixian, Thank you for the quick testing and for posting detailed results. Your patience with the suggested tests helped us reach the root cause within two days. With CONFIG_SPL_MMC_IO_VOLTAGE enabled, aldo1 is changed from its initial 1.8 V to 3.3 V and both the 32-block and 1956-block reads succeed. I am still unsure why set_vdd_mmc() initializes this rail to 1.8 V. Since we do not know the original hardware requirement, any change to that default should be reviewed by the code owner. I suggest enabling both CONFIG_SPL_MMC_IO_VOLTAGE and CONFIG_SPL_PINCTRL. The former fixes the voltage issue, while the latter ensures SPL applies the defined MMC pad configuration instead of relying on the Boot ROM state. Dave, I hope you are aligned with the changes discussed and tested. Could you please post a new version incorporating them? Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> Regards, Tanmay ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-12 14:00 ` Kathpalia, Tanmay @ 2026-10-12 14:30 ` Yixun Lan 2026-10-12 14:50 ` Kathpalia, Tanmay 0 siblings, 1 reply; 33+ messages in thread From: Yixun Lan @ 2026-10-12 14:30 UTC (permalink / raw) To: Kathpalia, Tanmay Cc: Zixian Zeng, Dave Klotz, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit Hi Kathpalia, Zexian, On 19:30 Mon 12 Oct , Kathpalia, Tanmay wrote: > > On 12-10-2026 18:45, Zixian Zeng wrote: > > On 2026/10/11 22:31, Kathpalia, Tanmay wrote: > >> Hi Zixian, > >> > >> Thanks for the logs. > >> > >> I hit the same pattern while testing the Cadence SD6HC driver. > >> Multi-block reads failed and single-block reads worked. On that board > >> the host and the card were in 1.8 V mode, but the I/O supply had been > >> left at 3.3 V. A short transfer got through; a longer one failed on the > >> data lines. > >> Both stages on K1 use the same PIO loop, so a FIFO that drains slower > >> than the card delivers would show up in U-Boot proper as well. Your > >> SPL/proper split fits an electrical setup difference. > >> > >> The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, > >> SD mode only): the controller detected 0 at the end-bit position of > >> read data on DAT, or of the write CRC status. That is a bad edge on > >> the data line during the transfer. > >> > >> On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot > >> dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, > >> value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, > >> called from board_init_f(), writes 1800000. The dts leaves aldo1 at > >> 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is > >> only after a UHS switch. mmc1_cfg is power-source 3300, and > >> mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. > >> > >> CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a > >> stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at > >> 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() > >> requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the > >> same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer > >> that succeeds. > >> > >> CONFIG_SPL_PINCTRL is not set either. The driver calls > >> pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that > >> function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return > >> is ignored. SPL never applies mmc1_cfg. Proper selects "default" for > >> SD_HS, which is that state. > >> > >> Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable > >> CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable > >> CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read > >> succeed, this is the F3 failure. > >> > >> Regards, > >> Tanmay > > > > Hi Tanmay, > > > > Your diagnosis was right - it is the I/O voltage. > > Enabling CONFIG_SPL_MMC_IO_VOLTAGE makes > > the multi-block read work on the Banana Pi-F3: > > > > Based on previous commit, I patched the following changes: > > > > diff --git a/configs/spacemit_k1_defconfig > > b/configs/spacemit_k1_defconfig > > index 9c15d96eae2..f5c717e5965 100644 > > --- a/configs/spacemit_k1_defconfig > > +++ b/configs/spacemit_k1_defconfig > > @@ -95,6 +95,7 @@ CONFIG_MMC=y > > CONFIG_MMC_SDHCI=y > > CONFIG_MMC_SDHCI_SPACEMIT=y > > CONFIG_MMC_IO_VOLTAGE=y > > +CONFIG_SPL_MMC_IO_VOLTAGE=y > > CONFIG_MMC_HS200_SUPPORT=y > > CONFIG_MMC_HS400_SUPPORT=y > > CONFIG_MMC_HS400_ES_SUPPORT=y > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > > index 23c655c6def..58374c482b3 100644 > > --- a/drivers/mmc/spacemit_sdhci.c > > +++ b/drivers/mmc/spacemit_sdhci.c > > @@ -251,6 +251,10 @@ static void spacemit_sdhci_set_voltage(struct > > sdhci_host *host) > > bool ok; > > int voltage_mv = to_180 ? 1800000 : 3300000; > > > > + printf("sdhci: voltage signal_voltage=%u > > vqmmc=%s -> %dmV\n", > > + mmc->signal_voltage, > > + mmc->vqmmc_supply ? > > mmc->vqmmc_supply->name : "none", > > + voltage_mv); > > if (spacemit_sdhci_set_vqmmc_voltage(mmc, > > voltage_mv)) > > return; > > if (!IS_SD(mmc)) > > @@ -274,7 +278,8 @@ static void spacemit_sdhci_set_voltage(struct > > sdhci_host *host) > > break; > > } > > default: > > - /* No signal voltage switch required */ > > + printf("sdhci: voltage signal_voltage=%u -> no > > switch\n", > > + mmc->signal_voltage); > > return; > > } > > } > > > > Booting logs as follows: > > > > U-Boot SPL 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > > Fail to detect board:-2 > > vdd_core, value:900000 > > vdd_1v8, value:1800000 > > vdd_1v8_mmc, value:1800000 > > DDR firmware: [0xc081d880]:0xf0227179, size:0x8d98 > > DDR is ready > > No SPI controller (-19) > > Trying to boot from MMC2 > > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > > max_clk=204800000 > > sdhci: voltage signal_voltage=0 -> no switch > > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > > cmd23_host=1 scr0=2358043 cmd23_card=1 > > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > > mmc: multi-blk blkcnt=1956 clk=50000000 mode=2 width=4 caps=300207ef > > cmd23_host=1 scr0=2358043 cmd23_card=1 > > sdhci: multi cmd18 arg=1000 blks=1956 blksz=512 mode=32 dma=0 > > > > <debug_uart> > > > > > > U-Boot 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > > > > DRAM: 4 GiB > > Core: 338 devices, 22 uclasses, devicetree: separate > > MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > > max_clk=204800000 > > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > > max_clk=204800000 > > mmc@d4280000: 1, mmc@d4281000: 0 > > Loading Environment from nowhere... OK > > In: serial@d4017000 > > Out: serial@d4017000 > > Err: serial@d4017000 > > Net: No ethernet found. > > => > > > > With the voltage corrected, a single 1956 block PIO CMD18 loads > > the whole FIT,so the controller is fine with the FIFO back pressure, > > the slow SPL drain was a symptom, not the cause :-). > > > > Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > > "sdhci: voltage signal_voltage=0 -> no switch". > > Since mmc_set_signWith the voltage corrected, a single 1956 block PIO > > CMD18 loads > > the whole FIT,so the controller is fine with the FIFO back pressure, > > the slow SPL drain was a symptom, not the cause :-). > > > > Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > > "sdhci: voltage signal_voltage=0 -> no switch". > > Since mmc_set_signal_voltage() is a stub in SPL, so mmc->signal_voltage > > stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > > "no switch required" path, and aldo1 stayed at the initial 1800000 that > > set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > > after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > > what hid it. > > > > On the pinctrl side I had already run the SPL with standalone > > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > > mmc1_uhs_cfg plus their pin groups. I confirmed that > > pinctrl_select_state() return successfully. The multi-block read still > > failed the same way with the rail at 1.8V. > > > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > > in pmic_init() may need to be modified. > > > > Thanks for your suggestions and guidance. > > > > Best regards, > > Zixianal_voltage() is a stub in SPL, so mmc->signal_voltage > > stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > > "no switch required" path, and aldo1 stayed at the initial 1800000 that > > set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > > after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > > what hid it. > > > > On the pinctrl side I had already run the SPL with standalone > > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > > mmc1_uhs_cfg plus their pin groups. I confirmed that > > pinctrl_select_state() return successfully. The multi-block read still > > failed the same way with the rail at 1.8V. > > > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > > in pmic_init() may need to be modified. > > > > Thanks for your suggestions and guidance. > > > > > > Hi Zixian, > > Thank you for the quick testing and for posting detailed results. Your > patience with the suggested tests helped us reach the root cause > within two days. > > With CONFIG_SPL_MMC_IO_VOLTAGE enabled, aldo1 is changed from its > initial 1.8 V to 3.3 V and both the 32-block and 1956-block reads > succeed. > > I am still unsure why set_vdd_mmc() initializes this rail to 1.8 V. I'm also looking into this.. It's definitely wrong here, and should be fixed in my opinion, refer to SD spec, the initial IO should be 3.3v, and later may change to 1.8v according to OCR report, the BROM code will set IO to 3.3v by default since cold boot, and I've done a test on this, drop set_vdd_mmc() & without CONFIG_SPL_MMC_IO_VOLTAGE enabled, the multi block read still works fine on SPL stage Also with Zexian's above test, it also prove that, enabling CONFIG_SPL_MMC_IO_VOLTAGE will lead the mmc core calling set_voltage() which will set IO to 3.3v, which also fix the problem > Since we do not know the original hardware requirement, any change to > that default should be reviewed by the code owner. > > I suggest enabling both CONFIG_SPL_MMC_IO_VOLTAGE and > CONFIG_SPL_PINCTRL. The former fixes the voltage issue, while the > latter ensures SPL applies the defined MMC pad configuration instead > of relying on the Boot ROM state. > I agree, it's safe to do this > Dave, I hope you are aligned with the changes discussed and tested. > Could you please post a new version incorporating them? > > Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> > > Regards, > Tanmay > -- Yixun Lan (dlan) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-12 14:30 ` Yixun Lan @ 2026-10-12 14:50 ` Kathpalia, Tanmay 2026-10-12 15:22 ` Yixun Lan 0 siblings, 1 reply; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-12 14:50 UTC (permalink / raw) To: Yixun Lan Cc: Zixian Zeng, Dave Klotz, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit Hi Yixun, On 12-10-2026 20:00, Yixun Lan wrote: > Hi Kathpalia, Zexian, > > On 19:30 Mon 12 Oct , Kathpalia, Tanmay wrote: >> On 12-10-2026 18:45, Zixian Zeng wrote: >>> On 2026/10/11 22:31, Kathpalia, Tanmay wrote: >>>> Hi Zixian, >>>> >>>> Thanks for the logs. >>>> >>>> I hit the same pattern while testing the Cadence SD6HC driver. >>>> Multi-block reads failed and single-block reads worked. On that board >>>> the host and the card were in 1.8 V mode, but the I/O supply had been >>>> left at 3.3 V. A short transfer got through; a longer one failed on the >>>> data lines. >>>> Both stages on K1 use the same PIO loop, so a FIFO that drains slower >>>> than the card delivers would show up in U-Boot proper as well. Your >>>> SPL/proper split fits an electrical setup difference. >>>> >>>> The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, >>>> SD mode only): the controller detected 0 at the end-bit position of >>>> read data on DAT, or of the write CRC status. That is a bad edge on >>>> the data line during the transfer. >>>> >>>> On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot >>>> dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, >>>> value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, >>>> called from board_init_f(), writes 1800000. The dts leaves aldo1 at >>>> 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is >>>> only after a UHS switch. mmc1_cfg is power-source 3300, and >>>> mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. >>>> >>>> CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a >>>> stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at >>>> 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() >>>> requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the >>>> same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer >>>> that succeeds. >>>> >>>> CONFIG_SPL_PINCTRL is not set either. The driver calls >>>> pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that >>>> function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return >>>> is ignored. SPL never applies mmc1_cfg. Proper selects "default" for >>>> SD_HS, which is that state. >>>> >>>> Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable >>>> CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable >>>> CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read >>>> succeed, this is the F3 failure. >>>> >>>> Regards, >>>> Tanmay >>> Hi Tanmay, >>> >>> Your diagnosis was right - it is the I/O voltage. >>> Enabling CONFIG_SPL_MMC_IO_VOLTAGE makes >>> the multi-block read work on the Banana Pi-F3: >>> >>> Based on previous commit, I patched the following changes: >>> >>> diff --git a/configs/spacemit_k1_defconfig >>> b/configs/spacemit_k1_defconfig >>> index 9c15d96eae2..f5c717e5965 100644 >>> --- a/configs/spacemit_k1_defconfig >>> +++ b/configs/spacemit_k1_defconfig >>> @@ -95,6 +95,7 @@ CONFIG_MMC=y >>> CONFIG_MMC_SDHCI=y >>> CONFIG_MMC_SDHCI_SPACEMIT=y >>> CONFIG_MMC_IO_VOLTAGE=y >>> +CONFIG_SPL_MMC_IO_VOLTAGE=y >>> CONFIG_MMC_HS200_SUPPORT=y >>> CONFIG_MMC_HS400_SUPPORT=y >>> CONFIG_MMC_HS400_ES_SUPPORT=y >>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c >>> index 23c655c6def..58374c482b3 100644 >>> --- a/drivers/mmc/spacemit_sdhci.c >>> +++ b/drivers/mmc/spacemit_sdhci.c >>> @@ -251,6 +251,10 @@ static void spacemit_sdhci_set_voltage(struct >>> sdhci_host *host) >>> bool ok; >>> int voltage_mv = to_180 ? 1800000 : 3300000; >>> >>> + printf("sdhci: voltage signal_voltage=%u >>> vqmmc=%s -> %dmV\n", >>> + mmc->signal_voltage, >>> + mmc->vqmmc_supply ? >>> mmc->vqmmc_supply->name : "none", >>> + voltage_mv); >>> if (spacemit_sdhci_set_vqmmc_voltage(mmc, >>> voltage_mv)) >>> return; >>> if (!IS_SD(mmc)) >>> @@ -274,7 +278,8 @@ static void spacemit_sdhci_set_voltage(struct >>> sdhci_host *host) >>> break; >>> } >>> default: >>> - /* No signal voltage switch required */ >>> + printf("sdhci: voltage signal_voltage=%u -> no >>> switch\n", >>> + mmc->signal_voltage); >>> return; >>> } >>> } >>> >>> Booting logs as follows: >>> >>> U-Boot SPL 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) >>> Fail to detect board:-2 >>> vdd_core, value:900000 >>> vdd_1v8, value:1800000 >>> vdd_1v8_mmc, value:1800000 >>> DDR firmware: [0xc081d880]:0xf0227179, size:0x8d98 >>> DDR is ready >>> No SPI controller (-19) >>> Trying to boot from MMC2 >>> sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 >>> max_clk=204800000 >>> sdhci: voltage signal_voltage=0 -> no switch >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV >>> mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef >>> cmd23_host=1 scr0=2358043 cmd23_card=1 >>> sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 >>> mmc: multi-blk blkcnt=1956 clk=50000000 mode=2 width=4 caps=300207ef >>> cmd23_host=1 scr0=2358043 cmd23_card=1 >>> sdhci: multi cmd18 arg=1000 blks=1956 blksz=512 mode=32 dma=0 >>> >>> <debug_uart> >>> >>> >>> U-Boot 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) >>> >>> DRAM: 4 GiB >>> Core: 338 devices, 22 uclasses, devicetree: separate >>> MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 >>> max_clk=204800000 >>> sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 >>> max_clk=204800000 >>> mmc@d4280000: 1, mmc@d4281000: 0 >>> Loading Environment from nowhere... OK >>> In: serial@d4017000 >>> Out: serial@d4017000 >>> Err: serial@d4017000 >>> Net: No ethernet found. >>> => >>> >>> With the voltage corrected, a single 1956 block PIO CMD18 loads >>> the whole FIT,so the controller is fine with the FIFO back pressure, >>> the slow SPL drain was a symptom, not the cause :-). >>> >>> Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed >>> "sdhci: voltage signal_voltage=0 -> no switch". >>> Since mmc_set_signWith the voltage corrected, a single 1956 block PIO >>> CMD18 loads >>> the whole FIT,so the controller is fine with the FIFO back pressure, >>> the slow SPL drain was a symptom, not the cause :-). >>> >>> Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed >>> "sdhci: voltage signal_voltage=0 -> no switch". >>> Since mmc_set_signal_voltage() is a stub in SPL, so mmc->signal_voltage >>> stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the >>> "no switch required" path, and aldo1 stayed at the initial 1800000 that >>> set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed >>> after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is >>> what hid it. >>> >>> On the pinctrl side I had already run the SPL with standalone >>> CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and >>> mmc1_uhs_cfg plus their pin groups. I confirmed that >>> pinctrl_select_state() return successfully. The multi-block read still >>> failed the same way with the rail at 1.8V. >>> >>> Therefore, I suspect that configuring the MMC signal voltage to 1.8V >>> in pmic_init() may need to be modified. >>> >>> Thanks for your suggestions and guidance. >>> >>> Best regards, >>> Zixianal_voltage() is a stub in SPL, so mmc->signal_voltage >>> stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the >>> "no switch required" path, and aldo1 stayed at the initial 1800000 that >>> set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed >>> after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is >>> what hid it. >>> >>> On the pinctrl side I had already run the SPL with standalone >>> CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and >>> mmc1_uhs_cfg plus their pin groups. I confirmed that >>> pinctrl_select_state() return successfully. The multi-block read still >>> failed the same way with the rail at 1.8V. >>> >>> Therefore, I suspect that configuring the MMC signal voltage to 1.8V >>> in pmic_init() may need to be modified. >>> >>> Thanks for your suggestions and guidance. >>> >>> >> Hi Zixian, >> >> Thank you for the quick testing and for posting detailed results. Your >> patience with the suggested tests helped us reach the root cause >> within two days. >> >> With CONFIG_SPL_MMC_IO_VOLTAGE enabled, aldo1 is changed from its >> initial 1.8 V to 3.3 V and both the 32-block and 1956-block reads >> succeed. >> >> I am still unsure why set_vdd_mmc() initializes this rail to 1.8 V. > I'm also looking into this.. > > It's definitely wrong here, and should be fixed in my opinion, refer > to SD spec, the initial IO should be 3.3v, and later may change to 1.8v > according to OCR report, the BROM code will set IO to 3.3v by default Agreed. The host and I/O signaling rail should initially be at 3.3 V, and the card powers up using 3.3 V signaling. It may switch to 1.8 V later only when entering a supported UHS timing mode. > since cold boot, and I've done a test on this, drop set_vdd_mmc() & without > CONFIG_SPL_MMC_IO_VOLTAGE enabled, the multi block read still works fine > on SPL stage Thanks for testing the multi-block operation after dropping set_vdd_mmc() and without CONFIG_SPL_MMC_IO_VOLTAGE. Since the BootROM leaves the I/O rail at 3.3 V after a cold boot, the successful result is expected and confirms that set_vdd_mmc() incorrectly changes it to 1.8 V. > > Also with Zexian's above test, it also prove that, enabling CONFIG_SPL_MMC_IO_VOLTAGE > will lead the mmc core calling set_voltage() which will set IO to 3.3v, which also > fix the problem I think both changes should be made: 1. Initialize the MMC I/O rail to 3.3 V instead of 1.8 V. 2. Enable CONFIG_SPL_MMC_IO_VOLTAGE so the MMC core can manage any subsequent signal-voltage transitions correctly. >> Since we do not know the original hardware requirement, any change to >> that default should be reviewed by the code owner. >> >> I suggest enabling both CONFIG_SPL_MMC_IO_VOLTAGE and >> CONFIG_SPL_PINCTRL. The former fixes the voltage issue, while the >> latter ensures SPL applies the defined MMC pad configuration instead >> of relying on the Boot ROM state. >> > I agree, it's safe to do this > >> Dave, I hope you are aligned with the changes discussed and tested. >> Could you please post a new version incorporating them? >> >> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> >> >> Regards, >> Tanmay >> ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-12 14:50 ` Kathpalia, Tanmay @ 2026-10-12 15:22 ` Yixun Lan 0 siblings, 0 replies; 33+ messages in thread From: Yixun Lan @ 2026-10-12 15:22 UTC (permalink / raw) To: Kathpalia, Tanmay Cc: Zixian Zeng, Dave Klotz, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit Hi Kathpalia, On 20:20 Mon 12 Oct , Kathpalia, Tanmay wrote: > Hi Yixun, > > On 12-10-2026 20:00, Yixun Lan wrote: > > Hi Kathpalia, Zexian, > > > > On 19:30 Mon 12 Oct , Kathpalia, Tanmay wrote: > >> On 12-10-2026 18:45, Zixian Zeng wrote: > >>> On 2026/10/11 22:31, Kathpalia, Tanmay wrote: > >>>> Hi Zixian, > >>>> > >>>> Thanks for the logs. > >>>> > >>>> I hit the same pattern while testing the Cadence SD6HC driver. > >>>> Multi-block reads failed and single-block reads worked. On that board > >>>> the host and the card were in 1.8 V mode, but the I/O supply had been > >>>> left at 3.3 V. A short transfer got through; a longer one failed on the > >>>> data lines. > >>>> Both stages on K1 use the same PIO loop, so a FIFO that drains slower > >>>> than the card delivers would show up in U-Boot proper as well. Your > >>>> SPL/proper split fits an electrical setup difference. > >>>> > >>>> The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, > >>>> SD mode only): the controller detected 0 at the end-bit position of > >>>> read data on DAT, or of the write CRC status. That is a bad edge on > >>>> the data line during the transfer. > >>>> > >>>> On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot > >>>> dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, > >>>> value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, > >>>> called from board_init_f(), writes 1800000. The dts leaves aldo1 at > >>>> 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is > >>>> only after a UHS switch. mmc1_cfg is power-source 3300, and > >>>> mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. > >>>> > >>>> CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a > >>>> stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at > >>>> 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() > >>>> requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the > >>>> same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer > >>>> that succeeds. > >>>> > >>>> CONFIG_SPL_PINCTRL is not set either. The driver calls > >>>> pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that > >>>> function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return > >>>> is ignored. SPL never applies mmc1_cfg. Proper selects "default" for > >>>> SD_HS, which is that state. > >>>> > >>>> Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable > >>>> CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable > >>>> CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read > >>>> succeed, this is the F3 failure. > >>>> > >>>> Regards, > >>>> Tanmay > >>> Hi Tanmay, > >>> > >>> Your diagnosis was right - it is the I/O voltage. > >>> Enabling CONFIG_SPL_MMC_IO_VOLTAGE makes > >>> the multi-block read work on the Banana Pi-F3: > >>> > >>> Based on previous commit, I patched the following changes: > >>> > >>> diff --git a/configs/spacemit_k1_defconfig > >>> b/configs/spacemit_k1_defconfig > >>> index 9c15d96eae2..f5c717e5965 100644 > >>> --- a/configs/spacemit_k1_defconfig > >>> +++ b/configs/spacemit_k1_defconfig > >>> @@ -95,6 +95,7 @@ CONFIG_MMC=y > >>> CONFIG_MMC_SDHCI=y > >>> CONFIG_MMC_SDHCI_SPACEMIT=y > >>> CONFIG_MMC_IO_VOLTAGE=y > >>> +CONFIG_SPL_MMC_IO_VOLTAGE=y > >>> CONFIG_MMC_HS200_SUPPORT=y > >>> CONFIG_MMC_HS400_SUPPORT=y > >>> CONFIG_MMC_HS400_ES_SUPPORT=y > >>> diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > >>> index 23c655c6def..58374c482b3 100644 > >>> --- a/drivers/mmc/spacemit_sdhci.c > >>> +++ b/drivers/mmc/spacemit_sdhci.c > >>> @@ -251,6 +251,10 @@ static void spacemit_sdhci_set_voltage(struct > >>> sdhci_host *host) > >>> bool ok; > >>> int voltage_mv = to_180 ? 1800000 : 3300000; > >>> > >>> + printf("sdhci: voltage signal_voltage=%u > >>> vqmmc=%s -> %dmV\n", > >>> + mmc->signal_voltage, > >>> + mmc->vqmmc_supply ? > >>> mmc->vqmmc_supply->name : "none", > >>> + voltage_mv); > >>> if (spacemit_sdhci_set_vqmmc_voltage(mmc, > >>> voltage_mv)) > >>> return; > >>> if (!IS_SD(mmc)) > >>> @@ -274,7 +278,8 @@ static void spacemit_sdhci_set_voltage(struct > >>> sdhci_host *host) > >>> break; > >>> } > >>> default: > >>> - /* No signal voltage switch required */ > >>> + printf("sdhci: voltage signal_voltage=%u -> no > >>> switch\n", > >>> + mmc->signal_voltage); > >>> return; > >>> } > >>> } > >>> > >>> Booting logs as follows: > >>> > >>> U-Boot SPL 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > >>> Fail to detect board:-2 > >>> vdd_core, value:900000 > >>> vdd_1v8, value:1800000 > >>> vdd_1v8_mmc, value:1800000 > >>> DDR firmware: [0xc081d880]:0xf0227179, size:0x8d98 > >>> DDR is ready > >>> No SPI controller (-19) > >>> Trying to boot from MMC2 > >>> sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > >>> max_clk=204800000 > >>> sdhci: voltage signal_voltage=0 -> no switch > >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > >>> sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > >>> mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > >>> cmd23_host=1 scr0=2358043 cmd23_card=1 > >>> sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > >>> mmc: multi-blk blkcnt=1956 clk=50000000 mode=2 width=4 caps=300207ef > >>> cmd23_host=1 scr0=2358043 cmd23_card=1 > >>> sdhci: multi cmd18 arg=1000 blks=1956 blksz=512 mode=32 dma=0 > >>> > >>> <debug_uart> > >>> > >>> > >>> U-Boot 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > >>> > >>> DRAM: 4 GiB > >>> Core: 338 devices, 22 uclasses, devicetree: separate > >>> MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > >>> max_clk=204800000 > >>> sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > >>> max_clk=204800000 > >>> mmc@d4280000: 1, mmc@d4281000: 0 > >>> Loading Environment from nowhere... OK > >>> In: serial@d4017000 > >>> Out: serial@d4017000 > >>> Err: serial@d4017000 > >>> Net: No ethernet found. > >>> => > >>> > >>> With the voltage corrected, a single 1956 block PIO CMD18 loads > >>> the whole FIT,so the controller is fine with the FIFO back pressure, > >>> the slow SPL drain was a symptom, not the cause :-). > >>> > >>> Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > >>> "sdhci: voltage signal_voltage=0 -> no switch". > >>> Since mmc_set_signWith the voltage corrected, a single 1956 block PIO > >>> CMD18 loads > >>> the whole FIT,so the controller is fine with the FIFO back pressure, > >>> the slow SPL drain was a symptom, not the cause :-). > >>> > >>> Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > >>> "sdhci: voltage signal_voltage=0 -> no switch". > >>> Since mmc_set_signal_voltage() is a stub in SPL, so mmc->signal_voltage > >>> stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > >>> "no switch required" path, and aldo1 stayed at the initial 1800000 that > >>> set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > >>> after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > >>> what hid it. > >>> > >>> On the pinctrl side I had already run the SPL with standalone > >>> CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > >>> mmc1_uhs_cfg plus their pin groups. I confirmed that > >>> pinctrl_select_state() return successfully. The multi-block read still > >>> failed the same way with the rail at 1.8V. > >>> > >>> Therefore, I suspect that configuring the MMC signal voltage to 1.8V > >>> in pmic_init() may need to be modified. > >>> > >>> Thanks for your suggestions and guidance. > >>> > >>> Best regards, > >>> Zixianal_voltage() is a stub in SPL, so mmc->signal_voltage > >>> stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > >>> "no switch required" path, and aldo1 stayed at the initial 1800000 that > >>> set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > >>> after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > >>> what hid it. > >>> > >>> On the pinctrl side I had already run the SPL with standalone > >>> CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > >>> mmc1_uhs_cfg plus their pin groups. I confirmed that > >>> pinctrl_select_state() return successfully. The multi-block read still > >>> failed the same way with the rail at 1.8V. > >>> > >>> Therefore, I suspect that configuring the MMC signal voltage to 1.8V > >>> in pmic_init() may need to be modified. > >>> > >>> Thanks for your suggestions and guidance. > >>> > >>> > >> Hi Zixian, > >> > >> Thank you for the quick testing and for posting detailed results. Your > >> patience with the suggested tests helped us reach the root cause > >> within two days. > >> > >> With CONFIG_SPL_MMC_IO_VOLTAGE enabled, aldo1 is changed from its > >> initial 1.8 V to 3.3 V and both the 32-block and 1956-block reads > >> succeed. > >> > >> I am still unsure why set_vdd_mmc() initializes this rail to 1.8 V. > > I'm also looking into this.. > > > > It's definitely wrong here, and should be fixed in my opinion, refer > > to SD spec, the initial IO should be 3.3v, and later may change to 1.8v > > according to OCR report, the BROM code will set IO to 3.3v by default > > Agreed. The host and I/O signaling rail should initially be at 3.3 V, > and the card powers up using 3.3 V signaling. It may switch to 1.8 V > later only when entering a supported UHS timing mode. > Currently, the spacemit_k1_defconfig does not enable UHS config, so no 1.8v switching will happen, but I think that's another problem which should investigate later.. > > since cold boot, and I've done a test on this, drop set_vdd_mmc() & without > > CONFIG_SPL_MMC_IO_VOLTAGE enabled, the multi block read still works fine > > on SPL stage > > Thanks for testing the multi-block operation after dropping > set_vdd_mmc() and without CONFIG_SPL_MMC_IO_VOLTAGE. Since the BootROM > leaves the I/O rail at 3.3 V after a cold boot, the successful result is > expected and confirms that set_vdd_mmc() incorrectly changes it to > 1.8 V. > > > > > Also with Zexian's above test, it also prove that, enabling CONFIG_SPL_MMC_IO_VOLTAGE > > will lead the mmc core calling set_voltage() which will set IO to 3.3v, which also > > fix the problem > > I think both changes should be made: > > 1. Initialize the MMC I/O rail to 3.3 V instead of 1.8 V. For how to achieve on this, I'd suggest drop set_vdd_mmc() from spl.c and the leave spacemit_sdhci.c to config the I/O rail accordingly > 2. Enable CONFIG_SPL_MMC_IO_VOLTAGE so the MMC core can manage any > subsequent signal-voltage transitions correctly. > I agree on this > >> Since we do not know the original hardware requirement, any change to > >> that default should be reviewed by the code owner. > >> > >> I suggest enabling both CONFIG_SPL_MMC_IO_VOLTAGE and > >> CONFIG_SPL_PINCTRL. The former fixes the voltage issue, while the > >> latter ensures SPL applies the defined MMC pad configuration instead > >> of relying on the Boot ROM state. > >> > > I agree, it's safe to do this > > > >> Dave, I hope you are aligned with the changes discussed and tested. > >> Could you please post a new version incorporating them? > >> > >> Signed-off-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> > >> > >> Regards, > >> Tanmay > >> -- Yixun Lan (dlan) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-12 13:15 ` Zixian Zeng 2026-10-12 14:00 ` Kathpalia, Tanmay @ 2026-10-12 16:07 ` Anand Moon 2026-10-13 0:15 ` Yixun Lan 1 sibling, 1 reply; 33+ messages in thread From: Anand Moon @ 2026-10-12 16:07 UTC (permalink / raw) To: Zixian Zeng Cc: Kathpalia, Tanmay, Dave Klotz, Yixun Lan, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit Hi Zixian, Tanmay, On Mon, 12 Oct 2026 at 18:49, Zixian Zeng <sycamoremoon376@gmail.com> wrote: > > On 2026/10/11 22:31, Kathpalia, Tanmay wrote: > > Hi Zixian, > > > > Thanks for the logs. > > > > I hit the same pattern while testing the Cadence SD6HC driver. > > Multi-block reads failed and single-block reads worked. On that board > > the host and the card were in 1.8 V mode, but the I/O supply had been > > left at 3.3 V. A short transfer got through; a longer one failed on the > > data lines. > > Both stages on K1 use the same PIO loop, so a FIFO that drains slower > > than the card delivers would show up in U-Boot proper as well. Your > > SPL/proper split fits an electrical setup difference. > > > > The SPL failure is irq=408020. Bit 22 is the Data End Bit Error (EDEB, > > SD mode only): the controller detected 0 at the end-bit position of > > read data on DAT, or of the write CRC status. That is a bad edge on > > the data line during the transfer. > > > > On the Banana Pi F3, aldo1 is vqmmc-supply of &sdhci0. The U-Boot > > dtsi names it vdd_1v8_mmc, and the SPL prints "vdd_1v8_mmc, > > value:1800000" before MMC2. set_vdd_mmc() in board/spacemit/k1/spl.c, > > called from board_init_f(), writes 1800000. The dts leaves aldo1 at > > 0.5 V to 3.4 V. SD High Speed (mode=2) uses 3.3 V signaling; 1.8 V is > > only after a UHS switch. mmc1_cfg is power-source 3300, and > > mmc1_uhs_cfg is the 1.8 V state. For this mode the rail should be 3.3 V. > > > > CONFIG_SPL_MMC_IO_VOLTAGE is not set, so mmc_set_signal_voltage() is a > > stub and signal_voltage stays MMC_SIGNAL_VOLTAGE_000. aldo1 stays at > > 1.8 V. U-Boot proper has CONFIG_MMC_IO_VOLTAGE. mmc_set_initial_state() > > requests MMC_SIGNAL_VOLTAGE_330, so the driver writes 3300000 to the > > same vqmmc-supply and clears SDHCI_CTRL_VDD_180 before the transfer > > that succeeds. > > > > CONFIG_SPL_PINCTRL is not set either. The driver calls > > pinctrl_select_state() under IS_ENABLED(CONFIG_PINCTRL), but that > > function is a stub unless CONFIG_IS_ENABLED(PINCTRL), and the return > > is ignored. SPL never applies mmc1_cfg. Proper selects "default" for > > SD_HS, which is that state. > > > > Keeping the multi-block path, set_vdd_mmc() to 3300000, or enable > > CONFIG_SPL_MMC_IO_VOLTAGE. If the 32-block CMD18 still fails, enable > > CONFIG_SPL_PINCTRL so mmc1_cfg is applied. If either makes the read > > succeed, this is the F3 failure. > > > > Regards, > > Tanmay > > Hi Tanmay, > > Your diagnosis was right - it is the I/O voltage. > Enabling CONFIG_SPL_MMC_IO_VOLTAGE makes > the multi-block read work on the Banana Pi-F3: > > Based on previous commit, I patched the following changes: > > diff --git a/configs/spacemit_k1_defconfig b/configs/spacemit_k1_defconfig > index 9c15d96eae2..f5c717e5965 100644 > --- a/configs/spacemit_k1_defconfig > +++ b/configs/spacemit_k1_defconfig > @@ -95,6 +95,7 @@ CONFIG_MMC=y > CONFIG_MMC_SDHCI=y > CONFIG_MMC_SDHCI_SPACEMIT=y > CONFIG_MMC_IO_VOLTAGE=y > +CONFIG_SPL_MMC_IO_VOLTAGE=y > CONFIG_MMC_HS200_SUPPORT=y > CONFIG_MMC_HS400_SUPPORT=y > CONFIG_MMC_HS400_ES_SUPPORT=y > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index 23c655c6def..58374c482b3 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -251,6 +251,10 @@ static void spacemit_sdhci_set_voltage(struct > sdhci_host *host) > bool ok; > int voltage_mv = to_180 ? 1800000 : 3300000; > > + printf("sdhci: voltage signal_voltage=%u > vqmmc=%s -> %dmV\n", > + mmc->signal_voltage, > + mmc->vqmmc_supply ? > mmc->vqmmc_supply->name : "none", > + voltage_mv); > if (spacemit_sdhci_set_vqmmc_voltage(mmc, > voltage_mv)) > return; > if (!IS_SD(mmc)) > @@ -274,7 +278,8 @@ static void spacemit_sdhci_set_voltage(struct > sdhci_host *host) > break; > } > default: > - /* No signal voltage switch required */ > + printf("sdhci: voltage signal_voltage=%u -> no > switch\n", > + mmc->signal_voltage); > return; > } > } > > Booting logs as follows: > > U-Boot SPL 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > Fail to detect board:-2 > vdd_core, value:900000 > vdd_1v8, value:1800000 > vdd_1v8_mmc, value:1800000 > DDR firmware: [0xc081d880]:0xf0227179, size:0x8d98 > DDR is ready > No SPI controller (-19) > Trying to boot from MMC2 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > sdhci: voltage signal_voltage=0 -> no switch > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > sdhci: voltage signal_voltage=4 vqmmc=aldo1 -> 3300000mV > mmc: multi-blk blkcnt=32 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=2 blks=32 blksz=512 mode=32 dma=0 > mmc: multi-blk blkcnt=1956 clk=50000000 mode=2 width=4 caps=300207ef > cmd23_host=1 scr0=2358043 cmd23_card=1 > sdhci: multi cmd18 arg=1000 blks=1956 blksz=512 mode=32 dma=0 > > <debug_uart> > > > U-Boot 2026.10-rc5-00643-g6a99fe92389a (Oct 12 2026 - 21:13:00 +0800) > > DRAM: 4 GiB > Core: 338 devices, 22 uclasses, devicetree: separate > MMC: sdhci: mmc@d4281000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > sdhci: mmc@d4280000 path=PIO flags=0 caps_sdma=1 caps_adma2=1 > max_clk=204800000 > mmc@d4280000: 1, mmc@d4281000: 0 > Loading Environment from nowhere... OK > In: serial@d4017000 > Out: serial@d4017000 > Err: serial@d4017000 > Net: No ethernet found. > => > > With the voltage corrected, a single 1956 block PIO CMD18 loads > the whole FIT,so the controller is fine with the FIFO back pressure, > the slow SPL drain was a symptom, not the cause :-). > > Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > "sdhci: voltage signal_voltage=0 -> no switch". > Since mmc_set_signWith the voltage corrected, a single 1956 block PIO > CMD18 loads > the whole FIT,so the controller is fine with the FIFO back pressure, > the slow SPL drain was a symptom, not the cause :-). > > Without the CONFIG_SPL_MMC_IO_VOLTAGE=y change the same driver printed > "sdhci: voltage signal_voltage=0 -> no switch". > Since mmc_set_signal_voltage() is a stub in SPL, so mmc->signal_voltage > stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > "no switch required" path, and aldo1 stayed at the initial 1800000 that > set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > what hid it. > > On the pinctrl side I had already run the SPL with standalone > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > mmc1_uhs_cfg plus their pin groups. I confirmed that > pinctrl_select_state() return successfully. The multi-block read still > failed the same way with the rail at 1.8V. > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > in pmic_init() may need to be modified. > > Thanks for your suggestions and guidance. > > Best regards, > Zixianal_voltage() is a stub in SPL, so mmc->signal_voltage > stayed MMC_SIGNAL_VOLTAGE_000, spacemit_sdhci_set_voltage() took the > "no switch required" path, and aldo1 stayed at the initial 1800000 that > set_vdd_mmc() writes in pmic_init(). The 32 block CMD18 then failed > after ~20 of 32 blocks. Single block reads passed at 1.8 V, which is > what hid it. > > On the pinctrl side I had already run the SPL with standalone > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > mmc1_uhs_cfg plus their pin groups. I confirmed that > pinctrl_select_state() return successfully. The multi-block read still > failed the same way with the rail at 1.8V. > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > in pmic_init() may need to be modified. > > Thanks for your suggestions and guidance. > I have also made some changes related to SPL GPIO and pinctrl support. On the Banana Pi BPI-F3, the MMC controller uses the following regulator references, which are not currently configured in `k1-musepi-pro-u-boot.dtsi`: vmmc-supply = <&buck4>; vqmmc-supply = <&aldo1>; To address this, I updated `k1-bananapi-f3-u-boot.dtsi` to include the required regulator configuration and make it available during SPL initialization. Could you review these changes and assess whether they can be integrated into the mainline U-Boot code? I would also appreciate feedback on any changes needed to make the implementation suitable for upstream submission. > Best regards, > Zixian > [1] https://gist.github.com/moonlinux/2ae03be59f263b0797acb138bed226b5 Thanks -Anand ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-12 16:07 ` Anand Moon @ 2026-10-13 0:15 ` Yixun Lan 2026-10-13 3:44 ` Anand Moon 0 siblings, 1 reply; 33+ messages in thread From: Yixun Lan @ 2026-10-13 0:15 UTC (permalink / raw) To: Anand Moon Cc: Zixian Zeng, Kathpalia, Tanmay, Dave Klotz, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit Hi Anand Moon, On 21:37 Mon 12 Oct , Anand Moon wrote: > Hi Zixian, Tanmay, > > On Mon, 12 Oct 2026 at 18:49, Zixian Zeng <sycamoremoon376@gmail.com> wrote: > > ... > > On the pinctrl side I had already run the SPL with standalone > > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > > mmc1_uhs_cfg plus their pin groups. I confirmed that > > pinctrl_select_state() return successfully. The multi-block read still > > failed the same way with the rail at 1.8V. > > > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > > in pmic_init() may need to be modified. > > > > Thanks for your suggestions and guidance. > > > I have also made some changes related to SPL GPIO and pinctrl support. > On the Banana Pi BPI-F3, the MMC controller uses the following > regulator references, > which are not currently configured in `k1-musepi-pro-u-boot.dtsi`: > vmmc-supply = <&buck4>; > vqmmc-supply = <&aldo1>; > > To address this, I updated `k1-bananapi-f3-u-boot.dtsi` to include the > required regulator > configuration and make it available during SPL initialization. > > Could you review these changes and assess whether they can be integrated > into the mainline U-Boot code? I would also appreciate feedback on any > changes needed > to make the implementation suitable for upstream submission. Hey, I'm confused, are you trying to prepare a patch here? I thought it's Dave Klotz who would do this, let's not hijack this thread but coordinate together, and please be patient, give Dave some time to respond.. I think what Zexian done here is trying to investigate and test the patches.. > [1] https://gist.github.com/moonlinux/2ae03be59f263b0797acb138bed226b5 > No, It's not a proper way for people to review and comment.. -- Yixun Lan (dlan) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time 2026-10-13 0:15 ` Yixun Lan @ 2026-10-13 3:44 ` Anand Moon 0 siblings, 0 replies; 33+ messages in thread From: Anand Moon @ 2026-10-13 3:44 UTC (permalink / raw) To: Yixun Lan Cc: Zixian Zeng, Kathpalia, Tanmay, Dave Klotz, Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini, u-boot-spacemit Hi Yixun, On Tue, 13 Oct 2026 at 05:45, Yixun Lan <dlan@kernel.org> wrote: > > Hi Anand Moon, > > On 21:37 Mon 12 Oct , Anand Moon wrote: > > Hi Zixian, Tanmay, > > > > On Mon, 12 Oct 2026 at 18:49, Zixian Zeng <sycamoremoon376@gmail.com> wrote: > > > > ... > > > On the pinctrl side I had already run the SPL with standalone > > > CONFIG_SPL_PINCTRL=y, with bootph-pre-ram on &pinctrl, mmc1_cfg and > > > mmc1_uhs_cfg plus their pin groups. I confirmed that > > > pinctrl_select_state() return successfully. The multi-block read still > > > failed the same way with the rail at 1.8V. > > > > > > Therefore, I suspect that configuring the MMC signal voltage to 1.8V > > > in pmic_init() may need to be modified. > > > > > > Thanks for your suggestions and guidance. > > > > > I have also made some changes related to SPL GPIO and pinctrl support. > > On the Banana Pi BPI-F3, the MMC controller uses the following > > regulator references, > > which are not currently configured in `k1-musepi-pro-u-boot.dtsi`: > > vmmc-supply = <&buck4>; > > vqmmc-supply = <&aldo1>; > > > > To address this, I updated `k1-bananapi-f3-u-boot.dtsi` to include the > > required regulator > > configuration and make it available during SPL initialization. > > > > Could you review these changes and assess whether they can be integrated > > into the mainline U-Boot code? I would also appreciate feedback on any > > changes needed > > to make the implementation suitable for upstream submission. > Hey, I'm confused, are you trying to prepare a patch here? I thought > it's Dave Klotz who would do this, let's not hijack this thread but > coordinate together, and please be patient, give Dave some time to > respond.. I think what Zexian done here is trying to investigate and > test the patches.. > > > [1] https://gist.github.com/moonlinux/2ae03be59f263b0797acb138bed226b5 > > > No, It's not a proper way for people to review and comment.. > Please accept my apology for this. > -- > Yixun Lan (dlan) Thanks -Anand ^ permalink raw reply [flat|nested] 33+ messages in thread
* [PATCH v2 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure 2026-10-05 17:50 ` [PATCH v2 " Dave Klotz 2026-10-05 17:55 ` [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz 2026-10-05 18:01 ` [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz @ 2026-10-05 18:11 ` Dave Klotz 2026-10-10 7:14 ` Yixun Lan 2 siblings, 1 reply; 33+ messages in thread From: Dave Klotz @ 2026-10-05 18:11 UTC (permalink / raw) To: Yixun Lan, Eric Chung, Peng Fan Cc: u-boot, Jaehoon Chung, Tanmay Kathpalia, Tom Rini When the probe fails, the driver releases its clock and reset bulks. clk_release_bulk() disables every clock and reset_release_bulk() asserts every reset, and the first entry of each is the SDH AXI bus clock and reset, which all three SDHCI controllers of the K1 share. One controller failing to probe therefore stops the bus of the others, and the next register access to any of them hangs the hart. On an OrangePi RV2, whose device tree enables the eMMC controller without a max-frequency, the eMMC probe failed in sdhci_setup_cfg() and U-Boot then hung at "MMC:" probing the microSD controller. Keep the clocks running and the resets deasserted on failure. Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> --- Validation: executable diff unchanged from v1; exact-base replay and checkpatch pass. Combined-firmware warm-boot results are in the cover; probe-failure paths have not been retested on hardware. drivers/mmc/spacemit_sdhci.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c index 4284553177..88e06a681c 100644 --- a/drivers/mmc/spacemit_sdhci.c +++ b/drivers/mmc/spacemit_sdhci.c @@ -642,10 +642,14 @@ spacemit_sdhci_phy_init(dev, host); return 0; + /* + * Leave the clocks and resets alone on failure. The "core" clock and + * the "axi" reset are the AXI clock and reset that every SDHCI + * controller of the K1 shares: releasing them would gate the bus of + * the other controllers, and the next access to one of them hangs. + */ err_reset: - reset_release_bulk(&plat->resets); err_clk: - clk_release_bulk(&plat->clks); return ret; } -- 2.55.0 ^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [PATCH v2 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure 2026-10-05 18:11 ` [PATCH v2 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz @ 2026-10-10 7:14 ` Yixun Lan 2026-10-10 19:27 ` Kathpalia, Tanmay 0 siblings, 1 reply; 33+ messages in thread From: Yixun Lan @ 2026-10-10 7:14 UTC (permalink / raw) To: Dave Klotz Cc: Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tanmay Kathpalia, Tom Rini Hi Dave, On 18:11 Mon 05 Oct , Dave Klotz wrote: > When the probe fails, the driver releases its clock and reset bulks. > clk_release_bulk() disables every clock and reset_release_bulk() > asserts every reset, and the first entry of each is the SDH AXI bus > clock and reset, which all three SDHCI controllers of the K1 share. > > One controller failing to probe therefore stops the bus of the others, > and the next register access to any of them hangs the hart. On an > OrangePi RV2, whose device tree enables the eMMC controller without a > max-frequency, the eMMC probe failed in sdhci_setup_cfg() and U-Boot > then hung at "MMC:" probing the microSD controller. > > Keep the clocks running and the resets deasserted on failure. > For the clock part: This doesn't make sense to me, but I've not put my hands on board to test and actually replicate the case myself.. It occur to me the clk driver should take care of the consumers and only disable the clock once 'enable_count' drop to zero, see https://git.u-boot-project.org/u-boot/custodians/u-boot-spacemit/-/blob/main/drivers/clk/clk-uclass.c?ref_type=heads#L744 For the reset part: As I checked the code, it seems exactly match what you described here, where there is no enable count tracking mechanism, so release() will trigger an assert() operation in hardware layer so, would this issue only relate to reset? > Signed-off-by: Dave Klotz <DaveWK225@protonmail.com> > Reviewed-by: Tanmay Kathpalia <tanmay.kathpalia@altera.com> > --- > Validation: executable diff unchanged from v1; exact-base replay and > checkpatch pass. Combined-firmware warm-boot results are in the cover; > probe-failure paths have not been retested on hardware. > > drivers/mmc/spacemit_sdhci.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/drivers/mmc/spacemit_sdhci.c b/drivers/mmc/spacemit_sdhci.c > index 4284553177..88e06a681c 100644 > --- a/drivers/mmc/spacemit_sdhci.c > +++ b/drivers/mmc/spacemit_sdhci.c > @@ -642,10 +642,14 @@ > spacemit_sdhci_phy_init(dev, host); > return 0; > > + /* > + * Leave the clocks and resets alone on failure. The "core" clock and > + * the "axi" reset are the AXI clock and reset that every SDHCI > + * controller of the K1 shares: releasing them would gate the bus of > + * the other controllers, and the next access to one of them hangs. > + */ > err_reset: > - reset_release_bulk(&plat->resets); > err_clk: > - clk_release_bulk(&plat->clks); > return ret; > } > > -- > 2.55.0 > -- Yixun Lan (dlan) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [PATCH v2 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure 2026-10-10 7:14 ` Yixun Lan @ 2026-10-10 19:27 ` Kathpalia, Tanmay 0 siblings, 0 replies; 33+ messages in thread From: Kathpalia, Tanmay @ 2026-10-10 19:27 UTC (permalink / raw) To: Yixun Lan, Dave Klotz Cc: Eric Chung, Peng Fan, u-boot, Jaehoon Chung, Tom Rini On 10-10-2026 12:44, Yixun Lan wrote: > Hi Dave, > > On 18:11 Mon 05 Oct , Dave Klotz wrote: >> When the probe fails, the driver releases its clock and reset bulks. >> clk_release_bulk() disables every clock and reset_release_bulk() >> asserts every reset, and the first entry of each is the SDH AXI bus >> clock and reset, which all three SDHCI controllers of the K1 share. >> >> One controller failing to probe therefore stops the bus of the others, >> and the next register access to any of them hangs the hart. On an >> OrangePi RV2, whose device tree enables the eMMC controller without a >> max-frequency, the eMMC probe failed in sdhci_setup_cfg() and U-Boot >> then hung at "MMC:" probing the microSD controller. >> >> Keep the clocks running and the resets deasserted on failure. >> > For the clock part: > > This doesn't make sense to me, but I've not put my hands on board to > test and actually replicate the case myself.. > > It occur to me the clk driver should take care of the consumers and > only disable the clock once 'enable_count' drop to zero, see > > https://git.u-boot-project.org/u-boot/custodians/u-boot-spacemit/-/blob/main/drivers/clk/clk-uclass.c?ref_type=heads#L744 > > > For the reset part: > As I checked the code, it seems exactly match what you described here, > where there is no enable count tracking mechanism, so release() will > trigger an assert() operation in hardware layer > > so, would this issue only relate to reset? > Given Dlan’s finding, I would withdraw the Reviewed-by pending that test or a narrower reset-only revision. ^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2026-10-13 3:45 UTC | newest] Thread overview: 33+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-02 21:29 [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz 2026-10-02 21:29 ` [PATCH 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz 2026-10-04 9:14 ` Kathpalia, Tanmay 2026-10-04 9:30 ` Kathpalia, Tanmay 2026-10-05 17:46 ` Dave Klotz 2026-10-02 21:29 ` [PATCH 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz 2026-10-04 9:28 ` Kathpalia, Tanmay 2026-10-02 21:29 ` [PATCH 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz 2026-10-04 9:28 ` Kathpalia, Tanmay 2026-10-02 22:06 ` [PATCH 0/3] mmc: k1: fixes for the SpacemiT K1 SDHCI driver Dave Klotz 2026-10-05 17:50 ` [PATCH v2 " Dave Klotz 2026-10-05 17:55 ` [PATCH v2 1/3] mmc: k1: handle a missing max-frequency and clk_set_rate()'s return value Dave Klotz 2026-10-06 5:40 ` Kathpalia, Tanmay 2026-10-10 8:45 ` Yixun Lan 2026-10-05 18:01 ` [PATCH v2 2/3] mmc: k1: let the SPL read SD cards more than one block at a time Dave Klotz 2026-10-10 6:17 ` Zixian Zeng 2026-10-10 19:02 ` Kathpalia, Tanmay 2026-10-10 19:16 ` Kathpalia, Tanmay 2026-10-11 3:38 ` Zixian Zeng 2026-10-11 14:31 ` Kathpalia, Tanmay 2026-10-11 15:33 ` Anand Moon 2026-10-11 19:41 ` Kathpalia, Tanmay 2026-10-12 13:15 ` Zixian Zeng 2026-10-12 14:00 ` Kathpalia, Tanmay 2026-10-12 14:30 ` Yixun Lan 2026-10-12 14:50 ` Kathpalia, Tanmay 2026-10-12 15:22 ` Yixun Lan 2026-10-12 16:07 ` Anand Moon 2026-10-13 0:15 ` Yixun Lan 2026-10-13 3:44 ` Anand Moon 2026-10-05 18:11 ` [PATCH v2 3/3] mmc: k1: do not release the shared AXI clock and reset on probe failure Dave Klotz 2026-10-10 7:14 ` Yixun Lan 2026-10-10 19:27 ` Kathpalia, Tanmay
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.