1 /* 2 * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #include "hal/clk_tree_hal.h" 8 #include "hal/clk_tree_ll.h" 9 #include "hal/assert.h" 10 #include "hal/log.h" 11 12 static const char *CLK_HAL_TAG = "clk_hal"; 13 clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src)14uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) 15 { 16 switch (cpu_clk_src) { 17 case SOC_CPU_CLK_SRC_XTAL: 18 return clk_hal_xtal_get_freq_mhz(); 19 case SOC_CPU_CLK_SRC_PLL: 20 return clk_ll_bbpll_get_freq_mhz(); 21 case SOC_CPU_CLK_SRC_RC_FAST: 22 return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; 23 case SOC_CPU_CLK_SRC_APLL: 24 return clk_hal_apll_get_freq_hz() / MHZ; 25 default: 26 // Unknown CPU_CLK mux input 27 HAL_ASSERT(false); 28 return 0; 29 } 30 } 31 clk_hal_cpu_get_freq_hz(void)32uint32_t clk_hal_cpu_get_freq_hz(void) 33 { 34 soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); 35 switch (source) { 36 case SOC_CPU_CLK_SRC_PLL: { 37 // PLL 320MHz, CPU 240MHz is an undetermined state 38 uint32_t pll_freq_mhz = clk_ll_bbpll_get_freq_mhz(); 39 uint32_t cpu_freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); 40 if (pll_freq_mhz == CLK_LL_PLL_320M_FREQ_MHZ && cpu_freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ) { 41 HAL_LOGE(CLK_HAL_TAG, "Invalid cpu config"); 42 return 0; 43 } 44 return cpu_freq_mhz * MHZ; 45 } 46 case SOC_CPU_CLK_SRC_APLL: { 47 uint32_t apll_freq_hz = clk_hal_apll_get_freq_hz(); 48 uint32_t divider = clk_ll_cpu_get_divider_from_apll(); 49 if (divider == 0) { 50 HAL_LOGE(CLK_HAL_TAG, "Invalid cpu config"); 51 return 0; 52 } 53 return apll_freq_hz / divider; 54 } 55 default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... 56 return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); 57 } 58 } 59 clk_hal_ahb_get_freq_hz(void)60uint32_t clk_hal_ahb_get_freq_hz(void) 61 { 62 // AHB_CLK path is highly dependent on CPU_CLK path 63 switch (clk_ll_cpu_get_src()) { 64 case SOC_CPU_CLK_SRC_PLL: 65 // AHB_CLK is a fixed value when CPU_CLK is clocked from PLL 66 return CLK_LL_AHB_MAX_FREQ_MHZ * MHZ; 67 case SOC_CPU_CLK_SRC_APLL: 68 return clk_hal_cpu_get_freq_hz() >> 1; 69 default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... 70 return clk_hal_cpu_get_freq_hz(); 71 } 72 } 73 clk_hal_apb_get_freq_hz(void)74uint32_t clk_hal_apb_get_freq_hz(void) 75 { 76 return clk_hal_ahb_get_freq_hz(); 77 } 78 clk_hal_lp_slow_get_freq_hz(void)79uint32_t clk_hal_lp_slow_get_freq_hz(void) 80 { 81 switch (clk_ll_rtc_slow_get_src()) { 82 case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: 83 return SOC_CLK_RC_SLOW_FREQ_APPROX; 84 case SOC_RTC_SLOW_CLK_SRC_XTAL32K: 85 return SOC_CLK_XTAL32K_FREQ_APPROX; 86 case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: 87 return SOC_CLK_RC_FAST_D256_FREQ_APPROX; 88 default: 89 // Unknown RTC_SLOW_CLK mux input 90 HAL_ASSERT(false); 91 return 0; 92 } 93 } 94 clk_hal_xtal_get_freq_mhz(void)95uint32_t clk_hal_xtal_get_freq_mhz(void) 96 { 97 // ESP32S2's supported XTAL frequency is fixed, didn't save in the RTC storage register 98 return CLK_LL_XTAL_FREQ_MHZ; 99 } 100 clk_hal_apll_get_freq_hz(void)101uint32_t clk_hal_apll_get_freq_hz(void) 102 { 103 uint32_t xtal_freq_mhz = clk_hal_xtal_get_freq_mhz(); 104 uint32_t o_div = 0; 105 uint32_t sdm0 = 0; 106 uint32_t sdm1 = 0; 107 uint32_t sdm2 = 0; 108 clk_ll_apll_get_config(&o_div, &sdm0, &sdm1, &sdm2); 109 uint32_t apll_freq_hz = (uint32_t)(xtal_freq_mhz * MHZ * (4 + sdm2 + (float)sdm1/256.0f + (float)sdm0/65536.0f) / 110 (((float)o_div + 2) * 2)); 111 return apll_freq_hz; 112 } 113