IT民工
分类: LINUX
2009-08-28 12:53:58
/*======================================
定时器程序还有一点点问题,按键的时候不能屏蔽中断,
一个键按下去会不停的产生中断
=======================================*/
#ifndef MODULE
#define MODULE
#endif
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "key"
#define KEY_NUMBER 123
#define GPF_CON 0x56000050
#define GPF_DATA 0x56000054
#define GPB_CON 0x56000010
#define GPB_DATA 0x56000014
#define GPG_CON 0x56000060
#define GPG_DATA 0x56000064
#define SRCPND 0x4a000000
#define no_key_enter -1
#define s1 1
#define s2 2
#define s3 3
#define s4 4
#define s5 5
#define s6 6
#define s7 7
#define s8 8
#define GPF_0_H (1<<0)
#define GPF_2_H (1<<2)
#define GPG_3_H (1<<3)
#define GPG_11_H (1<<11)
#define GPB_6_H (1<<6)
#define GPB_7_H (1<<7)
#define INTERRUPT_BASE 0x4a000000
#define EINT0 (1<<0)
#define EINT2 (1<<2)
#define EINT8_23 (1<<5) // EINT11,EINT19
#define EINT11 (1<<11)
#define EINT19 (1<<19)
#define INTMOD 0x04
#define INTMASK_CON 0x560000a4
MODULE_LICENSE("GPL");
static unsigned int ver_GPB_6_7_addr; //shu xian
static unsigned int hor_GPG_3_11_addr; //heng xian
static unsigned int hor_GPF_0_2_addr;
static unsigned int ver_GPB_6_7_data;
static unsigned int hor_GPF_0_2_data;
static unsigned int hor_GPG_3_11_data;
void *srcpnd;
static unsigned int interrupt_addr;
static unsigned char keyval;
int read=0;
static unsigned int GPB_6_7_LOW_PORT=0x73f;
static unsigned int EINTMASK_ADDR;
wait_queue_head_t buttons_wait;
static void set_interrupt_port();
static void cleanpend();
static void get_system_port_addr(void)
{
ver_GPB_6_7_addr=(unsigned int)ioremap(GPB_CON,4);
ver_GPB_6_7_data=(unsigned int)ioremap(GPB_DATA,4);
hor_GPF_0_2_addr=(unsigned int)ioremap(GPF_CON,4);
hor_GPF_0_2_data=(unsigned int)ioremap(GPF_DATA,4);
hor_GPG_3_11_addr=(unsigned int)ioremap(GPG_CON,4);
hor_GPG_3_11_data=(unsigned int)ioremap(GPG_DATA,4);
interrupt_addr=(unsigned int)ioremap(INTERRUPT_BASE,1024); //0x4a000000
EINTMASK_ADDR=(unsigned int )ioremap(INTMASK_CON,1024);
srcpnd=EINTMASK_ADDR;// srcpnd=EINTMASK_ADDR;
}
static void enable_interrupt()
{
unsigned int interrupt_statu;
interrupt_statu=readl(interrupt_addr);
interrupt_statu=interrupt_statu&0x021;
writel(interrupt_statu,interrupt_addr);
interrupt_statu=readl(interrupt_addr+INTMOD); //INTMOD 0x4a000000+ 0x04
interrupt_statu=interrupt_statu&(~(EINT0 | EINT2 | EINT8_23)); //set bit to 0 ,enable IRQ mode
writel(interrupt_statu,interrupt_addr+INTMOD);
// printk("<1> 01\r\n");
interrupt_statu=readl(EINTMASK_ADDR); //0x560000a4
interrupt_statu=interrupt_statu&(~(EINT0 | EINT2 | EINT11 | EINT19)); //set bit to 0 ,enable interrupt,to 1,is masked
writel(interrupt_statu,EINTMASK_ADDR);
// printk("<1> 02\r\n");
// interrupt_statu=readl(EINTMASK_ADDR);
// interrupt_statu=interrupt_statu&(~(EINT11 | EINT19));
// writel(interrupt_statu,EINTMASK_ADDR);
set_interrupt_port();
}
#if 0
static void unable_interrupt()
{
unsigned int interrupt_statu;
unsigned int GPF_IN_DATA,GPG_IN_DATA;
unsigned int hor_GPG_3_11_statu,hor_GPF_0_2_statu;
interrupt_statu=readl(interrupt_addr);
interrupt_statu=interrupt_statu&0x021;
writel(interrupt_statu,interrupt_addr);
interrupt_statu=readl(interrupt_addr+INTMOD); //INTMOD 0x4a000000+ 0x04
interrupt_statu=interrupt_statu&(~(EINT0 | EINT2 | EINT8_23)); //set bit to 0 ,enable IRQ mode
writel(interrupt_statu,interrupt_addr+INTMOD);
// printk("<1> 01\r\n");
interrupt_statu=readl(EINTMASK_ADDR); //0x560000a4
interrupt_statu=interrupt_statu&((EINT0 | EINT2 | EINT11 | EINT19)); //set bit to 0 ,enable interrupt,to 1,is masked
writel(interrupt_statu,EINTMASK_ADDR);
hor_GPF_0_2_statu=readl(hor_GPF_0_2_addr);
GPF_IN_DATA=(hor_GPF_0_2_statu&0xffcc)|0x0011; //set interrput port,enable GPF0,GPF2,interrupt module
printk("<1>GPF_IN_DATA=%x\r\n",GPF_IN_DATA);
writel(GPF_IN_DATA,hor_GPF_0_2_addr);
// printk("<1> 04\r\n");
hor_GPG_3_11_statu=readl(hor_GPG_3_11_addr);
GPG_IN_DATA=(hor_GPG_3_11_statu &0xff3fff3f)|0x00400040; //set interrput port,enable GPG3,GPG11,interrupt module
printk("<1>GPG_IN_DATA=%x\r\n",GPG_IN_DATA);
writel(GPG_IN_DATA,hor_GPG_3_11_addr);
// printk("<1> 02\r\n");
// interrupt_statu=readl(EINTMASK_ADDR);
// interrupt_statu=interrupt_statu&(~(EINT11 | EINT19));
// writel(interrupt_statu,EINTMASK_ADDR);
// set_interrupt_port();
}
#endif
static void set_interrupt_port()
{
unsigned int ver_GPB_6_7_statu;
unsigned int hor_GPF_0_2_statu;
unsigned int hor_GPG_3_11_statu;
unsigned int GPB_IN_DATA;
unsigned int GPF_IN_DATA;
unsigned int GPG_IN_DATA;
ver_GPB_6_7_statu=readl(ver_GPB_6_7_addr);
GPB_IN_DATA=(ver_GPB_6_7_statu&0x3f0fff)|0x005000; //set output port
printk("<1>GPB_IN_DATA=%x\r\n",GPB_IN_DATA);
writel(GPB_IN_DATA,ver_GPB_6_7_addr);
// printk("<1> 03\r\n");
hor_GPF_0_2_statu=readl(hor_GPF_0_2_addr);
GPF_IN_DATA=(hor_GPF_0_2_statu&0xffcc)|0x00ee; //set interrput port,enable GPF0,GPF2,interrupt module
printk("<1>GPF_IN_DATA=%x\r\n",GPF_IN_DATA);
writel(GPF_IN_DATA,hor_GPF_0_2_addr);
// printk("<1> 04\r\n");
hor_GPG_3_11_statu=readl(hor_GPG_3_11_addr);
GPG_IN_DATA=(hor_GPG_3_11_statu &0xff3fff3f)|0x00b000b0; //set interrput port,enable GPG3,GPG11,interrupt module
printk("<1>GPG_IN_DATA=%x\r\n",GPG_IN_DATA);
writel(GPG_IN_DATA,hor_GPG_3_11_addr);
// printk("<1> 05\r\n");
}
static void set_output_module()
{
unsigned int hor_GPF_0_2_statu;
unsigned int GPF_IN_DATA;
unsigned int hor_GPG_3_11_statu;
unsigned int GPG_IN_DATA;
hor_GPF_0_2_statu=readl(hor_GPF_0_2_addr);
GPF_IN_DATA=(hor_GPF_0_2_statu&0xffcc)|0x0011; //set output mode
// GPF_IN_DATA=(hor_GPF_0_2_statu&0xffcc); //set input mode
// printk("<1>GPF_IN_DTAT=%x\r\n",GPF_IN_DATA);
writel(GPF_IN_DATA,hor_GPF_0_2_addr);
// printk("<1> 06\r\n");
hor_GPG_3_11_statu=readl(hor_GPG_3_11_addr);
GPG_IN_DATA=(hor_GPG_3_11_statu & 0xff3fff3f)|0x0700070; //set output mode
// GPG_IN_DATA=(hor_GPG_3_11_statu & 0xff3fff3f); //set input mode
// printk("<1>GPG_IN_DATA=%x\r\n",GPG_IN_DATA);
writel(GPG_IN_DATA,hor_GPG_3_11_addr);
// printk("<1> 07\r\n");
}
void mytimer_ok(unsigned long expires)
{
cleanpend();
printk("<1>mytimer_ok!\r\n");
// printk("<1> 08");
}
static void irq_pend()
{
unsigned int port_statu;
port_statu=readl(srcpnd);
port_statu=port_statu | (EINT0 | EINT2 | EINT8_23);
writel(port_statu,srcpnd);
}
#define GPG_3_11_H ((1<<3) | (1<<11))
#define GPF_0_2_H ((1<<0) | (1<<2))
#define GPB_6_7_H ((1<<6) | (1<<7))
struct timer_list mytimer;
static unsigned int get_key_value()
{
unsigned int port_statu;
// unsigned int key_value=-1;
unsigned int GPF;
unsigned int GPG,GPB;
unsigned int GPG_STATU,GPF_STATU;
unsigned int GPG_STATU1,GPF_STATU1;
unsigned int GPF_STATU2,GPF_STATU3;
unsigned int GPG_STATU2,GPG_STATU3;
unsigned int GPB_IN_DATA,GPB_STATU;
unsigned int time,value=-1;
irq_pend();
init_timer(&mytimer);
mytimer.expires=500000;
mytimer.function=mytimer_ok;
add_timer(&mytimer);
printk("<1>add_timer\r\n");
// unsigned int statu1,statu2,statu3;
// set_output_module();
#if 0
port_statu=readl(ver_GPB_6_7_data);
port_statu=(port_statu & (GPB_6_7_LOW_PORT));
writel(port_statu,ver_GPB_6_7_data);
#endif
port_statu=readl(ver_GPB_6_7_data);
// printk("<1>GPB_6_7_LOW=%x\r\n",port_statu&GPB_6_7_LOW_PORT);
time=0;
while(time<4)
{
#if 1
if(time==0)
value=0x0;
if(time==1)
value=(1<<6);
if(time==2)
value=(1<<7);
if(time==3)
value=0x0;
port_statu=readl(ver_GPB_6_7_data);
port_statu=((port_statu&GPB_6_7_LOW_PORT)|value);
writel(port_statu,ver_GPB_6_7_data);
#endif
GPF=readl(hor_GPF_0_2_data);
GPG=readl(hor_GPG_3_11_data);
GPB=readl(ver_GPB_6_7_data);
GPG_STATU=GPG & GPG_3_11_H;
GPF_STATU=GPF & GPF_0_2_H;
GPB_STATU=GPB & GPB_6_7_H;
// printk("<1>GPG_STATU=%x,GPF_STATU=%x,GPB_STATU=%x\r\n",GPG_STATU,GPF_STATU,GPB_STATU);
if(time==0)
{
GPG_STATU1=GPG_STATU;
GPF_STATU1=GPF_STATU;
}
if(time==1)
{
GPG_STATU2=GPG_STATU;
GPF_STATU2=GPF_STATU;
}
if(time==2)
{
GPG_STATU3=GPG_STATU;
GPF_STATU3=GPF_STATU;
}
time++;
}
if((GPF_STATU1==0x04)&&(GPF_STATU3==0x04))
value=1;
if((GPF_STATU1==0x04)&&(GPF_STATU2==0x04))
value=2;
if((GPF_STATU1==0x01)&&(GPF_STATU3==0x01))
value=3;
if((GPF_STATU1==0x01)&&(GPF_STATU2==0x01))
value=4;
if((GPG_STATU1==0x800)&&(GPG_STATU3==0x800))
value=5;
if((GPG_STATU1==0x800)&&(GPG_STATU2==0x800))
value=6;
if((GPG_STATU1==0x08)&&(GPG_STATU3==0x08))
value=7;
if((GPG_STATU1==0x08)&&(GPG_STATU2==0x08))
value=8;
del_timer(&mytimer);
// cleanpend();
return value;
#if 0
if(GPG_STATU==0X800)
return 56;
if(GPG_STATU==0X08)
return 78;
if(GPF_STATU==0x04)
return 12;
if(GPF_STATU==0X01);
return 34;
#endif
}
#if 0
static unsigned int scan_key()
{
unsigned int key_value=-1;
// unsigned int time=0;
unsigned int port_statu;
// key_value=get_key_value();
printk("<1>key_value=%d\r\n",key_value);
if(key_value!=no_key_enter)
{
printk("the enter key is s%d\r\n",key_value);
}
port_statu=readl(ver_GPB_6_7_data);
port_statu=port_statu&GPB_6_7_LOW_PORT;
writel(port_statu,ver_GPB_6_7_data);
return key_value;
}
#endif
static void cleanpend()
{
unsigned int port_statu;
port_statu=readl(srcpnd);
port_statu=port_statu&(~(EINT0 | EINT2 | EINT8_23));
writel(port_statu,srcpnd);
// printk("<1> 08");
}
irqreturn_t keys_irq(int irq,void *dev_id,struct pt_regs *reg)
{
int flags;
keyval=(unsigned char )irq;
cleanpend();
read=1;
save_flags(flags);
cli();
// printk("<1>press key!\r\n");
printk("<1>key%d is enter!\r\n", get_key_value());
restore_flags(flags);
wake_up_interruptible(&buttons_wait);
return 0;
}
static int request_irqs(void)
{
int ret=0;
unsigned int port_statu;
unsigned int GPB_IN_DATA;
// printk("<1>request_irqs\r\n");
// enable_interrupt();
// set_interrupt_port();
// set the GPB6,GPB7 in low
// printk("<1>here\r\n");
// if(scan_key()>0)
// if(1)
// {
// enable_interrupt();
set_output_module(); //set input mode ,changed!
port_statu=readl(ver_GPB_6_7_addr);
GPB_IN_DATA=((port_statu & 0x3f0fff) | 0x05000); //set GPB6,GPB7 in output mode
printk("<1>GPB_IN_DATA=%x\r\n",GPB_IN_DATA);
writel(GPB_IN_DATA,ver_GPB_6_7_addr);
port_statu=readl(ver_GPB_6_7_data);
port_statu=port_statu&GPB_6_7_LOW_PORT;
writel(port_statu,ver_GPB_6_7_data);
enable_interrupt();
ret+=request_irq(IRQ_EINT0,keys_irq,SA_INTERRUPT,DEVICE_NAME,keys_irq);
ret+=request_irq(IRQ_EINT2,keys_irq,SA_INTERRUPT,DEVICE_NAME,keys_irq);
ret+=request_irq(IRQ_EINT11,keys_irq,SA_INTERRUPT,DEVICE_NAME,keys_irq);
ret+=request_irq(IRQ_EINT19,keys_irq,SA_INTERRUPT,DEVICE_NAME,keys_irq);
// printk("<1>IRQ_EINT19_RET=%x\r\n",ret);
set_irq_type(IRQ_EINT0,IRQT_BOTHEDGE);
set_irq_type(IRQ_EINT2,IRQT_BOTHEDGE);
set_irq_type(IRQ_EINT11,IRQT_BOTHEDGE);
set_irq_type(IRQ_EINT19,IRQT_BOTHEDGE);
// }
if(ret)
{
printk("<1>request irq failed! ret=%x\r\n",ret);
}
// printk("<1>scan_key()=%d\r\n",scan_key());
return 0;
}
static void free_irqs(void)
{
free_irq(IRQ_EINT0,keys_irq);
free_irq(IRQ_EINT2,keys_irq);
free_irq(IRQ_EINT11,keys_irq);
free_irq(IRQ_EINT19,keys_irq);
}
static int key_read(struct file *file,char *buf,size_t count,loff_t *ppos)
{
read=0;
printk("<1> read start!\r\n");
copy_to_user(buf,(char *)&keyval,1);
return 0;
}
static unsigned int key_select(struct file* file,struct poll_table_struct *wait){
if(read)
return 1;
interruptible_sleep_on(&buttons_wait);
return 0;
}
static int key_ioctl(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
switch(cmd)
{
default:
return -EINVAL;
}
}
static struct file_operations key_fops=
{
.owner=THIS_MODULE,
.ioctl=key_ioctl,
.poll=key_select,
.read=key_read,
};
static struct miscdevice key_dev=
{
KEY_NUMBER,
"key",
&key_fops,
};
static int __init key_init(void)
{
int ret;
misc_register(&key_dev);
get_system_port_addr();
init_waitqueue_head(&buttons_wait);
ret=request_irqs();
printk("<1>key_init ret=%x\r\n",ret);
return 0;
}
static void __exit key_exit(void)
{
free_irqs();
misc_deregister(&key_dev);
printk("<1> clean key module\r\n");
}
module_init(key_init);
module_exit(key_exit);