基于QualComm的mmc driver解析(Kernel-3.10)——(1)mmc bus

MMC:MMC就是 MultiMediaCard 的缩写,即多媒体卡
SD:SD卡为Secure Digital Memory Card, 即安全数码卡,(另TF卡又称microSD)
SDIO:SDIO是在SD标准上定义了一种外设接口
MCI:MCI是Multimedia Card Interface的简称,即多媒体卡接口。上述的MMC,SD,SDI卡定义的接口都属于MCI接口

SD卡引脚:
一根指令线CMD,4根数据线DAT0~DAT3,一个 SDCARD_DET_N 检测引脚。

MMC driver有3个层次,包括card,core和host layer。这三个层次的源码在以下的目录下:

kernel/drivers/mmc

我们可以看makefile来确定哪些文件被编译了。

各个目录的功能:

  • core:提供了mmc_bus、sdio_bus以及mmc和sd卡的操作的实现代码;
  • host:基于硬件平台的emmc controller的驱动代码;
  • card:对块操作封装的驱动;

MMC bus

core/core.c 中的mmc_init 函数中注册了mmc_bus 和 sdio bus:

static int __init mmc_init(void)
{
    int ret;

    workqueue = alloc_ordered_workqueue("kmmcd", 0);
    if (!workqueue)
        return -ENOMEM;

    ret = mmc_register_bus();//注册mmc bus
    if (ret)
        goto destroy_workqueue;

    ret = mmc_register_host_class();//创建/sys/class/mmc_host节点
    if (ret)
        goto unregister_bus;

    ret = sdio_register_bus();//注册sdio bus
    if (ret)
        goto unregister_host_class;

    return 0;

unregister_host_class:
    mmc_unregister_host_class();
unregister_bus:
    mmc_unregister_bus();
destroy_workqueue:
    destroy_workqueue(workqueue);

    return ret;
}

mmc_register_bus 在bus.c 文件中:

int mmc_register_bus(void)
{
    return bus_register(&mmc_bus_type);
}

该函数向总线注册了mmc总线,结构体是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,
    .shutdown        = mmc_bus_shutdown,
    .pm     = &mmc_bus_pm_ops,
};
  1. mmc_dev_attrs 注册了一个type接口,可以返回当前卡的类型:mmc、SD、SDIO、SDcombo,
static ssize_t mmc_type_show(struct device *dev,
    struct device_attribute *attr, char *buf)
{
    struct mmc_card *card = mmc_dev_to_card(dev);

    switch (card->type) {
    case MMC_TYPE_MMC:
        return sprintf(buf, "MMC\n");
    case MMC_TYPE_SD:
        return sprintf(buf, "SD\n");
    case MMC_TYPE_SDIO:
        return sprintf(buf, "SDIO\n");
    case MMC_TYPE_SD_COMBO:
        return sprintf(buf, "SDcombo\n");
    default:
        return -EFAULT;
    }
}

static struct device_attribute mmc_dev_attrs[] = {
    __ATTR(type, S_IRUGO, mmc_type_show, NULL),
    __ATTR_NULL,
};
  1. mmc_bus_match 是总线匹配函数,一直返回1:
static int mmc_bus_match(struct device *dev, struct device_driver *drv)
{
    return 1;
}
  1. mmc_bus_uevent 当卡拔插等事件发生的时候,内核向用户空间发送事件,使得用户空间可以动态加载驱动模块:
static int
mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
{
    struct mmc_card *card = mmc_dev_to_card(dev);
    const char *type;
    int retval = 0;

    switch (card->type) {
    case MMC_TYPE_MMC:
        type = "MMC";
        break;
    case MMC_TYPE_SD:
        type = "SD";
        break;
    case MMC_TYPE_SDIO:
        type = "SDIO";
        break;
    case MMC_TYPE_SD_COMBO:
        type = "SDcombo";
        break;
    default:
        type = NULL;
    }

    if (type) {
        retval = add_uevent_var(env, "MMC_TYPE=%s", type);
        if (retval)
            return retval;
    }

    retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card));
    if (retval)
        return retval;

    /*
     * Request the mmc_block device.  Note: that this is a direct request
     * for the module it carries no information as to what is inserted.
     */
    retval = add_uevent_var(env, "MODALIAS=mmc:block");

    return retval;
}
  1. mmc_bus_probe 调用driver的probe 函数:
static int mmc_bus_probe(struct device *dev)
{
    struct mmc_driver *drv = to_mmc_driver(dev->driver);
    struct mmc_card *card = mmc_dev_to_card(dev);

    return drv->probe(card);
}
  1. mmc_bus_remove remove bus:
static int mmc_bus_remove(struct device *dev)
{
    struct mmc_driver *drv = to_mmc_driver(dev->driver);
    struct mmc_card *card = mmc_dev_to_card(dev);

    drv->remove(card);

    return 0;
}
  1. mmc_bus_shutdown 调用driver的shutdown 函数:
static void mmc_bus_shutdown(struct device *dev)
{
    struct mmc_driver *drv = to_mmc_driver(dev->driver);
    struct mmc_card *card = mmc_dev_to_card(dev);

    if (!drv) {
        pr_debug("%s: %s: drv is NULL\n", dev_name(dev), __func__);
        return;
    }

    if (!card) {
        pr_debug("%s: %s: card is NULL\n", dev_name(dev), __func__);
        return;
    }

    if (drv->shutdown)
        drv->shutdown(card);
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值