当前位置:   article > 正文

Linux驱动(四)platform总线匹配过程_platform平台设备匹配过程

platform平台设备匹配过程

1、前言

在上一篇文章Linux驱动(三)platform总线驱动中讲解了platform的驱动框架,设备与驱动相匹配后会调用驱动的probe函数,设备与驱动的匹配则是platform总线中的match函数实现的,本文将详细讲解match函数的匹配过程。

2、match函数

match函数原型如下:

  1. /**
  2. * platform_match - 将平台设备与平台驱动程序绑定。
  3. * @dev: 设备。
  4. * @drv: 驱动程序。
  5. *
  6. * 假定平台设备的ID编码方式如下:
  7. * "<name><instance>",其中 <name> 是设备类型的简短描述,如 "pci" 或 "floppy",
  8. * <instance> 是设备的枚举实例,如 '0' 或 '42'。驱动程序的ID只是 "<name>"。
  9. * 因此,从 platform_device 结构中提取 <name>,并将其与驱动程序的名称进行比较。
  10. * 返回它们是否匹配。
  11. */
  12. static int platform_match(struct device *dev, struct device_driver *drv)
  13. {
  14. struct platform_device *pdev = to_platform_device(dev);
  15. struct platform_driver *pdrv = to_platform_driver(drv);
  16. /* 当 driver_override 被设置时,只绑定到匹配的驱动程序 */
  17. if (pdev->driver_override)
  18. return !strcmp(pdev->driver_override, drv->name);
  19. /* 首先尝试 OF 风格的匹配 */
  20. if (of_driver_match_device(dev, drv))
  21. return 1;
  22. /* 然后尝试 ACPI 风格的匹配 */
  23. if (acpi_driver_match_device(dev, drv))
  24. return 1;
  25. /* 然后尝试与 id 表进行匹配 */
  26. if (pdrv->id_table)
  27. return platform_match_id(pdrv->id_table, pdev) != NULL;
  28. /* 回退到驱动程序名称匹配 */
  29. return (strcmp(pdev->name, drv->name) == 0);
  30. }

在设备与驱动匹配比较的时候调用:

  1. static inline int driver_match_device(struct device_driver *drv,
  2. struct device *dev)
  3. {
  4. return drv->bus->match ? drv->bus->match(dev, drv) : 1;
  5. }

该接口在__platform_driver_register中赋值:

  1. int __platform_driver_register(struct platform_driver *drv,
  2. struct module *owner)
  3. {
  4. ……
  5. drv->driver.bus = &platform_bus_type;
  6. ……
  7. }
  8. 其中platform_bus_type
  9. struct bus_type platform_bus_type = {
  10. .name = "platform",
  11. .dev_groups = platform_dev_groups,
  12. .match = platform_match,
  13. .uevent = platform_uevent,
  14. .pm = &platform_dev_pm_ops,
  15. };

3、匹配过程

3.1 匹配优先级

match函数中代码执行顺序则代表了匹配的优先级:

  1. struct platform_device *pdev = to_platform_device(dev);
  2. struct platform_driver *pdrv = to_platform_driver(drv);
  3. if (pdev->driver_override)
  4. return !strcmp(pdev->driver_override, drv->name);
  5. if (of_driver_match_device(dev, drv))
  6. return 1;
  7. if (acpi_driver_match_device(dev, drv))
  8. return 1;
  9. if (pdrv->id_table)
  10. return platform_match_id(pdrv->id_table, pdev) != NULL;
  11. return (strcmp(pdev->name, drv->name) == 0);

其中to_platform_device和to_platform_driver是两个宏定义,在其内部使用了另一个宏定义container_of,用于根据结构体成员的地址来获取整个结构体本身的地址。

3.2 driver_override匹配

如果设置了driver_override,即driver_override不为NULL,那么只会进行driver_override的匹配,其优先级是最高的:

3.3 设备树匹配

设备树的匹配从of_driver_match_device开始分析,其函数调用关系如下:

  1. of_driver_match_device(struct device *dev,const struct device_driver *drv)
  2. -->of_match_device(drv->of_match_table, dev)
  3. ---->of_match_node(matches, dev->of_node);
  4. ------>__of_match_node(matches, node);
  5. -------->__of_device_is_compatible(node, matches->compatible,
  6. matches->type, matches->name);

分析内核代码可以得到设备树匹配比较的具体对象,其中device的device_node信息是通过解析设备树的节点得到的:

3.4 ACPI匹配

acpi的驱动在开发中没有使用到过,在此仅做简单分析,其代码调用如下,当没有设置acpi_match_table的时候会调用acpi_of_match_device进行匹配,设置了acpi_match_table的话会调用__acpi_match_device进行匹配:

  1. bool acpi_driver_match_device(struct device *dev,
  2. const struct device_driver *drv)
  3. {
  4. if (!drv->acpi_match_table)
  5. return acpi_of_match_device(ACPI_COMPANION(dev),
  6. drv->of_match_table);
  7. return !!__acpi_match_device(acpi_companion_match(dev),
  8. drv->acpi_match_table, drv->of_match_table);
  9. }

跟踪代码,其流程大致如下,后面的联合体内容较多未全部展开:

3.5 id_table匹配

id_table的匹配代码如下,通过比较pdev和id的name变量是否相等进行判定:

  1. static const struct platform_device_id *platform_match_id(
  2. const struct platform_device_id *id,
  3. struct platform_device *pdev)
  4. {
  5. while (id->name[0]) {
  6. if (strcmp(pdev->name, id->name) == 0) {
  7. pdev->id_entry = id;
  8. return id;
  9. }
  10. id++;
  11. }
  12. return NULL;
  13. }

3.6 名称匹配

名称匹配代码如下,仅通过名称判定:

return (strcmp(pdev->name, drv->name) == 0);

汇总所有优先级的图示如下:

4、总结

match函数的整体匹配流程基本上可以由上图表示,分析过程中有错误的地方欢迎评论指出。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/643783
推荐阅读
相关标签
  

闽ICP备14008679号