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 in linux

HI to all,

I am trying to enable GPIO interrupt on DM6446, i have written a code but getting error

i am using GPIO # 3,GPIOBANK 0,IRQ # 1

please guide me where i went wrong

following error is coming

Error requesting GPIO irq 56: returned -22

source code

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <asm/system.h>
#include <linux/kernel.h>
#include <linux/delay.h>              // udelay()
#include <linux/fs.h>                     // everything...
#include <asm/uaccess.h>          // copy_from/to_user
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/signal.h>    
#include <linux/irq.h>
#include <linux/random.h>


// Definition for ASP Base Address and the local Power or Sleep Controller LPSoC
#include </root/Desktop/linux/kernel/git/khilman/linux-davinci.git/arch/arm/mach-davinci/include/mach/hardware.h>
#include </root/Desktop/linux/kernel/git/khilman/linux-davinci.git/arch/arm/mach-davinci/include/mach/clock.h>
#include </root/Desktop/linux/kernel/git/khilman/linux-davinci.git/include/linux/clk.h>

/***************************FUNCTION PROTOTYPE*************************/
int gpio_open(struct inode *inode, struct file *filp);
int gpio_release(struct inode *inode, struct file *filp);
ssize_t gpio_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t gpio_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
static void gpio_exit(void);
static int gpio_init(void);

void gpio_interrupt_handler(void);
/*************************************************************************/

#define GPIO_REG(reg)        (*(int *__iomem) IO_ADDRESS(reg))
/********************************DEFINITION*******************************/
#define DM6446_GPIO_BASE    0x01C67000              
#define BINTEN                (DM6446_GPIO_BASE + 0x8)  //GPIO Interrupt Per Bank Enable
#define DIR01                (DM6446_GPIO_BASE + 0x10) //GPIO Bank O & 1 Direction Register GPIO[0:31]
#define OUT_DATA01            (DM6446_GPIO_BASE + 0x14) //GPIO Bank O & 1 Data Register GPIO[0:31]
#define SET_DATA01            (DM6446_GPIO_BASE + 0x18) //GPIO Bank O & 1 Set Data Register GPIO[0:31]
#define CLR_DATA01            (DM6446_GPIO_BASE + 0x1C) //GPIO Bank O & 1 Clear Data for Bank 0 and 1
#define IN_DATA01            (DM6446_GPIO_BASE + 0x20) //GPIO Bank O & 1 Input Data Register
#define SET_RIS_TRIG01        (DM6446_GPIO_BASE + 0x24) //GPIO Bank O & 1 Set Rising Edge Interrupt Register
#define CLR_RIS_TRIG01        (DM6446_GPIO_BASE + 0x28) //GPIO Bank O & 1 Clear Rising Edge Interrupt Register
#define SET_FALL_TRIG01        (DM6446_GPIO_BASE + 0x2C) //GPIO Bank O & 1 Set Falling Edge Interrupt Register
#define CLR_FAL_TRIG01        (DM6446_GPIO_BASE + 0x30) //GPIO Bank O & 1 Clear Falling Edge Interrupt Register
#define INSTAT                (DM6446_GPIO_BASE + 0x34) //Gpio Bank 0 & 1 Interrupt Status Register.
#define DM6446_DEV_BASE        0x01E02000 
#define PCR                    (DM6446_DEV_BASE  + 0x38)//Pin Control Register
#define PINMUX1             0x01c40004             // Definition for GPIO Pin Multiplexing
#define MDCTL17             0x01C41A44             // Module Control 17 Register (ASP)
#define PTCMD                 0x01C41120           // Power Domain Transition Command Register
#define PTSTAT              0x01C41128             // Power Domain Transition Status Register

#define MAJOR_VERSION       58                       // Version Number
#define MINOR_VERSION       01                        // Version Number

#define IRQ1            0x01C4800C            // Interrupt Request Status Register
#define EINT1            0x01C4801C            // Interrupt Enable Register
#define INTPRI6            0x01C48048            // Interrupt Proirty
#define EABASE            0x01C48024            // Interrupt Entry Table Base Address
#define IRQENTRY        0x01C48047            // Entry Address for Valid IRQ

