Proposal: FIT support for extension boards / overlays

Hi,
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
Some boards have extension add-ons which have their own devicetree overlays. It would be helpful to know which ones should be applied for a particular extension.
I propose implementing extensions in FIT. This has a new '/extensions' node, so you can specify what extensions are available for each FIT configuration.
For example:
/ { images { kernel { // common kernel };
fdt-1 { // FDT for board1 };
fdto-1 { // FDT overlay };
fdto-2 { // FDT overlay };
fdto-3 { // FDT overlay }; };
configurations { conf-1 { compatible = ... fdt = "fdt-1"; extensions = "ext1", "ext-2"; }; };
extensions { ext-1 { fdto = "fdto-1"; // FDT overlay for this 'cape' or 'hat' kernel = "kernel-1"; compatible = "vendor,combined-device1"; extensions = "ext-3"; };
ext-2 { fdto = "fdto-2"; // fdt overlay for this 'cape' compatible = "vendor,device2"; };
ext-3 { fdto = "fdto-3"; compatible = "vendor,device3"; }; }; };
So FIT configurations have a list of supported extensions. The extensions are hierarchical so that you can have ext-1 which can optionally have ext-2 as well. This allows boards to share a common SoC to add in overlays as needed by their board. It also allows common 'capes' or 'hats' to be specified only once and used by a group of boards which share the same interface.
Within U-Boot, extensions actually present are declared by a sysinfo driver for the board, with new methods:
get_compat() - determine the compatible strings for the current platform get_ext() - get a list of compatible strings for extensions which are actually present
The extension compatible-strings are used to select the correct things from the FIT, apply the overlays and produce the final DT.
To make this simpler for the common case (without extensions), we can allow multiple FDT images for a configuration, with the first one being the base SoC .dtb and the others being the .dtbo overlay(s) for the board:
confi-1 { compatible = ... fdt = "fdt-1", "fdto-1"; };
Comments welcome.
Regards, Simon

On 12.12.23 15:05, Simon Glass wrote:
Hi,
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
Some boards have extension add-ons which have their own devicetree overlays. It would be helpful to know which ones should be applied for a particular extension.
I propose implementing extensions in FIT. This has a new '/extensions' node, so you can specify what extensions are available for each FIT configuration.
For example:
/ { images { kernel { // common kernel };
fdt-1 { // FDT for board1 }; fdto-1 { // FDT overlay }; fdto-2 { // FDT overlay }; fdto-3 { // FDT overlay };
};
configurations { conf-1 { compatible = ... fdt = "fdt-1"; extensions = "ext1", "ext-2";
Shouldn't there be braces around the item list?
How do you specify optional and required but otherwise unrelated extensions for a configuration?
};
};
extensions { ext-1 { fdto = "fdto-1"; // FDT overlay for this 'cape' or 'hat' kernel = "kernel-1"; compatible = "vendor,combined-device1"; extensions = "ext-3"; };
ext-2 { fdto = "fdto-2"; // fdt overlay for this 'cape' compatible = "vendor,device2"; }; ext-3 { fdto = "fdto-3"; compatible = "vendor,device3"; };
}; };
So FIT configurations have a list of supported extensions. The extensions are hierarchical so that you can have ext-1 which can optionally have ext-2 as well. This allows boards to share a common
ext2 seems not to be related to ext-3. Do you mean ext-3 optionally extending ext-1? How would you specify that ext-n is required for ext-m to work?
The sequence of applying overlays may make a difference. I cannot see that your current suggestion defines a sequence in which the overlays are applied.
SoC to add in overlays as needed by their board. It also allows common 'capes' or 'hats' to be specified only once and used by a group of boards which share the same interface.
Within U-Boot, extensions actually present are declared by a sysinfo driver for the board, with new methods:
get_compat() - determine the compatible strings for the current platform get_ext() - get a list of compatible strings for extensions which are actually present
Do you expect U-Boot to have code that injects device-tree fragments with a compatible string into the control FDT after discovering add-ons?
Why can't we simply write the compatible constraint into the overlay definition (fdto-#) and enumerate the overlays in the configuration?
On some busses detection is problematic. Two alternative add-ons may use the same SPI address but need different FDT overlays.
Best regards
Heinrich
The extension compatible-strings are used to select the correct things from the FIT, apply the overlays and produce the final DT.
To make this simpler for the common case (without extensions), we can allow multiple FDT images for a configuration, with the first one being the base SoC .dtb and the others being the .dtbo overlay(s) for the board:
confi-1 { compatible = ... fdt = "fdt-1", "fdto-1"; };
Comments welcome.
Regards, Simon

Hi Heinrich,
On Tue, Dec 12, 2023 at 3:43 PM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12.12.23 15:05, Simon Glass wrote:
Hi,
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
Some boards have extension add-ons which have their own devicetree overlays. It would be helpful to know which ones should be applied for a particular extension.
I propose implementing extensions in FIT. This has a new '/extensions' node, so you can specify what extensions are available for each FIT configuration.
For example:
/ { images { kernel { // common kernel };
fdt-1 { // FDT for board1 }; fdto-1 { // FDT overlay }; fdto-2 { // FDT overlay }; fdto-3 { // FDT overlay };
};
configurations { conf-1 { compatible = ... fdt = "fdt-1"; extensions = "ext1", "ext-2";
Shouldn't there be braces around the item list?
I don't think so.
How do you specify optional and required but otherwise unrelated extensions for a configuration?
Do we actually need to know which extensions are required or optional? Do you have an example?
};
};
extensions { ext-1 { fdto = "fdto-1"; // FDT overlay for this 'cape' or 'hat' kernel = "kernel-1"; compatible = "vendor,combined-device1"; extensions = "ext-3"; };
ext-2 { fdto = "fdto-2"; // fdt overlay for this 'cape' compatible = "vendor,device2"; }; ext-3 { fdto = "fdto-3"; compatible = "vendor,device3"; };
}; };
So FIT configurations have a list of supported extensions. The extensions are hierarchical so that you can have ext-1 which can optionally have ext-2 as well. This allows boards to share a common
ext2 seems not to be related to ext-3. Do you mean ext-3 optionally extending ext-1? How would you specify that ext-n is required for ext-m to work?
Yes, I mean "optionally extending ext2". Again, I don't consider required extensions here.
The sequence of applying overlays may make a difference. I cannot see that your current suggestion defines a sequence in which the overlays are applied.
SoC to add in overlays as needed by their board. It also allows common 'capes' or 'hats' to be specified only once and used by a group of boards which share the same interface.
Within U-Boot, extensions actually present are declared by a sysinfo driver for the board, with new methods:
get_compat() - determine the compatible strings for the current platform get_ext() - get a list of compatible strings for extensions which are actually present
Do you expect U-Boot to have code that injects device-tree fragments with a compatible string into the control FDT after discovering add-ons?
Yes, that's right, by applying overlays.
Why can't we simply write the compatible constraint into the overlay definition (fdto-#) and enumerate the overlays in the configuration?
Yes, that is the example quoted below.
On some busses detection is problematic. Two alternative add-ons may use the same SPI address but need different FDT overlays.
If there is no way to detect the extension, then it cannot work anyway, right?
BTW I am not suggesting that the bus is used for detection, although I suppose this is possible. More likely there are GPIOs which can be decoded to indicate the extension, or perhaps an I2C EEPROM.
Best regards
Heinrich
The extension compatible-strings are used to select the correct things from the FIT, apply the overlays and produce the final DT.
To make this simpler for the common case (without extensions), we can allow multiple FDT images for a configuration, with the first one being the base SoC .dtb and the others being the .dtbo overlay(s) for the board:
confi-1 { compatible = ... fdt = "fdt-1", "fdto-1"; };
Comments welcome.
Regards, Simon

On Thu, Dec 28, 2023 at 1:49 AM Simon Glass sjg@chromium.org wrote:
Hi Heinrich,
On Tue, Dec 12, 2023 at 3:43 PM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12.12.23 15:05, Simon Glass wrote:
Hi,
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
Some boards have extension add-ons which have their own devicetree overlays. It would be helpful to know which ones should be applied for a particular extension.
I propose implementing extensions in FIT. This has a new '/extensions' node, so you can specify what extensions are available for each FIT configuration.
For example:
/ { images { kernel { // common kernel };
fdt-1 { // FDT for board1 }; fdto-1 { // FDT overlay }; fdto-2 { // FDT overlay }; fdto-3 { // FDT overlay };
};
configurations { conf-1 { compatible = ... fdt = "fdt-1"; extensions = "ext1", "ext-2";
Shouldn't there be braces around the item list?
I don't think so.
How do you specify optional and required but otherwise unrelated extensions for a configuration?
Do we actually need to know which extensions are required or optional? Do you have an example?
If an extension is required for a device, then it wouldn't be an extension per se. The referenced DT overlay should be directly tied to the device compatible through the configuration node.
If say "ext-3" depends on "ext-1" (assuming that is one definition of "required"), then based on the syntax I believe "ext-3" should only be listed in the "extensions" property under "ext-1", and not the base configuration?
};
};
extensions { ext-1 { fdto = "fdto-1"; // FDT overlay for this 'cape' or 'hat' kernel = "kernel-1"; compatible = "vendor,combined-device1"; extensions = "ext-3"; };
ext-2 { fdto = "fdto-2"; // fdt overlay for this 'cape' compatible = "vendor,device2"; }; ext-3 { fdto = "fdto-3"; compatible = "vendor,device3"; };
}; };
So FIT configurations have a list of supported extensions. The extensions are hierarchical so that you can have ext-1 which can optionally have ext-2 as well. This allows boards to share a common
ext2 seems not to be related to ext-3. Do you mean ext-3 optionally extending ext-1? How would you specify that ext-n is required for ext-m to work?
Yes, I mean "optionally extending ext2". Again, I don't consider required extensions here.
See above for my take on extension dependencies.
ChenYu
The sequence of applying overlays may make a difference. I cannot see that your current suggestion defines a sequence in which the overlays are applied.
SoC to add in overlays as needed by their board. It also allows common 'capes' or 'hats' to be specified only once and used by a group of boards which share the same interface.
Within U-Boot, extensions actually present are declared by a sysinfo driver for the board, with new methods:
get_compat() - determine the compatible strings for the current platform get_ext() - get a list of compatible strings for extensions which are actually present
Do you expect U-Boot to have code that injects device-tree fragments with a compatible string into the control FDT after discovering add-ons?
Yes, that's right, by applying overlays.
Why can't we simply write the compatible constraint into the overlay definition (fdto-#) and enumerate the overlays in the configuration?
Yes, that is the example quoted below.
On some busses detection is problematic. Two alternative add-ons may use the same SPI address but need different FDT overlays.
If there is no way to detect the extension, then it cannot work anyway, right?
BTW I am not suggesting that the bus is used for detection, although I suppose this is possible. More likely there are GPIOs which can be decoded to indicate the extension, or perhaps an I2C EEPROM.
Best regards
Heinrich
The extension compatible-strings are used to select the correct things from the FIT, apply the overlays and produce the final DT.
To make this simpler for the common case (without extensions), we can allow multiple FDT images for a configuration, with the first one being the base SoC .dtb and the others being the .dtbo overlay(s) for the board:
confi-1 { compatible = ... fdt = "fdt-1", "fdto-1"; };
Comments welcome.
Regards, Simon

On 12/12/23 8:05 AM, Simon Glass wrote:
Hi,
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
For this to save much size we would need to have the SoC split from each board that uses it. We don't have that in DT today. There are some efforts in progress to help on this but until then we will not get much here.
Some boards have extension add-ons which have their own devicetree overlays. It would be helpful to know which ones should be applied for a particular extension.
I propose implementing extensions in FIT. This has a new '/extensions' node, so you can specify what extensions are available for each FIT configuration.
For example:
/ { images { kernel { // common kernel };
fdt-1 { // FDT for board1 }; fdto-1 { // FDT overlay }; fdto-2 { // FDT overlay }; fdto-3 { // FDT overlay };
};
configurations { conf-1 { compatible = ... fdt = "fdt-1"; extensions = "ext1", "ext-2"; }; };
extensions { ext-1 { fdto = "fdto-1"; // FDT overlay for this 'cape' or 'hat' kernel = "kernel-1"; compatible = "vendor,combined-device1"; extensions = "ext-3"; };
ext-2 { fdto = "fdto-2"; // fdt overlay for this 'cape' compatible = "vendor,device2"; }; ext-3 { fdto = "fdto-3"; compatible = "vendor,device3"; };
}; };
So FIT configurations have a list of supported extensions. The extensions are hierarchical so that you can have ext-1 which can optionally have ext-2 as well. This allows boards to share a common SoC to add in overlays as needed by their board. It also allows common 'capes' or 'hats' to be specified only once and used by a group of boards which share the same interface.
Are you suggesting an 'extension' that lists every 'cape', then for each board that has a 'cape' header we list that 'hierarchical extension' to suggest support?
Seems reasonable, but we don't have universal DTB overlays today. Each overlay needs to be built for a specific board due to several reasons (I have some plans to help solve this but the upstream kernel path might be a ways out).
Within U-Boot, extensions actually present are declared by a sysinfo driver for the board, with new methods:
get_compat() - determine the compatible strings for the current platform get_ext() - get a list of compatible strings for extensions which are actually present
The extension compatible-strings are used to select the correct things from the FIT, apply the overlays and produce the final DT.
These extension compatible-strings, could they just be the name of the overlay file? That is what we do today with our name_overlays[0]. The benefit is these names can be used to load and apply overlays in the non-FIT case just the same.
If we name the configuration nodes after the DTBO that they contain then I'm not sure what this 'extensions' list gains us over having a list of overlays to apply like we do today.
Andrew
[0] https://github.com/trini/u-boot/blob/master/board/ti/am65x/evm.c#L189
To make this simpler for the common case (without extensions), we can allow multiple FDT images for a configuration, with the first one being the base SoC .dtb and the others being the .dtbo overlay(s) for the board:
confi-1 { compatible = ... fdt = "fdt-1", "fdto-1"; };
Comments welcome.
Regards, Simon

Hi,
On Tue, Dec 12, 2023 at 4:52 PM Andrew Davis afd@ti.com wrote:
On 12/12/23 8:05 AM, Simon Glass wrote:
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
For this to save much size we would need to have the SoC split from each board that uses it. We don't have that in DT today. There are some efforts in progress to help on this but until then we will not get much here.
Indeed.
E.g. The Kingfisher board[1] is an extension for (various) ULCB boards[2], but we cannot use an overlay for the former, as the combinations need to have different top-level compatible (and model) values. Hence currently we use a .dtsi file and lots of extra .dts files[3].
The other issue is the need for parameterization, due to slight differences in pins/signals on various base boards, or because the same connector is present multiple times (e.g. for multi-camera setups[4][5]).
[1] arch/arm64/boot/dts/renesas/ulcb-kf.dtsi [2] arch/arm64/boot/dts/renesas/*-ulcb.dts [3] arch/arm64/boot/dts/renesas/*-ulcb-kf.dts [4] arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov5640-single.dtsi [5] arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov7725-single.dtsi
Gr{oetje,eeting}s,
Geert

+Masahiro Yamada too
On Wed, 13 Dec 2023 at 01:22, Geert Uytterhoeven geert@linux-m68k.org wrote:
Hi,
On Tue, Dec 12, 2023 at 4:52 PM Andrew Davis afd@ti.com wrote:
On 12/12/23 8:05 AM, Simon Glass wrote:
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
For this to save much size we would need to have the SoC split from each board that uses it. We don't have that in DT today. There are some efforts in progress to help on this but until then we will not get much here.
Indeed.
E.g. The Kingfisher board[1] is an extension for (various) ULCB boards[2], but we cannot use an overlay for the former, as the combinations need to have different top-level compatible (and model) values. Hence currently we use a .dtsi file and lots of extra .dts files[3].
The other issue is the need for parameterization, due to slight differences in pins/signals on various base boards, or because the same connector is present multiple times (e.g. for multi-camera setups[4][5]).
[1] arch/arm64/boot/dts/renesas/ulcb-kf.dtsi [2] arch/arm64/boot/dts/renesas/*-ulcb.dts [3] arch/arm64/boot/dts/renesas/*-ulcb-kf.dts [4] arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov5640-single.dtsi [5] arch/arm/boot/dts/renesas/r8a7742-iwg21d-q7-dbcm-ov7725-single.dtsi
Gr{oetje,eeting}s,
Geert
-- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds

On Tue, Dec 12, 2023 at 10:06 PM Simon Glass sjg@chromium.org wrote:
Hi,
The devicetree files for a board can be quite large, perhaps around 60KB. To boot on any supported board, many of them need to be provided, typically hundreds.
All boards for a particular SoC share common parts. It would be helpful to use overlays for common pieces, to reduce the overall size.
Some boards have extension add-ons which have their own devicetree overlays. It would be helpful to know which ones should be applied for a particular extension.
I propose implementing extensions in FIT. This has a new '/extensions' node, so you can specify what extensions are available for each FIT configuration.
For example:
/ { images { kernel { // common kernel };
fdt-1 { // FDT for board1 }; fdto-1 { // FDT overlay }; fdto-2 { // FDT overlay }; fdto-3 { // FDT overlay };
};
configurations { conf-1 { compatible = ... fdt = "fdt-1"; extensions = "ext1", "ext-2"; }; };
extensions { ext-1 { fdto = "fdto-1"; // FDT overlay for this 'cape' or 'hat' kernel = "kernel-1"; compatible = "vendor,combined-device1";
I think the example would be a bit better if the extension compatibles were something like "vendor,device-X-feature-Y", so as not to be confused with device-specific compatibles for the configurations.
extensions = "ext-3";
I assume this means "existence of ext-1 makes ext-3 a valid option"?
I think a valid example would come in the form of: - ext-1 as a M.2 E-key hat, and - ext-3 as a WiFi/BT combo adapter for the M.2 slot, with BT UART and/or GPIOs described
}; ext-2 { fdto = "fdto-2"; // fdt overlay for this 'cape' compatible = "vendor,device2"; }; ext-3 { fdto = "fdto-3"; compatible = "vendor,device3"; };
}; };
So FIT configurations have a list of supported extensions. The extensions are hierarchical so that you can have ext-1 which can optionally have ext-2 as well. This allows boards to share a common SoC to add in overlays as needed by their board. It also allows common 'capes' or 'hats' to be specified only once and used by a group of boards which share the same interface.
Within U-Boot, extensions actually present are declared by a sysinfo driver for the board, with new methods:
get_compat() - determine the compatible strings for the current platform get_ext() - get a list of compatible strings for extensions which are actually present
The extension compatible-strings are used to select the correct things from the FIT, apply the overlays and produce the final DT.
To make this simpler for the common case (without extensions), we can allow multiple FDT images for a configuration, with the first one being the base SoC .dtb and the others being the .dtbo overlay(s) for the board:
confi-1 { compatible = ... fdt = "fdt-1", "fdto-1"; };
I thought this was already supported? At least that is what the FIT image spec says:
Unit name of the corresponding fdt blob (component image node of a "fdt type"). Additional fdt overlay nodes can be supplied which signify that the resulting device tree blob is generated by the first base fdt blob with all subsequent overlays applied.
Comments welcome.
Very happy to see this. This could help cut down the DT duplication for some of the ARM Chromebooks.
Thanks ChenYu
participants (5)
-
Andrew Davis
-
Chen-Yu Tsai
-
Geert Uytterhoeven
-
Heinrich Schuchardt
-
Simon Glass