1 /* 2 * Copyright (c) 2015 Google, Inc 3 * Written by Simon Glass <sjg@chromium.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <led.h> 12 #include <asm/gpio.h> 13 #include <dm/lists.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 struct led_gpio_priv { 18 struct gpio_desc gpio; 19 }; 20 21 static int gpio_led_set_on(struct udevice *dev, int on) 22 { 23 struct led_gpio_priv *priv = dev_get_priv(dev); 24 25 if (!dm_gpio_is_valid(&priv->gpio)) 26 return -EREMOTEIO; 27 28 return dm_gpio_set_value(&priv->gpio, on); 29 } 30 31 static int led_gpio_probe(struct udevice *dev) 32 { 33 struct led_uclass_plat *uc_plat = dev_get_uclass_platdata(dev); 34 struct led_gpio_priv *priv = dev_get_priv(dev); 35 36 /* Ignore the top-level LED node */ 37 if (!uc_plat->label) 38 return 0; 39 return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT); 40 } 41 42 static int led_gpio_remove(struct udevice *dev) 43 { 44 struct led_gpio_priv *priv = dev_get_priv(dev); 45 46 if (dm_gpio_is_valid(&priv->gpio)) 47 dm_gpio_free(dev, &priv->gpio); 48 49 return 0; 50 } 51 52 static int led_gpio_bind(struct udevice *parent) 53 { 54 const void *blob = gd->fdt_blob; 55 struct udevice *dev; 56 int node; 57 int ret; 58 59 for (node = fdt_first_subnode(blob, parent->of_offset); 60 node > 0; 61 node = fdt_next_subnode(blob, node)) { 62 struct led_uclass_plat *uc_plat; 63 const char *label; 64 65 label = fdt_getprop(blob, node, "label", NULL); 66 if (!label) { 67 debug("%s: node %s has no label\n", __func__, 68 fdt_get_name(blob, node, NULL)); 69 return -EINVAL; 70 } 71 ret = device_bind_driver_to_node(parent, "gpio_led", 72 fdt_get_name(blob, node, NULL), 73 node, &dev); 74 if (ret) 75 return ret; 76 uc_plat = dev_get_uclass_platdata(dev); 77 uc_plat->label = label; 78 } 79 80 return 0; 81 } 82 83 static const struct led_ops gpio_led_ops = { 84 .set_on = gpio_led_set_on, 85 }; 86 87 static const struct udevice_id led_gpio_ids[] = { 88 { .compatible = "gpio-leds" }, 89 { } 90 }; 91 92 U_BOOT_DRIVER(led_gpio) = { 93 .name = "gpio_led", 94 .id = UCLASS_LED, 95 .of_match = led_gpio_ids, 96 .ops = &gpio_led_ops, 97 .priv_auto_alloc_size = sizeof(struct led_gpio_priv), 98 .bind = led_gpio_bind, 99 .probe = led_gpio_probe, 100 .remove = led_gpio_remove, 101 }; 102