赞
踩
Linux的MMC/SD存储卡是一种典型的块设备,实现位于driver/mac中,分为card/core/host三层(最上面为文件系统)
块设备与字符设备的差异
主要分为三层:
mmc_core为mmc子系统标准接口,包括对各种sd/sdio协议的实现,因此代码健全,代码量大,且标准,完全安装协议来实现,建议根据实际问题进行阅读;
mmc_card负责与linux上面的内核系统调用接口(即块设备子系统)对接,完成块设备的驱动请求与协议下发,通过mmc_core层的实现具体协议解析,下发到host完成对外挂的mmc子设备进行控制。
linux上各个子系统,一般都是以总线、Device、Driver的方式进行管理,mmc也补例外。
针对通信总线,抽象出mmc_bus;
针对mmc controller,该子系统抽象为mmc_host,用于描述一个进行设备通信的控制器,提供了相应的访问接口(记为mmc_host->request);
针对mmc、sd、SDIO等具体设备,该子系统抽象为mmc_card,用于描述卡信息。mmc子系统提供年rescan接口用于mmc card的注册;
针对mmc、sd、tf,mmc子系统完成了统一的mmc driver,针对mmc总线规范以及SD规范,其已经详细的定义了一个存储卡的通信方式、通信命令,因此LINUXmmc子系统定义了mmc driver,用于和mmc、sd、tf等卡的通信,而不需要驱动开发人员来开发卡驱动。
从mmc_rescan调用关系中可以看出,mmc设备注册的过程依次完成了sdio设备、sd卡和mmc卡设备的初始化。
SDIO卡初始化的入口
a. 向卡发送CMD5命令,该命令有两个作用:
第一,通过判断卡是否有反馈信息来判断是否为SDIO设备mmc_send_io_op_cond():
如果有响应,并且响应中的MP位为0,说明对应卡槽中的卡为SDIO卡,进而开始SDIO卡的初始化流程
如果命令没有响应,则说明对应卡槽的卡为SD或MMC卡,进而开始SD/MMC卡的初始化流程(sdio卡时有魄力sdio协议,sd卡使用sd协议)
如果有响应,且响应中的MP位为说明这个卡mmc_alloc_card不但是SDIO卡,同时也时SD卡,也就是所谓的combo卡,则进行combo卡的初始化流程mmc_sdio_ops)
第二,如果是SDIO设备,就会给host反馈电压信息,就是说告诉host,本卡所能支持的电压是多少多少。
b. 设置sdio卡的总线操作集mmc_attach_bus(),传入struct mmc_bus_ops类型的实现mmc_sdio_ops。
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
{
host->bus_ops = ops;
}
c. host根据SDIO卡反馈回来的电压要求,给其提供合适的电压mmc_select_voltage()
d. 对sdio卡进行探测和初始化mmc_sdio_init_card()
e. 注册SDIO的各个功能模块sdio_init_func()
f. 注册SDIO卡mmc_add_card()
g. 将所有SDIO功能添加到device架构中sdio_add_func()
mmc_alloc_card():
调用device模型对应的接口完成device类型变量的初始化,并完成mmc_card与mmc_host的绑定。
mmc_add_card():
调用device_add,完成将该mmc_card注册至mmc bus上;
设置mmc_card的状态为在位状态。
sdio func
sdio_func的注册与注销接口对应于mmc_card的注册与注销接口。主要函数有sdio_alloc_func、sdio_add_func、sdio_remove_func、sdio_release_func(相比mmc card,多了针对acpi的配置调用)
SD卡初始化的入口
a. 发送CMD41指令,(sd卡支持该指令,但mmc卡不支持,所以可以以此区分)mmc_send_app_op_cond()
b. 设置sdio卡的总线操作集mmc_attach_bus(),传入struct mmc_bus_ops类型的实现mmc_sd_ops。
c. 设置合适的电压mmc_select_voltage()
d. 调用mmc_sd_init_card()(探测和初始化),获取mmc card的csd、cid,并创建mmc_card,并对mmc card进行初始化(如是否只读等信息)
e.调用mmc_add_card(),将该mmc_card注册至mmc_bus中,该接口会调用device_register将mmc_card注册至mmc_bus上,而这即触发mmc_driver与mmc_card的绑定流程,从而调用mmc_driver->probe接口,即执行mmc block device的注册操作(待解决,没有找到device_register相关代码)。
mmc卡初始化入口
a. 发送CMD1指令mmc_send_op_cond()
b. 设置mmc卡的总线操作集mmc_attach_bus(),传入struct mmc_bus_ops类型的实现mmc_ops。
c. 选择一个card和host都支持的最低工作电压mmc_select_voltage()
d. 初始化card使其进入工作状态mmc_init_card()
e. 为card构造对应的mmc_card并且注册到mmc_bus中mmc_add_card(),之后mmc_card就挂在了mmc_bus上,会和mmc_bus上的block(mmc_driver)匹配起来。相应block(mmc_driver)就会进行probe,驱动card,实现card的实际功能(也就是存储设备的功能)。会对接到块设备子系统中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。