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