0.层次关系
# 1.各平台 mmc host controler 驱动 qcom/freescale/atmel
/*---------------------------------------------------------------------------------*/
# 2.mmc控制器驱动相关接口函数,有些平台的控制器驱动不需要, 比如freescale、atmle
#drivers/mmc/host/sdhci.c (Secure Digital Host Controller Interface support)
/*--------------------------------------------------------------------------------*/
# 3.核心层
#drivers/mmc/core/mmc.c // mmc
#drivers/mmc/core/sdio.c // sdio
#drivers/mmc/core/sd.c // sdcard
/*-----------------------------------------*/
#drivers/mmc/core/core.c
#drivers/mmc/core/host.c
/*---------------------------------------------------------------------------------*/
1.framwork层核心函数 mmc_rescan
sdcard热插拔逻辑都在此函数中
#(drivers/mmc/core/core.c)
mmc_rescan
mmc_rescan_try_freq
/*
将依次尝试给sdio、sdcard、mmc上电
— 如果上电失败则表示不是此设备插入,继续尝试下一个设备的attach
- 如果上电成功
1. 注册SD总线上的操作函数 - struct mmc_bus_ops mmc_sd_ops
2. 设置主控制器的时钟和总线方式 - 通过回调函数host->ops->set_ios();
3. 启动SD卡 - 根据协议,完成SD卡启动的各个步骤
*/
if (!mmc_attach_sdio(host)) //sdio.c
return 0;
if (!mmc_attach_sd(host)) // sd.c
return 0;
if (!mmc_attach_mmc(host)) // mmc.c
return 0;
1.1 继续追踪 mmc_attach_sd 函数
mmc_attach_sd
mmc_send_app_op_cond // 尝试上电,上电不成功直接return
mmc_sd_attach_bus_ops // 注册sd总线上的操作函数 (sd.c 中的总线相关操作函数)
mmc_sd_init_card
mmc_set_clock(host, mmc_sd_get_max_clock(card)); // 根据卡的类型自动获取最大的时钟速率
...
host->ops->set_ios(host, ios); // 调用host->ops->set_ios设置bus时钟
1.各平台 mmc host controler 驱动
# drivers/mmc/host/msm_sdcc.c Qualcomm SDCC Controller Support
# drivers/mmc/host/mxs-mmc.c Freescale MXS Multimedia Card Interface support
# drivers/mmc/host/atmel-mci.c Atmel SD/MMC Driver Multimedia Card Interface
1.1 关于两个中断
一个为SD主控制器芯片内电路固有的内部中断,另一个为探测引脚的探测到外部有SD卡插拔引起的中断。
(1) 控制器内部中断
当调用(*request),即host->ops->request(host, mrq) (2.2节重要结构),即上文中的 sdhci_request() 后,控制器与SD卡之间开始进行一次指令或数据传输,
通信完毕后,主控芯片将产生一个内部中断,以告知此次指令或数据传输完毕。这个中断的具体值将保存在一个名为MMC_I_REG的中断寄存器中以供读取,
(2) 探测sdcard插拔引脚中断
检测sdcard的插拔,中断处理函数调用 core.c中的 mmc_detect_change -> mmc_rescan检测状态变化。
mmc_detect_change
mmc_schedule_delayed_work(&host->detect, delay); -》 INIT_DELAYED_WORK(&host->detect, mmc_rescan); // host.c
mmc_rescan
2.mmc控制器驱动相关接口函数
有些平台的控制器驱动不需要, 比如freescale、atmle
# drivers/mmc/host/sdhci.c (Secure Digital Host Controller Interface support)
2.1 主要函数
(1)sdhci_add_host // 核心函数 :对 struct mmc_host *mmc->ops 进行了赋值
request_irq(host->irq, sdhci_irq, IRQF_SHARED,mmc_hostname(mmc), host); // mmc控制器内部中断,数据或指令传输完成会产生一个中断(中断名以host名字命名)
(2)sdhci_irq // host内部中断数据或指令传输完成函数
// 读取中断状态寄存器
intmask = sdhci_readl(host, SDHCI_INT_STATUS);
// cmd 传输完毕
if (intmask & SDHCI_INT_CMD_MASK)
{
sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK,SDHCI_INT_STATUS);
sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
}
// data 传输完毕
if (intmask & SDHCI_INT_DATA_MASK)
{
sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK,
SDHCI_INT_STATUS);
sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
}
2.2 主要结构
host 驱动的驱动能力 struct mmc_host_ops
static const struct mmc_host_ops sdhci_ops = {
.pre_req = sdhci_pre_req,
.post_req = sdhci_post_req,
/*以上通过pxamci_request()实现了主控制器的通信功能,之后只须通过host->ops->request(host, mrq);回调函数即可。
协议层里,每条指令都会通过mmc_wait_for_req(host, &mrq)调用到host->ops->request(host, mrq)来发送指令和数据。*/
.request = sdhci_request, // 它是整个SD主控制器驱动的核心,实现了SD主控制器能与SD卡进行通信的能力 ☆
.set_ios = sdhci_set_ios, // ☆ 为主控制器设置总线和时钟等配置
.get_ro = sdhci_get_ro, // 得到只读属性
.hw_reset = sdhci_hw_reset,
.enable_sdio_irq = sdhci_enable_sdio_irq, //开启sdio中断
.start_signal_voltage_switch = sdhci_start_signal_voltage_switch,
.execute_tuning = sdhci_execute_tuning,
.enable_preset_value = sdhci_enable_preset_value,
.enable = sdhci_enable,
.disable = sdhci_disable,
.stop_request = sdhci_stop_request,
.get_xfer_remain = sdhci_get_xfer_remain,
.notify_load = sdhci_notify_load,
};
3.框架层
drivers/mmc/core/core.c
3.1 核心函数
// mmc、sdcard scanf、add、remove工作
mmc_rescan
----------
// 中断检测到sdcard变化调用 mmc_rescan 进行add/remove 操作;第二个参数是防抖操作,考虑到插入SD卡需要一个短时间的过程
mmc_detect_change(struct mmc_host *host, unsigned long delay)
----------
// 调用host->ops->request 完成和sdcard的通讯。
mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
drivers/mmc/core/host.c
4.结构体和层次关系
4.1 主控制器 mmc host controler
—— SD卡的控制器芯片,可以看成CPU的代言人,它为CPU分担了完成与SD卡数据通信的任务
—— struct mmc_host *mmc,此mmc指针指向不同平台芯片SD卡控制器的一个具体化对象。
4.2 mmc_host 的具体化对象列举
# msm_sdcc.c Qualcomm SDCC Controller Support
struct msmsdcc_host {
struct mmc_host *mmc;
struct resource *cmd_irqres;
struct resource *memres;
struct resource *dmares;
void __iomem *base;
int pdev_id;
unsigned int stat_irq;
struct msmsdcc_curr_req curr;
...
...
}
----------
# mxs-mmc.c Freescale MXS Multimedia Card Interface support
struct mxs_mmc_host {
struct mxs_ssp ssp;
struct mmc_host *mmc;
struct mmc_request *mrq;
struct mmc_command *cmd;
struct mmc_data *data;
...
...
}
----------
# atmel-mci.c Atmel SD/MMC Driver Multimedia Card Interface
struct atmel_mci_slot {
struct mmc_host *mmc;
struct atmel_mci *host;
u32 sdc_reg;
u32 sdio_irq;
struct mmc_request *mrq;
struct list_head queue_node;