📄 buttondrv.c
字号:
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++File Name: buttondrv.cAbstract: device driver for bond/restore button(conneted to gpf2/gpf0) Author: Huiqing GuoRevision History: 2007.10 created 2007.12 sleep_on() changed to interruptible_sleep_on(); wake_up() changed to wake_up_interruptible(); free_irq(irq,NULL) changed to free_irq(irq,pdata); add s3c_irq_*() function. 2008.1 add s3c_gpio_setmode() function. reimplement button check mechanism.---------------------------------------------------------------------------*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/interrupt.h>#include <linux/fs.h>#include <linux/init.h>#include <asm/arch/regs-gpio.h>#include <asm/arch/regs-irq.h>MODULE_AUTHOR("lxt"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS("led"); MODULE_LICENSE("GPL"); // ========== Constant definitions==========#define constant0 0x1#define constant2 0x4#define input_mode 0x0#define extint_mode 0x2//#define delay HZ/10 // 100ms//#define delay HZ/50 //#### modify my ttaaoo 20ms#define delay HZ/HZ //#### modify my ttaaoo 1ms// ========== dev number definitions========#define button_dev_num 230struct button_data_struct{ unsigned int readvalue; unsigned int irq; wait_queue_head_t readwaitqueue; struct timer_list timer; };static int button_open(struct inode * inode, struct file * filp);static int button_release(struct inode * inode, struct file * filp);static ssize_t button_read(struct file * filp, int * buf,size_t count,loff_t * l);static struct button_data_struct button_data[2];static struct file_operations button_fops = { .owner = THIS_MODULE, .open = button_open, .release = button_release, .read = button_read, };static void s3c_gpio_setmode(unsigned int irqno,unsigned char mode){ unsigned long value; unsigned long offset = (irqno - IRQ_EINT0) * 2; value = __raw_readl(S3C2410_GPFCON); value = (value & ~(3 << offset)) | (mode << offset); __raw_writel(value, S3C2410_GPFCON);}static void s3c_irq_mask(unsigned int irqno){ unsigned long mask; irqno -= IRQ_EINT0; mask = __raw_readl(S3C2410_INTMSK); mask |= 1UL << irqno; __raw_writel(mask, S3C2410_INTMSK);}static void s3c_irq_ack(unsigned int irqno){ unsigned long bitval = 1UL << (irqno - IRQ_EINT0); __raw_writel(bitval, S3C2410_SRCPND); __raw_writel(bitval, S3C2410_INTPND);}static void s3c_irq_unmask(unsigned int irqno){ unsigned long mask; irqno -= IRQ_EINT0; mask = __raw_readl(S3C2410_INTMSK); mask &= ~(1UL << irqno); __raw_writel(mask, S3C2410_INTMSK);}static void button_timer(unsigned long data){ struct button_data_struct *pdata = (struct button_data_struct *)data; unsigned long value; unsigned long mask; if(pdata->irq == IRQ_EINT0) mask = constant0; else mask = constant2; value = __raw_readl(S3C2410_GPFDAT); value &= mask; if(value) //unnormal interrupt { printk(KERN_EMERG"timer %ld , value = %d, readvalue = %d \n", jiffies, value, pdata->readvalue); s3c_gpio_setmode(pdata->irq,extint_mode); s3c_irq_unmask(pdata->irq); del_timer(&pdata->timer); wake_up_interruptible(&pdata->readwaitqueue); } else //normal interrupt { // printk(KERN_EMERG"timer %ld , value = %d\n", jiffies, value); mod_timer(&pdata->timer,jiffies + delay); pdata->readvalue ++; } }static irqreturn_t button_interrupt_handler(int irq,void * dev_id){ struct button_data_struct * pdata = (struct button_data_struct *)dev_id; printk(KERN_EMERG"\nenter interrupt %ld \n", jiffies); pdata->readvalue = 0; s3c_irq_mask(irq); s3c_gpio_setmode(irq,input_mode); /* 设置io 为输入模式 */ del_timer(&pdata->timer); pdata->timer.expires = jiffies + delay; add_timer(&pdata->timer);out: return IRQ_HANDLED;}static int button_open(struct inode * inode, struct file * filp){ unsigned char devnum = MINOR(inode->i_rdev); struct button_data_struct * pdata = &(button_data[devnum]); filp->private_data = pdata; return 0;}static int button_release(struct inode * inode,struct file * filp){ unsigned char devnum = MINOR(inode->i_rdev); struct button_data_struct * pdata = filp->private_data; unsigned int irq; if(devnum==0) irq = IRQ_EINT2; else irq = IRQ_EINT0; free_irq(irq,pdata); del_timer(&pdata->timer); return 0;}static ssize_t button_read(struct file * filp, int * buf, size_t count, loff_t * l){ struct button_data_struct * pdata = filp->private_data; interruptible_sleep_on(&pdata->readwaitqueue); if(copy_to_user(buf, &pdata->readvalue, 1)) return -EFAULT; pdata->readvalue = 0; return 0;}static int __init button_init(void){ int rc; if (register_chrdev(button_dev_num, "buttondrv", &button_fops) < 0) { printk("Can not allocate char type main device number %d\n",button_dev_num); return -1; } rc=request_irq(IRQ_EINT2, &button_interrupt_handler, IRQF_SHARED, "button", &(button_data[0])); if(rc<0) { printk("Can not allocate irq number %d,error number is %d\n",IRQ_EINT2, rc); return -1; } rc=request_irq(IRQ_EINT0,&button_interrupt_handler,IRQF_SHARED,"button",&(button_data[1])); if(rc<0) { printk("Can not allocate irq number %d,error number is %d\n",IRQ_EINT0, rc); return -1; } s3c_irq_mask(IRQ_EINT2); s3c_irq_ack(IRQ_EINT2); s3c_irq_unmask(IRQ_EINT2); init_timer(&button_data[0].timer); button_data[0].timer.function = &button_timer; button_data[0].timer.data = (unsigned long)(&(button_data[0])); button_data[0].irq = IRQ_EINT2; button_data[0].readvalue = 0; init_waitqueue_head(&button_data[0].readwaitqueue); s3c_irq_mask(IRQ_EINT0); s3c_irq_ack(IRQ_EINT0); s3c_irq_unmask(IRQ_EINT0); init_timer(&button_data[1].timer); button_data[1].timer.function = &button_timer; button_data[1].timer.data = (unsigned long)(&(button_data[1])); button_data[1].irq = IRQ_EINT0; button_data[1].readvalue = 0; init_waitqueue_head(&button_data[1].readwaitqueue); printk("######################################### register button\n "); printk("######################################### register button\n "); printk("######################################### register button\n "); return 0;}static void __exit button_cleanup(void){ unregister_chrdev(button_dev_num,"buttondrv"); return;}module_init (button_init);module_exit (button_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -