现在的位置: 首页 > 综合 > 正文

QualComm 8×50 上MMC host controller 驱动的初始化流程分析

2018年04月17日 ⁄ 综合 ⁄ 共 3059字 ⁄ 字号 评论关闭
 
下面是对QualComm 8x50 上MMC host controller 驱动的初始化流程分析.
分析基于kernel 2.6.29 版本 (主要的代码为 driver/mmc/msm_sdcc.c 和 msm_sdcc.h 以及 arch 下的代码)

1. MMC 中涉及的总线类型
MMC 目录中的代码主要涉及到三种总线, 一种是platform bus, MMC host controller
作为一种platform device
, 它是需要注册到platform bus上的。
另外两种是MMC自己创建的两种bus类型, 一种是 mmc bus type, 另一种是 sdio bus type. 它们是在mmc_init()中被创建的.通过调用 mmc_register_bus() 来注册 MMC 总线, 通过调用sdio_register_bus() 来注册 SDIO 总线.
当然 mmc bus 和 sdio bus 在 MMC host controller driver 的初始化中并没有被用到.
1.1 platform bus
the definition is in driver/base/platform.c
struct bus_type platform_bus_type = {
    .name        = "platform",
    .dev_attrs    = platform_dev_attrs,
    .match        = platform_match,
    .uevent        = platform_uevent,
    .pm        = PLATFORM_PM_OPS_PTR,
};

1.2 mmc bus type
static struct bus_type mmc_bus_type = {
    .name        = "mmc",
    .dev_attrs    = mmc_dev_attrs,
    .match        = mmc_bus_match,
    .uevent        = mmc_bus_uevent,
    .probe        = mmc_bus_probe,
    .remove        = mmc_bus_remove,
    .suspend    = mmc_bus_suspend,
    .resume        = mmc_bus_resume,
};

1.3 sdio bus type
static struct bus_type sdio_bus_type = {
    .name        = "sdio",
    .dev_attrs    = sdio_dev_attrs,
    .match        = sdio_bus_match,
    .uevent        = sdio_bus_uevent,
    .probe        = sdio_bus_probe,
    .remove        = sdio_bus_remove,
};

对于platform bus上的设备,通常初始化的流程是:
a. 在 platform bus上注册 platform device.
b. 在 platform bus上注册 platform driver.
c. 如果 platform bus 上的 device 和 driver 相互匹配, 则调用其 probe() 函数进行初始化.
对于SD host controller 设备也是一样.

2. MMC host controller device 的注册
MMC host controller 的硬件是嵌入在整个ap的芯片中的.因此如果在kernel中使能该MMC host controller 的配置,则在kernel的初始化中, MMC host controller device 将被注册.
在arch/arm/mach-xxx/<board-name>.c, 比如Qualcomm 的8x50,对应的文件是 board-qsd8x50.c, 设备的注册流程如下:
qsd8x50_init() -> qsd8x50_init_mmc() -> msm_add_sdcc() -> platform_device_register() 从而将其注册的platform bus上.
注册的device数据结构如下,它定义了该设备的一些资源.比如 MEM, IRQ, DMA.
struct platform_device msm_device_sdc1 = {
    .name        = "msm_sdcc",
    .id        = 1,
    .num_resources    = ARRAY_SIZE(resources_sdc1),
    .resource    = resources_sdc1,
    .dev        = {
        .coherent_dma_mask    = 0xffffffff,
    },
};

3. MMC host controller driver 的注册
在 driver/mmc/host/msm_sdcc.c 文件中,
msmsdcc_init() -> platform_driver_register() 从而将其注册到 platform bus 上.
static struct platform_driver msmsdcc_driver = {
    .probe        = msmsdcc_probe,
    .remove        = msmsdcc_remove,
    .suspend    = msmsdcc_suspend,
    .resume        = msmsdcc_resume,
    .driver        = {
        .name    = "msm_sdcc",
    },
};

platform_driver_register 的调用流程如下:
platform_driver_register()
driver_register()
bus_add_driver()
driver_attach()
bus_for_each_dev()
__driver_attach()
driver_probe_device()

在driver_probe_device()函数,它将调用总线的match函数。如果match的话,它将调用really_probe函数,在该函数中,将真正调用bus和driver的probe函数。

4. probe() 函数
在 MMC host controller driver 中的 probe() 函数为 msmsdcc_probe(). 它的处理流程如下.
a. get resource.
b. setup msm sdcc host structure.
c. setup DMA.
d. setup main peripheral bus clock.
e. setup SDC MMC clock.
f. setup MMC hsot structure.
g. setup card detect change.
h. setup a command timer.
总体来说, 就是初始化相关的数据结构, 并进行一些初始化设置.
下图是一个MMC中主要数据结构的关系图, probe() 函数主要是初始化 msmsdcc_host 和 mmc_host 数据结构,


5. MMC host controller driver 的对外接口
5.1 对上层的接口
msmsdcc_ops()
msmsdcc_status_notify_cb()

5.2 三个中断处理函数
msmsdcc_platform_status_irq()
msmsdcc_pio_irq()
msmsdcc_irq()

5.3 一个定时器
msmsdcc_command_expired

【上篇】
【下篇】

抱歉!评论已关闭.