1 /******************************************************************************
2 * @file system_si91x.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
34 #include <stdint.h>
35 #include "system_si91x.h"
36 #include "rsi_error.h"
37 #include "rsi_ccp_common.h"
38 #include "rsi_ps_ram_func.h"
39 #include "rsi_ipmu.h"
40 #include "rsi_pll.h"
41 #include "rsi_power_save.h"
42 #include "rsi_ulpss_clk.h"
43 #include "rsi_rom_ulpss_clk.h"
44 #include "rsi_rom_clks.h"
45 #if defined(SLI_SI91X_MCU_PSRAM_PRESENT)
46 #include "rsi_d_cache.h"
47 #endif
48
49 #if defined(SI91X_32kHz_EXTERNAL_OSCILLATOR)
50 #include "sl_si91x_external_oscillator.h"
51 #define MCU_RETENTION_BASE_ADDRESS 0x24048600
52 #define NPSS_GPIO_CTRL (MCU_RETENTION_BASE_ADDRESS + 0x1C)
53 #endif
54
55 #if defined(SLI_SI915)
56 #define BG_LDO_REG1 0x129 //IPMU Bandgap Top register
57 #define LDO_0P6_BYPASS_BIT 21 //Retention LDO bypass
58 #endif
59 /*----------------------------------------------------------------------------
60 Define clocks
61 *----------------------------------------------------------------------------*/
62 /*Cortex-m4 FPU registers*/
63 #define FPU_CPACR 0xE000ED88
64 #define SCB_MVFR0 0xE000EF40
65 #define SCB_MVFR0_RESET 0x10110021
66 #define SCB_MVFR1 0xE000EF44
67 #define SCB_MVFR1_RESET 0x11000011
68
69 /*Simulation macros*/
70 #define SIMULATION_SILICON_REV 0x14
71 #define SIMULATION_PACKAGE_TYPE 0x1
72
73 /* Constants required to manipulate the NVIC. */
74 /*----------------------------------------------------------------------------
75 Clock Variable definitions
76 *----------------------------------------------------------------------------*/
77 uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock)*/
78
79 SYSTEM_CLOCK_SOURCE_FREQUENCIES_T system_clocks; /*!< System Clock sources Frequencies */
80
81 uint32_t npssIntrState = 0;
82 uint32_t __sp;
83 uint32_t SiliconRev;
84 uint32_t package_type;
85
86 /**
87 * @fn void SystemCoreClockUpdate (void)
88 * @brief Updates the SystemCoreClock with current core Clock
89 * retrieved from cpu registers.
90 * @return none
91 */
SystemCoreClockUpdate(void)92 void SystemCoreClockUpdate(void) /* Get Core Clock Frequency */
93 {
94 const retention_boot_status_word_t *retention_reg = (const retention_boot_status_word_t *)MCURET_BOOTSTATUS;
95
96 /*Updated the default SOC clock frequency*/
97 SystemCoreClock = DEFAULT_40MHZ_CLOCK;
98 #if (defined(RAM_COMPILATION) && defined(SLI_SI91X_MCU_COMMON_FLASH_MODE))
99 /*Initialize QSPI for RAM based execution for common flash boards */
100 RSI_FLASH_Initialize();
101 #endif
102 #ifndef SIMULATION
103 #ifdef RAM_COMPILATION
104 if (retention_reg->product_mode == MCU) {
105 SiliconRev = SIMULATION_SILICON_REV;
106 package_type = SIMULATION_PACKAGE_TYPE;
107 } else {
108 SiliconRev = SILICON_REV_WMCU;
109 package_type = PACKAGE_TYPE_WMCU;
110 }
111 #else
112 if (retention_reg->product_mode == MCU) {
113 SiliconRev = SILICON_REV_MCU;
114 package_type = PACKAGE_TYPE_MCU;
115 } else {
116 SiliconRev = SILICON_REV_WMCU;
117 package_type = PACKAGE_TYPE_WMCU;
118 }
119 #endif
120 #if defined(SLI_SI91X_MCU_PSRAM_PRESENT)
121 rsi_d_cache_invalidate_all();
122 #endif
123 /*Initialize IPMU and MCU FSM blocks */
124 RSI_Ipmu_Init();
125 /*configures chip supply mode */
126 RSI_Configure_Ipmu_Mode();
127
128 #endif
129 /*Default clock mux configurations */
130 RSI_CLK_PeripheralClkEnable3(M4CLK, M4_SOC_CLK_FOR_OTHER_ENABLE);
131
132 /* NWP clock is selected as 40MHZ clock from MCU */
133 MCU_FSM->MCU_FSM_REF_CLK_REG_b.TASS_REF_CLK_SEL = ULP_MHZ_RC_CLK;
134 /* Changing NPSS GPIO 0 mode to 0, to disable buck-boost enable mode*/
135 MCU_RET->NPSS_GPIO_CNTRL[0].NPSS_GPIO_CTRLS_b.NPSS_GPIO_MODE = 0;
136 /* Configuring MCU FSM clock for BG_PMU */
137 RSI_IPMU_ClockMuxSel(2);
138
139 #if defined(SI91X_32kHz_EXTERNAL_OSCILLATOR)
140
141 // Configuring the UULP_GPIOs for external oscillator
142 *(volatile uint32 *)(NPSS_GPIO_CTRL + (4 * OSC_UULP_GPIO)) = (BIT(3) | UULP_GPIO_OSC_MODE);
143 MCUAON_GEN_CTRLS_REG |= BIT(0);
144 MCUAON_GEN_CTRLS_REG;
145
146 // Configuring RC 32KHz Clock for LF-FSM
147 RSI_PS_FsmLfClkSel(KHZ_RC_CLK_SEL);
148 #else
149 /* Configuring XTAL 32.768kHz Clock for LF-FSM */
150 RSI_PS_FsmLfClkSel(KHZ_XTAL_CLK_SEL);
151 #endif // SI91X_32kHz_EXTERNAL_OSCILLATOR
152
153 /* Configuring RC-MHz Clock for HF-FSM */
154 RSI_PS_FsmHfClkSel(FSM_MHZ_RC);
155
156 /* XTAL control pointed to Software and XTAL is Turned-Off from M4 */
157 RSI_ConfigXtal(XTAL_DISABLE_FROM_M4, XTAL_IS_IN_SW_CTRL_FROM_M4);
158
159 #if ((defined SLI_SI91X_MCU_COMMON_FLASH_MODE) && (!(defined(RAM_COMPILATION))))
160 /* Before NWP is going to power save mode ,set m4ss_ref_clk_mux_ctrl ,
161 tass_ref_clk_mux_ctrl, AON domain power supply controls from NWP to M4 */
162 RSI_Set_Cntrls_To_M4();
163
164 #endif
165 #if defined(SLI_SI915)
166 ULP_SPI_MEM_MAP(BG_LDO_REG1) |= BIT(LDO_0P6_BYPASS_BIT); //bypassing the retention LDO
167 #endif
168 /*Update the system clock sources with source generating frequency*/
169 system_clocks.m4ss_ref_clk = DEFAULT_40MHZ_CLOCK;
170 system_clocks.ulpss_ref_clk = DEFAULT_40MHZ_CLOCK;
171 system_clocks.soc_pll_clock = DEFAULT_SOC_PLL_CLOCK;
172 system_clocks.modem_pll_clock = DEFAULT_MODEM_PLL_CLOCK;
173 system_clocks.modem_pll_clock2 = DEFAULT_MODEM_PLL_CLOCK;
174 system_clocks.intf_pll_clock = DEFAULT_INTF_PLL_CLOCK;
175 system_clocks.soc_clock = DEFAULT_40MHZ_CLOCK;
176 system_clocks.rc_32khz_clock = DEFAULT_32KHZ_RC_CLOCK;
177 system_clocks.rc_mhz_clock = DEFAULT_MHZ_RC_CLOCK;
178 system_clocks.ro_20mhz_clock = DEFAULT_20MHZ_RO_CLOCK;
179 system_clocks.ro_32khz_clock = DEFAULT_32KHZ_RO_CLOCK;
180 system_clocks.xtal_32khz_clock = DEFAULT_32KHZ_XTAL_CLOCK;
181 system_clocks.doubler_clock = DEFAULT_DOUBLER_CLOCK;
182 system_clocks.rf_ref_clock = DEFAULT_40MHZ_CLOCK;
183 system_clocks.mems_ref_clock = DEFAULT_MEMS_REF_CLOCK;
184 system_clocks.byp_rc_ref_clock = DEFAULT_MHZ_RC_CLOCK;
185 system_clocks.i2s_pll_clock = DEFAULT_I2S_PLL_CLOCK;
186
187 return;
188 }
189
190 /**
191 * @fn void fpuInit(void)
192 * @brief This API is used to Early initialization of the FPU
193 * @return none
194 *
195 */
fpuInit(void)196 void fpuInit(void)
197 {
198 #if __FPU_PRESENT != 0
199 // from arm trm manual:
200 // ; CPACR is located at address 0xE000ED88
201 // LDR.W R0, =0xE000ED88
202 // ; Read CPACR
203 // LDR R1, [R0]
204 // ; Set bits 20-23 to enable CP10 and CP11 coprocessors
205 // ORR R1, R1, #(0xF << 20)
206 // ; Write back the modified value to the CPACR
207 // STR R1, [R0]
208
209 volatile uint32_t *regCpacr = (uint32_t *)FPU_CPACR;
210 volatile const uint32_t *regMvfr0 = (volatile const uint32_t *)SCB_MVFR0;
211 volatile const uint32_t *regMvfr1 = (volatile const uint32_t *)SCB_MVFR1;
212 volatile uint32_t Cpacr;
213 volatile uint32_t Mvfr0;
214 volatile uint32_t Mvfr1;
215 char vfpPresent = 0;
216
217 Mvfr0 = *regMvfr0;
218 Mvfr1 = *regMvfr1;
219
220 vfpPresent = ((SCB_MVFR0_RESET == Mvfr0) && (SCB_MVFR1_RESET == Mvfr1));
221
222 if (vfpPresent) {
223 Cpacr = *regCpacr;
224 Cpacr |= (0xF << 20);
225 *regCpacr = Cpacr; // enable CP10 and CP11 for full access
226 }
227 #endif /* __FPU_PRESENT != 0 */
228 }
229
230 /**
231 * @fn void SystemInit (void)
232 * @brief This API is used Setup the RS1xxxx chip(Initialize the system)
233 * @return none
234 */
SystemInit(void)235 void SystemInit(void)
236 {
237 volatile uint32_t ipmuDummyRead = 0;
238 volatile uint32_t spareReg2 = 0;
239
240 /*IPMU dummy read to make IPMU block out of RESET*/
241 ipmuDummyRead = ULP_SPI_MEM_MAP(0x144);
242 ipmuDummyRead = ipmuDummyRead;
243
244 /*Update the REG Access SPI division factor to increase the SPI read/write speed*/
245 RSI_SetRegSpiDivision(0U);
246
247 ULP_SPI_MEM_MAP(BG_SCDC_PROG_REG_1) &= REF_SEL_LP_DCDC;
248
249 /*Spare register write sequence*/
250 spareReg2 = ULP_SPI_MEM_MAP(0x1C1);
251 ULP_SPI_MEM_MAP(0x141) = spareReg2;
252 //while(GSPI_CTRL_REG1 & SPI_ACTIVE);
253 /*Spare register write sequence*/
254 spareReg2 = ULP_SPI_MEM_MAP(0x1C0);
255 ULP_SPI_MEM_MAP(0x140) = spareReg2;
256
257 /*Set IPMU BITS*/
258 ULP_SPI_MEM_MAP(SELECT_BG_CLK) |= (LATCH_TOP_SPI | LATCH_TRANSPARENT_HF | LATCH_TRANSPARENT_LF);
259
260 while (GSPI_CTRL_REG1 & SPI_ACTIVE)
261 ;
262
263 MCU_AON->MCUAON_GEN_CTRLS_b.ENABLE_PDO = 1;
264 MCU_AON->MCUAON_GEN_CTRLS_b.NPSS_SUPPLY_0P9 = 0;
265
266 /*Enable FPU*/
267 fpuInit();
268
269 /* Enable REF Clock Control*/
270 //FIXME: This will be configured by boot-loader based on product mode
271 *(volatile uint32_t *)0x41300004 = BIT(24);
272
273 /*Moving to BG sampling mode */
274 *(volatile uint32_t *)0x24048140 = (BIT(19) | BIT(1) | BIT(0));
275
276 /*Disable WIC based wake up */
277 MCU_FSM->MCU_FSM_PERI_CONFIG_REG_b.WICENREQ = 0;
278
279 /*Set ulp_wakeup_por*/
280 MCU_AON->MCUAON_KHZ_CLK_SEL_POR_RESET_STATUS_b.MCU_FIRST_POWERUP_POR = 1U;
281 MCU_AON->MCUAON_KHZ_CLK_SEL_POR_RESET_STATUS_b.MCU_FIRST_POWERUP_RESET_N = 1U;
282 /*Programmable delay 4mes for WDT reset */
283 PMU_DIRECT_ACCESS(BG_SLEEP_TIMER_REG_OFFSET) |= BIT(19); //bgs_active_timer_sel
284 /*Programmable delay 4mes for WDT reset */
285 MCU_AON->MCUAON_SHELF_MODE_b.SHELF_MODE_WAKEUP_DELAY = 0x7;
286 /* Enables software based control of isolation and reset for ULP AON */
287 BATT_FF->M4SS_BYPASS_PWRCTRL_REG1_b.BYPASS_M4SS_PWRCTL_ULP_AON_b = 1;
288 /* Enables software based control of isolation and reset for M4ss CORE */
289 BATT_FF->M4SS_BYPASS_PWRCTRL_REG1_b.BYPASS_M4SS_PWRCTL_ULP_M4_CORE_b = 1;
290 return;
291 }
292 /**
293 *@}
294 */
295