i2c的操作在内核中是当做字符设备来操作的,相关初始化在由i2c_dev_init函数来初始化。
并且i2c adapter的驱动通过i2cdev_driver这个通用驱动的attach方法来实现注册的。
下面具体分析整个过程。
函数首先调用register_chardev函数向内核注册主备号为I2C_MAJOR、操作集为i2cdev_fops的字符设备。
register_chrdev函数最终会向系统注册主设备为I2C_MAJOR,此设备号为0~255的设备。这表示系统最多可以容纳256个i2c adapter,adapter的字符操作方法i2cdev_fops如下:
当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和对应的驱动绑定。
下面具体分析i2c_add_driver注册i2cdev_driver的过程
2.i2c_add_driver
i2c_add_driver函数只是对i2c_register_driver做了简单的封装,下面直接分析i2c_register_driver
函数通过
值 一提的是此处i2cdev_driver中的attach_adapter的执行机会很大,通过bus_for_each_dev()函数
此处的bus_for_each_dev函数主要功能就是循环查询一遍i2c总线上所有的dev,包括adapter device和client device。
然后依次将dev和driver作为__process_new_driver的参数并执行__process_new_driver函数,但是只有adapter device
才会执行后续的操作,否则返回继续轮询i2c总线上的dev。
由于此处驱动并未初始化driver->detect,所以i2c_detect函数未执行有效操作就会退出。
接着通过传统方式执行driver->attach_adapter方法。
可见attach_adapter函数的作用就是调用device_create()函数 通过之前class_create的类信息在/dev下自动创建设备文件。
并且此设备的设备号是由固定的主设备号I2C_MAJOR 和 从设备号组成的,从设备号取的就是adapter的nr,此处为0。
并且可以推断出系统最多可以容纳0~255 总共256个i2c adapter。
到此i2c部分的初始化就完成了,可以通过read write来操作设备了。
补充:上面说的新方法好像在驱动里面就会detect client,然后把所有检测到的client放到一条链表里。
相关阅读: