1 /*
2  * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <stddef.h>
10 #include <assert.h>
11 #include <stdlib.h>
12 #include "sdkconfig.h"
13 #include "esp32s2/rom/rtc.h"
14 #include "soc/rtc.h"
15 #include "esp_private/rtc_clk.h"
16 #include "soc/rtc_cntl_reg.h"
17 #include "soc/rtc_io_reg.h"
18 #include "soc/soc_caps.h"
19 #include "esp_rom_sys.h"
20 #include "esp_hw_log.h"
21 #include "sdkconfig.h"
22 #include "hal/clk_tree_ll.h"
23 
24 static const char *TAG = "rtc_clk";
25 
26 // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
27 // On the ESP32-S2, 480MHz PLL is enabled at reset.
28 static uint32_t s_cur_pll_freq = CLK_LL_PLL_480M_FREQ_MHZ;
29 
30 static void rtc_clk_cpu_freq_to_xtal(int freq, int div);
31 static void rtc_clk_cpu_freq_to_8m(void);
32 
rtc_clk_32k_enable(bool enable)33 void rtc_clk_32k_enable(bool enable)
34 {
35     if (enable) {
36         SET_PERI_REG_MASK(RTC_IO_XTAL_32P_PAD_REG, RTC_IO_X32P_MUX_SEL);
37         SET_PERI_REG_MASK(RTC_IO_XTAL_32N_PAD_REG, RTC_IO_X32N_MUX_SEL);
38         clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL);
39     } else {
40         clk_ll_xtal32k_disable();
41     }
42 }
43 
rtc_clk_32k_enable_external(void)44 void rtc_clk_32k_enable_external(void)
45 {
46     SET_PERI_REG_MASK(RTC_IO_XTAL_32P_PAD_REG, RTC_IO_X32P_MUX_SEL);
47     SET_PERI_REG_MASK(RTC_IO_XTAL_32N_PAD_REG, RTC_IO_X32N_MUX_SEL);
48     clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL);
49 }
50 
rtc_clk_32k_bootstrap(uint32_t cycle)51 void rtc_clk_32k_bootstrap(uint32_t cycle)
52 {
53     /* No special bootstrapping needed for ESP32-S2, 'cycle' argument is to keep the signature
54      * same as for the ESP32. Just enable the XTAL here.
55      */
56     (void)cycle;
57     rtc_clk_32k_enable(true);
58 }
59 
rtc_clk_32k_enabled(void)60 bool rtc_clk_32k_enabled(void)
61 {
62     return clk_ll_xtal32k_is_enabled();
63 }
64 
rtc_clk_8m_enable(bool clk_8m_en,bool d256_en)65 void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
66 {
67     if (clk_8m_en) {
68         clk_ll_rc_fast_enable();
69         esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE);
70     } else {
71         clk_ll_rc_fast_disable();
72     }
73     /* d256 should be independent configured with 8M
74      * Maybe we can split this function into 8m and dmd256
75      */
76     if (d256_en) {
77         clk_ll_rc_fast_d256_enable();
78     } else {
79         clk_ll_rc_fast_d256_disable();
80     }
81 }
82 
rtc_clk_8m_enabled(void)83 bool rtc_clk_8m_enabled(void)
84 {
85     return clk_ll_rc_fast_is_enabled();
86 }
87 
rtc_clk_8md256_enabled(void)88 bool rtc_clk_8md256_enabled(void)
89 {
90     return clk_ll_rc_fast_d256_is_enabled();
91 }
92 
rtc_clk_apll_enable(bool enable)93 void rtc_clk_apll_enable(bool enable)
94 {
95     if (enable) {
96         clk_ll_apll_enable();
97     } else {
98         clk_ll_apll_disable();
99     }
100 }
101 
rtc_clk_apll_coeff_calc(uint32_t freq,uint32_t * _o_div,uint32_t * _sdm0,uint32_t * _sdm1,uint32_t * _sdm2)102 uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2)
103 {
104     uint32_t rtc_xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
105     if (rtc_xtal_freq == 0) {
106         // xtal_freq has not set yet
107         ESP_HW_LOGE(TAG, "Get xtal clock frequency failed, it has not been set yet");
108         abort();
109     }
110     /* Reference formula: apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) / ((o_div + 2) * 2)
111      *                                ----------------------------------------------   -----------------
112      *                                     350 MHz <= Numerator <= 500 MHz                Denominator
113      */
114     int o_div = 0; // range: 0~31
115     int sdm0 = 0;  // range: 0~255
116     int sdm1 = 0;  // range: 0~255
117     int sdm2 = 0;  // range: 0~63
118     /* Firstly try to satisfy the condition that the operation frequency of numerator should be greater than 350 MHz,
119      * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz, '+1' in the following code is to get the ceil value.
120      * With this condition, as we know the 'o_div' can't be greater than 31, then we can calculate the APLL minimum support frequency is
121      * 350 MHz / ((31 + 2) * 2) = 5303031 Hz (for ceil) */
122     o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MIN_HZ / (float)(freq * 2) + 1) - 2;
123     if (o_div > 31) {
124         ESP_HW_LOGE(TAG, "Expected frequency is too small");
125         return 0;
126     }
127     if (o_div < 0) {
128         /* Try to satisfy the condition that the operation frequency of numerator should be smaller than 500 MHz,
129          * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz, we need to get the floor value in the following code.
130          * With this condition, as we know the 'o_div' can't be smaller than 0, then we can calculate the APLL maximum support frequency is
131          * 500 MHz / ((0 + 2) * 2) = 125000000 Hz */
132         o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MAX_HZ / (float)(freq * 2)) - 2;
133         if (o_div < 0) {
134             ESP_HW_LOGE(TAG, "Expected frequency is too big");
135             return 0;
136         }
137     }
138     // sdm2 = (int)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4
139     sdm2 = (int)(((o_div + 2) * 2 * freq) / (rtc_xtal_freq * MHZ)) - 4;
140     // numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2
141     float numrator = (((o_div + 2) * 2 * freq) / ((float)rtc_xtal_freq * MHZ)) - 4 - sdm2;
142     // If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2
143     if (numrator > 1.0f - (1.0f / 65536.0f) / 2.0f) {
144         sdm2++;
145     }
146     // If numrator is smaller than (1/65536)/2, keep sdm0 = sdm1 = 0, otherwise calculate sdm0 and sdm1
147     else if (numrator > (1.0f / 65536.0f) / 2.0f) {
148         // Get the closest sdm1
149         sdm1 = (int)(numrator * 65536.0f + 0.5f) / 256;
150         // Get the closest sdm0
151         sdm0 = (int)(numrator * 65536.0f + 0.5f) % 256;
152     }
153     uint32_t real_freq = (uint32_t)(rtc_xtal_freq * MHZ * (4 + sdm2 + (float)sdm1/256.0f + (float)sdm0/65536.0f) / (((float)o_div + 2) * 2));
154     *_o_div = o_div;
155     *_sdm0 = sdm0;
156     *_sdm1 = sdm1;
157     *_sdm2 = sdm2;
158     return real_freq;
159 }
160 
rtc_clk_apll_coeff_set(uint32_t o_div,uint32_t sdm0,uint32_t sdm1,uint32_t sdm2)161 void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2)
162 {
163     clk_ll_apll_set_config(o_div, sdm0, sdm1, sdm2);
164 
165     /* calibration */
166     clk_ll_apll_set_calibration();
167 
168     /* wait for calibration end */
169     while (!clk_ll_apll_calibration_is_done()) {
170         /* use esp_rom_delay_us so the RTC bus doesn't get flooded */
171         esp_rom_delay_us(1);
172     }
173 }
174 
rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)175 void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
176 {
177     clk_ll_rtc_slow_set_src(clk_src);
178 
179     /* Why we need to connect this clock to digital?
180      * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
181      */
182     if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
183         clk_ll_xtal32k_digi_enable();
184     } else {
185         clk_ll_xtal32k_digi_disable();
186     }
187 
188     esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
189 }
190 
rtc_clk_slow_src_get(void)191 soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void)
192 {
193     return clk_ll_rtc_slow_get_src();
194 }
195 
rtc_clk_slow_freq_get_hz(void)196 uint32_t rtc_clk_slow_freq_get_hz(void)
197 {
198     switch (rtc_clk_slow_src_get()) {
199     case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX;
200     case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX;
201     case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX;
202     default: return 0;
203     }
204 }
205 
rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src)206 void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src)
207 {
208     clk_ll_rtc_fast_set_src(clk_src);
209     esp_rom_delay_us(SOC_DELAY_RTC_FAST_CLK_SWITCH);
210 }
211 
rtc_clk_fast_src_get(void)212 soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void)
213 {
214     return clk_ll_rtc_fast_get_src();
215 }
216 
rtc_clk_bbpll_disable(void)217 static void rtc_clk_bbpll_disable(void)
218 {
219     clk_ll_bbpll_disable();
220     s_cur_pll_freq = 0;
221 }
222 
rtc_clk_bbpll_enable(void)223 static void rtc_clk_bbpll_enable(void)
224 {
225     clk_ll_bbpll_enable();
226 }
227 
rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq,int pll_freq)228 static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
229 {
230     assert(xtal_freq == RTC_XTAL_FREQ_40M);
231 
232     /* Digital part */
233     clk_ll_bbpll_set_freq_mhz(pll_freq);
234     /* Analog part */
235     clk_ll_bbpll_set_config(pll_freq, xtal_freq);
236 
237     // Enable calibration by software
238     clk_ll_bbpll_calibration_enable();
239     for (int ext_cap = 0; ext_cap < 16; ext_cap++) {
240         if (clk_ll_bbpll_calibration_is_done(ext_cap)) {
241             break;
242         }
243         if (ext_cap == 15) {
244             ESP_HW_LOGE(TAG, "BBPLL SOFTWARE CAL FAIL");
245             abort();
246         }
247     }
248 
249     s_cur_pll_freq = pll_freq;
250 }
251 
252 /**
253  * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
254  * PLL must already be enabled.
255  * @param cpu_freq new CPU frequency
256  */
rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)257 static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
258 {
259     /* To avoid the problem of insufficient voltage when the CPU frequency is switched:
260      * When the CPU frequency is switched from low to high, it is necessary to
261      * increase the voltage first and then increase the frequency, and the frequency
262      * needs to wait for the voltage to fully increase before proceeding.
263      * When the frequency of the CPU is switched from high to low, it is necessary
264      * to reduce the frequency first and then reduce the voltage.
265      */
266 
267     rtc_cpu_freq_config_t cur_config;
268     rtc_clk_cpu_freq_get_config(&cur_config);
269     /* cpu_frequency < 240M: dbias = DIG_DBIAS_XTAL_80M_160M;
270      * cpu_frequency = 240M: dbias = DIG_DBIAS_240M;
271      */
272     if (cpu_freq_mhz > cur_config.freq_mhz) {
273         if (cpu_freq_mhz == 240) {
274             REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M);
275             REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_DBIAS_240M);
276             esp_rom_delay_us(40);
277         }
278     }
279 
280     clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz);
281     clk_ll_cpu_set_divider(1);
282     clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL);
283     rtc_clk_apb_freq_update(80 * MHZ);
284     esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
285 
286     if (cpu_freq_mhz < cur_config.freq_mhz) {
287         if (cur_config.freq_mhz == 240) {
288             REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL_80M_160M);
289             REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_DBIAS_XTAL_80M_160M);
290             esp_rom_delay_us(40);
291         }
292     }
293 
294 }
295 
rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz,rtc_cpu_freq_config_t * out_config)296 bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* out_config)
297 {
298     uint32_t source_freq_mhz;
299     soc_cpu_clk_src_t source;
300     uint32_t divider;
301     uint32_t real_freq_mhz;
302 
303     uint32_t xtal_freq = CLK_LL_XTAL_FREQ_MHZ;
304     if (freq_mhz <= xtal_freq && freq_mhz != 0) {
305         divider = xtal_freq / freq_mhz;
306         real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */
307         if (real_freq_mhz != freq_mhz) {
308             // no suitable divider
309             return false;
310         }
311 
312         source_freq_mhz = xtal_freq;
313         source = SOC_CPU_CLK_SRC_XTAL;
314     } else if (freq_mhz == 80) {
315         real_freq_mhz = freq_mhz;
316         source = SOC_CPU_CLK_SRC_PLL;
317         source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
318         divider = 6;
319     } else if (freq_mhz == 160) {
320         real_freq_mhz = freq_mhz;
321         source = SOC_CPU_CLK_SRC_PLL;
322         source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
323         divider = 3;
324     } else if (freq_mhz == 240) {
325         real_freq_mhz = freq_mhz;
326         source = SOC_CPU_CLK_SRC_PLL;
327         source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
328         divider = 2;
329     } else {
330         // unsupported frequency
331         return false;
332     }
333     *out_config = (rtc_cpu_freq_config_t) {
334         .source = source,
335         .div = divider,
336         .source_freq_mhz = source_freq_mhz,
337         .freq_mhz = real_freq_mhz
338     };
339     return true;
340 }
341 
rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t * config)342 void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t* config)
343 {
344     soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
345     if (old_cpu_clk_src != SOC_CPU_CLK_SRC_XTAL) {
346         rtc_clk_cpu_freq_to_xtal(CLK_LL_XTAL_FREQ_MHZ, 1);
347     }
348     if (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL && config->source_freq_mhz != s_cur_pll_freq) {
349         rtc_clk_bbpll_disable();
350     }
351 
352     if (config->source == SOC_CPU_CLK_SRC_XTAL) {
353         if (config->div > 1) {
354             rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
355         }
356     } else if (config->source == SOC_CPU_CLK_SRC_PLL) {
357         rtc_clk_bbpll_enable();
358         rtc_clk_bbpll_configure((rtc_xtal_freq_t)CLK_LL_XTAL_FREQ_MHZ, config->source_freq_mhz);
359         rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
360     } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
361         rtc_clk_cpu_freq_to_8m();
362     }
363 }
364 
rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t * out_config)365 void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t* out_config)
366 {
367     soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
368     uint32_t source_freq_mhz;
369     uint32_t div;
370     uint32_t freq_mhz;
371     switch (source) {
372         case SOC_CPU_CLK_SRC_XTAL: {
373             div = clk_ll_cpu_get_divider();
374             source_freq_mhz = CLK_LL_XTAL_FREQ_MHZ;
375             freq_mhz = source_freq_mhz / div;
376         }
377         break;
378         case SOC_CPU_CLK_SRC_PLL: {
379             freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll();
380             source_freq_mhz = clk_ll_bbpll_get_freq_mhz();
381             if (freq_mhz == CLK_LL_PLL_80M_FREQ_MHZ) {
382                 div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 6 : 4;
383             } else if (freq_mhz == CLK_LL_PLL_160M_FREQ_MHZ) {
384                 div = (source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) ? 3 : 2;
385             } else if (freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ && source_freq_mhz == CLK_LL_PLL_480M_FREQ_MHZ) {
386                 div = 2;
387             } else {
388                 ESP_HW_LOGE(TAG, "unsupported frequency configuration");
389                 abort();
390             }
391             break;
392         }
393         case SOC_CPU_CLK_SRC_RC_FAST:
394             source_freq_mhz = 8;
395             div = 1;
396             freq_mhz = source_freq_mhz;
397             break;
398         case SOC_CPU_CLK_SRC_APLL:
399         default:
400             ESP_HW_LOGE(TAG, "unsupported frequency configuration");
401             abort();
402     }
403     *out_config = (rtc_cpu_freq_config_t) {
404         .source = source,
405         .source_freq_mhz = source_freq_mhz,
406         .div = div,
407         .freq_mhz = freq_mhz
408     };
409 }
410 
rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t * config)411 void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t* config)
412 {
413     if (config->source == SOC_CPU_CLK_SRC_XTAL) {
414         rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
415     } else if (config->source == SOC_CPU_CLK_SRC_PLL &&
416             s_cur_pll_freq == config->source_freq_mhz) {
417         rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
418     } else {
419         /* fallback */
420         rtc_clk_cpu_freq_set_config(config);
421     }
422 }
423 
rtc_clk_cpu_freq_set_xtal(void)424 void rtc_clk_cpu_freq_set_xtal(void)
425 {
426     rtc_clk_cpu_set_to_default_config();
427     /* BBPLL is kept enabled */
428 }
429 
rtc_clk_cpu_set_to_default_config(void)430 void rtc_clk_cpu_set_to_default_config(void)
431 {
432     rtc_clk_cpu_freq_to_xtal(CLK_LL_XTAL_FREQ_MHZ, 1);
433 }
434 
435 /**
436  * Switch to use XTAL as the CPU clock source.
437  * Must satisfy: cpu_freq = XTAL_FREQ / div.
438  * Does not disable the PLL.
439  */
rtc_clk_cpu_freq_to_xtal(int cpu_freq,int div)440 static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
441 {
442     rtc_cpu_freq_config_t cur_config;
443     rtc_clk_cpu_freq_get_config(&cur_config);
444 
445     esp_rom_set_cpu_ticks_per_us(cpu_freq);
446     /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */
447     clk_ll_cpu_set_divider(1);
448     clk_ll_cpu_set_divider(div);
449     /* no need to adjust the REF_TICK, default register value already set it to 1MHz with any cpu clock source */
450     /* switch clock source */
451     clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
452     rtc_clk_apb_freq_update(cpu_freq * MHZ);
453 
454     /* lower the voltage
455      * cpu_frequency < 240M: dbias = DIG_DBIAS_XTAL_80M_160M;
456      * cpu_frequency = 240M: dbias = DIG_DBIAS_240M;
457      */
458     if (cur_config.freq_mhz == 240) {
459         REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL_80M_160M);
460         REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_DBIAS_XTAL_80M_160M);
461         esp_rom_delay_us(40);
462     }
463 
464 }
465 
rtc_clk_cpu_freq_to_8m(void)466 static void rtc_clk_cpu_freq_to_8m(void)
467 {
468     assert(0 && "LDO dbias need to modified");
469     esp_rom_set_cpu_ticks_per_us(8);
470     REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL);
471     esp_rom_delay_us(40);
472     clk_ll_cpu_set_divider(1);
473     clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
474     rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX);
475 }
476 
rtc_clk_xtal_freq_get(void)477 rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
478 {
479     // Note, inside esp32s2-only code it's better to use CLK_LL_XTAL_FREQ_MHZ constant
480     return (rtc_xtal_freq_t)CLK_LL_XTAL_FREQ_MHZ;
481 }
482 
rtc_clk_apb_freq_update(uint32_t apb_freq)483 void rtc_clk_apb_freq_update(uint32_t apb_freq)
484 {
485     clk_ll_apb_store_freq_hz(apb_freq);
486 }
487 
rtc_clk_apb_freq_get(void)488 uint32_t rtc_clk_apb_freq_get(void)
489 {
490     return clk_ll_apb_load_freq_hz();
491 }
492 
rtc_clk_divider_set(uint32_t div)493 void rtc_clk_divider_set(uint32_t div)
494 {
495     clk_ll_rc_slow_set_divider(div + 1);
496 }
497 
rtc_clk_8m_divider_set(uint32_t div)498 void rtc_clk_8m_divider_set(uint32_t div)
499 {
500     clk_ll_rc_fast_set_divider(div + 1);
501 }
502 
rtc_dig_clk8m_enable(void)503 void rtc_dig_clk8m_enable(void)
504 {
505     clk_ll_rc_fast_digi_enable();
506     esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
507 }
508 
rtc_dig_clk8m_disable(void)509 void rtc_dig_clk8m_disable(void)
510 {
511     clk_ll_rc_fast_digi_disable();
512     esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
513 }
514 
rtc_dig_8m_enabled(void)515 bool rtc_dig_8m_enabled(void)
516 {
517     return clk_ll_rc_fast_digi_is_enabled();
518 }
519 
520 /* Name used in libphy.a:phy_chip_v7.o
521  * TODO: update the library to use rtc_clk_xtal_freq_get
522  */
523 rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));
524