clk_tree_hal.c 3.1 KB

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