Changing GPIO behaviour using Device Tree Overlay

Hi,

I am using a Verdin iMX8M Plus module (currently on a Verdin Development Board), trying to change the (GPIO) behaviour of different pins using Device Tree Overlay.

The way I test is by modifying overlays/verdin-imx8mp_hmp_overlay.dts, re-building it following the Toradex documentation, and then load the overlay using the Toradex documentation:

This is the lines I add to overlays/verdin-imx8mp_hmp_overlay.dts to change the configuration of a pin:

#include "imx8mp.dtsi"
#include "imx8mp-verdin.dtsi"
#include "imx8mp-pinfunc.h"

(.....)

&iomuxc {
	pinctrl_gpio1_io00_disabled: disable_pinctrl_gpio1_io00 {
		fsl,pins = <MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00 0x0F>;
	};
};

&gpio1 {
	gpio1_io00: gpio1_io00_output {
		gpio-hog;
		gpios = <0 GPIO_ACTIVE_HIGH>;
		output-high;
		line-name = "gpio1_io00_output";
		status = "okay";
	};
};

But the direction of GPIO 1 0 (gpiochip0 0 - SODIMM_206) does not change.

Can you lead me in the correct direction of handling GPIOs using Device Tree Overlays?

Hi, I’m the Toradex AI Assistant. The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello,

To address the issue of changing GPIO behavior using Device Tree Overlays on your Verdin iMX8M Plus module, let’s ensure that your overlay is correctly configured and applied.

  1. Verify Pin Control Configuration:

    • Ensure that the pin control node is correctly defined in your overlay. The iomuxc node should include the correct pin settings, as you have done with pinctrl_gpio1_io00_disabled. Double-check the pin function and control settings to ensure they match the intended configuration.
  2. Check GPIO Node Configuration:

    • The GPIO node should be correctly defined with the gpio-hog property, as you have done. Ensure that the gpios property is correctly set, and the output-high or output-low directive is used as needed.
  3. Overlay Application:

    • After modifying the overlay, ensure it is compiled into a .dtbo file and placed in the correct location on the boot partition.
    • Update the overlays.txt file to include your custom overlay and run the sync command before rebooting the system. This ensures that changes are written to the file system.
  4. Check for Conflicts:

    • Ensure there are no conflicting overlays or pre-enabled overlays that might override your settings. You can list the currently applied overlays to verify this.
  5. Reboot Properly:

    • After making changes, reboot the system without power-cycling to ensure the overlay is applied correctly.

By following these steps, you should be able to modify the GPIO behavior as intended. If the issue persists, double-check the syntax and ensure there are no typos or misconfigurations in your overlay file.

Best regards,
Toradex AI Assistant

Please, also check if these links can help you solve your problem:

Verdin iMX8M - Device Tree Overlay, GPIO Output, Default State.

Hello @erikr,

I see that you are using the verdin-imx8mp_hmp_overlay.dts overlay, which is intended for use cases with the Cortex-M7 core.
Do you want to configure the pinmuxing for the Cortex-M7 in the device tree?
If yes, this is not possible. the Cortex-M7 needs to configure the pinmuxing for the pins which it will use. The device tree must not use such pins to avoid conflicts between Linux and the Cortex-M.

Otherwise, the issue you see with the gpio1_io00 configuration looks to be due to the fact that from your device tree overlay snippet, pinctrl_gpio1_io00_disabled is not added to pinctrl-0 from iomuxc.
Therefore, the following additional entry would be needed in your iomuxc node:

pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>,
		    <&pinctrl_gpio3>, <&pinctrl_gpio4>,
		    <&pinctrl_gpio7>, <&pinctrl_gpio8>,
		    <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>, <&pinctrl_gpio_hog4>,
		    <&pinctrl_hdmi_hog>, <&pinctrl_gpio1_io00_disabled>;

Additionally, please note that the pad configuration of 0x0F is setting reserved register bits in the SW_PAD_CTL_PAD_GPIO1_IO00 SW PAD Control Register, the recommended values for GPIOs are usually 0x1c4 (Weak pull-up) or 0x184 (Weak pull-down).
For more details, please check Section 8.2.4.153 SW_PAD_CTL_PAD_GPIO1_IO00 SW PAD Control Register (IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00) of the i.MX8MP Reference Manual.

