linux设备驱动-I2C驱动详解2
一 I2C核心层源码分析
1 I2C子系统注册函数:i2c_init
定义位于:drivers\i2c\i2c-core.c
1 static int __init i2c_init(void) 2 { 3 int retval; 4 5 retval = bus_register(&i2c_bus_type); // 注册i2c总线 /sys/bus/i2c 6 if (retval) 7 return retval; 8 #ifdef CONFIG_I2C_COMPAT 9 i2c_adapter_compat_class = class_compat_register("i2c-adapter"); 10 if (!i2c_adapter_compat_class) { 11 retval = -ENOMEM; 12 goto bus_err; 13 } 14 #endif 15 retval = i2c_add_driver(&dummy_driver); // 注册一个空设备驱动 /sys/bus/i2c/driver/dummy 16 if (retval) 17 goto class_err; 18 return 0; 19 20 class_err: 21 #ifdef CONFIG_I2C_COMPAT 22 class_compat_unregister(i2c_adapter_compat_class); 23 bus_err: 24 #endif 25 bus_unregister(&i2c_bus_type); 26 return retval; 27 }
28 postcore_initcall(i2c_init);
i2c_bus_type 的定义:
1 struct bus_type i2c_bus_type = { 2 .name = "i2c", 3 .match = i2c_device_match, 4 .probe = i2c_device_probe, 5 .remove = i2c_device_remove, 6 .shutdown = i2c_device_shutdown, 7 .pm = &i2c_device_pm_ops, 8 };
dummy_driver 的定义:
1 static struct i2c_driver dummy_driver = { 2 .driver.name = "dummy", 3 .probe = dummy_probe, 4 .remove = dummy_remove, 5 .id_table = dummy_id, 6 };
1.1 i2c_device_match
1 static int i2c_device_match(struct device *dev, struct device_driver *drv) 2 { 3 struct i2c_client *client = i2c_verify_client(dev); 4 struct i2c_driver *driver; 5 6 if (!client) 7 return 0; 8 9 /* Attempt an OF style match */ 10 if (of_driver_match_device(dev, drv)) 11 return 1; 12 13 /* Then ACPI style match */ 14 if (acpi_driver_match_device(dev, drv)) 15 return 1; 16 17 driver = to_i2c_driver(drv); 18 /* match on an id table if there is one */ 19 if (driver->id_table)//如果存在id表,通过id表匹配设备 20 return i2c_match_id(driver->id_table, client) != NULL; 21 22 return 0; 23 }
1.2 i2c_match_id
1 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, 2 const struct i2c_client *client) 3 { 4 while (id->name[0]) { 5 if (strcmp(client->name, id->name) == 0)//id表中的每个元素都一一与name比较 6 return id;//匹配成功,返回对应的id 7 id++; 8 } 9 return NULL;//匹配失败返回空 10 }
由i2c_match_id函数分析可以知道,在i2c总线下的设备与设备驱动的匹配是通过设备的名字和设备驱动的i2c_device_id表中的各个表项中的依次进行匹配的,只要有一个匹配成功则设备和设备驱动就匹配成功了,如果都没有匹配成功则表明匹配失败;由此可以对比platform平台总线的匹配原则,他们基本是一致的,但是platform总线下的设备与设备驱动匹配过程中还会将设备的名字和设备驱动的名字进行一个匹配,如果这个也没有成功才说明设备与设备驱动匹配过程失败。
1.3 i2c_device_probe
1 static int i2c_device_probe(struct device *dev) 2 { 3 struct i2c_client *client = i2c_verify_client(dev); // 通过device指针获取到对应的i2c_client指针 4 struct i2c_driver *driver; 5 int status; 6 7 if (!client) 8 return 0; 9 10 driver = to_i2c_driver(dev->driver); // 通过device->driver指针获取到对应的i2c_driver指针 11 if (!driver->probe || !driver->id_table) 12 return -ENODEV; 13 client->driver = driver; // i2c设备通过i2c_client->driver指针去指向与他匹配成功的设备驱动i2c_driver 14 if (!device_can_wakeup(&client->dev)) 15 device_init_wakeup(&client->dev, 16 client->flags & I2C_CLIENT_WAKE); 17 dev_dbg(dev, "probe\n"); 18 19 status = driver->probe(client, i2c_match_id(driver->id_table, client)); // 调用设备驱动层的probe函数 20 if (status) { 21 client->driver = NULL; 22 i2c_set_clientdata(client, NULL); 23 } 24 return status; 25 }
2 i2c_client
i2c_client即I2C设备的注册接口有三个:
i2c_register_board_info
i2c_new_device
i2c_new_dummy
i2c_new_dummy在内部其实也就是将client的name指定为dummy后依旧执行的是i2c_new_device,所以就只分析前两个就可以了。
首先看这两个函数的原型:
2.1 i2c_register_board_info
定义位于:drivers\i2c\i2c-boardinfo.c
busnum :通过总线号指定这个(些)设备属于哪个总线
info i2c:设备的数组集合 i2c_board_info格式
len: 数组个数ARRAY_SIZE(info)
1 /** 2 * i2c_register_board_info - statically declare I2C devices 3 * @busnum: identifies the bus to which these devices belong 4 * @info: vector of i2c device descriptors 5 * @len: how many descriptors in the vector; may be zero to reserve 6 * the specified bus number. 7 * 8 * Systems using the Linux I2C driver stack can declare tables of board info 9 * while they initialize. This should be done in board-specific init code 10 * near arch_initcall() time, or equivalent, before any I2C adapter driver is 11 * registered. For example, mainboard init code could define several devices, 12 * as could the init code for each daughtercard in a board stack. 13 * 14 * The I2C devices will be created later, after the adapter for the relevant 15 * bus has been registered. After that moment, standard driver model tools 16 * are used to bind "new style" I2C drivers to the devices. The bus number 17 * for any device declared using this routine is not available for dynamic 18 * allocation. 19 * 20 * The board info passed can safely be __initdata, but be careful of embedded 21 * pointers (for platform_data, functions, etc) since that won't be copied. 22 */ 23 int __init 24 i2c_register_board_info(int busnum, 25 struct i2c_board_info const *info, unsigned len) 26 { 27 int status; 28 29 down_write(&__i2c_board_lock); //i2c设备信息读写锁,锁写操作,其他只读 30 31 /* dynamic bus numbers will be assigned after the last static one */ 32 if (busnum >= __i2c_first_dynamic_bus_num) //与动态分配的总线号相关,动态分配的总线号应该是从已经现有最大总线号基础上+1的,这样能够保证动态分配出的总线号与板级总线号不会产生冲突 33 __i2c_first_dynamic_bus_num = busnum + 1; 34 35 for (status = 0; len; len--, info++) { //处理info数组中每个成员 36 struct i2c_devinfo *devinfo; 37 38 devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); 39 if (!devinfo) { 40 pr_debug("i2c-core: can't register boardinfo!\n"); 41 status = -ENOMEM; 42 break; 43 } 44 45 devinfo->busnum = busnum; //组装总线号 46 devinfo->board_info = *info; //组装设备信息 47 list_add_tail(&devinfo->list, &__i2c_board_list); //加入到__i2c_board_list链表中(尾部) 48 } 49 50 up_write(&__i2c_board_lock); //释放读锁,其他可读可写 51 52 return status; 53 }
核心内容就是说关于集成的I2C设备注册过程应该在板级代码初始化期间,也就是arch_initcall前后的时间,或者就在这个时候(board-xxx-yyy.c中),切记切记!!!一定要在I2C适配器驱动注册前完成!!!为什么说是静态注册,是因为真实的I2C设备是在适配器成功注册后才被生成的。如果在I2C适配器注册完后还想要添加I2C设备的话,就要通过新方式!(即i2c_new_device)。
借用博友对此过程的形容:小弟永远要挡在老大前边嘛!老大还没出来前,小弟们赶紧前排列阵好,老大到了可不等你,你列阵也没用了。而对于迟到的小弟,自己想办法追上去吧,在原地自己列阵是白费工夫了。
对于__i2c_board_list链表中的信息是如何变成实际的i2c设备信息的呢?此过程放在adapter注册中实现的。记得,重点是i2c_register_board_info方式一定要赶在I2C适配器的注册前,这样就没有问题。
2.2 i2c_new_device
定义位于:drivers\i2c\i2c-core.c
adap :此设备所依附的I2C适配器指针
info :此设备描述,i2c_board_info格式,bus_num成员是被忽略的
1 /** 2 * i2c_new_device - instantiate an i2c device 3 * @adap: the adapter managing the device 4 * @info: describes one I2C device; bus_num is ignored 5 * Context: can sleep 6 * 7 * Create an i2c device. Binding is handled through driver model 8 * probe()/remove() methods. A driver may be bound to this device when we 9 * return from this function, or any later moment (e.g. maybe hotplugging will 10 * load the driver module). This call is not appropriate for use by mainboard 11 * initialization logic, which usually runs during an arch_initcall() long 12 * before any i2c_adapter could exist. 13 * 14 * This returns the new i2c client, which may be saved for later use with 15 * i2c_unregister_device(); or NULL to indicate an error. 16 */ 17 struct i2c_client * 18 i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) 19 { 20 struct i2c_client *client; 21 int status; 22 23 client = kzalloc(sizeof *client, GFP_KERNEL); //为即将注册的client申请内存 24 if (!client) 25 return NULL; 26 27 client->adapter = adap; //绑定指定的adapter适配器 28 29 client->dev.platform_data = info->platform_data; //保存设备数据 30 31 if (info->archdata) //代码上看是DMA相关操作数据 32 client->dev.archdata = *info->archdata; 33 34 client->flags = info->flags; //类型,(一)中说过,或是10位地址,或是使用SMBus检错 35 client->addr = info->addr; //设备从地址 36 client->irq = info->irq; //设备终端 37 38 strlcpy(client->name, info->type, sizeof(client->name)); //从设备名 39 //瞧!(一)中说过i2c_board_info中的信息是与i2c_client有对应关系的,灵验了吧! 40 41 /* Check for address validity */ 42 status = i2c_check_client_addr_validity(client); //检测地址是否有效,10位地址是否大于0x3ff,7位地址是否大于0x7f或为0 43 if (status) { //非零(实际上为-22,无效参数Invalid argument 44 dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", 45 client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); 46 goto out_err_silent; 47 } 48 49 /* Check for address business */ 50 status = i2c_check_addr_busy(adap, client->addr); //检测指定适配器上该地址状态 51 if (status) 52 goto out_err; 53 54 client->dev.parent = &client->adapter->dev; //建立从设备与适配器的父子关系 55 client->dev.bus = &i2c_bus_type; 56 client->dev.type = &i2c_client_type; 57 client->dev.of_node = info->of_node; 58 ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle); 59 60 /* For 10-bit clients, add an arbitrary offset to avoid collisions */ 61 dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), 62 client->addr | ((client->flags & I2C_CLIENT_TEN) 63 ? 0xa000 : 0)); //如果是10位地址设备,那名字格式与7bit的会有不同 64 status = device_register(&client->dev); //注册了!注册了!!! 65 if (status) 66 goto out_err; 67 68 dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n", 69 client->name, dev_name(&client->dev)); 70 71 return client; 72 73 out_err: 74 dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " 75 "(%d)\n", client->name, client->addr, status); 76 out_err_silent: 77 kfree(client); 78 return NULL; 79 }
i2d_new_device没什么好多说的,由于有i2c_register_board_info的铺垫,相信也很好理解了。而i2c_new_device不但印证了i2c_client与i2c_board_info的对应关系,还顺便体现了10bit地址设备与7bit地址设备的略微不同。通过两者的对比,可以再总结出几点区别,从而更好的理解I2C设备的注册方法:
(1)i2c_register_board_info的形参需要的是总线号
(2)i2c_new_device的形参需要的直接是适配器的指针
我想这也正好能完美的说明两者的根本区别,对于板级设备更在乎适配器的总线号,因为这是固定的,没有异议的。而对于可插拔设备,因为其适配器可能非板级集成的,所以不能在乎其总线号,反而只要寻求其适配器指针进行绑定即可。后边adapter注册的分析能更好的证明这一点。
(1)i2c_register_board_info可以同时注册多个I2C设备
(2)i2c_new_device只能一次注册一个I2C设备
这也是其根本区别决定的,板级代码中常包含有许多I2C设备,所以i2c_register_board_info需要有同时注册多个I2C设备的能力也可以说是刚需。而i2c_new_device既然是用来给可插拔设备用的,想必设备数量并不多,而常可能只是一个两个而已,所以一次一个就够了,需求量并不大。
3 i2c_driver
I2C设备驱动。Linux内核给出的接口只有两个,一个是注册,另一个就是卸载。在之前也分析过module_i2c_driver这个宏定义,因为有它的存在,I2C设备驱动的开发可以不用在意你的I2C驱动需要如何注册以及如何卸载的,全部的精力都放在i2c_driver的完善上就可以了。
通过最开始的表单能明显察觉到,I2C子系统中I2C driver的开放接口最少,说白了就是需要驱动编写者完成完了i2c_driver放入module_i2c_driver宏中即可,而正因为如此,也恰恰说明,i2c_driver的灵活性是最高的。通常驱动会首先在意在用户空间的打开、关闭、读写等接口,但是对于i2c_driver来说,这些工作是I2C子系统已经做好的,关于常用的读写最终也是通过adapter实现的i2c_algorithm达到目的。好吧,再次说明了I2C子系统的完善程度,对于I2C设备及驱动开发来说是极其方便的。那么I2C驱动要实现什么呢?
先看下i2c_driver结构体,不过现在要剔除一些不常用的成员:
1 struct i2c_driver { 2 int (*probe)(struct i2c_client *, const struct i2c_device_id *); //现行通用的与对应设备进行绑定的接口函数 3 int (*remove)(struct i2c_client *); //现行通用与对应设备进行解绑的接口函数 4 5 void (*shutdown)(struct i2c_client *); //关闭设备 6 int (*suspend)(struct i2c_client *, pm_message_t mesg); //挂起设备,与电源管理有关,为省电 7 int (*resume)(struct i2c_client *); //从挂起状态恢复 8 9 struct device_driver driver; //I2C设备的驱动模型 10 const struct i2c_device_id *id_table; //匹配设备列表 11 ... 12 };
如果有可能的话,我还想再精简一下:
1 struct i2c_driver { 2 int (*probe)(struct i2c_client *, const struct i2c_device_id *); //现行通用的与对应设备进行绑定的接口函数 3 int (*remove)(struct i2c_client *); //现行通用与对应设备进行解绑的接口函数 4 5 struct device_driver driver; //I2C设备的驱动模型 6 const struct i2c_device_id *id_table; //匹配设备列表 7 ... 8 };
3.1 电源管理
i2c_driver精简到上述这种程度,为什么把电源管理相关也干掉了呢?实际上没有,通常实际的I2C驱动喜欢在drivers中完成这个动作(以mpu3050为例):
1 static UNIVERSAL_DEV_PM_OPS(mpu3050_pm, mpu3050_suspend, mpu3050_resume, NULL); 2 3 static const struct i2c_device_id mpu3050_ids[] = { 4 { "mpu3050", 0 }, 5 { } 6 }; 7 MODULE_DEVICE_TABLE(i2c, mpu3050_ids); 8 9 static const struct of_device_id mpu3050_of_match[] = { 10 { .compatible = "invn,mpu3050", }, 11 { }, 12 }; 13 MODULE_DEVICE_TABLE(of, mpu3050_of_match); 14 15 static struct i2c_driver mpu3050_i2c_driver = { 16 .driver = { 17 .name = "mpu3050", 18 .owner = THIS_MODULE, 19 .pm = &mpu3050_pm, 20 .of_match_table = mpu3050_of_match, 21 }, 22 .probe = mpu3050_probe, 23 .remove = mpu3050_remove, 24 .id_table = mpu3050_ids, 25 }; 26 27 module_i2c_driver(mpu3050_i2c_driver);
可以看到,实际驱动中喜欢将电源管理集成在i2c_driver的driver成员中。
UNIVERSAL_DEV_PM_OPS这个名字很犀利,貌似是“宇宙终极驱动电源管理大法”的样子:
1 #define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \ 2 const struct dev_pm_ops name = { \ 3 SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ 4 SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ 5 } 6 7 #define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \ 8 .suspend = suspend_fn, \ 9 .resume = resume_fn, \ 10 .freeze = suspend_fn, \ 11 .thaw = resume_fn, \ 12 .poweroff = suspend_fn, \ 13 .restore = resume_fn, 14 15 #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ 16 .runtime_suspend = suspend_fn, \ 17 .runtime_resume = resume_fn, \ 18 .runtime_idle = idle_fn,
结合MPU3050的驱动将其完整展开可以得到:
1 static const struct dev_pm_ops mpu3050_pm = { 2 .suspend = mpu3050_suspend, 3 .resume = mpu3050_resume, 4 .freeze = mpu3050_suspend, 5 .thaw = mpu3050_resume, 6 .poweroff = mpu3050_suspend, 7 .restore = mpu3050_resume, 8 .runtime_suspend = mpu3050_suspend, 9 .runtime_resume = mpu3050_resume, 10 .runtime_idle = NULL, 11 }
对电源管理有兴趣的可以去查阅pm.h,其中对电源管理有详尽的说明了,这里不做分析。可以看到,在电源管理中,有很多成员实际上是一样的,在现实驱动中这样的情况也经常出现,所以会有“终极电源管理大法”宏的出现了。
上边说过,i2c_driver的多样化最多,从mpu3050的驱动注册中也可以发现,其注重实现的为probe与电源管理,其中probe最为重要(好像是废话,哪个驱动这个都是最重要的-。-)。因为主要是从驱动的角度看待I2C子系统,所以这里不详尽分析mpu3050的代码,只以其为例说明I2C驱动大体框架。在mpu3050的probe主要对此传感器进行上电、工作模式初始化、注册INPUT子系统接口、关联中断处理程序(在中断处理线程中上报三轴参数)等工作。
3.2 i2c_add_driver
i2c_add_driver函数是定义在 include\linux\i2c.h 头文件中的一个静态内敛函数,但是函数内部是直接调用了I2C核心层的i2c_register_driver函数来进行正真的工作。该函数是提供用来注册一个I2C总线下的设备驱动的接口。
1 /*
2 * An i2c_driver is used with one or more i2c_client (device) nodes to access
3 * i2c slave chips, on a bus instance associated with some i2c_adapter.
4 */
5
6 int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
7 {
8 int res;
9
10 /* Can't register until after driver model init */
11 if (unlikely(WARN_ON(!i2c_bus_type.p)))
12 return -EAGAIN;
13
14 /* add the driver to the list of i2c drivers in the driver core */
15 driver->driver.owner = owner;
16 driver->driver.bus = &i2c_bus_type;//指定该设备驱动的总线类型 i2c
17
18 /* When registration returns, the driver core
19 * will have called probe() for all matching-but-unbound devices.
20 */
21 res = driver_register(&driver->driver);//注册设备驱动sys/bus/i2c/drivers/dummy,dummy就是一个设备驱动文件
22 if (res)
23 return res;
24
25 /* Drivers should switch to dev_pm_ops instead. */
26 if (driver->suspend)
27 pr_warn("i2c-core: driver [%s] using legacy suspend method\n",
28 driver->driver.name);
29 if (driver->resume)
30 pr_warn("i2c-core: driver [%s] using legacy resume method\n",
31 driver->driver.name);
32
33 pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
34
35 INIT_LIST_HEAD(&driver->clients);//初始化i2c_driver -> clients 链表
36 /* Walk the adapters that are already present */
37 i2c_for_each_dev(driver, __process_new_driver);
38
39 return 0;
40 }
3.3 总结
I2C设备驱动通常只是需要挂载在I2C总线(即依附于I2C子系统),I2C子系统对于设备驱动来说只是一个载体、基石。许多设备的主要核心是建立在其他子系统上,如重力传感器、三轴传感器、触摸屏等通常主要工作集中在INPUT子系统中,而相机模块、FM模块、GPS模块大多主要依附于V4L2子系统。这也能通过I2C设计理念证明,I2C的产生正是为了节省外围电路复杂度,让CPU使用有限的IO口挂载更多的外部模块。假设CPU的扩展IO口足够多,我想I2C也没什么必要存在了,毕竟直接操作IO口驱动设备比I2C来的更简单。
4 i2c_adapter
对于I2C adapter的注册有两种途径:i2c_add_adapter 或i2c_add_numbered_adapter,两者的区别是后者在注册时已经指定了此I2C适配器的总线号,而前者的总线号将由系统自动分配。
其各自的声明格式为:
int i2c_add_adapter(struct i2c_adapter *adapter)
int i2c_add_numbered_adapter(struct i2c_adapter *adap)
在i2c_add_numberd_adapter使用前必须制定adap->nr,如果给-1,说明还是叫系统去自动生成总线号的。
之所以区分开两种I2C adapter的注册方式,是因为他们的使用场景有所不同。
(1)i2c_add_adapter的使用经常是用来注册那些可插拔设备,如USB PCI设备等。主板上的其他模块与其没有直接联系,说白了就是现有模块不在乎新加入的I2C适配器的总线号是多少,因为他们不需要。反而这个可插拔设备上的一些模块会需要其注册成功的适配器指针。回看一开始就分析的i2c_client,会发现不同场景的设备与其匹配的适配器有着这样的对应关系:
1 i2c_register_board_info需要指定已有的busnum,而i2c_add_numbered_adapter注册前已经指定总线号; 2 i2c_new_device需要指定adapter指针,而i2c_add_adapter注册成功后恰好这个指针就有了。
借用博友的形象比喻:
想象这样一个场景:新设备插入后,对应的驱动程序通过i2c_add_adapter注册自己的I2C适配器,然后根据与小弟们的协定将其是适配器指针存放在某处,相当于对小弟们(依附在其上的I2C设备)说:“看见没?你们注册你们自己的设备的时候就通过这个就能找到我,就能跟我混了!”然后驱动程序继续,当执行到对自己的I2C设备注册时候,小弟们去约定地点找老大留下的记号,发现有效信息后,一拥而上:“看!老大在那!!!”
(2)i2c_add_numbered_adapter用来注册CPU自带的I2C适配器,或是集成在主板上的I2C适配器。主板上的其他I2C从设备(client)在注册时候需要这个总线号。
通过简短的代码分析看一看他们的区别究竟如何,以及为什么静态注册的i2c_client必须要在adapter注册前(此处会精简部分代码,只留重要部分):
4.1 i2c_add_adapter
1 /** 2 * i2c_add_adapter - declare i2c adapter, use dynamic bus number 3 * @adapter: the adapter to add 4 * Context: can sleep 5 * 6 * This routine is used to declare an I2C adapter when its bus number 7 * doesn't matter or when its bus number is specified by an dt alias. 8 * Examples of bases when the bus number doesn't matter: I2C adapters 9 * dynamically added by USB links or PCI plugin cards. 10 * 11 * When this returns zero, a new bus number was allocated and stored 12 * in adap->nr, and the specified adapter became available for clients. 13 * Otherwise, a negative errno value is returned. 14 */ 15 int i2c_add_adapter(struct i2c_adapter *adapter) 16 { 17 struct device *dev = &adapter->dev; 18 int id; 19 20 if (dev->of_node) { 21 id = of_alias_get_id(dev->of_node, "i2c"); 22 if (id >= 0) { 23 adapter->nr = id; 24 return __i2c_add_numbered_adapter(adapter); 25 } 26 } 27 28 mutex_lock(&core_lock); 29 id = idr_alloc(&i2c_adapter_idr, adapter, 30 __i2c_first_dynamic_bus_num, 0, GFP_KERNEL);//动态获取总线号 31 mutex_unlock(&core_lock); 32 if (id < 0) 33 return id; 34 35 adapter->nr = id; 36 37 return i2c_register_adapter(adapter);//注册i2c主机 38 }
4.2 i2c_add_numbered_adapter
1 int i2c_add_numbered_adapter(struct i2c_adapter *adap) 2 { 3 if (adap->nr == -1) /* -1 means dynamically assign bus id */ 4 return i2c_add_adapter(adap); 5 6 return __i2c_add_numbered_adapter(adap); 7 }
__i2c_add_numbered_adapter
1 /** 2 * __i2c_add_numbered_adapter - i2c_add_numbered_adapter where nr is never -1 3 * @adap: the adapter to register (with adap->nr initialized) 4 * Context: can sleep 5 * 6 * See i2c_add_numbered_adapter() for details. 7 */ 8 static int __i2c_add_numbered_adapter(struct i2c_adapter *adap) 9 { 10 int id; 11 12 mutex_lock(&core_lock); 13 id = idr_alloc(&i2c_adapter_idr, adap, adap->nr, adap->nr + 1, 14 GFP_KERNEL); 15 mutex_unlock(&core_lock); 16 if (id < 0) 17 return id == -ENOSPC ? -EBUSY : id; 18 19 return i2c_register_adapter(adap); 20 }
可见,最终他们都是通过i2c_register_adapter注册适配器:
4.3 i2c_register_adapter
向i2c总线注册适配器adapter
1 static int i2c_register_adapter(struct i2c_adapter *adap) 2 { 3 int res = 0; 4 5 /* Can't register until after driver model init */ //时序检查 6 if (unlikely(WARN_ON(!i2c_bus_type.p))) { 7 res = -EAGAIN; 8 goto out_list; 9 } 10 11 /* Sanity checks */ 12 if (unlikely(adap->name[0] == '\0')) { //防御型代码,检查适配器名称 13 pr_err("i2c-core: Attempt to register an adapter with " 14 "no name!\n"); 15 return -EINVAL; 16 } 17 if (unlikely(!adap->algo)) { //适配器是否已经完成了通信方法的实现 18 pr_err("i2c-core: Attempt to register adapter '%s' with " 19 "no algo!\n", adap->name); 20 return -EINVAL; 21 } 22 23 rt_mutex_init(&adap->bus_lock); 24 mutex_init(&adap->userspace_clients_lock); 25 INIT_LIST_HEAD(&adap->userspace_clients); 26 27 /* Set default timeout to 1 second if not already set */ 28 if (adap->timeout == 0) 29 adap->timeout = HZ; 30 31 dev_set_name(&adap->dev, "i2c-%d", adap->nr); 32 adap->dev.bus = &i2c_bus_type; 33 adap->dev.type = &i2c_adapter_type; 34 res = device_register(&adap->dev); //注册设备节点 35 if (res) 36 goto out_list; 37 dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); 38 39 #ifdef CONFIG_I2C_COMPAT 40 res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev, 41 adap->dev.parent); 42 if (res) 43 dev_warn(&adap->dev, 44 "Failed to create compatibility class link\n"); 45 #endif 46 47 /* bus recovery specific initialization */ 48 if (adap->bus_recovery_info) { 49 struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; 50 51 if (!bri->recover_bus) { 52 dev_err(&adap->dev, "No recover_bus() found, not using recovery\n"); 53 adap->bus_recovery_info = NULL; 54 goto exit_recovery; 55 } 56 57 /* Generic GPIO recovery */ 58 if (bri->recover_bus == i2c_generic_gpio_recovery) { 59 if (!gpio_is_valid(bri->scl_gpio)) { 60 dev_err(&adap->dev, "Invalid SCL gpio, not using recovery\n"); 61 adap->bus_recovery_info = NULL; 62 goto exit_recovery; 63 } 64 65 if (gpio_is_valid(bri->sda_gpio)) 66 bri->get_sda = get_sda_gpio_value; 67 else 68 bri->get_sda = NULL; 69 70 bri->get_scl = get_scl_gpio_value; 71 bri->set_scl = set_scl_gpio_value; 72 } else if (!bri->set_scl || !bri->get_scl) { 73 /* Generic SCL recovery */ 74 dev_err(&adap->dev, "No {get|set}_gpio() found, not using recovery\n"); 75 adap->bus_recovery_info = NULL; 76 } 77 } 78 79 exit_recovery: 80 /* create pre-declared device nodes */ //创建预-声明的I2C设备节点 81 if (adap->nr < __i2c_first_dynamic_bus_num) 82 i2c_scan_static_board_info(adap); 83 //如果adapter的总线号小于动态分配的总线号的最小那个,说明是板级adapter。 84 //因为通过i2c_add_adapter加入的适配器所分配的总线号一定是比__i2c_first_dynamic_bus_num大的。 85 /* Notify drivers */ 86 mutex_lock(&core_lock); 87 bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); 88 mutex_unlock(&core_lock); 89 90 return 0; 91 92 out_list: 93 mutex_lock(&core_lock); 94 idr_remove(&i2c_adapter_idr, adap->nr); 95 mutex_unlock(&core_lock); 96 return res; 97 }
i2c_register_adapter函数是I2C子系统核心层提供给I2C总线驱动层的用来向核心层注册一个adapter(适配器)的接口函数。从上可以知道这两个函数最终都是调用i2c_register_adapter函数去注册adapter,他们的区别在于:i2c_add_adapter函数是自动分配适配器编号,而i2c_add_numbered_adapter是需要自己手动指定一个适配器编号。这个编号的作用第一是为了i2c子系统方便管理系统中的adapter。
对于i2c_add_numbered_adapter来说会触发i2c_scan_static_board_info:
4.4 i2c_scan_static_board_info
扫描__i2c_board_list链表上挂接的所有的i2c次设备信息并与适配器进行匹配,匹配成功创建i2c次设备
static void i2c_scan_static_board_info(struct i2c_adapter *adapter) { struct i2c_devinfo *devinfo; // 定义一个i2c_devinfo 结构体指针 down_read(&__i2c_board_lock);//持有读写锁的读,由用户读的时候不允许写入 list_for_each_entry(devinfo, &__i2c_board_list, list) { // 遍历 __i2c_board_list 链表上的所有i2c_devinfo 结构体,这就是通过i2c_register_board_info组建起来的那个链表 if (devinfo->busnum == adapter->nr // 比较 i2c_devinfo->busnum 与 适配器的编号是否匹配 && !i2c_new_device(adapter, // 如果匹配就会调用 i2c_new_device 函数进行注册添加新的次设备 i2c_client &devinfo->board_info))//找到总线号与刚注册的这个adapter相同的并通过i2c_new_device进行注册 dev_err(&adapter->dev, "Can't create device at 0x%02x\n", devinfo->board_info.addr); } up_read(&__i2c_board_lock);//释放读写锁 }
而i2c_board_info成员与i2c_client的对应动作也是在i2c_new_device中进行的,这一点在上边已经分析过了。看到这里,对adapter与client的微妙关系应该了解程度就比较深了,为什么说i2c_register_board_info与i2c_add_numbered_adapter对应而不是i2c_add_adapter也可以说得通。
最后总结下两个问题:
(1)i2c_adapter驱动如何添加?
板级适配器(CPU自带、主板集成)要通过i2c_add_numbered_adapter注册,注册前要指定总线号,从0开始。假如板级I2C适配器注册了3个,那么第一个动态总线号一定是3,也就是说可插拔设备所带有的I2C适配器需要通过i2c_add_adapter进行注册,其总线号由系统指定。
(2)i2c_client与i2c_board_info的关系:
i2c_client与i2c_board_info的对应关系在i2c_new_device中有完整体现。
i2c_client->dev.platform_data = i2c_board_info->platform_data; i2c_client->dev.archdata = i2c_board_info->archdata; i2c_client->flags = i2c_board_info->flags; i2c_client->addr = i2c_board_info->addr; i2c_client->irq = i2c_board_info->irq;
4.5 i2c_new_device
i2c_new_device是I2C核心层提供给设备层注册i2c设备时使用的一个接口函数,我们可以在注册i2c设备时直接调用这个函数进行注册。
1 /** 2 * i2c_new_device - instantiate an i2c device 3 * @adap: the adapter managing the device 4 * @info: describes one I2C device; bus_num is ignored 5 * Context: can sleep 6 * 7 * Create an i2c device. Binding is handled through driver model 8 * probe()/remove() methods. A driver may be bound to this device when we 9 * return from this function, or any later moment (e.g. maybe hotplugging will 10 * load the driver module). This call is not appropriate for use by mainboard 11 * initialization logic, which usually runs during an arch_initcall() long 12 * before any i2c_adapter could exist. 13 * 14 * This returns the new i2c client, which may be saved for later use with 15 * i2c_unregister_device(); or NULL to indicate an error. 16 */ 17 struct i2c_client * 18 i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) 19 { 20 struct i2c_client *client; // 定义一个 i2c_client 指针 21 int status; 22 23 client = kzalloc(sizeof *client, GFP_KERNEL); // 申请分配 24 if (!client) 25 return NULL; 26 27 // 对i2c_client结构体变量进行填充 28 client->adapter = adap; // i2c次设备通过i2c_client->adapter指针去指向与它匹配成功的适配器i2c_adapter 29 client->dev.platform_data = info->platform_data; // 将传进来的i2c_board_info结构体作为i2c次设备的platform平台数据 30 31 if (info->archdata) 32 client->dev.archdata = *info->archdata; 33 34 client->flags = info->flags; // 标志位 35 client->addr = info->addr; // i2c次设备的地址 36 client->irq = info->irq; // 中断号 37 38 strlcpy(client->name, info->type, sizeof(client->name)); // 名字 39 40 /* Check for address validity */ 41 status = i2c_check_client_addr_validity(client); // 次设备地址校验 42 if (status) { 43 dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", 44 client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); 45 goto out_err_silent; 46 } 47 48 /* Check for address business */ 49 status = i2c_check_addr_busy(adap, client->addr); 50 if (status) 51 goto out_err; 52 53 client->dev.parent = &client->adapter->dev; // 指定i2c 次设备的父设备是与它匹配成功的适配器对应的设备 54 client->dev.bus = &i2c_bus_type; // 指定次设备的总线类型 55 client->dev.type = &i2c_client_type; // 指定次设备的设备类型 56 #ifdef CONFIG_OF 57 client->dev.of_node = info->of_node; 58 #endif 59 60 dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), // 设置次设备的名字 %d-%04x 61 client->addr); 62 status = device_register(&client->dev); // 注册次设备: /sys/devices/platform/s3c2410-i2cn/i2c-%d/%d-%04x 63 if (status) 64 goto out_err; 65 66 dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n", 67 client->name, dev_name(&client->dev)); 68 69 return client; 70 71 out_err: 72 dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " 73 "(%d)\n", client->name, client->addr, status); 74 out_err_silent: 75 kfree(client); 76 return NULL; 77 }
总结:从上面的分析其实可以知道:i2c子系统内部存在着2个匹配过程:
(1)i2c总线下的设备与设备驱动之间的匹配(通过设备驱动的id_table)
(2)adapter适配器与设备之间的匹配(通过适配器编号)
二 I2C总线驱动层代码分析
以此目录为例:drivers\i2c\busses\i2c-s3c2410.c
I2C总线驱动是I2C适配器的软件实现,提供I2C适配器与从设备间完成数据通信的能力,I2C总线驱动由i2c_adapter和i2c_algorithm来描述。
待续。
参考博文: