1 /*
2 * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include "soc/soc.h"
10 #include "soc/rtc.h"
11 #include "soc/rtc_cntl_reg.h"
12 #include "soc/syscon_reg.h"
13 #include "soc/i2s_reg.h"
14 #include "soc/bb_reg.h"
15 #include "soc/nrx_reg.h"
16 #include "soc/fe_reg.h"
17 #include "soc/timer_group_reg.h"
18 #include "soc/system_reg.h"
19 #include "esp32h2/rom/ets_sys.h"
20 #include "esp32h2/rom/rtc.h"
21 #include "regi2c_ctrl.h"
22 #include "esp_efuse.h"
23 #include "i2c_pmu.h"
24 #include "soc_log.h"
25 #include "esp_rom_uart.h"
26
27 /**
28 * Configure whether certain peripherals are powered down in deep sleep
29 * @param cfg power down flags as rtc_sleep_pu_config_t structure
30 */
31 static const char *TAG = "rtc_sleep";
32
rtc_sleep_pu(rtc_sleep_pu_config_t cfg)33 void rtc_sleep_pu(rtc_sleep_pu_config_t cfg)
34 {
35 REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu);
36 REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, cfg.rtc_fpu);
37 REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_DC_MEM_FORCE_PU, cfg.fe_fpu);
38 REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_PBUS_MEM_FORCE_PU, cfg.fe_fpu);
39 REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_AGC_MEM_FORCE_PU, cfg.fe_fpu);
40 REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu);
41 REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu);
42 REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu);
43 REG_SET_FIELD(NRXPD_CTRL, NRX_VIT_FORCE_PU, cfg.nrx_fpu);
44 REG_SET_FIELD(NRXPD_CTRL, NRX_DEMAP_FORCE_PU, cfg.nrx_fpu);
45 REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, cfg.fe_fpu);
46 REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, cfg.fe_fpu);
47 if (cfg.sram_fpu) {
48 REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, SYSCON_SRAM_POWER_UP);
49 } else {
50 REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_SRAM_POWER_UP, 0);
51 }
52 if (cfg.rom_ram_fpu) {
53 REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, SYSCON_ROM_POWER_UP);
54 } else {
55 REG_SET_FIELD(SYSCON_MEM_POWER_UP_REG, SYSCON_ROM_POWER_UP, 0);
56 }
57 }
58
dcdc_ctl(uint32_t mode)59 void dcdc_ctl(uint32_t mode)
60 {
61 REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_IDLE, RTC_CNTL_DCDC_TRX_MODE);
62 REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_MONITOR, RTC_CNTL_DCDC_TRX_MODE);
63 if ((mode & 0x10) == 0x10) {
64 REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, mode);
65 } else if (mode == 0) {
66 REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_TRX_MODE);
67 } else if (mode == 1) {
68 REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_LSLP_MODE);
69 } else if (mode == 2) {
70 REG_SET_FIELD(RTC_CNTL_DCDC_CTRL1_REG, RTC_CNTL_DCDC_MODE_SLP, RTC_CNTL_DCDC_DSLP_MODE);
71 } else {
72 SOC_LOGE(TAG, "invalid dcdc mode!\n");
73 }
74 }
75
regulator_set(regulator_cfg_t cfg)76 void regulator_set(regulator_cfg_t cfg)
77 {
78 // DIG REGULATOR0
79 if (cfg.dig_regul0_en) {
80 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PU, 0);
81 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PD, 0);
82 } else {
83 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PU, 0);
84 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_FORCE_PD, 1);
85 }
86 // DIG REGULATOR1
87 if (cfg.dig_regul1_en) {
88 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PU, 0);
89 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PD, 0);
90 } else {
91 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PU, 0);
92 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_REGULATOR_SLP_FORCE_PD, 1);
93 }
94 // RTC REGULATOR0
95 if (cfg.rtc_regul0_en) {
96 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 0);
97 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PD, 0);
98 } else {
99 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 0);
100 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PD, 1);
101 }
102 }
103
regulator_slt(regulator_config_t regula_cfg)104 void regulator_slt(regulator_config_t regula_cfg)
105 {
106 // dig regulator
107 if (regula_cfg.dig_source == 1) {
108 REG_SET_FIELD(RTC_CNTL_DIGULATOR1_DBIAS_REG, RTC_CNTL_DIG_REGULATOR1_DBIAS_SLP, regula_cfg.dig_slp_dbias);
109 REG_SET_FIELD(RTC_CNTL_DIGULATOR1_DBIAS_REG, RTC_CNTL_DIG_REGULATOR1_DBIAS_ACTIVE, regula_cfg.dig_active_dbias);
110 } else {
111 REG_SET_FIELD(RTC_CNTL_DIGULATOR0_DBIAS_REG, RTC_CNTL_DIG_REGULATOR0_DBIAS_SLP, regula_cfg.dig_slp_dbias);
112 REG_SET_FIELD(RTC_CNTL_DIGULATOR0_DBIAS_REG, RTC_CNTL_DIG_REGULATOR0_DBIAS_ACTIVE, regula_cfg.dig_active_dbias);
113 }
114 // rtc regulator
115 if (regula_cfg.rtc_source == 1) {
116 REG_SET_FIELD(RTC_CNTL_RTCULATOR1_DBIAS_REG, RTC_CNTL_REGULATOR1_DBIAS_SLP, regula_cfg.rtc_slp_dbias);
117 REG_SET_FIELD(RTC_CNTL_RTCULATOR1_DBIAS_REG, RTC_CNTL_REGULATOR1_DBIAS_ACTIVE, regula_cfg.rtc_active_dbias);
118 } else {
119 REG_SET_FIELD(RTC_CNTL_RTCULATOR0_DBIAS_REG, RTC_CNTL_REGULATOR0_DBIAS_SLP, regula_cfg.rtc_slp_dbias);
120 REG_SET_FIELD(RTC_CNTL_RTCULATOR0_DBIAS_REG, RTC_CNTL_REGULATOR0_DBIAS_ACTIVE, regula_cfg.rtc_active_dbias);
121 }
122 }
123
dbias_switch_set(dbias_swt_cfg_t cfg)124 void dbias_switch_set(dbias_swt_cfg_t cfg)
125 {
126 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_IDLE, cfg.swt_idle);
127 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_MONITOR, cfg.swt_monitor);
128 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SWITCH_SLP, cfg.swt_slp);
129 }
130
left_up_trx_fpu(bool fpu)131 void left_up_trx_fpu(bool fpu)
132 {
133 if (fpu) {
134 REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_FORCE_DISABLE_BIAS_SLEEP, 0);
135 REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_BIAS_BUF, 0);
136 REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 0);
137 SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_XPD_TRX_FORCE_PU);
138 } else {
139 CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_XPD_TRX_FORCE_PU);
140 }
141 }
142
rtc_sleep_pmu_init(void)143 void rtc_sleep_pmu_init(void)
144 {
145 dcdc_ctl(DCDC_SLP_DSLP_MODE);
146 dbias_swt_cfg_t swt_cfg = DBIAS_SWITCH_CONFIG_DEFAULT();
147 dbias_switch_set(swt_cfg);
148 regulator_config_t regula0_cfg = REGULATOR0_CONFIG_DEFAULT();
149 regulator_slt(regula0_cfg);
150 regulator_config_t regula1_cfg = REGULATOR1_CONFIG_DEFAULT();
151 regulator_slt(regula1_cfg);
152 regulator_cfg_t rg_set = REGULATOR_SET_DEFAULT();
153 regulator_set(rg_set);
154 left_up_trx_fpu(0);
155 }
156
157
rtc_sleep_init(rtc_sleep_config_t cfg)158 void rtc_sleep_init(rtc_sleep_config_t cfg)
159 {
160 if (cfg.lslp_mem_inf_fpu) {
161 rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
162 rtc_sleep_pu(pu_cfg);
163 }
164 if (cfg.bt_pd_en) {
165 SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN);
166 } else {
167 CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN);
168 }
169 if (cfg.cpu_pd_en) {
170 SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_PD_EN);
171 } else {
172 CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_PD_EN);
173 }
174 if (cfg.dig_peri_pd_en) {
175 SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN);
176 } else {
177 CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN);
178 }
179 if (cfg.dig_ret_pd_en) {
180 SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_RET_PD_EN);
181 } else {
182 CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_RET_PD_EN);
183 }
184
185 REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, RTC_CNTL_BIASSLP_MONITOR_DEFAULT);
186 REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, RTC_CNTL_BIASSLP_SLEEP_DEFAULT);
187 REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, RTC_CNTL_PD_CUR_MONITOR_DEFAULT);
188 REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, RTC_CNTL_PD_CUR_SLEEP_DEFAULT);
189 // ESP32-H2 TO-DO: IDF-3693
190 if (cfg.deep_slp) {
191 // REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0);
192 // CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU);
193 SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
194 CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,
195 RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU |
196 RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU);
197 CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU);
198 } else {
199 SET_PERI_REG_MASK(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_VDD_DRV_B_SLP_EN);
200 REG_SET_FIELD(RTC_CNTL_DIGULATOR_REG, RTC_CNTL_DG_VDD_DRV_B_SLP, RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT);
201 // SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU);
202 CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
203 }
204
205 /* enable VDDSDIO control by state machine */
206 REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
207 REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
208
209 REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject);
210 REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject);
211
212 /* gating XTAL clock */
213 REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING);
214 esp_rom_uart_tx_wait_idle(0);
215
216 }
217
rtc_sleep_low_init(uint32_t slowclk_period)218 void rtc_sleep_low_init(uint32_t slowclk_period)
219 {
220 // set 5 PWC state machine times to fit in main state machine time
221 REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
222 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));
223 REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
224 }
225
rtc_sleep_set_wakeup_time(uint64_t t)226 void rtc_sleep_set_wakeup_time(uint64_t t)
227 {
228 WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
229 WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
230 }
231
232 static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu);
233
rtc_sleep_start(uint32_t wakeup_opt,uint32_t reject_opt,uint32_t lslp_mem_inf_fpu)234 uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)
235 {
236 REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
237 REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_SLEEP_REJECT_ENA, reject_opt);
238
239 /* Start entry into sleep mode */
240 SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
241 while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG,
242 RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) {
243 ;
244 }
245
246 return rtc_sleep_finish(lslp_mem_inf_fpu);
247 }
248
249 #define STR2(X) #X
250 #define STR(X) STR2(X)
251
rtc_deep_sleep_start(uint32_t wakeup_opt,uint32_t reject_opt)252 uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
253 {
254 REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
255 WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt);
256
257 /* Calculate RTC Fast Memory CRC (for wake stub) & go to deep sleep
258
259 Because we may be running from RTC memory as stack, we can't easily call any
260 functions to do this (as registers will spill to stack, corrupting the CRC).
261
262 Instead, load all the values we need into registers then use register ops only to calculate
263 the CRC value, write it to the RTC CRC value register, and immediately go into deep sleep.
264 */
265
266 /* Values used to set the SYSTEM_RTC_FASTMEM_CONFIG_REG value */
267 const unsigned CRC_START_ADDR = 0;
268 const unsigned CRC_LEN = 0x7ff;
269
270 asm volatile(
271 /* Start CRC calculation */
272 "sw %1, 0(%0)\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN
273 "or t0, %1, %2\n"
274 "sw t0, 0(%0)\n" // set RTC_MEM_CRC_START
275
276 /* Wait for the CRC calculation to finish */
277 ".Lwaitcrc:\n"
278 "fence\n"
279 "lw t0, 0(%0)\n"
280 "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n"
281 "and t0, t0, t1\n"
282 "beqz t0, .Lwaitcrc\n"
283 "not %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START
284 "and t0, t0, %2\n"
285 "sw t0, 0(%0)\n" // clear RTC_MEM_CRC_START
286 "fence\n"
287 "not %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged
288
289 /* Store the calculated value in RTC_MEM_CRC_REG */
290 "lw t0, 0(%3)\n"
291 "sw t0, 0(%4)\n"
292 "fence\n"
293
294 /* Set register bit to go into deep sleep */
295 "lw t0, 0(%5)\n"
296 "or t0, t0, %6\n"
297 "sw t0, 0(%5)\n"
298 "fence\n"
299
300 /* Wait for sleep reject interrupt (never finishes if successful) */
301 ".Lwaitsleep:"
302 "fence\n"
303 "lw t0, 0(%7)\n"
304 "and t0, t0, %8\n"
305 "beqz t0, .Lwaitsleep\n"
306
307 :
308 :
309 "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG), // %0
310 "r" ( (CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S)
311 | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)), // %1
312 "r" (SYSTEM_RTC_MEM_CRC_START), // %2
313 "r" (SYSTEM_RTC_FASTMEM_CRC_REG), // %3
314 "r" (RTC_MEMORY_CRC_REG), // %4
315 "r" (RTC_CNTL_STATE0_REG), // %5
316 "r" (RTC_CNTL_SLEEP_EN), // %6
317 "r" (RTC_CNTL_INT_RAW_REG), // %7
318 "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8
319 : "t0", "t1" // working registers
320 );
321
322 return rtc_sleep_finish(0);
323 }
324
rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)325 static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)
326 {
327 /* In deep sleep mode, we never get here */
328 uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW);
329 SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
330 RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
331
332 /* restore config if it is a light sleep */
333 if (lslp_mem_inf_fpu) {
334 rtc_sleep_pu_config_t pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
335 rtc_sleep_pu(pu_cfg);
336 }
337 return reject;
338 }
339