Files
base/drivers/source/pmu/sdrv_pmu.c
2025-11-07 09:57:14 +08:00

1792 lines
45 KiB
C

/**
* @file sdrv_pmu.c
* @brief Sdrv PMU driver source.
*
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
* All rights reserved.
*/
#include <common.h>
#include <sdrv_pmu.h>
#include <regs_base.h>
#include <reg.h>
#include <bits.h>
#include <sdrv_ckgen.h>
#include <part.h>
#include "sdrv_pmu_reg.h"
#if CONFIG_RTC_SS_DYNAMIC_PCLK
#define PMU_REG_DUMMY_READ() readl(APB_PMU_CORE_BASE + WAKEUP_CTRL_OFF);
#else
#define PMU_REG_DUMMY_READ()
#endif
static inline uint32_t sdrv_pmu_readl(uint32_t offset)
{
return readl(APB_PMU_CORE_BASE + offset);
}
static inline void sdrv_pmu_writel(uint32_t offset, uint32_t value)
{
writel(value, APB_PMU_CORE_BASE + offset);
}
static void sdrv_pmu_wakeup_pin_0_init(sdrv_pmu_polarity_e pol)
{
uint32_t v;
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
switch (pol) {
case SDRV_PMU_HIGH_LEVEL:
v &= ~BM_WAKEUP_CTRL_WKUP0_EDGE;
v &= ~BM_WAKEUP_CTRL_WKUP0_POL;
break;
case SDRV_PMU_LOW_LEVEL:
v &= ~BM_WAKEUP_CTRL_WKUP0_EDGE;
v |= BM_WAKEUP_CTRL_WKUP0_POL;
break;
case SDRV_PMU_RISING_EDGE:
v |= BM_WAKEUP_CTRL_WKUP0_EDGE;
v &= ~BM_WAKEUP_CTRL_WKUP0_POL;
break;
case SDRV_PMU_FALLING_EDGE:
v |= BM_WAKEUP_CTRL_WKUP0_EDGE;
v |= BM_WAKEUP_CTRL_WKUP0_POL;
break;
default:
break;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
}
static void sdrv_pmu_wakeup_pin_0_enable(bool enable)
{
uint32_t v;
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (enable) {
v &= ~BM_WAKEUP_CTRL_WKUP0_DISABLE;
}
else {
v |= BM_WAKEUP_CTRL_WKUP0_DISABLE;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
}
static void sdrv_pmu_wakeup_pin_1_init(sdrv_pmu_polarity_e pol)
{
uint32_t v;
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
switch (pol) {
case SDRV_PMU_HIGH_LEVEL:
v &= ~BM_WAKEUP_CTRL_WKUP1_EDGE;
v &= ~BM_WAKEUP_CTRL_WKUP1_POL;
break;
case SDRV_PMU_LOW_LEVEL:
v &= ~BM_WAKEUP_CTRL_WKUP1_EDGE;
v |= BM_WAKEUP_CTRL_WKUP1_POL;
break;
case SDRV_PMU_RISING_EDGE:
v |= BM_WAKEUP_CTRL_WKUP1_EDGE;
v &= ~BM_WAKEUP_CTRL_WKUP1_POL;
break;
case SDRV_PMU_FALLING_EDGE:
v |= BM_WAKEUP_CTRL_WKUP1_EDGE;
v |= BM_WAKEUP_CTRL_WKUP1_POL;
break;
default:
break;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
}
static void sdrv_pmu_wakeup_pin_1_enable(bool enable)
{
uint32_t v;
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (enable) {
v &= ~BM_WAKEUP_CTRL_WKUP1_DISABLE;
}
else {
v |= BM_WAKEUP_CTRL_WKUP1_DISABLE;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
}
status_t sdrv_pmu_srcs_set(uint32_t bitmap)
{
RTC_SS_ACCESS_START();
writel(bitmap, APB_PMU_CORE_BASE + SRCS_BITS_SET_OFF);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_srcs_clear(uint32_t bitmap)
{
RTC_SS_ACCESS_START();
writel(bitmap, APB_PMU_CORE_BASE + SRCS_BITS_CLR_OFF);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Enable wakeup source when in RTC mode.
*
* This function enable which source can use to wakeup from RTC mode.
* Source are: SDRV_PMU_WAKEUP_PIN0_MASK, SDRV_PMU_WAKEUP_PIN1_MASK
* SDRV_PMU_WAKEUP_RTC_MASK, SDRV_PMU_WAKEUP_BC_MASK
*
* @param [in] enable_bitmap OR'ed value of the source.
*/
status_t sdrv_pmu_wakeup_enable(uint32_t enable_bitmap)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (enable_bitmap & SDRV_PMU_WAKEUP_PIN0_MASK) {
v &= ~BM_WAKEUP_CTRL_WKUP0_DISABLE;
}
if (enable_bitmap & SDRV_PMU_WAKEUP_PIN1_MASK) {
v &= ~BM_WAKEUP_CTRL_WKUP1_DISABLE;
}
if (enable_bitmap & SDRV_PMU_WAKEUP_RTC_MASK) {
v |= BM_WAKEUP_CTRL_INT_WAKEUP_EN;
}
if (enable_bitmap & SDRV_PMU_WAKEUP_BC_MASK) {
v |= BM_WAKEUP_CTRL_EXT_WAKEUP_EN;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Disable wakeup source when in RTC mode.
*
* This function disable which source can use to wakeup from RTC mode.
* Source are: SDRV_PMU_WAKEUP_PIN0_MASK, SDRV_PMU_WAKEUP_PIN1_MASK
* SDRV_PMU_WAKEUP_RTC_MASK, SDRV_PMU_WAKEUP_BC_MASK
*
* @param [in] disable_bitmap OR'ed value of the source.
*/
status_t sdrv_pmu_wakeup_disable(uint32_t disable_bitmap)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (disable_bitmap & SDRV_PMU_WAKEUP_PIN0_MASK) {
v |= BM_WAKEUP_CTRL_WKUP0_DISABLE;
}
if (disable_bitmap & SDRV_PMU_WAKEUP_PIN1_MASK) {
v |= BM_WAKEUP_CTRL_WKUP1_DISABLE;
}
if (disable_bitmap & SDRV_PMU_WAKEUP_RTC_MASK) {
v &= ~BM_WAKEUP_CTRL_INT_WAKEUP_EN;
}
if (disable_bitmap & SDRV_PMU_WAKEUP_BC_MASK) {
v &= ~BM_WAKEUP_CTRL_EXT_WAKEUP_EN;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config button control register.
*
* This function config button control enter/exit rtc mode active level or
* pulse.
*
* @param [in] bc_config button control config.
*/
status_t sdrv_pmu_button_control_init(sdrv_pmu_bc_config_t *bc_config)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_CTRL_SET_OFF);
switch (bc_config->bc_off_pol) {
case SDRV_PMU_HIGH_LEVEL:
v &= ~BM_BC_CTRL_SET_BC_OFF_EDGE;
v &= ~BM_BC_CTRL_SET_BC_OFF_POL;
break;
case SDRV_PMU_LOW_LEVEL:
v &= ~BM_BC_CTRL_SET_BC_OFF_EDGE;
v |= BM_BC_CTRL_SET_BC_OFF_POL;
break;
case SDRV_PMU_RISING_EDGE:
v |= BM_BC_CTRL_SET_BC_OFF_EDGE;
v &= ~BM_BC_CTRL_SET_BC_OFF_POL;
break;
case SDRV_PMU_FALLING_EDGE:
v |= BM_BC_CTRL_SET_BC_OFF_EDGE;
v |= BM_BC_CTRL_SET_BC_OFF_POL;
break;
default:
break;
}
switch (bc_config->bc_on_pol) {
case SDRV_PMU_HIGH_LEVEL:
v &= ~BM_BC_CTRL_SET_BC_ON_EDGE;
v &= ~BM_BC_CTRL_SET_BC_ON_POL;
break;
case SDRV_PMU_LOW_LEVEL:
v &= ~BM_BC_CTRL_SET_BC_ON_EDGE;
v |= BM_BC_CTRL_SET_BC_ON_POL;
break;
case SDRV_PMU_RISING_EDGE:
v |= BM_BC_CTRL_SET_BC_ON_EDGE;
v &= ~BM_BC_CTRL_SET_BC_ON_POL;
break;
case SDRV_PMU_FALLING_EDGE:
v |= BM_BC_CTRL_SET_BC_ON_EDGE;
v |= BM_BC_CTRL_SET_BC_ON_POL;
break;
default:
break;
}
sdrv_pmu_writel(BC_CTRL_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config edge filter for button control.
*
* @param [in] filter_config edge filter parameters.
*/
status_t sdrv_pmu_button_control_edge_filter_config(sdrv_pmu_edge_filter_t *filter_config)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_CTRL_SET_OFF);
if (filter_config->enable_filter) {
v &= ~BM_BC_CTRL_SET_BC_FILTER_BYPASS;
} else {
v |= BM_BC_CTRL_SET_BC_FILTER_BYPASS;
}
v &= ~FM_BC_CTRL_SET_BC_SAMPLE_INTERVAL;
v &= ~FM_BC_CTRL_SET_BC_FILTER_CNT;
v &= ~FM_BC_CTRL_SET_BC_FILTER_EDGE;
v |= FV_BC_CTRL_SET_BC_SAMPLE_INTERVAL(filter_config->filter_sample_interval);
v |= FV_BC_CTRL_SET_BC_FILTER_CNT(filter_config->filter_count);
v |= FV_BC_CTRL_SET_BC_FILTER_EDGE(filter_config->filter_type);
sdrv_pmu_writel(BC_CTRL_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config level filter parameters for button control.
*
* @param [in] filter_config level filter parameters.
*/
status_t sdrv_pmu_button_control_level_filter_para(sdrv_pmu_level_filter_t *filter_config)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_VLD_WINDOW_OFF);
v &= ~FM_BC_VLD_WINDOW_BC_ON_VLD_MIN;
v &= ~FM_BC_VLD_WINDOW_BC_ON_VLD_MAX;
v &= ~FM_BC_VLD_WINDOW_BC_OFF_VLD_MIN;
v &= ~FM_BC_VLD_WINDOW_BC_OFF_VLD_MAX;
v |= FV_BC_VLD_WINDOW_BC_ON_VLD_MIN(filter_config->min_window_for_on);
v |= FV_BC_VLD_WINDOW_BC_ON_VLD_MAX(filter_config->max_window_for_on);
v |= FV_BC_VLD_WINDOW_BC_OFF_VLD_MIN(filter_config->min_window_for_off);
v |= FV_BC_VLD_WINDOW_BC_OFF_VLD_MAX(filter_config->max_window_for_off);
sdrv_pmu_writel(BC_VLD_WINDOW_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Enable level filter for button control.
*
* @param [in] filter_config level filter config.
*/
status_t sdrv_pmu_button_control_level_filter_config(sdrv_pmu_level_filter_enable_t *filter_config)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_CTRL_SET_OFF);
v &= ~FM_BC_CTRL_SET_BC_CNT_UNIT;
v |= FV_BC_CTRL_SET_BC_CNT_UNIT(filter_config->bc_cnt_unit);
if (filter_config->max_window_for_on_en) {
v &= ~BM_BC_CTRL_SET_BC_ON_VLD_MAX_DISABLE;
}
else {
v |= BM_BC_CTRL_SET_BC_ON_VLD_MAX_DISABLE;
}
if (filter_config->max_window_for_off_en) {
v &= ~BM_BC_CTRL_SET_BC_OFF_VLD_MAX_DISABLE;
}
else {
v |= BM_BC_CTRL_SET_BC_OFF_VLD_MAX_DISABLE;
}
sdrv_pmu_writel(BC_CTRL_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config hardware power down request enable.
*
* @param [in] enable_bitmap OR' value defined in sdrv_pmu_hw_power_down_req_e.
* @param [in] enable enable or disable.
*/
status_t sdrv_pmu_hardware_power_down_request_enable(uint32_t enable_bitmap, bool enable)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_CTRL_SET_OFF);
enable_bitmap = FV_BC_CTRL_SET_PWR_DWN_HW_REQ_ENABLE(enable_bitmap);
if (enable) {
v |= enable_bitmap;
}
else {
v &= ~enable_bitmap;
}
sdrv_pmu_writel(BC_CTRL_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Enable or Disable button control function.
*
* This function config whether use button control or not.
*
* @param [in] enable true represents enable, false represents disable.
*/
status_t sdrv_pmu_button_control_enable(bool enable)
{
uint32_t v, v1;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_CTRL_SET_OFF);
v1 = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (enable) {
v &= ~BM_BC_CTRL_SET_BC_DISABLE;
v1 |= BM_WAKEUP_CTRL_EXT_WAKEUP_EN;
}
else {
v |= BM_BC_CTRL_SET_BC_DISABLE;
v1 &= ~BM_WAKEUP_CTRL_EXT_WAKEUP_EN;
}
sdrv_pmu_writel(BC_CTRL_SET_OFF, v);
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v1);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Enable status monitor for button control.
*
* This function enable satus monitor for button control.
* When enabled, only responds the valid power on request in BC_OFF state,
* and only respond the valid power off request in BC_ON state.
*
* @param [in] enable true represents enable fsm check, false represents disable fsm check.
*/
status_t sdrv_pmu_button_control_fsm_enable(bool enable)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_CTRL_SET_OFF);
if (enable) {
v |= BM_BC_CTRL_SET_BC_FSM_ENABLE;
}
else {
v &= ~BM_BC_CTRL_SET_BC_FSM_ENABLE;
}
sdrv_pmu_writel(BC_CTRL_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Initialize button control parameter config.
*
* @param [in] config bc config parameter.
* @return SDRV_STATUS_OK or error code.
*/
status_t sdrv_pmu_button_control_config(sdrv_pmu_buttonctrl_config_t *config)
{
RTC_SS_ACCESS_START();
sdrv_pmu_button_control_enable(false);
sdrv_pmu_button_control_init(&config->polarity);
sdrv_pmu_button_control_edge_filter_config(&config->edge_filter);
sdrv_pmu_button_control_level_filter_para(&config->level_filter_para);
sdrv_pmu_button_control_level_filter_config(&config->level_filter_en);
sdrv_pmu_button_control_fsm_enable(config->fsm_enable);
sdrv_pmu_button_control_enable(true);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config specific wakeup pin.
*
* This function config wakeup pin active level or pulse.
*
* @param [in] wakeup_pin wakeup pin defined in sdrv_pmu_wakeup_pin_e.
* @param [in] pin_config wakeup pin config parameters.
*/
status_t sdrv_pmu_wakeup_pin_init(sdrv_pmu_wakeup_pin_e wakeup_pin, sdrv_pmu_wakeup_pin_config_t *pin_config)
{
RTC_SS_ACCESS_START();
if (wakeup_pin == SDRV_PMU_WAKEUP_PIN_0) {
sdrv_pmu_wakeup_pin_0_init(pin_config->pin_pol);
}
else if (wakeup_pin == SDRV_PMU_WAKEUP_PIN_1) {
sdrv_pmu_wakeup_pin_1_init(pin_config->pin_pol);
}
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config edge filter for wakeup pin.
*
* This function config edge filter parameters for specific wakeup pin.
*
* @param [in] wakeup_pin wakeup pin defined in sdrv_pmu_wakeup_pin_e.
* @param [in] filter_config wakeup pin filter parameters.
*/
status_t sdrv_pmu_wakeup_pin_filter_config(sdrv_pmu_wakeup_pin_e wakeup_pin, sdrv_pmu_edge_filter_t *filter_config)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (wakeup_pin == SDRV_PMU_WAKEUP_PIN_0) {
if (filter_config->enable_filter) {
v &= ~BM_WAKEUP_CTRL_WKUP0_FILTER_BYPASS;
} else {
v |= BM_WAKEUP_CTRL_WKUP0_FILTER_BYPASS;
}
v &= ~FM_WAKEUP_CTRL_WKUP0_SAMPLE_INTERVAL;
v &= ~FM_WAKEUP_CTRL_WKUP0_FILTER_CNT;
v &= ~FM_WAKEUP_CTRL_WKUP0_FILTER_EDGE;
v |= FV_WAKEUP_CTRL_WKUP0_SAMPLE_INTERVAL(filter_config->filter_sample_interval);
v |= FV_WAKEUP_CTRL_WKUP0_FILTER_CNT(filter_config->filter_count);
v |= FV_WAKEUP_CTRL_WKUP0_FILTER_EDGE(filter_config->filter_type);
}
else if (wakeup_pin == SDRV_PMU_WAKEUP_PIN_1) {
if (filter_config->enable_filter) {
v &= ~BM_WAKEUP_CTRL_WKUP1_FILTER_BYPASS;
} else {
v |= BM_WAKEUP_CTRL_WKUP1_FILTER_BYPASS;
}
v &= ~FM_WAKEUP_CTRL_WKUP1_SAMPLE_INTERVAL;
v &= ~FM_WAKEUP_CTRL_WKUP1_FILTER_CNT;
v &= ~FM_WAKEUP_CTRL_WKUP1_FILTER_EDGE;
v |= FV_WAKEUP_CTRL_WKUP1_SAMPLE_INTERVAL(filter_config->filter_sample_interval);
v |= FV_WAKEUP_CTRL_WKUP1_FILTER_CNT(filter_config->filter_count);
v |= FV_WAKEUP_CTRL_WKUP1_FILTER_EDGE(filter_config->filter_type);
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Enable or Disable specific system wakeup pin.
*
* This function config whether specific wakeup pin use or not.
*
* @param [in] wakeup_pin wakeup pin defined in sdrv_pmu_wakeup_pin_e.
* @param [in] enable true represents enable, false represents disable.
*/
status_t sdrv_pmu_wakeup_pin_enable(sdrv_pmu_wakeup_pin_e wakeup_pin, bool enable)
{
RTC_SS_ACCESS_START();
if (wakeup_pin == SDRV_PMU_WAKEUP_PIN_0) {
sdrv_pmu_wakeup_pin_0_enable(enable);
}
else if (wakeup_pin == SDRV_PMU_WAKEUP_PIN_1) {
sdrv_pmu_wakeup_pin_1_enable(enable);
}
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config wakeup pin 0/1 generate wakeup event logic.
*
* This function config whether generate wakeup event needs both wakeup pins active or not.
*
* @param [in] logic defined in sdrv_pmu_wakeup_pin_logic_e.
*/
status_t sdrv_pmu_wakeup_pin_logic_set(sdrv_pmu_wakeup_pin_logic_e logic)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (logic == SDRV_PMU_WAKEUP_PIN_OR) {
v &= ~BM_WAKEUP_CTRL_WKUP01_AND_ENABLE;
} else if (logic == SDRV_PMU_WAKEUP_PIN_AND) {
v |= BM_WAKEUP_CTRL_WKUP01_AND_ENABLE;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config pmu action when receive wakeup event during rtc state.
*
* PMU has RTC and OFF state. During RTC state, pmu doesn't respond to wakeup
* event. It only responds to wakeup event in OFF state. This function config whether pmu ignore
* rtc state wakeup event or latch wakeup when enter off state.
*
* @param [in] latch defined in sdrv_pmu_wakeup_in_rtc_e.
*/
status_t sdrv_pmu_wakeup_latch_set(sdrv_pmu_wakeup_in_rtc_e latch)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
if (latch == SDRV_PMU_WAKEUP_IN_RTC_IGNORE) {
v &= ~BM_WAKEUP_CTRL_WAKEUP_IN_RTC_LATCH;
} else if (latch == SDRV_PMU_WAKEUP_IN_RTC_LATCH) {
v |= BM_WAKEUP_CTRL_WAKEUP_IN_RTC_LATCH;
}
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config Wake pin 0 and 1 enable and active level.
*
* @param [in] config config parameters defined in sdrv_pmu_wakeuppins_config_t.
* @return SDRV_STATUS_OK or error code.
*/
status_t sdrv_pmu_wakeup_pins_config(sdrv_pmu_wakeuppins_config_t *config)
{
#if CONFIG_E3 || CONFIG_D3
if (IS_1P0 && config->wakepin0_en &&
(config->wakepin0_glitch != SDRV_PMU_GLITCH_NONE)) {
return SDRV_PMU_CONFIG_NOT_SUPPORT;
}
#endif
if (config->logic == SDRV_PMU_WAKEUP_PIN_AND) {
if (!config->wakepin0_en || !config->wakepin1_en) {
return SDRV_PMU_CONFIG_NOT_SUPPORT;
}
#if CONFIG_E3 || CONFIG_D3
if (IS_1P0 && (config->wakepin0_pol == SDRV_PMU_RISING_EDGE || config->wakepin0_pol == SDRV_PMU_FALLING_EDGE) &&
(config->wakepin1_pol == SDRV_PMU_RISING_EDGE || config->wakepin1_pol == SDRV_PMU_FALLING_EDGE)) {
return SDRV_PMU_CONFIG_NOT_SUPPORT;
}
#endif
}
RTC_SS_ACCESS_START();
sdrv_pmu_wakeup_pin_0_enable(false);
sdrv_pmu_wakeup_pin_1_enable(false);
sdrv_pmu_wakeup0_glitch_disable(SDRV_PMU_GLITCH_BOTH);
sdrv_pmu_wakeup_pin_logic_set(config->logic);
sdrv_pmu_wakeup_latch_set(config->latch);
if ((config->logic == SDRV_PMU_WAKEUP_PIN_AND) &&
(config->wakepin0_pol == SDRV_PMU_RISING_EDGE || config->wakepin0_pol == SDRV_PMU_FALLING_EDGE
|| config->wakepin0_glitch != SDRV_PMU_GLITCH_NONE) &&
(config->wakepin1_pol == SDRV_PMU_RISING_EDGE || config->wakepin1_pol == SDRV_PMU_FALLING_EDGE)) {
/* config wakepin 0 */
sdrv_pmu_wakeup_pin_0_init(SDRV_PMU_HIGH_LEVEL);
if (config->wakepin0_glitch != SDRV_PMU_GLITCH_NONE) {
sdrv_pmu_wakeup0_glitch_enable(config->wakepin0_glitch);
}
else if (config->wakepin0_pol == SDRV_PMU_RISING_EDGE) {
sdrv_pmu_wakeup0_glitch_enable(SDRV_PMU_GLITCH_RISING);
}
else {
sdrv_pmu_wakeup0_glitch_enable(SDRV_PMU_GLITCH_FALLING);
}
sdrv_pmu_wakeup_pin_0_enable(true);
/* config wakepin 1 */
sdrv_pmu_wakeup_pin_1_init(config->wakepin1_pol);
sdrv_pmu_wakeup_pin_filter_config(SDRV_PMU_WAKEUP_PIN_1, &config->wakepin1_filter);
sdrv_pmu_wakeup_pin_1_enable(true);
}
else {
if (config->wakepin0_en) {
if (config->wakepin0_glitch != SDRV_PMU_GLITCH_NONE) {
sdrv_pmu_wakeup0_glitch_enable(config->wakepin0_glitch);
sdrv_pmu_wakeup_pin_0_init(SDRV_PMU_RISING_EDGE);
}
else {
sdrv_pmu_wakeup_pin_0_init(config->wakepin0_pol);
sdrv_pmu_wakeup_pin_filter_config(SDRV_PMU_WAKEUP_PIN_0, &config->wakepin0_filter);
}
sdrv_pmu_wakeup_pin_0_enable(true);
}
if (config->wakepin1_en) {
sdrv_pmu_wakeup_pin_1_init(config->wakepin1_pol);
sdrv_pmu_wakeup_pin_filter_config(SDRV_PMU_WAKEUP_PIN_1, &config->wakepin1_filter);
sdrv_pmu_wakeup_pin_1_enable(true);
}
}
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Software trigger power down.
*
* This function write register to trigger power down request. After call this function, system will enter
* RTC mode at once.
*/
status_t sdrv_pmu_power_down(void)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(BC_CTRL_SET_OFF);
v |= BM_BC_CTRL_SET_PWR_DWN_REQ_SOFT;
sdrv_pmu_writel(BC_CTRL_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config power good watchdog parameters for pwron.
*
* @param [in] wdt_config pwron watchdog config parameters.
*/
status_t sdrv_pmu_pwron_watchdog_config(sdrv_pmu_pwron_wdt_config_t *wdt_config)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PGM_CTRL_OFF);
v &= ~FM_PGM_CTRL_POR_TW;
v &= ~FM_PGM_CTRL_POR_TW_ADJ;
v &= ~FM_PGM_CTRL_WDT_DIV;
v |= FV_PGM_CTRL_POR_TW(wdt_config->por_tw);
v |= FV_PGM_CTRL_POR_TW_ADJ(wdt_config->por_tw_adj);
v |= FV_PGM_CTRL_WDT_DIV(wdt_config->wdt_div);
sdrv_pmu_writel(PGM_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Enable power good watchdog counter for specific pwron.
*
* @param [in] pwron pwron defined in sdrv_pmu_pwr_on_e.
* @param [in] enable_config enable config.
*/
status_t sdrv_pmu_pwron_watchdog_enable(sdrv_pmu_pwr_on_e pwron, sdrv_pmu_pwron_wdt_enable_t *enable_config)
{
uint32_t en_bit, cnt_bit;
uint32_t v;
en_bit = 28U + pwron;
cnt_bit = 4U * pwron;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PGM_CTRL_OFF);
if (enable_config->pwron_wdt_en) {
v |= (1U << en_bit);
}
else {
v &= ~(1U << en_bit);
}
v &= ~(0xFU << cnt_bit);
v |= ((enable_config->wdt_counter & 0xFU) << cnt_bit);
sdrv_pmu_writel(PGM_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config pwr ctrl output level for different mode.
*
* This function config pwr ctrl output level under run/sleep/hibernate/rtc mode.
*
* @param [in] ctrl pwr ctrl pin defined in sdrv_pmu_pwr_ctrl_e.
* @param [in] mode pmu work mode defined in sdrv_pmu_mode_e.
* @param [in] config config parameters.
*/
status_t sdrv_pmu_pwrctrl_config(sdrv_pmu_pwr_ctrl_e ctrl, sdrv_pmu_mode_e mode, sdrv_pmu_pwrctrl_config_t *config)
{
uint32_t v;
uint32_t mode_offset;
uint32_t on_off_bit;
uint32_t auto_manual_bit;
switch (mode) {
case SDRV_PMU_RUN:
mode_offset = 16;
break;
case SDRV_PMU_SLEEP:
mode_offset = 8;
break;
case SDRV_PMU_HIBERNATE:
mode_offset = 0;
break;
case SDRV_PMU_RTC:
mode_offset = 24;
break;
default:
return SDRV_PMU_CONFIG_TYPE_WRONG;
}
auto_manual_bit = (SDRV_PMU_PWR_CTRL_3 - ctrl) * 2;
on_off_bit = auto_manual_bit + 1;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PWR_CTRL_SET0_OFF);
if (config->ctrl_status == SDRV_PMU_CTRL_OFF) {
v &= ~(0x1u << (mode_offset + on_off_bit));
}
else {
v |= (0x1u << (mode_offset + on_off_bit));
}
if (config->ctrl_operate == SDRV_PMU_MANUAL) {
v &= ~(0x1u << (mode_offset + auto_manual_bit));
}
else {
v |= (0x1u << (mode_offset + auto_manual_bit));
}
sdrv_pmu_writel(PWR_CTRL_SET0_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwrctrl_min_delay_config(sdrv_pmu_pwrctrl_min_delay_config_t *config)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PWR_CTRL_SET1_OFF);
if (config->pwrup_run_min_delay_en) {
v |= BM_PWR_CTRL_SET1_PWR_UP_RUN_MIN_DELAY_ENABLE;
}
else {
v &= ~BM_PWR_CTRL_SET1_PWR_UP_RUN_MIN_DELAY_ENABLE;
}
if (config->sleep_run_min_delay_en) {
v |= BM_PWR_CTRL_SET1_SLEEP_RUN_MIN_DELAY_ENABLE;
}
else {
v &= ~BM_PWR_CTRL_SET1_SLEEP_RUN_MIN_DELAY_ENABLE;
}
if (config->hibernate_run_min_delay_en) {
v |= BM_PWR_CTRL_SET1_HIBERNATE_RUN_MIN_DELAY_ENABLE;
}
else {
v &= ~BM_PWR_CTRL_SET1_HIBERNATE_RUN_MIN_DELAY_ENABLE;
}
sdrv_pmu_writel(PWR_CTRL_SET1_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwrctrl_polarity_config(sdrv_pmu_pwr_ctrl_e ctrl, sdrv_pmu_pwr_ctrl_polarity_e pol)
{
uint32_t v;
uint32_t bit;
bit = 20U + ctrl;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PWR_CTRL_SET1_OFF);
if (pol == SDRV_PMU_PWR_CTRL_HIGH_ACTIVE) {
v &= ~(1U << bit);
}
else {
v |= (1U << bit);
}
sdrv_pmu_writel(PWR_CTRL_SET1_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwrctrl_software_override_enable(sdrv_pmu_pwr_ctrl_e ctrl, bool enable)
{
uint32_t v;
uint32_t bit;
bit = 12U + ctrl;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PWR_CTRL_SET1_OFF);
if (enable) {
v |= (1U << bit);
}
else {
v &= ~(1U << bit);
}
sdrv_pmu_writel(PWR_CTRL_SET1_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwrctrl_software_override_value(sdrv_pmu_pwr_ctrl_e ctrl, bool value)
{
uint32_t v;
uint32_t bit;
bit = 8U + ctrl;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PWR_CTRL_SET1_OFF);
if (value) {
v |= (1U << bit);
}
else {
v &= ~(1U << bit);
}
sdrv_pmu_writel(PWR_CTRL_SET1_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwrctrl_delay_config(sdrv_pmu_delay_period_e period, sdrv_pmu_pwr_ctrl_e ctrl, uint8_t delay, uint8_t delay_adj)
{
uint32_t reg, v, bit;
reg = PWR_UP_PWR_CTRL_DELAY_OFF + period * 0x4U;
bit = ctrl * 6U;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(reg);
v &= ~(BIT_MASK(6) << bit);
v |= ((delay & 0xFU) << bit);
v |= ((delay_adj & 0x3U) << (bit + 4));
sdrv_pmu_writel(reg, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config pwr on whether work for different mode.
*
* This function config pwr on whether work under run/sleep/hibernate/rtc mode.
*
* @param [in] ctrl pwr on defined in sdrv_pmu_pwr_on_e.
* @param [in] mode pmu work mode defined in sdrv_pmu_mode_e.
* @param [in] config config parameters.
*/
status_t sdrv_pmu_pwron_config(sdrv_pmu_pwr_on_e ctrl, sdrv_pmu_mode_e mode, sdrv_pmu_pwron_config_t *config)
{
uint32_t v, offset;
uint32_t on_off_bit;
uint32_t auto_manual_bit;
auto_manual_bit = ctrl * 0x4;
on_off_bit = auto_manual_bit + 1;
offset = RUN_PWR_ON_SET_OFF + mode * 0x4;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(offset);
if (config->ctrl_status == SDRV_PMU_CTRL_OFF) {
v &= ~(0x1u << on_off_bit);
}
else {
v |= (0x1u << on_off_bit);
}
if (config->ctrl_operate == SDRV_PMU_MANUAL) {
v &= ~(0x1u << auto_manual_bit);
}
else {
v |= (0x1u << auto_manual_bit);
}
sdrv_pmu_writel(offset, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwron_target_config_with_mode(sdrv_pmu_pwr_on_e ctrl, sdrv_pmu_mode_e mode, sdrv_pmu_target_e target)
{
uint32_t v, offset;
uint32_t bit;
bit = ctrl * 0x4 + 0x2;
offset = RUN_PWR_ON_SET_OFF + mode * 0x4;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(offset);
v &= ~(0x3U << bit);
v |= (target << bit);
sdrv_pmu_writel(offset, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config internal DCDC/LDO power supply.
*
* This function config internal DCDC/LDO power supply to SAF/AP/Others.
* It will effect hardware power on sequence.
*
* @param [in] ctrl pwr on defined in sdrv_pmu_pwr_on_e.
* @param [in] target target defined in sdrv_pmu_target_e.
*/
status_t sdrv_pmu_pwron_target_config(sdrv_pmu_pwr_on_e ctrl, sdrv_pmu_target_e target)
{
for (uint32_t i = 0; i <= SDRV_PMU_RTC; i++) {
sdrv_pmu_pwron_target_config_with_mode(ctrl, (sdrv_pmu_mode_e)i, target);
}
return SDRV_STATUS_OK;
}
/**
* @brief Config SAF/AP domain whether powered under different mode.
*
* This function config SAF/AP domain whether powered in run/sleep/hibernate/rtc mode.
* For example, if AP domain config powered in run mode and not powered in hibernate mode,
* after wakeup from hibernate to run, hardware will auto reset ap domain.
*
* @param [in] target target defined in sdrv_pmu_target_e.
* @param [in] mode mode defined in sdrv_pmu_mode_e.
* @param [in] powered true represents powered, false represents not powered.
*/
status_t sdrv_pmu_target_power_on_config(sdrv_pmu_target_e target, sdrv_pmu_mode_e mode, bool powered)
{
uint32_t v, offset;
uint32_t bit;
if (target == SDRV_PMU_SAF) {
bit = 17;
} else if (target == SDRV_PMU_AP) {
bit = 16;
} else {
return SDRV_PMU_CONFIG_TYPE_WRONG;
}
offset = RUN_PWR_ON_SET_OFF + mode * 0x4;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(offset);
if (powered) {
v |= (0x1u << bit);
}
else {
v &= ~(0x1u << bit);
}
sdrv_pmu_writel(offset, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwron_delay_config(sdrv_pmu_delay_period_e period, sdrv_pmu_pwr_on_e ctrl, uint8_t delay, uint8_t delay_adj)
{
uint32_t reg, v, bit;
reg = PWR_UP_PWR_ON_DELAY_OFF + period * 0x4U;
bit = ctrl * 6U;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(reg);
v &= ~(BIT_MASK(6) << bit);
v |= ((delay & 0xFU) << bit);
v |= ((delay_adj & 0x3U) << (bit + 4));
sdrv_pmu_writel(reg, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwron_software_override_enable(sdrv_pmu_pwr_on_e ctrl, bool enable)
{
uint32_t v, bit;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(SW_OVERRIDE_OFF);
bit = 4U + ctrl;
if (enable) {
v |= (1U << bit);
}
else {
v &= ~(1U << bit);
}
sdrv_pmu_writel(SW_OVERRIDE_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_pwron_software_override_value(sdrv_pmu_pwr_on_e ctrl, bool value)
{
uint32_t v, bit;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(SW_OVERRIDE_OFF);
bit = 0U + ctrl;
if (value) {
v |= (1U << bit);
}
else {
v &= ~(1U << bit);
}
sdrv_pmu_writel(SW_OVERRIDE_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_minimal_delay_for_state_transition(sdrv_pmu_state_e state, uint8_t delay, uint8_t delay_adj)
{
uint32_t v, bit;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(MIN_DELAY_STATE_TRAN_OFF);
bit = 8U * state;
v &= ~(BIT_MASK(6) << bit);
v |= ((delay & 0xFU) << bit);
v |= ((delay_adj & 0x3U) << (bit + 4));
sdrv_pmu_writel(MIN_DELAY_STATE_TRAN_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_interrupt_enable(uint32_t bitmap, bool enable)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PMU_INT_OFF);
bitmap = FV_PMU_INT_PMU_INT_EN(bitmap);
if (enable) {
v |= bitmap;
}
else {
v &= ~bitmap;
}
sdrv_pmu_writel(PMU_INT_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
uint32_t sdrv_pmu_get_interrupt_status(void)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PMU_INT_OFF);
RTC_SS_ACCESS_END();
return v & 0xFFFFU;
}
status_t sdrv_pmu_clear_interrupt_status(uint32_t bitmap)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PMU_INT_OFF);
bitmap &= 0xFFFFU;
v &= ~bitmap;
sdrv_pmu_writel(PMU_INT_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_vd_sf_ana_enable(bool enable)
{
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_VD_SF_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_VD_SF_PU33_B);
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_por_sf_enable(bool enable)
{
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_POR_SF_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_POR_SF_PU33_B);
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_rc24m_enable(bool enable)
{
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_RC24M_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_RC24M_PU33_B);
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_bgr_sf_enable(bool enable)
{
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_BGR_SF_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_BGR_SF_PU33_B);
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_bgr_ldo_enable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_BGR_LDO_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_BGR_LDO_PU33_B);
#endif
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_bgr_ana_sf1_sf2_enable(bool enable)
{
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_BGR_ANA_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_BGR_ANA_PU33_B);
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_vd_ap_enable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_VD_AP_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_VD_AP_PU33_B);
#endif
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_por_ap_enable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_POR_AP_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_POR_AP_PU33_B);
#endif
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_bgr_ap_enable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_BGR_AP_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_BGR_AP_PU33_B);
#endif
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_bgr_disp_enable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
enable ? sdrv_pmu_srcs_clear(0x1U << SRCS_BGR_DISP_PU33_B)
: sdrv_pmu_srcs_set(0x1U << SRCS_BGR_DISP_PU33_B);
#endif
return SDRV_STATUS_OK;
}
status_t sdrv_pmu_analog_cven33_enable(bool enable)
{
uint32_t bitmask = 0;
#if CONFIG_E3 || CONFIG_D3
bitmask = (0x1U << SRCS_PT_SNS_SF_PT_SNS_AP_CVEN33_FORCE_OFF)
| (0x1U << SRCS_ANA_SF_ANALOG_IP_CVEN33_FORCE_OFF);
#endif
#if CONFIG_E3L
bitmask = (0x1U << SRCS_SADC1_CVEN33) | (0x1U << SRCS_SACMP1_CVEN33)
| (0x1U << SRCS_APAD_CVEN33_B0_B1) | (0x1U << SRCS_APAD_CVEN33_B2_B8)
| (0x1U << SRCS_OTHER_CVEN33);
#endif
enable ? sdrv_pmu_srcs_clear(bitmask) : sdrv_pmu_srcs_set(bitmask);
return SDRV_STATUS_OK;
}
/**
* @brief Enable or disable analog IP power.
*
* This function config PMU to control pt_sns_sf/pt_sns_ap cven33 power.
* Default is power on.
*
* @param [in] enable true represents power on, false represents power down.
*/
status_t sdrv_pmu_pt_sns_enable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
if (IS_1P1)
{
if (enable) {
sdrv_pmu_srcs_clear(0x1u << SRCS_PT_SNS_SF_PT_SNS_AP_CVEN33_FORCE_OFF);
}
else {
sdrv_pmu_srcs_set(0x1u << SRCS_PT_SNS_SF_PT_SNS_AP_CVEN33_FORCE_OFF);
}
}
#endif
return SDRV_STATUS_OK;
}
/**
* @brief Enable or disable analog IP power.
*
* This function config PMU to control ana_sf analog IP cven33 power.
* Default is power on.
*
* @param [in] enable true represents power on, false represents power down.
*/
status_t sdrv_pmu_ana_sf_analog_enable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
if (IS_1P1)
{
if (enable) {
sdrv_pmu_srcs_clear(0x1u << SRCS_ANA_SF_ANALOG_IP_CVEN33_FORCE_OFF);
}
else {
sdrv_pmu_srcs_set(0x1u << SRCS_ANA_SF_ANALOG_IP_CVEN33_FORCE_OFF);
}
}
#endif
return SDRV_STATUS_OK;
}
/**
* @brief Config bgr_ldo auto-disable.
*
* This function config whether bgr_ldo auto-disable with rc24m/xtal24m when enter low power mode.
*
* @param [in] enable true represents auto-disable with rc24m/xtal24m, false represents not.
*/
status_t sdrv_pmu_bgr_ldo_auto_disable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
if (IS_1P1)
{
if (enable) {
sdrv_pmu_srcs_set(0x1u << SRCS_BGR_LDO_AUTO_DISABLE_BY_PMU_EN);
}
else {
sdrv_pmu_srcs_clear(0x1u << SRCS_BGR_LDO_AUTO_DISABLE_BY_PMU_EN);
}
}
#endif
return SDRV_STATUS_OK;
}
/**
* @brief Config bgr_sf auto-disable.
*
* This function config whether bgr_sf auto-disable with rc24m/xtal24m when enter low power mode.
*
* @param [in] enable true represents auto-disable with rc24m/xtal24m, false represents not.
*/
status_t sdrv_pmu_bgr_sf_auto_disable(bool enable)
{
#if CONFIG_E3 || CONFIG_D3
if (IS_1P1)
#endif
{
if (enable) {
sdrv_pmu_srcs_set(0x1u << SRCS_BGR_SF_AUTO_DISABLE_BY_SMC_EN);
}
else {
sdrv_pmu_srcs_clear(0x1u << SRCS_BGR_SF_AUTO_DISABLE_BY_SMC_EN);
}
}
return SDRV_STATUS_OK;
}
/**
* @brief Enable glitch circle for wakeup pin 0.
*
* This function enable glitch circle for wakeup pin 0, in this case, it can glitch < 32khz pulse.
* When enable this feature, filter for wakeup 0 will be disabled.
*
* @param [in] mask OR'ed value, bit0: rising edge, bit1: falling edge.
* for example: (1<<0) | (1<<1) means both edge.
*/
status_t sdrv_pmu_wakeup0_glitch_enable(uint32_t mask)
{
if (!mask) {
return SDRV_PMU_CONFIG_TYPE_WRONG;
}
#if CONFIG_E3 || CONFIG_D3
if (IS_1P1)
#endif
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
v |= BM_WAKEUP_CTRL_WKUP0_FILTER_BYPASS;
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
if ((mask & 0x1u) == 0x1u) {
sdrv_pmu_srcs_set(0x1u << SRCS_WAKEUP0_RISE_EDGE_TO_PULSE_EN);
}
if ((mask & 0x2u) == 0x2u) {
sdrv_pmu_srcs_set(0x1u << SRCS_WAKEUP0_FALL_EDGE_TO_PULSE_EN);
}
}
return SDRV_STATUS_OK;
}
/**
* @brief Disable glitch circle for wakeup pin 0.
*
* This function disable glitch circle for wakeup pin 0, in this case, it can't glitch < 32khz pulse.
* When both edge disabled, filter for wakeup 0 will be re-enabled.
*
* @param [in] mask OR'ed value, bit0: rising edge, bit1: falling edge.
* for example: (1<<0) | (1<<1) means both edge.
*/
status_t sdrv_pmu_wakeup0_glitch_disable(uint32_t mask)
{
uint32_t v;
uint32_t c_bit;
if (!mask) {
return SDRV_PMU_CONFIG_TYPE_WRONG;
}
#if CONFIG_E3 || CONFIG_D3
if (IS_1P1)
#endif
{
if ((mask & 0x1u) == 0x1u) {
sdrv_pmu_srcs_clear(0x1u << SRCS_WAKEUP0_RISE_EDGE_TO_PULSE_EN);
c_bit = 20;
}
if ((mask & 0x2u) == 0x2u) {
sdrv_pmu_srcs_clear(0x1u << SRCS_WAKEUP0_FALL_EDGE_TO_PULSE_EN);
c_bit = 31;
}
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(SRCS_BITS_OFF);
if ((v & (0x1u << c_bit)) == 0x0) {
v = sdrv_pmu_readl(WAKEUP_CTRL_OFF);
v &= ~BM_WAKEUP_CTRL_WKUP0_FILTER_BYPASS;
sdrv_pmu_writel(WAKEUP_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
}
RTC_SS_ACCESS_END();
}
return SDRV_STATUS_OK;
}
/**
* @brief Config saf domain 3.3v and 0.8v power good monitor.
*
* This function config saf domain power monitor , when enabled, once 3.3v or 0.8v is
* not good, saf isolate and sf_por_b is assert. After power is good, saf isolate and
* sf_por_b deassert.
*
* @param [in] cfg SDRV_PMU_POWER_GOOD_ENABLE/SDRV_PMU_POWER_GOOD_DISABLE
*/
status_t sdrv_pmu_saf_domain_power_good_monitor(sdrv_pmu_pg_e cfg)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PG_LP_MODE_CTRL_OFF);
if (cfg == SDRV_PMU_POWER_GOOD_ENABLE) {
v &= ~BM_PG_LP_MODE_CTRL_SF_HV_PG_DISABLE;
v &= ~BM_PG_LP_MODE_CTRL_SF_LV_PG_DISABLE;
}
else if (cfg == SDRV_PMU_POWER_GOOD_DISABLE) {
v |= BM_PG_LP_MODE_CTRL_SF_HV_PG_DISABLE;
v |= BM_PG_LP_MODE_CTRL_SF_LV_PG_DISABLE;
}
sdrv_pmu_writel(PG_LP_MODE_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config ap domain 3.3v and 0.8v power good monitor.
*
* This function config ap domain power monitor , when enabled, once 3.3v or 0.8v is
* not good, ap isolate and sf_por_b is assert. After power is good, ap isolate and
* sf_por_b deassert.
*
* @param [in] cfg SDRV_PMU_POWER_GOOD_ENABLE/SDRV_PMU_POWER_GOOD_DISABLE
*/
status_t sdrv_pmu_ap_domain_power_good_monitor(sdrv_pmu_pg_e cfg)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PG_LP_MODE_CTRL_OFF);
if (cfg == SDRV_PMU_POWER_GOOD_ENABLE) {
v &= ~BM_PG_LP_MODE_CTRL_AP_HV_PG_DISABLE;
v &= ~BM_PG_LP_MODE_CTRL_AP_LV_PG_DISABLE;
}
else if (cfg == SDRV_PMU_POWER_GOOD_DISABLE) {
v |= BM_PG_LP_MODE_CTRL_AP_HV_PG_DISABLE;
v |= BM_PG_LP_MODE_CTRL_AP_LV_PG_DISABLE;
}
sdrv_pmu_writel(PG_LP_MODE_CTRL_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config saf domain power good consider or ignore when switching from RTC state to OFF state.
*
* This function config saf domain power good whether consider when enter RTC mode. If enabled, switching
* from RTC state to OFF state only when the power down counter is done and saf domain power are not good.
* If disabled, switching from RTC state to OFF state only when the power down counter is done, but ignore
* saf domain power good.
*
* @param [in] cfg SDRV_PMU_POWER_GOOD_ENABLE/SDRV_PMU_POWER_GOOD_DISABLE
*/
status_t sdrv_pmu_rtc_to_off_saf_domain_power_good(sdrv_pmu_pg_e cfg)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(RTC_PWR_ON_SET_OFF);
if (cfg == SDRV_PMU_POWER_GOOD_ENABLE) {
v &= ~BM_RTC_PWR_ON_SET_RTC_TO_OFF_SF_HV_PG_DISABLE;
v &= ~BM_RTC_PWR_ON_SET_RTC_TO_OFF_SF_LV_PG_DISABLE;
}
else if (cfg == SDRV_PMU_POWER_GOOD_DISABLE) {
v |= BM_RTC_PWR_ON_SET_RTC_TO_OFF_SF_HV_PG_DISABLE;
v |= BM_RTC_PWR_ON_SET_RTC_TO_OFF_SF_LV_PG_DISABLE;
}
sdrv_pmu_writel(RTC_PWR_ON_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Config ap domain power good consider or ignore when switching from RTC state to OFF state.
*
* This function config ap domain power good whether consider when enter RTC mode. If enabled, switching
* from RTC state to OFF state only when the power down counter is done and ap domain power are not good.
* If disabled, switching from RTC state to OFF state only when the power down counter is done, but ignore
* ap domain power good.
*
* @param [in] cfg SDRV_PMU_POWER_GOOD_ENABLE/SDRV_PMU_POWER_GOOD_DISABLE
*/
status_t sdrv_pmu_rtc_to_off_ap_domain_power_good(sdrv_pmu_pg_e cfg)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(RTC_PWR_ON_SET_OFF);
if (cfg == SDRV_PMU_POWER_GOOD_ENABLE) {
v &= ~BM_RTC_PWR_ON_SET_RTC_TO_OFF_AP_HV_PG_DISABLE;
v &= ~BM_RTC_PWR_ON_SET_RTC_TO_OFF_AP_LV_PG_DISABLE;
}
else if (cfg == SDRV_PMU_POWER_GOOD_DISABLE) {
v |= BM_RTC_PWR_ON_SET_RTC_TO_OFF_AP_HV_PG_DISABLE;
v |= BM_RTC_PWR_ON_SET_RTC_TO_OFF_AP_LV_PG_DISABLE;
}
sdrv_pmu_writel(RTC_PWR_ON_SET_OFF, v);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Get system wakeup source.
*
* This function read pmu wakeup source, return value is OR'ed value of sdrv_pmu_wakeup_src_e
*
* @return uint32_t OR'ed value of sdrv_pmu_wakeup_src_e
*/
uint32_t sdrv_pmu_get_wakeup_source(void)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PMU_DOWN_UP_STATUS_OFF);
RTC_SS_ACCESS_END();
return (v & 0xFU);
}
/**
* @brief Clear system wakeup source.
*
* @return SDRV_STATUS_OK or error code.
*/
status_t sdrv_pmu_clear_wakeup_source(void)
{
RTC_SS_ACCESS_START();
sdrv_pmu_writel(PMU_DOWN_UP_STATUS_OFF, 0xFU);
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
/**
* @brief Get system power down reason.
*
* This function return last power down reason, each bit represent reason see sdrv_pmu_power_down_reason_e.
*
* @return uint32_t power down reason.
*/
uint32_t sdrv_pmu_get_power_down_reason(void)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PMU_DOWN_UP_STATUS_OFF);
RTC_SS_ACCESS_END();
return ((v & 0xFFFFU) >> 4U);
}
/**
* @brief Clear system power down reason.
*
* @return SDRV_STATUS_OK or error code.
*/
status_t sdrv_pmu_clear_power_down_reason(void)
{
RTC_SS_ACCESS_START();
sdrv_pmu_writel(PMU_DOWN_UP_STATUS_OFF, (0xFFFFU << 4U));
PMU_REG_DUMMY_READ();
RTC_SS_ACCESS_END();
return SDRV_STATUS_OK;
}
uint32_t sdrv_pmu_get_state(void)
{
uint32_t v;
RTC_SS_ACCESS_START();
v = sdrv_pmu_readl(PMU_STATE_OFF);
RTC_SS_ACCESS_END();
return v;
}