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 "soc/soc_caps.h"
47 #include "esp32s2/rom/ets_sys.h"
48 #include "esp32s2/rom/rtc.h"
49 #elif CONFIG_IDF_TARGET_ESP32C3
50 #include "soc/soc_caps.h"
51 #include "soc/rtc_cntl_reg.h"
52 #include "soc/syscon_reg.h"
53 #elif CONFIG_IDF_TARGET_ESP32S3
54 #include "soc/rtc_cntl_reg.h"
55 #include "soc/syscon_reg.h"
56 #endif
57 
58 #include <zephyr/kernel.h>
59 #include <zephyr/logging/log.h>
60 #include <stddef.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <stdbool.h>
64 #include <sys/lock.h>
65 
66 #if CONFIG_IDF_TARGET_ESP32
67 /* Callback function to update WiFi MAC time */
68 wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb = NULL;
69 #endif
70 
71 static const char *TAG = "phy_init";
72 
73 K_MUTEX_DEFINE(s_phy_access_lock);
74 
75 /* Indicate PHY is calibrated or not */
76 static bool s_is_phy_calibrated = false;
77 
78 /* Reference count of enabling PHY */
79 static uint8_t s_phy_access_ref = 0;
80 
81 #if CONFIG_MAC_BB_PD
82 /* Reference of powering down MAC and BB */
83 static bool s_mac_bb_pu = true;
84 #endif
85 
86 #if CONFIG_IDF_TARGET_ESP32
87 /* time stamp updated when the PHY/RF is turned on */
88 static int64_t s_phy_rf_en_ts = 0;
89 #endif
90 
91 /* PHY spinlock for libphy.a */
92 static DRAM_ATTR int s_phy_int_mux;
93 static DRAM_ATTR int s_phy_lock_nest = 0;
94 
95 /* Memory to store PHY digital registers */
96 static uint32_t *s_phy_digital_regs_mem = NULL;
97 
98 #if CONFIG_MAC_BB_PD
99 uint32_t *s_mac_bb_pd_mem = NULL;
100 #endif
101 
102 #if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
103 /* The following static variables are only used by Wi-Fi tasks, so they can be handled without lock */
104 static phy_init_data_type_t s_phy_init_data_type = 0;
105 
106 static phy_init_data_type_t s_current_apply_phy_init_data = 0;
107 
108 static char s_phy_current_country[PHY_COUNTRY_CODE_LEN] = {0};
109 
110 /* Whether it is a new bin */
111 static bool s_multiple_phy_init_data_bin = false;
112 
113 /* PHY init data type array */
114 static char *s_phy_type[ESP_PHY_INIT_DATA_TYPE_NUMBER] = {"DEFAULT", "SRRC", "FCC", "CE", "NCC", "KCC", "MIC", "IC",
115 														  "ACMA", "ANATEL", "ISED", "WPC", "OFCA", "IFETEL", "RCM"};
116 
117 /* Country and PHY init data type map */
118 static phy_country_to_bin_type_t s_country_code_map_type_table[] = {
119 	{"AT", ESP_PHY_INIT_DATA_TYPE_CE},
120 	{"AU", ESP_PHY_INIT_DATA_TYPE_ACMA},
121 	{"BE", ESP_PHY_INIT_DATA_TYPE_CE},
122 	{"BG", ESP_PHY_INIT_DATA_TYPE_CE},
123 	{"BR", ESP_PHY_INIT_DATA_TYPE_ANATEL},
124 	{"CA", ESP_PHY_INIT_DATA_TYPE_ISED},
125 	{"CH", ESP_PHY_INIT_DATA_TYPE_CE},
126 	{"CN", ESP_PHY_INIT_DATA_TYPE_SRRC},
127 	{"CY", ESP_PHY_INIT_DATA_TYPE_CE},
128 	{"CZ", ESP_PHY_INIT_DATA_TYPE_CE},
129 	{"DE", ESP_PHY_INIT_DATA_TYPE_CE},
130 	{"DK", ESP_PHY_INIT_DATA_TYPE_CE},
131 	{"EE", ESP_PHY_INIT_DATA_TYPE_CE},
132 	{"ES", ESP_PHY_INIT_DATA_TYPE_CE},
133 	{"FI", ESP_PHY_INIT_DATA_TYPE_CE},
134 	{"FR", ESP_PHY_INIT_DATA_TYPE_CE},
135 	{"GB", ESP_PHY_INIT_DATA_TYPE_CE},
136 	{"GR", ESP_PHY_INIT_DATA_TYPE_CE},
137 	{"HK", ESP_PHY_INIT_DATA_TYPE_OFCA},
138 	{"HR", ESP_PHY_INIT_DATA_TYPE_CE},
139 	{"HU", ESP_PHY_INIT_DATA_TYPE_CE},
140 	{"IE", ESP_PHY_INIT_DATA_TYPE_CE},
141 	{"IN", ESP_PHY_INIT_DATA_TYPE_WPC},
142 	{"IS", ESP_PHY_INIT_DATA_TYPE_CE},
143 	{"IT", ESP_PHY_INIT_DATA_TYPE_CE},
144 	{"JP", ESP_PHY_INIT_DATA_TYPE_MIC},
145 	{"KR", ESP_PHY_INIT_DATA_TYPE_KCC},
146 	{"LI", ESP_PHY_INIT_DATA_TYPE_CE},
147 	{"LT", ESP_PHY_INIT_DATA_TYPE_CE},
148 	{"LU", ESP_PHY_INIT_DATA_TYPE_CE},
149 	{"LV", ESP_PHY_INIT_DATA_TYPE_CE},
150 	{"MT", ESP_PHY_INIT_DATA_TYPE_CE},
151 	{"MX", ESP_PHY_INIT_DATA_TYPE_IFETEL},
152 	{"NL", ESP_PHY_INIT_DATA_TYPE_CE},
153 	{"NO", ESP_PHY_INIT_DATA_TYPE_CE},
154 	{"NZ", ESP_PHY_INIT_DATA_TYPE_RCM},
155 	{"PL", ESP_PHY_INIT_DATA_TYPE_CE},
156 	{"PT", ESP_PHY_INIT_DATA_TYPE_CE},
157 	{"RO", ESP_PHY_INIT_DATA_TYPE_CE},
158 	{"SE", ESP_PHY_INIT_DATA_TYPE_CE},
159 	{"SI", ESP_PHY_INIT_DATA_TYPE_CE},
160 	{"SK", ESP_PHY_INIT_DATA_TYPE_CE},
161 	{"TW", ESP_PHY_INIT_DATA_TYPE_NCC},
162 	{"US", ESP_PHY_INIT_DATA_TYPE_FCC},
163 };
164 #endif
phy_enter_critical(void)165 uint32_t IRAM_ATTR phy_enter_critical(void)
166 {
167 	if(s_phy_lock_nest == 0) {
168 		s_phy_int_mux = irq_lock();
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