Yuhang Zheng

第十八节、设备树中常用的of操作函数

N 人看过

本节用于介绍设备树中常用的of操作函数

设备都是以节点的形式“挂”到设备树上的,因此要想获取这个设备的其他属性信息,必须先获取到这个设备的节点。

Linux内核使用device_node结构体来描述一个节点

定义如下

文件位置路径:include/linux/of.h

struct device_node {
        const char *name;    /* 节点名称 */
        const char *type;    /* 设备类型 */
        phandle phandle;
        const char *full_name;    /* 节点全名 */
        struct fwnode_handle fwnode;

        struct  property *properties;    /* 属性 */
        struct  property *deadprops;    /* removed 属性 */
        struct  device_node *parent;    /* 父节点 */
        struct  device_node *child;    /* 子节点 */
        struct  device_node *sibling;
        struct  kobject kobj;
        unsigned long _flags;
        void    *data;
#if defined(CONFIG_SPARC)
        const char *path_component_name;
        unsigned int unique_id;
        struct of_irq_controller *irq_trans;
#endif
};

节点的属性信息里面保存了驱动所需要的内容,因此对于属性值的提取非常重要。

Linux内核中使用结构体property 表示属性,此结构体同样定义在文件include/linux/of.h中

内容如下

文件位置路径:include/linux/of.h

struct property {
        char    *name;    /* 属性名字 */
        int     length;    /* 属性长度 */
        void    *value;    /* 属性值 */
        struct property *next;    /* 下一个属性 */
        unsigned long _flags;
        unsigned int unique_id;
        struct bin_attribute attr;
};

获得设备树文件节点里面资源的步骤:

步骤一:查找我们要找的节点。

步骤二:获取我们需要的属性值。

一、查找节点的常用of函数

<1>of_find_node_by_path 函数

作用:函数通过路径来查找指定的节点

函数原型:

文件位置路径:include/linux/of_irq.h

static inline struct device_node *of_find_node_by_path(const char *path)
{
        return of_find_node_opts_by_path(path, NULL);
}
//参数
//path:带有全路径的节点名,可以使用节点的别名,比如"/backlight”就是backlight这个节点的全路径。
//返回值
//成功:返回找到的节点,失败返回NULL。

<2>of_get_parent函数

作用:用于获取指定节点的父节点(如果有父节点的话)

函数原型:

文件位置路径:include/linux/of_irq.h

extern struct device_node *of_get_parent(const struct device_node *node);
//参数
//node:要查找父节点的节点。
//返回值
//找到的父节点。

<3>of_get_next_child函数

作用:用迭代的方式查找子节点

函数原型:

文件位置路径:include/linux/of_irq.h

extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev);
//参数
//node:要查找子节点的节点。
//prev:前一个子节点,也就是从哪一个子节点开始迭代的查找下一个子节点。可以设置为NULL,表示从第一个子节点开始。
//返回值
//找到的下一个子节点

二、查找节点属性的常用of函数

<1>of_find_property函数

作用:用于查找指定的属性

函数原型:

文件位置路径:include/linux/of_irq.h

extern struct property *of_find_property(const struct device_node *np, const char *name, int *lenp);
//参数
//np:设备节点
//name:属性的名称
//lenp:属性值的字节数
//返回值
//找到的属性

<2>获取整数值属性

有些属性只有一个整型值,这四个函数就是用于读取这种只有一个整型值的属性,分别用于读取u8、u16、u32和u64类型属性值,函数原型如下:

文件位置路径:include/linux/of_irq.h

static inline int of_property_read_u8(const struct device_node *np, const char *propname, u8 *out_value)
static inline int of_property_read_u16(const struct device_node *np, const char *propname, u16 *out_value)
static inline int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value)
static inline int of_property_read_u64(const struct device_node *np, const char *propname, u64 *out_value)
//参数
//np:设备节点
//propname:属性的名称
//out_value:读取到的整数值
//返回值
//0:读取成功
//负值:读取失败

<3>获取数组属性

这4个函数分别是读取属性中u8、u16、u32和u64类型的数组数据,比如大多数的reg属性都是数组数据,可以使用这4个函数一次读取出reg属性中的所有数据。这四个函数的原型如下:

文件位置路径:include/linux/of_irq.h

static inline int of_property_read_u8_array(const struct device_node *np, const char *propname, u8 *out_values, size_t sz)
static inline int of_property_read_u16_array(const struct device_node *np, const char *propname, u16 *out_values, size_t sz)
static inline int of_property_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz)
static inline int of_property_read_u64_array(const struct device_node *np, const char *propname, u64 *out_values, size_t sz)
//参数
//np:设备节点
//propname:属性的名称
//out_value:读取到的数组值,分别为u8、u16、u32和u64。
//sz:要读取的数组元素数量。
//返回值
//0:读取成功
//负值:读取失败

<4>of_property_read_string函数

作用:用于读取属性中字符串值

函数原型:

文件位置路径:include/linux/of_irq.h

static inline int of_property_read_string(struct device_node *np, const char *propname, const char **out_string)
//参数
//np:设备节点
//propname:属性的名称
//out_string:读取到的字符串值
//返回值
//0:读取成功
//负值:读取失败

<5>of_iomap函数

作用:of_iomap函数用于直接内存映射,以前我们会通过ioremap函数来完成物理地址到虚拟地址的映射。

函数原型:

文件位置路径:include/linux/of_address.h

static inline void __iomem *of_iomap(struct device_node *device, int index)
//参数
//np:设备节点
//index:reg 属性中要完成内存映射的段,如果reg属性只有一段的话index就设置0。
//返回值
//经过内存映射后的虚拟内存首地址,如果为NULL的话表示内存映射失败

<6>of_get_named_gpio函数

作用:此函数获取GPIO编号,因为Linux内核中关于GPIO的API函数都要使用GPIO编号,此函数会将设备树中类似<&gpio1 3 GPIO_ACTIVE_LOW>的属性信息转换为对应的GPIO编号

函数原型:

文件位置路径:include/linux/of_gpio.h

static inline int of_get_named_gpio(struct device_node *np, const char *propname, int index)
//参数
//np:设备节点
//propname:属性的名称
//index:因为一个属性里面可能包含多个GPIO,此参数指定要获取哪个GPIO的编号,如果只有一个GPIO信息的话此参数为0。
//返回值
//成功返回到的GPIO编号
//失败返回一个负数