注册接口
#define i2c_add_driver(driver) \ i2c_register_driver(this_module, driver) int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
注册的结构体是struct i2c_driver,主要填充name、probe和id_table字段,其中name是驱动名称,到时会在/sys/bus/i2c/drivers显示这个驱动名称,probe会在i2c设备匹配后调用,不是发现i2c设备,即便实际上这个设备不在,但是代码里注册了这个设备,或者设备树里配置了这个设备,就会被调用。
driver.of_match_table和 id_table两个成员列出的是驱动程序所能支持的所有设备,其中driver.of_match_table里的设备,是跟设备树匹配的,id_table是跟静态注册是调用的struct i2c_board_info里的name做比较的。
示例代码
驱动注册:
static int __devinit zsl_i2c_drv_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct property *pp = null; uint8_t buf[4]; struct i2c_msg msgs[2] = {{0}, {0}}; int len = sizeof(msgs) / sizeof(msgs[0]); printk(kern_info "%s: %x\n",__func__,client->addr); pp = of_find_property(client->dev.of_node, "testdata", null); if (pp) printk(kern_info "%s: %d:%s \n",__func__,pp->length,(char *)pp->value); dump_stack(); if (client->adapter) { buf[0] = 0; buf[1] = 4; buf[2] = 0; buf[3] = 0; memset(msgs,0,sizeof(struct i2c_msg)*2); msgs[0].addr = client->addr; msgs[0].flags = 0x0; msgs[0].len = 2; msgs[0].buf = buf; msgs[1].addr = client->addr; msgs[1].flags = i2c_m_rd; msgs[1].len = 4; msgs[1].buf = buf; if (i2c_transfer(client->adapter, msgs, len) == len) printk(kern_info "zsl i2c_transfer r: %d:%x %x %x %x\n",len,buf[0],buf[1],buf[2],buf[3]); buf[0] = 0; buf[1] = 4; buf[2] = 7; buf[3] = 8; memset(msgs,0,sizeof(struct i2c_msg)*2); msgs[0].addr = client->addr; msgs[0].flags = 0; msgs[0].len = 4; msgs[0].buf = buf; if (i2c_transfer(client->adapter, msgs, 1) == 1) printk(kern_info "zsl i2c_transfer w: %d:%x %x %x %x\n",1,buf[0],buf[1],buf[2],buf[3]); buf[0] = 0; buf[1] = 4; buf[2] = 0; buf[3] = 0; memset(msgs,0,sizeof(struct i2c_msg)*2); msgs[0].addr = client->addr; msgs[0].flags = 0x0; msgs[0].len = 2; msgs[0].buf = buf; msgs[1].addr = client->addr; msgs[1].flags = i2c_m_rd; msgs[1].len = 4; msgs[1].buf = buf; msleep(100); len = i2c_transfer(client->adapter, msgs, len); if (2 == len) printk(kern_info "zsl i2c_transfer r: %d:%x %x %x %x\n",len,buf[0],buf[1],buf[2],buf[3]); } return 0; } static void __devexit zsl_i2c_drv_remove(struct i2c_client *client) { printk(kern_info "%s: \n",__func__); } static const struct i2c_device_id zsl_dev_id_table[] = { { "zsl_i2c_dev", 0 }, {} };//这里的名字很重要,驱动第一种匹配设备的方式要用到 static const struct of_device_id zsl_of_match_ids[] = { { .compatible = "i2c_name,zsl", .data = null }, { /* end of list */ } //最后一项为空,用于判断数组遍历完成 }; static struct i2c_driver zsl_i2c_driver = { .driver = { .name = "zsl_i2c", .owner = this_module, .of_match_table = zsl_of_match_ids,//设备树匹配用 }, .probe = zsl_i2c_drv_probe, .remove = __devexit_p(zsl_i2c_drv_remove), .id_table = zsl_dev_id_table, //设备树不需要,i2c_register_board_info匹配使用 }; void zsl_i2c_drv_init(void) { i2c_add_driver(&zsl_i2c_driver); }
静态设备注册
static struct i2c_board_info zsl_i2c_dev = { i2c_board_info("zsl_i2c_dev", 0x50),//这个名字很重要,用于匹配 i2c 驱动 }; static struct i2c_client *zsl_i2c_client; void zsl_i2c_dev_init(void) { i2c_register_board_info(4, &zsl_i2c_dev, 1); }
设备树注册
&i2c4 { zsli2c0: zsli2c@50 { compatible = "i2c_name,zsl"; status = "okay"; testdata = "asdfg"; reg = <0x50>; }; };
运行后probe就会被调用,无论配的是什么地址,0x50设备存在,0x60设备不存在,probe都能被调用,但是0x60的读不到数据。
调用关系
probe里的堆栈打印如下:
从芯片厂家的i2c驱动初始化接口rk3x_i2c_driver_init开始,使用platform_driver_register接口注册rk3x_i2c_driver,当设备树里有对应的i2c总线时,就会注册i2c设备,匹配后调用这里的probe接口rk3x_i2c_probe。
rk3x_i2c_probe里会初始化 rockchip i2c控制器,调用 i2c_register_adapter将 i2c 适配器注册到内核,进而调用of_i2c_register_devices 扫描设备树,调用i2c_new_client_device创建配置的i2c设备。
i2c_new_client_device里会创建struct i2c_client并调用device_register注册到内核,触发 device_add,内核会尝试匹配驱动(通过 compatible 字符串或者name)。如果匹配成功,调用 i2c_device_probe到probe接口的zsl_i2c_drv_probe。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论