Set Default Voltage Level to 0V from 3.3V on I2S Pin Configured as GPIO

Hello,

I’m having difficulty setting the default voltage level of the I2S configured as a GPIO pin to 0V rather than 3.3V. We plan to use the GPIO to power on/off a system that needs to be off when the software is not running or if they software crashes. After changing the I2S pins to GPIO, I noticed that the default voltage of the pin is 3.3V when the program is not driving it to 0V. Currently the system is using a 3.3V input to turn on and we would like to avoid adding additional hardware (inverter).

I have

  1. Changed the overlay to enable I2S to be GPIO.
  2. changed the Pinmux BCT (tegra234-mb1-bct-pinmux-p3767-dp-a03.dtsi) to have the following settings for the pins of interest:
  • Set pull=NONE, tristate=DISABLE, enable-input=DISABLE on all 5 pins, configuring pads as actively driven outputs (matches existing gpio-output-low pin patterns like uart4_cts_ph6)
  1. Changed the GPIO BCT (tegra234-mb1-bct-gpio-p3767-dp-a03.dtsi) with the following settings:
  • Moved H,7 / I,0 / I,1 / I,2 / AC,6 from gpio-input to gpio-output-low

After making these changes, the jetson does boot up with a default logic of low (0V) on the output, but running any software that uses the GPIO pin will cause it to go back to 3.3V after the software exits, even if the last output command was to set it low. Is there any way to make the GPIO output default to logic low (0V) permanently?

Here is the Overlay changes I made:

fragment@0 {
    target = <&pinmux>;

    __overlay__ {
        pinctrl-names = "default";
        pinctrl-0 = <&jetson_io_pinmux>;

        jetson_io_pinmux: exp-header-pinmux {

            // I2S0_DOUT_3V3 --> I2S0_DOUT
            hdr40-pin40 {
                nvidia,pins = "soc_gpio42_pi0";
                nvidia,tristate = <0x0>;
                nvidia,enable-input = <0x1>;
                nvidia,pull = <0x0>;
            };

            // I2S0_DIN_3V3 --> I2S0_DIN
            hdr40-pin38 {
                nvidia,pins = "soc_gpio43_pi1";
                nvidia,tristate = <0x0>;
                nvidia,enable-input = <0x1>;
                nvidia,pull = <0x0>;
            };

            // I2S0_LRCLK_3V3 --> I2S0_FS
            hdr40-pin35 {
                nvidia,pins = "soc_gpio44_pi2";
                nvidia,tristate = <0x0>;
                nvidia,enable-input = <0x1>;
                nvidia,pull = <0x0>;
            };

            // I2S0_SCLK_3V3 --> I2S0_SCLK
            hdr40-pin12 {
                nvidia,pins = "soc_gpio41_ph7";
                nvidia,tristate = <0x0>;
                nvidia,enable-input = <0x1>;
                nvidia,pull = <0x0>;
            };

            // AUD_MCLK_3V3 --> GPIO09
            hdr40-pin7 {
                nvidia,pins = "soc_gpio59_pac6";
                nvidia,tristate = <0x0>;
                nvidia,enable-input = <0x1>;
                nvidia,pull = <0x0>;
            };
        };
    };
};

