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