主题 : smart210按键驱动 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 113040
精华: 0
发帖: 7
金钱: 40 两
威望: 8 点
贡献值: 0 点
综合积分: 14 分
注册时间: 2015-02-28
最后登录: 2015-12-16
楼主  发表于: 2015-03-22 12:04

 smart210按键驱动

#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>

#define TASK_UNINTERRUPTIBLE 2

#define GPFCON 0xE0200C40
#define GPFDAT 0xE0200C44
struct work_struct *work1;
struct timer_list buttons_timer;
unsigned int *gpio_data;
unsigned int key_num = 0;
wait_queue_head_t  key_q;


void work1_func(struct work_struct *work)
{
    mod_timer(&buttons_timer, jiffies + (HZ /10));  
}
void buttons_timer_function(unsigned long data) 
{
    unsigned int key_val;
   
    key_val = readw(gpio_data)&0x1;
    if (key_val == 0)
       key_num = 1;
   
   
    key_val = readw(gpio_data)&0x2;
    if (key_val == 0)
        key_num = 2;
       
     key_val = readw(gpio_data)&0x4;
    if (key_val == 0)
       key_num = 3;
   
   
    key_val = readw(gpio_data)&0x8;
    if (key_val == 0)
        key_num = 4;
   
    wake_up(&key_q);
    printk("key is %d\n",key_num);
}

irqreturn_t key_int(int irq, void *dev_id)
{
    //1. 检测是否发生了按键中断
   
    //2. 清除已经发生的按键中断
    printk("key_int_end\n",key_num);
    //3. 提交下半部
    schedule_work(work1);
   
    //return 0;
    return IRQ_HANDLED;
     
}
void key_hw_init()
{
    unsigned int *gpio_config;
    unsigned short data;
     
    gpio_config = ioremap(GPFCON,4);
    data = readw(gpio_config);
    data &= ~0b110011;
    data |= 0xfffffff;
    writew(data,gpio_config);
   
    gpio_data = ioremap(GPFDAT,4);
 printk("gpio init end\n");
}

int key_open(struct inode *node,struct file *filp)
{
 printk("open end \n");
    return 0; 
}
ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
    wait_event(key_q,key_num);
    printk("in kernel :key num is %d\n",key_num); 
    copy_to_user(buf, &key_num, 4);
   
    key_num = 0;
 
    return 4;
}
struct file_operations key_fops =
{
    .open = key_open,
    .read = key_read, 
};
struct miscdevice key_miscdev = {
    .minor = 201,
    .name = "tq2440key",
    .fops = &key_fops, 
};
static int button_init()
{
    int ret;
    int irq =0,i=0 ;
    ret = misc_register(&key_miscdev);
   
    if (ret !=0)
        printk("register fail!\n");
   
    //注册中断处理程序
    for (i = 0; i < 4; i++)
    {
    irq = 160+i;
    request_irq(irq,key_int,IRQF_TRIGGER_FALLING,"tq2440key",0);
    }
 
    //按键初始化
    key_hw_init();
   
    //. 创建工作
    work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
    INIT_WORK(work1, work1_func);
   
    /* 初始化定时器 */ 
    init_timer(&buttons_timer);  
    buttons_timer.function  = buttons_timer_function; 
   
    /* 向内核注册一个定时器 */ 
    add_timer(&buttons_timer); 
   
    /*初始化等待队列*/
    init_waitqueue_head(&key_q);
 
    return 0;
   
}

static void button_exit()
{
    misc_deregister(&key_miscdev); 
}

module_init(button_init);
module_exit(button_exit);