Set GPIO output in Device Tree

Hi there

I want to put a GPIO pin (SODIMM 222) high on boot with a device tree overlay. However, I’m struggling a bit getting it to work properly. When manually writing to GPIO 97 in the FS (echo 1 > …) i can see the output jump to high. On boot however, it remains stuck low.
I am using a i.MX8MP Verdin

This is in my Device tree overlay so far:

/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include "imx8mp-verdin.dtsi"
#include "imx8mp-pinfunc.h"

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

&iomuxc {
    pinctrl_gpio8_mod: gpio8grp_mod {
        fsl,pins = <MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x105>;
    };
};

&gpio4 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_gpio8_mod>;
    sodimm222_hog: sodimm222_hog {
        gpio-hog;
        gpios = <1 GPIO_ACTIVE_HIGH>; /* GPIO4_IO01 = SODIMM 222 */
        output-high;
        line-name = "sodimm-222";
    };
};

From the datasheet:
image
and reference manual:

cat /sys/kernel/debug/gpio
...
gpiochip3: GPIOs 96-127, parent: platform/30230000.gpio, 30230000.gpio:
 gpio-96  (SODIMM_252          |Wake-Up             ) in  hi ACTIVE LOW
 gpio-97  (SODIMM_222          )
 gpio-98  (SODIMM_36           )

But somehow this does not translate to what i am seeing in /sys/kernel/debug/pinctrl/30330000.pinctrl/ :

pin 83 (MX8MP_IOMUXC_SAI1_RXC): 30330000.pinctrl (GPIO UNCLAIMED) (HOG) function pinctrl group gpio8grp

pin 97 (MX8MP_IOMUXC_SAI1_TXD3): 30be0000.ethernet (GPIO UNCLAIMED) function pinctrl group fecgrp

So what is going on here? How can I set SODIMM 222 high?

Best Regards
Tim

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello Tim,

Thanks for providing all the details and device tree snippet. Let’s go step by step to address your goal: setting SODIMM 222 (GPIO4_IO01, Linux GPIO 97) high at boot on a Verdin iMX8MP using a device tree overlay.

Analysis and Guidance

1. Device Tree Overlay Structure

Your overlay is mostly correct, but there are a few subtle issues:

  • The compatible string in the overlay should be as generic as possible or match your board’s base device tree.
  • Including dtsi and pinfunc headers is typically not required in overlays (the base device tree already includes them).
  • The pinmux setting (0x105) should match your electrical requirements, but 0x1b0b0 is more commonly used for GPIO (see below).

2. Pinmux configuration

The key to making the hog work is setting the correct pad control and ensuring no other DTS node claims the pin in parallel.

Here’s a simplified and corrected example you can use as your overlay:

/dts-v1/;
/plugin/;

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

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

    pinctrl_sodimm222: sodimm222grp {
        fsl,pins = <
            MX8MP_IOMUXC_SAI1_RXC__GPIO4_IO01 0x1b0b0
        >;
    };
};

&gpio4 {
    sodimm222_hog: sodimm222_hog {
        gpio-hog;
        gpios = <1 GPIO_ACTIVE_HIGH>;
        output-high;
        line-name = "sodimm-222";
    };
};

Key points:

  • Use 0x1b0b0 as the pad setting for a generic, strong-pull-up, fast slew GPIO.
  • Make sure the pin isn’t being used anywhere else (check your base device tree, verify it’s not used for SAI1 or any other peripheral).
  • The gpio-hog will set the pin as output and drive it high.

3. Make Sure There are No Conflicts

  • In /sys/kernel/debug/gpio, you should see gpio-97 as “sodimm-222” and OUT HI.
  • In /sys/kernel/debug/pinctrl/30330000.pinctrl/, check that MX8MP_IOMUXC_SAI1_RXC is assigned to your hog (not unclaimed).
  • If still “GPIO UNCLAIMED,” it’s possible another DTS fragment is conflicting. Double-check the base device tree and overlays that SAI1_RXC is not assigned to any SAI1 function.

Details here:

