linux平台设备和平台驱动

由module_init宏指定模块的初始化入口

下面来看看模块的初始化

static struct platform_driver efuse_driver = {                                                             
    .probe = efuse_probe,                                                                                  
    .remove = efuse_remove,                                                                                
    .driver = {                                                                                            
        .name = EFUSE_DEVICE_NAME,                                                                         
        .of_match_table = amlogic_efuse_dt_match,                                                          
    .owner = THIS_MODULE,                                                                                  
    },                                                                                                     
}; 
static int __init efuse_init(void)                                                                         
{                                                                                                          
    int ret = -1;                                                                                          
                                                                                                           
    ret = platform_driver_register(&efuse_driver);                                                         
    if (ret != 0) {                                                                                        
        pr_err("failed to register efuse driver, error %d\n", ret);                                        
        return -ENODEV;                                                                                    
    }                                                                                                      
                                                                                                           
    return ret;                                                                                            
} 
module_init(efuse_init);

这里注册了一个平台驱动,平台驱动是一种特殊的驱动,平台驱动使用的是平台总线,所以这里不需要指定总线。

  int __platform_driver_register(struct platform_driver *drv,                                                                               
                  struct module *owner)
  {
      drv->driver.owner = owner;
      drv->driver.bus = &platform_bus_type;    //挂载在平台总线platform_bus_type上
      drv->driver.probe = platform_drv_probe;
      drv->driver.remove = platform_drv_remove;
      drv->driver.shutdown = platform_drv_shutdown;
  
      return driver_register(&drv->driver);  //统一是调用driver_register进行驱动的注册
  }
    int platform_device_register(struct platform_device *pdev)
  {
      device_initialize(&pdev->dev);
      arch_setup_pdev_archdata(pdev);
      return platform_device_add(pdev);                                                                                                     
  }
    int platform_device_add(struct platform_device *pdev)
  {
  	pdev->dev.bus = &platform_bus_type;  //挂载在平台总线platform_bus_type上
  	...
  	ret = device_add(&pdev->dev);
  	...
  }

在DTB中描述平台硬件配置,由of解析并注册平台设备,平台设备使用的也是平台总线,所以在注册平台设备时,平台总线会遍历平台驱动,依次会调用平台驱动中的of_match_table 进行匹配(具体的规则更加复杂)

  struct bus_type platform_bus_type = {                                                                                                     
      .name       = "platform",
      .dev_groups = platform_dev_groups,
      .match      = platform_match,   //具体总线的match方法
      .uevent     = platform_uevent,
      .pm     = &platform_dev_pm_ops,
  };
    static int platform_match(struct device *dev, struct device_driver *drv)
  {
      struct platform_device *pdev = to_platform_device(dev);
      struct platform_driver *pdrv = to_platform_driver(drv);
  
      /* When driver_override is set, only bind to the matching driver */
      if (pdev->driver_override)
          return !strcmp(pdev->driver_override, drv->name);
  
      /* Attempt an OF style match first */
      if (of_driver_match_device(dev, drv))
          return 1;
  
      /* Then try ACPI style match */
      if (acpi_driver_match_device(dev, drv))
          return 1;
  
      /* Then try to match against the id table */
      if (pdrv->id_table)
          return platform_match_id(pdrv->id_table, pdev) != NULL;
  
      /* fall-back to driver name match */
      return (strcmp(pdev->name, drv->name) == 0);
  }  

如果匹配,这设备和相应的驱动相关联,同时调用驱动中的probe函数,进一步获取设备更详细的参数。

bus_rescan_devices_helper()-->device_attach()-->__device_attach()-->__device_attach_driver()-->driver_match_device()
bus_add_driver()-->driver_attach()-->__driver_attach()-->driver_match_device()
    
发布了85 篇原创文章 · 获赞 26 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/whuzm08/article/details/88394436