a.4 前面的2种方法都要事先确定适配器(I2C总线,I2C控制器)
如果我事先并不知道这个I2C设备在哪个适配器上,怎么办?去class表示的所有的适配器上查找
有上一些I2C设备的地址是一样,怎么继续分配它是哪一款?用detect函数
static struct i2c_driver at24cxx_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "100ask",
.owner = THIS_MODULE,
},
.probe = at24cxx_probe,
.remove = __devexit_p(at24cxx_remove),
.id_table = at24cxx_id_table,
.detect =
at24cxx_detect,
.address_list = addr_list,
};
去"class表示的这一类"I2C适配器,用"detect函数"来确定能否找到"address_list里的设备",
如果能找到就调用i2c_new_device来注册i2c_client,
这会和i2c_driver的id_table比较,
如果匹配,调用probe
i2c_add_driver
i2c_register_driver
a. at24cxx_driver放入i2c_bus_type的drv链表
并且从dev链表里取出能匹配的i2c_client并调用probe
driver_register
b. 对于每一个适配器,调用__process_new_driver
对于每一个适配器,调用它的函数确定address_list里的设备是否存在
如果存在,再调用detect进一步确定、设置,然后i2c_new_device
i2c_for_each_dev(driver, __process_new_driver);
__process_new_driver
i2c_do_add_adapter
i2c_detect(adap, driver);
for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) {
err = i2c_detect_address(temp_client, driver);
if (!i2c_default_probe(adapter, addr))
return 0;
memset(&info, 0, sizeof(struct i2c_board_info));
info.addr = addr;
// 设置info.type
err = driver->detect(temp_client, &info);
i2c_new_device
现在来具体写一个IIC设备驱动程序,驱动源码
static struct i2c_client *at24cxx_client;
static int at24cxx_dev_init(void)
{
struct i2c_adapter *i2c_adap;
i2c_adap = i2c_get_adapter(0);
at24cxx_client = i2c_new_device(i2c_adap,
&at24cxx_info);
i2c_put_adapter(i2c_adap);
return 0;
}
static struct i2c_driver at24cxx_driver = {
.driver = {
.name = "100ask",
.owner = THIS_MODULE,
},
.probe = at24cxx_probe,
.remove = __devexit_p(at24cxx_remove),
.id_table = at24cxx_id_table,
};
static int at24cxx_drv_init(void)
{
i2c_add_driver(&at24cxx_driver);
return 0;
}
i2c_add_driver
>i2c_register_driver
,i2c_register_driver函数里driver->driver.bus = &i2c_bus_type;
i2c_bus_type
>i2c_device_probe,
i2c_device_probe函数里 status
= driver->probe(client, i2c_match_id(driver->id_table,
client));调用了i2c_driver里的probe函数。
i2c_add_driver
>i2c_register_driver
>__process_new_driver
> i2c_do_add_adapter
> i2c_detect 里,
if (!driver->detect || !address_list)
return 0;
如果i2c_driver没有提供detect函数,则不创建i2c_client。
i2c_detect
>i2c_detect_address里i2c_new_device最终创建i2c_client对象。
iic_core.c文件里为我们封装了几种IIC设备的操作方式,如下
s32 i2c_smbus_read_byte(const struct i2c_client
*client)
读一个字节数据,不需要指定数据地址
s32 i2c_smbus_write_byte(const struct i2c_client *client, u8
value)
写一个字节数据,不需要指定数据地址
s32 i2c_smbus_read_byte_data(const struct i2c_client *client,
u8 command)
读一个字节数据,需要指定数据地址,参数command即为数据地址
s32 i2c_smbus_write_byte_data(const struct i2c_client *client,
u8 command,u8 value)
写一个字节数据,需要指定数据地址,指定数据值,参数command即为数据地址,参数value为数据值
s32 i2c_smbus_read_word_data(const struct i2c_client *client,
u8 command)
读一个字数据,需要指定数据地址,参数command即为数据地址
s32 i2c_smbus_write_word_data(const struct i2c_client *client,
u8 command,u16 value)
写一个字数据,需要指定数据地址,参数command即为数据地址,参数value为数据值,
注意(这里面的Word是16位的数据)
里面还封装了其他比如一块一块的读写数据的函数,这里就不一
一列出来了。