1 /*
2 * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9 #include <zephyr/random/random.h>
10 #include "zephyr_compat.h"
11
12 #include <esp_event.h>
13 #include <esp_wifi.h>
14 #include <soc/soc_caps.h>
15 #include "soc.h"
16 #include "esp_log.h"
17 #include "esp_private/wifi.h"
18 #include "esp_private/adc_share_hw_ctrl.h"
19 #include "esp_private/sleep_modem.h"
20 #include "esp_sleep.h"
21 #include "esp_check.h"
22 #include "esp_private/pm_impl.h"
23 #include "esp_private/esp_clk.h"
24 #include "esp_wpa.h"
25 #include "esp_phy_init.h"
26 #include "esp_private/phy.h"
27 #include "private/esp_modem_wrapper.h"
28
29 #ifdef CONFIG_ESP_WIFI_NAN_ENABLE
30 #include "apps_private/wifi_apps_private.h"
31 #endif
32 #ifdef CONFIG_ESP_WIFI_FTM_ENABLE
33 #include "esp_chip_info.h"
34 #endif
35
36 #if SOC_PM_MODEM_RETENTION_BY_REGDMA
37 #include "esp_private/sleep_retention.h"
38 #endif
39
40 #if CONFIG_SW_COEXIST_ENABLE
41 #include "private/esp_coexist_internal.h"
42 #endif
43
44 #include <zephyr/logging/log.h>
45 LOG_MODULE_REGISTER(wifi_init, CONFIG_WIFI_LOG_LEVEL);
46
47 static bool s_wifi_inited = false;
48
49 #if (CONFIG_ESP_WIFI_RX_BA_WIN > CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM)
50 #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than WIFI_DYNAMIC_RX_BUFFER_NUM!"
51 #endif
52
53 #if (CONFIG_ESP_WIFI_RX_BA_WIN > (CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM << 1))
54 #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than double of the WIFI_STATIC_RX_BUFFER_NUM!"
55 #endif
56
57 ESP_EVENT_DEFINE_BASE(WIFI_EVENT);
58
59 extern uint8_t esp_wifi_get_user_init_flag_internal(void);
60 extern esp_err_t coex_init(void);
61
62 #if CONFIG_IDF_TARGET_ESP32
63 /* Callback function to update WiFi MAC time */
64 extern wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb;
65 #endif
66
67 #if SOC_PM_SUPPORT_PMU_MODEM_STATE
68 # define WIFI_BEACON_MONITOR_CONFIG_DEFAULT(ena) { \
69 .enable = (ena), \
70 .loss_timeout = CONFIG_ESP_WIFI_SLP_BEACON_LOST_TIMEOUT, \
71 .loss_threshold = CONFIG_ESP_WIFI_SLP_BEACON_LOST_THRESHOLD, \
72 .delta_intr_early = 0, \
73 .delta_loss_timeout = 0, \
74 .beacon_abort = 1, \
75 .broadcast_wakeup = 1, \
76 .tsf_time_sync_deviation = 5, \
77 .modem_state_consecutive = 10, \
78 .rf_ctrl_wait_cycle = 20 \
79 }
80 #else
81 # define WIFI_BEACON_MONITOR_CONFIG_DEFAULT(ena) { \
82 .enable = (ena), \
83 .loss_timeout = CONFIG_ESP_WIFI_SLP_BEACON_LOST_TIMEOUT, \
84 .loss_threshold = CONFIG_ESP_WIFI_SLP_BEACON_LOST_THRESHOLD, \
85 .delta_intr_early = CONFIG_ESP_WIFI_SLP_PHY_ON_DELTA_EARLY_TIME, \
86 .delta_loss_timeout = CONFIG_ESP_WIFI_SLP_PHY_OFF_DELTA_TIMEOUT_TIME \
87 }
88 #endif
89
esp_wifi_set_log_level(void)90 static void esp_wifi_set_log_level(void)
91 {
92 wifi_log_level_t wifi_log_level = WIFI_LOG_INFO;
93 /* set WiFi log level */
94 #if CONFIG_LOG_MAXIMUM_LEVEL == 0
95 wifi_log_level = WIFI_LOG_NONE;
96 #elif CONFIG_LOG_MAXIMUM_LEVEL == 1
97 wifi_log_level = WIFI_LOG_ERROR;
98 #elif CONFIG_LOG_MAXIMUM_LEVEL == 2
99 wifi_log_level = WIFI_LOG_WARNING;
100 #elif CONFIG_LOG_MAXIMUM_LEVEL == 3
101 wifi_log_level = WIFI_LOG_INFO;
102 #elif CONFIG_LOG_MAXIMUM_LEVEL == 4
103 wifi_log_level = WIFI_LOG_DEBUG;
104 #elif CONFIG_LOG_MAXIMUM_LEVEL == 5
105 wifi_log_level = WIFI_LOG_VERBOSE;
106 #endif
107 esp_wifi_internal_set_log_level(wifi_log_level);
108 }
109
110 #if CONFIG_MAC_BB_PD
esp_wifi_mac_pd_mem_init(void)111 static void esp_wifi_mac_pd_mem_init(void)
112 {
113 #if SOC_PM_MODEM_RETENTION_BY_REGDMA
114 esp_err_t err = sleep_retention_module_allocate(SLEEP_RETENTION_MODULE_WIFI_MAC);
115 if (err != ESP_OK) {
116 LOG_WRN("failed to allocate sleep retention linked list for wifi mac retention");
117 }
118 #endif
119 esp_wifi_internal_set_mac_sleep(true);
120 }
esp_wifi_mac_pd_mem_deinit(void)121 static void esp_wifi_mac_pd_mem_deinit(void)
122 {
123 esp_wifi_internal_set_mac_sleep(false);
124 #if SOC_PM_MODEM_RETENTION_BY_REGDMA
125 esp_err_t err = sleep_retention_module_free(SLEEP_RETENTION_MODULE_WIFI_MAC);
126 if (err != ESP_OK) {
127 LOG_WRN("failed to free sleep retention linked list for wifi mac retention");
128 }
129 #endif
130 }
131 #endif
132
wifi_deinit_internal(void)133 static esp_err_t wifi_deinit_internal(void)
134 {
135 esp_err_t err = ESP_OK;
136
137 if (esp_wifi_get_user_init_flag_internal()) {
138 LOG_ERR("Wi-Fi not stop");
139 return ESP_ERR_WIFI_NOT_STOPPED;
140 }
141
142 if (esp_wifi_internal_reg_rxcb(WIFI_IF_STA, NULL) != ESP_OK ||
143 esp_wifi_internal_reg_rxcb(WIFI_IF_AP, NULL) != ESP_OK) {
144 LOG_WRN("Failed to unregister Rx callbacks");
145 }
146
147 #ifdef CONFIG_ESP_WIFI_NAN_ENABLE
148 esp_nan_app_deinit();
149 #endif
150
151 #if CONFIG_MAC_BB_PD
152 esp_wifi_mac_pd_mem_deinit();
153 esp_mac_bb_pd_mem_deinit();
154 #endif
155
156 esp_supplicant_deinit();
157 err = esp_wifi_deinit_internal();
158 if (err != ESP_OK) {
159 LOG_ERR("Failed to deinit Wi-Fi driver (0x%x)", err);
160 return err;
161 }
162 esp_wifi_power_domain_off();
163
164 #if CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT
165 wifi_beacon_monitor_config_t monitor_config = WIFI_BEACON_MONITOR_CONFIG_DEFAULT(false);
166 esp_wifi_beacon_monitor_configure(&monitor_config);
167 #endif
168
169 #if SOC_PM_MODEM_RETENTION_BY_REGDMA
170 err = sleep_retention_module_deinit(SLEEP_RETENTION_MODULE_WIFI_MAC);
171 if (err != ESP_OK) {
172 LOG_WRN("WiFi MAC sleep retention deinit failed");
173 }
174 #endif /* SOC_PM_MODEM_RETENTION_BY_REGDMA */
175 #if CONFIG_MAC_BB_PD
176 esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
177 esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
178 #endif
179 esp_phy_modem_deinit();
180
181 s_wifi_inited = false;
182
183 return err;
184 }
185
esp_wifi_deinit(void)186 esp_err_t esp_wifi_deinit(void)
187 {
188 if (s_wifi_inited == false) {
189 return ESP_ERR_WIFI_NOT_INIT;
190 }
191
192 return wifi_deinit_internal();
193 }
194
esp_wifi_config_info(void)195 static void esp_wifi_config_info(void)
196 {
197 #ifdef CONFIG_ESP_WIFI_RX_BA_WIN
198 LOG_INF("rx ba win: %d", CONFIG_ESP_WIFI_RX_BA_WIN);
199 #endif
200
201 #ifdef CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
202 LOG_INF("WiFi/LWIP prefer SPIRAM");
203 #endif
204
205 #ifdef CONFIG_ESP_WIFI_IRAM_OPT
206 LOG_INF("WiFi IRAM OP enabled");
207 #endif
208
209 #ifdef CONFIG_ESP_WIFI_RX_IRAM_OPT
210 LOG_INF("WiFi RX IRAM OP enabled");
211 #endif
212
213 #ifdef CONFIG_ESP_WIFI_SLP_IRAM_OPT
214 LOG_INF("WiFi SLP IRAM OP enabled");
215 #endif
216
217 #ifdef CONFIG_LWIP_IRAM_OPTIMIZATION
218 LOG_INF("LWIP IRAM OP enabled");
219 #endif
220 }
221
222 #if CONFIG_SPIRAM
esp_wifi_psram_check(const wifi_init_config_t * config)223 static esp_err_t esp_wifi_psram_check(const wifi_init_config_t *config)
224 {
225 #if CONFIG_SPIRAM_IGNORE_NOTFOUND
226 if (!esp_psram_is_initialized()) {
227 if (config->feature_caps & CONFIG_FEATURE_CACHE_TX_BUF_BIT) {
228 LOG_WRN("WiFi cache TX buffers should be disabled when initialize SPIRAM failed");
229 }
230 if (config->tx_buf_type == 0) {
231 LOG_WRN("TX buffers type should be changed from static to dynamic when initialize SPIRAM failed");
232 }
233 if (config->amsdu_tx_enable) {
234 LOG_WRN("WiFi AMSDU TX should be disabled when initialize SPIRAM failed");
235 }
236 }
237 #endif
238 if ((config->feature_caps & CONFIG_FEATURE_CACHE_TX_BUF_BIT) && (WIFI_CACHE_TX_BUFFER_NUM == 0)) {
239 LOG_ERR("Number of WiFi cache TX buffers should not equal 0 when enable SPIRAM");
240 return ESP_ERR_NOT_SUPPORTED;
241 }
242 return ESP_OK;
243 }
244 #endif
245
esp_wifi_init(const wifi_init_config_t * config)246 esp_err_t esp_wifi_init(const wifi_init_config_t *config)
247 {
248 if (s_wifi_inited) {
249 return ESP_OK;
250 }
251
252 #if CONFIG_SW_COEXIST_ENABLE
253 esp_coex_adapter_register(&g_coex_adapter_funcs);
254 coex_pre_init();
255 #endif
256 esp_err_t result = ESP_OK;
257 #ifdef CONFIG_SPIRAM
258 result = esp_wifi_psram_check(config);
259 if (result != ESP_OK) {
260 return result;
261 }
262 #endif
263
264 uint32_t min_active_time_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME * 1000;
265 esp_wifi_set_sleep_min_active_time(min_active_time_us);
266
267 uint32_t keep_alive_time_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME * 1000 * 1000;
268 esp_wifi_set_keep_alive_time(keep_alive_time_us);
269
270 uint32_t wait_broadcast_data_time_us = CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME * 1000;
271 esp_wifi_set_sleep_wait_broadcast_data_time(wait_broadcast_data_time_us);
272
273 #if CONFIG_MAC_BB_PD
274 if (esp_register_mac_bb_pd_callback(pm_mac_sleep) != ESP_OK
275 || esp_register_mac_bb_pu_callback(pm_mac_wakeup) != ESP_OK) {
276
277 esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
278 esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
279 return ESP_ERR_INVALID_ARG;
280 }
281 #endif
282
283 #if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
284 coex_init();
285 #endif
286 esp_wifi_set_log_level();
287 esp_wifi_power_domain_on();
288 #ifdef CONFIG_ESP_WIFI_FTM_ENABLE
289 esp_chip_info_t info = {0};
290 esp_chip_info(&info);
291 if (info.model == CHIP_ESP32C6 && info.revision <= 1) {
292 ((wifi_init_config_t *)config)->feature_caps &= ~(CONFIG_FEATURE_FTM_INITIATOR_BIT);
293 }
294 #endif
295 result = esp_wifi_init_internal(config);
296
297 if (result == ESP_OK) {
298 #if CONFIG_MAC_BB_PD
299 esp_mac_bb_pd_mem_init();
300 esp_wifi_mac_pd_mem_init();
301 #endif
302
303 esp_phy_modem_init();
304 #if CONFIG_IDF_TARGET_ESP32
305 s_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time;
306 #endif
307
308 result = esp_supplicant_init();
309 if (result != ESP_OK) {
310 LOG_ERR("Failed to init supplicant (0x%x)", result);
311 goto _deinit;
312 }
313 } else {
314 goto _deinit;
315 }
316 #if CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT
317 wifi_beacon_monitor_config_t monitor_config = WIFI_BEACON_MONITOR_CONFIG_DEFAULT(true);
318 esp_wifi_beacon_monitor_configure(&monitor_config);
319 #endif
320 esp_wifi_config_info();
321
322 #ifdef CONFIG_ESP_WIFI_NAN_ENABLE
323 esp_nan_app_init();
324 #endif
325
326 s_wifi_inited = true;
327
328 return result;
329
330 _deinit:
331 ;
332 esp_err_t deinit_ret = wifi_deinit_internal();
333 if (deinit_ret != ESP_OK) {
334 LOG_ERR("Failed to deinit Wi-Fi (0x%x)", deinit_ret);
335 }
336 return result;
337 }
338
339 #ifdef CONFIG_PM_ENABLE
wifi_apb80m_request(void)340 void wifi_apb80m_request(void)
341 {
342 }
343
wifi_apb80m_release(void)344 void wifi_apb80m_release(void)
345 {
346 }
347 #endif //CONFIG_PM_ENABLE
348
349 #ifndef CONFIG_ESP_WIFI_FTM_ENABLE
ieee80211_ftm_attach(void)350 esp_err_t ieee80211_ftm_attach(void)
351 {
352 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
353 return ESP_OK;
354 }
355 #endif
356
357 #ifndef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
net80211_softap_funcs_init(void)358 void net80211_softap_funcs_init(void)
359 {
360 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
361 }
362
ieee80211_ap_try_sa_query(void * p)363 bool ieee80211_ap_try_sa_query(void *p)
364 {
365 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
366 return false;
367 }
368
ieee80211_ap_sa_query_timeout(void * p)369 bool ieee80211_ap_sa_query_timeout(void *p)
370 {
371 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
372 return false;
373 }
374
add_mic_ie_bip(void * p)375 int add_mic_ie_bip(void *p)
376 {
377 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
378 return 0;
379 }
380
ieee80211_free_beacon_eb(void)381 void ieee80211_free_beacon_eb(void)
382 {
383 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
384 }
385
ieee80211_pwrsave(void * p1,void * p2)386 int ieee80211_pwrsave(void *p1, void *p2)
387 {
388 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
389 return 0;
390 }
391
cnx_node_remove(void * p)392 void cnx_node_remove(void *p)
393 {
394 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
395 }
396
ieee80211_set_tim(void * p,int arg)397 int ieee80211_set_tim(void *p, int arg)
398 {
399 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
400 return 0;
401 }
402
ieee80211_is_bufferable_mmpdu(void * p)403 bool ieee80211_is_bufferable_mmpdu(void *p)
404 {
405 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
406 return false;
407 }
408
cnx_node_leave(void * p,uint8_t arg)409 void cnx_node_leave(void *p, uint8_t arg)
410 {
411 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
412 }
413
ieee80211_beacon_construct(void * p1,void * p2,void * p3,void * p4)414 void ieee80211_beacon_construct(void *p1, void *p2, void *p3, void *p4)
415 {
416 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
417 }
418
ieee80211_assoc_resp_construct(void * p,int arg)419 void * ieee80211_assoc_resp_construct(void *p, int arg)
420 {
421 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
422 return NULL;
423 }
424
ieee80211_alloc_proberesp(void * p,int arg)425 void * ieee80211_alloc_proberesp(void *p, int arg)
426 {
427 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
428 return NULL;
429 }
430
431 #endif
432
433 #ifndef CONFIG_ESP_WIFI_NAN_ENABLE
434
nan_start(void)435 esp_err_t nan_start(void)
436 {
437 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
438 return ESP_OK;
439 }
440
nan_stop(void)441 esp_err_t nan_stop(void)
442 {
443 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
444 return ESP_OK;
445 }
446
nan_input(void * p1,int p2,int p3)447 int nan_input(void *p1, int p2, int p3)
448 {
449 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
450 return 0;
451 }
452
nan_sm_handle_event(void * p1,int p2)453 void nan_sm_handle_event(void *p1, int p2)
454 {
455 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
456 }
457
458 #if CONFIG_IDF_TARGET_ESP32C2
459 #ifndef CONFIG_SOC_ESP32C2_REV_2_0
esp32c2_eco4_rom_ptr_init(void)460 void esp32c2_eco4_rom_ptr_init(void)
461 {
462 /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
463 }
464 #endif
465 #endif
466
467 #endif
468