一、SD卡热插拔
识别SD的热插拔都是通过注册GPIO的中断来实现,插入SD卡的时候触发内核中断,在中断例程里面完成sd卡的识别和初始化工作。
下面通过代码来追踪一下。
高通芯片mci的驱动代码在/kernel/drivers/mmc/host/msm_sdcc.c文件中。
内核驱动第一招:
module_init(msmsdcc_init);
告诉我们驱动初始化入口函数是msmsdcc_init,顺着这个函数看
static int __init msmsdcc_init(void)
{
returnplatform_driver_register(&msmsdcc_driver);
}
非常简洁,就是注册了一个平台设备驱动。内核驱动第二招:找probe函数
static int
msmsdcc_probe(struct platform_device *pdev)
{
。。。。
host->stat_irq= stat_irqres->start;
ret =request_irq(host->stat_irq,
msmsdcc_platform_status_irq,
irqflags,
DRIVER_NAME " (slot)",
host);
。。。。
}
让我们找到了关键代码,这段代码注册了一个软中断,中断处理函数是msmsdcc_platform_status_irq。SD卡热插拔处理的庐山真面目就要显露了。
我一直觉得高通的代码阅读起来比较费力,就是他的函数调用层数比较多,这里也一样。
static irqreturn_t
msmsdcc_platform_status_irq(int irq, void *dev_id)
{
struct msmsdcc_host*host = dev_id;
printk(KERN_DEBUG"%s: %d\n", __func__, irq);
msmsdcc_check_status((unsignedlong) host);
return IRQ_HANDLED;
}
代码将我们引导到msmsdcc_check_status
感觉是顺风顺水,但是继续看下去的时候有了迷惑。
调用到mmc_detect_change函数,这个函数里面
mmc_schedule_delayed_work(&host->detect, delay);
让一切又迷惑起来了,host->detect是个什么东西?
还是回到源头probe函数里面,mmc_alloc_host才是我们需要关注的地方,这个函数里面初始化host->detect执行的是mmc_rescan函数,真累,看看mmc_rescan都做了些什么。
七拐八绕,看起来是调用了mmc_rescan_try_freq来看是否存在sd卡。
这里真是花了我不少时间,找到了调用顺序:
mmc_rescan_try_freq -> mmc_attach_sd -> mmc_sd_detect
这个里面有一个中间环节:mmc_sd_attach_bus_ops。这个是mmc检测中断里面的精华,统一了SDI、SD和MMC的热插拔检测。
mmc_attach_sd -> mmc_add_card调用device_add()会产生一个hotplug事件,最终调用mmc_bus_uevent向userspace发消息。