一、I2C子系统总体架构
1、三大组成部分
(1)I2C核心(i2c-core):I2C核心提供了I2C总线驱动(适配器)和设备驱动的注册、注销方法,I2C通信方法(”algorithm”)上层的,与具体硬件无关的代码以及探测设备
检测设备地址的上层代码等。。
(2)I2C总线驱动(I2Cadapter):I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力。I2C总线驱动由i2c_adapter和i2c_algorithm来描述
I2C适配器是SoC中内置i2c控制器的软件抽象,可以理解为他所代表的是一个I2C主机。
(3)I2C设备驱动(I2Cclient driver):包括两部分:设备的注册和设备驱动的注册
2、I2C子系统的主要目标是:让驱动开发者可以在内核中方便的添加自己的I2C设备的驱动程序,让内核统一管理I2C设备,从而可以更容易的在linux下驱动自己的I2C接口硬件。
3、I2C子系统提供的两种驱动实现方法(源码中I2C相关的驱动均位于:drivers/i2c目录下)
(1)第一种叫i2c-dev,对应drivers/i2c/i2c-dev.c,这种方法只是封装了主机(I2Cmaster,一般是SoC中内置的I2C控制器)的I2C基本操作,并且向应用层提供相应的操作
接口,应用层代码需要自己去实现对slave的控制和操作,所以这种I2C驱动相当于只是提供给应用层可以访问slave硬件设备的接口,本身并未对硬件做任何操作,应用需要实
现对硬件的操作,因此写应用的人必须对硬件非常了解,其实相当于传统的驱动中干的活儿丢给应用去做了,所以这种I2C驱动又叫做“应用层驱动”,这种方式并不主流,它的优势是
把差异化都放在应用中,这样在设备比较难缠(尤其是slave是非标准I2C时)时不用动驱动,而只需要修改应用就可以实现对各种设备的驱动。
(2)第二种I2C驱动是所有的代码都放在驱动层实现,直接向应用层提供最终结果。应用层甚至不需要知道这里面有I2C存在,譬如电容式触摸屏驱动,直接向应用层提供/dev/input/event1
的操作接口,应用层编程的人根本不知道event1中涉及到了I2C。
4、相关的结构体
(1)struct i2c_adapter(I2C适配器)
struct i2c_adapter是用来描述一个I2C适配器,在SoC中的指的就是内部外设I2C控制器,当向I2C核心层注册一个I2C适配器时就需要提供这样的一个结构体变量。
struct i2c_adapter {
struct module *owner; // 所有者
unsigned int id;
unsigned int class; // 该适配器支持的从设备的类型
const struct i2c_algorithm *algo; // 该适配器与从设备的通信算法
void *algo_data;
/* data fields that are valid for all devices */
struct rt_mutex bus_lock;
int timeout; // 超时时间
int retries;
struct device dev; // 该适配器设备对应的device
int nr; // 适配器的编号
char name[48]; // 适配器的名字
struct completion dev_released;
struct list_head userspace_clients; // 用来挂接与适配器匹配成功的从设备i2c_client的一个链表头
};