基于linux-3.14.16
一、注册I2C总线
一0、导出i2c的应用层接口
同样在init段中有i2c_dev_init,开机将会执行。
下面代码注册了主设备号为I2C_MAJOR(89),次设备号0~256的字符设备
看下操作集i2cdev_fops
我们看下open是对谁操作的好了
首先用次设备号获取注册的i2c_dev,
然后从i2c_dev中拿到i2c_adapter,
最后转成i2c_client保存在file私有数据
那么这个i2c_dev是哪里添加的呢????
显然是注册的i2c控制器。
下面看适配器的注册。
二、注册适配器
i2c适配器在硬件层面其实就是i2c控制器,因为跟芯片相关,一般内核会带对应厂商的芯片驱动,实现在i2c/busses中找好了。
以下以imx6为例。
1、平台总线匹配
2、执行probe(i2c_imx_probe)
看下i2c适配器是怎么注册的,注册到哪里的????
3、注册适配器总线i2c_add_numbered_adapter
4、i2c_register_adapter
i2c_add_numbered_adapter是i2c core的接口,用于注册一个i2c适配器
最终会调用i2c_register_adapter注册
接着,看看i2c_register_adapter里面干了什么
设置适配名称,设置bus为之前注册的i2c总线
调device_register注册,可以看到,适配器是作为一个i2c设备,,,
那他匹配的哪个i2c总线驱动呢???
遍历该i2c下所有的设备,添加到总线(of_i2c_register_devices)
这个是扫描设备树里面定义的。将会生成i2c设备
,,,,
下面
这个是遍历总线上的驱动,在每个i2c设备驱动的基础上去总线上扫描i2c设备,扫描成功,则会生成i2c设备,并和该驱动绑定。
对所有的device_driver执行__process_new_adapter
两种方式的区别就是,下面的需要i2c设备驱动参与。。
5、看如何添加i2c设备of_i2c_register_devices
其实就是遍历设备树,创建i2c设备。
看i2c_new_device干了什么
将i2c_borad_info转成i2c_client后最终注册为一个i2c设备,可知i2c_borad_info只是一个临时过渡作用
至此完成了i2c控制器以及其下面所挂的设备的i2c设备添加,这里用到了很多接口,都是在i2c core中定义的。
问题:打开控制器的时候 适配器实在哪里拿到的,注册控制器的时候,适配器又是保存在哪里去了???
三、i2c设备驱动
在设备树中,i2c3下面有一个ts设备
找到匹配的i2c设备驱动
如上图,
module_i2c_driver 最终会被展开成一个标准的驱动模块,
在加载和卸载将会执行
i2c_add_driver(&(egalax_ts_driver) );
以及
i2c_del_driver(&(egalax_ts_driver) );
看看注册i2c驱动
1、注册i2c驱动i2c_register_driver
标准的总线设备驱动的注册方法。
总共做了3件事情。
1、设置总线
2、注册设备驱动
3、遍历总线下所有i2c设备,跟新加的驱动区匹配关联。
我们讲注册控制器驱动的时候就提到过,遍历了设备树下的,指定I2c下的节点,并注册成i2c的设备挂在在总线上。
2、probe
四、基于i2c的通信
1、i2c_master_send
调用适配器自己实现的算法把数据传输出去,寄存器的操作有适配器实现。
看看
adap->retries是什么??重试次数,这里我们先不关注重复几次,有兴趣同学可以打印出来看下是几
adap->algo->master_xfer是什么
这2个都跟适配器有关,回头看看适配器的注册过程
1)algo
看看回调函数i2c_imx_xfer做了什么
1、i2c传输开始
2、根据消息个数(这里num是1)遍历传输数据
读写区分
3、i2c传输停止
总结:i2c_imx_xfer就是操作一堆的寄存器,把i2c_msg发出去,由芯片厂商实现了。
2、i2c_master_recv
跟发送一样,调用i2c_transfer,区别就是I2C_M_RD置位,表示读。
总结:
1、内核启动后会线注册一个i2c总线(i2c-core.c i2c_init()),并且会注册一个i2c总线设备驱动(dummy_driver)。
2、i2c控制器(内核中叫适配器)是主芯片封装他的外设之一,所以控制器驱动代码芯片厂商会在内核中提供(i2c/busses),笔者看的是imx6的代码,busses中存在文件i2c-imx.c,i2c总线在此注册。