Skip to content

Commit 5c51277

Browse files
westerirafaeljw
authored andcommitted
leds: leds-gpio: Add support for GPIO descriptors
GPIO descriptors are the preferred way over legacy GPIO numbers nowadays. Convert the driver to use GPIO descriptors internally but still allow passing legacy GPIO numbers from platform data to support existing platforms. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Alexandre Courbot <acourbot@nvidia.com> Acked-by: Bryan Wu <cooloney@gmail.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Grant Likely <grant.likely@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent c479ff0 commit 5c51277

File tree

2 files changed

+46
-35
lines changed

2 files changed

+46
-35
lines changed

drivers/leds/leds-gpio.c

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313
#include <linux/err.h>
1414
#include <linux/gpio.h>
15+
#include <linux/gpio/consumer.h>
1516
#include <linux/kernel.h>
1617
#include <linux/leds.h>
1718
#include <linux/module.h>
@@ -24,11 +25,10 @@
2425

2526
struct gpio_led_data {
2627
struct led_classdev cdev;
27-
unsigned gpio;
28+
struct gpio_desc *gpiod;
2829
struct work_struct work;
2930
u8 new_level;
3031
u8 can_sleep;
31-
u8 active_low;
3232
u8 blinking;
3333
int (*platform_gpio_blink_set)(unsigned gpio, int state,
3434
unsigned long *delay_on, unsigned long *delay_off);
@@ -40,12 +40,16 @@ static void gpio_led_work(struct work_struct *work)
4040
container_of(work, struct gpio_led_data, work);
4141

4242
if (led_dat->blinking) {
43-
led_dat->platform_gpio_blink_set(led_dat->gpio,
44-
led_dat->new_level,
45-
NULL, NULL);
43+
int gpio = desc_to_gpio(led_dat->gpiod);
44+
int level = led_dat->new_level;
45+
46+
if (gpiod_is_active_low(led_dat->gpiod))
47+
level = !level;
48+
49+
led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);
4650
led_dat->blinking = 0;
4751
} else
48-
gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
52+
gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
4953
}
5054

5155
static void gpio_led_set(struct led_classdev *led_cdev,
@@ -60,9 +64,6 @@ static void gpio_led_set(struct led_classdev *led_cdev,
6064
else
6165
level = 1;
6266

63-
if (led_dat->active_low)
64-
level = !level;
65-
6667
/* Setting GPIOs with I2C/etc requires a task context, and we don't
6768
* seem to have a reliable way to know if we're already in one; so
6869
* let's just assume the worst.
@@ -72,11 +73,16 @@ static void gpio_led_set(struct led_classdev *led_cdev,
7273
schedule_work(&led_dat->work);
7374
} else {
7475
if (led_dat->blinking) {
75-
led_dat->platform_gpio_blink_set(led_dat->gpio, level,
76-
NULL, NULL);
76+
int gpio = desc_to_gpio(led_dat->gpiod);
77+
78+
if (gpiod_is_active_low(led_dat->gpiod))
79+
level = !level;
80+
81+
led_dat->platform_gpio_blink_set(gpio, level, NULL,
82+
NULL);
7783
led_dat->blinking = 0;
7884
} else
79-
gpio_set_value(led_dat->gpio, level);
85+
gpiod_set_value(led_dat->gpiod, level);
8086
}
8187
}
8288

@@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
8591
{
8692
struct gpio_led_data *led_dat =
8793
container_of(led_cdev, struct gpio_led_data, cdev);
94+
int gpio = desc_to_gpio(led_dat->gpiod);
8895

8996
led_dat->blinking = 1;
90-
return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
97+
return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK,
9198
delay_on, delay_off);
9299
}
93100

@@ -97,55 +104,58 @@ static int create_gpio_led(const struct gpio_led *template,
97104
{
98105
int ret, state;
99106

100-
led_dat->gpio = -1;
107+
if (!template->gpiod) {
108+
unsigned long flags = 0;
101109

102-
/* skip leds that aren't available */
103-
if (!gpio_is_valid(template->gpio)) {
104-
dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
105-
template->gpio, template->name);
106-
return 0;
107-
}
110+
/* skip leds that aren't available */
111+
if (!gpio_is_valid(template->gpio)) {
112+
dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
113+
template->gpio, template->name);
114+
return 0;
115+
}
108116

109-
ret = devm_gpio_request(parent, template->gpio, template->name);
110-
if (ret < 0)
111-
return ret;
117+
if (template->active_low)
118+
flags |= GPIOF_ACTIVE_LOW;
119+
120+
ret = devm_gpio_request_one(parent, template->gpio, flags,
121+
template->name);
122+
if (ret < 0)
123+
return ret;
124+
125+
led_dat->gpiod = gpio_to_desc(template->gpio);
126+
if (IS_ERR(led_dat->gpiod))
127+
return PTR_ERR(led_dat->gpiod);
128+
}
112129

113130
led_dat->cdev.name = template->name;
114131
led_dat->cdev.default_trigger = template->default_trigger;
115-
led_dat->gpio = template->gpio;
116-
led_dat->can_sleep = gpio_cansleep(template->gpio);
117-
led_dat->active_low = template->active_low;
132+
led_dat->gpiod = template->gpiod;
133+
led_dat->can_sleep = gpiod_cansleep(template->gpiod);
118134
led_dat->blinking = 0;
119135
if (blink_set) {
120136
led_dat->platform_gpio_blink_set = blink_set;
121137
led_dat->cdev.blink_set = gpio_blink_set;
122138
}
123139
led_dat->cdev.brightness_set = gpio_led_set;
124140
if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
125-
state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
141+
state = !!gpiod_get_value_cansleep(led_dat->gpiod);
126142
else
127143
state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
128144
led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
129145
if (!template->retain_state_suspended)
130146
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
131147

132-
ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
148+
ret = gpiod_direction_output(led_dat->gpiod, state);
133149
if (ret < 0)
134150
return ret;
135151

136152
INIT_WORK(&led_dat->work, gpio_led_work);
137153

138-
ret = led_classdev_register(parent, &led_dat->cdev);
139-
if (ret < 0)
140-
return ret;
141-
142-
return 0;
154+
return led_classdev_register(parent, &led_dat->cdev);
143155
}
144156

145157
static void delete_gpio_led(struct gpio_led_data *led)
146158
{
147-
if (!gpio_is_valid(led->gpio))
148-
return;
149159
led_classdev_unregister(&led->cdev);
150160
cancel_work_sync(&led->work);
151161
}

include/linux/leds.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ struct gpio_led {
261261
unsigned retain_state_suspended : 1;
262262
unsigned default_state : 2;
263263
/* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
264+
struct gpio_desc *gpiod;
264265
};
265266
#define LEDS_GPIO_DEFSTATE_OFF 0
266267
#define LEDS_GPIO_DEFSTATE_ON 1

0 commit comments

Comments
 (0)