- 积分
- 8
贡献26
飞刀2 FD
注册时间2014-8-8
在线时间1 小时
扫一扫,手机访问本帖
|
各位大侠,我现在想把LINUX2.6下的按键驱动移植到linux3.2.0 AM335上!!但是好像总是无法中断!麻烦大侠们指点指点!
#include <linux/init.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/errno.h>
#include <linux/device.h>
#include <linux/syscalls.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <linux/gpio.h>
#include <asm/gpio.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/uaccess.h>
#include <linux/string.h>
static struct class *forthdrv_class;
static struct class_device *forthdrv_class_dev;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
/* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */
static volatile int ev_press = 0;
struct pin_desc{
unsigned int pin;
unsigned int key_val;
};
/* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */
/* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */
static unsigned char key_val;
struct pin_desc pins_desc[6] = {
{20, 0x01},
{21, 0x02},
{22, 0x03},
{23, 0x04},
{24, 0x05},
{25, 0x06},
};
#define DPRINTK(fmt,arg...) printk(fmt,##arg);
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE);
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
#define LED_ON 1
#define LED_OFF 0
#define DEV_NAME "led"
/*
* 确定按键值
*/
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
struct pin_desc * pindesc = (struct pin_desc *)dev_id;
unsigned int pinval;
printk("<0>""interrupt is open");
pinval = gpio_get_value(GPIO_TO_PIN(1, pindesc->pin));
if (pinval)
{
/* 松开 */
key_val = 0x80 | pindesc->key_val;
}
else
{
/* 按下 */
key_val = pindesc->key_val;
}
ev_press = 1; /* 表示中断发生了 */
wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */
return IRQ_RETVAL(IRQ_HANDLED);
}
static void led_on(int num)
{
//gpio had been requested so just use it
gpio_set_value(GPIO_TO_PIN(1, 16 + num), 0);
}
static void led_off(int num)
{
gpio_set_value(GPIO_TO_PIN(1, 16 + num), 1);
}
static int led_open(struct inode *inode, struct file *filp)
{
DPRINTK("led open\n");
request_irq(gpio_to_irq(GPIO_TO_PIN(1, 20)), buttons_irq, IRQF_TRIGGER_FALLING, "S0", &pins_desc[0]);
request_irq(gpio_to_irq(GPIO_TO_PIN(1, 21)), buttons_irq, IRQF_TRIGGER_FALLING, "S1", &pins_desc[1]);
request_irq(gpio_to_irq(GPIO_TO_PIN(1, 22)), buttons_irq, IRQF_TRIGGER_FALLING, "S2", &pins_desc[2]);
request_irq(gpio_to_irq(GPIO_TO_PIN(1, 23)), buttons_irq, IRQF_TRIGGER_FALLING, "S3", &pins_desc[3]);
request_irq(gpio_to_irq(GPIO_TO_PIN(1, 24)), buttons_irq, IRQF_TRIGGER_FALLING, "S4", &pins_desc[4]);
request_irq(gpio_to_irq(GPIO_TO_PIN(1, 25)), buttons_irq, IRQF_TRIGGER_FALLING, "S5", &pins_desc[5]);
return 0;
}
static int led_release(struct inode *inode, struct file *filp)
{
free_irq(gpio_to_irq(GPIO_TO_PIN(1, 20)), &pins_desc[0]);
free_irq(gpio_to_irq(GPIO_TO_PIN(1, 21)), &pins_desc[1]);
free_irq(gpio_to_irq(GPIO_TO_PIN(1, 22)), &pins_desc[2]);
free_irq(gpio_to_irq(GPIO_TO_PIN(1, 23)), &pins_desc[3]);
free_irq(gpio_to_irq(GPIO_TO_PIN(1, 24)), &pins_desc[4]);
free_irq(gpio_to_irq(GPIO_TO_PIN(1, 25)), &pins_desc[5]);
DPRINTK("led release\n");
return 0;
}
static long led_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
{
DPRINTK("led ioctl with cmd:%d,arg:%d\n",cmd,arg);
#if defined(CONFIG_OK335XD)
if(arg <0 || arg >3)
return -EINVAL;
#elif defined(CONFIG_OK335XS)
if(arg <0 || arg >0)
return -EINVAL;
#endif
switch (cmd) {
case LED_ON:
led_on(arg);
break;
case LED_OFF:
led_off(arg);
break;
default:
break;
}
return 0;
}
ssize_t led_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
{
int regval,i;
if (size != 1)
return -EINVAL;
/* 如果没有按键动作, 休眠 */
wait_event_interruptible(button_waitq, ev_press);
/* 如果有按键动作, 返回键值 */
copy_to_user(buf, &key_val, 1);
ev_press = 0;
return 1;
}
static struct file_operations forth_drv_fops = {
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.release = led_release,
.unlocked_ioctl = led_ioctl,
};
static struct miscdevice led_miscdev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = DEV_NAME,
.fops = &forth_drv_fops,
};
int major;
static int __init forthdrv_init(void)
{
//misc_register(&led_miscdev);
int ret=0;
int inter=0;
major = register_chrdev(0, "forth_drv", &forth_drv_fops); // 注册, 告诉内核
forthdrv_class = class_create(THIS_MODULE, "forthdrv");
forthdrv_class_dev = device_create(forthdrv_class, NULL, MKDEV(major, 0), NULL, "button"); /* /dev/button */
return 1;
}
static void __exit forthdrv_exit(void)
{
// misc_deregister(&led_miscdev);
unregister_chrdev(major, "forth_drv"); // 卸载
device_unregister(forthdrv_class_dev);
class_destroy(forthdrv_class);
}
module_init(forthdrv_init);
module_exit(forthdrv_exit);
MODULE_AUTHOR("duyahui <duyahui@forlinx.com>");
MODULE_DESCRIPTION("forth driver");
MODULE_LICENSE("GPL");
|
|