#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);
|