1*0db4cd25Smario.six@gdsys.ccPre-relocation device tree manipulation 2*0db4cd25Smario.six@gdsys.cc======================================= 3*0db4cd25Smario.six@gdsys.cc 4*0db4cd25Smario.six@gdsys.ccContents: 5*0db4cd25Smario.six@gdsys.cc 6*0db4cd25Smario.six@gdsys.cc1. Purpose 7*0db4cd25Smario.six@gdsys.cc2. Implementation 8*0db4cd25Smario.six@gdsys.cc3. Example 9*0db4cd25Smario.six@gdsys.cc4. Work to be done 10*0db4cd25Smario.six@gdsys.cc 11*0db4cd25Smario.six@gdsys.cc1. Purpose 12*0db4cd25Smario.six@gdsys.cc---------- 13*0db4cd25Smario.six@gdsys.cc 14*0db4cd25Smario.six@gdsys.ccIn certain markets, it is beneficial for manufacturers of embedded devices to 15*0db4cd25Smario.six@gdsys.ccoffer certain ranges of products, where the functionality of the devices within 16*0db4cd25Smario.six@gdsys.ccone series either don't differ greatly from another, or can be thought of as 17*0db4cd25Smario.six@gdsys.cc"extensions" of each other, where one device only differs from another in the 18*0db4cd25Smario.six@gdsys.ccaddition of a small number of features (e.g. an additional output connector). 19*0db4cd25Smario.six@gdsys.cc 20*0db4cd25Smario.six@gdsys.ccTo realize this in hardware, one method is to have a motherboard, and several 21*0db4cd25Smario.six@gdsys.ccpossible daughter boards that can be attached to this mother board. Different 22*0db4cd25Smario.six@gdsys.ccdaughter boards then either offer the slightly different functionality, or the 23*0db4cd25Smario.six@gdsys.ccaddition of the daughter board to the device realizes the "extension" of 24*0db4cd25Smario.six@gdsys.ccfunctionality to the device described previously. 25*0db4cd25Smario.six@gdsys.cc 26*0db4cd25Smario.six@gdsys.ccFor the software, we obviously want to reuse components for all these 27*0db4cd25Smario.six@gdsys.ccvariations of the device. This means that the software somehow needs to cope 28*0db4cd25Smario.six@gdsys.ccwith the situation that certain ICs may or may not be present on any given 29*0db4cd25Smario.six@gdsys.ccsystem, depending on which daughter boards are connected to the motherboard. 30*0db4cd25Smario.six@gdsys.cc 31*0db4cd25Smario.six@gdsys.ccIn the Linux kernel, one possible solution to this problem is to employ the 32*0db4cd25Smario.six@gdsys.ccdevice tree overlay mechanism: There exists one "base" device tree, which 33*0db4cd25Smario.six@gdsys.ccfeatures only the components guaranteed to exist in all varieties of the 34*0db4cd25Smario.six@gdsys.ccdevice. At the start of the kernel, the presence and type of the daughter 35*0db4cd25Smario.six@gdsys.ccboards is then detected, and the corresponding device tree overlays are applied 36*0db4cd25Smario.six@gdsys.ccto support the components on the daughter boards. 37*0db4cd25Smario.six@gdsys.cc 38*0db4cd25Smario.six@gdsys.ccNote that the components present on every variety of the board must, of course, 39*0db4cd25Smario.six@gdsys.ccprovide a way to find out if and which daughter boards are installed for this 40*0db4cd25Smario.six@gdsys.ccmechanism to work. 41*0db4cd25Smario.six@gdsys.cc 42*0db4cd25Smario.six@gdsys.ccIn the U-Boot boot loader, support for device tree overlays has recently been 43*0db4cd25Smario.six@gdsys.ccintegrated, and is used on some boards to alter the device tree that is later 44*0db4cd25Smario.six@gdsys.ccpassed to Linux. But since U-Boot's driver model, which is device tree-based as 45*0db4cd25Smario.six@gdsys.ccwell, is being used in more and more drivers, the same problem of altering the 46*0db4cd25Smario.six@gdsys.ccdevice tree starts cropping up in U-Boot itself as well. 47*0db4cd25Smario.six@gdsys.cc 48*0db4cd25Smario.six@gdsys.ccAn additional problem with the device tree in U-Boot is that it is read-only, 49*0db4cd25Smario.six@gdsys.ccand the current mechanisms don't allow easy manipulation of the device tree 50*0db4cd25Smario.six@gdsys.ccafter the driver model has been initialized. While migrating to a live device 51*0db4cd25Smario.six@gdsys.cctree (at least after the relocation) would greatly simplify the solution of 52*0db4cd25Smario.six@gdsys.ccthis problem, it is a non-negligible task to implement it, an a interim 53*0db4cd25Smario.six@gdsys.ccsolution is needed to address the problem at least in the medium-term. 54*0db4cd25Smario.six@gdsys.cc 55*0db4cd25Smario.six@gdsys.ccHence, we propose a solution to this problem by offering a board-specific 56*0db4cd25Smario.six@gdsys.cccall-back function, which is passed a writeable pointer to the device tree. 57*0db4cd25Smario.six@gdsys.ccThis function is called before the device tree is relocated, and specifically 58*0db4cd25Smario.six@gdsys.ccbefore the main U-Boot's driver model is instantiated, hence the main U-Boot 59*0db4cd25Smario.six@gdsys.cc"sees" all modifications to the device tree made in this function. Furthermore, 60*0db4cd25Smario.six@gdsys.ccwe have the pre-relocation driver model at our disposal at this stage, which 61*0db4cd25Smario.six@gdsys.ccmeans that we can query the hardware for the existence and variety of the 62*0db4cd25Smario.six@gdsys.cccomponents easily. 63*0db4cd25Smario.six@gdsys.cc 64*0db4cd25Smario.six@gdsys.cc2. Implementation 65*0db4cd25Smario.six@gdsys.cc----------------- 66*0db4cd25Smario.six@gdsys.cc 67*0db4cd25Smario.six@gdsys.ccTo take advantage of the pre-relocation device tree manipulation mechanism, 68*0db4cd25Smario.six@gdsys.ccboards have to implement the function board_fix_fdt, which has the following 69*0db4cd25Smario.six@gdsys.ccsignature: 70*0db4cd25Smario.six@gdsys.cc 71*0db4cd25Smario.six@gdsys.ccint board_fix_fdt (void *rw_fdt_blob) 72*0db4cd25Smario.six@gdsys.cc 73*0db4cd25Smario.six@gdsys.ccThe passed-in void pointer is a writeable pointer to the device tree, which can 74*0db4cd25Smario.six@gdsys.ccbe used to manipulate the device tree using e.g. functions from 75*0db4cd25Smario.six@gdsys.ccinclude/fdt_support.h. The return value should either be 0 in case of 76*0db4cd25Smario.six@gdsys.ccsuccessful execution of the device tree manipulation or something else for a 77*0db4cd25Smario.six@gdsys.ccfailure. Note that returning a non-null value from the function will 78*0db4cd25Smario.six@gdsys.ccunrecoverably halt the boot process, as with any function from init_sequence_f 79*0db4cd25Smario.six@gdsys.cc(in common/board_f.c). 80*0db4cd25Smario.six@gdsys.cc 81*0db4cd25Smario.six@gdsys.ccFurthermore, the Kconfig option OF_BOARD_FIXUP has to be set for the function 82*0db4cd25Smario.six@gdsys.ccto be called: 83*0db4cd25Smario.six@gdsys.cc 84*0db4cd25Smario.six@gdsys.ccDevice Tree Control 85*0db4cd25Smario.six@gdsys.cc-> [*] Board-specific manipulation of Device Tree 86*0db4cd25Smario.six@gdsys.cc 87*0db4cd25Smario.six@gdsys.cc+----------------------------------------------------------+ 88*0db4cd25Smario.six@gdsys.cc| WARNING: The actual manipulation of the device tree has | 89*0db4cd25Smario.six@gdsys.cc| to be the _last_ set of operations in board_fix_fdt! | 90*0db4cd25Smario.six@gdsys.cc| Since the pre-relocation driver model does not adapt to | 91*0db4cd25Smario.six@gdsys.cc| changes made to the device tree either, its references | 92*0db4cd25Smario.six@gdsys.cc| into the device tree will be invalid after manipulating | 93*0db4cd25Smario.six@gdsys.cc| it, and unpredictable behavior might occur when | 94*0db4cd25Smario.six@gdsys.cc| functions that rely on them are executed! | 95*0db4cd25Smario.six@gdsys.cc+----------------------------------------------------------+ 96*0db4cd25Smario.six@gdsys.cc 97*0db4cd25Smario.six@gdsys.ccHence, the recommended layout of the board_fixup_fdt call-back function is the 98*0db4cd25Smario.six@gdsys.ccfollowing: 99*0db4cd25Smario.six@gdsys.cc 100*0db4cd25Smario.six@gdsys.ccint board_fix_fdt(void *rw_fdt_blob) 101*0db4cd25Smario.six@gdsys.cc{ 102*0db4cd25Smario.six@gdsys.cc /* Collect information about device's hardware and store them in e.g. 103*0db4cd25Smario.six@gdsys.cc local variables */ 104*0db4cd25Smario.six@gdsys.cc 105*0db4cd25Smario.six@gdsys.cc /* Do device tree manipulation using the values previously collected */ 106*0db4cd25Smario.six@gdsys.cc 107*0db4cd25Smario.six@gdsys.cc /* Return 0 on successful manipulation and non-zero otherwise */ 108*0db4cd25Smario.six@gdsys.cc} 109*0db4cd25Smario.six@gdsys.cc 110*0db4cd25Smario.six@gdsys.ccIf this convention is kept, both an "additive" approach, meaning that nodes for 111*0db4cd25Smario.six@gdsys.ccdetected components are added to the device tree, as well as a "subtractive" 112*0db4cd25Smario.six@gdsys.ccapproach, meaning that nodes for absent components are removed from the tree, 113*0db4cd25Smario.six@gdsys.ccas well as a combination of both approaches should work. 114*0db4cd25Smario.six@gdsys.cc 115*0db4cd25Smario.six@gdsys.cc3. Example 116*0db4cd25Smario.six@gdsys.cc---------- 117*0db4cd25Smario.six@gdsys.cc 118*0db4cd25Smario.six@gdsys.ccThe controlcenterdc board (board/gdsys/a38x/controlcenterdc.c) features a 119*0db4cd25Smario.six@gdsys.ccboard_fix_fdt function, in which six GPIO expanders (which might be present or 120*0db4cd25Smario.six@gdsys.ccnot, since they are on daughter boards) on a I2C bus are queried for, and 121*0db4cd25Smario.six@gdsys.ccsubsequently deactivated in the device tree if they are not present. 122*0db4cd25Smario.six@gdsys.cc 123*0db4cd25Smario.six@gdsys.ccNote that the dm_i2c_simple_probe function does not use the device tree, hence 124*0db4cd25Smario.six@gdsys.ccit is safe to call it after the tree has already been manipulated. 125*0db4cd25Smario.six@gdsys.cc 126*0db4cd25Smario.six@gdsys.cc4. Work to be done 127*0db4cd25Smario.six@gdsys.cc------------------ 128*0db4cd25Smario.six@gdsys.cc 129*0db4cd25Smario.six@gdsys.cc* The application of device tree overlay should be possible in board_fixup_fdt, 130*0db4cd25Smario.six@gdsys.cc but has not been tested at this stage. 131*0db4cd25Smario.six@gdsys.cc 132*0db4cd25Smario.six@gdsys.cc2017-01-06, Mario Six <mario.six@gdsys.cc> 133