This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit b6e09955ddae3484251c632501375ce6e5006295
Author: chen...@espressif.com <chen...@espressif.com>
AuthorDate: Sun Oct 8 16:08:24 2023 +0800

    xtensa/esp32s3: Support multiple PHY init data bin
    
    1. If CONFIG_ESP32S3_PHY_INIT_DATA_IN_PARTITION and 
CONFIG_ESP32S3_SUPPORT_MULTIPLE_PHY_INIT_DATA are enabled,
    PHY initialization data (PHY initialization data is used for RF 
calibration) will be loaded from a partition.
    
    2. The corresponding PHY init data type can be automatically switched 
according to the country code,
    China's PHY init data bin is used by default, country code can be modified 
through the wapi command: wapi country <ifname> <country code>.
    
    Signed-off-by: chen...@espressif.com <chen...@espressif.com>
---
 arch/xtensa/src/esp32s3/Kconfig                    |  58 +-
 arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c     |  16 +-
 arch/xtensa/src/esp32s3/esp32s3_wireless.c         | 619 ++++++++++++++++++++-
 arch/xtensa/src/esp32s3/esp32s3_wireless.h         |  20 +-
 .../esp32s3/esp32s3-devkit/src/esp32s3_bringup.c   |  16 +-
 5 files changed, 699 insertions(+), 30 deletions(-)

diff --git a/arch/xtensa/src/esp32s3/Kconfig b/arch/xtensa/src/esp32s3/Kconfig
index fb7879e6b1..92fad2af41 100644
--- a/arch/xtensa/src/esp32s3/Kconfig
+++ b/arch/xtensa/src/esp32s3/Kconfig
@@ -1448,6 +1448,62 @@ config ESP32S3_BLE_INTERRUPT_SAVE_STATUS
 
 endmenu # BLE Configuration
 
+menu "PHY"
+       depends on ESP32S3_PARTITION_TABLE
+
+menuconfig ESP32S3_PHY_INIT_DATA_IN_PARTITION
+       bool "Use a partition to store PHY init data"
+       default n
+       ---help---
+               If enabled, PHY init data will be loaded from a partition. 
Otherwise,
+               PHY init data will be embedded into the application binary.
+
+               When using a custom partition table, make sure that the PHY data
+               partition is included (type: 'data', subtype: 'phy').
+
+               If PHY init data is stored in a partition, it has to be flashed 
there,
+               otherwise runtime error will occur.
+
+config ESP32S3_PHY_DEFAULT_INIT_IF_INVALID
+       bool "Reset default PHY init data if invalid"
+       default n
+       depends on ESP32S3_PHY_INIT_DATA_IN_PARTITION
+       ---help---
+               If enabled, PHY init data will be restored to default if
+               it cannot be verified successfully to avoid endless bootloops.
+
+               If unsure, choose 'n'.
+
+if ESP32S3_PHY_INIT_DATA_IN_PARTITION
+
+config ESP32S3_SUPPORT_MULTIPLE_PHY_INIT_DATA
+       bool "Support multiple PHY init data bin"
+       depends on ESP32S3_PHY_INIT_DATA_IN_PARTITION
+       default n
+       ---help---
+               If enabled, the corresponding PHY init data type can be 
automatically switched
+               according to the country code. China's PHY init data bin is 
used by default.
+               Can be modified by country information in API 
esp_wifi_set_country().
+               The priority of switching the PHY init data type is:
+               1. Country configured by API esp_wifi_set_country()
+               and the parameter policy is WIFI_COUNTRY_POLICY_MANUAL.
+               2. Country notified by the connected AP.
+               3. Country configured by API esp_wifi_set_country()
+               and the parameter policy is WIFI_COUNTRY_POLICY_AUTO.
+
+config ESP32S3_PHY_INIT_DATA_ERROR
+       bool "Terminate operation when PHY init data error"
+       depends on ESP32S3_SUPPORT_MULTIPLE_PHY_INIT_DATA
+       default n
+       ---help---
+               If enabled, when an error occurs while the PHY init data is 
updated,
+               the program will terminate and restart.
+               If not enabled, the PHY init data will not be updated when an 
error occurs.
+
+endif
+
+endmenu  # PHY
+
 menu "Timer/Counter Configuration"
        depends on ESP32S3_TIMER
 
