diff --git a/doc/guides/dts/api-usage.rst b/doc/guides/dts/api-usage.rst index 5756b086b8..8abb631f0c 100644 --- a/doc/guides/dts/api-usage.rst +++ b/doc/guides/dts/api-usage.rst @@ -174,6 +174,12 @@ number 0 or 1 in the case of booleans. For example: DT_PROP(I2C1, status) /* expands to the string literal "okay" */ +.. note:: + + Don't use DT_NODE_HAS_PROP() for boolean properties. Use DT_PROP() instead + as shown above. It will expand to either 0 or 1 depending on if the property + is present or absent. + Properties with type ``array``, ``uint8-array``, and ``string-array`` work similarly, except ``DT_PROP()`` expands to an array initializer in these cases. Here is an example devicetree fragment: diff --git a/doc/guides/dts/bindings.rst b/doc/guides/dts/bindings.rst index 67f4aa529d..b4f11ab826 100644 --- a/doc/guides/dts/bindings.rst +++ b/doc/guides/dts/bindings.rst @@ -3,56 +3,105 @@ Devicetree bindings ################### -A devicetree on its own is only half the story for describing hardware. The -devicetree format itself is relatively unstructured, and doesn't tell the -:ref:`build system ` which pieces of information in a -particular devicetree are useful to :ref:`device drivers ` or -:ref:`applications `. +A devicetree on its own is only half the story for describing hardware, as it +is a relatively unstructured format. *Devicetree bindings* provide the other +half. -*Devicetree bindings* provide the other half of this information. Zephyr +A devicetree binding declares requirements on the contents of nodes, and +provides semantic information about the contents of valid nodes. Zephyr devicetree bindings are YAML files in a custom format (Zephyr does not use the -dt-schema tools used by the Linux kernel). With one exception in -:ref:`dt-inferred-bindings` the build system uses bindings when generating -code for :ref:`dt-from-c`. +dt-schema tools used by the Linux kernel). + +This page introduces bindings, describes what they do, notes where they are +found, and explains their data format. .. note:: - See the :ref:`devicetree_binding_index` for information on existing - bindings. + See the :ref:`devicetree_binding_index` for reference information on + bindings built in to Zephyr. + +.. contents:: + :local: + :depth: 2 .. _dt-binding-compat: -Mapping nodes to bindings -************************* +Introduction +************ -During the :ref:`build_configuration_phase`, the build system tries to map each -node in the devicetree to a binding file. When this succeeds, the build system -uses the information in the binding file when generating macros for the node. +Devicetree nodes are matched to bindings using their :ref:`compatible +properties `. -Nodes are mapped to binding files by their :ref:`compatible properties -`. Take the following node as an example: +During the :ref:`build_configuration_phase`, the build system tries to match +each node in the devicetree to a binding file. When this succeeds, the build +system uses the information in the binding file both when validating the node's +contents and when generating macros for the node. + +.. _dt-bindings-simple-example: + +A simple example +================ + +Here is an example devicetree node: .. code-block:: DTS + /* Node in a DTS file */ bar-device { compatible = "foo-company,bar-device"; - /* ... */ + num-foos = <3>; }; -The build system will try to map the ``bar-device`` node to a YAML binding with -this ``compatible:`` line: +Here is a minimal binding file which matches the node: .. code-block:: yaml + # A YAML binding matching the node + compatible: "foo-company,bar-device" -Built-in bindings are stored in :zephyr_file:`dts/bindings/`. Binding file -names usually match their ``compatible:`` lines, so the above binding would be -named :file:`foo-company,bar-device.yaml`. + properties: + num-foos: + type: int + required: true + +The build system matches the ``bar-device`` node to its YAML binding because +the node's ``compatible`` property matches the binding's ``compatible:`` line. + +What the build system does with bindings +======================================== + +The build system uses bindings both to validate devicetree nodes and to convert +the devicetree's contents into the generated :ref:`devicetree_unfixed.h +` header file. + +For example, the build system would use the above binding to check that the +required ``num-foos`` property is present in the ``bar-device`` node, and that +its value, ``<3>``, has the correct type. + +The build system will then generate a macro for the ``bar-device`` node's +``num-foos`` property, which will expand to the integer literal ``3``. This +macro lets you get the value of the property in C code using the API which is +discussed later in this guide in :ref:`dt-from-c`. + +For another example, the following node would cause a build error, because it +has no ``num-foos`` property, and this property is marked required in the +binding: + +.. code-block:: DTS + + bad-node { + compatible = "foo-company,bar-device"; + }; + +Other ways nodes are matched to bindings +======================================== If a node has more than one string in its ``compatible`` property, the build system looks for compatible bindings in the listed order and uses the first -match. Take this node as an example: +match. + +Take this node as an example: .. code-block:: DTS @@ -60,26 +109,823 @@ match. Take this node as an example: compatible = "foo-company,baz-device", "generic-baz-device"; }; -The ``baz-device`` node would get mapped to the binding for compatible -``"generic-baz-device"`` if the build system can't find a binding for -``"foo-company,baz-device"``. +The ``baz-device`` node would get matched to a binding with a ``compatible: +"generic-baz-device"`` line if the build system can't find a binding with a +``compatible: "foo-company,baz-device"`` line. -Nodes without compatible properties can be mapped to bindings associated with -their parent nodes. For an example, see the ``pwmleds`` node in the bindings -file format described below. +Nodes without compatible properties can be matched to bindings associated with +their parent nodes. These are called "child bindings". If a node describes +hardware on a bus, like I2C or SPI, then the bus type is also taken into +account when matching nodes to bindings. (The :ref:`dt-bindings-file-syntax` +section below describes how to write child bindings and bus-specific bindings.) -If a node describes hardware on a bus, like I2C or SPI, then the bus type is -also taken into account when mapping nodes to bindings. See the comments near -``on-bus:`` in the bindings syntax for details. +Some special nodes without ``compatible`` properties are matched to +:ref:`dt-inferred-bindings`. For these nodes, the build system generates macros +based on the properties in the final devicetree. + +.. _dt-where-bindings-are-located: + +Where bindings are located +========================== + +Binding file names usually match their ``compatible:`` lines. For example, the +above example binding would be named :file:`foo-company,bar-device.yaml` by +convention. + +The build system looks for bindings in :file:`dts/bindings` +subdirectories of the following places: + +- the zephyr repository +- your :ref:`application source directory ` +- your :ref:`board directory ` +- any directories in the :ref:`DTS_ROOT ` CMake variable +- any :ref:`module ` that defines a ``dts_root`` in its + :ref:`modules_build_settings` + +The build system will consider any YAML file in any of these, including +in any subdirectories, when matching nodes to bindings. + +.. warning:: + + The binding files must be located somewhere inside the :file:`dts/bindings` + subdirectory of the above places. + + For example, if :file:`my-app` is your application directory, then you must + place application-specific bindings inside :file:`my-app/dts/bindings`. So + :file:`my-app/dts/bindings/serial/my-company,my-serial-port.yaml` would be + found, but :file:`my-app/my-company,my-serial-port.yaml` would be ignored. + +.. _dt-bindings-file-syntax: Bindings file syntax ******************** -Below is a template that shows the Zephyr bindings file syntax. It is stored in -:zephyr_file:`dts/binding-template.yaml`. +Zephyr bindings files are YAML files. The top-level value in the file is a +mapping. A :ref:`simple example ` is given above. -.. literalinclude:: ../../../dts/binding-template.yaml - :language: yaml +The top-level keys in the mapping look like this: + +.. code-block:: yaml + + # A high level description of the device the binding applies to: + description: | + This is the Vendomatic company's foo-device. + + Descriptions which span multiple lines (like this) are OK, + and are encouraged for complex bindings. + + See https://yaml-multiline.info/ for formatting help. + + # You can include definitions from other bindings using this syntax: + include: other.yaml + + # Used to match nodes to this binding as discussed above: + compatible: "manufacturer,foo-device" + + properties: + # Requirements for and descriptions of the properties that this + # binding's nodes need to satisfy go here. + + child-binding: + # You can constrain the children of the nodes matching this binding + # using this key. + + # If the node describes bus hardware, like an SPI bus controller + # on an SoC, use 'bus:' to say which one, like this: + bus: spi + + # If the node instead appears as a device on a bus, like an external + # SPI memory chip, use 'on-bus:' to say what type of bus, like this. + # Like 'compatible', this key also influences the way nodes match + # bindings. + on-bus: spi + + foo-cells: + # "Specifier" cell names for the 'foo' domain go here; example 'foo' + # values are 'gpio', 'pwm', and 'dma'. See below for more information. + +The following sections describe these keys in more detail: + +- :ref:`dt-bindings-description` +- :ref:`dt-bindings-compatible` +- :ref:`dt-bindings-properties` +- :ref:`dt-bindings-child` +- :ref:`dt-bindings-bus` +- :ref:`dt-bindings-on-bus` +- :ref:`dt-bindings-cells` +- :ref:`dt-bindings-include` + +The ``include:`` key usually appears early in the binding file, but it is +documented last here because you need to know how the other keys work before +understanding ``include:``. + +.. _dt-bindings-description: + +Description +=========== + +A free-form description of node hardware goes here. You can put links to +datasheets or example nodes or properties as well. + +.. _dt-bindings-compatible: + +Compatible +========== + +This key is used to match nodes to this binding as described above. +It should look like this in a binding file: + +.. code-block:: YAML + + # Note the comma-separated vendor prefix and device name + compatible: "manufacturer,device" + +This devicetree node would match the above binding: + +.. code-block:: DTS + + device { + compatible = "manufacturer,device"; + }; + +Assuming no binding has ``compatible: "manufacturer,device-v2"``, it would also +match this node: + +.. code-block:: DTS + + device-2 { + compatible = "manufacturer,device-v2", "manufacturer,device"; + }; + +Each node's ``compatible`` property is tried in order. The first matching +binding is used. The :ref:`on-bus: ` key can be used to +refine the search. + +If more than one binding for a compatible is found, an error is raised. + +The ``manufacturer`` prefix identifies the device vendor. See +:zephyr_file:`dts/bindings/vendor-prefixes.txt` for a list of accepted vendor +prefixes. The ``device`` part is usually from the datasheet. + +Some bindings apply to a generic class of devices which do not have a specific +vendor. In these cases, there is no vendor prefix. One example is the +:dtcompatible:`gpio-leds` compatible which is commonly used to describe board +LEDs connected to GPIOs. + +If more than one binding for a compatible is found, an error is raised. + +.. _dt-bindings-properties: + +Properties +========== + +The ``properties:`` key describes the properties that nodes which match the +binding can contain. + +For example, a binding for a UART peripheral might look something like this: + +.. code-block:: YAML + + compatible: "manufacturer,serial" + + properties: + reg: + type: array + description: UART peripheral MMIO register space + required: true + current-speed: + type: int + description: current baud rate + required: true + label: + type: string + description: human-readable name + required: false + +The properties in the following node would be validated by the above binding: + +.. code-block:: DTS + + my-serial@deadbeef { + compatible = "manufacturer,serial"; + reg = <0xdeadbeef 0x1000>; + current-speed = <115200>; + label = "UART_0"; + }; + +This is used to check that required properties appear, and to control the +format of output generated for them. + +Except for some special properties, like ``reg``, whose meaning is defined by +the devicetree specification itself, only properties listed in the +``properties:`` key will have generated macros. + +.. _dt-bindings-example-properties: + +Example property definitions +++++++++++++++++++++++++++++ + +Here are some more examples. + +.. code-block:: YAML + + properties: + # Describes a property like 'current-speed = <115200>;'. We pretend that + # it's obligatory for the example node and set 'required: true'. + current-speed: + type: int + required: true + description: Initial baud rate for bar-device + + # Describes an optional property like 'keys = "foo", "bar";' + keys: + type: string-array + required: false + description: Keys for bar-device + + # Describes an optional property like 'maximum-speed = "full-speed";' + # the enum specifies known values that the string property may take + maximum-speed: + type: string + required: false + description: Configures USB controllers to work up to a specific speed. + enum: + - "low-speed" + - "full-speed" + - "high-speed" + - "super-speed" + + # Describes an optional property like 'resolution = <16>;' + # the enum specifies known values that the int property may take + resolution: + type: int + required: false + enum: + - 8 + - 16 + - 24 + - 32 + + # Describes a required property '#address-cells = <1>'; the const + # specifies that the value for the property is expected to be the value 1 + "#address-cells": + type: int + required: true + const: 1 + + int-with-default: + type: int + required: false + default: 123 + description: Value for int register, default is power-up configuration. + + array-with-default: + type: array + required: false + default: [1, 2, 3] # Same as 'array-with-default = <1 2 3>' + + string-with-default: + type: string + required: false + default: "foo" + + string-array-with-default: + type: string-array + required: false + default: ["foo", "bar"] # Same as 'string-array-with-default = "foo", "bar"' + + uint8-array-with-default: + type: uint8-array + required: false + default: [0x12, 0x34] # Same as 'uint8-array-with-default = [12 34]' + +Property entry syntax ++++++++++++++++++++++ + +As shown by the above examples, each property entry in a binding looks like +this: + +.. code-block:: none + + : + required: + type: + deprecated: + default: + description: + enum: + - + - + ... + - + const: + +Required properties ++++++++++++++++++++ + +If a node matches a binding but is missing any property which the binding +defines with ``required: true``, the build fails. + +Property types +++++++++++++++ + +The type of a property constrains its values. +The following types are available. See :ref:`dt-writing-property-values` +for more details about writing values of each type in a DTS file. + +.. list-table:: + :header-rows: 1 + :widths: 1 3 2 + + * - Type + - Description + - Example in DTS + + * - ``string`` + - exactly one string + - ``label = "UART_0";`` + + * - ``int`` + - exactly one 32-bit value (cell) + - ``current-speed = <115200>;`` + + * - ``boolean`` + - flags that don't take a value when true, and are absent if false + - ``hw-flow-control;`` + + * - ``array`` + - zero or more 32-bit values (cells) + - ``offsets = <0x100 0x200 0x300>;`` + + * - ``uint8-array`` + - zero or more bytes, in hex ('bytestring' in the Devicetree specification) + - ``local-mac-address = [de ad be ef 12 34];`` + + * - ``string-array`` + - zero or more strings + - ``dma-names = "tx", "rx";`` + + * - ``phandle`` + - exactly one phandle + - ``interrupt-parent = <&gic>;`` + + * - ``phandles`` + - zero or more phandles + - ``pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>;`` + + * - ``phandle-array`` + - a list of phandles and 32-bit cells (usually specifiers) + - ``dmas = <&dma0 2>, <&dma0 3>;`` + + * - ``path`` + - a path to a node as a phandle path reference or path string + - ``zephyr,bt-c2h-uart = &uart0;`` or + ``foo = "/path/to/some/node";`` + + * - ``compound`` + - a catch-all for more complex types (no macros will be generated) + - ``foo = <&label>, [01 02];`` + +Deprecated properties ++++++++++++++++++++++ + +A property with ``deprecated: true`` indicates to both the user and the tooling +that the property is meant to be phased out. + +The tooling will report a warning if the devicetree includes the property that +is flagged as deprecated. (This warning is upgraded to an error in the +:ref:`twister_script` for upstream pull requests.) + +Default values for properties ++++++++++++++++++++++++++++++ + +The optional ``default:`` setting gives a value that will be used if the +property is missing from the devicetree node. + +For example, with this binding fragment: + +.. code-block:: YAML + + properties: + foo: + type: int + default: 3 + +If property ``foo`` is missing in a matching node, then the output will be as +if ``foo = <3>;`` had appeared in the DTS (except YAML data types are used for +the default value). + +Note that it only makes sense to combine ``default:`` with ``required: false``. +Combining it with ``required: true`` will raise an error. + +There is a risk in using ``default:`` when the value in the binding may be +incorrect for a particular board or hardware configuration. For example, +defaulting the capacity of the connected power cell in a charging IC binding +is likely to be incorrect. For such properties it's better to make the +property ``required: true``, forcing the devicetree maintainer into an explicit +and witting choice. + +Driver developers should use their best judgment as to whether a value can be +safely defaulted. Candidates for default values include: + +- delays that would be different only under unusual conditions + (such as intervening hardware) +- configuration for devices that have a standard initial configuration (such as + a USB audio headset) +- defaults which match the vendor-specified power-on reset value + (as long as they are independent from other properties) + +Power-on reset values may be used for defaults as long as they're independent. +If changing one property would require changing another to create a consistent +configuration, then those properties should be made required. + +In any case where ``default:`` is used, the property documentation should +explain why the value was selected and any conditions that would make it +necessary to provide a different value. (This is mandatory for built-in +bindings.) + +See :ref:`dt-bindings-example-properties` for examples. Putting ``default:`` on +any property type besides those used in the examples will raise an error. + +Enum values ++++++++++++ + +The ``enum:`` line is followed by a list of values the property may contain. If +a property value in DTS is not in the ``enum:`` list in the binding, an error +is raised. See :ref:`dt-bindings-example-properties` for examples. + +Const ++++++ + +This specifies a constant value the property must take. It is mainly useful for +constraining the values of common properties for a particular piece of +hardware. + +.. _dt-bindings-child: + +Child-binding +============= + +``child-binding`` can be used when a node has children that all share the same +properties. Each child gets the contents of ``child-binding`` as its binding, +though an explicit ``compatible = ...`` on the child node takes precedence, if +a binding is found for it. + +Consider a binding for a PWM LED node like this one, where the child nodes are +required to have a ``pwms`` property: + +.. code-block:: DTS + + pwmleds { + compatible = "pwm-leds"; + + red_pwm_led { + pwms = <&pwm3 4 15625000>; + }; + green_pwm_led { + pwms = <&pwm3 0 15625000>; + }; + /* ... */ + }; + +The binding would look like this: + +.. code-block:: YAML + + compatible: "pwm-leds" + + child-binding: + description: LED that uses PWM + + properties: + pwms: + type: phandle-array + required: true + +``child-binding`` also works recursively. For example, this binding: + +.. code-block:: YAML + + compatible: foo + + child-binding: + child-binding: + properties: + my-property: + type: int + required: true + +will apply to the ``grandchild`` node in this DTS: + +.. code-block:: DTS + + parent { + compatible = "foo"; + child { + grandchild { + my-property = <123>; + }; + }; + }; + +.. _dt-bindings-bus: + +Bus +=== + +If the node is a bus controller, use ``bus:`` in the binding to say what type +of bus. For example, a binding for a SPI peripheral on an SoC would look like +this: + +.. code-block:: YAML + + compatible: "manufacturer,spi-peripheral" + bus: spi + # ... + +The presence of this key in the binding informs the build system that the +children of any node matching this binding appear on this type of bus. + +This in turn influences the way ``on-bus:`` is used to match bindings for the +child nodes. + +.. _dt-bindings-on-bus: + +On-bus +====== + +If the node appears as a device on a bus, use ``on-bus:`` in the binding to say +what type of bus. + +For example, a binding for an external SPI memory chip should include this line: + +.. code-block:: YAML + + on-bus: spi + +And a binding for an I2C based temperature sensor should include this line: + +.. code-block:: YAML + + on-bus: i2c + +When looking for a binding for a node, the build system checks if the binding +for the parent node contains ``bus: ``. If it does, then only +bindings with a matching ``on-bus: `` and bindings without an +explicit ``on-bus`` are considered. Bindings with an explicit ``on-bus: `` are searched for first, before bindings without an explicit ``on-bus``. +The search repeats for each item in the node's ``compatible`` property, in +order. + +This feature allows the same device to have different bindings depending on +what bus it appears on. For example, consider a sensor device with compatible +``manufacturer,sensor`` which can be used via either I2C or SPI. + +The sensor node may therefore appear in the devicetree as a child node of +either an SPI or an I2C controller, like this: + +.. code-block:: DTS + + spi-bus@... { + /* ... some compatible with 'bus: spi', etc. ... */ + + sensor@0 { + compatible = "manufacturer,sensor"; + reg = <0>; + /* ... */ + }; + }; + + i2c-bus@... { + /* ... some compatible with 'bus: i2c', etc. ... */ + + sensor@79 { + compatible = "manufacturer,sensor"; + reg = <79>; + /* ... */ + }; + }; + +You can write two separate binding files which match these individual sensor +nodes, even though they have the same compatible: + +.. code-block:: YAML + + # manufacturer,sensor-spi.yaml, which matches sensor@0 on the SPI bus: + compatible: "manufacturer,sensor" + on-bus: spi + + # manufacturer,sensor-i2c.yaml, which matches sensor@79 on the I2C bus: + compatible: "manufacturer,sensor" + properties: + uses-clock-stretching: + type: boolean + required: false + on-bus: i2c + +Only ``sensor@79`` can have a ``use-clock-stretching`` property. The +bus-sensitive logic ignores :file:`manufacturer,sensor-i2c.yaml` when searching +for a binding for ``sensor@0``. + +.. _dt-bindings-cells: + +Specifier cell names (\*-cells) +=============================== + +Specifier cells are usually used with ``phandle-array`` type properties briefly +introduced above. + +To understand the purpose of ``*-cells``, assume that some node has the +following ``pwms`` property with type ``phandle-array``: + +.. code-block:: none + + my-device { + pwms = <&pwm0 1 2>, <&pwm3 4>; + }; + +The tooling strips the final ``s`` from the property name of such properties, +resulting in ``pwm``. Then the value of the ``#pwm-cells`` property is +looked up in each of the PWM controller nodes ``pwm0`` and ``pwm3``, like so: + +.. code-block:: DTS + + pwm0: pwm@... { + compatible = "foo,pwm"; + #pwm-cells = <2>; + }; + + pwm3: pwm@... { + compatible = "bar,pwm"; + #pwm-cells = <1>; + }; + +The ``&pwm0 1 2`` part of the property value has two cells, ``1`` and ``2``, +which matches ``#pwm-cells = <2>;``, so these cells are considered the +*specifier* associated with ``pwm0`` in the phandle array. + +Similarly, the cell ``4`` is the specifier associated with ``pwm3``. + +The number of PWM cells in the specifiers in ``pwms`` must match the +``#pwm-cells`` values, as shown above. If there is a mismatch, an error is +raised. For example, this node would result in an error: + +.. code-block:: DTS + + my-bad-device { + /* wrong: 2 cells given in the specifier, but #pwm-cells is 1 in pwm3. */ + pwms = <&pwm3 5 6>; + }; + +The binding for each PWM controller must also have a ``*-cells`` key, in this +case ``pwm-cells``, giving names to the cells in each specifier: + +.. code-block:: YAML + + # foo,pwm.yaml + compatible: "foo,pwm" + ... + pwm-cells: + - channel + - period + + # bar,pwm.yaml + compatible: "bar,pwm" + ... + pwm-cells: + - period + +A ``*-names`` (e.g. ``pwm-names``) property can appear on the node as well, +giving a name to each entry. + +This allows the cells in the specifiers to be accessed by name, e.g. using APIs +like :c:macro:`DT_PWMS_CHANNEL_BY_NAME`. + +Because other property names are derived from the name of the property by +removing the final ``s``, the property name must end in ``s``. An error is +raised if it doesn't. + +``*-gpios`` properties are special-cased so that e.g. ``foo-gpios`` resolves to +``#gpio-cells`` rather than ``#foo-gpio-cells``. + +If the specifier is empty (e.g. ``#clock-cells = <0>``), then ``*-cells`` can +either be omitted (recommended) or set to an empty array. Note that an empty +array is specified as e.g. ``clock-cells: []`` in YAML. + +All ``phandle-array`` type properties support mapping through ``*-map`` +properties, e.g. ``gpio-map``, as defined by the Devicetree specification. + +.. _dt-bindings-include: + +Include +======= + +Bindings can include other files, which can be used to share common property +definitions between bindings. Use the ``include:`` key for this. Its value is +either a string or a list. + +In the simplest case, you can include another file by giving its name as a +string, like this: + +.. code-block:: YAML + + include: foo.yaml + +If any file named :file:`foo.yaml` is found (see +:ref:`dt-where-bindings-are-located` for the search process), it will be +included into this binding. + +Included files are merged into bindings with a simple recursive dictionary +merge. The build system will check that the resulting merged binding is +well-formed. + +It is an error if a key appears with a different value in a binding and in a +file it includes, with one exception: a binding can have ``required: true`` for +a :ref:`property definition ` for which the included +file has ``required: false``. The ``required: true`` takes precedence, allowing +bindings to strengthen requirements from included files. + +Note that weakening requirements by having ``required: false`` where the +included file has ``required: true`` is an error. This is meant to keep the +organization clean. + +The file :zephyr_file:`base.yaml ` contains +definitions for many common properties. When writing a new binding, it is a +good idea to check if :file:`base.yaml` already defines some of the needed +properties, and include it if it does. + +Note that you can make a property defined in base.yaml obligatory like this, +taking :ref:`reg ` as an example: + +.. code-block:: YAML + + reg: + required: true + +This relies on the dictionary merge to fill in the other keys for ``reg``, like +``type``. + +To include multiple files, you can use a list of strings: + +.. code-block:: YAML + + include: + - foo.yaml + - bar.yaml + +This includes the files :file:`foo.yaml` and :file:`bar.yaml`. (You can +write this list in a single line of YAML as ``include: [foo.yaml, bar.yaml]``.) + +When including multiple files, any overlapping ``required`` keys on properties +in the included files are ORed together. This makes sure that a ``required: +true`` is always respected. + +In some cases, you may want to include some property definitions from a file, +but not all of them. In this case, ``include:`` should be a list, and you can +filter out just the definitions you want by putting a mapping in the list, like +this: + +.. code-block:: YAML + + include: + - name: foo.yaml + property-allowlist: + - i-want-this-one + - and-this-one + - name: bar.yaml + property-blocklist: + - do-not-include-this-one + - or-this-one + +Each map element must have a ``name`` key which is the filename to include, and +may have ``property-allowlist`` and ``property-blocklist`` keys that filter +which properties are included. + +You cannot have a single map element with both ``property-allowlist`` and +``property-blocklist`` keys. A map element with neither ``property-allowlist`` +nor ``property-blocklist`` is valid; no additional filtering is done. + +You can freely intermix strings and mappings in a single ``include:`` list: + +.. code-block:: YAML + + include: + - foo.yaml + - name: bar.yaml + property-blocklist: + - do-not-include-this-one + - or-this-one + +Finally, you can filter from a child binding like this: + +.. code-block:: YAML + + include: + - name: bar.yaml + child-binding: + property-allowlist: + - child-prop-to-allow .. _dt-inferred-bindings: diff --git a/doc/guides/dts/intro.rst b/doc/guides/dts/intro.rst index 1d99ae8905..f668b0b375 100644 --- a/doc/guides/dts/intro.rst +++ b/doc/guides/dts/intro.rst @@ -442,6 +442,18 @@ Additional notes on the above: 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 several ``<>`` + blocks, like this: + + .. code-block:: none + + 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 diff --git a/dts/binding-template.yaml b/dts/binding-template.yaml index 49d022946b..f44a58e096 100644 --- a/dts/binding-template.yaml +++ b/dts/binding-template.yaml @@ -1,437 +1,10 @@ -description: | - Free-form description of the device/node. Can have multiple - lines/paragraphs. - - See https://yaml-multiline.info/ for formatting help. - -# Used to map nodes to bindings -compatible: "manufacturer,device" - -# The 'compatible' above would match this node: +# The contents of this file have been moved to the documentation. # -# device { -# compatible = "manufacturer,device"; -# ... -# }; +# See this page in the HTML documentation: # -# Assuming no binding has 'compatible: "manufacturer,device-v2"', it would also -# match this node: +# User and Developer Guides > +# Devicetree Guide > +# Devicetree bindings # -# device { -# compatible = "manufacturer,device-v2", "manufacturer,device"; -# ... -# }; -# -# Strings in 'compatible' properties on nodes are tried from left to right, and -# the first binding found is used. -# -# If more than one binding for a compatible is found, an error is raised. - -# Bindings can include other files, which can be used to share common -# definitions between bindings. -# -# Included files are merged into bindings with a simple recursive dictionary -# merge. It is up to the binding author to make sure that the final merged -# binding is well-formed, though it is checked by the code as well. -# -# It is an error if a key appears with a different value in a binding and in a -# file it includes, with one exception: A binding can have 'required: true' for -# some property for which the included file has 'required: false' (see the -# description of 'properties' below). The 'required: true' from the binding -# takes precedence, allowing bindings to strengthen requirements from included -# files. -# -# Note that weakening requirements by having 'required: false' where the -# included file has 'required: true' is an error. This is meant to keep the -# organization clean. -# -# The file base.yaml contains definitions for many common properties. When -# writing a new binding, it is a good idea to check if base.yaml already -# defines some of the needed properties, and including it in that case. Note -# that you can make a property defined in base.yaml obligatory like this -# (taking 'reg' as an example): -# -# reg: -# required: true -# -# This relies on the dictionary merge to fill in the other keys for 'reg', like -# 'type'. -# -# When including multiple files, any overlapping 'required' keys on properties -# in the included files are ORed together. This makes sure that a -# 'required: true' is always respected. -# -# When 'include:' is a list, its elements can be either filenames as -# strings, or maps. Each map element must have a 'name' key which is -# the filename to include, and may have 'property-allowlist' and -# 'property-blocklist' keys that filter which properties are included. -# You can freely intermix strings and maps in a single 'include:' list. -# You cannot have a single map element with both 'property-allowlist' and -# 'property-blocklist' keys. A map element with neither 'property-allowlist' -# nor 'property-blocklist' is valid; no additional filtering is done. -include: other.yaml -# To include multiple files: -# -# include: -# - other1.yaml -# - other2.yaml -# -# To filter the included properties: -# -# include: -# - name: other1.yaml -# property-allowlist: -# - i-want-this-one -# - and-this-one -# - other2.yaml -# property-blocklist: -# - do-not-include-this-one -# - or-this-one -# -# You can intermix these types of includes: -# -# include: -# - other1.yaml -# - other2.yaml -# property-blocklist: -# - do-not-include-this-one -# - or-this-one -# -# And you can filter from a child binding like this: -# -# include: -# - name: bar.yaml -# child-binding: -# property-allowlist: -# - child-prop-to-allow - -# If the node describes a bus, then the bus type should be given, like below -bus: - -# If the node appears on a bus, then the bus type should be given, like below. -# -# When looking for a binding for a node, the code checks if the binding for the -# parent node contains 'bus: '. If it does, then only bindings with a -# matching 'on-bus: ' and bindings without an explicit 'on-bus' -# are considered. Bindings with an explicit 'on-bus: ' are looked -# for first, and if none is found bindings without an explicit `on-bus` are -# attempted. These two tests are done for each item in the `compatible` array -# in the order specified. This allows the same type of device to have different -# bindings depending on what bus it appears on. -on-bus: - -# 'properties' describes properties on the node, e.g. -# -# reg = <1 2>; -# current-speed = <115200>; -# label = "foo"; -# -# This is used to check that required properties appear, and to -# control the format of output generated for them. Except for some -# special-cased properties like 'reg', only properties listed here will -# generate output. -# -# A typical property entry looks like this: -# -# : -# deprecated: -# required: -# type: -# description: -# enum: -# - -# - -# ... -# - -# const: -# default: -# -# These types are available: -# -# - 'type: string' is for properties that are assigned a single string, like -# -# ident = "foo"; -# -# - 'type: int' is for properties that are assigned a single 32-bit value, -# like -# -# frequency = <100>; -# -# - 'type: boolean' is for properties used as flags that don't take a value, -# like -# -# hw-flow-control; -# -# The macro generated for the property gets set to 1 if the property exists -# on the node, and to 0 otherwise. When combined with 'required: true', -# this type just forces the flag to appear on the node. The output will -# always be 1 in that case. -# -# Warning: Since a macro is always generated for 'type: boolean' -# properties, don't use #ifdef in tests. Do this instead: -# -# #if DT_SOME_BOOLEAN_PROP == 1 -# -# - 'type: array' is for properties that are assigned zero or more 32-bit -# values, like -# -# pin-config = <1 2 3>; -# -# - 'type: uint8-array' is for properties that are assigned zero or more -# bytes with the [] syntax, like -# -# lookup-table = [89 AB CD EF]; -# -# Each byte is given in hex. -# -# This type is called 'bytestring' in the Devicetree specification. -# -# - 'type: string-array' if for properties that are assigned zero or more -# strings, like -# -# idents = "foo", "bar", "baz"; -# -# - 'type: phandle' is for properties that are assigned a single phandle, -# like -# -# foo = <&label>; -# -# - 'type: phandles' is for properties that are assigned zero or more -# phandles, like -# -# foo = <&label1 &label2 ...>; -# -# - 'type: phandle-array' is for properties that take a list of phandles and -# (possibly) 32-bit numbers, like -# -# pwms = <&ctrl-1 1 2 &ctrl-2 3 4>; -# -# This type requires that the property works in the standard way that -# devicetree properties like pwms, clocks, *-gpios, and io-channels work. -# Taking 'pwms' as an example, the final -s is stripped from the property -# name, and #pwm-cells is looked up in the node for the controller -# (&ctrl-1/&ctrl-2) to determine the number of data values after the -# phandle. The binding for each controller must also have a *-cells key -# (e.g. pwm-cells), giving names to data values. See below for an -# explanation of *-cells. -# -# A *-names (e.g. pwm-names) property can appear on the node as well, -# giving a name to each entry (the 'pwms' example above has two entries, -# <&ctrl-1 1 2> and <&ctrl-2 3 4>). -# -# Because other property names are derived from the name of the property by -# removing the final -s, the property name must end in -s. An error is -# raised if it doesn't. -# -# *-gpios properties are special-cased so that e.g. foo-gpios resolves to -# #gpio-cells rather than #foo-gpio-cells. -# -# All phandle-array properties support mapping through *-map properties, -# e.g. gpio-map. See the devicetree spec. -# -# - 'type: path' is for properties that are assigned a path. Usually, this -# would be done with a path reference: -# -# foo = &label; -# -# Plain strings are accepted too, and are verified to be a path to an -# existing node: -# -# foo = "/path/to/some/node"; -# -# - 'type: compound' is a catch-all for more complex types, e.g. -# -# foo = <&label>, [01 02]; -# -# 'type: array' and the other array types also allow splitting the value into -# several <> blocks, e.g. like this: -# -# 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' -# etc. -# -# A property with 'deprecated: True' indicates to both the user and the tooling -# that the property is meant to be phased out. The tooling will report a -# warning if the devicetree includes the property that is flagged as deprecated. -# There will be no other impact to having 'deprecated: True' set on the property. -# -# The optional 'default:' setting gives a value that will be used if the -# property is missing from the device tree node. If 'default: ' is -# given for a property and is missing, then the output will be as -# if ' = ' had appeared (except YAML data types are used for the -# default value). -# -# Note that it only makes sense to combine 'default:' with 'required: false'. -# Combining it with 'required: true' will raise an error. -# -# There is a risk in using 'default:' when the value in the binding may be -# incorrect for a particular board or hardware configuration. For example, -# defaulting the capacity of the connected power cell in a charging IC binding -# is likely to be incorrect. For such properties it's better to make the -# property 'required: true', forcing the devicetree maintainer into an explicit -# and witting choice. -# -# Driver developers should use their best judgment as to whether a value can be -# safely defaulted. Candidates for default values include delays that would -# different only under unusual conditions (such as intervening hardware), or -# configuration for devices that have a standard initial configuration (such as -# a USB audio headset). -# -# Properties may also be defaulted to the vendor-specified power-up default as -# long as they're independent. If changing one property would require changing -# another to create a consistent configuration then those properties should be -# made required. -# -# In any case where 'default:' is used the property documentation should -# explain why the value was selected and any conditions that would make it -# necessary to provide a different value. -# -# See below for examples of 'default:'. Putting 'default:' on any property type -# besides those used in the examples will raise an error. -properties: - # Describes a property like 'current-speed = <115200>;'. We pretend that - # it's obligatory for the example node and set 'required: true'. - current-speed: - type: int - required: true - description: Initial baud rate for bar-device - - # Describes an optional property like 'keys = "foo", "bar";' - keys: - type: string-array - required: false - description: Keys for bar-device - - # Describes an optional property like 'maximum-speed = "full-speed"; - # the enum specifies known values that the string property may take - maximum-speed: - type: string - required: false - description: Configures USB controllers to work up to a specific speed. - enum: - - "low-speed" - - "full-speed" - - "high-speed" - - "super-speed" - - # Describes a required property '#address-cells = <1>'; the const - # specifies that the value for the property is expected to be the value 1 - "#address-cells": - type: int - required: true - const: 1 - - int-with-default: - type: int - required: false - default: 123 - description: Value for int register, default is power-up configuration. - - array-with-default: - type: array - required: false - default: [1, 2, 3] # Same as 'array-with-default = <1 2 3>' - - string-with-default: - type: string - required: false - default: "foo" - - string-array-with-default: - type: string-array - required: false - default: ["foo", "bar"] # Same as 'string-array-with-default = "foo", "bar"' - - uint8-array-with-default: - type: uint8-array - required: false - default: [0x12, 0x34] # Same as 'uint8-array-with-default = [12 34]' - -# 'child-binding' can be used when a node has children that all share the same -# properties. Each child gets the contents of 'child-binding' as its binding -# (though an explicit 'compatible = ...' on the child node takes precedence, if -# a binding is found for it). -# -# The example below is for a binding for PWM LEDs, where the child nodes are -# required to have a 'pwms' property. It corresponds to this .dts structure -# (assuming the binding has 'compatible: "pwm-leds"'): -# -# pwmleds { -# compatible = "pwm-leds"; -# -# red_pwm_led { -# pwms = <&pwm3 4 15625000>; -# }; -# green_pwm_led { -# pwms = <&pwm3 0 15625000>; -# }; -# ... -# }; -child-binding: - description: LED that uses PWM - - properties: - pwms: - type: phandle-array - required: true - -# 'child-binding' also works recursively. For example, the binding below would -# provide a binding for the 'grandchild' node in this .dts (assuming -# 'compatible: "foo"'): -# -# parent { -# compatible = "foo"; -# child { -# grandchild { -# prop = <123>; -# }; -# }; -# } -child-binding: - description: ... - - ... - - child-binding: - description: ... - - properties: - prop: - type: int - required: true - -# If the binding describes an interrupt controller, GPIO controller, pinmux -# device, or any other node referenced by other nodes via 'phandle-array' -# properties, then *-cells should be given. -# -# To understand the purpose of *-cells, assume that some node has -# -# pwms = <&pwm-ctrl 1 2>; -# -# , where &pwm-ctrl refers to a node whose binding is this file. -# -# The <1 2> part of the property value is called a *specifier* (this -# terminology is from the devicetree specification), and contains additional -# data associated with the GPIO. Here, the specifier has two cells, and the -# node pointed at by &gpio-ctrl is expected to have '#pwm-cells = <2>'. -# -# *-cells gives a name to each cell in the specifier. These names are used when -# generating identifiers. -# -# In this example, assume that 1 refers to a pin and that 2 is a flag value. -# This gives a *-cells assignment like below. -pwm-cells: - - channel # name of first cell - - period # name of second cell - -# If the specifier is empty (e.g. '#clock-cells = <0>'), then *-cells can -# either be omitted (recommended) or set to an empty array. Note that an empty -# array is specified as e.g. 'clock-cells: []' in YAML. - -# As a special case, all *-gpio properties map to the key 'gpio-cells', -# regardless of prefix -gpio-cells: - - pin - - flags +# For the latest version: +# https://docs.zephyrproject.org/latest/guides/dts/bindings.html