现在的Linux内核中,mmc不仅是一个驱动,而是一个子系统。这里通过分析Linux3.2.0内核,结合TI的arm335x平台及omap_hsmmcd host分析下mmc子系统,重点关注sdio及架构在其上的具体sdio IP驱动实现。
1. General overview
1.1 源码概览
Linux kernel把mmc,sd以及sdio三者的驱动代码整合在一起,俗称mmc子系统。源码位于drivers/mmc下。其下有三个子目录,分别是:
其中,card用于构建一个块设备作为上层与mmc子系统沟通的桥梁;core抽象了mmc,sd,sdio三者的通用操作;host则是各类平台上的host驱动代码,包括如TI Omap的omap_hsmmc,三星的s3cmci等。
1.2 硬件层IP对象间的联系
即,cpu要访问slave必须通过host进行,包括slave的中断。omap host的具体组成及其与slave之间的连线如图1.1所示:
图1.1
和别的中断控制器一样,host的MPU中断子系统有一个仲裁机制,分别使用IE和ISE控制是否向CPU报中断以及是否care slave报出来的中断。
Host在数据传输时支持8bit模式,但slave是sdio时仅支持1-bit & 4-bit模式,当支持4-bit模式时,data1和IRQ线复用。
注意:MMCHS的smart-idle wake up line(SWAKEUP)没有连出去,在别的一些host中,它是和PRCM子系统连接,用于在MMCHS处于suspend时自动提醒PRCM给MMCHS提供clock。
2. 从bus,driver,device看mmc子系统
Linux下的任何驱动在内核中最终都抽象为bus, driver以及device三者间的相互作用。
2.1 mmc下的bus,driver,device模型
Mmc子系统涉及到三条总线。
Host驱动相应的driver和device挂载在Linux内核内置的虚拟抽象总线platform_bus_type。两者的匹配采用名称匹配的方式,即driver和device两者的name一样则认为该device对应该driver,这里是”omap_hsmmc”。
Card驱动相应的driver和device挂载在mmc自己创建的虚拟总线mmc_bus_type下,直接匹配。
Sdio驱动相应的driver和device挂载在mmc自己创建的虚拟总线sdio_bus_type下,ID匹配。
注意:Linux内核中,匹配函数默认使用bus注册的匹配函数,如果bus没有注册则使用driver注册的匹配函数。所以,一般自己创建虚拟总线时,其匹配函数和driver的匹配函数都是一致的。
2.2 按时间顺序观察mmc中各bus,driver,device对象初始化流程
2.2.1 Host device对象
Host device对象首先被初始化并挂载到platform_bus_type,但是这个过程不在mmc子系统源码下,它在平台初始化过程中init了,具体的流程参考5.1。
2.2.2 mmc_bus,sdio_bus对象
core初始化时,件core.c中的subsys_initcall(mmc_init)创建这两条mmc自己的虚拟总线。