and the changes to pinmux BCT:

			 soc_gpio41_ph7 {
				 nvidia,pins = "soc_gpio41_ph7";
				 nvidia,function = "rsvd2";
				 nvidia,pull = <TEGRA_PIN_PULL_NONE>;
				 nvidia,tristate = <TEGRA_PIN_DISABLE>;
				 nvidia,enable-input = <TEGRA_PIN_DISABLE>;
				 nvidia,lpdr = <TEGRA_PIN_DISABLE>;
			 };

			 soc_gpio42_pi0 {
				 nvidia,pins = "soc_gpio42_pi0";
				 nvidia,function = "rsvd2";
				 nvidia,pull = <TEGRA_PIN_PULL_NONE>;
				 nvidia,tristate = <TEGRA_PIN_DISABLE>;
				 nvidia,enable-input = <TEGRA_PIN_DISABLE>;
				 nvidia,lpdr = <TEGRA_PIN_DISABLE>;
			 };

			 soc_gpio43_pi1 {
				 nvidia,pins = "soc_gpio43_pi1";
				 nvidia,function = "rsvd2";
				 nvidia,pull = <TEGRA_PIN_PULL_NONE>;
				 nvidia,tristate = <TEGRA_PIN_DISABLE>;
				 nvidia,enable-input = <TEGRA_PIN_DISABLE>;
				 nvidia,lpdr = <TEGRA_PIN_DISABLE>;
			 };

			 soc_gpio44_pi2 {
				 nvidia,pins = "soc_gpio44_pi2";
				 nvidia,function = "rsvd2";
				 nvidia,pull = <TEGRA_PIN_PULL_NONE>;
				 nvidia,tristate = <TEGRA_PIN_DISABLE>;
				 nvidia,enable-input = <TEGRA_PIN_DISABLE>;
				 nvidia,lpdr = <TEGRA_PIN_DISABLE>;
			 };

			 soc_gpio59_pac6 {
				 nvidia,pins = "soc_gpio59_pac6";
				 nvidia,function = "rsvd2";
				 nvidia,pull = <TEGRA_PIN_PULL_NONE>;
				 nvidia,tristate = <TEGRA_PIN_DISABLE>;
				 nvidia,enable-input = <TEGRA_PIN_DISABLE>;
				 nvidia,lpdr = <TEGRA_PIN_DISABLE>;
			 };

and the changes to GPIO BCT

		 gpio-output-low = <
				 TEGRA234_MAIN_GPIO(H, 6)
				 TEGRA234_MAIN_GPIO(H, 7)
				 TEGRA234_MAIN_GPIO(I, 0)
				 TEGRA234_MAIN_GPIO(I, 1)
				 TEGRA234_MAIN_GPIO(I, 2)
				 TEGRA234_MAIN_GPIO(I, 5)
				 TEGRA234_MAIN_GPIO(AC, 0)
				 TEGRA234_MAIN_GPIO(AC, 6)
				 TEGRA234_MAIN_GPIO(K, 4)
				 TEGRA234_MAIN_GPIO(K, 5)
				 >;

Any help would be appreciated.

Thanks!

-Zach

*** Please note that this reply is generated by LLM automatically ***

Based on the provided context, it appears that you are trying to configure the I2S pins on the Jetson Orin Nano as GPIO pins to control a system that needs to be turned on and off. You have made changes to the overlay, Pinmux BCT, and GPIO BCT to achieve this. However, you are experiencing an issue where the GPIO pin defaults to 3.3V instead of 0V when the software is not running or crashes.

To address this issue, let’s break down the possible causes and potential solutions:

  1. Pin configuration: You have set the pins as actively driven outputs, which is correct. However, you may want to double-check the pin configuration to ensure that it is set to output mode and not input mode.
  2. GPIO configuration: You have moved the GPIO configuration from gpio-default to gpio-pull-down. This is a good start, but you may want to try setting the GPIO configuration to gpio-pull-down-strong to ensure that the pin is pulled down to 0V when not driven.
  3. Pinmux BCT: You have made changes to the Pinmux BCT to configure the pins as GPIO. However, you may want to verify that the Pinmux BCT is correctly configured to output the GPIO signal.
  4. Overlay changes: You have made changes to the overlay to enable I2S as GPIO. However, you may want to verify that the overlay is correctly configured and that the GPIO signal is being output correctly.

To permanently set the GPIO output to logic low (0V), you can try the following:

  1. Use a stronger pull-down: Try setting the GPIO configuration to gpio-pull-down-strong to ensure that the pin is pulled down to 0V when not driven.
  2. Use a GPIO output mode: Try setting the GPIO output mode to output-low to ensure that the pin is driven low when not driven.
  3. Verify the pin configuration: Double-check the pin configuration to ensure that it is set to output mode and not input mode.
  4. Verify the Pinmux BCT: Verify that the Pinmux BCT is correctly configured to output the GPIO signal.
  5. Verify the overlay changes: Verify that the overlay is correctly configured and that the GPIO signal is being output correctly.

