按照之前的初始化流程可以得到在该系统下I2C子系统的初始化顺序为:
- (drivers\i2c):postcore_initcall(i2c_init);
- Setup.c
(arch\arm\kernel):arch_initcall(customize_machine)对应的da850_evm_init中
-
davinci_cfg_reg_list(da850_i2c0_pins);
-
da8xx_register_i2c(0, &da850_evm_i2c_pdata);
- i2c_register_board_info(1, da850_evm_i2c_devices,
ARRAY_SIZE(da850_evm_i2c_devices)); - I2c-davinci.c(drivers\i2c\busses):subsys_initcall(davinci_i2c_init_driver);
- I2c-gpio.c (drivers\i2c\busses):subsys_initcall(i2c_gpio_init);
I2c-dev.c (drivers\i2c):module_init(i2c_dev_init);
下面按照这个顺序,先来分析i2c_init
static int __init i2c_init(void)
{
int retval;
/*注册I2C总线*/
retval = bus_register(&i2c_bus_type);
if (retval)
return retval;
#ifdef CONFIG_I2C_COMPAT
i2c_adapter_compat_class = class_compat_register("i2c-adapter");
if (!i2c_adapter_compat_class) {
retval = -ENOMEM;
goto bus_err;
}
#endif
retval = i2c_add_driver(&dummy_driver);
if (retval)
goto class_err;
return 0;
class_err:
#ifdef CONFIG_I2C_COMPAT
class_compat_unregister(i2c_adapter_compat_class);
bus_err:
#endif
bus_unregister(&i2c_bus_type);
return retval;
}
第一步先注册I2C总线:
retval = bus_register(&i2c_bus_type);
i2c_bus_type的定义如下:
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,//匹配函数
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,//与电源管理有关
};
重点分析一下:i2c_device_match和I2c_device_probe函数;
match用来进行device和driver的匹配
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
/*返回i2c_client的具体参数,它可以防止把一些不是i2c的设备当作是i2c_client*/
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
/*i2c_verify_client返回NULL,表示这个设备不是i2c的设备*/
if (!client)
return 0;
/* 尝试OF风格的匹配 */
if (of_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);//通过device->driver指针获取到对应的i2c_driver指针
/* match on an id table if there is one */
if (driver->id_table)
/*如果i2c驱动的id_table存在的话,使用该函数进行匹配,匹配的方法是拿driver-id_table中的
每一项与client进行匹配,如果相同则匹配成功*/
return i2c_match_id(driver->id_table, client) != NULL;
return 0;
}
probe用于在完成设备和驱动的配对之后调用执行。
static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);//通过device指针获取到对应的i2c_client指针
struct i2c_driver *driver;
int status;
if (!client)
return 0;
driver = to_i2c_driver(dev->driver);//通过device->driver指针获取到对应的i2c_driver指针
if (!driver->probe || !driver->id_table)
return -ENODEV;
client->driver = driver;//i2c设备通过i2c_client->driver指针去指向与他匹配成功的设备驱动i2c_driver
if (!device_can_wakeup(&client->dev))
device_init_wakeup(&client->dev,
client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n");
status = driver->probe(client, i2c_match_id(driver->id_table, client));调用设备驱动层的probe函数
if (status) {
client->driver = NULL;
i2c_set_clientdata(client, NULL);
}
return status;
}