DOs and DONâTs for designing and writing Devicetree bindings¶
This is a list of common review feedback items focused on binding design. With every rule, there are exceptions and bindings have many gray areas.
For guidelines related to patches, see Submitting Devicetree (DT) binding patches
Overall design¶
DO attempt to make bindings complete even if a driver doesnât support some features. For example, if a device has an interrupt, then include the âinterruptsâ property even if the driver is only polled mode.
DONâT refer to Linux or âdevice driverâ in bindings. Bindings should be based on what the hardware has, not what an OS and driver currently support.
DO use node names matching the class of the device. Many standard names are defined in the DT Spec. If there isnât one, consider adding it.
DO check that the example matches the documentation especially after making review changes.
DONâT create nodes just for the sake of instantiating drivers. Multi-function devices only need child nodes when the child nodes have their own DT resources. A single node can be multiple providers (e.g. clocks and resets).
DONâT treat device node names as a stable ABI, but instead use phandles or compatibles to find sibling devices. Exception: sub-nodes of given device could be treated as ABI, if explicitly documented in the bindings.
DONâT use âsysconâ alone without a specific compatible string. A âsysconâ hardware block should have a compatible string unique enough to infer the register layout of the entire block (at a minimum).
DONâT use âsimple-mfdâ compatible for non-trivial devices, where children depend on some resources from the parent. Similarly, âsimple-busâ should not be used for complex buses and even âregsâ property means device is not a simple bus.
Properties¶
DO make âcompatibleâ properties specific.
DONâT use wildcards or device-family names in compatible strings.
DO use fallback compatibles when devices are the same as or a superset of prior implementations. Fallback compatibles are applicable especially when sharing a programming interface or when able to discover the variants.
DONâT add fake fallback compatibles when software cannot use such to match and bind to a device, and still operate correctly.
DO use the commit message to explain why devices that may appear compatible in a diff (e.g. no differences in property use, same handling by the software) but are not made compatible in the binding, are not compatible.
DO add new compatibles in case there are new features or bugs.
DO use a SoC-specific compatible for all SoC devices, followed by a fallback if appropriate. SoC-specific compatibles are also preferred for the fallbacks.
DONâT use bus suffixes to encode the type of interface device is using. The parent bus node already implies that interface. DONâT add the type of device, if the device cannot be anything else.
DO use a vendor prefix on device-specific property names. Consider if properties could be common among devices of the same class. Check other existing bindings for similar devices.
DONâT redefine common properties. Just reference the definition and define constraints specific to the device.
DONâT add properties to avoid a specific compatible. DONâT add properties if they are implied by (deducible from) the compatible.
DO use common property unit suffixes for properties with scientific units. Recommended suffixes are listed at https://github.com/devicetree-org/dt-schema/blob/main/dtschema/schemas/property-units.yaml
DO define properties in terms of constraints. How many entries? What are possible values? What is the order? All these constraints represent the ABI as well.
DONâT make changes that break the ABI without explicit and detailed rationale for why the changes have to be made and their impact. ABI impact goes beyond the Linux kernel, because it also covers other open-source upstream projects.
Typical cases and caveats¶
Phandle entries, like clocks/dmas/interrupts/resets, should always be explicitly ordered. Include the {clock,dma,interrupt,reset}-names if there is more than one phandle. When used, both of these fields need the same constraints (e.g. list of items).
For names used in {clock,dma,interrupt,reset}-names, do not add any suffix, e.g.: âtxâ instead of âtxirqâ (for interrupt).
Properties without schema types (e.g. without standard suffix or not defined by schema) need the type, even if this is an enum.
If schema includes other schema (e.g. /schemas/i2c/i2c-controller.yaml) use âunevaluatedProperties:falseâ. In other cases, usually use âadditionalProperties:falseâ.
For sub-blocks/components of bigger device (e.g. SoC blocks) use rather device-based compatible (e.g. SoC-based compatible), instead of custom versioning of that component. For example use âvendor,soc1234-i2câ instead of âvendor,i2c-v2â.
âsysconâ is not a generic property. Use vendor and type, e.g. âvendor,power-manager-sysconâ.
Do not add instance index (IDs) properties or custom OF aliases. If the devices have different programming model, they might need different compatibles. If such devices use some other device in a different way, e.g. they program the phy differently, use cell/phandle arguments.
Bindings files should be named like compatible: vendor,device.yaml. In case of multiple compatibles in the binding, use one of the fallbacks or a more generic name, yet still matching compatible style.
Board/SoC .dts Files¶
DO put all MMIO devices under a bus node and not at the top-level.
DO use non-empty ârangesâ to limit the size of child buses/devices. 64-bit platforms donât need all devices to have 64-bit address and size.