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 Interrupt Handler not getting called - DM365

Other Parts Discussed in Thread: TSC2004

Hello,

I am connecting GIO8 of DM365 to a pin of  another IC which is always toggling (seen in  CRO).Also I am able to read the  state of GIO8 in the program.But I want to configure GIO8 as interrupt.I have registered interrupt , but the printk messages in the handler is not getting printed.

uname -a  returns   Linux DM365_IPNC 2.6.18_pro500-davinci_IPNC_DM365_2.0.0

The following is the code used.

    gpio_request(8, "tsc2004-irq");
    temp = __raw_readl(pinmux3);  
    temp = temp & 0xFFFFFF7F;
    __raw_writel(temp, pinmux3);
    gpio_direction_input(8);
    temp = davinci_readl(DM365_ARM_INTMUX);
    temp &= 0xffffbfff;
    davinci_writel(temp , DM365_ARM_INTMUX);

      data->irq = gpio_to_irq(8);

        if (request_irq(data->irq , tsc2004_irq, IRQF_TRIGGER_FALLING,  "tsc2004" , NULL)) {
        err = -EBUSY;
        goto exit_free;
        }
mdelay(10000);

static irqreturn_t  tsc2004_irq(int irq, void *handle,struct pt_regs *regs)    //ISR
{
    printk("\n ------------------------ in ISR -------------------------------\n");
    return IRQ_HANDLED;
}

# cat /proc/interrupts                                                                                
           CPU0                                                                                         
  0:          0       AINTC  csl
  1:          0       AINTC  csl
  2:          0       AINTC  csl
  3:          0       AINTC  csl
  4:          0       AINTC  csl
  5:          0       AINTC  csl
  6:          0       AINTC  csl
  8:       1015       AINTC  davinci_osd
 16:          0       AINTC  EDMA Completion
 17:          0       AINTC  EDMA CC Error
 18:          0       AINTC  EDMA TC0 Error
 19:          0       AINTC  EDMA TC1 Error
 26:        411       AINTC  davinci-mmc
 29:          0       AINTC  rtc0
 32:     191917       AINTC  clockevent
 33:          1       AINTC  free-run counter
 39:         21       AINTC  i2c_davinci
 40:       3412       AINTC  serial
 42:          0       AINTC  dm_spi
 61:          0       AINTC  EDMA TC2 Error
 62:          0       AINTC  EDMA TC3 Error
 72:          0        GPIO  tsc2004
Err:          0

SHould I add anything in addition to the above code ?

As soon as I load this module I am expecting printk messages in the handler (GIO8 toggling in CRO).But I couldn't find any messages in dmesg.Can some one help me out to figure it out ?

Regards,

