xref: /rk3399_rockchip-uboot/drivers/led/led_gpio.c (revision ddae9fcddc48d1e624c941148d0df5a4fc7d7d5c)
15ac76badSSimon Glass /*
25ac76badSSimon Glass  * Copyright (c) 2015 Google, Inc
35ac76badSSimon Glass  * Written by Simon Glass <sjg@chromium.org>
45ac76badSSimon Glass  *
55ac76badSSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
65ac76badSSimon Glass  */
75ac76badSSimon Glass 
85ac76badSSimon Glass #include <common.h>
95ac76badSSimon Glass #include <dm.h>
105ac76badSSimon Glass #include <errno.h>
115ac76badSSimon Glass #include <led.h>
125ac76badSSimon Glass #include <asm/gpio.h>
135ac76badSSimon Glass #include <dm/lists.h>
145ac76badSSimon Glass 
155ac76badSSimon Glass DECLARE_GLOBAL_DATA_PTR;
165ac76badSSimon Glass 
175ac76badSSimon Glass struct led_gpio_priv {
185ac76badSSimon Glass 	struct gpio_desc gpio;
195ac76badSSimon Glass };
205ac76badSSimon Glass 
21*ddae9fcdSSimon Glass static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
225ac76badSSimon Glass {
235ac76badSSimon Glass 	struct led_gpio_priv *priv = dev_get_priv(dev);
245ac76badSSimon Glass 
255ac76badSSimon Glass 	if (!dm_gpio_is_valid(&priv->gpio))
265ac76badSSimon Glass 		return -EREMOTEIO;
275ac76badSSimon Glass 
28*ddae9fcdSSimon Glass 	return dm_gpio_set_value(&priv->gpio, state);
295ac76badSSimon Glass }
305ac76badSSimon Glass 
315ac76badSSimon Glass static int led_gpio_probe(struct udevice *dev)
325ac76badSSimon Glass {
3356e19871SSimon Glass 	struct led_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
345ac76badSSimon Glass 	struct led_gpio_priv *priv = dev_get_priv(dev);
355ac76badSSimon Glass 
365ac76badSSimon Glass 	/* Ignore the top-level LED node */
375ac76badSSimon Glass 	if (!uc_plat->label)
385ac76badSSimon Glass 		return 0;
395ac76badSSimon Glass 	return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
405ac76badSSimon Glass }
415ac76badSSimon Glass 
425ac76badSSimon Glass static int led_gpio_remove(struct udevice *dev)
435ac76badSSimon Glass {
443c43fba3SSimon Glass 	/*
453c43fba3SSimon Glass 	 * The GPIO driver may have already been removed. We will need to
463c43fba3SSimon Glass 	 * address this more generally.
473c43fba3SSimon Glass 	 */
483c43fba3SSimon Glass #ifndef CONFIG_SANDBOX
495ac76badSSimon Glass 	struct led_gpio_priv *priv = dev_get_priv(dev);
505ac76badSSimon Glass 
515ac76badSSimon Glass 	if (dm_gpio_is_valid(&priv->gpio))
525ac76badSSimon Glass 		dm_gpio_free(dev, &priv->gpio);
533c43fba3SSimon Glass #endif
545ac76badSSimon Glass 
555ac76badSSimon Glass 	return 0;
565ac76badSSimon Glass }
575ac76badSSimon Glass 
585ac76badSSimon Glass static int led_gpio_bind(struct udevice *parent)
595ac76badSSimon Glass {
605ac76badSSimon Glass 	const void *blob = gd->fdt_blob;
615ac76badSSimon Glass 	struct udevice *dev;
625ac76badSSimon Glass 	int node;
635ac76badSSimon Glass 	int ret;
645ac76badSSimon Glass 
65e160f7d4SSimon Glass 	for (node = fdt_first_subnode(blob, dev_of_offset(parent));
665ac76badSSimon Glass 	     node > 0;
675ac76badSSimon Glass 	     node = fdt_next_subnode(blob, node)) {
6856e19871SSimon Glass 		struct led_uc_plat *uc_plat;
695ac76badSSimon Glass 		const char *label;
705ac76badSSimon Glass 
715ac76badSSimon Glass 		label = fdt_getprop(blob, node, "label", NULL);
725ac76badSSimon Glass 		if (!label) {
735ac76badSSimon Glass 			debug("%s: node %s has no label\n", __func__,
745ac76badSSimon Glass 			      fdt_get_name(blob, node, NULL));
755ac76badSSimon Glass 			return -EINVAL;
765ac76badSSimon Glass 		}
775ac76badSSimon Glass 		ret = device_bind_driver_to_node(parent, "gpio_led",
785ac76badSSimon Glass 						 fdt_get_name(blob, node, NULL),
795ac76badSSimon Glass 						 node, &dev);
805ac76badSSimon Glass 		if (ret)
815ac76badSSimon Glass 			return ret;
825ac76badSSimon Glass 		uc_plat = dev_get_uclass_platdata(dev);
835ac76badSSimon Glass 		uc_plat->label = label;
845ac76badSSimon Glass 	}
855ac76badSSimon Glass 
865ac76badSSimon Glass 	return 0;
875ac76badSSimon Glass }
885ac76badSSimon Glass 
895ac76badSSimon Glass static const struct led_ops gpio_led_ops = {
90*ddae9fcdSSimon Glass 	.set_state	= gpio_led_set_state,
915ac76badSSimon Glass };
925ac76badSSimon Glass 
935ac76badSSimon Glass static const struct udevice_id led_gpio_ids[] = {
945ac76badSSimon Glass 	{ .compatible = "gpio-leds" },
955ac76badSSimon Glass 	{ }
965ac76badSSimon Glass };
975ac76badSSimon Glass 
985ac76badSSimon Glass U_BOOT_DRIVER(led_gpio) = {
995ac76badSSimon Glass 	.name	= "gpio_led",
1005ac76badSSimon Glass 	.id	= UCLASS_LED,
1015ac76badSSimon Glass 	.of_match = led_gpio_ids,
1025ac76badSSimon Glass 	.ops	= &gpio_led_ops,
1035ac76badSSimon Glass 	.priv_auto_alloc_size = sizeof(struct led_gpio_priv),
1045ac76badSSimon Glass 	.bind	= led_gpio_bind,
1055ac76badSSimon Glass 	.probe	= led_gpio_probe,
1065ac76badSSimon Glass 	.remove	= led_gpio_remove,
1075ac76badSSimon Glass };
108