在上一节的文章中介绍了在linux2.6内核中的I2C驱动框架,2.6内核现在已基本上不再使用了,可能版本有点太老了,但对于我们分析内核结构来说也不算过时,看懂旧的再看新的也就没有那么大的压力了,那今天就来分析一下Linux3.4内核中的I2C框架吧
分析文件·drivers/i2c/busses/i2c-s3c2410.c
注册平台设备驱动,查看probe函数的内容
我只截取部分内容,从这些内容中就可以看出套路其实和之前的差不多,也是定义一个关于i2c的结构体,然后去设置这个结构体,设置的时候有一个比较重要的成员s3c24xx_i2c_algorithm,包含了和设备相关的发送和接收数据的函数,这个成员一定要赋值,设置好了i2c结构体,最后就是注册它,使用i2c_add_numbered_adapter函数
再去调用i2c_register_adapter函数 ,这函数中的重要代码片段如下
遍历内核中一个链表,使用i2c_new_device创建设备,传入参数adapter和board_info,i2c_new_client函数的内容这里就不再看了,就是使用传入的i2c_adapter和board_inifo构造i2c_client结构体,然后链入内核链表,看到这里只有一个未知的变量,就是board_info结构体中是什么内容,以及board_info链表在哪里设置?
接下来就要分析这里的内容了,在架构相关的文件里,我在2410架构的文件中没有找到相关内容,就来看mach-mini2440.c吧,是一样的,搜索i2c_board_info,找到如下内容
在mini2440_init函数中调用如下代码段
在
i2c_register_board_info就是把构造好的i2c_board_inifo结构体链入__i2c_board_list链表中,这个链表不就是之前i2c_new_device的时候使用的那个链表嘛,好了,接着往下看__i2c_board_list在哪里被使用,搜索这个全局变量
是在i2c_scan_static_board_info函数中使用,i2c_scan_static_board_info函数又被i2c_register_adapter调用
看到这里就和前面的对应上了,下面,来对前面的过程进行总结
当单板上电内核跑起来的时候,肯定是架构相关的程序首先运行,也就是mach-xxx.c
1、mach-xxx.c文件里关于i2c是怎么处理的呢?
文件里首先会定义i2c_board_info的结构体,在mach-xxx.c的初始化函数里调用
i2c_register_board_info函数把i2c_board_inifo链接进内核的__i2c_board_list
链表当中去,mach-xxx.c中关于i2c的工作到这里就可以结束了
那么,构造的__i2c_board_list链表在什么时候被使用呢?
是在驱动i2c目录下和单板对应的驱动文件中加载,i2c-xxx.c
2、在i2c-xxx.c文件里使用,一般在文件的开始会注册平台设备驱动,除了一些必要的
i2c的硬件设置之外就是老一套,分配i2c结构体,其中包含i2c_adapter成员,
设置i2c_adapter成员中的算法(s3c24xx_i2c_algorithm)、注册(也是通过adapter)
i2c_add_numbered_adapter -> i2c_register_adapter -> i2c_scan_static_board_info
在i2c_scan_static_board_info函数里就使用前面设置的__i2c_board_list链表
使用i2c_new_device函数,将adapter和i2c_board_info生成i2c_client,链入链表,
最终使用i2c_client
内核中i2c驱动框架的细节还有很多,我这里只是记录了我学习过程中的一点,关于更多的细节我会在后面的学习过程中遇到了再过分析。