Commit 2a792753d6a1fe8f2310928ebd5534e4d87a8030

Authored by mario.six@gdsys.cc
Committed by Stefan Roese
1 parent 1ec2a80b10

dm: Add callback to modify the device tree

Certain boards come in different variations by way of utilizing daughter
boards, for example. These boards might contain additional chips, which
are added to the main board's busses, e.g. I2C.

The device tree support for such boards would either, quite naturally,
employ the overlay mechanism to add such chips to the tree, or would use
one large default device tree, and delete the devices that are actually
not present.

Regardless of approach, even on the U-Boot level, a modification of the
device tree is a prerequisite to have such modular families of boards
supported properly.

Therefore, we add an option to make the U-Boot device tree (the actual
copy later used by the driver model) writeable, and add a callback
method that allows boards to modify the device tree at an early stage,
at which, hopefully, also the application of device tree overlays will
be possible.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Stefan Roese <sr@denx.de>

Showing 4 changed files with 153 additions and 0 deletions Side-by-side Diff

... ... @@ -751,6 +751,13 @@
751 751 return 0;
752 752 }
753 753  
  754 +#ifdef CONFIG_OF_BOARD_FIXUP
  755 +static int fix_fdt(void)
  756 +{
  757 + return board_fix_fdt((void *)gd->fdt_blob);
  758 +}
  759 +#endif
  760 +
754 761 /* ARM calls relocate_code from its crt0.S */
755 762 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && \
756 763 !CONFIG_IS_ENABLED(X86_64)
... ... @@ -1011,6 +1018,9 @@
1011 1018 display_new_sp,
1012 1019 #ifdef CONFIG_SYS_EXTBDINFO
1013 1020 setup_board_extra,
  1021 +#endif
  1022 +#ifdef CONFIG_OF_BOARD_FIXUP
  1023 + fix_fdt,
