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/rtc_cntl_reg.h"
11 #include "soc/syscon_reg.h"
12 #include "soc/dport_reg.h"
13 #include "soc/i2s_reg.h"
14 #include "soc/timer_group_reg.h"
15 #include "soc/bb_reg.h"
16 #include "soc/nrx_reg.h"
17 #include "soc/fe_reg.h"
18 #include "esp32s2/rom/ets_sys.h"
19 #include "esp32s2/rom/rtc.h"
20 #include "hal/rtc_cntl_ll.h"
21 #include "hal/misc.h"
22 
23 /**
24  * Configure whether certain peripherals are powered down in deep sleep
25  * @param cfg power down flags as rtc_sleep_pd_config_t structure
26  */
rtc_sleep_pd(rtc_sleep_pd_config_t cfg)27 void rtc_sleep_pd(rtc_sleep_pd_config_t cfg)
28 {
29     REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu);
30     REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, cfg.rtc_fpu);
31     REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_LPU, cfg.rtc_fpu);
32     REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_PLC_MEM_FORCE_PU, cfg.i2s_fpu);
33     REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_FIFO_FORCE_PU, cfg.i2s_fpu);
34     REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_DC_MEM_FORCE_PU, cfg.fe_fpu);
35     REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_PBUS_MEM_FORCE_PU, cfg.fe_fpu);
36     REG_SET_FIELD(SYSCON_FRONT_END_MEM_PD_REG, SYSCON_AGC_MEM_FORCE_PU, cfg.fe_fpu);
37     REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu);
38     REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu);
39     REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu);
40     REG_SET_FIELD(NRXPD_CTRL, NRX_VIT_FORCE_PU, cfg.nrx_fpu);
41     REG_SET_FIELD(NRXPD_CTRL, NRX_DEMAP_FORCE_PU, cfg.nrx_fpu);
42     REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, cfg.fe_fpu);
43     REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, cfg.fe_fpu);
44 }
45 
rtc_sleep_get_default_config(uint32_t sleep_flags,rtc_sleep_config_t * out_config)46 void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_config)
47 {
48     *out_config = (rtc_sleep_config_t) {
49         .lslp_mem_inf_fpu = 0,
50         .rtc_mem_inf_follow_cpu = (sleep_flags & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0,
51         .rtc_fastmem_pd_en = (sleep_flags & RTC_SLEEP_PD_RTC_FAST_MEM) ? 1 : 0,
52         .rtc_slowmem_pd_en = (sleep_flags & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0,
53         .rtc_peri_pd_en = (sleep_flags & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0,
54         .wifi_pd_en = (sleep_flags & RTC_SLEEP_PD_WIFI) ? 1 : 0,
55         .int_8m_pd_en = (sleep_flags & RTC_SLEEP_PD_INT_8M) ? 1 : 0,
56         .deep_slp = (sleep_flags & RTC_SLEEP_PD_DIG) ? 1 : 0,
57         .wdt_flashboot_mod_en = 0,
58         .vddsdio_pd_en = (sleep_flags & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0,
59         .xtal_fpu = (sleep_flags & RTC_SLEEP_PD_XTAL) ? 0 : 1,
60         .deep_slp_reject = 1,
61         .light_slp_reject = 1
62     };
63 
64     if (sleep_flags & RTC_SLEEP_PD_DIG) {
65         assert(sleep_flags & RTC_SLEEP_PD_XTAL);
66         out_config->dig_dbias_slp = 0;  //not used
67         //rtc voltage from high to low
68         if ((sleep_flags & RTC_SLEEP_USE_ADC_TESEN_MONITOR) || !(sleep_flags & RTC_SLEEP_PD_INT_8M)) {
69             /*
70              * rtc voltage in sleep mode >= 0.9v
71              * if 8MD256 select as RTC slow clock src, only need dbg_atten_slp set to 0
72              * Support all features:
73              * - ADC/Temperature sensor in monitor mode (ULP) (also need pd_cur_monitor = 0)
74              * - 8MD256 as RTC slow clock src
75              * - RTC IO as input
76              * - RTC Memory at high temperature
77              * - ULP
78              * - Touch sensor
79              */
80             out_config->rtc_regulator_fpu = 1;
81             out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP;
82             out_config->rtc_dbias_slp = RTC_CNTL_DBIAS_0V90;
83         } else if (sleep_flags & RTC_SLEEP_NO_ULTRA_LOW) {
84             /*
85              * rtc voltage in sleep mode >= 0.7v (default mode)
86              * Support features:
87              * - RTC IO as input
88              * - RTC Memory at high temperature
89              * - ULP
90              * - Touch sensor
91              */
92             out_config->rtc_regulator_fpu = 1;
93             out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT;
94             out_config->rtc_dbias_slp = RTC_CNTL_RTC_DBIAS_DEEPSLEEP_0V7;
95         } else {
96             /*
97              * rtc regulator not opened and rtc voltage is about 0.66v (ultra low power)
98              * Support features:
99              * - ULP
100              * - Touch sensor
101              */
102             out_config->rtc_regulator_fpu = 0;
103             out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT;
104             out_config->rtc_dbias_slp = 0;
105         }
106     } else {
107         out_config->rtc_regulator_fpu = 1;
108         // rtc & digital voltage from high to low
109         if ((sleep_flags & RTC_SLEEP_DIG_USE_8M) || !(sleep_flags & RTC_SLEEP_PD_XTAL) || !(sleep_flags & RTC_SLEEP_PD_INT_8M)) {
110             /*
111              * digital voltage need to be >= 1.1v
112              * if 8MD256 select as RTC slow clock src, only need dbg_atten_slp set to 0
113              * rtc voltage need to near digital voltage to keep system stable
114              * Support all features:
115              * - XTAL
116              * - RC 8M used by digital system
117              * - 8MD256 as RTC slow clock src (only need dbg_atten_slp set to 0)
118              * - ADC/Temperature sensor in monitor mode (ULP) (also need pd_cur_monitor = 0)
119              * - ULP
120              * - Touch sensor
121              */
122             out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP;
123             out_config->dig_dbias_slp = RTC_CNTL_DBIAS_1V10;
124             out_config->rtc_dbias_slp = RTC_CNTL_DBIAS_1V10;
125         } else if (sleep_flags & RTC_SLEEP_USE_ADC_TESEN_MONITOR) {
126             /*
127              * rtc voltage need to be >= 0.9v
128              * digital voltage need to near rtc voltage to make system stable and low current
129              * Support features:
130              * - ADC/Temperature sensor in monitor mode (ULP) (also need pd_cur_monitor = 0)
131              * - ULP
132              * - Touch sensor
133             */
134             out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT;
135             out_config->dig_dbias_slp = RTC_CNTL_DIG_DBIAS_LIGHTSLEEP_0V9;
136             out_config->rtc_dbias_slp = RTC_CNTL_RTC_DBIAS_LIGHTSLEEP_0V9;
137         } else {
138             /*
139              * digital voltage not less than 0.75v.
140              * rtc voltage need to near digital voltage to keep system stable
141              * Support features:
142              * - ULP
143              * - Touch sensor
144             */
145             out_config->dbg_atten_slp = RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT;
146             out_config->dig_dbias_slp = RTC_CNTL_DIG_DBIAS_LIGHTSLEEP_0V75;
147             out_config->rtc_dbias_slp = RTC_CNTL_RTC_DBIAS_LIGHTSLEEP_0V75;
148         }
149     }
150     if (!(sleep_flags & RTC_SLEEP_PD_XTAL)) {
151         out_config->bias_sleep_monitor = RTC_CNTL_BIASSLP_MONITOR_ON;
152         out_config->pd_cur_monitor = RTC_CNTL_PD_CUR_MONITOR_ON;
153         out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_ON;
154         out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_ON;
155     } else {
156         out_config->bias_sleep_monitor = RTC_CNTL_BIASSLP_MONITOR_DEFAULT;
157         out_config->pd_cur_monitor = (sleep_flags & RTC_SLEEP_USE_ADC_TESEN_MONITOR)?
158                                     RTC_CNTL_PD_CUR_MONITOR_ON : RTC_CNTL_PD_CUR_MONITOR_DEFAULT;
159         out_config->bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT;
160         out_config->pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT;
161     }
162 }
163 
rtc_sleep_init(rtc_sleep_config_t cfg)164 void rtc_sleep_init(rtc_sleep_config_t cfg)
165 {
166     if (cfg.lslp_mem_inf_fpu) {
167         rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(1);
168         rtc_sleep_pd(pd_cfg);
169     }
170 
171     if (cfg.rtc_mem_inf_follow_cpu) {
172         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FOLW_CPU);
173     } else {
174         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FOLW_CPU);
175     }
176 
177     if (cfg.rtc_fastmem_pd_en) {
178         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_PD_EN);
179         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_PU);
180         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO);
181     } else {
182         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_PD_EN);
183         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_PU);
184         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO);
185     }
186 
187     if (cfg.rtc_slowmem_pd_en) {
188         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_PD_EN);
189         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU);
190         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_NOISO);
191     } else {
192         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_PD_EN);
193         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU);
194         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_NOISO);
195     }
196 
197     if (cfg.rtc_peri_pd_en) {
198         SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PD_EN);
199     } else {
200         CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PD_EN);
201     }
202 
203     if (cfg.wifi_pd_en) {
204         REG_CLR_BIT(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
205         REG_CLR_BIT(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
206         SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
207     } else {
208         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
209     }
210 
211     assert(!cfg.pd_cur_monitor || cfg.bias_sleep_monitor);
212     assert(!cfg.pd_cur_slp || cfg.bias_sleep_slp);
213 
214     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, cfg.rtc_dbias_slp);
215     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_SLP, cfg.dig_dbias_slp);
216 
217     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
218     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, cfg.bias_sleep_monitor);
219     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, cfg.bias_sleep_slp);
220     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, cfg.pd_cur_monitor);
221     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, cfg.pd_cur_slp);
222     REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, cfg.dbg_atten_slp);
223 
224     if (cfg.deep_slp) {
225         SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
226         CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,
227                             RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU |
228                             RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU);
229         CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PU);
230     } else {
231         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
232     }
233 
234     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, cfg.rtc_regulator_fpu);
235     if (!cfg.int_8m_pd_en) {
236         REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
237     } else {
238         REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
239     }
240 
241     /* enable VDDSDIO control by state machine */
242     REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
243     REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
244 
245     REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject);
246     REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject);
247     /* Set wait cycle for touch or COCPU after deep sleep and light sleep. */
248     REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP);
249 
250     REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu);
251 }
252 
rtc_sleep_low_init(uint32_t slowclk_period)253 void rtc_sleep_low_init(uint32_t slowclk_period)
254 {
255     REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
256     REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
257     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));
258 }
259 
260 /* Read back 'reject' status when waking from light or deep sleep */
261 static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu);
262 
rtc_sleep_start(uint32_t wakeup_opt,uint32_t reject_opt,uint32_t lslp_mem_inf_fpu)263 uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)
264 {
265     REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
266     REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_SLEEP_REJECT_ENA, reject_opt);
267     if (reject_opt != 0) {
268         REG_SET_BIT(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN);
269     }
270 
271     SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
272                       RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
273 
274     /* Start entry into sleep mode */
275     SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
276 
277     while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG,
278                              RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) {
279         ;
280     }
281 
282     return rtc_sleep_finish(lslp_mem_inf_fpu);
283 }
284 
285 #define STR2(X) #X
286 #define STR(X) STR2(X)
287 
rtc_deep_sleep_start(uint32_t wakeup_opt,uint32_t reject_opt)288 uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
289 {
290     REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
291     WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt);
292 
293     SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
294                       RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
295 
296     /* Calculate RTC Fast Memory CRC (for wake stub) & go to deep sleep
297 
298        Because we may be running from RTC memory as stack, we can't easily call any
299        functions to do this (as registers may spill to stack, corrupting the CRC).
300 
301        Instead, load all the values we need into registers (triggering any stack spills)
302        then use register ops only to calculate the CRC value, write it to the RTC CRC value
303        register, and immediately go into deep sleep.
304      */
305 
306     /* Values used to set the DPORT_RTC_FASTMEM_CONFIG_REG value */
307     const unsigned CRC_START_ADDR = 0;
308     const unsigned CRC_LEN = 0x7ff;
309 
310     asm volatile(
311                  "movi a2, 0\n" // trigger a stack spill on working register if needed
312 
313                  /* Start CRC calculation */
314                  "s32i %1, %0, 0\n" // set RTC_MEM_CRC_ADDR & RTC_MEM_CRC_LEN
315                  "or a2, %1, %2\n"
316                  "s32i a2, %0, 0\n" // set RTC_MEM_CRC_START
317 
318                  /* Wait for the CRC calculation to finish */
319                  ".Lwaitcrc:\n"
320                  "memw\n"
321                  "l32i a2, %0, 0\n"
322                  "bbci a2, "STR(DPORT_RTC_MEM_CRC_FINISH_S)", .Lwaitcrc\n"
323                  "xor %2, %2, %2\n" // %2 -> ~DPORT_RTC_MEM_CRC_START
324                  "and a2, a2, %2\n"
325                  "s32i a2, %0, 0\n"  // clear RTC_MEM_CRC_START
326                  "memw\n"
327                  "xor %2, %2, %2\n" // %2 -> DPORT_RTC_MEM_CRC_START, probably unnecessary but gcc assumes inputs unchanged
328 
329                  /* Store the calculated value in RTC_MEM_CRC_REG */
330                  "l32i a2, %3, 0\n"
331                  "s32i a2, %4, 0\n"
332                  "memw\n"
333 
334                  /* Set register bit to go into deep sleep */
335                  "l32i a2, %5, 0\n"
336                  "or   a2, a2, %6\n"
337                  "s32i a2, %5, 0\n"
338                  "memw\n"
339 
340                  /* Wait for sleep reject interrupt (never finishes if successful) */
341                  ".Lwaitsleep:"
342                  "memw\n"
343                  "l32i a2, %7, 0\n"
344                  "and a2, a2, %8\n"
345                  "beqz a2, .Lwaitsleep\n"
346 
347                  :
348                  : /* Note, at -O0 this is the limit of available registers in this function */
349                    "r" (DPORT_RTC_FASTMEM_CONFIG_REG), // %0
350                    "r" ( (CRC_START_ADDR << DPORT_RTC_MEM_CRC_START_S)
351                          | (CRC_LEN << DPORT_RTC_MEM_CRC_LEN_S)), // %1
352                    "r" (DPORT_RTC_MEM_CRC_START), // %2
353                    "r" (DPORT_RTC_FASTMEM_CRC_REG), // %3
354                    "r" (RTC_MEMORY_CRC_REG), // %4
355                    "r" (RTC_CNTL_STATE0_REG), // %5
356                    "r" (RTC_CNTL_SLEEP_EN), // %6
357                    "r" (RTC_CNTL_INT_RAW_REG), // %7
358                    "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) // %8
359                  : "a2" // working register
360                  );
361 
362     return rtc_sleep_finish(0);
363 }
364 
rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)365 static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)
366 {
367     /* In deep sleep mode, we never get here */
368     uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW);
369     SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
370                       RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
371 
372     /* restore config if it is a light sleep */
373     if (lslp_mem_inf_fpu) {
374         rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(0);
375         rtc_sleep_pd(pd_cfg);
376     }
377 
378     /* Recover default wait cycle for touch or COCPU after wakeup. */
379     REG_SET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT);
380 
381     return reject;
382 }
383