所有的linux驱动的I2C这章都会说到,I2C的驱动分为I2C总线驱动和I2C设备驱动两个部分,其中I2C的总线驱动中,需要我们做的是I2C的适配器adapter的驱动和与其相关的算法algorithm的编写。而I2C的设备驱动则是普通的字符型设备。I2C设备通过I2C适配器与内核进行通信。
Linux内核中的I2C-core.c文件和I2C-dev.c文件已经提供了很多供我们使用的函数,而busses文件夹里是Linux支持的很多I2C适配器的驱动程序,chips文件夹中是I2C设备的驱动程序,chips文件夹中的都是I2C设备驱动,但并不是所有的I2C设备驱动都在chips文件夹下,例如连接在I2C上的rtc的芯片驱动就在/driver/rtc下,watchdog的芯片驱动就在/drvier/watchdog目录下。
这里以freescale的powerpc系列的I2C adapter和I2C的实时时钟ds-1338为例说明一下I2C适配器,设备,驱动的添加注册过程。
1 I2C总线的注册
总线肯定要优先于设备和驱动的注册。
/driver/i2c/i2c-core.c中的i2c_init函数
postcore_initcall(i2c_init) à bus_register(&i2c_bus_type)
2 I2C适配器设备在of_platform总线上的添加
适配器要先于I2C设备,适配器adapter和别的soc一样,都是在of_platform总线上注册。
Arch/powerpc/platform/83xx/Mpc831x_rdb.c
machine_device_initcall(mpc831x_rdb, declare_of_platform_devices);
declare_of_platform_devices à of_platform_bus_probe(NULL, of_bus_ids, NULL)
Arch/powerpc/kernel/of_platform.c
遍历系统初始化时在内存中生成链表的所有soc的子节点,将所有的soc子节点设备添加到of_platform总线。
of_platform_bus_probe à of_platform_device_create à of_device_register à device_add
这一步过后,在of_platform总线上就会有两个适配器i2c@3000和i2c@3100出现。
3 I2C适配器的驱动寻找设备
所有的powerpc 的I2C适配器驱动都在/driver/i2c/busses/I2c-mpc.c文件中。
module_init(fsl_i2c_init) à fsl_i2c_init à of_register_platform_driver(&mpc_i2c_driver)
在这里会调用of_platform总线的match函数of_platform_bus_match去做设备和驱动的匹配,of_platform_bus_match函数在比较了驱动的match-table和设备node中的相关字段后( compatible = "fsl-i2c" ),若匹配,进入fsl_i2c_probe。
4 fsl_i2c_probe
该函数做两件事:
1)调用i2c_add_adapter函数在内核中注册该I2C适配器。
2)调用of_register_i2c_devices函数在I2C总线上添加I2C设备。
/driver/i2c/busses/I2c-mpc.c
fsl_i2c_probe à i2c_add_adapter
fsl_i2c_probe à of_register_i2c_devices à i2c_new_device à device_register
of_register_i2c_devices函数首先在该适配器的节点上搜索子节点,提取它的名字,中断号,设备地址等信息到info结构体;然后将info结构体带入i2c_new_device函数,初始化表示I2C设备的结构体client;最后使用device_register在I2C总线上添加该I2C client。
5 I2C设备驱动的匹配
现在到具体的I2C设备的驱动了,在该例中为RTC ds-1338
/driver/rtc/rtc-1307.c
module_init(ds1307_init) à ds1307_init à i2c_add_driver(&ds1307_driver)
这里驱动寻找设备将调用I2C总线的match函数i2c_device_match。i2c_device_match函数会比较driver的id-table中成员的名字和client的name(ds-1338),若匹配就进入ds1307_probe对设备做配置
至此,I2C的adapter的设备和驱动,I2C设备和设备驱动都已经加载完毕。所幸的是项目中的I2C adapter和RTC设备在Linux中都支持,所以只要识别就可以工作,改动不大。要是一个不支持的设备或adapter就要改很多了。