blob: 974c09031edb7a8e2ac53f3030363222b1a58cc8 [file] [log] [blame]
Bin Mengaa66be62019-07-18 00:33:51 -07001.. SPDX-License-Identifier: GPL-2.0+
2.. 2017-01-06, Mario Six <mario.six@gdsys.cc>
3
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +01004Pre-relocation device tree manipulation
5=======================================
6
Bin Mengaa66be62019-07-18 00:33:51 -07007Purpose
8-------
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +01009
10In certain markets, it is beneficial for manufacturers of embedded devices to
11offer certain ranges of products, where the functionality of the devices within
12one series either don't differ greatly from another, or can be thought of as
13"extensions" of each other, where one device only differs from another in the
14addition of a small number of features (e.g. an additional output connector).
15
16To realize this in hardware, one method is to have a motherboard, and several
17possible daughter boards that can be attached to this mother board. Different
18daughter boards then either offer the slightly different functionality, or the
19addition of the daughter board to the device realizes the "extension" of
20functionality to the device described previously.
21
22For the software, we obviously want to reuse components for all these
23variations of the device. This means that the software somehow needs to cope
24with the situation that certain ICs may or may not be present on any given
25system, depending on which daughter boards are connected to the motherboard.
26
27In the Linux kernel, one possible solution to this problem is to employ the
28device tree overlay mechanism: There exists one "base" device tree, which
29features only the components guaranteed to exist in all varieties of the
30device. At the start of the kernel, the presence and type of the daughter
31boards is then detected, and the corresponding device tree overlays are applied
32to support the components on the daughter boards.
33
34Note that the components present on every variety of the board must, of course,
35provide a way to find out if and which daughter boards are installed for this
36mechanism to work.
37
38In the U-Boot boot loader, support for device tree overlays has recently been
39integrated, and is used on some boards to alter the device tree that is later
40passed to Linux. But since U-Boot's driver model, which is device tree-based as
41well, is being used in more and more drivers, the same problem of altering the
42device tree starts cropping up in U-Boot itself as well.
43
44An additional problem with the device tree in U-Boot is that it is read-only,
45and the current mechanisms don't allow easy manipulation of the device tree
46after the driver model has been initialized. While migrating to a live device
47tree (at least after the relocation) would greatly simplify the solution of
48this problem, it is a non-negligible task to implement it, an a interim
49solution is needed to address the problem at least in the medium-term.
50
51Hence, we propose a solution to this problem by offering a board-specific
52call-back function, which is passed a writeable pointer to the device tree.
53This function is called before the device tree is relocated, and specifically
54before the main U-Boot's driver model is instantiated, hence the main U-Boot
55"sees" all modifications to the device tree made in this function. Furthermore,
56we have the pre-relocation driver model at our disposal at this stage, which
57means that we can query the hardware for the existence and variety of the
58components easily.
59
Bin Mengaa66be62019-07-18 00:33:51 -070060Implementation
61--------------
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +010062
63To take advantage of the pre-relocation device tree manipulation mechanism,
64boards have to implement the function board_fix_fdt, which has the following
65signature:
66
Bin Mengaa66be62019-07-18 00:33:51 -070067.. code-block:: c
68
69 int board_fix_fdt (void *rw_fdt_blob)
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +010070
71The passed-in void pointer is a writeable pointer to the device tree, which can
72be used to manipulate the device tree using e.g. functions from
73include/fdt_support.h. The return value should either be 0 in case of
74successful execution of the device tree manipulation or something else for a
75failure. Note that returning a non-null value from the function will
76unrecoverably halt the boot process, as with any function from init_sequence_f
77(in common/board_f.c).
78
79Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function
Bin Mengaa66be62019-07-18 00:33:51 -070080to be called::
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +010081
Bin Mengaa66be62019-07-18 00:33:51 -070082 Device Tree Control
83 -> [*] Board-specific manipulation of Device Tree
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +010084
85+----------------------------------------------------------+
86| WARNING: The actual manipulation of the device tree has |
87| to be the _last_ set of operations in board_fix_fdt! |
88| Since the pre-relocation driver model does not adapt to |
89| changes made to the device tree either, its references |
90| into the device tree will be invalid after manipulating |
91| it, and unpredictable behavior might occur when |
92| functions that rely on them are executed! |
93+----------------------------------------------------------+
94
95Hence, the recommended layout of the board_fixup_fdt call-back function is the
96following:
97
Bin Mengaa66be62019-07-18 00:33:51 -070098.. code-block:: c
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +010099
Bin Mengaa66be62019-07-18 00:33:51 -0700100 int board_fix_fdt(void *rw_fdt_blob)
101 {
102 /*
103 * Collect information about device's hardware and store
104 * them in e.g. local variables
105 */
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +0100106
Bin Mengaa66be62019-07-18 00:33:51 -0700107 /* Do device tree manipulation using the values previously collected */
108
109 /* Return 0 on successful manipulation and non-zero otherwise */
110 }
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +0100111
112If this convention is kept, both an "additive" approach, meaning that nodes for
113detected components are added to the device tree, as well as a "subtractive"
114approach, meaning that nodes for absent components are removed from the tree,
115as well as a combination of both approaches should work.
116
Bin Mengaa66be62019-07-18 00:33:51 -0700117Example
118-------
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +0100119
120The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a
121board_fix_fdt function, in which six GPIO expanders (which might be present or
122not, since they are on daughter boards) on a I2C bus are queried for, and
123subsequently deactivated in the device tree if they are not present.
124
125Note that the dm_i2c_simple_probe function does not use the device tree, hence
126it is safe to call it after the tree has already been manipulated.
127
Bin Mengaa66be62019-07-18 00:33:51 -0700128Work to be done
129---------------
mario.six@gdsys.cc7e9b9d62017-02-22 16:07:22 +0100130
131* The application of device tree overlay should be possible in board_fixup_fdt,
132 but has not been tested at this stage.