旧版本的platform_device和platform_driver和新版本中的操作解释

旧版本中

一个linux设备的驱动和设备一般是挂载到一种总线上,系统中对于一些不能依附于总线的设备,linux设计出虚拟总线,platform设备总线。旧版本中,通过platform_device和platform_driver进行设备和驱动的注册,这个过程中,设备和驱动的名称必须一致,才能保证在程序启动的过程中,驱动才能匹配到总线上的设备。

新的版本中

只需要进行设备驱动的注册,而设备的注册通过DTS进行,在DTS中通过.compatible属性设置设备名称。当linux启动时通过dts就会将设备加载到platform设备总线上。当通过platform_driver_register函数进行注册时,内部就会调用一个总线注册的结构体,在结构体中有设备和驱动名称匹配函数,即将设备和驱动进行绑定。

#defineplatform_driver_register(drv) \

         __platform_driver_register(drv, THIS_MODULE)

int __platform_driver_register(struct platform_driver *drv,
                                         struct module *owner)
{
          drv->driver.owner = owner;
          drv->driver.bus = &platform_bus_type;
          if (drv->probe)
                    drv->driver.probe = platform_drv_probe;
          if (drv->remove)
                    drv->driver.remove = platform_drv_remove;
          if (drv->shutdown)
                    drv->driver.shutdown = platform_drv_shutdown;
 
          return driver_register(&drv->driver);
}
 
struct bus_type platform_bus_type = {
          .name               = "platform",
          .dev_groups         = platform_dev_groups,
          .match              = platform_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);
 
          /* 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);
}
static const struct platform_device_id *platform_match_id(
                               const struct platform_device_id *id,
                               struct platform_device *pdev)
{
          while (id->name[0]) {
                    if (strcmp(pdev->name, id->name) == 0) {
                               pdev->id_entry = id;
                               return id;
                    }
                    id++;
          }
          return NULL;
}
 
static inline int of_driver_match_device(struct device *dev,
                                                    const struct device_driver *drv)
{
          return of_match_device(drv->of_match_table, dev) != NULL;
}
 
const struct of_device_id *of_match_device(const struct of_device_id *matches,
                                               const struct device *dev)
{
         if ((!matches) || (!dev->of_node))
                 return NULL;
         return of_match_node(matches, dev->of_node);
}
 
const struct of_device_id *of_match_node(const struct of_device_id *matches,
                                                    const struct device_node *node)
{
          const struct of_device_id *match;
          unsigned long flags;
 
          raw_spin_lock_irqsave(&devtree_lock, flags);
          match = __of_match_node(matches, node);
          raw_spin_unlock_irqrestore(&devtree_lock, flags);
          return match;
}
 const struct of_device_id *__of_match_node(const struct of_device_id *matches,
                                                      const struct device_node *node)
{
          if (!matches)
                    return NULL;
 
          while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
                    int match = 1;
                    if (matches->name[0])
                               match &= node->name
                                         && !strcmp(matches->name, node->name);
                    if (matches->type[0])
                               match &= node->type
                                         && !strcmp(matches->type, node->type);
                    if (matches->compatible[0])
                               match &= __of_device_is_compatible(node,
                                                                          matches->compatible);
                    if (match)
                               return matches;
                    matches++;
          }
          return NULL;
}
在platform_当匹配函数完成后再调用platform_driver中自己定义的probe函数

你可能感兴趣的:(linux设备驱动)