1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18
19 /********************************************************************************************************
20 * @file pm.c
21 *
22 * @brief This is the source file for B91
23 *
24 * @author Driver Group
25 *
26 *******************************************************************************************************/
27 #include "pm.h"
28 #include "gpio.h"
29 #include "compiler.h"
30 #include "core.h"
31 #include "mspi.h"
32 #include "clock.h"
33 #include "flash.h"
34 #include "stimer.h"
35
36
37 _attribute_data_retention_sec_ _attribute_aligned_(4) pm_status_info_s g_pm_status_info;
38
39 //system timer clock source is constant 16M, never change
40 //NOTICE:We think that the external 32k crystal clk is very accurate, does not need to read through TIMER_32K_LAT_CAL.
41 //register, the conversion error(use 32k:16 cycle, count 16M sys tmr's ticks), at least the introduction of 64ppm.
42 #define CRYSTAL32768_TICK_PER_32CYCLE 15625 // 7812.5 * 2
43
44 _attribute_data_retention_sec_ unsigned int g_pm_tick_32k_calib;
45 _attribute_data_retention_sec_ unsigned int g_pm_tick_cur;
46 _attribute_data_retention_sec_ unsigned int g_pm_tick_32k_cur;
47 _attribute_data_retention_sec_ unsigned char g_pm_long_suspend;
48 _attribute_data_retention_sec_ unsigned char g_pm_vbat_v;
49 _attribute_data_retention_sec_ unsigned char g_pm_tick_update_en;
50 _attribute_data_retention_sec_ unsigned char g_pm_suspend_power_cfg=0x87;
51 _attribute_data_retention_sec_ unsigned int g_pm_multi_addr=0;
52
53 _attribute_data_retention_sec_
54 volatile pm_early_wakeup_time_us_s g_pm_early_wakeup_time_us = {
55 .suspend_early_wakeup_time_us = 100 + 188 + 109 + 200 + 225, //188(r_delay) + 109(3.5*(1/32k)) + 200(XTAL_delay) + 225(code)
56 .deep_ret_early_wakeup_time_us = 188 + 109, //188(r_delay) + 109(3.5*(1/32k))
57 .deep_early_wakeup_time_us = 688 + 259, //688(r_delay) + 109(3.5*(1/32k)) + 150(boot_rom)
58 .sleep_min_time_us = 100 + 688 + 259 + 200, //(the maximum value of suspend and deep) + 200. 200 means more margin, >32 is enough.
59 };
60
61 _attribute_data_retention_sec_
62 volatile pm_early_wakeup_time_us_s g_pm_longsleep_early_wakeup_time_us = {
63 .suspend_early_wakeup_time_us = 23,
64 .deep_ret_early_wakeup_time_us = 10 ,
65 .deep_early_wakeup_time_us = 32 ,
66 .sleep_min_time_us = 25,
67
68 };
69
70 _attribute_data_retention_sec_
71 volatile pm_r_delay_cycle_s g_pm_r_delay_cycle = {
72
73 .deep_r_delay_cycle = 3 + 8, // 11 * (1/16k) = 687.5
74 .suspend_ret_r_delay_cycle = 3, // 2 * 1/16k = 125 uS, 3 * 1/16k = 187.5 uS 4*1/16k = 250 uS
75 };
76
77 /**
78 * @brief This function configures pm wakeup time parameter.
79 * @param[in] param - pm wakeup time parameter.
80 * @return none.
81 */
pm_set_wakeup_time_param(pm_r_delay_cycle_s param)82 void pm_set_wakeup_time_param(pm_r_delay_cycle_s param)
83 {
84 g_pm_r_delay_cycle.deep_r_delay_cycle = param.deep_r_delay_cycle;
85 g_pm_r_delay_cycle.suspend_ret_r_delay_cycle = param.suspend_ret_r_delay_cycle;
86
87 int deep_rx_delay_us = g_pm_r_delay_cycle.deep_r_delay_cycle *1000 /16;
88 int suspend_ret_rx_delay_us = g_pm_r_delay_cycle.suspend_ret_r_delay_cycle *1000 /16;
89 g_pm_early_wakeup_time_us.suspend_early_wakeup_time_us = suspend_ret_rx_delay_us + 120 + 200 + 220;
90 g_pm_early_wakeup_time_us.deep_ret_early_wakeup_time_us = suspend_ret_rx_delay_us + 120 ;//64
91 g_pm_early_wakeup_time_us.deep_early_wakeup_time_us = deep_rx_delay_us + 259;
92 if(g_pm_early_wakeup_time_us.deep_early_wakeup_time_us < g_pm_early_wakeup_time_us.suspend_early_wakeup_time_us)
93 {
94 g_pm_early_wakeup_time_us.sleep_min_time_us = g_pm_early_wakeup_time_us.suspend_early_wakeup_time_us + 200;
95 }
96 else
97 {
98 g_pm_early_wakeup_time_us.sleep_min_time_us = g_pm_early_wakeup_time_us.deep_early_wakeup_time_us + 200;
99 }
100 }
101
102 /**
103 * @brief This function serves to recover system timer.
104 * The code is placed in the ram code section, in order to shorten the time.
105 * @return none.
106 */
pm_stimer_recover(void)107 void pm_stimer_recover(void)
108 {
109 #if SYS_TIMER_AUTO_MODE
110 REG_ADDR8(0x140218) = 0x02; //sys tick 16M set upon next 32k posedge
111 reg_system_ctrl |=(FLD_SYSTEM_TIMER_AUTO|FLD_SYSTEM_32K_TRACK_EN) ;
112 unsigned int now_tick_32k = clock_get_32k_tick();
113 if(g_pm_long_suspend){
114 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k + 1 - pmcd.ref_tick_32k) / 32 * g_pm_tick_32k_calib;
115 }else{
116 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k + 1 - pmcd.ref_tick_32k) * g_pm_tick_32k_calib / 32; // current clock
117 }
118 pmcd.rc32_wakeup = now_tick_32k + 1;
119 pmcd.rc32 = now_tick_32k + 1 - pmcd.ref_tick_32k;
120 reg_system_tick = g_pm_tick_cur + 1;
121 //wait cmd set dly done upon next 32k posedge
122 //if not using status bit, wait at least 1 32k cycle to set register r_run_upon_next_32k back to 0, or before next normal set
123 while((reg_system_st & BIT(7)) == 0); //system timer set done status upon next 32k posedge
124 REG_ADDR8(0x140218) = 0;//normal sys tick (16/sys) update
125 #else
126 unsigned int now_tick_32k = clock_get_32k_tick();
127 if(g_pm_long_suspend){
128 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k - pmcd.ref_tick_32k) / 32 * g_pm_tick_32k_calib;
129 }else{
130 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k - pmcd.ref_tick_32k) * g_pm_tick_32k_calib / 32; // current clock
131 }
132 pmcd.rc32_wakeup = now_tick_32k;
133 pmcd.rc32 = now_tick_32k - pmcd.ref_tick_32k;
134 reg_system_tick = g_pm_tick_cur;
135 reg_system_ctrl |= FLD_SYSTEM_32K_TRACK_EN | FLD_SYSTEM_TIMER_EN;
136 #endif
137 }
138
139 /**
140 * @brief This function configures a GPIO pin as the wakeup pin.
141 * @param[in] pin - the pin needs to be configured as wakeup pin.
142 * @param[in] pol - the wakeup polarity of the pad pin(0: low-level wakeup, 1: high-level wakeup).
143 * @param[in] en - enable or disable the wakeup function for the pan pin(1: enable, 0: disable).
144 * @return none.
145 */
pm_set_gpio_wakeup(gpio_pin_e pin,pm_gpio_wakeup_level_e pol,int en)146 void pm_set_gpio_wakeup (gpio_pin_e pin, pm_gpio_wakeup_level_e pol, int en)
147 {
148 ///////////////////////////////////////////////////////////
149 // PA[7:0] PB[7:0] PC[7:0] PD[7:0] PE[7:0]
150 // en: ana_0x41<7:0> ana_0x42<7:0> ana_0x43<7:0> ana_0x44<7:0> ana_0x45<7:0>
151 // pol: ana_0x46<7:0> ana_0x47<7:0> ana_0x48<7:0> ana_0x49<7:0> ana_0x4a<7:0>
152 unsigned char mask = pin & 0xff;
153 unsigned char areg;
154 unsigned char val;
155
156 ////////////////////////// polarity ////////////////////////
157 areg = ((pin>>8) + 0x41);
158 val = analog_read_reg8(areg);
159 if (pol) {
160 val &= ~mask;
161 }
162 else {
163 val |= mask;
164 }
165 analog_write_reg8 (areg, val);
166
167 /////////////////////////// enable /////////////////////
168 areg = ((pin>>8) + 0x46);
169 val = analog_read_reg8(areg);
170 if (en) {
171 val |= mask;
172 }
173 else {
174 val &= ~mask;
175 }
176 analog_write_reg8 (areg, val);
177 }
178
179 /**
180 * @brief this function servers to wait bbpll clock lock.
181 * @return none.
182 */
pm_wait_bbpll_done(void)183 _attribute_ram_code_ void pm_wait_bbpll_done(void)
184 {
185 unsigned char ana_81 = analog_read_reg8(0x81);
186 analog_write_reg8(0x81, ana_81 | BIT(6));
187 for(unsigned char j = 0; j < 3; j++)
188 {
189 for(volatile unsigned char i = 0; i < 30; i++){ //20us
190 __asm__("nop");
191 }
192 if(BIT(5) == (analog_read_reg8(0x88) & BIT(5)))
193 {
194 analog_write_reg8(0x81, ana_81 & 0xbf);
195 break;
196 }
197 else
198 {
199 if(j == 0){
200 analog_write_reg8(0x01, 0x46);
201 }
202 else if(j == 1){
203 analog_write_reg8(0x01, 0x43);
204 }
205 else{
206 analog_write_reg8(0x81, ana_81 & 0xbf);
207 }
208 }
209 }
210 }
211
212 /**
213 * @brief This function serves to update wakeup status.
214 * @return none.
215 */
pm_update_status_info(void)216 void pm_update_status_info(void)
217 {
218 unsigned char analog_38 = analog_read_reg8(PM_ANA_REG_WD_CLR_BUF0);
219 unsigned char analog_39 = analog_read_reg8(PM_ANA_REG_POWER_ON_CLR_BUF0);
220
221 if(analog_38 & BIT(0)){
222 if(analog_39 & BIT(0)){
223 g_pm_status_info.mcu_status = MCU_STATUS_REBOOT_BACK;
224 analog_write_reg8(PM_ANA_REG_WD_CLR_BUF0, analog_38 & 0xfe);
225 }else{
226 g_pm_status_info.mcu_status = MCU_STATUS_POWER_ON;
227 analog_write_reg8(PM_ANA_REG_WD_CLR_BUF0,analog_38 & 0xfe);
228 analog_write_reg8(PM_ANA_REG_POWER_ON_CLR_BUF0, analog_39 | BIT(0));
229 }
230 }else{
231 if(pm_get_deep_retention_flag()){
232 g_pm_status_info.mcu_status = MCU_STATUS_DEEPRET_BACK;
233 }else if(analog_39 & BIT(1)){
234 g_pm_status_info.mcu_status = MCU_STATUS_REBOOT_DEEP_BACK;
235 analog_write_reg8(PM_ANA_REG_POWER_ON_CLR_BUF0, analog_39 & 0xfd);
236 }else{
237 g_pm_status_info.mcu_status = MCU_STATUS_DEEP_BACK;
238 }
239 }
240 analog_write_reg8(0x7f, 0x01);
241 g_pm_status_info.wakeup_src = pm_get_wakeup_src();
242 g_pm_status_info.is_pad_wakeup = (g_pm_status_info.wakeup_src & BIT(3)) >> 3;
243 }
244
245 /**
246 * @brief this function srevers to start sleep mode.
247 * @return none.
248 */
pm_sleep_start(void)249 _attribute_ram_code_sec_noinline_ void pm_sleep_start(void)
250 {
251 //This is 1.4V and 1.8V power supply during sleep. Do not power on during initialization, because after power on,
252 //there will be two power supplies at the same time, which may cause abnormalities.add by weihua.zhang, confirmed by haitao 20210107
253 analog_write_reg8(0x0b, analog_read_reg8(0x0b) & ~(BIT(0) | BIT(1))); //<0>:pd_nvt_1p4, power on native 1P4.
254 //<1>:pd_nvt_1p8, power on native 1P8.
255 //A0 chip cann't disable baseband,A1 need disable baseband.See sys_init for specific instructions.(add by weihua zhang, confirmed by junwen 20200925)
256 if(0xff == g_chip_version){ //A0
257 analog_write_reg8(0x7d, g_pm_suspend_power_cfg&0xfe);
258 }else{
259 analog_write_reg8(0x7d, g_pm_suspend_power_cfg);
260 }
261
262 mspi_low();
263 mspi_write(0xb9); //flash deep
264 mspi_wait();
265 mspi_high();
266 write_reg8(0x140329, 0x00); //MSPI ie disable
267 analog_write_reg8(0x81, analog_read_reg8(0x81) | BIT(7));
268
269 write_reg8(0x1401ef,0x80); //trig pwdn
270
271 //After being triggered, the MCU needs to wait for a period of time before it actually goes to sleep,
272 //during which time the MCU will continue to execute code. If the following code is executed
273 //and some modules are awakened, the current will be larger than normal. About 20 empty instructions are fine,
274 //but to be on the safe side, add 64 empty instructions.
275 for(volatile unsigned int i = 0; i < 64; i++){
276 __asm__("nop");
277 }
278
279 analog_write_reg8(0x81, analog_read_reg8(0x81) & (~BIT(7)));
280 //The flash two-wire system uses clk+cn+ two communication lines, and the flash four-wire system uses
281 //clk+cn+ four communication lines. Before suspend sleep, the input of the six lines (PF0-PF5) used
282 //by flash will be disabled. After suspend wakes up, the six lines will be set to input function.
283 //(changed by weihua.zhang, confirmed by jianzhi 20201201)
284 write_reg8(0x140329, 0x3f); //MSPI(PF0-PF5) ie enable
285 mspi_low();
286 mspi_write(0xab); //flash wakeup
287 mspi_wait();
288 mspi_high();
289
290 analog_write_reg8(0x7d, 0x80); // enable digital bb, usb, npe
291 analog_write_reg8(0x0b, analog_read_reg8(0x0b) | (BIT(0) | BIT(1))); //<0>:pd_nvt_1p4, power down native 1P4.
292 //<1>:pd_nvt_1p8, power down native 1P8.
293 //wait for xtal stable
294 for(volatile unsigned int i = 0; i < 300; i++){ //200us
295 __asm__("nop");
296 }
297 //check 3 times for safety
298 while( BIT(7) != (analog_read_reg8(0x88) & (BIT(7)))); //0x88<7>: xo_ready_ana
299 while( BIT(7) != (analog_read_reg8(0x88) & (BIT(7)))); //0x88<7>: xo_ready_ana
300 while( BIT(7) != (analog_read_reg8(0x88) & (BIT(7)))); //0x88<7>: xo_ready_ana
301
302 pm_wait_bbpll_done();
303 }
304
305 /**
306 * @brief This function serves to switch external 32k pad to internal 32k rc.
307 * @return none.
308 */
pm_switch_ext32kpad_to_int32krc(void)309 void pm_switch_ext32kpad_to_int32krc(void)
310 {
311 //switch 32k clk src: select internal 32k rc, if not do this, when deep+pad wakeup: there's no stable 32k clk(therefore, the pad wake-up time
312 //is a bit long, the need for external 32k crystal vibration time) to count DCDC dly and XTAL dly. High temperatures even make it impossible
313 //to vibrate, as the code for PWM excitation crystals has not yet been effectively executed. SO, we can switch 32k clk to the internal 32k rc.
314 analog_write_reg8(0x4e, analog_read_reg8(0x4e) & (~BIT(7))); //32k select:[7]:0 sel 32k rc,1:32k pad
315 analog_write_reg8(0x05, 0x02); //[0]:32k rc;[1]:32k xtal (1->pwdn,0->pwup). Power up 32k rc.
316
317 //deep + no tmr wakeup(we need 32k clk to count dcdc dly and xtal dly, but this case, ext 32k clk need close, here we use 32k rc instead)
318 analog_write_reg8(0x4c, 0xef);
319 }
320
321 _attribute_data_retention_sec_ pm_clock_drift_t pmcd = {0, 0, 0, 0, 0, 0};
322 /**
323 * @brief When 32k rc sleeps, the calibration function is initialized.
324 * @return none.
325 */
pm_32k_rc_offset_init(void)326 void pm_32k_rc_offset_init(void)
327 {
328 pmcd.offset = 0;
329 pmcd.tc = 0;
330 pmcd.ref_tick = 0;
331 }
332
pm_update_32k_rc_sleep_tick(unsigned int tick_32k,unsigned int tick)333 _attribute_ram_code_ void pm_update_32k_rc_sleep_tick (unsigned int tick_32k, unsigned int tick)
334 {
335 pmcd.rc32_rt = tick_32k - pmcd.rc32_wakeup; //rc32_rt not used
336 if (pmcd.calib || pmcd.ref_no > 20 || !pmcd.ref_tick || ((tick_32k - pmcd.ref_tick_32k) & 0xfffffff) > 32 * 3000)//3 mS
337 {
338 pmcd.calib = 0;
339 pmcd.ref_tick_32k = tick_32k;
340 pmcd.ref_tick = tick | 1;
341 pmcd.ref_no = 0;
342 }
343 else
344 {
345 pmcd.ref_no++;
346 }
347 }
348
pm_ble_32k_rc_cal_reset(void)349 _attribute_ram_code_sec_noinline_ void pm_ble_32k_rc_cal_reset(void)
350 {
351 pmcd.offset = 0;
352 pmcd.tc = 0;
353 pmcd.ref_tick = 0;
354 pmcd.offset_cal_tick = 0;
355 }
356
357
pm_ble_cal_32k_rc_offset(int offset_tick,int rc32_cnt)358 _attribute_ram_code_sec_noinline_ void pm_ble_cal_32k_rc_offset (int offset_tick, int rc32_cnt)
359 {
360 int offset = offset_tick * (256 * 31) / rc32_cnt; //256mS / sleep_period
361 int thres = rc32_cnt/9600; //240*32=7680 300*32= 9600 400*32= 12800
362 if(!thres){
363 thres = 1;
364 }
365 thres *= 0x100;
366
367 if (offset > thres)
368 {
369 offset = thres;
370 }
371 else if (offset < -thres)
372 {
373 offset = -thres;
374 }
375 pmcd.calib = 1;
376 pmcd.offset += (offset - pmcd.offset) >> 4;
377 pmcd.offset_cal_tick = clock_time() | 1;
378 }
379
pm_cal_32k_rc_offset(int offset_tick)380 _attribute_ram_code_sec_noinline_ void pm_cal_32k_rc_offset (int offset_tick)
381 {
382 int offset = offset_tick * (240 * 31) / pmcd.rc32; //240ms / sleep_period
383 if (offset > 0x100)
384 {
385 offset = 0x100;
386 }
387 else if (offset < -0x100)
388 {
389 offset = -0x100;
390 }
391 pmcd.calib = 1;
392 pmcd.offset += (offset - pmcd.offset) >> 4;
393 pmcd.offset_dc += (offset_tick - pmcd.offset_dc) >> 3;
394 }
395
396 /**
397 * @brief 32k rc calibration clock compensation.
398 * @return 32k calibration value after compensation.
399 */
pm_get_32k_rc_calib(void)400 _attribute_ram_code_ unsigned int pm_get_32k_rc_calib (void)
401 {
402 while(!read_reg32(0x140214)); //Wait for the 32k clock calibration to complete.
403
404 int tc = read_reg32(0x140214);
405 pmcd.s0 = tc;
406 tc = tc << 4;
407 if (!pmcd.tc)
408 {
409 pmcd.tc = tc;
410 }
411 else
412 {
413 pmcd.tc += (tc - pmcd.tc) >> (4 - pmcd.calib);
414 }
415
416 int offset = (pmcd.offset * (pmcd.tc >> 4)) >> 18; //offset : tick per 256ms
417 offset = (pmcd.tc >> 4) + offset;
418 return (unsigned int)offset;
419 }
420
421 /**
422 * @brief This function serves to set the working mode of MCU based on 32k crystal,e.g. suspend mode, deepsleep mode, deepsleep with SRAM retention mode and shutdown mode.
423 * @param[in] sleep_mode - sleep mode type select.
424 * @param[in] wakeup_src - wake up source select.
425 * @param[in] wakeup_tick_type - tick type select. For long timer sleep.currently only 16M is supported(PM_TICK_STIMER_16M).
426 * @param[in] wakeup_tick - the time of short sleep, which means MCU can sleep for less than 5 minutes.
427 * @return indicate whether the cpu is wake up successful.
428 */
pm_sleep_wakeup(pm_sleep_mode_e sleep_mode,pm_sleep_wakeup_src_e wakeup_src,pm_wakeup_tick_type_e wakeup_tick_type,unsigned int wakeup_tick)429 int pm_sleep_wakeup(pm_sleep_mode_e sleep_mode, pm_sleep_wakeup_src_e wakeup_src, pm_wakeup_tick_type_e wakeup_tick_type, unsigned int wakeup_tick)
430 {
431 int timer_wakeup_enable = (wakeup_src & PM_WAKEUP_TIMER);
432 if(CLK_32K_RC == g_clk_32k_src){
433 g_pm_tick_32k_calib = pm_get_32k_rc_calib()*2;
434 }else{
435 //NOTICE:We think that the external 32k crystal clk is very accurate
436 g_pm_tick_32k_calib = CRYSTAL32768_TICK_PER_32CYCLE;
437
438 }
439 unsigned int tick_32k_halfCalib = g_pm_tick_32k_calib>>1;
440 unsigned int span = (unsigned int)(wakeup_tick - ((wakeup_tick_type == PM_TICK_STIMER_16M)?stimer_get_tick ():0));
441 if(timer_wakeup_enable && (wakeup_tick_type == PM_TICK_STIMER_16M)){
442 if (span > 0xE0000000){ //BIT(31)+BIT(30)+BIT(29) 7/8 cylce of 32bit, 268.44*7/8 = 234.88 S
443 return analog_read_reg8 (0x64) & 0x1f;
444 }
445 else if (span < g_pm_early_wakeup_time_us.sleep_min_time_us * SYSTEM_TIMER_TICK_1US){ // 0 us base
446 unsigned int t = stimer_get_tick ();
447 analog_write_reg8 (0x64, 0x1f);
448 unsigned char st;
449 do {
450 st = analog_read_reg8 (0x64) & 0x1f;
451 } while ( ((unsigned int)stimer_get_tick () - t < span) && !st);
452
453 return st;
454 }
455 }
456 ////////// disable IRQ //////////////////////////////////////////
457 unsigned int r= core_interrupt_disable();
458
459 #if SYS_TIMER_AUTO_MODE
460 BM_CLR(reg_system_irq_mask,BIT(0));
461 REG_ADDR8(0x140218) = 0x01; //system tick only update upon 32k posedge, must set before enable 32k read update!!!
462 BM_CLR(reg_system_ctrl,FLD_SYSTEM_32K_TRACK_EN);//disable 32k track
463 g_pm_tick_32k_cur = clock_get_32k_tick();
464 g_pm_tick_cur = stimer_get_tick();
465 BM_SET(reg_system_st,FLD_SYSTEM_CMD_STOP); //write 1, stop system timer when using auto mode
466 #else
467 g_pm_tick_cur = stimer_get_tick() + 37 * SYSTEM_TIMER_TICK_1US; //cpu_get_32k_tick will cost 30~40 us//15
468 BM_CLR(reg_system_irq_mask,BIT(0));
469 BM_CLR(reg_system_ctrl,FLD_SYSTEM_TIMER_EN | FLD_SYSTEM_TIMER_AUTO | FLD_SYSTEM_32K_TRACK_EN);//disable 32k track and stimer
470 g_pm_tick_32k_cur = clock_get_32k_tick ();
471 #endif
472
473 pm_update_32k_rc_sleep_tick (g_pm_tick_32k_cur, g_pm_tick_cur);
474
475 /////////////////// set wakeup source /////////////////////////////////
476 analog_write_reg8 (0x4b, wakeup_src);
477 analog_write_reg8 (0x64, 0x1f); //clear all flag
478
479 unsigned char cclk_reg = read_reg8(0x1401e8);
480 write_reg8(0x1401e8, cclk_reg & 0x8f );//change cclk to 24M rc clock
481 analog_write_reg8(0x7e, sleep_mode);//sram retention
482 unsigned int earlyWakeup_us;
483
484 if(sleep_mode & DEEPSLEEP_RETENTION_FLAG) { //deepsleep with retention
485 //0x00->0xd1
486 //<0>pd_rc32k_auto=1 <4>pwdn power suspend ldo=1
487 //<6>power down sequence enable=1 <7>enable isolation=1
488 if(wakeup_src & PM_WAKEUP_COMPARATOR)
489 {
490 analog_write_reg8(0x4d,0xd0);//retention
491 }
492 else
493 {
494 analog_write_reg8(0x4d,0xd1);//retention
495 }
496 #if (!WDT_REBOOT_RESET_ANA7F_WORK_AROUND)
497 analog_write_reg8(0x7f, 0x00);
498 #endif
499 //0x140104 mspi_set_l: mutiboot address offset option, 0:0k; 1:128k; 2:256k; 4:256k
500 //0x140105 mspi_set_h: program space size = mspi_set_h*4k
501 //0x140106 mspi_cmd_AHB: xip read command
502 //0x140107 mspi_fm_AHB: [3:0] dummy_h [5:4] dat_line_h [6] addr_line_h [7] cmd_line_h
503 g_pm_multi_addr = read_reg32(0x140104);
504
505 if(wakeup_tick_type == PM_TICK_STIMER_16M){
506 earlyWakeup_us = g_pm_early_wakeup_time_us.deep_ret_early_wakeup_time_us;
507 }else{
508 earlyWakeup_us = g_pm_longsleep_early_wakeup_time_us.deep_ret_early_wakeup_time_us;
509 }
510
511 }
512 else if(sleep_mode == DEEPSLEEP_MODE){ //deepsleep no retention
513 //0x00->0xf9
514 //<0>pd_rc32k_auto=1 <3>rst_xtal_quickstart_cnt=1 <4>pwdn power suspend ldo=1
515 //<5>pwdn power retention ldo=1 <6>power down sequence enable=1 <7>enable isolation=1
516 if(wakeup_src & PM_WAKEUP_COMPARATOR)
517 {
518 analog_write_reg8(0x4d,0xf8);//deep
519 }
520 else
521 {
522 analog_write_reg8(0x4d,0xf9);//deep
523 }
524 analog_write_reg8(0x7f, 0x01);
525 if(wakeup_tick_type == PM_TICK_STIMER_16M){
526 earlyWakeup_us = g_pm_early_wakeup_time_us.deep_early_wakeup_time_us;
527 }else{
528 earlyWakeup_us = g_pm_longsleep_early_wakeup_time_us.deep_early_wakeup_time_us;
529 }
530
531 }
532 else{ //suspend
533 //0x00->0x61
534 //<0>pd_rc32k_auto=1 <5>pwdn power retention ldo=1 <6>power down sequence enable=1
535 if(wakeup_src & PM_WAKEUP_COMPARATOR)
536 {
537 analog_write_reg8(0x4d,0x60);//suspend
538 }
539 else
540 {
541 analog_write_reg8(0x4d,0x61);//suspend
542 }
543 analog_write_reg8(0x7f, 0x01);
544
545 if(wakeup_tick_type == PM_TICK_STIMER_16M){
546 earlyWakeup_us = g_pm_early_wakeup_time_us.suspend_early_wakeup_time_us;
547 }else{
548 earlyWakeup_us = g_pm_longsleep_early_wakeup_time_us.suspend_early_wakeup_time_us;
549 }
550 }
551 unsigned int tick_wakeup_reset = wakeup_tick - ((wakeup_tick_type == PM_TICK_STIMER_16M)?(earlyWakeup_us * SYSTEM_TIMER_TICK_1US):earlyWakeup_us);
552 if(CLK_32K_RC == g_clk_32k_src){
553 //auto power down
554 if((wakeup_src & PM_WAKEUP_TIMER) || (wakeup_src & PM_WAKEUP_MDEC) || (wakeup_src & PM_WAKEUP_COMPARATOR)){
555 analog_write_reg8(0x4c,0xee);//disable auto power down 32KRC
556 }
557 else{
558 analog_write_reg8(0x4c, 0xef);//en auto power down 32KRC
559 }
560
561 }else{
562
563 if(sleep_mode == DEEPSLEEP_MODE && !timer_wakeup_enable){ //if deep mode and no tmr wakeup
564 pm_switch_ext32kpad_to_int32krc();
565 }
566 else{ //suspend mode or deepretn mode or tmr wakup (we don't pwdn ext 32k pad clk,even though three's no tmr wakup src in susped or deepretn mode)
567 analog_write_reg8(0x4c, 0xed);//if use tmr wakeup, auto pad 32k pwdn shoule be disabled
568 }
569 }
570
571 if(sleep_mode == DEEPSLEEP_MODE){
572 analog_write_reg8 (0x40, g_pm_r_delay_cycle.deep_r_delay_cycle);//(n): if timer wake up : (n*2) 32k cycle; else pad wake up: (n*2-1) ~ (n*2)32k cycle
573 }else{
574 analog_write_reg8 (0x40, g_pm_r_delay_cycle.suspend_ret_r_delay_cycle);//(n): if timer wake up : (n*2) 32k cycle; else pad wake up: (n*2-1) ~ (n*2)32k cycle
575 }
576
577 unsigned int tick_reset;
578 //The variable pmcd.ref_tick is added, replacing the original variable g_pm_tick_cur. Because pmcd.ref_tick directly affects the value of
579 //g_pm_long_suspend, g_pm_long_suspend can be assigned after pmcd.ref_tick is updated.changed by weihua,confirmed by biao.li.20201204.
580 if(timer_wakeup_enable && (wakeup_tick_type == PM_TICK_STIMER_16M)){
581 if( (unsigned int)(tick_wakeup_reset - pmcd.ref_tick) > 0x07ff0000 ){ //CLK_32K_RC:BIT(28) = 0x10000000 16M:16S;CLK_32K_XTAL:BIT(28) = 0x08000000 16M:8.389S
582 g_pm_long_suspend = 1;
583 }
584 else{
585 g_pm_long_suspend = 0;
586 }
587 }
588 if(wakeup_tick_type == PM_TICK_STIMER_16M){
589 if(g_pm_long_suspend){
590 tick_reset = pmcd.ref_tick_32k + (unsigned int)(tick_wakeup_reset - pmcd.ref_tick)/ g_pm_tick_32k_calib * 32;
591 }
592 else{
593 tick_reset = pmcd.ref_tick_32k + ((unsigned int)(tick_wakeup_reset - pmcd.ref_tick) * 32 + tick_32k_halfCalib) / g_pm_tick_32k_calib;
594 }
595 }else{
596 tick_reset = g_pm_tick_32k_cur + tick_wakeup_reset;
597 }
598 clock_set_32k_tick(tick_reset);
599
600 if(pm_get_wakeup_src()&0x1f){
601
602 }
603 else{
604 #if (WDT_REBOOT_RESET_ANA7F_WORK_AROUND)
605 if(sleep_mode & DEEPSLEEP_RETENTION_FLAG)
606 analog_write_reg8(0x7f, 0x00);
607 #endif
608 pm_sleep_start();
609 #if (WDT_REBOOT_RESET_ANA7F_WORK_AROUND)
610 analog_write_reg8(0x7f, 0x01);
611 #endif
612 }
613 if(sleep_mode == DEEPSLEEP_MODE){
614 write_reg8 (0x1401ef, 0x20); //reboot
615 }
616 #if SYS_TIMER_AUTO_MODE
617 REG_ADDR8(0x140218) = 0x02; //sys tick 16M set upon next 32k posedge
618 reg_system_ctrl |=(FLD_SYSTEM_TIMER_AUTO|FLD_SYSTEM_32K_TRACK_EN) ;
619 unsigned int now_tick_32k = clock_get_32k_tick();
620 if(g_pm_long_suspend){
621 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k + 1 - pmcd.ref_tick_32k) / 32 * g_pm_tick_32k_calib;
622 }else{
623 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k + 1 - pmcd.ref_tick_32k) * g_pm_tick_32k_calib / 32; // current clock
624 }
625 pmcd.rc32_wakeup = now_tick_32k + 1;
626 pmcd.rc32 = now_tick_32k + 1 - pmcd.ref_tick_32k;
627 reg_system_tick = g_pm_tick_cur + 1;
628
629 //wait cmd set dly done upon next 32k posedge
630 //if not using status bit, wait at least 1 32k cycle to set register r_run_upon_next_32k back to 0, or before next normal set
631 while((reg_system_st & BIT(7)) == 0); //system timer set done status upon next 32k posedge
632 REG_ADDR8(0x140218) = 0; //normal sys tick (16/sys) update
633 reg_system_irq_mask |= BIT(0); //enable system timer irq
634 #else
635 unsigned int now_tick_32k = clock_get_32k_tick();
636 if(g_pm_long_suspend){
637 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k - pmcd.ref_tick_32k) / 32 * g_pm_tick_32k_calib;
638 }else{
639 g_pm_tick_cur = pmcd.ref_tick + (unsigned int)(now_tick_32k - pmcd.ref_tick_32k) * g_pm_tick_32k_calib / 32; // current clock
640 }
641 pmcd.rc32_wakeup = now_tick_32k;
642 pmcd.rc32 = now_tick_32k - pmcd.ref_tick_32k;
643
644 reg_system_tick = g_pm_tick_cur + 20 * SYSTEM_TIMER_TICK_1US;
645 reg_system_ctrl |= FLD_SYSTEM_TIMER_EN | FLD_SYSTEM_32K_TRACK_EN; //enable 32k cal and stimer
646 reg_system_irq_mask |= BIT(0); //enable system timer irq
647 #endif
648
649 write_reg8(0x1401e8, cclk_reg );//restore cclk
650
651 unsigned char anareg64 = pm_get_wakeup_src();
652 // DBG_CHN2_HIGH;
653 if ( (anareg64 & WAKEUP_STATUS_TIMER) && timer_wakeup_enable ) //wakeup from timer only
654 {
655 if(wakeup_tick_type == PM_TICK_STIMER_16M){
656 while ((unsigned int)(stimer_get_tick () - wakeup_tick) > BIT(30));
657 }else{
658 while ((unsigned int)(clock_get_32k_tick() - wakeup_tick - g_pm_tick_32k_cur + 37*16) > BIT(30));
659 }
660 }
661
662 // DBG_CHN2_LOW;
663 core_restore_interrupt(r);
664 return (anareg64 ? (anareg64 | STATUS_ENTER_SUSPEND) : STATUS_GPIO_ERR_NO_ENTER_PM );
665 }
666
667