Device Tree Mysteries

Top Device Tree page

Some subjects are not documented anywhere, or the documentation is cryptic or incomplete. This page will try to provide some insights into those subjects.

device creation, driver binding, probing
See [[Media:Rowand--devicetree_kernel_internals.pdf | devicetree: Kernel Internals and Practical Troubleshooting [PDF] ]] , ELC Europe 2014 by Frank Rowand.

cryptic
The [[Media:Power_ePAPR_APPROVED_v1.1.pdf | ePAPR]] tells us

2.3.3 phandle

Property: phandle Value type: Description: The phandle property specifies a numerical identifier for a node that is unique within the device tree. The phandle property value is used by other nodes that need to refer to the node associated with the property.

Example:

See the following device tree excerpt:

pic@10000000 { phandle = < 1 >; interrupt-controller; };

A phandle value of 1 is defined. Another device node could reference the pic node with a  phandle value of 1:

interrupt-parent = < 1 >;

Programming Note

Most device trees in Device Tree Syntax (DTS) (see Appendix A) will not contain explicit phandle properties. The DTC tool automatically inserts the phandle properties when the DTS is compiled into the binary DTB format.

explain some more
The ePAPR explains phandles a bit more in Appendix A ("Device Tree Source Format") and shows more context of phandle usage in Appendix B1 (Ebony Device Tree) and Appendix B2 (MPC8572DS Device Tree).

Let's step back and ask what is the reason for having a phandle? It is really just a hack to get around the fact that device tree does not have a pointer data type. It is a way to reference "that node over there that is related to this node for some reason". In the above example from the ePAPR, it is a way to specify what node is the interrupt controller for a device node.

Modifying the example to show the use of the phandle helps a little bit:

pic@10000000 { phandle = < 1 >; };

A phandle value of 1 is defined. Another device node could reference the pic node with a  phandle value of 1:

uart@20000000 { interrupt-parent = < 1 >; };

There is nothing magic about the value '1'. You are free to use any value that you desire, as long as you do not specify the same value for the phandle property in two different nodes.

But you are not likely to find a modern device tree source file that explicitly defines a phandle or specifies a u32 value when referencing a phandle. This is because the dtc compiler kindly creates phandles from labels. So the above example would look like:

PIC_3: pic@10000000 { interrupt-controller; };

uart@20000000 { interrupt-parent = < &PIC_3 >; };

The '&' tells dtc that the following string is a phandle referencing the label matching the string.

dtc will create a unique u32 value for each label that is used for a phandle reference. If you insist on defining a phandle property in one node, and specify a label on a different node's name, then dtc will be aware of any phandle values explicitly stated and will not use those values when creating phandle values for labeled nodes.

The phandle reference can refer to a label that occurs later in the source file.

If you do not want to use a label you can instead specify a full path to reference a phandle. In this example, both uart@20000000 and uart@30000000 are pointing to the same interrupt controller node:

/{     soc { PIC_3: pic@10000000 { interrupt-controller; };     };

uart@20000000 { interrupt-parent = < &PIC_3 >; };

uart@30000000 { interrupt-parent = < &{/soc/pic@10000000} >; }; };

The previous example may lead to another question from the astute reader. Can a phandle reference by path occur when the target node does not have a label? The dtc compiler generates the phandle property because there is a phandle reference, not because the node has a label. So the answer is yes, as seen in the next example:

/{     soc { pic@10000000 { interrupt-controller; };     };

uart@30000000 { interrupt-parent = < &{/soc/pic@10000000} >; }; };

NOTE 1: A '&' only refers to a phandle if it is inside an array. If outside an array, it refers to a path. See Labels for more information.

NOTE 2: One place you will see phandles defined and a u32 value used for a phandle reference is if you decompile a compiled device tree, aka a .dtb or device tree blob. This is because labels are not retained in the compiled device tree. You will see that dtc simply allocates a unique u32 value for each label that is referenced and replaces any reference to the label with the unique u32 value.

kernel usage
As mentioned in the above example, all knowledge of label names and whether a value in a property is a phandle is lost when the source is compiled. You can see this by compiling a simple example into a device tree blob and then decompiling the blob:

$ cat test_phandle.dts

/dts-v1/;