If none of these solutions work, you may want to try using an external pull-down resistor to pull the pin down to 0V when not driven. This can be a simple and effective solution to ensure that the pin is always pulled down to 0V when not driven.

In comparison to other Jetson platforms, the Jetson Orin Nano has a similar GPIO configuration and pinmuxing scheme. However, the specific pin configuration and GPIO settings may vary depending on the platform and the specific use case.

In summary, to permanently set the GPIO output to logic low (0V) on the Jetson Orin Nano, you can try using a stronger pull-down, setting the GPIO output mode to output-low, verifying the pin configuration, verifying the Pinmux BCT, and verifying the overlay changes. If none of these solutions work, you may want to try using an external pull-down resistor to pull the pin down to 0V when not driven.

*** Please give the thumbs up if you get answers you like. Or provide feedback to help us improve the answer. ***

Hi zach.ruble,

To get the default GPIO/Low state, please use pinmux spreadsheet to configure the pin as GPIO/Drive 0.

What software do you run?
Is this GPIO only controlled by your driver/application?

We are trying to use it in a C++ application. I created the simple C++ application below for testing:

#include <iostream>
#include <gpiod.h>
#include <unistd.h>

class JetsonGPIO {
private:
    struct gpiod_chip *chip;
    struct gpiod_line *line;
    
public:
    JetsonGPIO() : chip(nullptr), line(nullptr) {}
    
    bool init(const char* chip_name, int offset) {
        chip = gpiod_chip_open_by_name(chip_name);
        if (!chip) {
            std::cerr << "Failed to open GPIO chip: " << chip_name << std::endl;
            return false;
        }
        
        line = gpiod_chip_get_line(chip, offset);
        if (!line) {
            std::cerr << "Failed to get GPIO line " << offset << std::endl;
            gpiod_chip_close(chip);
            chip = nullptr;
            return false;
        }
        
        std::cout << "Initialized GPIO: " << chip_name << " line " << offset << std::endl;
        return true;
    }
    
    bool setup_output(const char* consumer = "gpio_test") {
        if (!line) return false;
        
        int ret = gpiod_line_request_output(line, consumer, 0);
        if (ret < 0) {
            std::cerr << "Failed to request line as output" << std::endl;
            return false;
        }
        
        std::cout << "GPIO configured as output" << std::endl;
        return true;
    }
    
    bool output(bool value) {
        if (!line) return false;
        
        int ret = gpiod_line_set_value(line, value ? 1 : 0);
        if (ret < 0) {
            std::cerr << "Failed to set GPIO value" << std::endl;
            return false;
        }
        
        return true;
    }
    
    void cleanup() {
        if (line) {
            gpiod_line_release(line);
            line = nullptr;
        }
        if (chip) {
            gpiod_chip_close(chip);
            chip = nullptr;
        }
    }
    
    ~JetsonGPIO() {
        cleanup();
    }
};

int main() {
    std::cout << "Jetson GPIO Test - Pin 40 (Board Mode)" << std::endl;
    
    JetsonGPIO gpio;
    
    // Pin 40 = gpiochip0, line 51 (PI.00)
    if (!gpio.init("gpiochip0", 51)) {
        std::cerr << "Failed to initialize GPIO" << std::endl;
        return 1;
    }
    
    if (!gpio.setup_output()) {
        std::cerr << "Failed to setup GPIO as output" << std::endl;
        return 1;
    }
    
    std::cout << "Setting GPIO HIGH" << std::endl;
    gpio.output(true);
    sleep(10);
    
    std::cout << "Setting GPIO LOW" << std::endl;
    gpio.output(false);
    sleep(10);
    
    //std::cout << "Setting GPIO HIGH" << std::endl;
    //gpio.output(true);
    //sleep(10);
    
    std::cout << "Done!" << std::endl;
    
    return 0;
}

Could you check if there’s the similar issue if your use gpioset to control the GPIO manually?