📄 s3c24xx_buttons.c
字号:
/*按键驱动* date:Dec.02,2008* author: daihj07@thu* v1.0*/#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/irq.h>#include <linux/interrupt.h>#include <asm/uaccess.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>#include <asm/io.h> //for ioremap#include <linux/delay.h>#define DEVICE_NAME "buttons" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */#define BUTTON_MAJOR 232 /* 主设备号 */struct button_irq_desc { int irq; unsigned long flags; char *name;};/* 用来指定按键所用的外部中断引脚及中断触发方式, 名字 */static struct button_irq_desc button_irqs [] = { {IRQ_EINT1, IRQF_TRIGGER_FALLING, "KEYINT1"}, /* K1 */ {IRQ_EINT2, IRQF_TRIGGER_FALLING, "KEYINT2"}, /* K2 */ {IRQ_EINT3, IRQF_TRIGGER_FALLING, "KEYINT3"}, /* K3 */ {IRQ_EINT4, IRQF_TRIGGER_FALLING, "KEYINT4"}, /* K4 */ {IRQ_EINT5, IRQF_TRIGGER_FALLING, "KEYINT5"}, /* K5 */};/* 用来指定key 所用的GPIO引脚 */static unsigned long key_output_table [] = { S3C2410_GPB6, S3C2410_GPB7, S3C2410_GPB8, S3C2410_GPB9, S3C2410_GPB10,};/* 用来指定GPIO引脚的功能:输出 */static unsigned int key_output_cfg_table [] = { S3C2410_GPB6_OUTP, S3C2410_GPB7_OUTP, S3C2410_GPB8_OUTP, S3C2410_GPB9_OUTP, S3C2410_GPB10_OUTP,};static unsigned long key_input_table [] = { S3C2410_GPF1, S3C2410_GPF2, S3C2410_GPF3, S3C2410_GPF4, S3C2410_GPF5,};/* 按键被按下的次数(准确地说,是发生中断的次数) */static volatile int press_cnt [] = {0, 0, 0, 0, 0};/* 等待队列: * 当没有按键被按下时,如果有进程调用s3c24xx_buttons_read函数, * 它将休眠 */static DECLARE_WAIT_QUEUE_HEAD(button_waitq);/* 中断事件标志, 中断服务程序将它置1,s3c24xx_buttons_read将它清0 */static volatile int ev_press = 0;/* GPB6-10 output, low* GPF1-5, interrupt, 上拉 */static int s3c24xx_key_iocfg(void){ int i; for (i = 0; i < sizeof(key_output_table)/sizeof(key_output_table[0]);i++) { // 设置GPIO引脚的功能:本驱动中GPB6-10 引脚设为输出功能,low s3c2410_gpio_cfgpin(key_output_table[i], key_output_cfg_table[i]); s3c2410_gpio_setpin(key_output_table[i], 0); // output low } /* rGPFCON = (rGPFCON & ~(0x3ff<<2)) | (0x2aa<<2); //GPF 1-5 EINT rGPFUP = rGPFUP&(~(0x1f<<1)); rEXTINT0 = (rEXTINT0& ~(0xfffff<<4)) | (0x00000<<4); //EXTINT 1-5 low level triggered 先只确定内部上拉; */ for(i = 0; i < sizeof(key_input_table)/sizeof(key_input_table[0]);i++) { s3c2410_gpio_pullup(key_input_table[i], 0); } return 0;}/******************************************************************************5*5 键盘五个输入引脚: GPF5 EINT5 EINT5/GPF5 按键 CN1-91 EINTGPF4 EINT4 EINT4/GPF4 按键 CN1-90 EINTGPF3 EINT3 EINT3/GPF3 按键 CN1-89 EINTGPF2 EINT2 EINT2/GPF2 按键 CN1-88 EINTGPF1 EINT1 EINT1/GPF1 按键 CN1-87 EINTGPB10 nXDREQ0 GPB10 CN2-91 按键GPB9 nXDACK0 GPB9 CN2-90 按键GPB8 nXDREQ1 GPB8:LED4:LDMD3:KEY8 CN2-89 按键 输出GPB7 nXDACK1 GPB7:LED3:LDMD2:KEY7 CN2-88 按键 输出GPB6 nXBREQ GPB6:LED2:LDMD1:KEY6 CN2-87 按键 输出GPB5 nXBACK GPB5:LED1:LCM_D0 CN2-86 ******************************************************************************/#if 0static int T3h_key_Scan( int irq ){ int i; int dat; int j; int nirq; unsigned long GPBDAT,GPFDAT,GPFCON; nirq=sizeof(button_irqs)/sizeof(button_irqs[0]); printk("key scan started!,nirq= %d",nirq);/*读取GPFCON寄存器的值*#define rGPFCON (*(volatile unsigned *)0x56000050) //Port F control*/ GPBDAT=(unsigned long)ioremap(0x56000014,4); GPFDAT=(unsigned long)ioremap(0x56000054,4); GPFCON=(unsigned long)ioremap(0x56000050,4); printk("GPFCON = %x",GPFCON); printk("irq=%d in key scan", irq);// delay(900); for(j=0;j<nirq;j++){ if(irq==button_irqs[j].irq){ for(i=0;i<ncol;i++){ (*(volatile unsigned long *)GPBDAT) = ((*(volatile unsigned long *)GPBDAT) & ~(0x1f<<6)) | (~((1<<i)& 0x1f)<<6); // GPB 6-10 clear first and set, low to ready, clear the corresponding bit, set others dat= (*(volatile unsigned long *)GPFDAT)>>1; if(((dat>>j)&1)==0){ printk("row=%d, col=%d\n",i,j); return i+1; } } } } return -1;}#endifstatic int T3h_key_Scan( int irq ){ int i; int dat; int j; int nirq,ncol; int ret=-1; nirq=sizeof(button_irqs)/sizeof(button_irqs[0]); ncol=sizeof(key_output_table)/sizeof(key_output_table[0]);// printk("key scan started!,nirq= %d, ncol= %d,irq=%d in key scan\n", nirq ,ncol,irq); for(i=0;i<ncol;i++){ s3c2410_gpio_setpin(key_output_table[i], 1); // output high } for(j=0;j<nirq;j++){ if(irq==button_irqs[j].irq){ for(i=0;i<ncol;i++){ s3c2410_gpio_setpin(key_output_table[i], 0); // output low dat= s3c2410_gpio_getpin(key_input_table[j]); if(dat==0){// printk("row(j)=%d, col(i)=%d\n",j,i); ret= i+1; break; } s3c2410_gpio_setpin(key_output_table[i], 1); // output high } break; } } for(i=0;i<ncol;i++){ s3c2410_gpio_setpin(key_output_table[i], 0); // output low } return ret;}static irqreturn_t buttons_interrupt(int irq, void *dev_id){ volatile int *press_cnt = (volatile int *)dev_id; //device_id 如何传递的澹
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -