/**********************************************************
* s3c2440-ajirq.c
*
* keyboard driver for S3C2440 based PDA
*
*
* History:
*
*
***********************************************************/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
//#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/arch/irq.h>
#include <asm/arch/irqs.h>
#include <asm/arch/clocks.h>
#include <asm/hardware.h>
#include <asm/arch/S3C2440.h>
#define DEVICE_NAME "/dev/ajirq" //键盘设备名
#define IRINT_MAJOR 96 //申请的中断号
static int kbMajor = IRINT_MAJOR; //默认的主设备号
static int eint2_value = 0; //中断2的值
static int eint_number = 0; //产生中断的次数
static int TimerCount = 0; //超时标志
#define TIMER_DELAY (HZ/50) /* 消抖动 延时:1秒*/
#define TIMEOUT 3 //连读三次去抖动
static struct timer_list ring_timer; //定义一个时钟
static wait_queue_head_t wq ; //声明等待队列
//spinlock_t repeat_lock;
spinlock_t lock; //声明自旋锁
#define BLOCK 1 //阻塞方式
#define NONBLOCK 0 //非阻塞方式
static u_int FileMode=NONBLOCK; //初始化为非阻塞
//#define USE_ASYNC 1
#undef USE_ASYNC //关闭同步
#ifdef USE_ASYNC //不执行
static struct fasync_struct *AsyncQueue =NULL;
#endif
static int requestIrq(); //声明中断申请函数
#ifdef USE_ASYNC //不执行
static int s3c2440_irint_fasync(struct inode *inode, struct file *filp, int mode)
{
return fasync_helper(inode, filp, mode, &AsyncQueue);
}
#endif
/*----------------------------------------------------
* func: 读取eint2当前值
* param:
*
* return: if key is down, return 1; else 0
*
------------------------------------------------------*/
int get_eint2_value()
{
unsigned long IOValue;
IOValue = GPFDAT ;
if ( IOValue & 0x00000004) //有eint2
return 0;
else
return 1;
}
static inline void timer_handler(unsigned long data) //定时中断服务函数,定时读多次,防止抖动
{
if (!get_eint2_value()) /* 如果没有产生外部中断2,说明是抖动,屏蔽了*/
{
TimerCount=0; // 清0
del_timer(&ring_timer); //删除定时器
enableIrq(); //使能中断
}
TimerCount++; //有中断2产生
if (TimerCount==TIMEOUT) //看看是不是第三次定时都有中断2,确认是有按键按下
{
#ifdef USE_ASYNC //不执行
if(AsyncQueue)
kill_fasync(&(AsyncQueue), SIGIO, POLL_IN);
#endif
eint2_value =1; //确认一次中断,将其值置为1;
eint_number=eint_number+1; //中断次数加一
printk("int coming %d\n",eint_number); //打印外部中断次数
if(FileMode == BLOCK) //不执行
wake_up_interruptible(&wq); //阻塞,但可被中断
del_timer(&ring_timer); //删除定时器
TimerCount=0;
enableIrq();
}
else
{
ring_timer.expires = jiffies + TIMER_DELAY; //重新赋值定时器的数值
add_timer(&ring_timer); //重新启动定时器
}
}
/*----------------------------------------------------
* func: 使能中断
* param:
* return:
*
------------------------------------------------------*/
//使能中断
static void enableIrq()
{
//清除SRCPND寄存器中eint2相应位
SRCPND= 0x00000004;
//使能中断
enable_irq(IRQ_EINT2);
}
/*----------------------------------------------------
* func: 对应文件读的函数,如果循环队列中有键码,
则将键码拷贝到用户空间的buffer中
* param:
*
* return:
* 返回从循环队列中读取的键码的字节数
*
*
------------------------------------------------------*/
static ssize_t
S3C2440_irint_read(struct file *filp, char *buffer, size_t count, loff_t * ppos)
{
// printk("<0>,eint_number %d\n",eint_number);
if(FileMode == BLOCK) //不执行
{
if (eint2_value ==0) //如果没有数据
{
interruptible_sleep_on(&wq); //一直睡眠等待
// if(signal_pending(current))
// return -ERESTARTSYS;
}
}
count = sizeof(eint_number);
copy_to_user(buffer,&eint_number,count); //将按键按下的值eint_number拷贝到用户空间
eint2_value =0; //数据读完后,再次清除
return count;
}
/*----------------------------------------------------
* func: 与打开文件对应的open函数,初始化全局变量和定
* 时器以及请求中断
* param:
*
*
* return:
*
------------------------------------------------------*/
static int S3C2440_irint_open(struct inode *inode, struct file *filp)
{
// printk("<0> open\n");
// if(filp->f_flags & O_NONBLOCK)
// {
// FileMode = NONBLOCK;
// }
// else
// {
// FileMode = BLOCK;
// }
MOD_INC_USE_COUNT;
return 0;
}
static int s3c2440_irint_release(struct inode *inode, struct file *filp)
{
disable_irq(IRQ_EINT2); //关闭中断2
#ifdef USE_ASYNC //不执行
s3c2440_irint_fasync(inode,filp,0);
#endif
printk("release device\n");
MOD_DEC_USE_COUNT;
return 0;
}
static struct file_operations ring_fops = {
owner: THIS_MODULE,
open: S3C2440_irint_open,
read: S3C2440_irint_read,
release: s3c2440_irint_release,
#ifdef USE_ASYNC
fasync: s3c2440_irint_fasync,
#endif
};
/*----------------------------------------------------
* func: 中断处理程序,关闭中断,开启键盘扫描定时器
* param:
*
*
* return:
*
------------------------------------------------------*/
static void irint_interrupt(int irq, void *dev_id, struct pt_regs *regs) //外部中断2的服务函数
{
spin_lock_irq(&lock); //锁起来
disable_irq(IRQ_EINT2); //屏弊中断2
// printk("<0>,interrupt is coming\n");
//启动定时器
TimerCount = 0;
ring_timer.expires = jiffies + TIMER_DELAY; //设置定时时间
add_timer(&ring_timer); //启动定时器(定时时间要远远大于抖动时间,小于第二次按中断2的时间)
// enableIrq();
spin_un