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.

gpio as interrupt - sysfs irq works - kernel irq fail

Guru 20755 points
Other Parts Discussed in Thread: OMAPL138

Hello,

I am struglling some time with configuring irq for gpio 42 .

It works very good and easily when done using sysfs.

But On doing the same (with same gpio and hardware) from kernel, I have really trouble...

This is how I try to configure the gpio interrupt:

void start_irq()

{


int irq_num = gpio_to_irq(42);

unsigned int ret=request_irq(irq_num, key_irq, IRQF_TRIGGER_RISING , "gpio42", NULL);

}

static irqreturn_t key_irq(int irq, void *dev_id)

{

unsigned int status;
struct timespec curr_tm;
printk("key_irq!!!!!\n");

}

I get no interrupt. 

I appreciate any suggestions,

Regards,

Ran

  • Hi Ran,

    Which kernel are you using?

    You may also need to define this gpio irq in the device tree, something like:
    interrupt-parent = <&gpioX>;
    interrupts = <x x>;

    Best Regards,
    Yordan
  • Hi Yordna,

    I am using 2.6.37

    GPIO 42 pinmux is configured as GPIO.

    When working with sysfs the interrupt works OK.

    On changing to kernel APIs it does not function correctly. I've been struglling with it for couple of hours, but still don't have any progress.

    Best Regards,

    Ran

  • Hi,

    I've also tried the code in the attached file.

    But It does not give me the printing from the interrupt routine.

    4810.irq.c

    Maybe gpio42 in DM8148 need some additional configuration which are done automatically when using sysfs entires ?

    Regards,

    Ran

  • You can also check the interrupts through "cat /proc/interrupts"

    Try this.
    unsigned int ret=request_irq(irq_num, key_irq, 0 , "gpio42", NULL);

    Also try "Irq_set_type" API for triggering.

    Check the return of "gpio_to_irq" and "request_irq".
    Please first do "gpio_request" to check the availability of GPIO since it might busy with SYSFS that you might run without restart the board.
  • Hi Ran,
    Able to get interrupts ?

    Try to use the following API:
    irq_set_irq_type(irq_num,IRQ_TYPE_EDGE_BOTH);

    Able to get the updated triggered interrupts through "cat /proc/interrupts" ?
  • Hi Titus,

    Thank you very much for the feedback. It is helpful.
    using /proc/interrupts I see the following:
    - when using sysfs:
    202: 4 GPIO gpiolib
    - when using kernel APIs:
    202: 0 GPIO gpiolib
    I guess the 2nd column which indicates flag (I think) might point to the problem.

    All APIs are successful (return 0), and gpio_to_irq return 202.
    this is my code, I don't understand why it does not register the "raising" flag.
    err=request_irq(ev->irq, drv_gpio_interrupt,IRQF_TRIGGER_RISING , "gpiolib", ev);
    printk("return of request_irq is %d\n",err);

    trying to change as foloowing:
    err=request_irq(ev->irq, drv_gpio_interrupt,IRQF_TRIGGER_RISING , "gpiolib", ev);
    printk("return of request_irq is %d\n",err);
    err = irq_set_type(ev->irq, IRQF_TRIGGER_RISING);
    printk("return of irq_set_type is %d\n",err);

    And now I get compilation error:
    error: implicit declaration of function 'irq_set_type'

    Is it becuase kernel does not support irq_set_type ?

    Hiow can I add it ? I see that CONFIG_GENERIC_HARDIRQS is no by default for this architecture.



    Thank you!
    Ran

  • Hi,
    Some of the APIs got deprecated due to linux kernel version changes.

    I think, you can use this "set_irq_type" API for your kernel version.

    Else, you can check the following location in your kernel directory.

    include/linux/irq.h

    Also, you have to declare the following line.

    #include <linux/irq.h>



    using /proc/interrupts I see the following:
    - when using sysfs:
    202: 4 GPIO gpiolib

    If you able to see the "4" then it seems, four interrupts got generated for this IRQ no 202.

    Could you attach the o/p of "cat /proc/interrupts"
  • Hi,

    I didn't yet receved the interrupts when using kernel APIs (only with sysfs it works).

    root@dm814x:~# cat /proc/interrupts

              CPU0

     4:          0        INTC  omap2_elm

    12:          0        INTC  edma

    14:          0        INTC  edma_error

    16:          0        INTC  ahci

    17:          0        INTC  cppi41_dma

    18:          0        INTC  musb-hdrc.0

    19:          0        INTC  musb-hdrc.1

    20:          0        INTC  gpmc

    28:         13        INTC  mmc0

    31:          0        INTC  omap_i2c

    40:          0        INTC  cpsw.0

    41:       8632        INTC  cpsw.0

    42:      10109        INTC  cpsw.0

    43:          0        INTC  cpsw.0

    44:          0        INTC  serial idle

    45:          0        INTC  serial idle

    46:          0        INTC  serial idle

    67:       1018        INTC  gp timer

    70:        148        INTC  omap_i2c

    72:        214        INTC  serial idle, OMAP UART0

    73:          0        INTC  serial idle

    74:          0        INTC  serial idle

    75:          0        INTC  rtc0

    76:          0        INTC  rtc0

    77:          0        INTC  mailbox-dsp, mailbox-video, mailbox-vpss

    116:         94        INTC  CDMA

    122:          0        INTC  omap-iommu.1

    123:          0        INTC  omap-iommu.0

    202:          0        GPIO  gpiolib

    Err:          0

    I still can't use set_irq_type() .

    Can it be all related to CONFIG_GENERIC_HARDIRQS (in my config it is "NO" and I can't change it) ?

    Regards,

    Ran

  • I also see that the directory inside
    /proc/irq/202/gpiolib
    is empty !
    I had expected to find some clues there....
  • Hi Ran,

    Thanks.

    Have you tried the following API and seen same behavior ?

    1) unsigned int ret=request_irq(irq_num, key_irq, 0 , "gpio42", NULL);

    2) set_irq_type(ev->irq, IRQ_TYPE_EDGE_BOTH);

    How did you drive this GPIO pin to generate interrupt ?
    External any push button ?
  • Maybe sysfs also changes something in pinmux ?
  • Nope and never. Its just pseudo fs and provide about device information.

    Please refer to the following E2E posts.

    e2e.ti.com/.../1105527
    e2e.ti.com/.../1293978
  • Hi,

    Do you know what are all the following registers, which of them is required for the interrupt issue ?
    #define SET_RIS_TRIG01 0x01C67024 //2
    #define CLR_RIS_TRIG01 0x01C67028 //2
    #define SET_FAL_TRIG01 0x01C6702C //0
    #define CLR_FAL_TRIG01 0x01C67030 //0
    #define INTSTAT01 0x01C67034 //2
    #define DIR01 0x01C67010
    #define GPIO_BINTEN 0x01C67008

    Thank you,
    Ran
  • Hi Ran,

    You can ignore those settings. That's for DM35x device.

    I have attached the GPIO interrupt driver code which I have already worked with TI's OMAPL138 LCDK board, linux kernel version 3.2.

    Have a try and let me know.

    Just change the GPIO_INT for your GPIO no.

    2063.gpio_irq.c

  • Hi Titus,

    I just tried the code AS-IS (only changed the interrupt number from 37 to 42).
    But I get no interrupt yet.
    It is loaded successfuly, creates irq 202, and have no errors.

        root@dm814x:~# insmod gpio_irq.ko
        gpio_ctrl : GPIO NO: 42 Status -16
        IRQ is 202
        gpio_request_irq 202 status 0
        GPIO IRQ device is inserted sucessfully


    But , I don't even see the printing from the interrupt handler "GPIO interrupt raised; IRQ No ..."

    I really don't understand what I'm doing wrong.

    Thank you very much for the help,
    Ran

  • What are all the commands and steps used for sysfs ?
  • Hi Titus,

    These are the commands when using sysfs:

    echo 42 > /sys/class/gpio/export
    echo 'in' > /sys/class/gpio/gpio42/direction
    echo 'rising' > /sys/class/gpio/gpio42/edge

    And then I listen for changes with poll from userspace.

    Regards,
    Ran
  • Hi Ran,


    root@dm814x:~# insmod gpio_irq.ko
    gpio_ctrl : GPIO NO: 42 Status -16
    IRQ is 202
    gpio_request_irq 202 status 0
    GPIO IRQ device is inserted sucessfully


    If you see the status of "gpio_request", it is "-16" that means "EBUSY"; Device or Resource busy.
    Please reboot the board and insert this .ko directly and don't use sysfs commands.
  • Hi Ran,

    The attached driver (previous reply) is worked on my OMAPL138 LCDK board.

    Also I've tried to change the request_irq function like below.

    request_irq(irq_num,gpio_interrupt,IRQF_SHARED,"gpio_int",major);

    It worked flawlessly for both methods of "request_irq" API.

    Could you please tell me, how did you connect this GPIO in hardware ?

    With pull up or pull down etc., ?

    Custom board or EVM ?

    Any switch or driving this GPIO from any uC etc., ??

    How did you test the GPIO interrupt functionality with SYSFS commands and how did you confirm ?

    Did you probe that GPIO pin while you drive or asserting the pin or pressing switch ?

    Please make sure that you are using correct GPIO pin.

  • Hi Titus,

    Again thank you for this very helpful exchange.
    I tried to boot and load the module again, now I got correct returned value (0), but still the interrupt is not called.
    But I might get nearer to understand the root cause for this.
    I also see that GPIO41 which is set as output, is not changed when using kernel APIs, while it works OK with sysfs. with GPIO18, 19 (cooneced to LED) I have no such issues .
    Maybe BANK 2 GPIO is not enabled ?

    Regards,
    Ran
  • I connect GPIO41 (which is output) into GPIO42 which is the interrupt.
    Today, the first thing I tried was to see if something goes out in GPIO41, and I saw no change....
  • You have just shorted that both GPIOs (one-to-one) with out any pull up/down resistors.
    Try to enable the internal pull up/down resistors through registers if any.
  • Hi Titus,

    Since I already see the problem with PGIO41 output,

    I read the pinmux register og GPIO41 (GP1[9] ) for both when using sysfs, and when using the kernel APIs version.

    In both I see the same value :


    dm814x login: root
    root@dm814x:~# devmem2 0x481408fc
    /dev/mem opened.
    Memory mapped at address 0x4025b000.
    Read at address 0x481408FC (0x4025b8fc): 0x00040080
    root@dm814x:~# ./bit

    So, I still don't undertsnad why the output of GPIO41 is not changed. It seems that the pinmux registers which contain the pullup/down value is correct (becuase this same value is used with the working sysfs)

    Best Regards,

    Ran

  • Hi,
    gpio_direction_input() API would make the GPIO as input for interrupt.

    Do you have any switch (DIP or push button) on your custom board or EVM board ?
  • Hi,

    I thought that maybe the key in understanding the problem with interrupt input "GPIO 42" interrupt is output pin "GPIO 41" which is used as output pin (not iunterrupt).
    This output gpio is OK when sysfs is used, but does not change value with kernel APIs , other lower GPIOs output such as GPIO18, GPIO19, are OK with kernel API ?
  • Yes !!!!
    Thank you Titus, and thank you e2e community.
    I saw with the help of the following:
    e2e.ti.com/.../940136
    That I need to set the following registers (LVCMOS mode):
    MLBP_SIG_IO_CTRL
    MLBP_DAT_IO_CTRL

    Now it all works.
    Thank you very much!
    Ran
  • Sounds good.
    Good to hear.
    Thanks for your update.
  • It seems that the sysfs usage was under flag in my application - which already initlized that register using sysfs ,  and I just did not noticed that initilization :( ... , i.e. sysfs AS-IS was not doing any additional magic , but what it initlized was the magic.