1.IIC协议简介
在之前的ARM裸机里面有介绍:ARM裸机 - I2C通信协议是最常用的协议_一对多i2c-CSDN博客
2.Linux的IIC子系统框架
I2C主机驱动:I2C主机控制器的驱动,一般由SoC芯片厂商负责设计实现,用于控制II2C主机控制器发出时序信号。
I2C Core:为上层提供统一的API接口和对其他模块进行注册和注销等管理等。
I2C 驱动和我们之前接触到的平台总线设备驱动非常类似,都有总线、设备和驱这三者。
I2C驱动框架的主要目标是:让驱动开发者可以在内核中方便的添加自己的I2C设备的驱动程序,从而可以更容易的在linux下驱动自己的I2C接口硬件。
源码中I2C相关的驱动均位于:drivers/i2c目录下。
3.linux内核的I2C子系统源代码分析
I2C子系统的4个关键结构体:
struct i2c_adapter : I2C适配器
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 */
int nr;
char name[48];
struct completion dev_released;
struct list_head userspace_clients;
};
struct i2c_algorithm : I2C算法
struct i2c_algorithm {
int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data);
/* To determine what the adapter supports */
u32 (*functionality) (struct i2c_adapter *);
};
struct i2c_client :I2C(从机)设备信息
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 */
struct device dev; /* the device structure */
int irq; /* irq issued by device */
struct list_head detected;
};
struct i2c_driver : I2C(从机)设备驱动
struct i2c_driver {
unsigned int class;
int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *);
/* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
/* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg);
int (*resume)(struct i2c_client *);
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
struct device_driver driver;
const struct i2c_device_id *id_table;
/* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *, struct i2c_board_info *);
const unsigned short *address_list;
struct list_head clients;
};
4.i2c-core.c分析
match函数:
probe函数:
I2C总线上有2条分支:i2c_client链和i2c_driver链,当任何一个driver或者client去注册时,I2C总线都会调用match函数去对client.name和driver.id_table.name进行循环匹配。如果driver.id_table中所有的id都匹配不上则说明client并没有找到一个对应的driver。
5.i2c_s3c2410.c分析
driver和device配对过程:
probe函数:
填充一个i2c_adapter结构体,并且调用接口去注册之。
从platform_device接收硬件信息,做必要的处理(request_mem_region & ioremap、request_irq等)。
对硬件做初始化(直接操作210内部I2C控制器的寄存器)。
6.gslX680的驱动为例-----i2c_driver 和 i2c_client
i2c_driver:
i2c_client实现原理 :
内核维护一个链表 __i2c_board_list,这个链表上链接的是I2C总线上挂接的所有硬件设备的信息结构体。也就是说这个链表维护的是一个struct i2c_board_info结构体链表。