forked from sysprog21/lkmpg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintrpt.c
145 lines (108 loc) · 3.47 KB
/
intrpt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
* intrpt.c - Handling GPIO with interrupts
*
* Based upon the RPi example by Stefan Wendler ([email protected])
* from:
* https://github.com/wendlers/rpi-kmod-samples
*
* Press one button to turn on a LED and another to turn it off.
*/
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h> /* for ARRAY_SIZE() */
#include <linux/module.h>
#include <linux/printk.h>
static int button_irqs[] = { -1, -1 };
/* Define GPIOs for LEDs.
* TODO: Change the numbers for the GPIO on your board.
*/
static struct gpio leds[] = { { 4, GPIOF_OUT_INIT_LOW, "LED 1" } };
/* Define GPIOs for BUTTONS
* TODO: Change the numbers for the GPIO on your board.
*/
static struct gpio buttons[] = { { 17, GPIOF_IN, "LED 1 ON BUTTON" },
{ 18, GPIOF_IN, "LED 1 OFF BUTTON" } };
/* interrupt function triggered when a button is pressed. */
static irqreturn_t button_isr(int irq, void *data)
{
/* first button */
if (irq == button_irqs[0] && !gpio_get_value(leds[0].gpio))
gpio_set_value(leds[0].gpio, 1);
/* second button */
else if (irq == button_irqs[1] && gpio_get_value(leds[0].gpio))
gpio_set_value(leds[0].gpio, 0);
return IRQ_HANDLED;
}
static int __init intrpt_init(void)
{
int ret = 0;
pr_info("%s\n", __func__);
/* register LED gpios */
ret = gpio_request_array(leds, ARRAY_SIZE(leds));
if (ret) {
pr_err("Unable to request GPIOs for LEDs: %d\n", ret);
return ret;
}
/* register BUTTON gpios */
ret = gpio_request_array(buttons, ARRAY_SIZE(buttons));
if (ret) {
pr_err("Unable to request GPIOs for BUTTONs: %d\n", ret);
goto fail1;
}
pr_info("Current button1 value: %d\n", gpio_get_value(buttons[0].gpio));
ret = gpio_to_irq(buttons[0].gpio);
if (ret < 0) {
pr_err("Unable to request IRQ: %d\n", ret);
goto fail2;
}
button_irqs[0] = ret;
pr_info("Successfully requested BUTTON1 IRQ # %d\n", button_irqs[0]);
ret = request_irq(button_irqs[0], button_isr,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"gpiomod#button1", NULL);
if (ret) {
pr_err("Unable to request IRQ: %d\n", ret);
goto fail2;
}
ret = gpio_to_irq(buttons[1].gpio);
if (ret < 0) {
pr_err("Unable to request IRQ: %d\n", ret);
goto fail2;
}
button_irqs[1] = ret;
pr_info("Successfully requested BUTTON2 IRQ # %d\n", button_irqs[1]);
ret = request_irq(button_irqs[1], button_isr,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"gpiomod#button2", NULL);
if (ret) {
pr_err("Unable to request IRQ: %d\n", ret);
goto fail3;
}
return 0;
/* cleanup what has been setup so far */
fail3:
free_irq(button_irqs[0], NULL);
fail2:
gpio_free_array(buttons, ARRAY_SIZE(leds));
fail1:
gpio_free_array(leds, ARRAY_SIZE(leds));
return ret;
}
static void __exit intrpt_exit(void)
{
int i;
pr_info("%s\n", __func__);
/* free irqs */
free_irq(button_irqs[0], NULL);
free_irq(button_irqs[1], NULL);
/* turn all LEDs off */
for (i = 0; i < ARRAY_SIZE(leds); i++)
gpio_set_value(leds[i].gpio, 0);
/* unregister */
gpio_free_array(leds, ARRAY_SIZE(leds));
gpio_free_array(buttons, ARRAY_SIZE(buttons));
}
module_init(intrpt_init);
module_exit(intrpt_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Handle some GPIO interrupts");