Strange behavior using GPIO from userland

I am attempting to interface with a GPIO on the TX2, specifically:

pin G6, which (according to the pinmux spreadsheet) is mapped to Port/Num: M0

By default the pin is controlled by either the I2S3 or DMIC1 (whichever the pinmux is configured for).

I’ve modified the ‘tegra186-quill-common.dtsi’ and commented out any reference to the previous I2S3 and DMIC1 pinmux configuration so even if the pinmux is configured to use one of them they should not be on.

Here is what the relevant part of that file looks like:

pinmux@2430000 {
    /* Dynamic pinmux config for DMIC1 */
    dmic1_dap_active_state: dmic1_dap_active {
/*
      dmic_dmic1_clk_pm1 {
        nvidia,pins = "dmic1_clk_pm1";
        nvidia,function = "dmic1";
      };
      dmic_dmic1_dat_pm0 {
        nvidia,pins = "dmic1_dat_pm0";
        nvidia,function = "dmic1";
      };
*/
    };
    /* Dynamic pinmux config for DMIC2 */
    dmic2_dap_active_state: dmic2_dap_active {
      dmic_dmic2_dat_pm2 {
        nvidia,pins = "dmic2_dat_pm2";
        nvidia,function = "dmic2";
      };
      dmic_dmic2_clk_pm3 {
        nvidia,pins = "dmic2_clk_pm3";
        nvidia,function = "dmic2";
      };
    };
    /* Dynamic pinmux config for DMIC3 */
    dmic3_dap_active_state: dmic3_dap_active {
      dmic_can_gpio0_paa0 {
        nvidia,pins = "can_gpio0_paa0";
        nvidia,function = "dmic3";
      };
      dmic_can_gpio1_paa1 {
        nvidia,pins = "can_gpio1_paa1";
        nvidia,function = "dmic3";
      };
    };
    dmic3_dap_inactive_state: dmic3_dap_inactive {
      dmic_can_gpio0_paa0 {
        nvidia,pins = "can_gpio0_paa0";
        nvidia,function = "dmic5";
      };
      dmic_can_gpio1_paa1 {
        nvidia,pins = "can_gpio1_paa1";
        nvidia,function = "dmic5";
      };
    };
    /* Dynamic pinmux config for DMIC4 */
    dmic4_dap_active_state: dmic4_dap_active {
      dmic_dmic4_dat_pm4 {
        nvidia,pins = "dmic4_dat_pm4";
        nvidia,function = "dmic4";
      };
      dmic_dmic4_clk_pm5 {
        nvidia,pins = "dmic4_clk_pm5";
        nvidia,function = "dmic4";
      };
    };
    /* Dynamic pinmux config for I2S3 */
    i2s3_dap_active_state: i2s3_dap_active {
/*
      i2s3_dmic1_clk_pm1 {
        nvidia,pins = "dmic1_clk_pm1";
        nvidia,function = "i2s3";
      };
      i2s3_dmic1_dat_pm0 {
        nvidia,pins = "dmic1_dat_pm0";
        nvidia,function = "i2s3";
      };
      i2s3_dmic2_dat_pm2 {
        nvidia,pins = "dmic2_dat_pm2";
        nvidia,function = "i2s3";
      };
      i2s3_dmic2_clk_pm3 {
        nvidia,pins = "dmic2_clk_pm3";
        nvidia,function = "i2s3";
      };
*/
    };
  };

I’ve then created a pinmux entry in my top dts file: tegra186-quill-p3310-1000-c03-00-base.dts

(This is used to interface with an IMU chip on the board)

