using device-tree fragments/overlays

Greetings,
I'm working on some features for the imx8mm-venice boards I support which depend on making small changes to the dt before booting Linux.
The purpose is not to have any of this apply to the U-Boot controlling dt but instead to the Linux kernel dt applied within ft_board_setup. I could apply these changes with code but it would be way more readable if there was a way to store these as fragments in the FIT image and apply them.
The fragments would be small and have to do with two UART's routed to a multi-protocol RS232/RS485 transceiver that can be used as either of the following: - two tx/rx UART's (the default configuration for my dt's) - one rs232 uart with CTS/RTS flow control - one rs485 uart
Here would be an example dt overlay to apply over the default arch/arm/dts/imx8mm-venice-gw73xx-0x.dts to change it from 2x RS232 UARTS with TX/RX (uart2/uart4) to RS485 half duplex:
/* For RS485 HD: * - UART4_TX is DE for RS485 transmitter * - RS485_EN needs to be pulled high * - RS485_HALF needs to be pulled high * - RS485_TERM enables on-chip termination */ &uart2 { rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; rs485-term-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; };
&uart4 { status = "disabled"; };
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>;
pinctrl_hog: hoggrp { fsl,pins = < MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x40000104 /* RS485_TERM */ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x40000144 /* RS485_EN */ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x40000144 /* RS485_HALF */ >; };
pinctrl_uart2: uart2grp { fsl,pins = < MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140 MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140 MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29 0x140 >; }; };
Anyone do anything like this before or work with dt fragments/overlays in U-Boot or have any other suggestions?
Best regards,
Tim

Hi Tim,
I'm working on some features for the imx8mm-venice boards I support which depend on making small changes to the dt before booting Linux.
The purpose is not to have any of this apply to the U-Boot controlling dt but instead to the Linux kernel dt applied within ft_board_setup. I could apply these changes with code but it would be way more readable if there was a way to store these as fragments in the FIT image and apply them.
The fragments would be small and have to do with two UART's routed to a multi-protocol RS232/RS485 transceiver that can be used as either of the following:
- two tx/rx UART's (the default configuration for my dt's)
- one rs232 uart with CTS/RTS flow control
- one rs485 uart
Here would be an example dt overlay to apply over the default arch/arm/dts/imx8mm-venice-gw73xx-0x.dts to change it from 2x RS232 UARTS with TX/RX (uart2/uart4) to RS485 half duplex:
/* For RS485 HD:
- UART4_TX is DE for RS485 transmitter
- RS485_EN needs to be pulled high
- RS485_HALF needs to be pulled high
- RS485_TERM enables on-chip termination
*/ &uart2 { rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; rs485-term-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; };
&uart4 { status = "disabled"; };
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>;
pinctrl_hog: hoggrp { fsl,pins = < MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0
0x40000104 /* RS485_TERM */ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x40000144 /* RS485_EN */ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x40000144 /* RS485_HALF */ >; };
pinctrl_uart2: uart2grp { fsl,pins = < MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140 MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140 MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29 0x140 >; };
};
Anyone do anything like this before or work with dt fragments/overlays in U-Boot or have any other suggestions?
A feature for overlays landed upstream in May [1], so the 2021,07 release, so I'm sure there's most of the functionality you require already upstream. Not sure how a user would specify which of the variants to use or how it would load it from the FIT but I'm sure the patch series provides you a good start point.
Peter
[1] https://lists.denx.de/pipermail/u-boot/2021-May/448794.html