1014 1024 #endif
1015 1025 INIT_FUNC_WATCHDOG_RESET
1016 1026 reloc_fdt,
doc/driver-model/fdt-fixup.txt
  1 +Pre-relocation device tree manipulation
  2 +=======================================
  3 +
  4 +Contents:
  5 +
  6 +1. Purpose
  7 +2. Implementation
  8 +3. Example
  9 +4. Work to be done
  10 +
  11 +1. Purpose
  12 +----------
  13 +
  14 +In certain markets, it is beneficial for manufacturers of embedded devices to
  15 +offer certain ranges of products, where the functionality of the devices within
  16 +one series either don't differ greatly from another, or can be thought of as
  17 +"extensions" of each other, where one device only differs from another in the
  18 +addition of a small number of features (e.g. an additional output connector).
  19 +
  20 +To realize this in hardware, one method is to have a motherboard, and several
  21 +possible daughter boards that can be attached to this mother board. Different
  22 +daughter boards then either offer the slightly different functionality, or the
  23 +addition of the daughter board to the device realizes the "extension" of
  24 +functionality to the device described previously.
  25 +
  26 +For the software, we obviously want to reuse components for all these
  27 +variations of the device. This means that the software somehow needs to cope
  28 +with the situation that certain ICs may or may not be present on any given
  29 +system, depending on which daughter boards are connected to the motherboard.
  30 +
  31 +In the Linux kernel, one possible solution to this problem is to employ the
  32 +device tree overlay mechanism: There exists one "base" device tree, which
  33 +features only the components guaranteed to exist in all varieties of the
  34 +device. At the start of the kernel, the presence and type of the daughter
  35 +boards is then detected, and the corresponding device tree overlays are applied
  36 +to support the components on the daughter boards.
  37 +
  38 +Note that the components present on every variety of the board must, of course,
  39 +provide a way to find out if and which daughter boards are installed for this
  40 +mechanism to work.
  41 +
  42 +In the U-Boot boot loader, support for device tree overlays has recently been
  43 +integrated, and is used on some boards to alter the device tree that is later
  44 +passed to Linux. But since U-Boot's driver model, which is device tree-based as
  45 +well, is being used in more and more drivers, the same problem of altering the
  46 +device tree starts cropping up in U-Boot itself as well.
  47 +
  48 +An additional problem with the device tree in U-Boot is that it is read-only,
  49 +and the current mechanisms don't allow easy manipulation of the device tree
  50 +after the driver model has been initialized. While migrating to a live device
  51 +tree (at least after the relocation) would greatly simplify the solution of
  52 +this problem, it is a non-negligible task to implement it, an a interim
  53 +solution is needed to address the problem at least in the medium-term.
  54 +
  55 +Hence, we propose a solution to this problem by offering a board-specific
  56 +call-back function, which is passed a writeable pointer to the device tree.
  57 +This function is called before the device tree is relocated, and specifically
  58 +before the main U-Boot's driver model is instantiated, hence the main U-Boot
  59 +"sees" all modifications to the device tree made in this function. Furthermore,
  60 +we have the pre-relocation driver model at our disposal at this stage, which
  61 +means that we can query the hardware for the existence and variety of the
  62 +components easily.
  63 +
  64 +2. Implementation
  65 +-----------------
  66 +
  67 +To take advantage of the pre-relocation device tree manipulation mechanism,
  68 +boards have to implement the function board_fix_fdt, which has the following
  69 +signature:
  70 +
  71 +int board_fix_fdt (void *rw_fdt_blob)
  72 +
  73 +The passed-in void pointer is a writeable pointer to the device tree, which can
  74 +be used to manipulate the device tree using e.g. functions from
  75 +include/fdt_support.h. The return value should either be 0 in case of
  76 +successful execution of the device tree manipulation or something else for a
  77 +failure. Note that returning a non-null value from the function will
  78 +unrecoverably halt the boot process, as with any function from init_sequence_f
  79 +(in common/board_f.c).
  80 +
  81 +Furthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function
  82 +to be called:
  83 +
  84 +Device Tree Control
  85 +-> [*] Board-specific manipulation of Device Tree
  86 +
  87 ++----------------------------------------------------------+
  88 +| WARNING: The actual manipulation of the device tree has |
  89 +| to be the _last_ set of operations in board_fix_fdt! |
  90 +| Since the pre-relocation driver model does not adapt to |
  91 +| changes made to the device tree either, its references |
  92 +| into the device tree will be invalid after manipulating |
  93 +| it, and unpredictable behavior might occur when |
  94 +| functions that rely on them are executed! |
  95 ++----------------------------------------------------------+
  96 +
  97 +Hence, the recommended layout of the board_fixup_fdt call-back function is the
  98 +following:
  99 +
  100 +int board_fix_fdt(void *rw_fdt_blob)
  101 +{
  102 + /* Collect information about device's hardware and store them in e.g.
  103 + local variables */
  104 +
  105 + /* Do device tree manipulation using the values previously collected */
  106 +
  107 + /* Return 0 on successful manipulation and non-zero otherwise */
  108 +}
  109 +
  110 +If this convention is kept, both an "additive" approach, meaning that nodes for
  111 +detected components are added to the device tree, as well as a "subtractive"
  112 +approach, meaning that nodes for absent components are removed from the tree,
  113 +as well as a combination of both approaches should work.
  114 +
  115 +3. Example
  116 +----------
  117 +
  118 +The controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a
  119 +board_fix_fdt function, in which six GPIO expanders (which might be present or
  120 +not, since they are on daughter boards) on a I2C bus are queried for, and
  121 +subsequently deactivated in the device tree if they are not present.
  122 +
  123 +Note that the dm_i2c_simple_probe function does not use the device tree, hence
  124 +it is safe to call it after the tree has already been manipulated.
  125 +
  126 +4. Work to be done
  127 +------------------
  128 +
  129 +* The application of device tree overlay should be possible in board_fixup_fdt,
  130 + but has not been tested at this stage.
  131 +
  132 +2017-01-06, Mario Six <mario.six@gdsys.cc>
... ... @@ -14,6 +14,16 @@
14 14 This feature provides for run-time configuration of U-Boot
15 15 via a flattened device tree.
16 16  
  17 +config OF_BOARD_FIXUP
  18 + bool "Board-specific manipulation of Device Tree"
  19 + help
  20 + In certain circumstances it is necessary to be able to modify
  21 + U-Boot's device tree (e.g. to delete device from it). This option
  22 + make the Device Tree writeable and provides a board-specific
  23 + "board_fix_fdt" callback (called during pre-relocation time), which
  24 + enables the board initialization to modifiy the Device Tree. The
  25 + modified copy is subsequently used by U-Boot after relocation.
  26 +
17 27 config SPL_OF_CONTROL
18 28 bool "Enable run-time configuration via Device Tree in SPL"
19 29 depends on SPL && OF_CONTROL
... ... @@ -497,6 +497,7 @@
497 497  
498 498 /* $(BOARD)/$(BOARD).c */
499 499 int board_early_init_f (void);
  500 +int board_fix_fdt (void *rw_fdt_blob); /* manipulate the U-Boot fdt before its relocation */
500 501 int board_late_init (void);
501 502 int board_postclk_init (void); /* after clocks/timebase, before env/serial */
502 503 int board_early_init_r (void);