I2C子系统之 adapter driver注册——I2C_dev_init()


i2c的操作在内核中是当做字符设备来操作的,相关初始化在由i2c_dev_init函数来初始化。

并且i2c adapter的驱动通过i2cdev_driver这个通用驱动的attach方法来实现注册的。

下面具体分析整个过程。

  1. static int __init i2c_dev_init(void)  
  2. {  
  3.         。。。 。。。  
  4.     res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops);  
  5.     if (res)  
  6.         goto out;  
  7.   
  8.     i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");  
  9.     if (IS_ERR(i2c_dev_class)) {  
  10.         res = PTR_ERR(i2c_dev_class);  
  11.         goto out_unreg_chrdev;  
  12.     }  
  13.   
  14.     res = i2c_add_driver(&i2cdev_driver);  
  15.         。。。 。。。  
  16. }  

函数首先调用register_chardev函数向内核注册主备号为I2C_MAJOR、操作集为i2cdev_fops的字符设备。

register_chrdev函数最终会向系统注册主设备为I2C_MAJOR,此设备号为0~255的设备。这表示系统最多可以容纳256个i2c adapter,adapter的字符操作方法i2cdev_fops如下:

  1. static const struct file_operations i2cdev_fops = {  
  2.     .owner      = THIS_MODULE,  
  3.     .llseek     = no_llseek,  
  4.     .read       = i2cdev_read,  
  5.     .write      = i2cdev_write,  
  6.     .unlocked_ioctl = i2cdev_ioctl,  
  7.     .open       = i2cdev_open,  
  8.     .release    = i2cdev_release,  
  9. };  

当read()、write()、open()、close()、ioctl()等系统调用发生时就会调用到这些函数。

但是i2cdev_fops其实是通用的的操作,应为不同的adapter对应的操作方法肯定有区别所以这里的fops只是具体adapter操作方法的一层外壳,具体稍后分析。

字符设备注册完毕后通过class_create()函数初始化一个类i2c_dev_class,这个类稍后需要使用,用于在/dev/i2c-0下自动创建设备,后面分析。

类初始化完毕后,然后调用函数i2c_add_driver函数注册i2c driver。这里所说的i2c其实对应的是系统中所有的i2c类设备。

通过i2c driver中的attach_adapter方法来实现将adapter和对应的驱动绑定。

  1. static struct i2c_driver i2cdev_driver = {  
  2.     .driver = {  
  3.         .name   = "dev_driver",  
  4.     },  
  5.     .attach_adapter = i2cdev_attach_adapter,  
  6.     .detach_adapter = i2cdev_detach_adapter,  
  7. };  
此处注意attach_adapter这个方法,/dev目录下的设备创建是在通过执行此函数实现的。

下面具体分析i2c_add_driver注册i2cdev_driver的过程

2.i2c_add_driver

i2c_add_driver函数只是对i2c_register_driver做了简单的封装,下面直接分析i2c_register_driver

  1. int i2c_register_driver(struct module *owner, struct i2c_driver *driver)  
  2. {  
  3.     int res;  
  4.   
  5.     /* Can't register until after driver model init */  
  6.     if (unlikely(WARN_ON(!i2c_bus_type.p))){  
  7.         printk("Can't register until after driver model init\n");  
  8.         return -EAGAIN;  
  9.     }  
  10.   
  11.     /* add the driver to the list of i2c drivers in the driver core */  
  12.     driver->driver.owner = owner;  
  13.     driver->driver.bus = &i2c_bus_type;  
  14.   
  15.     /* When registration returns, the driver core 
  16.      * will have called probe() for all matching-but-unbound devices. 
  17.      */  
  18.     res = driver_register(&driver->driver);  
  19.     if (res)  
  20.         return res;  
  21.   
  22.     pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);  
  23.   
  24.     INIT_LIST_HEAD(&driver->clients);  
  25.     /* Walk the adapters that are already present */  
  26.     mutex_lock(&core_lock);  
  27.     bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);  
  28.     mutex_unlock(&core_lock);  
  29.   
  30.     return 0;  
  31. }  

函数通过

  1. driver->driver.bus = &i2c_bus_type;  
可见此驱动通过函数driver_register()之后 同样会被注册到了i2c总线上。

值���一提的是此处i2cdev_driver中的attach_adapter的执行机会很大,通过bus_for_each_dev()函数

  1. bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);  
会尝试和i2c总线上所有的dev进行一次匹配,只要获取的dev为adapter时,就可执行后续操作。

此处的bus_for_each_dev函数主要功能就是循环查询一遍i2c总线上所有的dev,包括adapter device和client device。

然后依次将dev和driver作为__process_new_driver的参数并执行__process_new_driver函数,但是只有adapter device

才会执行后续的操作,否则返回继续轮询i2c总线上的dev。

  1. static int __process_new_driver(struct device *dev, void *data)  
  2. {  
  3.     if (dev->type != &i2c_adapter_type)  
  4.         return 0;  
  5.     return i2c_do_add_adapter(data, to_i2c_adapter(dev));  
  6. }  
可以发现__process_new_driver函数首先判断的是dev的类型,假如是adapter类型才会继续执行后面的代码,假如不是则立即返回继续摘取下个dev然后循环执行__process_new_driver。因为对我们来说,我们只需要注册adapter的驱动就可以了,i2c的所有操作是通过主机来完成的,从机只是被动接受。由于之前已经通过i2cadd_numbered_adapter()注册过adapter到总线i2c_bus_type,所以此处有机会执行后面的i2c_do_add_adapter函数。
  1. static int i2c_do_add_adapter(struct i2c_driver *driver,  
  2.                   struct i2c_adapter *adap)  
  3. {  
  4.     /* Detect supported devices on that bus, and instantiate them */  
  5.     i2c_detect(adap, driver);  
  6.   
  7.     /* Let legacy drivers scan this bus for matching devices */  
  8.     if (driver->attach_adapter) {  
  9.         /* We ignore the return code; if it fails, too bad */  
  10.         driver->attach_adapter(adap);  
  11.     }  
  12.     return 0;  
  13. }  
可以发现在i2c_do_add_adapter函数主要执行的是i2c_dectect和driver->attach_adapter。

由于此处驱动并未初始化driver->detect,所以i2c_detect函数未执行有效操作就会退出。

接着通过传统方式执行driver->attach_adapter方法。

  1. tatic int i2cdev_attach_adapter(struct i2c_adapter *adap)  
  2. {  
  3.     struct i2c_dev *i2c_dev;  
  4.     int res;  
  5.   
  6.     i2c_dev = get_free_i2c_dev(adap);  
  7.     if (IS_ERR(i2c_dev))  
  8.         return PTR_ERR(i2c_dev);  
  9.   
  10.     /* register this i2c device with the driver core */  
  11.     i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,  
  12.                      MKDEV(I2C_MAJOR, adap->nr), NULL,  
  13.                      "i2c-%d", adap->nr);  
  14.     if (IS_ERR(i2c_dev->dev)) {  
  15.         res = PTR_ERR(i2c_dev->dev);  
  16.         goto error;  
  17.     }  
  18.     res = device_create_file(i2c_dev->dev, &dev_attr_name);  
  19.     if (res)  
  20.         goto error_destroy;  
  21.   
  22.     pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",  
  23.          adap->name, adap->nr);  
  24.     return 0;  
  25. error_destroy:  
  26.     device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));  
  27. error:  
  28.     return_i2c_dev(i2c_dev);  
  29.     return res;  
  30. }  

可见attach_adapter函数的作用就是调用device_create()函数 通过之前class_create的类信息在/dev下自动创建设备文件。

并且此设备的设备号是由固定的主设备号I2C_MAJOR 和 从设备号组成的,从设备号取的就是adapter的nr,此处为0。

并且可以推断出系统最多可以容纳0~255 总共256个i2c adapter。

到此i2c部分的初始化就完成了,可以通过read write来操作设备了。

补充:上面说的新方法好像在驱动里面就会detect client,然后把所有检测到的client放到一条链表里。

相关阅读:

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()

相关内容