From b578b06970f66eb985e67330226002d7ae4571ab Mon Sep 17 00:00:00 2001 From: Arunmani Alagarsamy Date: Tue, 18 Feb 2025 15:05:28 +0530 Subject: [PATCH] drivers: wifi: siwx91x: Add run time opermode This commit enables the device to change its operating mode at runtime. Signed-off-by: Arunmani Alagarsamy --- drivers/wifi/siwx91x/Kconfig.siwx91x | 1 - drivers/wifi/siwx91x/siwx91x_wifi.c | 45 ++++ .../silabs_siwx91x/siwg917/CMakeLists.txt | 2 +- soc/silabs/silabs_siwx91x/siwg917/nwp.c | 196 ++++++++++++++++++ soc/silabs/silabs_siwx91x/siwg917/nwp.h | 25 +++ soc/silabs/silabs_siwx91x/siwg917/nwp_init.c | 111 ---------- 6 files changed, 267 insertions(+), 113 deletions(-) create mode 100644 soc/silabs/silabs_siwx91x/siwg917/nwp.c create mode 100644 soc/silabs/silabs_siwx91x/siwg917/nwp.h delete mode 100644 soc/silabs/silabs_siwx91x/siwg917/nwp_init.c diff --git a/drivers/wifi/siwx91x/Kconfig.siwx91x b/drivers/wifi/siwx91x/Kconfig.siwx91x index 80e312d0f9e..56f17214b76 100644 --- a/drivers/wifi/siwx91x/Kconfig.siwx91x +++ b/drivers/wifi/siwx91x/Kconfig.siwx91x @@ -49,5 +49,4 @@ config NET_MGMT_EVENT_QUEUE_SIZE # This device supports filtering scan results for only one SSID. config WIFI_MGMT_SCAN_SSID_FILT_MAX default 1 - endif diff --git a/drivers/wifi/siwx91x/siwx91x_wifi.c b/drivers/wifi/siwx91x/siwx91x_wifi.c index 20ee852a4a1..7b85ca7f7c7 100644 --- a/drivers/wifi/siwx91x/siwx91x_wifi.c +++ b/drivers/wifi/siwx91x/siwx91x_wifi.c @@ -7,6 +7,7 @@ #include #include +#include #include "siwx91x_wifi.h" #include "siwx91x_wifi_socket.h" @@ -24,6 +25,20 @@ LOG_MODULE_REGISTER(siwx91x_wifi); NET_BUF_POOL_FIXED_DEFINE(siwx91x_tx_pool, 1, _NET_ETH_MAX_FRAME_SIZE, 0, NULL); +static int siwx91x_sl_to_z_mode(sl_wifi_interface_t interface) +{ + switch (interface) { + case SL_WIFI_CLIENT_INTERFACE: + return WIFI_STA_MODE; + case SL_WIFI_AP_INTERFACE: + return WIFI_AP_MODE; + default: + return -EIO; + } + + return 0; +} + static unsigned int siwx91x_on_join(sl_wifi_event_t event, char *result, uint32_t result_size, void *arg) { @@ -302,6 +317,35 @@ static int siwx91x_status(const struct device *dev, struct wifi_iface_status *st return 0; } +static int siwx91x_mode(const struct device *dev, struct wifi_mode_info *mode) +{ + sl_wifi_interface_t interface = sl_wifi_get_default_interface(); + struct siwx91x_dev *sidev = dev->data; + int cur_mode; + int ret = 0; + + __ASSERT(mode, "mode cannot be NULL"); + + cur_mode = siwx91x_sl_to_z_mode(FIELD_GET(SIWX91X_INTERFACE_MASK, interface)); + if (cur_mode < 0) { + return -EIO; + } + + if (mode->oper == WIFI_MGMT_GET) { + mode->mode = cur_mode; + } else if (mode->oper == WIFI_MGMT_SET) { + if (cur_mode != mode->mode) { + ret = siwx91x_nwp_mode_switch(mode->mode); + if (ret < 0) { + return ret; + } + } + sidev->state = WIFI_STATE_INACTIVE; + } + + return 0; +} + #ifdef CONFIG_WIFI_SILABS_SIWX91X_NET_STACK_NATIVE static int siwx91x_send(const struct device *dev, struct net_pkt *pkt) @@ -414,6 +458,7 @@ static const struct wifi_mgmt_ops siwx91x_mgmt = { .connect = siwx91x_connect, .disconnect = siwx91x_disconnect, .iface_status = siwx91x_status, + .mode = siwx91x_mode, }; static const struct net_wifi_mgmt_offload siwx91x_api = { diff --git a/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt b/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt index 33985be7796..d49353f7781 100644 --- a/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt +++ b/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt @@ -2,6 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_sources_ifdef(CONFIG_SOC_SERIES_SIWG917 soc.c) -zephyr_sources_ifdef(CONFIG_WISECONNECT_NETWORK_STACK nwp_init.c) +zephyr_sources_ifdef(CONFIG_WISECONNECT_NETWORK_STACK nwp.c) set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/silabs/silabs_siwx91x/siwg917/nwp.c b/soc/silabs/silabs_siwx91x/siwg917/nwp.c new file mode 100644 index 00000000000..3104ceebb90 --- /dev/null +++ b/soc/silabs/silabs_siwx91x/siwg917/nwp.c @@ -0,0 +1,196 @@ +/** + * @file + * @brief Network Processor Initialization for SiWx91x. + * + * This file contains the initialization routine for the (ThreadArch) network processor + * on the SiWx91x platform. The component is responsible for setting up the necessary + * hardware and software components to enable network communication. + * + * Copyright (c) 2025 Silicon Laboratories Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "nwp.h" +#include "sl_wifi_callback_framework.h" +#ifdef CONFIG_BT_SILABS_SIWX91X +#include "rsi_ble_common_config.h" +#endif + +LOG_MODULE_REGISTER(siwx91x_nwp); + +int siwg91x_get_nwp_config(int wifi_oper_mode, sl_wifi_device_configuration_t *get_config) +{ + sl_wifi_device_configuration_t default_config = { + .band = SL_SI91X_WIFI_BAND_2_4GHZ, + .region_code = DEFAULT_REGION, + .boot_option = LOAD_NWP_FW, + .boot_config = { + .feature_bit_map = SL_SI91X_FEAT_SECURITY_OPEN | SL_SI91X_FEAT_WPS_DISABLE, + .tcp_ip_feature_bit_map = SL_SI91X_TCP_IP_FEAT_EXTENSION_VALID, + .custom_feature_bit_map = SL_SI91X_CUSTOM_FEAT_EXTENSION_VALID, + .ext_custom_feature_bit_map = + MEMORY_CONFIG | + SL_SI91X_EXT_FEAT_XTAL_CLK, + } + }; + + __ASSERT(get_config, "get_config cannot be NULL"); + + sl_si91x_boot_configuration_t *boot_config = &default_config.boot_config; + + if (wifi_oper_mode == SL_SI91X_CLIENT_MODE) { + boot_config->oper_mode = SL_SI91X_CLIENT_MODE; + + if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X) && + IS_ENABLED(CONFIG_BT_SILABS_SIWX91X)) { + boot_config->coex_mode = SL_SI91X_WLAN_BLE_MODE; + } else if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X)) { + boot_config->coex_mode = SL_SI91X_WLAN_ONLY_MODE; + } else if (IS_ENABLED(CONFIG_BT_SILABS_SIWX91X)) { + boot_config->coex_mode = SL_SI91X_BLE_MODE; + } else { + /* + * Even if neither WiFi or BLE is used we have to specify a Coex mode + */ + boot_config->coex_mode = SL_SI91X_BLE_MODE; + } + +#ifdef CONFIG_WIFI_SILABS_SIWX91X + boot_config->ext_tcp_ip_feature_bit_map = SL_SI91X_CONFIG_FEAT_EXTENSION_VALID; + boot_config->config_feature_bit_map = SL_SI91X_ENABLE_ENHANCED_MAX_PSP; + 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; +#endif + +#ifdef CONFIG_BT_SILABS_SIWX91X + 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; + 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); +#endif + } else if (wifi_oper_mode == SL_SI91X_ACCESS_POINT_MODE) { + boot_config->oper_mode = SL_SI91X_ACCESS_POINT_MODE; + boot_config->coex_mode = SL_SI91X_WLAN_ONLY_MODE; + + if (IS_ENABLED(CONFIG_BT_SILABS_SIWX91X)) { + LOG_WRN("Bluetooth is not supported in AP mode"); + } + } else { + return -EINVAL; + } + +#ifdef CONFIG_WIFI_SILABS_SIWX91X + if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X_NET_STACK_OFFLOAD)) { + boot_config->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_ICMP; + boot_config->ext_tcp_ip_feature_bit_map |= SL_SI91X_EXT_TCP_IP_WINDOW_SCALING; + boot_config->ext_tcp_ip_feature_bit_map |= SL_SI91X_EXT_TCP_IP_TOTAL_SELECTS(10); + + if (IS_ENABLED(CONFIG_NET_IPV6)) { + boot_config->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_IPV6; + if (wifi_oper_mode == SL_SI91X_CLIENT_MODE) { + boot_config->tcp_ip_feature_bit_map |= + SL_SI91X_TCP_IP_FEAT_DHCPV6_CLIENT; + } else if (wifi_oper_mode == SL_SI91X_ACCESS_POINT_MODE) { + boot_config->tcp_ip_feature_bit_map |= + SL_SI91X_TCP_IP_FEAT_DHCPV6_SERVER; + } + } + + if (IS_ENABLED(CONFIG_NET_IPV4)) { + if (wifi_oper_mode == SL_SI91X_CLIENT_MODE) { + boot_config->tcp_ip_feature_bit_map |= + SL_SI91X_TCP_IP_FEAT_DHCPV4_CLIENT; + } else if (wifi_oper_mode == SL_SI91X_ACCESS_POINT_MODE) { + boot_config->tcp_ip_feature_bit_map |= + SL_SI91X_TCP_IP_FEAT_DHCPV4_SERVER; + } + } + } else { + boot_config->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_BYPASS; + } +#endif + memcpy(get_config, &default_config, sizeof(default_config)); + return 0; +} + +int siwx91x_nwp_mode_switch(uint8_t oper_mode) +{ + sl_wifi_device_configuration_t nwp_config; + sl_status_t status; + + switch (oper_mode) { + case WIFI_STA_MODE: + siwg91x_get_nwp_config(SL_SI91X_CLIENT_MODE, &nwp_config); + break; + case WIFI_AP_MODE: + siwg91x_get_nwp_config(SL_SI91X_ACCESS_POINT_MODE, &nwp_config); + break; + default: + return -EINVAL; + } + + /* FIXME: Calling sl_wifi_deinit() impacts Bluetooth if coexistence is enabled */ + status = sl_wifi_deinit(); + if (status != SL_STATUS_OK) { + return -ETIMEDOUT; + } + + status = sl_wifi_init(&nwp_config, NULL, sl_wifi_default_event_handler); + if (status != SL_STATUS_OK) { + return -ETIMEDOUT; + } + + return 0; +} + +static int siwg917_nwp_init(void) +{ + sl_wifi_device_configuration_t network_config; + sl_status_t status; + + siwg91x_get_nwp_config(SL_SI91X_CLIENT_MODE, &network_config); + /* TODO: If sl_net_*_profile() functions will be needed for WiFi then call + * sl_net_set_profile() here. Currently these are unused. + */ + status = sl_wifi_init(&network_config, NULL, sl_wifi_default_event_handler); + if (status != SL_STATUS_OK) { + return -EINVAL; + } + + return 0; +} +SYS_INIT(siwg917_nwp_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); + +/* IRQn 74 is used for communication with co-processor */ +Z_ISR_DECLARE(74, 0, IRQ074_Handler, 0); + +/* 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], + }; diff --git a/soc/silabs/silabs_siwx91x/siwg917/nwp.h b/soc/silabs/silabs_siwx91x/siwg917/nwp.h new file mode 100644 index 00000000000..74fbec48b85 --- /dev/null +++ b/soc/silabs/silabs_siwx91x/siwg917/nwp.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Silicon Laboratories Inc. + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef SIWG917_NWP_H +#define SIWG917_NWP_H + +#include "sl_wifi.h" + +#define SIWX91X_INTERFACE_MASK (0x03) + +/** + * @brief Switch the Wi-Fi operating modes. + * + * This function switches the mode. If the requested mode is already active, + * no action is performed. Otherwise, it reinitializes the Wi-Fi subsystem to + * apply the new mode. + * + * @param[in] oper_mode Desired Wi-Fi operating mode: + * + * @return 0 on success, or a negative error code on failure: + */ +int siwx91x_nwp_mode_switch(uint8_t oper_mode); + +#endif diff --git a/soc/silabs/silabs_siwx91x/siwg917/nwp_init.c b/soc/silabs/silabs_siwx91x/siwg917/nwp_init.c deleted file mode 100644 index fb508dae710..00000000000 --- a/soc/silabs/silabs_siwx91x/siwg917/nwp_init.c +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file - * @brief Network Processor Initialization for SiWx91x. - * - * This file contains the initialization routine for the (ThreadArch) network processor - * on the SiWx91x platform. The component is responsible for setting up the necessary - * hardware and software components to enable network communication. - * - * Copyright (c) 2024 Silicon Laboratories Inc. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include "sl_wifi.h" -#include "sl_wifi_callback_framework.h" -#ifdef CONFIG_BT_SILABS_SIWX91X -#include "rsi_ble_common_config.h" -#endif - -static int siwg917_nwp_init(void) -{ - sl_wifi_device_configuration_t network_config = { - .boot_option = LOAD_NWP_FW, - .band = SL_SI91X_WIFI_BAND_2_4GHZ, - .region_code = DEFAULT_REGION, - .boot_config = { - .oper_mode = SL_SI91X_CLIENT_MODE, - .tcp_ip_feature_bit_map = SL_SI91X_TCP_IP_FEAT_EXTENSION_VALID, - .ext_tcp_ip_feature_bit_map = SL_SI91X_CONFIG_FEAT_EXTENSION_VALID, - .config_feature_bit_map = SL_SI91X_ENABLE_ENHANCED_MAX_PSP, - .custom_feature_bit_map = SL_SI91X_CUSTOM_FEAT_EXTENSION_VALID, - .ext_custom_feature_bit_map = - MEMORY_CONFIG | - SL_SI91X_EXT_FEAT_XTAL_CLK | - SL_SI91X_EXT_FEAT_FRONT_END_SWITCH_PINS_ULP_GPIO_4_5_0, - } - }; - sl_si91x_boot_configuration_t *cfg = &network_config.boot_config; - - if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X) && IS_ENABLED(CONFIG_BT_SILABS_SIWX91X)) { - cfg->coex_mode = SL_SI91X_WLAN_BLE_MODE; - } else if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X)) { - cfg->coex_mode = SL_SI91X_WLAN_ONLY_MODE; - } else if (IS_ENABLED(CONFIG_BT_SILABS_SIWX91X)) { - cfg->coex_mode = SL_SI91X_BLE_MODE; - } else { - /* - * Even if neither WiFi or BLE is used we have to specify a Coex mode - */ - cfg->coex_mode = SL_SI91X_BLE_MODE; - } - -#ifdef CONFIG_WIFI_SILABS_SIWX91X - cfg->feature_bit_map |= SL_SI91X_FEAT_SECURITY_OPEN | SL_SI91X_FEAT_WPS_DISABLE, - cfg->ext_custom_feature_bit_map |= SL_SI91X_EXT_FEAT_IEEE_80211W; - if (IS_ENABLED(CONFIG_WIFI_SILABS_SIWX91X_NET_STACK_OFFLOAD)) { - cfg->ext_tcp_ip_feature_bit_map |= SL_SI91X_EXT_TCP_IP_WINDOW_SCALING; - cfg->ext_tcp_ip_feature_bit_map |= SL_SI91X_EXT_TCP_IP_TOTAL_SELECTS(10); - cfg->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_ICMP; - if (IS_ENABLED(CONFIG_NET_IPV6)) { - cfg->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_DHCPV6_CLIENT; - cfg->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_IPV6; - } - if (IS_ENABLED(CONFIG_NET_IPV4)) { - cfg->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_DHCPV4_CLIENT; - } - } else { - cfg->tcp_ip_feature_bit_map |= SL_SI91X_TCP_IP_FEAT_BYPASS; - } -#endif - -#ifdef CONFIG_BT_SILABS_SIWX91X - cfg->ext_custom_feature_bit_map |= SL_SI91X_EXT_FEAT_BT_CUSTOM_FEAT_ENABLE; - cfg->bt_feature_bit_map |= SL_SI91X_BT_RF_TYPE | SL_SI91X_ENABLE_BLE_PROTOCOL; - cfg->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; - cfg->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); -#endif - - /* TODO: If sl_net_*_profile() functions will be needed for WiFi then call - * sl_net_set_profile() here. Currently these are unused. - */ - return sl_wifi_init(&network_config, NULL, sl_wifi_default_event_handler); -} -SYS_INIT(siwg917_nwp_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); - -/* IRQn 74 is used for communication with co-processor */ -Z_ISR_DECLARE(74, 0, IRQ074_Handler, 0); - -/* 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], - };