#define SA_INTERRUPT     0
//#define GpioIrq  1
/*************************************************************************/
/*************************Variable Declaration****************************/
unsigned int *binten;
unsigned int *dir01;
unsigned int *out_data01;
unsigned int *set_data01;
unsigned int *clr_data01;
unsigned int *in_data01;
unsigned int *set_ris_trig01;
unsigned int *set_fall_trig01;
unsigned int *clr_ris_trig01;
unsigned int *clr_fall_trig01;
unsigned int *instat;
unsigned int *pcr;
int GpioIrq;
int i;
GpioIrq = 56;
/*************************************************************************/
/*************************************************************************/
/**********************Structure for File Operation***********************/
static struct file_operations gpio_fops = {
                read: gpio_read,
                write: gpio_write,
                open: gpio_open,
                release: gpio_release
};
/*************************************************************************/
static int gpio_init(void)
{
   
    int result;
    int GpioIntRet;
    result = register_chrdev(MAJOR_VERSION, "gpio", &gpio_fops);    /* Registering device */
  if (result < 0)
    {
            printk("<1>\nGPIO_INT: cannot obtain major number %d\n", MAJOR_VERSION);
            return result;
    }
/*
    binten            = (unsigned int *)ioremap(BINTEN,4);
    dir01             = (unsigned int *)ioremap(DIR01,4);
    out_data01        = (unsigned int *)ioremap(OUT_DATA01,4);
    set_data01        = (unsigned int *)ioremap(SET_DATA01,4);
    clr_data01        = (unsigned int *)ioremap(CLR_DATA01,4);
    in_data01         = (unsigned int *)ioremap(IN_DATA01,4);
    set_ris_trig01    = (unsigned int *)ioremap(SET_RIS_TRIG01,4);
    clr_ris_trig01       = (unsigned int *)ioremap(CLR_RIS_TRIG01,4);
    set_fall_trig01   = (unsigned int *)ioremap(SET_FALL_TRIG01,4);
    clr_fall_trig01      = (unsigned int *)ioremap(CLR_FAL_TRIG01,4);
    instat            = (unsigned int *)ioremap(INSTAT,4);
    pcr               = (unsigned int *)ioremap(PCR,4);
*/       
    printk("<1>\nInserting GPIO module\n");

/**************************************************************/       
    GPIO_REG(IRQ1)=0x01000000;        //GPIO0 INTERRUPT NUMBER = 48 BIT # 17
    GPIO_REG(EINT1)=0x01000000;        //INTERRUPT ENABLE
    GPIO_REG(INTPRI6) = (GPIO_REG(INTPRI6) & 0xFFFFFFFF ) | ( 0x00000003 );     //INTERRUPT PIRIORITY
       //ASP_REG(INTCTL);
    GPIO_REG(DIR01)=0x00000008;
       GPIO_REG(BINTEN)=0x00000001;
    printk("<1>GPIO_SET_INT: %x\n", GPIO_REG(BINTEN));   
    GPIO_REG(SET_RIS_TRIG01)=0x00000008;
    GPIO_REG(EABASE)=0x00000000;
    GPIO_REG(IRQENTRY)=GPIO_REG(EABASE)+(GpioIrq+1)*4;
/********************GPIO NTERRRUPT*******************/   
    //GpioIntRet = request_irq(GpioIrq, gpio_interrupt_handler, SA_INTERRUPT, "gpio",NULL);

    GpioIntRet = request_irq(GpioIrq, gpio_interrupt_handler, 0,"gpio",NULL);
    if (GpioIntRet)
    {
         printk ("Error requesting GPIO irq 56: returned %d\n", GpioIntRet);
    }
    enable_irq(GpioIrq);
/**************************************************************/   

    return 0;
}
/****************************************INTERRUPT HANDLER*****************************************/
void gpio_interrupt_handler(void)
{
    GPIO_REG(SET_DATA01)=0x00000040;
    msleep(100);
//printk("\nGPIO INTERRUPT HANDLER");   
}
/*********************************************Release Function*************************************/
int gpio_release(struct inode *inode, struct file *filp)
{
    // Next State = Disable for the ASP Module
    GPIO_REG(MDCTL17) = 0x00;
    printk("<1>\nMDCTL17: %x\n", GPIO_REG(MDCTL17));
    // Disable the ASP pins on the GPIO
    //ASP_REG(PINMUX1) &= ~(0x00000000 |  (0x1 << 10)); // ASP Multiplex
    printk("<1>PINMUX1: %x\n", GPIO_REG(PINMUX1));
    iounmap(binten);
    iounmap(dir01);
    iounmap(out_data01);
    iounmap(in_data01);
    iounmap(clr_data01);
    iounmap(set_data01);
    iounmap(set_ris_trig01);
    iounmap(clr_ris_trig01);
    iounmap(set_fall_trig01);
    iounmap(clr_fall_trig01);
    iounmap(instat);   
    return 0;
}
/**************************************************************************************************/
int gpio_open(struct inode *inode, struct file *filp)
{

    /* Power Up the ASP Device*/
    //unsigned int control=0;       
    /*Next State = Enable for the ASP Module*/
    GPIO_REG(MDCTL17) = 0x03;
    /* Enable State Transition*/
    GPIO_REG(PTCMD) = 0x1;    // Start power state transition for ALWAYSON
    while((GPIO_REG(PTSTAT) & 0x1) != 0);   /* Wait for power state transtion to finish */
       printk("<1>\nPTSTAT: %x\n", GPIO_REG(PTSTAT));   
    GPIO_REG(PINMUX1) = 0x00000000;    
    mdelay(100);

    printk("<1>BINTEN: %x\n", GPIO_REG(BINTEN));
    printk("<1>SET_RIS_TRIG01: %x\n", GPIO_REG(SET_RIS_TRIG01));

    printk("<1>XCR: %x\n", (unsigned int)ioread32((void *)binten));
    printk("<1>SPCR: %x\n", (unsigned int)ioread32((void *)set_ris_trig01));
   
    return 0;
}
/*********************************************Exit Function****************************************/
static void gpio_exit(void)
{
    /* Freeing the major number */
    unregister_chrdev(MAJOR_VERSION, "gpio");
    gpio_release(0, 0);
    disable_irq(GpioIrq);
    free_irq(GpioIrq, gpio_interrupt_handler);       
    printk("<1>\nRemoving GPIO module\n");
}
/**************************************************************************************************/
/**************************************************************************************************/
/******************************************Read Function*******************************************/
ssize_t gpio_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{   
    //short *data=0;                                
    //unsigned char tmp[2];   
        //data = (unsigned int)ioread32((void *)drr);                       
    //    tmp[0]  = data;                           
    //    tmp[1]    = data>>8;                        
        //    do
        //    {
        //            spcrr = (unsigned int)ioread32((void *)spcr);
        //    }
        //    while((spcrr & RRDY) != RRDY);        ////wait for recieve ready 
    //    copy_to_user(buf,tmp,2);

    return count;
}
/**************************************************************************************************/
/**************************************************************************************************/
ssize_t gpio_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{   
    //unsigned int  spcrr=0;
    //unsigned char tmp[2];   
    //short *data;
    //unsigned int XRDY = (0x00000000 | (0x1 << 17));

    //copy_from_user(tmp,buf,2);/////copy the array from user
    //data = (short *)tmp;//////type cast to the short value
    //printk("%x\n",*data);
    //printk("%x\n",tmp[1]);
//////////////////////////////////////////////////////////////////////////////////////////

        //do
        //{
        //    spcrr = (unsigned int)ioread32((void *)spcr);
        //}
//////////////////////////////////////////////////////////////////////////////////////////
         //while((spcrr & XRDY) != XRDY);             // Wait for Transmitter ready
        //iowrite32((unsigned int)(*data),(void *)dxr);//////transmit the value
       
        return count;
}

MODULE_LICENSE("Dual BSD/GPL");                             
module_init(gpio_init);                    
module_exit(gpio_exit);