1 /*
2 * SPDX-FileCopyrightText: 2015-2022 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 <stdlib.h>
11 #include "soc/rtc.h"
12 #include "esp_private/rtc_clk.h"
13 #include "soc/rtc_periph.h"
14 #include "soc/sens_periph.h"
15 #include "soc/soc_caps.h"
16 #include "soc/chip_revision.h"
17 #include "hal/efuse_ll.h"
18 #include "hal/efuse_hal.h"
19 #include "soc/gpio_struct.h"
20 #include "hal/gpio_ll.h"
21 #include "esp_hw_log.h"
22 #include "sdkconfig.h"
23 #include "esp_rom_sys.h"
24 #include "esp_rom_gpio.h"
25 #include "esp32/rom/rtc.h"
26 #include "hal/clk_tree_ll.h"
27 #include "soc/rtc_cntl_reg.h"
28 #include "soc/io_mux_reg.h"
29
30 #define XTAL_32K_BOOTSTRAP_TIME_US 7
31
32 static void rtc_clk_cpu_freq_to_8m(void);
33 static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz);
34
35 // Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
36 static uint32_t s_cur_pll_freq;
37
38 static const char* TAG = "rtc_clk";
39
rtc_clk_32k_enable_common(clk_ll_xtal32k_enable_mode_t mode)40 static void rtc_clk_32k_enable_common(clk_ll_xtal32k_enable_mode_t mode)
41 {
42 CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG,
43 RTC_IO_X32P_RDE | RTC_IO_X32P_RUE | RTC_IO_X32N_RUE |
44 RTC_IO_X32N_RDE | RTC_IO_X32N_FUN_IE | RTC_IO_X32P_FUN_IE);
45 SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
46
47 #ifdef CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT
48 // version0 and version1 need provide additional current to external XTAL.
49 if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 200)) {
50 /* TOUCH sensor can provide additional current to external XTAL.
51 In some case, X32N and X32P PAD don't have enough drive capability to start XTAL */
52 SET_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M);
53 /* Tie PAD Touch8 to VDD
54 NOTE: TOUCH8 and TOUCH9 register settings are reversed except for DAC, so we set RTC_IO_TOUCH_PAD9_REG here instead*/
55 SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_TIE_OPT_M);
56 /* Set the current used to compensate TOUCH PAD8 */
57 SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 4, RTC_IO_TOUCH_PAD8_DAC_S);
58 /* Power up TOUCH8
59 So the Touch DAC start to drive some current from VDD to TOUCH8(which is also XTAL-N)*/
60 SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
61 }
62 #elif defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT_V2
63 if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 200)) {
64 /* TOUCH sensor can provide additional current to external XTAL.
65 In some case, X32N and X32P PAD don't have enough drive capability to start XTAL */
66 SET_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M);
67 SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_DCUR, 3, RTC_IO_TOUCH_DCUR_S);
68 CLEAR_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FSM_EN_M);
69 /* Tie PAD Touch8 to VDD
70 NOTE: TOUCH8 and TOUCH9 register settings are reversed except for DAC, so we set RTC_IO_TOUCH_PAD9_REG here instead
71 */
72 SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_TIE_OPT_M);
73 /* Set the current used to compensate TOUCH PAD8 */
74 SET_PERI_REG_BITS(RTC_IO_TOUCH_PAD8_REG, RTC_IO_TOUCH_PAD8_DAC, 1, RTC_IO_TOUCH_PAD8_DAC_S);
75 /* Power up TOUCH8
76 So the Touch DAC start to drive some current from VDD to TOUCH8(which is also XTAL-N)
77 */
78 SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
79 CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_START_M);
80 }
81 #endif
82
83 clk_ll_xtal32k_enable(mode);
84 }
85
rtc_clk_32k_enable(bool enable)86 void rtc_clk_32k_enable(bool enable)
87 {
88 if (enable) {
89 rtc_clk_32k_enable_common(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL);
90 } else {
91 clk_ll_xtal32k_disable();
92 /* Disable X32N and X32P pad drive external xtal */
93 CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
94
95 #ifdef CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT
96 if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 200)) {
97 /* Power down TOUCH */
98 CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
99 }
100 #elif defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT_V2
101 if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 200)) {
102 /* Power down TOUCH */
103 CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_XPD_BIAS_M);
104 SET_PERI_REG_BITS(RTC_IO_TOUCH_CFG_REG, RTC_IO_TOUCH_DCUR, 0, RTC_IO_TOUCH_DCUR_S);
105 CLEAR_PERI_REG_MASK(RTC_IO_TOUCH_PAD9_REG, RTC_IO_TOUCH_PAD9_XPD_M);
106 SET_PERI_REG_MASK(SENS_SAR_TOUCH_CTRL2_REG, SENS_TOUCH_START_FSM_EN_M);
107 }
108 #endif
109 }
110 }
111
rtc_clk_32k_enable_external(void)112 void rtc_clk_32k_enable_external(void)
113 {
114 rtc_clk_32k_enable_common(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL);
115 }
116
117 /* Helping external 32kHz crystal to start up.
118 * External crystal connected to outputs GPIO32 GPIO33.
119 * Forms N pulses with a frequency of about 32KHz on the outputs of the crystal.
120 */
rtc_clk_32k_bootstrap(uint32_t cycle)121 void rtc_clk_32k_bootstrap(uint32_t cycle)
122 {
123 if (cycle){
124 esp_rom_gpio_pad_select_gpio(XTAL32K_P_GPIO_NUM);
125 esp_rom_gpio_pad_select_gpio(XTAL32K_N_GPIO_NUM);
126 gpio_ll_output_enable(&GPIO, XTAL32K_P_GPIO_NUM);
127 gpio_ll_output_enable(&GPIO, XTAL32K_N_GPIO_NUM);
128 gpio_ll_set_level(&GPIO, XTAL32K_P_GPIO_NUM, 1);
129 gpio_ll_set_level(&GPIO, XTAL32K_N_GPIO_NUM, 0);
130
131 const uint32_t delay_us = (1000000 / SOC_CLK_XTAL32K_FREQ_APPROX / 2);
132 while (cycle) {
133 gpio_ll_set_level(&GPIO, XTAL32K_P_GPIO_NUM, 1);
134 gpio_ll_set_level(&GPIO, XTAL32K_N_GPIO_NUM, 0);
135 esp_rom_delay_us(delay_us);
136 gpio_ll_set_level(&GPIO, XTAL32K_N_GPIO_NUM, 1);
137 gpio_ll_set_level(&GPIO, XTAL32K_P_GPIO_NUM, 0);
138 esp_rom_delay_us(delay_us);
139 cycle--;
140 }
141 // disable pins
142 gpio_ll_output_disable(&GPIO, XTAL32K_P_GPIO_NUM);
143 gpio_ll_output_disable(&GPIO, XTAL32K_N_GPIO_NUM);
144 }
145
146 clk_ll_xtal32k_disable();
147 SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_RUE | RTC_IO_X32N_RDE);
148 esp_rom_delay_us(XTAL_32K_BOOTSTRAP_TIME_US);
149
150 rtc_clk_32k_enable_common(CLK_LL_XTAL32K_ENABLE_MODE_BOOTSTRAP);
151 }
152
rtc_clk_32k_enabled(void)153 bool rtc_clk_32k_enabled(void)
154 {
155 return clk_ll_xtal32k_is_enabled();
156 }
157
rtc_clk_8m_enable(bool clk_8m_en,bool d256_en)158 void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
159 {
160 if (clk_8m_en) {
161 clk_ll_rc_fast_enable();
162 if (d256_en) {
163 clk_ll_rc_fast_d256_enable();
164 } else {
165 clk_ll_rc_fast_d256_disable();
166 }
167 esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE);
168 } else {
169 clk_ll_rc_fast_disable();
170 }
171 }
172
rtc_clk_8m_enabled(void)173 bool rtc_clk_8m_enabled(void)
174 {
175 return clk_ll_rc_fast_is_enabled();
176 }
177
rtc_clk_8md256_enabled(void)178 bool rtc_clk_8md256_enabled(void)
179 {
180 return clk_ll_rc_fast_d256_is_enabled();
181 }
182
rtc_clk_apll_enable(bool enable)183 void rtc_clk_apll_enable(bool enable)
184 {
185 if (enable) {
186 clk_ll_apll_enable();
187 } else {
188 clk_ll_apll_disable();
189 }
190
191 if (!enable && (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL)) {
192 // if apll and bbpll are both not in use, then can also power down the internal I2C bus
193 // this power down affects most of the analog peripherals
194 clk_ll_i2c_pd();
195 } else {
196 clk_ll_i2c_pu();
197 }
198 }
199
rtc_clk_apll_coeff_calc(uint32_t freq,uint32_t * _o_div,uint32_t * _sdm0,uint32_t * _sdm1,uint32_t * _sdm2)200 uint32_t rtc_clk_apll_coeff_calc(uint32_t freq, uint32_t *_o_div, uint32_t *_sdm0, uint32_t *_sdm1, uint32_t *_sdm2)
201 {
202 uint32_t xtal_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get();
203 if (xtal_freq_mhz == 0) {
204 // xtal_freq has not set yet
205 ESP_HW_LOGE(TAG, "Get xtal clock frequency failed, it has not been set yet");
206 abort();
207 }
208 /* Reference formula: apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) / ((o_div + 2) * 2)
209 * ---------------------------------------------- -----------------
210 * 350 MHz <= Numerator <= 500 MHz Denominator
211 */
212 int o_div = 0; // range: 0~31
213 int sdm0 = 0; // range: 0~255
214 int sdm1 = 0; // range: 0~255
215 int sdm2 = 0; // range: 0~63
216 /* Firstly try to satisfy the condition that the operation frequency of numerator should be greater than 350 MHz,
217 * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= 350 MHz, '+1' in the following code is to get the ceil value.
218 * 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
219 * 350 MHz / ((31 + 2) * 2) = 5303031 Hz (for ceil) */
220 o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MIN_HZ / (float)(freq * 2) + 1) - 2;
221 if (o_div > 31) {
222 ESP_HW_LOGE(TAG, "Expected frequency is too small");
223 return 0;
224 }
225 if (o_div < 0) {
226 /* Try to satisfy the condition that the operation frequency of numerator should be smaller than 500 MHz,
227 * i.e. xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) <= 500 MHz, we need to get the floor value in the following code.
228 * 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
229 * 500 MHz / ((0 + 2) * 2) = 125000000 Hz */
230 o_div = (int)(SOC_APLL_MULTIPLIER_OUT_MAX_HZ / (float)(freq * 2)) - 2;
231 if (o_div < 0) {
232 ESP_HW_LOGE(TAG, "Expected frequency is too big");
233 return 0;
234 }
235 }
236 // sdm2 = (int)(((o_div + 2) * 2) * apll_freq / xtal_freq) - 4
237 sdm2 = (int)(((o_div + 2) * 2 * freq) / (xtal_freq_mhz * MHZ)) - 4;
238 // numrator = (((o_div + 2) * 2) * apll_freq / xtal_freq) - 4 - sdm2
239 float numrator = (((o_div + 2) * 2 * freq) / ((float)xtal_freq_mhz * MHZ)) - 4 - sdm2;
240 // If numrator is bigger than 255/256 + 255/65536 + (1/65536)/2 = 1 - (1 / 65536)/2, carry bit to sdm2
241 if (numrator > 1.0f - (1.0f / 65536.0f) / 2.0f) {
242 sdm2++;
243 }
244 // If numrator is smaller than (1/65536)/2, keep sdm0 = sdm1 = 0, otherwise calculate sdm0 and sdm1
245 else if (numrator > (1.0f / 65536.0f) / 2.0f) {
246 // Get the closest sdm1
247 sdm1 = (int)(numrator * 65536.0f + 0.5f) / 256;
248 // Get the closest sdm0
249 sdm0 = (int)(numrator * 65536.0f + 0.5f) % 256;
250 }
251 uint32_t real_freq = (uint32_t)(xtal_freq_mhz * MHZ * (4 + sdm2 + (float)sdm1/256.0f + (float)sdm0/65536.0f) / (((float)o_div + 2) * 2));
252 *_o_div = o_div;
253 *_sdm0 = sdm0;
254 *_sdm1 = sdm1;
255 *_sdm2 = sdm2;
256 return real_freq;
257 }
258
rtc_clk_apll_coeff_set(uint32_t o_div,uint32_t sdm0,uint32_t sdm1,uint32_t sdm2)259 void rtc_clk_apll_coeff_set(uint32_t o_div, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2)
260 {
261 bool is_rev0 = (efuse_ll_get_chip_ver_rev1() == 0);
262 clk_ll_apll_set_config(is_rev0, o_div, sdm0, sdm1, sdm2);
263
264 /* calibration */
265 clk_ll_apll_set_calibration();
266
267 /* wait for calibration end */
268 while (!clk_ll_apll_calibration_is_done()) {
269 /* use esp_rom_delay_us so the RTC bus doesn't get flooded */
270 esp_rom_delay_us(1);
271 }
272 }
273
rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)274 void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
275 {
276 clk_ll_rtc_slow_set_src(clk_src);
277
278 // The logic should be moved to BT driver
279 if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
280 clk_ll_xtal32k_digi_enable();
281 } else {
282 clk_ll_xtal32k_digi_disable();
283 }
284
285 esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
286 }
287
rtc_clk_slow_src_get(void)288 soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void)
289 {
290 return clk_ll_rtc_slow_get_src();
291 }
292
rtc_clk_slow_freq_get_hz(void)293 uint32_t rtc_clk_slow_freq_get_hz(void)
294 {
295 switch (rtc_clk_slow_src_get()) {
296 case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX;
297 case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX;
298 case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: return SOC_CLK_RC_FAST_D256_FREQ_APPROX;
299 default: return 0;
300 }
301 }
302
rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src)303 void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src)
304 {
305 clk_ll_rtc_fast_set_src(clk_src);
306 esp_rom_delay_us(SOC_DELAY_RTC_FAST_CLK_SWITCH);
307 }
308
rtc_clk_fast_src_get(void)309 soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void)
310 {
311 return clk_ll_rtc_fast_get_src();
312 }
313
rtc_clk_bbpll_disable(void)314 static void rtc_clk_bbpll_disable(void)
315 {
316 clk_ll_bbpll_disable();
317 s_cur_pll_freq = 0;
318
319 // if apll is under force power down, then can also power down the internal I2C bus
320 // this power down affects most of the analog peripherals
321 if (clk_ll_apll_is_fpd()) {
322 clk_ll_i2c_pd();
323 }
324 }
325
rtc_clk_bbpll_enable(void)326 static void rtc_clk_bbpll_enable(void)
327 {
328 clk_ll_i2c_pu();
329 clk_ll_bbpll_enable();
330 }
331
rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq,int pll_freq)332 static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
333 {
334 /* Raise the voltage */
335 if (pll_freq == CLK_LL_PLL_320M_FREQ_MHZ) {
336 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_80M_160M);
337 } else { // CLK_LL_PLL_480M_FREQ_MHZ
338 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M);
339 esp_rom_delay_us(SOC_DELAY_PLL_DBIAS_RAISE);
340 }
341
342 clk_ll_bbpll_set_config(pll_freq, xtal_freq);
343 uint32_t delay_pll_en = (clk_ll_rtc_slow_get_src() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ?
344 SOC_DELAY_PLL_ENABLE_WITH_150K : SOC_DELAY_PLL_ENABLE_WITH_32K;
345 esp_rom_delay_us(delay_pll_en);
346 s_cur_pll_freq = pll_freq;
347 }
348
349 /**
350 * Switch to use XTAL as the CPU clock source.
351 * Must satisfy: cpu_freq = XTAL_FREQ / div.
352 * Does not disable the PLL.
353 */
rtc_clk_cpu_freq_to_xtal(int cpu_freq,int div)354 void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
355 {
356 esp_rom_set_cpu_ticks_per_us(cpu_freq);
357 /* set divider from XTAL to APB clock */
358 clk_ll_cpu_set_divider(div);
359 /* adjust ref_tick */
360 clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_XTAL, cpu_freq);
361 /* switch clock source */
362 clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
363 rtc_clk_apb_freq_update(cpu_freq * MHZ);
364 /* lower the voltage */
365 int dbias = (cpu_freq <= 2) ? DIG_DBIAS_2M : DIG_DBIAS_XTAL;
366 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias);
367 }
368
rtc_clk_cpu_freq_to_8m(void)369 static void rtc_clk_cpu_freq_to_8m(void)
370 {
371 esp_rom_set_cpu_ticks_per_us(8);
372 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL);
373 clk_ll_cpu_set_divider(1);
374 /* adjust ref_tick */
375 clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_RC_FAST, 8);
376 /* switch clock source */
377 clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
378 rtc_clk_apb_freq_update(SOC_CLK_RC_FAST_FREQ_APPROX);
379 }
380
381 /**
382 * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
383 * PLL must already be enabled.
384 * @param cpu_freq new CPU frequency
385 */
rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)386 static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
387 {
388 int dbias = (cpu_freq_mhz == 240) ? DIG_DBIAS_240M : DIG_DBIAS_80M_160M;
389 clk_ll_cpu_set_freq_mhz_from_pll(cpu_freq_mhz);
390 REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias);
391 /* adjust ref_tick */
392 clk_ll_ref_tick_set_divider(SOC_CPU_CLK_SRC_PLL, cpu_freq_mhz);
393 /* switch clock source */
394 clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL);
395 rtc_clk_apb_freq_update(80 * MHZ);
396 esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
397 rtc_clk_wait_for_slow_cycle();
398 }
399
rtc_clk_cpu_freq_set_xtal(void)400 void rtc_clk_cpu_freq_set_xtal(void)
401 {
402 rtc_clk_cpu_set_to_default_config();
403 rtc_clk_bbpll_disable();
404 }
405
rtc_clk_cpu_set_to_default_config(void)406 void rtc_clk_cpu_set_to_default_config(void)
407 {
408 int freq_mhz = (int)rtc_clk_xtal_freq_get();
409
410 rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
411 rtc_clk_wait_for_slow_cycle();
412 }
413
rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz,rtc_cpu_freq_config_t * out_config)414 bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t* out_config)
415 {
416 uint32_t source_freq_mhz;
417 soc_cpu_clk_src_t source;
418 uint32_t divider;
419 uint32_t real_freq_mhz;
420
421 uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get();
422 if (freq_mhz <= xtal_freq && freq_mhz != 0) {
423 divider = xtal_freq / freq_mhz;
424 real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */
425 if (real_freq_mhz != freq_mhz) {
426 // no suitable divider
427 return false;
428 }
429
430 source_freq_mhz = xtal_freq;
431 source = SOC_CPU_CLK_SRC_XTAL;
432 } else if (freq_mhz == 80) {
433 real_freq_mhz = freq_mhz;
434 source = SOC_CPU_CLK_SRC_PLL;
435 source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ;
436 divider = 4;
437 } else if (freq_mhz == 160) {
438 real_freq_mhz = freq_mhz;
439 source = SOC_CPU_CLK_SRC_PLL;
440 source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ;
441 divider = 2;
442 } else if (freq_mhz == 240) {
443 real_freq_mhz = freq_mhz;
444 source = SOC_CPU_CLK_SRC_PLL;
445 source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
446 divider = 2;
447 } else {
448 // unsupported frequency
449 return false;
450 }
451 *out_config = (rtc_cpu_freq_config_t) {
452 .source = source,
453 .div = divider,
454 .source_freq_mhz = source_freq_mhz,
455 .freq_mhz = real_freq_mhz
456 };
457 return true;
458 }
459
rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t * config)460 void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t* config)
461 {
462 rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
463 soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
464 if (old_cpu_clk_src != SOC_CPU_CLK_SRC_XTAL) {
465 rtc_clk_cpu_freq_to_xtal(xtal_freq, 1);
466 rtc_clk_wait_for_slow_cycle();
467 }
468 if (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) {
469 rtc_clk_bbpll_disable();
470 }
471
472 if (config->source == SOC_CPU_CLK_SRC_XTAL) {
473 if (config->div > 1) {
474 rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
475 }
476 } else if (config->source == SOC_CPU_CLK_SRC_PLL) {
477 rtc_clk_bbpll_enable();
478 rtc_clk_wait_for_slow_cycle();
479 rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
480 rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
481 } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
482 rtc_clk_cpu_freq_to_8m();
483 }
484 }
485
rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t * out_config)486 void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t* out_config)
487 {
488 soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
489 uint32_t source_freq_mhz;
490 uint32_t div;
491 uint32_t freq_mhz;
492 switch (source) {
493 case SOC_CPU_CLK_SRC_XTAL: {
494 div = clk_ll_cpu_get_divider();
495 source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get();
496 freq_mhz = source_freq_mhz / div;
497 }
498 break;
499 case SOC_CPU_CLK_SRC_PLL: {
500 freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll();
501 if (freq_mhz == CLK_LL_PLL_80M_FREQ_MHZ) {
502 source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ;
503 div = 4;
504 } else if (freq_mhz == CLK_LL_PLL_160M_FREQ_MHZ) {
505 source_freq_mhz = CLK_LL_PLL_320M_FREQ_MHZ;
506 div = 2;
507 } else if (freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ) {
508 source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
509 div = 2;
510 } else {
511 ESP_HW_LOGE(TAG, "unsupported frequency configuration");
512 abort();
513 }
514 break;
515 }
516 case SOC_CPU_CLK_SRC_RC_FAST:
517 source_freq_mhz = 8;
518 div = 1;
519 freq_mhz = source_freq_mhz;
520 break;
521 case SOC_CPU_CLK_SRC_APLL:
522 default:
523 ESP_HW_LOGE(TAG, "unsupported frequency configuration");
524 abort();
525 }
526 *out_config = (rtc_cpu_freq_config_t) {
527 .source = source,
528 .source_freq_mhz = source_freq_mhz,
529 .div = div,
530 .freq_mhz = freq_mhz
531 };
532 }
533
rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t * config)534 void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t* config)
535 {
536 if (config->source == SOC_CPU_CLK_SRC_XTAL) {
537 rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
538 } else if (config->source == SOC_CPU_CLK_SRC_PLL &&
539 s_cur_pll_freq == config->source_freq_mhz) {
540 rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
541 } else {
542 /* fallback */
543 rtc_clk_cpu_freq_set_config(config);
544 }
545 }
546
rtc_clk_xtal_freq_get(void)547 rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
548 {
549 uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz();
550 if (xtal_freq_mhz == 0) {
551 return RTC_XTAL_FREQ_AUTO;
552 }
553 return (rtc_xtal_freq_t)xtal_freq_mhz;
554 }
555
rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)556 void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
557 {
558 clk_ll_xtal_store_freq_mhz((uint32_t)xtal_freq);
559 }
560
rtc_clk_apb_freq_update(uint32_t apb_freq)561 void rtc_clk_apb_freq_update(uint32_t apb_freq)
562 {
563 clk_ll_apb_store_freq_hz(apb_freq);
564 }
565
rtc_clk_apb_freq_get(void)566 uint32_t rtc_clk_apb_freq_get(void)
567 {
568 #if CONFIG_IDF_ENV_FPGA
569 return CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * MHZ;
570 #endif // CONFIG_IDF_ENV_FPGA
571 return clk_ll_apb_load_freq_hz();
572 }
573
rtc_dig_clk8m_enable(void)574 void rtc_dig_clk8m_enable(void)
575 {
576 clk_ll_rc_fast_digi_enable();
577 esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
578 }
579
rtc_dig_clk8m_disable(void)580 void rtc_dig_clk8m_disable(void)
581 {
582 clk_ll_rc_fast_digi_disable();
583 esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
584 }
585
rtc_dig_8m_enabled(void)586 bool rtc_dig_8m_enabled(void)
587 {
588 return clk_ll_rc_fast_digi_is_enabled();
589 }
590
591 /* Name used in libphy.a:phy_chip_v7.o
592 * TODO: update the library to use rtc_clk_xtal_freq_get
593 */
594 rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));
595