- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/gpio.h>
- #include <linux/of_gpio.h>
- #include <linux/timer.h>
- #include <linux/of_irq.h>
- #include <linux/interrupt.h>
-
- //定义指针指向获取的设备树节点信息空间
- struct device_node *node;
- struct gpio_desc *gpiono1;
- struct gpio_desc *gpiono2;
- struct gpio_desc *gpiono3;
- int ret;
-
- unsigned int irqno1;
- unsigned int irqno2;
- unsigned int irqno3;
-
- struct device_node *node_irq;
-
- //中断处理函数
- irqreturn_t irq_handler1(int irqno, void *dev)
- {
-
- printk("key1 interrupt....\n");
- gpiod_set_value(gpiono1, !gpiod_get_value(gpiono1));
- return IRQ_HANDLED;
- }
- irqreturn_t irq_handler2(int irqno, void *dev)
- {
-
- printk("key2 interrupt...\n");
- gpiod_set_value(gpiono2, !gpiod_get_value(gpiono2));
- return IRQ_HANDLED;
- }
- irqreturn_t irq_handler3(int irqno, void *dev)
- {
-
- printk("key3 interrupt....\n");
- gpiod_set_value(gpiono3, !gpiod_get_value(gpiono3));
- return IRQ_HANDLED;
- }
-
- static int __init mycdev_init(void)
- {
- //通过名字获取设备树节点信息
- node = of_find_node_by_name(NULL, "myleds");
- if (node == NULL)
- {
- printk("通过名字解析设备树节点失败\n");
- return -EFAULT;
- }
- printk("成功解析到设备树节点\n");
- //获取并申请gpio编号
- gpiono1 = gpiod_get_from_of_node(node, "myled1", 0, GPIOD_OUT_LOW, NULL);
- if (IS_ERR(gpiono1))
- {
- printk("获取gpio编号失败\n");
- return PTR_ERR(gpiono1);
- }
- printk("成功获取到编号1\n");
- gpiono2 = gpiod_get_from_of_node(node, "myled2", 0, GPIOD_OUT_LOW, NULL);
- if (IS_ERR(gpiono2))
- {
- printk("获取gpio编号失败\n");
- return PTR_ERR(gpiono2);
- }
- printk("成功获取到编号2\n");
- gpiono3 = gpiod_get_from_of_node(node, "myled3", 0, GPIOD_OUT_LOW, NULL);
- if (IS_ERR(gpiono3))
- {
- printk("获取gpio编号失败\n");
- return PTR_ERR(gpiono3);
- }
- printk("成功获取到编号3\n");
- //通过名字获取中断设备树节点信息
- node_irq = of_find_node_by_name(NULL, "myirq");
- if (node_irq == NULL)
- {
- printk("通过名字解析设备树节点失败\n");
- return -EFAULT;
- }
- printk("成功解析到中断设备树节点\n");
- //根据设备树获取key1软中断号
- irqno1 = irq_of_parse_and_map(node_irq, 2);
- if (irqno1 == 0)
- {
- printk("获取软中断号失败\n");
- return EINVAL;
- }
- printk("获取key1软中断号成功\n");
- //根据设备树获取key2软中断号
- irqno2 = irq_of_parse_and_map(node_irq, 0);
- if (irqno2 == 0)
- {
- printk("获取软中断号失败\n");
- return EINVAL;
- }
- printk("获取key2软中断号成功\n");
- //根据设备树获取key2软中断号
- irqno3 = irq_of_parse_and_map(node_irq, 1);
- if (irqno3 == 0)
- {
- printk("获取软中断号失败\n");
- return EINVAL;
- }
- printk("获取key3软中断号成功\n");
- //将中断号注册进内核
- ret = request_irq(irqno1, irq_handler1, IRQF_TRIGGER_FALLING, "key1_inte", NULL);
- if (ret)
- {
- printk("注册中断失败\n");
- return ret;
- }
- ret = request_irq(irqno2, irq_handler2, IRQF_TRIGGER_FALLING, "key2_inte", NULL);
- if (ret)
- {
- printk("注册中断失败\n");
- return ret;
- }
- ret = request_irq(irqno3, irq_handler3, IRQF_TRIGGER_FALLING, "key3_inte", NULL);
- if (ret)
- {
- printk("注册中断失败\n");
- return ret;
- }
- printk("注册中断成功\n");
-
- return 0;
- }
- static void __exit mycdev_exit(void)
- {
- //中断注销
- free_irq(irqno1, NULL);
- free_irq(irqno2, NULL);
- free_irq(irqno3, NULL);
- //熄灭led
- gpiod_set_value(gpiono1, 0);
- gpiod_set_value(gpiono2, 0);
- gpiod_set_value(gpiono3, 0);
- //释放gpio编号
- gpiod_put(gpiono1);
- gpiod_put(gpiono2);
- gpiod_put(gpiono3);
- }
- module_init(mycdev_init);
- module_exit(mycdev_exit);
- MODULE_LICENSE("GPL");