LINUX驱动--ZLG7289(原创)
时间:2009-03-08 来源:c5435
*zlg7289 key driver * INT2, GPF3 ---DIO,GPF4---CLK,GPF2---CS;
*/
#i nclude <asm/hardware.h>
#i nclude <linux/module.h>
#i nclude <linux/fs.h>
#i nclude <linux/types.h>
#i nclude <linux/malloc.h>
#i nclude <asm/uaccess.h>
#i nclude <asm/page.h>
#i nclude <linux/errno.h>
#i nclude <linux/config.h>
#i nclude <asm-armnommu/uaccess.h>
#i nclude <asm/irq.h>
#i nclude <linux/module.h>
#i nclude <linux/version.h>
#i nclude "key.h"
#define uchar unsigned char
#define ushort unsigned short
#define BIT_EINT3 (0x1<<22)
#define BIT_EINT2 (0x1<<23)
#define BIT_EINT1 (0x1<<24)
#define BIT_EINT0 (0x1<<25)
#define BIT_GLOBAL (0x1<<26)
#define DEVICE_NAME "key7289"
#define KEY_MAJOR 88
#define KEY_IRQ INT_EINT2
void writekey(uchar cmd);//
uchar readkey();
void time_delay(ushort i);
static int key_read(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
copy_to_user(buf, &keyvalue, sizeof(keyvalue));
return 0;
}
static int key_write(struct file *filp,char *buf,size_t count,loff_t *f_pos)
{
return 0;
}
static int key_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
return 0;
}
static int key_open(struct inode *inode,struct file *filp)
{
MOD_INC_USE_COUNT;
printk("<>someone open key!\n");
return 0;
}
static int key_release(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
printk("<>someone close key\n");
return 0;
}
void key_handle(int irq,void *dev_id,struct pt_regs *regs)
{
uchar keyv;
disable_irq(KEY_IRQ);
CLEAR_PEND_INT(KEY_IRQ);
CSR_WRITE(rPCONG,(CSR_READ(rPCONG) &(~(3<<4))));
CSR_WRITE(rI_ISPC,(CSR_READ(rI_ISPC)|BIT_EINT2)); // Clear EINT's Pending Bit
CSR_WRITE(rPDATF,(CSR_READ(rPDATF)&(~(1<<2)))); //key_cs = 0
writekey(0x15);
time_delay(200);
keyv=readkey();
CSR_WRITE(rPDATF,(CSR_READ(rPDATF)|(1<<2))); //key_cs = 1
printk("%d",keyv);
time_delay(200);
CSR_WRITE(rPCONG,(CSR_READ(rPCONG)|(3<<4))); //INT2
enable_irq(KEY_IRQ);
}
void key_init(void)
{
int ret;
CSR_WRITE(rPCONG,(CSR_READ(rPCONG)|(3<<4))); //INT2 eint2 interrupt
CSR_WRITE(rEXTINT,(CSR_READ(rEXTINT)|0x22222200));//下降沿触发
CSR_WRITE(rI_ISPC,(CSR_READ(rI_ISPC)|BIT_EINT2)); // Clear EINT's Pending Bit
CSR_WRITE(rINTMSK,(CSR_READ(rINTMSK)&(~BIT_EINT2))); // Enable interrupt
CSR_WRITE(rPCONF,(CSR_READ(rPCONF) |(1<<6))); //GPF3 out GPF3 STATE will be change --DIO
CSR_WRITE(rPCONF,(CSR_READ(rPCONF) |(1<<8))); //GPF4 out -- CLK
CSR_WRITE(rPCONF,(CSR_READ(rPCONF) |(1<<4)));//GPF2 out ---CS
CSR_WRITE(rPDATF,(CSR_READ(rPDATF)|(1<<2))); //key_cs = 1
ret = register_chrdev(KEY_MAJOR,"key",&key_fops);
if(ret<0) {
printk("fail to register\n");
}
CLEAR_PEND_INT(KEY_IRQ);
if(KEY_IRQ >=0){
ret = request_irq(KEY_IRQ,key_handle,SA_INTERRUPT,"key",NULL);
if(ret){
printk("key:cant get assigned irq %i\n",KEY_IRQ);
}
else{
printk("key:request external interrupt %i\n",KEY_IRQ);
}
}
enable_irq(KEY_IRQ);
}
void writekey(uchar cmd)
{
uchar i =0,tem;
CSR_WRITE(rPCONF,(CSR_READ(rPCONF) |(1<<6)));//PF3 out
time_delay(50);
while(i<8)
{
CSR_WRITE(rPDATF,(CSR_READ(rPDATF)&(~(1<<4))));//key clk =0 GPF4;
tem = (cmd>>(7-i))&1;
if(tem == 0) CSR_WRITE(rPDATF,(CSR_READ(rPDATF)&(~(1<<3))));
else CSR_WRITE(rPDATF,(CSR_READ(rPDATF)|(1<<3)));
time_delay(20);
CSR_WRITE(rPDATF,(CSR_READ(rPDATF)|(1<<4))); //key_clk =1;
time_delay(20);
i++;
}
}
uchar readkey()
{
uchar i=0;
int pp;
uchar keyvalue;
keyvalue = 0;
CSR_WRITE(rPCONF,(CSR_READ(rPCONF)&(~(3<<6))));//PF3 in
time_delay(50);
while(i<9)
{
CSR_WRITE(rPDATF,(CSR_READ(rPDATF)|(1<<4)));//key clk =1;
time_delay(20);
pp = CSR_READ(rPDATF)&0x000f;
keyvalue=keyvalue<<1;
if(pp>=8) keyvalue++;
CSR_WRITE(rPDATF,(CSR_READ(rPDATF)&(~(1<<4))));//key clk =0;
time_delay(20);
i++;
}
keyvalue=keyvalue&(~(1<<8));
return keyvalue;
}
void time_delay(ushort i)
{
ushort cm=0;
while(cm<i)
{
cm++;
}
}