catalogue
2. Structure of equipment tree
4.3 #address-cells #size-cells
6.2 extracting attribute values
6.2.2 of_property_read_u32_index
6.2.3 of_property_read_u*_array
Let's not talk about the background of the introduction of the device tree. Look directly at the device tree.
1. What is a device tree?
The device tree describes the hardware in the system with a tree structure and nodes. Each node has attributes / values that describe the characteristics of the represented device, etc. So there are several concepts.
DTS | The code source file of the device tree can be understood as the reference customization of each DTSI node on each development board. |
DTSI | Device tree codes that are more common to the same platform can be defined in DTS files as header files. |
DTC | DTS compilation files can be compiled into DTB or decompiled into DTS |
DTB | Binary file compiled by DTC |
2. Structure of equipment tree
/dts-v1/; [memory reservations] /{ [property defintions] [child node] };
/dts-v1/; | Version information of the device tree |
[memory reservations] | The reserved memory space is not used / allocated by memory: / memreserve / < address > < lenth >; |
[property defintions] | Name of attribute and value of attribute: property name = value; |
There are two types of property name: one is a user-defined name, such as "led pins", and the other is a fixed name, such as "compatible".
The value of value is as follows:
empty | Can be empty, such as: enable active high; |
<u32>
| 32-bit data: TX_ delay = <0x30>; |
<u64>
| Two 32-bit data: < 0x11223344 0x55667788 > |
<string>
| String: compatible = "silergy,syr827"; |
<prop-encoded-array>
| Specified value: status = "okay"; |
<phandle>
| phandle value: basically not recommended |
<stringlist>
| Multiple strings: "hello", "world" |
Hexadecimal number |
local-mac-address = [00 00 12 34 56 78];
or: local-mac-address = [000012345678];
|
Node reference |
interrupt-parent = < &mpic >;
or: interrupt-parent = < &{/soc/interrupt-controller@40000} >;
|
No node reference for < > |
ethernet0 = &EMAC0; Here & emac0 will be expanded to the full path of the node
|
3. Node structure
The device tree has only one root node '/' and several nodes node1 and node2... If there are nodes under these nodes, such as node-a under node1, node-a is called a child node and node1 is its parent node.
[label:] node-name[@unit-address] { [properties definitions] [child nodes] };
[label:] | Node identification for easy reference |
node-name | Node name |
[@unit-address] | Starting address of node memory (if there is no node with the same name to distinguish, it can be omitted) |
4. Node standard attributes
4.1 compatible
This node is used to match the platform Driver when the attribute name and platform_ Of in drvier_ match_ When the table matches, the probe function will be executed on the driver matching.
Example: compatible = "active-semi,act8846";
4.2 status
Node status, available, disabled, and error.
value | Description |
"okay" | Equipment available |
"disabled" | Device disabled |
"fail" | The device has encountered an error and is unavailable |
"fail-sss" | An error occurred on the device with the error content "sss" |
Example: | status = "okay"; |
4.3 #address-cells #size-cells
#address-cells | The address of the "reg" attribute in the specified child node is represented by several 32 digits |
#size-cells | The address length of the "reg" attribute in the specified child node is represented by several 32 bits |
bus_intmem@ff700000 { compatible = "mmio-sram"; reg = <0x0 0xff700000 0x0 0x18000>; #address-cells = <1>; // The address is represented by a 32-digit number #size-cells = <1>; // The length is represented by a 32-digit number ranges = <0 0x0 0xff700000 0x18000>; smp-sram@0 { compatible = "rockchip,rk3066-smp-sram"; reg = <0x00 0x10>; //Here is the embodiment };
4.4 reg
It is used to define the starting address and length of the address / register. The value inside is specified by #address cells #size cells.
Format: reg = <addr1 lenth1 addr2 lenth2 ...>
4.5 name
Not recommended
4.6 device_type
It is not recommended. It should only be included in the "cpu" and "memory" nodes, but some devices will also be described with this attribute. I don't know why
serial@4600 { device_type = "serial"; compatible = "ns16550"; reg = <0x4600 0x100>; clock-frequency = <0>; interrupts = <0xA 0x8>; interrupt-parent = <&ipic>; }
4.7 phandle
It is used to specify that this node is the only node in the equipment tree and can be used by other nodes to associate this node. It is generally not used now.
pic@10000000 { phandle = <1>; interrupt-controller; }; another-device-node { interrupt-parent = <1>; };
4.8 virtul-reg
No research
4.9 range
No research
4.10 dma-range
No research
5. Special nodes
5.1 /aliases node
The official explanation is that this node is under the root node and can define an alias for other nodes. Let's start with an example.
/ { compatible = "rockchip,rk3288"; interrupt-parent = <&gic>; aliases { ethernet0 = &gmac; i2c0 = &i2c0; i2c1 = &i2c1; i2c2 = &i2c2; ... ... }; };
As mentioned above, property name = value. When value does not have < >, it will be expanded into a full path. You can see the full path of "&i2c0" through decompilation above. Here is an example.
aliases { serial0 = "/simple-bus@fe000000/serial@llc500"; ethernet0 = "/simple-bus@fe000000/ethernet@31c000"; };
After reading some articles on the Internet, the kernel will parse the node, find the node through the expanded node path, and explain the alias id (that is, the numbers' 0 ',' 1 'after i2c0 and i2c1) to register drivers and devices.
5.2 /chosen node
Parameters selected during system startup, such as nfs mount point, etc.
chosen { bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200"; };
6."of_" correlation function
6.1 finding nodes
6.1.1 of_find_node_by_name
struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
function | Find nodes by node name |
*from | The node name to start searching. If 'NULL', the entire device tree will be searched from the root node |
*name | Node name to find |
Return value | Found node pointer |
6.1.2 of_find_node_by_type
struct device_node *of_find_node_by_type(struct device_node *from, const char *type);
function | Via 'device'_ Find node with value of 'type' |
*from | The node name to start searching. If 'NULL', the entire device tree will be searched from the root node |
*name | 'device 'to find_ value of 'type' attribute (string) |
Return value | Found node pointer |
6.1.3 of_find_compatible_node
struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compatible)
function | Via 'device'_ The values of the 'type' and 'compatible' attributes find the node if the device_ If the type is NULL, the value of this attribute is ignored and the search is from the value of compatible |
*from | The node to start searching. If NULL, it means to start searching the entire device tree from the root node |
*type | Device corresponding to the node to be found_ Type attribute value, 'NULL' means to ignore this attribute |
*compatible | The compatible attribute value corresponding to the node to find |
Return value | Found node pointer |
6.1.4 of_find_node_by_path
struct device_node *of_find_node_by_path(const char *path)
function | Find nodes by their full path |
*path | Full path of node |
Return value | Found node pointer |
6.2 extracting attribute values
6.2.1 of_find_property
property *of_find_property(const struct device_node *np, const char *name, int *lenp)
function | Find properties |
*np | Node pointer |
*name | The name of the property |
*lenp | The value length of the attribute |
Return value | Found node pointer |
6.2.2 of_property_read_u32_index
int of_property_read_u32_index(const struct device_node *np, const char *propname, u32 index, u32 *out_value);
function | Reads the 32-bit unsigned value of the property |
*np | Node pointer |
*propname | The name of the property |
index | index of attribute value |
*out_value | Read value |
Return value | 0 read succeeded, non-0 read failed |
opp-microvolt = <1111 2222 3333>; //The value of this attribute is three 32-bit unsigned integer values If this function index Is 0, then the read value is'1111'
6.2.3 of_property_read_u*_array
int of_property_read_u8_array(const struct device_node *np, const char *propname, u8 *out_values, size_t sz); int of_property_read_u16_array(const struct device_node *np, const char *propname, u16 *out_values, size_t sz); int of_property_read_u32_array(const struct device_node *np, const char *propname,u32 *out_values, size_t sz); int of_property_read_u64_array(const struct device_node *np, const char *propname,u32 *out_values, size_t sz);
function | Attribute values are multiple u8(u16, u32, u64) numbers that can be read out at one time |
*np | Node pointer |
*propname | The name of the property |
*out_values | Array pointer read |
sz | The number of array members to read |
Return value | 0 read succeeded, non-0 read failed |
6.2.4 of_property_read_u*
int of_property_read_u8(const struct device_node *np, const char *propname, u8 *out_value) int of_property_read_u16(const struct device_node *np, const char *propname, u16 *out_value) int of_property_read_u32(const struct device_node *np, const char *propname, u32 *out_value) int of_property_read_u64(const struct device_node *np, const char *propname, u64 *out_value)
function | The value of the property has only one u8 (u16,u32,u64) value. Read the value |
*np | Node pointer |
*propname | The name of the property |
*out_values | Pointer to the value read |
Return value | 0 read succeeded, non-0 read failed |
remarks: | These functions can be used_ The function of array is replaced, but the sz variable is set to 1 |