Download as pdf or txt
Download as pdf or txt
You are on page 1of 21

8/27/23, 12:41 PM Device Tree Linux - eLinux.

org

Device Tree Linux

Top Device Tree page

Contents
Device Tree Framework Source Code
Linux Man pages
Linux Gotchas
disabled nodes
node name case sensitivity
phandles
phandle source property
phandle access in kernel (by drivers)

Location of .dts source files in Linux kernel source tree


discussion
Linux conventions
Linux Preferences
cpp
interrupts vs interrupts-extended
Linux vs ePAPR Version 1.1
#address-cells and #size-cells
aliases node
chosen node
device_type property
labels
names
status property
"ABI" stability
forward and backward dts compatibility
Bindings review process
Support of different hardware versions in a single driver
Hardware Version in struct of_device_id.data
Function Call Table pointer in struct of_device_id.data
Hardware Description pointer in struct of_device_id.data
FDT built into kernel as data
SPECIAL CASE: devicetree source filename containing dash

defaults and inheritance of #address-cells and #size-cells


/chosen node vs /firmware node
printk format string
boolean property
mixing devicetree and ACPI
Some references from Device_tree_plumbers_2016_etherpad:
CONFIG_ options
Object Lifetime
Devicetree Unittests
https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 1/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

FDT Flattened Device Tree


overlay FDT
EDT Expanded Device Tree
CONFIG_OF_DYNAMIC
CONFIG_OF_DYNAMIC=n
CONFIG_OF_DYNAMIC=y
Changesets

Device Tree Framework Source Code


The device tree framework source code is located in drivers/of/.

Code for manipulating the flattened device tree (FDT) is is scripts/dtc/libfdt.

libfdt is imported from the external project maintained in

https://git.kernel.org/cgit/utils/dtc/dtc.git
git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git

Linux Man pages


Linux man pages are a work in progress.

The current version of the pages can be downloaded or built locally.

Linux Gotchas

disabled nodes
Linux has widespread use of the "status" property to indicate that a node does not exist. This is used to create a generic
.dtsi file that defines all of the potential components of a device which might contain many different functions. When
the device is used in a system, many of the functions might not be routed to connectors or might not be usable due to
needing pins that are multiplexed with other devices that are active. The convention is to set the "status" property of
such functions to "disabled" in the .dtsi file, then the system .dts file that includes the .dtsi will change the "status"
property of functions that should be enabled to "okay".

Some kernel code does not check the node "status" property before trying to configure, probe, or enable it.

Expect efforts to fix the kernel code to respect the "status" property.

node name case sensitivity


Node names are supposed to be case sensitive. The function that checks whether a node name matches a string may be
defined by an architecture or may be the generic implementation. Due to some issues with old Macs the generic Linux
implementation was case insensitive. There is an architecture defined version that is not case sensitive.

Expect this to change so that the generic node name compare function is case sensitive, and only a few select sub-
architectures will not be case sensitive.

