phy_init.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. #include <stddef.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <stdbool.h>
  18. #include "rom/ets_sys.h"
  19. #include "soc/dport_reg.h"
  20. #include "esp_err.h"
  21. #include "esp_phy_init.h"
  22. #include "esp_system.h"
  23. #include "esp_log.h"
  24. #include "nvs.h"
  25. #include "sdkconfig.h"
  26. #ifdef CONFIG_PHY_ENABLED
  27. #include "phy.h"
  28. #include "phy_init_data.h"
  29. static const char* TAG = "phy_init";
  30. esp_err_t esp_phy_init(const esp_phy_init_data_t* init_data,
  31. esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data)
  32. {
  33. assert(init_data);
  34. assert(calibration_data);
  35. REG_SET_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
  36. REG_CLR_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
  37. // Enable WiFi peripheral clock
  38. SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf);
  39. ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d",
  40. init_data, calibration_data, mode);
  41. phy_set_wifi_mode_only(0);
  42. register_chipv7_phy(init_data, calibration_data, mode);
  43. coex_bt_high_prio();
  44. return ESP_OK;
  45. }
  46. // PHY init data handling functions
  47. #if CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
  48. #include "esp_partition.h"
  49. const esp_phy_init_data_t* esp_phy_get_init_data()
  50. {
  51. const esp_partition_t* partition = esp_partition_find_first(
  52. ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
  53. if (partition == NULL) {
  54. ESP_LOGE(TAG, "PHY data partition not found");
  55. return NULL;
  56. }
  57. ESP_LOGD(TAG, "loading PHY init data from partition at offset 0x%x", partition->address);
  58. size_t init_data_store_length = sizeof(phy_init_magic_pre) +
  59. sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
  60. uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
  61. if (init_data_store == NULL) {
  62. ESP_LOGE(TAG, "failed to allocate memory for PHY init data");
  63. return NULL;
  64. }
  65. esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
  66. if (err != ESP_OK) {
  67. ESP_LOGE(TAG, "failed to read PHY data partition (%d)", err);
  68. return NULL;
  69. }
  70. if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
  71. memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
  72. PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
  73. ESP_LOGE(TAG, "failed to validate PHY data partition");
  74. return NULL;
  75. }
  76. ESP_LOGE(TAG, "PHY data partition validated");
  77. return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre));
  78. }
  79. void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
  80. {
  81. free((uint8_t*) init_data - sizeof(phy_init_magic_pre));
  82. }
  83. #else // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
  84. // phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data
  85. const esp_phy_init_data_t* esp_phy_get_init_data()
  86. {
  87. ESP_LOGD(TAG, "loading PHY init data from application binary");
  88. return &phy_init_data;
  89. }
  90. void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
  91. {
  92. // no-op
  93. }
  94. #endif // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
  95. // PHY calibration data handling functions
  96. static const char* PHY_NAMESPACE = "phy";
  97. static const char* PHY_CAL_VERSION_KEY = "cal_version";
  98. static const char* PHY_CAL_MAC_KEY = "cal_mac";
  99. static const char* PHY_CAL_DATA_KEY = "cal_data";
  100. static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
  101. esp_phy_calibration_data_t* out_cal_data);
  102. static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
  103. const esp_phy_calibration_data_t* cal_data);
  104. esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data)
  105. {
  106. nvs_handle handle;
  107. esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle);
  108. if (err != ESP_OK) {
  109. ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err);
  110. return err;
  111. }
  112. else {
  113. err = load_cal_data_from_nvs_handle(handle, out_cal_data);
  114. nvs_close(handle);
  115. return err;
  116. }
  117. }
  118. esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data)
  119. {
  120. nvs_handle handle;
  121. esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle);
  122. if (err != ESP_OK) {
  123. ESP_LOGD(TAG, "%s: failed to open NVS namespace (%d)", __func__, err);
  124. return err;
  125. }
  126. else {
  127. err = store_cal_data_to_nvs_handle(handle, cal_data);
  128. nvs_close(handle);
  129. return err;
  130. }
  131. }
  132. static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
  133. esp_phy_calibration_data_t* out_cal_data)
  134. {
  135. esp_err_t err;
  136. uint32_t cal_data_version;
  137. err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version);
  138. if (err != ESP_OK) {
  139. ESP_LOGD(TAG, "%s: failed to get cal_version (%d)", __func__, err);
  140. return err;
  141. }
  142. uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
  143. ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
  144. if (cal_data_version != cal_format_version) {
  145. ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d",
  146. __func__, cal_format_version, cal_data_version);
  147. return ESP_FAIL;
  148. }
  149. uint8_t cal_data_mac[6];
  150. size_t length = sizeof(cal_data_mac);
  151. err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length);
  152. if (err != ESP_OK) {
  153. ESP_LOGD(TAG, "%s: failed to get cal_mac (%d)", __func__, err);
  154. return err;
  155. }
  156. if (length != sizeof(cal_data_mac)) {
  157. ESP_LOGD(TAG, "%s: invalid length of cal_mac (%d)", __func__, length);
  158. return ESP_ERR_INVALID_SIZE;
  159. }
  160. uint8_t sta_mac[6];
  161. esp_efuse_read_mac(sta_mac);
  162. if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) {
  163. ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \
  164. MACSTR ", found " MACSTR,
  165. __func__, MAC2STR(sta_mac), MAC2STR(cal_data_mac));
  166. return ESP_FAIL;
  167. }
  168. length = sizeof(*out_cal_data);
  169. err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length);
  170. if (err != ESP_OK) {
  171. ESP_LOGE(TAG, "%s: failed to get cal_data(%d)", __func__, err);
  172. return err;
  173. }
  174. if (length != sizeof(*out_cal_data)) {
  175. ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length);
  176. return ESP_ERR_INVALID_SIZE;
  177. }
  178. return ESP_OK;
  179. }
  180. static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
  181. const esp_phy_calibration_data_t* cal_data)
  182. {
  183. esp_err_t err;
  184. uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
  185. ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
  186. err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
  187. if (err != ESP_OK) {
  188. return err;
  189. }
  190. uint8_t sta_mac[6];
  191. esp_efuse_read_mac(sta_mac);
  192. err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
  193. if (err != ESP_OK) {
  194. return err;
  195. }
  196. err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
  197. return err;
  198. }
  199. #endif // CONFIG_PHY_ENABLED