Device Tree Customization Overwriting lcdif for imx7D Colibri

I’m trying to determine why overwriting a node according to the: Device Tree Customization document does not seem to work.

I am following the suggestion in the document to create a carrier board specific file where changes to nodes can be made to add or modify properties that are specific to our carrier board. The node that I’m attempting to overwrite is first defined in the imx7s.dtsi file:

lcdif: lcdif@30730000 {
				compatible = "fsl,imx7d-lcdif", "fsl,imx28-lcdif";
				reg = <0x30730000 0x10000>;
				interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX7D_LCDIF_PIXEL_ROOT_CLK>,
					<&clks IMX7D_CLK_DUMMY>,
					<&clks IMX7D_CLK_DUMMY>;
				clock-names = "pix", "axi", "disp_axi";
				status = "disabled";
};

It is then overwritten in the imx7-colibri-eval-v3.dtsi file:

&lcdif {
 	display = <&display0>;
 	status = "okay";

 	display0: lcd-display {
 		bits-per-pixel = <16>;
 		bus-width = <18>;

 		display-timings {
 		        native-mode = <&timing_wvga>;

 			/* Standard VGA timing */
 			timing_vga: 640x480 {
 				clock-frequency = <25175000>;
 				hactive = <640>;
 				vactive = <480>;
 				hback-porch = <40>;
 				hfront-porch = <24>;
    			        vback-porch = <32>;
  				vfront-porch = <11>;
 				hsync-len = <96>;
				vsync-len = <2>;

				de-active = <1>;
				hsync-active = <0>;
				vsync-active = <0>;
				pixelclk-active = <0>;
			};

			/* WVGA Timing, e.g. EDT ET070080DH6 */
			timing_wvga: 800x480 {
				clock-frequency = <33260000>;
				hactive = <800>;
				vactive = <480>;
				hback-porch = <216>;
				hfront-porch = <40>;
				vback-porch = <35>;
				vfront-porch = <10>;
				hsync-len = <128>;
				vsync-len = <2>;

				de-active = <1>;
				hsync-active = <0>;
				vsync-active = <0>;
				pixelclk-active = <0>;
			};
			/* WVGA Timing, TouchRevolution Fusion 7" */
			timing_wvga2: 800x480pixclkact {
				clock-frequency = <33260000>;
				hactive = <800>;
				vactive = <480>;
				hback-porch = <216>;
				hfront-porch = <40>;
				vback-porch = <35>;
				vfront-porch = <10>;
				hsync-len = <128>;
				vsync-len = <2>;

				de-active = <1>;
				hsync-active = <0>;
				vsync-active = <0>;
				pixelclk-active = <1>;
			};
			/* Standard SVGA timing */
			timing_svga: 800x600 {
				clock-frequency = <40000000>;
				hactive = <800>;
				vactive = <600>;
				hback-porch = <88>;
				hfront-porch = <40>;
				vback-porch = <23>;
				vfront-porch = <1>;
				hsync-len = <128>;
				vsync-len = <4>;

				de-active = <1>;
				hsync-active = <1>;
				vsync-active = <1>;
				pixelclk-active = <0>;
			};
			/* TouchRevolution Fusion 10"/CLAA101NC05 10.1 inch */
			timing_wsvga: 1024x600 {
				clock-frequency = <48000000>;
				hactive = <1024>;
				vactive = <600>;
				hback-porch = <104>;
				hfront-porch = <43>;
				vback-porch = <24>;\
				vfront-porch = <20>;
				hsync-len = <5>;
				vsync-len = <5>;

				de-active = <1>;
				hsync-active = <0>;
				vsync-active = <0>;
				pixelclk-active = <0>;
			};
			/* Standard XGA timing */
			timing_xga: 1024x768 {
				clock-frequency = <65000000>;
				hactive = <1024>;
				vactive = <768>;
				hback-porch = <160>;
				hfront-porch = <24>;
				vback-porch = <29>;
				vfront-porch = <3>;
				hsync-len = <136>;
				vsync-len = <6>;

				de-active = <1>;
				hsync-active = <0>;
				vsync-active = <0>;
				pixelclk-active = <0>;
			};
		};
	};
};

