uboot/drivers/led/led_gpio.c
<<
>>
Prefs
   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
  15DECLARE_GLOBAL_DATA_PTR;
  16
  17struct led_gpio_priv {
  18        struct gpio_desc gpio;
  19};
  20
  21static 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
  31static 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
  42static int led_gpio_remove(struct udevice *dev)
  43{
  44        /*
  45         * The GPIO driver may have already been removed. We will need to
  46         * address this more generally.
  47         */
  48#ifndef CONFIG_SANDBOX
  49        struct led_gpio_priv *priv = dev_get_priv(dev);
  50
  51        if (dm_gpio_is_valid(&priv->gpio))
  52                dm_gpio_free(dev, &priv->gpio);
  53#endif
  54
  55        return 0;
  56}
  57
  58static int led_gpio_bind(struct udevice *parent)
  59{
  60        const void *blob = gd->fdt_blob;
  61        struct udevice *dev;
  62        int node;
  63        int ret;
  64
  65        for (node = fdt_first_subnode(blob, parent->of_offset);
  66             node > 0;
  67             node = fdt_next_subnode(blob, node)) {
  68                struct led_uclass_plat *uc_plat;
  69                const char *label;
  70
  71                label = fdt_getprop(blob, node, "label", NULL);
  72                if (!label) {
  73                        debug("%s: node %s has no label\n", __func__,
  74                              fdt_get_name(blob, node, NULL));
  75                        return -EINVAL;
  76                }
  77                ret = device_bind_driver_to_node(parent, "gpio_led",
  78                                                 fdt_get_name(blob, node, NULL),
  79                                                 node, &dev);
  80                if (ret)
  81                        return ret;
  82                uc_plat = dev_get_uclass_platdata(dev);
  83                uc_plat->label = label;
  84        }
  85
  86        return 0;
  87}
  88
  89static const struct led_ops gpio_led_ops = {
  90        .set_on         = gpio_led_set_on,
  91};
  92
  93static const struct udevice_id led_gpio_ids[] = {
  94        { .compatible = "gpio-leds" },
  95        { }
  96};
  97
  98U_BOOT_DRIVER(led_gpio) = {
  99        .name   = "gpio_led",
 100        .id     = UCLASS_LED,
 101        .of_match = led_gpio_ids,
 102        .ops    = &gpio_led_ops,
 103        .priv_auto_alloc_size = sizeof(struct led_gpio_priv),
 104        .bind   = led_gpio_bind,
 105        .probe  = led_gpio_probe,
 106        .remove = led_gpio_remove,
 107};
 108