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")));