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