I2C子系统之I2C bus初始化——I2C_init()


根据前文的分析(
),在linux内核启动的时候最先执行的和I2C子系统相关的函数应该是driver/i2c/i2c-core.c文件中的

i2c_init()函数。下面具体此函数具体做了那些预备工作。

1.i2c总线的注册

i2c_init()的函数实现如下:

  1. static int __init i2c_init(void)    
  2. {    
  3.         ... ...    
  4.     retval = bus_register(&i2c_bus_type);    
  5.         ... ...    
  6. }    
可以发现i2c_inti的函数主要功能就是注册i2c总线。下面重点分析下这个i2c_bus_type这个表示总线的结构体。

2.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. };  

总线提供了match和probe方法:match方法的用来进行client device和client driver的配对。

在向总线i2c_bus_type注册设备或者驱动时会调用此方法。

2.6.37.1中的at24c02采用的是i2c_match_id这种方法,本质上还是通过name来配对。

  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)                              //判断当前的dev是否是client类型,假如不是立即返回   
  7.         return 0;  
  8.   
  9.     /* Attempt an OF style match */  
  10.     if (of_driver_match_device(dev, drv))    //条件drv->of_match_table,对at24来说是at24_driver->drv->of_match_table   
  11.         return 1;  
  12.   
  13.     driver = to_i2c_driver(drv);  
  14.     /* match on an id table if there is one */  
  15.     if (driver->id_table)  
  16.         return i2c_match_id(driver->id_table, client) != NULL;  
  17.   
  18.     return 0;  
  19. }  

probe方法在完成设备和驱动的配对后调用执行,i2c_bus_type的probe方法是通过传递进来的drv找到

包含此drv的i2c_driver驱动,然后再去调用i2c_driver的probe方法,此处就是at24_probe。为什么要这

样呢?因为driver_register后,注册的是i2_driver->drv,而drv中的probe未初始化,我们需要调用的是

i2c-driver的probe方法。

  1. static int i2c_device_probe(struct device *dev)  
  2. {  
  3.     struct i2c_client   *client = i2c_verify_client(dev);  
  4.     struct i2c_driver   *driver;  
  5.     int status;  
  6.   
  7.     if (!client)  
  8.         return 0;  
  9.   
  10.     driver = to_i2c_driver(dev->driver);  
  11.     if (!driver->probe || !driver->id_table)  
  12.         return -ENODEV;  
  13.     client->driver = 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));  
  20.     if (status) {  
  21.         client->driver = NULL;  
  22.         i2c_set_clientdata(client, NULL);  
  23.     }  
  24.     return status;  
  25. }  

相关阅读:

I2C子系统之at24c02读写测试
I2C子系统之ioctl() 
I2C子系统之at24c02简介
I2C子系统之总结
I2C子系统之内核中I2C子系统的结构
I2C子系统之I2C bus初始化——I2C_init()
I2C子系统之platfor_device初始化——smdk2440_machine_init()
I2C子系统之platform_driver初始化——I2C_adap_s3c_init()
I2C子系统之I2C总线时钟频率设置
I2C子系统之adapter device和client device注册——I2C_add_number_adapter()
I2C子系统之__I2C_first_dynamic_bus_num变量的相关分析
I2C子系统之 adapter driver注册——I2C_dev_init()
I2C子系统之write()

相关内容