LINUX I2C设备驱动模型分析之四 I2C CLIENT 与DRIVER框架实现分析(i2c模块分析结束篇)

 

原文再续,书接上回。本篇主要介绍i2c client与i2cdriver的框架实现,主要内容如下:

  1. I2c driver模块的注册与注销接口
  2. I2c client模块的注册与注销接口
  3. I2c client添加方式说明

 

I2c driver模块的注册与注销

本小节主要介绍i2c driver模块的注册与注销流程,i2c driver相关的结构体定义如下,可以理

解为设备驱动模型中struct device_driver的子类,并完成对基类方法(probe、remove、shutdown等接口)重载,并定义一些i2c 模块相关的变量(包括用于i2c client与i2c driver匹配判断的变量id_table)。

针对i2c_driver结构体而言,也就是重载了基类device_driver的方法,i2c_driver特有变量的

意义如下:

  1. 变量class、detect、address_list、clients,用于i2c模块自动探测i2c client(不通过设备驱动模型的方式实现i2c client与i2c driver的绑定),因此定义了链表头clients,实现i2c client、i2c_driver的绑定操作,这一类i2c设备的添加与探测,未通过linux设备驱动模型中的接口,因此i2c_driver来进行client与driver的绑定以及解绑的操作。这一类型的i2c client的探测,主要针对spd 、hwmon类型的硬件设备,且需要i2c adapter支持此种探测方式(通过class成员判断adapter、driver之间是否支持自动探测等)。
  2. 而command函数指针,如注释所述类似于ioctl,目前linux系统中很少有实现该函数指针的驱动。
  3. 而attach_adapter与上述a中的功能类似,内核不推荐使用。
	struct i2c_driver {
	    /*该变量主要指示该driver支持的类型,包括hwmon、内存相关的spd等,主要用于detect某一个adapter下的
	    已挂载的硬件设备(且该硬件设备对应的逻辑设备未注册到i2c总线上)。*/
		unsigned int class;
	
		/* Notifies the driver that a new bus has appeared. You should avoid
		 * using this, it will be removed in a near future.
		 */
		/*该接口主要用于新注册adapter时,通过遍历i2c总线上所有已注册的驱动程序,针对每一个驱动均调用
	    attach_adapter接口,识别该adapter上挂载的i2c设备,并未识别到的设备创建其对应的i2c_client*/
		int (*attach_adapter)(struct i2c_adapter *) __deprecated;
	
		/* Standard driver model interfaces */
	    /*设备驱动模型的probe接口,在driver_register/device_register时,对于已注册的device和driver,
	    若匹配则调用driver_probe_device进行探测操作,最终即调用该驱动的probe接口*/
		int (*probe)(struct i2c_client *, const struct i2c_device_id *);
	    /*设备驱动模型的probe接口,在driver_unregister/device_unregister时,对于已绑定的device-driver,
	    调用__device_release_driver进行移除操作,最终会调用该去的的remove接口*/
		int (*remove)(struct i2c_client *);
	
		/* driver model interfaces that don't relate to enumeration  */
	    /*电源管理相关的接口*/
		void (*shutdown)(struct i2c_client *);
		int (*suspend)(struct i2c_client *, pm_message_t mesg);
		int (*resume)(struct i2c_client *);
	
		/* Alert callback, for example for the SMBus alert protocol.
		 * The format and meaning of the data value depends on the protocol.
		 * For the SMBus alert protocol, there is a single bit of data passed
		 * as the alert response's low bit ("event flag").
		 */
		void (*alert)(struct i2c_client *, unsigned int data);
	
		/* a ioctl like command that can be used to perform specific functions
		 * with the device.
		 */
		int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
	
	    /*设备驱动模型中的device-driver类型变量,为了继承设备驱动模型,包含该变量,即可
	    使用设备驱动模型中的相应接口,实现驱动注册、驱动与设备的探测与移除等等内容*/
		struct device_driver driver;
	    /*该驱动支持的设备列表,该变量主要用于设备与驱动的匹配*/
		const struct i2c_device_id *id_table;
	
		/* Device detection callback for automatic device creation */
	    /*该接口的作用是若已注册到i2c总线上的adapter上挂载的物理设备,并没有创建对应的逻辑对象,则调用
	    该接口,并根据该驱动的address_list上支持的地址类型,进行搜索该adapter上挂载的物理设
	    备(且没有创建对应的逻辑对象)*/
		int (*detect)(struct i2c_client *, struct i2c_board_info *);
	    /*表明该驱动所支持的i2c设备的地址列表*/
		const unsigned short *address_list;
		struct list_head clients;
};

通过对i2c_driver的分析,我们可以发现,i2c_driver的注册与注销应该不复杂,也就是在调用设备驱动模型的driver_register的基础上,增加对自动探测i2c client的功能支持。

 

I2c driver 注册

   I2c driver的注册接口定义为i2c_register_driver,我们首先来看下该接口的流程图。

    和我们对i2c_driver结构体的分析结果一致(再一次说明了linux内核的结构体定义会提供很多有用的信息)。

  1. 调用driver_register,完成将该驱动注册到i2c总线上,同时针对所有已注册到i2c总线上的i2c client进行匹配检测与绑定操作(具体流程请看图“device_register/driver_register”);
  2. 针对需要自动探测的i2c client,遍历每一个注册到i2c总线上的adpater,根据该driver的address_list上支持的地址,进行探测与匹配,若匹配上则为该设备增加对应的i2c_client,同时调用i2c_new_device注册到i2c总线上,同时完成i2c_client与i2c_driver的绑定操作。(需要自动探测的设备类型为spd、hwmon等类型的设备)。

