The current u-boot (u-boot-2016.01-rc2) has been changed a lot compare to the 2014.04 version. Support the device model and device tree would be the most significant changes to me.
1. Preparing device tree (.dts) for my board.
The device source tree and include file (.dts and .dtsi) should be placed under the "arch/arm/dts" first.
2. Enabled the device model and device tree in the menu config. I could embed the device tree binary into u-boot binary or generate a separate binary (.dtb).
3. The build command will be like below.
$ make DEVICE_TREE=<dts-file-name>
4. Even though I can generate separate a device tree binary, I should concatenate the dtb binary to the u-boot to burn it into a NAND flash.
* The questions came up with this process
Q: Can I just enable the device model only? without device tree?
A: It should be (I believe). In reality, No, I should enable both of them together. The reason is that the uart in my board is compatible to "ns16650". This driver doesn't register itself as a serial device without device tree in current implementation.
Q: What's the differences between embedding a device tree binary and separating it?
A: Let's see the output of each case.
Embedding : u-boot.bin (This is actually u-boot binary + device tree bianry)
Separating : u-boot.bin, u-boot.dtb, and u-boot-dtb.bin. The last one is the same as combining the first two images.
Q: How the u-boot loads a device tree in each cases?
A: See u-boot/lib/fdtdec.c
device tree accessing
int fdtdec_setup(void)
{
#if CONFIG_IS_ENABLED(OF_CONTROL)
# ifdef CONFIG_OF_EMBED
/* Get a pointer to the FDT */
gd->fdt_blob = __dtb_dt_begin;
# elif defined CONFIG_OF_SEPARATE
# ifdef CONFIG_SPL_BUILD
/* FDT is at end of BSS unless it is in a different memory region */
if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
gd->fdt_blob = (ulong *)&_image_binary_end;
else
gd->fdt_blob = (ulong *)&__bss_end;
# else
/* FDT is at end of image */
gd->fdt_blob = (ulong *)&_end;
# endif
Embedding:
See where the "CONFIG_OF_EMBED" macro is enabled. The "__dtb_dt_begin" symbol is the start address of the device tree binary. This is defined in the "./dts/dt.dtb.S". See the code below.
./dts/dt.dtb.S
1 .section .dtb.init.rodata,"a"
2 .balign 16
3 .global __dtb_dt_begin
4 __dtb_dt_begin:
5 .incbin "dts/dt.dtb"
6 __dtb_dt_end:
7 .global __dtb_dt_end
8 .balign 16
Separating:
In this case, the start address is "_end", which can be found in the generated linker script. As it says, it is the end of binary.