Documentation\i2c\instantiating-devices
How to instantiate I2C devices ?(即怎么构造i2c_client,4种方法)
——————/法1 Declare the I2C devices by bus number
Example:
——————/法2 Instantiate the devices explicitly
① 直接调用i2c_new_device
At24cxx_drv.c:
/mnt # insmod at24cxx_drv.ko
/mnt # insmod at24cxx_dev.ko
/test/at24cxx_drv.c at24cxx_probe 12
/mnt # rmmod at24cxx_dev
/test/at24cxx_drv.c at24cxx_remove 18
总结:i2c_new_device认为设备肯定存在,即便将0x50改为0x60,实验结果同
How to instantiate I2C devices ?(即怎么构造i2c_client,4种方法)
——————/法1 Declare the I2C devices by bus number
Example:
static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
{
I2C_BOARD_INFO("24c08", 0x50),
//据名字可找到驱动、据地址可知访问谁
.platform_data = &at24c08,<span style="white-space:pre"> //给driver侧probe函数使用
},
};
i2c_register_board_info(0, mini2440_i2c_devs,ARRAY_SIZE(mini2440_i2c_devs));
i2c_register_board_info(int busnum,struct i2c_board_info *info, unsigned len)
for (status = 0; len; len--, info++) //busnum即哪一适配器
{
struct i2c_devinfo *devinfo;
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
devinfo->busnum = busnum;
devinfo->board_info = *info;
list_add_tail(&devinfo->list, &__i2c_board_list);
}
//放入__i2c_board_list链表,在什么时候用?
i2c_scan_static_board_info(struct i2c_adapter *adapter) //i2c-core.c
struct i2c_devinfo *devinfo;
list_for_each_entry(devinfo, &__i2c_board_list, list)
i2c_new_device(adapter,&devinfo->board_info)
struct i2c_client *client;
client = kzalloc(sizeof *client, GFP_KERNEL);
client->addr = info->addr;
client->flags = info->flags; //各种设置
device_register(&client->dev);
//谁来调用i2c_scan_static_board_info?静态函数,肯定只在本文件使用
i2c_register_adapter
i2c_scan_static_board_info(adap);
//注册adapter时,会为预先挂在该adapter上所有设备创建client
使用限制:必须在注册adapter之前注册i2c_board_info
——————/法2 Instantiate the devices explicitly
① 直接调用i2c_new_device
At24cxx_drv.c:
static int __devinit at24cxx_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
static int __devexit at24cxx_remove(struct i2c_client *client)
{
printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
return 0;
}
static const struct i2c_device_id at24cxx_id_table[] = {
{ "at24c08", 0 }, //数组,表可支持一个或多个设备
{}
};
static struct i2c_driver at24cxx_driver = {
.driver = {
.name = "lyl",
//此处名字不重要,id_table中名字重要,因match时根据它
.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;
}
static void at24cxx_drv_exit(void)
{
i2c_del_driver(&at24cxx_driver);
}
At24cxx_dev.c:
static struct i2c_board_info at24cxx_info = {
I2C_BOARD_INFO("at24c08", 0x50),
};
static struct i2c_client *at24cxx_client;
static int at24cxx_dev_init(void)
{
struct i2c_adapter *i2c_adap = i2c_get_adapter(0);
at24cxx_client = i2c_new_device(i2c_adap, &at24cxx_info);
//在i2c_adap下,创建一个新设备
i2c_put_adapter(i2c_adap);
return 0;
}
static void at24cxx_dev_exit(void)
{
i2c_unregister_device(at24cxx_client);
}
测试:
/mnt # insmod at24cxx_drv.ko
/mnt # insmod at24cxx_dev.ko
/test/at24cxx_drv.c at24cxx_probe 12
/mnt # rmmod at24cxx_dev
/test/at24cxx_drv.c at24cxx_remove 18
总结:i2c_new_device认为设备肯定存在,即便将0x50改为0x60,实验结果同