drivers: led: lp50xx: add enable gpio
Some boards may have connected the enable pin of the chipset to a GPIO. On these boards, it is necessary to configure and set this GPIO before using the chipset, otherwise the I2C circuitry is disabled. Based on initial work from: - Marek Janus <marek.janus@grinn-global.com> - Rico Ganahl <rico.ganahl@bytesatwork.ch> Signed-off-by: Mathieu Anquetin <mathieu.anquetin@groupe-cahors.com>
This commit is contained in:
parent
3c1b4d0a1f
commit
8807930248
2 changed files with 69 additions and 5 deletions
|
@ -12,6 +12,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <zephyr/device.h>
|
#include <zephyr/device.h>
|
||||||
#include <zephyr/devicetree.h>
|
#include <zephyr/devicetree.h>
|
||||||
|
#include <zephyr/drivers/gpio.h>
|
||||||
#include <zephyr/drivers/i2c.h>
|
#include <zephyr/drivers/i2c.h>
|
||||||
#include <zephyr/drivers/led.h>
|
#include <zephyr/drivers/led.h>
|
||||||
#include <zephyr/drivers/led/lp50xx.h>
|
#include <zephyr/drivers/led/lp50xx.h>
|
||||||
|
@ -42,6 +43,9 @@ LOG_MODULE_REGISTER(lp50xx, CONFIG_LED_LOG_LEVEL);
|
||||||
#define LP50XX_MAX_CHANNELS(nmodules) \
|
#define LP50XX_MAX_CHANNELS(nmodules) \
|
||||||
((LP50XX_COLORS_PER_LED + 1) * ((nmodules) + 1))
|
((LP50XX_COLORS_PER_LED + 1) * ((nmodules) + 1))
|
||||||
|
|
||||||
|
#define LP50XX_DISABLE_DELAY_US 3
|
||||||
|
#define LP50XX_ENABLE_DELAY_US 500
|
||||||
|
|
||||||
/* Base registers */
|
/* Base registers */
|
||||||
#define LP50XX_DEVICE_CONFIG0 0x00
|
#define LP50XX_DEVICE_CONFIG0 0x00
|
||||||
#define LP50XX_DEVICE_CONFIG1 0x01
|
#define LP50XX_DEVICE_CONFIG1 0x01
|
||||||
|
@ -73,6 +77,7 @@ LOG_MODULE_REGISTER(lp50xx, CONFIG_LED_LOG_LEVEL);
|
||||||
|
|
||||||
struct lp50xx_config {
|
struct lp50xx_config {
|
||||||
struct i2c_dt_spec bus;
|
struct i2c_dt_spec bus;
|
||||||
|
const struct gpio_dt_spec gpio_enable;
|
||||||
uint8_t num_modules;
|
uint8_t num_modules;
|
||||||
uint8_t max_leds;
|
uint8_t max_leds;
|
||||||
uint8_t num_leds;
|
uint8_t num_leds;
|
||||||
|
@ -233,10 +238,41 @@ static int lp50xx_reset(const struct device *dev)
|
||||||
return i2c_write_dt(&config->bus, buf, 2);
|
return i2c_write_dt(&config->bus, buf, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lp50xx_hw_enable(const struct device *dev, bool enable)
|
||||||
|
{
|
||||||
|
const struct lp50xx_config *config = dev->config;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (config->gpio_enable.port == NULL) {
|
||||||
|
/* Nothing to do */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gpio_pin_set_dt(&config->gpio_enable, enable);
|
||||||
|
if (err < 0) {
|
||||||
|
LOG_ERR("%s: failed to set enable gpio", dev->name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_usleep(enable ? LP50XX_ENABLE_DELAY_US : LP50XX_DISABLE_DELAY_US);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lp50xx_enable(const struct device *dev, bool enable)
|
||||||
|
{
|
||||||
|
const struct lp50xx_config *config = dev->config;
|
||||||
|
uint8_t value = enable ? CONFIG0_CHIP_EN : 0;
|
||||||
|
|
||||||
|
return i2c_reg_update_byte_dt(&config->bus,
|
||||||
|
LP50XX_DEVICE_CONFIG0,
|
||||||
|
CONFIG0_CHIP_EN,
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
|
||||||
static int lp50xx_init(const struct device *dev)
|
static int lp50xx_init(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct lp50xx_config *config = dev->config;
|
const struct lp50xx_config *config = dev->config;
|
||||||
uint8_t buf[3];
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!i2c_is_ready_dt(&config->bus)) {
|
if (!i2c_is_ready_dt(&config->bus)) {
|
||||||
|
@ -252,6 +288,29 @@ static int lp50xx_init(const struct device *dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Configure GPIO if present */
|
||||||
|
if (config->gpio_enable.port != NULL) {
|
||||||
|
if (!gpio_is_ready_dt(&config->gpio_enable)) {
|
||||||
|
LOG_ERR("%s: enable gpio is not ready", dev->name);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gpio_pin_configure_dt(&config->gpio_enable,
|
||||||
|
GPIO_OUTPUT_INACTIVE);
|
||||||
|
if (err < 0) {
|
||||||
|
LOG_ERR("%s: failed to initialize enable gpio",
|
||||||
|
dev->name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable hardware */
|
||||||
|
err = lp50xx_hw_enable(dev, true);
|
||||||
|
if (err < 0) {
|
||||||
|
LOG_ERR("%s: failed to enable hardware", dev->name);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset device */
|
/* Reset device */
|
||||||
err = lp50xx_reset(dev);
|
err = lp50xx_reset(dev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
@ -259,11 +318,10 @@ static int lp50xx_init(const struct device *dev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable LED controller. */
|
/* Enable device */
|
||||||
buf[0] = LP50XX_DEVICE_CONFIG0;
|
err = lp50xx_enable(dev, true);
|
||||||
buf[1] = CONFIG0_CHIP_EN;
|
|
||||||
err = i2c_write_dt(&config->bus, buf, 2);
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
|
LOG_ERR("%s: failed to enable", dev->name);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +359,8 @@ static const struct led_driver_api lp50xx_led_api = {
|
||||||
\
|
\
|
||||||
static const struct lp50xx_config lp##id##_config_##n = { \
|
static const struct lp50xx_config lp##id##_config_##n = { \
|
||||||
.bus = I2C_DT_SPEC_INST_GET(n), \
|
.bus = I2C_DT_SPEC_INST_GET(n), \
|
||||||
|
.gpio_enable = \
|
||||||
|
GPIO_DT_SPEC_INST_GET_OR(n, enable_gpios, {0}), \
|
||||||
.num_modules = nmodules, \
|
.num_modules = nmodules, \
|
||||||
.max_leds = LP##id##_MAX_LEDS, \
|
.max_leds = LP##id##_MAX_LEDS, \
|
||||||
.num_leds = ARRAY_SIZE(lp##id##_leds_##n), \
|
.num_leds = ARRAY_SIZE(lp##id##_leds_##n), \
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
include: ["i2c-device.yaml", "led-controller.yaml"]
|
include: ["i2c-device.yaml", "led-controller.yaml"]
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
|
enable-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
description: |
|
||||||
|
GPIO to use to enable/disable the controller.
|
||||||
max_curr_opt:
|
max_curr_opt:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: |
|
description: |
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue