linux块设备——mmc子系统

Linux的MMC/SD存储卡是一种典型的块设备,实现位于driver/mac中,分为card/core/host三层(最上面为文件系统)

  • card跟linux的块设备子系统对接,实现块设备的驱动请求,位于文件系统之下
  • core层实现具体的协议,一般指SDIO的协议
  • host实现具体的驱动

d1831917644c45f898fcb843b853c167.png

块设备与字符设备的差异

  1. 块设备在I/O操作中,贯穿始终的为请求,并对“请求”进行排队
  2. 不再包含类似字符设备的读写操作
  3. 块设备通常只是存储设备,不像字符设备那样五花八门(控制类、传感类、读写类等)

6efae08730f54d8a99e21c06fed556f0.png

主要分为三层:

  • mmc_card:负责与应用对接,实现mmc作为block块设备的驱动;
  • mmc_core:实现mmc/sd/sdio协议,其中包括
    • mmc 总线、sdio总线的实现
    • mmc device、mmc driver的注册接口、
    • mmc host与mmc card的注册与注销接口

mmc_core为mmc子系统标准接口,包括对各种sd/sdio协议的实现,因此代码健全,代码量大,且标准,完全安装协议来实现,建议根据实际问题进行阅读;

  • mmc_host:实现各个厂家关于mmc/scd/sdio控制器的驱动代码,最终操作mmc/sd/sdio卡的部分;

mmc_card负责与linux上面的内核系统调用接口(即块设备子系统)对接,完成块设备的驱动请求与协议下发,通过mmc_core层的实现具体协议解析,下发到host完成对外挂的mmc子设备进行控制。

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等卡的通信,而不需要驱动开发人员来开发卡驱动。
 

 SD卡/SDIO/MMC等子设备的探查

从mmc_rescan调用关系中可以看出,mmc设备注册的过程依次完成了sdio设备、sd卡和mmc卡设备的初始化。

A. mmc_attach_sdio()


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的配置调用)

B. mmc_attach_sd()


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相关代码)。

c. mmc_attach_mmc()


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的实际功能(也就是存储设备的功能)。会对接到块设备子系统中。
 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值