OrangePi3 LTS 驱动开发-GPIO 中断

OrangePi3 LTS 驱动开发-GPIO中断

上一节将到将普通gpio设置为输入,app端可以通过轮询的方式去读取外部设备的状态,但这样消耗的资源比较大。
如果采用中断的方法,当gpio高低电平发生变化的时候,我们再去处理相应的事件,那么会大大降低cpu的负担。

kernel版本:orange-pi-5.10-media
dts配置同上一节gpio输入

pl8连接pw0,
将pw0修改输出1hz的方波,
那么串口会每隔一秒打印一次中断处理函数。

在这里插入图片描述

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>
#include <linux/err.h>

#include <linux/input.h>
#include <linux/printk.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>

#include "../type.h"


#define DRIVER_NAME     "max_input"
#define DEVICE_NAME     "input"

typedef struct  input_driver
{
	struct mutex 		mutex;
    struct device     	*dev;
    struct gpio_desc 	*gpiod;
    unsigned int        irq;
    int                 irq_enable;
}max_inputs_driver;

static ssize_t name_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	return sprintf(buf, "%s\n", DRIVER_NAME);
}
static DEVICE_ATTR(name, 0444, name_show,NULL);

static ssize_t gpio_value_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
    max_inputs_driver * max_inputs = dev_get_drvdata(dev);

if (!max_inputs)
{
	max_error("get max_leds_driver error\n");
	return -ENODEV;
} 
int value = gpiod_get_value(max_inputs->gpiod);
return sprintf(buf, "%d\n", value);
}
static DEVICE_ATTR(gpio_value, 0444, gpio_value_show,NULL);

static ssize_t irq_enable_show(struct device *dev, struct device_attribute *attr,
			char *buf)
{
	int ret = 0;
    max_inputs_driver * max_inputs = dev_get_drvdata(dev);

if (!max_inputs)
{
	max_error("get max_inputs_driver error\n");
	return -ENODEV;
}

ret = sprintf(buf,"%s",max_inputs->irq_enable == 1 ? "PL8 IRQ On\n" : "PL8 IRQ On Off\n");

return ret;
}

static ssize_t irq_enable_store(struct device *dev,
                                            struct device_attribute *attr,
                                            const char *buf, size_t count)
{
	uint8_t value;
	int ret;

max_inputs_driver * max_inputs = dev_get_drvdata(dev);
if (!max_inputs)
{
	max_error("get max_inputs_driver error\n");
	return -ENODEV;
}
ret = kstrtou8(buf, 0, &value);// auto data format
if (ret)
{
	max_error("kstrtou8 error\n");
	return -ENODEV;
}
if (value == 0 )
{
    disable_irq_nosync(max_inputs->irq);
    max_inputs->irq_enable = 0;
}
else if (value == 1)
{
    enable_irq(max_inputs->irq);
    max_inputs->irq_enable = 1;
}
else
{
	max_info(" value only equal 1 and 0\n");
}
return count;
}
static DEVICE_ATTR(irq_enable, 0664, irq_enable_show,irq_enable_store);

static struct attribute *attrs[] = {
	&dev_attr_name.attr,
    &dev_attr_gpio_value.attr,
    &dev_attr_irq_enable.attr,
	NULL,	/* need to NULL terminate the list of attributes */
};

static struct attribute_group attr_group = {
	.attrs = attrs,
};

static irqreturn_t gpio_irq_handler(int irq, void *data)
{
	max_inputs_driver * max_inputs = (max_inputs_driver *)data;
	//mod_timer(&msa311_driver->timer,jiffies + msecs_to_jiffies(10));
	//unsigned long delay =  msecs_to_jiffies(2);
	//schedule_work(&msa311_driver->work);
	max_error("gpio_irq_handler  \n");
	return IRQ_HANDLED;
}

