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