drivers: bbled: pwm: mchp: BBLED low power mode updated

Updated the driver to support low power mode.
Introduced "enable-low-power" flag in device tree to
control(on/off) low power mode.

If flag added in DTS, during sleep BBLED will switch off the LEDs.
Otherwise BBLED will continue the configured blinking pattern on LEDs.

Signed-off-by: Manimaran A <manimaran.a@microchip.com>
This commit is contained in:
Manimaran A 2023-05-31 19:42:06 +05:30 committed by Carles Cufí
parent f907f9592d
commit b4cd531e2c
2 changed files with 85 additions and 4 deletions

View file

@ -18,6 +18,7 @@
#endif
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/logging/log.h>
#include <zephyr/pm/device.h>
#include <soc.h>
@ -104,6 +105,7 @@ LOG_MODULE_REGISTER(pwmbbled_mchp_xec, CONFIG_PWM_LOG_LEVEL);
#define XEC_PWM_BBLED_CLKSEL_1 XEC_PWM_BBLED_CLKSEL_PCR_SLOW
#define XEC_PWM_BBLED_CLKSEL_2 XEC_PWM_BBLED_CLKSEL_AHB_48M
struct bbled_regs {
volatile uint32_t config;
volatile uint32_t limits;
@ -118,12 +120,17 @@ struct bbled_regs {
struct pwm_bbled_xec_config {
struct bbled_regs * const regs;
const struct pinctrl_dev_config *pcfg;
uint8_t girq;
uint8_t girq_pos;
uint8_t pcr_idx;
uint8_t pcr_pos;
uint8_t clk_sel;
const struct pinctrl_dev_config *pcfg;
bool enable_low_power_32K;
};
struct bbled_xec_data {
uint32_t config;
};
/* Compute BBLED PWM delay factor to produce requested frequency.
@ -318,6 +325,63 @@ static int pwm_bbled_xec_get_cycles_per_sec(const struct device *dev,
return 0;
}
#ifdef CONFIG_PM_DEVICE
static int pwm_bbled_xec_pm_action(const struct device *dev, enum pm_device_action action)
{
const struct pwm_bbled_xec_config *const devcfg = dev->config;
struct bbled_regs * const regs = devcfg->regs;
struct bbled_xec_data * const data = dev->data;
int ret = 0;
/* 32K core clock is not gated by PCR in sleep, so BBLED can blink the LED even
* in sleep, if it is configured to use 32K clock. If we want to control it
* we shall use flag "enable_low_power_32K".
* This flag dont have effect on 48M clock. Since it is gated by PCR in sleep, BBLED
* will not get clock during sleep.
*/
if ((!devcfg->enable_low_power_32K) &&
(!(regs->config & BIT(XEC_PWM_BBLED_CFG_CLK_SRC_48M_POS)))) {
return ret;
}
switch (action) {
case PM_DEVICE_ACTION_RESUME:
ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_DEFAULT);
if (ret != 0) {
LOG_ERR("XEC BBLED pinctrl setup failed (%d)", ret);
}
/* Turn on BBLED only if it is ON before sleep */
if ((data->config & XEC_PWM_BBLED_CFG_MODE_MSK) != XEC_PWM_BBLED_CFG_MODE_OFF) {
regs->config |= (data->config & XEC_PWM_BBLED_CFG_MODE_MSK);
regs->config |= BIT(XEC_PWM_BBLED_CFG_EN_UPDATE_POS);
data->config = XEC_PWM_BBLED_CFG_MODE_OFF;
}
break;
case PM_DEVICE_ACTION_SUSPEND:
if ((regs->config & XEC_PWM_BBLED_CFG_MODE_MSK) != XEC_PWM_BBLED_CFG_MODE_OFF) {
/* Do copy first, then clear mode. */
data->config = regs->config;
regs->config &= ~(XEC_PWM_BBLED_CFG_MODE_MSK);
}
ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_SLEEP);
/* pinctrl-1 does not exist. */
if (ret == -ENOENT) {
ret = 0;
}
break;
default:
ret = -ENOTSUP;
}
return ret;
}
#endif /* CONFIG_PM_DEVICE */
static const struct pwm_driver_api pwm_bbled_xec_driver_api = {
.set_cycles = pwm_bbled_xec_set_cycles,
.get_cycles_per_sec = pwm_bbled_xec_get_cycles_per_sec,
@ -355,19 +419,24 @@ static int pwm_bbled_xec_init(const struct device *dev)
.girq_pos = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 1)), \
.pcr_idx = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 0), \
.pcr_pos = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 1), \
.clk_sel = UTIL_CAT(XEC_PWM_BBLED_CLKSEL_, XEC_PWM_BBLED_CLKSEL(n)), \
.clk_sel = UTIL_CAT(XEC_PWM_BBLED_CLKSEL_, XEC_PWM_BBLED_CLKSEL(inst)), \
.enable_low_power_32K = DT_INST_PROP(inst, enable_low_power_32k),\
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
};
#define XEC_PWM_BBLED_DEVICE_INIT(index) \
\
static struct bbled_xec_data bbled_xec_data_##index; \
\
PINCTRL_DT_INST_DEFINE(index); \
\
XEC_PWM_BBLED_CONFIG(index); \
\
PM_DEVICE_DT_INST_DEFINE(index, pwm_bbled_xec_pm_action); \
\
DEVICE_DT_INST_DEFINE(index, &pwm_bbled_xec_init, \
NULL, \
NULL, \
PM_DEVICE_DT_INST_GET(index), \
&bbled_xec_data_##index, \
&pwm_bbled_xec_config_##index, POST_KERNEL, \
CONFIG_PWM_INIT_PRIORITY, \
&pwm_bbled_xec_driver_api);

View file

@ -46,6 +46,18 @@ properties:
"#pwm-cells":
const: 2
enable-low-power-32k:
type: boolean
description: |
BBLED has two clock inputs.
- Main system clock (48MHz)
- 32KHz Core clock (32.768KHz)
When BBLED enter into Suspend state, 48MHz clock will be switched off by
PCR(Power, Clock and Reset) block. But 32KHz Core clock will be available to BBLED.
There may be a product requirement, either to blink (or) not blink LED in Suspend state.
Flag "enable-low-power-32k" shall be used along with 32KHz clock to blink (or) not blink
the LED in Suspend state.
pwm-cells:
- channel
- period