On Wed, Oct 13, 2021 at 1:38 AM Peter Robinson pbrobinson@gmail.com wrote:
Hi Tim,
I'm working on some features for the imx8mm-venice boards I support which depend on making small changes to the dt before booting Linux.
The purpose is not to have any of this apply to the U-Boot controlling dt but instead to the Linux kernel dt applied within ft_board_setup. I could apply these changes with code but it would be way more readable if there was a way to store these as fragments in the FIT image and apply them.
The fragments would be small and have to do with two UART's routed to a multi-protocol RS232/RS485 transceiver that can be used as either of the following:
- two tx/rx UART's (the default configuration for my dt's)
- one rs232 uart with CTS/RTS flow control
- one rs485 uart
Here would be an example dt overlay to apply over the default arch/arm/dts/imx8mm-venice-gw73xx-0x.dts to change it from 2x RS232 UARTS with TX/RX (uart2/uart4) to RS485 half duplex:
/* For RS485 HD:
- UART4_TX is DE for RS485 transmitter
- RS485_EN needs to be pulled high
- RS485_HALF needs to be pulled high
- RS485_TERM enables on-chip termination
*/ &uart2 { rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; rs485-term-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; };
&uart4 { status = "disabled"; };
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>;
pinctrl_hog: hoggrp { fsl,pins = < MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0
0x40000104 /* RS485_TERM */ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x40000144 /* RS485_EN */ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x40000144 /* RS485_HALF */ >; };
pinctrl_uart2: uart2grp { fsl,pins = < MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140 MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140 MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29 0x140 >; };
};
Anyone do anything like this before or work with dt fragments/overlays in U-Boot or have any other suggestions?
A feature for overlays landed upstream in May [1], so the 2021,07 release, so I'm sure there's most of the functionality you require already upstream. Not sure how a user would specify which of the variants to use or how it would load it from the FIT but I'm sure the patch series provides you a good start point.
Peter
[1] https://lists.denx.de/pipermail/u-boot/2021-May/448794.html
Peter,
Thanks - this is very helpful and is what I was looking for. My plan is to use the hwconfig env var for users to select how they want serial configured. I can use the methods used in the extension_apply function and it seems appropriate for me to put dtbo's on the root filesystem with the dtb's when using this.
Best regards,
Tim

Hi,
On Thu, Oct 14, 2021 at 08:13:55AM -0700, Tim Harvey wrote:
On Wed, Oct 13, 2021 at 1:38 AM Peter Robinson pbrobinson@gmail.com wrote:
Hi Tim,
I'm working on some features for the imx8mm-venice boards I support which depend on making small changes to the dt before booting Linux.
The purpose is not to have any of this apply to the U-Boot controlling dt but instead to the Linux kernel dt applied within ft_board_setup. I could apply these changes with code but it would be way more readable if there was a way to store these as fragments in the FIT image and apply them.
The fragments would be small and have to do with two UART's routed to a multi-protocol RS232/RS485 transceiver that can be used as either of the following:
- two tx/rx UART's (the default configuration for my dt's)
- one rs232 uart with CTS/RTS flow control
- one rs485 uart
Here would be an example dt overlay to apply over the default arch/arm/dts/imx8mm-venice-gw73xx-0x.dts to change it from 2x RS232 UARTS with TX/RX (uart2/uart4) to RS485 half duplex:
/* For RS485 HD:
- UART4_TX is DE for RS485 transmitter
- RS485_EN needs to be pulled high
- RS485_HALF needs to be pulled high
- RS485_TERM enables on-chip termination
*/ &uart2 { rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; rs485-term-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; };
&uart4 { status = "disabled"; };
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>;
pinctrl_hog: hoggrp { fsl,pins = < MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0
0x40000104 /* RS485_TERM */ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x40000144 /* RS485_EN */ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x40000144 /* RS485_HALF */ >; };
pinctrl_uart2: uart2grp { fsl,pins = < MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140 MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140 MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29 0x140 >; };
};
Anyone do anything like this before or work with dt fragments/overlays in U-Boot or have any other suggestions?
A feature for overlays landed upstream in May [1], so the 2021,07 release, so I'm sure there's most of the functionality you require already upstream. Not sure how a user would specify which of the variants to use or how it would load it from the FIT but I'm sure the patch series provides you a good start point.
Peter
[1] https://lists.denx.de/pipermail/u-boot/2021-May/448794.html
Peter,
Thanks - this is very helpful and is what I was looking for. My plan is to use the hwconfig env var for users to select how they want serial configured. I can use the methods used in the extension_apply function and it seems appropriate for me to put dtbo's on the root filesystem with the dtb's when using this.
If you have control over the FIT image creation and the uboot scripts, it might not even needed:
https://source.denx.de/u-boot/u-boot/-/blob/master/doc/uImage.FIT/overlay-fd...
Maxime

