Gpio irq can't trigger

Hi nvidia team:

I’m trying to use GPIO07 && GPIO13 as interrupt in orin nx devkit carries board, but when i take the gpio07 pin to 3.3v/gnd the interrupt count didn’t increase, can you help check the config all right?

my dts config:

    quadrature-encoder-0 {

        compatible = "gpio-quadrature-encoder";

        encoder-a-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 6) GPIO_ACTIVE_HIGH>;

        encoder-b-gpios = <&gpio TEGRA234_MAIN_GPIO(H, 0) GPIO_ACTIVE_HIGH>;

        interrupt-parent = <&gpio>;

        interrupts = <TEGRA234_MAIN_GPIO(G, 6) GPIO_ACTIVE_HIGH IRQ_TYPE_EDGE_BOTH>,

                    <TEGRA234_MAIN_GPIO(H, 0) GPIO_ACTIVE_HIGH IRQ_TYPE_EDGE_BOTH>;

        };

driver:



static int gpio_qenc_probe(struct platform_device *pdev)

{

struct device *dev = &pdev->dev;

struct gpio_qenc_priv *priv;

bool has_index;

int num_signals;

int num_synapses;

int ret;




priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);

if (!priv)

return -ENOMEM;




spin_lock_init(&priv->lock);




priv->gpio_a = devm_gpiod_get(dev, "encoder-a", GPIOD_IN);

if (IS_ERR(priv->gpio_a))

return dev_err_probe(dev, PTR_ERR(priv->gpio_a),

"failed to get encoder-a GPIO\n");




priv->gpio_b = devm_gpiod_get(dev, "encoder-b", GPIOD_IN);

if (IS_ERR(priv->gpio_b))

return dev_err_probe(dev, PTR_ERR(priv->gpio_b),

"failed to get encoder-b GPIO\n");




pr_info("Got GPIOs for A(%d) and B(%d)\n", desc_to_gpio(priv->gpio_a), desc_to_gpio(priv->gpio_b));

priv->gpio_index = devm_gpiod_get_optional(dev, "encoder-index",

GPIOD_IN);

if (IS_ERR(priv->gpio_index))

return dev_err_probe(dev, PTR_ERR(priv->gpio_index),

"failed to get encoder-index GPIO\n");




has_index = !!priv->gpio_index;




priv->irq_a = gpiod_to_irq(priv->gpio_a);

if (priv->irq_a < 0)

return dev_err_probe(dev, priv->irq_a,

"failed to get IRQ for encoder-a\n");




priv->irq_b = gpiod_to_irq(priv->gpio_b);

if (priv->irq_b < 0)

return dev_err_probe(dev, priv->irq_b,

"failed to get IRQ for encoder-b\n");




pr_info("Got IRQs for A(%d) and B(%d)\n", priv->irq_a, priv->irq_b);




if (has_index) {

priv->irq_index = gpiod_to_irq(priv->gpio_index);

if (priv->irq_index < 0)

return dev_err_probe(dev, priv->irq_index,

"failed to get IRQ for encoder-index\n");

    }




priv->prev_a = gpiod_get_value(priv->gpio_a);

priv->prev_b = gpiod_get_value(priv->gpio_b);




priv->function = GPIO_QENC_FUNC_QUAD_X4;

priv->direction = COUNTER_COUNT_DIRECTION_FORWARD;




num_signals = has_index ? 3 : 2;




priv->signals[GPIO_QENC_SIGNAL_A].id = GPIO_QENC_SIGNAL_A;

priv->signals[GPIO_QENC_SIGNAL_A].name = "Signal A";




priv->signals[GPIO_QENC_SIGNAL_B].id = GPIO_QENC_SIGNAL_B;

priv->signals[GPIO_QENC_SIGNAL_B].name = "Signal B";




