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.

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: 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.

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

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