Best Regards,
Bruno

Thank you @bruno.tx

I will do some more testing and let you know.

Hi @bruno.tx

I have done some testing now, and created my own .dts file:

/dts-v1/;
/plugin/;

#include "imx8mp.dtsi"
#include "imx8mp-verdin.dtsi"
#include "imx8mp-pinfunc.h"

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>,
			    <&pinctrl_gpio3>, <&pinctrl_gpio4>,
			    <&pinctrl_gpio7>, <&pinctrl_gpio8>,
			    <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>, <&pinctrl_gpio_hog4>,
			    <&pinctrl_hdmi_hog>, <&pinctrl_gpio4_io24_config>;

	/* LED 0 */
	pinctrl_gpio4_io24_config: gpio4_io24_pullup {
		fsl,pins = <
			MX8MP_IOMUXC_SAI2_TXFS__GPIO4_IO24 0x1c4 /* Weak pull-up */
		>;
	};
};

&gpio4 {
	/* LED 0 */
	gpio4_io24: gpio4_io24_output {
		gpio-hog;
		gpios = <24 GPIO_ACTIVE_HIGH>;
		output-high;
		line-name = "gpio4_io24_output";
		status = "okay";
	};
};

Unfortunately, when I include the built overlay file (I have verified that the include process itself work), GPIO4 IO24 is not changed to output.

Do you see what is wrong with this .dts file?

Hello @erikr,

Thanks for the update.
Are you trying to use SAI2_TXFS (SODIMM_133) or GPIO1_IO00 (SODIMM_206)?
Regardless of the pin(s) you want to use, you need to make sure they are not used elsewhere in your device tree.

Another relevant point here is that the following includes should not be used in your device tree overlay:

#include "imx8mp.dtsi"
#include "imx8mp-verdin.dtsi"

These are .dtsi files which are part of your base device tree and should not be included in your overlay. By doing so, it is likely that you are reverting some of the board-specific configuration present in your device tree.

Best Regards,
Bruno

@bruno.tx
Thanks for the quick reply!

I am trying to configure/use SODIMM_133.
How I understands it, this value:
MX8MP_IOMUXC_SAI2_TXFS__GPIO4_IO24
Says, “MUX the SAI2_TXFS to being GPIO4_IO24”.
Is this correct?

Hello @erikr,

Your understanding is correct, the MX8MP_IOMUXC_SAI2_TXFS__GPIO4_IO24 configures the SAI2_TXFS pin (SODIMM_133) to be a GPIO.

What may be the problem here is that this pin is used somewhere else in your device tree.
In this case, it is used in pinctrl_uart1: imx8mp-verdin.dtsi « freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules
Which is used by uart1: imx8mp-verdin.dtsi « freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules

Therefore, to use this pin you need to disable the uart1 node.

To configure pins with non-default configurations, you always need to search for the current configuration on the device tree and make sure it is not being used.

Best Regards,
Bruno

Hello @erikr,

Were you able to get this resolved?
Or do you need further support with this topic?

Best Regards,
Bruno

Hi @bruno.tx

Thanks for following up, and sorry for the delay.

I have tried some more on this issue, but I am still stuggling to get pins to act as GPIO outputs. And I have not been able to build my .dts files without "#include “imx8mp-verdin.dtsi”.

This is the latest .dts file I have created. The goal is to make GPIO1_IO00 an output GPIO. Do you see anything wrong with this file?
Again: I must include “imx8mp-verdin.dtsi”.
If I load the built dts file and check the pin (SODIMM_206) using gpioinfo, it always shows as input.

/dts-v1/;
/plugin/;

#include "imx8mp-verdin.dtsi" // TODO: Must be included to get the iomuxc definitions?
#include "imx8mp-pinfunc.h"

/ {
    compatible = "toradex,verdin-imx8mp";
};

&iomuxc {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_gpio1_io00_config>;

    pinctrl_gpio1_io00_config: gpio1_io00_grp {
        fsl,pins = <
            MX8MP_IOMUXC_GPIO1_IO00__GPIO1_IO00 0x140  /* Output with no pull */
        >;
    };
};

