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.

Enable interrupt for GPIO 82 in DM365 running Linux

Folks,

What else I need to do to enable an IRQ from edge events on GPIO 82? This input is working correctly (I can read it with gpio_get_value), but I can't register an interrupt to be called when its status changes.

To get a IRQ, I'm doing this within a Linux kernel module

    irq_num = gpio_to_irq(82);
    ret = request_irq(irq_num, (irq_handler_t) my_irq_handler,
        IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "gpio82", NULL);

but it fails. It seems I need to enable it through the correct HW register. This GPIO doesn't appear in the table "ARM Interrupt Mux (ARM_INTMUX) Control Register Field Descriptions" (page 132 of the SPRUFG5A), so I think it's multiplexed somewhere else. How can I find it?

Thanks in advance.

  • Hello,

    You need to configure the pinmux as input and also configure the gpio pin as input.

    Cheers,
    --Prabhakar Lad
  • Yes, but I'm already doing that -- I can read the input correctly with function gpio_get_value(82), as I did in my tests. I just can't make it raise an interrupt when its state changes (which allow me to avoid polling the input every few milliseconds).

    Excuse me if my post didn't make this clear.
  • Hello,

    Just try the below code.

    Cheers,
    --Prabhakar Lad

    #include <linux/module.h>
    #include <linux/version.h>
    #include <linux/delay.h>
    #include <linux/irq.h>
    #include <linux/interrupt.h>
    #include <linux/completion.h>
    #include <mach/hardware.h>
    #include <asm/gpio.h>


    static int gpio_num;

    DECLARE_COMPLETION(work);

    static irqreturn_t handler (int irq, void * dev)
    {
    complete_all(&work);
    return IRQ_HANDLED;
    }

    int init_module()
    {
    int status;
    int irq;

    init_completion(&work);

    gpio_num = 82;

    status = gpio_request(gpio_num, "gpio_test\n");
    if (status < 0) {
    printk("ERROR can not open GPIO %d\n", gpio_num);
    return status;
    }

    gpio_export(gpio_num, true);

    if(gpio_get_value(gpio_num) == 0)
    printk("OFF. \n\tWaiting for the pin to be on..\n");
    else
    printk("ON. \n\tWaiting for the pin to be off..\n");

    irq = gpio_to_irq(gpio_num);
    status = request_irq(irq, handler, 0, "gpio_test", NULL);
    if(status < 0) {
    printk(KERN_ERR "error %d requesting GPIO IRQ %d\n", status, gpio_num);
    return status;
    }

    set_irq_type(irq, IRQ_TYPE_EDGE_RISING);

    wait_for_completion_interruptible(&work);

    printk(".. done\n");

    return 0;
    }

    void cleanup_module(void) {
    free_irq(gpio_to_irq(gpio_num), NULL);
    gpio_free(gpio_num);
    }

    MODULE_LICENSE("GPL");
  • Hello,

    I just tried the test code (with changes, see bellow), but it failed with error -22 (invalid argument), exactly as happened before with my previous tests. It seems kernel refuses to register the IRQ.

    The exact test sequence was:

    root@camera /tmp# insmod testmod82.ko
    insmod: can't insert 'testmod82.ko': Invalid argument
    root@camera /tmp# insmod ./testmod82.ko
    insmod: can't insert './testmod82.ko': Device or resource busy
    root@camera /tmp# dmesg | tail
    UBIFS: default compressor: lzo
    UBIFS: reserved for root:  0 bytes (0 KiB)
    vpfe-capture vpfe-capture: IPIPE Chained
    vpfe-capture vpfe-capture: Resizer present
    vpfe-capture vpfe-capture: input information not found for the subdev
    ipipe_set_resizer, resizer - A enabled
    OFF.
            Waiting for the pin to be on..
    error -22 requesting GPIO IRQ 82
    ERROR can not open GPIO 82

    Also notice I made some changes to the original code: a typo in function irq_set_irq_type(), renamed init/cleanup_module, and changed the register "pinmux1" to connect GIO82 to the BGA pin C19 (where the GPIO is multiplexes with LCD_OE).  Follows the full code for reference:

    #include <linux/init.h>
    #include <linux/fs.h>
    #include <linux/module.h>
    #include <linux/gpio.h>
    #include <linux/interrupt.h>
    #include <linux/irq.h>
    #include <linux/types.h>
    #include <linux/cdev.h>
    #include <linux/delay.h>
    #include <mach/hardware.h>
    #include <linux/completion.h>
    #include <asm/uaccess.h>
    #include <asm/io.h>

    static int gpio_num;

    DECLARE_COMPLETION(work);


    static void gpio_test_pinmux_config(void)
    {
        static DEFINE_SPINLOCK(mux_spin_lock);
        unsigned long flags = 0;
        struct davinci_soc_info *soc_info = &davinci_soc_info;
        void __iomem *pinmux_base;
        void __iomem *pinmux1_addr;

        /* get pinmux address from soc_info */
        pinmux_base = ioremap(soc_info->pinmux_base, SZ_4K);
        pinmux1_addr = pinmux_base + 1 * sizeof(pinmux_base);

        spin_lock_irqsave(&mux_spin_lock, flags);
        /* GIO82: PINMUX1(BIT17) = 1 */
        __raw_writel((__raw_readl(pinmux1_addr) | (BIT(17))), pinmux1_addr);
        spin_unlock_irqrestore(&mux_spin_lock, flags);
    }


    static irqreturn_t handler (int irq, void * dev)
    {
        complete_all(&work);
        return IRQ_HANDLED;
    }

    static int my_init_module(void)
    {
        int status;
        int irq;

        init_completion(&work);

        gpio_num = 82;

        gpio_test_pinmux_config();
        status = gpio_request(gpio_num, "gpio_test\n");
        if (status < 0) {
            printk("ERROR can not open GPIO %d\n", gpio_num);
            return status;
        }

        gpio_export(gpio_num, true);

        if (gpio_get_value(gpio_num) == 0)
            printk("OFF. \n\tWaiting for the pin to be on..\n");
        else
            printk("ON. \n\tWaiting for the pin to be off..\n");

        irq = gpio_to_irq(gpio_num);
        status = request_irq(irq, handler, 0, "gpio_test", NULL);
        if(status < 0) {
            printk(KERN_ERR "error %d requesting GPIO IRQ %d\n", status, gpio_num);
            return status;
        }

        /* Was set_irq_type */
        irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
        wait_for_completion_interruptible(&work);

        printk(".. done\n");

        return 0;
    }


    static void my_cleanup_module(void) {
        free_irq(gpio_to_irq(gpio_num), NULL);
        gpio_free(gpio_num);
    }

    MODULE_LICENSE("GPL");
    module_init(my_init_module);
    module_exit(my_cleanup_module);

  • Hello,

    can you post the output of the command 'cat /proc/interrupts'

    can you try with request_irq(irq, handler, IRQF_SHARED, "gpio_test", NULL);

    Cheers,
    --Prabhakar Lad
  • Hello,

    I haven't tried the shared interrupts before and was very hopeful when you brought this possibility up ... but it didn't worked too :(

    root@camera /tmp# dmesg | tail
    UBIFS: mounted UBI device 0, volume 0, name "ubifs"
    UBIFS: file system size:   29966336 bytes (29264 KiB, 28 MiB, 236 LEBs)
    UBIFS: journal size:       6348800 bytes (6200 KiB, 6 MiB, 50 LEBs)
    UBIFS: media format:       w4/r0 (latest is w4/r0)
    UBIFS: default compressor: lzo
    UBIFS: reserved for root:  0 bytes (0 KiB)
    vpfe-capture vpfe-capture: IPIPE Chained
    vpfe-capture vpfe-capture: Resizer present
    vpfe-capture vpfe-capture: input information not found for the subdev
    ipipe_set_resizer, resizer - A enabled
    root@camera /tmp# insmod ./testmod82shared.ko
    insmod: can't insert './testmod82shared.ko': Invalid argument
    root@camera /tmp# dmesg | tail
    UBIFS: media format:       w4/r0 (latest is w4/r0)
    UBIFS: default compressor: lzo
    UBIFS: reserved for root:  0 bytes (0 KiB)
    vpfe-capture vpfe-capture: IPIPE Chained
    vpfe-capture vpfe-capture: Resizer present
    vpfe-capture vpfe-capture: input information not found for the subdev
    ipipe_set_resizer, resizer - A enabled
    OFF.
            Waiting for the pin to be on..
    error -22 requesting GPIO IRQ 82
    root@camera /tmp# cat /proc/interrupts
               CPU0       
      0:      14022     AINTC  vpfe_capture0
      3:      14004     AINTC  dm365_h3a_af
      5:       7011     AINTC  Imp_Sdram_Irq
     16:          0     AINTC  edma
     17:          0     AINTC  edma_error
     32:      22827     AINTC  clockevent
     33:          1     AINTC  free-run counter
     39:       6985     AINTC  i2c_davinci
     41:         84     AINTC  serial
     52:          0     AINTC  eth0
     53:        709     AINTC  eth0
     54:        155     AINTC  eth0
     55:          0     AINTC  eth0
    Err:          0
    r

    The /proc/interrupts with the non-shared version was

     root@camera /tmp# cat /proc/interrupts
               CPU0       
      0:     860131     AINTC  vpfe_capture0
      3:     860113     AINTC  dm365_h3a_af
      5:     430065     AINTC  Imp_Sdram_Irq
     16:          0     AINTC  edma
     17:          0     AINTC  edma_error
     32:    1330728     AINTC  clockevent
     33:         74     AINTC  free-run counter
     39:     303551     AINTC  i2c_davinci
     41:         84     AINTC  serial
     52:          0     AINTC  eth0
     53:      34138     AINTC  eth0
     54:        295     AINTC  eth0
     55:          0     AINTC  eth0
    Err:          0



  • Hi,

    Can you check the return value of gpio_to_irq() ? If it fails it returns negative number, try and print it.

    Cheers,
    --Prabhakar Lad
  • Interesting! I always though gpio_to_irq() as a static table kept somewhere in the BSP, but running this test I just got "gpio_to_irq(82) == -19". errno 19 is "No such device", which makes sense here.

    Maybe the interrupt for this GPIO is disabled? I'm searching for registers which can enable it, but no success yet.
  • Hello,

    unfortunately you cannot use gpio82 to generate interrupts only gpio0[0-15] are mapped to arm cpu, for more info refer www.ti.com/.../sprufh8c.pdf (section 2.8.7 page 15)

    Cheers,
    --Prabhakar Lad
  • So, it seems my HW design is utterly broken and the alternative is polling the GPIO.

    Anyway, thanks for the help!