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 "soc/rtc.h" 10 #include "hal/assert.h" 11 #include "hal/log.h" 12 13 static const char *CLK_HAL_TAG = "clk_hal"; 14 clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src)15uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) 16 { 17 switch (cpu_clk_src) { 18 case SOC_CPU_CLK_SRC_XTAL: 19 return clk_hal_xtal_get_freq_mhz(); 20 case SOC_CPU_CLK_SRC_PLL: 21 return clk_ll_bbpll_get_freq_mhz(); 22 case SOC_CPU_CLK_SRC_RC_FAST: 23 return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; 24 case SOC_CPU_CLK_SRC_APLL: 25 return clk_hal_apll_get_freq_hz() / MHZ; 26 default: 27 // Unknown CPU_CLK mux input 28 HAL_ASSERT(false); 29 return 0; 30 } 31 } 32 clk_hal_cpu_get_freq_hz(void)33uint32_t clk_hal_cpu_get_freq_hz(void) 34 { 35 soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); 36 switch (source) { 37 case SOC_CPU_CLK_SRC_PLL: 38 return clk_ll_cpu_get_freq_mhz_from_pll() * MHZ; 39 case SOC_CPU_CLK_SRC_APLL: { 40 uint32_t apll_freq_hz = clk_hal_apll_get_freq_hz(); 41 uint32_t divider = clk_ll_cpu_get_divider_from_apll(); 42 if (divider == 0) { 43 HAL_LOGE(CLK_HAL_TAG, "Invalid cpu config"); 44 return 0; 45 } 46 return apll_freq_hz / divider; 47 } 48 default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... 49 return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); 50 } 51 } 52 clk_hal_ahb_get_freq_hz(void)53uint32_t clk_hal_ahb_get_freq_hz(void) 54 { 55 // AHB_CLK path is highly dependent on CPU_CLK path 56 switch (clk_ll_cpu_get_src()) { 57 case SOC_CPU_CLK_SRC_PLL: 58 // AHB_CLK is a fixed value when CPU_CLK is clocked from PLL 59 return CLK_LL_AHB_MAX_FREQ_MHZ * MHZ; 60 case SOC_CPU_CLK_SRC_APLL: 61 return clk_hal_cpu_get_freq_hz() >> 1; 62 default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... 63 return clk_hal_cpu_get_freq_hz(); 64 } 65 } 66 clk_hal_apb_get_freq_hz(void)67uint32_t clk_hal_apb_get_freq_hz(void) 68 { 69 return clk_hal_ahb_get_freq_hz(); 70 } 71 clk_hal_lp_slow_get_freq_hz(void)72uint32_t clk_hal_lp_slow_get_freq_hz(void) 73 { 74 switch (clk_ll_rtc_slow_get_src()) { 75 case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: 76 return SOC_CLK_RC_SLOW_FREQ_APPROX; 77 case SOC_RTC_SLOW_CLK_SRC_XTAL32K: 78 return SOC_CLK_XTAL32K_FREQ_APPROX; 79 case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: 80 return SOC_CLK_RC_FAST_D256_FREQ_APPROX; 81 default: 82 // Unknown RTC_SLOW_CLK mux input 83 HAL_ASSERT(false); 84 return 0; 85 } 86 } 87 clk_hal_xtal_get_freq_mhz(void)88uint32_t clk_hal_xtal_get_freq_mhz(void) 89 { 90 uint32_t freq = clk_ll_xtal_load_freq_mhz(); 91 if (freq == 0) { 92 return (uint32_t)RTC_XTAL_FREQ_AUTO; 93 } 94 return freq; 95 } 96 clk_hal_apll_get_freq_hz(void)97uint32_t clk_hal_apll_get_freq_hz(void) 98 { 99 uint32_t xtal_freq_mhz = clk_hal_xtal_get_freq_mhz(); 100 uint32_t o_div = 0; 101 uint32_t sdm0 = 0; 102 uint32_t sdm1 = 0; 103 uint32_t sdm2 = 0; 104 clk_ll_apll_get_config(&o_div, &sdm0, &sdm1, &sdm2); 105 uint32_t apll_freq_hz = (uint32_t)(xtal_freq_mhz * MHZ * (4 + sdm2 + (float)sdm1/256.0f + (float)sdm0/65536.0f) / 106 (((float)o_div + 2) * 2)); 107 return apll_freq_hz; 108 } 109