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:
parent
f907f9592d
commit
b4cd531e2c
|
@ -18,6 +18,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include <zephyr/drivers/pinctrl.h>
|
#include <zephyr/drivers/pinctrl.h>
|
||||||
#include <zephyr/logging/log.h>
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/pm/device.h>
|
||||||
|
|
||||||
#include <soc.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_1 XEC_PWM_BBLED_CLKSEL_PCR_SLOW
|
||||||
#define XEC_PWM_BBLED_CLKSEL_2 XEC_PWM_BBLED_CLKSEL_AHB_48M
|
#define XEC_PWM_BBLED_CLKSEL_2 XEC_PWM_BBLED_CLKSEL_AHB_48M
|
||||||
|
|
||||||
|
|
||||||
struct bbled_regs {
|
struct bbled_regs {
|
||||||
volatile uint32_t config;
|
volatile uint32_t config;
|
||||||
volatile uint32_t limits;
|
volatile uint32_t limits;
|
||||||
|
@ -118,12 +120,17 @@ struct bbled_regs {
|
||||||
|
|
||||||
struct pwm_bbled_xec_config {
|
struct pwm_bbled_xec_config {
|
||||||
struct bbled_regs * const regs;
|
struct bbled_regs * const regs;
|
||||||
|
const struct pinctrl_dev_config *pcfg;
|
||||||
uint8_t girq;
|
uint8_t girq;
|
||||||
uint8_t girq_pos;
|
uint8_t girq_pos;
|
||||||
uint8_t pcr_idx;
|
uint8_t pcr_idx;
|
||||||
uint8_t pcr_pos;
|
uint8_t pcr_pos;
|
||||||
uint8_t clk_sel;
|
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.
|
/* 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;
|
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 = {
|
static const struct pwm_driver_api pwm_bbled_xec_driver_api = {
|
||||||
.set_cycles = pwm_bbled_xec_set_cycles,
|
.set_cycles = pwm_bbled_xec_set_cycles,
|
||||||
.get_cycles_per_sec = pwm_bbled_xec_get_cycles_per_sec,
|
.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)), \
|
.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_idx = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 0), \
|
||||||
.pcr_pos = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 1), \
|
.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), \
|
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
|
||||||
};
|
};
|
||||||
|
|
||||||
#define XEC_PWM_BBLED_DEVICE_INIT(index) \
|
#define XEC_PWM_BBLED_DEVICE_INIT(index) \
|
||||||
\
|
\
|
||||||
|
static struct bbled_xec_data bbled_xec_data_##index; \
|
||||||
|
\
|
||||||
PINCTRL_DT_INST_DEFINE(index); \
|
PINCTRL_DT_INST_DEFINE(index); \
|
||||||
\
|
\
|
||||||
XEC_PWM_BBLED_CONFIG(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, \
|
DEVICE_DT_INST_DEFINE(index, &pwm_bbled_xec_init, \
|
||||||
NULL, \
|
PM_DEVICE_DT_INST_GET(index), \
|
||||||
NULL, \
|
&bbled_xec_data_##index, \
|
||||||
&pwm_bbled_xec_config_##index, POST_KERNEL, \
|
&pwm_bbled_xec_config_##index, POST_KERNEL, \
|
||||||
CONFIG_PWM_INIT_PRIORITY, \
|
CONFIG_PWM_INIT_PRIORITY, \
|
||||||
&pwm_bbled_xec_driver_api);
|
&pwm_bbled_xec_driver_api);
|
||||||
|
|
|
@ -46,6 +46,18 @@ properties:
|
||||||
"#pwm-cells":
|
"#pwm-cells":
|
||||||
const: 2
|
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:
|
pwm-cells:
|
||||||
- channel
|
- channel
|
||||||
- period
|
- period
|
||||||
|
|
Loading…
Reference in a new issue