一、Linux的I2C体系结构
主要由三部分组成:
(1) I2C核心
提供I2C控制器和设备驱动的注册和注销方法,I2C通信方法,与适配器无关的代码以及探测设备等。
(2) I2C控制器驱动(适配器)
(3) I2C设备驱动
二、重要的结构体
- i2c_adapter
//i2c控制器(适配器)
- i2c_algorithm
//I2C传输方法
SMBus是基于I2C总线规范的,所以上面的传输函数要根据自己的总线来选择,选择其一就可以。
- i2c_driver
//I2C驱动,和platform_driver,spi_driver类似
- i2c_client
//I2C设备
- i2c_msg
//I2C传输数据结构体,代表一个消息数据
总结上面结构体关系:
1. i2c_adapter和i2c_algorithm
i2c_adapter对应物理上的一个适配器,而i2c_algorithm对应一套通信方法,适配器需要通过i2c_algorithm提供的通信函数来产生对应的访问时序。所以i2c_adapter中包含i2c_algorithm的指针。
i2c_algorithm使用master_xfer()来产生I2C时序,以i2c_msg为单位,i2c_msg代表一次传输的数据。
2. i2c_driver和i2c_client
i2c_driver对应一套驱动方法,包含probe,remove等方法。i2c_clent对应真实的物理设备,每个i2c设备都需要一个i2c_client来描述。i2c_driver与i2c_client是一对多的关系,一个i2c_driver上可以支持多个同类型的i2c_client。
3. i2c_adapter和i2c_client
i2c_adapter与i2c_client的关系和硬件上适配器与设备的关系一致,即i2c_client依附于i2c_adapter。一个适配器可以连接多个设备,所以i2c_adapter中包含i2c_client的链表。
三、API函数
//增加/删除i2c_adapter
i2c_transfer()函数本身不具备驱动适配器物理硬件以完成消息交互的能力,它只是寻找到与i2c_adapter对应的i2c_algorithm, 并使用i2c_algorithm的master_xfer()函数真正驱动硬件流程。
追踪i2c_transfer()的源码会发现下面的代码
for
四、适配器(控制器)驱动
由于I2C控制器通常是在内存上的,所以它本身也连接在platform总线上的,通过platform_driver和platform_device的匹配还执行。
(1) probe()完成如下工作:
- 初始化I2C控制器所使用的硬件资源,如申请IO地址,中断号,时钟等。
- 为特定I2C控制器实现通信方法,主要是实现i2c_algorithm的master_xfer()和functionality()函数。
- 通过i2c_add_adapter()添加i2c_adapter的数据结构(i2c_adapter成员已被初始化)。
模板代码:
static
xxx_adapter_hw_init实现和具体的CPU和I2C控制器硬件相关的初始化。
functionality() 函数比较简单,返回支持的通信协议。
master_xfer() 函数在适配器上完成i2c_msg的数据传输。
五、设备(外设)驱动
i2c_dirver就是i2c标准总线设备驱动模型中的驱动部分,i2c_client可理解为i2c总线上挂的外设。
模板代码:
static