1 /*
2 * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 // The HAL layer for MODEM CLOCK (ESP32-C6 specific part)
8 #include <stdbool.h>
9 #include "soc/soc.h"
10 #include "esp_attr.h"
11 #include "hal/modem_clock_hal.h"
12 #include "hal/modem_clock_types.h"
13 #include "hal/efuse_hal.h"
14 #include "hal/assert.h"
15
16 typedef enum {
17 MODEM_CLOCK_XTAL32K_CODE = 0,
18 MODEM_CLOCK_RC32K_CODE = 1,
19 MODEM_CLOCK_EXT32K_CODE = 2
20 } modem_clock_32k_clk_src_code_t;
21
modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t * hal,modem_clock_domain_t domain,uint32_t bitmap)22 void IRAM_ATTR modem_clock_hal_set_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain, uint32_t bitmap)
23 {
24 HAL_ASSERT(domain < MODEM_CLOCK_DOMAIN_MAX);
25 switch (domain)
26 {
27 case MODEM_CLOCK_DOMAIN_MODEM_APB:
28 modem_syscon_ll_set_modem_apb_icg_bitmap(hal->syscon_dev, bitmap);
29 break;
30 case MODEM_CLOCK_DOMAIN_MODEM_PERIPH:
31 modem_syscon_ll_set_modem_periph_icg_bitmap(hal->syscon_dev, bitmap);
32 break;
33 case MODEM_CLOCK_DOMAIN_WIFI:
34 modem_syscon_ll_set_wifi_icg_bitmap(hal->syscon_dev, bitmap);
35 break;
36 case MODEM_CLOCK_DOMAIN_BT:
37 modem_syscon_ll_set_bt_icg_bitmap(hal->syscon_dev, bitmap);
38 break;
39 case MODEM_CLOCK_DOMAIN_MODEM_FE:
40 modem_syscon_ll_set_fe_icg_bitmap(hal->syscon_dev, bitmap);
41 break;
42 case MODEM_CLOCK_DOMAIN_IEEE802154:
43 modem_syscon_ll_set_ieee802154_icg_bitmap(hal->syscon_dev, bitmap);
44 break;
45 case MODEM_CLOCK_DOMAIN_LP_APB:
46 modem_lpcon_ll_set_lp_apb_icg_bitmap(hal->lpcon_dev, bitmap);
47 break;
48 case MODEM_CLOCK_DOMAIN_I2C_MASTER:
49 modem_lpcon_ll_set_i2c_master_icg_bitmap(hal->lpcon_dev, bitmap);
50 break;
51 case MODEM_CLOCK_DOMAIN_COEX:
52 modem_lpcon_ll_set_coex_icg_bitmap(hal->lpcon_dev, bitmap);
53 break;
54 case MODEM_CLOCK_DOMAIN_WIFIPWR:
55 modem_lpcon_ll_set_wifipwr_icg_bitmap(hal->lpcon_dev, bitmap);
56 break;
57 default:
58 HAL_ASSERT(0);
59 }
60 }
61
modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t * hal,modem_clock_domain_t domain)62 uint32_t IRAM_ATTR modem_clock_hal_get_clock_domain_icg_bitmap(modem_clock_hal_context_t *hal, modem_clock_domain_t domain)
63 {
64 HAL_ASSERT(domain < MODEM_CLOCK_DOMAIN_MAX);
65 uint32_t bitmap = 0;
66 switch (domain)
67 {
68 case MODEM_CLOCK_DOMAIN_MODEM_APB:
69 bitmap = modem_syscon_ll_get_modem_apb_icg_bitmap(hal->syscon_dev);
70 break;
71 case MODEM_CLOCK_DOMAIN_MODEM_PERIPH:
72 bitmap = modem_syscon_ll_get_modem_periph_icg_bitmap(hal->syscon_dev);
73 break;
74 case MODEM_CLOCK_DOMAIN_WIFI:
75 bitmap = modem_syscon_ll_get_wifi_icg_bitmap(hal->syscon_dev);
76 break;
77 case MODEM_CLOCK_DOMAIN_BT:
78 bitmap = modem_syscon_ll_get_bt_icg_bitmap(hal->syscon_dev);
79 break;
80 case MODEM_CLOCK_DOMAIN_MODEM_FE:
81 bitmap = modem_syscon_ll_get_fe_icg_bitmap(hal->syscon_dev);
82 break;
83 case MODEM_CLOCK_DOMAIN_IEEE802154:
84 bitmap = modem_syscon_ll_get_ieee802154_icg_bitmap(hal->syscon_dev);
85 break;
86 case MODEM_CLOCK_DOMAIN_LP_APB:
87 bitmap = modem_lpcon_ll_get_lp_apb_icg_bitmap(hal->lpcon_dev);
88 break;
89 case MODEM_CLOCK_DOMAIN_I2C_MASTER:
90 bitmap = modem_lpcon_ll_get_i2c_master_icg_bitmap(hal->lpcon_dev);
91 break;
92 case MODEM_CLOCK_DOMAIN_COEX:
93 bitmap = modem_lpcon_ll_get_coex_icg_bitmap(hal->lpcon_dev);
94 break;
95 case MODEM_CLOCK_DOMAIN_WIFIPWR:
96 bitmap = modem_lpcon_ll_get_wifipwr_icg_bitmap(hal->lpcon_dev);
97 break;
98 default:
99 HAL_ASSERT(0);
100 }
101 return bitmap;
102 }
103
modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t * hal,bool enable)104 void IRAM_ATTR modem_clock_hal_enable_modem_adc_common_fe_clock(modem_clock_hal_context_t *hal, bool enable)
105 {
106 if (enable) {
107 modem_syscon_ll_enable_fe_apb_clock(hal->syscon_dev, enable);
108 modem_syscon_ll_enable_fe_80m_clock(hal->syscon_dev, enable);
109 }
110 }
111
modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_context_t * hal,bool enable)112 void IRAM_ATTR modem_clock_hal_enable_modem_private_fe_clock(modem_clock_hal_context_t *hal, bool enable)
113 {
114 if (enable) {
115 modem_syscon_ll_enable_fe_cal_160m_clock(hal->syscon_dev, enable);
116 modem_syscon_ll_enable_fe_160m_clock(hal->syscon_dev, enable);
117 }
118 }
119
modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t * hal,uint32_t divider)120 void modem_clock_hal_set_ble_rtc_timer_divisor_value(modem_clock_hal_context_t *hal, uint32_t divider)
121 {
122 modem_lpcon_ll_set_ble_rtc_timer_divisor_value(hal->lpcon_dev, divider);
123 }
124
modem_clock_hal_enable_ble_rtc_timer_clock(modem_clock_hal_context_t * hal,bool enable)125 void modem_clock_hal_enable_ble_rtc_timer_clock(modem_clock_hal_context_t *hal, bool enable)
126 {
127 modem_lpcon_ll_enable_ble_rtc_timer_clock(hal->lpcon_dev, enable);
128 }
129
modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(modem_clock_hal_context_t * hal)130 void modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(modem_clock_hal_context_t *hal)
131 {
132 modem_lpcon_ll_enable_ble_rtc_timer_slow_osc(hal->lpcon_dev, false);
133 modem_lpcon_ll_enable_ble_rtc_timer_fast_osc(hal->lpcon_dev, false);
134 modem_lpcon_ll_enable_ble_rtc_timer_32k_xtal(hal->lpcon_dev, false);
135 modem_lpcon_ll_enable_ble_rtc_timer_main_xtal(hal->lpcon_dev, false);
136 }
137
modem_clock_hal_select_ble_rtc_timer_lpclk_source(modem_clock_hal_context_t * hal,modem_clock_lpclk_src_t src)138 void modem_clock_hal_select_ble_rtc_timer_lpclk_source(modem_clock_hal_context_t *hal, modem_clock_lpclk_src_t src)
139 {
140 HAL_ASSERT(src < MODEM_CLOCK_LPCLK_SRC_MAX);
141
142 switch (src)
143 {
144 case MODEM_CLOCK_LPCLK_SRC_RC_SLOW:
145 modem_lpcon_ll_enable_ble_rtc_timer_slow_osc(hal->lpcon_dev, true);
146 break;
147 case MODEM_CLOCK_LPCLK_SRC_RC_FAST:
148 modem_lpcon_ll_enable_ble_rtc_timer_fast_osc(hal->lpcon_dev, true);
149 break;
150 case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL:
151 modem_lpcon_ll_enable_ble_rtc_timer_main_xtal(hal->lpcon_dev, true);
152 break;
153 case MODEM_CLOCK_LPCLK_SRC_RC32K:
154 modem_lpcon_ll_enable_ble_rtc_timer_32k_xtal(hal->lpcon_dev, true);
155 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_RC32K_CODE);
156 break;
157 case MODEM_CLOCK_LPCLK_SRC_XTAL32K:
158 modem_lpcon_ll_enable_ble_rtc_timer_32k_xtal(hal->lpcon_dev, true);
159 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_XTAL32K_CODE);
160 break;
161 case MODEM_CLOCK_LPCLK_SRC_EXT32K:
162 modem_lpcon_ll_enable_ble_rtc_timer_32k_xtal(hal->lpcon_dev, true);
163 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_EXT32K_CODE);
164 break;
165 default:
166 HAL_ASSERT(0);
167 }
168 }
169
modem_clock_hal_deselect_all_coex_lpclk_source(modem_clock_hal_context_t * hal)170 void modem_clock_hal_deselect_all_coex_lpclk_source(modem_clock_hal_context_t *hal)
171 {
172 modem_lpcon_ll_enable_coex_lpclk_slow_osc(hal->lpcon_dev, false);
173 modem_lpcon_ll_enable_coex_lpclk_fast_osc(hal->lpcon_dev, false);
174 modem_lpcon_ll_enable_coex_lpclk_32k_xtal(hal->lpcon_dev, false);
175 modem_lpcon_ll_enable_coex_lpclk_main_xtal(hal->lpcon_dev, false);
176 }
177
modem_clock_hal_select_coex_lpclk_source(modem_clock_hal_context_t * hal,modem_clock_lpclk_src_t src)178 void modem_clock_hal_select_coex_lpclk_source(modem_clock_hal_context_t *hal, modem_clock_lpclk_src_t src)
179 {
180 HAL_ASSERT(src < MODEM_CLOCK_LPCLK_SRC_MAX);
181
182 switch (src)
183 {
184 case MODEM_CLOCK_LPCLK_SRC_RC_SLOW:
185 modem_lpcon_ll_enable_coex_lpclk_slow_osc(hal->lpcon_dev, true);
186 break;
187 case MODEM_CLOCK_LPCLK_SRC_RC_FAST:
188 modem_lpcon_ll_enable_coex_lpclk_fast_osc(hal->lpcon_dev, true);
189 break;
190 case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL:
191 modem_lpcon_ll_enable_coex_lpclk_main_xtal(hal->lpcon_dev, true);
192 break;
193 case MODEM_CLOCK_LPCLK_SRC_RC32K:
194 modem_lpcon_ll_enable_coex_lpclk_32k_xtal(hal->lpcon_dev, true);
195 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_RC32K_CODE);
196 break;
197 case MODEM_CLOCK_LPCLK_SRC_XTAL32K:
198 modem_lpcon_ll_enable_coex_lpclk_32k_xtal(hal->lpcon_dev, true);
199 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_XTAL32K_CODE);
200 break;
201 case MODEM_CLOCK_LPCLK_SRC_EXT32K:
202 modem_lpcon_ll_enable_coex_lpclk_32k_xtal(hal->lpcon_dev, true);
203 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_EXT32K_CODE);
204 break;
205 default:
206 HAL_ASSERT(0);
207 }
208 }
209
modem_clock_hal_deselect_all_wifi_lpclk_source(modem_clock_hal_context_t * hal)210 void modem_clock_hal_deselect_all_wifi_lpclk_source(modem_clock_hal_context_t *hal)
211 {
212 modem_lpcon_ll_enable_wifi_lpclk_slow_osc(hal->lpcon_dev, false);
213 modem_lpcon_ll_enable_wifi_lpclk_fast_osc(hal->lpcon_dev, false);
214 modem_lpcon_ll_enable_wifi_lpclk_32k_xtal(hal->lpcon_dev, false);
215 modem_lpcon_ll_enable_wifi_lpclk_main_xtal(hal->lpcon_dev, false);
216 }
217
modem_clock_hal_select_wifi_lpclk_source(modem_clock_hal_context_t * hal,modem_clock_lpclk_src_t src)218 void modem_clock_hal_select_wifi_lpclk_source(modem_clock_hal_context_t *hal, modem_clock_lpclk_src_t src)
219 {
220 HAL_ASSERT(src < MODEM_CLOCK_LPCLK_SRC_MAX);
221
222 switch (src)
223 {
224 case MODEM_CLOCK_LPCLK_SRC_RC_SLOW:
225 modem_lpcon_ll_enable_wifi_lpclk_slow_osc(hal->lpcon_dev, true);
226 break;
227 case MODEM_CLOCK_LPCLK_SRC_RC_FAST:
228 modem_lpcon_ll_enable_wifi_lpclk_fast_osc(hal->lpcon_dev, true);
229 break;
230 case MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL:
231 modem_lpcon_ll_enable_wifi_lpclk_main_xtal(hal->lpcon_dev, true);
232 break;
233 case MODEM_CLOCK_LPCLK_SRC_RC32K:
234 modem_lpcon_ll_enable_wifi_lpclk_32k_xtal(hal->lpcon_dev, true);
235 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_RC32K_CODE);
236 break;
237 case MODEM_CLOCK_LPCLK_SRC_XTAL32K:
238 modem_lpcon_ll_enable_wifi_lpclk_32k_xtal(hal->lpcon_dev, true);
239 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_XTAL32K_CODE);
240 break;
241 case MODEM_CLOCK_LPCLK_SRC_EXT32K:
242 modem_lpcon_ll_enable_wifi_lpclk_32k_xtal(hal->lpcon_dev, true);
243 modem_lpcon_ll_select_modem_32k_clock_source(hal->lpcon_dev, MODEM_CLOCK_EXT32K_CODE);
244 break;
245 default:
246 HAL_ASSERT(0);
247 }
248 }
249
modem_clock_hal_enable_wifipwr_clock(modem_clock_hal_context_t * hal,bool enable)250 void modem_clock_hal_enable_wifipwr_clock(modem_clock_hal_context_t *hal, bool enable)
251 {
252 if (efuse_hal_chip_revision() == 0) { /* eco0 */
253 modem_lpcon_ll_enable_wifipwr_clock(hal->lpcon_dev, enable);
254 } else {
255 static int ref = 0;
256 if (enable) {
257 if (ref++ == 0) {
258 modem_lpcon_ll_enable_wifipwr_clock(hal->lpcon_dev, enable);
259 }
260 } else {
261 if (--ref == 0) {
262 modem_lpcon_ll_enable_wifipwr_clock(hal->lpcon_dev, enable);
263 }
264 }
265 HAL_ASSERT(ref > 0);
266 }
267 }
268