4. Deploy and Test

  1. Deploy the overlay as described in the Toradex documentation.
  2. Reboot and check:
    • cat /sys/kernel/debug/gpio to confirm the hog.
    • cat /sys/kernel/debug/pinctrl/30330000.pinctrl for pin assignment.

5. Troubleshooting

  • If the pin still isn’t claimed by the hog, try removing any unneeded overlay includes and keep the compatible entry short, as shown above.
  • If a conflict persists, search your base device tree and overlays for any occurrences of sai1 or the pin in question (SAI1_RXC or GPIO4_IO01) and comment those sections out if not needed.

Let me know if this overlay and these steps solve your issue or if you see further problems!

Best regards,
Toradex AI Assistant.

Reference:

One major error is that I had

#include "imx8mp-verdin.dtsi"

included, which probably ended up overwriting the things in the overlay. With this fixed, I ran into the next issue:

[    1.122965] imx8mp-pinctrl 30330000.pinctrl: pin MX8MP_IOMUXC_SAI1_RXC already requested by 30330000.pinctrl; cannot claim for 3023000o
[    1.135712] imx8mp-pinctrl 30330000.pinctrl: pin-83 (30230000.gpio) status -22
[    1.143112] imx8mp-pinctrl 30330000.pinctrl: could not request pin 83 (MX8MP_IOMUXC_SAI1_RXC) from group gpio8grp  on device 30330000.l
[    1.155993] gpio-mxc 30230000.gpio: Error applying setting, reverse things back

I then tried out the pin 97 as seen in /sys/kernel/debug/pinctrl/30330000.pinctrl/pins, which is MX8MP_IOMUXC_SAI1_TXD3__GPIO4_IO15.

I now have now output high on SODIMM 222… which is what i wanted, but now im even more confused:

 gpio-96  (SODIMM_252          |Wake-Up             ) in  hi ACTIVE LOW
 gpio-97  (SODIMM_222          |sodimm-222          ) out hi 
 gpio-98  (SODIMM_36           )

Why is GPIO4_IO15 doing SODIMM 222??
Datasheet again:
image

I use the verdin dev board btw…

In the case of “normal” GPIO use, the state of a GPIO pin cannot be defined solely by the Device Tree. You need to set its state at runtime using the sysfs GPIO interface or via libgpiod.

While you can configure a GPIO’s default state using the gpio-hog; property, doing so reserves the pin permanently, making it unavailable for later manipulation.

In the Linux Device Tree, the gpio-hog; property (within a GPIO controller node) is used to “hog” (pre-allocate) GPIO pins at boot time. This means the pins are reserved and locked into a fixed state by the OS, preventing other drivers or userspace from modifying them.

Hi @TimSiegrist !

Just some initial reference information about the pin MX8MP_IOMUXC_SAI1_RXC (SODIMM 222):

In your overlay, you are creating yet another pin control group (pinctrl_gpio8_mod) and using it to configure the same SODIMM 222 (as GPIO) and this what you see in your boot log:

Is it possible that you are confusing the gpio-* numbering with SODIMM numbering here? Linux provides a GPIO index to the pins and these numbers are generated by the Linux kernel (the gpio-* you got). They do not have a 1:1 correspondence with the SODIMM numbering scheme (which is given by the hardware: these are the pin position on the edge connector of the module).

So, just looking at what you shared, I think it is safe to assume that gpio-97 == SODIMM 222 == MX8MP_IOMUXC_SAI1_RXC == GPIO4_IO01 returns true :slight_smile:

The explanation above should help to answer this question. If not, let us know!


Now, let me try to directly help you on what you would like to accomplish :slight_smile:

I see you want a different pad configuration for the SODDIM 222 from the one default in our device tree (default is 0x184 and you are using 0x105). So, because of this, it makes sense to create your new pinctrl_gpio8_mod. Or you could overlay the &pinctrl_gpio8’s fsl,pins. Your call :slight_smile:

In the &iomuxc, you will need to tweak its pinctrl-0 because as it is, it applies the pinctrl_group8 configuration for SODIMM 222, which clashes with your gpio-hog. So you can do something like this in you &iomuxc’s pinctrl-0 property:

