Device Tree Mysteries

From eLinux.org
Revision as of 12:46, 26 June 2016 by Frowand (talk | contribs) (#xxx-cells property name)
Jump to: navigation, search


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

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

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

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

#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
-----------------                 ------------------------------------------
#address-cells                    reg, first tuple element -- exception to naming, phandle form
#atmel,pll-clk-output-range-cells
#atmel,pll-output-range-cells
#clock-cells                      clocks, second tuple element
#cooling-cells                    cooling device, second tuple element
#dma-cells                        dmas, second tuple element
#gpio-cells                       gpios
#gpio-range-cells
#hwlock-cells
#interrupt-cells                  interrupts -- exception to phandle form
#interrupt-cells                  interrupt-map -- exception to naming
#interrupt-cells                  interrupts-extended -- exception to naming
#io-channel-cells                 io-channels, second tuple element
#iommu-cells
#mbox-cells
#msi-cells
#nvidia,mipi-calibrate-cells
#phy-cells                        phys
#phys-cells
#pinctrl-single,gpio-range-cells
#power-domain-cells
#pwm-cells                        pwms
#qca,ddr-wb-channel-cells
#qcom,state-cells
#rcpm-wakeup-cells
#reset-cells
#size-cells                       reg, second tuple element -- exception to naming, phandle form
#sleep-cells
#sound-dai-cells                  sound-dai  -- exception to naming
#stream-id-cells
#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".

Example 1

       INTC_1: intc@10000000 {
               reg = <0x10000000 0x1000>;
               interrupt-controller;
               #interrupt-cells = <1>;
       };

       uart@20000000 {
               compatible = "my-uart-type";
               reg = <0x20000000 0x1000>;
               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 = <0x10000000 0x1000>;
               interrupt-controller;
               #interrupt-cells = <1>;
       };

       uart@20000000 {
               compatible = "my-uart-type";
               reg = <0x20000000 0x1000>;
               interrupt-parent = <&INTC_1>;
               interrupts = <17 4>;
       };

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, "<17 4>" 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 = <0x10000000 0x1000>;
               interrupt-controller;
               #interrupt-cells = <1>;
       };

       uart@20000000 {
               compatible = "my-uart-type";
               reg = <0x20000000 0x1000>;
               interrupt-parent = <&INTC_1>;
               interrupts = <17 4>;
       };

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:

Two tuples, one element per tuple:

   interrupts = <17>, <4>;

One tuple, two elements per tuple:

   interrupts = <17 4>;

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 >, < 23 8>, < &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 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.

device creation, driver binding, probing

See devicetree: Kernel Internals and Practical Troubleshooting [PDF] , ELC Europe 2014 by Frank Rowand.