[RK3399 Android7.1.2]新增wifi&bt模块:rtl8822cs驱动以及解决所遇问题
问题步骤
- 连接WIFI
- 循环软重启设备
- 偶现某次重启后无法打开WIFI
- lsmod 没有wifi模组ko驱动
问题日志
正常日志
[ 3.841058] mmc_host mmc2: Bus speed (slot 0) = 100000000Hz (slot req 100000000Hz, actual 100000000HZ div = 0)
[ 4.388154] dwmmc_rockchip fe310000.dwmmc: Successfully tuned phase to 206
[ 4.391066] mmc2: new ultra high speed SDR50 SDIO card at address 0001
[ 13.786083] RTW: module init start
[ 13.786173] RTW: rtl8821cs v5.12.0-8-g39bbb8dd2.20201015_COEX20200730-5151
[ 13.786363] RTW: build time: Aug 17 2024 14:07:56
[ 13.786604] RTW: rtl8821cs BT-Coex version = COEX20200730-5151
异常日志
[ 3.804439] mmc2: Skipping voltage switch
[ 5.138046] mmc2: error -110 whilst initialising SDIO card
[ 5.637970] mmc_host mmc2: Timeout sending command (cmd 0x202000 arg 0x0 status 0xa0000143)
[ 5.651471] mmc_host mmc2: Bus speed (slot 0) = 300000Hz (slot req 300000Hz, actual 300000HZ div = 0)
[ 5.672029] dwmmc_rockchip fe310000.dwmmc: card claims to support voltages below defined range
[ 5.704434] mmc2: Skipping voltage switch
[ 7.077991] mmc2: error -110 whilst initialising SDIO card
[ 7.577963] mmc_host mmc2: Timeout sending command (cmd 0x202000 arg 0x0 status 0xa0000143)
[ 7.591382] mmc_host mmc2: Bus speed (slot 0) = 200000Hz (slot req 200000Hz, actual 200000HZ div = 0)
[ 7.617742] dwmmc_rockchip fe310000.dwmmc: card claims to support voltages below defined range
[ 7.651318] mmc2: Skipping voltage switch
[ 9.001339] mmc2: error -110 whilst initialising SDIO card
[ 9.501289] mmc_host mmc2: Timeout sending command (cmd 0x202000 arg 0x0 status 0xa0000143)
驱动源码
kernel/drivers/mmc/core/sdio.c
/*
* Handle the detection and initialisation of a card.
*
* In the case of a resume, "oldcard" will contain the card
* we're trying to reinitialise.
*/
static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard, int powered_resume)
{
struct mmc_card *card;
int err;
int retries = 10;
u32 rocr = 0;
u32 ocr_card = ocr;
BUG_ON(!host);
WARN_ON(!host->claimed);
/* to query card if 1.8V signalling is supported */
if (mmc_host_uhs(host))
ocr |= R4_18V_PRESENT;
try_again:
if (!retries) {
// 此处打印
pr_warn("%s: Skipping voltage switch\n", mmc_hostname(host));
ocr &= ~R4_18V_PRESENT;
}
//----------------------------省略代码-----------------------------
/* If the host and card support UHS-I mode request the card
* to switch to 1.8V signaling level. No 1.8v signalling if
* UHS mode is not enabled to maintain compatibility and some
* systems that claim 1.8v signalling in fact do not support
* it. Per SDIO spec v3, section 3.1.2, if the voltage is already
* 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.
*/
if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
ocr_card);
if (err == -EAGAIN) {
mmc_sdio_resend_if_cond(host, card);
retries--;
goto try_again;
} else if (err) {
ocr &= ~R4_18V_PRESENT;
}
}
//------------------------------省略代码----------------------------
}
修改方案
Realtek 88x2BS系列, SDIO 3.0是1.8V,原先代码是走到一个函数里设置信号电压为1.8V,正常就可继续流程 错误返回I/O error ;所以要跳过设置信号电压这个步骤即可
kernel/drivers/mmc/core/sdio.c
if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
// modify start
// https://www.codeleading.com/article/96705503300/
// err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
// ocr_card);
pr_warn("%s: Skip set signal voltage to 1.8v\n", mmc_hostname(host));
err = 0;
// modify end
if (err == -EAGAIN) {
mmc_sdio_resend_if_cond(host, card);
retries--;
goto try_again;
} else if (err) {
ocr &= ~R4_18V_PRESENT;
}
}