• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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