if (has_index) {

priv->signals[GPIO_QENC_SIGNAL_INDEX].id =

GPIO_QENC_SIGNAL_INDEX;

priv->signals[GPIO_QENC_SIGNAL_INDEX].name = "Index";

    }




num_synapses = num_signals;




priv->synapses[0].actions_list = gpio_qenc_synapse_actions;

priv->synapses[0].num_actions = ARRAY_SIZE(gpio_qenc_synapse_actions);

priv->synapses[0].signal = &priv->signals[GPIO_QENC_SIGNAL_A];




priv->synapses[1].actions_list = gpio_qenc_synapse_actions;

priv->synapses[1].num_actions = ARRAY_SIZE(gpio_qenc_synapse_actions);

priv->synapses[1].signal = &priv->signals[GPIO_QENC_SIGNAL_B];




if (has_index) {

priv->synapses[2].actions_list = gpio_qenc_synapse_actions;

priv->synapses[2].num_actions =

ARRAY_SIZE(gpio_qenc_synapse_actions);

priv->synapses[2].signal =

&priv->signals[GPIO_QENC_SIGNAL_INDEX];

    }




priv->cnts.id = 0;

priv->cnts.name = "Position";

priv->cnts.functions_list = gpio_qenc_functions;

priv->cnts.num_functions = ARRAY_SIZE(gpio_qenc_functions);

priv->cnts.synapses = priv->synapses;

priv->cnts.num_synapses = num_synapses;

priv->cnts.ext = gpio_qenc_count_ext;

priv->cnts.num_ext = ARRAY_SIZE(gpio_qenc_count_ext);




priv->counter.priv = priv;

priv->counter.name = dev_name(dev);

priv->counter.parent = dev;

priv->counter.ops = &gpio_qenc_ops;

priv->counter.signals = priv->signals;

priv->counter.num_signals = num_signals;

priv->counter.counts = &priv->cnts;

priv->counter.num_counts = 1;




irq_set_status_flags(priv->irq_a, IRQ_NOAUTOEN);

ret = devm_request_irq(dev, priv->irq_a, gpio_qenc_a_isr,

IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,

"gpio-qenc-a", priv);

if (ret)

return dev_err_probe(dev, ret,

"failed to request IRQ for encoder-a\n");




irq_set_status_flags(priv->irq_b, IRQ_NOAUTOEN);

ret = devm_request_irq(dev, priv->irq_b, gpio_qenc_b_isr,

IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,

"gpio-qenc-b", priv);

if (ret)

return dev_err_probe(dev, ret,

"failed to request IRQ for encoder-b\n");




if (has_index) {

irq_set_status_flags(priv->irq_index, IRQ_NOAUTOEN);

ret = devm_request_irq(dev, priv->irq_index,

gpio_qenc_index_isr,

IRQF_TRIGGER_RISING,

"gpio-qenc-index", priv);

if (ret)

return dev_err_probe(dev, ret,

"failed to request IRQ for encoder-index\n");

    }




ret = devm_counter_register(dev, &priv->counter);

if (ret < 0)

return dev_err_probe(dev, ret, "failed to add counter\n");




dev_info(dev, "GPIO quadrature encoder registered (signals: A, B%s)\n",

has_index ? ", Index" : "");




return 0;

}

boot log:
[ 911.097319] Got GPIOs for A(389) and B(391)
[ 911.097342] Got IRQs for A(264) and B(265)
[ 911.097495] gpio-quadrature-encoder quadrature-encoder-0: GPIO quadrature encoder registered (signals: A, B)

after change the gpio pin status, irq count didn’t changed:

tao@littTech:~$ cat /proc/interrupts | grep gpio
227: 10 0 0 0 0 0 0 0 2200000.gpio 35 Edge Force Recovery
228: 0 0 0 0 0 0 0 0 c2f0000.gpio 27 Edge Power
262: 0 0 0 0 0 0 0 0 2200000.gpio 131 Level 1-0025
264: 0 0 0 0 0 0 0 0 2200000.gpio 41 Edge gpio-qenc-a
265: 0 0 0 0 0 0 0 0 2200000.gpio 43 Edge gpio-qenc-b

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

