2021-08-10 10:43:44 +00:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2020-11-26 05:10:21 +00:00
|
|
|
|
|
|
|
#include <stdint.h>
|
2021-01-14 06:32:31 +00:00
|
|
|
#include <stdlib.h>
|
2020-11-26 05:10:21 +00:00
|
|
|
#include "soc/soc.h"
|
|
|
|
#include "soc/rtc.h"
|
|
|
|
#include "soc/rtc_cntl_reg.h"
|
2021-09-16 12:57:57 +00:00
|
|
|
#include "soc/syscon_reg.h"
|
2020-11-26 05:10:21 +00:00
|
|
|
#include "soc/i2s_reg.h"
|
2020-12-29 07:39:52 +00:00
|
|
|
#include "soc/bb_reg.h"
|
|
|
|
#include "soc/nrx_reg.h"
|
|
|
|
#include "soc/fe_reg.h"
|
2020-11-26 05:10:21 +00:00
|
|
|
#include "soc/timer_group_reg.h"
|
2021-01-16 05:53:12 +00:00
|
|
|
#include "soc/system_reg.h"
|
2020-11-26 05:10:21 +00:00
|
|
|
#include "esp32c3/rom/ets_sys.h"
|
2021-01-16 05:53:12 +00:00
|
|
|
#include "esp32c3/rom/rtc.h"
|
2020-12-29 07:39:52 +00:00
|
|
|
#include "regi2c_ctrl.h"
|
2022-06-24 04:12:33 +00:00
|
|
|
#include "soc/regi2c_dig_reg.h"
|
|
|
|
#include "soc/regi2c_lp_bias.h"
|
2022-05-25 19:16:15 +00:00
|
|
|
#include "hal/efuse_hal.h"
|
2020-11-26 05:10:21 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Configure whether certain peripherals are powered down in deep sleep
|
2020-12-29 07:39:52 +00:00
|
|
|
* @param cfg power down flags as rtc_sleep_pu_config_t structure
|
2020-11-26 05:10:21 +00:00
|
|
|
*/
|
2020-12-29 07:39:52 +00:00
|
|
|
void rtc_sleep_pu(rtc_sleep_pu_config_t cfg)
|
2020-11-26 05:10:21 +00:00
|
|
|
{
|
2020-12-29 07:39:52 +00:00
|
|
|
REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu);
|
2022-08-03 06:33:13 +00:00
|
|
|
REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, cfg.rtc_fpu);
|
2021-09-16 12:57:57 +00:00
|
|
|
REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_DC_MEM_FORCE_PU, cfg.fe_fpu);
|
|
|
|
REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_PBUS_MEM_FORCE_PU, cfg.fe_fpu);
|
|
|
|
REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_AGC_MEM_FORCE_PU, cfg.fe_fpu);
|
2020-12-29 07:39:52 +00:00
|
|
|
REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu);
|
|
|
|
REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu);
|
|
|
|
REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu);
|
|
|
|
REG_SET_FIELD(NRXPD_CTRL, NRX_VIT_FORCE_PU, cfg.nrx_fpu);
|
|
|
|
REG_SET_FIELD(NRXPD_CTRL, NRX_DEMAP_FORCE_PU, cfg.nrx_fpu);
|
|
|
|
REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, cfg.fe_fpu);
|
|
|
|
REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, cfg.fe_fpu);
|
|
|
|
if (cfg.sram_fpu) {
|
2021-09-16 12:57:57 +00:00
|
|
|
REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, SYSCON_SRAM_POWER_UP);
|
2020-12-29 07:39:52 +00:00
|
|
|
} else {
|
2021-09-16 12:57:57 +00:00
|
|
|
REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, 0);
|
2020-12-29 07:39:52 +00:00
|
|
|
}
|
|
|
|
if (cfg.rom_ram_fpu) {
|
2021-09-16 12:57:57 +00:00
|
|
|
REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, SYSCON_ROM_POWER_UP);
|
2020-12-29 07:39:52 +00:00
|
|
|
} else {
|
2021-09-16 12:57:57 +00:00
|
|
|
REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, 0);
|
2020-12-29 07:39:52 +00:00
|
|
|
}
|
2020-11-26 05:10:21 +00:00
|
|
|
}
|
|
|
|
|
2022-05-04 19:19:35 +00:00
|
|
|
void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_config)
|
|
|
|
{
|
|
|
|
*out_config = (rtc_sleep_config_t) {
|
|
|
|
.lslp_mem_inf_fpu = 0,
|
|
|
|
.rtc_mem_inf_follow_cpu = (sleep_flags & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0,
|
|
|
|
.rtc_fastmem_pd_en = (sleep_flags & RTC_SLEEP_PD_RTC_FAST_MEM) ? 1 : 0,
|
|
|
|
.rtc_slowmem_pd_en = (sleep_flags & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0,
|
|
|
|
.rtc_peri_pd_en = (sleep_flags & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0,
|
|
|
|
.wifi_pd_en = (sleep_flags & RTC_SLEEP_PD_WIFI) ? 1 : 0,
|
|
|
|
.bt_pd_en = (sleep_flags & RTC_SLEEP_PD_BT) ? 1 : 0,
|
|
|
|
.cpu_pd_en = (sleep_flags & RTC_SLEEP_PD_CPU) ? 1 : 0,
|
|
|
|
.int_8m_pd_en = (sleep_flags & RTC_SLEEP_PD_INT_8M) ? 1 : 0,
|
|
|
|
.dig_peri_pd_en = (sleep_flags & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0,
|
|
|
|
.deep_slp = (sleep_flags & RTC_SLEEP_PD_DIG) ? 1 : 0,
|
|
|
|
.wdt_flashboot_mod_en = 0,
|
|
|
|
.vddsdio_pd_en = (sleep_flags & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0,
|
|
|
|
.xtal_fpu = (sleep_flags & RTC_SLEEP_PD_XTAL) ? 0 : 1,
|
|
|
|
.deep_slp_reject = 1,
|
|
|
|
.light_slp_reject = 1
|
|
|
|
};
|
|
|
|
|
|
|
|
if (sleep_flags & RTC_SLEEP_PD_DIG) {
|
|
|
|
unsigned atten_deep_sleep = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT;
|
|
|
|
#if CONFIG_ESP32C3_REV_MIN < 3
|
2022-05-25 19:16:15 +00:00
|
|
|
if (efuse_hal_get_minor_chip_version() < 3) {
|
2022-05-04 19:19:35 +00:00
|
|
|
atten_deep_sleep = 0; /* workaround for deep sleep issue in high temp on ECO2 and below */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
out_config->dig_dbias_wak = RTC_CNTL_DBIAS_1V10;
|
|
|
|
out_config->dig_dbias_slp = RTC_CNTL_DBIAS_SLP;
|
|
|
|
out_config->rtc_dbias_wak = RTC_CNTL_DBIAS_1V10;
|
|
|
|
out_config->rtc_dbias_slp = RTC_CNTL_DBIAS_SLP;
|
|
|
|
|
|
|
|
out_config->dbg_atten_monitor = RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT;
|
|
|
|
out_config->bias_sleep_monitor = RTC_CNTL_BIASSLP_MONITOR_DEFAULT;
|
|
|
|
out_config->dbg_atten_slp = atten_deep_sleep;
|
|
|
|
out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT;
|
|
|
|
out_config->pd_cur_monitor = RTC_CNTL_PD_CUR_MONITOR_DEFAULT;
|
|
|
|
out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT;
|
|
|
|
} else {
|
|
|
|
out_config->dig_dbias_wak = RTC_CNTL_DBIAS_1V10;
|
|
|
|
out_config->dig_dbias_slp = !(sleep_flags & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 : RTC_CNTL_DBIAS_SLP;
|
|
|
|
out_config->rtc_dbias_wak = RTC_CNTL_DBIAS_1V10;
|
|
|
|
out_config->rtc_dbias_slp = !(sleep_flags & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 : RTC_CNTL_DBIAS_SLP;
|
|
|
|
|
|
|
|
out_config->dbg_atten_monitor = RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT;
|
|
|
|
out_config->bias_sleep_monitor = RTC_CNTL_BIASSLP_MONITOR_DEFAULT;
|
|
|
|
out_config->dbg_atten_slp = (sleep_flags & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT : RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP;
|
|
|
|
out_config->bias_sleep_slp = !(sleep_flags & RTC_SLEEP_PD_XTAL) ? RTC_CNTL_BIASSLP_SLEEP_ON : RTC_CNTL_BIASSLP_SLEEP_DEFAULT;
|
|
|
|
out_config->pd_cur_monitor = RTC_CNTL_PD_CUR_MONITOR_DEFAULT;
|
|
|
|
out_config->pd_cur_slp = !(sleep_flags & RTC_SLEEP_PD_XTAL) ? RTC_CNTL_PD_CUR_SLEEP_ON : RTC_CNTL_PD_CUR_SLEEP_DEFAULT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-26 05:10:21 +00:00
|
|
|
void rtc_sleep_init(rtc_sleep_config_t cfg)
|
|
|
|
{
|
2020-12-29 07:39:52 +00:00
|
|
|
if (cfg.lslp_mem_inf_fpu) {
|
|
|
|
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
|
|
|
|
rtc_sleep_pu(pu_cfg);
|
|
|
|
}
|
|
|
|
if (cfg.wifi_pd_en) {
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
|
|
|
} else {
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
|
|
|
|
}
|
|
|
|
if (cfg.bt_pd_en) {
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN);
|
|
|
|
} else {
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN);
|
|
|
|
}
|
|
|
|
if (cfg.cpu_pd_en) {
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_PD_EN);
|
|
|
|
} else {
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_PD_EN);
|
|
|
|
}
|
|
|
|
if (cfg.dig_peri_pd_en) {
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN);
|
|
|
|
} else {
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN);
|
|
|
|
}
|
|
|
|
|
2022-05-04 19:19:35 +00:00
|
|
|
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, cfg.rtc_dbias_slp);
|
|
|
|
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG_SLEEP, cfg.dig_dbias_slp);
|
|
|
|
|
|
|
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, cfg.dbg_atten_monitor);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, cfg.bias_sleep_monitor);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, cfg.dbg_atten_slp);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, cfg.bias_sleep_slp);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, cfg.pd_cur_monitor);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, cfg.pd_cur_slp);
|
|
|
|
|
2020-12-29 07:39:52 +00:00
|
|
|
if (cfg.deep_slp) {
|
|
|
|
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0);
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU);
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,
|
|
|
|
RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU |
|
|
|
|
RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU);
|
2021-04-26 14:18:33 +00:00
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU);
|
2020-12-29 07:39:52 +00:00
|
|
|
} else {
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP_EN);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT);
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU);
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
|
|
|
|
}
|
2022-04-20 08:33:25 +00:00
|
|
|
/* mem force pu */
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU);
|
2020-12-29 07:39:52 +00:00
|
|
|
|
pm: fixed RTC8M domain power issues
introduced in e44ead535640525969c7e85892f38ca349d5ddf4
1. The int8M power domain config by default is PD. While LEDC is using
RTC8M as clock source, this power domain will be kept on.
But when 8MD256 is used as RTC clock source, the power domain should
also be kept on.
On ESP32, there was protection for it, but broken by commit
e44ead535640525969c7e85892f38ca349d5ddf4. Currently the power domain
will be forced on when LEDC is using RTC8M as clock source &&
!int8m_pd_en (user enable ESP_PDP_DOMAIN_RTC8M in lightsleep). Otherwise
the power domain will be powered off, regardless of RTC clock source.
In other words, int8M domain will be forced off (even when 8MD256
used as RTC clock source) if LEDC not using RTC8M as clock source, user
doesn't enable ESP_PDP_DOMAIN_RTC8M, or in deep sleep.
On later chips, there's no such protection, so 8MD256 could't be used as
RTC clock source in sleep modes.
This commit adds protection of 8MD256 clock to other chips. Fixes the
incorrect protection logic overriding on ESP32. Now the power domain
will be determiend by the logic below (order by priority):
1. When RTC clock source uses 8MD256, power up
2. When LEDC uses RTC8M clock source, power up
3. In deepsleep, power down
4. Otherwise determined by user config of ESP_PDP_DOMAIN_RTC8M,
power down by default. (This is preferred to have highest
priority, but it's kept as is because of current code structure.)
2. Before, after the macro `RTC_SLEEP_CONFIG_DEFAULT` decides dbias, the
protection above may force the int8m PU. This may cause the inconsistent
of dbias and the int8m PU status.
This commit lifts the logic of pd int8m/xtal fpu logic to upper layer
(sleep_modes.c).
Related: https://github.com/espressif/esp-idf/issues/8007, https://github.com/espressif/esp-idf/pull/8089
temp
2022-03-26 19:02:22 +00:00
|
|
|
if (!cfg.int_8m_pd_en) {
|
2021-08-27 02:38:55 +00:00
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_NOGATING);
|
|
|
|
} else {
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
|
|
|
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_NOGATING);
|
2020-12-29 07:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* enable VDDSDIO control by state machine */
|
|
|
|
REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
|
|
|
|
|
|
|
|
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject);
|
|
|
|
|
2021-09-06 06:17:43 +00:00
|
|
|
REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING, cfg.xtal_fpu);
|
2020-12-29 07:39:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void rtc_sleep_low_init(uint32_t slowclk_period)
|
|
|
|
{
|
|
|
|
// set 5 PWC state machine times to fit in main state machine time
|
|
|
|
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, slowclk_period));
|
|
|
|
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
|
2020-11-26 05:10:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void rtc_sleep_set_wakeup_time(uint64_t t)
|
|
|
|
{
|
|
|
|
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
|
|
|
|
WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
|
|
|
|
}
|
|
|
|
|
2021-01-16 05:53:12 +00:00
|
|
|
static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu);
|
|
|
|
|
2020-11-26 05:10:21 +00:00
|
|
|
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)
|
|
|
|
{
|
|
|
|
REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
|
|
|
|
REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_SLEEP_REJECT_ENA, reject_opt);
|
|
|
|
|
2021-06-15 12:20:20 +00:00
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
|
|
|
|
RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
|
|
|
|
|
2020-11-26 05:10:21 +00:00
|
|
|
/* Start entry into sleep mode */
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
|
|
|
|
|
|
|
|
while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG,
|
|
|
|
RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) {
|
|
|
|
;
|
|
|
|
}
|
2021-01-16 05:53:12 +00:00
|
|
|
|
|
|
|
return rtc_sleep_finish(lslp_mem_inf_fpu);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STR2(X) #X
|
|
|
|
#define STR(X) STR2(X)
|
|
|
|
|
|
|
|
uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
|
|
|
|
{
|
|
|
|
REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
|
|
|
|
WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt);
|
|
|
|
|
2021-06-15 12:20:20 +00:00
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
|
|
|
|
RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
|
|
|
|
|
2021-01-16 05:53:12 +00:00
|
|
|
/* Calculate RTC Fast Memory CRC (for wake stub) & go to deep sleep
|
|
|
|
|
|
|
|
Because we may be running from RTC memory as stack, we can't easily call any
|
|
|
|
functions to do this (as registers will spill to stack, corrupting the CRC).
|
|
|
|
|
|
|
|
Instead, load all the values we need into registers then use register ops only to calculate
|
|
|
|
the CRC value, write it to the RTC CRC value register, and immediately go into deep sleep.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Values used to set the SYSTEM_RTC_FASTMEM_CONFIG_REG value */
|
|
|
|
const unsigned CRC_START_ADDR = 0;
|
|
|
|
const unsigned CRC_LEN = 0x7ff;
|
|
|
|
|
|
|
|
asm volatile(
|
|
|
|
/* Start CRC calculation */
|
|
|
|
"sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN
|
|
|
|
"or t0, %1, %2\n"
|
|
|
|
"sw t0, 0(%0)\n" // set RTC_MEM_CRC_START
|
|
|
|
|
|
|
|
/* Wait for the CRC calculation to finish */
|
|
|
|
".Lwaitcrc:\n"
|
|
|
|
"fence\n"
|
|
|
|
"lw t0, 0(%0)\n"
|
|
|
|
"li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n"
|
|
|
|
"and t0, t0, t1\n"
|
|
|
|
"beqz t0, .Lwaitcrc\n"
|
|
|
|
"not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START
|
|
|
|
"and t0, t0, %2\n"
|
|
|
|
"sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START
|
|
|
|
"fence\n"
|
|
|
|
"not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged
|
|
|
|
|
|
|
|
/* Store the calculated value in RTC_MEM_CRC_REG */
|
|
|
|
"lw t0, 0(%3)\n"
|
|
|
|
"sw t0, 0(%4)\n"
|
|
|
|
"fence\n"
|
|
|
|
|
|
|
|
/* Set register bit to go into deep sleep */
|
|
|
|
"lw t0, 0(%5)\n"
|
|
|
|
"or t0, t0, %6\n"
|
|
|
|
"sw t0, 0(%5)\n"
|
|
|
|
"fence\n"
|
|
|
|
|
|
|
|
/* Wait for sleep reject interrupt (never finishes if successful) */
|
|
|
|
".Lwaitsleep:"
|
|
|
|
"fence\n"
|
|
|
|
"lw t0, 0(%7)\n"
|
|
|
|
"and t0, t0, %8\n"
|
|
|
|
"beqz t0, .Lwaitsleep\n"
|
|
|
|
|
|
|
|
:
|
|
|
|
:
|
|
|
|
"r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0
|
|
|
|
"r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S)
|
|
|
|
| (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1
|
|
|
|
"r" (SYSTEM_RTC_MEM_CRC_START), // %2
|
|
|
|
"r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3
|
|
|
|
"r" (RTC_MEMORY_CRC_REG), // %4
|
|
|
|
"r" (RTC_CNTL_STATE0_REG), // %5
|
|
|
|
"r" (RTC_CNTL_SLEEP_EN), // %6
|
|
|
|
"r" (RTC_CNTL_INT_RAW_REG), // %7
|
|
|
|
"r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8
|
|
|
|
: "t0", "t1" // working registers
|
|
|
|
);
|
|
|
|
|
|
|
|
return rtc_sleep_finish(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)
|
|
|
|
{
|
2020-11-26 05:10:21 +00:00
|
|
|
/* In deep sleep mode, we never get here */
|
|
|
|
uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW);
|
|
|
|
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
|
|
|
|
RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
|
|
|
|
|
|
|
|
/* restore config if it is a light sleep */
|
|
|
|
if (lslp_mem_inf_fpu) {
|
2020-12-29 07:39:52 +00:00
|
|
|
rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
|
|
|
|
rtc_sleep_pu(pu_cfg);
|
2020-11-26 05:10:21 +00:00
|
|
|
}
|
|
|
|
return reject;
|
|
|
|
}
|