Hi,
I try to understand the device tree build flow in the L4T BSP:
There are several makefiles for generating dtb. for example:
hardware/nvidia/platform/t19x/jakku/kernel-dts
hardware/nvidia/platform/t19x/galen/kernel-dts
and more.
Where it’s written which makefile to execute (for example the one in jakku folder or the one in galen folder) , the args for the makefile (for example the BUILD_19x_ENABLE and CONFIG_ARCH_TEGRA_19x_SOC args) and at which point this makefile is being executed?
At the makefile I see only .dtb and .dtbo files. Why it’s not using .dts and .dtsi files? from my understanding we use .dts and .dtsi to generate the .dtb. So what this makefile generates with all the .dtb and .dtbo files?
In addition, how all these .dtb files were built? where are all their makefiles and .dts/.dtsi files?
I can give a partial answer, but not exact. There are many non-plug-n-play devices in every system, and drivers in the kernel are more or less specific to that device, but the location (physical address) and arguments passed to the driver differ depending on the SoC and carrier board models. Instead of putting a different config for each combimation of device and possible address into the kernel and complicating the kernel with many different drivers for each variation the driver is left as a single generic config setting, and the device tree is used to pass address and other information to the driver. Thus the kernel tends to be configured for a set of drivers, and the device tree is built for any platform known to use that hardware (multiple device tree fragments built for possible variations of a single driver on different carrier boards).
This would mean, for example, that a single SoC module (not kernel module) would need specific drivers regardless of which carrier board is used even though arguments to the driver would vary based on carrier board. You might end up configuring for that specific hardware for multiple carrier boards, but instead it is easier to just build several device tree fragments for each combination of carrier board and SoC since one driver works for multiple systems with one given non-plug-n-play device (and your configuration of the kernel hints at which carrier boards could possibly be used). Finally, the fragments are combined into a single device tree (well, multiple trees, but each for just one SoC module plus carrier board combination).
The name of a fully assembled tree (combined fragments) is a combination of the module model and the carrier board model (which is how a tree is picked for install). Each tree might share parts (fragments) of the tree as an exact match (two carrier boards or SoCs might add hardware at the same address). Those matching fragments are built from a dtsi file…a “Device Tree Source Include” file for a single device at a single address.
The device tree is not really part of the kernel. However, since the kernel config names the drivers and indirectly names the SoC and carrier board it is convenient to build the dtsi fragments into a whole device tree within the same source tree. The dtb is a final tree of assembled fragments, and a dtbo is just an intermediate object file of a fragment which will become part of the final dtb.
If a kernel has been configured for a Jetson, then a set of trees will be generated with the “make dtbs” target (use the “O=/some/where” option for output to a temp location). There is more firmware than just a device tree, but you might find the “make O=/some/where firmware_install INSTALL_FW_PATH=/some/where/else” installs a set of device trees (which might not be a complete install…other tree install steps might be needed), although not all device trees will be useful. This is why some other config, e.g., flash to a partition or naming the dtb file in extlinux.conf, would also be required.
I suggest that after you have configured and built a kernel and modules you also build dtbs, then “firmware_install” naming an output location which is an empty temp directory to explore what it puts there.