&gpio1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_gpio1_io00_config>;
    
    gpio1_io00_hog: gpio1_io00 {
        gpio-hog;
        gpios = <0 GPIO_ACTIVE_HIGH>;
        output-high;
        line-name = "gpio1_io00";
    };
};

Hello @erikr,

Which error do you get when trying to build the overlay with #include "imx8mp-verdin.dtsi"?

It really should not be there, as adding this include means that all the configurations on the imx8mp-verdin.dtsi file will be carried over to your overlay, not just definitions as you may think in a c header file.

I also see that you have not disabled uart1, as I recommended in my previous post.
To do that, the following must be added to your overlay:

&uart1 {
    status = "disabled";
};

Best Regards,
Bruno

Hi @bruno.tx ,

The “&gpio1” part needed the #include “imx8mp-verdin.dtsi” to compile. I added this to change the pin direction, but I realized now that I am able to change the pin direction from Linux directly using e.g. gpiochip0 0=1 to change the pin to an output.
This means that I only need to do the PINMUX using overlays, and then it looks like that I am able to compile.

Is this correct thinking?

Hello @erikr,

Please note that this is not how device tree sources work, by including imx8mp-verdin.dtsi you are applying all the changes from that file in your overlay.
If without this include the device tree would not compile, this means that you were missing a definition that is found in a .h file which by chance was included by imx8mp-verdin.dtsi.
In this case, it seems you may have missed #include <dt-bindings/gpio/gpio.h>.

This is correct, you can set the direction on linux if this satisfies your requirements.

Best Regards,
Bruno

@bruno.tx

Thank you for the quick replies. I am starting to get what I need now.

One more question:
If I do this in an overlay file, will I then remove the RTS and CTS functionality from UART 1, meaning that I can use these pins (the pins that were set as RTS and CTS) as regular GPIOs?

&uart1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart1>;
};

&iomuxc {
    pinctrl_uart1: uart1grp {
		fsl,pins =
			<MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX		0x1c4>,	/* SODIMM 129 */
			<MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX		0x1c4>;	/* SODIMM 131 */
	};
};

Hello @erikr,

When it comes to uart1 on the Verdin Development Board we get to a very specific case:

This port is connected to an RS485 transceiver, which needs the RTS signal to toggle the driving mode.
Therefore, to use it as an RS485 port, RTS cannot be used as a GPIO.

Now, let’s say that you do not want to use this port as an RS485 port, you end up in another special case:
This node has the uart-has-rtscts property, which needs to be removed.
However, device tree overlays do not apply /delete-property/ property on the original device tree.
Therefore, to solve this, you need to disable the existing uart1 node and create a new one on your device-tree overlay:

&uart1 {
	status = "disabled";
};

&pinctrl_uart1 {
	fsl,pins =
				<MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX		0x1c4>,	/* SODIMM 129 */
				<MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX		0x1c4>;	/* SODIMM 131 */
};

&aips3 {
	uart1-custom: serial@30860000 {
		compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart";
		reg = <0x30860000 0x10000>;
		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
		clocks = <&clk IMX8MP_CLK_UART1_ROOT>,
			 <&clk IMX8MP_CLK_UART1_ROOT>;
		clock-names = "ipg", "per";
		dmas = <&sdma1 22 4 0>, <&sdma1 23 4 0>;
		dma-names = "rx", "tx";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_uart1>;
		status = "okay";
	};
};

Notes about the following in the snippet above:

  • I combined the definitions of the uart1 nodes from imx8mp-verdin.dtsi and imx8mp.dtsi.
  • Some includes may be missing, I recommend checking the imx8mp.dtsi file for dt-bindings .h includes.
  • pinctrl_uart1 was not redeclared as in your last message, but modified.
  • It only enables the use of uart1 without RTS and CTS, doing nothing to configure the now unused RTS and CTS pins as GPIOs.

To actually use the RTS and CTS pins as GPIOs, you will need to configure a new pinctrl node for them and add it to iomuxc. For more details, please check out pinmuxing guide.

Hopefully this explanation improves your understanding of device trees.
Most of this information is documented in our developer website documentation about device trees, so it is certainly worth a read while looking at some actual device trees: Device Tree Documentation Overview | Toradex Developer Center

Best Regards,
Bruno

@bruno.tx Thank you for great answers!
I think I know what I need to know now.

1 Like