summaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2018-09-06 18:09:40 -0400
committerJacek Anaszewski <jacek.anaszewski@gmail.com>2018-09-10 15:14:17 -0400
commit45d4c6de4e497e5b0026c77044ae5fcddf8fecd8 (patch)
tree4e60aff78bd51b5673b406f729a48725e5508427 /drivers/leds
parent9aec30371fb095a0c9415f3f0146ae269c3713d8 (diff)
leds: gpio: Try to lookup gpiod from device
This augments the GPIO lookup code in the GPIO LEDs to attempt to look up a GPIO descriptor from the device with index. This makes it possible to use GPIO machine look-up tables and stop passing global GPIO numbers through platform data. Using this we can stepwise convert existing board files to use machine descriptor tables and then eventually drop the legacy GPIO support and only include <linux/gpio/consumer.h> and use descriptors exclusively. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/leds-gpio.c92
1 files changed, 62 insertions, 30 deletions
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 764c31301f90..32fa752565bc 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -81,35 +81,6 @@ static int create_gpio_led(const struct gpio_led *template,
81{ 81{
82 int ret, state; 82 int ret, state;
83 83
84 led_dat->gpiod = template->gpiod;
85 if (!led_dat->gpiod) {
86 /*
87 * This is the legacy code path for platform code that
88 * still uses GPIO numbers. Ultimately we would like to get
89 * rid of this block completely.
90 */
91 unsigned long flags = GPIOF_OUT_INIT_LOW;
92
93 /* skip leds that aren't available */
94 if (!gpio_is_valid(template->gpio)) {
95 dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
96 template->gpio, template->name);
97 return 0;
98 }
99
100 if (template->active_low)
101 flags |= GPIOF_ACTIVE_LOW;
102
103 ret = devm_gpio_request_one(parent, template->gpio, flags,
104 template->name);
105 if (ret < 0)
106 return ret;
107
108 led_dat->gpiod = gpio_to_desc(template->gpio);
109 if (!led_dat->gpiod)
110 return -EINVAL;
111 }
112
113 led_dat->cdev.name = template->name; 84 led_dat->cdev.name = template->name;
114 led_dat->cdev.default_trigger = template->default_trigger; 85 led_dat->cdev.default_trigger = template->default_trigger;
115 led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); 86 led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod);
@@ -231,6 +202,52 @@ static const struct of_device_id of_gpio_leds_match[] = {
231 202
232MODULE_DEVICE_TABLE(of, of_gpio_leds_match); 203MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
233 204
205static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx,
206 const struct gpio_led *template)
207{
208 struct gpio_desc *gpiod;
209 unsigned long flags = GPIOF_OUT_INIT_LOW;
210 int ret;
211
212 /*
213 * This means the LED does not come from the device tree
214 * or ACPI, so let's try just getting it by index from the
215 * device, this will hit the board file, if any and get
216 * the GPIO from there.
217 */
218 gpiod = devm_gpiod_get_index(dev, NULL, idx, flags);
219 if (!IS_ERR(gpiod)) {
220 gpiod_set_consumer_name(gpiod, template->name);
221 return gpiod;
222 }
223 if (PTR_ERR(gpiod) != -ENOENT)
224 return gpiod;
225
226 /*
227 * This is the legacy code path for platform code that
228 * still uses GPIO numbers. Ultimately we would like to get
229 * rid of this block completely.
230 */
231
232 /* skip leds that aren't available */
233 if (!gpio_is_valid(template->gpio))
234 return ERR_PTR(-ENOENT);
235
236 if (template->active_low)
237 flags |= GPIOF_ACTIVE_LOW;
238
239 ret = devm_gpio_request_one(dev, template->gpio, flags,
240 template->name);
241 if (ret < 0)
242 return ERR_PTR(ret);
243
244 gpiod = gpio_to_desc(template->gpio);
245 if (!gpiod)
246 return ERR_PTR(-EINVAL);
247
248 return gpiod;
249}
250
234static int gpio_led_probe(struct platform_device *pdev) 251static int gpio_led_probe(struct platform_device *pdev)
235{ 252{
236 struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); 253 struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -246,7 +263,22 @@ static int gpio_led_probe(struct platform_device *pdev)
246 263
247 priv->num_leds = pdata->num_leds; 264 priv->num_leds = pdata->num_leds;
248 for (i = 0; i < priv->num_leds; i++) { 265 for (i = 0; i < priv->num_leds; i++) {
249 ret = create_gpio_led(&pdata->leds[i], &priv->leds[i], 266 const struct gpio_led *template = &pdata->leds[i];
267 struct gpio_led_data *led_dat = &priv->leds[i];
268
269 if (template->gpiod)
270 led_dat->gpiod = template->gpiod;
271 else
272 led_dat->gpiod =
273 gpio_led_get_gpiod(&pdev->dev,
274 i, template);
275 if (IS_ERR(led_dat->gpiod)) {
276 dev_info(&pdev->dev, "Skipping unavailable LED gpio %d (%s)\n",
277 template->gpio, template->name);
278 continue;
279 }
280
281 ret = create_gpio_led(template, led_dat,
250 &pdev->dev, NULL, 282 &pdev->dev, NULL,
251 pdata->gpio_blink_set); 283 pdata->gpio_blink_set);
252 if (ret < 0) 284 if (ret < 0)