1.Linux的I2C驱动架构Linux中I2C总线的驱动分为两个部分,总线驱动(BUS)和设备驱动(DEVICE)。其中总线驱动的职责,是为系统中每个I2C总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯,它只是存在在那里,等待设备驱动调用其函数。
设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。
设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。
总线驱动在系统开机时,首先装载的是I2C总线驱动。一个总线驱动用于支持一条特定的I2C总线的读写。提供i2c总线上的读写寄存器方法的东东叫做适配器,用结构体adapter表示的。
I2c总线上有寄存器存在,将i2c控制器(i2c寄存器所在的那块电路)抽象出来,用adapter(适配器)这个结构来描述,可以说一个适配器就代表一条 i2c总线,而挂接在i2c总线上的设备是用client这个结构体来表述,另外i2c_bus上的设备链表挂接的不单单是连接的这条i2c上的 client,同样adapter也作为一个设备挂在其所在的i2c_bus,也就是说控制器和设备都作为i2c_bus上的设备连接在设备链表,他们用 内嵌的struct device的type这个成员来区分,适配器的类型为i2c_adapter_type,client的类型为i2c_client_type。
struct i2c_adapter {
struct module *owner;
unsigned int id;
unsigned int class; /* classes to allow probing for */ 适配器支持的类型
const struct i2c_algorithm *algo; /* the algorithm to access the bus */ /*适配器的通信函数*/
void *algo_data; /通讯所需要的数据
/* data fields that are valid for all devices */
struct rt_mutex bus_lock;
int timeout; /* in jiffies */
int retries; //通信重复次数限定
struct device dev; /* the adapter device */
/*dev为adapter,其值为i2c_adapter_type */
int nr; /*适配器编号也是bus编号,第几条i2c总线 */
char name[48];
struct completion dev_released;
struct list_head userspace_clients;
};
struct i2c_client {
unsigned short flags; /* div., see below */
unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits */
char name[I2C_NAME_SIZE];
struct i2c_adapter *adapter; /* the adapter we sit on 设备所属的适配器 */
struct i2c_driver *driver; /* and our access routines 设备的driver */
struct device dev; /* 内嵌的标准device模型,其中dev->type标识该设备是个client,其值为i2c_client_type */
int irq; /* irq issued by device */
struct list_head detected;
};
可见,一个i2c_client代表着位于adapter总线上,地址为address,使用driver来驱动的一个设备。它将总线驱动与设备驱动,以及设备地址绑定在了一起。一个i2c_client就代表着一个I2C设备。