/ {       #address-cells = ; #size-cells = ; soc { #address-cells = ; #size-cells = ;

pic_3: pic@100 { reg = ; interrupt-controller; };       };

uart@200 { reg = ; interrupt-parent = < &pic_3 >; }; };

$ dtc -O dtb test_phandle.dts >test_phandle.dtb $ dtc -O dts test_phandle.dtb /dts-v1/;

/ {	#address-cells = ; #size-cells = ;

soc { #address-cells = ; #size-cells = ;

pic@100 { reg = ; interrupt-controller; linux,phandle = ; phandle = ; };	};

uart@200 { reg = ; interrupt-parent = ; }; };

Thus the value of the property "interrupt-parent" in node uart@200 is merely a u32 value. It is not a pointer to the location of node /soc/pic@100 in the device tree blob. When loaded by the kernel, it is also not a pointer in the expanded device tree. It is merely a value in a property. The only way that kernel code knows that the value in the "interrupt-parent" property is a phandle is because the binding documentation has defined that the value is a phandle. Thus the code that reads the "interrupt-parent" property has to be written to treat that value as a phandle. When the code needs to find what node the phandle points to, it calls of_find_node_by_phandle, which searches for a node containing a "phandle" property containing the specified value.

One other oddity you may have noted in the above example is that dtc created two properties for the label, "phandle" and "linux,phandle". Both of these properties will always have the same value in a given node. Do not use "linux,phandle" - this is a deprecated property that dtc continues to generate to maintain compatibility.

Labels
In an array a reference to a label will be expanded to that node's phandle. For instance, the property interrupt-parent in the following example.

Outside an array, a reference to a label will be expanded to that node's full path. For instance, the property interrupt-parent-path in the following example.

$ cat example_label_a.dts

/dts-v1/;

/ {       soc { #address-cells = ; #size-cells = ;

pic_3: pic@100 { reg = ; interrupt-controller; };

uart { interrupt-parent = < &pic_3 >; interrupt-parent-path = &pic_3 ; };       };

}; $ dtc -O dts example_label_a.dts /dts-v1/;

/ {

soc { #address-cells = ; #size-cells = ;

pic_3: pic@100 { reg = ; interrupt-controller; linux,phandle = ; phandle = ; };

uart { interrupt-parent = ; interrupt-parent-path = "/soc/pic@100"; };	}; };

Outside an array, a reference to a label will be expanded to that node's full path. The previous example shows how this value can be used as a property value. The following example shows how that can be used as the full path of a node.

Using a label for a node's path is commonly used to refer to a previously existing node for the purpose of modifying the value of one or more properties in that node. In this example, the reg property is modified. $ cat example_label_b.dts

/dts-v1/;

/ {       soc { #address-cells = ; #size-cells = ;

pic_3: pic@100 { reg = ; interrupt-controller; };

};

};

&pic_3 { reg = ; }; $ dtc -O dts example_label_b.dts /dts-v1/;

/ {

soc { #address-cells = ; #size-cells = ;

pic_3: pic@100 { reg = ; interrupt-controller; };	}; };

Labels may also appear before or after any component of a property value, or between elements of an array, or between bytes of a bytestring. e.g. reg = reglabel: <0 sizelabel: 0x1000000>; e.g. prop = [ab cd ef byte4: 00 ff fe]; e.g. str = start: "string value" end: ;

There is no syntax available to reference data labels elsewhere in dts source. There is no additional information added to the flattened device tree (.dtb) file for data labels. The only use of labels (as of dtc version 1.4.2) is when -Oasm is specified. In this case, the labels are exposed in the assembly output file. The intent is that the compiled assembly file would be linked into a very minimalist boot loader. This would allow the boot loader to easily perform very simple property data changes (in-place alterations, no re-sizing) without the complexity of FDT parsing.

Label as a phandle vs Label as a path
The description of Labels  example_label_a.dts showed that a label used in a property value could expand either to the phandle value of the referenced node (see property "interrupt-parent") or a string containing the path of the reference node (see property "interrupt-parent-path").

It is more common to use the phandle value form because:
 * less space is used in the Flattened Device Tree
 * it is easier to parse a multi-element property if the node reference is a fixed size phandle instead of a variable length string
 * it is easier and more clear to specify a multi-element property that consists of 32 bit items than one that consists of a mix of 32 bit items and a string (see the values of properties "interrupt-parent" and "interrupt-parent-path" in example_label_c.dts below)

