[PATCH 1/9] led: led_gpio: add support for SW Blink
Christian Marangi
ansuelsmth at gmail.com
Mon Jun 24 23:46:11 CEST 2024
Add support for GPIO-connected LEDs to make use of Cyclic API to
simulate Blink by software.
A new Kconfig is introduced to enable this, CONFIG_LED_GPIO_SW_BLINK.
Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
---
drivers/led/Kconfig | 9 +++++++
drivers/led/led_gpio.c | 56 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+)
diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig
index 9837960198d..13d6eb40cea 100644
--- a/drivers/led/Kconfig
+++ b/drivers/led/Kconfig
@@ -91,6 +91,15 @@ config LED_GPIO
The GPIO driver must used driver model. LEDs are configured using
the device tree.
+config LED_GPIO_SW_BLINK
+ bool "LED support for GPIO software blink"
+ depends on LED_GPIO
+ select CYCLIC
+ select LED_BLINK
+ help
+ Enable support for GPIO-connected LEDs to make use of Cyclic API
+ to simulate LED blink by software.
+
config SPL_LED_GPIO
bool "LED support for GPIO-connected LEDs in SPL"
depends on SPL_LED && SPL_DM_GPIO
diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c
index ce22fb49f2a..20a6c149e4a 100644
--- a/drivers/led/led_gpio.c
+++ b/drivers/led/led_gpio.c
@@ -4,6 +4,7 @@
* Written by Simon Glass <sjg at chromium.org>
*/
+#include <cyclic.h>
#include <dm.h>
#include <errno.h>
#include <led.h>
@@ -13,13 +14,60 @@
struct led_gpio_priv {
struct gpio_desc gpio;
+#ifdef CONFIG_LED_GPIO_SW_BLINK
+ bool sw_blink;
+ struct cyclic_info cyclic;
+#endif
};
+#ifdef CONFIG_LED_GPIO_SW_BLINK
+static void gpio_led_toggle(struct cyclic_info *ctx)
+{
+ struct led_gpio_priv *priv = container_of(ctx, struct led_gpio_priv, cyclic);
+ struct gpio_desc *gpio = &priv->gpio;
+ int state;
+
+ state = dm_gpio_get_value(gpio);
+ if (state < 0) {
+ printf("Error getting value for GPIO %d\n",
+ gpio->offset);
+ return;
+ }
+
+ dm_gpio_set_value(gpio, !state);
+}
+
+static int gpio_led_set_period(struct udevice *dev, int period_ms)
+{
+ struct led_gpio_priv *priv = dev_get_priv(dev);
+ char cyclic_name[16];
+
+ if (priv->sw_blink)
+ cyclic_unregister(&priv->cyclic);
+
+ snprintf(cyclic_name, sizeof(cyclic_name),
+ "gpio_cyclic%u", priv->gpio.offset);
+ cyclic_register(&priv->cyclic, gpio_led_toggle,
+ period_ms * 500, cyclic_name);
+
+ /* Init the LED on */
+ dm_gpio_set_value(&priv->gpio, LEDST_ON);
+
+ priv->sw_blink = true;
+ return 0;
+}
+#endif
+
static int gpio_led_set_state(struct udevice *dev, enum led_state_t state)
{
struct led_gpio_priv *priv = dev_get_priv(dev);
int ret;
+#ifdef CONFIG_LED_GPIO_SW_BLINK
+ if (priv->sw_blink)
+ cyclic_unregister(&priv->cyclic);
+#endif
+
if (!dm_gpio_is_valid(&priv->gpio))
return -EREMOTEIO;
switch (state) {
@@ -50,6 +98,11 @@ static enum led_state_t gpio_led_get_state(struct udevice *dev)
if (ret < 0)
return ret;
+#ifdef CONFIG_LED_GPIO_SW_BLINK
+ if (priv->sw_blink)
+ return LEDST_BLINK;
+#endif
+
return ret ? LEDST_ON : LEDST_OFF;
}
@@ -84,6 +137,9 @@ static int led_gpio_bind(struct udevice *parent)
static const struct led_ops gpio_led_ops = {
.set_state = gpio_led_set_state,
.get_state = gpio_led_get_state,
+#ifdef CONFIG_LED_GPIO_SW_BLINK
+ .set_period = gpio_led_set_period,
+#endif
};
U_BOOT_DRIVER(led_gpio) = {
--
2.45.1
More information about the U-Boot
mailing list