Skip to content

Commit

Permalink
drivers: regulator: Add power management to DCDC
Browse files Browse the repository at this point in the history
This change restore DCDC configuration after system resumes.

When CONFIG_PM_DEVICE is enabled each of the four rails that
support DCDC handle resume in regulator_da1469x_pm_action function.

Signed-off-by: Jerzy Kasenberg <[email protected]>
  • Loading branch information
kasjer committed Apr 24, 2024
1 parent bfe94a2 commit d0cd7e5
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/regulator/Kconfig.da1469x
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
config REGULATOR_DA1469X
bool "DA1469X regulators driver"
default y
select PM_DEVICE if PM
depends on DT_HAS_RENESAS_SMARTBOND_REGULATOR_ENABLED
help
Enable support for the Smartbond DA1469x regulators.
Expand Down
59 changes: 57 additions & 2 deletions drivers/regulator/regulator_da1469x.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <zephyr/drivers/regulator.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/linear_range.h>
#include <zephyr/pm/pm.h>
#include <zephyr/pm/device.h>
#include <DA1469xAB.h>

LOG_MODULE_REGISTER(regulator_da1469x, CONFIG_REGULATOR_LOG_LEVEL);
Expand Down Expand Up @@ -77,6 +79,16 @@ enum da1469x_rail {
V30,
};

struct dcdc_regs {
uint32_t v18;
uint32_t v18p;
uint32_t vdd;
uint32_t v14;
uint32_t ctrl1;
};

static struct dcdc_regs dcdc_state;

