1 /*
2 * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <esp_types.h>
10 #include "sdkconfig.h"
11 #include "esp_attr.h"
12 #include "soc/soc.h"
13 #include "soc/soc_caps.h"
14 #include "hal/clk_gate_ll.h"
15 #include "esp_private/esp_modem_clock.h"
16 #include "esp_private/esp_pmu.h"
17 #include "esp_sleep.h"
18 #include "hal/efuse_hal.h"
19 #include "hal/clk_tree_ll.h"
20
21 #include <zephyr/kernel.h>
22
23 // Please define the frequently called modules in the low bit,
24 // which will improve the execution efficiency
25 typedef enum {
26 MODEM_CLOCK_MODEM_ADC_COMMON_FE,
27 MODEM_CLOCK_MODEM_PRIVATE_FE,
28 MODEM_CLOCK_COEXIST,
29 MODEM_CLOCK_I2C_MASTER,
30 #if SOC_WIFI_SUPPORTED
31 MODEM_CLOCK_WIFI_MAC,
32 MODEM_CLOCK_WIFI_BB,
33 #endif
34 MODEM_CLOCK_ETM,
35 #if SOC_BT_SUPPORTED
36 MODEM_CLOCK_BLE_MAC,
37 MODEM_CLOCK_BLE_BB,
38 #endif
39 #if SOC_IEEE802154_SUPPORTED
40 MODEM_CLOCK_802154_MAC,
41 #endif
42 MODEM_CLOCK_DATADUMP,
43 MODEM_CLOCK_DEVICE_MAX
44 } modem_clock_device_t;
45
46
47 typedef struct modem_clock_context {
48 modem_clock_hal_context_t *hal;
49 unsigned int lock;
50 struct {
51 int16_t refs;
52 uint16_t reserved; /* reserved for 4 bytes aligned */
53 void (*configure)(struct modem_clock_context *, bool);
54 } dev[MODEM_CLOCK_DEVICE_MAX];
55 /* the low-power clock source for each module */
56 modem_clock_lpclk_src_t lpclk_src[PERIPH_MODEM_MODULE_NUM];
57 } modem_clock_context_t;
58
59
60 #if SOC_WIFI_SUPPORTED
modem_clock_wifi_mac_configure(modem_clock_context_t * ctx,bool enable)61 static void IRAM_ATTR modem_clock_wifi_mac_configure(modem_clock_context_t *ctx, bool enable)
62 {
63 if (enable) {
64 modem_syscon_ll_enable_wifi_apb_clock(ctx->hal->syscon_dev, enable);
65 modem_syscon_ll_enable_wifi_mac_clock(ctx->hal->syscon_dev, enable);
66 }
67 }
68
modem_clock_wifi_bb_configure(modem_clock_context_t * ctx,bool enable)69 static void IRAM_ATTR modem_clock_wifi_bb_configure(modem_clock_context_t *ctx, bool enable)
70 {
71 if (enable) {
72 modem_syscon_ll_clk_wifibb_configure(ctx->hal->syscon_dev, enable);
73 }
74 }
75 #endif // SOC_WIFI_SUPPORTED
76
77 #if SOC_BT_SUPPORTED
modem_clock_ble_mac_configure(modem_clock_context_t * ctx,bool enable)78 static void IRAM_ATTR modem_clock_ble_mac_configure(modem_clock_context_t *ctx, bool enable)
79 {
80 modem_syscon_ll_enable_modem_sec_clock(ctx->hal->syscon_dev, enable);
81 modem_syscon_ll_enable_ble_timer_clock(ctx->hal->syscon_dev, enable);
82 }
83
modem_clock_ble_bb_configure(modem_clock_context_t * ctx,bool enable)84 static void IRAM_ATTR modem_clock_ble_bb_configure(modem_clock_context_t *ctx, bool enable)
85 {
86 modem_syscon_ll_enable_bt_apb_clock(ctx->hal->syscon_dev, enable);
87 modem_syscon_ll_enable_bt_clock(ctx->hal->syscon_dev, enable);
88 }
89
90 #endif // SOC_BT_SUPPORTED
91
92 #if SOC_IEEE802154_SUPPORTED
modem_clock_ieee802154_mac_configure(modem_clock_context_t * ctx,bool enable)93 static void IRAM_ATTR modem_clock_ieee802154_mac_configure(modem_clock_context_t *ctx, bool enable)
94 {
95 modem_syscon_ll_enable_ieee802154_apb_clock(ctx->hal->syscon_dev, enable);
96 modem_syscon_ll_enable_ieee802154_mac_clock(ctx->hal->syscon_dev, enable);
97 }
98 #endif // SOC_IEEE802154_SUPPORTED
99
modem_clock_coex_configure(modem_clock_context_t * ctx,bool enable)100 static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, bool enable)
101 {
102 modem_lpcon_ll_enable_coex_clock(ctx->hal->lpcon_dev, enable);
103 }
104
modem_clock_modem_adc_common_fe_configure(modem_clock_context_t * ctx,bool enable)105 static void IRAM_ATTR modem_clock_modem_adc_common_fe_configure(modem_clock_context_t *ctx, bool enable)
106 {
107 modem_clock_hal_enable_modem_adc_common_fe_clock(ctx->hal, enable);
108 }
109
modem_clock_modem_private_fe_configure(modem_clock_context_t * ctx,bool enable)110 static void IRAM_ATTR modem_clock_modem_private_fe_configure(modem_clock_context_t *ctx, bool enable)
111 {
112 modem_clock_hal_enable_modem_private_fe_clock(ctx->hal, enable);
113 }
114
modem_clock_i2c_master_configure(modem_clock_context_t * ctx,bool enable)115 static void IRAM_ATTR modem_clock_i2c_master_configure(modem_clock_context_t *ctx, bool enable)
116 {
117 modem_lpcon_ll_enable_i2c_master_clock(ctx->hal->lpcon_dev, enable);
118 }
119
modem_clock_etm_configure(modem_clock_context_t * ctx,bool enable)120 static void IRAM_ATTR modem_clock_etm_configure(modem_clock_context_t *ctx, bool enable)
121 {
122 modem_syscon_ll_enable_etm_clock(ctx->hal->syscon_dev, enable);
123 }
124
modem_clock_data_dump_configure(modem_clock_context_t * ctx,bool enable)125 static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx, bool enable)
126 {
127 modem_syscon_ll_enable_data_dump_clock(ctx->hal->syscon_dev, enable);
128 modem_syscon_ll_enable_data_dump_mux_clock(ctx->hal->syscon_dev, enable);
129 }
130
MODEM_CLOCK_instance(void)131 modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(void)
132 {
133 /* It should be explicitly defined in the internal RAM */
134 static DRAM_ATTR modem_clock_hal_context_t modem_clock_hal = { .syscon_dev = &MODEM_SYSCON, .lpcon_dev = &MODEM_LPCON };
135 static DRAM_ATTR modem_clock_context_t modem_clock_context = {
136 .hal = &modem_clock_hal, .lock = 0,
137 .dev = {
138 [MODEM_CLOCK_MODEM_ADC_COMMON_FE] = { .refs = 0, .configure = modem_clock_modem_adc_common_fe_configure },
139 [MODEM_CLOCK_MODEM_PRIVATE_FE] = { .refs = 0, .configure = modem_clock_modem_private_fe_configure },
140 [MODEM_CLOCK_COEXIST] = { .refs = 0, .configure = modem_clock_coex_configure },
141 [MODEM_CLOCK_I2C_MASTER] = { .refs = 0, .configure = modem_clock_i2c_master_configure },
142 #if SOC_WIFI_SUPPORTED
143 [MODEM_CLOCK_WIFI_MAC] = { .refs = 0, .configure = modem_clock_wifi_mac_configure },
144 [MODEM_CLOCK_WIFI_BB] = { .refs = 0, .configure = modem_clock_wifi_bb_configure },
145 #endif
146 [MODEM_CLOCK_ETM] = { .refs = 0, .configure = modem_clock_etm_configure },
147 #if SOC_BT_SUPPORTED
148 [MODEM_CLOCK_BLE_MAC] = { .refs = 0, .configure = modem_clock_ble_mac_configure },
149 [MODEM_CLOCK_BLE_BB] = { .refs = 0, .configure = modem_clock_ble_bb_configure },
150 #endif
151 #if SOC_IEEE802154_SUPPORTED
152 [MODEM_CLOCK_802154_MAC] = { .refs = 0, .configure = modem_clock_ieee802154_mac_configure },
153 #endif
154 [MODEM_CLOCK_DATADUMP] = { .refs = 0, .configure = modem_clock_data_dump_configure }
155 },
156 .lpclk_src = { [0 ... PERIPH_MODEM_MODULE_NUM - 1] = MODEM_CLOCK_LPCLK_SRC_INVALID }
157 };
158 return &modem_clock_context;
159 }
160
161 #if SOC_PM_SUPPORT_PMU_MODEM_STATE
modem_clock_domain_clk_gate_enable(modem_clock_domain_t domain,pmu_hp_icg_modem_mode_t mode)162 esp_err_t modem_clock_domain_clk_gate_enable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode)
163 {
164 if (domain >= MODEM_CLOCK_DOMAIN_MAX || domain < MODEM_CLOCK_DOMAIN_MODEM_APB) {
165 return ESP_ERR_INVALID_ARG;
166 }
167 if (mode > PMU_HP_ICG_MODEM_CODE_ACTIVE || mode < PMU_HP_ICG_MODEM_CODE_SLEEP) {
168 return ESP_ERR_INVALID_ARG;
169 }
170
171 MODEM_CLOCK_instance()->lock = irq_lock();
172 uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain);
173 modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, (code & ~BIT(mode)));
174 irq_unlock(MODEM_CLOCK_instance()->lock);
175 return ESP_OK;
176 }
177
modem_clock_domain_clk_gate_disable(modem_clock_domain_t domain,pmu_hp_icg_modem_mode_t mode)178 esp_err_t modem_clock_domain_clk_gate_disable(modem_clock_domain_t domain, pmu_hp_icg_modem_mode_t mode)
179 {
180 if (domain >= MODEM_CLOCK_DOMAIN_MAX || domain < MODEM_CLOCK_DOMAIN_MODEM_APB) {
181 return ESP_ERR_INVALID_ARG;
182 }
183 if (mode > PMU_HP_ICG_MODEM_CODE_ACTIVE || mode < PMU_HP_ICG_MODEM_CODE_SLEEP) {
184 return ESP_ERR_INVALID_ARG;
185 }
186
187 MODEM_CLOCK_instance()->lock = irq_lock();
188 uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain);
189 modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, (code | BIT(mode)));
190 irq_unlock(MODEM_CLOCK_instance()->lock);
191 return ESP_OK;
192 }
193 #endif // #if SOC_PM_SUPPORT_PMU_MODEM_STATE
194
modem_clock_device_enable(modem_clock_context_t * ctx,uint32_t dev_map)195 static void IRAM_ATTR modem_clock_device_enable(modem_clock_context_t *ctx, uint32_t dev_map)
196 {
197 int16_t refs = 0;
198 ctx->lock = irq_lock();
199 for (int i = 0; dev_map; dev_map >>= 1, i++)
200 {
201 if (dev_map & BIT(0)) {
202 refs = ctx->dev[i].refs++;
203 if (refs == 0) {
204 (*ctx->dev[i].configure)(ctx, true);
205 }
206 }
207 }
208 irq_unlock(ctx->lock);
209 assert(refs >= 0);
210 }
211
modem_clock_device_disable(modem_clock_context_t * ctx,uint32_t dev_map)212 static void IRAM_ATTR modem_clock_device_disable(modem_clock_context_t *ctx, uint32_t dev_map)
213 {
214 int16_t refs = 0;
215 ctx->lock = irq_lock();
216 for (int i = 0; dev_map; dev_map >>= 1, i++) {
217 if (dev_map & BIT(0)) {
218 refs = --ctx->dev[i].refs;
219 if (refs == 0) {
220 (*ctx->dev[i].configure)(ctx, false);
221 }
222 }
223 }
224 irq_unlock(ctx->lock);
225 assert(refs >= 0);
226 }
227
modem_clock_module_mac_reset(periph_module_t module)228 void IRAM_ATTR modem_clock_module_mac_reset(periph_module_t module)
229 {
230 modem_clock_context_t *ctx = MODEM_CLOCK_instance();
231 ctx->lock = irq_lock();
232 switch (module)
233 {
234 #if SOC_WIFI_SUPPORTED
235 case PERIPH_WIFI_MODULE:
236 modem_syscon_ll_reset_wifimac(ctx->hal->syscon_dev);
237 break;
238 #endif
239 #if SOC_BT_SUPPORTED
240 case PERIPH_BT_MODULE:
241 modem_syscon_ll_reset_btmac(ctx->hal->syscon_dev);
242 modem_syscon_ll_reset_btmac_apb(ctx->hal->syscon_dev);
243 modem_syscon_ll_reset_ble_timer(ctx->hal->syscon_dev);
244 modem_syscon_ll_reset_modem_sec(ctx->hal->syscon_dev);
245 break;
246 #endif
247 #if SOC_IEEE802154_SUPPORTED
248 case PERIPH_IEEE802154_MODULE:
249 modem_syscon_ll_reset_zbmac(ctx->hal->syscon_dev);
250 break;
251 default:
252 #endif
253 assert(0);
254 }
255 irq_unlock(ctx->lock);
256 }
257
258 #define WIFI_CLOCK_DEPS (BIT(MODEM_CLOCK_WIFI_MAC) | BIT(MODEM_CLOCK_WIFI_BB) | BIT(MODEM_CLOCK_COEXIST))
259 #define BLE_CLOCK_DEPS (BIT(MODEM_CLOCK_BLE_MAC) | BIT(MODEM_CLOCK_BLE_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST))
260 #define IEEE802154_CLOCK_DEPS (BIT(MODEM_CLOCK_802154_MAC) | BIT(MODEM_CLOCK_BLE_BB) | BIT(MODEM_CLOCK_ETM) | BIT(MODEM_CLOCK_COEXIST))
261 #define COEXIST_CLOCK_DEPS (BIT(MODEM_CLOCK_COEXIST))
262 #define PHY_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER) | BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE) | BIT(MODEM_CLOCK_MODEM_PRIVATE_FE))
263 #define I2C_ANA_MST_CLOCK_DEPS (BIT(MODEM_CLOCK_I2C_MASTER))
264 #define MODEM_ETM_CLOCK_DEPS (BIT(MODEM_CLOCK_ETM))
265 #define MODEM_ADC_COMMON_FE_CLOCK_DEPS (BIT(MODEM_CLOCK_MODEM_ADC_COMMON_FE))
266
modem_clock_get_module_deps(periph_module_t module)267 static IRAM_ATTR uint32_t modem_clock_get_module_deps(periph_module_t module)
268 {
269 uint32_t deps = 0;
270 switch (module) {
271 case PERIPH_ANA_I2C_MASTER_MODULE: deps = I2C_ANA_MST_CLOCK_DEPS; break;
272 case PERIPH_PHY_MODULE: deps = PHY_CLOCK_DEPS; break;
273 case PERIPH_MODEM_ADC_COMMON_FE_MODULE: deps = MODEM_ADC_COMMON_FE_CLOCK_DEPS; break;
274 #if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED
275 case PERIPH_COEX_MODULE: deps = COEXIST_CLOCK_DEPS; break;
276 #endif
277 #if SOC_WIFI_SUPPORTED
278 case PERIPH_WIFI_MODULE: deps = WIFI_CLOCK_DEPS; break;
279 #endif
280 #if SOC_BT_SUPPORTED
281 case PERIPH_BT_MODULE: deps = BLE_CLOCK_DEPS; break;
282 #endif
283 #if SOC_IEEE802154_SUPPORTED
284 case PERIPH_IEEE802154_MODULE: deps = IEEE802154_CLOCK_DEPS; break;
285 #endif
286 #if SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED
287 case PERIPH_MODEM_ETM_MODULE: deps = MODEM_ETM_CLOCK_DEPS; break;
288 #endif
289 default:
290 assert(0);
291 }
292 return deps;
293 }
294
295 #if SOC_PM_SUPPORT_PMU_MODEM_STATE
296 /* the ICG code's bit 0, 1 and 2 indicates the ICG state
297 * of pmu SLEEP, MODEM and ACTIVE mode respectively */
298 #define ICG_NOGATING_SLEEP (BIT(PMU_HP_ICG_MODEM_CODE_SLEEP))
299 #define ICG_NOGATING_MODEM (BIT(PMU_HP_ICG_MODEM_CODE_MODEM))
300 #define ICG_NOGATING_ACTIVE (BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE))
301
302 static const DRAM_ATTR uint32_t initial_gating_mode[MODEM_CLOCK_DOMAIN_MAX] = {
303 [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
304 [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE,
305 [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
306 [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE,
307 [MODEM_CLOCK_DOMAIN_MODEM_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
308 [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE,
309 [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
310 [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
311 [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
312 [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
313 };
314
modem_clock_module_icg_map_init_all(void)315 static IRAM_ATTR void modem_clock_module_icg_map_init_all(void)
316 {
317 MODEM_CLOCK_instance()->lock = irq_lock();
318 for (int domain = 0; domain < MODEM_CLOCK_DOMAIN_MAX; domain++) {
319 uint32_t code = modem_clock_hal_get_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain);
320 modem_clock_hal_set_clock_domain_icg_bitmap(MODEM_CLOCK_instance()->hal, domain, initial_gating_mode[domain] | code);
321 }
322 irq_unlock(MODEM_CLOCK_instance()->lock);
323 }
324 #endif // SOC_PM_SUPPORT_PMU_MODEM_STATE
325
modem_clock_module_enable(periph_module_t module)326 void IRAM_ATTR modem_clock_module_enable(periph_module_t module)
327 {
328 assert(IS_MODEM_MODULE(module));
329 #if SOC_PM_SUPPORT_PMU_MODEM_STATE
330 modem_clock_module_icg_map_init_all();
331 #endif
332 uint32_t deps = modem_clock_get_module_deps(module);
333 modem_clock_device_enable(MODEM_CLOCK_instance(), deps);
334 }
335
modem_clock_module_disable(periph_module_t module)336 void IRAM_ATTR modem_clock_module_disable(periph_module_t module)
337 {
338 assert(IS_MODEM_MODULE(module));
339 uint32_t deps = modem_clock_get_module_deps(module);
340 modem_clock_device_disable(MODEM_CLOCK_instance(), deps);
341 }
342
modem_clock_deselect_all_module_lp_clock_source(void)343 void modem_clock_deselect_all_module_lp_clock_source(void)
344 {
345 #if SOC_WIFI_SUPPORTED
346 modem_clock_hal_deselect_all_wifi_lpclk_source(MODEM_CLOCK_instance()->hal);
347 #endif
348 #if SOC_BT_SUPPORTED
349 modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal);
350 #endif
351 modem_clock_hal_deselect_all_coex_lpclk_source(MODEM_CLOCK_instance()->hal);
352 }
353
modem_clock_select_lp_clock_source(periph_module_t module,modem_clock_lpclk_src_t src,uint32_t divider)354 void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpclk_src_t src, uint32_t divider)
355 {
356 assert(IS_MODEM_MODULE(module));
357 MODEM_CLOCK_instance()->lock = irq_lock();
358 switch (module)
359 {
360 #if SOC_WIFI_SUPPORTED
361 case PERIPH_WIFI_MODULE:
362 modem_clock_hal_deselect_all_wifi_lpclk_source(MODEM_CLOCK_instance()->hal);
363 modem_clock_hal_select_wifi_lpclk_source(MODEM_CLOCK_instance()->hal, src);
364 modem_lpcon_ll_set_wifi_lpclk_divisor_value(MODEM_CLOCK_instance()->hal->lpcon_dev, divider);
365 modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, true);
366 break;
367 #endif // SOC_WIFI_SUPPORTED
368
369 #if SOC_BT_SUPPORTED
370 case PERIPH_BT_MODULE:
371 #if CONFIG_IDF_TARGET_ESP32H2
372 bool rc_clk_en = true;
373 bool selected = (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ||
374 (src == MODEM_CLOCK_LPCLK_SRC_RC_SLOW);
375 if (selected) {
376 rc_clk_en = clk_ll_rc32k_is_enabled();
377 if (!rc_clk_en) {
378 clk_ll_rc32k_enable();
379 }
380 modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, MODEM_CLOCK_LPCLK_SRC_RC32K);
381 }
382 #endif // CONFIG_IDF_TARGET_ESP32H2
383 modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal);
384 modem_clock_hal_select_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal, src);
385 modem_clock_hal_set_ble_rtc_timer_divisor_value(MODEM_CLOCK_instance()->hal, divider);
386 modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, true);
387 #if CONFIG_IDF_TARGET_ESP32H2
388 if (!rc_clk_en) {
389 extern void r_esp_ble_rtc_ticks_delay(uint32_t ticks);
390 r_esp_ble_rtc_ticks_delay(2);
391 clk_ll_rc32k_disable();
392 }
393 #endif // CONFIG_IDF_TARGET_ESP32H2
394 #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
395 if (efuse_hal_chip_revision() != 0) {
396 if (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) {
397 pmu_sleep_enable_hp_sleep_sysclk(true);
398 modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, true);
399 modem_clock_domain_clk_gate_disable(MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP);
400 }
401 }
402 #endif
403 break;
404 #endif // SOC_BT_SUPPORTED
405
406 case PERIPH_COEX_MODULE:
407 modem_clock_hal_deselect_all_coex_lpclk_source(MODEM_CLOCK_instance()->hal);
408 modem_clock_hal_select_coex_lpclk_source(MODEM_CLOCK_instance()->hal, src);
409 modem_lpcon_ll_set_coex_lpclk_divisor_value(MODEM_CLOCK_instance()->hal->lpcon_dev, divider);
410 // modem_lpcon_ll_enable_coex_clock(MODEM_CLOCK_instance()->hal->lpcon_dev, true); // TODO: IDF-5727
411 break;
412 default:
413 break;
414 }
415 modem_clock_lpclk_src_t last_src = MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN];
416 MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = src;
417 irq_unlock(MODEM_CLOCK_instance()->lock);
418
419 /* The power domain of the low-power clock source required by the modem
420 * module remains powered on during sleep */
421 esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) ( \
422 (last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST \
423 : (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL \
424 : (last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K \
425 : (last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K \
426 : ESP_PD_DOMAIN_MAX);
427 esp_sleep_pd_domain_t pu_domain = (esp_sleep_pd_domain_t) ( \
428 (src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST \
429 : (src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL \
430 : (src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K \
431 : (src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K \
432 : ESP_PD_DOMAIN_MAX);
433 esp_sleep_pd_config(pd_domain, ESP_PD_OPTION_OFF);
434 esp_sleep_pd_config(pu_domain, ESP_PD_OPTION_ON);
435 }
436
modem_clock_deselect_lp_clock_source(periph_module_t module)437 void modem_clock_deselect_lp_clock_source(periph_module_t module)
438 {
439 assert(IS_MODEM_MODULE(module));
440 MODEM_CLOCK_instance()->lock = irq_lock();
441 modem_clock_lpclk_src_t last_src = MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN];
442 MODEM_CLOCK_instance()->lpclk_src[module - PERIPH_MODEM_MODULE_MIN] = MODEM_CLOCK_LPCLK_SRC_INVALID;
443 switch (module)
444 {
445 #if SOC_WIFI_SUPPORTED
446 case PERIPH_WIFI_MODULE:
447 modem_clock_hal_deselect_all_wifi_lpclk_source(MODEM_CLOCK_instance()->hal);
448 modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, false);
449 break;
450 #endif // SOC_WIFI_SUPPORTED
451
452 #if SOC_BT_SUPPORTED
453 case PERIPH_BT_MODULE:
454 modem_clock_hal_deselect_all_ble_rtc_timer_lpclk_source(MODEM_CLOCK_instance()->hal);
455 modem_clock_hal_enable_ble_rtc_timer_clock(MODEM_CLOCK_instance()->hal, false);
456 #if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
457 if (efuse_hal_chip_revision() != 0) {
458 if (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) {
459 pmu_sleep_enable_hp_sleep_sysclk(false);
460 modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, false);
461 modem_clock_domain_clk_gate_enable(MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP);
462 }
463 }
464 #endif
465 break;
466 #endif // SOC_BT_SUPPORTED
467 case PERIPH_COEX_MODULE:
468 modem_clock_hal_deselect_all_coex_lpclk_source(MODEM_CLOCK_instance()->hal);
469 // modem_lpcon_ll_enable_coex_clock(MODEM_CLOCK_instance()->hal->lpcon_dev, false); // TODO: IDF-5727
470 break;
471 default:
472 break;
473 }
474 irq_unlock(MODEM_CLOCK_instance()->lock);
475
476 esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) ( \
477 (last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST \
478 : (last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL \
479 : (last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K \
480 : (last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K \
481 : ESP_PD_DOMAIN_MAX);
482 esp_sleep_pd_config(pd_domain, ESP_PD_OPTION_OFF);
483 }
484