1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #define DT_DRV_COMPAT nordic_npm1300_led
7
8 #include <errno.h>
9
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/led.h>
12 #include <zephyr/drivers/mfd/npm1300.h>
13
14 /* nPM1300 LED base address */
15 #define NPM_LED_BASE 0x0AU
16
17 /* nPM1300 LED register offsets */
18 #define NPM_LED_OFFSET_MODE 0x00U
19 #define NPM_LED_OFFSET_SET 0x03U
20 #define NPM_LED_OFFSET_CLR 0x04U
21
22 /* nPM1300 Channel counts */
23 #define NPM1300_LED_PINS 3U
24
25 /* nPM1300 LED modes */
26 #define NPM_LED_HOST 2U
27
28 struct led_npm1300_config {
29 const struct device *mfd;
30 uint8_t mode[NPM1300_LED_PINS];
31 };
32
led_npm1300_on(const struct device * dev,uint32_t led)33 static int led_npm1300_on(const struct device *dev, uint32_t led)
34 {
35 const struct led_npm1300_config *config = dev->config;
36
37 if (led >= NPM1300_LED_PINS) {
38 return -EINVAL;
39 }
40
41 if (config->mode[led] != NPM_LED_HOST) {
42 return -EPERM;
43 }
44
45 return mfd_npm1300_reg_write(config->mfd, NPM_LED_BASE, NPM_LED_OFFSET_SET + (led * 2U),
46 1U);
47 }
48
led_npm1300_off(const struct device * dev,uint32_t led)49 static int led_npm1300_off(const struct device *dev, uint32_t led)
50 {
51 const struct led_npm1300_config *config = dev->config;
52
53 if (led >= NPM1300_LED_PINS) {
54 return -EINVAL;
55 }
56
57 if (config->mode[led] != NPM_LED_HOST) {
58 return -EPERM;
59 }
60
61 return mfd_npm1300_reg_write(config->mfd, NPM_LED_BASE, NPM_LED_OFFSET_CLR + (led * 2U),
62 1U);
63 }
64
65 static const struct led_driver_api led_npm1300_api = {
66 .on = led_npm1300_on,
67 .off = led_npm1300_off,
68 };
69
led_npm1300_init(const struct device * dev)70 static int led_npm1300_init(const struct device *dev)
71 {
72 const struct led_npm1300_config *config = dev->config;
73
74 if (!device_is_ready(config->mfd)) {
75 return -ENODEV;
76 }
77
78 for (uint8_t led = 0U; led < NPM1300_LED_PINS; led++) {
79 int ret = mfd_npm1300_reg_write(config->mfd, NPM_LED_BASE,
80 NPM_LED_OFFSET_MODE + led, config->mode[led]);
81
82 if (ret < 0) {
83 return ret;
84 }
85 }
86
87 return 0;
88 }
89
90 #define LED_NPM1300_DEFINE(n) \
91 static const struct led_npm1300_config led_npm1300_config##n = { \
92 .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \
93 .mode = {DT_INST_ENUM_IDX(n, nordic_led0_mode), \
94 DT_INST_ENUM_IDX(n, nordic_led1_mode), \
95 DT_INST_ENUM_IDX(n, nordic_led2_mode)}}; \
96 \
97 DEVICE_DT_INST_DEFINE(n, &led_npm1300_init, NULL, NULL, &led_npm1300_config##n, \
98 POST_KERNEL, CONFIG_LED_INIT_PRIORITY, &led_npm1300_api);
99
100 DT_INST_FOREACH_STATUS_OKAY(LED_NPM1300_DEFINE)
101