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