3
3
* ledtrig-gio.c - LED Trigger Based on GPIO events
4
4
*
5
5
* Copyright 2009 Felipe Balbi <[email protected] >
6
+ * Copyright 2023 Linus Walleij <[email protected] >
6
7
*/
7
8
8
9
#include <linux/module.h>
9
10
#include <linux/kernel.h>
10
11
#include <linux/init.h>
11
- #include <linux/gpio.h>
12
+ #include <linux/gpio/consumer .h>
12
13
#include <linux/interrupt.h>
13
14
#include <linux/leds.h>
14
15
#include <linux/slab.h>
15
16
#include "../leds.h"
16
17
17
18
struct gpio_trig_data {
18
19
struct led_classdev * led ;
19
-
20
20
unsigned desired_brightness ; /* desired brightness when led is on */
21
- unsigned inverted ; /* true when gpio is inverted */
22
- unsigned gpio ; /* gpio that triggers the leds */
21
+ struct gpio_desc * gpiod ; /* gpio that triggers the led */
23
22
};
24
23
25
24
static irqreturn_t gpio_trig_irq (int irq , void * _led )
@@ -28,10 +27,7 @@ static irqreturn_t gpio_trig_irq(int irq, void *_led)
28
27
struct gpio_trig_data * gpio_data = led_get_trigger_data (led );
29
28
int tmp ;
30
29
31
- tmp = gpio_get_value_cansleep (gpio_data -> gpio );
32
- if (gpio_data -> inverted )
33
- tmp = !tmp ;
34
-
30
+ tmp = gpiod_get_value_cansleep (gpio_data -> gpiod );
35
31
if (tmp ) {
36
32
if (gpio_data -> desired_brightness )
37
33
led_set_brightness_nosleep (gpio_data -> led ,
@@ -73,119 +69,66 @@ static ssize_t gpio_trig_brightness_store(struct device *dev,
73
69
static DEVICE_ATTR (desired_brightness , 0644 , gpio_trig_brightness_show ,
74
70
gpio_trig_brightness_store ) ;
75
71
76
- static ssize_t gpio_trig_inverted_show (struct device * dev ,
77
- struct device_attribute * attr , char * buf )
78
- {
79
- struct gpio_trig_data * gpio_data = led_trigger_get_drvdata (dev );
80
-
81
- return sprintf (buf , "%u\n" , gpio_data -> inverted );
82
- }
83
-
84
- static ssize_t gpio_trig_inverted_store (struct device * dev ,
85
- struct device_attribute * attr , const char * buf , size_t n )
86
- {
87
- struct led_classdev * led = led_trigger_get_led (dev );
88
- struct gpio_trig_data * gpio_data = led_trigger_get_drvdata (dev );
89
- unsigned long inverted ;
90
- int ret ;
91
-
92
- ret = kstrtoul (buf , 10 , & inverted );
93
- if (ret < 0 )
94
- return ret ;
95
-
96
- if (inverted > 1 )
97
- return - EINVAL ;
98
-
99
- gpio_data -> inverted = inverted ;
100
-
101
- /* After inverting, we need to update the LED. */
102
- if (gpio_is_valid (gpio_data -> gpio ))
103
- gpio_trig_irq (0 , led );
104
-
105
- return n ;
106
- }
107
- static DEVICE_ATTR (inverted , 0644 , gpio_trig_inverted_show ,
108
- gpio_trig_inverted_store ) ;
109
-
110
- static ssize_t gpio_trig_gpio_show (struct device * dev ,
111
- struct device_attribute * attr , char * buf )
112
- {
113
- struct gpio_trig_data * gpio_data = led_trigger_get_drvdata (dev );
114
-
115
- return sprintf (buf , "%u\n" , gpio_data -> gpio );
116
- }
117
-
118
- static ssize_t gpio_trig_gpio_store (struct device * dev ,
119
- struct device_attribute * attr , const char * buf , size_t n )
120
- {
121
- struct led_classdev * led = led_trigger_get_led (dev );
122
- struct gpio_trig_data * gpio_data = led_trigger_get_drvdata (dev );
123
- unsigned gpio ;
124
- int ret ;
125
-
126
- ret = sscanf (buf , "%u" , & gpio );
127
- if (ret < 1 ) {
128
- dev_err (dev , "couldn't read gpio number\n" );
129
- return - EINVAL ;
130
- }
131
-
132
- if (gpio_data -> gpio == gpio )
133
- return n ;
134
-
135
- if (!gpio_is_valid (gpio )) {
136
- if (gpio_is_valid (gpio_data -> gpio ))
137
- free_irq (gpio_to_irq (gpio_data -> gpio ), led );
138
- gpio_data -> gpio = gpio ;
139
- return n ;
140
- }
141
-
142
- ret = request_threaded_irq (gpio_to_irq (gpio ), NULL , gpio_trig_irq ,
143
- IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING
144
- | IRQF_TRIGGER_FALLING , "ledtrig-gpio" , led );
145
- if (ret ) {
146
- dev_err (dev , "request_irq failed with error %d\n" , ret );
147
- } else {
148
- if (gpio_is_valid (gpio_data -> gpio ))
149
- free_irq (gpio_to_irq (gpio_data -> gpio ), led );
150
- gpio_data -> gpio = gpio ;
151
- /* After changing the GPIO, we need to update the LED. */
152
- gpio_trig_irq (0 , led );
153
- }
154
-
155
- return ret ? ret : n ;
156
- }
157
- static DEVICE_ATTR (gpio , 0644 , gpio_trig_gpio_show , gpio_trig_gpio_store ) ;
158
-
159
72
static struct attribute * gpio_trig_attrs [] = {
160
73
& dev_attr_desired_brightness .attr ,
161
- & dev_attr_inverted .attr ,
162
- & dev_attr_gpio .attr ,
163
74
NULL
164
75
};
165
76
ATTRIBUTE_GROUPS (gpio_trig );
166
77
167
78
static int gpio_trig_activate (struct led_classdev * led )
168
79
{
169
80
struct gpio_trig_data * gpio_data ;
81
+ struct device * dev = led -> dev ;
82
+ int ret ;
170
83
171
84
gpio_data = kzalloc (sizeof (* gpio_data ), GFP_KERNEL );
172
85
if (!gpio_data )
173
86
return - ENOMEM ;
174
87
175
- gpio_data -> led = led ;
176
- gpio_data -> gpio = - ENOENT ;
88
+ /*
89
+ * The generic property "trigger-sources" is followed,
90
+ * and we hope that this is a GPIO.
91
+ */
92
+ gpio_data -> gpiod = fwnode_gpiod_get_index (dev -> fwnode ,
93
+ "trigger-sources" ,
94
+ 0 , GPIOD_IN ,
95
+ "led-trigger" );
96
+ if (IS_ERR (gpio_data -> gpiod )) {
97
+ ret = PTR_ERR (gpio_data -> gpiod );
98
+ kfree (gpio_data );
99
+ return ret ;
100
+ }
101
+ if (!gpio_data -> gpiod ) {
102
+ dev_err (dev , "no valid GPIO for the trigger\n" );
103
+ kfree (gpio_data );
104
+ return - EINVAL ;
105
+ }
177
106
107
+ gpio_data -> led = led ;
178
108
led_set_trigger_data (led , gpio_data );
179
109
110
+ ret = request_threaded_irq (gpiod_to_irq (gpio_data -> gpiod ), NULL , gpio_trig_irq ,
111
+ IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING
112
+ | IRQF_TRIGGER_FALLING , "ledtrig-gpio" , led );
113
+ if (ret ) {
114
+ dev_err (dev , "request_irq failed with error %d\n" , ret );
115
+ gpiod_put (gpio_data -> gpiod );
116
+ kfree (gpio_data );
117
+ return ret ;
118
+ }
119
+
120
+ /* Finally update the LED to initial status */
121
+ gpio_trig_irq (0 , led );
122
+
180
123
return 0 ;
181
124
}
182
125
183
126
static void gpio_trig_deactivate (struct led_classdev * led )
184
127
{
185
128
struct gpio_trig_data * gpio_data = led_get_trigger_data (led );
186
129
187
- if ( gpio_is_valid (gpio_data -> gpio ))
188
- free_irq ( gpio_to_irq ( gpio_data -> gpio ), led );
130
+ free_irq ( gpiod_to_irq (gpio_data -> gpiod ), led );
131
+ gpiod_put ( gpio_data -> gpiod );
189
132
kfree (gpio_data );
190
133
}
191
134
0 commit comments