Open Drain on Verdin IMX8M Plus

I am working with a minimal embedded linux system built with Yocto.

I am able to put pins into and out of open-drain mode with e.g.

gpioset -t0 -dopen-drain SODIMM_206=1

I confirmed with a multimeter that the output is floating, but goes high with an external pull-up resistor.

I notice that even though this is working properly (the right register was apparently set), gpioinfo does not show that the pin is in open-drain mode.

In addition, internal pull-up bias does not seem to work at all (using -bpull-up in the command line)

How can I fix/troubleshoot this?

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,

It sounds like you’re making good progress with configuring GPIO pins on your Verdin iMX8M Plus. Let’s address the issues you’re encountering with gpioinfo and the internal pull-up resistors.

Firstly, regarding gpioinfo not displaying the open-drain mode, this might be due to limitations in how the tool reports pin configurations. It may not fully support displaying all modes, depending on the GPIO driver or kernel version. To verify the pin configuration, consider directly inspecting the GPIO registers or using a tool that can accurately read these settings.

For the internal pull-up resistor issue, ensure the GPIO pin is correctly configured in the device tree or through the sysfs interface. Here are some steps to help troubleshoot:

  1. Device Tree Configuration: Verify your device tree settings to ensure the GPIO pin is configured with the correct pull-up settings. Check the pinctrl settings associated with your GPIO to confirm that the pull-up is enabled.

  2. Kernel and Driver Support: Make sure your kernel version and GPIO driver support the features you are using. Sometimes, updating to a newer kernel or applying patches can resolve such issues.

  3. Verification with Tools: Use a multimeter or oscilloscope to check the actual electrical state of the pin when configured with the internal pull-up. This can help determine if the issue is with the software configuration or the hardware.

  4. External Pull-up: If the internal pull-up is not functioning, consider using an external pull-up resistor as a temporary solution while you troubleshoot the software configuration.

By following these steps, you should be able to diagnose and resolve the issues with your GPIO configuration. If the problem persists, further investigation into the specific GPIO driver and kernel version might be necessary.

Best regards,
Toradex AI Assistant

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

iMX8MP: Generating clock at pin 91 CLKO2 pin.

As mentioned by AI, the GPIO driver has certain limitations that prevent it from displaying the Open Drain mode or configuring internal pull-up/pull-down resistors. To set up an internal pull-up or pull-down resistor, you can modify the pin settings in the &iomuxc node within the Device Tree.

Hi Louie,

Besides checking in here to see if Alex’s answer helped and if you have na update from your end. I just was wondering if you did have an opportunity to see our Torizon OS? This free and open source OS is based upon the same Yocto image you are working on but we believe makes development faster and easier thanks to the usage of Docker containers for your appliactions, and the VS Code Extension we created that serves as your IDE. Have you taken a look at it? If you want to know more we can schedule a quick 30 minute overview.
Assuming you need it also comes with the ability to easily do remote or offline updates securely.

Best regards,

Michael Park
Toradex

I have not, but plan to in the future. Please let me know when we can schedule an overview.

OK, so I have added a pinctrl block under iomuxc as follows:

pinctrl_modem: modemgrp {
        fsl,pins =
                <MX8MP_IOMUXC_SAI1_TXD2__GPIO4_IO14             0x96>,  /* NEW: MODEM_CFG_0             OLD: SODIMM 217 */
                <MX8MP_IOMUXC_SAI1_TXD3__GPIO4_IO15             0x96>,  /* NEW: MODEM_CFG_1             OLD: SODIMM 215 */
                <MX8MP_IOMUXC_SAI1_TXD0__GPIO4_IO12             0x96>,  /* NEW: MODEM_CFG_2             OLD: SODIMM 221 */
                <MX8MP_IOMUXC_SAI1_RXD5__GPIO4_IO07             0x96>,  /* NEW: MODEM_CFG_3             OLD: SODIMM 203 */
                <MX8MP_IOMUXC_SAI1_TXD1__GPIO4_IO13             0x96>,  /* NEW: MODEM_CFG_4             OLD: SODIMM 219 */
                <MX8MP_IOMUXC_SAI1_RXD6__GPIO4_IO08             0x96>,  /* NEW: MODEM_ON                OLD: SODIMM 205 */
                <MX8MP_IOMUXC_SAI1_RXD7__GPIO4_IO09             0x1f6>, /* NEW: MODEM_AIRPLANE_N        OLD: SODIMM 207 */
                <MX8MP_IOMUXC_SAI1_TXD4__GPIO4_IO16             0x96>,  /* NEW: MODEM_RESET_N           OLD: SODIMM 211 */
                <MX8MP_IOMUXC_SAI1_TXD5__GPIO4_IO17             0x96>;  /* NEW: MODEM_DPR               OLD: SODIMM 213 */
        };

