From 1471c2f81430fd0a381c37d263a4d0ff966e0cb4 Mon Sep 17 00:00:00 2001 From: Anuj Pathak Date: Tue, 27 Aug 2024 09:30:41 +0530 Subject: [PATCH] drivers: led: lp5562: Add PM Device support - Add PM_DEVICE support for power management Signed-off-by: Anuj Pathak --- drivers/led/lp5562.c | 62 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/drivers/led/lp5562.c b/drivers/led/lp5562.c index 751f94454f0..3ad3773c0de 100644 --- a/drivers/led/lp5562.c +++ b/drivers/led/lp5562.c @@ -35,6 +35,7 @@ #include #include #include +#include #define LOG_LEVEL CONFIG_LED_LOG_LEVEL #include @@ -937,7 +938,7 @@ static int lp5562_led_update_current(const struct device *dev) return ret; } -static int lp5562_enable(const struct device *dev) +static int lp5562_enable(const struct device *dev, bool soft_reset) { const struct lp5562_config *config = dev->config; const struct gpio_dt_spec *enable_gpio = &config->enable_gpio; @@ -958,11 +959,13 @@ static int lp5562_enable(const struct device *dev) k_sleep(K_MSEC(1)); } - /* Reset all internal registers to have a deterministic state. */ - err = i2c_reg_write_byte_dt(&config->bus, LP5562_RESET, 0xFF); - if (err) { - LOG_ERR("%s: failed to soft-reset device", dev->name); - return err; + if (soft_reset) { + /* Reset all internal registers to have a deterministic state. */ + err = i2c_reg_write_byte_dt(&config->bus, LP5562_RESET, 0xFF); + if (err) { + LOG_ERR("%s: failed to soft-reset device", dev->name); + return err; + } } /* Set en bit in LP5562_ENABLE register. */ @@ -977,6 +980,33 @@ static int lp5562_enable(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE +static int lp5562_disable(const struct device *dev) +{ + const struct lp5562_config *config = dev->config; + const struct gpio_dt_spec *enable_gpio = &config->enable_gpio; + int err = 0; + + /* clear en bit in register configurations */ + err = i2c_reg_update_byte_dt(&config->bus, LP5562_ENABLE, LP5562_ENABLE_CHIP_EN_MASK, + LP5562_ENABLE_CHIP_EN_CLR); + if (err) { + LOG_ERR("%s: failed to clear EN Bit in ENABLE register", dev->name); + return err; + } + + /* if gpio control is enabled, we can de-assert EN_GPIO now */ + if (enable_gpio->port != NULL) { + err = gpio_pin_set_dt(enable_gpio, 0); + if (err) { + LOG_ERR("%s: failed to set enable GPIO to 0", dev->name); + return err; + } + } + return 0; +} +#endif + static int lp5562_led_init(const struct device *dev) { const struct lp5562_config *config = dev->config; @@ -1001,7 +1031,7 @@ static int lp5562_led_init(const struct device *dev) return -ENODEV; } - ret = lp5562_enable(dev); + ret = lp5562_enable(dev, true); if (ret) { return ret; } @@ -1045,6 +1075,20 @@ static const struct led_driver_api lp5562_led_api = { .off = lp5562_led_off, }; +#ifdef CONFIG_PM_DEVICE +static int lp5562_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + return lp5562_disable(dev); + case PM_DEVICE_ACTION_RESUME: + return lp5562_enable(dev, false); + default: + return -ENOTSUP; + } +} +#endif /* CONFIG_PM_DEVICE */ + #define LP5562_DEFINE(id) \ BUILD_ASSERT(DT_INST_PROP(id, red_output_current) <= LP5562_MAX_CURRENT_SETTING,\ "Red channel current must be between 0 and 25.5 mA."); \ @@ -1063,8 +1107,10 @@ static const struct led_driver_api lp5562_led_api = { .enable_gpio = GPIO_DT_SPEC_INST_GET_OR(id, enable_gpios, {0}), \ }; \ \ + PM_DEVICE_DT_INST_DEFINE(id, lp5562_pm_action); \ + \ struct lp5562_data lp5562_data_##id; \ - DEVICE_DT_INST_DEFINE(id, &lp5562_led_init, NULL, \ + DEVICE_DT_INST_DEFINE(id, &lp5562_led_init, PM_DEVICE_DT_INST_GET(id), \ &lp5562_data_##id, \ &lp5562_config_##id, POST_KERNEL, \ CONFIG_LED_INIT_PRIORITY, \