This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/PROCESSOR-SDK-AM437X: Enabling GPIO interrupt in device tree

Part Number: PROCESSOR-SDK-AM437X
Other Parts Discussed in Thread: TCA8418, AM4372

Tool/software: Linux

Hello,

I am trying to connect a GPIO as an interrupt line. The relevant device tree parts are as below:

gpio0_pins_default: gpio0_pins_default {
        pinctrl-single,pins = <
            0x1a8 ( PIN_INPUT_PULLUP | MUX_MODE9 ) /* (M25) mcasp0_axr1.gpio0[2] */
            0x1ac ( PIN_INPUT_PULLUP | MUX_MODE9 ) /* (L24) mcasp0_ahclkx.gpio0[3] */
            0x158 ( PIN_INPUT_PULLUP | MUX_MODE7 ) /* (T21) spi0_d1.gpio0[4] */
            0x15c ( PIN_INPUT_PULLUP | MUX_MODE7 ) /* (T20) spi0_cs0.gpio0[5] */
            0x1a0 ( PIN_INPUT_PULLUP | MUX_MODE9 ) /* (L23) mcasp0_aclkr.gpio0[18] */
            0x1a4 ( PIN_INPUT_PULLUP | MUX_MODE9 ) /* (K23) mcasp0_fsr.gpio0[19] */
            0x264 ( PIN_INPUT_PULLUP | MUX_MODE9 ) /* (P22) spi2_d0.gpio0[20] */
            0x268 ( PIN_INPUT_PULLUP | MUX_MODE9 ) /* (P20) spi2_d1.gpio0[21] */
        >;
    };

tca8418:tca8418@34{
     compatible = "ti,tca8418";  
     reg = <0x34>;
     interrupt-parent = <&gpio0>;
     interrupts = <21 0x01>;     //gpio0_21 configured as interrupt
     keypad,num-rows = <5>;
     keypad,num-columns = <4>;
     linux,keymap = <
         0x0306003b
         0x06000111>;
     status = "okay";
     };

&gpio0 {
    pinctrl-names = "default";
    pinctrl-0 = <&gpio0_pins_default>;
    status = "okay";
};

The driver is configured without any error (checked using printk). And the interrupt gets added in /proc/interrupt

95:          0  48322000.gpio  24 Edge      tca8418

But, the interrupt never gets called.

In /sys/kernel/debug/pinctrl/44e10800.pinmux/pinmux-pins, we see that

pin 154 (PIN154): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 154 corresponds to GPIO0_21, but it says MUX UNCLAIMED.

In order to rectify this, I added the following in gpio0

    p21 {
        gpio-hog;
        gpios = <21 GPIO_ACTIVE_HIGH>;
        input;
        line-name = "GPIO0_21";
    };

After adding the above lines, the probe function of the driver never got called.

What am I doing wrong?

Thanks,

Rajat Rao

  • The software team have been notified. They will respond here.
  • Update:
    pin 154 (PIN154): 44e07000.gpio (GPIO UNCLAIMED) function gpio0_pins_default group gpio0_pins_default
    The pin does get configured as gpio. So that's not a problem.
    However, the interrupt is not getting triggered.

    If I try to read the value from /sys/class/gpio, I always read 0.
  • As first step the should be configured as GPIO.

    BR
    Tsvetolin Shulev
  • Hi Tsvetolin,

    I don't know what you mean exactly. If you're referring to GPIO UNCLAIMED message, then in the GP-EVM as well we see this:

    pin 85 (PIN85): matrix_keypad0 (GPIO UNCLAIMED) function matrix_keypad_default
    pin 105 (PIN105): matrix_keypad0 (GPIO UNCLAIMED) function matrix_keypad_default
    pin 106 (PIN106): matrix_keypad0 (GPIO UNCLAIMED) function matrix_keypad_default
    pin 107 (PIN107): matrix_keypad0 (GPIO UNCLAIMED) function matrix_keypad_default

    One problem I can see is that the gpio interrupt is not getting configured correctly. In my case, the output of cat /proc/interrupts should show a gpio0 interrupt but it shows

    95:          0  48322000.gpio  24 Edge      tca8418

    which should have been 44e07000.gpio.

    I see that this is getting configured correctly in the EVM.

    195:          0  44e07000.gpio   3 Edge      matrix-keypad

    I add printk in the driver as follows:

    irq = client->irq;
    printk(KERN_ALERT "Irq number %d\n", irq);
    irq = gpio_to_irq(irq);
    printk(KERN_ALERT "Irq number %d\n", irq);

    This prints:

    [    9.374763] [tca8418]: Irq number 56                                         
    [    9.374770] [tca8418]: Irq number 95

    How do I verify if these numbers are correct? Which header file has the definitions that map the interrupts into linux space?

    Thanks,

    Rajat Rao

  • Some updates.

    I have found that the gpio mapping on the EVM and our custom board differs. On the EVM, gpiochip96 controls gpio0 while gpiochip0 controls gpio0 on our board. I found this by comparing addresses in am4372.dtsi.

    I verified that the matrix_keypad driver configures pin 99 (96 +3 for gpio0[3]) as an interrupt pin. Then, if I try "echo 99 > /sys/class/gpio/export", then I get the message "Resource is busy." This behavior is expected since the matrix_keypad driver is holding it.

    On our board, the tca8418 driver does not configure the correct pin (pin 21 for gpio0[21]) as interrupt even though the device tree entry has gpio0[21]. So, I forced the driver to configure pin 21 as interrupt. After this, cat /proc/nterrupt gives
    114: 0 44e07000.gpio 21 Edge tca8418
    which corresponds to gpio0.

    Unfortunately, something is still missing. If I do "echo 21 > /sys/class/gpio/export", it does not say Resource is busy, which means that some configuration is missing.

    Can someone please help me with this? I've been stuck with this for more than a week!

    Thanks,
    Rajat Rao
  • I finally solved this issue.
    1) The tca8418 driver doesn't read/configure the interrupt correctly if it is passed using "interrupt" property in device tree. I had to separately read using of_get_named_gpio and then configure as interrupt.
    2) The driver doesn't have calls to gpio_request, gpio_direction_input, enable_irq. Adding these got things working.

    This forum was probably the wrong place for this question because the problems were in the driver and not in the device tree.

    Thanks,
    Rajat Rao
  • Hi Rajat,

    I think i have the same issue regarding the tca8418 driver.

    I am not that experienced with Linux drivers, so could you pleas share the changes you made with me?

    Regards,

    Andreas Lechner

  • Hi Andreas,

    I can't share the changes as a patch that you can apply, but below are the lines I changed -

        struct device_node *np = dev->of_node;
        if (!np) {
            dev_err(dev, "[tca8418]: device lacks DT data\n");
            return ERR_PTR(-ENODEV);
        }
        irq = of_get_named_gpio(np, "irq-gpio", 0);            //Add something like irq-gpio = <gpio0 21 GPIO_ACTIVE_HIGH>;
        printk(KERN_DEBUG "[tca8418]: GPIO number %d\n", irq);
        error = gpio_request(irq, "i2c_keypad_irq");
        if (error) {
            dev_err(dev,
                "[tca8418]: failed to request GPIO%d for IRQ\n",
                irq);
            return error;
        }
        gpio_direction_input(irq);
        printk(KERN_DEBUG "[tca8418]: GPIO set as input\n");
        irq = gpio_to_irq(irq);
        printk(KERN_DEBUG "[tca8418]: IRQ number %d\n", irq);
        
        enable_irq(irq);
        error = devm_request_threaded_irq(dev, irq, NULL, tca8418_irq_handler,
                          IRQF_TRIGGER_RISING |
                            IRQF_SHARED |
                            IRQF_ONESHOT,
                          client->name, keypad_data);

    Note that the interrupt may be FALLING edge triggered for you.

    Rajat Rao

  • Hi Rajat,

    Thanks for your quick response!
     
    Andreas