Skip to content

Commit 4a11dbf

Browse files
linuswlag-linaro
authored andcommitted
leds: triggers: gpio: Rewrite to use trigger-sources
By providing a GPIO line as "trigger-sources" in the FWNODE (such as from the device tree) and combining with the GPIO trigger, we can support a GPIO LED trigger in a natural way from the hardware description instead of using the custom sysfs and deprecated global GPIO numberspace. Example: gpio: gpio@0 { compatible "my-gpio"; gpio-controller; #gpio-cells = <2>; interrupt-controller; #interrupt-cells = <2>; #trigger-source-cells = <2>; }; leds { compatible = "gpio-leds"; led-my-gpio { label = "device:blue:myled"; gpios = <&gpio 0 GPIO_ACTIVE_HIGH>; default-state = "off"; linux,default-trigger = "gpio"; trigger-sources = <&gpio 1 GPIO_ACTIVE_HIGH>; }; }; Make this the norm, unmark the driver as broken. Delete the sysfs handling of GPIOs. Since GPIO descriptors inherently can describe inversion, the inversion handling can just be deleted. Signed-off-by: Linus Walleij <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Lee Jones <[email protected]>
1 parent f9be4d5 commit 4a11dbf

File tree

2 files changed

+41
-101
lines changed

2 files changed

+41
-101
lines changed

drivers/leds/trigger/Kconfig

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,10 @@ config LEDS_TRIGGER_ACTIVITY
8383
config LEDS_TRIGGER_GPIO
8484
tristate "LED GPIO Trigger"
8585
depends on GPIOLIB || COMPILE_TEST
86-
depends on BROKEN
8786
help
8887
This allows LEDs to be controlled by gpio events. It's good
8988
when using gpios as switches and triggering the needed LEDs
90-
from there. One use case is n810's keypad LEDs that could
91-
be triggered by this trigger when user slides up to show
92-
keypad.
89+
from there. Triggers are defined as device properties.
9390

9491
If unsure, say N.
9592

drivers/leds/trigger/ledtrig-gpio.c

Lines changed: 40 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,22 @@
33
* ledtrig-gio.c - LED Trigger Based on GPIO events
44
*
55
* Copyright 2009 Felipe Balbi <[email protected]>
6+
* Copyright 2023 Linus Walleij <[email protected]>
67
*/
78

89
#include <linux/module.h>
910
#include <linux/kernel.h>
1011
#include <linux/init.h>
11-
#include <linux/gpio.h>
12+
#include <linux/gpio/consumer.h>
1213
#include <linux/interrupt.h>
1314
#include <linux/leds.h>
1415
#include <linux/slab.h>
1516
#include "../leds.h"
1617

1718
struct gpio_trig_data {
1819
struct led_classdev *led;
19-
2020
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 */
2322
};
2423

2524
static irqreturn_t gpio_trig_irq(int irq, void *_led)
@@ -28,10 +27,7 @@ static irqreturn_t gpio_trig_irq(int irq, void *_led)
2827
struct gpio_trig_data *gpio_data = led_get_trigger_data(led);
2928
int tmp;
3029

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);
3531
if (tmp) {
3632
if (gpio_data->desired_brightness)
3733
led_set_brightness_nosleep(gpio_data->led,
@@ -73,119 +69,66 @@ static ssize_t gpio_trig_brightness_store(struct device *dev,
7369
static DEVICE_ATTR(desired_brightness, 0644, gpio_trig_brightness_show,
7470
gpio_trig_brightness_store);
7571

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-
15972
static struct attribute *gpio_trig_attrs[] = {
16073
&dev_attr_desired_brightness.attr,
161-
&dev_attr_inverted.attr,
162-
&dev_attr_gpio.attr,
16374
NULL
16475
};
16576
ATTRIBUTE_GROUPS(gpio_trig);
16677

16778
static int gpio_trig_activate(struct led_classdev *led)
16879
{
16980
struct gpio_trig_data *gpio_data;
81+
struct device *dev = led->dev;
82+
int ret;
17083

17184
gpio_data = kzalloc(sizeof(*gpio_data), GFP_KERNEL);
17285
if (!gpio_data)
17386
return -ENOMEM;
17487

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+
}
177106

107+
gpio_data->led = led;
178108
led_set_trigger_data(led, gpio_data);
179109

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+
180123
return 0;
181124
}
182125

183126
static void gpio_trig_deactivate(struct led_classdev *led)
184127
{
185128
struct gpio_trig_data *gpio_data = led_get_trigger_data(led);
186129

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);
189132
kfree(gpio_data);
190133
}
191134

0 commit comments

Comments
 (0)