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