I am overwritting this in our carrier board specific file imx7d-colibri-p1100.dts:

&lcdif {
	display = <&display0>;
	status = "okay";

	display0: lcd-display {
		bits-per-pixel = <16>;
		bus-width = <18>;

		display-timings {
			native-mode = <&my_wvga>;
			my_wvga: 800x480Tesco {
				clock-frequency = <40000000>;
				hactive = <800>;
				vactive = <480>;
				hback-porch = <40>;
				hfront-porch = <40>;
				vback-porch = <34>;
				vfront-porch = <13>;
				hsync-len = <45>;
				vsync-len = <3>; // 0x3E
		
				de-active = <1>;
				hsync-active = <0>;
				vsync-active = <0>;
				pixelclk-active = <0>;
			};
		};
	};
};

When I build the file imx7d-colibri-p1100.dtb it will build successfully, but when I update the imx7d with the new dtb file I build it is using the definition of lcdif in the imx7-colibri-eval-v3.dtsi file, not the overwritten lcdif in the imx7d-colibri-p1100.dts file.

My understanding, based on the information in the Device Tree Customization document linked above, is that overwritting nodes in later dtsi files overwrites nodes from earlier dtsi files.

I don’t understand why my overwrite did not work? Can nodes only be overwritten one time?

The only way that I’ve been able to get this to work is to completely comment out the overwrite of the lcdif node in the imx7-colibri-eval-v3.dtsi file. Then the overwrite in the imx7d-colibri-p1100.dts file will work.

Thank You

Overriding needs to be used with care. My guess is that you include imx7-colibri-eval-v3.dtsi at the top of imx7d-colibri-p1100.dts, hence your override ends up to be after the initial definition. As the documentation states:

Typically the higher layers (e.g. carrier board device tree) overwrite the lower layers (e.g. SoC device tree) since the higher layers include the lower layers at the very beginning.

I would recommend to not include our carrier board level device tree (in this case imx7-colibri-eval-v3.dtsi) but just make a copy of it. If you know that you will only use Colibri iMX7 Dual, you can omit the extra imx7-colibri-.../imx7d-colibri-... separation by just merge the two and create a single imx7d-colibri-p1100.dts which includes imx7d-colibri.dtsi.

Update: Actually my description above is wrong, imx7d-colibri-p1100.dts should really overwrite the setting in imx7-colibri-eval-v3.dtsi. In quick test I used fdtdump to examine the binary, it really seems that in this setting you should be able to overwrite the node. However, as mentioned, it is recommended to not include our carrier board level device tree but directly include the module level device tree.

stefan.tx,

Beautiful! Thank you so much for this information. It’s exactly what I needed. I was including the Toradex carrier board file: imx7-colibri-eval-v3.dtsi at the beginning of our imx7d-colibri-p1100.dts file as you said. I combined the contents of the: imx7-colibri-eval-v3.dtsi file into our: imx7d-colibri-p1100.dts file and it works the way we need! Sweet!

So, the overwrite only works between levels right? The reason the overwrite did not work the way that I expected was because I was trying to perform a node overwrite in the imx7d-colibri-p1100.dts file of what was in the imx7-colibri-eval-v3.dtsi file, but this will not work because both of these files are considered to be at the carrier board level according to the device tree flow image in the Device Tree Customization document. Is this correct?

What you have recommended to do to solve our problem works, and I very much appreciate your help with this.

Thank You!

The device tree files just use the regular preprocessor, which basically copy & pastes the content of every included file. In the end, neither the preprocessor nor the device tree compiler is really aware of soc/module/carrier board level device trees, its just a single combined file (that file is actually usually available as a hidden file, e.g. arch/arm/boot/dts/.imx7d-colibri-eval-v3.dtb.dts.tmp.

But we structured our module level device tree such that you almost never need to overwrite something. Instead, you just add nodes, and that works always…