OMAP3630 I2C device驱动

     在Linux内核中,I2C device驱动位于drivers/i2c/chips目录下,可以看到该目录下有很多相关的device驱动,这里以xxxx项目的mma7455为例介绍device驱动的注册过程,对应的device驱动程序为mma7455.c。

   既然有device驱动,那么必定有相应的device,I2C的device是什么呢?其实就是我们在1.3节中提到的i2c_client,所以在device驱动注册之前先来了解下i2c_client的注册过程。

  4.1 Mma7455 device注册
    Mma7455 device即i2c_client的创建以及注册分为两步。
4.1.1 将mma7455设备信息加入到设备链表
    在板级初始化时将I2C device的名称,地址和相关的信息加入到链表__i2c_board_list中,该链表记录了具体开发板上的I2C设备信息。
    在board-xxxx.c中,定义了mma7455的设备信息定义如下:
  1. static struct i2c_board_info __initdata xxxx_i2c_bus3_info[] = {   
  2. ……   
  3. #ifdef CONFIG_SENSORS_MMA7455   
  4.         {   
  5.         I2C_BOARD_INFO("mma7455", 0x1D),   
  6.         .platform_data = &xxxx_mma7455_platform_data,   
  7.         },   
  8. #endif   
  9. };  

    Mma7455加入到设备链表__i2c_board_list的流程图如下图:

 

  OMAP3630 I2C device驱动_第1张图片
相应的代码位于i2c-core.c如下:
  1. static void i2c_scan_static_board_info(struct i2c_adapter *adapter)   
  2. {   
  3.     ……   
  4.     list_for_each_entry(devinfo, &__i2c_board_list, list) {   
  5.         if (devinfo->busnum == adapter->nr   
  6.                 && !i2c_new_device(adapter,   
  7.                         &devinfo->board_info))   
  8.             ……   
  9.     }   
  10.     ……   
  11. }  

    在i2c_scan_static_board_info()函数中遍历I2C设备链表__i2c_board_list,设备的总线号和adapter的总线号相等,则使用函数i2c_new_device()创建该设备。

  1. struct i2c_client *   
  2. i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)   
  3. {   
  4.     ……   
  5.     client = kzalloc(sizeof *client, GFP_KERNEL);   
  6.     if (!client)   
  7.         return NULL;   
  8.     client->adapter = adap;   
  9.     client->dev.platform_data = info->platform_data;   
  10.     if (info->archdata)   
  11.         client->dev.archdata = *info->archdata;   
  12.     client->flags = info->flags;   
  13.     client->addr = info->addr;   
  14.     client->irq = info->irq;   
  15.     strlcpy(client->name, info->type, sizeof(client->name));   
  16.     ……   
  17.     status = i2c_attach_client(client);   
  18.     ……   
  19. }  

     在函数i2c_new_device()中创建一个i2c_client,初始化该结构体的adapter,addr,name等变量,这里的client->name被初始化为info->type,在4.1.1中,info->type初始化为“mma7455”, client->name后面会用于I2C device和I2C driver匹配时使用,最后调用i2c_attach_client()将该client注册到I2C core。

  1. int i2c_attach_client(struct i2c_client *client)   
  2. {   
  3.     struct i2c_adapter *adapter = client->adapter;   
  4.     ……   
  5.     client->dev.parent = &client->adapter->dev;   
  6.     client->dev.bus = &i2c_bus_type;   
  7.   
  8.     ……   
  9.     res = device_register(&client->dev);   
  10.     ……   
  11. }  

    函数i2c_attach_client()进一步初始化i2c_client结构体,将该设备的总线初始化为i2c_bus_type,说明该设备被放在I2C总线上,用于后面跟I2C driver匹配时使用,最后使用device_register(&client->dev)注册该i2c_client设备。
4.2 Mma7455 device驱动注册
    在mma7455.c中,定义了mma7455的device驱动,代码如下:

  1. static struct i2c_driver mma7455_driver = {   
  2.     .driver     = {   
  3.                 .name = "mma7455",   
  4.             },   
  5.     .class      = I2C_CLASS_HWMON,   
  6.     .probe      = mma7455_probe,   
  7.     .remove     = mma7455_remove,   
  8.     .id_table   = mma7455_id,   
  9.     ……   
  10. };  

OMAP3630 I2C device驱动_第2张图片

相应的代码位于mma7455.c和i2c-core.c。

  1. static int __init init_mma7455(void)   
  2. {   
  3.     ……   
  4.     res = i2c_add_driver(&mma7455_driver);   
  5.     ……   
  6.     return (res);   
  7. }  

    在模块加载的时候首先调用init_mma7455(),然后init_mma7455()调用函数i2c_add_driver()注册mma7455_driver结构体。

  1. int i2c_register_driver(struct module *owner, struct i2c_driver *driver)   
  2. {   
  3.     …….   
  4.     /* add the driver to the list of i2c drivers in the driver core */  
  5.     driver->driver.owner = owner;   
  6.     driver->driver.bus = &i2c_bus_type;   
  7.   
  8.     ……   
  9.     res = driver_register(&driver->driver);   
  10.     if (res)   
  11.         return res;   
  12.   
  13.     ……   
  14. }  

    函数i2c_register_driver()初始化该驱动的总线为i2c_bus_type,然后使用函数driver_register(&driver->driver)注册该驱动,因此内核会在I2C总线上遍历所有I2C设备,由于该mma7455 device驱动的匹配因子name变量为“mma7455”,因此正好和在4.1.2里创建的name也为“mma7455”的i2c client匹配。因此总线的probe函数将会被调用,I2C总线的probe函数为i2c_device_probe(),具体代码如下:

  1. static int i2c_device_probe(struct device *dev)   
  2. {   
  3.     struct i2c_client   *client = to_i2c_client(dev);   
  4.     struct i2c_driver   *driver = to_i2c_driver(dev->driver);   
  5.     int status;   
  6.   
  7.     if (!driver->probe || !driver->id_table)   
  8.         return -ENODEV;   
  9.     client->driver = driver;   
  10.     …….   
  11.     status = driver->probe(client, i2c_match_id(driver->id_table, client));   
  12.     ……   
  13.     return status;   
  14. }  

    在i2c_device_probe()函数中,语句client->driver = driver将I2C device和I2C driver绑定,然后直接调用具体设备的probe函数,这里即mma7455的probe函数mma7455_probe()。
    在mma7455_probe()函数会完成一些具体I2C设备相关的初始化等操作,这边就不再详述。

 


 

你可能感兴趣的:(OMAP3630 I2C device驱动)