Difference between revisions of "Device Tree Mysteries"

From eLinux.org
Jump to: navigation, search
(Phandle: add kernel usage)
(explain some more: what is the reason for having a phandle)
Line 46: Line 46:
  
 
=== explain some more ===
 
=== 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:
 
Modifying the example to show the use of the phandle helps a little bit:

Revision as of 01:47, 22 June 2016


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.

Phandle

cryptic

The ePAPR tells us

2.3.3 phandle

Property: phandle
Value type: <u32>
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, so long as you do not declare 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_1: pic@10000000 {
              interrupt-controller;
      };

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

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 in a different node, then dtc will not cause a conflict by attempting to create the same phandle value that you explicitly defined for another label.

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:

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

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

      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 = < 0x1 >;
	#size-cells = <0x1>;
        soc {
        	#address-cells = < 0x1 >;
		#size-cells = <0x1>;

                PIC_1: pic@100 {
		        reg = < 0x100 0x20 >;
                        interrupt-controller;
                };
        };

        uart@200 {
		reg = < 0x200 0x10 >;
                interrupt-parent = < &PIC_1 >;
        };
};

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

/ {
	#address-cells = <0x1>;
	#size-cells = <0x1>;

	soc {
		#address-cells = <0x1>;
		#size-cells = <0x1>;

		pic@100 {
			reg = <0x100 0x20>;
			interrupt-controller;
			linux,phandle = <0x1>;
			phandle = <0x1>;
		};
	};

	uart@200 {
		reg = <0x200 0x10>;
		interrupt-parent = <0x1>;
	};
};

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 coded 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 that contains the matching 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.