linux platfrom驱动

一、linux驱动的分离和分层

  为提高linux驱动可重用性和可移植性。下图以i2c驱动为例说明linux驱动的分离和分层思想。由于不同芯片的i2c控制器不同,所以不同厂家会提供自己的i2c控制器驱动,不同设备它们的i2c接口驱动也不一样,所以不同设备厂家也会提供各自的设备驱动,linux则提供统一的api接口,使i2c驱动和设备驱动联通。

为了实现这种分层和分离的思想,linux提出设备、总线、驱动的方法。linux内核中,用struct device、struct bus_type、struct device_driver这三个结构体分别表示设备、总线、驱动。

二、driver和device注册过程

driver注册过程

  ->driver_register                //注册驱动,      linux_kernel/drivers/base/drivers.c

    ->bus_add_driver              //将驱动添加到总线中, linux_kernel/drivers/base/bus.c

      ->driver_attach             //查找总线下的所有设备,并将该驱动与所有设备相匹配

        ->bus_for_each_dev        //查找总线下的所有设备,并将该驱动与所有设备相匹配

          ->fn                 //fn即__driver_attach函数,为总线下的每个设备与该驱动执行fn函数

            ->driver_match_device   //检查驱动与设备是否匹配

            ->driver_probe_device   //如果匹配值执行这个函数

              ->really_probe

                ->drv->probe   //最终执行device_driver 中的probe函数

 

 device注册过程

  ->device_register        //注册device, linux_kernel/drivers/base/core.c

    ->device_initialize      //初始化设备

    ->device_add        //添加设备

      ->bus_add_device    //向总线添加设备

      ->bus_probe_device

        ->device_initial_probe

          ->__device_attach

            ->bus_for_each_drv       //查找总线下的所有驱动

              ->fn             ///fn即__device_attach_driver函数,为总线下的每个驱动与该设备执行fn函数

                ->driver_match_device  //检测驱动和设备是否匹配

                ->driver_probe_device  //如果设备与驱动匹配,则执行该函数

                  ->really_probe

                    ->drv->probe   //最终执行device_driver 中的probe函数

 

综上,当注册驱动时,总线上的所有设备会与该驱动匹配,若匹配上,则执行驱动的prob函数。当注册设备时,总线上的所有驱动会与改设备匹配,当匹配时,也会执行驱动的prob函数。

三、platform、platform_device、platform_driver注册过程

3.1 platform注册过程

  ->platform_bus_init      //patform总线初始化, linux_kernel/drivers/base/platform.c

    ->device_register

    ->bus_register

 

3.2 platform_driver注册过程

  ->__platform_driver_probe     //注册platform_driver,用于替代platform_driver_register函数, linux_kernel/drivers/base/platform.c

    ->__platform_driver_register  //初始化platform_driver中的device_driver结构体,最后调用driver_register注册platform_driver中的device_driver

      ->driver_register      //注册platform_driver中的device_driver,后续过程跟上面的注册driver一致

__platform_driver_registery源码分析

int __platform_driver_register(struct platform_driver *drv,
struct module *owner)
{
drv->driver.owner = owner;
drv->driver.bus = &platform_bus_type;
drv->driver.probe = platform_drv_probe;     //将platform_driver中的device_driver指定为platform_drv_probe
drv->driver.remove = platform_drv_remove;
drv->driver.shutdown = platform_drv_shutdown;

return driver_register(&drv->driver);       //注册device_driver时最后会调用probe函数,而上面又将device_driver的probe指定为platform_drv_probe,

                       //platform_drv_probe函数中调用了struct platform_driver中的probe函数,所以最终还是调用了struct platform_driver中的prob函数
}

注册platform_driver将最终调用struct platform_driver中的prob函数

3.3 platform_device 注册

  ->platform_device_register          //注册platform_device, linux_kernel/drivers/base/platform.c

    ->platform_device_add      

       ->device_add          //向内核添加platform_device中的device,后续跟上面注册device中的的添加device一致

 

 

四、platform驱动和设备匹配过程

  如下图所示,paltform的匹配函数是platform_match,有三种匹配方式,分别是设备树匹配、acpi匹配、id匹配、name匹配。

   

.

  设备树的匹配方式。

  ->of_driver_match_device            //linux_kernel/drivers/base/platform.c

    ->of_match_device

      ->of_match_node

        ->__of_match_node

          ->__of_device_is_compatible  //这个函数会去读取设备树中的compatible值来匹配

 

posted @ 2021-02-22 11:41  YYFaGe  阅读(436)  评论(0)    收藏  举报