1 /*
2  * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stddef.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdbool.h>
11 #include <sys/lock.h>
12 
13 #include "soc/rtc.h"
14 #include "esp_err.h"
15 #include "esp_phy_init.h"
16 #include "esp_system.h"
17 #include "esp_timer.h"
18 #include "esp_log.h"
19 #ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
20 #include "nvs.h"
21 #include "nvs_flash.h"
22 #endif
23 #include "esp_efuse.h"
24 #include "sdkconfig.h"
25 #include "phy.h"
26 #include "phy_init_data.h"
27 #include "esp_coexist_internal.h"
28 #include "driver/periph_ctrl.h"
29 #include "esp_private/wifi.h"
30 #include "esp_rom_crc.h"
31 #include "esp_rom_sys.h"
32 
33 #if defined(__ZEPHYR__)
34 #include <zephyr/kernel.h>
35 #include <zephyr/logging/log.h>
36 #include "stubs.h"
37 #endif
38 
39 #include "soc/rtc_cntl_reg.h"
40 #if CONFIG_IDF_TARGET_ESP32C3
41 #include "soc/syscon_reg.h"
42 #elif CONFIG_IDF_TARGET_ESP32S3
43 #include "soc/syscon_reg.h"
44 #endif
45 
46 #if CONFIG_IDF_TARGET_ESP32
47 wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb;
48 #endif
49 
50 static const char* TAG = "phy_init";
51 
52 K_MUTEX_DEFINE(s_phy_access_lock);
53 
54 static DRAM_ATTR struct {
55     int     count;  /* power on count of wifi and bt power domain */
56     struct k_mutex lock;
57 } s_wifi_bt_pd_controller = { .count = 0 };
58 
59 /* Indicate PHY is calibrated or not */
60 static bool s_is_phy_calibrated = false;
61 
62 /* Reference count of enabling PHY */
63 static uint8_t s_phy_access_ref = 0;
64 
65 #if CONFIG_MAC_BB_PD
66 /* Reference of powering down MAC and BB */
67 static bool s_mac_bb_pu = true;
68 #endif
69 
70 #if CONFIG_IDF_TARGET_ESP32
71 /* time stamp updated when the PHY/RF is turned on */
72 static int64_t s_phy_rf_en_ts = 0;
73 #endif
74 
75 /* PHY spinlock for libphy.a */
76 /* PHY spinlock for libphy.a */
77 static DRAM_ATTR int s_phy_int_mux;
78 static DRAM_ATTR int s_phy_lock_nest = 0;
79 
80 /* Memory to store PHY digital registers */
81 static uint32_t* s_phy_digital_regs_mem = NULL;
82 
83 #if CONFIG_MAC_BB_PD
84 uint32_t* s_mac_bb_pd_mem = NULL;
85 #endif
86 
87 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN
88 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED
89 extern uint8_t multi_phy_init_data_bin_start[] asm("_binary_phy_multiple_init_data_bin_start");
90 extern uint8_t multi_phy_init_data_bin_end[]   asm("_binary_phy_multiple_init_data_bin_end");
91 #endif
92 /* The following static variables are only used by Wi-Fi tasks, so they can be handled without lock */
93 static phy_init_data_type_t s_phy_init_data_type = 0;
94 
95 static phy_init_data_type_t s_current_apply_phy_init_data = 0;
96 
97 static char s_phy_current_country[PHY_COUNTRY_CODE_LEN] = {0};
98 
99 /* Whether it is a new bin */
100 static bool s_multiple_phy_init_data_bin = false;
101 
102 /* PHY init data type array */
103 static char* s_phy_type[ESP_PHY_INIT_DATA_TYPE_NUMBER] = {"DEFAULT", "SRRC", "FCC", "CE", "NCC", "KCC", "MIC", "IC",
104     "ACMA", "ANATEL", "ISED", "WPC", "OFCA", "IFETEL", "RCM"};
105 
106 /* Country and PHY init data type map */
107 static phy_country_to_bin_type_t s_country_code_map_type_table[] = {
108     {"AT",  ESP_PHY_INIT_DATA_TYPE_CE},
109     {"AU",  ESP_PHY_INIT_DATA_TYPE_ACMA},
110     {"BE",  ESP_PHY_INIT_DATA_TYPE_CE},
111     {"BG",  ESP_PHY_INIT_DATA_TYPE_CE},
112     {"BR",  ESP_PHY_INIT_DATA_TYPE_ANATEL},
113     {"CA",  ESP_PHY_INIT_DATA_TYPE_ISED},
114     {"CH",  ESP_PHY_INIT_DATA_TYPE_CE},
115     {"CN",  ESP_PHY_INIT_DATA_TYPE_SRRC},
116     {"CY",  ESP_PHY_INIT_DATA_TYPE_CE},
117     {"CZ",  ESP_PHY_INIT_DATA_TYPE_CE},
118     {"DE",  ESP_PHY_INIT_DATA_TYPE_CE},
119     {"DK",  ESP_PHY_INIT_DATA_TYPE_CE},
120     {"EE",  ESP_PHY_INIT_DATA_TYPE_CE},
121     {"ES",  ESP_PHY_INIT_DATA_TYPE_CE},
122     {"FI",  ESP_PHY_INIT_DATA_TYPE_CE},
123     {"FR",  ESP_PHY_INIT_DATA_TYPE_CE},
124     {"GB",  ESP_PHY_INIT_DATA_TYPE_CE},
125     {"GR",  ESP_PHY_INIT_DATA_TYPE_CE},
126     {"HK",  ESP_PHY_INIT_DATA_TYPE_OFCA},
127     {"HR",  ESP_PHY_INIT_DATA_TYPE_CE},
128     {"HU",  ESP_PHY_INIT_DATA_TYPE_CE},
129     {"IE",  ESP_PHY_INIT_DATA_TYPE_CE},
130     {"IN",  ESP_PHY_INIT_DATA_TYPE_WPC},
131     {"IS",  ESP_PHY_INIT_DATA_TYPE_CE},
132     {"IT",  ESP_PHY_INIT_DATA_TYPE_CE},
133     {"JP",  ESP_PHY_INIT_DATA_TYPE_MIC},
134     {"KR",  ESP_PHY_INIT_DATA_TYPE_KCC},
135     {"LI",  ESP_PHY_INIT_DATA_TYPE_CE},
136     {"LT",  ESP_PHY_INIT_DATA_TYPE_CE},
137     {"LU",  ESP_PHY_INIT_DATA_TYPE_CE},
138     {"LV",  ESP_PHY_INIT_DATA_TYPE_CE},
139     {"MT",  ESP_PHY_INIT_DATA_TYPE_CE},
140     {"MX",  ESP_PHY_INIT_DATA_TYPE_IFETEL},
141     {"NL",  ESP_PHY_INIT_DATA_TYPE_CE},
142     {"NO",  ESP_PHY_INIT_DATA_TYPE_CE},
143     {"NZ",  ESP_PHY_INIT_DATA_TYPE_RCM},
144     {"PL",  ESP_PHY_INIT_DATA_TYPE_CE},
145     {"PT",  ESP_PHY_INIT_DATA_TYPE_CE},
146     {"RO",  ESP_PHY_INIT_DATA_TYPE_CE},
147     {"SE",  ESP_PHY_INIT_DATA_TYPE_CE},
148     {"SI",  ESP_PHY_INIT_DATA_TYPE_CE},
149     {"SK",  ESP_PHY_INIT_DATA_TYPE_CE},
150     {"TW",  ESP_PHY_INIT_DATA_TYPE_NCC},
151     {"US",  ESP_PHY_INIT_DATA_TYPE_FCC},
152 };
153 #endif
phy_enter_critical(void)154 uint32_t IRAM_ATTR phy_enter_critical(void)
155 {
156     if(s_phy_lock_nest == 0) {
157         s_phy_int_mux = irq_lock();
158     }
159 
160     if(s_phy_lock_nest < 0xFFFFFFFF) {
161         s_phy_lock_nest++;
162     }
163 
164     // Interrupt level will be stored in current tcb, so always return zero.
165     return 0;
166 }
167 
phy_exit_critical(uint32_t level)168 void IRAM_ATTR phy_exit_critical(uint32_t level)
169 {
170     if(s_phy_lock_nest > 0) {
171         s_phy_lock_nest--;
172     }
173 
174     if(s_phy_lock_nest == 0) {
175         // Param level don't need any more, ignore it.
176         irq_unlock(s_phy_int_mux);
177     }
178 }
179 
180 #if CONFIG_IDF_TARGET_ESP32
esp_phy_rf_get_on_ts(void)181 int64_t esp_phy_rf_get_on_ts(void)
182 {
183     return s_phy_rf_en_ts;
184 }
185 
phy_update_wifi_mac_time(bool en_clock_stopped,int64_t now)186 static inline void phy_update_wifi_mac_time(bool en_clock_stopped, int64_t now)
187 {
188     static uint32_t s_common_clock_disable_time = 0;
189 
190     if (en_clock_stopped) {
191         s_common_clock_disable_time = (uint32_t)now;
192     } else {
193         if (s_common_clock_disable_time) {
194             uint32_t diff = (uint64_t)now - s_common_clock_disable_time;
195 
196             if (s_wifi_mac_time_update_cb) {
197                 s_wifi_mac_time_update_cb(diff);
198             }
199             s_common_clock_disable_time = 0;
200         }
201     }
202 }
203 #endif
204 
esp_phy_common_clock_enable(void)205 IRAM_ATTR void esp_phy_common_clock_enable(void)
206 {
207     wifi_bt_common_module_enable();
208 }
209 
esp_phy_common_clock_disable(void)210 IRAM_ATTR void esp_phy_common_clock_disable(void)
211 {
212     wifi_bt_common_module_disable();
213 }
214 
phy_digital_regs_store(void)215 static inline void phy_digital_regs_store(void)
216 {
217     if (s_phy_digital_regs_mem == NULL) {
218         s_phy_digital_regs_mem = (uint32_t *)k_malloc(SOC_PHY_DIG_REGS_MEM_SIZE);
219     }
220 
221     if (s_phy_digital_regs_mem != NULL) {
222         phy_dig_reg_backup(true, s_phy_digital_regs_mem);
223     }
224 }
225 
phy_digital_regs_load(void)226 static inline void phy_digital_regs_load(void)
227 {
228     if (s_phy_digital_regs_mem != NULL) {
229         phy_dig_reg_backup(false, s_phy_digital_regs_mem);
230     }
231 }
232 
esp_phy_enable(void)233 void esp_phy_enable(void)
234 {
235     k_mutex_lock(&s_phy_access_lock, K_FOREVER);
236 
237     if (s_phy_access_ref == 0) {
238 #if CONFIG_IDF_TARGET_ESP32
239         // Update time stamp
240         s_phy_rf_en_ts = esp_timer_get_time();
241         // Update WiFi MAC time before WiFi/BT common clock is enabled
242         phy_update_wifi_mac_time(false, s_phy_rf_en_ts);
243 #endif
244         esp_phy_common_clock_enable();
245 
246         if (s_is_phy_calibrated == false) {
247             esp_phy_load_cal_and_init();
248             s_is_phy_calibrated = true;
249         }
250         else {
251             phy_wakeup_init();
252             phy_digital_regs_load();
253         }
254 
255 #if CONFIG_IDF_TARGET_ESP32
256         coex_bt_high_prio();
257 #endif
258 
259 #if CONFIG_BT_ENABLED && (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3)
260     extern void coex_pti_v2(void);
261     coex_pti_v2();
262 #endif
263 
264     }
265     s_phy_access_ref++;
266 
267     k_mutex_unlock(&s_phy_access_lock);
268 }
269 
esp_phy_disable(void)270 void esp_phy_disable(void)
271 {
272     k_mutex_lock(&s_phy_access_lock, K_FOREVER);
273 
274     s_phy_access_ref--;
275     if (s_phy_access_ref == 0) {
276         phy_digital_regs_store();
277         // Disable PHY and RF.
278         phy_close_rf();
279 #if !CONFIG_IDF_TARGET_ESP32
280         // Disable PHY temperature sensor
281         phy_xpd_tsens();
282 #endif
283 #if CONFIG_IDF_TARGET_ESP32
284         // Update WiFi MAC time before disalbe WiFi/BT common peripheral clock
285         phy_update_wifi_mac_time(true, esp_timer_get_time());
286 #endif
287         // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG
288         esp_phy_common_clock_disable();
289     }
290 
291     k_mutex_unlock(&s_phy_access_lock);
292 }
293 
esp_wifi_bt_power_domain_on(void)294 void IRAM_ATTR esp_wifi_bt_power_domain_on(void)
295 {
296     k_mutex_lock(&s_wifi_bt_pd_controller.lock, K_FOREVER);
297     if (s_wifi_bt_pd_controller.count++ == 0) {
298         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
299 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
300         SET_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, SYSTEM_BB_RST | SYSTEM_FE_RST);
301         CLEAR_PERI_REG_MASK(SYSCON_WIFI_RST_EN_REG, SYSTEM_BB_RST | SYSTEM_FE_RST);
302 #endif
303         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
304     }
305     k_mutex_unlock(&s_wifi_bt_pd_controller.lock);
306 }
307 
esp_wifi_bt_power_domain_off(void)308 void esp_wifi_bt_power_domain_off(void)
309 {
310     k_mutex_lock(&s_wifi_bt_pd_controller.lock, K_FOREVER);
311     if (--s_wifi_bt_pd_controller.count == 0) {
312         SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_ISO);
313         SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
314     }
315     k_mutex_unlock(&s_wifi_bt_pd_controller.lock);
316 }
317 
318 #if CONFIG_MAC_BB_PD
esp_mac_bb_pd_mem_init(void)319 void esp_mac_bb_pd_mem_init(void)
320 {
321     k_mutex_lock(&s_phy_access_lock, K_FOREVER);
322 
323     if (s_mac_bb_pd_mem == NULL) {
324         s_mac_bb_pd_mem = (uint32_t *)k_malloc(SOC_MAC_BB_PD_MEM_SIZE);
325     }
326 
327     k_mutex_unlock(&s_phy_access_lock);
328 }
329 
esp_mac_bb_power_up(void)330 IRAM_ATTR void esp_mac_bb_power_up(void)
331 {
332     if (s_mac_bb_pd_mem == NULL) {
333         return;
334     }
335     esp_wifi_bt_power_domain_on();
336     if (!s_mac_bb_pu) {
337         esp_phy_common_clock_enable();
338         phy_freq_mem_backup(false, s_mac_bb_pd_mem);
339         esp_phy_common_clock_disable();
340         s_mac_bb_pu = true;
341     }
342 }
343 
esp_mac_bb_power_down(void)344 IRAM_ATTR void esp_mac_bb_power_down(void)
345 {
346     if (s_mac_bb_pd_mem == NULL) {
347         return;
348     }
349     if (s_mac_bb_pu) {
350         esp_phy_common_clock_enable();
351         phy_freq_mem_backup(true, s_mac_bb_pd_mem);
352         esp_phy_common_clock_disable();
353         s_mac_bb_pu = false;
354     }
355     esp_wifi_bt_power_domain_off();
356 }
357 #endif
358 
359 // PHY init data handling functions
360 #if CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION
361 #include "esp_partition.h"
362 
esp_phy_get_init_data(void)363 const esp_phy_init_data_t* esp_phy_get_init_data(void)
364 {
365     esp_err_t err = ESP_OK;
366     const esp_partition_t* partition = NULL;
367 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED
368     size_t init_data_store_length = sizeof(phy_init_magic_pre) +
369             sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
370     uint8_t* init_data_store = (uint8_t*) k_malloc(init_data_store_length);
371     if (init_data_store == NULL) {
372         ESP_LOGE(TAG, "failed to allocate memory for updated country code PHY init data");
373         return NULL;
374     }
375     memcpy(init_data_store, multi_phy_init_data_bin_start, init_data_store_length);
376     ESP_LOGI(TAG, "loading embedded multiple PHY init data");
377 #else
378     partition = esp_partition_find_first(
379             ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
380     if (partition == NULL) {
381         ESP_LOGE(TAG, "PHY data partition not found");
382         return NULL;
383     }
384     ESP_LOGD(TAG, "loading PHY init data from partition at offset 0x%x", partition->address);
385     size_t init_data_store_length = sizeof(phy_init_magic_pre) +
386             sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
387     uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
388     if (init_data_store == NULL) {
389         ESP_LOGE(TAG, "failed to allocate memory for PHY init data");
390         return NULL;
391     }
392     // read phy data from flash
393     err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
394     if (err != ESP_OK) {
395         ESP_LOGE(TAG, "failed to read PHY data partition (0x%x)", err);
396         free(init_data_store);
397         return NULL;
398     }
399 #endif
400     // verify data
401     if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
402         memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
403                 PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
404 #ifndef CONFIG_ESP_PHY_DEFAULT_INIT_IF_INVALID
405         ESP_LOGE(TAG, "failed to validate PHY data partition");
406         k_free(init_data_store);
407         return NULL;
408 #else
409         ESP_LOGE(TAG, "failed to validate PHY data partition, restoring default data into flash...");
410 
411         memcpy(init_data_store,
412                PHY_INIT_MAGIC, sizeof(phy_init_magic_pre));
413         memcpy(init_data_store + sizeof(phy_init_magic_pre),
414                &phy_init_data, sizeof(phy_init_data));
415         memcpy(init_data_store + sizeof(phy_init_magic_pre) + sizeof(phy_init_data),
416                PHY_INIT_MAGIC, sizeof(phy_init_magic_post));
417 
418         assert(memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) == 0);
419         assert(memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
420                       PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) == 0);
421 
422         // write default data
423         err = esp_partition_write(partition, 0, init_data_store, init_data_store_length);
424         if (err != ESP_OK) {
425             ESP_LOGE(TAG, "failed to write default PHY data partition (0x%x)", err);
426             free(init_data_store);
427             return NULL;
428         }
429 #endif // CONFIG_ESP_PHY_DEFAULT_INIT_IF_INVALID
430     }
431 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN
432     if ((*(init_data_store + (sizeof(phy_init_magic_pre) + PHY_SUPPORT_MULTIPLE_BIN_OFFSET)))) {
433         s_multiple_phy_init_data_bin = true;
434         ESP_LOGI(TAG, "Support multiple PHY init data bins");
435     } else {
436         ESP_LOGW(TAG, "Does not support multiple PHY init data bins");
437     }
438 #endif
439     ESP_LOGD(TAG, "PHY data partition validated");
440     return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre));
441 }
442 
esp_phy_release_init_data(const esp_phy_init_data_t * init_data)443 void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
444 {
445     free((uint8_t*) init_data - sizeof(phy_init_magic_pre));
446 }
447 
448 #else // CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION
449 
450 // phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data
451 
esp_phy_get_init_data(void)452 const esp_phy_init_data_t* esp_phy_get_init_data(void)
453 {
454     ESP_LOGD(TAG, "loading PHY init data from application binary");
455     return &phy_init_data;
456 }
457 
esp_phy_release_init_data(const esp_phy_init_data_t * init_data)458 void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
459 {
460     // no-op
461 }
462 #endif // CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION
463 
464 
465 #ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
466 // PHY calibration data handling functions
467 static const char* PHY_NAMESPACE = "phy";
468 static const char* PHY_CAL_VERSION_KEY = "cal_version";
469 static const char* PHY_CAL_MAC_KEY = "cal_mac";
470 static const char* PHY_CAL_DATA_KEY = "cal_data";
471 
472 static esp_err_t load_cal_data_from_nvs_handle(nvs_handle_t handle,
473         esp_phy_calibration_data_t* out_cal_data);
474 
475 static esp_err_t store_cal_data_to_nvs_handle(nvs_handle_t handle,
476         const esp_phy_calibration_data_t* cal_data);
477 
esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t * out_cal_data)478 esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data)
479 {
480     nvs_handle_t handle;
481     esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle);
482     if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
483         ESP_LOGE(TAG, "%s: NVS has not been initialized. "
484                 "Call nvs_flash_init before starting WiFi/BT.", __func__);
485         return err;
486     } else if (err != ESP_OK) {
487         ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
488         return err;
489     }
490     err = load_cal_data_from_nvs_handle(handle, out_cal_data);
491     nvs_close(handle);
492     return err;
493 }
494 
esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t * cal_data)495 esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data)
496 {
497     nvs_handle_t handle;
498     esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle);
499     if (err != ESP_OK) {
500         ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
501         return err;
502     }
503     else {
504         err = store_cal_data_to_nvs_handle(handle, cal_data);
505         nvs_close(handle);
506         return err;
507     }
508 }
509 
esp_phy_erase_cal_data_in_nvs(void)510 esp_err_t esp_phy_erase_cal_data_in_nvs(void)
511 {
512     nvs_handle_t handle;
513     esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle);
514     if (err != ESP_OK) {
515         ESP_LOGE(TAG, "%s: failed to open NVS phy namespace (0x%x)", __func__, err);
516         return err;
517     }
518     else {
519         err = nvs_erase_all(handle);
520         if (err != ESP_OK) {
521             ESP_LOGE(TAG, "%s: failed to erase NVS phy namespace (0x%x)", __func__, err);
522         }
523         else {
524             err = nvs_commit(handle);
525             if (err != ESP_OK) {
526                 ESP_LOGE(TAG, "%s: failed to commit NVS phy namespace (0x%x)", __func__, err);
527             }
528         }
529     }
530     nvs_close(handle);
531     return err;
532 }
533 
load_cal_data_from_nvs_handle(nvs_handle_t handle,esp_phy_calibration_data_t * out_cal_data)534 static esp_err_t load_cal_data_from_nvs_handle(nvs_handle_t handle,
535         esp_phy_calibration_data_t* out_cal_data)
536 {
537     esp_err_t err;
538     uint32_t cal_data_version;
539 
540     err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version);
541     if (err != ESP_OK) {
542         ESP_LOGD(TAG, "%s: failed to get cal_version (0x%x)", __func__, err);
543         return err;
544     }
545     uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
546     ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
547     if (cal_data_version != cal_format_version) {
548         ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d",
549                 __func__, cal_format_version, cal_data_version);
550         return ESP_FAIL;
551     }
552     uint8_t cal_data_mac[6];
553     size_t length = sizeof(cal_data_mac);
554     err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length);
555     if (err != ESP_OK) {
556         ESP_LOGD(TAG, "%s: failed to get cal_mac (0x%x)", __func__, err);
557         return err;
558     }
559     if (length != sizeof(cal_data_mac)) {
560         ESP_LOGD(TAG, "%s: invalid length of cal_mac (%d)", __func__, length);
561         return ESP_ERR_INVALID_SIZE;
562     }
563     uint8_t sta_mac[6];
564     esp_efuse_mac_get_default(sta_mac);
565     if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) {
566         ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \
567                 MACSTR ", found " MACSTR,
568                 __func__, MAC2STR(sta_mac), MAC2STR(cal_data_mac));
569         return ESP_FAIL;
570     }
571     length = sizeof(*out_cal_data);
572     err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length);
573     if (err != ESP_OK) {
574         ESP_LOGE(TAG, "%s: failed to get cal_data(0x%x)", __func__, err);
575         return err;
576     }
577     if (length != sizeof(*out_cal_data)) {
578         ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length);
579         return ESP_ERR_INVALID_SIZE;
580     }
581     return ESP_OK;
582 }
583 
store_cal_data_to_nvs_handle(nvs_handle_t handle,const esp_phy_calibration_data_t * cal_data)584 static esp_err_t store_cal_data_to_nvs_handle(nvs_handle_t handle,
585         const esp_phy_calibration_data_t* cal_data)
586 {
587     esp_err_t err;
588 
589     err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
590     if (err != ESP_OK) {
591         ESP_LOGE(TAG, "%s: store calibration data failed(0x%x)\n", __func__, err);
592         return err;
593     }
594 
595     uint8_t sta_mac[6];
596     esp_efuse_mac_get_default(sta_mac);
597     err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
598     if (err != ESP_OK) {
599         ESP_LOGE(TAG, "%s: store calibration mac failed(0x%x)\n", __func__, err);
600         return err;
601     }
602 
603     uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
604     ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
605     err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
606     if (err != ESP_OK) {
607         ESP_LOGE(TAG, "%s: store calibration version failed(0x%x)\n", __func__, err);
608         return err;
609     }
610 
611     err = nvs_commit(handle);
612     if (err != ESP_OK) {
613         ESP_LOGE(TAG, "%s: store calibration nvs commit failed(0x%x)\n", __func__, err);
614     }
615 
616     return err;
617 }
618 
619 #endif /* CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE */
620 
621 #if CONFIG_ESP_PHY_REDUCE_TX_POWER
622 // TODO: fix the esp_phy_reduce_tx_power unused warning for esp32s2 - IDF-759
esp_phy_reduce_tx_power(esp_phy_init_data_t * init_data)623 static void __attribute((unused)) esp_phy_reduce_tx_power(esp_phy_init_data_t* init_data)
624 {
625     uint8_t i;
626 
627     for(i = 0; i < PHY_TX_POWER_NUM; i++) {
628         // LOWEST_PHY_TX_POWER is the lowest tx power
629         init_data->params[PHY_TX_POWER_OFFSET+i] = PHY_TX_POWER_LOWEST;
630     }
631 }
632 #endif
633 
esp_phy_load_cal_and_init(void)634 void esp_phy_load_cal_and_init(void)
635 {
636     char * phy_version = get_phy_version_str();
637     ESP_LOGI(TAG, "phy_version %s", phy_version);
638 
639     k_mutex_init(&s_wifi_bt_pd_controller.lock);
640 
641 // TODO: support efuse on Zephyr
642 // #if CONFIG_IDF_TARGET_ESP32S2
643     // phy_eco_version_sel(esp_efuse_get_chip_ver());
644 // #endif
645     esp_phy_calibration_data_t* cal_data =
646             (esp_phy_calibration_data_t*) k_calloc(sizeof(esp_phy_calibration_data_t), 1);
647     if (cal_data == NULL) {
648         ESP_LOGE(TAG, "failed to allocate memory for RF calibration data");
649         abort();
650     }
651 
652 #if CONFIG_ESP_PHY_REDUCE_TX_POWER
653     const esp_phy_init_data_t* phy_init_data = esp_phy_get_init_data();
654     if (phy_init_data == NULL) {
655         ESP_LOGE(TAG, "failed to obtain PHY init data");
656         abort();
657     }
658 
659     esp_phy_init_data_t* init_data = (esp_phy_init_data_t*) k_malloc(sizeof(esp_phy_init_data_t));
660     if (init_data == NULL) {
661         ESP_LOGE(TAG, "failed to allocate memory for phy init data");
662         abort();
663     }
664 
665     memcpy(init_data, phy_init_data, sizeof(esp_phy_init_data_t));
666     if (esp_reset_reason() == ESP_RST_BROWNOUT) {
667         esp_phy_reduce_tx_power(init_data);
668     }
669 #else
670     const esp_phy_init_data_t* init_data = esp_phy_get_init_data();
671     if (init_data == NULL) {
672         ESP_LOGE(TAG, "failed to obtain PHY init data");
673         abort();
674     }
675 #endif
676 
677 #if CONFIG_SOC_SERIES_ESP32S3 || CONFIG_SOC_SERIES_ESP32C3
678     phy_bbpll_en_usb(true);
679 #endif
680 
681 #ifdef CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE
682     esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
683     uint8_t sta_mac[6];
684     if (esp_rom_get_reset_reason(0) == RESET_REASON_CORE_DEEP_SLEEP) {
685         calibration_mode = PHY_RF_CAL_NONE;
686     }
687     esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data);
688     if (err != ESP_OK) {
689         ESP_LOGW(TAG, "failed to load RF calibration data (0x%x), falling back to full calibration", err);
690         calibration_mode = PHY_RF_CAL_FULL;
691     }
692 
693     esp_efuse_mac_get_default(sta_mac);
694     memcpy(cal_data->mac, sta_mac, 6);
695     esp_err_t ret = register_chipv7_phy(init_data, cal_data, calibration_mode);
696     if (ret == ESP_CAL_DATA_CHECK_FAIL) {
697         ESP_LOGW(TAG, "saving new calibration data because of checksum failure, mode(%d)", calibration_mode);
698     }
699 
700     if ((calibration_mode != PHY_RF_CAL_NONE && err != ESP_OK) ||
701             (calibration_mode != PHY_RF_CAL_FULL && ret == ESP_CAL_DATA_CHECK_FAIL)) {
702         err = esp_phy_store_cal_data_to_nvs(cal_data);
703     } else {
704         err = ESP_OK;
705     }
706 #else
707     register_chipv7_phy(init_data, cal_data, PHY_RF_CAL_FULL);
708 #endif
709 
710 #if CONFIG_ESP_PHY_REDUCE_TX_POWER
711     esp_phy_release_init_data(phy_init_data);
712     k_free(init_data);
713 #else
714     esp_phy_release_init_data(init_data);
715 #endif
716 
717     k_free(cal_data); // PHY maintains a copy of calibration data, so we can free this
718 }
719 
720 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN
phy_crc_check_init_data(uint8_t * init_data,const uint8_t * checksum,size_t init_data_length)721 static esp_err_t phy_crc_check_init_data(uint8_t* init_data, const uint8_t* checksum, size_t init_data_length)
722 {
723     uint32_t crc_data = 0;
724     crc_data = esp_rom_crc32_le(crc_data, init_data, init_data_length);
725     uint32_t crc_size_conversion = htonl(crc_data);
726 
727     if (crc_size_conversion != *(uint32_t*)(checksum)) {
728         return ESP_FAIL;
729     }
730     return ESP_OK;
731 }
732 
phy_find_bin_type_according_country(const char * country)733 static uint8_t phy_find_bin_type_according_country(const char* country)
734 {
735     uint32_t i = 0;
736     uint8_t phy_init_data_type = 0;
737 
738     for (i = 0; i < sizeof(s_country_code_map_type_table)/sizeof(phy_country_to_bin_type_t); i++)
739     {
740         if (!memcmp(country, s_country_code_map_type_table[i].cc, sizeof(s_phy_current_country))) {
741             phy_init_data_type = s_country_code_map_type_table[i].type;
742             ESP_LOGD(TAG, "Current country is %c%c, PHY init data type is %s\n", s_country_code_map_type_table[i].cc[0],
743                     s_country_code_map_type_table[i].cc[1], s_phy_type[s_country_code_map_type_table[i].type]);
744             break;
745         }
746     }
747 
748     if (i == sizeof(s_country_code_map_type_table)/sizeof(phy_country_to_bin_type_t)) {
749         phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
750         ESP_LOGW(TAG, "Use the default certification code beacuse %c%c doesn't have a certificate", country[0], country[1]);
751     }
752 
753     return phy_init_data_type;
754 }
755 
phy_find_bin_data_according_type(uint8_t * out_init_data_store,const phy_control_info_data_t * init_data_control_info,const uint8_t * init_data_multiple,phy_init_data_type_t init_data_type)756 static esp_err_t phy_find_bin_data_according_type(uint8_t* out_init_data_store,
757         const phy_control_info_data_t* init_data_control_info,
758         const uint8_t* init_data_multiple,
759         phy_init_data_type_t init_data_type)
760 {
761       int i = 0;
762       for (i = 0; i < init_data_control_info->number; i++) {
763           if (init_data_type == *(init_data_multiple + (i * sizeof(esp_phy_init_data_t)) + PHY_INIT_DATA_TYPE_OFFSET)) {
764               memcpy(out_init_data_store + sizeof(phy_init_magic_pre),
765                       init_data_multiple + (i * sizeof(esp_phy_init_data_t)), sizeof(esp_phy_init_data_t));
766               break;
767           }
768       }
769 
770       if (i == init_data_control_info->number) {
771           return ESP_FAIL;
772       }
773       return ESP_OK;
774 }
775 
phy_get_multiple_init_data(const esp_partition_t * partition,uint8_t * init_data_store,size_t init_data_store_length,phy_init_data_type_t init_data_type)776 static esp_err_t phy_get_multiple_init_data(const esp_partition_t* partition,
777         uint8_t* init_data_store,
778         size_t init_data_store_length,
779         phy_init_data_type_t init_data_type)
780 {
781     phy_control_info_data_t* init_data_control_info = (phy_control_info_data_t*) k_malloc(sizeof(phy_control_info_data_t));
782     if (init_data_control_info == NULL) {
783         ESP_LOGE(TAG, "failed to allocate memory for PHY init data control info");
784         return ESP_FAIL;
785     }
786     esp_err_t err = ESP_OK;
787 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED
788     memcpy(init_data_control_info, multi_phy_init_data_bin_start + init_data_store_length, sizeof(phy_control_info_data_t));
789 #else
790     err = esp_partition_read(partition, init_data_store_length, init_data_control_info, sizeof(phy_control_info_data_t));
791     if (err != ESP_OK) {
792         k_free(init_data_control_info);
793         ESP_LOGE(TAG, "failed to read PHY control info data partition (0x%x)", err);
794         return ESP_FAIL;
795     }
796 #endif
797     if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
798         err =  phy_crc_check_init_data(init_data_control_info->multiple_bin_checksum, init_data_control_info->control_info_checksum,
799                 sizeof(phy_control_info_data_t) - sizeof(init_data_control_info->control_info_checksum));
800         if (err != ESP_OK) {
801             k_free(init_data_control_info);
802             ESP_LOGE(TAG, "PHY init data control info check error");
803             return ESP_FAIL;
804         }
805     } else {
806         k_free(init_data_control_info);
807         ESP_LOGE(TAG, "Check algorithm not CRC, PHY init data update failed");
808         return ESP_FAIL;
809     }
810 
811     uint8_t* init_data_multiple = (uint8_t*) k_malloc(sizeof(esp_phy_init_data_t) * init_data_control_info->number);
812     if (init_data_multiple == NULL) {
813         k_free(init_data_control_info);
814         ESP_LOGE(TAG, "failed to allocate memory for PHY init data multiple bin");
815         return ESP_FAIL;
816     }
817 
818 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED
819     memcpy(init_data_multiple, multi_phy_init_data_bin_start + init_data_store_length + sizeof(phy_control_info_data_t), sizeof(esp_phy_init_data_t) * init_data_control_info->number);
820 #else
821     err = esp_partition_read(partition, init_data_store_length + sizeof(phy_control_info_data_t),
822             init_data_multiple, sizeof(esp_phy_init_data_t) * init_data_control_info->number);
823     if (err != ESP_OK) {
824         k_free(init_data_multiple);
825         k_free(init_data_control_info);
826         ESP_LOGE(TAG, "failed to read PHY init data multiple bin partition (0x%x)", err);
827         return ESP_FAIL;
828     }
829 #endif
830     if ((init_data_control_info->check_algorithm) == PHY_CRC_ALGORITHM) {
831         err = phy_crc_check_init_data(init_data_multiple, init_data_control_info->multiple_bin_checksum,
832                 sizeof(esp_phy_init_data_t) * init_data_control_info->number);
833         if (err != ESP_OK) {
834             k_free(init_data_multiple);
835             k_free(init_data_control_info);
836             ESP_LOGE(TAG, "PHY init data multiple bin check error");
837             return ESP_FAIL;
838         }
839     } else {
840         k_free(init_data_multiple);
841         k_free(init_data_control_info);
842         ESP_LOGE(TAG, "Check algorithm not CRC, PHY init data update failed");
843         return ESP_FAIL;
844     }
845 
846     err = phy_find_bin_data_according_type(init_data_store, init_data_control_info, init_data_multiple, init_data_type);
847     if (err != ESP_OK) {
848         ESP_LOGW(TAG, "%s has not been certified, use DEFAULT PHY init data", s_phy_type[init_data_type]);
849         s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
850     } else {
851         s_phy_init_data_type = init_data_type;
852     }
853 
854     k_free(init_data_multiple);
855     k_free(init_data_control_info);
856     return ESP_OK;
857 }
858 
esp_phy_update_init_data(phy_init_data_type_t init_data_type)859 esp_err_t esp_phy_update_init_data(phy_init_data_type_t init_data_type)
860 {
861 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED
862     esp_err_t err = ESP_OK;
863     const esp_partition_t* partition = NULL;
864     size_t init_data_store_length = sizeof(phy_init_magic_pre) +
865         sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
866     uint8_t* init_data_store = (uint8_t*) k_malloc(init_data_store_length);
867     if (init_data_store == NULL) {
868         ESP_LOGE(TAG, "failed to allocate memory for updated country code PHY init data");
869         return ESP_ERR_NO_MEM;
870     }
871     memcpy(init_data_store, multi_phy_init_data_bin_start, init_data_store_length);
872     ESP_LOGI(TAG, "load embedded multi phy init data");
873 #else
874     const esp_partition_t* partition = esp_partition_find_first(
875           ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
876     if (partition == NULL) {
877         ESP_LOGE(TAG, "Updated country code PHY data partition not found");
878         return ESP_FAIL;
879     }
880     size_t init_data_store_length = sizeof(phy_init_magic_pre) +
881         sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
882     uint8_t* init_data_store = (uint8_t*) k_malloc(init_data_store_length);
883     if (init_data_store == NULL) {
884         ESP_LOGE(TAG, "failed to allocate memory for updated country code PHY init data");
885         return ESP_ERR_NO_MEM;
886     }
887 
888     esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
889     if (err != ESP_OK) {
890         k_free(init_data_store);
891         ESP_LOGE(TAG, "failed to read updated country code PHY data partition (0x%x)", err);
892         return ESP_FAIL;
893     }
894 #endif
895     if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
896             memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
897                 PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
898         k_free(init_data_store);
899         ESP_LOGE(TAG, "failed to validate updated country code PHY data partition");
900         return ESP_FAIL;
901     }
902 
903     //find init data bin according init data type
904     if (init_data_type != ESP_PHY_INIT_DATA_TYPE_DEFAULT) {
905         err = phy_get_multiple_init_data(partition, init_data_store, init_data_store_length, init_data_type);
906         if (err != ESP_OK) {
907             k_free(init_data_store);
908 #if CONFIG_ESP_PHY_INIT_DATA_ERROR
909             abort();
910 #else
911             return ESP_FAIL;
912 #endif
913         }
914     } else {
915         s_phy_init_data_type = ESP_PHY_INIT_DATA_TYPE_DEFAULT;
916     }
917 
918     if (s_current_apply_phy_init_data != s_phy_init_data_type) {
919         err = esp_phy_apply_phy_init_data(init_data_store + sizeof(phy_init_magic_pre));
920         if (err != ESP_OK) {
921             ESP_LOGE(TAG, "PHY init data failed to load");
922             k_free(init_data_store);
923             return ESP_FAIL;
924         }
925 
926         ESP_LOGI(TAG, "PHY init data type updated from %s to %s",
927                 s_phy_type[s_current_apply_phy_init_data], s_phy_type[s_phy_init_data_type]);
928         s_current_apply_phy_init_data = s_phy_init_data_type;
929     }
930 
931     k_free(init_data_store);
932     return ESP_OK;
933 }
934 #endif
935 
esp_phy_update_country_info(const char * country)936 esp_err_t esp_phy_update_country_info(const char *country)
937 {
938 #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN
939     uint8_t phy_init_data_type_map = 0;
940 
941     if (!s_multiple_phy_init_data_bin) {
942         ESP_LOGD(TAG, "Does not support multiple PHY init data bins");
943         return ESP_FAIL;
944     }
945 
946    //if country equal s_phy_current_country, return;
947     if (!memcmp(country, s_phy_current_country, sizeof(s_phy_current_country))) {
948         return ESP_OK;
949     }
950 
951     memcpy(s_phy_current_country, country, sizeof(s_phy_current_country));
952 
953     phy_init_data_type_map = phy_find_bin_type_according_country(country);
954     if (phy_init_data_type_map == s_phy_init_data_type) {
955         return ESP_OK;
956     }
957 
958     esp_err_t err =  esp_phy_update_init_data(phy_init_data_type_map);
959     if (err != ESP_OK) {
960         return err;
961     }
962 #endif
963     return ESP_OK;
964 }
965 
966 void esp_wifi_power_domain_on(void) __attribute__((alias("esp_wifi_bt_power_domain_on")));
967 void esp_wifi_power_domain_off(void) __attribute__((alias("esp_wifi_bt_power_domain_off")));