* [PATCH v2 0/2] mmc: core: sdio: fix UHS init with fixed 1.8V vqmmc
@ 2026-10-27 12:24 Deomid rojer Ryabkov
2026-10-27 12:24 ` [PATCH v2 1/2] mmc: core: sdio: retry without UHS if UHS init fails Deomid rojer Ryabkov
2026-10-27 12:24 ` [PATCH v2 2/2] mmc: core: sdio: skip CMD11 if signalling is already 1.8V Deomid rojer Ryabkov
0 siblings, 2 replies; 3+ messages in thread
From: Deomid rojer Ryabkov @ 2026-10-27 12:24 UTC (permalink / raw)
To: ulfh; +Cc: linux-mmc, linux-kernel, shawn.lin, llj, Deomid rojer Ryabkov
The Realtek RTL8822CS SDIO Wi-Fi module on the FriendlyElec NanoPi R2S
Plus (fixed 1.8V vqmmc) reports S18A = 1 in its R4 response although the
bus is already at 1.8V, contrary to the SDIO Simplified Specification
3.00, section 3.1.2. CMD11 then times out and the module ends up at
50 MHz high-speed instead of SDR104. The SWT6621S behaves the same way
and, without patch 2, doesn't come up at all.
Patch 1 makes SDIO init fall back to high-speed mode if UHS init fails
(e.g. tuning), instead of failing the card altogether.
Patch 2 skips CMD11 when the host is already at 1.8V.
Tested on a NanoPi R2S Plus (OpenWrt 25.12, Linux 6.12.112 with these
patches; applies to mainline as of 2026-10-22): SDR104 at 150 MHz; iperf
as a 5 GHz VHT80 station goes from 70/29 to 123/125 Mbit/s (rx/tx). eMMC
(HS200) and SD card on the same SoC are unaffected. Longjian tested
patch 2 with an SWT6621S.
The device tree part for the R2S Plus is sent separately to
linux-rockchip.
Changes in v2:
- 1/2: the existing CCCR fallback resets the card, it doesn't
power-cycle it (Shawn).
- 2/2: note in the commit message that this relies on the fixed 1.8V
supply being described as vqmmc-supply (Shawn).
- Dropped "2/2 alt", the alternative to 2/2 that kept sending CMD11.
- Collected Reviewed-by (Shawn) and Tested-by (Longjian, 2/2; his
reply didn't reach the list, it was HTML).
v1: https://lore.kernel.org/linux-mmc/20261023232813.2983368-1-rojer@rojer.me/
Deomid rojer Ryabkov (2):
mmc: core: sdio: retry without UHS if UHS init fails
mmc: core: sdio: skip CMD11 if signalling is already 1.8V
drivers/mmc/core/sdio.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
base-commit: 734bef548a96e8774d6eef5dfa2026c6edc4e80b
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 1/2] mmc: core: sdio: retry without UHS if UHS init fails
2026-10-27 12:24 [PATCH v2 0/2] mmc: core: sdio: fix UHS init with fixed 1.8V vqmmc Deomid rojer Ryabkov
@ 2026-10-27 12:24 ` Deomid rojer Ryabkov
2026-10-27 12:24 ` [PATCH v2 2/2] mmc: core: sdio: skip CMD11 if signalling is already 1.8V Deomid rojer Ryabkov
1 sibling, 0 replies; 3+ messages in thread
From: Deomid rojer Ryabkov @ 2026-10-27 12:24 UTC (permalink / raw)
To: ulfh; +Cc: linux-mmc, linux-kernel, shawn.lin, llj, Deomid rojer Ryabkov
If mmc_sdio_init_uhs_card() fails, e.g. because tuning finds no
working sample phase, card initialisation fails and the card is not
usable at all, even though it would work fine in high-speed mode.
This happens for example on the FriendlyElec NanoPi R2S Plus when the
SDIO pins of the RTL8822CS Wi-Fi module are left at their default 4 mA
drive strength:
dwmmc_rockchip ff5f0000.mmc: All phases bad!
mmc2: tuning execution failed: -5
mmc2: error -5 whilst initialising SDIO card
[... repeated for every init frequency ...]
mmc2: Failed to initialize a non-removable card
There is already a fallback for a failure to read the CCCR in UHS mode:
reset the card and restart the init sequence without R4_18V_PRESENT.
Do the same when UHS init fails, so that the card comes up in
high-speed mode instead:
mmc2: UHS init failed (-5), retrying without UHS
mmc2: Skipping voltage switch
mmc2: new high speed SDIO card at address 0001
The fallback is taken at most once, as the retry doesn't request UHS.
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Deomid rojer Ryabkov <rojer@rojer.me>
---
drivers/mmc/core/sdio.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 83085e76486..6787fdf1c53 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -867,8 +867,14 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
/* Only if card supports 1.8v and UHS signaling */
if ((ocr & R4_18V_PRESENT) && card->sw_caps.sd3_bus_mode) {
err = mmc_sdio_init_uhs_card(card);
- if (err)
- goto remove;
+ if (err) {
+ pr_warn("%s: UHS init failed (%d), retrying without UHS\n",
+ mmc_hostname(host), err);
+ mmc_sdio_pre_init(host, ocr_card,
+ card != oldcard ? card : NULL);
+ retries = 0;
+ goto try_again;
+ }
} else {
/*
* Switch to high-speed (if supported).
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2 2/2] mmc: core: sdio: skip CMD11 if signalling is already 1.8V
2026-10-27 12:24 [PATCH v2 0/2] mmc: core: sdio: fix UHS init with fixed 1.8V vqmmc Deomid rojer Ryabkov
2026-10-27 12:24 ` [PATCH v2 1/2] mmc: core: sdio: retry without UHS if UHS init fails Deomid rojer Ryabkov
@ 2026-10-27 12:24 ` Deomid rojer Ryabkov
1 sibling, 0 replies; 3+ messages in thread
From: Deomid rojer Ryabkov @ 2026-10-27 12:24 UTC (permalink / raw)
To: ulfh
Cc: linux-mmc, linux-kernel, shawn.lin, llj, Deomid rojer Ryabkov,
Jensen Huang
Per the SDIO Simplified Specification Version 3.00, section 3.1.2, a card
whose signalling is already at 1.8V must report S18A = 0 in the R4
response, and the core relies on that: it only sends CMD11
(SD_SWITCH_VOLTAGE) when S18A is set.
Some cards don't follow this. The Realtek RTL8822CS (as fitted on the
FriendlyElec NanoPi R2S Plus, where the M.2 SDIO bus is wired to a fixed
1.8V vqmmc) answers CMD5 with S18A = 1 even though the bus is already at
1.8V. CMD11 then times out:
dwmmc_rockchip ff5f0000.mmc: Unexpected CMD11 timeout
mmc_host mmc2: Timeout sending command (cmd 0x10202000 arg 0x0 status 0x90202000)
mmc2: new high speed SDIO card at address 0001
and the card ends up in 50 MHz high-speed mode instead of SDR104.
The SWT6621S misreports S18A the same way; there, the failed switch
leaves the card unable to initialise at all (error -110) instead of
falling back to high speed.
When vqmmc can't do 3.3V, mmc_set_initial_signal_voltage() has already
fallen back to 1.8V by the time CMD5 is sent, so the host knows there is
nothing to switch. Skip CMD11 in that case. ocr keeps R4_18V_PRESENT, so
mmc_sdio_init_uhs_card() still runs and the card is tuned to SDR104:
dwmmc_rockchip ff5f0000.mmc: Successfully tuned phase to 64
mmc2: new ultra high speed SDR104 SDIO card at address 0001
Hosts that start at 3.3V are not affected, nor are compliant cards that
report S18A = 0 at 1.8V. A non-compliant card that does need CMD11
before entering UHS at 1.8V would now fail UHS init; with the previous
patch it falls back to high-speed mode and keeps working.
This relies on the fixed 1.8V supply being described as vqmmc-supply.
vqmmc is optional: without it, the host can't tell that the bus is
hardwired to 1.8V. Setting 3.3V then "succeeds", the core believes the
bus is at 3.3V and CMD11 is still sent, so the patch doesn't help. Such
boards need to describe the supply (e.g. a fixed 1.8V regulator as
vqmmc-supply) to benefit from it.
FriendlyElec's BSP for this board works around this with a card
quirk, MMC_QUIRK_BROKEN_ROCR_S18A[1], matched on the "realtek,rtl8822cs"
compatible, which drops the switch request whenever this chip is
present. The misreported S18A is the card's fault, but ignoring it is
only correct when the bus is already at 1.8V: on a board with a
switchable vqmmc the same chip would then be run in UHS at 3.3V. A card
quirk would need knowledge of the board's supply that it doesn't have.
The core does know the current signal voltage, so handle it there, which
also takes care of any other card that turns out to behave the same way.
[1] https://github.com/friendlyarm/kernel-rockchip/commit/aee62cf7ae16b5ede6c6d92a8ee20e796482754e
Cc: Jensen Huang <jensenhuang@friendlyarm.com>
Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
Tested-by: Longjian Lin <llj@rock-chips.com>
Signed-off-by: Deomid rojer Ryabkov <rojer@rojer.me>
---
drivers/mmc/core/sdio.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 6787fdf1c53..a986ee04ba2 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -737,9 +737,11 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
* 1.8v, the card sets S18A to 0 in the R4 response. So it will
* fails to check rocr & R4_18V_PRESENT, but we still need to
* try to init uhs card. sdio_read_cccr will take over this task
- * to make sure which speed mode should work.
+ * to make sure which speed mode should work. Some cards (RTL8822CS)
+ * set S18A regardless, so don't send CMD11 if we are already at 1.8V.
*/
- if (rocr & ocr & R4_18V_PRESENT) {
+ if ((rocr & ocr & R4_18V_PRESENT) &&
+ host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
err = mmc_set_uhs_voltage(host, ocr_card);
if (err == -EAGAIN) {
mmc_sdio_pre_init(host, ocr_card, card);
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-27 12:24 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-27 12:24 [PATCH v2 0/2] mmc: core: sdio: fix UHS init with fixed 1.8V vqmmc Deomid rojer Ryabkov
2026-10-27 12:24 ` [PATCH v2 1/2] mmc: core: sdio: retry without UHS if UHS init fails Deomid rojer Ryabkov
2026-10-27 12:24 ` [PATCH v2 2/2] mmc: core: sdio: skip CMD11 if signalling is already 1.8V Deomid rojer Ryabkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®