imx8qm平台用的是有WIFI和BT功能的Murata 芯片,型号是LBEE6U41LQ,WIFI采用sdio接口,由WL_EN控制上电;BT是UART1接口,由BT_EN控制上电;
一.硬件原理
二.引脚信息
/* bt enable*/
SC_P_USDHC2_VSELECT
/* uart1 */
SC_P_UART1_RX
SC_P_UART1_TX
SC_P_UART1_CTS_B
SC_P_UART1_RTS_B
/* wifi */
SC_P_SPI2_SDO // IRQ gpio3 8
SC_P_USDHC2_RESET_B //ENABLE gpio4 9
/* USDHC2 SDIO*/
SC_P_USDHC2_CLK
SC_P_USDHC2_CMD
SC_P_USDHC2_DATA0
SC_P_USDHC2_DATA1
SC_P_USDHC2_DATA2
SC_P_USDHC2_DATA3
三.问题描述
1.SDIO扫描不到设备,wifi起不来,加打印如下,四个频率都扫描不到。
2.wifi enable脚正常情况如下,基本上不会出现掉电:
3.不正常情况在scan sdio时wifi enable脚被拉低7s左右。
四.分析过程
(1)SDIO扫描原理:
1.drivers/mmc/core/core.c -->mmc_rescan,在4个频率下扫描设备(400kHZ,300kHZ,200kHZ,100kHZ)
void mmc_rescan(struct work_struct *work)
{
struct mmc_host *host = container_of(work, struct mmc_host, detect.work);
int i;
if (host->rescan_disable)
return;
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
{
printk("%s freq[%d] OK!\n",__func__,freqs[i]);
break;
}
if (freqs[i] <= host->f_min)
break;
}
2.drivers/mmc/core/core.c --> mmc_rescan_try_freq ,在扫描前先发个sdio_reset(CMD52)命令,只有sdio设备会有响应,之后按照sdio(CMD5),sd,mmc的顺序扫描,一旦扫到立即返回
static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
{
host->f_init = freq;
/*
* sdio_reset sends CMD52 to reset card. Since we do not know
* if the card is being re-initialized, just send it. CMD52
* should be ignored by SD/eMMC cards.
* Skip it if we already know that we do not support SDIO commands
*/
if (!(host->caps2 & MMC_CAP2_NO_SDIO))
sdio_reset(host);
mmc_go_idle(host);
if (!(host->caps2 & MMC_CAP2_NO_SD))
mmc_send_if_cond(host, host->ocr_avail);
/* Order's important: probe SDIO, then SD, then MMC */
if (!(host->caps2 & MMC_CAP2_NO_SDIO))
if (!mmc_attach_sdio(host))
{
printk("%s line=%d\n",__FUNCTION__,__LINE__);
return 0;
}
if (!(host->caps2 & MMC_CAP2_NO_SD))
if (!mmc_attach_sd(host))
return 0;
if (!(host->caps2 & MMC_CAP2_NO_MMC))
if (!mmc_attach_mmc(host))
return 0;
mmc_power_off(host);
return -EIO;
}
3.如果成功检测到设备,便会进行后续的mmc_sdio_init_card和mmc_add_card及sdio_add_func,进行建立设备节点等操作。
检测到设备的check方式:
查看节点
查看开机kernel log [ 8.382000] mmc0: new SDIO card at address 0001
/*
* Starting point for SDIO card init.
*/
int mmc_attach_sdio(struct mmc_host *host)
{
int err, i, funcs;
u32 ocr, rocr;
struct mmc_card *card;
printk("%s line=%d\n",__FUNCTION__,__LINE__);
WARN_ON(!host->claimed);
.....
err = mmc_sdio_init_card(host, rocr, NULL, 0);
......
for (i = 0; i < funcs; i++, card->sdio_funcs++) {
#ifdef CONFIG_MMC_EMBEDDED_SDIO
if (host->embedded_sdio_data.funcs) {
struct sdio_func *tmp;
tmp = sdio_alloc_func(host->card);
} else {
#endif
printk("%s line=%d\n",__FUNCTION__,__LINE__);
err = sdio_init_func(host->card, i + 1);
if (err)
goto remove;
}
mmc_release_host(host);
err = mmc_add_card(host->card);
if (err)
goto remove_added;
/*
* ...then the SDIO functions.
*/
for (i = 0;i < funcs;i++) {
err = sdio_add_func(host->card->sdio_func[i]);
if (err)
goto remove_added;
}
}
4.接下来将读取sdio CIS值并打印出来。
sdio_init_func
---->sdio_read_func_cis(func);
----->sdio_read_cis
(2)分析过程
1.首先wifi enable脚入手,原本一直以为是DPU资源调换过来后引起uhsdc3 clock有问题了,后面通过各种对比试验定位到问题在fsl-imx8qm-mek-domu.dts里面。
wifi_en脚是gpio4 9,dts如下:
pinctrl_wifi: wifi {
fsl,pins = <
SC_P_USDHC2_RESET_B_LSIO_GPIO4_IO09 0x18000000
SC_P_SPI2_SDO_LSIO_GPIO3_IO08 0x1E000000
>;
};
发现pcie也用了USDHC2_RESET_B这个脚:
pinctrl_pciea: pcieagrp{
fsl,pins = <
SC_P_PCIE_CTRL0_CLKREQ_B_LSIO_GPIO4_IO27 0x06000021
SC_P_PCIE_CTRL0_WAKE_B_LSIO_GPIO4_IO28 0x04000021
SC_P_PCIE_CTRL0_PERST_B_LSIO_GPIO4_IO29 0x06000021
SC_P_LVDS1_I2C0_SDA_LSIO_GPIO1_IO13 0x06000000
SC_P_USDHC2_RESET_B_LSIO_GPIO4_IO09 0x06000021
>;
};
&pciea {
ext_osc = <1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pciea>;
disable-gpio = <&gpio1 13 GPIO_ACTIVE_LOW>;
reset-gpio = <&gpio4 29 GPIO_ACTIVE_LOW>;
clkreq-gpio = <&gpio4 27 GPIO_ACTIVE_LOW>;
epdev_on-supply = <&epdev_on>;
status = "disabled";
};
epdev_on: fixedregulator@100 {
compatible = "regulator-fixed";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-name = "epdev_on";
gpio = <&gpio4 9 0>;
enable-active-high;
};
最后解决方法就是注释掉整个pciea的dts。
mmc2所有打印信息如下:
[ 1.155040] sdhci: Secure Digital Host Controller Interface driver
[ 1.155054] sdhci: Copyright(c) Pierre Ossman
[ 1.155143] sdhci-pltfm: SDHCI platform and OF driver helper
[ 1.203808] mmc2: CQHCI version 5.10
[ 1.203854] enable-sdio-wakeup ok
[ 1.203881] sdhci-esdhc-imx 5b030000.usdhc: assigned as wifi host
[ 1.204884] mmc_rescan line=2748
[ 1.211333] mmc_attach_sdio line=1136
[ 1.250588] mmc2: SDHCI controller on 5b030000.usdhc [5b030000.usdhc] using ADMA
[ 1.255110] mmc_rescan line=2748
[ 1.255132] mmc2: mmc_rescan_try_freq: trying to init card at 400000 Hz
[ 1.264293] Galcore version 6.2.4.190076
[ 1.269699] mmc_attach_sdio line=1136
[ 1.272419] sdio_read_cis line=239
[ 1.280186] mmc2: queuing unknown CIS tuple 0x80 (2 bytes)
[ 1.282545] random: fast init done
[ 1.285154] mmc2: queuing unknown CIS tuple 0x80 (7 bytes)
[ 1.289261] mmc2: queuing unknown CIS tuple 0x80 (6 bytes)
[ 1.300245] mmc2: queuing unknown CIS tuple 0x80 (31 bytes)
[ 1.303460] mmc2: queuing unknown CIS tuple 0x80 (7 bytes)
[ 1.312601] mmc2: queuing unknown CIS tuple 0x80 (25 bytes)
[ 1.319569] mmc_rescan freq[400000] OK!
[ 1.321768] mmc2: queuing unknown CIS tuple 0x80 (25 bytes)
[ 1.369956] sdio_init_func line=86
[ 1.369979] sdio_read_func_cis line=377
[ 1.369989] sdio_read_cis line=239
[ 1.371074] sdio_init_func line=86
[ 1.371086] sdio_read_func_cis line=377
[ 1.371095] sdio_read_cis line=239
[ 1.372121] sdio_init_func line=86
[ 1.372132] sdio_read_func_cis line=377
[ 1.372141] sdio_read_cis line=239
[ 1.373259] mmc2: new high speed SDIO card at address 0001
[ 1.373610] mmc_rescan_try_freq line=2643
[ 1.373622] mmc_rescan freq[400000] OK!