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: Disable GPIO Interrupt Handling

Other Parts Discussed in Thread: OMAP-L138

I am using the OMAP-L138 with embedded Linux running on the ARM core and BIOS running on the DSP core.  I currently have the DSP setup to detect a GPIO interrupt on Bank 5, but have found that the INTSTAT register is always clear when the DSP services the interrupt.  I believe the Linux kernel is handling the interrupt as well and clearing the INTSTAT register.

How do I disable the Linux kernel from handling a GPIO interrupt on bank 5?  Linux still needs to continue to receive interrupts on the other banks.

Thanks,

abkirchhofff

  • I believe I have figured out how to prevent Linux from setting up an interrupt handler for a GPIO bank on the OMAP-L138:

    In arch/arm/mach-davinci/gpio.c, I found the following function, which must be called when the kernel starts.

    static int __init davinci_gpio_irq_setup(void)

    Inside this function, an IRQ is assigned to every GPIO pin available on the chip, whether it is used or not.  Most of the setup occurs in the following for loop since the GPIO interrupts on the OMAP-L138 are banked.  I added a check for the two banks the DSP is using to prevent IRQ being assigned.  The bank numbers are hardcoded, as I don't know how to provide this information from some other structure.

    /*
     * Or, AINTC can handle IRQs for banks of 16 GPIO IRQs, which we
     * then chain through our own handler.
     */
    for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
            gpio < ngpio;
            bank++, bank_irq++) {
        unsigned        i;

        /* disabled by default, enabled only as needed */
        g = gpio2controller(gpio);
        __raw_writel(~0, &g->clr_falling);
        __raw_writel(~0, &g->clr_rising);

        /* ABK: Do not setup IRQ for banks 4 and 5, as the DSP core
         * is using these bank interrupts.
         */
        if ((bank == 4) || (bank == 5)) {
            irq += 16;
            gpio += 16;
        }
        else {
            /* set up all irqs in this bank */
            set_irq_chained_handler(bank_irq, gpio_irq_handler);
            set_irq_chip_data(bank_irq, g);
            set_irq_data(bank_irq, (void *)irq);

            for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
                set_irq_chip(irq, &gpio_irqchip);
                set_irq_chip_data(irq, g);
                set_irq_data(irq, (void *) __gpio_mask(gpio));
                set_irq_handler(irq, handle_simple_irq);
                set_irq_flags(irq, IRQF_VALID);
            }

            binten |= BIT(bank);
        }
    }

    Let me know if I missed something, but everything seems to be working fine.

    abkirchhoff