1 /*
2  * SPDX-FileCopyrightText: 2020-2021 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 "esp32h2/rom/ets_sys.h"
14 #include "esp32h2/rom/rtc.h"
15 #include "esp32h2/rom/uart.h"
16 #include "esp32h2/rom/gpio.h"
17 #include "soc/rtc.h"
18 #include "i2c_bbpll.h"
19 #include "soc/rtc_cntl_reg.h"
20 #include "soc/efuse_reg.h"
21 #include "soc/syscon_reg.h"
22 #include "soc/system_reg.h"
23 #include "regi2c_ctrl.h"
24 #include "soc_log.h"
25 #include "rtc_clk_common.h"
26 #include "esp_rom_sys.h"
27 
28 static const char *TAG = "rtc_clk";
29 
30 #define RTC_PLL_FREQ_96M    96
31 #define RTC_OSC_FREQ_RC8M   18
32 #define DELAY_RTC_CLK_SWITCH 5
33 #define RTC_CNTL_ANA_CONF0_CAL_REG 0x6000e040
34 #define RTC_CNTL_ANA_CONF0_CAL_START BIT(2)
35 #define RTC_CNTL_ANA_CONF0_CAL_STOP BIT(3)
36 #define RTC_CNTL_ANA_CONF0_CAL_DONE BIT(24)
37 
38 // Current PLL frequency, in 96MHZ. Zero if PLL is not enabled.
39 static int s_cur_pll_freq;
40 
41 void rtc_clk_cpu_freq_to_8m(void);
42 static uint32_t rtc_clk_ahb_freq_set(uint32_t div);
43 
rtc_clk_32k_enable_internal(x32k_config_t cfg)44 void rtc_clk_32k_enable_internal(x32k_config_t cfg)
45 {
46     REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac);
47     REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres);
48     REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm);
49     REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf);
50     SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
51 }
52 
rtc_clk_32k_enable(bool enable)53 void rtc_clk_32k_enable(bool enable)
54 {
55     if (enable) {
56         /* need to hangup gpio0 & 1 before enable xtal_32k */
57         rtc_gpio_hangup(0);
58         rtc_gpio_hangup(1);
59         x32k_config_t cfg = X32K_CONFIG_DEFAULT();
60         rtc_clk_32k_enable_internal(cfg);
61     } else {
62         SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE);
63         CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
64     }
65 }
66 
rtc_clk_rc32k_dfreq(uint32_t dfreq)67 void rtc_clk_rc32k_dfreq(uint32_t dfreq)
68 {
69     REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_DFREQ, dfreq);
70 }
71 
rtc_clk_rc32k_enable(bool enable)72 void rtc_clk_rc32k_enable(bool enable)
73 {
74     rc32k_config_t cfg = RC32K_CONFIG_DEFAULT();
75     rtc_clk_rc32k_dfreq(cfg.dfreq);
76     REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG, RTC_CNTL_RC32K_XPD, enable);
77 }
78 
rtc_clk_32k_enable_external(void)79 void rtc_clk_32k_enable_external(void)
80 {
81     rtc_clk_32k_enable(true);
82 }
83 
rtc_clk_32k_bootstrap(uint32_t cycle)84 void rtc_clk_32k_bootstrap(uint32_t cycle)
85 {
86     /* No special bootstrapping needed for ESP32-H2, 'cycle' argument is to keep the signature
87      * same as for the ESP32. Just enable the XTAL here.
88      */
89     (void) cycle;
90     rtc_clk_32k_enable(true);
91 }
92 
rtc_clk_32k_enabled(void)93 bool rtc_clk_32k_enabled(void)
94 {
95     uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG);
96     /* If xtal xpd is controlled by software */
97     bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S;
98     /* If xtal xpd software control is on */
99     bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S;
100     bool disabled = xtal_xpd_sw && !xtal_xpd_st;
101     return !disabled;
102 }
103 
rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)104 void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
105 {
106     REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq);
107     rtc_clk_32k_enable((slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0);
108     rtc_clk_rc32k_enable((slow_freq == RTC_SLOW_FREQ_RC32K) ? 1 : 0);
109     esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH);
110 }
111 
rtc_clk_slow_freq_get(void)112 rtc_slow_freq_t rtc_clk_slow_freq_get(void)
113 {
114     return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
115 }
116 
rtc_clk_slow_freq_get_hz(void)117 uint32_t rtc_clk_slow_freq_get_hz(void)
118 {
119     switch (rtc_clk_slow_freq_get()) {
120     case RTC_SLOW_FREQ_RTC: return RTC_SLOW_CLK_FREQ_150K;
121     case RTC_SLOW_FREQ_32K_XTAL: return RTC_SLOW_CLK_FREQ_32K;
122     case RTC_SLOW_FREQ_RC32K: return RTC_SLOW_CLK_FREQ_RC32;
123     }
124     return 0;
125 }
126 
rtc_clk_fast_freq_set(rtc_fast_freq_t fast_freq)127 void rtc_clk_fast_freq_set(rtc_fast_freq_t fast_freq)
128 {
129     REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq);
130     esp_rom_delay_us(DELAY_FAST_CLK_SWITCH);
131 }
132 
rtc_clk_fast_freq_get(void)133 rtc_fast_freq_t rtc_clk_fast_freq_get(void)
134 {
135     return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL);
136 }
137 
rtc_clk_bbpll_disable(void)138 static void rtc_clk_bbpll_disable(void)
139 {
140     SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
141                       RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
142     s_cur_pll_freq = 0;
143 }
144 
rtc_clk_bbpll_enable(void)145 static void rtc_clk_bbpll_enable(void)
146 {
147     CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
148                         RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
149 }
rtc_clk_bbpll_cali_stop(void)150 static void rtc_clk_bbpll_cali_stop(void)
151 {
152     while (!REG_GET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_DONE));
153     REG_CLR_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_STOP);
154     REG_SET_BIT(RTC_CNTL_ANA_CONF0_CAL_REG, RTC_CNTL_ANA_CONF0_CAL_START);
155 
156 }
157 
rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq,int pll_freq)158 void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
159 {
160     uint8_t div_ref;
161     uint8_t div5_0;
162     if ((pll_freq == RTC_PLL_FREQ_96M) && (xtal_freq == RTC_XTAL_FREQ_32M)) {
163         /* Configure 96M PLL */
164         div_ref = 0;
165         div5_0 = 1;
166     } else {
167         div_ref = 0;
168         div5_0 = 1;
169         SOC_LOGE(TAG, "invalid pll frequency");
170     }
171 
172     REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, div_ref);
173     REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DIV, div5_0); //I2C_BBPLL_OC_DIV_5_0
174     REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 3); // need update to 3 since s2
175     REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1);
176     s_cur_pll_freq = pll_freq;
177 }
178 
179 /**
180  * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
181  * PLL must already be enabled.
182  * @param cpu_freq new CPU frequency
183  */
rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)184 static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
185 {
186     int div = 1;
187     if (RTC_PLL_FREQ_96M % cpu_freq_mhz == 0) {
188         div = RTC_PLL_FREQ_96M / cpu_freq_mhz;
189     } else {
190         SOC_LOGE(TAG, "invalid frequency");
191         abort();
192     }
193     rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_PLL, div - 1);
194     if (cpu_freq_mhz > RTC_XTAL_FREQ_32M) {
195         rtc_clk_ahb_freq_set(2);
196     } else {
197         rtc_clk_ahb_freq_set(1);
198     }
199 
200     rtc_clk_apb_freq_update(rtc_clk_apb_freq_get());
201     ets_update_cpu_frequency(cpu_freq_mhz);
202 }
203 
rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz,rtc_cpu_freq_config_t * out_config)204 bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
205 {
206     uint32_t source_freq_mhz;
207     rtc_cpu_freq_src_t source;
208     uint32_t divider;
209     uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get();
210     if (freq_mhz > xtal_freq) {
211         source = RTC_CPU_FREQ_SRC_PLL;
212         source_freq_mhz = RTC_PLL_FREQ_96M;
213         divider = RTC_PLL_FREQ_96M / freq_mhz;
214         rtc_clk_ahb_freq_set(2);
215     } else {
216         source = root_clk_get();
217         source_freq_mhz = root_clk_slt(source);
218         divider = source_freq_mhz / freq_mhz;
219         rtc_clk_ahb_freq_set(1);
220     }
221     *out_config = (rtc_cpu_freq_config_t) {
222         .source = source,
223         .div = divider,
224         .source_freq_mhz = source_freq_mhz,
225         .freq_mhz = freq_mhz
226     };
227     return true;
228 }
229 
rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t * config)230 void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
231 {
232     uint32_t src_freq_mhz = root_clk_slt(config->source);
233     uint32_t div = src_freq_mhz / (config->freq_mhz);
234     rtc_clk_cpu_freq_set(config->source, div);
235 }
236 
rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t * out_config)237 void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
238 {
239     rtc_cpu_freq_src_t source;
240     uint32_t source_freq_mhz;
241     uint32_t div;
242     uint32_t freq_mhz;
243     uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
244     switch (soc_clk_sel) {
245     case DPORT_SOC_CLK_SEL_XTAL: {
246         source = RTC_CPU_FREQ_SRC_XTAL;
247         div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1;
248         source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get();
249         freq_mhz = source_freq_mhz / div;
250         break;
251     }
252     case DPORT_SOC_CLK_SEL_PLL: {
253         source = RTC_CPU_FREQ_SRC_PLL;
254         div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1;
255         source_freq_mhz = RTC_PLL_FREQ_96M;
256         freq_mhz = source_freq_mhz / div;
257         break;
258     }
259     case DPORT_SOC_CLK_SEL_8M: {
260         source = RTC_CPU_FREQ_SRC_8M;
261         source_freq_mhz = RTC_OSC_FREQ_RC8M;
262         div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1;
263         freq_mhz = source_freq_mhz / div;
264         break;
265     }
266     case DPORT_SOC_CLK_SEL_XTAL_D2: {
267         source = RTC_CPU_FREQ_SRC_XTAL_D2;
268         div = REG_GET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1;
269         source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get();
270         freq_mhz = source_freq_mhz / div / 2;
271         break;
272     }
273     default: {
274         SOC_LOGE(TAG, "unsupported frequency configuration");
275         abort();
276     }
277     }
278     *out_config = (rtc_cpu_freq_config_t) {
279         .source = source,
280         .source_freq_mhz = source_freq_mhz,
281         .div = div,
282         .freq_mhz = freq_mhz
283     };
284 }
285 
rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t * config)286 void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
287 {
288     if (config->source == RTC_CPU_FREQ_SRC_XTAL) {
289         rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
290     } else if (config->source == RTC_CPU_FREQ_SRC_PLL &&
291                s_cur_pll_freq == config->source_freq_mhz) {
292         rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
293     } else {
294         /* fallback */
295         rtc_clk_cpu_freq_set_config(config);
296     }
297 }
298 
rtc_clk_cpu_freq_set_xtal(void)299 void rtc_clk_cpu_freq_set_xtal(void)
300 {
301     int freq_mhz = (int) rtc_clk_xtal_freq_get();
302     rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
303     rtc_clk_bbpll_disable();
304 }
305 
306 /**
307  * Switch to XTAL frequency. Does not disable the PLL.
308  */
rtc_clk_cpu_freq_to_xtal(int freq,int div)309 void rtc_clk_cpu_freq_to_xtal(int freq, int div)
310 {
311     ets_update_cpu_frequency(freq);
312     /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */
313     rtc_clk_cpu_freq_set(DPORT_SOC_CLK_SEL_XTAL, div);
314     /* no need to adjust the REF_TICK */
315     /* switch clock source */
316     rtc_clk_apb_freq_update(rtc_clk_apb_freq_get());
317 }
318 
rtc_clk_cpu_freq_to_8m(void)319 void rtc_clk_cpu_freq_to_8m(void)
320 {
321     ets_update_cpu_frequency(RTC_OSC_FREQ_RC8M);
322     root_clk_slt(DPORT_SOC_CLK_SEL_8M);
323     rtc_clk_apb_freq_update(rtc_clk_apb_freq_get());
324 }
325 
rtc_clk_xtal_freq_get(void)326 rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
327 {
328     uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG);
329     if (!clk_val_is_valid(xtal_freq_reg)) {
330         SOC_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg);
331         return RTC_XTAL_FREQ_32M;
332     }
333     return reg_val_to_clk_val(xtal_freq_reg);
334 }
335 
rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)336 void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
337 {
338     WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq));
339 }
340 
rtc_clk_apb_freq_update(uint32_t apb_freq)341 void rtc_clk_apb_freq_update(uint32_t apb_freq)
342 {
343     WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12));
344 }
345 
346 
rtc_clk_apb_freq_get(void)347 uint32_t rtc_clk_apb_freq_get(void)
348 {
349     uint32_t apb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM) + 1;
350     return rtc_clk_ahb_freq_get() / apb_div;
351 }
352 
rtc_clk_ahb_freq_get()353 uint32_t rtc_clk_ahb_freq_get()
354 {
355     rtc_cpu_freq_config_t cpu_config;
356     uint32_t ahb_div = REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM) + 1;
357     rtc_clk_cpu_freq_get_config(&cpu_config) ;
358     return   cpu_config.freq_mhz / ahb_div;
359 }
360 
rtc_clk_ahb_freq_set(uint32_t div)361 uint32_t rtc_clk_ahb_freq_set(uint32_t div)
362 {
363     REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM, div - 1);
364     return rtc_clk_ahb_freq_get();
365 }
366 
rtc_clk_apb_freq_set(uint32_t div)367 uint32_t rtc_clk_apb_freq_set(uint32_t div)
368 {
369     REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM, div - 1);
370     return rtc_clk_apb_freq_get();
371 }
372 
rtc_clk_cpu_freq_set(uint32_t source,uint32_t div)373 void rtc_clk_cpu_freq_set(uint32_t source, uint32_t div)
374 {
375     if (root_clk_get() != source) {
376         root_clk_slt(source);
377     }
378     REG_SET_FIELD(SYSTEM_CPUCLK_CONF_REG, SYSTEM_CPU_DIV_NUM, div - 1);
379 }
380 
rtc_clk_divider_set(uint32_t div)381 void rtc_clk_divider_set(uint32_t div)
382 {
383     CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
384     REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div - 1);
385     SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
386 }
387 
rtc_clk_8m_divider_set(uint32_t div)388 void rtc_clk_8m_divider_set(uint32_t div)
389 {
390     CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
391     REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div - 1);
392     SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
393 }
394 
rtc_dig_clk8m_enable(void)395 void rtc_dig_clk8m_enable(void)
396 {
397     SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN);
398     esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
399 }
400 
rtc_dig_clk8m_disable(void)401 void rtc_dig_clk8m_disable(void)
402 {
403     CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN);
404     esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
405 }
406 
read_spll_freq(void)407 uint32_t read_spll_freq(void)
408 {
409     return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SPLL_FREQ);
410 }
411 
read_xtal_freq(void)412 uint32_t read_xtal_freq(void)
413 {
414     return REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_CLK_XTAL_FREQ);
415 }
416 
417 /* Select clock root source for esp32h2. return source clk freq_mhz
418  */
root_clk_slt(uint32_t source)419 uint32_t root_clk_slt(uint32_t source)
420 {
421     uint32_t root_clk_freq_mhz;
422     switch (source) {
423     case RTC_CPU_FREQ_SRC_XTAL:
424         root_clk_freq_mhz = RTC_XTAL_FREQ_32M;
425         rtc_clk_bbpll_disable();
426         break;
427     case RTC_CPU_FREQ_SRC_PLL:
428         // SPLL_ENABLE
429         root_clk_freq_mhz = RTC_PLL_FREQ_96M;
430         rtc_clk_bbpll_enable();
431         rtc_clk_bbpll_configure(RTC_XTAL_FREQ_32M, root_clk_freq_mhz);
432         rtc_clk_bbpll_cali_stop();
433         break;
434     case RTC_CPU_FREQ_SRC_8M:
435         root_clk_freq_mhz = RTC_OSC_FREQ_RC8M;
436         rtc_dig_clk8m_enable();
437         rtc_clk_8m_divider_set(1);
438         rtc_clk_bbpll_disable();
439         break;
440     case RTC_CPU_FREQ_SRC_XTAL_D2:
441         root_clk_freq_mhz = RTC_XTAL_FREQ_32M / 2;
442         rtc_clk_bbpll_disable();
443         break;
444     default:
445         SOC_LOGE(TAG, "unsupported source clk configuration");
446         root_clk_freq_mhz = RTC_XTAL_FREQ_32M;
447         rtc_clk_bbpll_disable();
448         source = 0;
449         break;
450     }
451     REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, source);
452     return root_clk_freq_mhz;
453 }
454 
root_clk_get()455 uint32_t root_clk_get()
456 {
457     uint32_t src_slt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
458     return src_slt;
459 }
460 
461 /* Name used in libphy.a:phy_chip_v7.o
462  * TODO: update the library to use rtc_clk_xtal_freq_get
463  */
464 rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));
465