blob: 71421de628c993860dfde9efa5e0c7519d5618f2 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass5ac76ba2015-06-23 15:38:46 -06002/*
3 * Copyright (c) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glass5ac76ba2015-06-23 15:38:46 -06005 */
6
7#include <common.h>
8#include <dm.h>
9#include <errno.h>
10#include <led.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060011#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070012#include <malloc.h>
Simon Glass5ac76ba2015-06-23 15:38:46 -060013#include <asm/gpio.h>
Simon Glass5ac76ba2015-06-23 15:38:46 -060014
Simon Glass5ac76ba2015-06-23 15:38:46 -060015struct led_gpio_priv {
16 struct gpio_desc gpio;
17};
18
Simon Glassddae9fc2017-04-10 11:34:54 -060019static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
Simon Glass5ac76ba2015-06-23 15:38:46 -060020{
21 struct led_gpio_priv *priv = dev_get_priv(dev);
Simon Glass9413ad42017-04-10 11:34:56 -060022 int ret;
Simon Glass5ac76ba2015-06-23 15:38:46 -060023
24 if (!dm_gpio_is_valid(&priv->gpio))
25 return -EREMOTEIO;
Simon Glass8f4b6122017-04-10 11:34:55 -060026 switch (state) {
27 case LEDST_OFF:
28 case LEDST_ON:
29 break;
Simon Glass9413ad42017-04-10 11:34:56 -060030 case LEDST_TOGGLE:
31 ret = dm_gpio_get_value(&priv->gpio);
32 if (ret < 0)
33 return ret;
34 state = !ret;
35 break;
Simon Glass8f4b6122017-04-10 11:34:55 -060036 default:
37 return -ENOSYS;
38 }
Simon Glass5ac76ba2015-06-23 15:38:46 -060039
Simon Glassddae9fc2017-04-10 11:34:54 -060040 return dm_gpio_set_value(&priv->gpio, state);
Simon Glass5ac76ba2015-06-23 15:38:46 -060041}
42
Simon Glass8f4b6122017-04-10 11:34:55 -060043static enum led_state_t gpio_led_get_state(struct udevice *dev)
44{
45 struct led_gpio_priv *priv = dev_get_priv(dev);
46 int ret;
47
48 if (!dm_gpio_is_valid(&priv->gpio))
49 return -EREMOTEIO;
50 ret = dm_gpio_get_value(&priv->gpio);
51 if (ret < 0)
52 return ret;
53
54 return ret ? LEDST_ON : LEDST_OFF;
55}
56
Simon Glass5ac76ba2015-06-23 15:38:46 -060057static int led_gpio_probe(struct udevice *dev)
58{
Simon Glass5ac76ba2015-06-23 15:38:46 -060059 struct led_gpio_priv *priv = dev_get_priv(dev);
60
Marek Vasut01074692022-04-22 15:34:00 +020061 return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
Simon Glass5ac76ba2015-06-23 15:38:46 -060062}
63
64static int led_gpio_remove(struct udevice *dev)
65{
Simon Glass3c43fba2015-07-06 12:54:34 -060066 /*
67 * The GPIO driver may have already been removed. We will need to
68 * address this more generally.
69 */
70#ifndef CONFIG_SANDBOX
Simon Glass5ac76ba2015-06-23 15:38:46 -060071 struct led_gpio_priv *priv = dev_get_priv(dev);
72
73 if (dm_gpio_is_valid(&priv->gpio))
74 dm_gpio_free(dev, &priv->gpio);
Simon Glass3c43fba2015-07-06 12:54:34 -060075#endif
Simon Glass5ac76ba2015-06-23 15:38:46 -060076
77 return 0;
78}
79
80static int led_gpio_bind(struct udevice *parent)
81{
Rasmus Villemoes82eb8e52023-11-17 12:38:09 +010082 return led_bind_generic(parent, "gpio_led");
Simon Glass5ac76ba2015-06-23 15:38:46 -060083}
84
85static const struct led_ops gpio_led_ops = {
Simon Glassddae9fc2017-04-10 11:34:54 -060086 .set_state = gpio_led_set_state,
Simon Glass8f4b6122017-04-10 11:34:55 -060087 .get_state = gpio_led_get_state,
Simon Glass5ac76ba2015-06-23 15:38:46 -060088};
89
Marek Vasut01074692022-04-22 15:34:00 +020090U_BOOT_DRIVER(led_gpio) = {
91 .name = "gpio_led",
92 .id = UCLASS_LED,
93 .ops = &gpio_led_ops,
94 .priv_auto = sizeof(struct led_gpio_priv),
95 .probe = led_gpio_probe,
96 .remove = led_gpio_remove,
97};
98
Simon Glass5ac76ba2015-06-23 15:38:46 -060099static const struct udevice_id led_gpio_ids[] = {
100 { .compatible = "gpio-leds" },
101 { }
102};
103
Marek Vasut01074692022-04-22 15:34:00 +0200104U_BOOT_DRIVER(led_gpio_wrap) = {
105 .name = "gpio_led_wrap",
106 .id = UCLASS_NOP,
Simon Glass5ac76ba2015-06-23 15:38:46 -0600107 .of_match = led_gpio_ids,
Simon Glass5ac76ba2015-06-23 15:38:46 -0600108 .bind = led_gpio_bind,
Simon Glass5ac76ba2015-06-23 15:38:46 -0600109};