以下是网上找到的FS2410下面的键盘驱动,本人稍作修改。可以编译通过,但是下到板子里insmod,发现不能注册中断。即request_irq函数有什么问题么?希望高手帮忙! #include <linux/module.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/config.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/sched.h> #include <linux/devfs_fs_kernel.h> #include <linux/slab.h> #include <linux/fcntl.h> #include <linux/delay.h> #include <linux/poll.h> #include <linux/console.h> #include <linux/parport.h> #include <linux/lp.h> #include <asm/io.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <asm/uaccess.h>
#define GPECON (0x56000040) #define GPFCON (0x56000050) #define GPGCON (0x56000060) #define GPEDAT (0x56000044) #define GPFDAT (0x56000054) #define GPGDAT (0x56000064) #define SRCPND (0x4A000000) #define EINTMASK (0x560000A4) #define INTMASK (0x4A000008) static void *gpecon; static void *gpfcon; static void *gpgcon; static void *gpedat; static void *gpfdat; static void *gpgdat; static void *srcpnd; static void *eintmask; static void *intmask; MODULE_LICENSE("GPL"); //2.6内核必须有,否则不能加载 #define keyirq_MAJOR 242 #define NAME "buttons" #define NOKEY 0xff static struct semaphore key_sem; static char key=NOKEY; /*----------清除中断------------------*/ static void inline clearIrq(void) { //mdelay(100); //防抖动 writel(readl(srcpnd)|0x25,srcpnd);//clear srcpnd 0 2 11 19 } /*---------键盘扫描-----------------*/ static int Key_Scan( void ) { //mdelay(100); writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (1<<6) | (0<<2) ,gpgdat); //GPG2 output 0;GP6 output 1 writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (1<<13) | (1<<11) ,gpedat); //GPE13,11 output 1 if( (readl(gpfdat)&(1<< 0)) == 0 ) return 16 ; else if( (readl(gpfdat)&(1<< 2)) == 0 ) return 15 ; else if( (readl(gpgdat)&(1<< 3)) == 0 ) return 14 ; else if( (readl(gpgdat)&(1<<11)) == 0 ) return 13 ; writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (0<<6) | (1<<2) ,gpgdat); //GPG6 output 0;GPG2 output 1 writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (1<<13) | (1<<11) ,gpedat); //GPE13,11 output 1 if( (readl(gpfdat)&(1<< 0)) == 0 ) return 11 ; else if( (readl(gpfdat)&(1<< 2)) == 0 ) return 8 ; else if( (readl(gpgdat)&(1<< 3)) == 0 ) return 5 ; else if( (readl(gpgdat)&(1<<11)) == 0 ) return 2 ; writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (1<<6) | (1<<2) ,gpgdat); //GPG6,2 output 1 writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (1<<13) | (0<<11) ,gpedat); //GPE13 output 1;GPE11 output 0 if( (readl(gpfdat)&(1<< 0)) == 0 ) return 10 ; else if( (readl(gpfdat)&(1<< 2)) == 0 ) return 7 ; else if( (readl(gpgdat)&(1<< 3)) == 0 ) return 4 ; else if( (readl(gpgdat)&(1<<11)) == 0 ) return 1 ;
writel(readl(gpgdat)&(~((1<<6)|(1<<2))) | (1<<6) | (1<<2) ,gpgdat); //GPG6,2 output 1 writel(readl(gpedat)&(~((1<<13)|(1<<11))) | (0<<13) | (1<<11) ,gpedat); //GPE11 output 1;GPE13 output 0 if( (readl(gpfdat)&(1<< 0)) == 0 ) return 12 ; else if( (readl(gpfdat)&(1<< 2)) == 0 ) return 9 ; else if( (readl(gpgdat)&(1<< 3)) == 0 ) return 6 ; else if( (readl(gpgdat)&(1<<11)) == 0 ) return 3 ; return 0xff ; } static irqreturn_t irq_isr(int irq, void *dev_id, struct pt_regs *regs) { //GPGCON = GPGCON & (~((3<<22)|(3<<6))) | ((0<<22)|(0<<6)) ; //GPG11,3 set input //GPFCON = GPFCON & (~((3<<4)|(3<<0))) | ((0<<4)|(0<<0)) ; //GPF2,0 set input writel(readl(gpgcon)& (~((3<<22)|(3<<6))) | ((0<<22)|(0<<6)),gpgcon);//set gpg11 3 to input writel(readl(gpfcon)& (~((3<<4)|(3<<0))) | ((0<<4)|(0<<0)),gpfcon);//set gpf2 0 to input //查询按键键值 key = Key_Scan() ; if( key != 0xff ) printk("Interrupt occur... K%d is pressed!\n", key ) ; //printk("Interrupt " ) ; //Beep( 2000, 3000 ) ;
//重新初始化IO口 //rGPGCON = rGPGCON & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)) ; //GPG6,2 set output //rGPGDAT = rGPGDAT & (~((1<<6)|(1<<2))); //GPG6,2 output 0
//rGPECON = rGPECON & (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22)); //GPE13,11 set output //rGPEDAT = rGPEDAT & (~((1<<13)|(1<<11))); //GPE13,11 output 0
//rGPGCON = rGPGCON & (~((3<<22)|(3<<6))) | ((2<<22)|(2<<6)) ; //GPG11,3 set EINT //rGPFCON = rGPFCON & (~((3<<4)|(3<<0))) | ((2<<4)|(2<<0)) ; //GPF2,0 set EINT
writel(readl(gpecon)& (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22)),gpecon);//set gpe11 13 to output writel(readl(gpedat)&(~((1<<13)|(1<<11))) ,gpedat); //set GPE11 13 to 00 writel(readl(gpgcon) & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)),gpgcon);//set gpe2 6 to output writel(readl(gpgdat)&(~((1<<6)|(1<<2))) ,gpgdat); //set GPG2 6 to 00 : writel(readl(gpgcon)&(~((3<<22)|(3<<6))) | ((2<<22)|(2<<6)),gpgcon); //set GPG3/EINT11,GPG11/EINT19 writel(readl(gpfcon)&(~((3<<4)|(3<<0))) | ((2<<4)|(2<<0)),gpfcon);//set GPF0/EINT0,GPF2/EINT2 up(&key_sem); return IRQ_HANDLED; }
static ssize_t keyirq_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { if(down_interruptible(&key_sem)) { return -ERESTARTSYS; }; put_user(key, buf); key = NOKEY; return 1; } int keyirq_open(struct inode *inode, struct file *file) { clearIrq(); #if 1 enable_irq(IRQ_EINT0); enable_irq(IRQ_EINT2); enable_irq(IRQ_EINT11); enable_irq(IRQ_EINT19); #endif sema_init(&key_sem, 0); return 0; } int keyirq_release(struct inode *inode, struct file *filp) { #if 1 disable_irq(IRQ_EINT0); disable_irq(IRQ_EINT2); disable_irq(IRQ_EINT11); disable_irq(IRQ_EINT19); #endif return 0; }
static int keyirq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return 0; } struct file_operations keyirq_fops = { .owner= THIS_MODULE, .read = keyirq_read, .open = keyirq_open, .release = keyirq_release, .ioctl = keyirq_ioctl, }; int __init keyirq_init(void) { int rc; if ((rc = register_chrdev(keyirq_MAJOR, NAME, &keyirq_fops)) < 0) { printk("keyirq: can't get major %d\n", keyirq_MAJOR); return 1; } else { printk("buttons.ko register success"); } gpecon=ioremap_nocache(GPECON,0x0000004); gpfcon=ioremap_nocache(GPFCON,0x0000004); gpgcon=ioremap_nocache(GPGCON,0x0000004); srcpnd=ioremap_nocache(SRCPND,0x0000004); intmask=ioremap_nocache(INTMASK,0x0000004); eintmask=ioremap_nocache(EINTMASK,0x0000004); gpedat=ioremap_nocache(GPEDAT,0x0000004);//remap, ready for follow step gpfdat=ioremap_nocache(GPFDAT,0x0000004); gpgdat=ioremap_nocache(GPGDAT,0x0000004); writel(readl(gpgcon)&0xffbfffbf,gpgcon); //set GPG3/EINT11,GPG11/EINT19 writel(readl(gpgcon)|0x800080,gpgcon);//... writel(readl(gpfcon)&0xffffffee,gpfcon);//set GPF0/EINT0,GPF2/EINT2 writel(readl(gpfcon)|0x22,gpfcon);//... writel(readl(intmask)&0xffffffda,intmask);//set interr enable writel(readl(eintmask)&0xfff7f7ff,eintmask); writel(readl(gpecon)& (~((3<<26)|(3<<22))) | ((1<<26)|(1<<22)),gpecon);//set gpe11 13 to output writel(readl(gpedat)&(~((1<<13)|(1<<11))) ,gpedat); //set GPE11 13 to 00 writel(readl(gpgcon) & (~((3<<12)|(3<<4))) | ((1<<12)|(1<<4)),gpgcon);//set gpe2 6 to output writel(readl(gpgdat)&(~((1<<6)|(1<<2))) ,gpgdat); //set GPG2 6 to 00 : printk(KERN_ERR "have initial interr,ok!\n"); set_irq_type(IRQ_EINT0, IRQT_FALLING); set_irq_type(IRQ_EINT2, IRQT_FALLING); set_irq_type(IRQ_EINT11, IRQT_FALLING); set_irq_type(IRQ_EINT19, IRQT_FALLING);
rc = request_irq(IRQ_EINT0, irq_isr, SA_INTERRUPT, NAME, NULL); if (rc) { printk ("<1>keyirq 1 irq not registered. Error:%d\n", rc); } rc = request_irq(IRQ_EINT2, irq_isr, SA_INTERRUPT, NAME, NULL); if (rc) { printk ("<1>keyirq 2 irq not registered. Error:%d\n", rc); } rc = request_irq(IRQ_EINT11, irq_isr, SA_INTERRUPT, NAME, NULL); if (rc) { printk ("<1>keyirq 4 irq not registered. Error:%d\n", rc); } rc = request_irq(IRQ_EINT19, irq_isr, SA_INTERRUPT, NAME, NULL); if (rc) { printk ("<1>keyirq 4 irq not registered. Error:%d\n", rc); } disable_irq(IRQ_EINT0); disable_irq(IRQ_EINT2); disable_irq(IRQ_EINT11); disable_irq(IRQ_EINT19); #if 0 enable_irq(IRQ_EINT0); enable_irq(IRQ_EINT2); enable_irq(IRQ_EINT11); enable_irq(IRQ_EINT19); #endif /* if ((rc = register_chrdev(keyirq_MAJOR, NAME, &keyirq_fops)) < 0){ printk("keyirq: can't get major %d\n", keyirq_MAJOR); return 1; }*/ return 0; } void keyirq_exit(void) { #if 1 disable_irq(IRQ_EINT0); disable_irq(IRQ_EINT2); disable_irq(IRQ_EINT11); disable_irq(IRQ_EINT19); #endif free_irq(IRQ_EINT0, NULL); free_irq(IRQ_EINT2, NULL); free_irq(IRQ_EINT11, NULL); free_irq(IRQ_EINT19, NULL);
unregister_chrdev(keyirq_MAJOR, NAME); } module_init(keyirq_init); module_exit(keyirq_exit); |
|