I2C adapter init流程分析
1. 前言
I2C adapter作为一条I2C总线的适配器,提供访问其总线上的device的方法,CPU要通过它才能访问到这些device。有兴趣的话可以下载《I2C总线协议》去研究,这些在本文中尚未提及,只是在Linux的I2C的整个架构的角度去描述的。I2C虽然很大程度上已经像经典的Linux设备模型靠拢,但是还是有些地方具有自己的特色。在看开始之前先简单介绍一下init的时候会做些什么,最重要的是获得platform_driver对应的platform_device,然后会回调platform_driver中的probe函数,来完成我们的适配器的结构体,紧接着会把适配器注册到i2c_bus上。(这个部分是由i2c-core.c完成。可以参考另外一个文档。)
#!本文用到的内核版本是2.6.28
2. i2c-s3c2410.c (driver/i2c/busses)
按通常逻辑,先找到module_init,看看i2c_adap_s3c_init。
static int __init i2c_adap_s3c_init(void)
{
...
ret = platform_driver_register(&s3c2410_i2c_driver);
...
}
先给出s3c2410_i2c_driver结构体的定义,因为待会会用到这个。我们看到了刚才提到的probe函数,这里的.driver是一个device_driver类型。
static struct platform_driver s3c2410_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
.suspend_late = s3c24xx_i2c_suspend_late,
.resume = s3c24xx_i2c_resume,
.driver = {
.owner = THIS_MODULE,
.name = "s3c2410-i2c",
},
};
好的,我们回到上面的函数,继续。
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown;
if (drv->suspend)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
drv->driver.resume = platform_drv_resume;
if (drv->pm)
drv->driver.pm = &drv->pm->base;
return driver_register(&drv->driver);
}