1 /******************************************************************************
2 * @file  rsi_rom_power_save.h
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 // Includes
31 
32 #ifndef __RSI_ROM_POWER_SAVE_H__
33 #define __RSI_ROM_POWER_SAVE_H__
34 
35 #include "rsi_ccp_user_config.h"
36 #include "rsi_packing.h"
37 #if defined(A11_ROM)
38 #include "rsi_rom_table_si91x.h"
39 #else
40 #include "rsi_rom_table_RS1xxxx.h"
41 #endif
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 #ifndef UNUSED_PARAMETER
48 #define UNUSED_PARAMETER(x) (void)(x)
49 #endif // UNUSED_PARAMETER
50 
51 /**
52  * \ingroup   RSI_SPECIFIC_DRIVERS
53  * \defgroup POWER_SAVE
54  *  @{
55  *
56  */
57 /**
58  * @fn            STATIC INLINE rsi_error_t RSI_PS_PowerStateChangePs4toPs2(ULP_MODE_T enCtxSel          ,
59  *		                                          uint8_t PwrMuxSelUlpssRam    ,
60  *                                                        uint8_t pwrMuxSelM4UlpRam    ,
61  *							  uint8_t pwrMuxSelM4UlpRam16K ,
62  *					   		  uint8_t pwrMuxSelM4Ulp       ,
63  *                                                        uint8_t pwrMuxSelUlpss       ,
64  *						          uint8_t bgSampleEnable       ,
65  *		                                          uint8_t dcDcEnable           ,
66  *		                                          uint8_t socLdoEnable         ,
67  *		                                          uint8_t standByDc
68  *                                                        )
69  * @brief         This API is used to used to change the power transition state from Power save state 4/3 to power save state 2
70  * @param[in]     enCtxSel : is Select enum for the context top ULP mode
71  *                \n  00, 10 - \ref HP-MCU/LP-MCU Mode
72  *                \n  01 - \ref ULP-MCU Mode
73  *                \n  11 - \ref UULP-MCU Mode
74  *                \n  (1st 16K of M4 RAM is dedicated to IM,
75  *                \n  2nd 16K of M4 RAM is dedicated to DM)
76  * @param[in]     pwrMuxSelM4UlpRam : Select value for M4 ULP RAM Power MUX
77  *                \n  3 \ref  SOC LDO
78  *                \n  1 \ref  SCDCDC 0.9
79  *                \n  0 \ref  SCDCDC 0.6
80  * @param[in]    PwrMuxSelUlpssRam :Select value for ULPSS RAM Power MUX
81  *                \n  3 \ref  SOC LDO
82  *                \n  1 \ref  SCDCDC 0.9
83  *                \n  0 \ref  SCDCDC 0.6
84  * @param[in]     pwrMuxSelM4UlpRam16K : is Select value for M4 ULP RAM 16K Power MUX
85  *                \n  3 \ref  SOC LDO
86  *                \n  1 \ref  SCDCDC 0.9
87  *                \n  0  \ref SCDCDC 0.6
88  * @param[in]     pwrMuxSelM4Ulp : is Select value for M4 ULP (Peripherals + CORTEX Core )Power MUX
89  *                \n  3 \ref SOC LDO
90  *                \n  1 \ref SCDCDC 0.9
91  *                \n  0 \ref SCDCDC 0.6
92  * @param[in]     pwrMuxSelUlpss : is Select value for ULPSS(Peripherals) Power MUX
93  *                \n  1 \ref SOC LDO
94  *                \n  0 \ref SCDCDC 0.9
95  * @param[in]     bgSampleEnable  : Value to enable or disable the bg Sample
96  *                                  \n 0 :Disable
97  *                                  \n 1 :Enale
98  * @param[in]     dcDcEnable      : Value to enable or disable the dcDcEnable
99  *                                  \n 0 :Disable
100  *                                  \n 1 :Enale
101  * @param[in]     socLdoEnable    : Value to enable or disable the socLdoEnable
102  *                                  \n 0 :Disable
103  *                                  \n 1 :Enale
104  * @param[in]     standByDc       : Value to enable or disable the standByDc
105  *                                  \n 0 :Disable
106  *                                  \n 1 :Enale
107  * @return        returns 0 \ref RSI_OK on success,return error code on error
108  */
RSI_PS_PowerStateChangePs4toPs2(ULP_MODE_T enCtxSel,uint8_t PwrMuxSelUlpssRam,uint8_t pwrMuxSelM4UlpRam,uint8_t pwrMuxSelM4UlpRam16K,uint8_t pwrMuxSelM4Ulp,uint8_t pwrMuxSelUlpss,uint8_t bgSampleEnable,uint8_t dcDcEnable,uint8_t socLdoEnable,uint8_t standByDc,uint8_t taRamRetEnable,uint8_t M4RamRetEnable)109 STATIC INLINE rsi_error_t RSI_PS_PowerStateChangePs4toPs2(ULP_MODE_T enCtxSel,
110                                                           uint8_t PwrMuxSelUlpssRam,
111                                                           uint8_t pwrMuxSelM4UlpRam,
112                                                           uint8_t pwrMuxSelM4UlpRam16K,
113                                                           uint8_t pwrMuxSelM4Ulp,
114                                                           uint8_t pwrMuxSelUlpss,
115                                                           uint8_t bgSampleEnable,
116                                                           uint8_t dcDcEnable,
117                                                           uint8_t socLdoEnable,
118                                                           uint8_t standByDc,
119                                                           uint8_t taRamRetEnable,
120                                                           uint8_t M4RamRetEnable)
121 {
122   // TODO: Check  silicon rev from flash/efuse offset; for 1.4V do this programming
123   if (SiliconRev >= 0x14) {
124     if (taRamRetEnable) {
125       MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE |= HPSRAM_RET_ULP_MODE_EN;
126       MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE |= TA_RAM_RETENTION_MODE_EN;
127     }
128     if (M4RamRetEnable) {
129       MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE |= HPSRAM_RET_ULP_MODE_EN;
130       MCU_FSM->MCU_FSM_SLEEP_CTRLS_AND_WAKEUP_MODE |= M4SS_RAM_RETENTION_MODE_EN;
131 #if !defined(SLI_SI917) && !defined(SLI_SI915)
132       M4CLK->CLK_ENABLE_SET_REG1_b.M4SS_UM_CLK_STATIC_EN_b = 0x1;
133 #endif
134       for (uint8_t x = 0; x < 10; x++) {
135         __ASM("NOP");
136       }
137 #if !defined(SLI_SI917) && !defined(SLI_SI915)
138       M4CLK->CLK_ENABLE_CLR_REG1_b.M4SS_UM_CLK_STATIC_EN_b = 0x1;
139 #endif
140     }
141   }
142   // Moved this API from ROM to appication memmory
143   return ps_power_state_change_ps4tops2(enCtxSel,
144                                         PwrMuxSelUlpssRam,
145                                         pwrMuxSelM4UlpRam,
146                                         pwrMuxSelM4UlpRam16K,
147                                         pwrMuxSelM4Ulp,
148                                         pwrMuxSelUlpss,
149                                         bgSampleEnable,
150                                         dcDcEnable,
151                                         socLdoEnable,
152                                         standByDc);
153 }
154 
155 /**
156  * @fn          STATIC INLINE rsi_error_t RSI_PS_PowerStateChangePs2toPs4(uint32_t PmuBuckTurnOnWaitTime , uint32_t SocLdoTurnOnWaitTime)
157  * @brief	      This API is used to change the power state from PS2 to PS4
158  * @param[in]	  PmuBuckTurnOnWaitTime :  PMU buck time
159  * @param[in]	  SocLdoTurnOnWaitTime : soc ldo turn on time
160  * @return       returns 0 \ref RSI_OK on success,return error code on error
161  */
RSI_PS_PowerStateChangePs2toPs4(uint32_t PmuBuckTurnOnWaitTime,uint32_t SocLdoTurnOnWaitTime)162 STATIC INLINE rsi_error_t RSI_PS_PowerStateChangePs2toPs4(uint32_t PmuBuckTurnOnWaitTime, uint32_t SocLdoTurnOnWaitTime)
163 {
164   // Moved this API from ROM to appication memmory
165   return ps_power_state_change_ps2_to_Ps4(PmuBuckTurnOnWaitTime, SocLdoTurnOnWaitTime);
166 }
167 
168 /**
169  * @fn            void RSI_PS_ClrWkpUpStatus(uint32_t wakeUpIntrClear)
170  * @brief	        This API is used clear the NPSS/wake up interrupts.
171  * @param         wakeUpIntrClear :  OR'ed value of register bits of NPSS interrupt register
172  * @return        none
173  */
RSI_PS_ClrWkpUpStatus(uint32_t wakeUpIntrClear)174 STATIC INLINE void RSI_PS_ClrWkpUpStatus(uint32_t wakeUpIntrClear)
175 {
176 #if defined(PS_ROMDRIVER_PRESENT)
177   ROMAPI_PWR_API->ps_clr_wkp_up_status(wakeUpIntrClear);
178 #else
179   ps_clr_wkp_up_status(wakeUpIntrClear);
180 #endif
181 }
182 
183 #if defined(SLI_SI917B0) || defined(SLI_SI915)
184 
RSI_PS_RetentionSleepConfig_bypass(uint32_t stack_address,uint32_t jump_cb_address,uint32_t vector_offset,uint32_t mode)185 STATIC INLINE void RSI_PS_RetentionSleepConfig_bypass(uint32_t stack_address,
186                                                       uint32_t jump_cb_address,
187                                                       uint32_t vector_offset,
188                                                       uint32_t mode)
189 {
190   UNUSED_PARAMETER(vector_offset);
191   qspi_reg_t *qspi_reg2 = (qspi_reg_t *)M4SS_PSRAM_QSPI_BASE_ADDRESS;
192   if (mode == RSI_WAKEUP_WITH_RETENTION) {
193     *(uint32 *)RSI_WAKE_FROM_FLASH_JUMP_ADDR = jump_cb_address;
194   } else {
195     if (MCURET_BOOTSTATUS_REG & BIT(13) || (M4_BBFF_STORAGE1 & PSRAM_SEC_EN)) {
196       if (((((qspi_reg_t *)QSPI)->QSPI_AES_CONFIG) & QSPI_KEY_SIZE_256)
197           || ((qspi_reg2->QSPI_AES_CONFIG) & QSPI_KEY_SIZE_256)) {
198         M4_BBFF_STORAGE1 |= KEY_LENGTH;
199       }
200     }
201     M4_BBFF_STORAGE1 &= ~(0xffUL << STACK_AND_CB_ADDR_BIT_NO);
202     //! Keeping stack address with 2k granularity.
203     M4_BBFF_STORAGE1 |= (((stack_address >> 11) & 0xFF) << STACK_AND_CB_ADDR_BIT_NO);
204 
205     M4_BBFF_STORAGE1 |= STACK_AND_CB_ADDR_PRESENT_IN_BBFF;
206   }
207 }
208 #endif
209 
210 /**
211  * @fn            STATIC INLINE void RSI_PS_RetentionSleepConfig(uint32_t stack_address, uint32_t jump_cb_address, uint32_t vector_offset,uint32_t mode)
212  * @brief	        This API is used configure the wake up parameter for retention sleep
213  * @param         stack_address   :
214  * @param         jump_cb_address :
215  * @param         stack_address   :
216  * @param         vector_offset   :
217  * @param         mode            : Following are the possible parameters for this parameter
218  *                                  \n \ref RSI_WAKEUP_FROM_FLASH_MODE    : Wakes from flash with retention. Upon wake up control jumps to wake up handler in flash.
219  *                                                                 In this mode ULPSS RAMs are used to store the stack pointer and wake up handler address.
220  *                                  \n \ref RSI_WAKEUP_WITH_OUT_RETENTION : Without retention sleep common for both FLASH/RAM based execution.
221  *                                                                  In this mode ULPSS RAMs are used to store the stack pointer and control block address.
222  *                                                                  if stack_addr and jump_cb_addr are not valid then 0x2404_0C00 and 0x2404_0000 are used
223  *                                                                  for stack and control block address respectively.
224  *
225  *                                  \n \ref RSI_WAKEUP_WITH_RETENTION     : With retention branches to wake up handler in RAM.
226  *                                                                  In this mode ULPSS RAMs are used to store the wake up handler address.
227  *                                  \n \ref RSI_WAKEUP_WITH_RETENTION_WO_ULPSS_RAM : In this mode ULPSS RAMs are not used by boot-loader instead it uses the NPSS battery flip flops.
228  *                                  \n \ref RSI_WAKEUP_WO_RETENTION_WO_ULPSS_RAM   :In this mode ULPSS RAMs are not used by boot-loader.
229  *                                                                          Instead it uses the NPSS battery flip flops to store the stack and derives the control block address by adding 0XC00
230  *                                                                          to the stack address stored in battery flops.
231  * @return        none
232  */
RSI_PS_RetentionSleepConfig(uint32_t stack_address,uint32_t jump_cb_address,uint32_t vector_offset,uint32_t mode)233 STATIC INLINE void RSI_PS_RetentionSleepConfig(uint32_t stack_address,
234                                                uint32_t jump_cb_address,
235                                                uint32_t vector_offset,
236                                                uint32_t mode)
237 {
238 
239 #if defined(SLI_SI917B0) || defined(SLI_SI915)
240   //!write magic numbers in retention ram content ulp memory start ,end addresses (work around for jtag mode powersave)
241   RETEN_RAM_CONTENT_START_LOCATION = 0xBEAFBEAF;
242   RETEN_RAM_CONTENT_END_LOCATION   = 0xBEADBEAD;
243 
244   //!remove wakeup flash bit in ulpss ram if flash is not required upon wakuep
245   if (mode == SL_SI91X_MCU_WAKEUP_PSRAM_MODE) {
246     RETEN_RAM_CONTENT_WAKEUP_FLASH_BIT_LOCATION = 0x0;
247   }
248 
249   if ((mode == RSI_WAKEUP_WITH_RETENTION) || (mode == RSI_WAKEUP_WO_RETENTION_WO_ULPSS_RAM)) {
250     RSI_PS_RetentionSleepConfig_bypass(stack_address, jump_cb_address, vector_offset, mode);
251   } else {
252     ROMAPI_PWR_API->RSI_GotoSleepWithRetention(stack_address, jump_cb_address, vector_offset, mode);
253   }
254 #else
255   ROMAPI_PWR_API->RSI_GotoSleepWithRetention(stack_address, jump_cb_address, vector_offset, mode);
256 #endif
257 }
258 
259 /**
260  * @fn            STATIC INLINE void RSI_PS_BgLdoConfig(uint8_t ldo_0p6_ctrl, uint8_t ldo_0p6_lp_mode)
261  * @brief	        This API is used configure the LP low power mode and vref for DCDC1p1_lp_500uA
262  * @param         ldo_0p6_ctrl :  vref for DCDC1p1_lp_500uA
263  *                                - 0 - 0.8V
264  *                                - 1 - 0.75V
265  *                                - 2 - 0.7V
266  *                                - 3 - 0.65V
267  *                                - 4 - 0.6V
268  *                                - 5 - 0.55V
269  * @param         ldo_0p6_lp_mode : 1:enable low power mode, 0:otherwise in high power mode
270  * @return        none
271  */
RSI_PS_BgLdoConfig(uint8_t ldo_0p6_ctrl,uint8_t ldo_0p6_lp_mode)272 STATIC INLINE void RSI_PS_BgLdoConfig(uint8_t ldo_0p6_ctrl, uint8_t ldo_0p6_lp_mode)
273 {
274 #if defined(CHIP_9118) && defined(A11_ROM) && defined(PS_ROMDRIVER_PRESENT)
275   ROMAPI_PWR_API->ps_bg_ldo_config(ldo_0p6_ctrl, ldo_0p6_lp_mode);
276 #else
277   ps_bg_ldo_config(ldo_0p6_ctrl, ldo_0p6_lp_mode);
278 #endif
279 }
280 
281 /**
282  * @fn            STATIC INLINE void RSI_PS_ConfigurTrimValues(uint16_t lf_ro_trim ,uint16_t lf_rc_trim , uint16_t hf_ro_trim ,uint16_t hf_rc_trim ,uint16_t bg_ptat_trim , uint16_t bg_trim)
283  * @brief	        This API is used configure the clock and bg trim values
284  * @param[in]         lf_ro_trim : trim value for low frequency RO clock
285  * @param[in]         lf_rc_trim : trim value for low frequency RC clock
286  * @param[in]         hf_ro_trim : trim value for high frequency RO clock
287  * @param[in]         hf_rc_trim : trim value for high frequency RC clock
288  * @param[in]         bg_ptat_trim : trim value for bg ptat
289  * @param[in]         bg_trim    : trim value for bg(Band Gap)
290  * @return        none
291  */
RSI_PS_ConfigurTrimValues(uint16_t lf_ro_trim,uint16_t lf_rc_trim,uint16_t hf_ro_trim,uint16_t hf_rc_trim,uint16_t bg_ptat_trim,uint16_t bg_trim)292 STATIC INLINE void RSI_PS_ConfigurTrimValues(uint16_t lf_ro_trim,
293                                              uint16_t lf_rc_trim,
294                                              uint16_t hf_ro_trim,
295                                              uint16_t hf_rc_trim,
296                                              uint16_t bg_ptat_trim,
297                                              uint16_t bg_trim)
298 {
299 #if defined(CHIP_9118) && defined(A11_ROM) && defined(PS_ROMDRIVER_PRESENT)
300   ROMAPI_PWR_API->ps_configure_trim_values(lf_ro_trim, lf_rc_trim, hf_ro_trim, hf_rc_trim, bg_ptat_trim, bg_trim);
301 #else
302   ps_configure_trim_values(lf_ro_trim, lf_rc_trim, hf_ro_trim, hf_rc_trim, bg_ptat_trim, bg_trim);
303 #endif
304 }
305 
306 /**
307  * @fn            STATIC INLINE void RSI_PS_WirelessShutdown(void)
308  * @brief	        This API is used shut-down the wireless
309  * @return        none
310  */
RSI_PS_WirelessShutdown(void)311 STATIC INLINE void RSI_PS_WirelessShutdown(void)
312 {
313   // Wireless shutdown should be called only on First/Reset boot
314   if (MCU_FSM->MCU_FSM_CLK_ENS_AND_FIRST_BOOTUP_b.FIRST_BOOTUP_MCU_N_b == 0) {
315 #if defined(CHIP_9118) && defined(A11_ROM) && defined(PS_ROMDRIVER_PRESENT)
316     ROMAPI_PWR_API->ps_wireless_shutdown();
317 #else
318     ps_wireless_shutdown();
319 #endif
320   }
321 }
322 
323 /*end of file*/
324 
325 #ifdef __cplusplus
326 }
327 #endif
328 
329 #endif /*__RSI_ROM_POWER_SAVE_H__*/
330 
331 /* @}end of RSI_POWER_SAVE */
332