struct regulator_da1469x_desc {
const struct linear_range *voltage_ranges;
const struct linear_range *current_ranges;
Expand All @@ -85,6 +97,7 @@ struct regulator_da1469x_desc {
uint32_t enable_mask;
uint32_t voltage_idx_mask;
volatile uint32_t *dcdc_register;
uint32_t *dcdc_register_shadow;
};

static const struct regulator_da1469x_desc vdd_desc = {
Expand All @@ -94,6 +107,7 @@ static const struct regulator_da1469x_desc vdd_desc = {
.enable_mask = CRG_TOP_POWER_CTRL_REG_LDO_CORE_ENABLE_Msk,
.voltage_idx_mask = CRG_TOP_POWER_CTRL_REG_VDD_LEVEL_Msk,
.dcdc_register = &DCDC->DCDC_VDD_REG,
.dcdc_register_shadow = &dcdc_state.vdd,
};

static const struct regulator_da1469x_desc vdd_sleep_desc = {
Expand All @@ -117,6 +131,7 @@ static const struct regulator_da1469x_desc v14_desc = {
.enable_mask = CRG_TOP_POWER_CTRL_REG_LDO_RADIO_ENABLE_Msk,
.voltage_idx_mask = CRG_TOP_POWER_CTRL_REG_V14_LEVEL_Msk,
.dcdc_register = &DCDC->DCDC_V14_REG,
.dcdc_register_shadow = &dcdc_state.v14,
};

static const struct regulator_da1469x_desc v18_desc = {
Expand All @@ -127,6 +142,7 @@ static const struct regulator_da1469x_desc v18_desc = {
CRG_TOP_POWER_CTRL_REG_LDO_1V8_RET_ENABLE_SLEEP_Msk,
.voltage_idx_mask = CRG_TOP_POWER_CTRL_REG_V18_LEVEL_Msk,
.dcdc_register = &DCDC->DCDC_V18_REG,
.dcdc_register_shadow = &dcdc_state.v18,
};

static const struct regulator_da1469x_desc v18p_desc = {
Expand All @@ -137,6 +153,7 @@ static const struct regulator_da1469x_desc v18p_desc = {
CRG_TOP_POWER_CTRL_REG_LDO_1V8P_RET_ENABLE_SLEEP_Msk,
.voltage_idx_mask = 0,
.dcdc_register = &DCDC->DCDC_V18P_REG,
.dcdc_register_shadow = &dcdc_state.v18p,
};

static const struct regulator_da1469x_desc v30_desc = {
Expand Down Expand Up @@ -183,6 +200,7 @@ static int regulator_da1469x_enable(const struct device *dev)
~(DCDC_DCDC_V14_REG_DCDC_V14_ENABLE_HV_Msk |
DCDC_DCDC_V14_REG_DCDC_V14_ENABLE_LV_Msk);
reg_val |= config->dcdc_bits;
*config->desc->dcdc_register_shadow = reg_val;
*config->desc->dcdc_register = reg_val;
}

Expand All @@ -196,6 +214,7 @@ static int regulator_da1469x_enable(const struct device *dev)
(CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_COMP_VBAT_HIGH_Msk) &&
config->dcdc_bits & DCDC_REQUESTED) {
DCDC->DCDC_CTRL1_REG |= DCDC_DCDC_CTRL1_REG_DCDC_ENABLE_Msk;
dcdc_state.ctrl1 = DCDC->DCDC_CTRL1_REG;
}

return 0;
Expand All @@ -214,6 +233,7 @@ static int regulator_da1469x_disable(const struct device *dev)
reg_val = *config->desc->dcdc_register &
~(DCDC_DCDC_V14_REG_DCDC_V14_ENABLE_HV_Msk |
DCDC_DCDC_V14_REG_DCDC_V14_ENABLE_LV_Msk);
*config->desc->dcdc_register_shadow = reg_val;
*config->desc->dcdc_register = reg_val;
}

Expand All @@ -224,6 +244,7 @@ static int regulator_da1469x_disable(const struct device *dev)
(DCDC->DCDC_V18_REG & DCDC_REQUESTED) == 0 &&
(DCDC->DCDC_V18P_REG & DCDC_REQUESTED) == 0) {
DCDC->DCDC_CTRL1_REG &= ~DCDC_DCDC_CTRL1_REG_DCDC_ENABLE_Msk;
dcdc_state.ctrl1 = DCDC->DCDC_CTRL1_REG;
}

return 0;
Expand Down Expand Up @@ -321,7 +342,7 @@ static int regulator_da1469x_set_current_limit(const struct device *dev,
reg_val |= FIELD_PREP(DCDC_DCDC_V14_REG_DCDC_V14_CUR_LIM_MAX_HV_Msk, idx);
reg_val |= FIELD_PREP(DCDC_DCDC_V14_REG_DCDC_V14_CUR_LIM_MAX_LV_Msk, idx);
reg_val |= FIELD_PREP(DCDC_DCDC_V14_REG_DCDC_V14_CUR_LIM_MIN_Msk, idx);

*config->desc->dcdc_register_shadow = reg_val;
*config->desc->dcdc_register = reg_val;

return ret;
Expand Down Expand Up @@ -369,6 +390,37 @@ static int regulator_da1469x_init(const struct device *dev)
return regulator_common_init(dev, 0);
}

#if IS_ENABLED(CONFIG_PM_DEVICE)
static int regulator_da1469x_pm_action(const struct device *dev,
enum pm_device_action action)
{
const struct regulator_da1469x_config *config = dev->config;
int ret = 0;

switch (action) {
case PM_DEVICE_ACTION_RESUME:
if (config->desc->dcdc_register) {
*config->desc->dcdc_register = *config->desc->dcdc_register_shadow;
if ((CRG_TOP->ANA_STATUS_REG & CRG_TOP_ANA_STATUS_REG_COMP_VBAT_HIGH_Msk) &&
(*config->desc->dcdc_register_shadow & DCDC_REQUESTED)) {
DCDC->DCDC_CTRL1_REG = dcdc_state.ctrl1;
}
}
break;
case PM_DEVICE_ACTION_SUSPEND:
/*
* Shadow register is saved on each regulator API call, there is no need
* to save it here.
*/
break;
default:
ret = -ENOTSUP;
}

return ret;
}
#endif

#define REGULATOR_DA1469X_DEFINE(node, id, rail_id) \
static struct regulator_da1469x_data data_##id; \
\
Expand All @@ -392,7 +444,10 @@ static int regulator_da1469x_init(const struct device *dev)
(DT_PROP(node, renesas_regulator_dcdc_vbat_low) * \
DCDC_DCDC_VDD_REG_DCDC_VDD_ENABLE_LV_Msk) \
}; \
DEVICE_DT_DEFINE(node, regulator_da1469x_init, NULL, &data_##id, \
PM_DEVICE_DT_DEFINE(node, regulator_da1469x_pm_action); \
DEVICE_DT_DEFINE(node, regulator_da1469x_init, \
PM_DEVICE_DT_GET(node), \
&data_##id, \
&config_##id, PRE_KERNEL_1, \
CONFIG_REGULATOR_DA1469X_INIT_PRIORITY, \
&regulator_da1469x_api);
Expand Down

0 comments on commit d0cd7e5

Please sign in to comment.