@@ -1667,7 +1723,7 @@ comment "Partition Table configuration"
 config ESP32S3_PARTITION_TABLE
        bool "Create MTD partitions from Partition Table"
        default n
-       depends on ESP32S3_MTD
+       depends on ESP32S3_MTD && ESP32S3_BOOTLOADER_BUILD_FROM_SOURCE
        ---help---
                Decode partition table and initialize partitions as MTD.
 
diff --git a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c 
b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c
index 79c145bd5e..8ba356cf79 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_wifi_adapter.c
@@ -259,7 +259,6 @@ static void esp_dport_access_stall_other_cpu_start(void);
 static void esp_dport_access_stall_other_cpu_end(void);
 static void wifi_apb80m_request(void);
 static void wifi_apb80m_release(void);
-static int32_t wifi_phy_update_country_info(const char *country);
 static int32_t esp_wifi_read_mac(uint8_t *mac, uint32_t type);
 static void esp_timer_arm(void *timer, uint32_t tmout, bool repeat);
 static void esp_timer_disarm(void *timer);
@@ -487,7 +486,7 @@ wifi_osi_funcs_t g_wifi_osi_funcs =
   ._wifi_apb80m_release = wifi_apb80m_release,
   ._phy_disable = esp32s3_phy_disable,
   ._phy_enable = esp32s3_phy_enable,
-  ._phy_update_country_info = wifi_phy_update_country_info,
+  ._phy_update_country_info = esp32s3_phy_update_country_info,
   ._read_mac = esp_wifi_read_mac,
   ._timer_arm = esp_timer_arm,
   ._timer_disarm = esp_timer_disarm,
@@ -2535,19 +2534,6 @@ static void wifi_apb80m_release(void)
 #endif
 }
 
-/****************************************************************************
- * Name: wifi_phy_update_country_info
- *
- * Description:
- *   Don't support
- *
- ****************************************************************************/
-
-static int32_t wifi_phy_update_country_info(const char *country)
-{
-  return -1;
-}
-
 /****************************************************************************
  * Name: esp_wifi_read_mac
  *
diff --git a/arch/xtensa/src/esp32s3/esp32s3_wireless.c 
b/arch/xtensa/src/esp32s3/esp32s3_wireless.c
index c74bf12f2a..9da89df749 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_wireless.c
+++ b/arch/xtensa/src/esp32s3/esp32s3_wireless.c
@@ -25,9 +25,12 @@
 #include <nuttx/config.h>
 #include <nuttx/kmalloc.h>
 #include <nuttx/mqueue.h>
+#include <nuttx/spinlock.h>
 
 #include <debug.h>
 #include <assert.h>
+#include <netinet/in.h>
+#include <sys/param.h>
 
 #include "xtensa.h"
 #include "hardware/esp32s3_efuse.h"
@@ -42,6 +45,7 @@
 #include "phy_init_data.h"
 
 #include "esp32s3_wireless.h"
+#include "esp32s3_partition.h"
 
 /****************************************************************************
  * Pre-processor Definitions
@@ -90,6 +94,7 @@ extern uint8_t phy_dig_reg_backup(bool init, uint32_t *regs);
 extern int  register_chipv7_phy(const esp_phy_init_data_t *init_data,
                                 esp_phy_calibration_data_t *cal_data,
                                 esp_phy_calibration_mode_t cal_mode);
+extern uint32_t crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len);
 
 /****************************************************************************
  * Private Data
@@ -119,6 +124,83 @@ static uint8_t g_wifi_bt_pd_controller;
 
 static struct esp_wireless_priv_s g_esp_wireless_priv;
 
+#ifdef CONFIG_ESP32S3_PHY_INIT_DATA_IN_PARTITION
+static const char *phy_partion_label = "phy_init";
+#endif
+
+#ifdef CONFIG_ESP32S3_SUPPORT_MULTIPLE_PHY_INIT_DATA
+
+static phy_init_data_type_t g_phy_init_data_type;
+
+static phy_init_data_type_t g_current_apply_phy_init_data;
+
+static char g_phy_current_country[PHY_COUNTRY_CODE_LEN];
+
+/* Whether it is a new bin */
+
+static bool g_multiple_phy_init_data_bin;
+
+/* PHY init data type array */
+
+static const char *g_phy_type[ESP_PHY_INIT_DATA_TYPE_NUMBER] =
+{
+  "DEFAULT", "SRRC", "FCC", "CE", "NCC", "KCC", "MIC", "IC",
+  "ACMA", "ANATEL", "ISED", "WPC", "OFCA", "IFETEL", "RCM"
+};
+
+/* Country and PHY init data type map */
+
+static phy_country_to_bin_type_t g_country_code_map_type_table[] =
+{
+  {"01",  ESP_PHY_INIT_DATA_TYPE_DEFAULT},
+  {"AT",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"AU",  ESP_PHY_INIT_DATA_TYPE_ACMA},
+  {"BE",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"BG",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"BR",  ESP_PHY_INIT_DATA_TYPE_ANATEL},
+  {"CA",  ESP_PHY_INIT_DATA_TYPE_ISED},
+  {"CH",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"CN",  ESP_PHY_INIT_DATA_TYPE_SRRC},
+  {"CY",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"CZ",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"DE",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"DK",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"EE",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"ES",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"FI",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"FR",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"GB",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"GR",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"HK",  ESP_PHY_INIT_DATA_TYPE_OFCA},
+  {"HR",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"HU",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"IE",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"IN",  ESP_PHY_INIT_DATA_TYPE_WPC},
+  {"IS",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"IT",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"JP",  ESP_PHY_INIT_DATA_TYPE_MIC},
+  {"KR",  ESP_PHY_INIT_DATA_TYPE_KCC},
+  {"LI",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"LT",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"LU",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"LV",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"MT",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"MX",  ESP_PHY_INIT_DATA_TYPE_IFETEL},
+  {"NL",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"NO",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"NZ",  ESP_PHY_INIT_DATA_TYPE_RCM},
+  {"PL",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"PT",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"RO",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"SE",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"SI",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"SK",  ESP_PHY_INIT_DATA_TYPE_CE},
+  {"TW",  ESP_PHY_INIT_DATA_TYPE_NCC},
+  {"US",  ESP_PHY_INIT_DATA_TYPE_FCC},
+};
+
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -312,6 +394,481 @@ void IRAM_ATTR esp32s3_phy_disable_clock(void)
   esp32s3_periph_wifi_bt_common_module_disable();
 }
 