To address your issue with using GPIO07 and GPIO13 as interrupts on the Jetson Orin NX devkit carrier board, let’s break down the necessary steps and configurations.

Hardware Configuration

First, ensure that your hardware setup is correct. You’ve mentioned using GPIO07 and GPIO13, which are available on the 40-pin header of the Jetson Orin NX module. Verify that these pins are not being used for any other purpose on your custom carrier board.

Device Tree Configuration (DTS)

The Device Tree Source (DTS) file is used to describe the hardware components of your system. To configure GPIO07 and GPIO13 as interrupts, you’ll need to modify the DTS file for your Jetson Orin NX module.

Here’s an example of how you might configure these GPIOs as interrupts in your DTS file:

&gpio {
    gpio07 {
        gpio-pin = <7>;
        gpio-function = "input";
        gpio-interrupt = <1>; // Enable interrupt on rising edge
    };

    gpio13 {
        gpio-pin = <13>;
        gpio-function = "input";
        gpio-interrupt = <1>; // Enable interrupt on rising edge
    };
};

Driver Configuration

Next, you’ll need to configure the GPIO driver to handle interrupts. This typically involves writing a custom driver or modifying an existing one to handle the interrupt events.

Here’s an example of how you might handle interrupts in a custom driver:

#include <linux/gpio.h>
#include <linux/interrupt.h>

// Define the interrupt handler function
static irqreturn_t gpio_irq_handler(int irq, void *dev_id) {
    // Handle the interrupt event here
    printk(KERN_INFO "GPIO interrupt received!\n");
    return IRQ_HANDLED;
}

// Initialize the GPIO driver
static int __init gpio_driver_init(void) {
    // Register the GPIO driver
    gpio_request(7, "gpio07");
    gpio_request(13, "gpio13");

    // Configure the GPIOs as inputs
    gpio_direction_input(7);
    gpio_direction_input(13);

    // Register the interrupt handler
    irq_handler_t irq_handler = gpio_irq_handler;
    irq_request(irq_handler, 7, "gpio07");
    irq_request(irq_handler, 13, "gpio13");

    return 0;
}

Boot Log and Interrupt Count

After modifying the DTS file and driver configuration, reboot your system and verify that the interrupt count increases when you toggle the GPIO07 pin.

Check the boot log for any errors or warnings related to the GPIO configuration. You can use the dmesg command to view the boot log.

To verify the interrupt count, you can use the cat /proc/interrupts command. This will display the current interrupt count for each interrupt line.

Comparison with Other Jetson Modules

The Jetson Orin NX module has a similar GPIO configuration to other Jetson modules, such as the Jetson AGX Orin and Jetson Xavier NX. However, there may be some differences in the DTS file and driver configuration.

When comparing the GPIO configuration between different Jetson modules, ensure that you consult the relevant documentation for each module. The Jetson Orin NX module has a specific DTS file and driver configuration that may differ from other modules.

In summary, to use GPIO07 and GPIO13 as interrupts on the Jetson Orin NX devkit carrier board, you’ll need to:

  1. Verify the hardware setup and ensure that the GPIO pins are not being used for any other purpose.
  2. Modify the DTS file to configure the GPIOs as interrupts.
  3. Configure the GPIO driver to handle interrupts.
  4. Reboot the system and verify that the interrupt count increases when you toggle the GPIO07 pin.

If you’re still experiencing issues, please provide more details about your configuration and setup, and I’ll be happy to help you troubleshoot the problem.

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

Hi tangqaq,

Are you using the devkit or custom board for Orin NX?
What’s the Jetpack version in use?

Have you configured the pinmux for GPIO07 and GPIO13 as input pin before use them as interrupt?

Is it your custom driver to handle the GPIO interrupt?

Hi Kevin:

