drivers: led: Add Onsemi ncp5623c driver
The controller and the driver support two hardware configurations: - one three-channel (RGB) LED - or three single-channel LEDs Signed-off-by: Peter van der Perk <peter.vanderperk@nxp.com>
This commit is contained in:
parent
28c139f653
commit
a095bd7328
6 changed files with 308 additions and 0 deletions
|
@ -14,6 +14,7 @@ zephyr_library_sources_ifdef(CONFIG_LP3943 lp3943.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_LP50XX lp50xx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LP5562 lp5562.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_LP5569 lp5569.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NCP5623 ncp5623.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_PCA9633 pca9633.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_TLC59108 tlc59108.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c)
|
||||
|
|
|
@ -33,6 +33,7 @@ source "drivers/led/Kconfig.lp3943"
|
|||
source "drivers/led/Kconfig.lp50xx"
|
||||
source "drivers/led/Kconfig.lp5562"
|
||||
source "drivers/led/Kconfig.lp5569"
|
||||
source "drivers/led/Kconfig.ncp5623"
|
||||
source "drivers/led/Kconfig.npm1300"
|
||||
source "drivers/led/Kconfig.pca9633"
|
||||
source "drivers/led/Kconfig.pwm"
|
||||
|
|
14
drivers/led/Kconfig.ncp5623
Normal file
14
drivers/led/Kconfig.ncp5623
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Copyright (c) 2023 NXP Semiconductors
|
||||
# Copyright (c) 2023 Cognipilot Foundation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config NCP5623
|
||||
bool "NCP5623 LED driver"
|
||||
default y
|
||||
depends on DT_HAS_ONNN_NCP5623_ENABLED
|
||||
select I2C
|
||||
help
|
||||
Enable driver for the Onsemi NCP5623 I2C LED controller.
|
||||
The controller and the driver support two hardware configurations:
|
||||
- one three-channel (RGB) LED
|
||||
- or three single-channel LEDs
|
219
drivers/led/ncp5623.c
Normal file
219
drivers/led/ncp5623.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (c) 2023 NXP Semiconductors
|
||||
* Copyright (c) 2023 Cognipilot Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT onnn_ncp5623
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief NCP5623 LED driver
|
||||
*
|
||||
* The NCP5623 is a 3-channel LED driver that communicates over I2C.
|
||||
*/
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/drivers/led.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(ncp5623, CONFIG_LED_LOG_LEVEL);
|
||||
|
||||
#define NCP5623_LED_CURRENT 0x20
|
||||
#define NCP5623_LED_PWM0 0x40
|
||||
#define NCP5623_LED_PWM1 0x60
|
||||
#define NCP5623_LED_PWM2 0x80
|
||||
|
||||
#define NCP5623_CHANNEL_COUNT 3
|
||||
|
||||
/* Brightness limits */
|
||||
#define NCP5623_MIN_BRIGHTNESS 0
|
||||
#define NCP5623_MAX_BRIGHTNESS 0x1f
|
||||
|
||||
static const uint8_t led_channels[] = {NCP5623_LED_PWM0, NCP5623_LED_PWM1, NCP5623_LED_PWM2};
|
||||
|
||||
struct ncp5623_config {
|
||||
struct i2c_dt_spec bus;
|
||||
uint8_t num_leds;
|
||||
const struct led_info *leds_info;
|
||||
};
|
||||
|
||||
static const struct led_info *ncp5623_led_to_info(const struct ncp5623_config *config, uint32_t led)
|
||||
{
|
||||
if (led < config->num_leds) {
|
||||
return &config->leds_info[led];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int ncp5623_get_info(const struct device *dev, uint32_t led, const struct led_info **info)
|
||||
{
|
||||
const struct ncp5623_config *config = dev->config;
|
||||
const struct led_info *led_info = ncp5623_led_to_info(config, led);
|
||||
|
||||
if (!led_info) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*info = led_info;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ncp5623_set_color(const struct device *dev, uint32_t led, uint8_t num_colors,
|
||||
const uint8_t *color)
|
||||
{
|
||||
const struct ncp5623_config *config = dev->config;
|
||||
const struct led_info *led_info = ncp5623_led_to_info(config, led);
|
||||
uint8_t buf[6] = {0x70, NCP5623_LED_PWM0, 0x70, NCP5623_LED_PWM1, 0x70, NCP5623_LED_PWM2};
|
||||
|
||||
if (!led_info) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (led_info->num_colors != 3) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
if (num_colors != 3) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf[1] = buf[1] | color[0] / 8;
|
||||
buf[3] = buf[3] | color[1] / 8;
|
||||
buf[5] = buf[5] | color[2] / 8;
|
||||
|
||||
return i2c_burst_write_dt(&config->bus, NCP5623_LED_CURRENT | NCP5623_MAX_BRIGHTNESS, buf,
|
||||
sizeof(buf));
|
||||
}
|
||||
|
||||
static int ncp5623_set_brightness(const struct device *dev, uint32_t led, uint8_t value)
|
||||
{
|
||||
const struct ncp5623_config *config = dev->config;
|
||||
const struct led_info *led_info = ncp5623_led_to_info(config, led);
|
||||
int ret = 0;
|
||||
|
||||
if (!led_info) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (value > 100) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (led_info->num_colors != 1) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Rescale 0..100 to 0..31 */
|
||||
value = value * NCP5623_MAX_BRIGHTNESS / 100;
|
||||
|
||||
ret = i2c_reg_write_byte_dt(&config->bus, led_channels[led] | value, 0x70);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERR("%s: LED write failed", dev->name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int ncp5623_led_on(const struct device *dev, uint32_t led)
|
||||
{
|
||||
return ncp5623_set_brightness(dev, led, 100);
|
||||
}
|
||||
|
||||
static inline int ncp5623_led_off(const struct device *dev, uint32_t led)
|
||||
{
|
||||
return ncp5623_set_brightness(dev, led, 0);
|
||||
}
|
||||
|
||||
static int ncp5623_led_init(const struct device *dev)
|
||||
{
|
||||
const struct ncp5623_config *config = dev->config;
|
||||
const struct led_info *led_info = NULL;
|
||||
int i;
|
||||
uint8_t buf[6] = {0x70, NCP5623_LED_PWM0, 0x70, NCP5623_LED_PWM1, 0x70, NCP5623_LED_PWM2};
|
||||
|
||||
if (!i2c_is_ready_dt(&config->bus)) {
|
||||
LOG_ERR("%s: I2C device not ready", dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (config->num_leds == 1) { /* one three-channel (RGB) LED */
|
||||
led_info = ncp5623_led_to_info(config, 0);
|
||||
|
||||
if (!led_info) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (led_info->num_colors != 3 || led_info->num_colors != 1) {
|
||||
LOG_ERR("%s: invalid number of colors %d (must be %d or 1)", dev->name,
|
||||
led_info->num_colors, NCP5623_CHANNEL_COUNT);
|
||||
}
|
||||
} else if (config->num_leds <= 3) { /* three single-channel LEDs */
|
||||
for (i = 0; i < config->num_leds; i++) {
|
||||
led_info = ncp5623_led_to_info(config, 0);
|
||||
|
||||
if (!led_info) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (led_info->num_colors > 1) {
|
||||
LOG_ERR("%s: invalid number of colors %d (must be 1 when defining "
|
||||
"multiple leds)",
|
||||
dev->name, led_info->num_colors);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_ERR("%s: invalid number of leds %d (max %d)", dev->name, config->num_leds,
|
||||
NCP5623_CHANNEL_COUNT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (i2c_burst_write_dt(&config->bus, NCP5623_LED_CURRENT | NCP5623_MAX_BRIGHTNESS, buf,
|
||||
6)) {
|
||||
LOG_ERR("%s: LED write failed", dev->name);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct led_driver_api ncp5623_led_api = {
|
||||
.set_brightness = ncp5623_set_brightness,
|
||||
.on = ncp5623_led_on,
|
||||
.off = ncp5623_led_off,
|
||||
.get_info = ncp5623_get_info,
|
||||
.set_color = ncp5623_set_color,
|
||||
};
|
||||
|
||||
#define COLOR_MAPPING(led_node_id) \
|
||||
static const uint8_t color_mapping_##led_node_id[] = DT_PROP(led_node_id, color_mapping);
|
||||
|
||||
#define LED_INFO(led_node_id) \
|
||||
{ \
|
||||
.label = DT_PROP(led_node_id, label), \
|
||||
.index = DT_PROP(led_node_id, index), \
|
||||
.num_colors = DT_PROP_LEN(led_node_id, color_mapping), \
|
||||
.color_mapping = color_mapping_##led_node_id, \
|
||||
},
|
||||
|
||||
#define NCP5623_DEFINE(id) \
|
||||
\
|
||||
DT_INST_FOREACH_CHILD(id, COLOR_MAPPING) \
|
||||
\
|
||||
static const struct led_info ncp5623_leds_##id[] = {DT_INST_FOREACH_CHILD(id, LED_INFO)}; \
|
||||
\
|
||||
static const struct ncp5623_config ncp5623_config_##id = { \
|
||||
.bus = I2C_DT_SPEC_INST_GET(id), \
|
||||
.num_leds = ARRAY_SIZE(ncp5623_leds_##id), \
|
||||
.leds_info = ncp5623_leds_##id, \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(id, &ncp5623_led_init, NULL, NULL, &ncp5623_config_##id, \
|
||||
POST_KERNEL, CONFIG_LED_INIT_PRIORITY, &ncp5623_led_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(NCP5623_DEFINE)
|
68
dts/bindings/led/onnn,ncp5623.yaml
Normal file
68
dts/bindings/led/onnn,ncp5623.yaml
Normal file
|
@ -0,0 +1,68 @@
|
|||
# Copyright (c) 2023 NXP Semiconductors
|
||||
# Copyright (c) 2023 Congipilot Foundation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
NCP5623 Triple Output I2C Controlled RGB LED driver
|
||||
|
||||
The LED_SHELL application can be used for testing
|
||||
|
||||
The following example defines a single RGB LED in the ncp5623 DT node
|
||||
|
||||
ncp5623c@39 {
|
||||
compatible = "onnn,ncp5623";
|
||||
reg = <0x39>;
|
||||
|
||||
led_0 {
|
||||
label = "RGB LED";
|
||||
index = <0>;
|
||||
color-mapping =
|
||||
<LED_COLOR_ID_RED>,
|
||||
<LED_COLOR_ID_GREEN>,
|
||||
<LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
The following example defines three single-channel LEDs in the ncp5623 DT node
|
||||
|
||||
ncp5623c@39 {
|
||||
compatible = "onnn,ncp5623";
|
||||
reg = <0x39>;
|
||||
|
||||
led_0 {
|
||||
label = "RED LED";
|
||||
index = <0>;
|
||||
color-mapping =
|
||||
<LED_COLOR_ID_RED>;
|
||||
};
|
||||
|
||||
led_1 {
|
||||
label = "GREEN LED";
|
||||
index = <1>;
|
||||
color-mapping =
|
||||
<LED_COLOR_ID_GREEN>;
|
||||
};
|
||||
|
||||
led_2 {
|
||||
label = "BLUE LED";
|
||||
index = <2>;
|
||||
color-mapping =
|
||||
<LED_COLOR_ID_BLUE>;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
compatible: "onnn,ncp5623"
|
||||
|
||||
include: ["i2c-device.yaml", "led-controller.yaml"]
|
||||
|
||||
child-binding:
|
||||
properties:
|
||||
label:
|
||||
required: true
|
||||
|
||||
index:
|
||||
required: true
|
||||
|
||||
color-mapping:
|
||||
required: true
|
|
@ -99,6 +99,11 @@
|
|||
compatible = "ti,tlc59108";
|
||||
reg = <0xc>;
|
||||
};
|
||||
|
||||
ncp5623@d {
|
||||
compatible = "onnn,ncp5623";
|
||||
reg = <0xd>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue