linux I2C 驱动之----i2c_driver的注册


分类: linux 驱动

       在 linux I2C 驱动之----i2c_client 的注册中介绍了i2c_client的注册,现在再来说说i2c_driver的注册过程。

       每一个驱动程序都有 module_init(xxxx_init) 这个语句,它代表系统启动的时候会自动执行 xxxx 这个函数,也就是说驱动的人口函数是由module_init来定义的。当然还有module_exit(XXXX),它代表系统卸载驱动时调用(linux系统允许动态加载卸载驱动),这一部分这不细说了。 

       上文提到的 xxxx_init 是驱动的入口函数,在此函数中,我们一般注册驱动的driver,比如我今天说的 i2c_driver:

        static int __init xxxx_init(void)
       {
           
 return i2c_add_driver(&xxxx_driver);
       }

其中xxxx_driver就是我们今天的主角 i2c_driver :

      static struct i2c_driver xxxx_driver =
     {
         .driver =
         {
             .owner = THIS_MODULE, 
             .name = "xxxx",
         }, 
        .id_table = xxxx_idtable,
        .probe = xxxx_probe, 
     }

完整的 i2c_driver 非常复杂,上面的定义只是完成了最基本的部分,当然也是必须,也就代表完成了上面的部分你的驱动就可以工作了,当然还有其他的,这里不细说了。

i2c_driver 中的driver.name 要和i2c_client一致,因为这是他们配备的一个依据,id_table 是i2c_device_id结构体的一个对象,里面定义了i2c驱动对应设备的i2c地址,probe函数是个非常重要的函数,等下我再来细说。

     现在我来说说 i2c_add_driver 的执行过程。

   

(注意:此函数是linux系统i2c 子系统已经为我们做好了的,我们完全不需要了解它的执行过程,只需要明白,当系统中已经注册了和上文提到的i2c_driver  xxxx_driver 对应的i2c_client,所谓对应的是说,name一样,i2c设备的地址也一样,那么i2c_driver 与i2c_client配备成功,接着就会调用i2c_driver 的probe函数,在此函数中可以做一系列的初始化工作。)

     

i2c_add_driver 函数只是调用了i2c_register_driver函数,在i2c_register_driver里调用了driver_register(&i2c_driver->driver),

注意 driver_register 是linux系统设备模型里面的函数了,每一类linux设备驱动的注册最终都会调用它,传递的参数也由原来的i2c_driver 变成了 device_driver。

driver_register做了一些判断,

最后调用了 bus_add_driver,

然后调用 driver_attach,

然后调用bus_for_each_dev,

这个函数就是搜索总线上所有的device,我们这里是i2c总线,也即搜索i2c总线上的i2c_client,

调用__driver_attach判断i2c_driver i2c_client是否配备,

再调用driver_match_device,driver_match_device

最终调用了bus的match函数,我们这也就是i2c bus的match函数,

再调用i2c_match_id,这里到最后的id 配备了,

如果配备成功则正常返回到__driver_attach函数,

调用driver_probe_device,再调用really_probe,

最后调用bus的probe函数,

在bus的probe函数里利用to_i2c_driver 将device_driver转换成了i2c_driver,最后调用了i2c_driver的probe函数,这个部分有点复杂,其中我可能也没说的太清楚,建议用source insight自己跟一边,因为其中有很多是公用的,跟一边后,其他驱动注册也就容易了。

你可能感兴趣的:(linux I2C 驱动之----i2c_driver的注册)