soc: silabs: siwx91x: transform nwp soc files into a driver

The goal of this patch is to switch from the nwp.c and nwp.h soc files
to the new nwp driver. During this transition, we also renamed
CONFIG_WISECONNECT_NETWORK_STACK to CONFIG_SILABS_SIWX91X_NWP which are
a better naming to let the user knows that the network coprocessor files
will be added to the compilation.

The switch from a soc file to a driver device introduce a notion of nwp
device that allows us to check for good initialization and ressources
allocation.

Before this patch, it is not possible to know if the nwp have booted
successfully or not. We can now check if the device driver is ready
or not before trying to do operation related to the nwp.

Signed-off-by: Martin Hoff <martin.hoff@silabs.com>
This commit is contained in:
Martin Hoff
2025-10-14 14:50:26 +02:00
committed by Henrik Brix Andersen
parent bdb64d1bbf
commit ba1d267c62
18 changed files with 189 additions and 123 deletions

View File

@@ -182,7 +182,7 @@ config BT_SILABS_SIWX91X
bool "Silabs SiWx91x Bluetooth interface"
default y
depends on DT_HAS_SILABS_SIWX91X_BT_HCI_ENABLED
select WISECONNECT_NETWORK_STACK
select SILABS_SIWX91X_NWP
select ENTROPY_GENERATOR
help
Use Silicon Labs Wiseconnect 3.x Bluetooth library to connect to the controller.

View File

@@ -9,7 +9,7 @@ config SOC_FLASH_SILABS_SIWX91X
select FLASH_HAS_EXPLICIT_ERASE
select FLASH_HAS_PAGE_LAYOUT
# Flash controller is handled by the network coprocessor
select WISECONNECT_NETWORK_STACK
select SILABS_SIWX91X_NWP
help
Enable flash controller for flash embedded on Silicon Labs SiWx91x
chips.

View File

@@ -6,7 +6,7 @@ config WIFI_SILABS_SIWX91X
default y
depends on DT_HAS_SILABS_SIWX91X_WIFI_ENABLED
depends on NETWORKING
select WISECONNECT_NETWORK_STACK
select SILABS_SIWX91X_NWP
select EVENTS
select NET_L2_WIFI_MGMT
help

View File

