通过设备树的 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_node
和 of_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");