1 /***************************************************************************/ /**
2 * @file sli_siwx917_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 #if defined(SL_COMPONENT_CATALOG_PRESENT)
31 #include "sl_component_catalog.h"
32 #endif
33 #include "system_si91x.h"
34 #include "rsi_error.h"
35 #include "rsi_ccp_common.h"
36 #include "sl_si91x_constants.h"
37 #include "rsi_ipmu.h"
38 #include "rsi_rom_clks.h"
39 #include "rsi_rom_ulpss_clk.h"
40 #include "rsi_m4.h"
41 #include "sl_si91x_status.h"
42 #include "sli_siwx917_timer.h"
43 #include "sli_siwx917_soc.h"
44 #include "sl_constants.h"
45 #include "rsi_temp_sensor.h"
46 #include "sl_si91x_host_interface.h"
47 #if defined(SL_CATALOG_KERNEL_PRESENT)
48 #include "cmsis_os2.h"
49 #endif
50
51 #define RSI_HAL_MAX_WR_BUFF_LEN 4096
52
53 #define SI91X_INTERFACE_OUT_REGISTER (*(uint32_t *)(RSI_HOST_INTF_REG_OUT))
54 #define SI91X_INTERFACE_IN_REGISTER (*(uint32_t *)(RSI_HOST_INTF_REG_IN))
55 #define SI91X_INTERFACE_STATUS_REGISTER (*(uint32_t *)(RSI_HOST_INTF_STATUS_REG))
56 #define SI91X_PING_BUFFER_ADDRESS_REGISTER (*(uint32_t *)(RSI_PING_BUFFER_ADDR))
57 #define SI91X_PONG_BUFFER_ADDRESS_REGISTER (*(uint32_t *)(RSI_PONG_BUFFER_ADDR))
58
59 typedef struct {
60 uint8_t _[2048];
61 } sli_si91x_pingpong_buffer_t;
62
63 #define SI91X_PING_BUFFER ((sli_si91x_pingpong_buffer_t *)(0x19000))
64 #define SI91X_PONG_BUFFER ((sli_si91x_pingpong_buffer_t *)(0x1A000))
65
66 /**
67 * @fn int16_t rsi_bl_select_option(uint8_t cmd)
68 * @brief Send firmware load request to module or update default configurations.
69 * @param[in] cmd - type of configuration to be saved \n
70 * BURN_NWP_FW - 0x42 \n
71 * LOAD_NWP_FW - 0x31 \n
72 * LOAD_DEFAULT_NWP_FW_ACTIVE_LOW - 0x71 \n
73 * @return 0 - Success \n
74 * Non-Zero Value - Failure \n
75 * -28 - Firmware Load or Upgrade timeout error \n
76 * -14 - Valid Firmware not present \n
77 * -15 - Invalid Option
78 *
79 */
80 /// @private
rsi_bl_select_option(uint8_t cmd)81 int16_t rsi_bl_select_option(uint8_t cmd)
82 {
83 uint16_t boot_cmd = 0;
84 int16_t retval = 0;
85 uint16_t read_value = 0;
86 sl_si91x_timer_t timer_instance;
87
88 SI91X_INTERFACE_OUT_REGISTER = boot_cmd;
89
90 if (cmd == BURN_NWP_FW) {
91 boot_cmd = RSI_HOST_INTERACT_REG_VALID_FW | cmd;
92 } else {
93 boot_cmd = RSI_HOST_INTERACT_REG_VALID | cmd;
94 }
95 retval = sli_si91x_send_boot_instruction(RSI_REG_WRITE, &boot_cmd);
96 if (retval < 0) {
97 return retval;
98 }
99
100 sl_si91x_timer_init(&timer_instance, 300);
101
102 while ((cmd != LOAD_NWP_FW) && (cmd != LOAD_DEFAULT_NWP_FW_ACTIVE_LOW)) {
103 retval = sli_si91x_send_boot_instruction(RSI_REG_READ, &read_value);
104 if (retval < 0) {
105 return retval;
106 }
107 if (cmd == BURN_NWP_FW) {
108 if (read_value == (RSI_HOST_INTERACT_REG_VALID | RSI_SEND_RPS_FILE)) {
109 break;
110 }
111 }
112
113 else if (read_value == (RSI_HOST_INTERACT_REG_VALID | cmd)) {
114 break;
115 }
116 if (sl_si91x_timer_expired(&timer_instance)) {
117 return RSI_ERROR_FW_LOAD_OR_UPGRADE_TIMEOUT;
118 }
119 }
120 if ((cmd == LOAD_NWP_FW) || (cmd == LOAD_DEFAULT_NWP_FW_ACTIVE_LOW)) {
121 sl_si91x_timer_init(&timer_instance, 3000);
122 do {
123 retval = sli_si91x_send_boot_instruction(RSI_REG_READ, &read_value);
124 if (retval < 0) {
125 return retval;
126 }
127 if ((read_value & 0xF000) == (RSI_HOST_INTERACT_REG_VALID_FW & 0xF000)) {
128 if ((read_value & 0xFF) == VALID_FIRMWARE_NOT_PRESENT) {
129 #ifdef RSI_DEBUG_PRINT
130 RSI_DPRINT(RSI_PL4, "VALID_FIRMWARE_NOT_PRESENT\n");
131 #endif
132 return RSI_ERROR_VALID_FIRMWARE_NOT_PRESENT;
133 }
134 if ((read_value & 0xFF) == RSI_INVALID_OPTION) {
135 #ifdef RSI_DEBUG_PRINT
136 RSI_DPRINT(RSI_PL4, "INVALID CMD\n");
137 #endif
138
139 return RSI_ERROR_INVALID_OPTION;
140 }
141 if ((read_value & 0xFF) == RSI_CHECKSUM_SUCCESS) {
142 #ifdef RSI_DEBUG_PRINT
143 RSI_DPRINT(RSI_PL4, "LOAD SUCCESS\n");
144 #endif
145 break;
146 }
147 }
148 if (sl_si91x_timer_expired(&timer_instance)) {
149 return RSI_ERROR_FW_LOAD_OR_UPGRADE_TIMEOUT;
150 }
151
152 } while (1);
153 }
154 return retval;
155 }
156
157 /**
158 * @fn int16_t sli_si91x_send_boot_instruction(uint8_t type, uint16_t *data)
159 * @brief Send boot instructions to module.
160 * @param[in] type - type of the insruction to perform \n
161 * 0xD1 - RSI_REG_READ \n
162 * 0xD2 - RSI_REG_WRITE \n
163 * 0xD5 - RSI_PING_WRITE \n
164 * 0xD4 - RSI_PONG_WRITE \n
165 * 0x42 - BURN_NWP_FW \n
166 * 0x31 - LOAD_NWP_FW \n
167 * 0x71 - LOAD_DEFAULT_NWP_FW_ACTIVE_LOW
168 * @param[in] data - pointer to data which is to be read/write \n
169 * @return 0 - Success \n
170 * Non-Zero Value - Failure \n
171 * -28 - Firmware Load or Upgrade timeout error \n
172 * -2 - Invalid Parameter \n
173 * -1 or -2 - SPI Failure
174 * @note This is a proprietry API and it is not recommended to be used by the user directly.
175 */
176 /// @private
sli_si91x_send_boot_instruction(uint8_t type,uint16_t * data)177 int16_t sli_si91x_send_boot_instruction(uint8_t type, uint16_t *data)
178 {
179 int16_t retval = 0;
180 uint32_t cmd = 0;
181 uint16_t read_data = 0;
182 sl_si91x_timer_t timer_instance;
183
184 switch (type) {
185 case RSI_REG_READ:
186 *data = (uint16_t)SI91X_INTERFACE_OUT_REGISTER;
187 break;
188
189 case RSI_REG_WRITE:
190 SI91X_INTERFACE_IN_REGISTER = *data;
191 break;
192
193 case BURN_NWP_FW:
194 cmd = BURN_NWP_FW | RSI_HOST_INTERACT_REG_VALID;
195
196 SI91X_INTERFACE_IN_REGISTER = cmd;
197
198 sl_si91x_timer_init(&timer_instance, 300);
199
200 do {
201 read_data = (uint16_t)SI91X_INTERFACE_OUT_REGISTER;
202 if (sl_si91x_timer_expired(&timer_instance)) {
203 return RSI_ERROR_FW_LOAD_OR_UPGRADE_TIMEOUT;
204 }
205 } while (read_data != (RSI_SEND_RPS_FILE | RSI_HOST_INTERACT_REG_VALID));
206 break;
207
208 case LOAD_NWP_FW:
209 SI91X_INTERFACE_IN_REGISTER = LOAD_NWP_FW | RSI_HOST_INTERACT_REG_VALID;
210 break;
211
212 case LOAD_DEFAULT_NWP_FW_ACTIVE_LOW:
213 SI91X_INTERFACE_IN_REGISTER = LOAD_DEFAULT_NWP_FW_ACTIVE_LOW | RSI_HOST_INTERACT_REG_VALID;
214 break;
215
216 default:
217 retval = RSI_ERROR_INVALID_PARAM;
218 break;
219 }
220 return retval;
221 }
222
223 /**
224 * @fn int16 rsi_waitfor_boardready(void)
225 * @brief Waits to receive board ready from WiFi module
226 * @param[in] none
227 * @param[out] none
228 * @return errCode
229 * 0 = SUCCESS
230 * < 0 = Failure
231 * -7 = Error in OS operation
232 * -9 = Bootup options last configuration not saved
233 * -10 = Bootup options checksum failed
234 * -11 = Bootloader version mismatch
235 * -12 = Board ready not received
236 * @section description
237 * This API is used to check board ready from WiFi module.
238 */
rsi_waitfor_boardready(void)239 int16_t rsi_waitfor_boardready(void)
240 {
241 int16_t retval = 0;
242 uint16_t read_value = 0;
243
244 retval = rsi_boot_insn(REG_READ, &read_value);
245
246 if (retval < 0) {
247 return retval;
248 }
249 if (read_value == 0) {
250 return RSI_ERROR_IN_OS_OPERATION;
251 }
252 if ((read_value & 0xFF00) == (HOST_INTERACT_REG_VALID_READ & 0xFF00)) {
253 if ((read_value & 0xFF) == RSI_BOOTUP_OPTIONS_LAST_CONFIG_NOT_SAVED) {
254 #ifdef RSI_DEBUG_PRINT
255 RSI_DPRINT(RSI_PL3, "BOOTUP OPTIOINS LAST CONFIGURATION NOT SAVED\n");
256 #endif
257 return RSI_ERROR_BOOTUP_OPTIONS_NOT_SAVED;
258 } else if ((read_value & 0xFF) == RSI_BOOTUP_OPTIONS_CHECKSUM_FAIL) {
259 #ifdef RSI_DEBUG_PRINT
260 RSI_DPRINT(RSI_PL3, "BOOTUP OPTIONS CHECKSUM FAIL\n");
261 #endif
262 return RSI_ERROR_BOOTUP_OPTIONS_CHECKSUM_FAIL;
263 }
264 #if defined(BOOTLOADER_VERSION_CHECK) && (BOOTLOADER_VERSION_CHECK == 1)
265 else if ((read_value & 0xFF) == BOOTLOADER_VERSION) {
266 #ifdef RSI_DEBUG_PRINT
267 RSI_DPRINT(RSI_PL3, "BOOTLOADER VERSION CORRECT\n");
268 #endif
269 } else {
270 #ifdef RSI_DEBUG_PRINT
271 RSI_DPRINT(RSI_PL3, "BOOTLOADER VERSION NOT MATCHING\n");
272 #endif
273
274 return RSI_ERROR_BOOTLOADER_VERSION_NOT_MATCHING;
275 }
276 #endif
277
278 #ifdef RSI_DEBUG_PRINT
279 RSI_DPRINT(RSI_PL3, "RECIEVED BOARD READY\n");
280 #endif
281 return RSI_ERROR_NONE;
282 }
283
284 #ifdef RSI_DEBUG_PRINT
285 RSI_DPRINT(RSI_PL3, "WAITING FOR BOARD READY\n");
286 #endif
287 return RSI_ERROR_WAITING_FOR_BOARD_READY;
288 }
289
290 /**
291 * @fn int16 rsi_select_option(uint8 cmd)
292 * @brief Sends cmd to select option to load or update configuration
293 * @param[in] uint8 cmd, type of configuration to be saved
294 * @param[out] none
295 * @return errCode
296 < 0 = Command issue failed
297 * 0 = SUCCESS
298 * @section description
299 * This API is used to send firmware load request to WiFi module or update default configurations.
300 */
rsi_select_option(uint8_t cmd)301 int16_t rsi_select_option(uint8_t cmd)
302 {
303 uint16_t boot_cmd = 0;
304 int16_t retval = 0;
305 uint16_t read_value = 0;
306 uint8_t image_number = 0;
307 volatile int32_t loop_counter = 0;
308
309 boot_cmd = HOST_INTERACT_REG_VALID | cmd;
310 if (cmd == CHECK_NWP_INTEGRITY) {
311 boot_cmd &= 0xF0FF;
312 boot_cmd = boot_cmd | (uint16_t)(image_number << 8);
313 }
314 retval = rsi_boot_insn(REG_WRITE, &boot_cmd);
315 if (retval < 0) {
316 return retval;
317 }
318
319 if ((cmd != LOAD_NWP_FW) && (cmd != LOAD_DEFAULT_NWP_FW_ACTIVE_LOW) && (cmd != RSI_JUMP_TO_PC)) {
320 RSI_RESET_LOOP_COUNTER(loop_counter);
321 RSI_WHILE_LOOP((uint32_t)loop_counter, RSI_LOOP_COUNT_SELECT_OPTION)
322 {
323 retval = rsi_boot_insn(REG_READ, &read_value);
324 if (retval < 0) {
325 return retval;
326 }
327 if (cmd == CHECK_NWP_INTEGRITY) {
328 if ((read_value & 0xFF) == RSI_CHECKSUM_SUCCESS) {
329 #ifdef RSI_DEBUG_PRINT
330 RSI_DPRINT(RSI_PL3, "CHECKSUM SUCCESS\n");
331 #endif
332 } else if (read_value == RSI_CHECKSUM_FAILURE) {
333 #ifdef RSI_DEBUG_PRINT
334 RSI_DPRINT(RSI_PL3, "CHECKSUM FAIL\n");
335 #endif
336 } else if (read_value == RSI_CHECKSUM_INVALID_ADDRESS) {
337 #ifdef RSI_DEBUG_PRINT
338 RSI_DPRINT(RSI_PL3, "Invalid Address \n");
339 #endif
340 }
341 }
342 if (read_value == (HOST_INTERACT_REG_VALID | cmd)) {
343 break;
344 }
345 }
346 RSI_CHECK_LOOP_COUNTER(loop_counter, RSI_LOOP_COUNT_SELECT_OPTION);
347 } else if ((cmd == LOAD_NWP_FW) || (cmd == LOAD_DEFAULT_NWP_FW_ACTIVE_LOW) || (cmd == RSI_JUMP_TO_PC)) {
348 retval = rsi_boot_insn(REG_READ, &read_value);
349 if (retval < 0) {
350 return retval;
351 }
352 if ((read_value & 0xFF) == VALID_FIRMWARE_NOT_PRESENT) {
353 #ifdef RSI_DEBUG_PRINT
354 RSI_DPRINT(RSI_PL3, "VALID_FIRMWARE_NOT_PRESENT\n");
355 #endif
356 return RSI_ERROR_VALID_FIRMWARE_NOT_PRESENT;
357 }
358 if ((read_value & 0xFF) == RSI_INVALID_OPTION) {
359 #ifdef RSI_DEBUG_PRINT
360 RSI_DPRINT(RSI_PL3, "INVALID CMD\n");
361 #endif
362 return RSI_ERROR_COMMAND_NOT_SUPPORTED;
363 }
364 }
365 return retval;
366 }
367
368 /**
369 * @fn int16 rsi_boot_insn(uint8 type, uint16 *data)
370 * @brief Sends boot instructions to WiFi module
371 * @param[in] uint8 type, type of the insruction to perform
372 * @param[in] uint32 *data, pointer to data which is to be read/write
373 * @param[out] none
374 * @return errCode
375 * < 0 = Command issued failure/Invalid command
376 * 0 = SUCCESS
377 * > 0 = Read value
378 * @section description
379 * This API is used to send boot instructions to WiFi module.
380 */
381
rsi_boot_insn(uint8_t type,uint16_t * data)382 int16_t rsi_boot_insn(uint8_t type, uint16_t *data)
383 {
384 int16_t retval = 0;
385 uint16_t read_data = 0;
386 volatile int32_t loop_counter = 0;
387 #ifdef RSI_DEBUG_PRINT
388 RSI_DPRINT(RSI_PL3, "\nBootInsn\n");
389 #endif
390
391 switch (type) {
392 case REG_READ:
393 *data = (uint16_t)SI91X_INTERFACE_OUT_REGISTER;
394 break;
395
396 case REG_WRITE:
397 SI91X_INTERFACE_IN_REGISTER = *data;
398 break;
399
400 case PING_WRITE:
401 memcpy(SI91X_PING_BUFFER, data, sizeof(sli_si91x_pingpong_buffer_t));
402 SI91X_INTERFACE_IN_REGISTER = 0xab49;
403 break;
404
405 case PONG_WRITE:
406 memcpy(SI91X_PONG_BUFFER, data, sizeof(sli_si91x_pingpong_buffer_t));
407 SI91X_INTERFACE_IN_REGISTER = 0xab4f;
408 break;
409
410 case BURN_NWP_FW:
411 SI91X_INTERFACE_IN_REGISTER = BURN_NWP_FW | HOST_INTERACT_REG_VALID;
412
413 RSI_RESET_LOOP_COUNTER(loop_counter);
414 RSI_WHILE_LOOP((uint32_t)loop_counter, RSI_LOOP_COUNT_UPGRADE_IMAGE)
415 {
416 read_data = (uint16_t)SI91X_INTERFACE_OUT_REGISTER;
417 if (read_data == (RSI_SEND_RPS_FILE | HOST_INTERACT_REG_VALID)) {
418 break;
419 }
420 }
421 RSI_CHECK_LOOP_COUNTER(loop_counter, RSI_LOOP_COUNT_UPGRADE_IMAGE);
422 break;
423
424 case LOAD_NWP_FW:
425 SI91X_INTERFACE_IN_REGISTER = LOAD_NWP_FW | HOST_INTERACT_REG_VALID;
426 break;
427 case LOAD_DEFAULT_NWP_FW_ACTIVE_LOW:
428 SI91X_INTERFACE_IN_REGISTER = LOAD_DEFAULT_NWP_FW_ACTIVE_LOW | HOST_INTERACT_REG_VALID;
429 break;
430 case RSI_UPGRADE_BL:
431 SI91X_INTERFACE_IN_REGISTER = RSI_UPGRADE_BL | HOST_INTERACT_REG_VALID;
432 RSI_RESET_LOOP_COUNTER(loop_counter);
433 RSI_WHILE_LOOP((uint32_t)loop_counter, RSI_LOOP_COUNT_UPGRADE_IMAGE)
434 {
435 read_data = (uint16_t)SI91X_INTERFACE_OUT_REGISTER;
436 if (read_data == (RSI_SEND_RPS_FILE | HOST_INTERACT_REG_VALID)) {
437 break;
438 }
439 }
440 RSI_CHECK_LOOP_COUNTER(loop_counter, RSI_LOOP_COUNT_UPGRADE_IMAGE);
441 break;
442 default:
443 retval = -2;
444 break;
445 }
446 return retval;
447 }
448
unmask_ta_interrupt(uint32_t interrupt_no)449 void unmask_ta_interrupt(uint32_t interrupt_no)
450 {
451 TASS_P2P_INTR_MASK_CLR = interrupt_no;
452 }
453
sli_m4_ta_interrupt_init(void)454 void sli_m4_ta_interrupt_init(void)
455 {
456 #if defined(SLI_SI917) || defined(SLI_SI915)
457 //! Unmask the interrupt
458 unmask_ta_interrupt(TX_PKT_TRANSFER_DONE_INTERRUPT | RX_PKT_TRANSFER_DONE_INTERRUPT | TA_WRITING_ON_COMM_FLASH
459 | NWP_DEINIT_IN_COMM_FLASH
460 #ifdef SLI_SI91X_MCU_FW_UPGRADE_OTA_DUAL_FLASH
461 | M4_IMAGE_UPGRADATION_PENDING_INTERRUPT
462 #endif
463 #ifdef SL_SI91X_SIDE_BAND_CRYPTO
464 | SIDE_BAND_CRYPTO_DONE
465 #endif
466 );
467 #else
468 //! Unmask the interrupt
469 unmask_ta_interrupt(TX_PKT_TRANSFER_DONE_INTERRUPT | RX_PKT_TRANSFER_DONE_INTERRUPT);
470 #endif
471 P2P_STATUS_REG |= M4_is_active;
472
473 *(volatile uint32_t *)0xE000E108 = 0x00000400;
474
475 //! Set P2P Intr priority
476 NVIC_SetPriority(TASS_P2P_IRQn, TASS_P2P_INTR_PRI);
477
478 return;
479 }
480
sl_si91x_ulp_wakeup_init(void)481 void sl_si91x_ulp_wakeup_init(void)
482 {
483 // for compilation
484 }
485