2020-06-04 18:18:10 +08:00
|
|
|
|
# Device Tree
|
|
|
|
|
|
2020-06-05 11:34:46 +08:00
|
|
|
|
## 设备树的起源
|
|
|
|
|
|
|
|
|
|
linux 2.6 及之前,大量板级信息被硬编码到内核里,十分庞大,大量代码冗余。
|
|
|
|
|
|
|
|
|
|
linux 2.6 之后,引入了设备树。设备树源于 OpenFirmware,描述硬件的数据结构。由一些列节点(node)和属性(property)组成,通常包括下列信息:
|
|
|
|
|
|
|
|
|
|
* CPU 数量和类别
|
|
|
|
|
* 内存基地址和大小
|
|
|
|
|
* 总线和桥
|
|
|
|
|
* 外设连接
|
|
|
|
|
* 中断控制器和中断使用情况
|
|
|
|
|
* GPIO 控制器和 GPIO 使用情况
|
|
|
|
|
* 时钟控制器和时钟使用情况
|
|
|
|
|
|
|
|
|
|
本质上是画一棵 CPU、总线、设备组成的树,Linux 内核会把设备树展开成 platform_device、i2c_client、spi_device 等设备,而这些设备用到的内存、中断等资源,也会传递个内核,内核会将这些资源绑定给展开的相应设备。
|
|
|
|
|
|
|
|
|
|
## DTSI/DTS/DTC/DTB
|
|
|
|
|
|
|
|
|
|
dtsi:可被 #include 的设备树源文件;
|
|
|
|
|
|
|
|
|
|
dts:设备树源文件;
|
|
|
|
|
|
|
|
|
|
dtc:编译 dts 和 dtsi 后得到的设备树文件,dts 及 dtsi 中的内容被组合或覆盖,该文件为源码形式,Linux 内核无法识别;
|
|
|
|
|
|
|
|
|
|
dtb:编译 dtc 后得到的二进制设备树文件,Linux 内核可加载和识别其中的内容。
|
|
|
|
|
|
|
|
|
|
如果谋 dts 文件引用了谋 dtsi 文件,可以在 dts 中覆盖 dtsi 中的部分内容。
|
|
|
|
|
|
2020-06-04 18:18:10 +08:00
|
|
|
|
## DTS 语法
|
|
|
|
|
|
2020-06-05 11:34:46 +08:00
|
|
|
|
包含一个根节点和多个子节点,如果在 dts/dtsi 中写了多个根节点,则在编译后被组合成一个根节点。子节点可嵌套。 节点会被展开为 device,其 compatible 属性用于与 driver 的 compatible 属性项匹配,如果匹配成功则调用该 driver 的 probe 函数。
|
|
|
|
|
|
2020-06-05 11:58:48 +08:00
|
|
|
|
属性值可以为整数或字符串。如果为整数则用“<>”括起来,“<>”中可以有多个单元,称为 cell,cell 间使用空格隔开,不同的 cell 可以有不同的含义。字符串使用英文双引号括起来。
|
|
|
|
|
|
|
|
|
|
DTS 中使用“//”进行行注释或“/**/”进行块注释。
|
|
|
|
|
|
|
|
|
|
### 设备节点
|
|
|
|
|
|
|
|
|
|
设备节点采用:
|
|
|
|
|
|
|
|
|
|
```dts
|
|
|
|
|
[label]:<name>[@<unit-address>]
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
的格式来标识。挂到内存空间的设备,其 unit-address 一般是内存地址。别的地方可以通过标签来引用该节点。
|
|
|
|
|
|
|
|
|
|
### reg 属性和 address-cells、size-cells
|
|
|
|
|
|
|
|
|
|
子节点的“reg”属性由“address”字段和“size”字段构成,如:
|
|
|
|
|
|
|
|
|
|
```dts
|
|
|
|
|
reg = <address1 size1 [address2 size2] [address3 size3]...>;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
属性“#address-cells”描述了子节点的“reg”属性的“address”字段为几个 32bit 的整型数据。
|
|
|
|
|
|
|
|
|
|
属性“#size-cells”描述了子节点的“reg”属性的“size”字段为几个 32bit 整型数据,如果为 0,则没有 lenth 字段。
|
|
|
|
|
|
|
|
|
|
### 中断连接
|
|
|
|
|
|
|
|
|
|
* interrutt-controller:属性为空,表明“我是中断控制器”;
|
|
|
|
|
* #interrupt-cells:表明连接此中断控制器的设备的中断属性的 cell 大小,也就是 interrupt = <> 属性的 cell 大小;
|
|
|
|
|
* interrupt-parent:设备节点通过这个关键字指定其依附的中断控制器 phandle,如果没有指定,则继承父节点的 interrupt-parent 配置;
|
2020-06-05 13:14:58 +08:00
|
|
|
|
* interrupt:设备节点里使用,一般包含中断号、触发方法等。具体有多少个 cell,由 #interrupt-cells 决定,每个 cell 的具体含义,一般由驱动决定。
|
2020-06-05 11:58:48 +08:00
|
|
|
|
|
|
|
|
|
### DTS 示例
|
|
|
|
|
|
|
|
|
|
一个简单的 dts 文件示例如下:
|
2020-06-05 11:34:46 +08:00
|
|
|
|
|
|
|
|
|
```dts
|
|
|
|
|
/ {
|
2020-06-05 11:58:48 +08:00
|
|
|
|
compatible = "acme,coyotes-rev"
|
2020-06-05 11:34:46 +08:00
|
|
|
|
#address-cells = <1>; // 描述下一级子节点的数据属性
|
|
|
|
|
#size-cells = <1>;
|
|
|
|
|
interrupt-parent = <&intc>;
|
|
|
|
|
|
|
|
|
|
cpus {
|
|
|
|
|
#address-cells = <1>;
|
|
|
|
|
#size-cells = <0>;
|
|
|
|
|
cpu@0 {
|
|
|
|
|
compatible = "arm,cortex-a9"; // device兼容性,用于与driver匹配
|
|
|
|
|
reg = <0>;
|
|
|
|
|
};
|
|
|
|
|
cpu@1 {
|
|
|
|
|
compatible = "arm,cortex-a9";
|
|
|
|
|
reg = <1>;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
serial@101f0000 { // 地址
|
|
|
|
|
compatible = "arm,pl011";
|
|
|
|
|
reg = <0x101f0000 0x1000 >;
|
|
|
|
|
interrupts = < 1 0 >;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
serial@101f2000 {
|
|
|
|
|
compatible = "arm,pl011";
|
|
|
|
|
reg = <0x101f2000 0x1000 >;
|
|
|
|
|
interrupts = < 2 0 >;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
gpio@101f3000 {
|
|
|
|
|
compatible = "arm,pl061";
|
|
|
|
|
reg = <0x101f3000 0x1000
|
|
|
|
|
0x101f4000 0x0010>;
|
|
|
|
|
interrupts = < 3 0 >;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
intc: interrupt-controller@10140000 {
|
|
|
|
|
compatible = "arm,pl190";
|
|
|
|
|
reg = <0x10140000 0x1000 >;
|
|
|
|
|
interrupt-controller;
|
|
|
|
|
#interrupt-cells = <2>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
spi@10115000 {
|
|
|
|
|
compatible = "arm,pl022";
|
|
|
|
|
reg = <0x10115000 0x1000 >;
|
2020-06-05 11:36:18 +08:00
|
|
|
|
interrupts = < 4 0 >;50
|
|
|
|
|
};
|
2020-06-05 11:34:46 +08:00
|
|
|
|
|
|
|
|
|
external-bus {
|
|
|
|
|
#address-cells = <2>
|
|
|
|
|
#size-cells = <1>;
|
|
|
|
|
ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet
|
|
|
|
|
1 0 0x10160000 0x10000 // Chipselect 2, i2c controller
|
|
|
|
|
2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash
|
|
|
|
|
|
|
|
|
|
ethernet@0,0 {
|
|
|
|
|
compatible = "smc,smc91c111";
|
|
|
|
|
reg = <0 0 0x1000>;
|
|
|
|
|
interrupts = < 5 2 >;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
i2c@1,0 {
|
|
|
|
|
compatible = "acme,a1234-i2c-bus";
|
|
|
|
|
#address-cells = <1>;
|
|
|
|
|
#size-cells = <0>;
|
|
|
|
|
reg = <1 0 0x1000>;
|
|
|
|
|
interrupts = < 6 2 >;
|
|
|
|
|
rtc@58 {
|
|
|
|
|
compatible = "maxim,ds1338";
|
|
|
|
|
reg = <58>;
|
|
|
|
|
interrupts = < 7 3 >;
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
flash@2,0 {
|
|
|
|
|
compatible = "samsung,k8f1315ebm", "cfi-flash";
|
|
|
|
|
reg = <2 0 0x4000000>;
|
|
|
|
|
};
|
|
|
|
|
};// end of external-bus
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
2020-06-04 18:18:10 +08:00
|
|
|
|
## Device Tree 的解析
|
|
|
|
|
|
2020-06-05 11:34:46 +08:00
|
|
|
|
device 包含 “of_node” 属性,其类型为“struct device_node*”,通过 dev_of_node(device) 可获得该 of_node。of_node 代表了该设备在设备树中所对应的节点。各 driver 可以使用内核 API 结合 of_node 属性自行解析设备树中对应的资源。
|
|
|
|
|
|
2020-06-04 18:18:10 +08:00
|
|
|
|
### device_node 结构体
|
|
|
|
|
|
|
|
|
|
Linux 内核中使用 device_node 结构体来描述一个节点,此结构体定义在文件 include/linux/of.h 中,定义如下:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct device_node {
|
|
|
|
|
const char *name; /* 节点名字 */
|
|
|
|
|
const char *type; /* 设备类型 */
|
|
|
|
|
phandle phandle;
|
|
|
|
|
const char *full_name; /* 节点全名 */
|
|
|
|
|
struct fwnode_handle fnode;
|
|
|
|
|
|
|
|
|
|
struct property *properties; /* 属性 */
|
|
|
|
|
struct property *deadprops; /* removes 属性 */
|
|
|
|
|
struct device_node *parend; /* 父节点 */
|
|
|
|
|
struct device_node *child; /* 子节点 */
|
|
|
|
|
struct device_node *sibling;
|
|
|
|
|
struct kobject kobj;
|
|
|
|
|
...
|
2020-06-05 10:26:04 +08:00
|
|
|
|
};
|
2020-06-04 18:18:10 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### property 结构体
|
|
|
|
|
|
|
|
|
|
Linux 内核中使用 struct property 结构体来表示属性,定义如下:
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct property {
|
|
|
|
|
char *name; //属性名字
|
|
|
|
|
int length; //属性长度
|
|
|
|
|
void *value; //属性值
|
|
|
|
|
struct property *next;//下一个属性
|
|
|
|
|
unsigned long _flags;
|
|
|
|
|
unsigned int unique_id;
|
|
|
|
|
struct bin_attribute attr;
|
2020-06-05 10:26:04 +08:00
|
|
|
|
};
|
2020-06-04 18:18:10 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 常用 OF 函数
|
|
|
|
|
|
|
|
|
|
#### of_find_node_by_name 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
通过节点名字查找指定的节点。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
name:要查找的节点名字。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的节点,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_find_node_by_type 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct device_node *of_find_node_by_type(struct device_node *from, const char *type);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
通过 device_type 属性查找指定的节点。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
type:要查找的节点对应的字符串,也就是 device_type 属性值。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的节点,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_find_compatible_node 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct device_node *of_find_compatible_node(struct device_node *from, const struct of_device_id *matches, const struct of_device_id **match);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
根据 device_type 和 compatible 这两个属性查找指定的节点。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
matches:of_device_id 匹配表,也就是在此匹配表里面查找节点;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
match:找到的匹配的 of_device_id。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的节点,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_find_node_by_path 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
inline struct device_node *of_find_node_by_path(const char *path);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
通过路径来查找指定的节点。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
path:带有全路径的节点名。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的节点,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_get_parent 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct device_node *of_get_parent(const struct device_node *node);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于获取指定节点的父节点(如果有父节点的话)。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
node:子节点。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的父节点,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_get_next_child 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
查找谋节点的子节点。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
node:父节点;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
prev:前一个子节点,也就是从哪一个子节点开始的下一个子节点,如果为 NULL 表示从第一个子节点开始。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的下一个子节点,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_find_property 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct property *of_find_property(const struct device_node *np, const char *name, int *lenp);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
通过属性名称查找指定的属性
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
np:设备节点;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
name:属性名字;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
lenp:返回属性值的字节数。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的属性,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_get_property 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
2020-06-05 10:26:04 +08:00
|
|
|
|
const void *of_get_property(const struct device_node *np, const char *name, int *lenp);
|
2020-06-04 18:18:10 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
是 of_find_property 函数的扩展,直接返回 property 的 value 属性。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
np:设备节点;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
name:属性名字;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
lenp:返回属性值的字节数。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回找到的 value,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_property_count_elems_of_size 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
2020-06-05 10:26:04 +08:00
|
|
|
|
int of_property_count_elems_of_size(const struct device_node *np, const char *propname int elem_size);
|
2020-06-04 18:18:10 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于获取属性中元素的数量,比如 reg 属性值是一个数组,那么使用此函数可以获取到这个数组的大小。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
np:设备节点;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
proname:需要统计元素数量的属性名字;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
elem_size:元素长度。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
得到的属性元素数量。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u32_index 函数
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u32_index(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u32 index,
|
|
|
|
|
u32 *out_value);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于从属性中获取指定标号的 u32 类型数据值(无符号 32 位),比如某个属性有多个 u32 类型的值,那么就可以使用此函数来获取指定标号的数据值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
index:要读取的值标号;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的值。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u8 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u8(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u8 *out_value);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于读取属性只有一个 u8 数据的值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u16 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u16(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u16 *out_value);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于读取属性只有一个 u16 数据的值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u32 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u32(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u32 *out_value);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于读取属性只有一个 u32 数据的值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u64 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u64(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u64 *out_value);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于读取属性只有一个 u64 数据的值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u8_array 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u8_array(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u8 *out_values,
|
|
|
|
|
size_t sz);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
以 u8 数组形式读取属性值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值;
|
|
|
|
|
|
|
|
|
|
sz:要读取的数组元素数量。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u16_array 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u16_array(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u16 *out_values,
|
|
|
|
|
size_t sz);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
以 u16 数组形式读取属性值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值;
|
|
|
|
|
|
|
|
|
|
sz:要读取的数组元素数量。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u32_array 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u32_array(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u32 *out_values,
|
|
|
|
|
size_t sz);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
以 u32 数组形式读取属性值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值;
|
|
|
|
|
|
|
|
|
|
sz:要读取的数组元素数量。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。-EINVAL 表示属性不存在,-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_u64_array 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_u64_array(const struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
u64 *out_values,
|
|
|
|
|
size_t sz);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
以 u64 数组形式读取属性值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_value:读取到的数组值;
|
|
|
|
|
|
|
|
|
|
sz:要读取的数组元素数量。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败,-EINVAL 表示属性不存在。-ENODATA 表示没有要读取的数据,-EOVERFLOW 表示属性值列表太小。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
#### of_property_read_string 函数
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
**函数原型:**
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
```cpp
|
|
|
|
|
int of_property_read_string(struct device_node *np,
|
|
|
|
|
const char *propname,
|
|
|
|
|
const char **out_string);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于读取属性中字符串值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字;
|
|
|
|
|
|
|
|
|
|
out_string:读取到的字符串值。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:读取成功;
|
|
|
|
|
|
|
|
|
|
负值:读取失败。
|
|
|
|
|
|
|
|
|
|
#### of_property_read_bool 函数
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
2020-06-05 10:26:04 +08:00
|
|
|
|
static inline bool of_property_read_bool(const struct device_node *np,
|
|
|
|
|
const char *propname);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于读取属性中布尔类型数据的值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
proname:要读取的属性名字。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
属性存在则返回 true,否则返回 false。
|
|
|
|
|
|
|
|
|
|
#### of_n_addr_cells 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_n_addr_cells(struct device_node *np);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于获取“#address-cells“属性值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
获取到的“#address-cells”属性值。
|
|
|
|
|
|
|
|
|
|
#### of_n_size_cells 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_n_size_cells(struct device_node *np);
|
2020-06-04 18:18:10 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
用于获取“#size-cells“属性值。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
获取到的“#size-cells”属性值。
|
|
|
|
|
|
|
|
|
|
#### of_device_is_compatible 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_device_is_compatible(const struct device_node *device,
|
|
|
|
|
const char *compat);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于查看节点的 compatible 属性是否有包含 compat 指定的字符串,也就是检查设备节点的兼容性。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
device:设备节点;
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
compat:要查看的字符串。
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
0:节点的 compatible 属性中不包含 compat 指定的字符串;
|
|
|
|
|
|
|
|
|
|
正数:节点的 compatible 属性中包含 compat 指定的字符串。
|
|
|
|
|
|
|
|
|
|
#### of_get_address 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
const __be32 *of_get_address(struct device_node *dev,
|
|
|
|
|
int index,
|
|
|
|
|
u64 *size,
|
|
|
|
|
unsigned int *flags);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
用于获取地址相关属性,主要是“reg”或者“assigned-addresses”属性值。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
dev:设备节点;
|
|
|
|
|
|
|
|
|
|
index:要读取的地址标号;
|
|
|
|
|
|
|
|
|
|
size:地址长度;
|
|
|
|
|
|
|
|
|
|
flags:参数,比如 IORESOURCE_IO、IORESOURCE_MEM 等。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回读取到的地址数据首地址,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### of_translate_address 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
u64 of_translate_address(struct device_node *dev,const __be32 *in_addr);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
将从设备树读取到的地址转换为物理地址。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
dev:设备节点;
|
|
|
|
|
|
|
|
|
|
in_addr:要转换的地址。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回转换得到的物理地址,失败返回 OF_BAD_ADDR。
|
|
|
|
|
|
|
|
|
|
#### of_address_to_resource 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
int of_address_to_resource(struct device_node *dev,
|
|
|
|
|
int index,
|
|
|
|
|
struct resource *r);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
根据索引号从设备树中获取“reg”这一类的地址资源。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
dev:设备节点;
|
|
|
|
|
|
|
|
|
|
index:地址资源索引号。
|
|
|
|
|
|
|
|
|
|
r:得到的 resource 类型的资源值
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
0:成功;
|
|
|
|
|
|
|
|
|
|
负值:失败。
|
|
|
|
|
|
|
|
|
|
#### of_iomap 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
void __iomem *of_iomap(struct device_node *np, int index);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
通过设备结点的“reg”字段直接进行设备内存区间的 ioremap()。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
np:设备节点;
|
|
|
|
|
|
|
|
|
|
index:reg 属性中要完成内存映射的段,如果 reg 属性只有一段的话 index 就设置为 0。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回经过内存映射后的虚拟内存首地址,失败返回 NULL。
|
|
|
|
|
|
|
|
|
|
#### irq_of_parse_and_map 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
unsigned int irq_of_parse_and_map(struct device_node *node, int index);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
从设备树的 interrupt 字段解析出中断号,如果有多个中断则通过 index 来指定。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
node:设备节点;
|
|
|
|
|
|
|
|
|
|
index:用于指定要解析中断的段,如果只有一段的话,就设置为 0。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
|
|
|
|
|
|
|
|
|
成功则返回解析的中断号,失败返回 0。
|
|
|
|
|
|
|
|
|
|
#### of_find_device_by_node 函数
|
|
|
|
|
|
|
|
|
|
**函数原型:**
|
|
|
|
|
|
|
|
|
|
```cpp
|
|
|
|
|
struct platform_device *of_find_device_by_node(struct device_node *np);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**说明:**
|
|
|
|
|
|
|
|
|
|
获取与节点对应的 platform_device。
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
|
|
|
|
node:设备节点。
|
|
|
|
|
|
|
|
|
|
**返回值:**
|
2020-06-04 18:18:10 +08:00
|
|
|
|
|
2020-06-05 10:26:04 +08:00
|
|
|
|
成功则返回 platform_device 指针,失败返回 NULL。
|