However, I can’t seem to get the directions set properly. I tried changing directions under the gpio4 block as follows:

gpio_modem: modem_gpio_hogs {
                compatible = "gpio-hog";
                gpios = <&gpio4 14>,                                    /* MODEM_CFG0:          Input */
                        <&gpio4 15>,                                    /* MODEM_CFG1:          Input */
                        <&gpio4 12>,                                    /* MODEM_CFG2:          Input */
                        <&gpio4 7>,                                     /* MODEM_CFG3:          Input */
                        <&gpio4 13>,                                    /* MODEM_CFG3:          Input */
                        <&gpio4 8 GPIO_ACTIVE_LOW>,                     /* MODEM_ON:            Output, Initially low */
                        <&gpio4 9 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>, /* MODEM_AIRPLANE_N:    Output, Open-Drain, Initially low */
                        <&gpio4 16 GPIO_ACTIVE_HIGH>,                   /* MODEM_RST_N:         Output, Initially low */
                        <&gpio4 17 GPIO_ACTIVE_LOW>;                    /* MODEM_DPR:           Output, Initially low */

        };

However, when I check the register states with tools such as devmem2, they are not set as I expected.

# From imx8mp-pinfunc.h, the control register for GPIO4_IO14 is 0x03e0
# From the NXP IMX8MP reference manual, this is address 0x3033_03e0
root@verdin-imx8mp-15446091:~# devmem2 0x303303e0 w
/dev/mem opened.
Memory mapped at address 0x7f85a81000.
Read at address  0x303303E0 (0x7f85a813e0): 0x00000016

So that register is set to 0x16, but I expected it to be set to 0x96. Clearly my settings aren’t being taken!

After the Linux kernel boots, all GPIO pins are configured as inputs by default. You can configure a specific GPIO line as an output using the gpioset command or by utilizing the Libgpiod API.

I understand how I can do that in userspace, but I would expect there is some way to tell the device tree to NOT set my GPIOs as input! It is clearly able to do that for e.g.

gpioinfo
…
line 20: unnamed output consumer=regulator-module-eth1phy

Is that set in the device tree, or is there some process early in the boot cycle that is setting that?

"This indicates that line 20 is controlled by the regulator-module-eth1phy .

reg_module_eth1phy: regulator-module-eth1phy {
compatible = “regulator-fixed”;
enable-active-high;
gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>; /* PMIC_EN_ETH */
off-on-delay-us = <500000>;
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_reg_eth>;
regulator-always-on;
regulator-boot-on;
regulator-max-microvolt = <3300000>;
regulator-min-microvolt = <3300000>;
regulator-name = “On-module +V3.3_ETH”;
startup-delay-us = <200000>;
vin-supply = <&reg_vdd_3v3>;
};

The purpose of the device tree is to describe the hardware, not its configuration. To my knowledge, it is not possible to set the GPIO direction directly via the device tree. However, if you assign the GPIO to a specific function, such as an LED (or a fixed regulator, as in the case above), the corresponding driver (e.g., the LED driver or fixed-regulator driver) will handle the GPIO direction for you. If you need to set the GPIO as an output earlier in the boot process, you can configure it in U-Boot

1 Like

You can set a GPIO as an output in the device tree using GPIO-hogging. The gpio-hog property instructs the controller to set the pin high or low during bootup, preventing any other driver or user space from requesting it.

If you intend to use the GPIO in user space, you should not use gpio-hog.

1 Like

Thank you for the response, that clarifies some things for me!

I want to be able to twiddle my gpios directly from userspace, so I will not use the gpio-hogging option. I think that for now, I will only modify my device tree to give the pins accurate names, and create a script to be run at boot up that correctly sets direction, drive, pull ups, etc.

Does this sound like a sane approach? Is creating a systemd service script to set these GPIOs the best practice for doing this?

Yes, that’s a reasonable approach. Configure the pin speed, strength, and pull-up/pull-down settings in the device tree. Then, you can use a script or a C/C++/Python application to set the GPIO direction and level.