Run-time configuration of U-Boot via a flat device tree (fdt)
Subsystems (2)
cover Run-time configuration of U-Boot via a flat device tree (fdt)
At present in U-Boot configuration is mostly done using CONFIG options in the board file. This patch set aims to make it possible for a single U-Boot binary to support multiple boards, with the exact configuration of each board controlled by a flat device tree (fdt). This is the approach recently taken by the ARM Linux kernel and has been used by PowerPC for some time.
The fdt is a convenient vehicle for implementing run-time configuration for three reasons. Firstly it is easy to use, being a simple text file. It is extensible since it consists of nodes and properties in a nice hierarchical format.
Finally, there is already excellent infrastructure for the fdt: a compiler checks the text file and converts it to a compact binary format, and a library is already available in U-Boot (libfdt) for handling this format.
To read about fdts, take a look at the specification here:
https://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf
You also might find this section of the Linux kernel documentation useful:
(access this in the Linux kernel source code)
Documentation/devicetree/booting-without-of.txt
To use this patch set you will need to get the device tree compiler here:
git://jdl.com/software/dtc.git
and add some defines to your board (only ARM is currently supported):
#define CONFIG_OF_CONTROL (to enable run-time config control via fdt)
#define CONFIG_OF_EMBED or CONFIG_OF_SEPARATE
(either build the fdt blob into U-Boot, or create a separate u-boot.dtb)
#define CONFIG_DEFAULT_DEVICE_TREE "<your name>"
(to specify the name of the device tree file is
board/<vendor>/<board>/<your name>.dts)
This patch set does not include any drivers which actually use the fdt. I have some concerns about spreading fdt code around the U-Boot code base so am thinking of having a support file which makes this easier. I can provide a UART driver modified to use fdt if there is interest.
It is important to understand that the fdt only selects options available in the platform / drivers. It cannot add new drivers (yet). So you must still have the CONFIG option to enable the driver. For example, you need to define CONFIG_SYS_NS16550 to bring in the NS16550 driver, but can use the fdt to specific the UART clock, peripheral address, etc. In very broad terms, the CONFIG options in general control *what* driver files are pulled in, and the fdt controls *how* those files work.
While only ARM is supported in this patch series, it should be easy enough to add support for other architectures.
Simon Glass (4):
fdt: ARM: Add device tree control of U-Boot (CONFIG_OF_CONTROL)
fdt: Add support for embedded device tree (CONFIG_OF_EMBED)
fdt: Add support for a separate device tree (CONFIG_OF_SEPARATE)
fdt: ARM: Implement embedded and separate device tree
.gitignore | 1 + Makefile | 9 ++ README | 25 ++++++ arch/arm/include/asm/global_data.h | 1 + arch/arm/lib/board.c | 22 +++++ config.mk | 1 + doc/README.fdt-control | 168 ++++++++++++++++++++++++++++++++++++ dts/Makefile | 100 +++++++++++++++++++++ include/common.h | 1 + 9 files changed, 328 insertions(+), 0 deletions(-) create mode 100644 doc/README.fdt-control create mode 100644 dts/Makefile
Signature · 1 line
1.7.3.1
RFC PATCH 1/4 fdt: ARM: Add device tree control of U-Boot (CONFIG_OF_CONTROL)
This adds a device tree pointer to the global data. It can be set by board code. A later commit will add support for embedding it in U-Boot.
--- README | 11 +++++++++++ arch/arm/include/asm/global_data.h | 1 + 2 files changed, 12 insertions(+), 0 deletions(-)
README +11 -0
@@ -795,6 +795,17 @@ The following options need to be configured: XXX - this list needs to get updated! +- Device tree: + CONFIG_OF_CONTROL + If this variable is defined, U-Boot will use a device tree + to configure its devices, instead of relying on statically + compiled #defines in the board file. This option is + experimental and only available on a few boards. The device + tree is available in the global data as gd->blob. + + U-Boot needs to get its device tree from somewhere. This will + be enabled in a future patch. + - Watchdog: CONFIG_WATCHDOG If this variable is defined, it enables watchdog
arch/arm/include/asm/global_data.h +1 -0
@@ -73,6 +73,7 @@ typedef struct global_data {#if !(defined(CONFIG_SYS_ICACHE_OFF ) && defined(CONFIG_SYS_DCACHE_OFF ))unsigned long tlb_addr;#endif +const void *blob;/* Our device tree, NULL if none */ void **jt;/* jump table */ char env_buf[32 ];/* buffer for getenv() before reloc. */ } gd_t;
Signature · 1 line
1.7.3.1
RFC PATCH 1/4 fdt: ARM: Add device tree control of U-Boot (CONFIG_OF_CONTROL)
arch/arm/include/asm/global_data.h
Quoted 4 lines · On Thursday, September 01, 2011 16:49:06 Simon Glass wrote:
arch/arm/include/asm/global_data.h +1
-0+const void *blob;/* Our device tree, NULL if none */
let's call it "fdt_blob" or something less generic than "blob"
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110902/8b256d34/attachment.pgp
RFC PATCH 1/4 fdt: ARM: Add device tree control of U-Boot (CONFIG_OF_CONTROL)
Hi Mike,
Quoted 9 lines · Mike Frysinger
arch/arm/include/asm/global_data.h
Quoted 4 lines · On Thursday, September 01, 2011 16:49:06 Simon Glass wrote:
arch/arm/include/asm/global_data.h +1
-0+ ? ? const void ? ? ?*blob; ? ? ? ? ?/* Our device tree, NULL if none */let's call it "
fdt_blob" or something less generic than "blob" -mike
OK, will change to fdt_blob within the global data.
Regards,
Simon
RFC PATCH 2/4 fdt: Add support for embedded device tree (CONFIG_OF_EMBED)
In reply to Simon GlassThis new option allows U-Boot to embed a binary device tree into its image to allow run-time control of peripherals. This device tree is for U-Boot's own use and is not necessarily the same one as is passed to the kernel.
The device tree compiler output should be placed in the $(obj) rooted tree. Since $(OBJCOPY) insists on adding the path to the generated symbol names, to ensure consistency it should be invoked from the directory where the .dtb file is located and given the input file name without the path.
This commit contains my entry for the ugliest Makefile / shell interaction competition.
--- Makefile | 4 ++ README | 11 +++++- config.mk | 1 + dts/Makefile | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/common.h | 1 + 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 dts/Makefile
Makefile +4 -0
@@ -224,6 +224,9 @@ endif ifeq ($(CPU),ixp) LIBS += arch/arm/cpu/ixp/npe/libnpe.o endif +ifeq ($(CONFIG_OF_EMBED),y) +LIBS += dts/libdts.o +endif LIBS += arch/$(ARCH)/lib/lib$(ARCH).o LIBS += fs/cramfs/libcramfs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o \ fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/yaffs2/libyaffs2.o \
@@ -1045,6 +1048,7 @@ clobber: clean @rm -f $(obj)u-boot.kwb @rm -f $(obj)u-boot.imx @rm -f $(obj)u-boot.ubl + @rm -f $(obj)u-boot.dtb @rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes} @rm -f $(obj)arch/powerpc/cpu/mpc824x/bedbug_603e.c @rm -fr $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
README +9 -2
@@ -803,8 +803,15 @@ The following options need to be configured: experimental and only available on a few boards. The device tree is available in the global data as gd->blob. - U-Boot needs to get its device tree from somewhere. This will - be enabled in a future patch. + U-Boot needs to get its device tree from somewhere. At present + the only way is to embed it in the image with CONFIG_OF_EMBED. + + CONFIG_OF_EMBED + If this variable is defined, U-Boot will embed a device tree + binary in its image. This device tree file should be in the + board directory and called <soc>-<board>.dts. The binary file + is then picked up in board_init_f() and made available through + the global data structure as gd->blob. - Watchdog: CONFIG_WATCHDOG
config.mk +1 -0
@@ -124,6 +124,7 @@ STRIP = $(CROSS_COMPILE)strip OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump RANLIB = $(CROSS_COMPILE)RANLIB +DTC = dtc #########################################################################
dts/Makefile new file +100 -0
100 lines not on this page · raw message
include/common.h +1 -0
@@ -249,6 +249,7 @@ int checkdram (void);int last_stage_init (void );extern ulong monitor_flash_len;int mac_read_from_eeprom (void ); +extern u8 _binary_dt_dtb_start[];/* embedded device tree blob */ /* common/flash.c */ void flash_perror (int );
Signature · 1 line
1.7.3.1
RFC PATCH 3/4 fdt: Add support for a separate device tree (CONFIG_OF_SEPARATE)
In reply to Simon GlassThis adds support for an FDT to be build as a separate binary file called u-boot.dtb. This can be concatenated with the U-Boot binary to provide a device tree located at run-time by U-Boot.
--- .gitignore | 1 + Makefile | 5 ++ README | 11 +++- doc/README.fdt-control | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 doc/README.fdt-control
.gitignore +1 -0
@@ -34,6 +34,7 @@ /u-boot.dis /u-boot.lds /u-boot.ubl +/u-boot.dtb # # Generated files
Makefile +5 -0
@@ -352,9 +352,14 @@ ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin ONENAND_BIN ?= $(obj)onenand_ipl/onenand-ipl-2k.bin ALL-$(CONFIG_MMC_U_BOOT) += $(obj)mmc_spl/u-boot-mmc-spl.bin ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin +ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb all: $(ALL-y) +$(obj)u-boot.dtb: $(obj)u-boot + $(MAKE) -C dts binary + mv $(obj)dts/dt.dtb $@ + $(obj)u-boot.hex: $(obj)u-boot $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
README +9 -2
@@ -803,8 +803,8 @@ The following options need to be configured: experimental and only available on a few boards. The device tree is available in the global data as gd->blob. - U-Boot needs to get its device tree from somewhere. At present - the only way is to embed it in the image with CONFIG_OF_EMBED. + U-Boot needs to get its device tree from somewhere. This can + be done using one of the two options below: CONFIG_OF_EMBED If this variable is defined, U-Boot will embed a device tree
@@ -813,6 +813,13 @@ The following options need to be configured: is then picked up in board_init_f() and made available through the global data structure as gd->blob. + CONFIG_OF_SEPARATE + If this variable is defined, U-Boot will build a device tree + binary. It will be called u-boot.dtb. Architecture-specific + code will locate it at run-time. Generally this works by: + + cat u-boot.bin u-boot.dtb >image.bin + - Watchdog: CONFIG_WATCHDOG If this variable is defined, it enables watchdog
doc/README.fdt-control new file +168 -0
168 lines not on this page · raw message
Signature · 1 line
1.7.3.1
RFC PATCH 4/4 fdt: ARM: Implement embedded and separate device tree
In reply to Simon GlassThis locates the device tree either embedded within U-Boot or attached to the end as a separate binary.
When CONFIG_OF_CONTROL is defined, U-Boot requires a valid fdt. A check is provided for this early in initialisation.
--- arch/arm/lib/board.c | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-)
arch/arm/lib/board.c +22 -0
@@ -48,6 +48,7 @@#include <nand.h> #include <onenand_uboot.h> #include <mmc.h> +#include <libfdt.h> #ifdef CONFIG_BITBANGMII #include <miiphy.h>
@@ -195,6 +196,17 @@ static int arm_pci_init(void) }#endif /* CONFIG_CMD_PCI || CONFIG_PCI */ +#ifdef CONFIG_OF_CONTROL +static int check_fdt (void ) +{ +/* We must have an fdt */ +if (fdt_check_header (gd->blob)) +panic ("No valid fdt found - please append one to U-Boot\n" +"binary or define CONFIG_OF_EMBED\n" ); +return 0 ; +} +#endif +/* * Breathe some life into the board... *
@@ -237,6 +249,9 @@ init_fnc_t *init_sequence[] = {#if defined(CONFIG_BOARD_EARLY_INIT_F ) board_early_init_f,#endif +#ifdef CONFIG_OF_CONTROL + check_fdt, +#endif timer_init, /* initialize timer */#ifdef CONFIG_FSL_ESDHC get_clocks,
@@ -274,6 +289,13 @@ void board_init_f(ulong bootflag)memset ((void *)gd,0 ,sizeof (gd_t)); gd->mon_len = _bss_end_ofs; +#ifdef CONFIG_OF_EMBED +/* Get a pointer to the FDT */ + gd->blob = _binary_dt_dtb_start; +#elif definedCONFIG_OF_SEPARATE +/* FDT is at end of image */ + gd->blob = (void *)(_end_ofs + _TEXT_BASE); +#endif #ifdef CONFIG_MACH_TYPE gd->bd->bi_arch_number =CONFIG_MACH_TYPE ;/* board id for Linux */
Signature · 1 line
1.7.3.1
cover Run-time configuration of U-Boot via a flat device tree (fdt)
In reply to Simon GlassHi Simon,
Quoted 5 lines · Simon Glass
At present in U-Boot configuration is mostly done using CONFIG options in the board file. This patch set aims to make it possible for a single U-Boot binary to support multiple boards, with the exact configuration of each board controlled by a flat device tree (fdt). This is the approach recently taken by the ARM Linux kernel and has been used by PowerPC for some time.
Very exciting. I've thought about doing this for years, but never had the ambition (or time).
[snip]
Quoted 9 lines
and add some defines to your board (only ARM is currently supported):
#define
CONFIG_OF_CONTROL(to enable run-time config control via fdt)
#defineCONFIG_OF_EMBEDorCONFIG_OF_SEPARATE
(either build the fdt blob into U-Boot, or create a separate u-boot.dtb)
#defineCONFIG_DEFAULT_DEVICE_TREE"<your name>"
(to specify the name of the device tree file is
board/<vendor>/<board>/<your name>.dts)
Quoted 4 lines
This patch set does not include any drivers which actually use the fdt. I have some concerns about spreading fdt code around the U-Boot code base so am thinking of having a support file which makes this easier. I can provide a UART driver modified to use fdt if there is interest.
Please. A concrete reference is very useful, especially for discussion.
Quoted 7 lines
It is important to understand that the fdt only selects options available in the platform / drivers. It cannot add new drivers (yet). So you must still have the CONFIG option to enable the driver. For example, you need to define
CONFIG_SYS_NS16550to bring in the NS16550 driver, but can use the fdt to specific the UART clock, peripheral address, etc. In very broad terms, the CONFIG options in general control *what* driver files are pulled in, and the fdt controls *how* those files work.
Sounds reasonable and practical. One of the things u-boot struggles with is staying small (but it is nice to be able to make it all inclusive and big if you have the flash).
Quoted 2 lines
While only ARM is supported in this patch series, it should be easy enough to add support for other architectures.
Exercise left for the students. :-)
[snip]
Thanks!
gvb
cover Run-time configuration of U-Boot via a flat device tree (fdt)
Hi Jerry,
Quoted 13 lines · Jerry Van Baren
Hi Simon,
Quoted 9 lines · Simon Glass
At present in U-Boot configuration is mostly done using CONFIG options in the
board file. This patch set aims to make it possible for a single U-Boot binary to support multiple boards, with the exact configuration of each board
controlled by a flat device tree (fdt). This is the approach recently taken
by the ARM Linux kernel and has been used by PowerPC for some time.
Quoted 2 lines
Very exciting. ?I've thought about doing this for years, but never had the ambition (or time).
Thanks for your comments. Yes there was mention of it in the UBML a few years ago:
http://lists.denx.de/pipermail/u-boot/2008-August/038052.html
Quoted 4 lines · where Wolfgang
A much more powerful concept is to have U-Boot read and interpret the DT dynamically - only then can you use the same U-Boot binary image on different board configurations, which is an important feature for many board vendors.
This is basically what my patch set sets out to do.
Quoted 14 lines
[snip]
Quoted 11 lines
and add some defines to your board (only ARM is currently supported):
?#define
CONFIG_OF_CONTROL? ? ? (to enable run-time config control via fdt)
?#defineCONFIG_OF_EMBEDorCONFIG_OF_SEPARATE
? ? ?(either build the fdt blob into U-Boot, or create a separate u-boot.dtb)
?#defineCONFIG_DEFAULT_DEVICE_TREE? ?"<your name>"
? ? ?(to specify the name of the device tree file is
? ? ? board/<vendor>/<board>/<your name>.dts)
Quoted 7 lines
Quoted 5 lines
This patch set does not include any drivers which actually use the fdt. I have
some concerns about spreading fdt code around the U-Boot code base so am thinking of having a support file which makes this easier. I can provide a UART driver modified to use fdt if there is interest.Please. ?A concrete reference is very useful, especially for discussion.
I will try to create a driver for something for which we have a device tree definition in the kernel. Will post to the list as an RFC.
Quoted 12 lines
Quoted 11 lines
It is important to understand that the fdt only selects options available in
the platform / drivers. It cannot add new drivers (yet). So you must still have the CONFIG option to enable the driver. For example, you need to defineCONFIG_SYS_NS16550to bring in the NS16550 driver, but can use the fdt to specific the UART clock, peripheral address, etc. In very broad terms, the CONFIG options in general control *what* driver files are pulled in, and the
fdt controls *how* those files work.
Quoted 3 lines
Sounds reasonable and practical. ?One of the things u-boot struggles with is staying small (but it is nice to be able to make it all inclusive and big if you have the flash).
Yes to some extent this is a halfway house, but it is a way of introducing this feature without changing the way things currently work. I almost feel as if there are two types of configs, and perhaps the naming should recognize that (SELECT_ and CONFIG_?). No, I don't want to modify all the board files...
Quoted 6 lines
Quoted 4 lines
While only ARM is supported in this patch series, it should be easy enough to
add support for other architectures.Exercise left for the students. ?:-)
Yes - you can pretty-much just copy the ARM board.c code into your board.c file to try this out.
Regards,
Simon
Quoted 6 lines
[snip]
Thanks!
gvb
cover Run-time configuration of U-Boot via a flat device tree (fdt)
In reply to Simon GlassQuoted 7 lines · On Thursday, September 01, 2011 16:49:05 Simon Glass wrote:
At present in U-Boot configuration is mostly done using CONFIG options in the board file. This patch set aims to make it possible for a single U-Boot binary to support multiple boards, with the exact configuration of each board controlled by a flat device tree (fdt). This is the approach recently taken by the ARM Linux kernel and has been used by PowerPC for some time.
Quoted 8 lines
The fdt is a convenient vehicle for implementing run-time configuration for three reasons. Firstly it is easy to use, being a simple text file. It is extensible since it consists of nodes and properties in a nice hierarchical format.
Finally, there is already excellent infrastructure for the fdt: a compiler checks the text file and converts it to a compact binary format, and a library is already available in U-Boot (libfdt) for handling this format.
i guess the important questions for u-boot: size and speed. have you done any comparisons in this area ?
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20110902/eeb02433/attachment.pgp
cover Run-time configuration of U-Boot via a flat device tree (fdt)
HI Mike,
Quoted 13 lines · Mike Frysinger
Quoted 12 lines · On Thursday, September 01, 2011 16:49:05 Simon Glass wrote:
At present in U-Boot configuration is mostly done using CONFIG options in the board file. This patch set aims to make it possible for a single U-Boot binary to support multiple boards, with the exact configuration of each board controlled by a flat device tree (fdt). This is the approach recently taken by the ARM Linux kernel and has been used by PowerPC for some time.
The fdt is a convenient vehicle for implementing run-time configuration for three reasons. Firstly it is easy to use, being a simple text file. It is extensible since it consists of nodes and properties in a nice hierarchical format.
Quoted 6 lines
Quoted 3 lines
Finally, there is already excellent infrastructure for the fdt: a compiler checks the text file and converts it to a compact binary format, and a library is already available in U-Boot (libfdt) for handling this format.
i guess the important questions for u-boot: size and speed. ?have you done any comparisons in this area ?
In general the main difference between compile-time and run-time config is the device init. Rather than spreading CONFIG_ items through the driiver, we can define a structure which holds the config. Then it can be set up at driver init, either by assigning from CONFIG items, or decoding values from the fdt. Using this structure could in some cases have some small affect on code size and performance within the driver. For example, if the driver has something like:
for (very tight loop executed 1000 times) {
writel(CONFIG_SOME_VALUE / 9, &periph->reg);
}then the compiler can work out the value at run time, whereas when the driver is modified to use a structure:
writel(config.some_value / 9, &periph->reg);
the compiler must actually do the calculation. I don't see much of this in the code base though. So overall the performance difference is small, and with a little effort can be close to zero.
In terms of code size, apart from adding the init code to decode from the fdt, I don't see a difference. I think an fdt_decode library is a good idea so that drivers have helper functions for doing common tasks (higher level than the existing fdt_support library, with specific driver decode support). That means that the fdt decode code size hit might happen once per driver class, maybe.
Regards,
Simon
Quoted 2 lines
-mike