Hi ,
I am trying to get edge sensitive interrupt (from GPIO Port B bit 0), working
on my Ts-7250 board.
I run kernel 2.6 through rootfs mounted through NFS.
Following is the part kernel module i had written for it .
/*********************************************************************/
/*** Assume all the necessary hdr are present*/
/******************** GLOBALS *********************************/
static char *dev_name = "My GPIOs";
static unsigned int bit = 0;
static int counter = 0;
static int irq_num = IRQ_EP93XX_GPIO_AB;
/******************** GLOBALS *********************************/
/****************** IRQ handler ***************/
static irqreturn_t irq_handler(int irq, void * dev_id)
{
unsigned int unmasked;
printk("IRQ %d handler called\n", irq);
printk( "GPIO_B_INTENB = 0x%x\n ",
__raw_readl(EP93XX_GPIO_B_INT_ENABLE) );
printk( "GPIO_B_TYP1 = 0x%x\n ",
__raw_readl(EP93XX_GPIO_B_INT_TYPE1) );
printk( "GPIO_B_TYP2 = 0x%x\n ",
__raw_readl(EP93XX_GPIO_B_INT_TYPE2) );
printk( "GPIO_B_EOI = 0x%x\n ",
__raw_readl(EP93XX_GPIO_B_INT_ACK) );
printk( "EP93XX_GPIO_B_INT_STATUS = 0x%x\n ",
__raw_readl(EP93XX_GPIO_B_INT_STATUS));
return IRQ_HANDLED;
}
/***** INIT******/
int irqtest_init(void)
{
int ret=0;
struct task_struct* tid=NULL;
printk("Entering irqtest_init\n");
ret=request_irq (irq_num,
irq_handler, SA_INTERRUPT, DEVICE_NAME, NULL );
if (ret)
{
printk(KERN_ERR MODULE_NAME " :Unable to get irq %d for "
DEVICE_NAME " (err=%d)\n",
bit,ret);
return false;
}
//Requesting gpio port B bit 0 of of
ret=request_irq (72,
irq_handler,SA_INTERRUPT,DEVICE_NAME, NULL );
if (ret)
{
printk(KERN_ERR MODULE_NAME " :Unable to get irq %d for "
DEVICE_NAME " (err=%d)\n", 72,ret);
return false;
}
//Configure registers
config_intr();
return ret;
}
/************* Module EXIT ****************************/
void irqtest_exit(void) {
unsigned int unmasked = 0, mask ;
printk("Entering irqtest_exit\n");
printk( "GPIO_B_INTENB = 0x%x\n ",
readl(EP93XX_GPIO_B_INT_ENABLE) );
printk( "GPIO_B_TYP1 = 0x%x\n ",
readl(EP93XX_GPIO_B_INT_TYPE1) );
printk( "GPIO_B_TYP2 = 0x%x\n ",
readl(EP93XX_GPIO_B_INT_TYPE2) );
printk( "GPIO_B_EOI = 0x%x\n ",
readl(EP93XX_GPIO_B_INT_ACK) );
printk( "EP93XX_GPIO_B_INT_STATUS = 0x%x\n ",
__raw_readl(EP93XX_GPIO_B_INT_STATUS) );
//Restore the pin to GPIO mode
mask = (1 << bit);
//Disable interrupt by writing to GPIO Interrupt Enable register.
unmasked = __raw_readb(EP93XX_GPIO_B_INT_ENABLE);
unmasked = unmasked & (~mask);
__raw_writel( unmasked , EP93XX_GPIO_B_INT_ENABLE );
printk(" EP93XX_GPIO_B_INT_ENABLE = 0x%x \n",
__raw_readl( EP93XX_GPIO_B_INT_ENABLE ) );
//Clear the interrupt by writing to GPIO_B_EOI register
unmasked = __raw_readb(EP93XX_GPIO_B_INT_ACK);
unmasked = unmasked | mask;
__raw_writel( unmasked, EP93XX_GPIO_B_INT_ACK );
printk(" EP93XX_GPIO_B_INT_ACK = 0x%x \n",
__raw_readl( EP93XX_GPIO_B_INT_ACK ) );
free_irq( irq_num, NULL);
free_irq( 72, NULL);
}
/**** config interrupt registers ******/
void config_intr()
{
unsigned int unmasked =0, mask =0;
/*
In order to stop any spurious interrupts that may occur during the programming
of the GPIOxINTTYPEx registers, the following sequence should be observed:
1. Disable interrupt by writing to GPIO Interrupt Enable register.
2. Set interrupt type by writing GPIOxINTTYPE1/2 register.
3. Clear interrupt by writing to GPIOxEOI register.
4. Enable interrupt by writing to GPIO Interrupt Enable register.
*/
mask = (1 << bit);
//Set interupt line as Input
gpio_line_config ( EP93XX_GPIO_LINE_B(bit), GPIO_IN);
//Disable interrupt by writing to GPIO Interrupt Enable register.
unmasked = __raw_readl(EP93XX_GPIO_B_INT_ENABLE);
unmasked = unmasked & (~mask);
__raw_writel( unmasked ,EP93XX_GPIO_B_INT_ENABLE );
//Set interrupt type ,as Edge Sensitive, by writing 1 to
GPIO_B_INTTYPE1 register
unmasked = __raw_readl(EP93XX_GPIO_B_INT_TYPE1);
unmasked = unmasked | mask;
__raw_writel( unmasked, EP93XX_GPIO_B_INT_TYPE1 );
//Set Edge Sensitive interrupt type ,
//as Rising Edge, by writing 1 to GPIO_B_INTTYPE2 register.
unmasked = __raw_readl(EP93XX_GPIO_B_INT_TYPE2);
unmasked = unmasked | mask;
__raw_writel( unmasked, EP93XX_GPIO_B_INT_TYPE2 );
//Clear EOI by writing 1
unmasked = __raw_readl(EP93XX_GPIO_B_INT_ACK );
unmasked = unmasked | mask;
__raw_writel( unmasked, EP93XX_GPIO_B_INT_ACK );
//Enable interrupt by writing to GPIO Interrupt Enable register.
unmasked = __raw_readl(EP93XX_GPIO_B_INT_ENABLE);
unmasked = unmasked | mask;
__raw_writel( unmasked ,EP93XX_GPIO_B_INT_ENABLE );
}
I give pulses to the EGPIO8(Port B bit 0) on DIO pins of the board.
Following are my queries
1. My irq_handler does not get hit if I register to only IRQ_EP93XX_GPIO(
EP93XX_GPIO_LINE_B(0) ) - 72 , (which correponds to port b bit 0 )
It gets hit only when I request_irq() for IRQ 72 and IRQ_EP93XX_GPIO_AB. Why
is this so ?
2. I find after doing the above , the interrupt handler is invoked only for
level sensitive interrupts- by having a logic0 on the pin EGPIO8.
This happens even after setting the necessary GPIO interrupt registers in
config_intr() to respond to rising-edge pulses.
I got to know that by printing the contents the registers
I need to know if this is the right way and if, not what is right way to set
the interrupt type. Is there any kernel function to do this?
------------------------------------
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> Your email settings:
Individual Email | Traditional
<*> To change settings online go to:
http://groups.yahoo.com/group/ts-7000/join
(Yahoo! ID required)
<*> To change settings via email:
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|