Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 1 | .. SPDX-License-Identifier: GPL-2.0+ |
| 2 | .. 2017-01-06, Mario Six <mario.six@gdsys.cc> |
| 3 | |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 4 | Pre-relocation device tree manipulation |
| 5 | ======================================= |
| 6 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 7 | Purpose |
| 8 | ------- |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 9 | |
| 10 | In certain markets, it is beneficial for manufacturers of embedded devices to |
| 11 | offer certain ranges of products, where the functionality of the devices within |
| 12 | one 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 |
| 14 | addition of a small number of features (e.g. an additional output connector). |
| 15 | |
| 16 | To realize this in hardware, one method is to have a motherboard, and several |
| 17 | possible daughter boards that can be attached to this mother board. Different |
| 18 | daughter boards then either offer the slightly different functionality, or the |
| 19 | addition of the daughter board to the device realizes the "extension" of |
| 20 | functionality to the device described previously. |
| 21 | |
| 22 | For the software, we obviously want to reuse components for all these |
| 23 | variations of the device. This means that the software somehow needs to cope |
| 24 | with the situation that certain ICs may or may not be present on any given |
| 25 | system, depending on which daughter boards are connected to the motherboard. |
| 26 | |
| 27 | In the Linux kernel, one possible solution to this problem is to employ the |
| 28 | device tree overlay mechanism: There exists one "base" device tree, which |
| 29 | features only the components guaranteed to exist in all varieties of the |
| 30 | device. At the start of the kernel, the presence and type of the daughter |
| 31 | boards is then detected, and the corresponding device tree overlays are applied |
| 32 | to support the components on the daughter boards. |
| 33 | |
| 34 | Note that the components present on every variety of the board must, of course, |
| 35 | provide a way to find out if and which daughter boards are installed for this |
| 36 | mechanism to work. |
| 37 | |
| 38 | In the U-Boot boot loader, support for device tree overlays has recently been |
| 39 | integrated, and is used on some boards to alter the device tree that is later |
| 40 | passed to Linux. But since U-Boot's driver model, which is device tree-based as |
| 41 | well, is being used in more and more drivers, the same problem of altering the |
| 42 | device tree starts cropping up in U-Boot itself as well. |
| 43 | |
| 44 | An additional problem with the device tree in U-Boot is that it is read-only, |
| 45 | and the current mechanisms don't allow easy manipulation of the device tree |
| 46 | after the driver model has been initialized. While migrating to a live device |
| 47 | tree (at least after the relocation) would greatly simplify the solution of |
| 48 | this problem, it is a non-negligible task to implement it, an a interim |
| 49 | solution is needed to address the problem at least in the medium-term. |
| 50 | |
| 51 | Hence, we propose a solution to this problem by offering a board-specific |
| 52 | call-back function, which is passed a writeable pointer to the device tree. |
| 53 | This function is called before the device tree is relocated, and specifically |
| 54 | before 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, |
| 56 | we have the pre-relocation driver model at our disposal at this stage, which |
| 57 | means that we can query the hardware for the existence and variety of the |
| 58 | components easily. |
| 59 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 60 | Implementation |
| 61 | -------------- |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 62 | |
| 63 | To take advantage of the pre-relocation device tree manipulation mechanism, |
| 64 | boards have to implement the function board_fix_fdt, which has the following |
| 65 | signature: |
| 66 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 67 | .. code-block:: c |
| 68 | |
| 69 | int board_fix_fdt (void *rw_fdt_blob) |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 70 | |
| 71 | The passed-in void pointer is a writeable pointer to the device tree, which can |
| 72 | be used to manipulate the device tree using e.g. functions from |
| 73 | include/fdt_support.h. The return value should either be 0 in case of |
| 74 | successful execution of the device tree manipulation or something else for a |
| 75 | failure. Note that returning a non-null value from the function will |
| 76 | unrecoverably halt the boot process, as with any function from init_sequence_f |
| 77 | (in common/board_f.c). |
| 78 | |
| 79 | Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 80 | to be called:: |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 81 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 82 | Device Tree Control |
| 83 | -> [*] Board-specific manipulation of Device Tree |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 84 | |
| 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 | |
| 95 | Hence, the recommended layout of the board_fixup_fdt call-back function is the |
| 96 | following: |
| 97 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 98 | .. code-block:: c |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 99 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 100 | 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.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 106 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 107 | /* Do device tree manipulation using the values previously collected */ |
| 108 | |
| 109 | /* Return 0 on successful manipulation and non-zero otherwise */ |
| 110 | } |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 111 | |
| 112 | If this convention is kept, both an "additive" approach, meaning that nodes for |
| 113 | detected components are added to the device tree, as well as a "subtractive" |
| 114 | approach, meaning that nodes for absent components are removed from the tree, |
| 115 | as well as a combination of both approaches should work. |
| 116 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 117 | Example |
| 118 | ------- |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 119 | |
| 120 | The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a |
| 121 | board_fix_fdt function, in which six GPIO expanders (which might be present or |
| 122 | not, since they are on daughter boards) on a I2C bus are queried for, and |
| 123 | subsequently deactivated in the device tree if they are not present. |
| 124 | |
| 125 | Note that the dm_i2c_simple_probe function does not use the device tree, hence |
| 126 | it is safe to call it after the tree has already been manipulated. |
| 127 | |
Bin Meng | f156aae | 2019-07-18 00:33:51 -0700 | [diff] [blame^] | 128 | Work to be done |
| 129 | --------------- |
mario.six@gdsys.cc | 2a79275 | 2017-02-22 16:07:22 +0100 | [diff] [blame] | 130 | |
| 131 | * The application of device tree overlay should be possible in board_fixup_fdt, |
| 132 | but has not been tested at this stage. |