From 4a77680894c3c47a1cb61c8790a8f1a36205b3b6 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Mon, 30 Jun 2025 11:39:36 +0200 Subject: [PATCH 1/5] drivers: led: pwm: automatically select PWM For all LED drivers, the underlying subsystem is automatically selected in Kconfig if their compatible node is found in DT. The only exception is the PWM LED driver which depends on PWM instead of selecting it. The PWM Kconfig option must be explicitely selected in order to have LED_PWM enabled. This patch updates the Kconfig of the PWM LED driver to have the same behavior as other LED drivers: PWM is now automatically selected if a "pwm-leds" compatible node is found in DT. Signed-off-by: Simon Guinot --- drivers/led/Kconfig.pwm | 3 ++- samples/drivers/led/pwm/prj.conf | 2 -- tests/drivers/build_all/led/prj.conf | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/led/Kconfig.pwm b/drivers/led/Kconfig.pwm index 8247df198b47..977a0c009f38 100644 --- a/drivers/led/Kconfig.pwm +++ b/drivers/led/Kconfig.pwm @@ -4,6 +4,7 @@ config LED_PWM bool "PWM LED driver" default y - depends on PWM && DT_HAS_PWM_LEDS_ENABLED + depends on DT_HAS_PWM_LEDS_ENABLED + select PWM help Enable driver for PWM LEDs. diff --git a/samples/drivers/led/pwm/prj.conf b/samples/drivers/led/pwm/prj.conf index b6286f0aa56a..547575b6dc9a 100644 --- a/samples/drivers/led/pwm/prj.conf +++ b/samples/drivers/led/pwm/prj.conf @@ -1,7 +1,5 @@ CONFIG_LOG=y -CONFIG_PWM=y - CONFIG_LED=y CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/tests/drivers/build_all/led/prj.conf b/tests/drivers/build_all/led/prj.conf index d3ea88e4d47f..ab827be3a48b 100644 --- a/tests/drivers/build_all/led/prj.conf +++ b/tests/drivers/build_all/led/prj.conf @@ -1,4 +1,3 @@ CONFIG_TEST=y CONFIG_TEST_USERSPACE=y CONFIG_LED=y -CONFIG_PWM=y From 2f25c1fccd0f80aa429ace153a495b2989ce8d0e Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Mon, 30 Jun 2025 15:54:35 +0200 Subject: [PATCH 2/5] dts: bindings: led: introduce led-node.yaml This patch moves the label and color-mapping LED property definitions from led-controller.yaml into led-node.yaml. This allows to use these properties from a LED node which is not a child node of a LED controller. This is preparatory work for adding the leds-group-multicolor binding. In addition this patch also removes the redundant "label" property definitions in gpio-leds.yaml and pwm-leds.yaml. It is now included from led-node.yaml. Signed-off-by: Simon Guinot --- dts/bindings/led/gpio-leds.yaml | 12 ++++++------ dts/bindings/led/led-controller.yaml | 19 +++---------------- dts/bindings/led/led-node.yaml | 25 +++++++++++++++++++++++++ dts/bindings/led/pwm-leds.yaml | 13 ++++++------- 4 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 dts/bindings/led/led-node.yaml diff --git a/dts/bindings/led/gpio-leds.yaml b/dts/bindings/led/gpio-leds.yaml index 3589b394c8c9..13206fc9e307 100644 --- a/dts/bindings/led/gpio-leds.yaml +++ b/dts/bindings/led/gpio-leds.yaml @@ -36,13 +36,13 @@ compatible: "gpio-leds" child-binding: description: GPIO LED child node + + include: + - name: led-node.yaml + property-allowlist: + - label + properties: gpios: type: phandle-array required: true - label: - type: string - description: | - Human readable string describing the LED. It can be used by an - application to identify this LED or to retrieve its number/index - (i.e. child node number) on the parent device. diff --git a/dts/bindings/led/led-controller.yaml b/dts/bindings/led/led-controller.yaml index 86aac36baf51..30deb0f8b2ae 100644 --- a/dts/bindings/led/led-controller.yaml +++ b/dts/bindings/led/led-controller.yaml @@ -5,10 +5,10 @@ child-binding: description: LED child node + + include: led-node.yaml + properties: - label: - type: string - description: Human readable string describing the LED index: type: int description: | @@ -17,16 +17,3 @@ child-binding: controller. For example, this allows to handle boards where the LEDs in an array/strip are not wired following the LED order of the controller. - color-mapping: - type: array - description: | - Channel to color mapping of a multicolor LED. If a LED supports - several colors, then the color-mapping property can be used to - describe how the hardware channels and the colors are mapped. - - For example the channel to color mapping of RGB LEDs would be - - color-mapping = - , - , - ; diff --git a/dts/bindings/led/led-node.yaml b/dts/bindings/led/led-node.yaml new file mode 100644 index 000000000000..cd5b66394f9b --- /dev/null +++ b/dts/bindings/led/led-node.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2025 Seagate Technology LLC +# SPDX-License-Identifier: Apache-2.0 + +# Common fields for LED nodes + +properties: + label: + type: string + description: | + Human readable string describing the LED. It can be used by an + application to identify this LED or to retrieve its number/index + (i.e. child node number) on the parent device. + color-mapping: + type: array + description: | + Channel to color mapping of a multicolor LED. If a LED supports + several colors, then the color-mapping property can be used to + describe how the hardware channels and the colors are mapped. + + For example the channel to color mapping of RGB LEDs would be + + color-mapping = + , + , + ; diff --git a/dts/bindings/led/pwm-leds.yaml b/dts/bindings/led/pwm-leds.yaml index c5619e038831..0394d34bb9fe 100644 --- a/dts/bindings/led/pwm-leds.yaml +++ b/dts/bindings/led/pwm-leds.yaml @@ -10,6 +10,12 @@ compatible: "pwm-leds" child-binding: description: PWM LED child node + + include: + - name: led-node.yaml + property-allowlist: + - label + properties: pwms: required: true @@ -22,10 +28,3 @@ child-binding: brigtness granularity) and lesser than 50 milliseconds (average visual persistence time of the human eye). Typical values for the PWM period are 10 or 20 milliseconds. - - label: - type: string - description: | - Human readable string describing the LED. It can be used by an - application to identify this LED or to retrieve its number/index - (i.e. child node number) on the parent device. From db55efa6c1b8112ec8664ca93a93156d51c7c029 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Fri, 22 Mar 2024 11:22:19 +0100 Subject: [PATCH 3/5] dts: bindings: led: introduce leds-group-multicolor binding The leds-group-multicolor binding allows to combines several monochromatic LEDs into one multi-color LED. Signed-off-by: Simon Guinot --- dts/bindings/led/leds-group-multicolor.yaml | 49 +++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 dts/bindings/led/leds-group-multicolor.yaml diff --git a/dts/bindings/led/leds-group-multicolor.yaml b/dts/bindings/led/leds-group-multicolor.yaml new file mode 100644 index 000000000000..4a6008b151d2 --- /dev/null +++ b/dts/bindings/led/leds-group-multicolor.yaml @@ -0,0 +1,49 @@ +# Copyright (c) 2025 Seagate Technology LLC +# SPDX-License-Identifier: Apache-2.0 + +title: Combines several monochromatic LEDs into one multi-color LED. + +description: | + Here is an example that defines an RGB LED with a group of monochromatic + PWM LEDs. Note that the pwms property definition handle depends on the PWM + controller model. In this example, an STM32 PWM controller is assumed. + + #include + + / { + monochromatic-leds { + compatible = "pwm-leds"; + + red_pwm_led: led-0 { + pwms = <&pwm1 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + + green_pwm_led: led-1 { + pwms = <&pwm2 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + + blue_pwm_led: led-2 { + pwms = <&pwm3 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + + rgb-led { + compatible = "leds-group-multicolor"; + + leds = <&red_pwm_led>, <&green_pwm_led>, <&blue_pwm_led>; + color-mapping = , + , + ; + }; + }; + +compatible: "leds-group-multicolor" + +include: led-node.yaml + +properties: + leds: + required: true + type: phandles + description: | + References to monochromatic LED nodes. From 051d6388fbe3ace47f41a55986d5bbbf8b6144f6 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Fri, 27 Jun 2025 16:54:59 +0200 Subject: [PATCH 4/5] drivers: led: add leds-group-multicolor driver This driver supports multi-color LEDs built with several monochromatic LEDs. ->set_color is the only LED driver API method implemented. Instead of calling led_set_brightness() for each monochromatic LED, led_set_color() can be called on the leds-group-multicolor device to set all colors at once. See the leds-group-multicolor DT binding for details. Signed-off-by: Simon Guinot --- drivers/led/CMakeLists.txt | 1 + drivers/led/Kconfig | 1 + drivers/led/Kconfig.leds-group-multicolor | 12 +++ drivers/led/leds_group_multicolor.c | 94 +++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 drivers/led/Kconfig.leds-group-multicolor create mode 100644 drivers/led/leds_group_multicolor.c diff --git a/drivers/led/CMakeLists.txt b/drivers/led/CMakeLists.txt index 1d8b9d2aa960..6cbfb493fdfd 100644 --- a/drivers/led/CMakeLists.txt +++ b/drivers/led/CMakeLists.txt @@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_HT16K33 ht16k33.c) zephyr_library_sources_ifdef(CONFIG_IS31FL3194 is31fl3194.c) zephyr_library_sources_ifdef(CONFIG_IS31FL3216A is31fl3216a.c) zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c) +zephyr_library_sources_ifdef(CONFIG_LEDS_GROUP_MULTICOLOR leds_group_multicolor.c) zephyr_library_sources_ifdef(CONFIG_LED_AXP192_AXP2101 led_axp192.c) zephyr_library_sources_ifdef(CONFIG_LED_DAC led_dac.c) zephyr_library_sources_ifdef(CONFIG_LED_GPIO led_gpio.c) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 0e411ce21f04..c9139846c344 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -34,6 +34,7 @@ source "drivers/led/Kconfig.ht16k33" source "drivers/led/Kconfig.is31fl3194" source "drivers/led/Kconfig.is31fl3216a" source "drivers/led/Kconfig.is31fl3733" +source "drivers/led/Kconfig.leds-group-multicolor" source "drivers/led/Kconfig.lp3943" source "drivers/led/Kconfig.lp50xx" source "drivers/led/Kconfig.lp5562" diff --git a/drivers/led/Kconfig.leds-group-multicolor b/drivers/led/Kconfig.leds-group-multicolor new file mode 100644 index 000000000000..9340c4547703 --- /dev/null +++ b/drivers/led/Kconfig.leds-group-multicolor @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Seagate Technology LLC +# SPDX-License-Identifier: Apache-2.0 + +config LEDS_GROUP_MULTICOLOR + bool "LEDs group multi-color driver" + default y + depends on DT_HAS_LEDS_GROUP_MULTICOLOR_ENABLED + help + Enable this driver to supports multi-color LEDs built with several + monochromatic LEDs. + + See the leds-group-multicolor DT binding for details. diff --git a/drivers/led/leds_group_multicolor.c b/drivers/led/leds_group_multicolor.c new file mode 100644 index 000000000000..f9613a02244d --- /dev/null +++ b/drivers/led/leds_group_multicolor.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025 Seagate Technology LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT leds_group_multicolor + +/** + * @file + * @brief Driver for multi-color LED built from monochromatic LEDs. + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(leds_group_multicolor, CONFIG_LED_LOG_LEVEL); + +struct leds_group_multicolor_config { + uint8_t num_leds; + const struct led_dt_spec *led; +}; + +static int leds_group_multicolor_set_color(const struct device *dev, uint32_t led, + uint8_t num_colors, const uint8_t *color) +{ + const struct leds_group_multicolor_config *config = dev->config; + + if (led != 0) { + return -EINVAL; + } + if (num_colors != config->num_leds) { + return -EINVAL; + } + + for (uint8_t i = 0; i < num_colors; i++) { + int err; + + err = led_set_brightness_dt(&config->led[i], color[i]); + if (err) { + return err; + } + } + + return 0; +} + +static int leds_group_multicolor_init(const struct device *dev) +{ + const struct leds_group_multicolor_config *config = dev->config; + + for (uint8_t i = 0; i < config->num_leds; i++) { + const struct led_dt_spec *led = &config->led[i]; + + if (!led_is_ready_dt(led)) { + LOG_ERR("%s: LED device %s is not ready", dev->name, led->dev->name); + return -ENODEV; + } + } + + return 0; +} + +static DEVICE_API(led, leds_group_multicolor_api) = { + .set_color = leds_group_multicolor_set_color, +}; + +#define LED_DT_SPEC_GET_BY_PHANDLE_IDX(node_id, prop, idx) \ + LED_DT_SPEC_GET(DT_PHANDLE_BY_IDX(node_id, prop, idx)) + +#define LEDS_GROUP_MULTICOLOR_DEVICE(inst) \ + \ + BUILD_ASSERT(DT_INST_PROP_LEN(inst, leds) > 0, \ + "at least one LED phandle must be present"); \ + \ + static const struct led_dt_spec led_group_multicolor_##inst[] = { \ + DT_INST_FOREACH_PROP_ELEM_SEP( \ + inst, leds, LED_DT_SPEC_GET_BY_PHANDLE_IDX, (,)) \ + }; \ + \ + static const struct leds_group_multicolor_config \ + leds_group_multicolor_config_##inst = { \ + .num_leds = ARRAY_SIZE(led_group_multicolor_##inst), \ + .led = led_group_multicolor_##inst, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &leds_group_multicolor_init, NULL, \ + NULL, &leds_group_multicolor_config_##inst, \ + POST_KERNEL, CONFIG_LED_INIT_PRIORITY, \ + &leds_group_multicolor_api); + +DT_INST_FOREACH_STATUS_OKAY(LEDS_GROUP_MULTICOLOR_DEVICE) From ab647ef6ee8a3295bb42b5564b55213d78f2c073 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Mon, 30 Jun 2025 19:54:25 +0200 Subject: [PATCH 5/5] tests: drivers: build_all: led: add leds-group-multicolor Add test for leds-group-multicolor driver. Signed-off-by: Simon Guinot --- tests/drivers/build_all/led/app.overlay | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/drivers/build_all/led/app.overlay b/tests/drivers/build_all/led/app.overlay index ce0e7ee4ad62..185ea95960b5 100644 --- a/tests/drivers/build_all/led/app.overlay +++ b/tests/drivers/build_all/led/app.overlay @@ -207,6 +207,14 @@ test_pwm_led0: test_pwm_led_0 { pwms = <&test_pwm 0 0 0>; }; + test_pwm_led1: test_pwm_led_1 { + pwms = <&test_pwm 1 0 0>; + }; + }; + + multi-led { + compatible = "leds-group-multicolor"; + leds = <&test_pwm_led0>, <&test_pwm_led1>; }; }; };