static int dts_parse(struct platform_device *pdev)
{

int ret = 0;
struct device_node * node;
const char *str;
max_inputs_driver * max_inputs = (max_inputs_driver *)platform_get_drvdata(pdev); 

node = pdev->dev.of_node;
if (!node) 
{
	max_error("failed to find node for %s\n",DEVICE_NAME);
	return -ENODEV;
}

if (node)
{
	ret = of_property_read_string(node, "gpios", &str);
	if (ret)
	{
		max_error("no define %s in dts\n", "gpios");
		return -1;
	}
	else
	{
		max_inputs->gpiod = devm_gpiod_get(&pdev->dev,NULL,GPIOD_IN);
		if (IS_ERR_OR_NULL(max_inputs->gpiod))
		{
			max_error("devm_gpiod_get error\n");
		}
	}

    ///gpiod_get_value(max_inputs->gpiod);

    //申请irq
    max_inputs->irq = gpiod_to_irq(max_inputs->gpiod);
    // 申请中断
    ret = devm_request_irq(&pdev->dev,
				       max_inputs->irq,
				       gpio_irq_handler,
				       IRQF_TRIGGER_FALLING,
				       "max", max_inputs);

    max_inputs->irq_enable = 1;
    if (ret)
    {
	    max_error("devm_request_irq error\n");
    }
}
return 0;
}

static int max_input_probe(struct platform_device *pdev)
{
    int ret = 0;
	struct class 			*inputs_class;
	max_inputs_driver      	*max_inputs;
	
max_inputs = kzalloc(sizeof(max_inputs_driver), GFP_KERNEL);
if (!max_inputs) {
	max_error("kzalloc max_inputs error\n");
	return -ENOMEM;
}

mutex_init(&max_inputs->mutex);

platform_set_drvdata(pdev, max_inputs);
ret = dts_parse(pdev);
if (ret){
	max_error("dts parse error\n");
	goto malloc_error;
}

inputs_class = class_create(THIS_MODULE, DRIVER_NAME);
if (IS_ERR(inputs_class)) {
	ret= PTR_ERR(inputs_class);
	max_error("inputs_class: class create failed\n");
	goto malloc_error;
}

max_inputs->dev = device_create(inputs_class,
		 &pdev->dev, 0, NULL, DEVICE_NAME);
if (unlikely(IS_ERR(max_inputs->dev))) {
	ret = PTR_ERR(max_inputs->dev);
	max_inputs->dev = NULL;
	goto destory_class;
}

ret = sysfs_create_group(&max_inputs->dev->kobj, &attr_group);
if(ret){
	max_error("sysfs_create_group in leds driver\n");
	goto destory_device;
}

dev_set_drvdata(max_inputs->dev,max_inputs);
max_info("max_input_probe success \n");
return 0;


destory_device:
	device_destroy(inputs_class,0);
destory_class:
	class_destroy(inputs_class);
malloc_error:
	kfree(max_inputs);
	return -ENODEV;
}

static int max_input_remove(struct platform_device *pdev)
{
	max_inputs_driver * max_inputs = (max_inputs_driver 				*)platform_get_drvdata(pdev); 

	devm_free_irq(&pdev->dev, max_inputs->irq, max_inputs);
	platform_set_drvdata(pdev, NULL);
	kfree(max_inputs);
	return 0;
}

static const struct of_device_id max_input_dt_match[] = {
	{
		.compatible = "max, input",
	},
	{},
};

static struct platform_driver input_driver = {
	.driver = {
		.name =  DEVICE_NAME,
		.owner = THIS_MODULE,
		.of_match_table = max_input_dt_match,
	},
	.probe = max_input_probe,
	.remove = max_input_remove,
};

static int __init orange_input_init(void)
{
    if (platform_driver_register(&input_driver)) {
		max_error("failed to register driver\n");
		return -ENODEV;
	}
	max_info("orange_input_init:module init\n");
	return 0;
}

static void __exit orange_input_exit(void)
{
	max_info("orange_input_exit module exit\n");
}

module_init(orange_input_init);
module_exit(orange_input_exit);

MODULE_DESCRIPTION("Max GPIO Input Test Driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("738270732@qq.com");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值