forked from PacktPublishing/Linux-Device-Drivers-Development
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gpio-legacy-dt-module.c
116 lines (96 loc) · 3.2 KB
/
gpio-legacy-dt-module.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
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h> /* For platform devices */
#include <linux/interrupt.h> /* For IRQ */
#include <linux/gpio.h> /* For Legacy integer based GPIO */
#include <linux/of_gpio.h> /* For of_gpio* functions */
#include <linux/of.h> /* For DT*/
/*
* Let us consider the node bellow
*
* foo_device {
* compatible = "packt,gpio-legacy-sample";
* led-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>, // red
* <&gpio2 16 GPIO_ACTIVE_HIGH>, // green
*
* btn1-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
* btn2-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
* };
*/
static unsigned int gpio_red, gpio_green, gpio_btn1, gpio_btn2;
static int irq;
static irqreturn_t btn1_pushed_irq_handler(int irq, void *dev_id)
{
int state;
/* read the button value and change the led state */
state = gpio_get_value(gpio_btn2);
gpio_set_value(gpio_red, state);
gpio_set_value(gpio_green, state);
pr_info("gpio_btn1 interrupt: Interrupt! gpio_btn2 state is %d)\n", state);
return IRQ_HANDLED;
}
static const struct of_device_id gpio_dt_ids[] = {
{ .compatible = "packt,gpio-legacy-sample", },
{ /* sentinel */ }
};
static int my_pdrv_probe (struct platform_device *pdev)
{
int retval;
struct device_node *np = pdev->dev.of_node;
if (!np)
return -ENOENT;
gpio_red = of_get_named_gpio(np, "led", 0);
gpio_green = of_get_named_gpio(np, "led", 1);
gpio_btn1 = of_get_named_gpio(np, "btn1", 0);
gpio_btn2 = of_get_named_gpio(np, "btn2", 0);
gpio_request(gpio_green, "green-led");
gpio_request(gpio_red, "red-led");
gpio_request(gpio_btn1, "button-1");
gpio_request(gpio_btn2, "button-2");
/*
* Configure Button GPIOs as input
*
* After this, one can call gpio_set_debounce()
* only if the controller has the feature
*
* For example, to debounce a button with a delay of 200ms
* gpio_set_debounce(gpio_btn1, 200);
*/
gpio_direction_input(gpio_btn1);
gpio_direction_input(gpio_btn2);
/*
* Set LED GPIOs as output, with their initial values set to 0
*/
gpio_direction_output(gpio_red, 0);
gpio_direction_output(gpio_green, 0);
irq = gpio_to_irq(gpio_btn1);
retval = request_threaded_irq(irq, NULL,
btn1_pushed_irq_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"gpio-legacy-sample", NULL);
pr_info("Hello world!\n");
return 0;
}
static int my_pdrv_remove(struct platform_device *pdev)
{
free_irq(irq, NULL);
gpio_free(gpio_red);
gpio_free(gpio_green);
gpio_free(gpio_btn1);
gpio_free(gpio_btn2);
pr_info("End of the world\n");
return 0;
}
static struct platform_driver mypdrv = {
.probe = my_pdrv_probe,
.remove = my_pdrv_remove,
.driver = {
.name = "gpio_legacy_sample",
.of_match_table = of_match_ptr(gpio_dt_ids),
.owner = THIS_MODULE,
},
};
module_platform_driver(mypdrv);
MODULE_AUTHOR("John Madieu <john.madieu@gmail.com>");
MODULE_LICENSE("GPL");