...
  pinmux@2430000 {                                                                                                     
    pinctrl-names = "default";                                                                                         
    pinctrl-0 = <&pinmux_imu_default>;                                                                                 
    pinmux_imu_default: imu_gpio {                                                            
      //Reset Line (Active Low)                         
      dmic1_dat_pm0 {                                                                                                  
        nvidia,pins = "dmic1_dat_pm0";                                                                                 
        nvidia,pull = <TEGRA_PIN_PULL_NONE>;                                                                           
        nvidia,tristate = <TEGRA_PIN_DISABLE>;                                                                         
        nvidia,enable-input = <TEGRA_PIN_ENABLE>;                                                                     
      };                                                                                                               
                                                                                                                       
      //SPI                                                                                                            
      gpio_sen1_pv1 {                                                                                                  
        nvidia,pins = "gpio_sen1_pv1";                                                                                 
        nvidia,function = "spi2";                                                                                      
        nvidia,pull = <TEGRA_PIN_PULL_DOWN>;                                                                           
        nvidia,tristate = <TEGRA_PIN_DISABLE>;                                                                         
        nvidia,enable-input = <TEGRA_PIN_ENABLE>;                                                                      
        nvidia,lpdr = <TEGRA_PIN_DISABLE>;                                                                             
      };                                                                                                               
                                                                                                                       
      gpio_sen2_pv2 {                                                                                                  
        nvidia,pins = "gpio_sen2_pv2";                                                                                 
        nvidia,function = "spi2";                                                                                      
        nvidia,pull = <TEGRA_PIN_PULL_DOWN>;                                                                           
        nvidia,tristate = <TEGRA_PIN_DISABLE>;                                                                         
        nvidia,enable-input = <TEGRA_PIN_ENABLE>;                                                                      
        nvidia,lpdr = <TEGRA_PIN_DISABLE>;                                                                             
      };                                                                                                               
                                                                                                                       
      gpio_sen3_pv3 {                                                                                                  
        nvidia,pins = "gpio_sen3_pv3";                                                                                 
        nvidia,function = "spi2";                                                                                      
        nvidia,pull = <TEGRA_PIN_PULL_DOWN>;                                                                           
        nvidia,tristate = <TEGRA_PIN_DISABLE>;                                                                         
        nvidia,enable-input = <TEGRA_PIN_ENABLE>;                                                                      
        nvidia,lpdr = <TEGRA_PIN_DISABLE>;                                                                             
      };                                                                                                               
                                                                                                                       
      gpio_sen4_pv4 {                                                                                                  
        nvidia,pins = "gpio_sen4_pv4";                                                                                 
        nvidia,function = "spi2";                                                                                      
        nvidia,pull = <TEGRA_PIN_PULL_UP>;                                                                             
        nvidia,tristate = <TEGRA_PIN_DISABLE>;                                                                         
        nvidia,enable-input = <TEGRA_PIN_ENABLE>;                                                                      
        nvidia,lpdr = <TEGRA_PIN_DISABLE>;                                                                             
      };                                                                                                               
    };                                                                                                                 
  }; 
...

I’ve also declared that pin as a GPIO output:

...
  gpio@2200000 {
    imu-control-input {
      gpio-hog; //Take over a pin                                                                                      
      input; 
      status = "okay";
      gpios = < IMU_DATA_RDY    0>;                                                                                    
      label = "imu-drdy";                                                                                              
    };
    imu-control-output-low {
      gpio-hog; //Take over a pin                                                                                      
      output-low;
      status = "okay";
      gpios = < IMU_SYNC_IN     0
                IMU_RST_L       0 >;                                                                                   
      label = "imu-sync", "imu-rst";                                                                                   
    };                                                                                                                 
  };
...

Logged into the board I’ve ‘exported’ GPIO 416 and it looks like it’s configured correctly:

root@tegra-ubuntu:/sys/class/gpio/gpio416# cat direction
out
root@tegra-ubuntu:/sys/class/gpio/gpio416# cat value 
1
root@tegra-ubuntu:/sys/class/gpio/gpio416# echo 0 > value 
root@tegra-ubuntu:/sys/class/gpio/gpio416# cat value
0

So the GPIO driver does work correctly and I have verified that this works on another GPIO attached to an LED but this pin is unresponsive. I used a scope to measure the voltage and it sits at 960mV regardless of if the ‘value’ is 0 or 1.

When the kernel boots up I do see that the GPIO controller does successfully set the pin to be an output:

[    1.143607] GPIO line 416 (imu-rst) hogged as output/low

(By the way, nice move publishing the user accessible number in the kernel messages, that makes things much easier)

Is there a reason why this pin is behaving like this?

I’ve used this same design with the TX1 and the pin worked fine.

Thanks for any help.

Dave

I found this is a problem with the IMU and not with the GPIO. I removed the IMU and the reset pin worked correctly. I could toggle the GPIO in userland.