I’m using the devkit and the JP verison is 6.2.

I’ve checked the GPIO07 and GPIO13 pinmux default config is input pin.

The driver is my custom driver.

What’s the Req. Initial State in your case? with default Int PD?
image

We are not clear about your custom driver.
Have you tried using gpiomon to check the pin state change?

Hi kevin:

I didn’t change the pinmux,so it’s should be Int PD, should i change the state?
custom driver probe as follow:

static int gpio_qenc_probe(struct platform_device *pdev)

{

struct device *dev = &pdev->dev;

struct gpio_qenc_priv *priv;

bool has_index;

int num_signals;

int num_synapses;

int ret;

priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);

if (!priv)

return -ENOMEM;

spin_lock_init(&priv->lock);

priv->gpio_a = devm_gpiod_get(dev, “encoder-a”, GPIOD_IN);

if (IS_ERR(priv->gpio_a))

return dev_err_probe(dev, PTR_ERR(priv->gpio_a),

“failed to get encoder-a GPIO\n”);

priv->gpio_b = devm_gpiod_get(dev, “encoder-b”, GPIOD_IN);

if (IS_ERR(priv->gpio_b))

return dev_err_probe(dev, PTR_ERR(priv->gpio_b),

“failed to get encoder-b GPIO\n”);

pr_info(“Got GPIOs for A(%d) and B(%d)\n”, desc_to_gpio(priv->gpio_a), desc_to_gpio(priv->gpio_b));

priv->gpio_index = devm_gpiod_get_optional(dev, “encoder-index”,

GPIOD_IN);

if (IS_ERR(priv->gpio_index))

return dev_err_probe(dev, PTR_ERR(priv->gpio_index),

“failed to get encoder-index GPIO\n”);

has_index = !!priv->gpio_index;

priv->irq_a = gpiod_to_irq(priv->gpio_a);

if (priv->irq_a < 0)

return dev_err_probe(dev, priv->irq_a,

“failed to get IRQ for encoder-a\n”);

priv->irq_b = gpiod_to_irq(priv->gpio_b);

if (priv->irq_b < 0)

return dev_err_probe(dev, priv->irq_b,

“failed to get IRQ for encoder-b\n”);

pr_info(“Got IRQs for A(%d) and B(%d)\n”, priv->irq_a, priv->irq_b);

if (has_index) {

priv->irq_index = gpiod_to_irq(priv->gpio_index);

if (priv->irq_index < 0)

return dev_err_probe(dev, priv->irq_index,

“failed to get IRQ for encoder-index\n”);

}

priv->prev_a = gpiod_get_value(priv->gpio_a);

priv->prev_b = gpiod_get_value(priv->gpio_b);

priv->function = GPIO_QENC_FUNC_QUAD_X4;

priv->direction = COUNTER_COUNT_DIRECTION_FORWARD;

num_signals = has_index ? 3 : 2;

priv->signals[GPIO_QENC_SIGNAL_A].id = GPIO_QENC_SIGNAL_A;

priv->signals[GPIO_QENC_SIGNAL_A].name = “Signal A”;

priv->signals[GPIO_QENC_SIGNAL_B].id = GPIO_QENC_SIGNAL_B;

priv->signals[GPIO_QENC_SIGNAL_B].name = “Signal B”;

if (has_index) {

priv->signals[GPIO_QENC_SIGNAL_INDEX].id =

GPIO_QENC_SIGNAL_INDEX;

priv->signals[GPIO_QENC_SIGNAL_INDEX].name = “Index”;

}

num_synapses = num_signals;

priv->synapses[0].actions_list = gpio_qenc_synapse_actions;

priv->synapses[0].num_actions = ARRAY_SIZE(gpio_qenc_synapse_actions);

priv->synapses[0].signal = &priv->signals[GPIO_QENC_SIGNAL_A];

priv->synapses[1].actions_list = gpio_qenc_synapse_actions;

