1 /******************************************************************************
2 * @file rsi_deepsleep_soc.c
3 *******************************************************************************
4 * # License
5 * <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
6 *******************************************************************************
7 *
8 * SPDX-License-Identifier: Zlib
9 *
10 * The licensor of this software is Silicon Laboratories Inc.
11 *
12 * This software is provided 'as-is', without any express or implied
13 * warranty. In no event will the authors be held liable for any damages
14 * arising from the use of this software.
15 *
16 * Permission is granted to anyone to use this software for any purpose,
17 * including commercial applications, and to alter it and redistribute it
18 * freely, subject to the following restrictions:
19 *
20 * 1. The origin of this software must not be misrepresented; you must not
21 * claim that you wrote the original software. If you use this software
22 * in a product, an acknowledgment in the product documentation would be
23 * appreciated but is not required.
24 * 2. Altered source versions must be plainly marked as such, and must not be
25 * misrepresented as being the original software.
26 * 3. This notice may not be removed or altered from any source distribution.
27 *
28 ******************************************************************************/
29
30 /**
31 * Includes
32 */
33 #include "rsi_ccp_common.h"
34 #include "rsi_power_save.h"
35 #include "rsi_temp_sensor.h"
36 #include "rsi_retention.h"
37 #ifdef DEBUG_UART
38 #include "rsi_debug.h"
39 #endif
40
41 void fpuInit(void);
42 #define NWPAON_MEM_HOST_ACCESS_CTRL_CLEAR_1 (*(volatile uint32_t *)(0x41300000 + 0x4))
43 #define NWPAON_MEM_HOST_ACCESS_CTRL_SET_1 (*(volatile uint32_t *)(0x41300000 + 0x0))
44 #define M4SS_TASS_CTRL_SET_REG (*(volatile uint32_t *)(0x24048400 + 0x34))
45 #define M4SS_TASS_CTRL_CLEAR_REG (*(volatile uint32_t *)(0x24048400 + 0x38))
46 #define M4SS_TASS_CTRL_CLR_REG (*(volatile uint32_t *)(0x24048400 + 0x38))
47 #define MAX_NVIC_REGS 3 // Max Interrupts register
48 #define MAX_IPS 240 // Max Interrupt Priority registers
49 #define MAX_SHP 12 // Max System Handlers Priority registers
50 #define NPSS_GPIO_CLR_VALUE 0x3E // NPSS GPIO rising edge interrupt clear value
51
52 #ifdef SLI_SI91X_MCU_4MB_LITE_IMAGE
53 #define MBR_MAGIC_WORD (*(volatile uint32_t *)(0x8160000))
54 #else
55 #define MBR_MAGIC_WORD (*(volatile uint32_t *)(0x81F0000))
56 #endif
57
58 #define SL_SCDC_SLEEP 1
59 #define SL_SCDC_ACTIVE 0
60
61 /* MACRO definition for External LDO Handle, the user must provide the definition for External LDO ON/OFF Handle*/
62 #ifndef EXTERNAL_LDO_HANDLE
63 /*If User Handle definition is not available keep a Null Definition*/
64 #define EXTERNAL_LDO_HANDLE
65 #endif
66
67 extern void set_scdc(uint32_t Deepsleep);
68
69 #ifdef SLI_SI91X_MCU_ENABLE_PSRAM_FEATURE
70 #include "sl_si91x_psram_config.h"
71 #endif
72
73 uint32_t nvic_enable[MAX_NVIC_REGS] = { 0 };
74 uint8_t nvic_ip_reg[MAX_IPS] = { 0 };
75 uint8_t scs_shp_reg[MAX_SHP] = { 0 };
76 volatile uint32_t msp_value;
77 volatile uint32_t psp_value;
78 volatile uint32_t control_reg_val;
79 uint32_t npss_gpio_config = 0;
80
81 #if defined(SLI_SI91X_MCU_ENABLE_RAM_BASED_EXECUTION)
82 extern char ram_vector[SI91X_VECTOR_TABLE_ENTRIES];
83 #endif
84
85 /**
86 * @fn void RSI_Save_Context(void)
87 * @brief This function is to save Stack pointer value and Control registers.
88 *
89 */
RSI_Save_Context(void)90 void RSI_Save_Context(void)
91 {
92 msp_value = __get_MSP();
93 psp_value = __get_PSP();
94 control_reg_val = __get_CONTROL();
95 }
96 /**
97 * @fn void RSI_Restore_Context(void)
98 * @brief This function is to Restore Stack pointer value and Control registers.
99 *
100 */
101 #ifdef SLI_SI91X_ENABLE_OS
RSI_Restore_Context(void)102 STATIC INLINE void RSI_Restore_Context(void)
103 {
104 __set_CONTROL(control_reg_val);
105 __set_PSP(psp_value);
106 __set_MSP(msp_value);
107 }
108 #endif
109 #if defined(__CC_ARM) /*------------------ARM CC Compiler -----------------*/
110 /**
111 * @fn __asm void RSI_PS_SaveCpuContext(void)
112 * @brief This API is used to save the CPU status register into RAM, this API should be used when sleep with RET is required
113 * @return none
114 */
RSI_PS_SaveCpuContext(void)115 __asm void RSI_PS_SaveCpuContext(void)
116 {
117 IMPORT __sp;
118 PUSH{ r0 };
119 PUSH{ r1 };
120 PUSH{ r2 };
121 PUSH{ r3 };
122 PUSH{ r4 };
123 PUSH{ r5 };
124 PUSH{ r6 };
125 PUSH{ r7 };
126 PUSH{ r8 };
127 PUSH{ r9 };
128 PUSH{ r10 };
129 PUSH{ r11 };
130 PUSH{ r12 };
131 PUSH{ r14 };
132 LDR r0, = __sp;
133 MRS r1, msp;
134 STR r1, [r0];
135 WFI;
136 }
137
138 /**
139 * @fn void RSI_PS_RestoreCpuContext(void)
140 * @brief This API is used to restore the current CPU processing content from (POP) stack
141 * @return none
142 */
RSI_PS_RestoreCpuContext(void)143 __asm void RSI_PS_RestoreCpuContext(void)
144 {
145 IMPORT __sp;
146 LDR r0, = __sp;
147 LDR sp, [r0, #0];
148 POP{ r14 };
149 POP{ r12 };
150 POP{ r11 };
151 POP{ r10 };
152 POP{ r9 };
153 POP{ r8 };
154 POP{ r7 };
155 POP{ r6 };
156 POP{ r5 };
157 POP{ r4 };
158 POP{ r3 };
159 POP{ r2 };
160 POP{ r1 };
161 POP{ r0 };
162 BX LR;
163 }
164 #endif /*------------------ARM CC Compiler -----------------*/
165
166 #if defined(__GNUC__) /*------------------ GNU Compiler ---------------------*/
167
168 /**
169 * @fn void RSI_PS_SaveCpuContext(void)
170 * @brief This API is used to save the CPU status register into RAM, this API should be used when sleep with RET is required
171 * @return none
172 */
RSI_PS_SaveCpuContext(void)173 void RSI_PS_SaveCpuContext(void)
174 {
175 __asm("push {r0}");
176 __asm("push {r1}");
177 __asm("push {r2}");
178 __asm("push {r3}");
179 __asm("push {r4}");
180 __asm("push {r5}");
181 __asm("push {r6}");
182 __asm("push {r7}");
183 __asm("push {r8}");
184 __asm("push {r9}");
185 __asm("push {r10}");
186 __asm("push {r11}");
187 __asm("push {r12}");
188 __asm("push {r14}");
189
190 /*R13 Stack pointer */
191 __asm("mov %0, sp\n\t" : "=r"(__sp));
192 __asm("WFI");
193 }
194
195 /**
196 * @fn void RSI_PS_RestoreCpuContext(void)
197 * @brief This API is used to restore the current CPU processing content from (POP) stack
198 * @return none
199 */
RSI_PS_RestoreCpuContext(void)200 void RSI_PS_RestoreCpuContext(void)
201 {
202 __asm("ldr r0 , =__sp");
203 __asm("ldr sp , [r0 , #0]");
204 __asm("pop {r14}");
205 __asm("pop {r12}");
206 __asm("pop {r11}");
207 __asm("pop {r10}");
208 __asm("pop {r9}");
209 __asm("pop {r8}");
210 __asm("pop {r7}");
211 __asm("pop {r6}");
212 __asm("pop {r5}");
213 __asm("pop {r4}");
214 __asm("pop {r3}");
215 __asm("pop {r2}");
216 __asm("pop {r1}");
217 __asm("pop {r0}");
218 }
219 #endif /*------------------ GNU Compiler ---------------------*/
220
221 #if defined(__ICCARM__) /*------------------ IAR Compiler ---------------------*/
222 /**
223 * @fn void RSI_PS_SaveCpuContext(void)
224 * @brief This API is used to save the CPU status register into RAM, this API should be used when sleep with RET is required
225 * @return none
226 */
RSI_PS_SaveCpuContext(void)227 void RSI_PS_SaveCpuContext(void)
228 {
229 __asm("push {r0}");
230 __asm("push {r1}");
231 __asm("push {r2}");
232 __asm("push {r3}");
233 __asm("push {r4}");
234 __asm("push {r5}");
235 __asm("push {r6}");
236 __asm("push {r7}");
237 __asm("push {r8}");
238 __asm("push {r9}");
239 __asm("push {r10}");
240 __asm("push {r11}");
241 __asm("push {r12}");
242 __asm("push {r14}");
243
244 /*R13 Stack pointer */
245 __asm("mov %0, sp\n\t" : "=r"(__sp));
246 __asm("WFI");
247 }
248
249 /**
250 * @fn void RSI_PS_RestoreCpuContext(void)
251 * @brief This API is used to restore the current CPU processing content from (POP) stack
252 * @return none
253 */
RSI_PS_RestoreCpuContext(void)254 void RSI_PS_RestoreCpuContext(void)
255 {
256 __asm("ldr r0 , =__sp");
257 __asm("ldr sp , [r0 , #0]");
258 __asm("pop {r14}");
259 __asm("pop {r12}");
260 __asm("pop {r11}");
261 __asm("pop {r10}");
262 __asm("pop {r9}");
263 __asm("pop {r8}");
264 __asm("pop {r7}");
265 __asm("pop {r6}");
266 __asm("pop {r5}");
267 __asm("pop {r4}");
268 __asm("pop {r3}");
269 __asm("pop {r2}");
270 __asm("pop {r1}");
271 __asm("pop {r0}");
272 }
273 #endif /*------------------ IAR Compiler ---------------------*/
274
275 #ifdef SLI_SI91X_MCU_COMMON_FLASH_MODE
276 /**
277 * @fn void RSI_Set_Cntrls_To_M4(void)
278 * @brief This API is used to set m4ss_ref_clk_mux_ctrl ,tass_ref_clk_mux_ctrl, AON domain power supply controls
279 * from NWP to M4
280 *
281 *
282 * @return none
283 */
RSI_Set_Cntrls_To_M4(void)284 void RSI_Set_Cntrls_To_M4(void)
285 {
286 #if defined(SLI_SI917B0) || defined(SLI_SI915)
287 //!take TASS ref clock control to M4
288 MCUAON_CONTROL_REG4 &= ~(MCU_TASS_REF_CLK_SEL_MUX_CTRL);
289 #else
290 /* m4ss_ref_clk_mux_ctrl and tass_ref_clk_mux_ctr in M4 Control */
291 NWPAON_MEM_HOST_ACCESS_CTRL_CLEAR_1 = (M4SS_REF_CLK_MUX_CTRL | TASS_REF_CLK_MUX_CTRL);
292 #endif
293 /* M4SS controlling Power supply for TASS AON domain */
294 BATT_FF->M4SS_TASS_CTRL_SET_REG_b.M4SS_CTRL_TASS_AON_PWRGATE_EN = ENABLE;
295 /* M4SS controlling Power supply for TASS AON domains isolation enable in bypass mode*/
296 BATT_FF->M4SS_TASS_CTRL_SET_REG_b.M4SS_CTRL_TASS_AON_DISABLE_ISOLATION_BYPASS = ENABLE;
297 /* M4SS controlling Power supply for TASS AON domains reset pin in bypass mode. */
298 M4SS_TASS_CTRL_CLR_REG = M4SS_CTRL_TASS_AON_PWR_DMN_RST_BYPASS_BIT;
299 for (volatile uint8_t delay = 0; delay < 10; delay++) {
300 __ASM("NOP");
301 }
302 }
303 /**
304 * @fn void RSI_Set_Cntrls_To_TA(void)
305 * @brief This API is used to set m4ss_ref_clk_mux_ctrl ,tass_ref_clk_mux_ctrl ,AON domain power supply controls
306 * from M4 to NWP
307 *
308 *
309 * @return none
310 */
RSI_Set_Cntrls_To_TA(void)311 void RSI_Set_Cntrls_To_TA(void)
312 {
313 /* tass_ref_clk_mux_ctr in NWP Control */
314 NWPAON_MEM_HOST_ACCESS_CTRL_SET_1 = TASS_REF_CLK_MUX_CTRL;
315 }
316 #endif
317
318 /**
319 * @fn rsi_error_t RSI_PS_EnterDeepSleep(SLEEP_TYPE_T sleepType , uint8_t lf_clk_mode)
320 * @brief This is the common API to keep the system in sleep state. from all possible active states.
321 * @param[in] sleepType : selects the retention or non retention mode of processor. refer 'SLEEP_TYPE_T'.
322 * SLEEP_WITH_RETENTION : When this is used, user must configure the which RAMs to be retained during sleep by using the 'RSI_PS_SetRamRetention()' function.
323 * @param[in] lf_clk_mode : This parameter is used to switch the processor clock from high frequency clock to low-frequency clock. This is used in some critical power save cases.
324 * 0: 'DISABLE_LF_MODE' Normal mode of operation , recommended in most of the applications.
325 * 1: 'LF_32_KHZ_RC' Processor clock is configured to low-frequency RC clock
326 * 2: 'LF_32_KHZ_XTAL' Processor clock is configured to low-frequency XTAL clock
327 * 3: 'EXTERNAL_CAP_MODE' Switches the supply to internal cap mode 0.95V.
328 * @par note
329 \n User must ensure the selected clocks are active before selecting the 'LF_32_KHZ_RC' and 'LF_32_KHZ_XTAL' clocks to the processor using this API.
330 * @return Returns the execution status.
331 */
RSI_PS_EnterDeepSleep(SLEEP_TYPE_T sleepType,uint8_t lf_clk_mode)332 rsi_error_t RSI_PS_EnterDeepSleep(SLEEP_TYPE_T sleepType, uint8_t lf_clk_mode)
333 {
334 volatile int var = 0;
335 volatile int enable_sdcss_based_wakeup = 0;
336 volatile int enable_m4ulp_retention = 0;
337 volatile int Temp;
338
339 volatile uint8_t in_ps2_state = 0;
340
341 uint32_t ipmuDummyRead = 0;
342 uint32_t m4ulp_ram_core_status = 0;
343 uint32_t m4ulp_ram_peri_status = 0;
344 uint32_t disable_pads_ctrl = 0;
345 uint32_t ulp_proc_clk = 0;
346 sl_p2p_intr_status_bkp_t p2p_intr_status_bkp;
347
348 /*Save the NVIC registers */
349 for (var = 0; var < MAX_NVIC_REGS; ++var) {
350 nvic_enable[var] = NVIC->ISER[var];
351 }
352 /* Save the Interrupt Priority Register */
353 for (var = 0; var < MAX_IPS; ++var) {
354 nvic_ip_reg[var] = NVIC->IP[var];
355 }
356 /* Save the System Handlers Priority Registers */
357 for (var = 0; var < MAX_SHP; ++var) {
358 scs_shp_reg[var] = SCB->SHP[var];
359 }
360 /*store the NPSS interrupt mask clear status*/
361 npssIntrState = NPSS_INTR_MASK_CLR_REG;
362 // Stores the NPSS GPIO interrupt configurations
363 npss_gpio_config = NPSS_GPIO_CONFIG_REG;
364
365 /*Clear AUX and DAC pg enables */
366 if (!((MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_b.SDCSS_BASED_WAKEUP_b)
367 || (MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_b.ULPSS_BASED_WAKEUP_b))) {
368 RSI_IPMU_PowerGateClr(AUXDAC_PG_ENB | AUXADC_PG_ENB);
369 }
370 /*Check the PS2 state or not*/
371 if (M4_ULP_SLP_STATUS_REG & ULP_MODE_SWITCHED_NPSS) {
372
373 in_ps2_state = 1U;
374
375 if (!((MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_b.SDCSS_BASED_WAKEUP_b)
376 || (MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_b.ULPSS_BASED_WAKEUP_b))) {
377 disable_pads_ctrl = (ULP_SPI_MEM_MAP(0x141) & BIT(11)); // ULP PADS PDO Status
378 ULP_SPI_MEM_MAP(0x141) &= ~(BIT(11)); // ULP PADS PDO OFF
379 enable_sdcss_based_wakeup = 1;
380 RSI_PS_SetWkpSources(SDCSS_BASED_WAKEUP);
381 }
382
383 if (!(MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_b.M4ULP_RAM_RETENTION_MODE_EN_b)) {
384 enable_m4ulp_retention = 1;
385 m4ulp_ram_core_status = RSI_PS_M4ssRamBanksGetPowerSts();
386 m4ulp_ram_peri_status = RSI_PS_M4ssRamBanksGetPeriPowerSts();
387 RSI_PS_M4ssRamBanksPowerDown(RAM_BANK_7 | RAM_BANK_8 | RAM_BANK_9);
388 RSI_PS_M4ssRamBanksPeriPowerDown(RAM_BANK_7 | RAM_BANK_8 | RAM_BANK_9);
389 #ifdef CHIP_9118
390 RSI_PS_SetRamRetention(M4ULP_RAM_RETENTION_MODE_EN);
391 #endif
392 }
393 }
394 /*Move to LP mode */
395 RSI_IPMU_RetnLdoLpmode();
396 if (sleepType == SLEEP_WITHOUT_RETENTION) {
397 /*POC1 */
398 RSI_IPMU_PocbiasCurrent();
399 /*RO32K_00_EFUSE. */
400 RSI_IPMU_RO32khzTrim00Efuse();
401 /*RETN1 */
402 RSI_IPMU_RetnLdoLpmode();
403 /*RETN0 */
404 RSI_IPMU_RetnLdoVoltsel();
405 }
406
407 if (!in_ps2_state && MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_b.ULPSS_BASED_WAKEUP_b
408 #if (XTAL_CAP_MODE == POWER_TARN_CONDITIONAL_USE)
409 && (lf_clk_mode & BIT(4))
410 #endif
411 ) {
412 #if (XTAL_CAP_MODE == POWER_TARN_CONDITIONAL_USE)
413 RSI_PS_NpssPeriPowerUp(SLPSS_PWRGATE_ULP_MCUTS);
414 /*configure the slope,nominal temperature and f2_nominal*/
415 RSI_TS_Config(MCU_TEMP, 25);
416 /*disable the bjt based temp sensor*/
417 RSI_TS_RoBjtEnable(MCU_TEMP, 0);
418 /*Enable the RO based temp sensor*/
419 RSI_TS_Enable(MCU_TEMP, 1);
420 /*update the temperature periodically*/
421 RSI_Periodic_TempUpdate(TIME_PERIOD, 1, 0);
422 /*read the temperature*/
423 Temp = (int)RSI_TS_ReadTemp(MCU_TEMP);
424 if (Temp > 45) {
425 // disable the XTAL CAP mode
426 RSI_IPMU_ProgramConfigData(lp_scdc_extcapmode);
427 }
428 #endif
429
430 #if (XTAL_CAP_MODE == POWER_TARN_ALWAYS_USE)
431 // disable the XTAL CAP mode
432 RSI_IPMU_ProgramConfigData(lp_scdc_extcapmode);
433 #endif
434 }
435
436 /*Clear IPMU BITS*/
437 RSI_PS_LatchCntrlClr(LATCH_TOP_SPI | LATCH_TRANSPARENT_HF | LATCH_TRANSPARENT_LF);
438
439 ipmuDummyRead = MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP;
440
441 /*Update the SCB with Deep sleep BIT */
442 SCB->SCR = 0x4;
443
444 if (in_ps2_state) {
445 /*Read processor clock */
446 ulp_proc_clk = ULPCLK->ULP_TA_CLK_GEN_REG_b.ULP_PROC_CLK_SEL;
447
448 /*LF processor clock configuration */
449 switch (lf_clk_mode & 0x7) {
450 case DISABLE_LF_MODE:
451 /*Do nothing*/
452 break;
453 case LF_32_KHZ_RC:
454 ULPCLK->ULP_TA_CLK_GEN_REG_b.ULP_PROC_CLK_SEL = 2U;
455 break;
456 case LF_32_KHZ_XTAL:
457 ULPCLK->ULP_TA_CLK_GEN_REG_b.ULP_PROC_CLK_SEL = 3U;
458 break;
459 case HF_MHZ_RO:
460 ULPCLK->ULP_TA_CLK_GEN_REG_b.ULP_PROC_CLK_SEL = 5U;
461 break;
462 default:
463 return INVALID_PARAMETERS;
464 }
465 /* HF processor clock */
466 }
467
468 /* Before sleep,Reduce the SCDC voltage by one value */
469 set_scdc(SL_SCDC_SLEEP);
470
471 #ifdef SLI_SI91X_MCU_ENABLE_PSRAM_FEATURE
472 #if (defined SLI_SI91X_MCU_INTERNAL_LDO_FOR_PSRAM)
473 RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_EFUSE_PERI);
474 if (sleepType == SLEEP_WITH_RETENTION) {
475 //!enable flash LDO and PMU DCDC ON in M4 for PSRAM with retention
476 MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_REG |= (LDO_FLASH_ON | PMU_DCDC_ON);
477 #if PSRAM_HALF_SLEEP_SUPPORTED != FALSE
478 /* Put PSRAM device to sleep */
479 sl_si91x_psram_sleep();
480 #endif
481 }
482 #elif (defined SLI_SI91X_MCU_EXTERNAL_LDO_FOR_PSRAM)
483 #if PSRAM_HALF_SLEEP_SUPPORTED != FALSE
484 if (sleepType == SLEEP_WITH_RETENTION) {
485 /* Put PSRAM device to sleep */
486 sl_si91x_psram_sleep();
487 } else {
488 /* External LDO handle for PSRAM */
489 EXTERNAL_LDO_HANDLE;
490 }
491 #endif
492 #endif
493 #endif
494
495 #ifdef SLI_SI91X_ENABLE_OS
496 /* Save Stack pointer value and Control registers */
497 RSI_Save_Context();
498 #endif
499 /* Take backup before going to PowerSave */
500 p2p_intr_status_bkp.tass_p2p_intr_mask_clr_bkp = TASS_P2P_INTR_MASK_CLR;
501 p2p_intr_status_bkp.m4ss_p2p_intr_set_reg_bkp = M4SS_P2P_INTR_SET_REG;
502
503 #if ((defined SLI_SI91X_MCU_COMMON_FLASH_MODE) && (!(defined(RAM_COMPILATION))))
504 /* Reset M4_USING_FLASH bit before going to sleep */
505 M4SS_P2P_INTR_CLR_REG = M4_USING_FLASH;
506 /*Before M4 is going to deep sleep , set m4ss_ref_clk_mux_ctrl ,tass_ref_clk_mux_ctr, AON domain power supply controls from M4 to NWP */
507 #if defined(SLI_SI917B0) || defined(SLI_SI915)
508 MCUAON_CONTROL_REG4 |= (MCU_TASS_REF_CLK_SEL_MUX_CTRL);
509 MCUAON_CONTROL_REG4;
510 #else
511 NWPAON_MEM_HOST_ACCESS_CTRL_SET_1 = TASS_REF_CLK_MUX_CTRL;
512 #endif
513 #endif
514 /*Enter sleep with retention*/
515 if (sleepType == SLEEP_WITH_RETENTION) {
516 /*If retention mode is enabled save the CPU context*/
517 RSI_PS_SaveCpuContext();
518 } else {
519 /*Clear RAM retentions*/
520 RSI_PS_ClrRamRetention(M4ULP_RAM16K_RETENTION_MODE_EN | TA_RAM_RETENTION_MODE_EN | M4ULP_RAM_RETENTION_MODE_EN
521 | M4SS_RAM_RETENTION_MODE_EN);
522 /*do not save CPU context and go to deep sleep */
523 __asm("WFI");
524 }
525 //Disable the NVIC interrupts.
526 __asm volatile("cpsid i" ::: "memory");
527 __asm volatile("dsb");
528 __asm volatile("isb");
529 #ifdef SLI_SI91X_MCU_COMMON_FLASH_MODE
530 /* if flash is not initialised ,then raise a request to NWP */
531 if (!(in_ps2_state) && !(M4SS_P2P_INTR_SET_REG & M4_USING_FLASH)) {
532 //!check NWP wokeup or not
533 if (!(P2P_STATUS_REG & TA_IS_ACTIVE)) {
534 //!wakeup NWP
535 P2P_STATUS_REG |= M4_WAKEUP_TA;
536
537 //!wait for NWP active
538 while (!(P2P_STATUS_REG & TA_IS_ACTIVE))
539 ;
540 }
541 //!Check for TA_USING flash bit
542 if (!(TASS_P2P_INTR_CLEAR_REG & TA_USING_FLASH)) {
543 //! Request NWP to program flash
544 //! raise an interrupt to NWP register
545 M4SS_P2P_INTR_SET_REG = PROGRAM_COMMON_FLASH;
546
547 //!Wait for NWP using flash bit
548 while (!(TASS_P2P_INTR_CLEAR_REG & TA_USING_FLASH))
549 ;
550 }
551 M4SS_P2P_INTR_SET_REG = M4_USING_FLASH;
552 }
553 #endif
554 #ifdef SLI_SI91X_MCU_ENABLE_PSRAM_FEATURE
555 #if PSRAM_HALF_SLEEP_SUPPORTED != FALSE
556 /* Exit PSRAM device from sleep */
557 sl_si91x_psram_wakeup();
558 #endif
559 #endif
560
561 #ifdef SLI_SI91X_ENABLE_OS
562 /* Restore Stack pointer value and Control registers */
563 RSI_Restore_Context();
564 #endif
565 /*Restore the default value to the processor clock */
566 if ((in_ps2_state)) {
567 ULPCLK->ULP_TA_CLK_GEN_REG_b.ULP_PROC_CLK_SEL = (unsigned int)(ulp_proc_clk & 0xF);
568 }
569
570 #if ((defined SLI_SI91X_MCU_COMMON_FLASH_MODE) && (!(defined(RAM_COMPILATION))))
571 /* Before NWP is going to power save mode, set m4ss_ref_clk_mux_ctrl ,tass_ref_clk_mux_ctrl ,AON domain power supply controls from NWP to M4 */
572 RSI_Set_Cntrls_To_M4();
573 #endif
574
575 // READ_MBR_MAGIC_WORD_ON_WAKEUP
576 #ifdef SLI_SI91X_MCU_COMMON_FLASH_MODE
577 if (!(in_ps2_state)) {
578 //!Poll for flash magic word
579 while (MBR_MAGIC_WORD != 0x5A5A)
580 ;
581 }
582 #endif
583
584 #ifndef SL_SI91X_NPSS_GPIO_BTN_HANDLER
585 // Clearing NPSS GPIO rise edge interrupts to avoid false triggering after wakeup
586 NPSS_GPIO_CONFIG_CLR_REG = NPSS_GPIO_CLR_VALUE;
587
588 // Restoring the NPSS GPIO interrupt configurations after wakeup
589 NPSS_GPIO_CONFIG_REG = npss_gpio_config;
590 #endif
591 /* After wake-up, Set the SCDC voltage to the actual value*/
592 /* As this function is located in flash accessing this fucntion only after getting controls*/
593 set_scdc(SL_SCDC_ACTIVE);
594
595 /*Update the REG Access SPI division factor to increase the SPI read/write speed*/
596
597 RSI_SetRegSpiDivision(1U);
598
599 /*IPMU dummy read to make IPMU block out of RESET*/
600 ipmuDummyRead = ULP_SPI_MEM_MAP(0x144);
601 // After Wakeup
602 if (!((in_ps2_state) && (MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE_b.ULPSS_BASED_WAKEUP_b))) {
603 #if (XTAL_CAP_MODE == POWER_TARN_CONDITIONAL_USE)
604 if (lf_clk_mode & BIT(4)) {
605 // disable the XTAL CAP mode
606 RSI_PS_NpssPeriPowerUp(SLPSS_PWRGATE_ULP_MCUTS);
607 /*configure the slope,nominal temperature and f2_nominal*/
608 RSI_TS_Config(MCU_TEMP, 25);
609 /*disable the bjt based temp sensor*/
610 RSI_TS_RoBjtEnable(MCU_TEMP, 0);
611 /*Enable the RO based temp sensor*/
612 RSI_TS_Enable(MCU_TEMP, 1);
613 /*update the temperature periodically*/
614 RSI_Periodic_TempUpdate(TIME_PERIOD, 1, 0);
615 /*read the temperature*/
616 Temp = (int)RSI_TS_ReadTemp(MCU_TEMP);
617 if (Temp > 45) {
618 //SCDC0
619 RSI_IPMU_ProgramConfigData(scdc_volt_sel1);
620 RSI_IPMU_ProgramConfigData(scdc_volt_trim_efuse);
621 //SCDC0_1
622 RSI_IPMU_ProgramConfigData(scdc_volt_sel2);
623 }
624 }
625 #endif
626
627 #if (XTAL_CAP_MODE == POWER_TARN_ALWAYS_USE)
628 // disable the XTAL CAP mode
629 //SCDC0
630 RSI_IPMU_ProgramConfigData(scdc_volt_sel1);
631 RSI_IPMU_ProgramConfigData(scdc_volt_trim_efuse);
632 //SCDC0_1
633 RSI_IPMU_ProgramConfigData(scdc_volt_sel2);
634 #endif
635 }
636 /*Spare register write sequence*/
637 ipmuDummyRead = ULP_SPI_MEM_MAP(0x1C1);
638 ULP_SPI_MEM_MAP(0x141) = ipmuDummyRead;
639
640 ipmuDummyRead = ULP_SPI_MEM_MAP(0x1C0);
641 ULP_SPI_MEM_MAP(0x140) = ipmuDummyRead;
642 RSI_PS_LatchCntrlSet(LATCH_TOP_SPI);
643
644 if (in_ps2_state) {
645 /*Come out of LP mode */
646 /* enabling the RETN_LDO HP MODE */
647 RSI_IPMU_RetnLdoHpmode();
648 }
649 /*I2S-PLL Bypass*/
650 *(volatile uint32_t *)(0x24041400 + 0x3C) |= BIT(0);
651
652 if (enable_sdcss_based_wakeup) {
653 RSI_PS_ClrWkpSources(SDCSS_BASED_WAKEUP);
654 enable_sdcss_based_wakeup = 0;
655 }
656 if (enable_m4ulp_retention) {
657 RSI_PS_M4ssRamBanksPowerUp(m4ulp_ram_core_status);
658 RSI_PS_M4ssRamBanksPeriPowerUp(m4ulp_ram_peri_status);
659 enable_m4ulp_retention = 0;
660 }
661 if (disable_pads_ctrl) {
662 ULP_SPI_MEM_MAP(0x141) |= (BIT(11)); // ULP PADS PDO ON
663 disable_pads_ctrl = 0;
664 }
665
666 /* powerup FPU domain*/
667 RSI_PS_M4ssPeriPowerUp(M4SS_PWRGATE_ULP_M4_DEBUG_FPU);
668
669 /*Initialize floating point unit */
670 fpuInit();
671
672 #if defined(SLI_SI91X_MCU_ENABLE_RAM_BASED_EXECUTION)
673 //passing the ram vector address to VTOR register
674 SCB->VTOR = (uint32_t)ram_vector;
675 #endif
676
677 /* Restore NPSS INTERRUPTS*/
678 NPSS_INTR_MASK_CLR_REG = ~npssIntrState;
679
680 /* Restore P2P register values from backup */
681 TASS_P2P_INTR_MASK_CLR = ~p2p_intr_status_bkp.tass_p2p_intr_mask_clr_bkp;
682 M4SS_P2P_INTR_SET_REG = p2p_intr_status_bkp.m4ss_p2p_intr_set_reg_bkp;
683
684 /* Restore the Interrupt Priority Register */
685 for (var = 0; var < MAX_IPS; ++var) {
686 NVIC->IP[var] = nvic_ip_reg[var];
687 }
688 /* Restore the System Handlers Priority Registers */
689 for (var = 0; var < MAX_SHP; ++var) {
690 SCB->SHP[var] = scs_shp_reg[var];
691 }
692 /* Restore the NVIC registers */
693 for (var = 0; var < MAX_NVIC_REGS; ++var) {
694 NVIC->ISER[var] = nvic_enable[var];
695 }
696 return RSI_OK;
697 }
698