@@ -7,7 +7,7 @@
#include <zephyr/version.h>
#include <nwp.h>
#include <siwx91x_nwp.h>
#include "siwx91x_wifi.h"
#include "siwx91x_wifi_ap.h"
#include "siwx91x_wifi_ps.h"
@@ -207,7 +207,7 @@ static int siwx91x_mode(const struct device *dev, struct wifi_mode_info *mode)
mode->mode = cur_mode;
} else if (mode->oper == WIFI_MGMT_SET) {
if (cur_mode != mode->mode) {
ret = siwx91x_nwp_mode_switch(mode->mode, false, 0);
ret = siwx91x_nwp_mode_switch(siwx91x_cfg->nwp_dev, mode->mode, false, 0);
if (ret < 0) {
return ret;
}
@@ -394,6 +394,7 @@ static int map_sdk_region_to_zephyr_channel_info(const sli_si91x_set_region_ap_r
static int siwx91x_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_domain)
{
const struct siwx91x_config *siwx91x_cfg = dev->config;
const sli_si91x_set_region_ap_request_t *sdk_reg = NULL;
sl_wifi_operation_mode_t oper_mode = sli_get_opermode();
sl_wifi_region_code_t region_code;
@@ -411,13 +412,13 @@ static int siwx91x_wifi_reg_domain(const struct device *dev, struct wifi_reg_dom
}
if (region_code == SL_WIFI_DEFAULT_REGION) {
siwx91x_store_country_code(DEFAULT_COUNTRY_CODE);
siwx91x_store_country_code(siwx91x_cfg->nwp_dev, DEFAULT_COUNTRY_CODE);
LOG_INF("Country code not supported, using default region");
} else {
siwx91x_store_country_code(reg_domain->country_code);
siwx91x_store_country_code(siwx91x_cfg->nwp_dev, reg_domain->country_code);
}
} else if (reg_domain->oper == WIFI_MGMT_GET) {
country_code = siwx91x_get_country_code();
country_code = siwx91x_get_country_code(siwx91x_cfg->nwp_dev);
memcpy(reg_domain->country_code, country_code, WIFI_COUNTRY_CODE_LEN);
region_code = siwx91x_map_country_code_to_region(country_code);
@@ -532,6 +533,13 @@ int siwx91x_set_rts_threshold(const struct device *dev, unsigned int rts_thresho
static int siwx91x_dev_init(const struct device *dev)
{
const struct siwx91x_config *siwx91x_cfg = dev->config;
if (!device_is_ready(siwx91x_cfg->nwp_dev)) {
LOG_ERR("NWP device not ready");
return -ENODEV;
}
return 0;
}
@@ -568,6 +576,7 @@ static const struct net_wifi_mgmt_offload siwx91x_api = {
};
static const struct siwx91x_config siwx91x_cfg = {
.nwp_dev = DEVICE_DT_GET(DT_INST_PARENT(0)),
.scan_tx_power = DT_INST_PROP(0, wifi_max_tx_pwr_scan),
.join_tx_power = DT_INST_PROP(0, wifi_max_tx_pwr_join),
};

View File

@@ -10,6 +10,7 @@
#include "sl_si91x_types.h"
struct siwx91x_config {
const struct device *nwp_dev;
uint8_t scan_tx_power;
uint8_t join_tx_power;
};

View File

@@ -3,7 +3,7 @@
* Copyright (c) 2024-2025 Silicon Laboratories Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#include <nwp.h>
#include <siwx91x_nwp.h>
#include "siwx91x_wifi.h"
#include "sl_rsi_utility.h"
@@ -15,11 +15,13 @@ LOG_MODULE_DECLARE(siwx91x_wifi);
static int siwx91x_nwp_reboot_if_required(const struct device *dev, uint8_t oper_mode)
{
const struct siwx91x_config *siwx91x_cfg = dev->config;
struct siwx91x_dev *sidev = dev->data;
int ret;
if (sidev->reboot_needed) {
ret = siwx91x_nwp_mode_switch(oper_mode, sidev->hidden_ssid, sidev->max_num_sta);
ret = siwx91x_nwp_mode_switch(siwx91x_cfg->nwp_dev, oper_mode, sidev->hidden_ssid,
sidev->max_num_sta);
if (ret < 0) {
LOG_ERR("Failed to reboot the device: %d", ret);
return ret;

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/sys/util.h>
#include <nwp.h>
#include <siwx91x_nwp.h>
#include "siwx91x_wifi.h"
#include "siwx91x_wifi_ps.h"

View File

@@ -5,7 +5,7 @@
*/
#include <zephyr/logging/log.h>
#include <nwp.h>
#include <siwx91x_nwp.h>
#include "siwx91x_wifi.h"
#include "siwx91x_wifi_scan.h"

View File

@@ -5,7 +5,7 @@
*/
#include <zephyr/logging/log.h>
#include <nwp.h>
#include <siwx91x_nwp.h>
#include "siwx91x_wifi.h"
#include "siwx91x_wifi_socket.h"
#include "siwx91x_wifi_ps.h"

View File

@@ -76,6 +76,11 @@
nwp: nwp {
compatible = "silabs,siwx91x-nwp";
power-profile = "high-performance";
stack-size = <10240>;
interrupt-parent = <&nvic>;
interrupts = <30 0>, <74 0>;
interrupt-names = "nwp_stack", "nwp_irq";
status = "okay";
bt_hci0: bt_hci {
compatible = "silabs,siwx91x-bt-hci";

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2025 Silicon Laboratories Inc.
# SPDX-License-Identifier: Apache-2.0
title: Silicon Labs SiWx91x NWP (Network Wireless Processor)
title: Silicon Labs SiWx91x NWP (Network Wireless Coprocessor)
description: |
The Network Wireless Processor (NWP) manages Wi-Fi and Bluetooth connectivity on SiWx91x devices,
@@ -10,7 +10,17 @@ description: |
compatible: "silabs,siwx91x-nwp"
include: base.yaml
properties:
interrupts:
required: true
stack-size:
type: int
description: Stack size for the NWP in bytes
required: true
power-profile:
type: string
description: Power/performance profile

View File

@@ -154,7 +154,7 @@ if(CONFIG_BT_SILABS_SIWX91X)
)
endif() # CONFIG_BT_SILABS_SIWX91X
if(CONFIG_WISECONNECT_NETWORK_STACK)
if(CONFIG_SILABS_SIWX91X_NWP)
zephyr_compile_definitions(
SLI_SI91X_ENABLE_OS
SL_SI91X_SI917_RAM_MEM_CONFIG=2
@@ -198,7 +198,7 @@ if(CONFIG_WISECONNECT_NETWORK_STACK)
${WISECONNECT_DIR}/components/device/silabs/si91x/wireless/firmware_upgrade/firmware_upgradation.c
)
zephyr_include_directories(.)
endif() # CONFIG_WISECONNECT_NETWORK_STACK
endif() # CONFIG_SILABS_SIWX91X_NWP
if(CONFIG_SOC_SILABS_SLEEPTIMER)
zephyr_include_directories(

View File

@@ -20,9 +20,22 @@ config SOC_SILABS_SLEEPTIMER
help
The Sleeptimer HAL module is used for SIWX91X.
config SILABS_SIWX91X_NWP
bool "Silabs Network Coprocessor"
depends on DT_HAS_SILABS_SIWX91X_NWP_ENABLED
select CMSIS_RTOS_V2
select POLL
select DYNAMIC_THREAD
select THREAD_NAME
select THREAD_STACK_INFO
select THREAD_MONITOR
select INIT_STACKS
help
Add support for Network Coprocessor (also named NWP) presents on SiWx91x parts.
config SOC_SIWX91X_PM_BACKEND_PMGR
bool
select WISECONNECT_NETWORK_STACK
select SILABS_SIWX91X_NWP
select SILABS_SLEEPTIMER_TIMER
select SRAM_VECTOR_TABLE
select CODE_DATA_RELOCATION_SRAM
@@ -64,7 +77,7 @@ config SIWX91X_ENCRYPT
config SIWX91X_FIRMWARE_UPGRADE
bool "Support for firmware upgrade"
select WISECONNECT_NETWORK_STACK
select SILABS_SIWX91X_NWP
help
The firmware upgrade process for SiWx91x devices involves coordinated
communication with both the Network Co-Processor (NCP) and the ROM

View File

@@ -13,17 +13,7 @@ configdefault SYS_CLOCK_TICKS_PER_SEC
configdefault UART_NS16550_DW8250_DW_APB
default y
config WISECONNECT_NETWORK_STACK
bool
select CMSIS_RTOS_V2
select POLL
select DYNAMIC_THREAD
select THREAD_NAME
select THREAD_STACK_INFO
select THREAD_MONITOR
select INIT_STACKS
if WISECONNECT_NETWORK_STACK
if SILABS_SIWX91X_NWP
# WiseConnect create threads with realtime priority. Default (10kHz) clock tick
# prevent proper use of the system with these threads.
@@ -42,7 +32,7 @@ config CMSIS_V2_THREAD_DYNAMIC_STACK_SIZE
config CMSIS_V2_THREAD_MAX_STACK_SIZE
default 2048
endif # WISECONNECT_NETWORK_STACK
endif
rsource "*/Kconfig.defconfig"

View File

@@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_sources_ifdef(CONFIG_SOC_SERIES_SIWG917 soc.c)
zephyr_sources_ifdef(CONFIG_WISECONNECT_NETWORK_STACK nwp.c)
zephyr_sources_ifdef(CONFIG_SILABS_SIWX91X_NWP siwx91x_nwp.c)
zephyr_sources_ifdef(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR soc_siwx91x_power_pmgr.c)
set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "")

View File

@@ -10,12 +10,14 @@
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT silabs_siwx91x_nwp
#include <zephyr/kernel.h>
#include <zephyr/net/wifi.h>
#include <zephyr/logging/log.h>
#include <zephyr/devicetree.h>
#include "nwp.h"
#include "siwx91x_nwp.h"
#include "nwp_fw_version.h"
#include "sl_wifi_callback_framework.h"
@@ -25,8 +27,6 @@
#endif
#include "sl_si91x_power_manager.h"
#define NWP_NODE DT_NODELABEL(nwp)
#define SI91X_POWER_PROFILE DT_ENUM_IDX(NWP_NODE, power_profile)
#define AP_MAX_NUM_STA 4
LOG_MODULE_REGISTER(siwx91x_nwp);
@@ -35,14 +35,16 @@ BUILD_ASSERT(DT_REG_SIZE(DT_CHOSEN(zephyr_sram)) == KB(195) ||
DT_REG_SIZE(DT_CHOSEN(zephyr_sram)) == KB(255) ||
DT_REG_SIZE(DT_CHOSEN(zephyr_sram)) == KB(319));
extern const sli_si91x_set_region_ap_request_t default_US_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_EU_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_JP_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_KR_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_SG_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_CN_region_2_4GHZ_configurations;
struct siwx91x_nwp_data {
char current_country_code[WIFI_COUNTRY_CODE_LEN];
};
struct siwx91x_nwp_config {
void (*config_irq)(const struct device *dev);
uint32_t stack_size;
uint8_t power_profile;
};
static char current_country_code[WIFI_COUNTRY_CODE_LEN];
typedef struct {
const char *const *codes;
size_t num_codes;
@@ -50,30 +52,31 @@ typedef struct {
const sli_si91x_set_region_ap_request_t *sdk_reg;
} region_map_t;
extern const sli_si91x_set_region_ap_request_t default_US_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_EU_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_JP_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_KR_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_SG_region_2_4GHZ_configurations;
extern const sli_si91x_set_region_ap_request_t default_CN_region_2_4GHZ_configurations;
static const char *const us_codes[] = {
"AE", "AR", "AS", "BB", "BM", "BR", "BS", "CA", "CO", "CR", "CU", "CX",
"DM", "DO", "EC", "FM", "GD", "GY", "GU", "HN", "HT", "JM", "KY", "LB",
"LK", "MH", "MN", "MP", "MO", "MY", "NI", "PA", "PE", "PG", "PH", "PK",
"PR", "PW", "PY", "SG", "MX", "SV", "TC", "TH", "TT", "US", "UY", "VE",
"VI", "VN", "VU", "00"
/* Map "00" (world domain) to US region,
* as using the world domain is not recommended
*/
"AE", "AR", "AS", "BB", "BM", "BR", "BS", "CA", "CO", "CR", "CU", "CX", "DM", "DO",
"EC", "FM", "GD", "GY", "GU", "HN", "HT", "JM", "KY", "LB", "LK", "MH", "MN", "MP",
"MO", "MY", "NI", "PA", "PE", "PG", "PH", "PK", "PR", "PW", "PY", "SG", "MX", "SV",
"TC", "TH", "TT", "US", "UY", "VE", "VI", "VN", "VU", "00"
/* Map "00" (world domain) to US region as using the world domain is not recommended */
};
static const char *const eu_codes[] = {
"AD", "AF", "AI", "AL", "AM", "AN", "AT", "AW", "AU", "AZ", "BA", "BE",
"BG", "BH", "BL", "BT", "BY", "CH", "CY", "CZ", "DE", "DK", "EE", "ES",
"FR", "GB", "GE", "GF", "GL", "GP", "GR", "GT", "HK", "HR", "HU", "ID",
"IE", "IL", "IN", "IR", "IS", "IT", "JO", "KH", "FI", "KN", "KW", "KZ",
"LC", "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MF", "MT", "MV", "MQ",
"NL", "NO", "NZ", "OM", "PF", "PL", "PM", "PT", "QA", "RO", "RS", "RU",
"SA", "SE", "SI", "SK", "SR", "SY", "TR", "TW", "UA", "UZ", "VC", "WF",
"WS", "YE", "RE", "YT"
"AD", "AF", "AI", "AL", "AM", "AN", "AT", "AW", "AU", "AZ", "BA", "BE", "BG", "BH", "BL",
"BT", "BY", "CH", "CY", "CZ", "DE", "DK", "EE", "ES", "FR", "GB", "GE", "GF", "GL", "GP",
"GR", "GT", "HK", "HR", "HU", "ID", "IE", "IL", "IN", "IR", "IS", "IT", "JO", "KH", "FI",
"KN", "KW", "KZ", "LC", "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MF", "MT", "MV", "MQ",
"NL", "NO", "NZ", "OM", "PF", "PL", "PM", "PT", "QA", "RO", "RS", "RU", "SA", "SE", "SI",
"SK", "SR", "SY", "TR", "TW", "UA", "UZ", "VC", "WF", "WS", "YE", "RE", "YT"
};
static const char *const jp_codes[] = {"BD", "BN", "BO", "CL", "BZ", "JP", "NP"};
static const char *const kr_codes[] = {"KR", "KP"};
static const char *const cn_codes[] = {"CN"};
static const region_map_t region_maps[] = {
{us_codes, ARRAY_SIZE(us_codes), SL_WIFI_REGION_US,
&default_US_region_2_4GHZ_configurations},
@@ -87,17 +90,20 @@ static const region_map_t region_maps[] = {
&default_CN_region_2_4GHZ_configurations},
};
int siwx91x_store_country_code(const char *country_code)
int siwx91x_store_country_code(const struct device *dev, const char *country_code)
{
__ASSERT(country_code, "country_code cannot be NULL");
struct siwx91x_nwp_data *data = dev->data;
memcpy(current_country_code, country_code, WIFI_COUNTRY_CODE_LEN);
memcpy(data->current_country_code, country_code, WIFI_COUNTRY_CODE_LEN);
return 0;
}
const char *siwx91x_get_country_code(void)
const char *siwx91x_get_country_code(const struct device *dev)
{
return current_country_code;
const struct siwx91x_nwp_data *data = dev->data;
return data->current_country_code;
}
sl_wifi_region_code_t siwx91x_map_country_code_to_region(const char *country_code)
@@ -107,7 +113,7 @@ sl_wifi_region_code_t siwx91x_map_country_code_to_region(const char *country_cod
ARRAY_FOR_EACH(region_maps, i) {
for (size_t j = 0; j < region_maps[i].num_codes; j++) {
if (memcmp(country_code, region_maps[i].codes[j],
WIFI_COUNTRY_CODE_LEN) == 0) {
WIFI_COUNTRY_CODE_LEN) == 0) {
return region_maps[i].region_code;
}
}
@@ -166,8 +172,9 @@ static void siwx91x_configure_sta_mode(sl_si91x_boot_configuration_t *boot_confi
#ifdef CONFIG_WIFI_SILABS_SIWX91X
boot_config->ext_tcp_ip_feature_bit_map = SL_SI91X_CONFIG_FEAT_EXTENSION_VALID;
boot_config->ext_custom_feature_bit_map |= SL_SI91X_EXT_FEAT_IEEE_80211W |
SL_SI91X_EXT_FEAT_FRONT_END_SWITCH_PINS_ULP_GPIO_4_5_0;
boot_config->ext_custom_feature_bit_map |=
SL_SI91X_EXT_FEAT_IEEE_80211W |
SL_SI91X_EXT_FEAT_FRONT_END_SWITCH_PINS_ULP_GPIO_4_5_0;
if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X_ENHANCED_MAX_PSP)) {
boot_config->config_feature_bit_map = SL_SI91X_ENABLE_ENHANCED_MAX_PSP;
}
@@ -177,26 +184,25 @@ static void siwx91x_configure_sta_mode(sl_si91x_boot_configuration_t *boot_confi
boot_config->ext_custom_feature_bit_map |= SL_SI91X_EXT_FEAT_BT_CUSTOM_FEAT_ENABLE;
boot_config->bt_feature_bit_map |= SL_SI91X_BT_RF_TYPE | SL_SI91X_ENABLE_BLE_PROTOCOL;
boot_config->ble_feature_bit_map |=
SL_SI91X_BLE_MAX_NBR_PERIPHERALS(RSI_BLE_MAX_NBR_PERIPHERALS) |
SL_SI91X_BLE_MAX_NBR_CENTRALS(RSI_BLE_MAX_NBR_CENTRALS) |
SL_SI91X_BLE_MAX_NBR_ATT_SERV(RSI_BLE_MAX_NBR_ATT_SERV) |
SL_SI91X_BLE_MAX_NBR_ATT_REC(RSI_BLE_MAX_NBR_ATT_REC) |
SL_SI91X_BLE_PWR_INX(RSI_BLE_PWR_INX) |
SL_SI91X_BLE_PWR_SAVE_OPTIONS(RSI_BLE_PWR_SAVE_OPTIONS) |
SL_SI91X_916_BLE_COMPATIBLE_FEAT_ENABLE |
SL_SI91X_FEAT_BLE_CUSTOM_FEAT_EXTENSION_VALID;
SL_SI91X_BLE_MAX_NBR_PERIPHERALS(RSI_BLE_MAX_NBR_PERIPHERALS) |
SL_SI91X_BLE_MAX_NBR_CENTRALS(RSI_BLE_MAX_NBR_CENTRALS) |
SL_SI91X_BLE_MAX_NBR_ATT_SERV(RSI_BLE_MAX_NBR_ATT_SERV) |
SL_SI91X_BLE_MAX_NBR_ATT_REC(RSI_BLE_MAX_NBR_ATT_REC) |
SL_SI91X_BLE_PWR_INX(RSI_BLE_PWR_INX) |
SL_SI91X_BLE_PWR_SAVE_OPTIONS(RSI_BLE_PWR_SAVE_OPTIONS) |
SL_SI91X_916_BLE_COMPATIBLE_FEAT_ENABLE |
SL_SI91X_FEAT_BLE_CUSTOM_FEAT_EXTENSION_VALID;
boot_config->ble_ext_feature_bit_map |=
SL_SI91X_BLE_NUM_CONN_EVENTS(RSI_BLE_NUM_CONN_EVENTS) |
SL_SI91X_BLE_NUM_REC_BYTES(RSI_BLE_NUM_REC_BYTES) |
SL_SI91X_BLE_ENABLE_ADV_EXTN |
SL_SI91X_BLE_AE_MAX_ADV_SETS(RSI_BLE_AE_MAX_ADV_SETS) |
SL_SI91X_BT_BLE_STACK_BYPASS_ENABLE;
SL_SI91X_BLE_NUM_CONN_EVENTS(RSI_BLE_NUM_CONN_EVENTS) |
SL_SI91X_BLE_NUM_REC_BYTES(RSI_BLE_NUM_REC_BYTES) | SL_SI91X_BLE_ENABLE_ADV_EXTN |
SL_SI91X_BLE_AE_MAX_ADV_SETS(RSI_BLE_AE_MAX_ADV_SETS) |
SL_SI91X_BT_BLE_STACK_BYPASS_ENABLE;
#endif
}
static void siwx91x_configure_ap_mode(sl_si91x_boot_configuration_t *boot_config,
bool hidden_ssid, uint8_t max_num_sta)
static void siwx91x_configure_ap_mode(sl_si91x_boot_configuration_t *boot_config, bool hidden_ssid,
uint8_t max_num_sta)
{
boot_config->oper_mode = SL_SI91X_ACCESS_POINT_MODE;
boot_config->coex_mode = SL_SI91X_WLAN_ONLY_MODE;
@@ -299,8 +305,9 @@ static int siwx91x_check_nwp_version(void)
return 0;
}
int siwx91x_get_nwp_config(sl_wifi_device_configuration_t *get_config, uint8_t wifi_oper_mode,
bool hidden_ssid, uint8_t max_num_sta)
static int siwx91x_get_nwp_config(const struct device *dev,
sl_wifi_device_configuration_t *get_config,
uint8_t wifi_oper_mode, bool hidden_ssid, uint8_t max_num_sta)
{
sl_wifi_device_configuration_t default_config = {
.region_code = siwx91x_map_country_code_to_region(DEFAULT_COUNTRY_CODE),
@@ -335,7 +342,7 @@ int siwx91x_get_nwp_config(sl_wifi_device_configuration_t *get_config, uint8_t w
return -EINVAL;
}
siwx91x_store_country_code(DEFAULT_COUNTRY_CODE);
siwx91x_store_country_code(dev, DEFAULT_COUNTRY_CODE);
siwx91x_apply_sram_config(boot_config);
switch (wifi_oper_mode) {
@@ -357,12 +364,13 @@ int siwx91x_get_nwp_config(sl_wifi_device_configuration_t *get_config, uint8_t w
return 0;
}
int siwx91x_nwp_mode_switch(uint8_t oper_mode, bool hidden_ssid, uint8_t max_num_sta)
int siwx91x_nwp_mode_switch(const struct device *dev, uint8_t oper_mode, bool hidden_ssid,
uint8_t max_num_sta)
{
sl_wifi_device_configuration_t nwp_config;
int status;
status = siwx91x_get_nwp_config(&nwp_config, oper_mode, hidden_ssid, max_num_sta);
status = siwx91x_get_nwp_config(dev, &nwp_config, oper_mode, hidden_ssid, max_num_sta);
if (status < 0) {
return status;
}
@@ -381,74 +389,96 @@ int siwx91x_nwp_mode_switch(uint8_t oper_mode, bool hidden_ssid, uint8_t max_num
return 0;
}
static int siwg917_nwp_init(void)
static int siwx91x_nwp_init(const struct device *dev)
{
sl_wifi_device_configuration_t network_config;
int status;
const struct siwx91x_nwp_config *config = dev->config;
__maybe_unused sl_wifi_performance_profile_t performance_profile = {
.profile = SI91X_POWER_PROFILE};
.profile = config->power_profile};
__maybe_unused sl_bt_performance_profile_t bt_performance_profile = {
.profile = SI91X_POWER_PROFILE};
.profile = config->power_profile};
sl_wifi_device_configuration_t network_config;
int ret;
siwx91x_get_nwp_config(&network_config, WIFI_STA_MODE, false, 0);
siwx91x_get_nwp_config(dev, &network_config, WIFI_STA_MODE, false, 0);
/* TODO: If sl_net_*_profile() functions will be needed for WiFi then call
* sl_net_set_profile() here. Currently these are unused.
* Despite its name, this function need to be called even if wifi is not used.
*/
status = sl_wifi_init(&network_config, NULL, sl_wifi_default_event_handler);
if (status != SL_STATUS_OK) {
ret = sl_wifi_init(&network_config, NULL, sl_wifi_default_event_handler);
if (ret) {
return -EINVAL;
}
/* Check if the NWP firmware version is correct */
status = siwx91x_check_nwp_version();
if (status < 0) {
ret = siwx91x_check_nwp_version();
if (ret < 0) {
LOG_ERR("Unexpected NWP firmware version (expected: %s)",
SIWX91X_NWP_FW_EXPECTED_VERSION);
SIWX91X_NWP_FW_EXPECTED_VERSION);
}
if (IS_ENABLED(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR)) {
if (IS_ENABLED(CONFIG_BT_SILABS_SIWX91X)) {
status = sl_si91x_bt_set_performance_profile(&bt_performance_profile);
if (status != SL_STATUS_OK) {
ret = sl_si91x_bt_set_performance_profile(&bt_performance_profile);
if (ret) {
LOG_ERR("Failed to initiate power save in BLE mode");
return -EINVAL;
}
}
/*
* Note: the WiFi related sources are always imported (because of
* CONFIG_WISECONNECT_NETWORK_STACK) whatever the value of CONFIG_WIFI. However,
* CONFIG_SILABS_SIWX91X_NWP) whatever the value of CONFIG_WIFI. However,
* because of boot_config->coex_mode, sl_wifi_set_performance_profile() is a no-op
* if CONFIG_WIFI=n and CONFIG_BT=y. We could probably remove the dependency to the
* WiFi sources in this case. However, outside of the code size, this dependency
* does not hurt.
*/
status = sl_wifi_set_performance_profile(&performance_profile);
if (status != SL_STATUS_OK) {
ret = sl_wifi_set_performance_profile(&performance_profile);
if (ret) {
return -EINVAL;
}
/* Remove the previously added PS4 power state requirement */
sl_si91x_power_manager_remove_ps_requirement(SL_SI91X_POWER_MANAGER_PS4);
}
config->config_irq(dev);
return 0;
}
#if defined(CONFIG_MBEDTLS_INIT)
BUILD_ASSERT(CONFIG_SIWX91X_NWP_INIT_PRIORITY < CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
"mbed TLS must be initialized after the NWP.");
#endif
SYS_INIT(siwg917_nwp_init, POST_KERNEL, CONFIG_SIWX91X_NWP_INIT_PRIORITY);
/* IRQn 74 is used for communication with co-processor */
Z_ISR_DECLARE(74, 0, IRQ074_Handler, 0);
#define SIWX91X_NWP_DEFINE(inst) \
\
static void silabs_siwx91x_nwp_irq_configure_##inst(const struct device *dev) \
{ \
ARG_UNUSED(dev); \
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, nwp_irq, irq), \
DT_INST_IRQ_BY_NAME(inst, nwp_irq, priority), IRQ074_Handler, NULL, 0);\
irq_enable(DT_INST_IRQ_BY_NAME(inst, nwp_irq, irq)); \
}; \
\
static struct siwx91x_nwp_data siwx91x_nwp_data_##inst = {}; \
\
static const struct siwx91x_nwp_config siwx91x_nwp_config_##inst = { \
.config_irq = silabs_siwx91x_nwp_irq_configure_##inst, \
.power_profile = DT_ENUM_IDX(DT_DRV_INST(inst), power_profile), \
.stack_size = DT_INST_PROP(inst, stack_size) \
}; \
\
/* Coprocessor uses value stored in IVT to store its stack. We can't use Z_ISR_DECLARE() */\
static uint8_t __aligned(8) siwx91x_nwp_stack_##inst[DT_INST_PROP(inst, stack_size)]; \
static Z_DECL_ALIGN(struct _isr_list) Z_GENERIC_SECTION(.intList) \
__used __isr_siwg917_coprocessor_stack_irq_##inst = { \
.irq = DT_IRQ_BY_NAME(DT_DRV_INST(inst), nwp_stack, irq), \
.flags = ISR_FLAG_DIRECT, \
.func = &siwx91x_nwp_stack_##inst[sizeof(siwx91x_nwp_stack_##inst) - 1], \
}; \
\
DEVICE_DT_INST_DEFINE(inst, &siwx91x_nwp_init, NULL, &siwx91x_nwp_data_##inst, \
&siwx91x_nwp_config_##inst, POST_KERNEL, \
CONFIG_SIWX91X_NWP_INIT_PRIORITY, NULL);
/* Co-processor will use value stored in IVT to store its stack.
*
* FIXME: We can't use Z_ISR_DECLARE() to declare this entry
* FIXME: Allow to configure size of buffer
*/
static uint8_t __aligned(8) siwg917_nwp_stack[10 * 1024];
static Z_DECL_ALIGN(struct _isr_list) Z_GENERIC_SECTION(.intList)
__used __isr_siwg917_coprocessor_stack_irq = {
.irq = 30,
.flags = ISR_FLAG_DIRECT,
.func = &siwg917_nwp_stack[sizeof(siwg917_nwp_stack) - 1],
};
DT_INST_FOREACH_STATUS_OKAY(SIWX91X_NWP_DEFINE)

View File

@@ -2,13 +2,14 @@
* Copyright (c) 2025 Silicon Laboratories Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef SIWG917_NWP_H
#define SIWG917_NWP_H
#ifndef SIWX91X_NWP_H
#define SIWX91X_NWP_H
#include <zephyr/device.h>
#include "sl_wifi.h"
#define SIWX91X_INTERFACE_MASK (0x03)
#define DEFAULT_COUNTRY_CODE "00"
#define DEFAULT_COUNTRY_CODE "00"
/**
* @brief Switch the Wi-Fi operating mode.
@@ -17,13 +18,15 @@
* operating mode based on the provided features. It performs a soft reboot
* of the NWP to apply the new mode along with the updated features.
*
* @param[in] dev NWP device.
* @param[in] oper_mode Wi-Fi operating mode to switch to.
* @param[in] hidden_ssid SSID and its length (used only in WIFI_AP_MODE).
* @param[in] max_num_sta Maximum number of supported stations (only for WIFI_AP_MODE).
*
* @return 0 on success, negative error code on failure.
*/
int siwx91x_nwp_mode_switch(uint8_t oper_mode, bool hidden_ssid, uint8_t max_num_sta);
int siwx91x_nwp_mode_switch(const struct device *dev, uint8_t oper_mode, bool hidden_ssid,
uint8_t max_num_sta);
/**
* @brief Map an ISO/IEC 3166-1 alpha-2 country code to a Wi-Fi region code.
@@ -55,9 +58,10 @@ const sli_si91x_set_region_ap_request_t *siwx91x_find_sdk_region_table(uint8_t r
*
* This function saves the provided country code to a static internal buffer.
*
* @param[in] dev NWP device.
* @param[in] country_code Pointer to a 2-character ISO country code.
*/
int siwx91x_store_country_code(const char *country_code);
int siwx91x_store_country_code(const struct device *dev, const char *country_code);
/**
* @brief Retrieve the currently stored country code.
@@ -65,8 +69,10 @@ int siwx91x_store_country_code(const char *country_code);
* This function returns a pointer to the internally stored 2-character
* country code set by store_country_code().
*
* @param[in] dev NWP device.
*
* @return Pointer to the stored country code string.
*/
const char *siwx91x_get_country_code(void);
const char *siwx91x_get_country_code(const struct device *dev);
#endif

View File

@@ -42,7 +42,7 @@ void pm_state_set(enum pm_state state, uint8_t substate_id)
LOG_ERR("Failed to configure clocks for sleep mode");
goto out;
}
if (IS_ENABLED(CONFIG_WISECONNECT_NETWORK_STACK)) {
if (IS_ENABLED(CONFIG_SILABS_SIWX91X_NWP)) {
if (!(M4_ULP_SLP_STATUS_REG & ULP_MODE_SWITCHED_NPSS)) {
if (!sl_si91x_is_device_initialized()) {
LOG_ERR("Device is not initialized");