一.of函数概述
Linux内核给我们提供了一系列的函数来获取设备树中的节点或者属性信息,这一系列的函数都有一个统一的前缀 ”of“ , 所以在很多资料里面也被叫做OF函数。
Linux 内核使用device_node 结构体来描述一个节点,此结构体定义在文件include/linux/of.h 中,定义如下:
二.查找节点的of函数
of_find_node_by_name 函数,该函数通过节点名字查找指定的节点。
struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
from : 开始查找的节点,如果为NULL 表示从根节点开始查找整个设备树。
name :**要查找的节点名字。
返回值:**找到的节点,如果为NULL 表示查找失败。
of_find_node_by_path,该函数通过路径来查找指定的节点。
struct device_node *of_find_node_by_path(const char *path);
path : 带有全路径的节点名,可以使用节点的别名,比如:“/backlight” 就是backlight 这个节点的
返回值:**找到的节点,如果为NULL 表示查找失败。
of_get_parent 函数,该函数用于获取指定节点的父节点(如果有父节点的话)。
struct device_node *of_get_parent(const struct device_node *node);
node : 要查找父节点的节点。
返回值: 找到的父节点。
of_get_next_child 函数,该函数用迭代的方式查找子节点。
struct device_node *of_get_next_child(const struct device_node *node,struct device_node *prev);
node : 父节点。
prev:**前一个子节点,也就是从哪个子节点开始迭代的查找下一个子节点。可以设置为NULL,表示从第一个子节点开始。
返回值:**找到的下一个子节点
of_find_compatible_node 该函数根据device_type 和compatible 这两个属性查找指定的节点
struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
from : 开始查找的节点,如果为NULL 表示从根节点开始查找整个设备树。
type :**要查找的节点对应的type 字符串,也就是device_type 属性值。可以为NULL,表示忽略掉device_type 属性。
compatible : 要查找的节点所对应的compatible 属性列表。
返回值:**找到的节点,如果为NULL 表示查找失败。
of_find_matching_node_and_match该函数通过 of_device_id 匹配表来查找指定的节点。
struct device_node *of_find_matching_node_and_match(struct device_node *from,const struct of_device_id *matches,const struct of_device_id **match);
from : 开始查找的节点,如果为NULL 表示从根节点开始查找整个设备树。
matches : of_device_id 匹配表,也就是在此匹配表里面查找节点。
match : 找到的匹配的of_device_id 。
返回值:**找到的节点,如果为NULL 表示查找失败。
三.of函数获取设备树节点实验
dts:
/{topeet{#address-cells = <1>;#size-cells = <1>;compatible = "simple-bus";myLed{compatible = "my devicetree";reg = <0xFDD60000 0x00000004>;};};
};
驱动程序:
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mod_devicetable.h>
#include <linux/of.h>struct device_node *mydevice_node;
const struct of_device_id *mynode_match;
struct of_device_id mynode_of_match[] = {{.compatible="my devicetree"},{},
};// 平台设备的初始化函数
static int my_platform_probe(struct platform_device *pdev)
{printk(KERN_INFO "my_platform_probe: Probing platform device\n");// 通过节点名称查找设备树节点mydevice_node = of_find_node_by_name(NULL, "myLed");printk("mydevice node is %s\n", mydevice_node->name);// 通过节点路径查找设备树节点mydevice_node = of_find_node_by_path("/topeet/myLed");printk("mydevice node is %s\n", mydevice_node->name);// 获取父节点mydevice_node = of_get_parent(mydevice_node);printk("myled's parent node is %s\n", mydevice_node->name);// 获取子节点mydevice_node = of_get_next_child(mydevice_node, NULL);printk("myled's sibling node is %s\n", mydevice_node->name);// 使用compatible值查找节点mydevice_node=of_find_compatible_node(NULL ,NULL, "my devicetree");printk("mydevice node is %s\n" , mydevice_node->name);//根据给定的of_device_id匹配表在设备树中查找匹配的节点mydevice_node=of_find_matching_node_and_match(NULL , mynode_of_match, &mynode_match);printk("mydevice node is %s\n" ,mydevice_node->name);return 0;
}// 平台设备的移除函数
static int my_platform_remove(struct platform_device *pdev)
{printk(KERN_INFO "my_platform_remove: Removing platform device\n");// 清理设备特定的操作// ...return 0;
}const struct of_device_id of_match_table_id[] = {{.compatible="my devicetree"},
};// 定义平台驱动结构体
static struct platform_driver my_platform_driver = {.probe = my_platform_probe,.remove = my_platform_remove,.driver = {.name = "my_platform_device",.owner = THIS_MODULE,.of_match_table = of_match_table_id,},
};// 模块初始化函数
static int __init my_platform_driver_init(void)
{int ret;// 注册平台驱动ret = platform_driver_register(&my_platform_driver);if (ret) {printk(KERN_ERR "Failed to register platform driver\n");return ret;}printk(KERN_INFO "my_platform_driver: Platform driver initialized\n");return 0;
}// 模块退出函数
static void __exit my_platform_driver_exit(void)
{// 注销平台驱动platform_driver_unregister(&my_platform_driver);printk(KERN_INFO "my_platform_driver: Platform driver exited\n");
}module_init(my_platform_driver_init);
module_exit(my_platform_driver_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("topeet");