糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > Linux内核4.14版本——mmc core(2)——bus模块

Linux内核4.14版本——mmc core(2)——bus模块

时间:2018-12-31 21:23:48

相关推荐

Linux内核4.14版本——mmc core(2)——bus模块

1. 简介

2. API总览(drivers/mmc/core/bus.h)

2.1mmc bus相关

2.2mmc driver相关

2.3mmc card相关

3.mmc_bus_type数据结构

4.接口代码说明

4.1mmc_register_bus

4.2mmc_register_driver

4.3mmc_alloc_card

4.4mmc_add_card

5.相关节点

6. 参考文章

1. 简介

图片1 Linux MMC framework软件架构

有前文知道,MMC协议是一个总线协议,因此包括Host controller、Bus、Card三类实体(从左到右)。相应的,MMC framework抽象出了host、bus、card三个软件实体,以便和硬件一一对应:

host,负责驱动Host controller,提供诸如访问card的寄存器、检测card的插拔、读写card等操作方法。从设备模型的角度看,host会检测卡的插入,并向bus注册MMC card设备;

bus,是MMC bus的虚拟抽象,以标准设备模型的方式,收纳MMC card(device)以及对应的MMC driver(driver);

card,抽象具体的MMC卡,由对应的MMC driver驱动(从这个角度看,可以忽略MMC的技术细节,只需关心一个个具有特定功能的卡设备,如存储卡、WIFI卡、GPS卡等等)。

本文分析bus部分的内容,代码对应如下

drivers/mmc/core/bus.c

drivers/mmc/core/bus.h

2. API总览(drivers/mmc/core/bus.h)

struct mmc_card *mmc_alloc_card(struct mmc_host *host,struct device_type *type);int mmc_add_card(struct mmc_card *card);void mmc_remove_card(struct mmc_card *card);int mmc_register_bus(void);void mmc_unregister_bus(void);int mmc_register_driver(struct mmc_driver *drv);void mmc_unregister_driver(struct mmc_driver *drv);

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

2.1mmc bus相关

int mmc_register_bus(void);void mmc_unregister_bus(void);

2.2mmc driver相关

int mmc_register_driver(struct mmc_driver *drv);void mmc_unregister_driver(struct mmc_driver *drv);

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

2.3mmc card相关

struct mmc_card *mmc_alloc_card(struct mmc_host *host,struct device_type *type);int mmc_add_card(struct mmc_card *card);void mmc_remove_card(struct mmc_card *card);

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

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

3.mmc_bus_type数据结构

static struct bus_type mmc_bus_type = {.name = "mmc",// 相应会在/sys/bus下生成mmc目录.dev_groups= mmc_dev_groups,.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是无条件匹配的。

4.接口代码说明

4.1mmc_register_bus

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。

4.2mmc_register_driver

int mmc_register_driver(struct mmc_driver *drv){drv->drv.bus = &mmc_bus_type;return driver_register(&drv->drv);}

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

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

4.3mmc_alloc_card

/** Allocate and initialise a new MMC card structure.*/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); // (1)if (!card)return ERR_PTR(-ENOMEM);card->host = host; // (2)device_initialize(&card->dev);card->dev.parent = mmc_classdev(host); // (3)card->dev.bus = &mmc_bus_type; // (4)card->dev.release = mmc_release_card;card->dev.type = type;return card;}

(1) 分配一个mmc_card。

(2)关联mmc_card与mmc_host。

(3)设置card的device的parent device为mmc_host的classdev,注册到设备驱动模型中之后,会在/sys/class/mmc_host/mmc0目录下生成相应card的节点,如mmc0:0001。

(4)设置card的bus为mmc_bus_type,这样,mmc_card注册到设备驱动模型中之后就会挂在mmc_bus下。会在/sys/bus/mmc/devices/目录下生成相应card的节点,如mmc0:0001

4.4mmc_add_card

/** Register a new MMC card with the driver model.*/int mmc_add_card(struct mmc_card *card){int ret;const char *type;const char *uhs_bus_speed_mode = "";// 设置速度模式的字符串,为了后面打印出card信息static const char *const uhs_speeds[] = {[UHS_SDR12_BUS_SPEED] = "SDR12 ",[UHS_SDR25_BUS_SPEED] = "SDR25 ",[UHS_SDR50_BUS_SPEED] = "SDR50 ",[UHS_SDR104_BUS_SPEED] = "SDR104 ",[UHS_DDR50_BUS_SPEED] = "DDR50 ",};dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);switch (card->type) {case MMC_TYPE_MMC:type = "MMC";break;case MMC_TYPE_SD:type = "SD";if (mmc_card_blockaddr(card)) {if (mmc_card_ext_capacity(card))type = "SDXC";elsetype = "SDHC";}break;case MMC_TYPE_SDIO:type = "SDIO";break;case MMC_TYPE_SD_COMBO:type = "SD-combo";if (mmc_card_blockaddr(card))type = "SDHC-combo";break;default:type = "?";break;}if (mmc_card_uhs(card) &&(card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];if (mmc_host_is_spi(card->host)) {pr_info("%s: new %s%s%s card on SPI\n",mmc_hostname(card->host),mmc_card_hs(card) ? "high speed " : "",mmc_card_ddr52(card) ? "DDR " : "",type);} else {pr_info("%s: new %s%s%s%s%s%s card at address %04x\n",mmc_hostname(card->host),mmc_card_uhs(card) ? "ultra high speed " :(mmc_card_hs(card) ? "high speed " : ""),mmc_card_hs400(card) ? "HS400 " :(mmc_card_hs200(card) ? "HS200 " : ""),mmc_card_hs400es(card) ? "Enhanced strobe " : "",mmc_card_ddr52(card) ? "DDR " : "",uhs_bus_speed_mode, type, card->rca);}#ifdef CONFIG_DEBUG_FS/* 设置card的debug节点 *//* 创建card对应的debug节点,对应路径例如:/sys/kernel/debug/mmc0/mmc0:0001 */mmc_add_card_debugfs(card);#endifmmc_init_context_info(card->host); // 初始化同步的文本信息card->dev.of_node = mmc_of_find_child_device(card->host, 0);/* 使能异步device suspend,初始化runtime_pm_timeout属性 */device_enable_async_suspend(&card->dev);/* 添加到设备驱动模型中 *//* 会创建/sys/bus/mmc/devices/mmc0:0001节点和/sys/class/mmc_host/mmc0/mmc0:0001节点 */ ret = device_add(&card->dev);if (ret)return ret;/* 设置mmc card的state标识 *//* 设置card的MMC_STATE_PRESENT状态#define MMC_STATE_PRESENT (1<<0) 表示card已经合入到sysfs中了*/mmc_card_set_present(card);return 0;}

5.相关节点

/sys/bus/mmc/devices/mmc0:0001

/sys/class/mmc_host/mmc0/mmc0:0001

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

6. 参考文章

[mmc subsystem] mmc core(第三章)——bus模块说明_ooonebook的博客-CSDN博客

如果觉得《Linux内核4.14版本——mmc core(2)——bus模块》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。