diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index bed539e6c0..315cd7732d 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -26,7 +26,9 @@ if(NOT BOOTLOADER_BUILD) "sleep_mac_bb.c" "regi2c_ctrl.c" "adc_share_hw_ctrl.c" - "port/${target}/io_mux.c") + "port/${target}/io_mux.c" + "port/${target}/clk_tree.c" + "port/clk_tree_common.c") if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2) list(APPEND srcs "sleep_retention.c") @@ -86,6 +88,7 @@ if(NOT BOOTLOADER_BUILD) if(CONFIG_IDF_TARGET_ESP32H2) list(REMOVE_ITEM srcs "adc_share_hw_ctrl.c" # TODO: IDF-6215 + "port/clk_tree_common.c" # TODO: IDF-6265 ) endif() else() diff --git a/components/esp_hw_support/clk_ctrl_os.c b/components/esp_hw_support/clk_ctrl_os.c index 4afcbcc17e..b69f3a189b 100644 --- a/components/esp_hw_support/clk_ctrl_os.c +++ b/components/esp_hw_support/clk_ctrl_os.c @@ -7,6 +7,7 @@ #include #include "clk_ctrl_os.h" #include "soc/rtc.h" +#include "esp_private/clk_tree_common.h" #include "esp_check.h" static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED; @@ -27,14 +28,9 @@ bool periph_rtc_dig_clk8m_enable(void) if (s_periph_ref_counts == 0) { rtc_dig_clk8m_enable(); #if SOC_CLK_RC_FAST_SUPPORT_CALIBRATION -#if SOC_CLK_RC_FAST_D256_SUPPORTED - // If RC_FAST_D256 clock exists, calibration on a slow freq clock is much faster (less slow clock cycles need to wait) - s_rc_fast_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, 100)) << 8; // f_[rc_fast] = f_[rc_fast_d256] * 256; -#else - // Calibrate directly on the RC_FAST clock requires much more slow clock cycles to get an accurate freq value - s_rc_fast_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_RC_FAST, 10000)); -#endif + s_rc_fast_freq = clk_tree_rc_fast_get_freq_hz(CLK_TREE_SRC_FREQ_PRECISION_EXACT); if (s_rc_fast_freq == 0) { + rtc_dig_clk8m_disable(); portEXIT_CRITICAL(&periph_spinlock); return false; } diff --git a/components/esp_hw_support/include/clk_tree.h b/components/esp_hw_support/include/clk_tree.h new file mode 100644 index 0000000000..73f8007e6e --- /dev/null +++ b/components/esp_hw_support/include/clk_tree.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_err.h" +#include "soc/clk_tree_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Degree of precision of frequency value to be returned by clk_tree_src_get_freq_hz() + */ +typedef enum { + CLK_TREE_SRC_FREQ_PRECISION_CACHED, /*< Get value from the data cached by the driver; If the data is 0, then a calibration will be performed */ + CLK_TREE_SRC_FREQ_PRECISION_APPROX, /*< Get its approxiamte frequency value */ + CLK_TREE_SRC_FREQ_PRECISION_EXACT, /*< Always perform a calibration */ + CLK_TREE_SRC_FREQ_PRECISION_INVALID, /*< Invalid degree of precision */ +} clk_tree_src_freq_precision_t; + +/** + * @brief Get frequency of module clock source + * + * @param[in] clk_src Clock source available to modules, in soc_module_clk_t + * @param[in] precision Degree of precision, one of clk_tree_src_freq_precision_t values + * This arg only applies to the clock sources that their frequencies can vary: + * SOC_MOD_CLK_RTC_FAST, SOC_MOD_CLK_RTC_SLOW, SOC_MOD_CLK_RC_FAST, SOC_MOD_CLK_RC_FAST_D256, + * SOC_MOD_CLK_XTAL32K + * For other clock sources, this field is ignored. + * @param[out] freq_value Frequency of the clock source, in Hz + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_FAIL Calibration failed + */ +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_private/clk_tree_common.h b/components/esp_hw_support/include/esp_private/clk_tree_common.h new file mode 100644 index 0000000000..aa9ed39b4a --- /dev/null +++ b/components/esp_hw_support/include/esp_private/clk_tree_common.h @@ -0,0 +1,79 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "clk_tree.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_CLK_RC_FAST_D256_SUPPORTED +/** + * @brief Get frequency of RC_FAST_D256_CLK + * + * @param precision Degree of precision of the returned frequency value, one of clk_tree_src_freq_precision_t values + * + * @return RC_FAST_D256 clock frequency, in Hz. Returns 0 if degree of precision is invalid or calibration failed. + */ +uint32_t clk_tree_rc_fast_d256_get_freq_hz(clk_tree_src_freq_precision_t precision); +#endif + +#if SOC_CLK_XTAL32K_SUPPORTED +/** + * @brief Get frequency of XTAL32K_CLK + * + * @param precision Degree of precision of the returned frequency value, one of clk_tree_src_freq_precision_t values + * + * @return XTAL32K clock frequency, in Hz. Returns 0 if degree of precision is invalid or calibration failed. + */ +uint32_t clk_tree_xtal32k_get_freq_hz(clk_tree_src_freq_precision_t precision); +#endif + +#if SOC_CLK_OSC_SLOW_SUPPORTED +/** + * @brief Get frequency of OSC_SLOW_CLK + * + * @param precision Degree of precision of the returned frequency value, one of clk_tree_src_freq_precision_t values + * + * @return OSC_SLOW clock frequency, in Hz. Returns 0 if degree of precision is invalid or calibration failed. + */ +uint32_t clk_tree_osc_slow_get_freq_hz(clk_tree_src_freq_precision_t precision); +#endif + +/** + * @brief Get frequency of RC_FAST_CLK + * + * @param precision Degree of precision of the returned frequency value, one of clk_tree_src_freq_precision_t values + * + * @return RC_FAST clock frequency, in Hz. Returns 0 if degree of precision is invalid or calibration failed. + */ +uint32_t clk_tree_rc_fast_get_freq_hz(clk_tree_src_freq_precision_t precision); + +/** + * @brief Get frequency of LP_SLOW_CLK (i.e. RTC_SLOW_CLK) + * + * @param precision Degree of precision of the returned frequency value, one of clk_tree_src_freq_precision_t values + * + * @return LP_SLOW clock frequency, in Hz. Returns 0 if degree of precision is invalid or calibration failed. + */ +uint32_t clk_tree_lp_slow_get_freq_hz(clk_tree_src_freq_precision_t precision); + +/** + * @brief Get frequency of LP_FAST_CLK (i.e. RTC_FAST_CLK) + * + * @param precision Degree of precision of the returned frequency value, one of clk_tree_src_freq_precision_t values + * + * @return LP_FAST clock frequency, in Hz. Returns 0 if degree of precision is invalid or calibration failed. + */ +uint32_t clk_tree_lp_fast_get_freq_hz(clk_tree_src_freq_precision_t precision); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/clk_tree_common.c b/components/esp_hw_support/port/clk_tree_common.c new file mode 100644 index 0000000000..676d5e9665 --- /dev/null +++ b/components/esp_hw_support/port/clk_tree_common.c @@ -0,0 +1,190 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_private/clk_tree_common.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "esp_private/esp_clk.h" +#include "soc/clk_tree_defs.h" +#include "soc/soc_caps.h" +#include "sdkconfig.h" +#include "esp_hw_log.h" + +static const char *TAG = "clk_tree_common"; + +typedef struct clk_tree_calibrated_freq_t clk_tree_calibrated_freq_t; + +struct clk_tree_calibrated_freq_t { +#if SOC_CLK_RC_FAST_D256_SUPPORTED + uint32_t rc_fast_d256; +#elif SOC_CLK_RC_FAST_SUPPORT_CALIBRATION // && !SOC_CLK_RC_FAST_D256_SUPPORTED + uint32_t rc_fast; +#endif +#if SOC_CLK_XTAL32K_SUPPORTED + uint32_t xtal32k; +#endif +#if SOC_CLK_OSC_SLOW_SUPPORTED + uint32_t osc_slow; +#endif +}; + +// TODO: Better to implement a spinlock for the static variables +static clk_tree_calibrated_freq_t s_calibrated_freq = {}; + +/* Number of cycles for RTC_SLOW_CLK calibration */ +#define RTC_SLOW_CLK_CAL_CYCLES CONFIG_RTC_CLK_CAL_CYCLES +/* Number of cycles for ~32kHz clocks calibration (rc_fast_d256, xtal32k, osc_slow, rc32k) */ +#define DEFAULT_32K_CLK_CAL_CYCLES 100 +/* Number of cycles for RC_FAST calibration */ +#define DEFAULT_RC_FAST_CAL_CYCLES 10000 // RC_FAST has a higher frequency, therefore, requires more cycles to get an accurate value + + +/** + * Performs a frequency calibration to RTC slow clock + * + * slowclk_cycles Number of slow clock cycles to count. + * If slowclk_cycles = 0, calibration will not be performed. Clock's theoretical value will be used. + * + * Returns the number of XTAL clock cycles within the given number of slow clock cycles + * It returns 0 if calibration failed, i.e. clock is not running + */ +static uint32_t clk_tree_rtc_slow_calibration(uint32_t slowclk_cycles) +{ + uint32_t cal_val = 0; + if (slowclk_cycles > 0) { + cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, slowclk_cycles); + } else { + const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL; + uint32_t source_approx_freq = clk_hal_lp_slow_get_freq_hz(); + assert(source_approx_freq); + cal_val = (uint32_t)(cal_dividend / source_approx_freq); + } + if (cal_val) { + ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val); + // Update the calibration value of RTC_SLOW_CLK + esp_clk_slowclk_cal_set(cal_val); + } + return cal_val; +} + +#if SOC_CLK_RC_FAST_D256_SUPPORTED +uint32_t clk_tree_rc_fast_d256_get_freq_hz(clk_tree_src_freq_precision_t precision) +{ + switch (precision) { + case CLK_TREE_SRC_FREQ_PRECISION_APPROX: + return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + case CLK_TREE_SRC_FREQ_PRECISION_CACHED: + if (!s_calibrated_freq.rc_fast_d256) { + s_calibrated_freq.rc_fast_d256 = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, DEFAULT_32K_CLK_CAL_CYCLES)); + } + return s_calibrated_freq.rc_fast_d256; + case CLK_TREE_SRC_FREQ_PRECISION_EXACT: + s_calibrated_freq.rc_fast_d256 = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, DEFAULT_32K_CLK_CAL_CYCLES)); + return s_calibrated_freq.rc_fast_d256; + default: + return 0; + } +} +#endif + +#if SOC_CLK_XTAL32K_SUPPORTED +uint32_t clk_tree_xtal32k_get_freq_hz(clk_tree_src_freq_precision_t precision) +{ + switch (precision) { + case CLK_TREE_SRC_FREQ_PRECISION_APPROX: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case CLK_TREE_SRC_FREQ_PRECISION_CACHED: + if (!s_calibrated_freq.xtal32k) { + s_calibrated_freq.xtal32k = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_XTAL, DEFAULT_32K_CLK_CAL_CYCLES)); + } + return s_calibrated_freq.xtal32k; + case CLK_TREE_SRC_FREQ_PRECISION_EXACT: + s_calibrated_freq.xtal32k = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_XTAL, DEFAULT_32K_CLK_CAL_CYCLES)); + return s_calibrated_freq.xtal32k; + default: + return 0; + } +} +#endif + +#if SOC_CLK_OSC_SLOW_SUPPORTED +uint32_t clk_tree_osc_slow_get_freq_hz(clk_tree_src_freq_precision_t precision) +{ + switch (precision) { + case CLK_TREE_SRC_FREQ_PRECISION_APPROX: + return SOC_CLK_OSC_SLOW_FREQ_APPROX; + case CLK_TREE_SRC_FREQ_PRECISION_CACHED: + if (!s_calibrated_freq.osc_slow) { + s_calibrated_freq.osc_slow = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_OSC_SLOW, DEFAULT_32K_CLK_CAL_CYCLES)); + } + return s_calibrated_freq.osc_slow; + case CLK_TREE_SRC_FREQ_PRECISION_EXACT: + s_calibrated_freq.osc_slow = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_32K_OSC_SLOW, DEFAULT_32K_CLK_CAL_CYCLES)); + return s_calibrated_freq.osc_slow; + default: + return 0; + } +} +#endif + +uint32_t clk_tree_lp_slow_get_freq_hz(clk_tree_src_freq_precision_t precision) +{ + switch (precision) { + case CLK_TREE_SRC_FREQ_PRECISION_CACHED: + // This returns calibrated (if CONFIG_xxx_RTC_CLK_CAL_CYCLES) value stored in RTC storage register + return rtc_clk_freq_cal(clk_ll_rtc_slow_load_cal()); + case CLK_TREE_SRC_FREQ_PRECISION_APPROX: + return clk_hal_lp_slow_get_freq_hz(); + case CLK_TREE_SRC_FREQ_PRECISION_EXACT: + return rtc_clk_freq_cal(clk_tree_rtc_slow_calibration(RTC_SLOW_CLK_CAL_CYCLES)); + default: + return 0; + } +} + +uint32_t clk_tree_rc_fast_get_freq_hz(clk_tree_src_freq_precision_t precision) +{ +#if SOC_CLK_RC_FAST_SUPPORT_CALIBRATION + if (precision == CLK_TREE_SRC_FREQ_PRECISION_APPROX) { + return SOC_CLK_RC_FAST_FREQ_APPROX; + } +#if SOC_CLK_RC_FAST_D256_SUPPORTED + // If RC_FAST_D256 clock exists, calibration on a slow freq clock is much faster (less slow clock cycles need to wait) + return clk_tree_rc_fast_d256_get_freq_hz(precision) << 8; +#else + // Calibrate directly on the RC_FAST clock requires much more slow clock cycles to get an accurate freq value + if (precision != CLK_TREE_SRC_FREQ_PRECISION_CACHED || !s_calibrated_freq.rc_fast) { + s_calibrated_freq.rc_fast = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_RC_FAST, DEFAULT_RC_FAST_CAL_CYCLES)); + } + return s_calibrated_freq.rc_fast; +#endif //SOC_CLK_RC_FAST_D256_SUPPORTED +#else //!SOC_CLK_RC_FAST_SUPPORT_CALIBRATION + if (precision != CLK_TREE_SRC_FREQ_PRECISION_APPROX) { + // No way of getting exact rc_fast freq + ESP_HW_LOGW(TAG, "unable to get the exact freq of rc_fast_clk, returning its approx. freq value"); + } + return SOC_CLK_RC_FAST_FREQ_APPROX; +#endif //SOC_CLK_RC_FAST_SUPPORT_CALIBRATION +} + +uint32_t clk_tree_lp_fast_get_freq_hz(clk_tree_src_freq_precision_t precision) +{ + switch (clk_ll_rtc_fast_get_src()) { + case SOC_RTC_FAST_CLK_SRC_XTAL_DIV: +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 //SOC_RTC_FAST_CLK_SRC_XTAL_D4 + return clk_hal_xtal_get_freq_mhz() * MHZ >> 2; +#else //SOC_RTC_FAST_CLK_SRC_XTAL_D2 + return clk_hal_xtal_get_freq_mhz() * MHZ >> 1; +#endif + case SOC_RTC_FAST_CLK_SRC_RC_FAST: + return clk_tree_rc_fast_get_freq_hz(precision) / clk_ll_rc_fast_get_divider(); + default: + // Invalid clock source + assert(false); + return 0; + } +} diff --git a/components/esp_hw_support/port/esp32/clk_tree.c b/components/esp_hw_support/port/esp32/clk_tree.c new file mode 100644 index 0000000000..da0719d094 --- /dev/null +++ b/components/esp_hw_support/port/esp32/clk_tree.c @@ -0,0 +1,71 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/clk_tree_common.h" + +static const char *TAG = "clk_tree"; + +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; + case SOC_MOD_CLK_APB: + clk_src_freq = clk_hal_apb_get_freq_hz(); + break; + case SOC_MOD_CLK_XTAL: + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_PLL_D2: + clk_src_freq = (clk_ll_bbpll_get_freq_mhz() * MHZ) >> 1; + break; + case SOC_MOD_CLK_PLL_F160M: + clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + clk_src_freq = clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST_D256: + clk_src_freq = clk_tree_rc_fast_d256_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL32K: + clk_src_freq = clk_tree_xtal32k_get_freq_hz(precision); + break; + case SOC_MOD_CLK_REF_TICK: + clk_src_freq = 1 * MHZ; + break; + case SOC_MOD_CLK_APLL: + clk_src_freq = clk_hal_apll_get_freq_hz(); + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c2/clk_tree.c b/components/esp_hw_support/port/esp32c2/clk_tree.c new file mode 100644 index 0000000000..5f46239ea7 --- /dev/null +++ b/components/esp_hw_support/port/esp32c2/clk_tree.c @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/clk_tree_common.h" + +static const char *TAG = "clk_tree"; + +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; + case SOC_MOD_CLK_XTAL: + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_PLL_F40M: + clk_src_freq = CLK_LL_PLL_40M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_PLL_F60M: + clk_src_freq = CLK_LL_PLL_60M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_PLL_F80M: + clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + clk_src_freq = clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST_D256: + clk_src_freq = clk_tree_rc_fast_d256_get_freq_hz(precision); + break; + case SOC_MOD_CLK_OSC_SLOW: + clk_src_freq = clk_tree_osc_slow_get_freq_hz(precision); + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c3/clk_tree.c b/components/esp_hw_support/port/esp32c3/clk_tree.c new file mode 100644 index 0000000000..61302a3ceb --- /dev/null +++ b/components/esp_hw_support/port/esp32c3/clk_tree.c @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/clk_tree_common.h" + +static const char *TAG = "clk_tree"; + +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; + case SOC_MOD_CLK_APB: + clk_src_freq = clk_hal_apb_get_freq_hz(); + break; + case SOC_MOD_CLK_XTAL: + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_PLL_F80M: + clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_PLL_F160M: + clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + clk_src_freq = clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST_D256: + clk_src_freq = clk_tree_rc_fast_d256_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL32K: + clk_src_freq = clk_tree_xtal32k_get_freq_hz(precision); + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c6/clk_tree.c b/components/esp_hw_support/port/esp32c6/clk_tree.c new file mode 100644 index 0000000000..161155f467 --- /dev/null +++ b/components/esp_hw_support/port/esp32c6/clk_tree.c @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/clk_tree_common.h" + +static const char *TAG = "clk_tree"; + +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; + case SOC_MOD_CLK_XTAL: + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_PLL_F80M: + clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_PLL_F160M: + clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_PLL_F240M: + clk_src_freq = CLK_LL_PLL_240M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + clk_src_freq = clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL32K: + clk_src_freq = clk_tree_xtal32k_get_freq_hz(precision); + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32h2/clk_tree.c b/components/esp_hw_support/port/esp32h2/clk_tree.c new file mode 100644 index 0000000000..9e6047a6a8 --- /dev/null +++ b/components/esp_hw_support/port/esp32h2/clk_tree.c @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" + +static const char *TAG = "clk_tree"; + +// TODO: IDF-6265 +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_XTAL: + clk_src_freq = 32 * MHZ; + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32h4/clk_tree.c b/components/esp_hw_support/port/esp32h4/clk_tree.c new file mode 100644 index 0000000000..e4e193a136 --- /dev/null +++ b/components/esp_hw_support/port/esp32h4/clk_tree.c @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/clk_tree_common.h" + +static const char *TAG = "clk_tree"; + +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; + case SOC_MOD_CLK_AHB: + clk_src_freq = clk_hal_ahb_get_freq_hz(); + break; + case SOC_MOD_CLK_APB: + clk_src_freq = clk_hal_apb_get_freq_hz(); + break; + case SOC_MOD_CLK_XTAL: + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_PLL: + clk_src_freq = clk_ll_bbpll_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + clk_src_freq = clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL32K: + clk_src_freq = clk_tree_xtal32k_get_freq_hz(precision); + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32s2/clk_tree.c b/components/esp_hw_support/port/esp32s2/clk_tree.c new file mode 100644 index 0000000000..9e7ea76008 --- /dev/null +++ b/components/esp_hw_support/port/esp32s2/clk_tree.c @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/clk_tree_common.h" + +static const char *TAG = "clk_tree"; + +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; + case SOC_MOD_CLK_APB: + clk_src_freq = clk_hal_apb_get_freq_hz(); + break; + case SOC_MOD_CLK_XTAL: + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_PLL_F160M: + clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + case SOC_MOD_CLK_TEMP_SENSOR: + clk_src_freq = clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST_D256: + clk_src_freq = clk_tree_rc_fast_d256_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL32K: + clk_src_freq = clk_tree_xtal32k_get_freq_hz(precision); + break; + case SOC_MOD_CLK_REF_TICK: + clk_src_freq = 1 * MHZ; + break; + case SOC_MOD_CLK_APLL: + clk_src_freq = clk_hal_apll_get_freq_hz(); + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32s3/clk_tree.c b/components/esp_hw_support/port/esp32s3/clk_tree.c new file mode 100644 index 0000000000..f861eacdfa --- /dev/null +++ b/components/esp_hw_support/port/esp32s3/clk_tree.c @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "clk_tree.h" +#include "esp_err.h" +#include "esp_check.h" +#include "soc/rtc.h" +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "esp_private/clk_tree_common.h" + +static const char *TAG = "clk_tree"; + +esp_err_t clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, clk_tree_src_freq_precision_t precision, +uint32_t *freq_value) +{ + ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src"); + ESP_RETURN_ON_FALSE(precision < CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision"); + ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer"); + + uint32_t clk_src_freq = 0; + switch (clk_src) { + case SOC_MOD_CLK_CPU: + clk_src_freq = clk_hal_cpu_get_freq_hz(); + break; + case SOC_MOD_CLK_APB: + clk_src_freq = clk_hal_apb_get_freq_hz(); + break; + case SOC_MOD_CLK_XTAL: + clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ; + break; + case SOC_MOD_CLK_PLL_F80M: + clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_PLL_F160M: + clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ; + break; + case SOC_MOD_CLK_PLL_D2: + clk_src_freq = (clk_ll_bbpll_get_freq_mhz() * MHZ) >> 1; + break; + case SOC_MOD_CLK_RTC_SLOW: + clk_src_freq = clk_tree_lp_slow_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = clk_tree_lp_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST: + case SOC_MOD_CLK_TEMP_SENSOR: + clk_src_freq = clk_tree_rc_fast_get_freq_hz(precision); + break; + case SOC_MOD_CLK_RC_FAST_D256: + clk_src_freq = clk_tree_rc_fast_d256_get_freq_hz(precision); + break; + case SOC_MOD_CLK_XTAL32K: + clk_src_freq = clk_tree_xtal32k_get_freq_hz(precision); + break; + default: + break; + } + + ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG, + "freq shouldn't be 0, calibration failed"); + *freq_value = clk_src_freq; + return ESP_OK; +} diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 0a3196239b..f35b0b9e7e 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -39,7 +39,8 @@ if(NOT BOOTLOADER_BUILD) "spi_flash_hal_iram.c" "spi_flash_encrypt_hal_iram.c" "adc_hal_common.c" - "adc_oneshot_hal.c") + "adc_oneshot_hal.c" + "${target}/clk_tree_hal.c") if(CONFIG_SOC_SYSTIMER_SUPPORTED AND NOT CONFIG_HAL_SYSTIMER_USE_ROM_IMPL) list(APPEND srcs "systimer_hal.c") @@ -209,6 +210,7 @@ if(NOT BOOTLOADER_BUILD) "adc_oneshot_hal.c" # TODO: IDF-6214 "adc_hal_common.c" # TODO: IDF-6215 "esp32h2/rtc_cntl_hal.c" + "esp32h2/clk_tree_hal.c" ) endif() endif() diff --git a/components/hal/esp32/clk_tree_hal.c b/components/hal/esp32/clk_tree_hal.c new file mode 100644 index 0000000000..70920088b7 --- /dev/null +++ b/components/hal/esp32/clk_tree_hal.c @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + case SOC_CPU_CLK_SRC_APLL: + return clk_hal_apll_get_freq_hz() / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + switch (source) { + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_cpu_get_freq_mhz_from_pll() * MHZ; + case SOC_CPU_CLK_SRC_APLL: { + uint32_t apll_freq_hz = clk_hal_apll_get_freq_hz(); + uint32_t divider = clk_ll_cpu_get_divider_from_apll(); + if (divider == 0) { + HAL_LOGE(CLK_HAL_TAG, "Invalid cpu config"); + return 0; + } + return apll_freq_hz / divider; + } + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); + } +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + // AHB_CLK path is highly dependent on CPU_CLK path + switch (clk_ll_cpu_get_src()) { + case SOC_CPU_CLK_SRC_PLL: + // AHB_CLK is a fixed value when CPU_CLK is clocked from PLL + return CLK_LL_AHB_MAX_FREQ_MHZ * MHZ; + case SOC_CPU_CLK_SRC_APLL: + return clk_hal_cpu_get_freq_hz() >> 1; + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_cpu_get_freq_hz(); + } +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + return (uint32_t)RTC_XTAL_FREQ_AUTO; + } + return freq; +} + +uint32_t clk_hal_apll_get_freq_hz(void) +{ + uint32_t xtal_freq_mhz = clk_hal_xtal_get_freq_mhz(); + uint32_t o_div = 0; + uint32_t sdm0 = 0; + uint32_t sdm1 = 0; + uint32_t sdm2 = 0; + clk_ll_apll_get_config(&o_div, &sdm0, &sdm1, &sdm2); + uint32_t apll_freq_hz = (uint32_t)(xtal_freq_mhz * MHZ * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / + (((float)o_div + 2) * 2)); + return apll_freq_hz; +} diff --git a/components/hal/esp32/include/hal/clk_tree_ll.h b/components/hal/esp32/include/hal/clk_tree_ll.h index ea2336fc76..d6a15c2bed 100644 --- a/components/hal/esp32/include/hal/clk_tree_ll.h +++ b/components/hal/esp32/include/hal/clk_tree_ll.h @@ -33,6 +33,8 @@ extern "C" { #define CLK_LL_PLL_320M_FREQ_MHZ (320) #define CLK_LL_PLL_480M_FREQ_MHZ (480) +#define CLK_LL_AHB_MAX_FREQ_MHZ CLK_LL_PLL_80M_FREQ_MHZ + /* BBPLL configuration parameters at reset */ #define CLK_LL_BBPLL_IR_CAL_DELAY_VAL 0x18 #define CLK_LL_BBPLL_IR_CAL_EXT_CAP_VAL 0x20 @@ -150,6 +152,22 @@ static inline bool clk_ll_apll_is_fpd(void) return REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); } +/** + * @brief Get APLL configuration which can be used to calculate APLL frequency + * + * @param[out] o_div Frequency divider, 0..31 + * @param[out] sdm0 Frequency adjustment parameter, 0..255 + * @param[out] sdm1 Frequency adjustment parameter, 0..255 + * @param[out] sdm2 Frequency adjustment parameter, 0..63 + */ +static inline void clk_ll_apll_get_config(uint32_t *o_div, uint32_t *sdm0, uint32_t *sdm1, uint32_t *sdm2) +{ + *o_div = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV); + *sdm0 = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_DSDM0); + *sdm1 = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_DSDM1); + *sdm2 = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_DSDM2); +} + /** * @brief Set APLL configuration * @@ -618,6 +636,26 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(voi return REG_GET_FIELD(SYSCON_SYSCLK_CONF_REG, SYSCON_PRE_DIV_CNT) + 1; } +/** + * @brief Get CPU_CLK's APLL clock source path divider + * + * @return Divider. Returns 0 means invalid. + */ +static inline uint32_t clk_ll_cpu_get_divider_from_apll(void) +{ + // APLL path divider choice shares the same register with CPUPERIOD_SEL + uint32_t cpu_freq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL); + switch (cpu_freq_sel) { + case 0: + return 4; + case 1: + return 2; + default: + // Invalid CPUPERIOD_SEL value if APLL is the clock source + return 0; + } +} + /** * @brief Set REF_TICK divider to make REF_TICK frequency at 1MHz * diff --git a/components/hal/esp32c2/clk_tree_hal.c b/components/hal/esp32c2/clk_tree_hal.c new file mode 100644 index 0000000000..ba870243b3 --- /dev/null +++ b/components/hal/esp32c2/clk_tree_hal.c @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "sdkconfig.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + switch (source) { + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_cpu_get_freq_mhz_from_pll() * MHZ; + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); + } +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + // AHB_CLK path is highly dependent on CPU_CLK path + switch (clk_ll_cpu_get_src()) { + case SOC_CPU_CLK_SRC_PLL: + // AHB_CLK is a fixed value when CPU_CLK is clocked from PLL + return CLK_LL_AHB_MAX_FREQ_MHZ * MHZ; + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_cpu_get_freq_hz(); + } +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: + return SOC_CLK_OSC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume %dMHz", CONFIG_XTAL_FREQ); + return CONFIG_XTAL_FREQ; + } + return freq; +} diff --git a/components/hal/esp32c2/include/hal/clk_tree_ll.h b/components/hal/esp32c2/include/hal/clk_tree_ll.h index e0c46a665d..92b49da10e 100644 --- a/components/hal/esp32c2/include/hal/clk_tree_ll.h +++ b/components/hal/esp32c2/include/hal/clk_tree_ll.h @@ -24,11 +24,15 @@ extern "C" { #define MHZ (1000000) +#define CLK_LL_PLL_40M_FREQ_MHZ (40) +#define CLK_LL_PLL_60M_FREQ_MHZ (60) #define CLK_LL_PLL_80M_FREQ_MHZ (80) #define CLK_LL_PLL_120M_FREQ_MHZ (120) #define CLK_LL_PLL_480M_FREQ_MHZ (480) +#define CLK_LL_AHB_MAX_FREQ_MHZ CLK_LL_PLL_40M_FREQ_MHZ + /** * @brief XTAL32K_CLK enable modes */ @@ -504,10 +508,18 @@ static inline void clk_ll_rc_slow_set_divider(uint32_t divider) * Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit * halves. These are the routines to work with that representation. * - * @param xtal_freq_mhz XTAL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz. The frequency must necessarily be even, + * otherwise there will be a conflict with the low bit, which is used to disable logs + * in the ROM code. */ static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) { + // Read the status of whether disabling logging from ROM code + uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG; + // If so, need to write back this setting + if (reg == RTC_DISABLE_ROM_LOG) { + xtal_freq_mhz |= 1; + } WRITE_PERI_REG(RTC_XTAL_FREQ_REG, (xtal_freq_mhz & UINT16_MAX) | ((xtal_freq_mhz & UINT16_MAX) << 16)); } @@ -525,7 +537,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz( uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); if ((xtal_freq_reg & 0xFFFF) == ((xtal_freq_reg >> 16) & 0xFFFF) && xtal_freq_reg != 0 && xtal_freq_reg != UINT32_MAX) { - return xtal_freq_reg & UINT16_MAX; + return xtal_freq_reg & ~RTC_DISABLE_ROM_LOG & UINT16_MAX; } // If the format in reg is invalid return 0; diff --git a/components/hal/esp32c3/clk_tree_hal.c b/components/hal/esp32c3/clk_tree_hal.c new file mode 100644 index 0000000000..39c58befd2 --- /dev/null +++ b/components/hal/esp32c3/clk_tree_hal.c @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + switch (source) { + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_cpu_get_freq_mhz_from_pll() * MHZ; + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); + } +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + // AHB_CLK path is highly dependent on CPU_CLK path + switch (clk_ll_cpu_get_src()) { + case SOC_CPU_CLK_SRC_PLL: + // AHB_CLK is a fixed value when CPU_CLK is clocked from PLL + return CLK_LL_AHB_MAX_FREQ_MHZ * MHZ; + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_cpu_get_freq_hz(); + } +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); + return (uint32_t)RTC_XTAL_FREQ_40M; + } + return freq; +} diff --git a/components/hal/esp32c3/include/hal/clk_tree_ll.h b/components/hal/esp32c3/include/hal/clk_tree_ll.h index 8661952691..1eec6acfd6 100644 --- a/components/hal/esp32c3/include/hal/clk_tree_ll.h +++ b/components/hal/esp32c3/include/hal/clk_tree_ll.h @@ -30,6 +30,8 @@ extern "C" { #define CLK_LL_PLL_320M_FREQ_MHZ (320) #define CLK_LL_PLL_480M_FREQ_MHZ (480) +#define CLK_LL_AHB_MAX_FREQ_MHZ CLK_LL_PLL_80M_FREQ_MHZ + #define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ .dac = 3, \ .dres = 3, \ @@ -613,10 +615,18 @@ static inline void clk_ll_rc_slow_set_divider(uint32_t divider) * Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit * halves. These are the routines to work with that representation. * - * @param xtal_freq_mhz XTAL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz. The frequency must necessarily be even, + * otherwise there will be a conflict with the low bit, which is used to disable logs + * in the ROM code. */ static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) { + // Read the status of whether disabling logging from ROM code + uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG; + // If so, need to write back this setting + if (reg == RTC_DISABLE_ROM_LOG) { + xtal_freq_mhz |= 1; + } WRITE_PERI_REG(RTC_XTAL_FREQ_REG, (xtal_freq_mhz & UINT16_MAX) | ((xtal_freq_mhz & UINT16_MAX) << 16)); } @@ -634,7 +644,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz( uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); if ((xtal_freq_reg & 0xFFFF) == ((xtal_freq_reg >> 16) & 0xFFFF) && xtal_freq_reg != 0 && xtal_freq_reg != UINT32_MAX) { - return xtal_freq_reg & UINT16_MAX; + return xtal_freq_reg & ~RTC_DISABLE_ROM_LOG & UINT16_MAX; } // If the format in reg is invalid return 0; diff --git a/components/hal/esp32c6/clk_tree_hal.c b/components/hal/esp32c6/clk_tree_hal.c new file mode 100644 index 0000000000..ca6ccd1e20 --- /dev/null +++ b/components/hal/esp32c6/clk_tree_hal.c @@ -0,0 +1,76 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + uint32_t divider = (source == SOC_CPU_CLK_SRC_PLL) ? clk_ll_cpu_get_hs_divider() : clk_ll_cpu_get_ls_divider(); + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / divider; +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + uint32_t divider = (source == SOC_CPU_CLK_SRC_PLL) ? clk_ll_ahb_get_hs_divider() : clk_ll_ahb_get_ls_divider(); + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / divider; +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz() / clk_ll_apb_get_divider(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: + return SOC_CLK_OSC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC32K: + return SOC_CLK_RC32K_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); + return (uint32_t)RTC_XTAL_FREQ_40M; + } + return freq; +} diff --git a/components/hal/esp32c6/include/hal/clk_tree_ll.h b/components/hal/esp32c6/include/hal/clk_tree_ll.h index f64cf3cefd..bf72adb451 100644 --- a/components/hal/esp32c6/include/hal/clk_tree_ll.h +++ b/components/hal/esp32c6/include/hal/clk_tree_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,6 +28,7 @@ extern "C" { #define CLK_LL_PLL_80M_FREQ_MHZ (80) #define CLK_LL_PLL_120M_FREQ_MHZ (120) #define CLK_LL_PLL_160M_FREQ_MHZ (160) +#define CLK_LL_PLL_240M_FREQ_MHZ (240) #define CLK_LL_PLL_480M_FREQ_MHZ (480) @@ -717,10 +718,18 @@ static inline void clk_ll_rc_slow_set_divider(uint32_t divider) * Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit * halves. These are the routines to work with that representation. * - * @param xtal_freq_mhz XTAL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz. The frequency must necessarily be even, + * otherwise there will be a conflict with the low bit, which is used to disable logs + * in the ROM code. */ static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) { + // Read the status of whether disabling logging from ROM code + uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG; + // If so, need to write back this setting + if (reg == RTC_DISABLE_ROM_LOG) { + xtal_freq_mhz |= 1; + } WRITE_PERI_REG(RTC_XTAL_FREQ_REG, (xtal_freq_mhz & UINT16_MAX) | ((xtal_freq_mhz & UINT16_MAX) << 16)); } @@ -738,7 +747,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz( uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); if ((xtal_freq_reg & 0xFFFF) == ((xtal_freq_reg >> 16) & 0xFFFF) && xtal_freq_reg != 0 && xtal_freq_reg != UINT32_MAX) { - return xtal_freq_reg & UINT16_MAX; + return xtal_freq_reg & ~RTC_DISABLE_ROM_LOG & UINT16_MAX; } // If the format in reg is invalid return 0; diff --git a/components/hal/esp32h2/clk_tree_hal.c b/components/hal/esp32h2/clk_tree_hal.c new file mode 100644 index 0000000000..29f357a66c --- /dev/null +++ b/components/hal/esp32h2/clk_tree_hal.c @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_ahb_get_divider(); +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz() / clk_ll_apb_get_divider(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: + return SOC_CLK_OSC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC32K: + return SOC_CLK_RC32K_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume 32MHz"); + return (uint32_t)RTC_XTAL_FREQ_32M; + } + return freq; +} diff --git a/components/hal/esp32h2/include/hal/clk_tree_ll.h b/components/hal/esp32h2/include/hal/clk_tree_ll.h index 36055eef6c..b09d5bbd05 100644 --- a/components/hal/esp32h2/include/hal/clk_tree_ll.h +++ b/components/hal/esp32h2/include/hal/clk_tree_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/hal/esp32h4/clk_tree_hal.c b/components/hal/esp32h4/clk_tree_hal.c new file mode 100644 index 0000000000..fbef1bb2b0 --- /dev/null +++ b/components/hal/esp32h4/clk_tree_hal.c @@ -0,0 +1,73 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + case SOC_CPU_CLK_SRC_XTAL_D2: + return clk_hal_xtal_get_freq_mhz() >> 1; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + return clk_hal_cpu_get_freq_hz() / clk_ll_ahb_get_divider(); +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz() / clk_ll_apb_get_divider(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC32K: + return SOC_CLK_RC32K_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume 32MHz"); + return (uint32_t)RTC_XTAL_FREQ_32M; + } + return freq; +} diff --git a/components/hal/esp32h4/include/hal/clk_tree_ll.h b/components/hal/esp32h4/include/hal/clk_tree_ll.h index 1d74126456..24adea1c0a 100644 --- a/components/hal/esp32h4/include/hal/clk_tree_ll.h +++ b/components/hal/esp32h4/include/hal/clk_tree_ll.h @@ -341,7 +341,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(voi * * @param divider Divider. AHB_DIV_NUM = divider - 1. */ -static inline void clk_ll_ahb_set_divider(uint32_t divider) +static inline __attribute__((always_inline)) void clk_ll_ahb_set_divider(uint32_t divider) { HAL_ASSERT(divider > 0); REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM, divider - 1); @@ -352,7 +352,7 @@ static inline void clk_ll_ahb_set_divider(uint32_t divider) * * @return Divider. Divider = (AHB_DIV_NUM + 1). */ -static inline uint32_t clk_ll_ahb_get_divider(void) +static inline __attribute__((always_inline)) uint32_t clk_ll_ahb_get_divider(void) { return REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_AHB_DIV_NUM) + 1; } @@ -362,7 +362,7 @@ static inline uint32_t clk_ll_ahb_get_divider(void) * * @param divider Divider. APB_DIV_NUM = divider - 1. */ -static inline void clk_ll_apb_set_divider(uint32_t divider) +static inline __attribute__((always_inline)) void clk_ll_apb_set_divider(uint32_t divider) { HAL_ASSERT(divider > 0); REG_SET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM, divider - 1); @@ -373,7 +373,7 @@ static inline void clk_ll_apb_set_divider(uint32_t divider) * * @return Divider. Divider = (APB_DIV_NUM + 1). */ -static inline uint32_t clk_ll_apb_get_divider(void) +static inline __attribute__((always_inline)) uint32_t clk_ll_apb_get_divider(void) { return REG_GET_FIELD(SYSTEM_BUSCLK_CONF_REG, SYSTEM_APB_DIV_NUM) + 1; } @@ -503,10 +503,18 @@ static inline void clk_ll_rc_slow_set_divider(uint32_t divider) * Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit * halves. These are the routines to work with that representation. * - * @param xtal_freq_mhz XTAL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz. The frequency must necessarily be even, + * otherwise there will be a conflict with the low bit, which is used to disable logs + * in the ROM code. */ static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) { + // Read the status of whether disabling logging from ROM code + uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG; + // If so, need to write back this setting + if (reg == RTC_DISABLE_ROM_LOG) { + xtal_freq_mhz |= 1; + } WRITE_PERI_REG(RTC_XTAL_FREQ_REG, (xtal_freq_mhz & UINT16_MAX) | ((xtal_freq_mhz & UINT16_MAX) << 16)); } @@ -522,7 +530,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz( { // ESP32H4 has a fixed crystal frequency (32MHz), but we will still read from the RTC storage register uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); - if ((xtal_freq_reg & UINT16_MAX) != RTC_XTAL_FREQ_32M) { + if ((xtal_freq_reg & ~RTC_DISABLE_ROM_LOG & UINT16_MAX) != RTC_XTAL_FREQ_32M) { return 0; } return (uint32_t)RTC_XTAL_FREQ_32M; diff --git a/components/hal/esp32s2/clk_tree_hal.c b/components/hal/esp32s2/clk_tree_hal.c new file mode 100644 index 0000000000..c619a3c0e2 --- /dev/null +++ b/components/hal/esp32s2/clk_tree_hal.c @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + case SOC_CPU_CLK_SRC_APLL: + return clk_hal_apll_get_freq_hz() / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + switch (source) { + case SOC_CPU_CLK_SRC_PLL: { + // PLL 320MHz, CPU 240MHz is an undetermined state + uint32_t pll_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + uint32_t cpu_freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); + if (pll_freq_mhz == CLK_LL_PLL_320M_FREQ_MHZ && cpu_freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ) { + HAL_LOGE(CLK_HAL_TAG, "Invalid cpu config"); + return 0; + } + return cpu_freq_mhz * MHZ; + } + case SOC_CPU_CLK_SRC_APLL: { + uint32_t apll_freq_hz = clk_hal_apll_get_freq_hz(); + uint32_t divider = clk_ll_cpu_get_divider_from_apll(); + if (divider == 0) { + HAL_LOGE(CLK_HAL_TAG, "Invalid cpu config"); + return 0; + } + return apll_freq_hz / divider; + } + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); + } +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + // AHB_CLK path is highly dependent on CPU_CLK path + switch (clk_ll_cpu_get_src()) { + case SOC_CPU_CLK_SRC_PLL: + // AHB_CLK is a fixed value when CPU_CLK is clocked from PLL + return CLK_LL_AHB_MAX_FREQ_MHZ * MHZ; + case SOC_CPU_CLK_SRC_APLL: + return clk_hal_cpu_get_freq_hz() >> 1; + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_cpu_get_freq_hz(); + } +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + // ESP32S2's supported XTAL frequency is fixed, didn't save in the RTC storage register + return CLK_LL_XTAL_FREQ_MHZ; +} + +uint32_t clk_hal_apll_get_freq_hz(void) +{ + uint32_t xtal_freq_mhz = clk_hal_xtal_get_freq_mhz(); + uint32_t o_div = 0; + uint32_t sdm0 = 0; + uint32_t sdm1 = 0; + uint32_t sdm2 = 0; + clk_ll_apll_get_config(&o_div, &sdm0, &sdm1, &sdm2); + uint32_t apll_freq_hz = (uint32_t)(xtal_freq_mhz * MHZ * (4 + sdm2 + (float)sdm1/256.0 + (float)sdm0/65536.0) / + (((float)o_div + 2) * 2)); + return apll_freq_hz; +} diff --git a/components/hal/esp32s2/include/hal/clk_tree_ll.h b/components/hal/esp32s2/include/hal/clk_tree_ll.h index 716f205806..ae4b9f0b96 100644 --- a/components/hal/esp32s2/include/hal/clk_tree_ll.h +++ b/components/hal/esp32s2/include/hal/clk_tree_ll.h @@ -32,6 +32,8 @@ extern "C" { #define CLK_LL_PLL_320M_FREQ_MHZ (320) #define CLK_LL_PLL_480M_FREQ_MHZ (480) +#define CLK_LL_AHB_MAX_FREQ_MHZ CLK_LL_PLL_80M_FREQ_MHZ + // ESP32S2 only supports 40MHz crystal #define CLK_LL_XTAL_FREQ_MHZ (40) @@ -107,6 +109,22 @@ static inline void clk_ll_apll_disable(void) CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU); } +/** + * @brief Get APLL configuration which can be used to calculate APLL frequency + * + * @param[out] o_div Frequency divider, 0..31 + * @param[out] sdm0 Frequency adjustment parameter, 0..255 + * @param[out] sdm1 Frequency adjustment parameter, 0..255 + * @param[out] sdm2 Frequency adjustment parameter, 0..63 + */ +static inline void clk_ll_apll_get_config(uint32_t *o_div, uint32_t *sdm0, uint32_t *sdm1, uint32_t *sdm2) +{ + *o_div = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV); + *sdm0 = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_DSDM0); + *sdm1 = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_DSDM1); + *sdm2 = REGI2C_READ_MASK(I2C_APLL, I2C_APLL_DSDM2); +} + /** * @brief Set APLL configuration * @@ -542,6 +560,26 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_cpu_get_divider(voi return REG_GET_FIELD(DPORT_SYSCLK_CONF_REG, DPORT_PRE_DIV_CNT) + 1; } +/** + * @brief Get CPU_CLK's APLL clock source path divider + * + * @return Divider. Returns 0 means invalid. + */ +static inline uint32_t clk_ll_cpu_get_divider_from_apll(void) +{ + // APLL path divider choice depends on PLL_FREQ_SEL and CPUPERIOD_SEL + uint32_t pll_freq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_PLL_FREQ_SEL); + uint32_t cpu_freq_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL); + if (pll_freq_sel == 0 && cpu_freq_sel == 0) { + return 4; + } else if (pll_freq_sel == 0 && cpu_freq_sel == 1) { + return 2; + } else { + // Invalid configuration if APLL is the clock source + return 0; + } +} + /** * @brief Set REF_TICK divider to make REF_TICK frequency at 1MHz * diff --git a/components/hal/esp32s3/clk_tree_hal.c b/components/hal/esp32s3/clk_tree_hal.c new file mode 100644 index 0000000000..6e62a377a0 --- /dev/null +++ b/components/hal/esp32s3/clk_tree_hal.c @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "hal/clk_tree_hal.h" +#include "hal/clk_tree_ll.h" +#include "soc/rtc.h" +#include "hal/assert.h" +#include "hal/log.h" + +static const char *CLK_HAL_TAG = "clk_hal"; + +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src) +{ + switch (cpu_clk_src) { + case SOC_CPU_CLK_SRC_XTAL: + return clk_hal_xtal_get_freq_mhz(); + case SOC_CPU_CLK_SRC_PLL: + return clk_ll_bbpll_get_freq_mhz(); + case SOC_CPU_CLK_SRC_RC_FAST: + return SOC_CLK_RC_FAST_FREQ_APPROX / MHZ; + default: + // Unknown CPU_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_cpu_get_freq_hz(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + switch (source) { + case SOC_CPU_CLK_SRC_PLL: { + // PLL 320MHz, CPU 240MHz is an undetermined state + uint32_t pll_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + uint32_t cpu_freq_mhz = clk_ll_cpu_get_freq_mhz_from_pll(); + if (pll_freq_mhz == CLK_LL_PLL_320M_FREQ_MHZ && cpu_freq_mhz == CLK_LL_PLL_240M_FREQ_MHZ) { + HAL_LOGE(CLK_HAL_TAG, "Invalid cpu config"); + return 0; + } + return cpu_freq_mhz * MHZ; + } + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_soc_root_get_freq_mhz(source) * MHZ / clk_ll_cpu_get_divider(); + } +} + +uint32_t clk_hal_ahb_get_freq_hz(void) +{ + // AHB_CLK path is highly dependent on CPU_CLK path + switch (clk_ll_cpu_get_src()) { + case SOC_CPU_CLK_SRC_PLL: + // AHB_CLK is a fixed value when CPU_CLK is clocked from PLL + return CLK_LL_AHB_MAX_FREQ_MHZ * MHZ; + default: // SOC_CPU_CLK_SRC_XTAL, SOC_CPU_CLK_SRC_RC_FAST... + return clk_hal_cpu_get_freq_hz(); + } +} + +uint32_t clk_hal_apb_get_freq_hz(void) +{ + return clk_hal_ahb_get_freq_hz(); +} + +uint32_t clk_hal_lp_slow_get_freq_hz(void) +{ + switch (clk_ll_rtc_slow_get_src()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: + return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: + return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256: + return SOC_CLK_RC_FAST_D256_FREQ_APPROX; + default: + // Unknown RTC_SLOW_CLK mux input + HAL_ASSERT(false); + return 0; + } +} + +uint32_t clk_hal_xtal_get_freq_mhz(void) +{ + uint32_t freq = clk_ll_xtal_load_freq_mhz(); + if (freq == 0) { + HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume 40MHz"); + return (uint32_t)RTC_XTAL_FREQ_40M; + } + return freq; +} diff --git a/components/hal/esp32s3/include/hal/clk_tree_ll.h b/components/hal/esp32s3/include/hal/clk_tree_ll.h index c62334c8c8..c247c36b3f 100644 --- a/components/hal/esp32s3/include/hal/clk_tree_ll.h +++ b/components/hal/esp32s3/include/hal/clk_tree_ll.h @@ -31,6 +31,8 @@ extern "C" { #define CLK_LL_PLL_320M_FREQ_MHZ (320) #define CLK_LL_PLL_480M_FREQ_MHZ (480) +#define CLK_LL_AHB_MAX_FREQ_MHZ CLK_LL_PLL_80M_FREQ_MHZ + #define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ .dac = 3, \ .dres = 3, \ @@ -620,10 +622,18 @@ static inline void clk_ll_rc_slow_set_divider(uint32_t divider) * Value of RTC_XTAL_FREQ_REG is stored as two copies in lower and upper 16-bit * halves. These are the routines to work with that representation. * - * @param xtal_freq_mhz XTAL frequency, in MHz + * @param xtal_freq_mhz XTAL frequency, in MHz. The frequency must necessarily be even, + * otherwise there will be a conflict with the low bit, which is used to disable logs + * in the ROM code. */ static inline void clk_ll_xtal_store_freq_mhz(uint32_t xtal_freq_mhz) { + // Read the status of whether disabling logging from ROM code + uint32_t reg = READ_PERI_REG(RTC_XTAL_FREQ_REG) & RTC_DISABLE_ROM_LOG; + // If so, need to write back this setting + if (reg == RTC_DISABLE_ROM_LOG) { + xtal_freq_mhz |= 1; + } WRITE_PERI_REG(RTC_XTAL_FREQ_REG, (xtal_freq_mhz & UINT16_MAX) | ((xtal_freq_mhz & UINT16_MAX) << 16)); } @@ -641,7 +651,7 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_xtal_load_freq_mhz( uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG); if ((xtal_freq_reg & 0xFFFF) == ((xtal_freq_reg >> 16) & 0xFFFF) && xtal_freq_reg != 0 && xtal_freq_reg != UINT32_MAX) { - return xtal_freq_reg & UINT16_MAX; + return xtal_freq_reg & ~RTC_DISABLE_ROM_LOG & UINT16_MAX; } // If the format in reg is invalid return 0; diff --git a/components/hal/include/hal/clk_tree_hal.h b/components/hal/include/hal/clk_tree_hal.h new file mode 100644 index 0000000000..e05ab128c9 --- /dev/null +++ b/components/hal/include/hal/clk_tree_hal.h @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include "soc/clk_tree_defs.h" +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Get SOC_ROOT_CLK frequency + * + * @param cpu_clk_src One of the clock sources in soc_cpu_clk_src_t + * + * @return SOC ROOT clock frequency, in MHz. Returns 0 if input argument is invalid. + */ +uint32_t clk_hal_soc_root_get_freq_mhz(soc_cpu_clk_src_t cpu_clk_src); + +/** + * @brief Get CPU_CLK frequency + * + * @return CPU clock frequency, in Hz. Returns 0 if internal clock configuration is invalid. + */ +uint32_t clk_hal_cpu_get_freq_hz(void); + +/** + * @brief Get AHB_CLK frequency + * + * @return AHB clock frequency, in Hz. Returns 0 if internal clock configuration is invalid. + */ +uint32_t clk_hal_ahb_get_freq_hz(void); + +/** + * @brief Get APB_CLK frequency + * + * @return APB clock frequency, in Hz. Returns 0 if internal clock configuration is invalid. + */ +uint32_t clk_hal_apb_get_freq_hz(void); + +/** + * @brief Get LP_SLOW_CLK (i.e. RTC_SLOW_CLK) approximate frequency + * + * @return LP Slow clock frequency, in Hz. Returns 0 if LP_SLOW clock source is invalid. + */ +uint32_t clk_hal_lp_slow_get_freq_hz(void); + +/** + * @brief Get XTAL_CLK frequency + * + * @return XTAL clock frequency, in MHz + */ +uint32_t clk_hal_xtal_get_freq_mhz(void); + +#if SOC_CLK_APLL_SUPPORTED +/** + * @brief Get APLL_CLK frequency + * + * @return APLL clock frequency, in Hz + */ +uint32_t clk_hal_apll_get_freq_hz(void); +#endif //SOC_CLK_APLL_SUPPORTED + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 11f7e8e150..d4884ec25d 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -771,6 +771,10 @@ config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y +config SOC_CLK_XTAL32K_SUPPORTED + bool + default y + config SOC_SDMMC_USE_IOMUX bool default y diff --git a/components/soc/esp32/include/soc/clk_tree_defs.h b/components/soc/esp32/include/soc/clk_tree_defs.h index ee4a10046b..63506e28d7 100644 --- a/components/soc/esp32/include/soc/clk_tree_defs.h +++ b/components/soc/esp32/include/soc/clk_tree_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -115,6 +115,7 @@ typedef enum { SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external crystal (2~40MHz) */ SOC_MOD_CLK_REF_TICK, /*!< REF_TICK is derived from APB, it has a fixed frequency of 1MHz even when APB frequency changes */ SOC_MOD_CLK_APLL, /*!< APLL is sourced from PLL, and its frequency is configurable through APLL configuration registers */ + SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ } soc_module_clk_t; //////////////////////////////////////////////////SYSTIMER/////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 291aac7cb1..c9da452ffe 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -384,6 +384,8 @@ #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 (1) #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) +#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ + /*-------------------------- SDMMC CAPS -----------------------------------------*/ /* On ESP32, clock/cmd/data pins use IO MUX. diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 581ae70901..e35ad85ced 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -615,6 +615,10 @@ config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y +config SOC_CLK_OSC_SLOW_SUPPORTED + bool + default y + config SOC_WIFI_HW_TSF bool default y diff --git a/components/soc/esp32c2/include/soc/clk_tree_defs.h b/components/soc/esp32c2/include/soc/clk_tree_defs.h index bb3b0f4ac4..6954fea0cb 100644 --- a/components/soc/esp32c2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c2/include/soc/clk_tree_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -110,6 +110,7 @@ typedef enum { SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST_D256, /*!< RC_FAST_D256_CLK comes from the internal 20MHz rc oscillator, divided by 256, and passing a clock gating to the peripherals */ SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 26/40MHz crystal */ + SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ } soc_module_clk_t; //////////////////////////////////////////////////SYSTIMER/////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index d883c46be6..a2f8eb473b 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -294,6 +294,8 @@ #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 (1) #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) +#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< ESP32C2 only supports to connect an external oscillator, not a crystal */ + /*------------------------------------ WI-FI CAPS ------------------------------------*/ #define SOC_WIFI_HW_TSF (1) /*!< Support hardware TSF */ #define SOC_WIFI_FTM_SUPPORT (0) /*!< FTM is not supported */ diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index e3c0bd6215..b829bd5ab0 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -871,6 +871,10 @@ config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y +config SOC_CLK_XTAL32K_SUPPORTED + bool + default y + config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC bool default y diff --git a/components/soc/esp32c3/include/soc/clk_tree_defs.h b/components/soc/esp32c3/include/soc/clk_tree_defs.h index e8550b73a6..3c906fce58 100644 --- a/components/soc/esp32c3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c3/include/soc/clk_tree_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -106,11 +106,11 @@ typedef enum { SOC_MOD_CLK_APB, /*!< APB_CLK is highly dependent on the CPU_CLK source */ SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from PLL, and has a fixed frequency of 80MHz */ SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from PLL, and has a fixed frequency of 160MHz */ - SOC_MOD_CLK_PLL_D2, /*!< PLL_D2_CLK is derived from PLL, it has a fixed divider of 2 */ SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST_D256, /*!< RC_FAST_D256_CLK comes from the internal 20MHz rc oscillator, divided by 256, and passing a clock gating to the peripherals */ SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 40MHz crystal */ + SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ } soc_module_clk_t; //////////////////////////////////////////////////SYSTIMER/////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index b02b02fc03..725174e186 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -388,6 +388,8 @@ #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 (1) #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) +#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ + /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 8b6165ffb4..c8d25e64e5 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -999,6 +999,18 @@ config SOC_MODEM_CLOCK_IS_INDEPENDENT bool default y +config SOC_CLK_XTAL32K_SUPPORTED + bool + default y + +config SOC_CLK_OSC_SLOW_SUPPORTED + bool + default y + +config SOC_CLK_RC32K_SUPPORTED + bool + default y + config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC bool default y diff --git a/components/soc/esp32c6/include/soc/clk_tree_defs.h b/components/soc/esp32c6/include/soc/clk_tree_defs.h index a6b9c77700..16243140eb 100644 --- a/components/soc/esp32c6/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c6/include/soc/clk_tree_defs.h @@ -37,8 +37,8 @@ extern "C" { * * 6) External Slow Clock (optional): OSC_SLOW * - * A clock signal generated by an external circuit with frequency ~32kHz can be connected to GPIO0 - * to be the clock source for the RTC_SLOW_CLK. + * A slow clock signal generated by an external circuit can be connected to GPIO0 to be the clock source for the + * RTC_SLOW_CLK. * * OSC_SLOW_CLK can also be calibrated to get its exact frequency. */ @@ -95,7 +95,7 @@ typedef enum { */ typedef enum { SOC_RTC_FAST_CLK_SRC_RC_FAST = 0, /*!< Select RC_FAST_CLK as RTC_FAST_CLK source */ - SOC_RTC_FAST_CLK_SRC_XTAL_D2 = 1, /*!< Select XTAL_D2_CLK (may referred as XTAL_CLK_DIV_2) as RTC_FAST_CLK source */ + SOC_RTC_FAST_CLK_SRC_XTAL_D2 = 1, /*!< Select XTAL_D2_CLK as RTC_FAST_CLK source */ SOC_RTC_FAST_CLK_SRC_XTAL_DIV = SOC_RTC_FAST_CLK_SRC_XTAL_D2, /*!< Alias name for `SOC_RTC_FAST_CLK_SRC_XTAL_D2` */ SOC_RTC_FAST_CLK_SRC_INVALID, /*!< Invalid RTC_FAST_CLK source */ } soc_rtc_fast_clk_src_t; @@ -121,6 +121,7 @@ typedef enum { SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 40MHz crystal */ + SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ } soc_module_clk_t; //////////////////////////////////////////////////SYSTIMER////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 8d67a42e99..b8ce95ff0e 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -446,6 +446,10 @@ #define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1) #define SOC_MODEM_CLOCK_IS_INDEPENDENT (1) +#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */ +#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */ +#define SOC_CLK_RC32K_SUPPORTED (1) /*!< Support an internal 32kHz RC oscillator */ + /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 400f89f2bc..4b54431c59 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -795,6 +795,18 @@ config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y +config SOC_CLK_XTAL32K_SUPPORTED + bool + default y + +config SOC_CLK_OSC_SLOW_SUPPORTED + bool + default y + +config SOC_CLK_RC32K_SUPPORTED + bool + default y + config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC bool default y diff --git a/components/soc/esp32h2/include/soc/clk_tree_defs.h b/components/soc/esp32h2/include/soc/clk_tree_defs.h index 7175713248..d584e56278 100644 --- a/components/soc/esp32h2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h2/include/soc/clk_tree_defs.h @@ -124,6 +124,7 @@ typedef enum { SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 8MHz rc oscillator, passing a clock gating to the peripherals */ SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 40MHz crystal */ + SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ } soc_module_clk_t; //////////////////////////////////////////////////SYSTIMER/////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index a3cbb0669b..a21f3ff543 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -423,6 +423,13 @@ #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!