$ cat example_label_c.dts

/dts-v1/;

/ {       soc { #address-cells = ; #size-cells = ;

pic_3: pic@100 { reg = ; interrupt-controller; };

uart { // NOTE: this is not a valid interrupt-parent binding interrupt-parent = < 7 &pic_3 4 >; interrupt-parent-path = < 7 >, &pic_3, < 4 > ; };       };

}; $ dtc -O dts example_label_c.dts /dts-v1/;

/ {

soc { #address-cells = ; #size-cells = ;

pic_3: pic@100 { reg = ; interrupt-controller; linux,phandle = ; phandle = ; };

uart { interrupt-parent = ; interrupt-parent-path = [00 00 00 07 2f 73 6f 63 2f 70 69 63 40 31 30 30 00 00 00 00 04]; };	}; };

Label vs aliases node property
A label can be used in a device tree source file as either a phandle value or a path, depending on context, as seen in sections Labels and Label as a phandle vs Label as a path.

The "/aliases" node contains properties that are aliases. The name of each property is the name of the alias, and the value of the property is the full path to a node in the device tree.

The aliases are not used directly in the device tree source, but are instead dereferenced by the Linux kernel. When a path is provided to of_find_node_by_path or of_find_node_opts_by_path, if the path does not begin with a "/" then the first element of the path must be a property name in the "/aliases" node. That element is replaced with the full path from the alias.

#xxx-cells property name
Property names with a leading '#', ending with '-cells' are used to provide information about the format of another property. The convention is that the #xxx-cells property describes the number of u32 cells used to hold the data item in a property named 'xxxs'.

A common pattern for the 'xxxs' property is to contain tuples of the form:

phandle cell_1 cell_2 ... cell_n where: #xxx-cells determines 'n'   if n is zero, typically the tuple contains just phandle

Exceptions to the rules are noted in the following table.

'#' prefixed property names in Linux 4.7-rc2 documented bindings Entries with no corresponding property name are because this table is still under construction. '#xxx-cells' name                corresponding property name -                -- #qca,ddr-wb-channel-cells
 * 1) address-cells                   reg, first tuple element -- exception to naming, phandle form
 * 2) atmel,pll-clk-output-range-cells
 * 3) atmel,pll-output-range-cells
 * 4) clock-cells                     clocks, second tuple element
 * 5) cooling-cells                   cooling device, second tuple element
 * 6) dma-cells                       dmas, second tuple element
 * 7) gpio-cells                      gpios
 * 8) gpio-range-cells
 * 9) hwlock-cells
 * 10) interrupt-cells                 interrupts -- exception to phandle form
 * 11) interrupt-cells                 interrupt-map -- exception to naming
 * 12) interrupt-cells                 interrupts-extended -- exception to naming
 * 13) io-channel-cells                io-channels, second tuple element
 * 14) iommu-cells
 * 15) mbox-cells
 * 16) msi-cells
 * 17) nvidia,mipi-calibrate-cells
 * 18) phy-cells                       phys
 * 19) phys-cells
 * 20) pinctrl-single,gpio-range-cells
 * 21) power-domain-cells
 * 22) pwm-cells                       pwms
 * 1) qcom,state-cells
 * 2) rcpm-wakeup-cells
 * 3) reset-cells
 * 4) size-cells                      reg, second tuple element -- exception to naming, phandle form
 * 5) sleep-cells
 * 6) sound-dai-cells                 sound-dai  -- exception to naming
 * 7) stream-id-cells
 * 8) thermal-sensor-cells            thermal-sensors, second tuple element

The '#xxx-cells' properties may or may not be inheritable from an ancestor node, or from a node found via phandle search. This can be determined from the binding documentation.

Some examples of how #xxx-cells is used follow.

Example 1 is a simple interrupt setup. A uart device specifies an interrupt with a tuple size of 1. The size of the tuples in the "interrupts" property is found in the "#interrupt-cells" property that is in the interupt controller node, according to the binding document Documentation/devicetree/bindings/interrupt-controller/interrupts.txt. In this case, the interrupt controller is the node referenced the the phandle contained in property "interrupt-parent".

Note that the "interrupt" property does not follow the common tuple form of:

