免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1261 | 回复: 0
打印 上一主题 下一主题

linux 2.6下的第一个驱动(s3c2440)[按键驱动] [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-28 12:53 |只看该作者 |倒序浏览

linux 2.6下的第一个驱动(s3c2440)[按键驱动]
2007-09-02 12:01:04
/*======================================
定时器程序还有一点点问题,按键的时候不能屏蔽中断,
一个键按下去会不停的产生中断
=======================================*/

#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 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(" 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(" 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("GPF_IN_DATA=%x\r\n",GPF_IN_DATA);
writel(GPF_IN_DATA,hor_GPF_0_2_addr);
//  printk(" 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("GPG_IN_DATA=%x\r\n",GPG_IN_DATA);
writel(GPG_IN_DATA,hor_GPG_3_11_addr);
//  printk(" 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("GPB_IN_DATA=%x\r\n",GPB_IN_DATA);
writel(GPB_IN_DATA,ver_GPB_6_7_addr);
//  printk(" 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("GPF_IN_DATA=%x\r\n",GPF_IN_DATA);
writel(GPF_IN_DATA,hor_GPF_0_2_addr);
//  printk(" 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("GPG_IN_DATA=%x\r\n",GPG_IN_DATA);
writel(GPG_IN_DATA,hor_GPG_3_11_addr);
// printk(" 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("GPF_IN_DTAT=%x\r\n",GPF_IN_DATA);
writel(GPF_IN_DATA,hor_GPF_0_2_addr);
// printk(" 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("GPG_IN_DATA=%x\r\n",GPG_IN_DATA);
writel(GPG_IN_DATA,hor_GPG_3_11_addr);
// printk(" 07\r\n");
}

void mytimer_ok(unsigned long expires)
{
cleanpend();
printk("mytimer_ok!\r\n");
//   printk(" 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  ((1add_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("GPB_6_7_LOW=%x\r\n",port_statu&GPB_6_7_LOW_PORT);

time=0;
while(timeGPG_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("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(" 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("press key!\r\n");
printk("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("request_irqs\r\n");
// enable_interrupt();
// set_interrupt_port();
// set the GPB6,GPB7 in low
// printk("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("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("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("request irq failed! ret=%x\r\n",ret);
}
// printk("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(" 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("key_init  ret=%x\r\n",ret);
return 0;
}
static void __exit key_exit(void)
{
free_irqs();
misc_deregister(&key_dev);
printk(" clean key module\r\n");
}
module_init(key_init);
module_exit(key_exit);


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/103668/showart_2040292.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP