写在前面
由于IIC总线只需要两根线就可以完成读写操作,而且通信协议简单,一条总线上可以挂载多个设备,因此被广泛使用。但是IIC总线有一个缺点,就是传输速率比较低。本文基于Linux-2.6.36版本,说说IIC子系统在Linux中的实现。
借用某书上的IIC子系统的体系结构图:
Linux IIC子系统体系结构
下面开始分析IIC子系统。
IIC子系统的初始化在drivers/i2c/i2c-core.c文件中的i2c_init函数中:
00001221 static int __init i2c_init(void)
00001222 {
00001223 int retval;
00001224
00001225 retval = bus_register(&i2c_bus_type);
00001226 if (retval)
00001227 return retval;
00001228 #ifdef CONFIG_I2C_COMPAT
00001229 i2c_adapter_compat_class = class_compat_register("i2c-adapter");
00001230 if (!i2c_adapter_compat_class) {
00001231 retval = -ENOMEM;
00001232 goto bus_err;
00001233 }
00001234 #endif
00001235 retval = i2c_add_driver(&dummy_driver);
00001236 if (retval)
00001237 goto class_err;
00001238 return 0;
00001239
00001240 class_err:
00001241 #ifdef CONFIG_I2C_COMPAT
00001242 class_compat_unregister(i2c_adapter_compat_class);
00001243 bus_err:
00001244 #endif
00001245 bus_unregister(&i2c_bus_type);
00001246 return retval;
00001247 }
1225行,向系统注册IIC总线,其中i2c_bus_type的定义为:
00000343 struct bus_type i2c_bus_type = {
00000344 .name = "i2c",
00000345 .match = i2c_device_match,
00000346 .probe = i2c_device_probe,
00000347 .remove = i2c_device_remove,
00000348 .shutdown = i2c_device_shutdown,
00000349 .pm = &i2c_device_pm_ops,
00000350 };
345行,i2c_device_match函数时用来匹配IIC总线上的设备和设备驱动的,下面看下它的定义:
00000068 static int i2c_device_match(struct device *dev, struct device_driver *drv)
00000069 {
00000070 struct i2c_client *client = i2c_verify_client(dev);
00000071 struct i2c_driver *driver;
00000072
00000073 if (!client)
00000074 return 0;
00000075
00000076 /* Attempt an OF style match */
00000077 if (of_driver_match_device(dev, drv))
00000078 return 1;
00000079
00000080 driver = to_i2c_driver(drv);
00000081 /* match on an id table if there is one */
00000082 if (driver->id_table)
00000083 return i2c_match_id(driver->id_table, client) != NULL;
00000084
00000085 return 0;
00000086 }
在IIC子系统中,用struct i2c_client来描述一个具体的IIC设备(IIC从机)。73行,如果没有IIC设备的话就直接返回0,表示匹配不成功。
77行,用of的方式进行匹配,应该是设备树方面的,具体没了解过。
82行,如果驱动的id table存在则调用83行的i2c_match_id函数进行匹配:
00000057 static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
00000058 const struct i2c_client *client)
00000059 {
00000060 while (id->name[0]) {
00000061 if (strcmp(client->name, id->name) == 0)
00000062 return id;
00000063 id++;
00000064 }
00000065 return NULL;
00000066 }
很简单,就是拿驱动的id table中的每一项与i2c_client的name成员进行比较,如果它们的名字相同就表示匹配成功,否则匹配失败,返回NULL。从这里也可以看出IIC的总线匹配方式与platform总线的匹配方式是不一样,一般情况下,IIC总线的匹配方式是根据设备名字和驱动中的id tabl