+#ifdef CONFIG_ESP32S3_SUPPORT_MULTIPLE_PHY_INIT_DATA
+
+/****************************************************************************
+ * Name: phy_crc_check
+ *
+ * Description:
+ *   Check the checksum value of data
+ *
+ * Input Parameters:
+ *   data     - Data buffer pointer
+ *   length   - Data length
+ *   checksum - Checksum pointer
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int phy_crc_check(uint8_t *data, const uint8_t *checksum,
+                         size_t length)
+{
+  uint32_t crc_data = crc32_le(0, data, length);
+  uint32_t crc_size_conversion = HTONL(crc_data);
+  uint32_t tmp_crc = checksum[0] | (checksum[1] << 8) | (checksum[2] << 16) |
+                     (checksum[3] << 24);
+  if (crc_size_conversion != tmp_crc)
+    {
+      return ERROR;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: phy_find_bin_type_according_country
+ *
+ * Description:
+ *   Find the PHY initialization data type according to country code
+ *
+ * Input Parameters:
+ *   country - Country code pointer
+ *
+ * Returned Value:
+ *   PHY initialization data type
+ *
+ ****************************************************************************/
+
+static uint8_t phy_find_bin_type_according_country(const char *country)
+{
+  uint8_t i;
+  uint8_t phy_init_data_type;
+  uint8_t num = nitems(g_country_code_map_type_table);
+  for (i = 0; i < num; i++)
+    {
+      if (memcmp(country, g_country_code_map_type_table[i].cc,
+                 sizeof(g_phy_current_country)) == 0)
+        {
+          phy_init_data_type = g_country_code_map_type_table[i].type;
+          wlinfo("Current country is %c%c, PHY init data type is %s\n",
+                  g_country_code_map_type_table[i].cc[0],
+                  g_country_code_map_type_table[i].cc[1],
+                  g_phy_type[g_country_code_map_type_table[i].type]);
+          break;
+        }
+    }
+
+  if (i == num)
+    {
+      phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
+      wlerr("Use the default certification code beacuse %c%c doesn't "
+            "have a certificate\n", country[0], country[1]);
+    }
+
+  return phy_init_data_type;
+}
+
+/****************************************************************************
+ * Name: phy_find_bin_data_according_type
+ *
+ * Description:
+ *   Find the PHY initialization data according to PHY init data type
+ *
+ * Input Parameters:
+ *   output_data    - Output data buffer pointer
+ *   control_info   - PHY init data control infomation
+ *   input_data     - Input data buffer pointer
+ *   init_data_type - PHY init data type
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int phy_find_bin_data_according_type(uint8_t *output_data,
+        const phy_control_info_data_t *control_info,
+        const esp_phy_init_data_t *input_data,
+        phy_init_data_type_t init_data_type)
+{
+  int i;
+  for (i = 0; i < control_info->number; i++)
+    {
+      if (init_data_type == *((uint8_t *)(input_data + i)
+                              + PHY_INIT_DATA_TYPE_OFFSET))
+        {
+          memcpy(output_data + sizeof(phy_init_magic_pre),
+                 (input_data + i), sizeof(esp_phy_init_data_t));
+          break;
+        }
+    }
+
+  if (i == control_info->number)
+    {
+      return ERROR;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: phy_get_multiple_init_data
+ *
+ * Description:
+ *   Get multiple PHY init data according to PHY init data type
+ *
+ * Input Parameters:
+ *   data           - Data buffer pointer
+ *   length         - Data length
+ *   init_data_type - PHY init data type
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int phy_get_multiple_init_data(uint8_t *data, size_t length,
+                                      phy_init_data_type_t init_data_type)
+{
+  phy_control_info_data_t *control_info = (phy_control_info_data_t *)
+                                kmm_malloc(sizeof(phy_control_info_data_t));
+  if (control_info == NULL)
+    {
+      wlerr("ERROR: Failed to allocate memory for\
+            PHY init data control info\n");
+      return -ENOMEM;
+    }
+
+  int ret = esp32s3_partition_read(phy_partion_label, length, control_info,
+                                   sizeof(phy_control_info_data_t));
+  if (ret != OK)
+    {
+      kmm_free(control_info);
+      wlerr("ERROR: Failed to read PHY control info data partition\n");
+      return ret;
+    }
+
+  if ((control_info->check_algorithm) == PHY_CRC_ALGORITHM)
+    {
+      ret = phy_crc_check(control_info->multiple_bin_checksum,
+                          control_info->control_info_checksum,
+                          sizeof(phy_control_info_data_t) -
+                          sizeof(control_info->control_info_checksum));
+      if (ret != OK)
+        {
+          kmm_free(control_info);
+          wlerr("ERROR: PHY init data control info check error\n");
+          return ret;
+        }
+    }
+  else
+    {
+      kmm_free(control_info);
+      wlerr("ERROR: Check algorithm not CRC, PHY init data update failed\n");
+      return ERROR;
+    }
+
+  uint8_t *init_data_multiple = (uint8_t *)
+        kmm_malloc(sizeof(esp_phy_init_data_t) * control_info->number);
+  if (init_data_multiple == NULL)
+    {
+      kmm_free(control_info);
+      wlerr("ERROR: Failed to allocate memory for PHY init data\n");
+      return -ENOMEM;
+    }
+
+  ret = esp32s3_partition_read(phy_partion_label, length +
+          sizeof(phy_control_info_data_t), init_data_multiple,
+          sizeof(esp_phy_init_data_t) * control_info->number);
+  if (ret != OK)
+    {
+      kmm_free(init_data_multiple);
+      kmm_free(control_info);
+      wlerr("ERROR: Failed to read PHY init data multiple bin partition\n");
+      return ret;
+    }
+
+  if ((control_info->check_algorithm) == PHY_CRC_ALGORITHM)
+    {
+      ret = phy_crc_check(init_data_multiple,
+                    control_info->multiple_bin_checksum,
+                    sizeof(esp_phy_init_data_t) * control_info->number);
+      if (ret != OK)
+        {
+          kmm_free(init_data_multiple);
+          kmm_free(control_info);
+          wlerr("ERROR: PHY init data multiple bin check error\n");
+          return ret;
+        }
+    }
+  else
+    {
+      kmm_free(init_data_multiple);
+      kmm_free(control_info);
+      wlerr("ERROR: Check algorithm not CRC, PHY init data update failed\n");
+      return ERROR;
+    }
+
+  ret = phy_find_bin_data_according_type(data, control_info,
+          (const esp_phy_init_data_t *)init_data_multiple, init_data_type);
+  if (ret != OK)
+    {
+      wlerr("ERROR: %s has not been certified, use DEFAULT PHY init data\n",
+            g_phy_type[init_data_type]);
+      g_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
+    }
+  else
+    {
+      g_phy_init_data_type = init_data_type;
+    }
+
+  kmm_free(init_data_multiple);
+  kmm_free(control_info);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: phy_update_init_data
+ *
+ * Description:
+ *   Update PHY init data according to PHY init data type
+ *
+ * Input Parameters:
+ *   init_data_type - PHY init data type
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+static int phy_update_init_data(phy_init_data_type_t init_data_type)
+{
+  int ret;
+  size_t length = sizeof(phy_init_magic_pre) +
+      sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
+  uint8_t *init_data_store = kmm_malloc(length);
+  if (init_data_store == NULL)
+    {
+      wlerr("ERROR: Failed to allocate memory for updated country code "
+            "PHY init data\n");
+      return -ENOMEM;
+    }
+
+  ret = esp32s3_partition_read(phy_partion_label, 0, init_data_store,
+                               length);
+  if (ret != OK)
+    {
+      kmm_free(init_data_store);
+      wlerr("ERROR: Failed to read updated country code PHY data\n");
+      return ret;
+    }
+
+  if (memcmp(init_data_store, PHY_INIT_MAGIC,
+             sizeof(phy_init_magic_pre)) != 0 ||
+      memcmp(init_data_store + length - sizeof(phy_init_magic_post),
+             PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0)
+    {
+      kmm_free(init_data_store);
+      wlerr("ERROR: Failed to validate updated country code PHY data\n");
+      return ERROR;
+    }
+
+  /* find init data bin according init data type */
+
+  if (init_data_type != ESP_PHY_INIT_DATA_TYPE_DEFAULT)
+    {
+      ret = phy_get_multiple_init_data(init_data_store, length,
+                                       init_data_type);
+      if (ret != OK)
+        {
+          kmm_free(init_data_store);
+#ifdef CONFIG_ESP32S3_PHY_INIT_DATA_ERROR
+          abort();
+#else
+          return ret;
+#endif
+        }
+    }
+  else
+    {
+      g_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
+    }
+
+  if (g_current_apply_phy_init_data != g_phy_init_data_type)
+    {
+      ret = esp_phy_apply_phy_init_data(init_data_store +
+                                        sizeof(phy_init_magic_pre));
+      if (ret != OK)
+        {
+          wlerr("ERROR: PHY init data failed to load\n");
+          kmm_free(init_data_store);
+          return ret;
+        }
+
+      wlinfo("PHY init data type updated from %s to %s\n",
+             g_phy_type[g_current_apply_phy_init_data],
+             g_phy_type[g_phy_init_data_type]);
+      g_current_apply_phy_init_data = g_phy_init_data_type;
+    }
+
+  kmm_free(init_data_store);
+  return OK;
+}
+
+#endif
+
+#ifdef CONFIG_ESP32S3_PHY_INIT_DATA_IN_PARTITION
+
+/****************************************************************************
+ * Name: esp_phy_get_init_data
+ *
+ * Description:
+ *   Get PHY init data
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Pointer to PHY init data structure
+ *
+ ****************************************************************************/
+
+const esp_phy_init_data_t *esp_phy_get_init_data(void)
+{
+  int ret;
+  size_t length = sizeof(phy_init_magic_pre) +
+                  sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
+  uint8_t *init_data_store = kmm_malloc(length);
+  if (init_data_store == NULL)
+    {
+      wlerr("ERROR: Failed to allocate memory for PHY init data\n");
+      return NULL;
+    }
+
+  ret = esp32s3_partition_read(phy_partion_label, 0, init_data_store,
+                               length);
+  if (ret != OK)
+    {
+      wlerr("ERROR: Failed to get read data from MTD\n");
+      kmm_free(init_data_store);
+      return NULL;
+    }
+
+  if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre))
+      != 0 || memcmp(init_data_store + length - sizeof(phy_init_magic_post),
+              PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0)
+    {
+#ifdef CONFIG_ESP32S3_PHY_DEFAULT_INIT_IF_INVALID
+      wlerr("ERROR: Failed to validate PHY data partition, restoring "
+            "default data into flash...");
+      memcpy(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre));
+      memcpy(init_data_store + sizeof(phy_init_magic_pre),
+             &phy_init_data, sizeof(phy_init_data));
+      memcpy(init_data_store + sizeof(phy_init_magic_pre) +
+             sizeof(phy_init_data), PHY_INIT_MAGIC,
+             sizeof(phy_init_magic_post));
+      DEBUGASSERT(memcmp(init_data_store, PHY_INIT_MAGIC,
+                  sizeof(phy_init_magic_pre)) == 0);
+      DEBUGASSERT(memcmp(init_data_store + length -
+                  sizeof(phy_init_magic_post), PHY_INIT_MAGIC,
+                  sizeof(phy_init_magic_post)) == 0);
+
+      /* write default data */
+
+      ret = esp32s3_partition_write(phy_partion_label, 0, init_data_store,
+                                    length);
+      if (ret != OK)
+        {
+          wlerr("ERROR: Failed to write default PHY data partition\n");
+          kmm_free(init_data_store);
+          return NULL;
+        }
+#else /* CONFIG_ESP32S3_PHY_DEFAULT_INIT_IF_INVALID */ 
+      wlerr("ERROR: Failed to validate PHY data partition\n");
+      kmm_free(init_data_store);
+      return NULL;
+#endif
+    }
+
+#ifdef CONFIG_ESP32S3_SUPPORT_MULTIPLE_PHY_INIT_DATA
+  if (*(init_data_store + (sizeof(phy_init_magic_pre) +
+      PHY_SUPPORT_MULTIPLE_BIN_OFFSET)))
+    {
+      g_multiple_phy_init_data_bin = true;
+      wlinfo("Support multiple PHY init data bins\n");
+    }
+  else
+    {
+      wlinfo("Does not support multiple PHY init data bins\n");
+    }
+#endif
+
+  wlinfo("PHY data partition validated\n");
+  return (const esp_phy_init_data_t *)
+         (init_data_store + sizeof(phy_init_magic_pre));
+}
+
+/****************************************************************************
+ * Name: esp_phy_release_init_data
+ *
+ * Description:
+ *   Release PHY init data
+ *
+ * Input Parameters:
+ *   init_data - Pointer to PHY init data structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_phy_release_init_data(const esp_phy_init_data_t *init_data)
+{
+  kmm_free((uint8_t *)init_data - sizeof(phy_init_magic_pre));
+}
+
+#else /* CONFIG_ESP32S3_PHY_INIT_DATA_IN_PARTITION */ 
+
+/****************************************************************************
+ * Name: esp_phy_get_init_data
+ *
+ * Description:
+ *   Get PHY init data
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Pointer to PHY init data structure
+ *
+ ****************************************************************************/
+
+const esp_phy_init_data_t *esp_phy_get_init_data(void)
+{
+  wlinfo("Loading PHY init data from application binary\n");
+  return &phy_init_data;
+}
+
+/****************************************************************************
+ * Name: esp_phy_release_init_data
+ *
+ * Description:
+ *   Release PHY init data
+ *
+ * Input Parameters:
+ *   init_data - Pointer to PHY init data structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp_phy_release_init_data(const esp_phy_init_data_t *init_data)
+{
+}
+#endif
+
 /****************************************************************************
  * Name: esp_read_mac
  *
@@ -395,6 +952,54 @@ int32_t esp_read_mac(uint8_t *mac, esp_mac_type_t type)
   return 0;
 }
 
+/****************************************************************************
+ * Name: esp32s3_phy_update_country_info
+ *
+ * Description:
+ *   Update PHY init data according to country code
+ *
+ * Input Parameters:
+ *   country - PHY init data type
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int esp32s3_phy_update_country_info(const char *country)
+{
+#ifdef CONFIG_ESP32S3_SUPPORT_MULTIPLE_PHY_INIT_DATA
+  uint8_t phy_init_data_type_map = 0;
+  if (memcmp(country, g_phy_current_country, sizeof(g_phy_current_country))
+      == 0)
+    {
+      return OK;
+    }
+
+  memcpy(g_phy_current_country, country, sizeof(g_phy_current_country));
+  if (!g_multiple_phy_init_data_bin)
+    {
+      wlerr("ERROR: Does not support multiple PHY init data bins\n");
+      return ERROR;
+    }
+
+  phy_init_data_type_map = phy_find_bin_type_according_country(country);
+  if (phy_init_data_type_map == g_phy_init_data_type)
+    {
+      return OK;
+    }
+
+  int ret =  phy_update_init_data(phy_init_data_type_map);
+  if (ret != OK)
+    {
+      wlerr("ERROR: Failed to update PHY init data\n");
+      return ret;
+    }
+#endif
+
+  return OK;
+}
+
 /****************************************************************************
  * Name: esp32s3_phy_disable
  *
@@ -465,7 +1070,7 @@ void esp32s3_phy_enable(void)
       debug = true;
     }
 
-  flags = enter_critical_section();
+  flags = spin_lock_irqsave(NULL);
 
   if (g_phy_access_ref == 0)
     {
@@ -485,7 +1090,15 @@ void esp32s3_phy_enable(void)
           phy_bbpll_en_usb(true);
 #endif
           wlinfo("calibrating");
-          register_chipv7_phy(&phy_init_data, cal_data, PHY_RF_CAL_FULL);
+          const esp_phy_init_data_t *init_data = esp_phy_get_init_data();
+          if (init_data == NULL)
+            {
+              wlerr("ERROR: Failed to obtain PHY init data");
+              abort();
+            }
+
+          register_chipv7_phy(init_data, cal_data, PHY_RF_CAL_FULL);
+          esp_phy_release_init_data(init_data);
           g_is_phy_calibrated = true;
           kmm_free(cal_data);
         }
@@ -498,7 +1111,7 @@ void esp32s3_phy_enable(void)
 
   g_phy_access_ref++;
 
-  leave_critical_section(flags);
+  spin_unlock_irqrestore(NULL, flags);
 }
 
 /****************************************************************************
diff --git a/arch/xtensa/src/esp32s3/esp32s3_wireless.h 
b/arch/xtensa/src/esp32s3/esp32s3_wireless.h
index 9586d0fa2a..a1f8c4a243 100644
--- a/arch/xtensa/src/esp32s3/esp32s3_wireless.h
+++ b/arch/xtensa/src/esp32s3/esp32s3_wireless.h
@@ -44,9 +44,7 @@
  * headers
  */
 