(针对驱动注册接口driver_register,属于LINUX设备-总线-驱动模型部分的内容,这部分内容在之前的文章中已经分析过,此处不再赘述,感兴趣的朋友可翻看我之前分析的文档,针对i2c、spi、pci这类驱动模块,强烈建议先熟悉LINUX设备-总线-驱动模型,把这个模型搞熟悉了,就会有一览众山小的感觉了)

 

 

 

 

 

I2c driver注销

I2c driver的注销接口为i2c_del_driver,该接口实现的内容刚好与上述注册部分相反,流程图如下:

  1. 针对i2c driver自动探测的i2c client,调用__process_removed_driver完成解除绑定及移除操作;
  2. 针对通过LINUX设备驱动模型完成的绑定的i2c client,通过调用driver_unregister完成i2c client的解绑以及i2c driver从i2c总线上注销(调用流程图如下device_unregister/driver_unregister)。

I2c client模块的注册与注销

I2c client相关的结构体的定义如下,也可以将i2c_client理解为device类型的子类。针对i2c模块的自定义变量有:

  1. flag用于说明i2c client的通信地址类型(7bit还是10bit)
  2. addr表示该i2c client的地址;
  3. 该i2c client所依附的adapter(因为一个i2c client需要借助i2c adapter的通信方法才能与cpu进行通信,因此增加该指针指向所依附的adapter);
  4. 该i2c_clietn所绑定的i2c_driver(这个操作所具体想表达的意思,我还不明晰,我认为使用设备驱动模型中的device、device_driver已经能实现i2c client与i2c driver的绑定类,此处为何还要增加一个指向i2c_driver的变量呢??)
  5. detected变量作用在上面的i2c_driver中就已经说明了(当该i2c client是由i2c_driver的detect接口探测且进行创建的,则通过该变量链接至对应的i2c_driver上)。
	struct i2c_client {
	    /*主要用于设置i2c client的地址类型(10bit还是7bit)等信息*/
		unsigned short flags;		/* div., see below		*/
	    /*标注该i2c设备的地址,7bit或9bit()*/
		unsigned short addr;		/* chip address - NOTE: 7bit	*/
						/* addresses are stored in the	*/
						/* _LOWER_ 7 bits		*/
		char name[I2C_NAME_SIZE];
	    /*该i2c client所依附的i2c适配器*/
		struct i2c_adapter *adapter;	/* the adapter we sit on	*/
	    /*该i2c设备所绑定的驱动*/
		struct i2c_driver *driver;	/* and our access routines	*/
	    /*对应的device类型的变量,用于使用linux设备驱动模型*/
		struct device dev;		/* the device structure		*/
	    /*中断号*/
		int irq;			/* irq issued by device		*/
	    /*用于将该设备链接至其绑定的驱动对应的clients链表上*/
		struct list_head detected;
	};

而针对i2c client的注册与注销而言,应该也就是调用设备驱动模型中的注册与注销接口,不像i2c_driver那样还有自动探测与移除的功能,i2c client的注册与注销应该还是很简单的,我们来分析下

 

i2c_client的注册

      I2c client创建与注册接口为i2c_new_device,该接口完成i2c_client的创建,并调用device_register将其注册到i2c总线上(若i2c总线上已注册了该设备对应的驱动,则会触发该client与对应driver的绑定操作,而device_register的调用流程,请参考上面图“device_regiser/driver_register”)。和我们分析i2c_client结构体中的说明一致,主要就是调用device_register完成注册及绑定操作。

I2c client的注销

I2c client的注销接口为i2c_unregister_device,该接口就是直接调用device_unregister,完成从i2c总线上注销该client,同时完成与绑定驱动的解除绑定操作,而关于device_unregister的调用流程,请参看上面图“device_unregister/driver_unregister”。

 

 

I2c client创建方式

针对i2c client而言,大致有两种创建方式,下面我们分别说明:

  1. 通过调用i2c_new_device,在LINUX系统初始化时,完成i2c client的创建与注册操作,而针对这一类设备,其与驱动的绑定与探测操作,由LINUX设备-总线-驱动模型中的流程机制来完成;(针对支持设备树的LINUX内核,在系统初始化时,通过读取dtb中定义的i2c client,调用该接口完成i2c设备注册到i2c总线上)。
  2. 由I2C driver通过其detect函数指针接口进行探测的client,这一类client与driver的绑定与解绑由i2c模块自己完成(通过__process_new_adapter/__process_new_driver实现绑定,通过__process_removed_adapter/__process_removed_driver),这种机制主要针对spd、hwmon类型的i2c设备。而这种机制的探测也是有条件的,即:
    1. I2c driver需要支持detect函数;
    2. I2c adapter与i2c driver均需要标注其支持自动探测i2c设备的类,且它们支持的类型存在交集时方可支持探测(如均标注支持hwmon、spd的探测等)。

 

 

以上即为本次分析的内容,主要涉及i2c client的注册与注销、i2c driver的注册与注销。而针对诸如i2c_new_probed_device、i2c_scan_static_board_info、i2c_sysfs_new_device等接口,也是调用i2c_new_device完成具体功能,此处不再介绍。下一章介绍i2c 通用设备以及i2c相关的通信接口的分析以及i2c模块的总结。

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

猜你喜欢

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