1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT gpio_leds
8
9 /**
10 * @file
11 * @brief GPIO driven LEDs
12 */
13
14 #include <zephyr/drivers/led.h>
15 #include <zephyr/drivers/gpio.h>
16 #include <zephyr/device.h>
17 #include <zephyr/kernel.h>
18
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(led_gpio, CONFIG_LED_LOG_LEVEL);
21
22 struct led_gpio_config {
23 size_t num_leds;
24 const struct gpio_dt_spec *led;
25 };
26
led_gpio_set_brightness(const struct device * dev,uint32_t led,uint8_t value)27 static int led_gpio_set_brightness(const struct device *dev, uint32_t led, uint8_t value)
28 {
29
30 const struct led_gpio_config *config = dev->config;
31 const struct gpio_dt_spec *led_gpio;
32
33 if ((led >= config->num_leds) || (value > 100)) {
34 return -EINVAL;
35 }
36
37 led_gpio = &config->led[led];
38
39 return gpio_pin_set_dt(led_gpio, value > 0);
40 }
41
led_gpio_on(const struct device * dev,uint32_t led)42 static int led_gpio_on(const struct device *dev, uint32_t led)
43 {
44 return led_gpio_set_brightness(dev, led, 100);
45 }
46
led_gpio_off(const struct device * dev,uint32_t led)47 static int led_gpio_off(const struct device *dev, uint32_t led)
48 {
49 return led_gpio_set_brightness(dev, led, 0);
50 }
51
led_gpio_init(const struct device * dev)52 static int led_gpio_init(const struct device *dev)
53 {
54 const struct led_gpio_config *config = dev->config;
55 int err = 0;
56
57 if (!config->num_leds) {
58 LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name);
59 err = -ENODEV;
60 }
61
62 for (size_t i = 0; (i < config->num_leds) && !err; i++) {
63 const struct gpio_dt_spec *led = &config->led[i];
64
65 if (device_is_ready(led->port)) {
66 err = gpio_pin_configure_dt(led, GPIO_OUTPUT_INACTIVE);
67
68 if (err) {
69 LOG_ERR("Cannot configure GPIO (err %d)", err);
70 }
71 } else {
72 LOG_ERR("%s: GPIO device not ready", dev->name);
73 err = -ENODEV;
74 }
75 }
76
77 return err;
78 }
79
80 static const struct led_driver_api led_gpio_api = {
81 .on = led_gpio_on,
82 .off = led_gpio_off,
83 .set_brightness = led_gpio_set_brightness,
84 };
85
86 #define LED_GPIO_DEVICE(i) \
87 \
88 static const struct gpio_dt_spec gpio_dt_spec_##i[] = { \
89 DT_INST_FOREACH_CHILD_SEP_VARGS(i, GPIO_DT_SPEC_GET, (,), gpios) \
90 }; \
91 \
92 static const struct led_gpio_config led_gpio_config_##i = { \
93 .num_leds = ARRAY_SIZE(gpio_dt_spec_##i), \
94 .led = gpio_dt_spec_##i, \
95 }; \
96 \
97 DEVICE_DT_INST_DEFINE(i, &led_gpio_init, NULL, \
98 NULL, &led_gpio_config_##i, \
99 POST_KERNEL, CONFIG_LED_INIT_PRIORITY, \
100 &led_gpio_api);
101
102 DT_INST_FOREACH_STATUS_OKAY(LED_GPIO_DEVICE)
103