/* linux/drivers/char
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define EINT_MAJOR 250 //主设备号
static int s_tp_openflag = 0;
static int s_pen_status = PEN_UP;
struct eirq_dev
{
struct cdev cdev;
unsigned short count;
};
struct eirq_dev *eirqdev;
static void s3c6410_eirq_setup(void)
{
*(volatile unsigned long*)INTC_IMR_V |= 0x200; //extern int 8
*(volatile unsigned long*)INTC_IER_V |= 0x200;
disable_irq(INTSRC_EXTINT8);
mdelay(20);
printk("in the touchpad setup \n");
enable_irq(INTSRC_EXTINT8);
}
static void tsevent(void)
{
}
static int s3c6410_tp_irqhandler(int irq, void *dev_id, struct pt_regs *regs)
{
disable_irq(INTSRC_EXTINT8);
s_pen_status = PEN_UNSURE;
tpdev->tp_timer.expires = jiffies + PEN_TIMER_DELAY_JUDGE;
add_timer(&tpdev->tp_timer);
*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V |= 0x100;
*(volatile unsigned long*)GPIO_PORTA_INTRCLR_V &= 0x0; //清除中断
//we will turn on the irq in the timer_handler
return IRQ_HANDLED;
}
static int s3c6410_tp_open(struct inode *inode, struct file *filp)
{
eirqdev->count = 0;
s3c6410_eirq_setup();
return 0;
}
static int s3c6410_eirq_release(struct inode *inode, struct file *filp)
{
return 0;
}
static ssize_t s3c6410_eirq_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
unsigned int a = 0;
a = eirqpdev->count;
copy_to_user(buf, a, sizeof(a));
return 0;
}
static struct file_operations s3c6410_tp_fops =
{
.owner = THIS_MODULE,
.read = s3c6410_eirq_read,
.open = s3c6410_eirq_open,
.release = s3c6410_eirq_release,
};
static int __init s3c6410_eirq_init(void)
{
int err,result;
dev_t devno = MKDEV(EINT_MAJOR, 0);
#ifdef EINT_MAJOR
result = register_chrdev_region(devno, 1, "s3c6410_eirq");//向系统静态申请设备号
#else
result = alloc_chrdev_region(&devno, 0, 1, "s3c6410_eirq");//向系统动态申请设备号
#endif
if(result < 0)
return result;
eirqdev = kmalloc(sizeof(struct eirq_dev),GFP_KERNEL);
if (!eirqdev)
{
result = -ENOMEM;
unregister_chrdev_region(devno,1);
return result;
}
memset(eirqdev,0,sizeof(struct eirq_dev));
//add a irqhandler
if(request_irq(S3C_EINT(19),s3c6410_eirq_irqhandler,SA_INTERRUPT,"s3c6410_eirq",NULL))
{
printk("request eirq irq8 failed!\n");
unregister_chrdev_region(devno,1);
kfree(tpdev);
return -1;
}
//init the tpdev device struct
cdev_init(&eirqdev->cdev, &s3c6410_eirq_fops);
eirqdev->cdev.owner = THIS_MODULE;
//just init the timer, not add to the kernel now
//setup_timer(&tpdev->tp_timer,tp_timer_handler,0);
//向系统注册该字符设备
err = cdev_add(&eirqdev->cdev, devno, 1);
if(err)
{
printk("adding err\r\n");
unregister_chrdev_region(devno,1);
kfree(tpdev);
free_irq(INTSRC_EXTINT8,NULL);
return err;
}
return 0;
}
static void __exit s3c6410_tp_exit(void)
{
cdev_del(&eirqdev->cdev);
kfree(eirqdev);
free_irq(INTSRC_EXTINT8,NULL);
unregister_chrdev_region(MKDEV(EINT_MAJOR, 0),1);
}
module_init(s3c6410_eirq_init);
module_exit(s3c6410_eirq_exit);
MODULE_AUTHOR("Rockie Cheng");
MODULE_LICENSE("GPL");