AM625: AM62X GPIO Interrupt Configuration Issue: Failed to Set Trigger Mode

Part Number: AM625

Tool/software:

I am currently working on a project that involves the AM62X platform, and I am encountering an issue when trying to configure GPIO interrupts. I would greatly appreciate your guidance in understanding and resolving this problem.

The problem occurs when attempting to request an IRQ for a GPIO pin. Below is the relevant code snippet I am using:

=========================================================================================================

data->ph1_near_irqnumber = -1;
data->ph1_near_empty = devm_gpiod_get(&pdev->dev, "ph1_near_empty", GPIOD_IN);
if (IS_ERR(data->ph1_near_empty)){
printk("gpio_printhead_driver: please check device node with gpio 'ph1_near_empty-gpios'\n");
return PTR_ERR(data->ph1_near_empty);

}

pDrv->irq_nearempty = gpiod_to_irq(data->ph1_near_empty);
printk("gpio_printhead_driver: IRQ number for ph1_near_empty is %d\n", pDrv->irq_nearempty);


result = request_irq(pDrv->irq_nearempty ,
(irq_handler_t) near_irq_handler,
IRQF_TRIGGER_HIGH,
"near empty",
pDrv);

However, when I run this code, I receive the following error messages in the kernel log:

[ 905.474809] genirq: Setting trigger mode 4 for irq 387 failed (gpio_irq_type+0x0/0x20)
[ 905.482782] ========================pDrv->request_irq = -22

It seems that the issue lies in setting the trigger mode for the requested IRQ. Specifically:

  • The error indicates .Setting trigger mode 4 (IRQF_TRIGGER_HIGH) for irq 387 failed
  • The call returns an error code of , which suggests an invalid argument ().request_irq()-22EINVAL

I would be grateful for any suggestions or guidance you can provide to help resolve this issue. If there are specific documents or resources that I should refer to, please let me know.

Thank you very much for your time and support.

  • Hello,

    There is limited support we can give for custom applications since this is not code from TI and is beyond our support scope.

    First, you can check the gpiolib.c driver for the gpiod_to_irq function: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/drivers/gpio/gpiolib.c?h=ti-linux-6.6.y#n3396

    As you mentioned, the output is Invalid argument which looks to be caused by this line: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/drivers/gpio/gpiolib.c?h=ti-linux-6.6.y#n3414

    You can add debug statements to see which condition in the if statement is being met, resulting in the error.

    Second, From searching the error message, you can find the Linux driver that prints the error: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/kernel/irq/manage.c?h=ti-linux-6.6.y#n954

    Looks like line 979 set the 'ret' variable used by the switch statement, but does not enter any of the case blocks which results into the default case. You could try adding some debug statements within that function to see how the variables are being set.

    The 'irq_set_trigger' function itself gets called by other functions within the same driver, so you can also check those functions.

    There is a section within the legacy API about IRQs that might help: https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/Documentation/driver-api/gpio/legacy.rst?h=ti-linux-6.6.y#n351

    Just to keep expectations clear, TI cannot provide E2E support for custom applications.

    Best Regards,

    Anshu

  • After tracing the code in the following location of AM62x  SDK:

    ti-processor-sdk-linux-am62xx-evm-09.00.00.03\board-support\ti-linux-kernel\drivers\gpio\gpio-davinci.c

    I came across the following function:


    static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
    {
    struct davinci_gpio_controller *d;
    struct davinci_gpio_regs __iomem *g;
    u32 mask, i;

    d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data);
    g = (struct davinci_gpio_regs __iomem *)d->regs[0];
    for (i = 0; i < MAX_INT_PER_BANK; i++)
    if (data->irq == d->irqs[i])
    break;

    if (i == MAX_INT_PER_BANK)
    return -EINVAL;

    mask = __gpio_mask(i);

    if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
    return -EINVAL;

    writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
    ? &g->set_falling : &g->clr_falling);
    writel_relaxed(mask, (trigger & IRQ_TYPE_EDGE_RISING)
    ? &g->set_rising : &g->clr_rising);

    return 0;
    }
    From my understanding, this function only supports edge-triggered interrupts:

    IRQ_TYPE_EDGE_FALLING
    IRQ_TYPE_EDGE_RISING

    However, it seems that level-triggered interrupts (e.g., IRQ_TYPE_LEVEL_HIGH and IRQ_TYPE_LEVEL_LOW) are not supported. Given the hardware capabilities of the AM62x platform, I expected it to support both edge- and level-triggered interrupts.

    Support for level-triggered interrupts is essential for certain use cases, such as monitoring GPIO inputs that remain active for extended periods, where high-level or low-level states must be detected. It would significantly enhance the flexibility and functionality of the GPIO controller.

    Could you please confirm if this is an intentional limitation? If not, could you provide guidance on how to enable IRQ_TYPE_LEVEL_HIGH and IRQ_TYPE_LEVEL_LOW triggers?

    Your assistance and insights on this matter would be highly appreciated.

    Best regards,
    Oliver

  • Hi Oliver,

    I'll check internally on this. Please ping this thread if you have not received a response by Wednesday next week.

    Thanks,

    Anshu

  • Hi Anshu,

    I appreciate your assistance. Since it's already past Wednesday, I wanted to kindly follow up on this matter to check if there has been any update from your side.

    Thank you again for your help!

    Best regards,
    Oliver

  • Hi Oliver,

    Its a holiday this week for TI India so I've had no response from the developer. I'll ask them again next week when they return.

    Thanks,

    Anshu

  • Hi Anshu,

            Thank you for your assistance, and I look forward to hearing back from you.

    Best regards,
    Oliver

  • Hi Oliver,

    I've asked for a response again. I will update the thread when I have a reply.

    Thanks,

    Anshu

  • Hi Oliver,

    When reviewing the Technical Reference Manual for AM62x, the GPIO is not capable of Level based interrupts, only edge based interrupts.

    See section 12.2.1.1.1 GPIO Features in the AM62 TRM for more details: https://www.ti.com/lit/ug/spruiv7b/spruiv7b.pdf

    Because the processor doesn't support level base interrupts, the gpio-davinci driver will not either.



    Best Regards,

    Anshu