sdio设备无法识别

最近遇到sdio设备无法识别问题,一直解决不掉很痛苦,好在最终解决,分享下

模块:

用的是有WIFI和BT功能的芯片,WIFI采用sdio接口,由WL_EN控制上电;BT是UART接口,由BT_EN控制上电;

基础知识:

首先sdio属于mmc子系统中设备,mmc子系统包括:sdio,sd,mmc

sdio设备在加载driver之前,首先得被mmc子系统识别到,才能进行后续操作

  • drivers/mmc/core/core.c,在4个频率下扫描设备(400kHZ,300kHZ,200kHZ,100kHZ)
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };

void mmc_rescan(struct work_struct *work)
{	
	......
	for (i = 0; i < ARRAY_SIZE(freqs); i++) {
		if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) {
			extend_wakelock = true;
			break;
		}
		if (freqs[i] <= host->f_min)
			break;
	}
	......
}
  • 在扫描前先发个sdio_reset(CMD52)命令,只有sdio设备会有响应

之后按照sdio(CMD5),sd,mmc的顺序扫描,一旦扫到立即返回

static int mmc_rescan_try_freq(struct mmc_host *host, unsigned 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.
	 */
	sdio_reset(host);
	mmc_go_idle(host);

	mmc_send_if_cond(host, host->ocr_avail);

	/* Order's important: probe SDIO, then SD, then MMC */
	if (!mmc_attach_sdio(host))
		return 0;
	if (!mmc_attach_sd(host))
		return 0;
	if (!mmc_attach_mmc(host))
		return 0;

	mmc_power_off(host);
	return -EIO;
}

如果成功检测到设备,便会进行后续的mmc_sdio_init_card和mmc_add_card,进行建立设备节点等操作

检测到设备的check方式:

  1. 查看节点             sdio设备无法识别_第1张图片
  2. 看开机kernel log        <6>[    8.382000] mmc0: new SDIO card at address 0001

实验经历

以上都check过后,sdio设备依然对CMD52和CMD没有response,于是做了下面的实验

  • 测量波形

用示波器量开机时候的波形,确认是否有信号出来;结果是发现开机过程中是有信号的,正常开完机就没有了

(黄色SDIO_CLK,蓝色SDIO_CMD),所以猜测这个信号可能是host端发给sdio设备的检测信号,但sdio是否有回复呢?

可以用逻辑分析仪看一下结果,逻辑分析仪用法可以参考上篇博文https://blog.csdn.net/miss_lazygoat/article/details/84105304

sdio设备无法识别_第2张图片

截取一段逻辑分析仪的结果来看,全是从host端发出的cmd,没有slave的回应,CMD52也是符合预期的

Time [s] Value
1.96874275 START
1.9687453 DIR:from Host
1.9687478 CMD:52
1.968763 ARG:0x00
1.9688441 CRC:0x1C
1.96886185 STOP
1.9696981 START
1.96970065 DIR:from Host
1.96970315 CMD:52
1.96971835 ARG:0x08
1.96979945 CRC:0x4F
1.9698172 STOP
1.9719129 START
1.9719154 DIR:from Host

既然能确认host端已发送检测命令,没有response就是slave端的问题了,给芯片供应商去排查就好了。

最后发现问题所在:WL_EN和BT_EN需同时拉高模组才能正常工作(由于模块bug),之后sdio便能正常被识别了

关键log

  • 没有response,request返回的都是-110
<7>[    8.261000] mmc0: req failed (CMD5): -110, retrying...
<7>[    8.261000] dwmmc_balong 900ae000.dwmmc1: start command: ARGR=0x00000000 CMDR=0x20000045 CMD(5)
<6>[    8.261000] ftyreset module initialized.
<6>[    8.261000] [HWLOCK] drv verify simlock init ok!
<7>[    8.262000] mmc0: req done (CMD5): -110: 00000000 00000000 00000000 00000000
<7>[    8.262000] mmc0: starting CMD55 arg 00000000 flags 000000f5
<7>[    8.262000] dwmmc_balong 900ae000.dwmmc1: start command: ARGR=0x00000000 CMDR=0x20000177 CMD(55)
<6>[    8.263000] SIO data mode[0], clk mode[1], clk rate[2048000]
<7>[    8.263000] mmc0: req done (CMD55): -110: 00000000 00000000 00000000 00000000
  • 有response,request返回0,最后能找到SDIO card
<7>[    8.410000] mmc0: starting CMD52 arg 00227800 flags 00000195
<7>[    8.410000] dwmmc_balong 900ae000.dwmmc1: start command: ARGR=0x00227800 CMDR=0x20000174 CMD(52)
<7>[    8.410000] mmc0: req done (CMD52): 0: 00001082 00000000 00000000 00000000
<7>[    8.410000] mmc0: starting CMD52 arg 00227a00 flags 00000195
<7>[    8.410000] dwmmc_balong 900ae000.dwmmc1: start command: ARGR=0x00227a00 CMDR=0x20000174 CMD(52)
<7>[    8.410000] mmc0: req done (CMD52): 0: 00001001 00000000 00000000 00000000
<7>[    8.410000] mmc0: starting CMD52 arg 00227c00 flags 00000195
<7>[    8.410000] dwmmc_balong 900ae000.dwmmc1: start command: ARGR=0x00227c00 CMDR=0x20000174 CMD(52)
<7>[    8.410000] mmc0: req done (CMD52): 0: 000010df 00000000 00000000 00000000
<4>[    8.410000] mmc0: queuing unknown CIS tuple 0x82 (1 bytes)
<7>[    8.410000] mmc0: starting CMD52 arg 00227e00 flags 00000195
<7>[    8.410000] dwmmc_balong 900ae000.dwmmc1: start command: ARGR=0x00227e00 CMDR=0x20000174 CMD(52)
<7>[    8.410000] mmc0: req done (CMD52): 0: 000010ff 00000000 00000000 00000000
<6>[    8.410000] mmc0: new SDIO card at address 0001

 

你可能感兴趣的:(问题记录)