linux iic驱动体系分三部分。
struct i2c_adapter 用来描述I2C控制器的,只和主机有关系。换一颗SoC则需要修改该结构体。
struct i2c_client I2C从机设备信息
struct i2c_driver I2C(从机)设备驱动
- I2C总线上有2条分支:i2c_client链和i2c_driver链;
- 当任何一个driver或者client去注册时,I2C总线都会调用match函数去对client.name和driver.id_table.name进行循环匹配。
- 如果driver.id_table中所有的id都匹配不上则说明client并没有找到一个对应的driver;
- 如果匹配上了则标明client和driver是适用的,那么I2C总线会调用自身的probe函数,自身的probe函数又会调用driver中提供的probe函数,driver中的probe函数会对设备进行硬件初始化和后续工作。
(1)i2c_add_adapter/i2c_add_numbered_adapter:注册adapter的,比如i2c-s3c2410.c中就使用此函数来注册一个adapter。
(2)i2c_add_driver:注册driver的
(3)i2c_new_device:注册client的
(4)i2c_register_board_info()函数用于往__i2c_board_list 这条链表添加一条i2c设备信息,在i2c adapter注册的时候,会扫描 __i2c_board_list链表, 然后调用i2c_new_device()函数来注册i2c设备,
注意,要先于i2c adapter注册之前就添加好i2c设备信息,否则会出现调用了i2c_register_board_info()函数,
而设备不能注册的情况。
下面介绍如何利用platform_data 通过板级文件向驱动传输参数。
板级文件中:
static struct gt9xx_platform_data gt911_pdata =
{
.rst = SABRESD_GT911_RST,//GPIO number
.irq = SABRESD_GT911_INT,//GPIO number
.reset = gt911_reset,//函数
};
static struct i2c_board_info mxc_i2c2_board_info[] __initdata =
{
{
I2C_BOARD_INFO("Goodix-TS-gt911", 0x14),
.platform_data = (void *)>911_pdata,
}
};
imx6q_add_imx_i2c(0, &mx6q_sabresd_i2c_data);//注册适配器设备
i2c_register_board_info(2, mxc_i2c2_board_info,ARRAY_SIZE(mxc_i2c2_board_info));//添加 I2C从设备
驱动文件中:
static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
s32 ret = -1;
struct goodix_ts_data *ts;
struct gt9xx_platform_data *pdata = client->dev.platform_data;
if(pdata->reset)
pdata->reset(client->addr);
***************************
ts->client = client;
ts->gpio_rst = pdata->rst;
ts->gpio_irq = pdata->irq;
*****************************
return ret;
}
(5)I2C总线的i2c_client的提供是内核通过i2c_add_adapter/i2c_add_numbered_adapter接口调用时自动生成的,生成的原料是 mach-x210.c中的i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));