[PATCH 1/2] wifi: rtw88: 8703b: complete the card-disable to card-emulation transition
From: Cristian Deluxe
Date: Fri Sep 11 2026 - 13:49:15 EST
On an RTL8723CS the driver cannot power the MAC on after a warm reboot:
the power-on sequence waits forever for power ready and probe fails.
rtw88_8723cs mmc2:0001:1: failed to poll offset=0x6 mask=0x2 value=0x2
rtw88_8723cs mmc2:0001:1: mac power on failed
trans_carddis_to_cardemu_8703b has a single entry, clearing the hardware
power-down bit. Its sibling trans_carddis_to_cardemu_8723d has six more,
and 8822b and 8822c carry the same SDIO pair: withdraw the SDIO suspend
request on local register 0x86 and wait for the interface to leave the
suspended state, clear the WL suspend bit alongside the power-down bit,
and take the 12H LDO out of sleep mode. The transition is the reverse of
trans_cardemu_to_carddis_8703b, which sets 0x23[4] and asks the
interface to suspend, so with those operations missing neither is ever
undone.
The chip then comes back with the WLAN MAC unpowered while the SDIO
function still enumerates and CMD52 still works, and nothing in the
sequence wakes it. rtw_mac_pre_system_cfg() does not cover it either: it
returns early for 8051 wcpu chips, of which this is one.
It survives a reboot on any board where WL_REG_ON is the only reset the
host has and the chip's rail is not switchable. On the Denver TAQ-102
the pwrseq reset line, the BT enable line, the 32.768 kHz clock and
every switchable PMIC rail were each toggled against a wedged chip and
none of them cleared it, while the vendor driver recovered it every
time.
Take the operations 8723d has and this table lacks. That table's USB-only
and PCI-only entries are left out: this chip has no such variant.
Tested on an RTL8723CS over SDIO: recovers a chip left wedged by a
previous boot, and survives repeated warm reboots and loader-mode flash
cycles.
Signed-off-by: Cristian Deluxe <me@xxxxxxxxxxxxxxxxxx>
---
drivers/net/wireless/realtek/rtw88/rtw8703b.c | 33 ++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
index b5e7ae7eb..67bbd70f4 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
@@ -187,11 +187,38 @@ static const struct rtw_pwr_seq_cmd trans_pre_enable_8703b[] = {
};
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8703b[] = {
+ /* clear WL suspend enable and HW power down enable */
{0x0005,
RTW_PWR_CUT_ALL_MSK,
RTW_PWR_INTF_ALL_MSK,
RTW_PWR_ADDR_MAC,
- RTW_PWR_CMD_WRITE, BIT(7), 0},
+ RTW_PWR_CMD_WRITE, BIT(3) | BIT(7), 0},
+ /* withdraw the SDIO suspend request */
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_WRITE, BIT(0), 0},
+ /* and wait for the interface to leave the suspended state */
+ {0x0086,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_SDIO,
+ RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
+ /* disable WL suspend */
+ {0x0005,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_ALL_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), 0},
+ /* take the 12H LDO back out of sleep mode, which the card-disable
+ * transition put it into
+ */
+ {0x0023,
+ RTW_PWR_CUT_ALL_MSK,
+ RTW_PWR_INTF_SDIO_MSK,
+ RTW_PWR_ADDR_MAC,
+ RTW_PWR_CMD_WRITE, BIT(4), 0},
{TRANS_SEQ_END},
};
--
2.51.0