mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 11:03:11 +00:00
refactor(clk_tree): use general api to enable the clk
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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" {
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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, \
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <freertos/FreeRTOS.h>
|
||||
#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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <stdbool.h>
|
||||
#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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.h>
|
||||
#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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,21 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdatomic.h>
|
||||
#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
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stdatomic.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 "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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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/////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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/////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user