#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/delay.h>
//#include <unistd.h>
#define IRQ_GPIO 145
#define IRQ_TEST "IRQTEST"
#define DEVNAME "GPIOIRQDEV"
#define CONFIG_DISABLE_IN_HANDLER
unsigned short int gpio_irq = 0;
//static unsigned long flags = 0;
unsigned long irqflags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE;
int irq_index = 0;
static struct task_struct *gpio_irq_kthread = NULL;
static irqreturn_t gpio_isr(int irq, void *data)
{
unsigned long flags = 0;
local_irq_save(flags);
printk("gpio_isr triggered\n");
irq_index = 1;
#ifdef CONFIG_DISABLE_IN_HANDLER
disable_irq_nosync(gpio_irq);
#endif
local_irq_restore(flags);
return IRQ_HANDLED;
}
static int thread_gpio_irq_func(void *data)
{
while(!kthread_should_stop()) {
if(irq_index == 1){
#ifdef CONFIG_DISABLE_IN_HANDLER
printk("irq_index = %d enable_irq in kthread\n",irq_index);
enable_irq(gpio_irq);
#else
disable_irq_nosync(gpio_irq);
printk("irq_index = %d disable_irq_nosync in kthread\n",irq_index);
#endif
irq_index = 2;
}else {
#ifdef CONFIG_DISABLE_IN_HANDLER
printk("irq_index = %d irq already enabled\n",irq_index);
#else
if(irq_index == 2){
enable_irq(gpio_irq);
irq_index = 0;
printk("irq_index = %d enable_irq in kthread\n",irq_index);
}
#endif
msleep(300);
}
}
return 0;
}
int __init gpio_irq_init(void)
{
int ret;
ret = gpio_request(IRQ_GPIO,IRQ_TEST);
if (ret) {
printk("IRQ_GPIO!\n");
return ret;
}
ret = gpio_direction_input(IRQ_GPIO);
if (ret) {
printk("gpio_direction_input failed!\n");
return ret;
}
gpio_irq = gpio_to_irq(IRQ_GPIO);
if (gpio_irq < 0) {
printk("gpio_to_irq FAILED!\n");
return -1;
}
irqflags &= IRQF_TRIGGER_MASK;
ret = request_irq(gpio_irq, gpio_isr, irqflags, IRQ_TEST, DEVNAME);
if (ret < 0)
return -1;
ret = enable_irq_wake(gpio_irq);
if (ret < 0){
printk("enable_irq_wake failed\n");
return -1;
}
gpio_irq_kthread = kthread_run(thread_gpio_irq_func,NULL,"thread-gpio-irq");
if (!gpio_irq_kthread) {
printk("kthread_run fail\n");
return -ECHILD;
}
printk("Version 1.2\n");
return ret;
}
void __exit gpio_irq_exit(void)
{
if (gpio_irq_kthread) {
printk("kthread_stop\n");
kthread_stop(gpio_irq_kthread);
gpio_irq_kthread = NULL;
}
disable_irq(gpio_irq);
free_irq(gpio_irq, DEVNAME);
gpio_free(IRQ_GPIO);
}
module_init(gpio_irq_init);
module_exit(gpio_irq_exit);
MODULE_LICENSE("GPL");