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