Bootstrap

Linux内核 -- 通过设备树的compatiable字段获取device *dev指针的方法

通过设备树的 compatible 获取 device * 的方法

背景

在 Linux 内核中,通过设备树(Device Tree, DT)的 compatible 属性,可以实现设备节点与驱动程序的匹配,从而获取对应的 device * 对象。这一过程依赖于内核的设备树解析机制和设备驱动模型的协同工作。本文将详细介绍该机制的背景、流程以及代码实现。

实现流程

1. 设备树节点匹配

在设备树中,每个设备节点通常具有一个 compatible 属性,用于标识设备类型和驱动程序支持情况。示例设备树节点如下:

my_device: my_device@0 {
    compatible = "myvendor,mydevice";
    reg = <0x0 0x1000>;
};

2. 驱动注册

驱动程序通过 of_match_table 表声明支持的 compatible 属性。内核通过此表来确定设备是否与驱动程序匹配。

示例代码:

static const struct of_device_id my_device_of_match[] = {
    { .compatible = "myvendor,mydevice" },
    {},
};
MODULE_DEVICE_TABLE(of, my_device_of_match);

static struct platform_driver my_device_driver = {
    .driver = {
        .name = "my_device_driver",
        .of_match_table = my_device_of_match,
    },
    .probe = my_device_probe,
};

module_platform_driver(my_device_driver);

3. 驱动绑定

当内核解析设备树时,会根据 compatible 属性在 of_device_id 表中查找匹配的驱动程序,并调用驱动程序的 probe 函数。probe 函数会接收到一个 struct device * 对象。

probe 函数示例:

static int my_device_probe(struct platform_device *pdev) {
    struct device *dev = &pdev->dev;
    dev_info(dev, "Device probed successfully\n");
    return 0;
}

4. 手动获取设备

如果需要在代码中手动根据 compatible 获取设备,可以通过以下方式:

struct device_node *np = of_find_compatible_node(NULL, NULL, "myvendor,mydevice");
if (np) {
    struct platform_device *pdev = of_find_device_by_node(np);
    if (pdev) {
        struct device *dev = &pdev->dev;
        dev_info(dev, "Device found: %s\n", dev_name(dev));
    }
    of_node_put(np);
}

上述代码中:

  • of_find_compatible_node 用于查找设备树节点。
  • of_find_device_by_node 根据设备树节点查找对应的 platform_device
  • 通过 &pdev->dev 获取 device *

总结

通过设备树的 compatible 属性,Linux 内核可以实现设备和驱动的自动匹配。在需要手动获取设备的场景,可以结合 of_find_compatible_nodeof_find_device_by_node API 完成。

示例代码完整实现

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>

static const struct of_device_id my_device_of_match[] = {
    { .compatible = "myvendor,mydevice" },
    {},
};
MODULE_DEVICE_TABLE(of, my_device_of_match);

static int my_device_probe(struct platform_device *pdev) {
    struct device *dev = &pdev->dev;
    dev_info(dev, "Device probed successfully\n");
    return 0;
}

static struct platform_driver my_device_driver = {
    .driver = {
        .name = "my_device_driver",
        .of_match_table = my_device_of_match,
    },
    .probe = my_device_probe,
};

module_platform_driver(my_device_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Example Author");
MODULE_DESCRIPTION("Example driver using compatible to find device");

;