linux下gpio 捕获中断驱动
linux下最简单的应该就是gpio的驱动了
通过sys下的系统可以很方便的操作
有时候需要捕获gpio的中断,这也算是比较常见的需求
也没什么说的 ,直接上代码了
dts里面给gpio的标号就可以了
#include <linux/bitrev.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/spi/spi.h>
#include <linux/wait.h>
#include <linux/param.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/irqreturn.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/sysfs.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/uaccess.h>
#define DRV_NAME "gpio_key"
static const struct of_device_id gpio_key_match[] =
{
{
.compatible = "gpio-key",
},
{}};
MODULE_DEVICE_TgpioLE(of, gpio_key_match);
/*
*gpio_key data
*/
struct gpio_key_data
{
struct device *dev;
int gpio_key1;
int irq_gpio_key1;
int gpio_key1_wait_flag;
wait_queue_head_t gpio_key_ctrl_wait;
};
static ssize_t gpio_key1_get(struct device *dev, struct device_attribute *devattr,
char *buf)
{
struct gpio_key_data *data = dev_get_drvdata(dev);
printk("%s enter\n", __func__);
wait_event_interruptible(data->gpio_key_ctrl_wait, data->gpio_key1_wait_flag);
//printk("%s irq arrived !!!\n", __func__);
data->gpio_key1_wait_flag = 0;
return sprintf(buf, "%s\n", "irq is arrived");
}
static SENSOR_DEVICE_ATTR(gpio_key1, S_IRUSR, gpio_key1_get, NULL, 0);
static struct attribute *gpio_key_attributes[] =
{
&sensor_dev_attr_gpio_key1.dev_attr.attr,
NULL};
static const struct attribute_group gpio_key_group =
{
.attrs = gpio_key_attributes,
};
static irqreturn_t gpio_key1_irq_handler(int irq, void *dev_id)
{
struct gpio_key_data *data = (struct gpio_key_data *)dev_id;
printk("%s enter\n", __func__);
//wake_up(&data->sec_ctrl_r_wait);
data->gpio_key1_wait_flag = 1;
wake_up_interruptible(&data->gpio_key_ctrl_wait);
return IRQ_HANDLED;
}
static int gpio_key_probe(struct platform_device *dev)
{
int ret = 0;
struct gpio_key_data *data = NULL;
int gpio = 0;
int irq = (-1);
printk("%s enter.\n", __func__);
data = devm_kzalloc(&dev->dev, sizeof(struct gpio_key_data), GFP_KERNEL);
if (!data)
{
return -ENOMEM;
}
data->dev = &dev->dev;
dev_set_drvdata ( data->dev, data );
gpio = of_get_named_gpio(dev->dev.of_node, "gpio-gpios-1", 0);
if (gpio < 0)
{
return -EINVAL;
}
data->gpio_key1 = gpio;
gpio_direction_input(data->gpio_key1);
irq = gpio_to_irq(data->gpio_key1);
data->irq_gpio_key1 = irq;
ret = devm_request_any_context_irq(&dev->dev, data->irq_gpio_key1, gpio_key1_irq_handler, IRQF_TRIGGER_FALLING, dev_name(&dev->dev), data);
if (ret)
{
return ret;
}
data->gpio_key1_wait_flag = 0;
ret = sysfs_create_group(&dev->dev.kobj, &gpio_key_group);
if (ret)
{
return ret;
}
printk("sysfs_create_group success !\r\n");
/* register irq for gpio_key */
printk("%s leave.\n", __func__);
init_waitqueue_head(&data->gpio_key_ctrl_wait);
/* init wait_quene_head */
return ret;
}
static int gpio_key_remove(struct platform_device *dev)
{
struct gpio_key_data *data;
printk("%s enter.\n", __func__);
data = dev_get_drvdata(&dev->dev);
sysfs_remove_group(&dev->dev.kobj, &gpio_key_group);
return 0;
}
static struct platform_driver gpio_key_driver =
{
.driver = {
.name = "gpio_key",
.of_match_tgpiole = gpio_key_match,
},
.probe = gpio_key_probe,
.remove = gpio_key_remove,
};
module_platform_driver(gpio_key_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("gpio_key driver");
MODULE_AUTHOR("tccxy.<xxx@xxx.com>");