diff --git a/components/driver/i2c/i2c.c b/components/driver/i2c/i2c.c index 98496ea79f..aba642e880 100644 --- a/components/driver/i2c/i2c.c +++ b/components/driver/i2c/i2c.c @@ -36,9 +36,7 @@ #if SOC_I2C_SUPPORT_APB || SOC_I2C_SUPPORT_XTAL #include "esp_private/esp_clk.h" #endif -#if SOC_I2C_SUPPORT_RTC -#include "clk_ctrl_os.h" -#endif +#include "esp_private/esp_clk_tree_common.h" static const char *I2C_TAG = "i2c"; @@ -740,34 +738,8 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num) static uint32_t s_get_src_clk_freq(i2c_clock_source_t clk_src) { - // TODO: replace the following switch table by clk_tree API uint32_t periph_src_clk_hz = 0; - switch (clk_src) { -#if SOC_I2C_SUPPORT_APB - case I2C_CLK_SRC_APB: - periph_src_clk_hz = esp_clk_apb_freq(); - break; -#endif -#if SOC_I2C_SUPPORT_XTAL - case I2C_CLK_SRC_XTAL: - periph_src_clk_hz = esp_clk_xtal_freq(); - break; -#endif -#if SOC_I2C_SUPPORT_RTC - case I2C_CLK_SRC_RC_FAST: - periph_rtc_dig_clk8m_enable(); - periph_src_clk_hz = periph_rtc_dig_clk8m_get_freq(); - break; -#endif -#if SOC_I2C_SUPPORT_REF_TICK - case I2C_CLK_SRC_REF_TICK: - periph_src_clk_hz = REF_CLK_FREQ; - break; -#endif - default: - ESP_RETURN_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, I2C_TAG, "clock source %d is not supported", clk_src); - break; - } + esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz); return periph_src_clk_hz; } diff --git a/components/driver/twai/twai.c b/components/driver/twai/twai.c index 8fde520ee7..4e45592baa 100644 --- a/components/driver/twai/twai.c +++ b/components/driver/twai/twai.c @@ -18,7 +18,6 @@ #include "esp_check.h" #include "esp_heap_caps.h" #include "esp_clk_tree.h" -#include "clk_ctrl_os.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" #include "esp_private/gpio.h" diff --git a/components/esp_driver_dac/dac_cosine.c b/components/esp_driver_dac/dac_cosine.c index 445cc7455b..d68edb39e6 100644 --- a/components/esp_driver_dac/dac_cosine.c +++ b/components/esp_driver_dac/dac_cosine.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,7 +9,7 @@ #include "driver/dac_cosine.h" #include "hal/clk_tree_ll.h" #include "dac_priv_common.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #if CONFIG_DAC_ENABLE_DEBUG_LOG // The local log level must be defined before including esp_log.h @@ -57,13 +57,10 @@ esp_err_t dac_cosine_new_channel(const dac_cosine_config_t *cos_cfg, dac_cosine_ /* Register the handle */ ESP_GOTO_ON_ERROR(dac_priv_register_channel(cos_cfg->chan_id, "dac cosine"), err1, TAG, "register dac channel %d failed", cos_cfg->chan_id); - /* Only enabled for getting the correct rtc clock frequency */ - periph_rtc_dig_clk8m_enable(); /* Cosine wave generator uses RTC_FAST clock which is divided from RC_FAST */ - // [clk_tree] TODO: replace the following calculation with the RTC_FAST frequency getter - uint32_t rtc_clk_freq = periph_rtc_dig_clk8m_get_freq() / clk_ll_rc_fast_get_divider(); - /* Disabled after getting the frequency, will re-enabled again when start outputting cosine wave */ - periph_rtc_dig_clk8m_disable(); + uint32_t rtc_clk_freq = 0; + esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_RC_FAST, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rtc_clk_freq); + if (rtc_clk_freq == 0) { ESP_LOGW(TAG, "RTC clock calibration failed, using the approximate value as default"); rtc_clk_freq = SOC_CLK_RC_FAST_FREQ_APPROX; @@ -106,14 +103,15 @@ esp_err_t dac_cosine_del_channel(dac_cosine_handle_t handle) esp_err_t dac_cosine_start(dac_cosine_handle_t handle) { + esp_err_t ret = ESP_OK; DAC_NULL_POINTER_CHECK(handle); ESP_RETURN_ON_FALSE(!handle->is_started, ESP_ERR_INVALID_STATE, TAG, "the dac channel has already started"); /* Acquire the RTC clock */ - periph_rtc_dig_clk8m_enable(); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_RC_FAST, true), TAG, "RC_FAST clock enable failed"); /* Enabled DAC channel */ - ESP_RETURN_ON_ERROR(dac_priv_enable_channel(handle->cfg.chan_id), TAG, - "enable dac channel %d failed", handle->cfg.chan_id); + ESP_GOTO_ON_ERROR(dac_priv_enable_channel(handle->cfg.chan_id), err, TAG, + "enable dac channel %d failed", handle->cfg.chan_id); /* Enabled the cosine wave generator if no channel using it before */ DAC_RTC_ENTER_CRITICAL(); if (s_cwg_refer_cnt == 0) { @@ -126,6 +124,10 @@ esp_err_t dac_cosine_start(dac_cosine_handle_t handle) DAC_RTC_EXIT_CRITICAL(); return ESP_OK; + +err: + esp_clk_tree_enable_src(SOC_MOD_CLK_RC_FAST, false); + return ret; } esp_err_t dac_cosine_stop(dac_cosine_handle_t handle) @@ -148,7 +150,7 @@ esp_err_t dac_cosine_stop(dac_cosine_handle_t handle) handle->is_started = false; DAC_RTC_EXIT_CRITICAL(); /* Release the RTC clock */ - periph_rtc_dig_clk8m_disable(); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_RC_FAST, false), TAG, "RC_FAST clock disable failed"); return ESP_OK; } diff --git a/components/esp_driver_dac/esp32/dac_dma.c b/components/esp_driver_dac/esp32/dac_dma.c index 21314ad098..67e500dc27 100644 --- a/components/esp_driver_dac/esp32/dac_dma.c +++ b/components/esp_driver_dac/esp32/dac_dma.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,7 +22,7 @@ #include "../dac_priv_dma.h" #include "esp_private/i2s_platform.h" #include "esp_private/esp_clk.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #if CONFIG_DAC_ENABLE_DEBUG_LOG // The local log level must be defined before including esp_log.h // Set the maximum log level for this source file @@ -56,7 +56,7 @@ static uint32_t s_dac_set_apll_freq(uint32_t mclk) uint32_t expt_freq = mclk * div; /* Set APLL coefficients to the given frequency */ uint32_t real_freq = 0; - esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq); + esp_err_t ret = esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, expt_freq, &real_freq); if (ret == ESP_ERR_INVALID_ARG) { return 0; } @@ -120,7 +120,7 @@ esp_err_t dac_dma_periph_init(uint32_t freq_hz, bool is_alternate, bool is_apll) s_ddp->periph_dev = (void *)I2S_LL_GET_HW(DAC_DMA_PERIPH_I2S_NUM); if (is_apll) { - periph_rtc_apll_acquire(); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true), err, TAG, "APLL enable failed"); s_ddp->use_apll = true; } ESP_GOTO_ON_ERROR(s_dac_dma_periph_set_clock(freq_hz, is_apll), err, TAG, "Failed to set clock of DMA peripheral"); @@ -157,7 +157,7 @@ esp_err_t dac_dma_periph_deinit(void) ESP_RETURN_ON_ERROR(i2s_platform_release_occupation(I2S_CTLR_HP, DAC_DMA_PERIPH_I2S_NUM), TAG, "Failed to release DAC DMA peripheral"); i2s_ll_enable_intr(s_ddp->periph_dev, I2S_LL_EVENT_TX_EOF | I2S_LL_EVENT_TX_TEOF, false); if (s_ddp->use_apll) { - periph_rtc_apll_release(); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false), TAG, "APLL disable failed"); s_ddp->use_apll = false; } free(s_ddp); diff --git a/components/esp_driver_dac/esp32s2/dac_dma.c b/components/esp_driver_dac/esp32s2/dac_dma.c index ad10e62f84..12d9710ac0 100644 --- a/components/esp_driver_dac/esp32s2/dac_dma.c +++ b/components/esp_driver_dac/esp32s2/dac_dma.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,7 @@ #include "soc/soc.h" #include "soc/soc_caps.h" #include "../dac_priv_dma.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #if CONFIG_DAC_ENABLE_DEBUG_LOG // The local log level must be defined before including esp_log.h // Set the maximum log level for this source file @@ -52,7 +52,7 @@ static uint32_t s_dac_set_apll_freq(uint32_t expt_freq) { /* Set APLL coefficients to the given frequency */ uint32_t real_freq = 0; - esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq); + esp_err_t ret = esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, expt_freq, &real_freq); if (ret == ESP_ERR_INVALID_ARG) { return 0; } @@ -138,7 +138,7 @@ esp_err_t dac_dma_periph_init(uint32_t freq_hz, bool is_alternate, bool is_apll) s_ddp->periph_dev = (void *)SPI_LL_GET_HW(DAC_DMA_PERIPH_SPI_HOST); if (is_apll) { - periph_rtc_apll_acquire(); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true), err, TAG, "APLL enable failed"); s_ddp->use_apll = true; } /* When transmit alternately, twice frequency is needed to guarantee the convert frequency in one channel */ @@ -167,7 +167,7 @@ esp_err_t dac_dma_periph_deinit(void) adc_apb_periph_free(); if (s_ddp) { if (s_ddp->use_apll) { - periph_rtc_apll_release(); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false), TAG, "APLL disable failed"); s_ddp->use_apll = false; } free(s_ddp); diff --git a/components/esp_driver_gptimer/src/gptimer.c b/components/esp_driver_gptimer/src/gptimer.c index 0f97c59460..fe90ffd3d9 100644 --- a/components/esp_driver_gptimer/src/gptimer.c +++ b/components/esp_driver_gptimer/src/gptimer.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -160,7 +160,6 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re // initialize HAL layer timer_hal_init(&timer->hal, group_id, timer_id); // select clock source, set clock resolution - ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)config->clk_src, true), err, TAG, "clock source enable failed"); ESP_GOTO_ON_ERROR(gptimer_select_periph_clock(timer, config->clk_src, config->resolution_hz), err, TAG, "set periph clock failed"); // initialize counter value to zero timer_hal_set_counter_value(&timer->hal, 0); @@ -195,7 +194,6 @@ esp_err_t gptimer_del_timer(gptimer_handle_t timer) ESP_RETURN_ON_FALSE(timer, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(atomic_load(&timer->fsm) == GPTIMER_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "timer not in init state"); gptimer_group_t *group = timer->group; - gptimer_clock_source_t clk_src = timer->clk_src; int group_id = group->group_id; int timer_id = timer->timer_id; timer_hal_context_t *hal = &timer->hal; @@ -208,15 +206,6 @@ esp_err_t gptimer_del_timer(gptimer_handle_t timer) // recycle memory resource ESP_RETURN_ON_ERROR(gptimer_destroy(timer), TAG, "destroy gptimer failed"); - switch (clk_src) { -#if TIMER_LL_FUNC_CLOCK_SUPPORT_RC_FAST - case GPTIMER_CLK_SRC_RC_FAST: - periph_rtc_dig_clk8m_disable(); - break; -#endif // TIMER_LL_FUNC_CLOCK_SUPPORT_RC_FAST - default: - break; - } return ESP_OK; } diff --git a/components/esp_driver_gptimer/src/gptimer_common.c b/components/esp_driver_gptimer/src/gptimer_common.c index c66a447136..66ac6f8ee2 100644 --- a/components/esp_driver_gptimer/src/gptimer_common.c +++ b/components/esp_driver_gptimer/src/gptimer_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -91,14 +91,7 @@ esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t s uint32_t counter_src_hz = 0; int timer_id = timer->timer_id; int group_id = timer->group->group_id; - // TODO: [clk_tree] to use a generic clock enable/disable or acquire/release function for all clock source -#if TIMER_LL_FUNC_CLOCK_SUPPORT_RC_FAST - if (src_clk == GPTIMER_CLK_SRC_RC_FAST) { - // RC_FAST clock is not enabled automatically on start up, we enable it here manually. - // Note there's a ref count in the enable/disable function, we must call them in pair in the driver. - periph_rtc_dig_clk8m_enable(); - } -#endif // TIMER_LL_FUNC_CLOCK_SUPPORT_RC_FAST + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(src_clk, true), TAG, "clock source enable failed"); timer->clk_src = src_clk; // get clock source frequency diff --git a/components/esp_driver_gptimer/src/gptimer_priv.h b/components/esp_driver_gptimer/src/gptimer_priv.h index 320bc1ea07..23ae985acc 100644 --- a/components/esp_driver_gptimer/src/gptimer_priv.h +++ b/components/esp_driver_gptimer/src/gptimer_priv.h @@ -27,7 +27,7 @@ #include "hal/timer_types.h" #include "hal/timer_hal.h" #include "hal/timer_ll.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #include "esp_private/esp_clk_tree_common.h" #include "esp_private/sleep_retention.h" #include "esp_private/periph_ctrl.h" diff --git a/components/esp_driver_i2c/i2c_common.c b/components/esp_driver_i2c/i2c_common.c index 165ec5d894..cc09324bff 100644 --- a/components/esp_driver_i2c/i2c_common.c +++ b/components/esp_driver_i2c/i2c_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,7 @@ #include "soc/clk_tree_defs.h" #include "hal/i2c_periph.h" #include "esp_clk_tree.h" -#include "clk_ctrl_os.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_private/gpio.h" #include "esp_private/esp_gpio_reserve.h" #if SOC_LP_I2C_SUPPORTED @@ -233,15 +233,7 @@ esp_err_t i2c_release_bus_handle(i2c_bus_handle_t i2c_bus) } _lock_release(&s_i2c_platform.mutex); - switch (clk_src) { -#if SOC_I2C_SUPPORT_RTC - case I2C_CLK_SRC_RC_FAST: - periph_rtc_dig_clk8m_disable(); - break; -#endif // SOC_I2C_SUPPORT_RTC - default: - break; - } + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(clk_src, false), TAG, "clock source clock disable failed"); if (do_deinitialize) { ESP_LOGD(TAG, "delete bus %d", port_num); @@ -268,14 +260,7 @@ esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, soc_module_clk_t clk_ ESP_RETURN_ON_FALSE(!clock_selection_conflict, ESP_ERR_INVALID_STATE, TAG, "group clock conflict, already is %d but attempt to %d", handle->clk_src, clk_src); - // TODO: [clk_tree] to use a generic clock enable/disable or acquire/release function for all clock source -#if SOC_I2C_SUPPORT_RTC - if (clk_src == (soc_module_clk_t)I2C_CLK_SRC_RC_FAST) { - // RC_FAST clock is not enabled automatically on start up, we enable it here manually. - // Note there's a ref count in the enable/disable function, we must call them in pair in the driver. - periph_rtc_dig_clk8m_enable(); - } -#endif // SOC_I2C_SUPPORT_RTC + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(clk_src, true), TAG, "clock source clock enable failed"); ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &periph_src_clk_hz), TAG, "i2c get clock frequency error"); diff --git a/components/esp_driver_i2c/i2c_slave.c b/components/esp_driver_i2c/i2c_slave.c index a477389674..a367fb4444 100644 --- a/components/esp_driver_i2c/i2c_slave.c +++ b/components/esp_driver_i2c/i2c_slave.c @@ -305,6 +305,7 @@ esp_err_t i2c_new_slave_device(const i2c_slave_config_t *slave_config, i2c_slave i2c_ll_set_slave_addr(hal->dev, slave_config->slave_addr, false); i2c_ll_set_tout(hal->dev, I2C_LL_MAX_TIMEOUT); + ESP_GOTO_ON_ERROR(i2c_select_periph_clock(i2c_slave->base, slave_config->clk_source), err, TAG, "select periph clock failed"); PERIPH_RCC_ATOMIC() { i2c_ll_set_source_clk(hal->dev, slave_config->clk_source); } diff --git a/components/esp_driver_i2s/i2s_common.c b/components/esp_driver_i2s/i2s_common.c index affce1bc1a..981ae04dd0 100644 --- a/components/esp_driver_i2s/i2s_common.c +++ b/components/esp_driver_i2s/i2s_common.c @@ -36,7 +36,6 @@ #endif #if SOC_I2S_SUPPORTS_APLL #include "hal/clk_tree_ll.h" -#include "clk_ctrl_os.h" #endif #include "esp_private/i2s_platform.h" @@ -55,7 +54,6 @@ #include "esp_clock_output.h" #endif -#include "clk_ctrl_os.h" #include "esp_clk_tree.h" #include "esp_private/esp_clk_tree_common.h" #include "esp_intr_alloc.h" @@ -319,9 +317,6 @@ static esp_err_t i2s_register_channel(i2s_controller_t *i2s_obj, i2s_dir_t dir, new_chan->role = I2S_ROLE_MASTER; // Set default role to master new_chan->dir = dir; new_chan->state = I2S_CHAN_STATE_REGISTER; -#if SOC_I2S_SUPPORTS_APLL - new_chan->apll_en = false; -#endif new_chan->mode_info = NULL; new_chan->controller = i2s_obj; #if CONFIG_PM_ENABLE @@ -580,7 +575,7 @@ static uint32_t i2s_set_get_apll_freq(uint32_t mclk_freq_hz) return 0; } uint32_t real_freq = 0; - esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq); + esp_err_t ret = esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, expt_freq, &real_freq); if (ret == ESP_ERR_INVALID_ARG) { ESP_LOGE(TAG, "set APLL freq failed due to invalid argument"); return 0; @@ -1029,7 +1024,6 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * i2s_obj->tx_chan->start = i2s_tx_channel_start; i2s_obj->tx_chan->stop = i2s_tx_channel_stop; *tx_handle = i2s_obj->tx_chan; - esp_clk_tree_enable_src((soc_module_clk_t)i2s_ll_tx_clk_get_src(i2s_obj->hal.dev), true); ESP_LOGD(TAG, "tx channel is registered on I2S%d successfully", i2s_obj->id); } /* Register and specify the rx handle */ @@ -1044,7 +1038,6 @@ esp_err_t i2s_new_channel(const i2s_chan_config_t *chan_cfg, i2s_chan_handle_t * i2s_obj->rx_chan->start = i2s_rx_channel_start; i2s_obj->rx_chan->stop = i2s_rx_channel_stop; *rx_handle = i2s_obj->rx_chan; - esp_clk_tree_enable_src((soc_module_clk_t)i2s_ll_rx_clk_get_src(i2s_obj->hal.dev), true); ESP_LOGD(TAG, "rx channel is registered on I2S%d successfully", i2s_obj->id); } @@ -1081,6 +1074,20 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle) i2s_dir_t __attribute__((unused)) dir = handle->dir; bool is_bound = true; +#if SOC_I2S_SUPPORTS_APLL + /* Must switch back to D2CLK on ESP32-S2, + * because the clock of some registers are bound to APLL, + * otherwise, once APLL is disabled, the registers can't be updated anymore + * NOTE: even this limitation is only applicable to ESP32-S2, switch back to Default clock does not harm for other chips */ + PERIPH_RCC_ATOMIC() { + if (handle->dir == I2S_DIR_TX) { + i2s_ll_tx_clk_set_src(handle->controller->hal.dev, I2S_CLK_SRC_DEFAULT); + } else { + i2s_ll_rx_clk_set_src(handle->controller->hal.dev, I2S_CLK_SRC_DEFAULT); + } + } +#endif + #if SOC_I2S_HW_VERSION_2 PERIPH_RCC_ATOMIC() { if (dir == I2S_DIR_TX) { @@ -1089,33 +1096,20 @@ esp_err_t i2s_del_channel(i2s_chan_handle_t handle) i2s_ll_rx_disable_clock(handle->controller->hal.dev); } } - if (handle->clk_src != I2S_CLK_SRC_EXTERNAL) #endif - { - i2s_clock_src_t clk_src = handle->clk_src; + + // disable clock source + i2s_clock_src_t clk_src = handle->clk_src; #ifdef I2S_LL_DEFAULT_CLK_SRC - if (clk_src == I2S_CLK_SRC_DEFAULT) { - clk_src = I2S_LL_DEFAULT_CLK_SRC; - } + if (clk_src == I2S_CLK_SRC_DEFAULT) { + clk_src = I2S_LL_DEFAULT_CLK_SRC; + } #endif + // since the enum value of default clock on some chips may be 0, we use mode to check if the clock is enabled + if (handle->mode != I2S_COMM_MODE_NONE) { esp_clk_tree_enable_src((soc_module_clk_t)clk_src, false); } -#if SOC_I2S_SUPPORTS_APLL - if (handle->apll_en) { - /* Must switch back to D2CLK on ESP32-S2, - * because the clock of some registers are bound to APLL, - * otherwise, once APLL is disabled, the registers can't be updated anymore */ - PERIPH_RCC_ATOMIC() { - if (handle->dir == I2S_DIR_TX) { - i2s_ll_tx_clk_set_src(handle->controller->hal.dev, I2S_CLK_SRC_DEFAULT); - } else { - i2s_ll_rx_clk_set_src(handle->controller->hal.dev, I2S_CLK_SRC_DEFAULT); - } - } - periph_rtc_apll_release(); - } -#endif #if CONFIG_PM_ENABLE if (handle->pm_lock) { esp_pm_lock_delete(handle->pm_lock); @@ -1442,6 +1436,8 @@ esp_err_t i2s_channel_read(i2s_chan_handle_t handle, void *dest, size_t size, si esp_err_t i2s_channel_tune_rate(i2s_chan_handle_t handle, const i2s_tuning_config_t *tune_cfg, i2s_tuning_info_t *tune_info) { + esp_err_t ret = ESP_OK; + /** We tune the sample rate via the MCLK clock. * Because the sample rate is decided by MCLK eventually, * and MCLK has a higher resolution which can be tuned more precisely. @@ -1480,11 +1476,11 @@ esp_err_t i2s_channel_tune_rate(i2s_chan_handle_t handle, const i2s_tuning_confi new_mclk = handle->origin_mclk_hz + tune_cfg->min_delta_mclk; } xSemaphoreTake(handle->mutex, portMAX_DELAY); -#if SOC_CLK_APLL_SUPPORTED +#if SOC_I2S_SUPPORTS_APLL if (handle->clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_release(); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false), err, TAG, "APLL disable failed"); handle->sclk_hz = i2s_set_get_apll_freq(new_mclk); - periph_rtc_apll_acquire(); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true), err, TAG, "APLL enable failed"); } #endif /* Calculate the new divider */ @@ -1492,7 +1488,8 @@ esp_err_t i2s_channel_tune_rate(i2s_chan_handle_t handle, const i2s_tuning_confi i2s_hal_calc_mclk_precise_division(handle->sclk_hz, new_mclk, &mclk_div); /* mclk_div = sclk / mclk >= 2 */ if (mclk_div.integer < 2) { - return ESP_ERR_INVALID_ARG; + ret = ESP_ERR_INVALID_ARG; + goto err; } /* Set the new divider for MCLK */ PERIPH_RCC_ATOMIC() { @@ -1526,7 +1523,11 @@ result: tune_info->water_mark = used_size * 100 / tot_size; } xSemaphoreGive(handle->mutex); - return ESP_OK; + return ret; + +err: + xSemaphoreGive(handle->mutex); + return ret; } #if SOC_I2S_SUPPORTS_TX_SYNC_CNT diff --git a/components/esp_driver_i2s/i2s_pdm.c b/components/esp_driver_i2s/i2s_pdm.c index 4d0b0cadac..855aceca88 100644 --- a/components/esp_driver_i2s/i2s_pdm.c +++ b/components/esp_driver_i2s/i2s_pdm.c @@ -20,7 +20,6 @@ #include "driver/i2s_pdm.h" #include "i2s_private.h" #include "esp_private/esp_clk_tree_common.h" -#include "clk_ctrl_os.h" #include "esp_intr_alloc.h" #include "esp_check.h" @@ -79,23 +78,18 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx #endif ESP_RETURN_ON_FALSE(clk_cfg->up_sample_fs <= 480, ESP_ERR_INVALID_ARG, TAG, "up_sample_fs should be within 480"); - i2s_hal_clock_info_t clk_info; - /* Calculate clock parameters */ - ESP_RETURN_ON_ERROR(i2s_pdm_tx_calculate_clock(handle, clk_cfg, &clk_info), TAG, "clock calculate failed"); - -#if SOC_I2S_HW_VERSION_2 - i2s_clock_src_t old_clk_src = handle->clk_src; - if (clk_cfg->clk_src != I2S_CLK_SRC_EXTERNAL) -#endif - { - i2s_clock_src_t clk_src = clk_cfg->clk_src; + i2s_clock_src_t clk_src = clk_cfg->clk_src; #ifdef I2S_LL_DEFAULT_CLK_SRC - if (clk_src == I2S_CLK_SRC_DEFAULT) { - clk_src = I2S_LL_DEFAULT_CLK_SRC; - } -#endif - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + if (clk_src == I2S_CLK_SRC_DEFAULT) { + clk_src = I2S_LL_DEFAULT_CLK_SRC; } +#endif + + i2s_hal_clock_info_t clk_info; + // Calculate clock parameters before enabling clock source + ESP_RETURN_ON_ERROR(i2s_pdm_tx_calculate_clock(handle, clk_cfg, &clk_info), TAG, "clock calculate failed"); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), TAG, "clock source enable failed"); + hal_utils_clk_div_t ret_mclk_div = {}; portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ @@ -110,7 +104,7 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx portEXIT_CRITICAL(&g_i2s.spinlock); uint64_t tmp_div = (uint64_t)ret_mclk_div.integer * ret_mclk_div.denominator + ret_mclk_div.numerator; - ESP_RETURN_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, TAG, "invalid mclk division result"); + ESP_GOTO_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid mclk division result"); /* Update the mode info: clock configuration */ memcpy(&(pdm_tx_cfg->clk_cfg), clk_cfg, sizeof(i2s_pdm_tx_clk_config_t)); @@ -120,16 +114,14 @@ static esp_err_t i2s_pdm_tx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_tx handle->curr_mclk_hz = handle->origin_mclk_hz; handle->bclk_hz = clk_info.bclk; -#if SOC_I2S_HW_VERSION_2 - if (old_clk_src != I2S_CLK_SRC_EXTERNAL) { - esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false); - } -#endif - ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); return ret; + +err: + esp_clk_tree_enable_src((soc_module_clk_t)clk_src, false); + return ret; } static esp_err_t i2s_pdm_tx_set_slot(i2s_chan_handle_t handle, const i2s_pdm_tx_slot_config_t *slot_cfg) @@ -238,13 +230,6 @@ esp_err_t i2s_channel_init_pdm_tx_mode(i2s_chan_handle_t handle, const i2s_pdm_t * while initializing, because clock and gpio is relay on the slot */ ESP_GOTO_ON_ERROR(i2s_pdm_tx_set_slot(handle, &pdm_tx_cfg->slot_cfg), err, TAG, "initialize channel failed while setting slot"); ESP_GOTO_ON_ERROR(i2s_pdm_tx_set_gpio(handle, &pdm_tx_cfg->gpio_cfg), err, TAG, "initialize channel failed while setting gpio pins"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is APLL */ - if (pdm_tx_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } -#endif ESP_GOTO_ON_ERROR(i2s_pdm_tx_set_clock(handle, &pdm_tx_cfg->clk_cfg), err, TAG, "initialize channel failed while setting clock"); ESP_GOTO_ON_ERROR(i2s_init_dma_intr(handle, I2S_INTR_ALLOC_FLAGS), err, TAG, "initialize dma interrupt failed"); @@ -287,23 +272,20 @@ esp_err_t i2s_channel_reconfig_pdm_tx_clock(i2s_chan_handle_t handle, const i2s_ i2s_pdm_tx_config_t *pdm_tx_cfg = (i2s_pdm_tx_config_t *)handle->mode_info; ESP_GOTO_ON_FALSE(pdm_tx_cfg, ESP_ERR_INVALID_STATE, err, TAG, "initialization not complete"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is changed to APLL */ - if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && pdm_tx_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } - /* Disable APLL and release its lock when clock source is changed to 160M_PLL */ - if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && pdm_tx_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_release(); - handle->apll_en = false; + i2s_clock_src_t old_clk_src = pdm_tx_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; } #endif ESP_GOTO_ON_ERROR(i2s_pdm_tx_set_clock(handle, clk_cfg), err, TAG, "update clock failed"); + + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); #ifdef CONFIG_PM_ENABLE // Create/Re-create power management lock - if (pdm_tx_cfg->clk_cfg.clk_src != clk_cfg->clk_src) { + if (old_clk_src != clk_cfg->clk_src) { ESP_GOTO_ON_ERROR(esp_pm_lock_delete(handle->pm_lock), err, TAG, "I2S delete old pm lock failed"); esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX; #if SOC_I2S_SUPPORTS_APLL && SOC_I2S_HW_VERSION_2 @@ -345,7 +327,15 @@ esp_err_t i2s_channel_reconfig_pdm_tx_slot(i2s_chan_handle_t handle, const i2s_p /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; if (pdm_tx_cfg->slot_cfg.slot_bit_width != slot_bits) { + i2s_clock_src_t old_clk_src = pdm_tx_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; + } +#endif ESP_GOTO_ON_ERROR(i2s_pdm_tx_set_clock(handle, &pdm_tx_cfg->clk_cfg), err, TAG, "update clock failed"); + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); } xSemaphoreGive(handle->mutex); @@ -435,23 +425,20 @@ static esp_err_t i2s_pdm_rx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_rx ESP_RETURN_ON_FALSE(clk_cfg->clk_src != I2S_CLK_SRC_EXTERNAL, ESP_ERR_INVALID_ARG, TAG, "not support external clock source in pdm mode"); #endif + i2s_clock_src_t clk_src = clk_cfg->clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (clk_src == I2S_CLK_SRC_DEFAULT) { + clk_src = I2S_LL_DEFAULT_CLK_SRC; + } +#endif + i2s_hal_clock_info_t clk_info; - /* Calculate clock parameters */ + /* Calculate clock parameters before enabling clock source, so that APLL frequency + * can be set while ref_cnt is still < 2 (which is the threshold for freq change) */ ESP_RETURN_ON_ERROR(i2s_pdm_rx_calculate_clock(handle, clk_cfg, &clk_info), TAG, "clock calculate failed"); -#if SOC_I2S_HW_VERSION_2 - i2s_clock_src_t old_clk_src = handle->clk_src; - if (clk_cfg->clk_src != I2S_CLK_SRC_EXTERNAL) -#endif - { - i2s_clock_src_t clk_src = clk_cfg->clk_src; -#ifdef I2S_LL_DEFAULT_CLK_SRC - if (clk_src == I2S_CLK_SRC_DEFAULT) { - clk_src = I2S_LL_DEFAULT_CLK_SRC; - } -#endif - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); - } + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), TAG, "clock source enable failed"); + hal_utils_clk_div_t ret_mclk_div = {}; portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ @@ -461,7 +448,7 @@ static esp_err_t i2s_pdm_rx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_rx portEXIT_CRITICAL(&g_i2s.spinlock); uint64_t tmp_div = (uint64_t)ret_mclk_div.integer * ret_mclk_div.denominator + ret_mclk_div.numerator; - ESP_RETURN_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, TAG, "invalid mclk division result"); + ESP_GOTO_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid mclk division result"); /* Update the mode info: clock configuration */ memcpy(&(pdm_rx_cfg->clk_cfg), clk_cfg, sizeof(i2s_pdm_rx_clk_config_t)); @@ -471,16 +458,14 @@ static esp_err_t i2s_pdm_rx_set_clock(i2s_chan_handle_t handle, const i2s_pdm_rx handle->curr_mclk_hz = handle->origin_mclk_hz; handle->bclk_hz = clk_info.bclk; -#if SOC_I2S_HW_VERSION_2 - if (old_clk_src != I2S_CLK_SRC_EXTERNAL) { - esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false); - } -#endif - ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); return ret; + +err: + esp_clk_tree_enable_src((soc_module_clk_t)clk_src, false); + return ret; } static esp_err_t i2s_pdm_rx_set_slot(i2s_chan_handle_t handle, const i2s_pdm_rx_slot_config_t *slot_cfg) @@ -590,13 +575,6 @@ esp_err_t i2s_channel_init_pdm_rx_mode(i2s_chan_handle_t handle, const i2s_pdm_r /* i2s_set_pdm_rx_slot should be called before i2s_set_pdm_rx_clock and i2s_pdm_rx_set_gpio while initializing, because clock is relay on the slot */ ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_slot(handle, &pdm_rx_cfg->slot_cfg), err, TAG, "initialize channel failed while setting slot"); ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_gpio(handle, &pdm_rx_cfg->gpio_cfg), err, TAG, "initialize channel failed while setting gpio pins"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is APLL */ - if (pdm_rx_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } -#endif ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_clock(handle, &pdm_rx_cfg->clk_cfg), err, TAG, "initialize channel failed while setting clock"); ESP_GOTO_ON_ERROR(i2s_init_dma_intr(handle, I2S_INTR_ALLOC_FLAGS), err, TAG, "initialize dma interrupt failed"); @@ -639,23 +617,20 @@ esp_err_t i2s_channel_reconfig_pdm_rx_clock(i2s_chan_handle_t handle, const i2s_ i2s_pdm_rx_config_t *pdm_rx_cfg = (i2s_pdm_rx_config_t *)handle->mode_info; ESP_GOTO_ON_FALSE(pdm_rx_cfg, ESP_ERR_INVALID_STATE, err, TAG, "initialization not complete"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is changed to APLL */ - if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && pdm_rx_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } - /* Disable APLL and release its lock when clock source is changed to 160M_PLL */ - if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && pdm_rx_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_release(); - handle->apll_en = false; + i2s_clock_src_t old_clk_src = pdm_rx_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; } #endif ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_clock(handle, clk_cfg), err, TAG, "update clock failed"); + + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); #ifdef CONFIG_PM_ENABLE // Create/Re-create power management lock - if (pdm_rx_cfg->clk_cfg.clk_src != clk_cfg->clk_src) { + if (old_clk_src != clk_cfg->clk_src) { ESP_GOTO_ON_ERROR(esp_pm_lock_delete(handle->pm_lock), err, TAG, "I2S delete old pm lock failed"); esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX; #if SOC_I2S_SUPPORTS_APLL && SOC_I2S_HW_VERSION_2 @@ -697,7 +672,15 @@ esp_err_t i2s_channel_reconfig_pdm_rx_slot(i2s_chan_handle_t handle, const i2s_p /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; if (pdm_rx_cfg->slot_cfg.slot_bit_width != slot_bits) { + i2s_clock_src_t old_clk_src = pdm_rx_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; + } +#endif ESP_GOTO_ON_ERROR(i2s_pdm_rx_set_clock(handle, &pdm_rx_cfg->clk_cfg), err, TAG, "update clock failed"); + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); } xSemaphoreGive(handle->mutex); diff --git a/components/esp_driver_i2s/i2s_private.h b/components/esp_driver_i2s/i2s_private.h index 331078c433..12f9d5572c 100644 --- a/components/esp_driver_i2s/i2s_private.h +++ b/components/esp_driver_i2s/i2s_private.h @@ -155,9 +155,6 @@ struct i2s_channel_obj_t { bool is_raw_pdm: 1; /*!< Flag of whether send/receive PDM in raw data, i.e., no PCM2PDM/PDM2PCM filter enabled */ bool is_external: 1; /*!< Whether use external clock */ bool full_duplex_slave: 1; /*!< whether the channel is forced to switch to slave role for full duplex */ -#if SOC_I2S_SUPPORTS_APLL - bool apll_en: 1; /*!< Flag of whether APLL enabled */ -#endif }; uint32_t active_slot; /*!< Active slot number */ uint32_t total_slot; /*!< Total slot number */ diff --git a/components/esp_driver_i2s/i2s_std.c b/components/esp_driver_i2s/i2s_std.c index 4db7741356..4a5d73ffa7 100644 --- a/components/esp_driver_i2s/i2s_std.c +++ b/components/esp_driver_i2s/i2s_std.c @@ -21,7 +21,6 @@ #include "driver/i2s_std.h" #include "i2s_private.h" #include "esp_private/esp_clk_tree_common.h" -#include "clk_ctrl_os.h" #include "esp_intr_alloc.h" #include "esp_check.h" @@ -82,23 +81,18 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c (clk_cfg->mclk_multiple % 3 == 0), ESP_ERR_INVALID_ARG, TAG, "The 'mclk_multiple' should be the multiple of 3 while using 24-bit data width"); - i2s_hal_clock_info_t clk_info; - /* Calculate clock parameters */ - ESP_RETURN_ON_ERROR(i2s_std_calculate_clock(handle, clk_cfg, &clk_info), TAG, "clock calculate failed"); - -#if SOC_I2S_HW_VERSION_2 - i2s_clock_src_t old_clk_src = handle->clk_src; - if (clk_cfg->clk_src != I2S_CLK_SRC_EXTERNAL) -#endif - { - i2s_clock_src_t clk_src = clk_cfg->clk_src; + i2s_clock_src_t clk_src = clk_cfg->clk_src; #ifdef I2S_LL_DEFAULT_CLK_SRC - if (clk_src == I2S_CLK_SRC_DEFAULT) { - clk_src = I2S_LL_DEFAULT_CLK_SRC; - } -#endif - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + if (clk_src == I2S_CLK_SRC_DEFAULT) { + clk_src = I2S_LL_DEFAULT_CLK_SRC; } +#endif + + i2s_hal_clock_info_t clk_info; + // Calculate clock parameters before enabling clock source + ESP_RETURN_ON_ERROR(i2s_std_calculate_clock(handle, clk_cfg, &clk_info), TAG, "clock calculate failed"); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), TAG, "clock source enable failed"); + hal_utils_clk_div_t ret_mclk_div = {}; portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ @@ -111,7 +105,7 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c } portEXIT_CRITICAL(&g_i2s.spinlock); uint64_t tmp_div = (uint64_t)ret_mclk_div.integer * ret_mclk_div.denominator + ret_mclk_div.numerator; - ESP_RETURN_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, TAG, "invalid mclk division result"); + ESP_GOTO_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid mclk division result"); /* Update the mode info: clock configuration */ memcpy(&(std_cfg->clk_cfg), clk_cfg, sizeof(i2s_std_clk_config_t)); @@ -121,16 +115,14 @@ static esp_err_t i2s_std_set_clock(i2s_chan_handle_t handle, const i2s_std_clk_c handle->curr_mclk_hz = handle->origin_mclk_hz; handle->bclk_hz = clk_info.bclk; -#if SOC_I2S_HW_VERSION_2 - if (old_clk_src != I2S_CLK_SRC_EXTERNAL) { - esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false); - } -#endif - ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); return ret; + +err: + esp_clk_tree_enable_src((soc_module_clk_t)clk_src, false); + return ret; } static i2s_std_slot_config_t s_i2s_std_normalize_slot_config(const i2s_std_slot_config_t *slot_cfg) @@ -345,13 +337,6 @@ esp_err_t i2s_channel_init_std_mode(i2s_chan_handle_t handle, const i2s_std_conf #endif /* i2s_set_std_slot should be called before i2s_set_std_clock while initializing, because clock is relay on the slot */ ESP_GOTO_ON_ERROR(i2s_std_set_slot(handle, &std_cfg->slot_cfg), err, TAG, "initialize channel failed while setting slot"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is APLL */ - if (std_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } -#endif ESP_GOTO_ON_ERROR(i2s_std_set_clock(handle, &std_cfg->clk_cfg), err, TAG, "initialize channel failed while setting clock"); /* i2s_std_set_gpio should be called after i2s_std_set_clock as mclk relies on the clock source */ ESP_GOTO_ON_ERROR(i2s_std_set_gpio(handle, &std_cfg->gpio_cfg), err, TAG, "initialize channel failed while setting gpio pins"); @@ -403,23 +388,21 @@ esp_err_t i2s_channel_reconfig_std_clock(i2s_chan_handle_t handle, const i2s_std i2s_std_config_t *std_cfg = (i2s_std_config_t *)handle->mode_info; ESP_GOTO_ON_FALSE(std_cfg, ESP_ERR_INVALID_STATE, err, TAG, "initialization not complete"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is changed to APLL */ - if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && std_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } - /* Disable APLL and release its lock when clock source is changed to 160M_PLL */ - if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && std_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_release(); - handle->apll_en = false; + i2s_clock_src_t old_clk_src = std_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; } #endif + ESP_GOTO_ON_ERROR(i2s_std_set_clock(handle, clk_cfg), err, TAG, "update clock failed"); + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); + #ifdef CONFIG_PM_ENABLE // Create/Re-create power management lock - if (std_cfg->clk_cfg.clk_src != clk_cfg->clk_src) { + if (old_clk_src != clk_cfg->clk_src) { ESP_GOTO_ON_ERROR(esp_pm_lock_delete(handle->pm_lock), err, TAG, "I2S delete old pm lock failed"); esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX; #if SOC_I2S_SUPPORTS_APLL && SOC_I2S_HW_VERSION_2 @@ -460,7 +443,15 @@ esp_err_t i2s_channel_reconfig_std_slot(i2s_chan_handle_t handle, const i2s_std_ /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; if (std_cfg->slot_cfg.slot_bit_width != slot_bits) { + i2s_clock_src_t old_clk_src = std_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; + } +#endif ESP_GOTO_ON_ERROR(i2s_std_set_clock(handle, &std_cfg->clk_cfg), err, TAG, "update clock failed"); + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); } xSemaphoreGive(handle->mutex); diff --git a/components/esp_driver_i2s/i2s_tdm.c b/components/esp_driver_i2s/i2s_tdm.c index fa508ca466..2808dae5cd 100644 --- a/components/esp_driver_i2s/i2s_tdm.c +++ b/components/esp_driver_i2s/i2s_tdm.c @@ -21,7 +21,6 @@ #include "driver/i2s_tdm.h" #include "i2s_private.h" #include "esp_private/esp_clk_tree_common.h" -#include "clk_ctrl_os.h" #include "esp_intr_alloc.h" #include "esp_check.h" @@ -79,23 +78,18 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c esp_err_t ret = ESP_OK; i2s_tdm_config_t *tdm_cfg = (i2s_tdm_config_t *)(handle->mode_info); - i2s_hal_clock_info_t clk_info; - /* Calculate clock parameters */ - ESP_RETURN_ON_ERROR(i2s_tdm_calculate_clock(handle, clk_cfg, &clk_info), TAG, "clock calculate failed"); - -#if SOC_I2S_HW_VERSION_2 - i2s_clock_src_t old_clk_src = handle->clk_src; - if (clk_cfg->clk_src != I2S_CLK_SRC_EXTERNAL) -#endif - { - i2s_clock_src_t clk_src = clk_cfg->clk_src; + i2s_clock_src_t clk_src = clk_cfg->clk_src; #ifdef I2S_LL_DEFAULT_CLK_SRC - if (clk_src == I2S_CLK_SRC_DEFAULT) { - clk_src = I2S_LL_DEFAULT_CLK_SRC; - } -#endif - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + if (clk_src == I2S_CLK_SRC_DEFAULT) { + clk_src = I2S_LL_DEFAULT_CLK_SRC; } +#endif + + i2s_hal_clock_info_t clk_info; + // Calculate clock parameters before enabling clock source + ESP_RETURN_ON_ERROR(i2s_tdm_calculate_clock(handle, clk_cfg, &clk_info), TAG, "clock calculate failed"); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), TAG, "clock source enable failed"); + hal_utils_clk_div_t ret_mclk_div = {}; portENTER_CRITICAL(&g_i2s.spinlock); /* Set clock configurations in HAL*/ @@ -108,7 +102,7 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c } portEXIT_CRITICAL(&g_i2s.spinlock); uint64_t tmp_div = (uint64_t)ret_mclk_div.integer * ret_mclk_div.denominator + ret_mclk_div.numerator; - ESP_RETURN_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, TAG, "invalid mclk division result"); + ESP_GOTO_ON_FALSE(tmp_div != 0 && ret_mclk_div.denominator != 0, ESP_ERR_INVALID_ARG, err, TAG, "invalid mclk division result"); /* Update the mode info: clock configuration */ memcpy(&(tdm_cfg->clk_cfg), clk_cfg, sizeof(i2s_tdm_clk_config_t)); @@ -118,16 +112,14 @@ static esp_err_t i2s_tdm_set_clock(i2s_chan_handle_t handle, const i2s_tdm_clk_c handle->curr_mclk_hz = handle->origin_mclk_hz; handle->bclk_hz = clk_info.bclk; -#if SOC_I2S_HW_VERSION_2 - if (old_clk_src != I2S_CLK_SRC_EXTERNAL) { - esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false); - } -#endif - ESP_LOGD(TAG, "Clock division info: [sclk] %"PRIu32" Hz [mdiv] %"PRIu32" %"PRIu32"/%"PRIu32" [mclk] %"PRIu32" Hz [bdiv] %d [bclk] %"PRIu32" Hz", clk_info.sclk, ret_mclk_div.integer, ret_mclk_div.numerator, ret_mclk_div.denominator, handle->origin_mclk_hz, clk_info.bclk_div, clk_info.bclk); return ret; + +err: + esp_clk_tree_enable_src((soc_module_clk_t)clk_src, false); + return ret; } static i2s_tdm_slot_config_t s_i2s_tdm_normalize_slot_config(const i2s_tdm_slot_config_t *slot_cfg) @@ -327,13 +319,6 @@ esp_err_t i2s_channel_init_tdm_mode(i2s_chan_handle_t handle, const i2s_tdm_conf s_i2s_channel_try_to_constitude_tdm_duplex(handle, tdm_cfg); /* i2s_set_tdm_slot should be called before i2s_set_tdm_clock while initializing, because clock is relay on the slot */ ESP_GOTO_ON_ERROR(i2s_tdm_set_slot(handle, &tdm_cfg->slot_cfg), err, TAG, "initialize channel failed while setting slot"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is APLL */ - if (tdm_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } -#endif ESP_GOTO_ON_ERROR(i2s_tdm_set_clock(handle, &tdm_cfg->clk_cfg), err, TAG, "initialize channel failed while setting clock"); /* i2s_tdm_set_gpio should be called after i2s_tdm_set_clock as mclk relies on the clock source */ ESP_GOTO_ON_ERROR(i2s_tdm_set_gpio(handle, &tdm_cfg->gpio_cfg), err, TAG, "initialize channel failed while setting gpio pins"); @@ -384,24 +369,21 @@ esp_err_t i2s_channel_reconfig_tdm_clock(i2s_chan_handle_t handle, const i2s_tdm i2s_tdm_config_t *tdm_cfg = (i2s_tdm_config_t *)handle->mode_info; ESP_GOTO_ON_FALSE(tdm_cfg, ESP_ERR_INVALID_STATE, err, TAG, "initialization not complete"); -#if SOC_I2S_SUPPORTS_APLL - /* Enable APLL and acquire its lock when the clock source is changed to APLL */ - if (clk_cfg->clk_src == I2S_CLK_SRC_APLL && tdm_cfg->clk_cfg.clk_src != I2S_CLK_SRC_APLL) { - periph_rtc_apll_acquire(); - handle->apll_en = true; - } - /* Disable APLL and release its lock when clock source is changed to 160M_PLL */ - if (clk_cfg->clk_src != I2S_CLK_SRC_APLL && tdm_cfg->clk_cfg.clk_src == I2S_CLK_SRC_APLL) { - periph_rtc_apll_release(); - handle->apll_en = false; + i2s_clock_src_t old_clk_src = tdm_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; } #endif ESP_GOTO_ON_ERROR(i2s_tdm_set_clock(handle, clk_cfg), err, TAG, "update clock failed"); + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); + #ifdef CONFIG_PM_ENABLE // Create/Re-create power management lock - if (tdm_cfg->clk_cfg.clk_src != clk_cfg->clk_src) { + if (old_clk_src != clk_cfg->clk_src) { ESP_GOTO_ON_ERROR(esp_pm_lock_delete(handle->pm_lock), err, TAG, "I2S delete old pm lock failed"); esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX; #if SOC_I2S_SUPPORTS_APLL && SOC_I2S_HW_VERSION_2 @@ -442,7 +424,15 @@ esp_err_t i2s_channel_reconfig_tdm_slot(i2s_chan_handle_t handle, const i2s_tdm_ /* If the slot bit width changed, then need to update the clock */ uint32_t slot_bits = slot_cfg->slot_bit_width == I2S_SLOT_BIT_WIDTH_AUTO ? slot_cfg->data_bit_width : slot_cfg->slot_bit_width; if (tdm_cfg->slot_cfg.slot_bit_width != slot_bits) { + i2s_clock_src_t old_clk_src = tdm_cfg->clk_cfg.clk_src; +#ifdef I2S_LL_DEFAULT_CLK_SRC + if (old_clk_src == I2S_CLK_SRC_DEFAULT) { + old_clk_src = I2S_LL_DEFAULT_CLK_SRC; + } +#endif ESP_GOTO_ON_ERROR(i2s_tdm_set_clock(handle, &tdm_cfg->clk_cfg), err, TAG, "update clock failed"); + // disable old clock source after new clock is successfully configured + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)old_clk_src, false), err, TAG, "clock source disable failed"); } /* Reset queue */ diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index 29cb828c74..ddd62a5a69 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -17,7 +17,6 @@ #include "soc/soc_caps.h" #include "hal/ledc_hal.h" #include "driver/ledc.h" -#include "clk_ctrl_os.h" #include "esp_private/esp_sleep_internal.h" #include "esp_private/periph_ctrl.h" #include "driver/gpio.h" @@ -162,18 +161,17 @@ static IRAM_ATTR void ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channe //We know that RC_FAST is about 8M/20M, but don't know the actual value. So we need to do a calibration. static bool ledc_slow_clk_calibrate(void) { - if (periph_rtc_dig_clk8m_enable()) { - s_ledc_slow_clk_rc_fast_freq = periph_rtc_dig_clk8m_get_freq(); -#if !SOC_CLK_RC_FAST_SUPPORT_CALIBRATION - /* Workaround: RC_FAST calibration cannot be performed, we can only use its theoretic freq */ - ESP_LOGD(LEDC_TAG, "Calibration cannot be performed, approximate RC_FAST_CLK : %"PRIu32" Hz", s_ledc_slow_clk_rc_fast_freq); -#else - ESP_LOGD(LEDC_TAG, "Calibrate RC_FAST_CLK : %"PRIu32" Hz", s_ledc_slow_clk_rc_fast_freq); -#endif - return true; + if (esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_RC_FAST, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &s_ledc_slow_clk_rc_fast_freq) != ESP_OK) { + ESP_LOGE(LEDC_TAG, "Calibrate RC_FAST_CLK failed"); + return false; } - ESP_LOGE(LEDC_TAG, "Calibrate RC_FAST_CLK failed"); - return false; +#if !SOC_CLK_RC_FAST_SUPPORT_CALIBRATION + /* Workaround: RC_FAST calibration cannot be performed, we can only use its theoretic freq */ + ESP_LOGD(LEDC_TAG, "Calibration cannot be performed, approximate RC_FAST_CLK : %"PRIu32" Hz", s_ledc_slow_clk_rc_fast_freq); +#else + ESP_LOGD(LEDC_TAG, "Calibrate RC_FAST_CLK : %"PRIu32" Hz", s_ledc_slow_clk_rc_fast_freq); +#endif + return true; } static void _ledc_fade_hw_acquire(ledc_mode_t mode, ledc_channel_t channel) diff --git a/components/esp_driver_parlio/src/parlio_common.c b/components/esp_driver_parlio/src/parlio_common.c index ecb2845ee0..1f3de27658 100644 --- a/components/esp_driver_parlio/src/parlio_common.c +++ b/components/esp_driver_parlio/src/parlio_common.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #include "esp_private/esp_clk.h" #include "esp_private/sleep_retention.h" #include "parlio_priv.h" diff --git a/components/esp_driver_rmt/src/rmt_common.c b/components/esp_driver_rmt/src/rmt_common.c index 9a91391064..d509fef5b3 100644 --- a/components/esp_driver_rmt/src/rmt_common.c +++ b/components/esp_driver_rmt/src/rmt_common.c @@ -1,11 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "rmt_private.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #include "soc/rtc.h" #include "driver/gpio.h" @@ -81,7 +81,6 @@ rmt_group_t *rmt_acquire_group_handle(int group_id) void rmt_release_group_handle(rmt_group_t *group) { int group_id = group->group_id; - rmt_clock_source_t clk_src = group->clk_src; bool do_deinitialize = false; rmt_hal_context_t *hal = &group->hal; @@ -103,16 +102,6 @@ void rmt_release_group_handle(rmt_group_t *group) } _lock_release(&s_platform.mutex); - switch (clk_src) { -#if RMT_LL_SUPPORT(RC_FAST) - case RMT_CLK_SRC_RC_FAST: - periph_rtc_dig_clk8m_disable(); - break; -#endif // RMT_LL_SUPPORT(RC_FAST) - default: - break; - } - if (do_deinitialize) { #if RMT_USE_RETENTION_LINK sleep_retention_module_t module = rmt_reg_retention_info[group_id].module; @@ -195,18 +184,9 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t clock_selection_conflict = (group->clk_src != clk_src); } portEXIT_CRITICAL(&group->spinlock); - ESP_RETURN_ON_FALSE(!clock_selection_conflict, ESP_ERR_INVALID_ARG, TAG, + ESP_RETURN_ON_FALSE(!clock_selection_conflict, ESP_ERR_INVALID_STATE, TAG, "group clock conflict, already is %d but attempt to %d", group->clk_src, clk_src); - // TODO: [clk_tree] to use a generic clock enable/disable or acquire/release function for all clock source -#if RMT_LL_SUPPORT(RC_FAST) - if (clk_src == RMT_CLK_SRC_RC_FAST) { - // RC_FAST clock is not enabled automatically on start up, we enable it here manually. - // Note there's a ref count in the enable/disable function, we must call them in pair in the driver. - periph_rtc_dig_clk8m_enable(); - } -#endif // RMT_LL_SUPPORT(RC_FAST) - #if CONFIG_PM_ENABLE // if DMA is not used, we're using CPU to push the data to the RMT FIFO // if the CPU frequency goes down, the transfer+encoding scheme could be unstable because CPU can't fill the data in time @@ -224,8 +204,8 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t #if RMT_LL_GET(CHANNEL_CLK_INDEPENDENT) uint32_t periph_src_clk_hz = 0; // get clock source frequency - ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), - TAG, "get clock source frequency failed"); + ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &periph_src_clk_hz), + err, TAG, "get clock source frequency failed"); PERIPH_RCC_ATOMIC() { rmt_ll_set_group_clock_src(group->hal.regs, chan->channel_id, clk_src, 1, 1, 0); rmt_ll_enable_group_clock(group->hal.regs, true); @@ -235,7 +215,7 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t real_div = (group->resolution_hz + expect_channel_resolution / 2) / expect_channel_resolution; #else // set division for group clock source, to achieve highest resolution while guaranteeing the channel resolution. - ESP_RETURN_ON_ERROR(rmt_set_group_prescale(chan, expect_channel_resolution, &real_div), TAG, "set rmt group prescale failed"); + ESP_GOTO_ON_ERROR(rmt_set_group_prescale(chan, expect_channel_resolution, &real_div), err, TAG, "set rmt group prescale failed"); #endif // RMT_LL_GET(CHANNEL_CLK_INDEPENDENT) if (chan->direction == RMT_CHANNEL_DIRECTION_TX) { @@ -249,6 +229,10 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t ESP_LOGW(TAG, "channel resolution loss, real=%"PRIu32, chan->resolution_hz); } return ret; + +err: + esp_clk_tree_enable_src((soc_module_clk_t)clk_src, false); + return ret; } esp_err_t rmt_get_channel_id(rmt_channel_handle_t channel, int *ret_id) diff --git a/components/esp_driver_rmt/src/rmt_rx.c b/components/esp_driver_rmt/src/rmt_rx.c index dbf250b4f2..51af2291c2 100644 --- a/components/esp_driver_rmt/src/rmt_rx.c +++ b/components/esp_driver_rmt/src/rmt_rx.c @@ -318,9 +318,12 @@ static esp_err_t rmt_del_rx_channel(rmt_channel_handle_t channel) rmt_group_t *group = channel->group; int group_id = group->group_id; int channel_id = channel->channel_id; + soc_module_clk_t clk_src = (soc_module_clk_t)group->clk_src; ESP_LOGD(TAG, "del rx channel(%d,%d)", group_id, channel_id); // recycle memory resource ESP_RETURN_ON_ERROR(rmt_rx_destroy(rx_chan), TAG, "destroy rx channel failed"); + // disable the clock source at last + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(clk_src, false), TAG, "clock source disable failed"); return ESP_OK; } diff --git a/components/esp_driver_rmt/src/rmt_tx.c b/components/esp_driver_rmt/src/rmt_tx.c index fbe3b48037..b1a70e5a58 100644 --- a/components/esp_driver_rmt/src/rmt_tx.c +++ b/components/esp_driver_rmt/src/rmt_tx.c @@ -377,9 +377,12 @@ static esp_err_t rmt_del_tx_channel(rmt_channel_handle_t channel) rmt_group_t *group = channel->group; int group_id = group->group_id; int channel_id = channel->channel_id; + soc_module_clk_t clk_src = (soc_module_clk_t)group->clk_src; ESP_LOGD(TAG, "del tx channel(%d,%d)", group_id, channel_id); // recycle memory resource ESP_RETURN_ON_ERROR(rmt_tx_destroy(tx_chan), TAG, "destroy tx channel failed"); + // disable the clock source at last + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(clk_src, false), TAG, "clock source disable failed"); return ESP_OK; } diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index c999d9a47d..1602f59ddd 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -118,7 +118,7 @@ We have two bits to control the interrupt: #include "esp_private/esp_clk_tree_common.h" #include "esp_private/cache_utils.h" #include "driver/spi_master.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #include "esp_log.h" #include "esp_check.h" #include "esp_ipc.h" @@ -450,9 +450,6 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa uint32_t clock_source_hz = 0; uint32_t clock_source_div = 1; spi_clock_source_t clk_src = dev_config->clock_source ? dev_config->clock_source : SPI_CLK_SRC_DEFAULT; - if ((soc_module_clk_t)clk_src == SOC_MOD_CLK_RC_FAST) { - SPI_CHECK(periph_rtc_dig_clk8m_enable(), "the selected clock not available", ESP_ERR_INVALID_STATE); - } SPI_CHECK(esp_clk_tree_enable_src(clk_src, true) == ESP_OK, "clock source enable failed", ESP_ERR_INVALID_STATE); esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clock_source_hz); #if SPI_LL_SRC_PRE_DIV_MAX @@ -613,7 +610,6 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle) } spi_device_release_bus(handle); } - periph_rtc_dig_clk8m_disable(); } SPI_CHECK(esp_clk_tree_enable_src(handle->hal_dev.timing_conf.clock_source, false) == ESP_OK, "clock source disable failed", ESP_ERR_INVALID_STATE); diff --git a/components/esp_driver_tsens/src/temperature_sensor.c b/components/esp_driver_tsens/src/temperature_sensor.c index a251ad528c..cdbbb22f46 100644 --- a/components/esp_driver_tsens/src/temperature_sensor.c +++ b/components/esp_driver_tsens/src/temperature_sensor.c @@ -19,7 +19,7 @@ #include "esp_check.h" #include "esp_types.h" #include "esp_heap_caps.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #include "freertos/FreeRTOS.h" #include "driver/temperature_sensor.h" #include "esp_private/periph_ctrl.h" @@ -242,11 +242,7 @@ esp_err_t temperature_sensor_enable(temperature_sensor_handle_t tsens) ESP_RETURN_ON_FALSE((tsens != NULL), ESP_ERR_INVALID_ARG, TAG, "invalid argument"); ESP_RETURN_ON_FALSE(tsens->fsm == TEMP_SENSOR_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "tsens not in init state"); -#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC - if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_RC_FAST) { - periph_rtc_dig_clk8m_enable(); - } -#endif + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(tsens->clk_src, true), TAG, "clock source enable failed"); #if SOC_TEMPERATURE_SENSOR_INTR_SUPPORT temperature_sensor_ll_wakeup_enable(true); @@ -271,13 +267,10 @@ esp_err_t temperature_sensor_disable(temperature_sensor_handle_t tsens) temperature_sensor_ll_sample_enable(false); #endif -#if SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC - if (tsens->clk_src == TEMPERATURE_SENSOR_CLK_SRC_RC_FAST) { - periph_rtc_dig_clk8m_disable(); - } -#endif - tsens->fsm = TEMP_SENSOR_FSM_INIT; + + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(tsens->clk_src, false), TAG, "clock source disable failed"); + return ESP_OK; } diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index e6ce90bb83..5f044093ed 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -39,7 +39,6 @@ #include "soc/lp_gpio_pins.h" #endif #endif -#include "clk_ctrl_os.h" #include "esp_pm.h" #ifdef CONFIG_UART_ISR_IN_IRAM @@ -1087,11 +1086,6 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf // Enable the newly selected clock source esp_clk_tree_enable_src(uart_sclk_sel, true); -#if SOC_UART_SUPPORT_RTC_CLK - if (uart_sclk_sel == (soc_module_clk_t)UART_SCLK_RTC) { - periph_rtc_dig_clk8m_enable(); - } -#endif bool success = false; UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); @@ -2139,11 +2133,6 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { esp_clk_tree_enable_src(uart_context[uart_num].sclk_sel, false); -#if SOC_UART_SUPPORT_RTC_CLK - if (uart_context[uart_num].sclk_sel == (soc_module_clk_t)UART_SCLK_RTC) { - periph_rtc_dig_clk8m_disable(); - } -#endif uart_context[uart_num].sclk_sel = -1; } @@ -2348,11 +2337,6 @@ esp_err_t uart_detect_bitrate_start(uart_port_t uart_num, const uart_bitrate_det uint32_t sclk_freq = 0; ESP_GOTO_ON_ERROR(esp_clk_tree_src_get_freq_hz(uart_sclk_sel, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), err, UART_TAG, "invalid source_clk"); esp_clk_tree_enable_src(uart_sclk_sel, true); -#if SOC_UART_SUPPORT_RTC_CLK - if (uart_sclk_sel == (soc_module_clk_t)UART_SCLK_RTC) { - periph_rtc_dig_clk8m_enable(); - } -#endif UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); PERIPH_RCC_ATOMIC() { uart_hal_set_sclk(&(uart_context[uart_num].hal), uart_sclk_sel); @@ -2436,11 +2420,6 @@ esp_err_t uart_detect_bitrate_stop(uart_port_t uart_num, bool deinit, uart_bitra uart_release_pin(uart_num, true, true, true, true, true, true); if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { esp_clk_tree_enable_src(uart_context[uart_num].sclk_sel, false); -#if SOC_UART_SUPPORT_RTC_CLK - if (src_clk == (soc_module_clk_t)UART_SCLK_RTC) { - periph_rtc_dig_clk8m_disable(); - } -#endif uart_context[uart_num].sclk_sel = -1; } uart_module_disable(uart_num); diff --git a/components/esp_eth/src/mac/esp_eth_mac_esp.c b/components/esp_eth/src/mac/esp_eth_mac_esp.c index aa979d1c7a..d9f31a3ed0 100644 --- a/components/esp_eth/src/mac/esp_eth_mac_esp.c +++ b/components/esp_eth/src/mac/esp_eth_mac_esp.c @@ -31,7 +31,7 @@ #include "hal/emac_hal.h" #include "soc/soc.h" #include "hal/emac_periph.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #include "sdkconfig.h" #include "esp_rom_sys.h" #include "esp_private/eth_mac_esp_dma.h" @@ -486,18 +486,18 @@ static esp_err_t emac_config_pll_clock(emac_esp32_t *emac) #if SOC_EMAC_REF_CLK_FROM_APLL // the RMII reference comes from the APLL - periph_rtc_apll_acquire(); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true), TAG, "APLL enable failed"); emac->use_pll = true; - esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq); + esp_err_t ret = esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, expt_freq, &real_freq); ESP_RETURN_ON_FALSE(ret != ESP_ERR_INVALID_ARG, ESP_FAIL, TAG, "Set APLL clock coefficients failed"); if (ret == ESP_ERR_INVALID_STATE) { ESP_LOGW(TAG, "APLL is occupied already, it is working at %" PRIu32 " Hz", real_freq); } #elif SOC_EMAC_REF_CLK_FROM_MPLL // the RMII reference comes from the MPLL - periph_rtc_mpll_acquire(); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, true), TAG, "MPLL enable failed"); emac->use_pll = true; - esp_err_t ret = periph_rtc_mpll_freq_set(expt_freq * 2, &real_freq); // cannot set 50MHz at MPLL, the nearest possible freq is 100 MHz + esp_err_t ret = esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_MPLL, expt_freq * 2, &real_freq); // cannot set 50MHz at MPLL, the nearest possible freq is 100 MHz if (ret == ESP_ERR_INVALID_STATE) { ESP_LOGW(TAG, "MPLL is occupied already, it is working at %" PRIu32 " Hz", real_freq); ESP_LOGW(TAG, "Trying to derive RMII clock to be %" PRIu32 " Hz...", RMII_CLK_HZ); @@ -671,9 +671,9 @@ static void emac_esp_free_driver_obj(emac_esp32_t *emac) if (emac->use_pll) { #if CONFIG_IDF_TARGET_ESP32 - periph_rtc_apll_release(); + esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false); #elif CONFIG_IDF_TARGET_ESP32P4 - periph_rtc_mpll_release(); + esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, false); #endif } #ifdef CONFIG_IDF_TARGET_ESP32 diff --git a/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c b/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c index 691a099332..62caaac532 100644 --- a/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c +++ b/components/esp_eth/test_apps/main/esp_eth_test_esp_emac.c @@ -16,7 +16,7 @@ #include "esp_log.h" #include "esp_eth_test_utils.h" #include "hal/emac_hal.h" // for MAC_HAL_TDES0_* control bits -#include "clk_ctrl_os.h" +#include "esp_private/esp_clk_tree_common.h" #define ETHERTYPE_TX_STD 0x2222 // frame transmitted via _transmit_frame #define ETHERTYPE_TX_MULTI_2 0x2223 // frame transmitted via _transmit_multiple_buf_frame (2 buffers) @@ -615,37 +615,37 @@ TEST_CASE("internal emac MPLL shared with PSRAM", "[esp_emac_clk_out][skip_setup // PSRAM default speed: MPLL at 400 MHz — EMAC divider 8 gives exactly 50 MHz ESP_LOGI(TAG, "Verify MPLL at 400 MHz (simulating PSRAM default)"); - TEST_ESP_OK(periph_rtc_mpll_acquire()); - TEST_ESP_OK(periph_rtc_mpll_freq_set(400 * 1000000, &real_freq)); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, true)); + TEST_ESP_OK(esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_MPLL, 400 * 1000000, &real_freq)); ESP_LOGI(TAG, "MPLL set to %" PRIu32 " Hz", real_freq); mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); TEST_ASSERT_NOT_NULL(mac); TEST_ESP_OK(mac->del(mac)); - periph_rtc_mpll_release(); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, false)); // PSRAM 250M speed: MPLL at 500 MHz — EMAC divider 10 gives exactly 50 MHz ESP_LOGI(TAG, "Verify MPLL at 500 MHz (simulating PSRAM @ 250M speed)"); - TEST_ESP_OK(periph_rtc_mpll_acquire()); - TEST_ESP_OK(periph_rtc_mpll_freq_set(500 * 1000000, &real_freq)); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, true)); + TEST_ESP_OK(esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_MPLL, 500 * 1000000, &real_freq)); ESP_LOGI(TAG, "MPLL set to %" PRIu32 " Hz", real_freq); mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); TEST_ASSERT_NOT_NULL(mac); TEST_ESP_OK(mac->del(mac)); - periph_rtc_mpll_release(); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, false)); // PSRAM 80M speed: MPLL at 320 MHz — no integer divider can produce 50 MHz within tolerance, // see AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ for reference // Best candidate: 320/6 = 53.33 MHz (error ~3.33 MHz >> 2500 Hz tolerance) ESP_LOGI(TAG, "Verify MPLL at 320 MHz (simulating PSRAM @ 80M speed) — expected to fail"); - TEST_ESP_OK(periph_rtc_mpll_acquire()); - TEST_ESP_OK(periph_rtc_mpll_freq_set(320 * 1000000, &real_freq)); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, true)); + TEST_ESP_OK(esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_MPLL, 320 * 1000000, &real_freq)); ESP_LOGI(TAG, "MPLL set to %" PRIu32 " Hz", real_freq); mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); TEST_ASSERT_NULL(mac); - periph_rtc_mpll_release(); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_MPLL, false)); } #endif // SOC_EMAC_REF_CLK_FROM_MPLL @@ -669,24 +669,24 @@ TEST_CASE("internal emac APLL shared with I2S", "[esp_emac_clk_out][skip_setup_t // Another peripheral has APLL at 50 MHz — exact RMII clock match, EMAC should succeed ESP_LOGI(TAG, "Verify APLL at 50 MHz (exact RMII clock match)"); - periph_rtc_apll_acquire(); - TEST_ESP_OK(periph_rtc_apll_freq_set(50 * 1000000, &real_freq)); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true)); + TEST_ESP_OK(esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, 50 * 1000000, &real_freq)); ESP_LOGI(TAG, "APLL set to %" PRIu32 " Hz", real_freq); mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); TEST_ASSERT_NOT_NULL(mac); TEST_ESP_OK(mac->del(mac)); - periph_rtc_apll_release(); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false)); // I2S typical frequency: APLL at ~12.288 MHz (48 kHz * 256) — far from 50 MHz, EMAC should fail ESP_LOGI(TAG, "Verify APLL at ~12.288 MHz (simulating I2S @ 48 kHz) — expected to fail"); - periph_rtc_apll_acquire(); - TEST_ESP_OK(periph_rtc_apll_freq_set(12288000, &real_freq)); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true)); + TEST_ESP_OK(esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, 12288000, &real_freq)); ESP_LOGI(TAG, "APLL set to %" PRIu32 " Hz", real_freq); mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); TEST_ASSERT_NULL(mac); - periph_rtc_apll_release(); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false)); } #endif // SOC_EMAC_REF_CLK_FROM_APLL diff --git a/components/esp_hal_clock/esp32/include/hal/clk_tree_ll.h b/components/esp_hal_clock/esp32/include/hal/clk_tree_ll.h index 0188ec4532..c19aa25e9b 100644 --- a/components/esp_hal_clock/esp32/include/hal/clk_tree_ll.h +++ b/components/esp_hal_clock/esp32/include/hal/clk_tree_ll.h @@ -81,8 +81,8 @@ #define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz /* APLL output frequency range */ -#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation -#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation +#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation +#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation #ifdef __cplusplus extern "C" { diff --git a/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h b/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h index 3fc6043000..bb6e74e488 100644 --- a/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h +++ b/components/esp_hal_clock/esp32p4/include/hal/clk_tree_ll.h @@ -60,8 +60,8 @@ #define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz /* APLL output frequency range */ -#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation -#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation +#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation +#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation #define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ .dac = 3, \ diff --git a/components/esp_hal_clock/esp32s2/include/hal/clk_tree_ll.h b/components/esp_hal_clock/esp32s2/include/hal/clk_tree_ll.h index 430940489f..48e3c6b1a0 100644 --- a/components/esp_hal_clock/esp32s2/include/hal/clk_tree_ll.h +++ b/components/esp_hal_clock/esp32s2/include/hal/clk_tree_ll.h @@ -55,8 +55,8 @@ #define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz /* APLL output frequency range */ -#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation -#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation +#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation +#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation #define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ .dac = 3, \ diff --git a/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h b/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h index 925a3803af..9a4f91a98d 100644 --- a/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h +++ b/components/esp_hal_clock/esp32s31/include/hal/clk_tree_ll.h @@ -52,8 +52,8 @@ #define CLK_LL_APLL_MULTIPLIER_MAX_HZ (500000000) // 500 MHz /* APLL output frequency range */ -#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'periph_rtc_apll_freq_set' for the calculation -#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'periph_rtc_apll_freq_set' for the calculation +#define CLK_LL_APLL_MIN_HZ (5303031) // 5.303031 MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation +#define CLK_LL_APLL_MAX_HZ (125000000) // 125MHz, refer to 'esp_clk_tree_apll_freq_set' for the calculation #define CLK_LL_XTAL32K_CONFIG_DEFAULT() { \ .dac = 7, \ diff --git a/components/esp_hal_regi2c/test_apps/main/test_regi2c.c b/components/esp_hal_regi2c/test_apps/main/test_regi2c.c index b8766a7748..5b34f72b52 100644 --- a/components/esp_hal_regi2c/test_apps/main/test_regi2c.c +++ b/components/esp_hal_regi2c/test_apps/main/test_regi2c.c @@ -9,6 +9,7 @@ #include "unity.h" #include "test_regi2c.h" #include "esp_private/regi2c_ctrl.h" +#include "esp_private/esp_clk_tree_common.h" #include "sdkconfig.h" TEST_CASE("regi2c basic read/write test", "[regi2c]") @@ -19,7 +20,7 @@ TEST_CASE("regi2c basic read/write test", "[regi2c]") #if CONFIG_IDF_TARGET_ESP32 // For ESP32, we need to enable the APLL clock before accessing the APLL regi2c registers - periph_rtc_apll_acquire(); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true)); #endif /* ---- Part 1: full-register read / write ---- */ @@ -91,6 +92,6 @@ TEST_CASE("regi2c basic read/write test", "[regi2c]") #if CONFIG_IDF_TARGET_ESP32 // Disable APLL clock - periph_rtc_apll_release(); + TEST_ESP_OK(esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false)); #endif } diff --git a/components/esp_hal_regi2c/test_apps/main/test_regi2c.h b/components/esp_hal_regi2c/test_apps/main/test_regi2c.h index eca63b75c0..9d0c1acfb1 100644 --- a/components/esp_hal_regi2c/test_apps/main/test_regi2c.h +++ b/components/esp_hal_regi2c/test_apps/main/test_regi2c.h @@ -25,7 +25,6 @@ extern "C" { #if CONFIG_IDF_TARGET_ESP32 -#include "clk_ctrl_os.h" #include "soc/regi2c_apll.h" #define TEST_BLOCK I2C_APLL #define TEST_HOST_ID I2C_APLL_HOSTID diff --git a/components/esp_hw_support/clk_ctrl_os.c b/components/esp_hw_support/clk_ctrl_os.c index f8d457d194..860bfe86f4 100644 --- a/components/esp_hw_support/clk_ctrl_os.c +++ b/components/esp_hw_support/clk_ctrl_os.c @@ -1,211 +1,66 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include #include "clk_ctrl_os.h" -#include "soc/rtc.h" -#include "esp_ldo_regulator.h" +#include "esp_attr.h" #include "esp_private/esp_clk_tree_common.h" -#include "esp_private/critical_section.h" -#include "esp_check.h" -#include "hal/clk_tree_hal.h" -#include "hal/clk_tree_ll.h" -#if SOC_CLK_MPLL_SUPPORTED -#include "rtc_clk.h" -#endif - -#if SOC_CLK_APLL_SUPPORTED || SOC_CLK_MPLL_SUPPORTED -ESP_LOG_ATTR_TAG(TAG, "clk_ctrl_os"); -#endif - -static portMUX_TYPE __attribute__((unused)) periph_spinlock = portMUX_INITIALIZER_UNLOCKED; - -static uint8_t s_periph_ref_counts = 0; -static uint32_t s_rc_fast_freq_hz = 0; // Frequency of the RC_FAST clock in Hz -#if SOC_CLK_APLL_SUPPORTED -// Current APLL frequency, in HZ. Zero if APLL is not enabled. -static uint32_t s_cur_apll_freq_hz = 0; -static int s_apll_ref_cnt = 0; -#endif -#if SOC_CLK_MPLL_SUPPORTED -static uint32_t s_cur_mpll_freq_hz = 0; -static int s_mpll_ref_cnt = 0; -#endif -#if CONFIG_ESP_LDO_RESERVE_PSRAM -static esp_ldo_channel_handle_t s_ldo_chan = NULL; -#endif +#include "soc/clk_tree_defs.h" bool periph_rtc_dig_clk8m_enable(void) { - esp_os_enter_critical(&periph_spinlock); - if (s_periph_ref_counts == 0) { - rtc_dig_clk8m_enable(); -#if SOC_CLK_RC_FAST_SUPPORT_CALIBRATION - s_rc_fast_freq_hz = esp_clk_tree_rc_fast_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT); - if (s_rc_fast_freq_hz == 0) { - rtc_dig_clk8m_disable(); - esp_os_exit_critical(&periph_spinlock); - return false; - } -#endif //SOC_CLK_RC_FAST_SUPPORT_CALIBRATION - } - s_periph_ref_counts++; - esp_os_exit_critical(&periph_spinlock); - return true; + return esp_clk_tree_enable_src(SOC_MOD_CLK_RC_FAST, true) == ESP_OK; } uint32_t periph_rtc_dig_clk8m_get_freq(void) { -#if !SOC_CLK_RC_FAST_SUPPORT_CALIBRATION - /* Workaround: CLK8M calibration cannot be performed, we can only return its theoretic value */ - return SOC_CLK_RC_FAST_FREQ_APPROX; +#if SOC_CLK_RC_FAST_SUPPORT_CALIBRATION + return esp_clk_tree_rc_fast_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT); #else - return s_rc_fast_freq_hz; + return SOC_CLK_RC_FAST_FREQ_APPROX; #endif } void periph_rtc_dig_clk8m_disable(void) { - esp_os_enter_critical(&periph_spinlock); - assert(s_periph_ref_counts > 0); - s_periph_ref_counts--; - if (s_periph_ref_counts == 0) { - s_rc_fast_freq_hz = 0; - rtc_dig_clk8m_disable(); - } - esp_os_exit_critical(&periph_spinlock); + (void)esp_clk_tree_enable_src(SOC_MOD_CLK_RC_FAST, false); } #if SOC_CLK_APLL_SUPPORTED void periph_rtc_apll_acquire(void) { - esp_os_enter_critical(&periph_spinlock); - s_apll_ref_cnt++; - if (s_apll_ref_cnt == 1) { - // For the first time enable APLL, need to set power up - rtc_clk_apll_enable(true); - } - esp_os_exit_critical(&periph_spinlock); + (void)esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, true); } void periph_rtc_apll_release(void) { - esp_os_enter_critical(&periph_spinlock); - assert(s_apll_ref_cnt > 0); - s_apll_ref_cnt--; - if (s_apll_ref_cnt == 0) { - // If there is no peripheral using APLL, shut down the power - s_cur_apll_freq_hz = 0; - rtc_clk_apll_enable(false); - } - esp_os_exit_critical(&periph_spinlock); + (void)esp_clk_tree_enable_src(SOC_MOD_CLK_APLL, false); } esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz) { - uint32_t o_div = 0; - uint32_t sdm0 = 0; - uint32_t sdm1 = 0; - uint32_t sdm2 = 0; - // Guarantee 'periph_rtc_apll_acquire' has been called before set apll freq - assert(s_apll_ref_cnt > 0); - uint32_t apll_freq = rtc_clk_apll_coeff_calc(expt_freq_hz, &o_div, &sdm0, &sdm1, &sdm2); - - ESP_RETURN_ON_FALSE(apll_freq, ESP_ERR_INVALID_ARG, TAG, "APLL coefficients calculate failed"); - bool need_config = true; - esp_os_enter_critical(&periph_spinlock); - /* If APLL is not in use or only one peripheral in use, its frequency can be changed as will - * But when more than one peripheral refers APLL, its frequency is not allowed to change once it is set */ - if (s_cur_apll_freq_hz == 0 || s_apll_ref_cnt < 2) { - s_cur_apll_freq_hz = apll_freq; - } else { - apll_freq = s_cur_apll_freq_hz; - need_config = false; - } - esp_os_exit_critical(&periph_spinlock); - *real_freq_hz = apll_freq; - - if (need_config) { - ESP_LOGD(TAG, "APLL will working at %"PRIu32" Hz with coefficients [sdm0] %"PRIu32" [sdm1] %"PRIu32" [sdm2] %"PRIu32" [o_div] %"PRIu32"", - apll_freq, sdm0, sdm1, sdm2, o_div); - /* Set coefficients for APLL, notice that it doesn't mean APLL will start */ - rtc_clk_apll_coeff_set(o_div, sdm0, sdm1, sdm2); - } else { - return ESP_ERR_INVALID_STATE; - } - - return ESP_OK; + return esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, expt_freq_hz, real_freq_hz); } #endif // SOC_CLK_APLL_SUPPORTED #if SOC_CLK_MPLL_SUPPORTED esp_err_t IRAM_ATTR periph_rtc_mpll_acquire(void) { - // power up LDO for the MPLL -#if CONFIG_ESP_LDO_RESERVE_PSRAM - esp_ldo_channel_config_t ldo_mpll_config = { - .chan_id = CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN, - .voltage_mv = CONFIG_ESP_LDO_VOLTAGE_PSRAM_DOMAIN, - }; - ESP_RETURN_ON_ERROR(esp_ldo_acquire_channel(&ldo_mpll_config, &s_ldo_chan), TAG, "acquire internal LDO for MPLL failed"); -#endif - - esp_os_enter_critical(&periph_spinlock); - s_mpll_ref_cnt++; - if (s_mpll_ref_cnt == 1) { - // For the first time enable MPLL, need to set power up - rtc_clk_mpll_enable(); - } - esp_os_exit_critical(&periph_spinlock); - return ESP_OK; + // For IRAM compatibility, we do not use esp_clk_tree_enable_src here + return esp_clk_tree_mpll_acquire(); } void periph_rtc_mpll_release(void) { -#if defined(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN) && CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN != -1 - if (s_ldo_chan) { - esp_ldo_release_channel(s_ldo_chan); - } -#endif - esp_os_enter_critical(&periph_spinlock); - assert(s_mpll_ref_cnt > 0); - s_mpll_ref_cnt--; - if (s_mpll_ref_cnt == 0) { - // If there is no peripheral using MPLL, shut down the power - s_cur_mpll_freq_hz = 0; - rtc_clk_mpll_disable(); - } - esp_os_exit_critical(&periph_spinlock); + // For IRAM compatibility, we do not use esp_clk_tree_enable_src here + (void)esp_clk_tree_mpll_release(); } esp_err_t IRAM_ATTR periph_rtc_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz) { - esp_err_t ret = ESP_OK; - - // Guarantee 'periph_rtc_apll_acquire' has been called before set apll freq - assert(s_mpll_ref_cnt > 0); - - esp_os_enter_critical(&periph_spinlock); - if (s_cur_mpll_freq_hz == expt_freq_hz) { - goto end; - } - /* If MPLL is not in use or only one peripheral in use, its frequency can be changed as will - * But when more than one peripheral refers MPLL, its frequency is not allowed to change once it is set */ - if (s_cur_mpll_freq_hz == 0 || s_mpll_ref_cnt < 2) { - uint32_t xtal_freq_mhz = clk_hal_xtal_get_freq_mhz(); - rtc_clk_mpll_configure(xtal_freq_mhz, expt_freq_hz / MHZ, false); - s_cur_mpll_freq_hz = clk_ll_mpll_get_freq_mhz(xtal_freq_mhz) * MHZ; - } else { - ret = ESP_ERR_INVALID_STATE; - } -end: - if (real_freq_hz != NULL) { - *real_freq_hz = s_cur_mpll_freq_hz; - } - esp_os_exit_critical(&periph_spinlock); - return ret; + // For IRAM compatibility, we do not use esp_clk_tree_src_set_freq_hz here + return esp_clk_tree_mpll_freq_set(expt_freq_hz, real_freq_hz); } #endif // SOC_CLK_MPLL_SUPPORTED diff --git a/components/esp_hw_support/include/clk_ctrl_os.h b/components/esp_hw_support/include/clk_ctrl_os.h index 5a72239e02..32af2baa5a 100644 --- a/components/esp_hw_support/include/clk_ctrl_os.h +++ b/components/esp_hw_support/include/clk_ctrl_os.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -21,7 +21,7 @@ extern "C" { * * @return true: success for enable the RC_FAST clock, false: RC_FAST clock enable failed */ -bool periph_rtc_dig_clk8m_enable(void); +bool periph_rtc_dig_clk8m_enable(void) __attribute__((deprecated("Please use esp_clk_tree_enable_src instead"))); /** * @brief This function is used to disable the digital RC_FAST clock, which should be called @@ -30,25 +30,25 @@ bool periph_rtc_dig_clk8m_enable(void); * @note If this function is called a number of times, the `periph_rtc_dig_clk8m_disable` * function needs to be called same times to disable. */ -void periph_rtc_dig_clk8m_disable(void); +void periph_rtc_dig_clk8m_disable(void) __attribute__((deprecated("Please use esp_clk_tree_enable_src instead"))); /** * @brief This function is used to get the real clock frequency value of RC_FAST clock * * @return The real clock value, in Hz */ -uint32_t periph_rtc_dig_clk8m_get_freq(void); +uint32_t periph_rtc_dig_clk8m_get_freq(void) __attribute__((deprecated("Please use esp_clk_tree_src_get_freq_hz instead"))); #if SOC_CLK_APLL_SUPPORTED /** * @brief Enable APLL power if it has not enabled */ -void periph_rtc_apll_acquire(void); +void periph_rtc_apll_acquire(void) __attribute__((deprecated("Please use esp_clk_tree_enable_src instead"))); /** * @brief Shut down APLL power if no peripherals using APLL */ -void periph_rtc_apll_release(void); +void periph_rtc_apll_release(void) __attribute__((deprecated("Please use esp_clk_tree_enable_src instead"))); /** * @brief Calculate and set APLL coefficients by given frequency @@ -69,19 +69,19 @@ void periph_rtc_apll_release(void); * - ESP_ERR_INVALID_ARG: The input expt_freq is out of APLL support range * - ESP_ERR_INVALID_STATE: APLL is referred by more than one peripherals, not allowed to change its frequency now */ -esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz); +esp_err_t periph_rtc_apll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz) __attribute__((deprecated("Please use esp_clk_tree_src_set_freq_hz instead"))); #endif // SOC_CLK_APLL_SUPPORTED #if SOC_CLK_MPLL_SUPPORTED /** * @brief Enable MPLL power if it has not enabled */ -esp_err_t periph_rtc_mpll_acquire(void); +esp_err_t periph_rtc_mpll_acquire(void) __attribute__((deprecated("Please use esp_clk_tree_enable_src instead"))); /** * @brief Shut down MPLL power if no peripherals using APLL */ -void periph_rtc_mpll_release(void); +void periph_rtc_mpll_release(void) __attribute__((deprecated("Please use esp_clk_tree_enable_src instead"))); /** * @brief Configure MPLL frequency @@ -96,7 +96,7 @@ void periph_rtc_mpll_release(void); * - ESP_OK: MPLL frequency set success * - ESP_ERR_INVALID_STATE: MPLL is referred by more than one peripherals, not allowed to change its frequency now */ -esp_err_t periph_rtc_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz); +esp_err_t periph_rtc_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz) __attribute__((deprecated("Please use esp_clk_tree_src_set_freq_hz instead"))); #endif // SOC_CLK_MPLL_SUPPORTED #ifdef __cplusplus diff --git a/components/esp_hw_support/include/esp_clk_tree.h b/components/esp_hw_support/include/esp_clk_tree.h index 50dcc64412..9f15b30e06 100644 --- a/components/esp_hw_support/include/esp_clk_tree.h +++ b/components/esp_hw_support/include/esp_clk_tree.h @@ -1,13 +1,15 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include #include "esp_err.h" #include "soc/clk_tree_defs.h" +#include "soc/soc_caps.h" #ifdef __cplusplus extern "C" { @@ -18,7 +20,7 @@ extern "C" { */ typedef enum { ESP_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 */ - ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, /*< Get its approxiamte frequency value */ + ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, /*< Get its approximate frequency value */ ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, /*< Always perform a calibration */ ESP_CLK_TREE_SRC_FREQ_PRECISION_INVALID, /*< Invalid degree of precision */ } esp_clk_tree_src_freq_precision_t; @@ -42,6 +44,20 @@ typedef enum { esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value); +/** + * @brief Set frequency of module clock source + * + * @param[in] clk_src Clock source available to modules, in soc_module_clk_t + * @param[in] expt_freq_value Expected frequency of the clock source, in Hz + * @param[out] ret_freq_value Real frequency of the clock source, in Hz + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_SUPPORTED Unsupported clock source + */ +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value); + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h b/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h index c915dfc029..82ac6ec93e 100644 --- a/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h +++ b/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -119,6 +119,72 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable); */ bool esp_clk_tree_is_power_on(soc_root_clk_circuit_t clk_circuit); +#if SOC_CLK_APLL_SUPPORTED +/** + * @brief Enable APLL power if it has not enabled + * + * @note Do not use this function in applications or drivers, please use `esp_clk_tree_enable_src` instead. + */ +void esp_clk_tree_apll_acquire(void); + +/** + * @brief Shut down APLL power if no peripherals using APLL + * + * @note Do not use this function in applications or drivers, please use `esp_clk_tree_enable_src` instead. + */ +void esp_clk_tree_apll_release(void); + +/** + * @brief Calculate and set APLL coefficients by given frequency + * @note This calculation is based on the inequality: + * xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) >= CLK_LL_APLL_MULTIPLIER_MIN_HZ(350 MHz) + * It will always calculate the minimum coefficients that can satisfy the inequality above, instead of loop them one by one. + * which means more appropriate coefficients are likely to exist. + * But this algorithm can meet almost all the cases and the accuracy can be guaranteed as well. + * @note The APLL frequency is only allowed to set when there is only one peripheral refer to it. + * If APLL is already set by another peripheral, this function will return `ESP_ERR_INVALID_STATE` + * and output the current frequency by parameter `real_freq`. + * + * @param expt_freq Expected APLL frequency (unit: Hz) + * @param real_freq APLL real working frequency [output] (unit: Hz) + * @return + * - ESP_OK: APLL frequency set success + * - ESP_ERR_INVALID_ARG: The input expt_freq is out of APLL support range + * - ESP_ERR_INVALID_STATE: APLL is referred by more than one peripherals, not allowed to change its frequency now + */ +esp_err_t esp_clk_tree_apll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz); +#endif // SOC_CLK_APLL_SUPPORTED + +#if SOC_CLK_MPLL_SUPPORTED +/** + * @brief Enable MPLL power if it has not enabled + * + * @note Do not use this function in applications or drivers, please use `esp_clk_tree_enable_src` instead. + */ +esp_err_t esp_clk_tree_mpll_acquire(void); + +/** + * @brief Shut down MPLL power if no peripherals using MPLL + * + * @note Do not use this function in applications or drivers, please use `esp_clk_tree_enable_src` instead. + */ +void esp_clk_tree_mpll_release(void); + +/** + * @brief Configure MPLL frequency + * @note The MPLL frequency is only allowed to set when there is only one peripheral refer to it. + * If MPLL is already set by another peripheral, this function will return `ESP_ERR_INVALID_STATE` + * and output the current frequency by parameter `real_freq`. + * + * @param expt_freq Expected MPLL frequency (unit: Hz) + * @param real_freq MPLL current working frequency [output] (unit: Hz) + * @return + * - ESP_OK: MPLL frequency set success + * - ESP_ERR_INVALID_STATE: MPLL is referred by more than one peripherals, not allowed to change its frequency now + */ +esp_err_t esp_clk_tree_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz); +#endif // SOC_CLK_MPLL_SUPPORTED + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/port/esp32/esp_clk_tree.c b/components/esp_hw_support/port/esp32/esp_clk_tree.c index ce7f888d0c..73eec5531e 100644 --- a/components/esp_hw_support/port/esp32/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -70,6 +75,26 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_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(expt_freq_value > 0, ESP_ERR_INVALID_ARG, TAG, "invalid frequency"); + + uint32_t real_freq_value = 0; + esp_err_t ret = ESP_OK; + switch (clk_src) { + case SOC_MOD_CLK_APLL: + ret = esp_clk_tree_apll_freq_set(expt_freq_value, &real_freq_value); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + if (ret_freq_value) { + *ret_freq_value = real_freq_value; + } + return ret; +} + void esp_clk_tree_initialize(void) { } @@ -88,6 +113,41 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + + // APLL has its own reference counting + if (clk_src == SOC_MOD_CLK_APLL) { + if (enable) { + esp_clk_tree_apll_acquire(); + } else { + esp_clk_tree_apll_release(); + } + return ESP_OK; + } + + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32c2/esp_clk_tree.c b/components/esp_hw_support/port/esp32c2/esp_clk_tree.c index 6269656ce1..d6919477c0 100644 --- a/components/esp_hw_support/port/esp32c2/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c2/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -64,6 +69,12 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + void esp_clk_tree_initialize(void) { } @@ -82,6 +93,31 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32c3/esp_clk_tree.c b/components/esp_hw_support/port/esp32c3/esp_clk_tree.c index 13db39f1aa..66e8d506f8 100644 --- a/components/esp_hw_support/port/esp32c3/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c3/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -64,6 +69,12 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + void esp_clk_tree_initialize(void) { } @@ -82,6 +93,31 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c index 1e1cc11cad..8d60246392 100644 --- a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c @@ -1,20 +1,22 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "sdkconfig.h" #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "hal/clk_gate_ll.h" #include "esp_private/esp_clk_tree_common.h" -#include "esp_rom_sys.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); @@ -70,8 +72,13 @@ uint32_t *freq_value) return ESP_OK; } -#define ENUM2ARRAY(clk_src) (clk_src - SOC_MOD_CLK_PLL_F12M) -static int16_t s_pll_src_cg_ref_cnt[9] = { 0 }; +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; static bool esp_clk_tree_initialized = false; void esp_clk_tree_initialize(void) @@ -87,10 +94,10 @@ void esp_clk_tree_initialize(void) soc_cpu_clk_src_t current_cpu_clk_src = clk_ll_cpu_get_src(); if (current_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) { - s_pll_src_cg_ref_cnt[ENUM2ARRAY(SOC_MOD_CLK_PLL_F160M)] = 1; + s_pll_src_cg_ref_cnt[SOC_MOD_CLK_PLL_F160M] = 1; _clk_gate_ll_ref_240m_clk_en(false); } else if (current_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M) { - s_pll_src_cg_ref_cnt[ENUM2ARRAY(SOC_MOD_CLK_PLL_F240M)] = 1; + s_pll_src_cg_ref_cnt[SOC_MOD_CLK_PLL_F240M] = 1; _clk_gate_ll_ref_160m_clk_en(false); } _clk_gate_ll_ref_120m_clk_en(false); @@ -117,38 +124,47 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) return false; // TODO: PM-653 } +#define ENABLE_CLK_GATE(clk_src_en_func, enable) \ + PERIPH_RCC_ATOMIC() { \ + clk_src_en_func(enable); \ + } + esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - if (!esp_clk_tree_initialized || (clk_src < SOC_MOD_CLK_PLL_F12M) || (clk_src > SOC_MOD_CLK_PLL_F240M)) { + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + if (!esp_clk_tree_initialized) { return ESP_OK; } - PERIPH_RCC_ATOMIC() { - if (enable) { - s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)]++; - } - if (s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] == 1) { - switch (clk_src) { - case SOC_MOD_CLK_PLL_F12M: clk_gate_ll_ref_12m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F20M: clk_gate_ll_ref_20m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F40M: clk_gate_ll_ref_40m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F48M: clk_gate_ll_ref_48m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F60M: clk_gate_ll_ref_60m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F80M: clk_gate_ll_ref_80m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F120M: clk_gate_ll_ref_120m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F160M: clk_gate_ll_ref_160m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F240M: clk_gate_ll_ref_240m_clk_en(enable); break; - default: break; - } - } - if (!enable) { - s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)]--; - } - if (s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] < 0) { + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); - s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] = 0; + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; } } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); break; + case SOC_MOD_CLK_PLL_F12M: ENABLE_CLK_GATE(clk_gate_ll_ref_12m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F20M: ENABLE_CLK_GATE(clk_gate_ll_ref_20m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F40M: ENABLE_CLK_GATE(clk_gate_ll_ref_40m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F48M: ENABLE_CLK_GATE(clk_gate_ll_ref_48m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F60M: ENABLE_CLK_GATE(clk_gate_ll_ref_60m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F80M: ENABLE_CLK_GATE(clk_gate_ll_ref_80m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F120M: ENABLE_CLK_GATE(clk_gate_ll_ref_120m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F160M: ENABLE_CLK_GATE(clk_gate_ll_ref_160m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F240M: ENABLE_CLK_GATE(clk_gate_ll_ref_240m_clk_en, enable); break; + default: break; + } + } + return ESP_OK; } -#undef ENUM2ARRAY diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk.c b/components/esp_hw_support/port/esp32c5/rtc_clk.c index ba3c83cfd2..b6fe9e1694 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c5/rtc_clk.c @@ -448,7 +448,9 @@ FORCE_IRAM_ATTR void rtc_clk_cpu_set_to_default_config(void) #endif rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); #ifndef BOOTLOADER_BUILD - esp_clk_tree_enable_src(old_cpu_clk_src, false); + if (old_cpu_clk_src != SOC_MOD_CLK_XTAL) { + esp_clk_tree_enable_src(old_cpu_clk_src, false); + } #endif s_cur_pll_freq = 0; // no disable PLL, but set freq to 0 to trigger a PLL calibration after wake-up from sleep } diff --git a/components/esp_hw_support/port/esp32c6/esp_clk_tree.c b/components/esp_hw_support/port/esp32c6/esp_clk_tree.c index 6f5249bb8b..4aa62f3376 100644 --- a/components/esp_hw_support/port/esp32c6/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c6/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -64,6 +69,12 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + void esp_clk_tree_initialize(void) { } @@ -82,6 +93,31 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32c61/esp_clk_tree.c b/components/esp_hw_support/port/esp32c61/esp_clk_tree.c index abb1e50f77..a2f9f86f43 100644 --- a/components/esp_hw_support/port/esp32c61/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c61/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -64,6 +69,12 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + void esp_clk_tree_initialize(void) { } @@ -82,6 +93,29 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32h2/esp_clk_tree.c b/components/esp_hw_support/port/esp32h2/esp_clk_tree.c index a5820b18e6..dd3a800d91 100644 --- a/components/esp_hw_support/port/esp32h2/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32h2/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -61,6 +66,12 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + void esp_clk_tree_initialize(void) { } @@ -79,6 +90,29 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32h21/esp_clk_tree.c b/components/esp_hw_support/port/esp32h21/esp_clk_tree.c index 7a4e0601de..3e4fe553c0 100644 --- a/components/esp_hw_support/port/esp32h21/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32h21/esp_clk_tree.c @@ -5,16 +5,21 @@ */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -60,6 +65,12 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + static int16_t s_xtal_x2_ref_cnt = 0; static int16_t s_bbpll_ref_cnt = 0; @@ -139,8 +150,26 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - PERIPH_RCC_ATOMIC() { + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; case SOC_MOD_CLK_XTAL_X2_F64M: // later, here should handle ref count for XTAL_X2_F64M clock gating, then also handle XTAL_X2 circuit enable/disable esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, enable); @@ -154,5 +183,5 @@ esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) break; } } - return ESP_OK; // TODO: PM-653 + return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32h4/esp_clk_tree.c b/components/esp_hw_support/port/esp32h4/esp_clk_tree.c index 9211539956..26a95cacf8 100644 --- a/components/esp_hw_support/port/esp32h4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32h4/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -63,9 +68,14 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + static int16_t s_xtal_x2_ref_cnt = 0; static int16_t s_bbpll_ref_cnt = 0; - void esp_clk_tree_initialize(void) { // Power @@ -142,8 +152,26 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - PERIPH_RCC_ATOMIC() { + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; case SOC_MOD_CLK_XTAL_X2_F32M: // later, here should handle ref count for XTAL_X2_F32M clock gating, then also handle XTAL_X2 circuit enable/disable esp_clk_tree_enable_power(SOC_ROOT_CIRCUIT_CLK_XTAL_X2, enable); diff --git a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c index 9f266e7f2c..8ccee3dc96 100644 --- a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c @@ -5,6 +5,7 @@ */ #include +#include #include "sdkconfig.h" #include "esp_clk_tree.h" #include "esp_err.h" @@ -13,12 +14,12 @@ #include "soc/clk_tree_defs.h" #include "soc/rtc.h" #include "soc/reset_reasons.h" +#include "soc/soc_caps.h" #include "hal/clk_gate_ll.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" #include "esp_private/periph_ctrl.h" -#include "esp_rom_sys.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); @@ -103,8 +104,30 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr return ESP_OK; } -#define ENUM2ARRAY(clk_src) (clk_src - SOC_MOD_CLK_PLL_F20M) -static int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_PLL_F240M - SOC_MOD_CLK_PLL_F20M + 1] = { 0 }; +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_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(expt_freq_value > 0, ESP_ERR_INVALID_ARG, TAG, "invalid frequency"); + + uint32_t real_freq_value = 0; + esp_err_t ret = ESP_OK; + switch (clk_src) { + case SOC_MOD_CLK_APLL: + ret = esp_clk_tree_apll_freq_set(expt_freq_value, &real_freq_value); + break; + case SOC_MOD_CLK_MPLL: + ret = esp_clk_tree_mpll_freq_set(expt_freq_value, &real_freq_value); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + if (ret_freq_value) { + *ret_freq_value = real_freq_value; + } + return ret; +} + +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; static bool esp_clk_tree_initialized = false; void esp_clk_tree_initialize(void) @@ -139,36 +162,67 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) return false; // TODO: PM-653 } +#define ENABLE_CLK_GATE(clk_src_en_func, enable) \ + PERIPH_RCC_ATOMIC() { \ + clk_src_en_func(enable); \ + } + esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - if (!esp_clk_tree_initialized || (clk_src < SOC_MOD_CLK_PLL_F20M) || (clk_src > SOC_MOD_CLK_PLL_F240M)) { + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source return ESP_OK; } - PERIPH_RCC_ATOMIC() { - if (enable) { - s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)]++; - } - if (s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] == 1) { - switch (clk_src) { - case SOC_MOD_CLK_PLL_F20M: clk_gate_ll_ref_20m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F25M: clk_gate_ll_ref_25m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F50M: clk_gate_ll_ref_50m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F80M: clk_gate_ll_ref_80m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F120M: clk_gate_ll_ref_120m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F160M: clk_gate_ll_ref_160m_clk_en(enable); break; - case SOC_MOD_CLK_PLL_F240M: clk_gate_ll_ref_240m_clk_en(enable); break; - default: break; + if (!esp_clk_tree_initialized) { + return ESP_OK; + } + + // these clock sources have their own reference counting + switch (clk_src) { + case SOC_MOD_CLK_APLL: + if (enable) { + esp_clk_tree_apll_acquire(); + } else { + esp_clk_tree_apll_release(); } - } - if (!enable) { - s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)]--; - } - if (s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] < 0) { + return ESP_OK; + case SOC_MOD_CLK_MPLL: + if (enable) { + return esp_clk_tree_mpll_acquire(); + } else { + esp_clk_tree_mpll_release(); + } + return ESP_OK; + default: + break; + } + + // other clock sources use the global reference counting + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); - s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] = 0; + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; } } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); break; + case SOC_MOD_CLK_PLL_F20M: ENABLE_CLK_GATE(clk_gate_ll_ref_20m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F25M: ENABLE_CLK_GATE(clk_gate_ll_ref_25m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F50M: ENABLE_CLK_GATE(clk_gate_ll_ref_50m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F80M: ENABLE_CLK_GATE(clk_gate_ll_ref_80m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F120M: ENABLE_CLK_GATE(clk_gate_ll_ref_120m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F160M: ENABLE_CLK_GATE(clk_gate_ll_ref_160m_clk_en, enable); break; + case SOC_MOD_CLK_PLL_F240M: ENABLE_CLK_GATE(clk_gate_ll_ref_240m_clk_en, enable); break; + default: break; + } + } + return ESP_OK; } -#undef ENUM2ARRAY diff --git a/components/esp_hw_support/port/esp32s2/esp_clk_tree.c b/components/esp_hw_support/port/esp32s2/esp_clk_tree.c index 33c06d23bc..6bb4ec4f12 100644 --- a/components/esp_hw_support/port/esp32s2/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32s2/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -68,6 +73,26 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_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(expt_freq_value > 0, ESP_ERR_INVALID_ARG, TAG, "invalid frequency"); + + uint32_t real_freq_value = 0; + esp_err_t ret = ESP_OK; + switch (clk_src) { + case SOC_MOD_CLK_APLL: + ret = esp_clk_tree_apll_freq_set(expt_freq_value, &real_freq_value); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + if (ret_freq_value) { + *ret_freq_value = real_freq_value; + } + return ret; +} + void esp_clk_tree_initialize(void) { } @@ -86,6 +111,40 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + + // APLL has its own reference counting + if (clk_src == SOC_MOD_CLK_APLL) { + if (enable) { + esp_clk_tree_apll_acquire(); + } else { + esp_clk_tree_apll_release(); + } + return ESP_OK; + } + + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32s3/esp_clk_tree.c b/components/esp_hw_support/port/esp32s3/esp_clk_tree.c index d174637ca7..efe7430ea6 100644 --- a/components/esp_hw_support/port/esp32s3/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32s3/esp_clk_tree.c @@ -1,20 +1,25 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" +#include "esp_log.h" #include "soc/rtc.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/periph_ctrl.h" ESP_LOG_ATTR_TAG(TAG, "esp_clk_tree"); +static _Atomic int16_t s_pll_src_cg_ref_cnt[SOC_MOD_CLK_INVALID] = { 0 }; + esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision, uint32_t *freq_value) { @@ -68,6 +73,18 @@ uint32_t *freq_value) return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_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(expt_freq_value > 0, ESP_ERR_INVALID_ARG, TAG, "invalid frequency"); + + switch (clk_src) { + default: + return ESP_ERR_NOT_SUPPORTED; + } + return ESP_OK; +} + void esp_clk_tree_initialize(void) { } @@ -86,6 +103,29 @@ bool esp_clk_tree_enable_power(soc_root_clk_circuit_t clk_circuit, bool enable) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + if (clk_src < 1 || clk_src >= SOC_MOD_CLK_INVALID) { + // some conditions is legal, e.g. -1 means external clock source + return ESP_OK; + } + int16_t prev_ref_cnt = 0; + if (enable) { + prev_ref_cnt = atomic_fetch_add(&s_pll_src_cg_ref_cnt[clk_src], 1); + } else { + prev_ref_cnt = atomic_fetch_sub(&s_pll_src_cg_ref_cnt[clk_src], 1); + if (prev_ref_cnt <= 0) { + ESP_EARLY_LOGW(TAG, "soc_module_clk_t %d disabled multiple times!!", clk_src); + atomic_store(&s_pll_src_cg_ref_cnt[clk_src], 0); + return ESP_OK; + } + } + if ((prev_ref_cnt == 0 && enable) || (prev_ref_cnt == 1 && !enable)) { + switch (clk_src) { + case SOC_MOD_CLK_RC_FAST: + enable ? rtc_dig_clk8m_enable() : rtc_dig_clk8m_disable(); + break; + default: + break; + } + } return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32s31/esp_clk_tree.c b/components/esp_hw_support/port/esp32s31/esp_clk_tree.c index 8e93d82156..565ff53eb5 100644 --- a/components/esp_hw_support/port/esp32s31/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32s31/esp_clk_tree.c @@ -80,6 +80,13 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr return ESP_OK; } +esp_err_t esp_clk_tree_src_set_freq_hz(soc_module_clk_t clk_src, uint32_t expt_freq_value, uint32_t *ret_freq_value) +{ + /* TODO: [ESP32S31] IDF-14733 */ + (void)clk_src; (void)expt_freq_value; (void)ret_freq_value; + return ESP_ERR_NOT_SUPPORTED; +} + static int16_t s_cpll_ref_cnt = 0; void esp_clk_tree_initialize(void) diff --git a/components/esp_hw_support/port/esp_clk_tree_common.c b/components/esp_hw_support/port/esp_clk_tree_common.c index bf3a7e6b91..a19f0bd8a1 100644 --- a/components/esp_hw_support/port/esp_clk_tree_common.c +++ b/components/esp_hw_support/port/esp_clk_tree_common.c @@ -1,10 +1,14 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include +#include +#include #include "esp_private/esp_clk_tree_common.h" +#include "esp_private/critical_section.h" #include "hal/clk_tree_hal.h" #include "hal/clk_tree_ll.h" #include "soc/rtc.h" @@ -12,7 +16,13 @@ #include "soc/clk_tree_defs.h" #include "soc/soc_caps.h" #include "sdkconfig.h" +#include "esp_check.h" #include "esp_hw_log.h" +#include "esp_log.h" +#if SOC_CLK_MPLL_SUPPORTED +#include "esp_private/rtc_clk.h" +#include "esp_ldo_regulator.h" +#endif ESP_HW_LOG_ATTR_TAG(TAG, "esp_clk_tree_common"); @@ -201,3 +211,182 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec return 0; } } + +#if SOC_CLK_APLL_SUPPORTED +// Current APLL frequency, in HZ. Zero if APLL is not enabled. +static portMUX_TYPE __attribute__((unused)) s_periph_apll_spinlock = portMUX_INITIALIZER_UNLOCKED; +static uint32_t s_cur_apll_freq_hz = 0; +static int s_apll_ref_cnt = 0; + +// Pending APLL coefficients: calibration requires APLL to be powered on, +// so if freq is set before acquire, we defer rtc_clk_apll_coeff_set until enable. +static bool s_apll_coeff_pending = false; +static uint32_t s_apll_pending_o_div = 0; +static uint32_t s_apll_pending_sdm0 = 0; +static uint32_t s_apll_pending_sdm1 = 0; +static uint32_t s_apll_pending_sdm2 = 0; + +void esp_clk_tree_apll_acquire(void) +{ + bool apply_pending = false; + uint32_t o_div, sdm0, sdm1, sdm2; + + esp_os_enter_critical(&s_periph_apll_spinlock); + s_apll_ref_cnt++; + if (s_apll_ref_cnt == 1) { + rtc_clk_apll_enable(true); + if (s_apll_coeff_pending) { + apply_pending = true; + o_div = s_apll_pending_o_div; + sdm0 = s_apll_pending_sdm0; + sdm1 = s_apll_pending_sdm1; + sdm2 = s_apll_pending_sdm2; + s_apll_coeff_pending = false; + } + } + esp_os_exit_critical(&s_periph_apll_spinlock); + + if (apply_pending) { + rtc_clk_apll_coeff_set(o_div, sdm0, sdm1, sdm2); + } +} + +void esp_clk_tree_apll_release(void) +{ + esp_os_enter_critical(&s_periph_apll_spinlock); + assert(s_apll_ref_cnt > 0); + s_apll_ref_cnt--; + if (s_apll_ref_cnt == 0) { + s_cur_apll_freq_hz = 0; + s_apll_coeff_pending = false; + rtc_clk_apll_enable(false); + } + esp_os_exit_critical(&s_periph_apll_spinlock); +} + +esp_err_t esp_clk_tree_apll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz) +{ + uint32_t o_div = 0; + uint32_t sdm0 = 0; + uint32_t sdm1 = 0; + uint32_t sdm2 = 0; + + uint32_t apll_freq = rtc_clk_apll_coeff_calc(expt_freq_hz, &o_div, &sdm0, &sdm1, &sdm2); + ESP_RETURN_ON_FALSE(apll_freq, ESP_ERR_INVALID_ARG, TAG, "APLL coefficients calculate failed"); + bool need_config = true; + bool apll_enabled = false; + esp_os_enter_critical(&s_periph_apll_spinlock); + /* If APLL is not in use or only one peripheral in use, its frequency can be changed as will + * But when more than one peripheral refers APLL, its frequency is not allowed to change once it is set */ + if (s_cur_apll_freq_hz == 0 || s_apll_ref_cnt < 2) { + s_cur_apll_freq_hz = apll_freq; + apll_enabled = (s_apll_ref_cnt > 0); + if (!apll_enabled) { + // APLL not yet powered on, defer coeff_set (which includes calibration) until acquire + s_apll_coeff_pending = true; + s_apll_pending_o_div = o_div; + s_apll_pending_sdm0 = sdm0; + s_apll_pending_sdm1 = sdm1; + s_apll_pending_sdm2 = sdm2; + } + } else { + apll_freq = s_cur_apll_freq_hz; + need_config = false; + } + esp_os_exit_critical(&s_periph_apll_spinlock); + if (real_freq_hz != NULL) { + *real_freq_hz = apll_freq; + } + if (need_config) { + ESP_LOGD(TAG, "APLL works at %"PRIu32" Hz with coefficients [sdm0] %"PRIu32" [sdm1] %"PRIu32" [sdm2] %"PRIu32" [o_div] %"PRIu32"", + apll_freq, sdm0, sdm1, sdm2, o_div); + if (apll_enabled) { + rtc_clk_apll_coeff_set(o_div, sdm0, sdm1, sdm2); + } + } else { + return ESP_ERR_INVALID_STATE; + } + return ESP_OK; +} +#endif /* SOC_CLK_APLL_SUPPORTED */ + +#if SOC_CLK_MPLL_SUPPORTED +static portMUX_TYPE __attribute__((unused)) s_periph_mpll_spinlock = portMUX_INITIALIZER_UNLOCKED; +static uint32_t s_cur_mpll_freq_hz = 0; +static int s_mpll_ref_cnt = 0; +#if CONFIG_ESP_LDO_RESERVE_PSRAM +static esp_ldo_channel_handle_t s_ldo_chan = NULL; +#endif + +esp_err_t IRAM_ATTR esp_clk_tree_mpll_acquire(void) +{ + // power up LDO for the MPLL +#if CONFIG_ESP_LDO_RESERVE_PSRAM + if (s_ldo_chan == NULL) { + esp_ldo_channel_config_t ldo_mpll_config = { + .chan_id = CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN, + .voltage_mv = CONFIG_ESP_LDO_VOLTAGE_PSRAM_DOMAIN, + }; + ESP_RETURN_ON_ERROR(esp_ldo_acquire_channel(&ldo_mpll_config, &s_ldo_chan), TAG, "acquire internal LDO for MPLL failed"); + } +#endif + + esp_os_enter_critical(&s_periph_mpll_spinlock); + s_mpll_ref_cnt++; + if (s_mpll_ref_cnt == 1) { + // For the first time enable MPLL, need to set power up + rtc_clk_mpll_enable(); + } + esp_os_exit_critical(&s_periph_mpll_spinlock); + return ESP_OK; +} + +void esp_clk_tree_mpll_release(void) +{ + bool __attribute__((unused)) release_ldo = false; + esp_os_enter_critical(&s_periph_mpll_spinlock); + assert(s_mpll_ref_cnt > 0); + s_mpll_ref_cnt--; + if (s_mpll_ref_cnt == 0) { + s_cur_mpll_freq_hz = 0; + rtc_clk_mpll_disable(); + release_ldo = true; + } + esp_os_exit_critical(&s_periph_mpll_spinlock); + +#if defined(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN) && CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN != -1 + if (release_ldo && s_ldo_chan) { + esp_ldo_release_channel(s_ldo_chan); + s_ldo_chan = NULL; + } +#endif +} + +esp_err_t IRAM_ATTR esp_clk_tree_mpll_freq_set(uint32_t expt_freq_hz, uint32_t *real_freq_hz) +{ + esp_err_t ret = ESP_OK; + + // Guarantee 'esp_clk_tree_mpll_acquire' has been called before set mpll freq + assert(s_mpll_ref_cnt > 0); + + esp_os_enter_critical(&s_periph_mpll_spinlock); + if (s_cur_mpll_freq_hz == expt_freq_hz) { + goto end; + } + /* If MPLL is not in use or only one peripheral in use, its frequency can be changed as will + * But when more than one peripheral refers MPLL, its frequency is not allowed to change once it is set */ + if (s_cur_mpll_freq_hz == 0 || s_mpll_ref_cnt < 2) { + uint32_t xtal_freq_mhz = clk_hal_xtal_get_freq_mhz(); + rtc_clk_mpll_configure(xtal_freq_mhz, expt_freq_hz / MHZ, false); + s_cur_mpll_freq_hz = clk_ll_mpll_get_freq_mhz(xtal_freq_mhz) * MHZ; + } else { + ret = ESP_ERR_INVALID_STATE; + } +end: + if (real_freq_hz != NULL) { + *real_freq_hz = s_cur_mpll_freq_hz; + } + esp_os_exit_critical(&s_periph_mpll_spinlock); + return ret; +} +#endif /* SOC_CLK_MPLL_SUPPORTED */ diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index 6fb15766d3..8c63a117a5 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -133,6 +133,7 @@ struct esp_rgb_panel_t { gpio_num_t data_gpio_nums[LCD_LL_GET(RGB_BUS_WIDTH)]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color" uint64_t gpio_reserve_mask; // GPIOs reserved by this panel, used to revoke the GPIO reservation when the panel is deleted uint32_t src_clk_hz; // Peripheral source clock resolution + lcd_clock_source_t clk_src; // Peripheral clock source esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width) int bounce_pos_px; // Position in whatever source material is used for the bounce buffer, in pixels size_t bb_eof_count; // record the number we received the DMA EOF event, compare with `expect_eof_count` in the VSYNC_END ISR @@ -241,6 +242,9 @@ static esp_err_t lcd_rgb_panel_destroy(esp_rgb_panel_t *rgb_panel) PERIPH_RCC_ATOMIC() { lcd_ll_enable_clock(rgb_panel->hal.dev, false); } + if (rgb_panel->clk_src) { + esp_clk_tree_enable_src(rgb_panel->clk_src, false); + } if (rgb_panel->panel_id >= 0) { PERIPH_RCC_RELEASE_ATOMIC(soc_lcd_rgb_signals[rgb_panel->panel_id].module, ref_count) { if (ref_count == 0) { @@ -891,10 +895,11 @@ static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *rgb_panel, lcd_ { // get clock source frequency uint32_t src_clk_hz = 0; + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), TAG, "clock source enable failed"); + rgb_panel->clk_src = clk_src; ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_hz), TAG, "get clock source frequency failed"); rgb_panel->src_clk_hz = src_clk_hz; - ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), TAG, "clock source enable failed"); PERIPH_RCC_ATOMIC() { lcd_ll_select_clk_src(rgb_panel->hal.dev, clk_src); } diff --git a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c index bd3aac9201..3130b820f5 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c +++ b/components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,7 @@ #include "esp_attr.h" #include "test_rgb_board.h" #include "esp_private/spi_flash_os.h" +#include "esp_clk_tree.h" #if CONFIG_LCD_RGB_ISR_IRAM_SAFE #define TEST_LCD_CALLBACK_ATTR IRAM_ATTR @@ -25,7 +26,7 @@ #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t)) -static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, lcd_color_format_t in_color_format, size_t bb_pixels, bool refresh_on_demand, bool user_fb, +static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, lcd_color_format_t in_color_format, size_t bb_pixels, lcd_clock_source_t clk_src, bool refresh_on_demand, bool user_fb, esp_lcd_rgb_panel_vsync_cb_t vsync_cb, void *user_data) { esp_lcd_panel_handle_t panel_handle = NULL; @@ -34,7 +35,7 @@ static esp_lcd_panel_handle_t test_rgb_panel_initialization(size_t data_width, l .in_color_format = in_color_format, .dma_burst_size = 64, .bounce_buffer_size_px = bb_pixels, - .clk_src = LCD_CLK_SRC_DEFAULT, + .clk_src = clk_src, .disp_gpio_num = TEST_LCD_DISP_EN_GPIO, .pclk_gpio_num = TEST_LCD_PCLK_GPIO, .vsync_gpio_num = TEST_LCD_VSYNC_GPIO, @@ -97,7 +98,7 @@ TEST_CASE("lcd_rgb_panel_stream_mode", "[lcd]") TEST_ASSERT_NOT_NULL(img); printf("initialize RGB panel with stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, false, NULL, NULL); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL); printf("flush random color block\r\n"); for (int i = 0; i < 200; i++) { uint8_t color_byte = esp_random() & 0xFF; @@ -119,7 +120,7 @@ TEST_CASE("lcd_rgb_panel_8bit_interface", "[lcd]") printf("initialize RGB panel with stream mode\r\n"); // bpp for RGB888 is 24 - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(8, LCD_COLOR_FMT_RGB888, 0, false, false, NULL, NULL); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(8, LCD_COLOR_FMT_RGB888, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL); uint8_t color_byte = esp_random() & 0xFF; printf("flush random color block 0x%x\r\n", color_byte); int x_start = esp_random() % (TEST_LCD_H_RES - 100); @@ -147,7 +148,7 @@ TEST_CASE("lcd_rgb_panel_refresh_on_demand", "[lcd]") TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); printf("initialize RGB panel with non-stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, true, false, test_rgb_panel_trans_done, cur_task); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, true, false, test_rgb_panel_trans_done, cur_task); printf("flush random color block\r\n"); for (int i = 0; i < 200; i++) { uint8_t color_byte = esp_random() & 0xFF; @@ -172,7 +173,7 @@ TEST_CASE("lcd_rgb_panel_bounce_buffer", "[lcd]") TaskHandle_t cur_task = xTaskGetCurrentTaskHandle(); printf("initialize RGB panel with non-stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 20 * TEST_LCD_H_RES, false, false, test_rgb_panel_trans_done, cur_task); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 20 * TEST_LCD_H_RES, LCD_CLK_SRC_DEFAULT, false, false, test_rgb_panel_trans_done, cur_task); printf("flush random color block\r\n"); for (int i = 0; i < 200; i++) { uint8_t color_byte = esp_random() & 0xFF; @@ -195,7 +196,7 @@ TEST_CASE("lcd_rgb_panel_update_pclk", "[lcd]") TEST_ASSERT_NOT_NULL(img); printf("initialize RGB panel with stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, false, NULL, NULL); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL); printf("flush one clock block to the LCD\r\n"); uint8_t color_byte = esp_random() & 0xFF; int x_start = esp_random() % (TEST_LCD_H_RES - 100); @@ -223,7 +224,7 @@ TEST_CASE("lcd_rgb_panel_restart", "[lcd]") TEST_ASSERT_NOT_NULL(img); printf("initialize RGB panel with stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, false, NULL, NULL); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL); printf("flush one clock block to the LCD\r\n"); uint8_t color_byte = esp_random() & 0xFF; int x_start = esp_random() % (TEST_LCD_H_RES - 100); @@ -253,7 +254,7 @@ TEST_CASE("lcd_rgb_panel_rotate", "[lcd]") memset(img, color_byte, w * h * sizeof(uint16_t)); printf("initialize RGB panel with stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, false, NULL, NULL); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, NULL, NULL); printf("Update the rotation of panel\r\n"); for (size_t i = 0; i < 8; i++) { @@ -278,7 +279,7 @@ TEST_CASE("lcd_rgb_panel_user_frame_buffer", "[lcd]") TEST_ASSERT_NOT_NULL(img); printf("initialize RGB panel with stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, true, NULL, NULL); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, true, NULL, NULL); printf("flush one clock block to the LCD\r\n"); uint8_t color_byte = esp_random() & 0xFF; @@ -300,6 +301,34 @@ TEST_CASE("lcd_rgb_panel_user_frame_buffer", "[lcd]") free(user_frame_buffer); } +#if SOC_CLK_APLL_SUPPORTED +TEST_CASE("lcd_rgb_panel_use_apll", "[lcd]") +{ + uint8_t *img = malloc(TEST_IMG_SIZE); + TEST_ASSERT_NOT_NULL(img); + + printf("set APLL frequency\r\n"); + uint32_t real_freq = 0; + TEST_ESP_OK(esp_clk_tree_src_set_freq_hz(SOC_MOD_CLK_APLL, 160 * 1000 * 1000, &real_freq)); + printf("APLL frequency: %"PRIu32" Hz\r\n", real_freq); + + printf("initialize RGB panel with stream mode\r\n"); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_APLL, false, false, NULL, NULL); + printf("flush random color block\r\n"); + for (int i = 0; i < 200; i++) { + uint8_t color_byte = esp_random() & 0xFF; + int x_start = esp_random() % (TEST_LCD_H_RES - 100); + int y_start = esp_random() % (TEST_LCD_V_RES - 100); + memset(img, color_byte, TEST_IMG_SIZE); + esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img); + vTaskDelay(pdMS_TO_TICKS(10)); + } + printf("delete RGB panel\r\n"); + TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); + free(img); +} +#endif // SOC_CLK_APLL_SUPPORTED + #if CONFIG_LCD_RGB_ISR_IRAM_SAFE TEST_LCD_CALLBACK_ATTR static bool test_rgb_panel_count_in_callback(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx) { @@ -325,7 +354,7 @@ TEST_CASE("lcd_rgb_panel_iram_safe", "[lcd]") uint32_t callback_calls = 0; printf("initialize RGB panel with stream mode\r\n"); - esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, false, false, test_rgb_panel_count_in_callback, &callback_calls); + esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(16, LCD_COLOR_FMT_RGB565, 0, LCD_CLK_SRC_DEFAULT, false, false, test_rgb_panel_count_in_callback, &callback_calls); printf("flush one clock block to the LCD\r\n"); uint8_t color_byte = esp_random() & 0xFF; int x_start = esp_random() % (TEST_LCD_H_RES - 100); diff --git a/components/esp_psram/device/esp_psram_impl_ap_hex.c b/components/esp_psram/device/esp_psram_impl_ap_hex.c index ec5b796b81..daed4151e2 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_hex.c +++ b/components/esp_psram/device/esp_psram_impl_ap_hex.c @@ -14,8 +14,9 @@ #include "esp_private/esp_psram_ldo.h" #include "hal/psram_ctrlr_ll.h" #include "hal/mspi_ll.h" -#include "clk_ctrl_os.h" #include "soc/rtc.h" +#include "esp_check.h" +#include "esp_private/esp_clk_tree_common.h" #define AP_HEX_PSRAM_SYNC_READ 0x0000 #define AP_HEX_PSRAM_SYNC_WRITE 0x8080 @@ -418,9 +419,10 @@ static void s_configure_psram_ecc(void) esp_err_t esp_psram_impl_enable(void) { #if SOC_CLK_MPLL_SUPPORTED - periph_rtc_mpll_acquire(); + // We need to use the acquire and freq_set functions directly instead of general clk_tree API for IRAM safe function + esp_clk_tree_mpll_acquire(); uint32_t real_mpll_freq = 0; - periph_rtc_mpll_freq_set(AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ * 1000000, &real_mpll_freq); + esp_clk_tree_mpll_freq_set(AP_HEX_PSRAM_MPLL_DEFAULT_FREQ_MHZ * 1000000, &real_mpll_freq); ESP_EARLY_LOGD(TAG, "real_mpll_freq: %d", real_mpll_freq); #endif diff --git a/components/esp_psram/device/esp_psram_impl_ap_oct.c b/components/esp_psram/device/esp_psram_impl_ap_oct.c index 756eb9edb6..90721a66bd 100644 --- a/components/esp_psram/device/esp_psram_impl_ap_oct.c +++ b/components/esp_psram/device/esp_psram_impl_ap_oct.c @@ -6,15 +6,16 @@ #include "sdkconfig.h" #include "esp_attr.h" +#include "esp_clk_tree.h" #include "esp_err.h" #include "esp_log.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_private/periph_ctrl.h" #include "esp_private/mspi_timing_tuning.h" #include "esp_private/esp_psram_impl.h" #include "esp_private/esp_psram_ldo.h" #include "hal/psram_ctrlr_ll.h" #include "hal/mspi_ll.h" -#include "clk_ctrl_os.h" #include "soc/rtc.h" #define AP_OCT_PSRAM_SYNC_READ 0x0000 @@ -419,9 +420,10 @@ esp_err_t esp_psram_impl_enable(void) esp_psram_power_init(&config); #endif #if SOC_CLK_MPLL_SUPPORTED - periph_rtc_mpll_acquire(); + // We need to use the acquire and freq_set functions directly instead of general clk_tree API for IRAM safe function + esp_clk_tree_mpll_acquire(); uint32_t real_mpll_freq = 0; - periph_rtc_mpll_freq_set(AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ * 1000000, &real_mpll_freq); + esp_clk_tree_mpll_freq_set(AP_OCT_PSRAM_MPLL_DEFAULT_FREQ_MHZ * 1000000, &real_mpll_freq); ESP_EARLY_LOGD(TAG, "real_mpll_freq: %d", real_mpll_freq); #endif diff --git a/components/soc/esp32s2/include/soc/clk_tree_defs.h b/components/soc/esp32s2/include/soc/clk_tree_defs.h index a26a2e0e48..10821e3988 100644 --- a/components/soc/esp32s2/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s2/include/soc/clk_tree_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -225,14 +225,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of Temperature Sensor */ -#define SOC_TEMP_SENSOR_CLKS {SOC_MOD_CLK_TEMP_SENSOR} +#define SOC_TEMP_SENSOR_CLKS {SOC_MOD_CLK_RC_FAST} /** * @brief Type of Temp Sensor clock source */ typedef enum { - TEMPERATURE_SENSOR_CLK_SRC_RC_FAST = SOC_MOD_CLK_TEMP_SENSOR, /*!< Select RC_FAST as the source clock */ - TEMPERATURE_SENSOR_CLK_SRC_DEFAULT = SOC_MOD_CLK_TEMP_SENSOR, /*!< Select RC_FAST as the default choice */ + TEMPERATURE_SENSOR_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + TEMPERATURE_SENSOR_CLK_SRC_DEFAULT = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the default choice */ } soc_periph_temperature_sensor_clk_src_t; ///////////////////////////////////////////////////UART///////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32s3/include/soc/clk_tree_defs.h b/components/soc/esp32s3/include/soc/clk_tree_defs.h index 642e462810..a14db35ac6 100644 --- a/components/soc/esp32s3/include/soc/clk_tree_defs.h +++ b/components/soc/esp32s3/include/soc/clk_tree_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -244,14 +244,14 @@ typedef enum { /** * @brief Array initializer for all supported clock sources of Temperature Sensor */ -#define SOC_TEMP_SENSOR_CLKS {SOC_MOD_CLK_TEMP_SENSOR} +#define SOC_TEMP_SENSOR_CLKS {SOC_MOD_CLK_RC_FAST} /** * @brief Type of Temp Sensor clock source */ typedef enum { - TEMPERATURE_SENSOR_CLK_SRC_RC_FAST = SOC_MOD_CLK_TEMP_SENSOR, /*!< Select RC_FAST as the source clock */ - TEMPERATURE_SENSOR_CLK_SRC_DEFAULT = SOC_MOD_CLK_TEMP_SENSOR, /*!< Select RC_FAST as the default choice */ + TEMPERATURE_SENSOR_CLK_SRC_RC_FAST = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the source clock */ + TEMPERATURE_SENSOR_CLK_SRC_DEFAULT = SOC_MOD_CLK_RC_FAST, /*!< Select RC_FAST as the default choice */ } soc_periph_temperature_sensor_clk_src_t; ///////////////////////////////////////////////////UART///////////////////////////////////////////////////////////////// diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 5c9eb78edf..3be999840b 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -24,7 +24,7 @@ #include "bootloader_flash.h" #include "esp_check.h" #include "esp_private/esp_clk_tree_common.h" -#include "clk_ctrl_os.h" +#include "esp_clk_tree.h" #include "soc/soc_caps.h" #include "hal/spi_flash_hal.h" #include "hal/mspi_ll.h" @@ -287,9 +287,6 @@ static uint32_t init_gpspi_clock(esp_flash_t *chip, const esp_flash_spi_device_c uint32_t clk_src_freq = 0; spi_clock_source_t clk_src = config->clock_source ? config->clock_source : SPI_CLK_SRC_DEFAULT; - if ((soc_module_clk_t)clk_src == SOC_MOD_CLK_RC_FAST) { - periph_rtc_dig_clk8m_enable(); - } esp_clk_tree_enable_src(clk_src, true); esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &clk_src_freq); @@ -356,11 +353,6 @@ static void deinit_gpspi_clock(esp_flash_t *chip) // Disable the clock source esp_clk_tree_enable_src(chip->clock_source, false); - - // Disable RC_FAST clock if it was used - if ((soc_module_clk_t)chip->clock_source == SOC_MOD_CLK_RC_FAST) { - periph_rtc_dig_clk8m_disable(); - } #endif // !CONFIG_IDF_TARGET_ESP32 }