fdt: Add support for embedded device tree (CONFIG_OF_EMBED)

This 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.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2011-10-15 05:48:21 +00:00 committed by Wolfgang Denk
parent 45ba8077f3
commit bbb0b128c3
6 changed files with 291 additions and 2 deletions

View File

@ -229,6 +229,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 \
@ -879,6 +882,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
@ -886,6 +890,7 @@ clobber: clean
@[ ! -d $(obj)nand_spl ] || find $(obj)nand_spl -name "*" -type l -print | xargs rm -f
@[ ! -d $(obj)onenand_ipl ] || find $(obj)onenand_ipl -name "*" -type l -print | xargs rm -f
@[ ! -d $(obj)mmc_spl ] || find $(obj)mmc_spl -name "*" -type l -print | xargs rm -f
@rm -f $(obj)dts/*.tmp
mrproper \
distclean: clobber unconfig

11
README
View File

@ -824,8 +824,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->fdt_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

View File

@ -124,6 +124,7 @@ STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
DTC = dtc
#########################################################################

172
doc/README.fdt-control Normal file
View File

@ -0,0 +1,172 @@
#
# Copyright (c) 2011 The Chromium OS Authors.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundatio; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
Device Tree Control in U-Boot
=============================
This feature provides for run-time configuration of U-Boot via a flat
device tree (fdt). U-Boot configuration has traditionally been done
using CONFIG options in the board config file. This feature 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.
The dts directory contains a Makefile for building the device tree blob
and embedding it in your U-Boot image. This is useful since it allows
U-Boot to configure itself according to what it finds there. If you have
a number of similar boards with different peripherals, you can describe
the features of each board in the device tree file, and have a single
generic source base.
To enable this feature, add CONFIG_OF_CONTROL to your board config file.
What is a Flat Device Tree?
---------------------------
An fdt can be specified in source format as a text file. To read about
the fdt syntax, 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
There is also a mailing list:
http://lists.ozlabs.org/listinfo/devicetree-discuss
In case you are wondering, OF stands for Open Firmware.
Tools
-----
To use this feature you will need to get the device tree compiler here:
git://jdl.com/software/dtc.git
For example:
$ git clone git://jdl.com/software/dtc.git
$ cd dtc
$ make
$ sudo make install
Then run the compiler (your version will vary):
$ dtc -v
Version: DTC 1.2.0-g2cb4b51f
$ make tests
$ cd tests
$ ./run_tests.sh
********** TEST SUMMARY
* Total testcases: 1371
* PASS: 1371
* FAIL: 0
* Bad configuration: 0
* Strange test result: 0
You will also find a useful ftdump utility for decoding a binary file.
Where do I get an fdt file for my board?
----------------------------------------
You may find that the Linux kernel has a suitable file. Look in the
kernel source in arch/<arch>/boot/dts.
If not you might find other boards with suitable files that you can
modify to your needs. Look in the board directories for files with a
.dts extension.
Failing that, you could write one from scratch yourself!
Configuration
-------------
Use:
#define CONFIG_DEFAULT_DEVICE_TREE "<name>"
to set the filename of the device tree source. Then put your device tree
file into
board/<vendor>/dts/<name>.dts
This should include your CPU or SOC's device tree file, placed in
arch/<arch>/dts, and then make any adjustments required. The name of this
is CONFIG_ARCH_DEVICE_TREE.dts.
If CONFIG_OF_EMBED is defined, then it will be picked up and built into
the U-Boot image (including u-boot.bin).
If CONFIG_OF_SEPARATE is defined, then it will be built and placed in
a u-boot.dtb file alongside u-boot.bin. A common approach is then to
join the two:
cat u-boot.bin u-boot.dtb >image.bin
and then flash image.bin onto your board.
You cannot use both of these options at the same time.
Limitations
-----------
U-Boot is designed to build with a single architecture type and CPU
type. So for example it is not possible to build a single ARM binary
which runs on your AT91 and OMAP boards, relying on an fdt to configure
the various features. This is because you must select one of
the CPU families within arch/arm/cpu/arm926ejs (omap or at91) at build
time. Similarly you cannot build for multiple cpu types or
architectures.
That said the complexity reduction by using fdt to support variants of
boards which use the same SOC / CPU can be substantial.
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.
--
Simon Glass <sjg@chromium.org>
1-Sep-11

103
dts/Makefile Normal file
View File

@ -0,0 +1,103 @@
#
# Copyright (c) 2011 The Chromium OS Authors.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundatio; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
# This Makefile builds the internal U-Boot fdt if CONFIG_OF_CONTROL is
# enabled. See doc/README.fdt-control for more details.
include $(TOPDIR)/config.mk
LIB = $(obj)libdts.o
$(if $(CONFIG_DEFAULT_DEVICE_TREE),,\
$(error Please define CONFIG_DEFAULT_DEVICE_TREE in your board header file))
DEVICE_TREE = $(subst ",,$(CONFIG_DEFAULT_DEVICE_TREE))
$(if $(CONFIG_ARCH_DEVICE_TREE),,\
$(error Your architecture does not have device tree support enabled. \
Please define CONFIG_ARCH_DEVICE_TREE))
# We preprocess the device tree file provide a useful define
DTS_CPPFLAGS := -DARCH_CPU_DTS=\"../arch/$(ARCH)/dts/$(CONFIG_ARCH_DEVICE_TREE).dtsi\"
all: $(obj).depend $(LIB)
# Use a constant name for this so we can access it from C code.
# objcopy doesn't seem to allow us to set the symbol name independently of
# the filename.
DT_BIN := $(obj)dt.dtb
$(DT_BIN): $(TOPDIR)/board/$(VENDOR)/dts/$(DEVICE_TREE).dts
cat $< | $(CPP) -P $(DTS_CPPFLAGS) - >$@.tmp
$(DTC) -R 4 -p 0x1000 -O dtb -o ${DT_BIN} $@.tmp
rm $@.tmp
process_lds = \
$(1) | sed -r -n 's/^OUTPUT_$(2)[ ("]*([^")]*).*/\1/p'
# Run the compiler and get the link script from the linker
GET_LDS = $(CC) $(CFLAGS) $(LDFLAGS) -Wl,--verbose 2>&1
$(obj)dt.o: $(DT_BIN)
# We want the output format and arch.
# We also hope to win a prize for ugliest Makefile / shell interaction
# We look in the LDSCRIPT first.
# Then try the linker which should give us the answer.
# Then check it worked.
oformat=`$(call process_lds,cat $(LDSCRIPT),FORMAT)` ;\
oarch=`$(call process_lds,cat $(LDSCRIPT),ARCH)` ;\
\
[ -z $${oformat} ] && \
oformat=`$(call process_lds,$(GET_LDS),FORMAT)` ;\
[ -z $${oarch} ] && \
oarch=`$(call process_lds,$(GET_LDS),ARCH)` ;\
\
[ -z $${oformat} ] && \
echo "Cannot read OUTPUT_FORMAT from lds file $(LDSCRIPT)" && \
exit 1 || true ;\
[ -z $${oarch} ] && \
echo "Cannot read OUTPUT_ARCH from lds file $(LDSCRIPT)" && \
exit 1 || true ;\
\
cd $(dir ${DT_BIN}) && \
$(OBJCOPY) -I binary -O $${oformat} -B $${oarch} \
$(notdir ${DT_BIN}) $@
rm $(DT_BIN)
OBJS-$(CONFIG_OF_EMBED) := dt.o
COBJS := $(OBJS-y)
OBJS := $(addprefix $(obj),$(COBJS))
binary: $(DT_BIN)
$(LIB): $(OBJS) $(DTB)
$(call cmd_link_o_target, $(OBJS))
#########################################################################
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################

View File

@ -276,6 +276,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);