全志H3的IRQ驱动程序

1. 使用PG11引脚作为中断输入引脚

2. 如何在DTS文件中申明使用IRQ

​ 如图所示便是标准的使用一个PIN的IRQ的DTS语法,个人觉得在不同的SoC中所使用的DTS语法稍微有一些不同,对于具体的使用方法需要参考官方代码中给出的标准格式。下面是我的代码中给出的:

​ 我认为最重要的属性是interrupts相关的属性,其他的pincrtl可以启动辅助作用(在这里不能够通过gpio获得irq号,需要注意的是gpio_in不能被设置到目标引脚).

3. 我的驱动代码

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/init.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>

#define DEV_NAME	"button"

static ssize_t irq_open(struct inode *node, struct file *filp)
{
	printk("IRQ device file opened !\n");

	return 0;
}

static ssize_t irq_close(struct inode *node, struct file *filp)
{
	printk("IRQ device fiel closed !\n");

	return 0;
}


static irqreturn_t button_isr(int irq, void *dev)
{
	printk("<kernel>: The isr for irq = %d \n", irq);

	return IRQ_HANDLED;
}

static const struct file_operations f_ops = {
	.owner = THIS_MODULE,
	.open = irq_open,
	.release = irq_close,
};

static struct miscdevice irq_misc = {
		.name = DEV_NAME,
		.minor = MISC_DYNAMIC_MINOR,
		.fops = &f_ops
};

static int probe(struct platform_device *pdev)
{
	int ret, irq;
	//struct device_node *node;

	// 1. get device node
	/*
	node = of_find_node_by_path("/irq_test");
	if(node == NULL){
		printk("<kernel>: Failed to get node by path! \n");
		return -EINVAL;
	}
	printk("<kernel>: Success to get node by path !\n");

	pin = of_get_named_gpio(node, "gpio", 0);
	if(pin < 0){
		printk("<kernel>: Failed to get pin number \n");
		return -EINVAL;
	}
	printk("<kernel>: Success get device need pins = %d \n", pin);

	// 2. transfer gpio number to irq number
	irq = gpio_to_irq(pin);
	if(irq < 0){
		printk("<kernel>: Failed to get irq number of pin(%d) !\n", pin);
		return -EINVAL;
	}
	printk("<kernel>: The irq of pin is %d !\n", irq);
	*/

	// a. through platform device get irq
	irq = platform_get_irq(pdev, 0);
	if(irq < 0){
		printk("<kernel>: Failed to get irq number through platform device !\n");
		return -EINVAL;
	}
	printk("<kernel>: Get irq = %d though platform !\n", irq);

	ret = devm_request_irq(&pdev->dev, irq, button_isr,
						IRQF_TRIGGER_RISING, DEV_NAME, &pdev->dev);
	if(ret){
		printk("<kernel>: Failed to request irq:%d !\n", irq);
		return ret;
	}
	printk("<kernel>: Had register interrupt isr !\n");

	ret = misc_register(&irq_misc);
	if(ret != 0){
		printk("<kernel>: Failed to register misc device !\n");
		return ret;
	}
	printk("<kernel>: Success register misc device, minor = %d !\n", irq_misc.minor);

	return 0;
}

static int __exit remove(struct platform_device *pdev)
{
	printk("<kernel>: Deregister misc device--irq_misc !\n");
	misc_deregister(&irq_misc);

	return 0;
}

static const struct of_device_id irq_ids[] = {
		{.compatible = "allwinner,buttons"},
		{ },
};

static struct platform_driver irq_driver = {
		.probe = probe,
		.remove = remove,
		.driver = {
			.name = DEV_NAME,
			.of_match_table = irq_ids,
			.owner = THIS_MODULE
		},
};

module_platform_driver(irq_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("weirdo");
MODULE_DESCRIPTION("This driver for Allwinner H3 irq!");

​ 对于irq驱动的tasklet,workqueen这些需要读者自己去学习,我只是给出如何使用全志H3的IRQ的方法。

** 驱动测试代码 **

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<termios.h>
#include<string.h>

int main()
{	
	
	int i,fd, ret;
	char dat;

	fd = open("/dev/button", O_RDONLY);
	if (fd == -1) 
	{
		printf("Can not open /dev/myfile!\n");
		exit(0);
	}
	
	printf("Open file success ! \n");

	for(i=0;i<20;i++)	
	{
		printf("Now the time is = %d\n", i);

		sleep(1);
	}
		
	close(fd);

	return 0;

}
    

测试结果:

posted @ 2020-07-05 21:30  FOFI  阅读(803)  评论(0编辑  收藏  举报