linux内核I2C总线驱动(二)
上回书讲到:
注册具有静态总线号的i2c适配器的函数,这样就能够使用我们后面的i2c_adapter等方法了啦。
idr_get_new_aboveidr机制整数id与指针建立关系
i2c_register_adapter注册i2c适配器
注册了adapter
这回我们来继续分析
kernel-3.4.39\drivers\i2c\i2c-core.c
这里主要是你编写的设备驱动,去和总线关联的,所以他管理着怎么匹配主要
经历了
bus_register(&i2c_bus_type); Linux的总线设备驱动模型
i2c_adapter_compat_class = class_compat_register("i2c-adapter");类兼容注册
retval = i2c_add_driver(&dummy_driver); 如果内核中已经注册了i2c适配器,则顺序调用这些适配器来连接我们的i2c设备。
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
static struct i2c_driver dummy_driver = {
.driver.name = "dummy",
.probe = dummy_probe,
.remove = dummy_remove,
.id_table = dummy_id,
};
可见匹配机制是通过i2c_match_id(driver->id_table, client) != NULL;去匹配的
匹配之后会执行
这里会调用你自己编写的prob,如果匹配上会成功。猜测这里会呼叫一下芯片
I2C总线上有2条分支:i2c_client链和i2c_driver链;
当任何一个driver或者client去注册时,I2C总线都会调用match函数去对client.name和driver.id_table.name进行循环匹配。
如果driver.id_table中所有的id都匹配不上则说明client并没有找到一个对应的driver;
如果匹配上了则标明client和driver是适用的,那么I2C总线会调用自身的probe函数,自身的probe函数又会调用driver中提供的probe函数,driver中的probe函数会对设备进行硬件初始化和后续工作。
i2c_add_adapter/i2c_add_numbered_adapter:注册adapter的,比如i2c-s3c2410.c中就使用此函数来注册一个adapter。
i2c_add_driver:注册driver的
i2c_new_device:注册client的
总结:
适配部分,我们和硬件进行紧紧的关联,使用平台模型,之后注册上i2c适配器,包含着硬件的全部信息,这一块主要是芯片厂商提供好的,我们有更改的时候也可以根据需求去更改,也就是说他是板级支撑文件和设备树解析的部分,我们写设备驱动的时候,通过他注册的soc硬件信息去获取。核心层提供了你的设备应该怎样去注册,给你一个通用的方法和模型,这个是需要你去遵守的,这个文件是linux官方提供的模型,你只需要自己怎么去提供给他适配器,他提供给你了什么i2c的方法,你可以使用他去写驱动即可。设备驱动是需要自己编写的,向上层提供各种接口即可。