在mmc子系统学习笔记七 基于mmc总线的驱动代码研究中我们看到了最后添加mmc_card设备到mmc总线上,那么在添加之前总线控制器发现了有卡插进了卡槽,做了什么操作,构造mmc card这个设备呢?
还回到host下的msmsdcc-host.c文件中。
当然还是msmsdcc_probe函数,在上面5.2中我已经简要的分析了,但之前分析的时候,故意把一些重要的问题留到后面,也就是这儿。
在这个函数的最后,调用了mmc_add_host(mmc);
那这个mmc_add_host(mmc);干了什么么?
发现了mmc_start_host(host)函数,然后又调用了mmc_detect_change(host, 0);
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
{
#ifdef CONFIG_MMC_DEBUG
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
WARN_ON(host->removed);
spin_unlock_irqrestore(&host->lock, flags);
#endif
mmc_schedule_delayed_work(&host->detect, delay);
}
mmc_schedule_delayed_work(&host->detect, delay);/*延时函数,在probe最后的定时器负责polling,一旦host寄存器发生变化就调用延时的工作函数mmc_rescan,那现在假设polling的时候发现了host那块的寄存器状态改变,延时函数mmc_rescan做了什么?*/
初始化插入的设备
无论什么卡设备统一发送cmd0和cmd8
在mmc_go_idle(host);发送cmd0
cmd 0复位。
在mmc_send_if_cond(host, host->ocr_avail);发送cmd8
cmd 8 是否是sd 2.0即高容量
首先判断是不是sdio设备
err = mmc_send_io_op_cond(host, 0, &ocr);
if (!err) {
if (mmc_attach_sdio(host, ocr))
mmc_power_off(host);
extend_wakelock = 1;
goto out;
}
mmc_send_io_op_cond(),这个函数是cmd5,ocr为0,即arg=0,回应是r4,正确的response则继续mmc_attach_sdio(host, ocr))需要完成以下工作:
(1)host->ocr = mmc_select_voltage(host, ocr);选择ocr中主机支持,且为最低的电压
(2)告诉卡,主机的的工作电压,这一步仍发送cmd5,但是arg有参数了,即是主机的选中的工作电压
(3)分配mmc card,并开始初始化
(4)发布rca,cmd3命令
(5)读取cia中通用寄存器cccr,使用地址0x00来完成操作function0,注CIA包含 CCCR+FBR+CIS
(6)最后err = mmc_add_card(host->card);
是不是sd设备
和上述差不多,可自行分析,注意获取ocr的命令此时变成acmd41.