⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gpio_interrupt.c

📁 gpio驱动程序
💻 C
字号:
/*  * extdrv/peripheral/keypad/keypad.c * * Copyright (c) 2006 Hisilicon Co., Ltd.  * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA * *  * History:  *      10-April-2006 create this file */#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/string.h>#include <linux/poll.h>#include <linux/interrupt.h>#include <linux/timer.h>#include <linux/miscdevice.h>#include <asm/hardware.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>//#include "gpio_interrupt.h"#include "hi_gpio.h"#if 0static unsigned int  watch_dog = 0; 	static               DECLARE_WAIT_QUEUE_HEAD(keypad_wait);int             	  ready = 0;static int      	  key_value = 0; int             	  keypad_rx_buf[BUFSIZE];size_t          	  rx_buf_tail = 0;size_t              rx_buf_head = 0;static struct   	  timer_list delay_timer;int    			        duration_beg,duration_end;static char 	    	Col_Scan[1]={0x0c};/*  *	initalize gpio config */void gpio_init(void){	   int bitvalue0;     int bitvalue1;	   gpio_dirsetbit(GPIO_1,0,0);//intput;		 gpio_dirsetbit(GPIO_1,1,0);//intput; 		 gpio_readbit(GPIO_1,0,&bitvalue0);	   gpio_readbit(GPIO_1,1,&bitvalue1);	   printk("gpio_1_0 read bitvalue:%d\n",bitvalue0);	   printk("gpio_1_1 read bitvalue:%d\n",bitvalue1);		        unsigned int tmp;    	    	/* set gpio_1 dir: in 0,1 out 2,3 */    	gpio_dirgetbyte(KEY_C_PORT,&tmp);    	tmp |= 0x0c;    	tmp &= 0xfc;    	gpio_dirsetbyte(KEY_C_PORT,tmp);    	/* set gpio_1 interrupt mode */    	gpio_interruptset_byte(                              		KEY_C_PORT,                               		0x03,                               		SENSE_BOTH,                               		SENSE_EDGE,                               		EVENT_FALLING_EDGE                               );                                       /* disable gpio_1_2,3 interrupt */                           	tmp = 0x03;    	gpio_interruptdisable_byte(KEY_C_PORT,tmp);    	    	/* set gpio_1_2,3 low */    //	writew(0xf3,(KEY_C_PORT_ADDR+0x038));        	    	/* clear the int_flags of gpio_1_2,3 */    	tmp = 0x03;    	gpio_interruptclear_byte(KEY_C_PORT,tmp);    	    	/* enable interrupt gpio_1_2,3 */    	tmp = 0x03;    	gpio_interruptenable_byte(KEY_C_PORT,tmp);    }/* *	interrupt handle and start time_list *      Do not to modify the input parameter! */static irqreturn_t  keypad_irq_1(int irq, void *dev_id, struct pt_regs *reg){ 	   	unsigned int  tmp;     	int handled = 0;    	tmp = 0x0f;    	gpio_interruptdisable_byte(KEY_C_PORT,tmp);        	delay_timer.expires = jiffies + margin;    	add_timer (&delay_timer);        	handled = 1;    	return IRQ_RETVAL(handled);}/* *	time_list handle */     //中断处理程序static int delay_timer_handler(unsigned long data)    {    	key_info *key_table=NULL;     	static int key;    	unsigned int i;     	int found_irq = 0;     	int found_key = 0;     	unsigned char current_irq;    	unsigned int  up,tmp;     	/* get the int_flag */    	//扫描按键表,根据中断号,找出所按下的按键    	//列选    	current_irq = readw(KEY_C_PORT_ADDR+GPIO_RIS);    	current_irq = current_irq & 0x03;       	keypad_rx_buf[0]=0;        	keypad_rx_buf[1]=0;    	for (i = 0; i < sizeof key_info_tab / sizeof key_info_tab[1]; i++)      {       	     	    	key_table = (key_info *)(key_info_tab + i);    	    if (key_table->irq_source == current_irq)          {           	keypad_rx_buf[i] = i + 10;          	printk("%d is pressed\n",key_table->irq_source);          }   	   } 	   if(0x03 == current_irq)     {      		keypad_rx_buf[0]=10;      		keypad_rx_buf[1]=11;      }/*  	tmp = 0x03;  	gpio_interruptclear_byte(KEY_C_PORT,tmp);  	if (!found_irq)    {	           	gpio_init();          	printk("interrupt clear error.....................\n");          	return 0;    } // identify the raising_edge int   	up = readw(KEY_C_PORT_ADDR+0x3c0);   	up = up & current_irq;   	    	  	if (up && watch_dog == 1)          	duration_end = jiffies;  	else if(!up && watch_dog == 0)          	duration_beg = jiffies-margin;    else  	{    	gpio_init();    	watch_dog = 0;    	keypad_rx_buf[rx_buf_head] = -1;    	if (++rx_buf_head >= BUFSIZE)    		rx_buf_head -= BUFSIZE;            	    	ready = 1;	    	return 0;    	  	}    //行选   // fix the position of key  	 for(i=0;i<(sizeof (Col_Scan) / sizeof(Col_Scan[1]));i++ )	 {		 writew(Col_Scan[i],(KEY_C_PORT_ADDR+0x038));	   tmp = readw(KEY_C_PORT_ADDR+0x3c0);		 if(!(tmp&current_irq))	   {	  	key_value = key_table->keycode[i];	  	key_value = key_value ;	  	found_key = 1;	  	key = key_value;	   	break;	   }	 }  	if (up && (key<0x5a))  	{     		key_value = key+0x20;        	found_key = 1;  	}  	if(found_key)   	{      	keypad_rx_buf[rx_buf_head] = key_value;          	if (++rx_buf_head >= BUFSIZE)          		rx_buf_head -= BUFSIZE;     }      	if(up)  	{    	  		tmp = duration_end - duration_beg;      	keypad_rx_buf[rx_buf_head] = tmp;      	if (++rx_buf_head >= BUFSIZE)          		rx_buf_head -= BUFSIZE;       	watch_dog = 0;   	  	}  	else      	watch_dog = 1;   */        	gpio_init();  	ready = 1;  	wake_up_interruptible(&keypad_wait);       return 0;}/* *	open device. init gpio and empty the key_value buf */ #endifstatic int alarm_open(struct inode *inode ,struct file *file){//    gpio_init();//   	rx_buf_tail = 0;//   	rx_buf_head = 0;//    ready = 0;    	return 0;}/* *	Close device, Do nothing! */static int alarm_close(struct inode *inode ,struct file *file){    return 0;}#if 0/* *	read key_value buf.  */static int hi_keypad_read(struct file * file, char * buffer, size_t count, loff_t *ppos) {     	int *user_buf = (int *)buffer;    	int *rx_key;retry:    	if (ready)    	{        	copy_to_user(user_buf,(int *)keypad_rx_buf,sizeof(*rx_key)*2);        	if (++rx_buf_tail >= BUFSIZE)            		rx_buf_tail -= BUFSIZE;     	        	count = sizeof(*rx_key)*2;        	if(rx_buf_tail == rx_buf_head)        		ready = 0;	        	return count;    	}    	else    	{        	if ((file->f_flags & O_NONBLOCK) == O_NONBLOCK)                    	return -EAGAIN;                	interruptible_sleep_on(&keypad_wait);        	goto retry;    	}}/* select method. */static unsigned int hi_keypad_select( struct file *file, struct poll_table_struct *wait) {     	if(0 == keypad_rx_buf[0]&& 0 == keypad_rx_buf[1])    	       	ready = 0;        	if(ready)            	return 1;        	poll_wait(file, &keypad_wait, wait);    	return 0;} #endif/* ioctl method,do thing. for future use */static int alarm_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg){	unsigned long val=0;	int bitvalue;	int ret;	unsigned char retval=0;	void __user *argp=(void __user *)arg;    	switch(cmd)     	{ 		case 0:  //read gpio//			if(copy_from_user(&val,argp,sizeof(val)))//				return -EFAULT;			ret = gpio_modeset(GPIO_1,0);//set gpio 1 as software control;  			if(ret!=0)  			  {  				printk("gpio_modeset error\n");  				return -1;  			  }			 ret = gpio_dirsetbit(GPIO_1,0,0);//intput; 			 if(ret!=0) 			    {  				printk("gpio1_4 dir set error\n");  				return -1;  			    }  			 gpio_readbit(GPIO_1,0,&bitvalue );  			 printk("gpio_1_0 read bitvalue:%d\n",bitvalue);			  val=(unsigned long)(bitvalue&0x01);  			 msleep(1);    		return copy_to_user(argp,&val,sizeof(val))? -EFAULT : 0;					case 1: //write gpio			if(copy_from_user(&val,argp,sizeof(val)))				return -EFAULT;			retval=(val&0x01);			ret = gpio_dirsetbit(GPIO_1, 2, 1);//output;  			if(ret!=0) 			 {  				printk("gpio1_4 dir set error\n");  				return -1;  			}  			gpio_writebit(GPIO_1, 2, retval);     					return 0;		        	default:             	return -EINVAL;     	} }    static struct file_operations alarm_fops ={     	.owner =    THIS_MODULE,     	.open =    alarm_open,    	.release=  alarm_close,    	.ioctl=    alarm_ioctl, //   	.poll=     hi_keypad_select, //   	.read=     hi_keypad_read, }; static struct miscdevice alarm_dev = {	MISC_DYNAMIC_MINOR,	DEVICE_NAME,	&alarm_fops,};   static int __init  alarm_init(void){     	int ret;     	ret = misc_register(&alarm_dev);    	if(ret)    	{    		printk("could not register tlv320 devices. \n");    		return ret;    	}      	     	           	gpio_remap();  	ret = gpio_dirsetbit(GPIO_1, 0, 1);//output;	if(ret!=0)  	{  		printk("gpio1_4 dir set error\n");  		return -1; 	 } 	 gpio_writebit(GPIO_1, 0, 1);	 ret = gpio_dirsetbit(GPIO_1, 2, 1);//output;	if(ret!=0)  	{  		printk("gpio1_4 dir set error\n");  		return -1; 	 } 	 gpio_writebit(GPIO_1, 2, 1);		#if 0 	  	ret = request_irq(Irq_1,&keypad_irq_1,0,DEVICE_NAME,NULL);     	if (ret)     	{        	misc_deregister(&alarm_dev); 		      printk(DEVICE_NAME " can't request irq(%d)\n",Irq_0); 		      return ret;    	}	    	printk("Hi35**  Keypad Device Driver v1.0\n");    	init_waitqueue_head(&keypad_wait);    	init_timer(&delay_timer);    	delay_timer.function = (void *)delay_timer_handler;#endif    	return 0; } static void __exit alarm_exit(void){ //    del_timer(&delay_timer);        misc_deregister(&alarm_dev);//     free_irq(Irq_0,NULL);     	gpio_unmap();}module_init(alarm_init);module_exit(alarm_exit);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -