Commit 06158853 authored by Arunmani Alagarsamy's avatar Arunmani Alagarsamy Committed by Benjamin Cabé
Browse files

drivers: wifi: siwx91x: Add support for regulatory domain GET



Added support for retrieving the regulatory domain information from
the siwx91x driver. Since the SDK does not provide a GET API for
region details, the driver now stores the country code and reuse
the configuration `sli_si91x_set_region_ap_request_t` to get the
channel information. This stored data is returned when a GET
operation is requested.

Signed-off-by: default avatarArunmani Alagarsamy <arunmani.a@silabs.com>
parent eac77845
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "sl_wifi_callback_framework.h"

#define SIWX91X_DRIVER_VERSION KERNEL_VERSION_STRING
#define MAX_24GHZ_CHANNELS 14

LOG_MODULE_REGISTER(siwx91x_wifi);

@@ -369,10 +370,43 @@ static int siwx91x_get_version(const struct device *dev, struct wifi_version *pa
	return 0;
}

static int map_sdk_region_to_zephyr_channel_info(const sli_si91x_set_region_ap_request_t *sdk_reg,
						 struct wifi_reg_chan_info *z_chan_info,
						 size_t *num_channels)
{
	uint8_t first_channel = sdk_reg->channel_info[0].first_channel;
	uint8_t channel;
	uint16_t freq;

	*num_channels = sdk_reg->channel_info[0].no_of_channels;
	if (*num_channels > MAX_24GHZ_CHANNELS) {
		return -EOVERFLOW;
	}

	for (int idx = 0; idx < *num_channels; idx++) {
		channel = first_channel + idx;
		freq = 2407 + channel * 5;

		if (freq > 2472) {
			freq = 2484; /* channel 14 */
		}

		z_chan_info[idx].center_frequency = freq;
		z_chan_info[idx].max_power = sdk_reg->channel_info[0].max_tx_power;
		z_chan_info[idx].supported = 1;
		z_chan_info[idx].passive_only = 0;
		z_chan_info[idx].dfs = 0;
	}

	return 0;
}

static int siwx91x_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_domain)
{
	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;
	const char *country_code;
	int ret;

	__ASSERT(reg_domain, "reg_domain cannot be NULL");
@@ -386,8 +420,28 @@ 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);
			LOG_INF("Country code not supported, using default region");
		} else {
			siwx91x_store_country_code(reg_domain->country_code);
		}
	} else if (reg_domain->oper == WIFI_MGMT_GET) {
		country_code = siwx91x_get_country_code();
		memcpy(reg_domain->country_code, country_code, WIFI_COUNTRY_CODE_LEN);
		region_code = siwx91x_map_country_code_to_region(country_code);

		sdk_reg = siwx91x_find_sdk_region_table(region_code);
		if (!sdk_reg) {
			return -ENOENT;
		}

		ret = map_sdk_region_to_zephyr_channel_info(sdk_reg, reg_domain->chan_info,
							    &reg_domain->num_channels);
		if (ret) {
			return ret;
		}
	} else {
		return -EINVAL;
	}

	return 0;
+44 −6
Original line number Diff line number Diff line
@@ -32,10 +32,19 @@ 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;

static char current_country_code[WIFI_COUNTRY_CODE_LEN];
typedef struct {
	const char *const *codes;
	size_t num_codes;
	sl_wifi_region_code_t region_code;
	const sli_si91x_set_region_ap_request_t *sdk_reg;
} region_map_t;

static const char *const us_codes[] = {
@@ -63,13 +72,31 @@ 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},
	{eu_codes, ARRAY_SIZE(eu_codes), SL_WIFI_REGION_EU},
	{jp_codes, ARRAY_SIZE(jp_codes), SL_WIFI_REGION_JP},
	{kr_codes, ARRAY_SIZE(kr_codes), SL_WIFI_REGION_KR},
	{cn_codes, ARRAY_SIZE(cn_codes), SL_WIFI_REGION_CN},
	{us_codes, ARRAY_SIZE(us_codes), SL_WIFI_REGION_US,
	 &default_US_region_2_4GHZ_configurations},
	{eu_codes, ARRAY_SIZE(eu_codes), SL_WIFI_REGION_EU,
	 &default_EU_region_2_4GHZ_configurations},
	{jp_codes, ARRAY_SIZE(jp_codes), SL_WIFI_REGION_JP,
	 &default_JP_region_2_4GHZ_configurations},
	{kr_codes, ARRAY_SIZE(kr_codes), SL_WIFI_REGION_KR,
	 &default_KR_region_2_4GHZ_configurations},
	{cn_codes, ARRAY_SIZE(cn_codes), SL_WIFI_REGION_CN,
	 &default_CN_region_2_4GHZ_configurations},
};

int siwx91x_store_country_code(const char *country_code)
{
	__ASSERT(country_code, "country_code cannot be NULL");

	memcpy(current_country_code, country_code, WIFI_COUNTRY_CODE_LEN);
	return 0;
}

const char *siwx91x_get_country_code(void)
{
	return current_country_code;
}

sl_wifi_region_code_t siwx91x_map_country_code_to_region(const char *country_code)
{
	__ASSERT(country_code, "country_code cannot be NULL");
@@ -85,6 +112,16 @@ sl_wifi_region_code_t siwx91x_map_country_code_to_region(const char *country_cod
	return SL_WIFI_DEFAULT_REGION;
}

const sli_si91x_set_region_ap_request_t *siwx91x_find_sdk_region_table(uint8_t region_code)
{
	ARRAY_FOR_EACH(region_maps, i) {
		if (region_maps[i].region_code == region_code) {
			return region_maps[i].sdk_reg;
		}
	}
	return NULL;
}

static void siwx91x_apply_sram_config(sl_si91x_boot_configuration_t *boot_config)
{
	/* The size does not match exactly because 1 KB is reserved at the start of the RAM */
@@ -214,8 +251,8 @@ int siwx91x_get_nwp_config(sl_wifi_device_configuration_t *get_config, uint8_t w
			   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),
		.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 |
@@ -246,6 +283,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_apply_sram_config(boot_config);

	switch (wifi_oper_mode) {
+32 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include "sl_wifi.h"

#define SIWX91X_INTERFACE_MASK (0x03)
#define DEFAULT_COUNTRY_CODE	"00"

/**
 * @brief Switch the Wi-Fi operating mode.
@@ -37,4 +38,35 @@ int siwx91x_nwp_mode_switch(uint8_t oper_mode, bool hidden_ssid, uint8_t max_num
 */
sl_wifi_region_code_t siwx91x_map_country_code_to_region(const char *country_code);

/**
 * @brief Get the default SDK region configuration for a region code.
 *
 * Looks up the given sl_wifi_region_code_t and returns the corresponding
 * SDK region configuration, or NULL if not found.
 *
 * @param[in] region_code  Wi-Fi region code (SL_WIFI_REGION_*).
 *
 * @return Pointer to SDK region configuration, or NULL if unsupported.
 */
const sli_si91x_set_region_ap_request_t *siwx91x_find_sdk_region_table(uint8_t region_code);

/**
 * @brief Store the country code internally for GET operation.
 *
 * This function saves the provided country code to a static internal buffer.
 *
 * @param[in] country_code  Pointer to a 2-character ISO country code.
 */
int siwx91x_store_country_code(const char *country_code);

/**
 * @brief Retrieve the currently stored country code.
 *
 * This function returns a pointer to the internally stored 2-character
 * country code set by store_country_code().
 *
 * @return Pointer to the stored country code string.
 */
const char *siwx91x_get_country_code(void);

#endif