priv->synapses[1].num_actions = ARRAY_SIZE(gpio_qenc_synapse_actions);

priv->synapses[1].signal = &priv->signals[GPIO_QENC_SIGNAL_B];

if (has_index) {

priv->synapses[2].actions_list = gpio_qenc_synapse_actions;

priv->synapses[2].num_actions =

ARRAY_SIZE(gpio_qenc_synapse_actions);

priv->synapses[2].signal =

&priv->signals[GPIO_QENC_SIGNAL_INDEX];

}

priv->cnts.id = 0;

priv->cnts.name = “Position”;

priv->cnts.functions_list = gpio_qenc_functions;

priv->cnts.num_functions = ARRAY_SIZE(gpio_qenc_functions);

priv->cnts.synapses = priv->synapses;

priv->cnts.num_synapses = num_synapses;

priv->cnts.ext = gpio_qenc_count_ext;

priv->cnts.num_ext = ARRAY_SIZE(gpio_qenc_count_ext);

priv->counter.priv = priv;

priv->counter.name = dev_name(dev);

priv->counter.parent = dev;

priv->counter.ops = &gpio_qenc_ops;

priv->counter.signals = priv->signals;

priv->counter.num_signals = num_signals;

priv->counter.counts = &priv->cnts;

priv->counter.num_counts = 1;

irq_set_status_flags(priv->irq_a, IRQ_NOAUTOEN);

ret = devm_request_irq(dev, priv->irq_a, gpio_qenc_a_isr,

IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,

“gpio-qenc-a”, priv);

if (ret)

return dev_err_probe(dev, ret,

“failed to request IRQ for encoder-a\n”);

irq_set_status_flags(priv->irq_b, IRQ_NOAUTOEN);

ret = devm_request_irq(dev, priv->irq_b, gpio_qenc_b_isr,

IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,

“gpio-qenc-b”, priv);

if (ret)

return dev_err_probe(dev, ret,

“failed to request IRQ for encoder-b\n”);

if (has_index) {

irq_set_status_flags(priv->irq_index, IRQ_NOAUTOEN);

ret = devm_request_irq(dev, priv->irq_index,

gpio_qenc_index_isr,

IRQF_TRIGGER_RISING,

“gpio-qenc-index”, priv);

if (ret)

return dev_err_probe(dev, ret,

“failed to request IRQ for encoder-index\n”);

}

ret = devm_counter_register(dev, &priv->counter);

if (ret < 0)

return dev_err_probe(dev, ret, “failed to add counter\n”);

dev_info(dev, “GPIO quadrature encoder registered (signals: A, B%s)\n”,

has_index ? “, Index” : “”);

return 0;

}

It depends on your use case.
Do you want it low active or high active?

They seem not the expected configuration for interrupt.

irq_set_status_flags(priv->irq_a, IRQ_NOAUTOEN);

IRQ_NOAUTOEN means the IRQ line will not be automatically enabled after request_irq() succeeds.

So in /proc/interrupts, you still see entries like:

264:          0          0          0          0          0          0          0          0  2200000.gpio  41 Edge      gpio-qenc-a
265:          0          0          0          0          0          0          0          0  2200000.gpio  43 Edge      gpio-qenc-b

because the IRQ handlers were registered successfully.
But the IRQs are still disabled, so the interrupt handler will never be called, and the interrupt count will stay at 0.

hi kevin:

After irq_set_status_flags is set, After devm_request_irq it should theoretically trigger once. However, external high/low level changes are not increasing the interrupt count at all.

IRQ_NOAUTOEN means the IRQ will not be enabled automatically after devm_request_irq().

So devm_request_irq() only registers the handler and makes it appear in /proc/interrupts; it does not trigger the IRQ once.

If the driver never calls:

enable_irq(priv->irq_a);
enable_irq(priv->irq_b);

then external high/low GPIO changes will not enter the ISR, and the interrupt count will stay 0.