Commit 5ac76bad authored by Simon Glass's avatar Simon Glass

dm: led: Add a driver for GPIO-controlled LEDs

Add a simple driver which allows use of LEDs attached to GPIOs. The linux
device tree binding is used.
Signed-off-by: default avatarSimon Glass <sjg@chromium.org>
parent 5917112c
LEDs connected to GPIO lines
Required properties:
- compatible : should be "gpio-leds".
Each LED is represented as a sub-node of the gpio-leds device. Each
node's name represents the name of the corresponding LED.
LED sub-node properties:
- gpios : Should specify the LED's GPIO, see "gpios property" in
Documentation/devicetree/bindings/gpio/gpio.txt. Active low LEDs should be
indicated using flags in the GPIO specifier.
- label : (optional)
see Documentation/devicetree/bindings/leds/common.txt
- linux,default-trigger : (optional)
see Documentation/devicetree/bindings/leds/common.txt
- default-state: (optional) The initial state of the LED. Valid
values are "on", "off", and "keep". If the LED is already on or off
and the default-state property is set the to same value, then no
glitch should be produced where the LED momentarily turns off (or
on). The "keep" setting will keep the LED at whatever its current
state is, without producing a glitch. The default is off if this
property is not present.
Examples:
leds {
compatible = "gpio-leds";
hdd {
label = "IDE Activity";
gpios = <&mcu_pio 0 1>; /* Active low */
linux,default-trigger = "ide-disk";
};
fault {
gpios = <&mcu_pio 1 0>;
/* Keep LED on if BIOS detected hardware fault */
default-state = "keep";
};
};
run-control {
compatible = "gpio-leds";
red {
gpios = <&mpc8572 6 0>;
default-state = "off";
};
green {
gpios = <&mpc8572 7 0>;
default-state = "on";
};
};
......@@ -15,3 +15,12 @@ config SPL_LED_SUPPORT
If this is acceptable and you have a need to use LEDs in SPL,
enable this option. You will need to enable device tree in SPL
for this to work.
config LED_GPIO
bool "LED support for GPIO-connected LEDs"
depends on LED && DM_GPIO
help
Enable support for LEDs which are connected to GPIO lines. These
GPIOs may be on the SoC or some other device which provides GPIOs.
The GPIO driver must used driver model. LEDs are configured using
the device tree.
......@@ -6,3 +6,4 @@
#
obj-$(CONFIG_LED) += led-uclass.o
obj-$(CONFIG_LED_GPIO) += led_gpio.o
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <led.h>
#include <asm/gpio.h>
#include <dm/lists.h>
DECLARE_GLOBAL_DATA_PTR;
struct led_gpio_priv {
struct gpio_desc gpio;
};
static int gpio_led_set_on(struct udevice *dev, int on)
{
struct led_gpio_priv *priv = dev_get_priv(dev);
if (!dm_gpio_is_valid(&priv->gpio))
return -EREMOTEIO;
return dm_gpio_set_value(&priv->gpio, on);
}
static int led_gpio_probe(struct udevice *dev)
{
struct led_uclass_plat *uc_plat = dev_get_uclass_platdata(dev);
struct led_gpio_priv *priv = dev_get_priv(dev);
/* Ignore the top-level LED node */
if (!uc_plat->label)
return 0;
return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
}
static int led_gpio_remove(struct udevice *dev)
{
struct led_gpio_priv *priv = dev_get_priv(dev);
if (dm_gpio_is_valid(&priv->gpio))
dm_gpio_free(dev, &priv->gpio);
return 0;
}
static int led_gpio_bind(struct udevice *parent)
{
const void *blob = gd->fdt_blob;
struct udevice *dev;
int node;
int ret;
for (node = fdt_first_subnode(blob, parent->of_offset);
node > 0;
node = fdt_next_subnode(blob, node)) {
struct led_uclass_plat *uc_plat;
const char *label;
label = fdt_getprop(blob, node, "label", NULL);
if (!label) {
debug("%s: node %s has no label\n", __func__,
fdt_get_name(blob, node, NULL));
return -EINVAL;
}
ret = device_bind_driver_to_node(parent, "gpio_led",
fdt_get_name(blob, node, NULL),
node, &dev);
if (ret)
return ret;
uc_plat = dev_get_uclass_platdata(dev);
uc_plat->label = label;
}
return 0;
}
static const struct led_ops gpio_led_ops = {
.set_on = gpio_led_set_on,
};
static const struct udevice_id led_gpio_ids[] = {
{ .compatible = "gpio-leds" },
{ }
};
U_BOOT_DRIVER(led_gpio) = {
.name = "gpio_led",
.id = UCLASS_LED,
.of_match = led_gpio_ids,
.ops = &gpio_led_ops,
.priv_auto_alloc_size = sizeof(struct led_gpio_priv),
.bind = led_gpio_bind,
.probe = led_gpio_probe,
.remove = led_gpio_remove,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment