fix(driver): fix drivers clock management

This commit is contained in:
wuzhenghui
2026-09-02 19:20:14 +08:00
parent f9428ecc1e
commit 0b7f047e9e
7 changed files with 82 additions and 3 deletions
@@ -66,6 +66,7 @@ typedef struct dvp_platform {
static dvp_platform_t s_platform;
static const char *TAG = "dvp_cam";
static soc_module_clk_t s_dvp_clk_src[CAP_DVP_PERIPH_NUM];
/**
* @brief Claim DVP controller
@@ -346,6 +347,11 @@ esp_err_t esp_cam_ctlr_dvp_init(int ctlr_id, cam_clock_source_t clk_src, const e
esp_rom_gpio_connect_out_signal(pin->xclk_io, cam_periph_signals.buses[ctlr_id].clk_sig, false, false);
}
#if CONFIG_IDF_TARGET_ESP32S31
// PLL 120M was selected in esp_perip_clk_init on esp32s31.
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, true));
#endif
PERIPH_RCC_ACQUIRE_ATOMIC(cam_periph_signals.buses[ctlr_id].module, ref_count) {
if (ref_count == 0) {
cam_ll_enable_bus_clock(ctlr_id, true);
@@ -354,6 +360,7 @@ esp_err_t esp_cam_ctlr_dvp_init(int ctlr_id, cam_clock_source_t clk_src, const e
}
ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true));
s_dvp_clk_src[ctlr_id] = (soc_module_clk_t)clk_src;
PERIPH_RCC_ATOMIC() {
cam_ll_enable_clk(ctlr_id, true);
cam_ll_select_clk_src(ctlr_id, clk_src);
@@ -458,6 +465,15 @@ esp_err_t esp_cam_ctlr_dvp_deinit(int ctlr_id)
}
}
if (s_dvp_clk_src[ctlr_id]) {
esp_clk_tree_enable_src(s_dvp_clk_src[ctlr_id], false);
s_dvp_clk_src[ctlr_id] = 0;
}
#if CONFIG_IDF_TARGET_ESP32S31
esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false);
#endif
return ESP_OK;
}
@@ -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
*/
@@ -18,7 +18,13 @@
#include "esp_private/esp_sleep_internal.h"
#include "esp_private/esp_pmu.h"
static bool test_gptimer_alarm_stop_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
#if CONFIG_GPTIMER_ISR_CACHE_SAFE
#define TEST_ALARM_CALLBACK_ATTR IRAM_ATTR
#else
#define TEST_ALARM_CALLBACK_ATTR
#endif // CONFIG_GPTIMER_ISR_CACHE_SAFE
TEST_ALARM_CALLBACK_ATTR static bool test_gptimer_alarm_stop_callback(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
{
TaskHandle_t task_handle = (TaskHandle_t)user_data;
BaseType_t high_task_wakeup;
+17 -1
View File
@@ -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
*/
@@ -27,6 +27,7 @@
#include "esp_private/etm_interface.h"
#include "esp_private/sleep_retention.h"
#include "esp_private/critical_section.h"
#include "esp_private/esp_clk_tree_common.h"
#define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
@@ -63,6 +64,9 @@ struct esp_etm_channel_t {
_Atomic etm_chan_fsm_t fsm; // record ETM channel's driver state
esp_etm_event_handle_t event; // which event is connect to the channel
esp_etm_task_handle_t task; // which task is connect to the channel
#if ETM_LL_SUPPORT(CLOCK_SRC)
etm_clock_source_t clk_src; // function clock source enabled for this channel
#endif
};
// ETM driver platform, it's always a singleton
@@ -272,6 +276,8 @@ esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_ch
if (clk_src == 0) {
clk_src = ETM_CLK_SRC_DEFAULT;
}
ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), err, TAG, "clock source enable failed");
chan->clk_src = clk_src;
etm_ll_set_clock_source(group_id, clk_src);
#endif
@@ -290,6 +296,11 @@ esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_ch
err:
if (chan) {
#if ETM_LL_SUPPORT(CLOCK_SRC)
if (chan->clk_src != 0) {
esp_clk_tree_enable_src((soc_module_clk_t)chan->clk_src, false);
}
#endif
etm_chan_destroy(chan);
}
return ret;
@@ -310,6 +321,11 @@ esp_err_t esp_etm_del_channel(esp_etm_channel_handle_t chan)
etm_ll_channel_set_task(group->hal.regs, chan_id, 0);
ESP_LOGD(TAG, "del etm channel (%d,%d)", group_id, chan_id);
#if ETM_LL_SUPPORT(CLOCK_SRC)
// Back to hardware default clock selection, otherwise it might get stuck when stopping the bus during sleep process.
etm_ll_set_clock_source(group_id, ETM_CLK_SRC_XTAL);
ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)chan->clk_src, false), TAG, "clock source disable failed");
#endif
// recycle memory resource
ESP_RETURN_ON_ERROR(etm_chan_destroy(chan), TAG, "destroy etm channel failed");
return ESP_OK;
@@ -6,6 +6,8 @@
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_check.h"
#include "esp_clk_tree.h"
#include "soc/soc_caps.h"
#include "modem/modem_clock_impl.h"
#include "esp_private/regi2c_ctrl.h"
@@ -212,7 +214,13 @@ static void IRAM_ATTR modem_clock_coex_configure(modem_clock_context_t *ctx, boo
#if SOC_MODEM_CLOCK_SOC_PLL_SOURCE_CG_SUPPORTED
static void IRAM_ATTR modem_clock_soc_pll_source_cg_configure(modem_clock_context_t *ctx, bool enable)
{
if (enable) {
ESP_ERROR_CHECK(esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F160M, true));
}
modem_clock_hal_enable_soc_pll_source_cg(ctx->hal, enable);
if (!enable) {
ESP_ERROR_CHECK(esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F160M, false));
}
}
#endif
@@ -144,6 +144,9 @@ uint32_t rtc_clk_cal_internal(soc_clk_freq_calculation_src_t cal_clk_sel, uint32
}
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
clk_ll_freq_calculation_set_divider(1);
// Back to always on clock source, Otherwise, if the source for this calibration is subsequently turned off,
// the next calibration will not be able to switch to the new calibration source.
clk_ll_freq_calulation_set_target(CLK_CAL_RC_SLOW);
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
if (cal_clk_sel == CLK_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
@@ -123,6 +123,9 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
{
esp_err_t ret = ESP_OK;
esp_lcd_i80_bus_t *bus = NULL;
#if CONFIG_IDF_TARGET_ESP32S31
bool pll_f120m_enabled = false;
#endif
ESP_RETURN_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
// although LCD_CAM can support up to 24 data lines, we restrict users to only use 8 or 16 bit width
ESP_RETURN_ON_FALSE(bus_config->bus_width == 8 || bus_config->bus_width == 16, ESP_ERR_INVALID_ARG,
@@ -181,6 +184,11 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
#endif // I80_USE_RETENTION_LINK
// initialize HAL layer, so we can call LL APIs later
lcd_hal_init(&bus->hal, bus_id);
#if CONFIG_IDF_TARGET_ESP32S31
// PLL 120M was selected in esp_perip_clk_init on esp32s31.
ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, true), err, TAG, "clock source enable failed");
pll_f120m_enabled = true;
#endif
PERIPH_RCC_ATOMIC() {
lcd_ll_enable_clock(bus->hal.dev, true);
}
@@ -264,6 +272,11 @@ err:
esp_clk_tree_enable_src(bus->clk_src, false);
bus->clk_src = SOC_MOD_CLK_INVALID;
}
#if CONFIG_IDF_TARGET_ESP32S31
if (pll_f120m_enabled) {
esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false);
}
#endif
#if CONFIG_PM_ENABLE
if (bus->pm_lock) {
esp_pm_lock_delete(bus->pm_lock);
@@ -287,6 +300,9 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus)
esp_clk_tree_enable_src(bus->clk_src, false);
bus->clk_src = SOC_MOD_CLK_INVALID;
}
#if CONFIG_IDF_TARGET_ESP32S31
ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false), err, TAG, "clock source disable failed");
#endif
#if I80_USE_RETENTION_LINK
const periph_retention_module_t module_id = soc_i80_lcd_retention_info[bus_id].retention_module;
sleep_retention_module_detach(module_id);
@@ -173,6 +173,9 @@ struct esp_rgb_panel_t {
uint32_t fb_behind_cache: 1; // Whether the frame buffer is behind the cache
uint32_t bb_behind_cache: 1; // Whether the bounce buffer is behind the cache
uint32_t user_fb: 1; // Whether the frame buffer is provided by user
#if CONFIG_IDF_TARGET_ESP32S31
uint32_t pll_f120m_enabled: 1; // Whether PLL_F120M was enabled for this panel instance
#endif
} flags;
// hook fields
esp_lcd_panel_draw_bitmap_hook_t draw_bitmap_hook; // Draw bitmap hook function
@@ -265,6 +268,12 @@ 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 CONFIG_IDF_TARGET_ESP32S31
if (rgb_panel->flags.pll_f120m_enabled) {
esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, false);
rgb_panel->flags.pll_f120m_enabled = 0;
}
#endif
if (rgb_panel->clk_src) {
esp_clk_tree_enable_src(rgb_panel->clk_src, false);
}
@@ -419,6 +428,11 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
lcd_hal_init(&rgb_panel->hal, panel_id);
lcd_hal_context_t *hal = &rgb_panel->hal;
// enable clock
#if CONFIG_IDF_TARGET_ESP32S31
// PLL 120M was selected in esp_perip_clk_init on esp32s31.
ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)SOC_MOD_CLK_PLL_F120M, true), err, TAG, "clock source enable failed");
rgb_panel->flags.pll_f120m_enabled = 1;
#endif
PERIPH_RCC_ATOMIC() {
lcd_ll_enable_clock(hal->dev, true);
}