The move to a case sensitive compare began in v4.19 with commit f42b0e18f2e5cf34f73ef1b6327b49040b307a33 ("of:
add node name compare helper functions"), which creates of_node_name_eq() and of_node_name_prefix(). Use of
these functions is added in later commits.

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 2/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

Note that dtc has had node name case sensitivity for a long time (or maybe even from the beginning).

phandles

phandle source property


There are three distinct properties that may be the source of a node's phandle:

ibm,phandle
linux,phandle
phandle
Property "linux,phandle" is obsolete. If it exists, its value should be equivalent to the value of property "phandle".

Property "ibm,phandle" may be used in the IBM pSeries dynamic device tree.

phandle access in kernel (by drivers)


The "phandle" and "linux,phandle" properties may exist in device tree source and in the compiled Flattened Device
Tree (FDT), aka "binary blob" or ".dtb". But the Linux kernel views the phandle values as device tree structure
information instead of device tree data and thus does not store them as properties.

This results in a special rule:

DO NOT USE property access functions to access the properties:

ibm,phandle
linux,phandle
phandle

Note: other properties may contain phandle values. It is proper


to use property access functions to read these values. Then the
node containing the phandle value can be found via
of_find_node_by_phandle(handle).

Functions to access phandles are:

of_find_node_by_phandle()

Functions that indirectly access phandles are:

of_for_each_phandle()
of_parse_phandle_with_args()
of_parse_phandle_with_fixed_args()

Location of .dts source files in Linux kernel source tree


Header files (.h files) for devictree bindings are located in include/dt-bindings/

The directory structure for the .dts and .dtsi files varies by architecture. Some architectures place all .dts files at a
single level, others use two or level levels of directories.

As of Linux v4.11-rc1, the layout is:

===== arch/arc/boot/
dts

===== arch/arm/boot/
dts

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 3/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

===== arch/arm64/boot/
dts
dts/actions
dts/realtek
dts/altera
dts/lg
dts/rockchip
dts/broadcom
dts/broadcom/stingray
dts/broadcom/northstar2
dts/broadcom/bcm4908
dts/socionext
dts/xilinx
dts/bitmain
dts/cavium
dts/allwinner
dts/sprd
dts/intel
dts/amlogic
dts/qcom
dts/toshiba
dts/microchip
dts/arm
dts/ti
dts/marvell
dts/nvidia
dts/freescale
dts/amazon
dts/hisilicon
dts/amd
dts/mediatek
dts/apm
dts/synaptics
dts/zte
dts/renesas
dts/exynos

===== arch/c6x/boot/
dts

===== arch/csky/boot/
dts

===== arch/h8300/boot/
dts

===== arch/microblaze/boot/
dts

===== arch/mips/boot/
dts
dts/netlogic
dts/mti
dts/ingenic
dts/img
dts/mscc
dts/xilfpga
dts/ralink
dts/ni
dts/loongson
dts/cavium-octeon
dts/lantiq
dts/brcm
dts/pic32
dts/qca

===== arch/nds32/boot/
dts

===== arch/nios2/boot/
dts

===== arch/openrisc/boot/
dts

===== arch/powerpc/boot/
dts
dts/fsl

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 4/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
===== arch/riscv/boot/
dts
dts/sifive
dts/kendryte

===== arch/sh/boot/
dts

===== arch/xtensa/boot/
dts

discussion
A discussion of the directory layout for .dts files was triggered by the announcement of a script to move the dts files
and update the makefiles [1 (https://lore.kernel.org/linux-arm-kernel/20181204183649.GA5716@bogus/)].

Linux conventions
hex constants are lower case

use "0x" instead of "0X"


use a..f instead of A..F, eg 0xf instead of 0xF

node names

should begin with a character in the range 'a' to 'z', 'A' to 'Z'
unit-address does not have a leading "0x" (the number is assumed to be hexadecimal)
unit-address does not have leading zeros
use dash "-" instead of underscore "_"

label names

should begin with a character in the range 'a' to 'z', 'A' to 'Z'
should be lowercase
use underscore "_" instead of dash "-"

property names

should be lower case


should begin with a character in the range 'a' to 'z'
use dash "-" instead of underscore "_"

Actual usage in Linux 4.11-rc1: arch/arm/boot/dts/*

2512 unique property names


1877 use dash "-"
234 use underscore "_"
100 use both dash "-" and underscore "_"
501 use neither dash "-" nor underscore "_"

property ordering within a node (this describes bindings, but .dts should be consistent with bindings)

compatible
reg
common properties (alphabetical order)
vendor specific properties (alphabetical order)

tuple data

property data that is a tuple is more readable when grouped into tuples

preferred style:

reg = <0x2c000 0x30>, <0x2d000 0x800>, <0x20000 0x1000>


https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 5/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

instead of:

reg = <0x2c000 0x30 0x2d000 0x800 0x20000 0x1000>

maximum depth of device tree

#define FDT_MAX_DEPTH 64

Linux Preferences
Items in this section may be less firm or certain than items in "Linux Conventions".

If you can document or explain why any item should move to "Linux Conventions" please email frowand.list at
gmail.com".

cpp
The Linux kernel build system preprocesses dts files with cpp before passing them to dtc. The dtc compileralso has an
"/include/" directive.

Files that are included via the "/include/" directive can not contain any cpp directives. This is because such files
are not visible to cpp.
Although cpp can do conditional inclusion with features such as "#if" and "#ifdef" this is frowned upon.
Common use of cpp is for "#include" and simple "#defines" for symbolic names.
Bindings related include files are in include/dt-bindings/
More complex macros do exist, but are rare.

Complex example 1

include/dt-bindings/pinctrl/omap.h:
#define OMAP_IOPAD_OFFSET(pa, offset) (((pa) & 0xffff) - (offset))

#define OMAP2420_CORE_IOPAD(pa, val) OMAP_IOPAD_OFFSET((pa), 0x0030) (val)

Complex example 2

include/dt-bindings/input/input.h:

#define MATRIX_KEY(row, col, code) \


((((row) & 0xFF) << 24) | (((col) & 0xFF) << 16) | ((code) & 0xFFFF))

interrupts vs interrupts-extended
Should I use 1) the "interrupts" property in association with the "interrupt-parent" property or 2) the "interrupts-
extended" property?

"Interrupts" is well understood and commonly used. It is ok to use that model.

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 6/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

The main purpose of "interrupts-extended" is to allow one device to have multiple interrupts that are handled by
different controllers, without introducing a (more complex) "interrupt-map" property in the parent.

Linux vs ePAPR Version 1.1

#address-cells and #size-cells

--- ePAPR

2.3.5 #address-cells and #size-cells


'The #address-cells and #size-cells properties are not
inherited from ancestors in the device tree. They shall be
explicitly defined.'

--- Linux

#address-cells defaults to 2
#size-cells defaults to 1
dtc may warn that the default is being used.

aliases node

--- ePAPR

3.3 aliases node


'A client program may use an alias property name to refer to
a full device path as all or part of its string value.'

'A client program, when considering a string as a device path,


shall detect and use the alias.'

--- Linux

of_find_node_by_path() and of_find_node_opts_by_path() check


whether the path begins with "/". If it does not, then the first
element must be a property in the aliases node. That first element
is replaced with the value of the property in the aliases node.

It is not known whether other code (such as drivers) is aware of


the requirement to be aware of aliases.

Linux also has a concept of numeric id derived from the property


names in the aliases node. All trailing digits in the property
name are used to create the "id". The "stem" is the property
name, with the trailing digits removed. For each property in
the aliases node, the tuple of stem, id, and the device tree
node pointer for the path in the property's value is added to
the aliases_lookup list. A driver can use of_alias_get_id()
to retrieve the id for a given stem and device tree node
pointer.

This is commonly used to number devices, although the practice


is controversial.

chosen node

--- ePAPR

3.5 chosen node

The chosen node is not required. If it was required, sections 3.1 and 3.5
would explicitly state such (for example, section 3.6 CPUS Node Properties
states 'A cpus node is required for all device trees.').

The list of required nodes is listed in section 3.1:

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 7/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
3.1 Base Device Node Types

'The sections that follow specify the requirements for the base set of device nodes required in an
ePAPR-compliant device tree.

All device trees shall have a root node and the following nodes shall be present at the root of all
device trees:
• One cpus node
• At least one memory node'

--- Linux

The chosen node is required.

device_type property

--- ePAPR

2.3.11 device_type
'The device_type property was used in IEEE 1275 to describe the device’s FCode
programming model. Because ePAPR does not have FCode, new use of the property is
deprecated, and it should be included only on cpu and memory nodes for compatibility with
IEEE 1275–derived device trees.'

--- Linux

Many Linux bindings have a device_type property. Many of these bindings are not
well documented.

Linux source code accesses this property via for_each_node_by_type(),


of_find_node_by_type(), and by open coding. As of 4.10-rc3, the list
of values searched for by for_each_node_by_type() and of_find_node_by_type()
is:

8042
CBEA-Internal-Interrupt-Controller
PowerPC-External-Interrupt-Presentation
adb
be
cache
cpm
cpu
display
fcu
fdc
interrupt-controller
ipic
isa
memory
memory-controller
mic-tm
mpc8xx-pic
nvram
open-pic
pci
pcie-endpoint
pervasive
pic-router
qe
qeic
serial
smu
soc
spe
tsi-bridge

labels

--- ePAPR

Appendix A Device Tree Source Format (version 1)

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 8/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
Node and property definitions

'Device tree nodes are defined with a node name and unit address with braces marking the start and
end of the node definition. They may be preceded by a label.'

There is no note as to whether a label is allowed on the root node.

--- Linux

dtc does not allow a label on the root node.

names
Node name

--- ePAPR

2.2.1 Node Names


The node name follows the convention:

node-name@unit-address

Characters in node-name may be:


0-9
a-z
A-Z
,._+-

--- Linux

dtc allows characters in node-name to be:


0-9
a-z
A-Z
,._+-
*#? removed Feb 9 2021 by commit 9d2279e7e6ee, not yet in a dtc release

Discouraged:
#?.+*_

Node Name length

--- ePAPR

The node-name component shall be 1 to 31 characters in length.

--- Linux

The maximun length of the node-name component is not enforced.

It has been proposed that the Devicetree Specification be


updated with a maximum length that is consistent with current
Linux kernel usage.

Property name

--- ePAPR

2.2.4.1 Property Names


Characters in the property name may be:
0-9
a-z
A-Z
,._+-?#

--- Linux

dtc allows characters in property name to be:


0-9
a-z

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 9/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
A-Z
,._+-?#
*

Discouraged:
?.+*_
# is only recommended as the first character of a property name

Label names

--- ePAPR

No information on characters in label names.

--- Linux

dtc allows characters in label name to be:


0-9
a-z
A-Z
_
The label name may not begin with 0-9

property name must not match node name

--- ePAPR

No prohibition of a property name matching the name of the node


containing the property.

--- Linux

The validation tools use a YAML format. YAML format does not
allow a property name to match the name of the node containing
the property.

Some Apple OpenFirmware contains this sort of node name / property name
collision.

Linux does not have any node name / property name collisions. Adding
any such collision is not allowed. This was discussed in the email
thread rooted at https://www.spinics.net/lists/devicetree-spec/msg00978.html

NOTE: the dtc compiler allows a property name to match the name of
the node containing the property. There will not be an error when
a devicetree containing a node name / property name collision is compiled.
A patch to dtc to trigger a warning on node name / property name has been
accepted, but is not yet in a released version.

status property

--- ePAPR

2.3.4 status
'Valid values for status are: "okay", "disabled", "fail", "fail-sss".
"Refer to the device binding for details on what disabled means for
a given device.'

3.7.1 General Properties of CPU nodes


Valid values for status are: "okay", "disabled".

--- Linux

A node is enabled if:


status == "okay"
status == "ok" (deprecated)
status property does not exist
Convention for disabling a node:

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 10/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
status == "disabled"
Not all code checks whether a node is disabled. These cases are bugs.

"ABI" stability
Are device tree bindings stable?

Well.... Let me put this open jar full of gasoline on the floor and step away for a little while. Oh, can I loan you a lighter
or a book of matches?

See slides 8 and following from the Grant Likely presentation at the Kernel Summit 2013 discussion: It's Broken!
Fixing the DT binding process (PDF)

Email thread: (https://lkml.org/lkml/2013/7/25/387) DT bindings as ABI [was: Do we have people interested in


device tree janitoring / cleanup?]

"The Device Tree as a Stable ABI: A Fairy Tale?", ELC 2015 by Thomas Petazzoni (PDF)

forward and backward dts compatibility


Current practice is that

new kernels work with old devicetrees


old kernels may or may not work with new devicetrees
This means that if a binding is modified in a non-compatible manner then the kernel implementation must still
recognize the old binding until old devicetrees have been obsoleted and no longer exist.

Bindings review process


devicetree/bindings/submitting-patches.txt (https://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob_pla
in;f=Documentation/devicetree/bindings/submitting-patches.txt;hb=HEAD) was created following discussion at the
2013 Kernel Summit.

Email thread: (https://lists.ozlabs.org/pipermail/devicetree-discuss/2013-July/037769.html) [Ksummit-2013-


discuss] [ATTEND] Handling of devicetree bindings

The slides that Grant Likely presented at the Kernel Summit discussion were in an email (https://lists.linuxfoundatio
n.org/pipermail/ksummit-2013-discuss/2013-October/001907.html) attachment that the mail list stripped. Here are
the slides: It's Broken! Fixing the DT binding process (PDF)

Slides 18 and 19 of [PDF] "Device Tree, the Disaster so Far", ELC Europe 2013 by Mark Rutland.

Support of different hardware versions in a single


driver
Examples of drivers that match more than one compatible string.

This list is not an endorsement of any particular technique. It is instead a (partial) list of some existing code in the
Linux kernel.

The examples are not meant to capture each method entirely; they are instead meant to illustrate the basic concept.

Hardware Version in struct of_device_id.data

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 11/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

The hardware version is used throughout the driver to choose alternate actions.

drivers/iommu/arm-smmu.c:

static const struct of_device_id arm_smmu_of_match[] = {


{ .compatible = "arm,smmu-v1", .data = (void *)ARM_SMMU_V1 },
{ .compatible = "arm,smmu-v2", .data = (void *)ARM_SMMU_V2 },
{ .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 },
{ .compatible = "arm,mmu-401", .data = (void *)ARM_SMMU_V1 },
{ .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 },
{ },
};
MODULE_DEVICE_TABLE(of, arm_smmu_of_match);

static int arm_smmu_device_dt_probe(struct platform_device *pdev)


{
const struct of_device_id *of_id;

of_id = of_match_node(arm_smmu_of_match, dev->of_node);


smmu->version = (enum arm_smmu_arch_version)of_id->data;

...

if (smmu->version > ARM_SMMU_V1) {


...
}
}

static struct platform_driver arm_smmu_driver = {


.driver = {
.name = "arm-smmu",
.of_match_table = of_match_ptr(arm_smmu_of_match),
},
.probe = arm_smmu_device_dt_probe,
.remove = arm_smmu_device_remove,
};

Function Call Table pointer in struct of_device_id.data


The function call table is used throughout the driver to choose alternate actions.

drivers/iio/adc/xilinx-xadc-core.c:

static const struct xadc_ops xadc_zynq_ops = {


.read = xadc_zynq_read_adc_reg,
.write = xadc_zynq_write_adc_reg,
.setup = xadc_zynq_setup,
.get_dclk_rate = xadc_zynq_get_dclk_rate,
.interrupt_handler = xadc_zynq_interrupt_handler,
.threaded_interrupt_handler = xadc_zynq_threaded_interrupt_handler,
.update_alarm = xadc_zynq_update_alarm,
};

static const struct of_device_id xadc_of_match_table[] = {


{ .compatible = "xlnx,zynq-xadc-1.00.a", (void *)&xadc_zynq_ops },
{ .compatible = "xlnx,axi-xadc-1.00.a", (void *)&xadc_axi_ops },
{ },
};
MODULE_DEVICE_TABLE(of, xadc_of_match_table);

static int xadc_probe(struct platform_device *pdev)


{
const struct of_device_id *id;
id = of_match_node(xadc_of_match_table, pdev->dev.of_node);
...
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*xadc));
xadc = iio_priv(indio_dev);
...
xadc->ops = id->data;
...
ret = xadc->ops->setup(pdev, indio_dev, irq);
...
}

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 12/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

static struct platform_driver xadc_driver = {


.probe = xadc_probe,
.remove = xadc_remove,
.driver = {
.name = "xadc",
.of_match_table = xadc_of_match_table,
},
};
module_platform_driver(xadc_driver);

Hardware Description pointer in struct of_device_id.data


The hardware description data is used to configure the device.

This struct pointed to by struct of_device_id.data in this example includes a function call table in addition to the
hardware description fields.

drivers/iio/adc/twl6030-gpadc.c:

static const struct twl6030_gpadc_platform_data twl6030_pdata = {


.iio_channels = twl6030_gpadc_iio_channels,
.nchannels = TWL6030_GPADC_USED_CHANNELS,
.ideal = twl6030_ideal,
.start_conversion = twl6030_start_conversion,
.channel_to_reg = twl6030_channel_to_reg,
.calibrate = twl6030_calibration,
};

static const struct of_device_id of_twl6030_match_tbl[] = {


{
.compatible = "ti,twl6030-gpadc",
.data = &twl6030_pdata,
},
{
.compatible = "ti,twl6032-gpadc",
.data = &twl6032_pdata,
},
{ /* end */ }
};

static int twl6030_gpadc_probe(struct platform_device *pdev)


{
const struct of_device_id *match;
const struct twl6030_gpadc_platform_data *pdata;

match = of_match_device(of_twl6030_match_tbl, dev);


pdata = match->data;
indio_dev = devm_iio_device_alloc(dev, sizeof(*gpadc));
gpadc = iio_priv(indio_dev);
gpadc->pdata = pdata;
platform_set_drvdata(pdev, indio_dev);
...
ret = pdata->calibrate(gpadc);
...
indio_dev->channels = pdata->iio_channels;
indio_dev->num_channels = pdata->nchannels;
}

FDT built into kernel as data


This mechanism is not intended for use by drivers. The use by drivers/gpu/drm/rcar-du/ has been
grandfathered as an existing user before this policy was created.

The Linux kernel build system has a rule to automagically place an FDT in the kernel image as a binary data object. To
invoke the rule, add entries to the makefile of the form XXX.dtb.o to create a data object for devicetree source file
XXX.dts.

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 13/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

obj-y += my_system.dtb.o
obj-$(CONFIG_XXX) += XXX.dtb.o

# enable export of phandle symbols to be used by another overlay


DTC_FLAGS_my_system += -@

PRECIOUS was also required in the makefile until removed by commit 54a702f70589 ("kbuild: mark $(targets) as
.SECONDARY and remove .PRECIOUS markers"), as of Linux kernel 4.17.

.PRECIOUS: \
$(obj)/%.dtb.S \
$(obj)/%.dtb

The data object can be accessed in the kernel through extern declarations of pointers to the beginning and just past the
end of the data:

extern uint8_t __dtb_XXX_begin[];


extern uint8_t __dtb_XXX_end[];

SPECIAL CASE: devicetree source filename containing dash


The name of the devicetree source file is embedded in the pointers to the binary data object in the kernel image. A file
name containing a dash can not be embedded in the pointer names because dash ("-", aka hyphen) is not a valid
character in a pointer name. To resolve this problem, the build system process will convert each dash ("-") in the file
name to an underscore ("_") in the pointer names.

This fixup is scheduled to be added in Linux version 4.16, 4.4.122, 4.9.88, 4.14.27, 4.15.10

defaults and inheritance of #address-cells and #size-


cells
The standards used by Linux do not allow a default value for #address-cells and #size-cells. This also means that a
node should not inherit the values from a predecessor in the tree.

Contrary to the standards, the Linux implementation provides both default values and inheritance.

of_n_addr_cells() will search up through the devicetree until a node with the #address-cells property is found. If none
is found the default value of OF_ROOT_NODE_ADDR_CELLS_DEFAULT is returned.

of_n_size_cells() will search up through the devicetree until a node with the #size-cells property is found. If none is
found the default value of OF_ROOT_NODE_SIZE_CELLS_DEFAULT is returned.

The values of OF_ROOT_NODE_ADDR_CELLS_DEFAULT and OF_ROOT_NODE_SIZE_CELLS_DEFAULT are


normally 1, but can be changed to a difference value by architecture specific defines. Currently (Linux 4.17) overrides
for sparc are 1 for OF_ROOT_NODE_SIZE_CELLS_DEFAULT and 2 for
OF_ROOT_NODE_ADDR_CELLS_DEFAULT.

ePAPR 1.1, section 2.3.5, page 24

The #address-cells and #size-cells properties are not inherited from


ancestors in the device tree. They shall be explicitly defined.

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 14/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

The Linux kernel supports a default for #address-cells and #size-cells to avoid breaking old OF based platforms which
did not set them.

... the default that Linux implements does not match the one defined by
the IEE1275 spec, in order to accomodate certain broken device trees on
certain machines (mostly Apple, I think). The IEEE1275 default is
simply 2, ... These properties were never supposed to be inherited,
but apparently some old firmwares didn't get the memo.

reference:
Date: Thu, 19 Jul 2018 15:37:09 +1000
From: David Gibson <david@gibson.dropbear.id.au>
Subject: Re: [PATCH] libfdt: fdt_address_cells() and fdt_size_cells()
Message-ID: <20180719053709.GB18205@umbus.fritz.box>
List-ID: <devicetree-compiler.vger.kernel.org>

The dtc devicetree compiler will warn if #address-cells or #size-cells is missing. New devicetree source is expected to
properly provide the values for #address-cells and #size-cells.

/chosen node vs /firmware node


The /chosen node is used by firmware to communicate boot time information to the Linux kernel.

The /firmware node is used to describe the interface that the Linux kernel can use for run-time communication with
the firmware. Examples of run-time communication include secure calls, a mailbox, IPC, and hypervisor calls.

An exception to using the /firmware node for run-time communication with the firmware is if the firmware is accessed
through a register based interface, in which case the firmware would be under simple-bus. [1]

The specific bindings for the /firmware nodes on various platforms are documented in the same manner as other
Linux bindings.

[1] Rob Herring; aug 24, 2018; Re: Recognize "/firmware" node usage (https://www.spinics.net/lists/devicetree-spec/msg
00767.html)

printk format string


There are some printk() format specifiers to do complicated formatting of pointers to some structures. For devicetree,
there is a family of specifiers for struct device_node.

Documentation/core-api/printk-formats.rst (https://git.kernel.org/?p=/linux/kernel/git/torvalds/linux.git;a=blob_p
lain;f=Documentation/core-api/printk-formats.rst) contains a description of the format specifiers. Check printk-
formats.rst for the current specification of the format specifiers.

Excerpt from Linux 4.18 printk-formats.rst:

%pOF[fnpPcCF]

For printing kobject based structs (device nodes). Default behaviour is


equivalent to %pOFf.

- f - device node full_name


- n - device node name
- p - device node phandle
- P - device node path spec (name + @unit)

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 15/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
- F - device node flags
- c - major compatible string
- C - full compatible string

The separator when using multiple arguments is ':'

Examples::

%pOF /foo/bar@0 - Node full name


%pOFf /foo/bar@0 - Same as above
%pOFfp /foo/bar@0:10 - Node full name + phandle
%pOFfcF /foo/bar@0:foo,device:--P- - Node full name +
major compatible string +
node flags
D - dynamic
d - detached
P - Populated
B - Populated bus

Notice that multiple arguments can follow '%pOF'. This has the unfortunate side effect that the current
implementation of decoding the format specifier with eat the character following the final argument if that character is
not detected as a boundary between specifiers, such as a space or a '%'. For example, in this snprintf(), the 'T' is meant
to be printed as a literal value, but is instead suppressed:

csize = snprintf(str, len, "of:N%pOFnT%s", dev->of_node,


dev->of_node->type);

For a node with name of 'name' and a null pointer for type,
desired result: of:NnameT<NULL>
actual result: of:Nname<NULL>

A temporary workaround is to use a '%c' specifier:

csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node,


"T",
dev->of_node->type);

boolean property
The devicetree standards do not define a boolean type, but the Linux kernel API includes a function to determine
whether a property is true or false:

/**
* of_property_read_bool - Findfrom a property
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
*
* Search for a property in a device node.
* Returns true if the property exists false otherwise.
*/
static inline bool of_property_read_bool(const struct device_node *np,
const char *propname)
{

The return value of of_property_read_bool() is based on whether the property is present or not. The return value is
not based on the value of the property. Thus the following confusing result:

a_node {
flag="false";
}

The result of of_property_read_bool(np, "flag") is true.

mixing devicetree and ACPI


https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 16/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

Yeah, no

For the non-native English speaker:

(emphatic, colloquial) Used sarcastically to answer "no" to a question where the negative answer should have been
obvious. [1]

[1] https://en.wiktionary.org/wiki/yeah,_no#:~:text=
(emphatic%2C%20colloquial)%20Used%20sarcastically,answer%20should%20have%20been%20obvious.

Some references from Device_tree_plumbers_2016_etherpad:


Question: what about device tree on x86

Answer: there's already support for DT on x86. But, we should not mix DT and ACPI.
A controversial topic is ACPI overlays (putting DT in ACPI or ACPI in DT).

Don't want to have drivers that get part of their info from ACPI and part from DT. That's nuts.
Question: Can you have ACPI and DT at the same time on x86?

Answer: No. Some ARM64 systems have support for both ACPI and DT, but the system selects one to use at
runtime. They are not used at the same time.
You can run the DT unit tests on x86.

CONFIG_ options
Additional CONFIG_ options are unlikely to be accepted into the devicetree subsystem:

The following email fragment is copied from:

https://lore.kernel.org/all/971f874c-a2b3-6fbf-99e4-3c248078e098@gmail.com/

On 2/2/22 6:15 PM, Rob Herring wrote:


> On Wed, Feb 2, 2022 at 4:01 PM Frank Rowand <frowand.list@gmail.com> wrote:
>>
>> On 2/2/22 2:29 PM, Rob Herring wrote:
>>> On Wed, Feb 2, 2022 at 12:38 PM Frank Rowand <frowand.list@gmail.com> wrote:
>>>>

...

>>>> I think a better solution would be to add a config option, something


>>>> like CONFIG_OF_UNITTEST_VERBOSE, that would print the pass messages
>>>> at loglevel KERN_ERR. I'll submit a patch for that and see what the
>>>> review responses are.
>>>
>>> Nak for another config option.
>>
>> Because?
>
> It's another config option... Another build combination to test...
> Users have to rebuild to change behavior...

Thanks for the explanation.

-Frank

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 17/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

For context, Rob and Frank are devicetree maintainers. Frank's final comment is an implicit agreement with Rob's
reasoning.

Object Lifetime

Devicetree Unittests
The devicetree unittests, drivers/of/unittest.c, uses FDT, EDT, and Changesets. In many cases the usage is as
described in the FDT, EDT, and Changesets general descriptions below. However there are exceptions to the general
descriptions due to test requirements.

No attempt will be made here to describe the exceptions; the unittest code must be read to understand the exceptions.

FDT Flattened Device Tree


A source devicetree file, xxx.dts, is compiled into file xxx.dtb, which is in Flattened Device Tree (FDT) format.

An FDT may be provided to the Linux kernel by the bootloader, or may be linked into a special section of the kernel
image.

Once overlay suppport is sufficiently complete and robust a way to load an overlay FDT from userspace might be
implemented. There has been an out of mainline tree implementation for many years.

Early in the kernel boot process, before normal memory allocation is available, the FDT passed by the bootloader is
copied from initial_boot_params into properly aligned memory, allocated by early_init_dt_alloc_memory_arch().
initial_boot_params is changed to point to the newly allocated memory and the memory containing the FDT
passed from the bootloader is not freed.

The FDT will not be freed after use because:

1. The Extended Device Tree (EDT) created from the FDT will contain pointers into the FDT.
2. If a new kernel image is booted via kexec (see drivers/of/kexec.c) then the FDT at initial_boot_params is copied
and modified to be passed to the newly booted kernel

overlay FDT
The API to apply an overlay FDT to the System Devicetree is of_overlay_fdt_apply(). The FDT passed to
of_overlay_fdt_apply() is copied to an overlay subsystem private copy, and thus may be freed by the caller.

The overlay subsystem private copy of the overlay FDT will not be freed after use because:

1. The OF_DETACHED Extended Device Tree (EDT) created from the FDT will contain pointers into the FDT.
2. The System Devicetree that the FDT is applied to will contain pointers into the FDT.
3. Even if the overlay is removed, the devicetree APIs to access the System Devicetree can return pointers into the
FDT and there is no way to guarantee that those pointers are no longer in use

TODO: finish this note...

The above explanation is probably incomplete, misleading, and needs


further elaboration.

When a property is added to a changeset, in anticipation of being


applied into the live devicetree, the data is copied into newly
allocated memory so that the live devicetree will NOT contain a
pointer into the FDT.

add_changeset_property()

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 18/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
...
__of_prop_dup()
new->name = kstrdup()
new->value = kmemdup()
return new
...

EDT Expanded Device Tree


An FDT is expanded into a runtime data structure, the Expanded Device Tree (EDT). The expansion is performed by
__unflatten_device_tree().

__unflatten_device_tree() is in the call path of:

unflatten_and_copy_device_tree() for the FDT provided by the bootloader


of_overlay_fdt_apply() for an overlay FDT
unusual ways by drivers/of/unittest.c for devicetree unittest (these unusual ways are not to be used by normal
non-test kernel code)
The EDT that describes the current system is rooted at of_root. This tree may be referred to by names such as the
"system devicetree", "system device tree", "live tree", "live devicetree", "live device tree", "devicetree", "device tree", in
various documents and code comments.

Some of the APIs to access nodes in the system devicetree will default to starting to scan the tree at of_root if the caller
specifies a starting pointer with the value of NULL.

When a new dynamic EDT is created from an FDT, the EDT is marked as OF_DETACHED. If dynamic content is
added to the system devicetree, new objects are created in the system devicetree; the system devicetree will not
contain pointers into an OF_DETACHED EDT. However, the newly created nodes in the system devicetree may
contain pointers into the FDT that was expanded into the OF_DETACHED EDT.

CONFIG_OF_DYNAMIC
System devicetree internal data structure object lifetime is determined by CONFIG_OF_DYNAMIC.

For normal cases, CONFIG_OF_DYNAMIC is selected by other CONFIG_ options.

This information is valid as of as of Linux v6.2-rc1. The overall


concepts should also apply as far back as v4.15-rc1, where commit b56b5528f5b3
"of: make kobject and bin_attribute support configurable" made device nodes
(struct device_node) as kobjects configurable.

Some additional portions of the concepts should apply as far back as v3.15-rc,
where commit 0829f6d1f69e "of: device_node kobject lifecycle fixes" fixed some
issues with struct device_node objects.

The following CONFIG_ options will select


CONFIG_OF_DYNAMIC:

CONFIG_MPC885ADS
CONFIG_PPC_PSERIES
CONFIG_I2C_DEMUX_PINCTRL
CONFIG_HOTPLUG_PCI_POWERNV
CONFIG_OF_OVERLAY

As a special case, CONFIG_OF_DYNAMIC can be explicitly chosen to


add devicetree unittest coverage for the dynamic code, without also
testing overlays, with the
option:

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 19/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org

"Support for dynamic device trees"

CONFIG_OF_DYNAMIC=n
There is no concept of live devicetree object lifetime.

This is because of_node_get() and of_node_put() are defined as empty functions.

CONFIG_OF_DYNAMIC=y
Live devicetree object lifetime will be one of:

1. exist until kernel shutdown


2. exist as long as the associated dynamic devicetree node reference count is positive
Objects that are created from the boot time Flattened Device Tree (FDT) will exist until kernel shutdown.

Objects that are created via a dynamic device tree API will exist as long as the associated devicetree node
reference count is positive.

How to read the pseudo-code in the following blocks:

Each level of indentation represents the body of the function


call on the previous line.

Arguments when calling a function are enclosed with "()".

If the names of the arguments within the called function differ


from the caller, then the function call line is duplicated, but
the names of the arguments within the called function are
enclosed with "[]".

The pseudo code does not show the entire contents of the functions.

Some functionality is abstracted into comments, pre-fixed with '//'.


The actual functionality may or may not also be shown in the pseudo-code.

The kobject release function node->kobj->ktype is initialized to


of_node_release() when a devicetree node is created:

struct kobj_type of_node_ktype = {


.release = of_node_release,
};

of_node_init[node]
#if defined(CONFIG_OF_KOBJ)
kobject_init(&node->kobj, &of_node_ktype)
kobject_init[kobj, ktype]
kobj->ktype = ktype

When a devicetree node refcount becomes zero, of_node_release() is called.

of_node_put[node]
kobject_put(&node->kobj)
kobject_put[kobj]
kref_put(&kobj->kref, kobject_release)
kref_put[kref, release]
if (refcount_dec_and_test(&kref->refcount))
release(kref)
// release() is kobject_release()
kobj = container_of(kref, struct kobject, kref)
kobject_cleanup(kobj)
t = get_ktype(kobj)
return kobj->ktype
t->release(kobj)
// t->release() is of_node_release()
of_node_release[kobj]

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 20/21
8/27/23, 12:41 PM Device Tree Linux - eLinux.org
// kobject_cleanup() might continue up the tree:
// parent will either be NULL or kobj->parent
// parent should be NULL for devicetree
kobject_put(parent)

The memory associated with any property from an overlay that was added to a
devicetree node that was created from the boot time Flattened Device Tree (FDT)
will never be freed because the refcount of that node should never become zero.
Even if the refcount of the node becomes zero, of_node_put() will return without
freeing anything because the node is not detached, not dynamic, and not an
overlay node.

Continuing the call path from of_node_put() down into of_node_release():

This is the 't->release(kobj)' in kobject_cleanup() when of_node_put() results


in the refcount being decremented to zero:

of_node_release(kobj)
// objects associated with kobj are not freed if
// any of the following is true:
// kobj is not detached
// kobj is not a dynamic node
// kobj if not an overlay node
if (of_node_check_flag(node, OF_OVERLAY))
// sanity check that a changeset free of kobj is in progress
if (!of_node_check_flag(node, OF_OVERLAY_FREE_CSET))
pr_err("ERROR: memory leak ...
// sanity check for unexpected properties in node
if (node->properties)
r_err("ERROR: %s(), unexpected properties in ...
property_list_free(node->properties)
property_list_free[prop_list]
// for each property in prop_list
kfree(prop->name)
kfree(prop->value)
kfree(prop)
property_list_free(node->deadprops)
property_list_free[prop_list]
// for each property in prop_list
kfree(prop->name)
kfree(prop->value)
kfree(prop)
fwnode_links_purge(of_fwnode_handle(node))
kfree(node->full_name)
kfree(node->data)
kfree(node)

Changesets
Each dynamic (run-time) change to the System Devicetree is described by a list of changeset entries (struct
of_changeset_entry). Overlay apply and remove code adds another layer of data structure, the struct
overlay_changeset, to describe how the overlay modifies the System Devicetree.

TODO: describe how changeset related data objects are allocated and freed.

Retrieved from "https://elinux.org/index.php?title=Device_Tree_Linux&oldid=578830"

This page was last edited on 16 August 2023, at 08:10.

Content is available under a Creative Commons Attribution-ShareAlike 3.0 Unported License unless otherwise noted.

https://elinux.org/Device_Tree_Linux#Linux_vs_ePAPR_Version_1.1 21/21

You might also like