Nizar

  • Hi Nizar,

    As soon as I load this module I am expecting printk messages in the handler (GIO8 toggling in CRO).But I couldn't find any messages in dmesg.Can some one help me out to figure it out ?

    I think, your are not configured GPIO8 properly, i suspect that It is configured default as a ethernet rx bit, thats why its toggling,

    1) Try to use GPIO8 pin as o/p first then try as a input.

    2) Use printk msg before and after every reqd lines for debugging,

    3) Double check PINMUX3 settings to access GIO8

    program like get the PINMUX3 value and or with (0 << 7)

    4) Read the PINMU3 & print it to chk 7th bit written as zero or not!

    5) use IRQF_SHARED flasg in IRQ reg

    #define GPIO8        8
    #define LOW        0
    #define HIGH        1

      gpio_request(GPIO8, "tsc2004-irq");
        temp = __raw_readl(pinmux3);  
    printk("PINMUX3 val before is = %x\n"temp);//debug
        temp = temp & 0xFFFFFF7F;  //temp |= (0 <<7)// { temp = temp | (0 << 7) };
    printk("PINMUX3 val after is = %x\n"temp);//debug
        __raw_writel(temp, pinmux3);
    printk("PINMUX3 val final is = %x\n"temp); //cross chk it,
        gpio_direction_input(GPIO8);    // first make it o/p & probe from CRO to chk PINMUX done correctly then try as a input
    //printk("GPIO8 o/p high\n);//debug
    //    gpio_direction_output(GPIO8,HIGH);//debug
    //printk("sleep started\n);//debug
    //mdelay(1000);//debug
    //printk("Sleep over\n);//debug
    //    gpio_direction_output(GPIO8,LOW);//debug
    //printk("GPIO8 o/p low);//debug
        temp = davinci_readl(DM365_ARM_INTMUX);
        temp &= 0xffffbfff;
        davinci_writel(temp , DM365_ARM_INTMUX);

          data->irq = gpio_to_irq(GPIO8);

            if (request_irq(data->irq , tsc2004_irq, IRQF_TRIGGER_FALLING,  "tsc2004" , NULL)) {
    //        if (request_irq(data->irq , tsc2004_irq, IRQF_SHARED,  "tsc2004" , <ur major no or use NULL>)) {//try this
    printk("IRQ reg failed);//debug
            err = -EBUSY;
            goto exit_free;
            }
    printk("IRQ reg success);//debug
    mdelay(10000);

    static irqreturn_t  tsc2004_irq(int irq, void *handle,struct pt_regs *regs)    //ISR
    //static irqreturn_t tsc2004_irq(int irq, void *dev_id, struct pt_regs *regs) //try this
    {
        printk("\n ------------------------ IRQ is = %d -------------------------------\n",irq);
        return IRQ_HANDLED;
    }

    try this let me know.

  • Hi ,

    Thanks very much for helping.

    First of all let me make clear that interrupt pin of TSC2004 is connected to GIO8.And I meant that  the interrupt pin of TSC2004 is always  toggling(for which I am not bothered right now).

    So, Since the interrupt pin  is always toggling , I am expecting the IRQ Handler message at-least once.And I am sure that the pin is configured correctly because by polling method I am able to read the status of interrupt pin correctly and i can toggle it also by configuring it as output.So I think there is no problem with pin muxing of that.

    I will try with the interrupt type  IRQF_SHARED  and I will let you know soon.

    Best Regards,

    Nizar

  • Hi Nizar,

    understood.

    Use "set_irq_type" API to assign whether rising edge | falling edge interrupt reqd.

    set_irq_type(72,IRQ_TYPE_EDGE_RISING); //include/linux/irq.h

    Refer this attached doc

    In my AM35x board, by default TSC2004 touch screen support is there,

    So, You can enable these support in board file itself, PFA too

    5545.EN-Linux generic IRQ handling.pdf

    https://gitorious.org/android-enablement/omap-3530-kernel/source/fd0914597719a0b00b14637afedfbf53d35f8f68:arch/arm/mach-omap2/board-am3517evm.c

    https://www.mail-archive.com/linux-omap@vger.kernel.org/msg20588.html

  • Hi ,

    Thanks for replying.

    For the time being, Let us not bother about to what IC its connected.Because In CRO I could see the pin toggling.So , as a generic Interrupt case, shouldn't it work?

    In my program, did I miss something which could cause calling ISR Handler ? Or Should I initialize any variables related to interrupt anywhere ?

    Also does the kernel version matter ?

    Best Regards,

    Nizar

  • Hi Nizar,

    I am using linux kernel 2.6.18 and worked with interrupts,

    This push button interrupt driver raise interrupt when you press button which is configured as GIO0

    PFA of interrupt module driver & plz configure the GPIO as per your hw & GIO.

    /******************************************************************************
     * This file creates a char device and registers the interrupt for the soft shutdown 
     * interrupt. Iterrupt handler sends asynchronous notification to
     * the user space application.
     * 
     * Device :-> /dev/pwrdn_int
     * Major Number :-> Dynamically allocated by the kernel
     * Minor Number :-> 0
     * Version : 1.0
     ******************************************************************************/
    
    /* Include linux kernel header files */
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/fs.h>
    #include <linux/cdev.h>
    #include <asm/uaccess.h>
    #include <linux/device.h>
    #include <asm/arch/hardware.h>
    #include <asm/gpio.h>
    #include <linux/interrupt.h>
    #include <asm/irq.h>
    
    /* Include local header file */
    #include "pwrdn_int.h"
    
    MODULE_LICENSE("GPL"); 
    
    /* declare location variables */
    static dev_t dev;  
    static struct cdev *pwrdn_int_cdev;
    /* local functions */
    static int pwrdn_int_open (struct inode *inode, struct file *filp);
    static int pwrdn_int_release (struct inode *inode, struct file *filp);
    static int pwrdn_int_fasync(int fd, struct file *filp, int on);
    int pwrdn_int_init_module(void);
    void pwrdn_int_cleanup_module(void);
    struct class *hhtp_class; /* Tie with the device model */
    static struct fasync_struct *pwrdn_int_async_queue;
    
    /* declare file operation structure */
    static struct file_operations pwrdn_int_fops = {
        .owner = THIS_MODULE,
        .open  = pwrdn_int_open,
        .release = pwrdn_int_release,
    	.fasync	= pwrdn_int_fasync,
    };
    
    /*Interrupt Handler */
    static irqreturn_t hhtint_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    {
    	printk("\n pwrdn_interrupt raised\n");
    	kill_fasync(&pwrdn_int_async_queue, SIGIO, POLL_IN);
    	return IRQ_HANDLED;
    }
    
    /***************************************************************************
     * Function             - gpio_request_irq
     * Functionality        - Registers Handlers to the IRQ's of GPIO's by request_irq
     * Input Params - 
     * Return Value - None
     * Note                 - None
     ****************************************************************************/
    void gpio_request_irq(int irq_num)
    {
    	int status = 0;
    
    	status = request_irq(irq_num, hhtint_interrupt,SA_INTERRUPT,"pwrdn_int", NULL);
    
    	printk(KERN_WARNING "gpio_request_irq %d status %d\n",
    			   irq_num, status);
    
    	if (status == -EINVAL) {
    		printk("<1> EINVAL \n");
    		} 
    	else if (status == -ENOMEM) {
    		printk("<1> ENOMEM ");
    		} 		
    		
    	if (status < 0) {
    		printk("<1> gpio_request_irq : Failed to Register IRQ %d  \n",
    		       irq_num);
    		printk("<1> gpio_request_irq : return status is %d  \n",
    		       status);
    	}
    
    }
    
    /***************************************************************************
     * Function             - gpio_unrequest_irq
     * Functionality        - Free Handlers o the IRQ's of GPIO's
     * Input Params - 
     * Return Value - None
     * Note                 - None
     ****************************************************************************/
    void gpio_unrequest_irq(int irq_num)
    {
    	free_irq(irq_num, NULL);
    	printk("<1> gpio_unrequest_irq :  Freeing IRQ %d  \n", irq_num);
    
    }
    /****************************************************************************/
    
    
    static int pwrdn_int_fasync(int fd, struct file *filp, int on)
    {
    	int temp;
    //	return fasync_helper(fd, filp, on, &pwrdn_int_async_queue);
    	temp = fasync_helper(fd, filp, on, &pwrdn_int_async_queue);
    	if (fd != -1)
    		kill_fasync(&pwrdn_int_async_queue, SIGIO, POLL_IN);
    	return(temp);
    }
    
    /******************************************************************************
     * pwrdn_int_open - do nothing 
     *****************************************************************************/
    void hhtp_gpio_init(void)
    {
    	unsigned int control;
    
    	/*control=WRI_REG(PINMUX3);
    	control &=0xf07fffe0; // 23-27=0 > GIO8 to 11 
    	WRI_REG(PINMUX3)= control;
    
    	gpio_direction_input(KPD_R4);*/
    	gpio_direction_input(PUSH_INT);
    	/* Rows: inputs */
    	//gpio_direction_output(KPD_C0,0);
    	//gpio_direction_output(KPD_C1,0);
    	//gpio_direction_output(KPD_C2,0);
    	//gpio_direction_output(KPD_C3,0);
    
    	control=WRI_REG(SET_FAL_TRIG01);
    	control |= 0x00000001;	// 
    	WRI_REG(SET_FAL_TRIG01)=control;
    
    	control=WRI_REG(CLR_FAL_TRIG01);
    	control |= 0x00000001;	// 
    	WRI_REG(SET_FAL_TRIG01)=control;
    
    	control=WRI_REG(DIR01);
    	//control &= 0xfffff0ff; // set columns as GIO[11:8] OUTPUT = 0
    	control |= 0x00000001; // set rows as GIO[30:26] INPUT = 1
    	WRI_REG(DIR01)=control;
    
    	control=WRI_REG(GPIO_BINTEN);
    	control |= 0x00000001;	// Bank 1 interrupt enabled
    	WRI_REG(GPIO_BINTEN)=control;
    
    	//control = WRI_REG(OUT_DATA01);	//initialize rows
    	//control &= 0xfffff0ff;		// GIO 26 - 30 => 0
    	//WRI_REG(OUT_DATA01) = control;	// Output all rows and wait for interrupt
    
    	gpio_request_irq(gpio_to_irq(PUSH_INT));
    }
    
    /******************************************************************************
     * pwrdn_int_open - do nothing 
     *****************************************************************************/
    static int pwrdn_int_open (struct inode *inode, struct file *filp)
    {
        return 0;
    }    
    
    /******************************************************************************
     * pwrdn_int_release - do nothing 
     *****************************************************************************/
    static int pwrdn_int_release (struct inode *inode, struct file *filp)
    {
    	if (filp->f_flags & FASYNC) {
    		pwrdn_int_fasync (-1, filp, 0);
    	}
    	return 0;
    } 
    
    /*****************************************************************************
     * pwrdn_int_init_module - initialise user gpio module
     ****************************************************************************/
    int pwrdn_int_init_module ()
    {
    //alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name)
        if (alloc_chrdev_region(&dev, 0, 1, "pwrdn_int") < 0) {
            printk(KERN_WARNING "Failed to register the device\n");
            return 1;
        }
    
    	hhtp_class = class_create(THIS_MODULE, "pwrdn_int");
    
        pwrdn_int_cdev = cdev_alloc();
        if (pwrdn_int_cdev == NULL) {
            printk(KERN_WARNING "Failed to allocate cdev\n");
            return 1;
        }
    
        cdev_init(pwrdn_int_cdev, &pwrdn_int_fops);
        if (cdev_add(pwrdn_int_cdev, dev, 1) < 0) {
            printk(KERN_WARNING "Failed to add cdev\n");
            return 1;
        }
    
    	class_device_create(hhtp_class, NULL, dev, NULL, "pwrdn_int", 0);
    
        hhtp_gpio_init();
        return 0;
    }
    
    /*****************************************************************************
     * pwrdn_int_init_cleanup - cleanup user gpio module
     ****************************************************************************/
    void pwrdn_int_cleanup_module ()
    {
        cdev_del(pwrdn_int_cdev);
        unregister_chrdev_region(dev, 1);
    	class_device_destroy(hhtp_class, MKDEV(MAJOR(dev), 0));
    	class_destroy(hhtp_class);
    	gpio_unrequest_irq(gpio_to_irq(PUSH_INT));
    }
    
    module_init(pwrdn_int_init_module);
    module_exit(pwrdn_int_cleanup_module);
    
    
    
    

    1373.pwrdn_int.h

    plz let me know the status.

  • Hi,

    The problem might be becuase I have no bank enable or something similar.
    I see in your code nin routuine hhtp_gpio_init, access to several registers.
    I'm not sure how I should do it is my case. I guess there is no linux API for simple gpio/bank interrupt enable.

    Regards,
    Ran
  • If there is any clue on this issue, please tell me. I'm struggling with it for some days now...