1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# Copyright (c) 2011 The Chromium OS Authors. 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0+ 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunDevice Tree Control in U-Boot 8*4882a593Smuzhiyun============================= 9*4882a593Smuzhiyun 10*4882a593SmuzhiyunThis feature provides for run-time configuration of U-Boot via a flat 11*4882a593Smuzhiyundevice tree (fdt). U-Boot configuration has traditionally been done 12*4882a593Smuzhiyunusing CONFIG options in the board config file. This feature aims to 13*4882a593Smuzhiyunmake it possible for a single U-Boot binary to support multiple boards, 14*4882a593Smuzhiyunwith the exact configuration of each board controlled by a flat device 15*4882a593Smuzhiyuntree (fdt). This is the approach recently taken by the ARM Linux kernel 16*4882a593Smuzhiyunand has been used by PowerPC for some time. 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunThe fdt is a convenient vehicle for implementing run-time configuration 19*4882a593Smuzhiyunfor three reasons. Firstly it is easy to use, being a simple text file. 20*4882a593SmuzhiyunIt is extensible since it consists of nodes and properties in a nice 21*4882a593Smuzhiyunhierarchical format. 22*4882a593Smuzhiyun 23*4882a593SmuzhiyunFinally, there is already excellent infrastructure for the fdt: a 24*4882a593Smuzhiyuncompiler checks the text file and converts it to a compact binary 25*4882a593Smuzhiyunformat, and a library is already available in U-Boot (libfdt) for 26*4882a593Smuzhiyunhandling this format. 27*4882a593Smuzhiyun 28*4882a593SmuzhiyunThe dts directory contains a Makefile for building the device tree blob 29*4882a593Smuzhiyunand embedding it in your U-Boot image. This is useful since it allows 30*4882a593SmuzhiyunU-Boot to configure itself according to what it finds there. If you have 31*4882a593Smuzhiyuna number of similar boards with different peripherals, you can describe 32*4882a593Smuzhiyunthe features of each board in the device tree file, and have a single 33*4882a593Smuzhiyungeneric source base. 34*4882a593Smuzhiyun 35*4882a593SmuzhiyunTo enable this feature, add CONFIG_OF_CONTROL to your board config file. 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun 38*4882a593SmuzhiyunWhat is a Flat Device Tree? 39*4882a593Smuzhiyun--------------------------- 40*4882a593Smuzhiyun 41*4882a593SmuzhiyunAn fdt can be specified in source format as a text file. To read about 42*4882a593Smuzhiyunthe fdt syntax, take a look at the specification here: 43*4882a593Smuzhiyun 44*4882a593Smuzhiyunhttps://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf 45*4882a593Smuzhiyun 46*4882a593SmuzhiyunYou also might find this section of the Linux kernel documentation 47*4882a593Smuzhiyunuseful: (access this in the Linux kernel source code) 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun Documentation/devicetree/booting-without-of.txt 50*4882a593Smuzhiyun 51*4882a593SmuzhiyunThere is also a mailing list: 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun http://lists.ozlabs.org/listinfo/devicetree-discuss 54*4882a593Smuzhiyun 55*4882a593SmuzhiyunIn case you are wondering, OF stands for Open Firmware. 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun 58*4882a593SmuzhiyunTools 59*4882a593Smuzhiyun----- 60*4882a593Smuzhiyun 61*4882a593SmuzhiyunTo use this feature you will need to get the device tree compiler here: 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun git://git.kernel.org/pub/scm/utils/dtc/dtc.git 64*4882a593Smuzhiyun 65*4882a593SmuzhiyunFor example: 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun $ git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git 68*4882a593Smuzhiyun $ cd dtc 69*4882a593Smuzhiyun $ make 70*4882a593Smuzhiyun $ sudo make install 71*4882a593Smuzhiyun 72*4882a593SmuzhiyunThen run the compiler (your version will vary): 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun $ dtc -v 75*4882a593Smuzhiyun Version: DTC 1.2.0-g2cb4b51f 76*4882a593Smuzhiyun $ make tests 77*4882a593Smuzhiyun $ cd tests 78*4882a593Smuzhiyun $ ./run_tests.sh 79*4882a593Smuzhiyun ********** TEST SUMMARY 80*4882a593Smuzhiyun * Total testcases: 1371 81*4882a593Smuzhiyun * PASS: 1371 82*4882a593Smuzhiyun * FAIL: 0 83*4882a593Smuzhiyun * Bad configuration: 0 84*4882a593Smuzhiyun * Strange test result: 0 85*4882a593Smuzhiyun 86*4882a593SmuzhiyunYou will also find a useful fdtdump utility for decoding a binary file, as 87*4882a593Smuzhiyunwell as fdtget/fdtput for reading and writing properties in a binary file. 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun 90*4882a593SmuzhiyunWhere do I get an fdt file for my board? 91*4882a593Smuzhiyun---------------------------------------- 92*4882a593Smuzhiyun 93*4882a593SmuzhiyunYou may find that the Linux kernel has a suitable file. Look in the 94*4882a593Smuzhiyunkernel source in arch/<arch>/boot/dts. 95*4882a593Smuzhiyun 96*4882a593SmuzhiyunIf not you might find other boards with suitable files that you can 97*4882a593Smuzhiyunmodify to your needs. Look in the board directories for files with a 98*4882a593Smuzhiyun.dts extension. 99*4882a593Smuzhiyun 100*4882a593SmuzhiyunFailing that, you could write one from scratch yourself! 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun 103*4882a593SmuzhiyunConfiguration 104*4882a593Smuzhiyun------------- 105*4882a593Smuzhiyun 106*4882a593SmuzhiyunUse: 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun#define CONFIG_DEFAULT_DEVICE_TREE "<name>" 109*4882a593Smuzhiyun 110*4882a593Smuzhiyunto set the filename of the device tree source. Then put your device tree 111*4882a593Smuzhiyunfile into 112*4882a593Smuzhiyun 113*4882a593Smuzhiyun board/<vendor>/dts/<name>.dts 114*4882a593Smuzhiyun 115*4882a593SmuzhiyunThis should include your CPU or SOC's device tree file, placed in 116*4882a593Smuzhiyunarch/<arch>/dts, and then make any adjustments required. 117*4882a593Smuzhiyun 118*4882a593SmuzhiyunIf CONFIG_OF_EMBED is defined, then it will be picked up and built into 119*4882a593Smuzhiyunthe U-Boot image (including u-boot.bin). This is suitable for debugging 120*4882a593Smuzhiyunand development only and is not recommended for production devices. 121*4882a593Smuzhiyun 122*4882a593SmuzhiyunIf CONFIG_OF_SEPARATE is defined, then it will be built and placed in 123*4882a593Smuzhiyuna u-boot.dtb file alongside u-boot.bin. A common approach is then to 124*4882a593Smuzhiyunjoin the two: 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun cat u-boot.bin u-boot.dtb >image.bin 127*4882a593Smuzhiyun 128*4882a593Smuzhiyunand then flash image.bin onto your board. Note that U-Boot creates 129*4882a593Smuzhiyunu-boot-dtb.bin which does the above step for you also. If you are using 130*4882a593SmuzhiyunCONFIG_SPL_FRAMEWORK, then u-boot.img will be built to include the device 131*4882a593Smuzhiyuntree binary. 132*4882a593Smuzhiyun 133*4882a593SmuzhiyunIf CONFIG_OF_BOARD is defined, a board-specific routine will provide the 134*4882a593Smuzhiyundevice tree at runtime, for example if an earlier bootloader stage creates 135*4882a593Smuzhiyunit and passes it to U-Boot. 136*4882a593Smuzhiyun 137*4882a593SmuzhiyunIf CONFIG_OF_HOSTFILE is defined, then it will be read from a file on 138*4882a593Smuzhiyunstartup. This is only useful for sandbox. Use the -d flag to U-Boot to 139*4882a593Smuzhiyunspecify the file to read. 140*4882a593Smuzhiyun 141*4882a593SmuzhiyunYou cannot use more than one of these options at the same time. 142*4882a593Smuzhiyun 143*4882a593SmuzhiyunTo use a device tree file that you have compiled yourself, pass 144*4882a593SmuzhiyunEXT_DTB=<filename> to 'make', as in: 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun make EXT_DTB=boot/am335x-boneblack-pubkey.dtb 147*4882a593Smuzhiyun 148*4882a593SmuzhiyunThen U-Boot will copy that file to u-boot.dtb, put it in the .img file 149*4882a593Smuzhiyunif used, and u-boot-dtb.bin. 150*4882a593Smuzhiyun 151*4882a593SmuzhiyunIf you wish to put the fdt at a different address in memory, you can 152*4882a593Smuzhiyundefine the "fdtcontroladdr" environment variable. This is the hex 153*4882a593Smuzhiyunaddress of the fdt binary blob, and will override either of the options. 154*4882a593SmuzhiyunBe aware that this environment variable is checked prior to relocation, 155*4882a593Smuzhiyunwhen only the compiled-in environment is available. Therefore it is not 156*4882a593Smuzhiyunpossible to define this variable in the saved SPI/NAND flash 157*4882a593Smuzhiyunenvironment, for example (it will be ignored). After relocation, this 158*4882a593Smuzhiyunvariable will be set to the address of the newly relocated fdt blob. 159*4882a593SmuzhiyunIt is read-only and cannot be changed. It can optionally be used to 160*4882a593Smuzhiyuncontrol the boot process of Linux with bootm/bootz commands. 161*4882a593Smuzhiyun 162*4882a593SmuzhiyunTo use this, put something like this in your board header file: 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun#define CONFIG_EXTRA_ENV_SETTINGS "fdtcontroladdr=10000\0" 165*4882a593Smuzhiyun 166*4882a593SmuzhiyunBuild: 167*4882a593Smuzhiyun 168*4882a593SmuzhiyunAfter board configuration is done, fdt supported u-boot can be build in two ways: 169*4882a593Smuzhiyun1) build the default dts which is defined from CONFIG_DEFAULT_DEVICE_TREE 170*4882a593Smuzhiyun $ make 171*4882a593Smuzhiyun2) build the user specified dts file 172*4882a593Smuzhiyun $ make DEVICE_TREE=<dts-file-name> 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun 175*4882a593SmuzhiyunLimitations 176*4882a593Smuzhiyun----------- 177*4882a593Smuzhiyun 178*4882a593SmuzhiyunU-Boot is designed to build with a single architecture type and CPU 179*4882a593Smuzhiyuntype. So for example it is not possible to build a single ARM binary 180*4882a593Smuzhiyunwhich runs on your AT91 and OMAP boards, relying on an fdt to configure 181*4882a593Smuzhiyunthe various features. This is because you must select one of 182*4882a593Smuzhiyunthe CPU families within arch/arm/cpu/arm926ejs (omap or at91) at build 183*4882a593Smuzhiyuntime. Similarly you cannot build for multiple cpu types or 184*4882a593Smuzhiyunarchitectures. 185*4882a593Smuzhiyun 186*4882a593SmuzhiyunThat said the complexity reduction by using fdt to support variants of 187*4882a593Smuzhiyunboards which use the same SOC / CPU can be substantial. 188*4882a593Smuzhiyun 189*4882a593SmuzhiyunIt is important to understand that the fdt only selects options 190*4882a593Smuzhiyunavailable in the platform / drivers. It cannot add new drivers (yet). So 191*4882a593Smuzhiyunyou must still have the CONFIG option to enable the driver. For example, 192*4882a593Smuzhiyunyou need to define CONFIG_SYS_NS16550 to bring in the NS16550 driver, 193*4882a593Smuzhiyunbut can use the fdt to specific the UART clock, peripheral address, etc. 194*4882a593SmuzhiyunIn very broad terms, the CONFIG options in general control *what* driver 195*4882a593Smuzhiyunfiles are pulled in, and the fdt controls *how* those files work. 196*4882a593Smuzhiyun 197*4882a593Smuzhiyun-- 198*4882a593SmuzhiyunSimon Glass <sjg@chromium.org> 199*4882a593Smuzhiyun1-Sep-11 200