天天看點

imx8qm wifi sdio調試

imx8qm平台用的是有WIFI和BT功能的Murata 晶片,型号是LBEE6U41LQ,WIFI采用sdio接口,由WL_EN控制上電;BT是UART1接口,由BT_EN控制上電;

一.硬體原理

imx8qm wifi sdio調試

二.引腳資訊

/* 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起不來,加列印如下,四個頻率都掃描不到。

imx8qm wifi sdio調試

2.wifi enable腳正常情況如下,基本上不會出現掉電:

imx8qm wifi sdio調試

3.不正常情況在scan sdio時wifi enable腳被拉低7s左右。

imx8qm wifi sdio調試

四.分析過程

(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方式:

檢視節點             

imx8qm wifi sdio調試

檢視開機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

imx8qm wifi sdio調試

(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: [email protected] {
				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!
           

繼續閱讀