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