LINUX I2C设备驱动模型分析之二 总线部分分析

       上一章我们对I2C模块做了总体框架的分析,本章我们主要分析下I2C模块的总线部分,主要涉

及总线初始化、总线相关属性、总线相关接口函数处理等几部分

I2c bus的定义

I2c bus的定义如下,主要定义了i2c总线的匹配检测接口、探测接口、移除接口以及电源管理相关的接口。

struct bus_type i2c_bus_type = {
    /*总线的名称,同时也是在sysfs目录下创建子目录的名称*/
	.name		= "i2c",
	/
    /*该接口用于验证i2c device与i2c driver是否匹配*/
	.match		= i2c_device_match,
	/*当device与driver匹配后,则调用该总线的probe接口对设备进行探测*/
	.probe		= i2c_device_probe,
	/*当设备或驱动注销时(调用device_unregister、driver_unregister),调用该接口
    进行注销操作*/
	.remove		= i2c_device_remove,
	/*以下两个变量,为电源管理相关的接口*/
	.shutdown	= i2c_device_shutdown,
	.pm		= &i2c_device_pm_ops,
};

i2c_device_match接口分析

该接口主要实现i2c device与i2c driver匹配检测,该接口的实现流程如下

  • 首先是调用of_driver_match_device进行匹配,当系统中支持设备树时,则可以通过该接口进行匹配检测,主要是对drv->of_match_table与dev->of_node间变量的匹配;

              若需要让我们的i2c driver支持OF(也即设备树),则只需设置i2c_driver->driver->of_match_table即可。我们以一个例             子说明,如下即为支持OF模块的i2c驱动,只要完成了这个操作,即可支持OF模块的匹配操作(当然了若要支持设备                  树,在probe接口中,同样需要调用设备树节点相关的接口,去获取该设备相关的资源,然后进行探测(这也是我们在                        platform模块所说的资源与驱动的抽离))

	static const struct of_device_id i2c_imx_dt_ids[] = {
	        { .compatible = "fsl,imx1-i2c", .data = &imx1_i2c_hwdata, },
	        { .compatible = "fsl,imx21-i2c", .data = &imx21_i2c_hwdata, },
	        { .compatible = "fsl,vf610-i2c", .data = &vf610_i2c_hwdata, },
	        { /* sentinel */ }
	
	static struct platform_driver i2c_imx_driver = {
	        .probe = i2c_imx_probe,
	        .remove = i2c_imx_remove,
	        .driver = {
	                .name = DRIVER_NAME,
	                .pm = I2C_IMX_PM_OPS,
	                .of_match_table = i2c_imx_dt_ids,
	        },
	        .id_table = imx_i2c_devtype,
};
  • 当第一种匹配不成功时,则调用acpi_driver_match_devuce针对支持acpi的设备与驱动,调用该接口继续进行匹配(对acpi不熟悉,此处先跳过);
  • 当以上两种方式均没有匹配时,则调用i2c_match_id进行设备与驱动的匹配,主要是将i2c_client->name与i2c_driver->id_table中所支持的设备名称进行匹配。

i2c_device_probe接口分析

该接口为i2c总线的probe,该接口一般也就是调用driver的probe接口,实现探测操作。

该接口的流程图如下,相对来说还是比较简单的,我们主要说些i2c模块相关的实现:

  1. 首先根据dev->type是否为i2c_client_type来确定是否需要进行设备与驱动的绑定操作,这主要是因为i2c_adapter、i2c_client均会注册到i2c总线上,此处即为区分i2c_clinet、i2c_adapter。
  2. 当区分i2c_client后,则直接调用i2c_driver->probe,而不是直接调用device_driver->probe,其实大多数模块device_driver->probe与其xxx_driver->probe是相同的。

i2c_device_remove接口分析

该接口的调用流程与i2c_device_probe接口类似,首先也要确认该device是否为i2c_adapter,若为i2c_adapter,则不需要进行设备与驱动的解绑操作。

针对i2c_client,则直接调用其绑定i2c_driver->remove接口进行移除操作,并完成设备与驱动的解绑定操作。

 

 

i2c_device_match、i2c_device_remove、i2c_device_probe何时调用

上面介绍了这三个函数,下面来说明下这三个函数的调用关系及何时调用。

针对i2c_device_probe、i2c_device_match接口,在i2c_client、i2c_adapte、i2c driver注册时(通过调用device_register、driver_register接口)而实现调用,函数调用关系图如下:

其中绿色箭头相关的流程图,为i2c_device_probe接口的调用路径。i2c模块借助设备驱动模型中设备与驱动的注册接口,完成了针对i2c设备和驱动的绑定及探测操作。

 

 

        针对i2c_device_remove接口,当从i2c总线上注销i2c设备或i2c驱动时,会执行到i2c_device_remove接口。借助设备驱动模型的设备注销与驱动注销接口,完成i2c设备或者i2c驱动的注销以及设备与驱动间的解绑定操作。

     

以上即是i2c总线变量的定义、操作接口分析以及接口间的调用关系。

 

I2c bus的注册

 

在i2c_init接口中通过调用bus_register,进行i2c总线的注册。当完成i2c bus的注册后,则i2c_bus_type以及其关联的kset、kobject、sysfs_dirent、i2c bus的属性文件、i2c属性文件的操作方式的关联,就已经建立完成,这些结构体类型的变量关联图如下图所示(这张图在之前介绍设备驱动模型时已经给出过,此处为了让不熟悉的朋友也能快速了解,又放在此处,加深记忆)。

此处不再细说bus_register,想了解的朋友,请查看以前的分析文档。此处就说下如下这张图。

  1. 将i2c_bus_type对应的kobject链接至系统的bus_kset,同时将bus_kset对应的kobject作为其父kobject(通过这种父子关系,以及kobject对应sysf的目录,实现在/sys/bus/目录下创建i2c子目录,即/sys/bus/i2c)。
  2. 为i2c_bus_type创建device与driver对应的kset,且devices_kset、drivers_kset对应的kobject,其父对象即为i2c_bus_type对应的kobject,因此完成/sys/bus/i2c/devices、/sys/bus/i2c/drivers目录的创建;
  3. 针对i2c_bus_type来说,没有定义特定的属性,只有通用的属性bus_attr_uevent、bus_attr_drivers_probe、bus_attr_drivers_probe,而根据这三个属性在sysfs下创建对应的文件drivers_autoprobe  drivers_probe  uevent(/sys/bus/i2c/目录下),而针对这三个文件的读写接口,通过i2c_bus_type的kobj_type的sysfs_ops->bus_attr_show、sysfs_ops->bus_attr_store接口,然后再调用者三个属性所定义的show/store接口。

        以上便是i2c总线的介绍,内容相对来说也不是很难,大部分内容都和之前分析的LINUX内核设备驱动总线模型的内容是相似的。下一篇将i2c device、i2c driver放在一起分析,因为我们在熟悉LINUX内核设备驱动模型的基础上,分析i2c device、i2c driver则会游刃有余。

发布了140 篇原创文章 · 获赞 30 · 访问量 45万+

猜你喜欢

转载自blog.csdn.net/lickylin/article/details/103058295
今日推荐