Hi Tim,
On 10/7/21 4:07 PM, Tim Harvey wrote:
Greetings,
I'm working on some features for the imx8mm-venice boards I support which depend on making small changes to the dt before booting Linux.
The purpose is not to have any of this apply to the U-Boot controlling dt but instead to the Linux kernel dt applied within ft_board_setup. I could apply these changes with code but it would be way more readable if there was a way to store these as fragments in the FIT image and apply them.
The fragments would be small and have to do with two UART's routed to a multi-protocol RS232/RS485 transceiver that can be used as either of the following:
- two tx/rx UART's (the default configuration for my dt's)
- one rs232 uart with CTS/RTS flow control
- one rs485 uart
Here would be an example dt overlay to apply over the default arch/arm/dts/imx8mm-venice-gw73xx-0x.dts to change it from 2x RS232 UARTS with TX/RX (uart2/uart4) to RS485 half duplex:
/* For RS485 HD:
- UART4_TX is DE for RS485 transmitter
- RS485_EN needs to be pulled high
- RS485_HALF needs to be pulled high
- RS485_TERM enables on-chip termination
*/ &uart2 { rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; rs485-term-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; };
&uart4 { status = "disabled"; };
&iomuxc { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_hog>;
pinctrl_hog: hoggrp { fsl,pins = < MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0
0x40000104 /* RS485_TERM */ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x40000144 /* RS485_EN */ MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x40000144 /* RS485_HALF */ >; };
pinctrl_uart2: uart2grp { fsl,pins = < MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140 MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140 MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29 0x140 >; };
};
Anyone do anything like this before or work with dt fragments/overlays in U-Boot or have any other suggestions?
I had the exact same use case. A couple of prerequisites:
* Compile kernel DTB with __symbols__ ('-@' argument to dtc) * Enable FIT devicetree overlays in u-boot - Slightly different CONFIG_s for loading FITs from u-boot or SPL * Assemble a FIT with overlays in it
I think there's also a way to do apply overlays from the u-boot commandline, but I never found that to be intuitive.
You might have to specify a "loadaddr=" for the overlays if you're loading the FIT from u-boot instead of SPL. AFAIR the u-boot FIT loader is defective in this regard.
Alex
APPENDIX A: Example FIT ITS
/dts-v1/ ;/ { description = "Flu-boot image with overlays"; #address-cells = <1>; images { kernel-1 { description = "Linux kernel"; data = /incbin/("kernel/zImage"); type = "kernel"; arch = "arm"; os = "linux"; compression = "none"; load = <0xc2000040>; entry = <0xc2000040>; hash-1 { algo = "sha256"; }; };
fdt-stm32mp157c-dk2.dtb { description = "Flattened Device Tree blob"; data = /incbin/("kernel/stm32mp157c-dk2.dtb"); type = "flat_dt"; arch = "arm"; compression = "none"; hash-1 { algo = "sha256"; }; }; fdt-dk2-can1-enable.dto { description = "Flattened Device Tree blob"; data = /incbin/("overlays/dk2-can1-enable.dto"); type = "flat_dt"; arch = "arm"; compression = "none"; hash-1 { algo = "sha256"; }; }; }; configurations { secure-stm32mp157c-dk2.dtb { description = "Linux for stm32mp157c-dk2.dtb"; kernel = "kernel-1"; fdt = "fdt-stm32mp157c-dk2.dtb", "fdt-dk2-can1-enable.dto"; hash-1 { algo = "sha256"; }; }; }; };
participants (4)
-
Alex G.
-
Maxime Ripard
-
Peter Robinson
-
Tim Harvey