Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Linus Walleij and committed by
Jacek Anaszewski
45d4c6de 9aec3037

+62 -30
+62 -30
drivers/leds/leds-gpio.c
··· 81 81 { 82 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 84 led_dat->cdev.name = template->name; 114 85 led_dat->cdev.default_trigger = template->default_trigger; 115 86 led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); ··· 202 231 203 232 MODULE_DEVICE_TABLE(of, of_gpio_leds_match); 204 233 234 + static struct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx, 235 + const struct gpio_led *template) 236 + { 237 + struct gpio_desc *gpiod; 238 + unsigned long flags = GPIOF_OUT_INIT_LOW; 239 + int ret; 240 + 241 + /* 242 + * This means the LED does not come from the device tree 243 + * or ACPI, so let's try just getting it by index from the 244 + * device, this will hit the board file, if any and get 245 + * the GPIO from there. 246 + */ 247 + gpiod = devm_gpiod_get_index(dev, NULL, idx, flags); 248 + if (!IS_ERR(gpiod)) { 249 + gpiod_set_consumer_name(gpiod, template->name); 250 + return gpiod; 251 + } 252 + if (PTR_ERR(gpiod) != -ENOENT) 253 + return gpiod; 254 + 255 + /* 256 + * This is the legacy code path for platform code that 257 + * still uses GPIO numbers. Ultimately we would like to get 258 + * rid of this block completely. 259 + */ 260 + 261 + /* skip leds that aren't available */ 262 + if (!gpio_is_valid(template->gpio)) 263 + return ERR_PTR(-ENOENT); 264 + 265 + if (template->active_low) 266 + flags |= GPIOF_ACTIVE_LOW; 267 + 268 + ret = devm_gpio_request_one(dev, template->gpio, flags, 269 + template->name); 270 + if (ret < 0) 271 + return ERR_PTR(ret); 272 + 273 + gpiod = gpio_to_desc(template->gpio); 274 + if (!gpiod) 275 + return ERR_PTR(-EINVAL); 276 + 277 + return gpiod; 278 + } 279 + 205 280 static int gpio_led_probe(struct platform_device *pdev) 206 281 { 207 282 struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev); ··· 263 246 264 247 priv->num_leds = pdata->num_leds; 265 248 for (i = 0; i < priv->num_leds; i++) { 266 - ret = create_gpio_led(&pdata->leds[i], &priv->leds[i], 249 + const struct gpio_led *template = &pdata->leds[i]; 250 + struct gpio_led_data *led_dat = &priv->leds[i]; 251 + 252 + if (template->gpiod) 253 + led_dat->gpiod = template->gpiod; 254 + else 255 + led_dat->gpiod = 256 + gpio_led_get_gpiod(&pdev->dev, 257 + i, template); 258 + if (IS_ERR(led_dat->gpiod)) { 259 + dev_info(&pdev->dev, "Skipping unavailable LED gpio %d (%s)\n", 260 + template->gpio, template->name); 261 + continue; 262 + } 263 + 264 + ret = create_gpio_led(template, led_dat, 267 265 &pdev->dev, NULL, 268 266 pdata->gpio_blink_set); 269 267 if (ret < 0)