-#define CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN     0
-#define CONFIG_MAC_BB_PD                                    0
-
+#define CONFIG_MAC_BB_PD                              (0)
 #define MAC_LEN                                       (6)
 
 /****************************************************************************
@@ -159,6 +157,22 @@ void IRAM_ATTR esp32s3_phy_enable_clock(void);
 
 void esp32s3_phy_disable_clock(void);
 
+/****************************************************************************
+ * Name: esp32s3_phy_update_country_info
+ *
+ * Description:
+ *   Update PHY init data according to country code
+ *
+ * Input Parameters:
+ *   country - PHY init data type
+ *
+ * Returned Value:
+ *   OK on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+int esp32s3_phy_update_country_info(const char *country);
+
 /****************************************************************************
  * Functions needed by libphy.a
  ****************************************************************************/
diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c 
b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c
index 8887575c23..bd7675f178 100644
--- a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c
+++ b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c
@@ -170,6 +170,14 @@ int esp32s3_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ESP32S3_SPIFLASH
+  ret = board_spiflash_init();
+  if (ret)
+    {
+      syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n");
+    }
+#endif
+
 #ifdef CONFIG_ESP32S3_PARTITION_TABLE
   ret = esp32s3_partition_init();
   if (ret < 0)
@@ -319,14 +327,6 @@ int esp32s3_bringup(void)
     }
 #endif
 
-#ifdef CONFIG_ESP32S3_SPIFLASH
-  ret = board_spiflash_init();
-  if (ret)
-    {
-      syslog(LOG_ERR, "ERROR: Failed to initialize SPI Flash\n");
-    }
-#endif
-
 #ifdef CONFIG_ESP32S3_WIRELESS
 
 #ifdef CONFIG_ESP32S3_WIFI_BT_COEXIST

Reply via email to