dts: bindings: Add lots more documentation
Add some information that would've saved me a lot of time: - Give an overview of how device tree nodes and bindings fit together, with examples. Assume people might be coming at it without knowing anything about device tree. - Explain how 'inherits' works in more detail - Explain what 'parent/child: bus: ...' does more concretely, and what problem it solves - Add more examples to show what things look like in the .dts file - Clean up the language a bit and make things more consistent Also fix some errors, like 'properties: compatible: ...' being wrong (missing 'constraint:' and compatible strings in the wrong place). Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
parent
20ccdab445
commit
850e3626da
2 changed files with 129 additions and 84 deletions
|
@ -71,16 +71,19 @@ The device tree files are compiled using the device tree compiler. The compiler
|
|||
runs the .dts file through the C preprocessor to resolve any macro or #defines
|
||||
utilized in the file. The output of the compile is another dts formatted file.
|
||||
|
||||
After compilation, a python script extracts information from the compiled device
|
||||
tree file using a set of rules specified in YAML binding files. The extracted
|
||||
information is placed in a header file that is used by the rest of the code as
|
||||
the project is compiled.
|
||||
After compilation, a Python script extracts information from the compiled
|
||||
device tree file using rules specified in *bindings* (see the :ref:`bindings`
|
||||
section). The extracted information is placed in a header file that is used by
|
||||
the rest of the code as the project is compiled.
|
||||
|
||||
Temporary fixup files are required for device tree support on most devices.
|
||||
These fixup files by default reside in the board and soc directories and are
|
||||
named ``dts_fixup.h``. These fixup files map the generated include information to
|
||||
the current driver/source usage.
|
||||
|
||||
The Python code that deals with device tree and bindings is in
|
||||
:zephyr_file:`scripts/dts/`.
|
||||
|
||||
.. _dt_vs_kconfig:
|
||||
|
||||
Device Tree vs Kconfig
|
||||
|
@ -356,32 +359,58 @@ Example: Subset of DTS/YAML files for NXP FRDM K64F (Subject to Change)::
|
|||
dts/bindings/pinctrl/nxp,kinetis-pinmux.yaml
|
||||
dts/bindings/serial/nxp,kinetis-uart.yaml
|
||||
|
||||
YAML bindings for device nodes
|
||||
******************************
|
||||
.. _bindings:
|
||||
|
||||
Device tree describes hardware and configuration, but it doesn't tell the
|
||||
system which pieces of information are useful, or how to generate configuration
|
||||
data from the device tree nodes. For this, we rely on YAML binding files to
|
||||
describe the contents or definition of a device tree node and instruct how the
|
||||
extracted information should be formatted.
|
||||
Bindings
|
||||
********
|
||||
|
||||
A YAML description (called "YAML binding") must be provided for every device node
|
||||
that is a source of information for the system. A YAML binding file
|
||||
is associated to each node ``compatible`` property. Information within the YAML
|
||||
file will instruct the python DTS parsing script (located in ``scripts/dts``) how
|
||||
each property of the node is expected to be generated, either the type of the
|
||||
value or the format of its name. Node properties are generated as C-style
|
||||
``#define``'s in include files
|
||||
made available to all Zephyr components.
|
||||
``.dts`` files describe the available hardware devices, but don't tell the
|
||||
system which pieces of information are useful, or what kind of configuration
|
||||
output (``#define``'s) should be generated. *Bindings* provide this
|
||||
information. Bindings are files in YAML format.
|
||||
|
||||
A YAML template file is provided to show the required format. This file is
|
||||
located at::
|
||||
Configuration output is only generated for devices that have bindings.
|
||||
|
||||
dts/bindings/device_node.yaml.template
|
||||
Nodes are mapped to bindings via their ``compatible`` string(s). Take
|
||||
the following node as an example:
|
||||
|
||||
YAML files must end in a .yaml suffix. YAML files are scanned during the
|
||||
information extraction phase and are matched to device tree nodes via the
|
||||
compatible property.
|
||||
.. code-block:: none
|
||||
|
||||
bar-device {
|
||||
compatible = "foo-company,bar-device";
|
||||
...
|
||||
};
|
||||
|
||||
This node would get mapped to a binding with this in it:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
...
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
constraint: "foo-company,bar-device"
|
||||
|
||||
...
|
||||
|
||||
Bindings are stored in :zephyr_file:`dts/bindings/`. The filename usually
|
||||
matches the ``compatible`` string.
|
||||
|
||||
If a node has more than one ``compatible`` string, then the first binding found
|
||||
is used, going from the first string to the last. For example, a node with
|
||||
``compatible = "foo-company,bar-device", "generic-bar-device"`` would get
|
||||
mapped to the binding for ``generic-bar-device`` if there is no binding for
|
||||
``foo-company,bar-device``.
|
||||
|
||||
If a node appears on a bus (e.g. I2C or SPI), then the bus type is also taken
|
||||
into account when mapping nodes to bindings. See the description of ``parent``
|
||||
and ``child`` in the template below.
|
||||
|
||||
Below is a template that shows the format of binding files, stored in
|
||||
:zephyr_file:`dts/bindings/device_node.yaml.template`.
|
||||
|
||||
.. literalinclude:: ../../../dts/bindings/device_node.yaml.template
|
||||
:language: yaml
|
||||
|
||||
|
||||
Include files generation
|
||||
|
|
|
@ -1,88 +1,104 @@
|
|||
title: <short description of the node>
|
||||
title: Short description of the node
|
||||
|
||||
description: >
|
||||
Longer free-form description of the node, with spanning
|
||||
lines
|
||||
Longer free-form description of the node.
|
||||
Can go over multiple lines.
|
||||
|
||||
inherits:
|
||||
- !include other.yaml # or [other1.yaml, other2.yaml]
|
||||
# Files with other bindings that also apply to the node. If an attribute is set
|
||||
# both in an included file and in the file that includes it, then the value
|
||||
# from the including file (the file with the !include) is used.
|
||||
|
||||
< parent | child >:
|
||||
# parent/child is used to document implicit relation between nodes.
|
||||
# This information is required to generate parent related bits in child
|
||||
# attributes.
|
||||
# In case parent has 'bus', slave inherits some information from master.
|
||||
# parent and child should share same bus-type value.
|
||||
bus: <bus-type>
|
||||
|
||||
sub-node:
|
||||
# Used for cases in which a dts node has children, and the children dont
|
||||
# require/specify a 'compatible' property. The sub-node is effective the
|
||||
# binding for the child.
|
||||
# Bindings are often based on other bindings, which are given in 'inherits'.
|
||||
# The resulting binding is the union of the inherited bindings and this binding
|
||||
# (internally, it's a recursive dictionary merge).
|
||||
#
|
||||
# Here's an example for a pwm-leds binding in which the child nodes
|
||||
# would be required to have 'pwms' properties.
|
||||
# If a field appears both in this binding and in a binding it inherits, then
|
||||
# the value in this binding takes precedence. This can be used to change a
|
||||
# 'category: optional' from an inherited binding to a 'category: required' (see
|
||||
# the 'properties' description below).
|
||||
inherits:
|
||||
!include other.yaml # or [other1.yaml, other2.yaml]
|
||||
|
||||
# If the node describes a bus, then the bus type should be given, like below
|
||||
parent:
|
||||
bus: <string describing bus type, e.g. "i2c">
|
||||
|
||||
# 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 'parent: bus: <bus type>'. If it does, then only
|
||||
# bindings with a matching 'child: bus: <bus type>' are considered. This allows
|
||||
# the same type of device to have different bindings depending on what bus it
|
||||
# appears on.
|
||||
child:
|
||||
bus: <string describing bus type, e.g. "i2c">
|
||||
|
||||
# 'sub-node' is used to simplify cases where a node has children that can all
|
||||
# use the same binding. The contents of 'sub-node' becomes the binding for each
|
||||
# child node.
|
||||
#
|
||||
# The example below is for a binding for pwm-leds where the child nodes are
|
||||
# required to have a 'pwms' property.
|
||||
sub-node:
|
||||
properties:
|
||||
pwms:
|
||||
type: compound
|
||||
category: required
|
||||
|
||||
properties:
|
||||
|
||||
# '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:
|
||||
#
|
||||
# <name of the property in the device tree - regexes are supported>:
|
||||
# <property name>:
|
||||
# category: <required | optional>
|
||||
# type: <string | int | boolean | array | uint8-array | string-array | compound>
|
||||
# description: <description of property>
|
||||
# description: <description of the property>
|
||||
#
|
||||
# Note that uint8-array is the name for what devicetree standard calls
|
||||
# bytestring: its value is hexadecimal text with whitespace ignored,
|
||||
# enclosed in square brackets.
|
||||
# 'uint8-array' is our name for what the device tree specification calls
|
||||
# 'bytestring'. Properties of type 'uint8-array' should be set like this:
|
||||
#
|
||||
# The 'type' attribute is currently ignored.
|
||||
# foo = [89 AB CD];
|
||||
#
|
||||
# Each value is a byte in hex.
|
||||
properties:
|
||||
# An entry for 'compatible' must appear, as it's used to map nodes to
|
||||
# bindings
|
||||
compatible:
|
||||
constraint: "foo-company,bar-device"
|
||||
|
||||
# At a minimum, an entry for the 'compatible' property is required, for
|
||||
# matching nodes
|
||||
compatible: <list of string compatible matches>
|
||||
category: required
|
||||
type: string
|
||||
description: compatible of node
|
||||
# Describes a property like 'current-speed = <115200>;'. We pretend that
|
||||
# it's obligatory for the example node and set 'category: required'.
|
||||
current-speed:
|
||||
type: int
|
||||
category: required
|
||||
description: Initial baud rate for bar-device
|
||||
|
||||
# 'reg' describes mmio registers
|
||||
reg:
|
||||
category: required
|
||||
type: array
|
||||
description: mmio register space
|
||||
|
||||
# 'interrupts' specifies the interrupts that the driver may use
|
||||
interrupts:
|
||||
category: required
|
||||
type: array
|
||||
description: required interrupts
|
||||
# Describes an optional property like 'keys = "foo", "bar";'
|
||||
keys:
|
||||
type: string-array
|
||||
category: optional
|
||||
description: Keys for bar-device
|
||||
|
||||
# If the binding describes an interrupt controller, GPIO controller, pinmux
|
||||
# device, or any other device referenced via a phandle plus a specifier (some
|
||||
# additional data besides the phandle), then the cells in the specifier must be
|
||||
# listed in '#cells', like below.
|
||||
|
||||
#
|
||||
# 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 '"#cells": []' in YAML.
|
||||
#
|
||||
# For example, say that some node has 'foo-gpios = <&gpio1 1 2>'. The <1 2>
|
||||
# part of the property value is the specifier, with two cells. The node pointed
|
||||
# at by &gpio1 is expected to have '#gpio-cells = <2>', and its binding should
|
||||
# have two elements in '#cells', corresponding to the 1 and 2 values above.
|
||||
"#cells":
|
||||
- cell0 # name of first cell
|
||||
- cell1 # name of second cell
|
||||
- cell2 # name of third cell
|
||||
- and so on and so forth
|
||||
|
||||
# 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 '"#cells": []' in YAML.
|
||||
#
|
||||
# For example, say that some device tree node has 'foo-gpios = <&gpio1 1 2>'.
|
||||
# The <1 2> part of the property value is the specifier, with two cells in this
|
||||
# example. The node pointed at by &gpio1 is expected to have
|
||||
# '#gpio-cells = <2>', and its binding should have two elements in '#cells',
|
||||
# corresponding to the 1 and 2 values above.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue