From a712c3622d78101d34eb5823e12a2852986ba109 Mon Sep 17 00:00:00 2001 From: Marek Pieta Date: Tue, 20 Apr 2021 11:49:32 +0200 Subject: [PATCH] drivers: led: Add LED GPIO driver Change introduces LED GPIO driver. Signed-off-by: Marek Pieta --- drivers/led/CMakeLists.txt | 1 + drivers/led/Kconfig | 1 + drivers/led/Kconfig.gpio | 8 +++ drivers/led/led_gpio.c | 107 +++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 drivers/led/Kconfig.gpio create mode 100644 drivers/led/led_gpio.c diff --git a/drivers/led/CMakeLists.txt b/drivers/led/CMakeLists.txt index cdbb2a95d88..eed5e5b5304 100644 --- a/drivers/led/CMakeLists.txt +++ b/drivers/led/CMakeLists.txt @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources_ifdef(CONFIG_HT16K33 ht16k33.c) +zephyr_sources_ifdef(CONFIG_LED_GPIO led_gpio.c) zephyr_sources_ifdef(CONFIG_LED_PWM led_pwm.c) zephyr_sources_ifdef(CONFIG_LP3943 lp3943.c) zephyr_sources_ifdef(CONFIG_LP503X lp503x.c) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index d147a5f17cb..ab66a68a85b 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -26,6 +26,7 @@ config LED_SHELL help Enable LED shell for testing. +source "drivers/led/Kconfig.gpio" source "drivers/led/Kconfig.ht16k33" source "drivers/led/Kconfig.lp3943" source "drivers/led/Kconfig.lp503x" diff --git a/drivers/led/Kconfig.gpio b/drivers/led/Kconfig.gpio new file mode 100644 index 00000000000..72507a6831f --- /dev/null +++ b/drivers/led/Kconfig.gpio @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config LED_GPIO + bool "GPIO LED driver" + depends on GPIO && $(dt_compat_enabled,gpio-leds) + help + Enable driver for GPIO LEDs. diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c new file mode 100644 index 00000000000..025d5b9f878 --- /dev/null +++ b/drivers/led/led_gpio.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT gpio_leds + +/** + * @file + * @brief GPIO driven LEDs + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(led_gpio, CONFIG_LED_LOG_LEVEL); + +struct led_gpio_config { + size_t num_leds; + const struct gpio_dt_spec *led; +}; + + +static int led_gpio_set_brightness(const struct device *dev, uint32_t led, uint8_t value) +{ + + const struct led_gpio_config *config = dev->config; + const struct gpio_dt_spec *led_gpio; + + if ((led >= config->num_leds) || (value > 100)) { + return -EINVAL; + } + + led_gpio = &config->led[led]; + + return gpio_pin_set(led_gpio->port, led_gpio->pin, (value >= 50)); +} + +static int led_gpio_on(const struct device *dev, uint32_t led) +{ + return led_gpio_set_brightness(dev, led, 100); +} + +static int led_gpio_off(const struct device *dev, uint32_t led) +{ + return led_gpio_set_brightness(dev, led, 0); +} + +static int led_gpio_init(const struct device *dev) +{ + const struct led_gpio_config *config = dev->config; + int err = 0; + + if (!config->num_leds) { + LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name); + err = -ENODEV; + } + + for (size_t i = 0; (i < config->num_leds) && !err; i++) { + const struct gpio_dt_spec *led = &config->led[i]; + + if (device_is_ready(led->port)) { + err = gpio_pin_configure(led->port, led->pin, + led->dt_flags | GPIO_OUTPUT_INACTIVE); + + if (err) { + LOG_ERR("Cannot configure GPIO (err %d)", err); + } + } else { + LOG_ERR("%s: GPIO device not ready", dev->name); + err = -ENODEV; + } + } + + return err; +} + +static const struct led_driver_api led_gpio_api = { + .on = led_gpio_on, + .off = led_gpio_off, + .set_brightness = led_gpio_set_brightness, +}; + +#define LED_GPIO_DT_SPEC(led_node_id) \ + GPIO_DT_SPEC_GET(led_node_id, gpios), \ + +#define LED_GPIO_DEVICE(i) \ + \ +static const struct gpio_dt_spec gpio_dt_spec_##i[] = { \ + DT_INST_FOREACH_CHILD(i, LED_GPIO_DT_SPEC) \ +}; \ + \ +static const struct led_gpio_config led_gpio_config_##i = { \ + .num_leds = ARRAY_SIZE(gpio_dt_spec_##i), \ + .led = gpio_dt_spec_##i, \ +}; \ + \ +DEVICE_DT_INST_DEFINE(i, &led_gpio_init, device_pm_control_nop, \ + NULL, &led_gpio_config_##i, \ + POST_KERNEL, CONFIG_LED_INIT_PRIORITY, \ + &led_gpio_api); + +DT_INST_FOREACH_STATUS_OKAY(LED_GPIO_DEVICE)