phandle cell_1 cell_2 ... cell_n

An example that includes phandle in a tuple can be seen in the "interrupts-extended" property in example 3.1.

Example 1 INTC_1: intc@10000000 { reg = ; interrupt-controller; #interrupt-cells = <1>; };       uart@20000000 { compatible = "my-uart-type"; reg = ; interrupt-parent = <&INTC_1>; interrupts = <17>; };

In example 2, the tuple size remains 1, but the uart device uses two interrupts. An example of a second interrupt might be for an alarm interrupt to wake the system when the uart detects input.

Example 2 INTC_1: intc@10000000 { reg = ; interrupt-controller; #interrupt-cells = <1>; };       uart@20000000 { compatible = "my-uart-type"; reg = ; interrupt-parent = <&INTC_1>; interrupts = ; };

In example 3, the tuple size is changed from 1 to 2, and the uart device uses one interrupt. The second value in the tuple is a flag (see interrupts.txt). The value of the "interrupts" property is exactly the same as in the previous example, but has an entirely different meaning. The meaning is defined by the binding document for the specific interrupt controller. In the previous example, " " specified interrupt 17 and interrupt 4. In this example it specifies interrupt 17 with a flag value of 4 (meaning active high level-sensitive according to interrupts.txt.


 * How do I know what value to specify for property "#interrupt-cells" in the interrupt controller?
 * The binding document for the specific type of interrupt controller will specify this value.
 * How do I know the semantics of each element of the tuple?
 * The binding document for the specific type of interrupt controller will specify the tuple semantics.
 * How do I know which binding document applies to the interrupt controller when adding a device node to a device tree that contains an interrupt controller?
 * To keep the examples less cluttered, a key property has been left out. The interrupt controller nodes must contain a "compatible" property that defines the specific programming model for the device.  The binding document that specifies a "compatible" property value that matches the value in the interrupt controller node is the applicable document.

Example 3 INTC_1: intc@10000000 { reg = ; interrupt-controller; #interrupt-cells = <1>; };       uart@20000000 { compatible = "my-uart-type"; reg = ; interrupt-parent = <&INTC_1>; interrupts = ; };

The dtc compiler has syntax that allows specifying tuple values in a way that distinguishes between two tuples with one element per tuple and one tuple with two elements per tuple. The difference between the tuple format in example 2 and example 3 would be more clear if this syntax was used:

Example 3.1 Two tuples, one element per tuple: interrupts = <17>, <4>; One tuple, two elements per tuple: interrupts = ; Three tuples, with formats of: 1) phandle, interrupt   2) phandle, interrupt, flags 2) phandle, interrupt   interrupts-extended = < &INTC_1 17 >, < &INTC_2 23 8 >, < &INTC_4 27 >; There are no type declarations for arrays and tuples, so the dtc compiler can not enforce conformance with tuple size in the value declarations. Thus the above three tuples would properly compile if specified as:    interrupts-extended = < &INTC_1 17 &INTC_2 >,, < &INTC_4 27 >; even though it appears not to match the formats of the three tuples. If you compile a device tree source file containing each of the two above definitions of interrupts, then decompile the resulting .dtb file, you will see the dtc simply converts both forms to be:    <0x2 0x11 0x3 0x17 0x8 0x4 0x1b> (In the test .dts file I created, &INTC_1 has the value 0x2, &INTC_2 has the value 0x3, and &INTC_4 has the value 0x4.)

PCI Host Bridge
See PCI Host Bridge for information about PCI host bridges and PCI address translation.

Interrupt Nexus
An Interrupt Nexus is jargon for a device tree node that contains an interrupt-map property.

See Interrupt Mapping immediately below.

Interrupt Mapping
A bus controller routes interrupts from devices on the bus to an interrupt controller available to the bus controller. The interrupt map provides the correspondance between interrupts on the bus and where the bus controller routes those interrupts.

See Advanced Interrupt Mapping for information about complex interrupt mapping. The example is for PCI, but the concepts also apply to non-PCI nodes.

Some useful reference information when reading Advanced Interrupt Mapping is located in section "2.4.3 Interrupt Nexus Properties" of the ePAPR.

error messages
Error messages can be cryptic.

Error: xxx.dts:1.1-2 syntax error Is reporting that something is not valid in file xxx.dts line 1 columns 1-2