1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/kernel.h>
7 
8 #include "hal/clk_gate_ll.h"
9 #include "esp_attr.h"
10 #include "esp_private/periph_ctrl.h"
11 #include "soc/soc_caps.h"
12 
13 #if SOC_MODEM_CLOCK_IS_INDEPENDENT
14 #include "esp_private/esp_modem_clock.h"
15 #endif
16 
17 static int periph_spinlock;
18 
19 #define ENTER_CRITICAL_SECTION()    do { periph_spinlock = irq_lock(); } while(0)
20 #define LEAVE_CRITICAL_SECTION()    irq_unlock(periph_spinlock);
21 
22 static uint8_t ref_counts[PERIPH_MODULE_MAX] = {0};
23 
24 #pragma GCC diagnostic push
25 #pragma GCC diagnostic ignored "-Warray-bounds"
periph_module_enable(periph_module_t periph)26 void periph_module_enable(periph_module_t periph)
27 {
28     assert(periph < PERIPH_MODULE_MAX);
29     ENTER_CRITICAL_SECTION();
30     if (ref_counts[periph] == 0) {
31         periph_ll_enable_clk_clear_rst(periph);
32     }
33     ref_counts[periph]++;
34     LEAVE_CRITICAL_SECTION();
35 }
36 #pragma GCC diagnostic pop
37 
38 #pragma GCC diagnostic push
39 #pragma GCC diagnostic ignored "-Warray-bounds"
periph_module_disable(periph_module_t periph)40 void periph_module_disable(periph_module_t periph)
41 {
42     assert(periph < PERIPH_MODULE_MAX);
43     ENTER_CRITICAL_SECTION();
44     ref_counts[periph]--;
45     if (ref_counts[periph] == 0) {
46         periph_ll_disable_clk_set_rst(periph);
47     }
48     LEAVE_CRITICAL_SECTION();
49 }
50 #pragma GCC diagnostic pop
51 
periph_module_reset(periph_module_t periph)52 void periph_module_reset(periph_module_t periph)
53 {
54     assert(periph < PERIPH_MODULE_MAX);
55     ENTER_CRITICAL_SECTION();
56     periph_ll_reset(periph);
57     LEAVE_CRITICAL_SECTION();
58 }
59 
60 #if !SOC_IEEE802154_BLE_ONLY
wifi_bt_common_module_enable(void)61 IRAM_ATTR void wifi_bt_common_module_enable(void)
62 {
63 #if SOC_MODEM_CLOCK_IS_INDEPENDENT
64     modem_clock_module_enable(PERIPH_PHY_MODULE);
65 #else
66     ENTER_CRITICAL_SECTION();
67     if (ref_counts[PERIPH_WIFI_BT_COMMON_MODULE] == 0) {
68         periph_ll_wifi_bt_module_enable_clk_clear_rst();
69     }
70     ref_counts[PERIPH_WIFI_BT_COMMON_MODULE]++;
71     LEAVE_CRITICAL_SECTION();
72 #endif
73 }
74 
wifi_bt_common_module_disable(void)75 IRAM_ATTR void wifi_bt_common_module_disable(void)
76 {
77 #if SOC_MODEM_CLOCK_IS_INDEPENDENT
78     modem_clock_module_disable(PERIPH_PHY_MODULE);
79 #else
80     ENTER_CRITICAL_SECTION();
81     ref_counts[PERIPH_WIFI_BT_COMMON_MODULE]--;
82     if (ref_counts[PERIPH_WIFI_BT_COMMON_MODULE] == 0) {
83         periph_ll_wifi_bt_module_disable_clk_set_rst();
84     }
85     LEAVE_CRITICAL_SECTION();
86 #endif
87 }
88 #endif
89 
90 #if CONFIG_WIFI_ESP32
wifi_module_enable(void)91 void wifi_module_enable(void)
92 {
93 #if SOC_MODEM_CLOCK_IS_INDEPENDENT
94     modem_clock_module_enable(PERIPH_WIFI_MODULE);
95 #else
96     ENTER_CRITICAL_SECTION();
97     periph_ll_wifi_module_enable_clk_clear_rst();
98     LEAVE_CRITICAL_SECTION();
99 #endif
100 }
101 
wifi_module_disable(void)102 void wifi_module_disable(void)
103 {
104 #if SOC_MODEM_CLOCK_IS_INDEPENDENT
105     modem_clock_module_disable(PERIPH_WIFI_MODULE);
106 #else
107     ENTER_CRITICAL_SECTION();
108     periph_ll_wifi_module_disable_clk_set_rst();
109     LEAVE_CRITICAL_SECTION();
110 #endif
111 }
112 #endif // CONFIG_WIFI_ESP32
113