...
&iomuxc {
	pinctrl-0 = <&pinctrl_gpio1>, <&pinctrl_gpio2>,
		    <&pinctrl_gpio3>, <&pinctrl_gpio4>,
		    <&pinctrl_gpio7>,
		    <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>, <&pinctrl_gpio_hog4>,
		    <&pinctrl_hdmi_hog>;
    pinctrl_gpio8_mod: ...
};
...

Please note that I got the value assigned to pinctrl-0 from imx8mp-verdin-wifi.dtsi « freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules and just deleted the <&pinctrl_gpio8> from it. Therefore, when the overlay is applied, even though the pinctrl_gpio8 configuration still exists itself, it won’t be applied in here.

If you are using a Verdin iMX8MP without Wi-Fi, please be sure to get the default pinctrl-0 value from the imx8mp-verdin-nonwifi.dtsi instead of imx8mp-verdin-wifi.dtsi :wink:

Please keep in mind that what @alex.tx shared holds: this GPIO will not be able to be controlled in runtime.

And another possibly important piece of information (which I actually expect to not affect you): this configuration via device tree [overlay] won’t take place as soon as the module is powered. After it is powered, we have some early stages of the boot that happen before the kernel (therefore, before the overlay is applied), so there might be a few seconds between the power on and the pin to go high. I hope it is not a problem for your use case.

Let us know if this helps you! :slight_smile:

Best regards,

Hi @henrique.tx

Thanks for the answer!

I am still not quite sure if follow completely. The pin 97 i refer to is the one i see here:

cat /sys/kernel/debug/pinctrl/30330000.pinctrl/pins
pin 83 (MX8MP_IOMUXC_SAI1_RXC) 1:30230000.gpio 30330000.pinctrl
...
pin 97 (MX8MP_IOMUXC_SAI1_TXD3) 15:30230000.gpio 30330000.pinctrl

So I guess that GPIO 97 in this instance is the numbering by Linux. I can (If i am not using the hog) set the pin via the FS and see the corresponding result on SODIMM 222.

What I now discovered in cat /sys/kernel/debug/pinctrl/30330000.pinctrl/pinmux-pins is the following:

pin 83 (MX8MP_IOMUXC_SAI1_RXC): 30330000.pinctrl 30230000.gpio:97 (HOG) function pinctrl group gpio8grp
...
pin 97 (MX8MP_IOMUXC_SAI1_TXD3): 30230000.gpio (GPIO UNCLAIMED) function pinctrl group gpio8grp_mod

I guess this is the connection from the SAI_RXC to the GPIO 97? With the 30230000.gpio:97 I mean.

My DT is still like this:

&iomuxc {
    pinctrl_gpio8_mod: gpio8grp_mod {
        fsl,pins = <MX8MP_IOMUXC_SAI1_TXD3__GPIO4_IO15 0x5>;
    };
};

&gpio4 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_gpio8_mod>;
    
    sodimm222_hog: sodimm222_hog {
        gpio-hog;
        gpios = <1 GPIO_ACTIVE_HIGH>;
        output-high;
        line-name = "sodimm-222";
    };
};

Does this make sense to you? It works as i can see the pin getting pulled high, but I am not sure if I doing something wrong still…

Cheers
Tim

Hello @TimSiegrist,

From your output we see that pin 97 in the kernel’s assignment corresponds to the SAI1_TXD3 SOC ball.
This ball is connected to SODIMM 215, as per the module’s datasheet.
It should have not directly relation to SODIMM 222.

Pin 83 however, is connected to the SAI1_RXC SOC ball.
SAI1_RXC is connected to SODIMM 222.


The only downside I see in your device tree snippet is that pinctrl-0 of gpio4 is being overwritten.
If you already have a another group that is defined there before in your device tree or in the base device tree, it will be removed.
What you could do is to check what you already have on pinctrl-0 of gpio4 and add it alongside <&pinctrl_gpio8_mod>.

Best Regards,
Bruno