Search code examples
embedded-linuxyoctodevice-tree

When should we use device tree overlay over multiple device tree blob?


I have a custom board based on iMX8MP processors. This board can have 3 different hardware configuration. Basically the number of adc and shift registers are different between them. I want to be able to select correct dtb at boot time based on a truth table. I have done a u-boot script to select correct dtb which should be located in /boot/.

For a time being, I have generated all dtbs with dtc command. Then I generated dts again from those dtbs to get rid of all dtsi and to have one compact dts file for each hardware configuration.

My yocto recipe look like this:

SUMMARY = "U-boot script: auto select dtb for devboard"
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
COMPATIBLE_MACHINE = "devboard"

DEPENDS = "u-boot-mkimage-native dtc-native"

SRC_URI = "file://autoselect-dtb.txt \
            file://devboard-cirrus8.dts \
            file://devboard-cirrus16.dts \
            file://devboard-cirrus32.dts"

do_compile() {
    mkimage -A arm64 -O linux -T script -C none -d "${WORKDIR}/autoselect-dtb.txt" boot.scr
    dtc -I dts -O dtb -o devboard-cirrus8.dtb ${WORKDIR}/devboard-cirrus8.dts
    dtc -I dts -O dtb -o devboard-cirrus16.dtb ${WORKDIR}/devboard-cirrus16.dts
    dtc -I dts -O dtb -o devboard-cirrus32.dtb ${WORKDIR}/devboard-cirrus32.dts
}

do_install() {
    install -d ${D}/boot/
    install -m 0644 boot.scr ${D}/boot/
    install -m 0644 devboard-cirrus8.dtb ${D}/boot/
    install -m 0644 devboard-cirrus16.dtb ${D}/boot/
    install -m 0644 devboard-cirrus32.dtb ${D}/boot/
}

FILES:${PN} = "/boot/*"

I am aware that this is not good practice. Now I am confused, should I create multiple dtsi to suit each configuration then compile multiple dtb then install it in /boot/ or should I use device tree overlay ?


Solution

  • It depends on use case. DTSI's are for developers while DTO's are for end-users.

    So if you are working on a "platform" for some customers, like RPi or cases when someone needs to change functionality (integrators, service staff) very frequently - you should prefer DTO's to let end-users decide what nodes they need.

    For you as for developer, or in case your DTB is final (for example - some device which is released form factory and not intended to be reconfigured anymore) I would suggest use DTSI's, with defines.

    If you want to select DTB to load at boot time, I think it's all up to you - to use DTO's with base DTB or to use different DTB's w/o DTO's.

    NB

    To omit compiling-decompiling cycle you can use cpp (C Preprocessor) to get rid of all DTSI's like that:

    CPP_FLAGS   := -nostdinc -I $(INCLUDE) -undef -x assembler-with-cpp     
    $(TARGET_PP): $(TARGET_DTS)
            cpp $(CPP_FLAGS) $(TARGET_DTS) $(TARGET_PP)
    

    and you'll get $(TARGET_PP) file which will contain your whole DTS with all includes (but still with not grouped nodes).