clk_tree_hal.c 3.4 KB

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