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