.. _dt-syntax: Syntax and structure #################### As the name indicates, a devicetree is a tree. The human-readable text format for this tree is called DTS (for devicetree source), and is defined in the `Devicetree specification`_. .. _Devicetree specification: https://www.devicetree.org/ This page's purpose is to introduce devicetree in a more gradual way than the specification. However, you may still need to refer to the specification to understand some detailed cases. .. contents:: Contents :local: Example ******* Here is an example DTS file: .. code-block:: devicetree /dts-v1/; / { a-node { subnode_nodelabel: a-sub-node { foo = <3>; }; }; }; The ``/dts-v1/;`` line means the file's contents are in version 1 of the DTS syntax, which has replaced a now-obsolete "version 0". Nodes ***** Like any tree data structure, a devicetree has a hierarchy of *nodes*. The above tree has three nodes: #. A root node: ``/`` #. A node named ``a-node``, which is a child of the root node #. A node named ``a-sub-node``, which is a child of ``a-node`` .. _dt-node-labels: Nodes can be assigned *node labels*, which are unique shorthands that refer to the labeled node. Above, ``a-sub-node`` has the node label ``subnode_nodelabel``. A node can have zero, one, or multiple node labels. You can use node labels to refer to the node elsewhere in the devicetree. Devicetree nodes have *paths* identifying their locations in the tree. Like Unix file system paths, devicetree paths are strings separated by slashes (``/``), and the root node's path is a single slash: ``/``. Otherwise, each node's path is formed by concatenating the node's ancestors' names with the node's own name, separated by slashes. For example, the full path to ``a-sub-node`` is ``/a-node/a-sub-node``. Properties ********** Devicetree nodes can also have *properties*. Properties are name/value pairs. Property values can be any sequence of bytes. In some cases, the values are an array of what are called *cells*. A cell is just a 32-bit unsigned integer. Node ``a-sub-node`` has a property named ``foo``, whose value is a cell with value 3. The size and type of ``foo``\ 's value are implied by the enclosing angle brackets (``<`` and ``>``) in the DTS. See :ref:`dt-writing-property-values` below for more example property values. Devicetrees reflect hardware **************************** In practice, devicetree nodes usually correspond to some hardware, and the node hierarchy reflects the hardware's physical layout. For example, let's consider a board with three I2C peripherals connected to an I2C bus controller on an SoC, like this: .. figure:: ../../../../../../../zephyr/doc/build/dts/zephyr_dt_i2c_high_level.png :alt: representation of a board with three I2C peripherals :figclass: align-center Nodes corresponding to the I2C bus controller and each I2C peripheral would be present in the devicetree. Reflecting the hardware layout, the I2C peripheral nodes would be children of the bus controller node. Similar conventions exist for representing other types of hardware. The DTS would look something like this: .. code-block:: devicetree /dts-v1/; / { soc { i2c-bus-controller { i2c-peripheral-1 { }; i2c-peripheral-2 { }; i2c-peripheral-3 { }; }; }; }; Properties in practice ********************** In practice, properties usually describe or configure the hardware the node represents. For example, an I2C peripheral's node has a property whose value is the peripheral's address on the bus. Here's a tree representing the same example, but with real-world node names and properties you might see when working with I2C devices. .. figure:: ../../../../../../../zephyr/doc/build/dts/zephyr_dt_i2c_example.png :figclass: align-center I2C devicetree example with real-world names and properties. Node names are at the top of each node with a gray background. Properties are shown as "name=value" lines. This is the corresponding DTS: .. code-block:: devicetree /dts-v1/; / { soc { i2c@40003000 { compatible = "nordic,nrf-twim"; reg = <0x40003000 0x1000>; apds9960@39 { compatible = "avago,apds9960"; reg = <0x39>; }; ti_hdc@43 { compatible = "ti,hdc", "ti,hdc1010"; reg = <0x43>; }; mma8652fc@1d { compatible = "nxp,fxos8700", "nxp,mma8652fc"; reg = <0x1d>; }; }; }; }; .. _dt-unit-address: Unit addresses ************** In addition to showing more real-world names and properties, the above example introduces a new devicetree concept: unit addresses. Unit addresses are the parts of node names after an "at" sign (``@``), like ``40003000`` in ``i2c@40003000``, or ``39`` in ``apds9960@39``. Unit addresses are optional: the ``soc`` node does not have one. In devicetree, unit addresses give a node's address in the address space of its parent node. Here are some example unit addresses for different types of hardware. Memory-mapped peripherals The peripheral's register map base address. For example, the node named ``i2c@40003000`` represents an I2C controller whose register map base address is 0x40003000. I2C peripherals The peripheral's address on the I2C bus. For example, the child node ``apds9960@39`` of the I2C controller in the previous section has I2C address 0x39. SPI peripherals An index representing the peripheral's chip select line number. (If there is no chip select line, 0 is used.) Memory The physical start address. For example, a node named ``memory@2000000`` represents RAM starting at physical address 0x2000000. Memory-mapped flash Like RAM, the physical start address. For example, a node named ``flash@8000000`` represents a flash device whose physical start address is 0x8000000. Fixed flash partitions This applies when the devicetree is used to store a flash partition table. The unit address is the partition's start offset within the flash memory. For example, take this flash device and its partitions: .. code-block:: devicetree flash@8000000 { /* ... */ partitions { partition@0 { /* ... */ }; partition@20000 { /* ... */ }; /* ... */ }; }; The node named ``partition@0`` has offset 0 from the start of its flash device, so its base address is 0x8000000. Similarly, the base address of the node named ``partition@20000`` is 0x8020000. .. _dt-important-props: Important properties ******************** .. Documentation maintainers: If you add a property to this list, make sure it gets linked to from gen_devicetree_rest.py too. The devicetree specification defines several standard properties. Some of the most important ones are: compatible The name of the hardware device the node represents. The recommended format is ``"vendor,device"``, like ``"avago,apds9960"``, or a sequence of these, like ``"ti,hdc", "ti,hdc1010"``. The ``vendor`` part is an abbreviated name of the vendor. The file :zephyr_file:`dts/bindings/vendor-prefixes.txt` contains a list of commonly accepted ``vendor`` names. The ``device`` part is usually taken from the datasheet. It is also sometimes a value like ``gpio-keys``, ``mmio-sram``, or ``fixed-clock`` when the hardware's behavior is generic. The build system uses the compatible property to find the right :ref:`bindings ` for the node. Device drivers use ``devicetree.h`` to find nodes with relevant compatibles, in order to determine the available hardware to manage. The ``compatible`` property can have multiple values. Additional values are useful when the device is a specific instance of a more general family, to allow the system to match from most- to least-specific device drivers. Within Zephyr's bindings syntax, this property has type ``string-array``. reg Information used to address the device. The value is specific to the device (i.e. is different depending on the compatible property). The ``reg`` property is a sequence of ``(address, length)`` pairs. Each pair is called a "register block". Values are conventionally written in hex. Here are some common patterns: - Devices accessed via memory-mapped I/O registers (like ``i2c@40003000``): ``address`` is usually the base address of the I/O register space, and ``length`` is the number of bytes occupied by the registers. - I2C devices (like ``apds9960@39`` and its siblings): ``address`` is a slave address on the I2C bus. There is no ``length`` value. - SPI devices: ``address`` is a chip select line number; there is no ``length``. You may notice some similarities between the ``reg`` property and common unit addresses described above. This is not a coincidence. The ``reg`` property can be seen as a more detailed view of the addressable resources within a device than its unit address. status A string which describes whether the node is enabled. The devicetree specification allows this property to have values ``"okay"``, ``"disabled"``, ``"reserved"``, ``"fail"``, and ``"fail-sss"``. Only the values ``"okay"`` and ``"disabled"`` are currently relevant to Zephyr; use of other values currently results in undefined behavior. A node is considered enabled if its status property is either ``"okay"`` or not defined (i.e. does not exist in the devicetree source). Nodes with status ``"disabled"`` are explicitly disabled. (For backwards compatibility, the value ``"ok"`` is treated the same as ``"okay"``, but this usage is deprecated.) Devicetree nodes which correspond to physical devices must be enabled for the corresponding ``struct device`` in the Zephyr driver model to be allocated and initialized. interrupts Information about interrupts generated by the device, encoded as an array of one or more *interrupt specifiers*. Each interrupt specifier has some number of cells. See section 2.4, *Interrupts and Interrupt Mapping*, in the `Devicetree Specification release v0.3`_ for more details. Zephyr's devicetree bindings language lets you give a name to each cell in an interrupt specifier. .. _Devicetree Specification release v0.3: https://www.devicetree.org/specifications/ .. highlight:: none .. note:: Earlier versions of Zephyr made frequent use of the ``label`` property, which is distinct from the standard :ref:`node label `. Use of the label *property* in new devicetree bindings, as well as use of the :c:macro:`DT_LABEL` macro in new code, are actively discouraged. Label properties continue to persist for historical reasons in some existing bindings and overlays, but should not be used in new bindings or device implementations. .. _dt-writing-property-values: Writing property values *********************** This section describes how to write property values in DTS format. The property types in the table below are described in detail in :ref:`dt-bindings`. Some specifics are skipped in the interest of keeping things simple; if you're curious about details, see the devicetree specification. .. list-table:: :header-rows: 1 :widths: 1 4 4 * - Property type - How to write - Example * - string - Double quoted - ``a-string = "hello, world!";`` * - int - between angle brackets (``<`` and ``>``) - ``an-int = <1>;`` * - boolean - for ``true``, with no value (for ``false``, use ``/delete-property/``) - ``my-true-boolean;`` * - array - between angle brackets (``<`` and ``>``), separated by spaces - ``foo = <0xdeadbeef 1234 0>;`` * - uint8-array - in hexadecimal *without* leading ``0x``, between square brackets (``[`` and ``]``). - ``a-byte-array = [00 01 ab];`` * - string-array - separated by commas - ``a-string-array = "string one", "string two", "string three";`` * - phandle - between angle brackets (``<`` and ``>``) - ``a-phandle = <&mynode>;`` * - phandles - between angle brackets (``<`` and ``>``), separated by spaces - ``some-phandles = <&mynode0 &mynode1 &mynode2>;`` * - phandle-array - between angle brackets (``<`` and ``>``), separated by spaces - ``a-phandle-array = <&mynode0 1 2>, <&mynode1 3 4>;`` Additional notes on the above: - The values in the ``phandle``, ``phandles``, and ``phandle-array`` types are described further in :ref:`dt-phandles` - Boolean properties are true if present. They should not have a value. A boolean property is only false if it is completely missing in the DTS. - The ``foo`` property value above has three *cells* with values 0xdeadbeef, 1234, and 0, in that order. Note that hexadecimal and decimal numbers are allowed and can be intermixed. Since Zephyr transforms DTS to C sources, it is not necessary to specify the endianness of an individual cell here. - 64-bit integers are written as two 32-bit cells in big-endian order. The value 0xaaaa0000bbbb1111 would be written ``<0xaaaa0000 0xbbbb1111>``. - The ``a-byte-array`` property value is the three bytes 0x00, 0x01, and 0xab, in that order. - Parentheses, arithmetic operators, and bitwise operators are allowed. The ``bar`` property contains a single cell with value 64: .. code-block:: devicetree bar = <(2 * (1 << 5))>; Note that the entire expression must be parenthesized. - Property values refer to other nodes in the devicetree by their *phandles*. You can write a phandle using ``&foo``, where ``foo`` is a :ref:`node label `. Here is an example devicetree fragment: .. code-block:: devicetree foo: device@0 { }; device@1 { sibling = <&foo 1 2>; }; The ``sibling`` property of node ``device@1`` contains three cells, in this order: #. The ``device@0`` node's phandle, which is written here as ``&foo`` since the ``device@0`` node has a node label ``foo`` #. The value 1 #. The value 2 In the devicetree, a phandle value is a cell -- which again is just a 32-bit unsigned int. However, the Zephyr devicetree API generally exposes these values as *node identifiers*. Node identifiers are covered in more detail in :ref:`dt-from-c`. - Array and similar type property values can be split into several ``<>`` blocks, like this: .. code-block:: devicetree foo = <1 2>, <3 4>; // Okay for 'type: array' foo = <&label1 &label2>, <&label3 &label4>; // Okay for 'type: phandles' foo = <&label1 1 2>, <&label2 3 4>; // Okay for 'type: phandle-array' This is recommended for readability when possible if the value can be logically grouped into blocks of sub-values. .. _dt-alias-chosen: Aliases and chosen nodes ************************ There are two additional ways beyond :ref:`node labels ` to refer to a particular node without specifying its entire path: by alias, or by chosen node. Here is an example devicetree which uses both: .. code-block:: devicetree /dts-v1/; / { chosen { zephyr,console = &uart0; }; aliases { my-uart = &uart0; }; soc { uart0: serial@12340000 { ... }; }; }; The ``/aliases`` and ``/chosen`` nodes do not refer to an actual hardware device. Their purpose is to specify other nodes in the devicetree. Above, ``my-uart`` is an alias for the node with path ``/soc/serial@12340000``. Using its node label ``uart0``, the same node is set as the value of the chosen ``zephyr,console`` node. Zephyr sample applications sometimes use aliases to allow overriding the particular hardware device used by the application in a generic way. For example, :zephyr:code-sample:`blinky` uses this to abstract the LED to blink via the ``led0`` alias. The ``/chosen`` node's properties are used to configure system- or subsystem-wide values. See :ref:`devicetree-chosen-nodes` for more information.