#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DRIVER_NAME "irq"
#define BUFFER_SIZE 256
#ifdef DEBUG
#define PRINTK(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
#else
#define PRINTK(fmt, arg...)
#endif
unsigned int my_irq_Major = 0;
static spinlock_t buffer_lock=SPIN_LOCK_UNLOCKED;
struct kfifo *buffer;
struct semaphore lock;
static struct timer_list myTimer;
void irq_open()
{
enable_irq(IRQ_EINT0);
enable_irq(IRQ_EINT1);
enable_irq(IRQ_EINT2);
enable_irq(IRQ_EINT3);
}
/* Driver Operation Functions */
static int my_irq_open(struct inode *inode, struct file *filp)
{
MOD_INC_USE_COUNT;
GPFCON = 0xffaa; // gpf0~~gpf7 : 1111 1111 1010 1010
GPFUP = 0xf0; //gpf0~~gpf7 : 1111 0000
GPFDAT = 0x0f; //gpf0~~gpf7 : 0000 1111
irq_open();
PRINTK("my_irq open called!\n");
return 0;
}
static int my_irq_release(struct inode *inode, struct file *filp)
{
MOD_DEC_USE_COUNT;
PRINTK("my_irq release called!\n");
return 0;
}
static ssize_t my_irq_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
unsigned char key;
down_interruptible(&lock);
if (kfifo_len(buffer) >= sizeof(key))
kfifo_get(buffer,&key,sizeof(key));
copy_to_user(buf,&key,sizeof(key));
return 0;
}
static ssize_t my_irq_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
PRINTK("my_irq write called!\n");
return 0;
}
static int my_irq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
return 0;
}
/* Driver Operation structure */
static struct file_operations my_irq_fops = {
owner: THIS_MODULE,
write: my_irq_write,
read: my_irq_read,
ioctl: my_irq_ioctl,
open: my_irq_open,
release: my_irq_release,
};
void key14_irq(int irq,void *dev_id,struct pt_regs *regs)
{
disable_irq(irq);
myTimer.expires = jiffies + (7/10)*HZ;
add_timer(&myTimer);
printk("IRQ_EXIT = %d\n",irq);
}
void timerHander(unsigned long data)
{
unsigned char key;
GPFCON = 0x00;
key = GPFDAT;
mdelay(200);
key &= 0x0f;
if (key != 0x0f)
{
key = (~key) & 0x0f;
kfifo_put(buffer,&key,sizeof(key));
up(&lock);
}
GPFCON = 0xaa;
irq_open();
}
/* Module Init & Exit function */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t devfs_my_irq_dir;
devfs_handle_t devfs_my_irq_raw;
#endif
static int __init s3c2410_irq_init(void)
{
/* Module init code */
PRINTK("s3c2410_irq_init\n");
/* Driver register */
my_irq_Major = register_chrdev(0, DRIVER_NAME, &my_irq_fops);
if(my_irq_Major < 0)
{
PRINTK("register char device fail!\n");
return my_irq_Major;
}
PRINTK("register my_irq OK! Major = %d\n", my_irq_Major);
set_external_irq(IRQ_EINT0,EXT_FALLING_EDGE,0);
request_irq(IRQ_EINT0,key14_irq,SA_INTERRUPT,"key_01",(void *)0);
set_external_irq(IRQ_EINT1,EXT_FALLING_EDGE,0);
request_irq(IRQ_EINT1,key14_irq,SA_INTERRUPT,"key_02",(void *)1);
set_external_irq(IRQ_EINT2,EXT_FALLING_EDGE,0);
request_irq(IRQ_EINT2,key14_irq,SA_INTERRUPT,"key_03",(void *)2);
set_external_irq(IRQ_EINT3,EXT_FALLING_EDGE,0);
request_irq(IRQ_EINT3,key14_irq,SA_INTERRUPT,"key_04",(void *)3);
sema_init(&lock,0);
init_timer(&myTimer);
// myTimer.expires = jiffies + (5/100)*HZ; can't
myTimer.data = 0L;
myTimer.function = &timerHander;
add_timer(&myTimer);
buffer = kfifo_alloc(BUFFER_SIZE,GFP_KERNEL,&buffer_lock);
#ifdef CONFIG_DEVFS_FS
devfs_my_irq_dir = devfs_mk_dir(NULL, "my_irq", NULL);
devfs_my_irq_raw = devfs_register(devfs_my_irq_dir, "raw0", DEVFS_FL_DEFAULT, my_irq_Major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &my_irq_fops, NULL);
PRINTK("add dev file to devfs OK!\n");
#endif
return 0;
}
static void __exit s3c2410_irq_exit(void)
{
kfifo_free(buffer);
del_timer(&myTimer);
free_irq(IRQ_EINT0,(void *)0);
free_irq(IRQ_EINT1,(void *)1);
free_irq(IRQ_EINT2,(void *)2);
free_irq(IRQ_EINT3,(void *)3);
/* Module exit code */
PRINTK("s3c2410_irq_exit\n");
/* Driver unregister */
if(my_irq_Major > 0)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_my_irq_raw);
devfs_unregister(devfs_my_irq_dir);
#endif
unregister_chrdev(my_irq_Major, DRIVER_NAME);
}
return;
}
MODULE_AUTHOR("zhanglei");
MODULE_LICENSE("Dual BSD/GPL");
module_init(s3c2410_irq_init);
module_exit(s3c2410_irq_exit);
|