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