The idea behind device tree is quite simple. When the kernel starts, it needs to initialize the drivers for the devices on the board. But often on embedded systems, devices can't be discover at running time. In this case, the Linux kernel has a c file that initialize the devices for the board. So the kernel must be modified/compiled for each board.
Another way is to provide a small file that describe the board to the Linux kernel. When the kernel start, it reads this file (called dtb for Device Tree Binary) to know the devices on the board, and initialize usefull drivers.
Some information on device tree may be found here:
To use device tree on arm, both bootloader (U-Boot) and kernel should be compiled with the support of device tree.
- If you have an older U-Boot, instructions are kept here.
The 3.4+ kernels have already the Device Tree support for some ARM SoC.
- imxl (apf9328) : no
- imx27 (apf27) : yes
- imx51 (apf51) : yes
- imx28 (apf28) : yes
- imx6 (apf6) : yes
The Linux configuration file should have (should be done by default):
- CONFIG_MACH_IMX27_DT (on APF27)
- CONFIG_MACH_IMX51_DT (on APF51)
- CONFIG_MACH_MXS_DT (on APF28)
- CONFIG_SERIAL_MXS_AUART_CONSOLE=y (on 3.8 ??)
Nothing else needs to be done, because the kernel image is build by the armadeus SDK with the "make" command.
- Starting with 3.8+ kernels, multi arch support is activated for i.MX(1/2/3/5) processors and so loadaddr should be given at uImage build time:
$ make linux LOADADDR=0xA0008000 (APF27) $ make linux LOADADDR=0x40008000 (APF28) $ make linux LOADADDR=0x90008000 (APF51)
- or configured inside Buildroot (2013.05+), here for APF51:
$ make menuconfig
Kernel ---> (0x90008000) load address (for 3.7+ multi-platform image)
A dtb (Device Tree Binary) file is created from a dts (Device Tree Source) file.
If your board hasn't a dts file, a <board>.dts must be added in the directory arch/arm/boot/dts/ of the linux kernel.
Only recent Buildroot have direct support for dtb image generation (example for APF51):
$ make menuconfig
Kernel ---> ... [*] Device tree support Device tree source (Use a device tree present in the kernel.) ---> (imx51-apf51dev) Device Tree Source file names
If your armadeus SDK/BSP doesn't have support for dtb image generation, you will have to do it yourself:
- go to the directory buildroot/output/build/linux-<version>
- add the file <soc>-<board>.dts the directory arch/arm/boot/dts/
- build the dtb with the command:
$ make ARCH=arm CROSS_COMPILE=../../host/usr/bin/arm-linux- <soc>-<board>.dtb
The file <soc>-<board>.dtb should then appear in arch/arm/boot/. Copy it to your TFTP directory:
$ cp buildroot/output/build/linux-3.5-rc5/arch/arm/boot/imx28-apf28.dtb /tftpboot/apf28.dtb
by naming your dtb file in /tftpboot apfXX.dtb you will be able to use the U-Boot 2013.03 scripts download_dtb, flash_dtb and update_dtb. These scripts are equivalent to usual kernel scripts download_kernel, flash_kernel and update_kernel.
Boot Linux manually (deprecated)
- Infos are kept here.
Boot Linux using U-Boot scripts
On the APF27, 28 and 51 with the latest U-Boot version things are even simpler:
- Device Tree can be loaded from the Flash memory
- The variable fdt_addr_r defines the RAM address to load the DTB structure and will be used to notify the kernel of the DT location in RAM
- APF27: Set the fdt_addr_r to A1000000
- APF28: set the fdt_addr_r to 41000000
- APF51: set the fdt_addr_r to 91000000
- APF6: fdt_addr is set to 0x18000000 by default
- Some scripts are available to update the dtb partition:
- download_dtb (download the dtb into the RAM from your local network)
- flash_dtb (transfer a dtb from RAM to flash)
- update_dtb (download and flash a dtb)
- the boot scripts ubifsboot, nfsboot and mmcboot support booting a kernel with a DT
Here is the example on the APF27:
BIOS> setenv consoledev ttymxc0 BIOS> setenv fdt_addr_r a1000000 (with the apf27 - 41000000 with an apf28 - 91000000 with an apf51 ) BIOS> saveenv BIOS> run update_kernel BIOS> run update_dtb BIOS> boot
Here is the example on the APF51:
BIOS> setenv consoledev ttymxc2 BIOS> setenv fdt_addr_r 91000000 BIOS> saveenv BIOS> run update_kernel BIOS> run update_dtb BIOS> boot
Here is the example on the APF28:
BIOS> setenv consoledev ttyAMA0 BIOS> setenv fdt_addr_r 41000000 BIOS> saveenv BIOS> run update_kernel BIOS> run update_dtb BIOS> boot
Remove DT boot
- just in case you want to come back to normal boot:
BIOS> setenv fdt_addr_r BIOS> saveenv