1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 #include "soc/soc.h"
9 #include "soc/rtc.h"
10 #include "soc/dport_reg.h"
11 #include "soc/i2s_periph.h"
12 #include "soc/timer_periph.h"
13 #include "soc/bb_reg.h"
14 #include "soc/nrx_reg.h"
15 #include "soc/fe_reg.h"
16 #include "esp32/rom/ets_sys.h"
17 #include "esp32/rom/rtc.h"
18 #include "hal/rtc_cntl_ll.h"
19 #include "esp_rom_sys.h"
20 
21 #define MHZ (1000000)
22 
23 #define ROM_RAM_POWERUP_CYCLES   RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
24 #define ROM_RAM_WAIT_CYCLES      RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
25 
26 #define WIFI_POWERUP_CYCLES      RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
27 #define WIFI_WAIT_CYCLES         RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
28 
29 #define RTC_POWERUP_CYCLES       RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
30 #define RTC_WAIT_CYCLES          RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
31 
32 #define DG_WRAP_POWERUP_CYCLES   RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
33 #define DG_WRAP_WAIT_CYCLES      RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
34 
35 #define RTC_MEM_POWERUP_CYCLES   RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES
36 #define RTC_MEM_WAIT_CYCLES      RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES
37 
38 /**
39  * @brief Power down flags for rtc_sleep_pd function
40  */
41 typedef struct {
42     uint32_t dig_pd : 1;    //!< Set to 1 to power down digital part in sleep
43     uint32_t rtc_pd : 1;    //!< Set to 1 to power down RTC memories in sleep
44     uint32_t cpu_pd : 1;    //!< Set to 1 to power down digital memories and CPU in sleep
45     uint32_t i2s_pd : 1;    //!< Set to 1 to power down I2S in sleep
46     uint32_t bb_pd : 1;     //!< Set to 1 to power down WiFi in sleep
47     uint32_t nrx_pd : 1;    //!< Set to 1 to power down WiFi in sleep
48     uint32_t fe_pd : 1;     //!< Set to 1 to power down WiFi in sleep
49 } rtc_sleep_pd_config_t;
50 
51 /**
52  * Initializer for rtc_sleep_pd_config_t which sets all flags to the same value
53  */
54 #define RTC_SLEEP_PD_CONFIG_ALL(val) {\
55     .dig_pd = (val), \
56     .rtc_pd = (val), \
57     .cpu_pd = (val), \
58     .i2s_pd = (val), \
59     .bb_pd = (val), \
60     .nrx_pd = (val), \
61     .fe_pd = (val), \
62 }
63 
64 /**
65  * Configure whether certain peripherals are powered down in deep sleep
66  * @param cfg power down flags as rtc_sleep_pd_config_t structure
67  */
rtc_sleep_pd(rtc_sleep_pd_config_t cfg)68 static void rtc_sleep_pd(rtc_sleep_pd_config_t cfg)
69 {
70     REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, ~cfg.dig_pd);
71     REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_LPU, ~cfg.rtc_pd);
72     REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, ~cfg.rtc_pd);
73     DPORT_REG_SET_FIELD(DPORT_MEM_PD_MASK_REG, DPORT_LSLP_MEM_PD_MASK, ~cfg.cpu_pd);
74     REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_PLC_MEM_FORCE_PU, ~cfg.i2s_pd);
75     REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_FIFO_FORCE_PU, ~cfg.i2s_pd);
76     REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, ~cfg.bb_pd);
77     REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, ~cfg.bb_pd);
78     REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, ~cfg.nrx_pd);
79     REG_SET_FIELD(NRXPD_CTRL, NRX_VIT_FORCE_PU, ~cfg.nrx_pd);
80     REG_SET_FIELD(NRXPD_CTRL, NRX_DEMAP_FORCE_PU, ~cfg.nrx_pd);
81     REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, ~cfg.fe_pd);
82     REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, ~cfg.fe_pd);
83 }
84 
rtc_sleep_get_default_config(uint32_t sleep_flags,rtc_sleep_config_t * out_config)85 void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_config)
86 {
87     *out_config = (rtc_sleep_config_t) {
88         .lslp_mem_inf_fpu = 0,
89         .rtc_mem_inf_fpu = 0,
90         .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0,
91         .rtc_fastmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_FAST_MEM) ? 1 : 0,
92         .rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0,
93         .rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0,
94         .modem_pd_en = (sleep_flags & RTC_SLEEP_PD_MODEM) ? 1 : 0,
95         .int_8m_pd_en = ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0,
96         .rom_mem_pd_en = 0,
97         .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0,
98         .wdt_flashboot_mod_en = 0,
99         .lslp_meminf_pd = 1,
100         .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0,
101         .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1,
102         .deep_slp_reject = 1,
103         .light_slp_reject = 1,
104     };
105 
106     if ((sleep_flags) & RTC_SLEEP_PD_DIG) {
107         out_config->dig_dbias_wak = RTC_CNTL_DBIAS_1V10;
108         out_config->dig_dbias_slp = RTC_CNTL_DBIAS_0V90;
109         out_config->rtc_dbias_wak = RTC_CNTL_DBIAS_1V10;
110         out_config->rtc_dbias_slp = RTC_CNTL_DBIAS_0V90;
111         out_config->dbg_atten_slp = !(sleep_flags & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBG_ATTEN_NODROP : RTC_CNTL_DBG_ATTEN_DEFAULT;
112     } else {
113         out_config->dig_dbias_wak = RTC_CNTL_DBIAS_1V10;
114         out_config->dig_dbias_slp = !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 : RTC_CNTL_DBIAS_0V90;
115         out_config->rtc_dbias_wak = RTC_CNTL_DBIAS_1V10;
116         out_config->rtc_dbias_slp = !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 : RTC_CNTL_DBIAS_0V90;
117         out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_NODROP;
118     }
119 }
120 
rtc_sleep_init(rtc_sleep_config_t cfg)121 void rtc_sleep_init(rtc_sleep_config_t cfg)
122 {
123     // set shortest possible sleep time limit
124     REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN);
125 
126     // set rom&ram timer
127     REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, ROM_RAM_POWERUP_CYCLES);
128     REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, ROM_RAM_WAIT_CYCLES);
129     // set wifi timer
130     REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, WIFI_POWERUP_CYCLES);
131     REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, WIFI_WAIT_CYCLES);
132     // set rtc peri timer
133     REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_POWERUP_TIMER, RTC_POWERUP_CYCLES);
134     REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_WAIT_TIMER, RTC_WAIT_CYCLES);
135     // set digital wrap timer
136     REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER, DG_WRAP_POWERUP_CYCLES);
137     REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER, DG_WRAP_WAIT_CYCLES);
138     // set rtc memory timer
139     REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_POWERUP_TIMER, RTC_MEM_POWERUP_CYCLES);
140     REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_WAIT_TIMER, RTC_MEM_WAIT_CYCLES);
141 
142     REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.lslp_mem_inf_fpu);
143 
144     rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(cfg.lslp_meminf_pd);
145     rtc_sleep_pd(pd_cfg);
146 
147     if (cfg.rtc_mem_inf_fpu) {
148         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
149     } else {
150         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
151     }
152 
153     if (cfg.rtc_mem_inf_follow_cpu) {
154         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FOLW_CPU);
155     } else {
156         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FOLW_CPU);
157     }
158 
159     if (cfg.rtc_fastmem_pd_en) {
160         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_PD_EN);
161         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_PU);
162         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO);
163     } else {
164         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_PD_EN);
165         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_PU);
166         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO);
167     }
168 
169     if (cfg.rtc_slowmem_pd_en) {
170         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_PD_EN);
171         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU);
172         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_NOISO);
173     } else {
174         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_PD_EN);
175         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU);
176         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_NOISO);
177     }
178 
179     if (cfg.rtc_peri_pd_en) {
180         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PD_EN);
181     } else {
182         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PD_EN);
183     }
184 
185     if (cfg.modem_pd_en) {
186         REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
187         REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
188         SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
189     } else {
190         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
191     }
192 
193     if (cfg.rom_mem_pd_en) {
194         SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_ROM_RAM_PD_EN);
195     } else {
196         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_ROM_RAM_PD_EN);
197     }
198 
199     if (cfg.deep_slp) {
200         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG,
201                 RTC_CNTL_DG_PAD_FORCE_ISO | RTC_CNTL_DG_PAD_FORCE_NOISO);
202         SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
203         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG,
204                 RTC_CNTL_DG_WRAP_FORCE_PU | RTC_CNTL_DG_WRAP_FORCE_PD);
205         CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_FORCE_NOSLEEP);
206 
207         // Shut down parts of RTC which may have been left enabled by the wireless drivers
208         CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,
209                 RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU |
210                 RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU);
211         CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU);
212     } else {
213         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
214     }
215 
216     REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu);
217 
218     if (!cfg.int_8m_pd_en) {
219         REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
220     } else {
221         REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
222     }
223 
224     /* enable VDDSDIO control by state machine */
225     REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
226     REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
227 
228     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, cfg.rtc_dbias_slp);
229     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, cfg.rtc_dbias_wak);
230     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, cfg.dig_dbias_wak);
231     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_SLP, cfg.dig_dbias_slp);
232     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, cfg.dbg_atten_slp);
233 
234     REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject);
235     REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject);
236 }
237 
rtc_sleep_low_init(uint32_t slowclk_period)238 void rtc_sleep_low_init(uint32_t slowclk_period)
239 {
240     // set 5 PWC state machine times to fit in main state machine time
241     REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
242     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));
243     REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
244 }
245 
246 /* Read back 'reject' status when waking from light or deep sleep */
247 static uint32_t rtc_sleep_finish(void);
248 
rtc_sleep_start(uint32_t wakeup_opt,uint32_t reject_opt)249 uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
250 {
251     REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
252     WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt);
253 
254     SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
255             RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
256 
257     /* Start entry into sleep mode */
258     SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
259 
260     while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG,
261                              RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) {
262         ;
263     }
264 
265     return rtc_sleep_finish();
266 }
267 
268 #define STR2(X) #X
269 #define STR(X) STR2(X)
270 
rtc_deep_sleep_start(uint32_t wakeup_opt,uint32_t reject_opt)271 uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
272 {
273     REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
274     WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt);
275 
276     SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
277             RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
278 
279     /* Calculate RTC Fast Memory CRC (for wake stub) & go to deep sleep
280 
281        Because we may be running from RTC memory as stack, we can't easily call any
282        functions to do this (as registers may spill to stack, corrupting the CRC).
283 
284        Instead, load all the values we need into registers (triggering any stack spills)
285        then use register ops only to calculate the CRC value, write it to the RTC CRC value
286        register, and immediately go into deep sleep.
287      */
288 
289     /* Values used to set the RTC_MEM_CONFG value */
290     const unsigned CRC_START_ADDR = 0;
291     const unsigned CRC_LEN = 0x7ff;
292     const unsigned RTC_MEM_PID = 1;
293 
294     __asm__ volatile(
295                  "movi a2, 0\n" // trigger a stack spill on working register if needed
296 
297                  /* Start CRC calculation */
298                  "s32i %1, %0, 0\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN
299                  "or a2, %1, %2\n"
300                  "s32i a2, %0, 0\n" // set RTC_MEM_CRC_START
301 
302                  /* Wait for the CRC calculation to finish */
303                  ".Lwaitcrc:\n"
304                  "memw\n"
305                  "l32i a2, %0, 0\n"
306                  "bbci a2, "STR(RTC_MEM_CRC_FINISH_S)", .Lwaitcrc\n"
307                  "and a2, a2, %3\n" // clear RTC_MEM_CRC_START
308                  "s32i a2, %0, 0\n"
309                  "memw\n"
310 
311                  /* Store the calculated value in RTC_MEM_CRC_REG */
312                  "l32i a2, %4, 0\n"
313                  "s32i a2, %5, 0\n"
314                  "memw\n"
315 
316                  /* Set register bit to go into deep sleep */
317                  "l32i a2, %6, 0\n"
318                  "or   a2, a2, %7\n"
319                  "s32i a2, %6, 0\n"
320                  "memw\n"
321 
322                  /* Set wait cycle for touch or COCPU after deep sleep. */
323                  ".Lwaitsleep:"
324                  "memw\n"
325                  "l32i a2, %8, 0\n"
326                  "and a2, a2, %9\n"
327                  "beqz a2, .Lwaitsleep\n"
328 
329                  :
330                  : "r" (RTC_MEM_CONF), // %0
331                    "r" ( (CRC_START_ADDR << RTC_MEM_CRC_ADDR_S)
332                          | (CRC_LEN << RTC_MEM_CRC_LEN_S)
333                          | (RTC_MEM_PID << RTC_MEM_PID_CONF_S) ), // %1
334                    "r" (RTC_MEM_CRC_START), // %2
335                    "r" (~RTC_MEM_CRC_START), // %3
336                    "r" (RTC_MEM_CRC_RES), // %4
337                    "r" (RTC_MEMORY_CRC_REG), // %5
338                    "r" (RTC_CNTL_STATE0_REG), // %6
339                    "r" (RTC_CNTL_SLEEP_EN), // %7
340                    "r" (RTC_CNTL_INT_RAW_REG), // %8
341                    "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %9
342                  : "a2" // working register
343                  );
344 
345     return rtc_sleep_finish();
346 }
347 
rtc_sleep_finish(void)348 static uint32_t rtc_sleep_finish(void)
349 {
350     /* In deep sleep mode, we never get here */
351     uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW);
352     SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
353             RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
354 
355     /* restore DBG_ATTEN to the default value */
356     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, RTC_CNTL_DBG_ATTEN_DEFAULT);
357     return reject;
358 }
359