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)15 uint32_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)33 uint32_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)53 uint32_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)67 uint32_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)72 uint32_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)88 uint32_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)97 uint32_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