zoukankan      html  css  js  c++  java
  • 3. [mmc subsystem] mmc core(第三章)——bus模块说明

    零、说明

    对应代码drivers/mmc/core/bus.c。

    抽象出虚拟mmc bus,实现mmc bus的操作。

    一、API总览

    1、mmc bus相关

    • mmc_register_bus & mmc_unregister_bus

    用于注册和卸载mmc bus(虚拟mmc总线)到设备驱动模型中。

        原型:int mmc_register_bus(void)
        原型:void mmc_unregister_bus(void)
    

    2、mmc driver相关

    • mmc_alloc_card & mmc_release_card

    3、mmc card相关

    • mmc_alloc_card & mmc_release_card

    用于分配或者释放一个struct mmc_card结构体,创建其于mmc host以及mmc bus之间的关联。

    原型:struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
        参数说明:host——》要分配的card所属的mmc_host,type——》对应的device type。
    
        原型:static void mmc_release_card(struct device *dev)
    
    • mmc_add_card & mmc_remove_card

    用于注册或者卸载struct mmc_card到mmc_bus上。

    原型:int mmc_add_card(struct mmc_card *card)
    原型:void mmc_remove_card(struct mmc_card *card)
    

    二、数据结构

    1、mmc_bus_type

    mmc_bus_type代表了mmc虚拟总线。其内容如下:

    static struct bus_type mmc_bus_type = {
        .name       = "mmc",                        // 相应会在/sys/bus下生成mmc目录
        .dev_attrs  = mmc_dev_attrs,                  // bus下的device下继承的属性,可以看到/sys/bus/mmc/devices/mmc0:0001/type属性就是这里来的
        .match      = mmc_bus_match,       // 用于mmc bus上device和driver的匹配
        .uevent     = mmc_bus_uevent,
        .probe      = mmc_bus_probe,       // 当match成功的时候,执行的probe操作
        .remove     = mmc_bus_remove,
        .shutdown        = mmc_bus_shutdown,
        .pm     = &mmc_bus_pm_ops,         // 挂在mmc bus上的device的电源管理操作集合
    };
    
    /***************************match方法***************************/
    static int mmc_bus_match(struct device *dev, struct device_driver *drv)
    {
        return 1;      // 无条件返回1,说明挂载mmc bus上的device(mmc_card)和driver(mmc_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);   // 直接调用mmc_driver中的probe操作,对于block.c来说就是mmc_blk_probe
    }
    

    补充说明,通过上述mmc_bus的match方法实现,我们可以知道挂载mmc bus上的mmc_card和mmc_driver是无条件匹配的。

    三、接口代码说明

    1、mmc_register_bus实现

    用于注册mmc bus(虚拟mmc总线)到设备驱动模型中。

    int mmc_register_bus(void)
    {
        return bus_register(&mmc_bus_type);    // 以mmc_bus_type为bus_type注册一条虚拟bus,关于mmc_bus_type上面已经说明过了
    }
    

    后续我们将mmc_bus_type的这条bus称之为mmc_bus。

    相关节点:/sys/bus/mmc。

    2、mmc_register_driver实现

    用于注册struct mmc_driver *drv到mmc_bus上。mmc_driver就是mmc core抽象出来的card设备driver。

    int mmc_register_driver(struct mmc_driver *drv)
    {
        drv->drv.bus = &mmc_bus_type;    // 通过设置mmc_driver——》device_driver——》bus_type来设置mmc_driver所属bus为mmc_bus
        return driver_register(&drv->drv);    // 这样就将mmc_driver挂在了mmc_bus上了。
    }
    

    相关节点:/sys/bus/mmc/drivers.

    3、mmc_alloc_card实现

    用于分配一个struct mmc_card结构体,创建其于mmc host以及mmc bus之间的关联。

    struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
    {
        struct mmc_card *card;
    
        card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);    // 分配一个mmc_card
        if (!card)
            return ERR_PTR(-ENOMEM);
    
        card->host = host;        // 关联mmc_card与mmc_host 
    
        device_initialize(&card->dev);
    
        card->dev.parent = mmc_classdev(host);    
            // 设置card的device的parent device为mmc_host的classdev,
            // 注册到设备驱动模型中之后,会在/sys/class/mmc_host/mmc0目录下生成相应card的节点,如mmc0:0001
        card->dev.bus = &mmc_bus_type;
            // 设置card的bus为mmc_bus_type,这样,mmc_card注册到设备驱动模型中之后就会挂在mmc_bus下。
            // 会在/sys/bus/mmc/devices/目录下生成相应card的节点,如mmc0:0001
        card->dev.release = mmc_release_card;
        card->dev.type = type;    // 设置device type
    
        spin_lock_init(&card->bkops_info.bkops_stats.lock);    // 初始化spin_lock
        spin_lock_init(&card->wr_pack_stats.lock);                   // 初始化spin_lock
    
        return card;
    }
    

    4、mmc_add_card实现

    用于注册struct mmc_card到mmc_bus上。

    /*
     * Register a new MMC card with the driver model.
     */
    int mmc_add_card(struct mmc_card *card)
    {
        int ret;
    
    /* 以下用于打印card的注册信息 */
        const char *type;
        const char *uhs_bus_speed_mode = "";
            // 设置速度模式的字符串,为了后面打印出card信息
            //......
    
        if (mmc_host_is_spi(card->host)) {
            pr_info("%s: new %s%s%s card on SPI
    ",
                mmc_hostname(card->host),
                mmc_card_highspeed(card) ? "high speed " : "",
                mmc_card_ddr_mode(card) ? "DDR " : "",
                type);
        } else {
            pr_info("%s: new %s%s%s%s%s%s card at address %04x
    ",
                mmc_hostname(card->host),
                mmc_card_uhs(card) ? "ultra high speed " :
                (mmc_card_highspeed(card) ? "high speed " : ""),
                (mmc_card_hs400(card) ? "HS400 " : ""),
                (mmc_card_hs200(card) ? "HS200 " : ""),
                mmc_card_ddr_mode(card) ? "DDR " : "",
                uhs_bus_speed_mode, type, card->rca);
        }
            // 在这里会打印出card信息的字符串
            // eg:mmc0: new HS200 MMC card at address 0001
    
    /* 设置card的debug节点 */
    #ifdef CONFIG_DEBUG_FS
        mmc_add_card_debugfs(card);
            // 创建card对应的debug节点,对应路径例如:/sys/kernel/debug/mmc0/mmc0:0001
    #endif
        mmc_init_context_info(card->host);   // 初始化同步的文本信息
    
    /* 以下使能card device的pm runtime的功能 */
        ret = pm_runtime_set_active(&card->dev);   
        if (ret)
            pr_err("%s: %s: failed setting runtime active: ret: %d
    ",
                   mmc_hostname(card->host), __func__, ret);
        else if (!mmc_card_sdio(card) && mmc_use_core_runtime_pm(card->host))
            pm_runtime_enable(&card->dev);
    
    /* 添加到设备驱动模型中 */
        ret = device_add(&card->dev);
            // 会创建/sys/bus/mmc/devices/mmc0:0001节点和/sys/class/mmc_host/mmc0/mmc0:0001节点
    
    /* 使能异步device suspend,初始化runtime_pm_timeout属性 */
        device_enable_async_suspend(&card->dev);
        if (mmc_use_core_runtime_pm(card->host) && !mmc_card_sdio(card)) {
            card->rpm_attrib.show = show_rpm_delay;
            card->rpm_attrib.store = store_rpm_delay;
            sysfs_attr_init(&card->rpm_attrib.attr);
            card->rpm_attrib.attr.name = "runtime_pm_timeout";
            card->rpm_attrib.attr.mode = S_IRUGO | S_IWUSR;
    
            ret = device_create_file(&card->dev, &card->rpm_attrib);
            if (ret)
                pr_err("%s: %s: creating runtime pm sysfs entry: failed: %d
    ",
                       mmc_hostname(card->host), __func__, ret);
            /* Default timeout is 10 seconds */
            card->idle_timeout = RUNTIME_SUSPEND_DELAY_MS;
        }
    
    /* 设置mmc card的state标识 */
        mmc_card_set_present(card);
            // 设置card的MMC_STATE_PRESENT状态
            // #define MMC_STATE_PRESENT    (1<<0)      /* present in sysfs */
            // 表示card已经合入到sysfs中了
    
        return 0;
    }
    

    相关节点:
    /sys/bus/mmc/devices/mmc0:0001
    /sys/class/mmc_host/mmc0/mmc0:0001

    /sys/kernel/debug/mmc0/mmc0:0001

  • 相关阅读:
    Netty学习笔记——(一)
    [feather]StarlingUi框架——组件库及渲染器
    [feather]StarlingUi框架——Screen及界面导航
    [feather]StarlingUi框架——feather抱怨
    [feather]StarlingUi框架——初识feather、界面启动及Ui加载
    Shader Language是什么
    GPU图形绘制管线总结
    ActionScript学习笔记(九)——坐标旋转、角度回弹与台球物理
    ActionScript学习笔记(八)——碰撞检测
    使用Javascript类库Qrcode处理和生成二维码
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/10790128.html
Copyright © 2011-2022 走看看