From 34f249a28bb9812f1253badc356e6f0779d48cf9 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 20 Jan 2025 15:49:03 +0800 Subject: [PATCH 1/3] feat(esp_hw_support): support esp_perip_clk_init for esp32c5 --- .../port/esp32c5/esp_clk_tree.c | 37 ++- .../esp_hw_support/port/esp32c5/io_mux.c | 2 + .../esp_hw_support/port/esp32c5/rtc_time.c | 3 +- components/esp_system/port/soc/esp32c5/clk.c | 228 ++++++++++-------- components/esp_system/port/soc/esp32c6/clk.c | 2 +- components/esp_system/port/soc/esp32c61/clk.c | 2 +- .../hal/esp32c5/include/hal/clk_gate_ll.h | 128 ++++++++++ .../hal/esp32c5/include/hal/clk_tree_ll.h | 11 +- .../hal/esp32c5/include/hal/lp_clkrst_ll.h | 55 +++++ .../hal/esp32c5/include/hal/lp_core_ll.h | 4 +- .../hal/esp32c5/include/hal/rtc_io_ll.h | 3 +- components/hal/esp32c5/include/hal/uart_ll.h | 4 +- .../esp32c5/include/hal/usb_serial_jtag_ll.h | 21 +- .../soc/esp32c5/include/soc/clk_tree_defs.h | 12 +- 14 files changed, 402 insertions(+), 110 deletions(-) create mode 100644 components/hal/esp32c5/include/hal/clk_gate_ll.h create mode 100644 components/hal/esp32c5/include/hal/lp_clkrst_ll.h diff --git a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c index f91284e682..195d31097c 100644 --- a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +11,7 @@ #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" static const char *TAG = "esp_clk_tree"; @@ -69,6 +70,38 @@ uint32_t *freq_value) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { - (void)clk_src; (void)enable; + PERIPH_RCC_ATOMIC() { + 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; + } + } return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32c5/io_mux.c b/components/esp_hw_support/port/esp32c5/io_mux.c index 90f5013dd0..e6e53ee3ba 100644 --- a/components/esp_hw_support/port/esp32c5/io_mux.c +++ b/components/esp_hw_support/port/esp32c5/io_mux.c @@ -6,6 +6,7 @@ #include "sdkconfig.h" #include "freertos/FreeRTOS.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_private/io_mux.h" #include "esp_private/periph_ctrl.h" #include "hal/gpio_ll.h" @@ -40,6 +41,7 @@ esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src) return ESP_ERR_INVALID_STATE; } + esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); gpio_ll_iomux_set_clk_src(clk_src); return ESP_OK; diff --git a/components/esp_hw_support/port/esp32c5/rtc_time.c b/components/esp_hw_support/port/esp32c5/rtc_time.c index cb1b4ee6be..b37055c2c6 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_time.c +++ b/components/esp_hw_support/port/esp32c5/rtc_time.c @@ -64,7 +64,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc rtc_dig_clk8m_enable(); } } - + clk_ll_enable_timergroup_rtc_calibration_clock(true); /* There may be another calibration process already running during we call this function, * so we should wait the last process is done. */ @@ -123,6 +123,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc } CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); + clk_ll_enable_timergroup_rtc_calibration_clock(false); /* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */ if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { clk_ll_xtal32k_digi_disable(); diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index 836286748c..0af7ecc3cc 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -27,6 +27,38 @@ #if SOC_MODEM_CLOCK_SUPPORTED #include "hal/modem_lpcon_ll.h" #endif +#include "hal/adc_ll.h" +#include "hal/aes_ll.h" +#include "hal/assist_debug_ll.h" +#include "hal/apm_ll.h" +#include "hal/clk_gate_ll.h" +#include "hal/clk_tree_ll.h" +#include "hal/ds_ll.h" +#include "hal/ecc_ll.h" +#include "hal/etm_ll.h" +#include "hal/gdma_ll.h" +#include "hal/hmac_ll.h" +#include "hal/i2c_ll.h" +#include "hal/i2s_ll.h" +#include "hal/ledc_ll.h" +#include "hal/lp_core_ll.h" +#include "hal/lp_clkrst_ll.h" +#include "hal/mcpwm_ll.h" +#include "hal/mpi_ll.h" +#include "hal/mspi_ll.h" +#include "hal/parlio_ll.h" +#include "hal/pau_ll.h" +#include "hal/pcnt_ll.h" +#include "hal/rmt_ll.h" +#include "hal/rtc_io_ll.h" +#include "hal/sha_ll.h" +#include "hal/spi_ll.h" +#include "hal/temperature_sensor_ll.h" +#include "hal/timer_ll.h" +#include "hal/twaifd_ll.h" +#include "hal/uart_ll.h" +#include "hal/uhci_ll.h" +#include "hal/usb_serial_jtag_ll.h" #include "esp_private/esp_sleep_internal.h" #include "esp_private/esp_modem_clock.h" #include "esp_private/periph_ctrl.h" @@ -200,23 +232,19 @@ void rtc_clk_select_rtc_slow_clk(void) */ __attribute__((weak)) void esp_perip_clk_init(void) { -// TODO: [ESP32C5] IDF-8844 -#if SOC_MODEM_CLOCK_SUPPORTED - // modem_clock_domain_pmu_state_icg_map_init(); /* During system initialization, the low-power clock source of the modem * (WiFi, BLE or Coexist) follows the configuration of the slow clock source * of the system. If the WiFi, BLE or Coexist module needs a higher * precision sleep clock (for example, the BLE needs to use the main XTAL * oscillator (40 MHz) to provide the clock during the sleep process in some * scenarios), the module needs to switch to the required clock source by - * itself. */ //TODO - WIFI-5233 + * itself. */ soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t)( (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? MODEM_CLOCK_LPCLK_SRC_XTAL32K : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K : MODEM_CLOCK_LPCLK_SRC_RC_SLOW); modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); -#endif /* On ESP32-C5 ECO1, clearing BIT(31) of PCR_FPGA_DEBUG_REG is used to fix * the issue where the modem module fails to transmit and receive packets @@ -225,102 +253,112 @@ __attribute__((weak)) void esp_perip_clk_init(void) * to IDF-11064. */ clk_ll_soc_root_clk_auto_gating_bypass(true); - ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet"); -#if 0 // TODO: [ESP32C5] IDF-8844 - uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; - uint32_t common_perip_clk1 = 0; - soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); - - /* For reason that only reset CPU, do not disable the clocks - * that have been enabled before reset. - */ - if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW || - rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) { - common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG); - hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG); - wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG); - } else { - common_perip_clk = SYSTEM_WDG_CLK_EN | - SYSTEM_I2S0_CLK_EN | + if ((rst_reason != RESET_REASON_CPU0_MWDT0) && (rst_reason != RESET_REASON_CPU0_MWDT1) \ + && (rst_reason != RESET_REASON_CPU0_SW) && (rst_reason != RESET_REASON_CPU0_RTC_WDT) \ + && (rst_reason != RESET_REASON_CPU0_JTAG) && (rst_reason != RESET_REASON_CPU0_LOCKUP)) { #if CONFIG_ESP_CONSOLE_UART_NUM != 0 - SYSTEM_UART_CLK_EN | + uart_ll_enable_bus_clock(UART_NUM_0, false); + uart_ll_sclk_disable(&UART0); +#elif CONFIG_ESP_CONSOLE_UART_NUM != 1 + uart_ll_sclk_disable(&UART1); + uart_ll_enable_bus_clock(UART_NUM_1, false); #endif -#if CONFIG_ESP_CONSOLE_UART_NUM != 1 - SYSTEM_UART1_CLK_EN | + i2c_ll_enable_bus_clock(0, false); + i2c_ll_enable_controller_clock(&I2C0, false); + rmt_ll_enable_bus_clock(0, false); + rmt_ll_enable_group_clock(0, false); + ledc_ll_enable_clock(&LEDC, false); + ledc_ll_enable_bus_clock(false); + clk_ll_enable_timergroup_rtc_calibration_clock(false); + timer_ll_enable_clock(0, 0, false); + timer_ll_enable_clock(1, 0, false); + _timer_ll_enable_bus_clock(0, false); + _timer_ll_enable_bus_clock(1, false); + twaifd_ll_enable_clock(0, false); + twaifd_ll_enable_bus_clock(0, false); + twaifd_ll_enable_clock(1, false); + twaifd_ll_enable_bus_clock(1, false); + i2s_ll_enable_bus_clock(0, false); + i2s_ll_tx_disable_clock(&I2S0); + i2s_ll_rx_disable_clock(&I2S0); + adc_ll_enable_bus_clock(false); + pcnt_ll_enable_bus_clock(0, false); + etm_ll_enable_bus_clock(0, false); + mcpwm_ll_enable_bus_clock(0, false); + mcpwm_ll_group_enable_clock(0, false); + parlio_ll_rx_enable_clock(&PARL_IO, false); + parlio_ll_tx_enable_clock(&PARL_IO, false); + parlio_ll_enable_bus_clock(0, false); + ahb_dma_ll_force_enable_reg_clock(&AHB_DMA, false); + _gdma_ll_enable_bus_clock(0, false); +#if CONFIG_APP_BUILD_TYPE_PURE_RAM_APP + mspi_timing_ll_enable_core_clock(0, false); #endif - SYSTEM_SPI2_CLK_EN | - SYSTEM_I2C_EXT0_CLK_EN | - SYSTEM_UHCI0_CLK_EN | - SYSTEM_RMT_CLK_EN | - SYSTEM_LEDC_CLK_EN | - SYSTEM_TIMERGROUP1_CLK_EN | - SYSTEM_SPI3_CLK_EN | - SYSTEM_SPI4_CLK_EN | - SYSTEM_TWAI_CLK_EN | - SYSTEM_I2S0_CLK_EN | - SYSTEM_SPI2_DMA_CLK_EN | - SYSTEM_SPI3_DMA_CLK_EN; + spi_ll_enable_bus_clock(SPI2_HOST, false); + temperature_sensor_ll_bus_clk_enable(false); + pau_ll_enable_bus_clock(false); +#if !CONFIG_ESP_SYSTEM_HW_PC_RECORD + /* Disable ASSIST Debug module clock if PC recoreding function is not used, + * if stack guard function needs it, it will be re-enabled at esp_hw_stack_guard_init */ + assist_debug_ll_enable_bus_clock(false); +#endif + mpi_ll_enable_bus_clock(false); + aes_ll_enable_bus_clock(false); + sha_ll_enable_bus_clock(false); + ecc_ll_enable_bus_clock(false); + hmac_ll_enable_bus_clock(false); + ds_ll_enable_bus_clock(false); + apm_tee_ll_clk_gating_enable(false); + uhci_ll_enable_bus_clock(0, false); - common_perip_clk1 = 0; - hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN | - SYSTEM_CRYPTO_SHA_CLK_EN | - SYSTEM_CRYPTO_RSA_CLK_EN; - wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN | - SYSTEM_WIFI_CLK_BT_EN_M | - SYSTEM_WIFI_CLK_UNUSED_BIT5 | - SYSTEM_WIFI_CLK_UNUSED_BIT12; + // TODO: Replace with hal implementation + REG_CLR_BIT(HP_APM_CLOCK_GATE_REG, HP_APM_CLK_EN); + REG_CLR_BIT(LP_TEE_CLOCK_GATE_REG, LP_TEE_CLK_EN); + REG_CLR_BIT(PCR_TRACE_CONF_REG, PCR_TRACE_CLK_EN); + REG_CLR_BIT(PCR_TCM_MEM_MONITOR_CONF_REG, PCR_TCM_MEM_MONITOR_CLK_EN); + REG_CLR_BIT(PCR_PSRAM_MEM_MONITOR_CONF_REG, PCR_PSRAM_MEM_MONITOR_CLK_EN); + REG_CLR_BIT(PCR_PVT_MONITOR_CONF_REG, PCR_PVT_MONITOR_CLK_EN); + REG_CLR_BIT(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_EN); + WRITE_PERI_REG(PCR_CTRL_CLK_OUT_EN_REG, 0); + +#if !CONFIG_USJ_ENABLE_USB_SERIAL_JTAG && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED + // Disable USB-Serial-JTAG clock and it's pad if not used + usb_serial_jtag_ll_phy_enable_pad(false); + usb_serial_jtag_ll_enable_bus_clock(false); + usb_serial_jtag_ll_enable_mem_clock(false); + usb_serial_jtag_ll_set_mem_pd(true); +#endif + + if (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL_F240M) { + _clk_gate_ll_ref_240m_clk_en(false); + } + if (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL_F160M) { + _clk_gate_ll_ref_160m_clk_en(false); + } + _clk_gate_ll_ref_120m_clk_en(false); + _clk_gate_ll_ref_80m_clk_en(false); + _clk_gate_ll_ref_60m_clk_en(false); + _clk_gate_ll_ref_40m_clk_en(false); + _clk_gate_ll_ref_20m_clk_en(false); + _clk_gate_ll_ref_12m_clk_en(false); } - //Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state. - common_perip_clk |= SYSTEM_I2S0_CLK_EN | -#if CONFIG_ESP_CONSOLE_UART_NUM != 0 - SYSTEM_UART_CLK_EN | -#endif -#if CONFIG_ESP_CONSOLE_UART_NUM != 1 - SYSTEM_UART1_CLK_EN | -#endif - SYSTEM_SPI2_CLK_EN | - SYSTEM_I2C_EXT0_CLK_EN | - SYSTEM_UHCI0_CLK_EN | - SYSTEM_RMT_CLK_EN | - SYSTEM_UHCI1_CLK_EN | - SYSTEM_SPI3_CLK_EN | - SYSTEM_SPI4_CLK_EN | - SYSTEM_I2C_EXT1_CLK_EN | - SYSTEM_I2S0_CLK_EN | - SYSTEM_SPI2_DMA_CLK_EN | - SYSTEM_SPI3_DMA_CLK_EN; - common_perip_clk1 = 0; + if ((rst_reason == RESET_REASON_CHIP_POWER_ON) || (rst_reason == RESET_REASON_CHIP_BROWN_OUT) \ + || (rst_reason == RESET_REASON_SYS_RTC_WDT) || (rst_reason == RESET_REASON_SYS_SUPER_WDT) \ + || (rst_reason == RESET_REASON_CORE_PWR_GLITCH)) { + _lp_i2c_ll_enable_bus_clock(0, false); + lp_uart_ll_sclk_disable(0); + _lp_uart_ll_enable_bus_clock(0, false); + _lp_core_ll_enable_bus_clock(false); + _rtcio_ll_enable_io_clock(false); + _lp_clkrst_ll_enable_rng_clock(false); + _lp_clkrst_ll_enable_otp_dbg_clock(false); + _lp_clkrst_ll_enable_lp_ana_i2c_clock(false); + _lp_clkrst_ll_enable_lp_ext_i2c_clock(false); - /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, - * the current is not reduced when disable I2S clock. - */ - // TOCK(check replacement) - // REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); - // REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); - - /* Disable some peripheral clocks. */ - CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk); - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk); - - CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1); - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, common_perip_clk1); - - /* Disable hardware crypto clocks. */ - CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk); - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk); - - /* Disable WiFi/BT/SDIO clocks. */ - CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); - SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN); - - /* Set WiFi light sleep clock source to RTC slow clock */ - REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0); - CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M); - SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW); - - /* Enable RNG clock. */ - periph_module_enable(PERIPH_RNG_MODULE); -#endif + REG_CLR_BIT(LP_APM_CLOCK_GATE_REG, LP_APM_CLK_EN); + REG_CLR_BIT(LP_APM0_CLOCK_GATE_REG, LP_APM0_CLK_EN); + WRITE_PERI_REG(LP_CLKRST_LP_CLK_PO_EN_REG, 0); + } } diff --git a/components/esp_system/port/soc/esp32c6/clk.c b/components/esp_system/port/soc/esp32c6/clk.c index 1c2997c419..121621c577 100644 --- a/components/esp_system/port/soc/esp32c6/clk.c +++ b/components/esp_system/port/soc/esp32c6/clk.c @@ -224,7 +224,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) * precision sleep clock (for example, the BLE needs to use the main XTAL * oscillator (40 MHz) to provide the clock during the sleep process in some * scenarios), the module needs to switch to the required clock source by - * itself. */ //TODO - WIFI-5233 + * itself. */ soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t)(\ (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_RC_SLOW \ diff --git a/components/esp_system/port/soc/esp32c61/clk.c b/components/esp_system/port/soc/esp32c61/clk.c index 0e51476772..00942220af 100644 --- a/components/esp_system/port/soc/esp32c61/clk.c +++ b/components/esp_system/port/soc/esp32c61/clk.c @@ -188,7 +188,7 @@ __attribute__((weak)) void esp_perip_clk_init(void) * precision sleep clock (for example, the BLE needs to use the main XTAL * oscillator (40 MHz) to provide the clock during the sleep process in some * scenarios), the module needs to switch to the required clock source by - * itself. */ //TODO - WIFI-5233 + * itself. */ soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t)( (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_RC_SLOW diff --git a/components/hal/esp32c5/include/hal/clk_gate_ll.h b/components/hal/esp32c5/include/hal/clk_gate_ll.h new file mode 100644 index 0000000000..4a1d7d2ac6 --- /dev/null +++ b/components/hal/esp32c5/include/hal/clk_gate_ll.h @@ -0,0 +1,128 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "esp_attr.h" +#include "soc/pcr_struct.h" + +/** + * Enable or disable the clock gate for ref_12m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_12m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_12m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_12m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_12m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_20m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_20m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_20m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_20m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_20m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_40m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_40m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_40m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_40m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_40m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_48m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_48m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_48m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_48m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_48m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_60m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_60m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_60m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_60m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_60m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_80m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_80m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_80m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_80m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_80m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_120m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_120m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_120m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_120m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_120m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_160m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_160m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_160m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_160m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_160m_clk_en(__VA_ARGS__) + +/** + * Enable or disable the clock gate for ref_240m. + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_ref_240m_clk_en(bool enable) +{ + PCR.pll_div_clk_en.pll_240m_clk_en = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_ref_240m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_240m_clk_en(__VA_ARGS__) + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c5/include/hal/clk_tree_ll.h b/components/hal/esp32c5/include/hal/clk_tree_ll.h index 67c695401e..00c1057955 100644 --- a/components/hal/esp32c5/include/hal/clk_tree_ll.h +++ b/components/hal/esp32c5/include/hal/clk_tree_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -568,6 +568,15 @@ static inline __attribute__((always_inline)) void clk_ll_rc_slow_set_divider(uin HAL_ASSERT(divider == 1); } +/** + * @brief Enable the RTC clock calibration reference XTAL source on timer group0. + * @param enable enable or disable the XTAL source. + */ +static inline __attribute__((always_inline)) void clk_ll_enable_timergroup_rtc_calibration_clock(bool enable) +{ + PCR.timergroup_xtal_conf.tg0_xtal_clk_en = enable; +} + /************************** LP STORAGE REGISTER STORE/LOAD **************************/ /** * @brief Store RTC_SLOW_CLK calibration value in RTC storage register diff --git a/components/hal/esp32c5/include/hal/lp_clkrst_ll.h b/components/hal/esp32c5/include/hal/lp_clkrst_ll.h new file mode 100644 index 0000000000..e2d215ee45 --- /dev/null +++ b/components/hal/esp32c5/include/hal/lp_clkrst_ll.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-C5 LP_CLKRST & LP PERI register operations + +#pragma once + +#include +#include +#include "soc/soc.h" +#include "soc/lp_clkrst_struct.h" +#include "soc/lpperi_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((always_inline)) +static inline void _lp_clkrst_ll_enable_rng_clock(bool en) +{ + LPPERI.clk_en.rng_ck_en = en; +} +/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way +#define lp_clkrst_ll_enable_rng_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _lp_clkrst_ll_enable_rng_clock(__VA_ARGS__) + +__attribute__((always_inline)) +static inline void _lp_clkrst_ll_enable_otp_dbg_clock(bool en) +{ + LPPERI.clk_en.otp_dbg_ck_en = en; +} +/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way +#define lp_clkrst_ll_enable_otp_dbg_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _lp_clkrst_ll_enable_otp_dbg_clock(__VA_ARGS__) + +__attribute__((always_inline)) +static inline void _lp_clkrst_ll_enable_lp_ana_i2c_clock(bool en) +{ + LPPERI.clk_en.lp_ana_i2c_ck_en = en; +} +/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way +#define lp_clkrst_ll_enable_lp_ana_i2c_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _lp_clkrst_ll_enable_lp_ana_i2c_clock(__VA_ARGS__) + +__attribute__((always_inline)) +static inline void _lp_clkrst_ll_enable_lp_ext_i2c_clock(bool en) +{ + LPPERI.clk_en.lp_ext_i2c_ck_en = en; +} +/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way +#define lp_clkrst_ll_enable_lp_ext_i2c_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; _lp_clkrst_ll_enable_lp_ext_i2c_clock(__VA_ARGS__) + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c5/include/hal/lp_core_ll.h b/components/hal/esp32c5/include/hal/lp_core_ll.h index f73950ed8e..baecfb1f1e 100644 --- a/components/hal/esp32c5/include/hal/lp_core_ll.h +++ b/components/hal/esp32c5/include/hal/lp_core_ll.h @@ -32,7 +32,7 @@ extern "C" { * * @param enable true to enable, false to disable */ -static inline void lp_core_ll_enable_bus_clock(bool enable) +static inline void _lp_core_ll_enable_bus_clock(bool enable) { LPPERI.clk_en.lp_cpu_ck_en = enable; } @@ -41,7 +41,7 @@ static inline void lp_core_ll_enable_bus_clock(bool enable) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define lp_core_ll_enable_bus_clock(...) do { \ (void)__DECLARE_RCC_ATOMIC_ENV; \ - lp_core_ll_enable_bus_clock(__VA_ARGS__); \ + _lp_core_ll_enable_bus_clock(__VA_ARGS__); \ } while(0) /** diff --git a/components/hal/esp32c5/include/hal/rtc_io_ll.h b/components/hal/esp32c5/include/hal/rtc_io_ll.h index be9daf5c5c..04e2afd905 100644 --- a/components/hal/esp32c5/include/hal/rtc_io_ll.h +++ b/components/hal/esp32c5/include/hal/rtc_io_ll.h @@ -60,7 +60,8 @@ static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) static inline void _rtcio_ll_enable_io_clock(bool enable) { LPPERI.clk_en.lp_io_ck_en = enable; - while (LPPERI.clk_en.lp_io_ck_en != enable) { + LP_GPIO.clock_gate.clk_en = enable; + while ((LPPERI.clk_en.lp_io_ck_en != enable) || (LP_GPIO.clock_gate.clk_en != enable)) { ; } } diff --git a/components/hal/esp32c5/include/hal/uart_ll.h b/components/hal/esp32c5/include/hal/uart_ll.h index f4050db9cc..17f8a3b0e1 100644 --- a/components/hal/esp32c5/include/hal/uart_ll.h +++ b/components/hal/esp32c5/include/hal/uart_ll.h @@ -188,7 +188,7 @@ FORCE_INLINE_ATTR bool lp_uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, ui * @param hw_id LP UART instance ID * @param enable True to enable, False to disable */ -static inline void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) +static inline void _lp_uart_ll_enable_bus_clock(int hw_id, bool enable) { (void)hw_id; LPPERI.clk_en.lp_uart_ck_en = enable; @@ -197,7 +197,7 @@ static inline void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) /// LPPERI.clk_en is a shared register, so this function must be used in an atomic way #define lp_uart_ll_enable_bus_clock(...) do { \ (void)__DECLARE_RCC_ATOMIC_ENV; \ - lp_uart_ll_enable_bus_clock(__VA_ARGS__); \ + _lp_uart_ll_enable_bus_clock(__VA_ARGS__); \ } while(0) /** diff --git a/components/hal/esp32c5/include/hal/usb_serial_jtag_ll.h b/components/hal/esp32c5/include/hal/usb_serial_jtag_ll.h index 6cff591138..1850a92182 100644 --- a/components/hal/esp32c5/include/hal/usb_serial_jtag_ll.h +++ b/components/hal/esp32c5/include/hal/usb_serial_jtag_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -329,6 +329,25 @@ FORCE_INLINE_ATTR bool usb_serial_jtag_ll_module_is_enabled(void) return (PCR.usb_device_conf.usb_device_clk_en && !PCR.usb_device_conf.usb_device_rst_en); } +/* ---------------------------- USB MEM Control ---------------------------- */ +/** + * @brief Power down the power USJ mem. + * @param clk_en True if power down the USJ mem. + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_set_mem_pd(bool pd) +{ + USB_SERIAL_JTAG.mem_conf.usb_mem_pd = pd; +} + +/** + * @brief Enable the mem clock for USJ module + * @param clk_en True if enable the clock of USJ module mem. + */ +FORCE_INLINE_ATTR void usb_serial_jtag_ll_enable_mem_clock(bool clk_en) +{ + USB_SERIAL_JTAG.mem_conf.usb_mem_clk_en = clk_en; +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c5/include/soc/clk_tree_defs.h b/components/soc/esp32c5/include/soc/clk_tree_defs.h index 04341d8d63..d7618a9153 100644 --- a/components/soc/esp32c5/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c5/include/soc/clk_tree_defs.h @@ -124,9 +124,15 @@ typedef enum { SOC_MOD_CLK_RTC_FAST, /*!< RTC_FAST_CLK can be sourced from XTAL_D2 or RC_FAST by configuring soc_rtc_fast_clk_src_t */ SOC_MOD_CLK_RTC_SLOW, /*!< RTC_SLOW_CLK can be sourced from RC_SLOW, XTAL32K, or OSC_SLOW by configuring soc_rtc_slow_clk_src_t */ // For digital domain: peripherals, WIFI, BLE - SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from PLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */ - SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from PLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */ - SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from PLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */ + SOC_MOD_CLK_PLL_F12M, /*!< PLL_F12M_CLK is derived from SPLL (clock gating + fixed divider of 40), it has a fixed frequency of 12MHz */ + SOC_MOD_CLK_PLL_F20M, /*!< PLL_F20M_CLK is derived from SPLL (clock gating + fixed divider of 24), it has a fixed frequency of 20MHz */ + SOC_MOD_CLK_PLL_F40M, /*!< PLL_F40M_CLK is derived from SPLL (clock gating + fixed divider of 12), it has a fixed frequency of 40MHz */ + SOC_MOD_CLK_PLL_F48M, /*!< PLL_F48M_CLK is derived from SPLL (clock gating + fixed divider of 10), it has a fixed frequency of 48MHz */ + SOC_MOD_CLK_PLL_F60M, /*!< PLL_F60M_CLK is derived from SPLL (clock gating + fixed divider of 8), it has a fixed frequency of 60MHz */ + SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */ + SOC_MOD_CLK_PLL_F120M, /*!< PLL_F120M_CLK is derived from SPLL (clock gating + fixed divider of 4), it has a fixed frequency of 120MHz */ + SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */ + SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */ SOC_MOD_CLK_SPLL, /*!< SPLL is from the main XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */ SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ From 113f40a3e02c78260eab76bec1a65edcd9c06d21 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 15 Jan 2025 21:41:34 +0800 Subject: [PATCH 2/3] feat(esp_hw_support): support gate PLL div clock source by reference count --- .../include/esp_private/esp_clk_tree_common.h | 10 ++ .../include/esp_private/regi2c_ctrl.h | 23 ++++- components/esp_hw_support/linker.lf | 1 + components/esp_hw_support/modem_clock.c | 9 +- .../port/esp32c5/esp_clk_tree.c | 93 +++++++++++++------ .../esp_hw_support/port/esp32c5/rtc_clk.c | 54 +++++++---- .../port/esp32h21/esp_clk_tree.c | 2 +- components/esp_system/port/cpu_start.c | 3 + components/esp_system/port/soc/esp32c5/clk.c | 15 +-- .../esp32c5/include/soc/Kconfig.soc_caps.in | 8 ++ .../soc/esp32c5/include/soc/clk_tree_defs.h | 2 +- components/soc/esp32c5/include/soc/soc_caps.h | 3 + 12 files changed, 154 insertions(+), 69 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h b/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h index 4a3c895b4f..7b57285062 100644 --- a/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h +++ b/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h @@ -78,6 +78,9 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec /** * @brief Enable / Disable the clock gate of the clock source * + * @note The clock enable status is maintained by reference counter and + * its status is not reset after software restart. + * * @param[in] clk_src Clock source available to modules, in soc_module_clk_t * @param[in] enable Enable / Disable the clock gate * @@ -92,6 +95,13 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec */ esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable); +#if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED +/** + * @brief Set the clock source not in use on the clock tree to the gated state. + */ +void esp_clk_tree_initialize(void); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h index c8f95ce881..b35d356b59 100644 --- a/components/esp_hw_support/include/esp_private/regi2c_ctrl.h +++ b/components/esp_hw_support/include/esp_private/regi2c_ctrl.h @@ -7,12 +7,17 @@ #pragma once #include +#include #include "sdkconfig.h" #include "esp_rom_regi2c.h" #include "soc/soc_caps.h" #include "esp_private/periph_ctrl.h" #include "hal/regi2c_ctrl_ll.h" +#ifndef BOOTLOADER_BUILD +#include "esp_private/esp_clk_tree_common.h" +#endif + #ifdef __cplusplus extern "C" { #endif @@ -25,22 +30,32 @@ extern "C" { #else // !BOOTLOADER_BUILD +static inline __attribute__((always_inline)) void ANA_I2C_SRC_CLOCK_ENABLE(bool enable) { +#if SOC_CLK_ANA_I2C_MST_DEPENDS_ON_MODEM_APB + esp_clk_tree_enable_src(SOC_MOD_CLK_MODEM_APB, enable); +#endif +} + #if ANA_I2C_MST_CLK_HAS_ROOT_GATING // This clock needs to be enabled for regi2c write/read, pll calibaration, PHY, RNG, ADC, etc. // Use reference count to manage the analog i2c master clock -#define ANALOG_CLOCK_ENABLE() \ +#define ANALOG_CLOCK_ENABLE() { \ + ANA_I2C_SRC_CLOCK_ENABLE(true); \ PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_ANA_I2C_MASTER_MODULE, ref_count) { \ if (ref_count == 0) { \ regi2c_ctrl_ll_master_enable_clock(true); \ } \ - } + } \ + } -#define ANALOG_CLOCK_DISABLE() \ +#define ANALOG_CLOCK_DISABLE() { \ PERIPH_RCC_RELEASE_ATOMIC(PERIPH_ANA_I2C_MASTER_MODULE, ref_count) { \ if (ref_count == 0) { \ regi2c_ctrl_ll_master_enable_clock(false); \ } \ - } + } \ + ANA_I2C_SRC_CLOCK_ENABLE(false); \ + } #else #define ANALOG_CLOCK_ENABLE() diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 9218409e71..1ee15d6e2f 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -16,6 +16,7 @@ entries: if PM_SLP_IRAM_OPT = y: rtc_clk (noflash) rtc_time (noflash_text) + esp_clk_tree: esp_clk_tree_enable_src (noflash) if IDF_TARGET_ESP32 = y: rtc_clk:rtc_clk_cpu_freq_to_pll_mhz (noflash) rtc_clk:rtc_clk_cpu_freq_to_xtal (noflash) diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 043d5fd544..8e98b61f37 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -141,7 +141,7 @@ static void IRAM_ATTR modem_clock_data_dump_configure(modem_clock_context_t *ctx modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(void) { /* It should be explicitly defined in the internal RAM */ - static DRAM_ATTR modem_clock_hal_context_t modem_clock_hal = { .syscon_dev = &MODEM_SYSCON, .lpcon_dev = &MODEM_LPCON }; + static DRAM_ATTR modem_clock_hal_context_t modem_clock_hal = { .syscon_dev = NULL, .lpcon_dev = NULL }; static DRAM_ATTR modem_clock_context_t modem_clock_context = { .hal = &modem_clock_hal, .lock = portMUX_INITIALIZER_UNLOCKED, .dev = { @@ -167,6 +167,13 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi }, .lpclk_src = { [0 ... PERIPH_MODEM_MODULE_NUM - 1] = MODEM_CLOCK_LPCLK_SRC_INVALID } }; + if (modem_clock_hal.syscon_dev == NULL || modem_clock_hal.lpcon_dev == NULL) { + modem_clock_hal.syscon_dev = &MODEM_SYSCON; + modem_clock_hal.lpcon_dev = &MODEM_LPCON; +#if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED + esp_clk_tree_enable_src(SOC_MOD_CLK_MODEM_APB, true); +#endif + } return &modem_clock_context; } diff --git a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c index 195d31097c..a84919e032 100644 --- a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c @@ -5,6 +5,7 @@ */ #include +#include "sdkconfig.h" #include "esp_clk_tree.h" #include "esp_err.h" #include "esp_check.h" @@ -68,40 +69,72 @@ uint32_t *freq_value) return ESP_OK; } +#define ENUM2ARRAY(clk_src) (clk_src - SOC_MOD_CLK_PLL_F12M) +static __NOINIT_ATTR int16_t s_pll_src_cg_ref_cnt[9] = { 0 }; +static bool esp_clk_tree_initialized = false; + +void esp_clk_tree_initialize(void) +{ + soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); + if ((rst_reason == RESET_REASON_CPU0_MWDT0) || (rst_reason == RESET_REASON_CPU0_MWDT1) \ + || (rst_reason == RESET_REASON_CPU0_SW) || (rst_reason == RESET_REASON_CPU0_RTC_WDT) \ + || (rst_reason == RESET_REASON_CPU0_JTAG) || (rst_reason == RESET_REASON_CPU0_LOCKUP)) { + esp_clk_tree_initialized = true; + return; + } else { + bzero(s_pll_src_cg_ref_cnt, sizeof(s_pll_src_cg_ref_cnt)); + } + + 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; + _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; + _clk_gate_ll_ref_160m_clk_en(false); + } + _clk_gate_ll_ref_120m_clk_en(false); + _clk_gate_ll_ref_80m_clk_en(false); + _clk_gate_ll_ref_60m_clk_en(false); +#if !CONFIG_USJ_ENABLE_USB_SERIAL_JTAG && !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED + _clk_gate_ll_ref_48m_clk_en(false); +#endif + _clk_gate_ll_ref_40m_clk_en(false); + _clk_gate_ll_ref_20m_clk_en(false); + _clk_gate_ll_ref_12m_clk_en(false); + esp_clk_tree_initialized = true; +} + 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)) { + return ESP_OK; + } + PERIPH_RCC_ATOMIC() { - 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)] == 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)]--; + } + assert(s_pll_src_cg_ref_cnt[ENUM2ARRAY(clk_src)] >= 0); } return ESP_OK; } +#undef ENUM2ARRAY diff --git a/components/esp_hw_support/port/esp32c5/rtc_clk.c b/components/esp_hw_support/port/esp32c5/rtc_clk.c index b585c29867..55d5e2e62c 100644 --- a/components/esp_hw_support/port/esp32c5/rtc_clk.c +++ b/components/esp_hw_support/port/esp32c5/rtc_clk.c @@ -286,37 +286,53 @@ __attribute__((weak)) void rtc_clk_set_cpu_switch_to_pll(int event_id) { } -void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) +static void rtc_clk_update_pll_state_on_cpu_src_switching_start(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src) { - soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); - if (config->source == SOC_CPU_CLK_SRC_XTAL) { - rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); - if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) { + if ((new_src == SOC_CPU_CLK_SRC_PLL_F160M) || (new_src == SOC_CPU_CLK_SRC_PLL_F240M)) { + if (s_cur_pll_freq != CLK_LL_PLL_480M_FREQ_MHZ) { + rtc_clk_bbpll_enable(); + rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ); + } +#ifndef BOOTLOADER_BUILD + esp_clk_tree_enable_src((new_src == SOC_CPU_CLK_SRC_PLL_F240M) ? SOC_MOD_CLK_PLL_F240M : SOC_MOD_CLK_PLL_F160M, true); +#endif + } +} + +static void rtc_clk_update_pll_state_on_cpu_switching_end(soc_cpu_clk_src_t old_src, soc_cpu_clk_src_t new_src) +{ + if ((old_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_src == SOC_CPU_CLK_SRC_PLL_F240M)) { +#ifndef BOOTLOADER_BUILD + esp_clk_tree_enable_src((old_src == SOC_CPU_CLK_SRC_PLL_F240M) ? SOC_MOD_CLK_PLL_F240M : SOC_MOD_CLK_PLL_F160M, false); +#endif + if ((new_src != SOC_CPU_CLK_SRC_PLL_F160M) && (new_src != SOC_CPU_CLK_SRC_PLL_F240M) && !s_bbpll_digi_consumers_ref_count) { // We don't turn off the bbpll if some consumers depend on bbpll rtc_clk_bbpll_disable(); } + } +} + +void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) +{ + soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); + if (old_cpu_clk_src != config->source) { + rtc_clk_update_pll_state_on_cpu_src_switching_start(old_cpu_clk_src, config->source); + } + if (config->source == SOC_CPU_CLK_SRC_XTAL) { + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); } else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M) { - if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) { - rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START); - rtc_clk_bbpll_enable(); - rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ); - } + rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START); rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz); rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP); } else if (config->source == SOC_CPU_CLK_SRC_PLL_F160M) { - if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) { - rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START); - rtc_clk_bbpll_enable(); - rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ); - } + rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START); rtc_clk_cpu_freq_to_pll_160_mhz(config->freq_mhz); rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP); } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { rtc_clk_cpu_freq_to_8m(); - if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) { - // We don't turn off the bbpll if some consumers depend on bbpll - rtc_clk_bbpll_disable(); - } + } + if (old_cpu_clk_src != config->source) { + rtc_clk_update_pll_state_on_cpu_switching_end(old_cpu_clk_src, config->source); } } diff --git a/components/esp_hw_support/port/esp32h21/esp_clk_tree.c b/components/esp_hw_support/port/esp32h21/esp_clk_tree.c index a0c3e5a07d..f2b4c71017 100644 --- a/components/esp_hw_support/port/esp32h21/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32h21/esp_clk_tree.c @@ -54,5 +54,5 @@ uint32_t *freq_value) esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { (void)clk_src; (void)enable; - return ESP_ERR_NOT_SUPPORTED; + return ESP_OK; } diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 5af3d7bbbc..d37e809fd3 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -707,6 +707,9 @@ void IRAM_ATTR call_start_cpu0(void) trax_start_trace(TRAX_DOWNCOUNT_WORDS); #endif // CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX || CONFIG_ESP32S3_TRAX +#if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED + esp_clk_tree_initialize(); +#endif esp_clk_init(); esp_perip_clk_init(); diff --git a/components/esp_system/port/soc/esp32c5/clk.c b/components/esp_system/port/soc/esp32c5/clk.c index 0af7ecc3cc..294f485998 100644 --- a/components/esp_system/port/soc/esp32c5/clk.c +++ b/components/esp_system/port/soc/esp32c5/clk.c @@ -239,12 +239,14 @@ __attribute__((weak)) void esp_perip_clk_init(void) * oscillator (40 MHz) to provide the clock during the sleep process in some * scenarios), the module needs to switch to the required clock source by * itself. */ +#if CONFIG_ESP_WIFI_ENABLED soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get(); modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t)( (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? MODEM_CLOCK_LPCLK_SRC_XTAL32K : (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K : MODEM_CLOCK_LPCLK_SRC_RC_SLOW); modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0); +#endif /* On ESP32-C5 ECO1, clearing BIT(31) of PCR_FPGA_DEBUG_REG is used to fix * the issue where the modem module fails to transmit and receive packets @@ -329,19 +331,6 @@ __attribute__((weak)) void esp_perip_clk_init(void) usb_serial_jtag_ll_enable_mem_clock(false); usb_serial_jtag_ll_set_mem_pd(true); #endif - - if (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL_F240M) { - _clk_gate_ll_ref_240m_clk_en(false); - } - if (clk_ll_cpu_get_src() != SOC_CPU_CLK_SRC_PLL_F160M) { - _clk_gate_ll_ref_160m_clk_en(false); - } - _clk_gate_ll_ref_120m_clk_en(false); - _clk_gate_ll_ref_80m_clk_en(false); - _clk_gate_ll_ref_60m_clk_en(false); - _clk_gate_ll_ref_40m_clk_en(false); - _clk_gate_ll_ref_20m_clk_en(false); - _clk_gate_ll_ref_12m_clk_en(false); } if ((rst_reason == RESET_REASON_CHIP_POWER_ON) || (rst_reason == RESET_REASON_CHIP_BROWN_OUT) \ diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index ffacb5385f..3f84165796 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -255,6 +255,10 @@ config SOC_PM_SUPPORTED bool default y +config SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED + bool + default y + config SOC_SPIRAM_SUPPORTED bool default y @@ -1671,6 +1675,10 @@ config SOC_RCC_IS_INDEPENDENT bool default y +config SOC_CLK_ANA_I2C_MST_DEPENDS_ON_MODEM_APB + bool + default y + config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC bool default y diff --git a/components/soc/esp32c5/include/soc/clk_tree_defs.h b/components/soc/esp32c5/include/soc/clk_tree_defs.h index d7618a9153..43226a472d 100644 --- a/components/soc/esp32c5/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c5/include/soc/clk_tree_defs.h @@ -132,6 +132,7 @@ typedef enum { SOC_MOD_CLK_PLL_F80M, /*!< PLL_F80M_CLK is derived from SPLL (clock gating + fixed divider of 6), it has a fixed frequency of 80MHz */ SOC_MOD_CLK_PLL_F120M, /*!< PLL_F120M_CLK is derived from SPLL (clock gating + fixed divider of 4), it has a fixed frequency of 120MHz */ SOC_MOD_CLK_PLL_F160M, /*!< PLL_F160M_CLK is derived from SPLL (clock gating + fixed divider of 3), it has a fixed frequency of 160MHz */ + SOC_MOD_CLK_MODEM_APB = SOC_MOD_CLK_PLL_F160M, /*!< Modem APB clock comes from the CLK_160M_REF */ SOC_MOD_CLK_PLL_F240M, /*!< PLL_F240M_CLK is derived from SPLL (clock gating + fixed divider of 2), it has a fixed frequency of 240MHz */ SOC_MOD_CLK_SPLL, /*!< SPLL is from the main XTAL oscillator frequency multipliers, it has a "fixed" frequency of 480MHz */ SOC_MOD_CLK_XTAL32K, /*!< XTAL32K_CLK comes from the external 32kHz crystal, passing a clock gating to the peripherals */ @@ -139,7 +140,6 @@ typedef enum { SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 48MHz crystal */ // For LP peripherals SOC_MOD_CLK_XTAL_D2, /*!< XTAL_D2_CLK comes from the external 48MHz crystal, passing a div of 2 to the LP peripherals */ - SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ } soc_module_clk_t; diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 1b59fb4924..9729736553 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -82,6 +82,7 @@ #define SOC_LIGHT_SLEEP_SUPPORTED 1 #define SOC_DEEP_SLEEP_SUPPORTED 1 #define SOC_PM_SUPPORTED 1 +#define SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 @@ -658,6 +659,8 @@ #define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */ +#define SOC_CLK_ANA_I2C_MST_DEPENDS_ON_MODEM_APB (1) /*!< Analog I2C master clock depends on CLK_160M_REF on clock tree */ + /*-------------------------- Temperature Sensor CAPS -------------------------------------*/ #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC (1) #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL (1) From 65b7e70564d4b4ad9d82b26934816d95247e1cb1 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Mon, 20 Jan 2025 15:45:38 +0800 Subject: [PATCH 3/3] feat(driver): support acquire/release clock source dependency for all drivers --- components/driver/deprecated/adc_dma_legacy.c | 3 +- components/driver/deprecated/adc_legacy.c | 6 +- components/driver/deprecated/mcpwm_legacy.c | 7 +- components/driver/deprecated/rmt_legacy.c | 4 +- components/driver/deprecated/timer_legacy.c | 3 +- components/esp_adc/adc_continuous.c | 9 +- components/esp_adc/adc_oneshot.c | 19 ++-- .../esp_driver_cam/csi/src/esp_cam_ctlr_csi.c | 2 +- .../dvp/src/esp_cam_ctlr_dvp_cam.c | 2 +- components/esp_driver_gptimer/src/gptimer.c | 4 + .../esp_driver_gptimer/src/gptimer_common.c | 3 +- .../esp_driver_gptimer/src/gptimer_priv.h | 1 + .../include/esp_private/isp_private.h | 1 + components/esp_driver_isp/src/isp_core.c | 6 +- components/esp_driver_ledc/src/ledc.c | 4 +- .../test_apps/ledc/main/test_ledc.c | 2 +- components/esp_driver_mcpwm/src/mcpwm_com.c | 2 +- components/esp_driver_parlio/src/parlio_rx.c | 7 +- components/esp_driver_parlio/src/parlio_tx.c | 8 +- components/esp_driver_rmt/src/rmt_common.c | 2 +- .../esp_driver_sdmmc/src/sd_host_sdmmc.c | 2 +- .../esp_driver_spi/src/gpspi/spi_master.c | 4 +- components/esp_driver_twai/esp_twai_onchip.c | 2 + components/esp_driver_uart/src/uart.c | 102 ++++++++++-------- components/esp_eth/src/mac/esp_eth_mac_esp.c | 2 +- .../include/esp_private/esp_clk_tree_common.h | 7 +- components/esp_hw_support/modem_clock.c | 2 +- .../esp_hw_support/port/esp32c5/io_mux.c | 2 +- .../port/esp32p4/esp_clk_tree.c | 7 +- .../esp_hw_support/port/esp32p4/io_mux.c | 2 +- components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c | 2 +- components/esp_lcd/dsi/esp_lcd_panel_dpi.c | 2 +- components/esp_lcd/i80/esp_lcd_panel_io_i80.c | 2 +- components/esp_lcd/rgb/esp_lcd_panel_rgb.c | 2 +- components/esp_pm/pm_impl.c | 2 +- 35 files changed, 135 insertions(+), 102 deletions(-) diff --git a/components/driver/deprecated/adc_dma_legacy.c b/components/driver/deprecated/adc_dma_legacy.c index 9c7800e0fc..5e135ca53d 100644 --- a/components/driver/deprecated/adc_dma_legacy.c +++ b/components/driver/deprecated/adc_dma_legacy.c @@ -480,7 +480,7 @@ esp_err_t adc_digi_start(void) adc_hal_digi_init(&s_adc_digi_ctx->hal); #if !CONFIG_IDF_TARGET_ESP32 - esp_clk_tree_enable_src((soc_module_clk_t)(s_adc_digi_ctx->hal_digi_ctrlr_cfg.clk_src), true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(s_adc_digi_ctx->hal_digi_ctrlr_cfg.clk_src), true)); #endif adc_hal_digi_controller_config(&s_adc_digi_ctx->hal, &s_adc_digi_ctx->hal_digi_ctrlr_cfg); @@ -524,6 +524,7 @@ esp_err_t adc_digi_stop(void) if (s_adc_digi_ctx->use_adc1) { adc_lock_release(ADC_UNIT_1); } + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(s_adc_digi_ctx->hal_digi_ctrlr_cfg.clk_src), false)); sar_periph_ctrl_adc_continuous_power_release(); return ESP_OK; diff --git a/components/driver/deprecated/adc_legacy.c b/components/driver/deprecated/adc_legacy.c index 2cbbcf083b..e331e0c30e 100644 --- a/components/driver/deprecated/adc_legacy.c +++ b/components/driver/deprecated/adc_legacy.c @@ -756,7 +756,7 @@ int adc1_get_raw(adc1_channel_t channel) adc_apb_periph_claim(); sar_periph_ctrl_adc_oneshot_power_acquire(); - esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, true)); adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT); adc_atten_t atten = s_atten1_single[channel]; @@ -775,6 +775,7 @@ int adc1_get_raw(adc1_channel_t channel) adc_hal_convert(ADC_UNIT_1, channel, clk_src_freq_hz, &raw_out); ADC_REG_LOCK_EXIT(); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, false)); sar_periph_ctrl_adc_oneshot_power_release(); adc_apb_periph_free(); adc_lock_release(ADC_UNIT_1); @@ -820,7 +821,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * adc_apb_periph_claim(); sar_periph_ctrl_adc_oneshot_power_acquire(); - esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, true)); adc_ll_digi_clk_sel(ADC_DIGI_CLK_SRC_DEFAULT); #if SOC_ADC_ARBITER_SUPPORTED @@ -838,6 +839,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int * ret = adc_hal_convert(ADC_UNIT_2, channel, clk_src_freq_hz, raw_out); ADC_REG_LOCK_EXIT(); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)ADC_DIGI_CLK_SRC_DEFAULT, false)); sar_periph_ctrl_adc_oneshot_power_release(); adc_apb_periph_free(); adc_lock_release(ADC_UNIT_2); diff --git a/components/driver/deprecated/mcpwm_legacy.c b/components/driver/deprecated/mcpwm_legacy.c index 94723decdd..9be6b29518 100644 --- a/components/driver/deprecated/mcpwm_legacy.c +++ b/components/driver/deprecated/mcpwm_legacy.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -470,7 +470,7 @@ esp_err_t mcpwm_init(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, const mcpw uint32_t group_pre_scale = clk_src_hz / group_resolution; uint32_t timer_pre_scale = group_resolution / timer_resolution; - esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true)); MCPWM_CLOCK_SRC_ATOMIC() { mcpwm_ll_group_set_clock_source(mcpwm_num, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT); mcpwm_ll_group_set_clock_prescale(mcpwm_num, group_pre_scale); @@ -868,7 +868,7 @@ esp_err_t mcpwm_capture_enable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_cha uint32_t group_resolution = mcpwm_group_get_resolution(mcpwm_num); uint32_t group_pre_scale = clk_src_hz / group_resolution; - esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, true)); MCPWM_CLOCK_SRC_ATOMIC() { mcpwm_ll_group_set_clock_source(mcpwm_num, (soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT); mcpwm_ll_group_set_clock_prescale(mcpwm_num, group_pre_scale); @@ -910,6 +910,7 @@ esp_err_t mcpwm_capture_disable_channel(mcpwm_unit_t mcpwm_num, mcpwm_capture_ch mcpwm_ll_capture_enable_channel(hal->dev, cap_channel, false); mcpwm_ll_intr_enable(hal->dev, MCPWM_LL_EVENT_CAPTURE(cap_channel), false); mcpwm_critical_exit(mcpwm_num); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)MCPWM_CAPTURE_CLK_SRC_DEFAULT, false)); mcpwm_mutex_lock(mcpwm_num); context[mcpwm_num].cap_isr_func[cap_channel].fn = NULL; diff --git a/components/driver/deprecated/rmt_legacy.c b/components/driver/deprecated/rmt_legacy.c index baff30aa46..254aa46c06 100644 --- a/components/driver/deprecated/rmt_legacy.c +++ b/components/driver/deprecated/rmt_legacy.c @@ -440,7 +440,7 @@ esp_err_t rmt_set_source_clk(rmt_channel_t channel, rmt_source_clk_t base_clk) { ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR); RMT_ENTER_CRITICAL(); - esp_clk_tree_enable_src((soc_module_clk_t)base_clk, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)base_clk, true)); // `rmt_clock_source_t` and `rmt_source_clk_t` are binary compatible, as the underlying enum entries come from the same `soc_module_clk_t` RMT_CLOCK_SRC_ATOMIC() { rmt_ll_set_group_clock_src(rmt_contex.hal.regs, channel, (rmt_clock_source_t)base_clk, 1, 0, 0); @@ -606,7 +606,7 @@ static esp_err_t rmt_internal_config(rmt_dev_t *dev, const rmt_config_t *rmt_par #endif } esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &rmt_source_clk_hz); - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true)); RMT_CLOCK_SRC_ATOMIC() { rmt_ll_set_group_clock_src(dev, channel, clk_src, 1, 0, 0); rmt_ll_enable_group_clock(dev, true); diff --git a/components/driver/deprecated/timer_legacy.c b/components/driver/deprecated/timer_legacy.c index 27c446836b..48c8aeb725 100644 --- a/components/driver/deprecated/timer_legacy.c +++ b/components/driver/deprecated/timer_legacy.c @@ -328,7 +328,7 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer if (config->clk_src) { clk_src = config->clk_src; } - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true)); GPTIMER_CLOCK_SRC_ATOMIC() { // although `clk_src` is of `timer_src_clk_t` type, but it's binary compatible with `gptimer_clock_source_t`, // as the underlying enum entries come from the same `soc_module_clk_t` @@ -364,6 +364,7 @@ esp_err_t timer_deinit(timer_group_t group_num, timer_idx_t timer_num) GPTIMER_CLOCK_SRC_ATOMIC() { timer_ll_enable_clock(group_num, hal->timer_id, false); } + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)p_timer_obj[group_num][timer_num]->clk_src, false)); TIMER_ENTER_CRITICAL(&timer_spinlock[group_num]); timer_ll_enable_intr(hal->dev, TIMER_LL_EVENT_ALARM(timer_num), false); timer_ll_clear_intr_status(hal->dev, TIMER_LL_EVENT_ALARM(timer_num)); diff --git a/components/esp_adc/adc_continuous.c b/components/esp_adc/adc_continuous.c index 8e609d73b6..fe7173e704 100644 --- a/components/esp_adc/adc_continuous.c +++ b/components/esp_adc/adc_continuous.c @@ -321,10 +321,10 @@ esp_err_t adc_continuous_start(adc_continuous_handle_t handle) adc_hal_set_controller(ADC_UNIT_2, ADC_HAL_CONTINUOUS_READ_MODE); } - adc_hal_digi_init(&handle->hal); #if !CONFIG_IDF_TARGET_ESP32 - esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal_digi_ctrlr_cfg.clk_src), true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal_digi_ctrlr_cfg.clk_src), true)); #endif + adc_hal_digi_init(&handle->hal); adc_hal_digi_controller_config(&handle->hal, &handle->hal_digi_ctrlr_cfg); adc_hal_digi_enable(false); @@ -362,7 +362,9 @@ esp_err_t adc_continuous_stop(adc_continuous_handle_t handle) #endif adc_hal_digi_deinit(); - +#if !CONFIG_IDF_TARGET_ESP32 + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal_digi_ctrlr_cfg.clk_src), false)); +#endif if (handle->use_adc2) { adc_lock_release(ADC_UNIT_2); } @@ -377,7 +379,6 @@ esp_err_t adc_continuous_stop(adc_continuous_handle_t handle) ESP_RETURN_ON_ERROR(esp_pm_lock_release(handle->pm_lock), ADC_TAG, "release pm_lock failed"); } #endif - ANALOG_CLOCK_DISABLE(); return ESP_OK; diff --git a/components/esp_adc/adc_oneshot.c b/components/esp_adc/adc_oneshot.c index aba44c2748..cd85a76281 100644 --- a/components/esp_adc/adc_oneshot.c +++ b/components/esp_adc/adc_oneshot.c @@ -156,6 +156,9 @@ esp_err_t adc_oneshot_new_unit(const adc_oneshot_unit_init_cfg_t *init_config, a if (init_config->ulp_mode == ADC_ULP_MODE_DISABLE) { sar_periph_ctrl_adc_oneshot_power_acquire(); } else { +#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)(unit->hal.clk_src), true), err, TAG, "clock source enable failed"); +#endif #if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, true); #endif @@ -189,9 +192,6 @@ esp_err_t adc_oneshot_config_channel(adc_oneshot_unit_handle_t handle, adc_chann portENTER_CRITICAL(&rtc_spinlock); adc_oneshot_hal_channel_config(hal, &cfg, channel); if (handle->ulp_mode) { -#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED - esp_clk_tree_enable_src((soc_module_clk_t)(hal->clk_src), true); -#endif adc_oneshot_hal_setup(hal, channel); } portEXIT_CRITICAL(&rtc_spinlock); @@ -210,7 +210,7 @@ esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, portENTER_CRITICAL(&rtc_spinlock); #if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED - esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), true)); #endif ANALOG_CLOCK_ENABLE(); adc_oneshot_hal_setup(&(handle->hal), chan); @@ -222,6 +222,9 @@ esp_err_t adc_oneshot_read(adc_oneshot_unit_handle_t handle, adc_channel_t chan, bool valid = false; valid = adc_oneshot_hal_convert(&(handle->hal), out_raw); ANALOG_CLOCK_DISABLE(); +#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), false)); +#endif portEXIT_CRITICAL(&rtc_spinlock); adc_lock_release(handle->unit_id); @@ -238,7 +241,7 @@ esp_err_t adc_oneshot_read_isr(adc_oneshot_unit_handle_t handle, adc_channel_t c portENTER_CRITICAL_SAFE(&rtc_spinlock); #if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED - esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), true)); #endif ANALOG_CLOCK_ENABLE(); adc_oneshot_hal_setup(&(handle->hal), chan); @@ -249,6 +252,9 @@ esp_err_t adc_oneshot_read_isr(adc_oneshot_unit_handle_t handle, adc_channel_t c #endif adc_oneshot_hal_convert(&(handle->hal), out_raw); ANALOG_CLOCK_DISABLE(); +#if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), false)); +#endif portEXIT_CRITICAL_SAFE(&rtc_spinlock); @@ -271,7 +277,6 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle) _lock_release(&s_ctx.mutex); ESP_LOGD(TAG, "adc unit%"PRId32" is deleted", handle->unit_id); - free(handle); if (ulp_mode == ADC_ULP_MODE_DISABLE) { sar_periph_ctrl_adc_oneshot_power_release(); @@ -279,7 +284,9 @@ esp_err_t adc_oneshot_del_unit(adc_oneshot_unit_handle_t handle) #if SOC_LIGHT_SLEEP_SUPPORTED || SOC_DEEP_SLEEP_SUPPORTED esp_sleep_sub_mode_config(ESP_SLEEP_USE_ADC_TSEN_MONITOR_MODE, false); #endif + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(handle->hal.clk_src), false)); } + free(handle); #if SOC_ADC_DIG_CTRL_SUPPORTED && !SOC_ADC_RTC_CTRL_SUPPORTED //To free the APB_SARADC periph if needed diff --git a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c index 0b759a86fe..5dbaf54ba6 100644 --- a/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c +++ b/components/esp_driver_cam/csi/src/esp_cam_ctlr_csi.c @@ -119,7 +119,7 @@ esp_err_t esp_cam_new_csi_ctlr(const esp_cam_ctlr_csi_config_t *config, esp_cam_ #endif mipi_csi_phy_clock_source_t clk_src = !config->clk_src ? MIPI_CSI_PHY_CLK_SRC_DEFAULT : config->clk_src; - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), err, TAG, "clock source enable failed"); PERIPH_RCC_ATOMIC() { // phy clock source setting mipi_csi_ll_set_phy_clock_source(ctlr->csi_id, clk_src); diff --git a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c index 5e867279f5..5e53b9bab4 100644 --- a/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c +++ b/components/esp_driver_cam/dvp/src/esp_cam_ctlr_dvp_cam.c @@ -332,7 +332,7 @@ esp_err_t esp_cam_ctlr_dvp_init(int ctlr_id, cam_clock_source_t clk_src, const e } } - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true)); PERIPH_RCC_ATOMIC() { cam_ll_enable_clk(ctlr_id, true); cam_ll_select_clk_src(ctlr_id, clk_src); diff --git a/components/esp_driver_gptimer/src/gptimer.c b/components/esp_driver_gptimer/src/gptimer.c index 40cd65d4eb..88d6cea08d 100644 --- a/components/esp_driver_gptimer/src/gptimer.c +++ b/components/esp_driver_gptimer/src/gptimer.c @@ -108,6 +108,9 @@ static void gptimer_unregister_from_group(gptimer_t *timer) static esp_err_t gptimer_destroy(gptimer_t *timer) { + if (timer->clk_src) { + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)(timer->clk_src), false), TAG, "clock source disable failed"); + } #if CONFIG_PM_ENABLE if (timer->pm_lock) { ESP_RETURN_ON_ERROR(esp_pm_lock_delete(timer->pm_lock), TAG, "delete pm_lock failed"); @@ -157,6 +160,7 @@ 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); diff --git a/components/esp_driver_gptimer/src/gptimer_common.c b/components/esp_driver_gptimer/src/gptimer_common.c index 3adae18d24..67d3a0cdab 100644 --- a/components/esp_driver_gptimer/src/gptimer_common.c +++ b/components/esp_driver_gptimer/src/gptimer_common.c @@ -99,6 +99,7 @@ esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t s periph_rtc_dig_clk8m_enable(); } #endif // SOC_TIMER_GROUP_SUPPORT_RC_FAST + timer->clk_src = src_clk; // get clock source frequency ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz((soc_module_clk_t)src_clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz), @@ -139,7 +140,6 @@ esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t s } #endif // CONFIG_PM_ENABLE - esp_clk_tree_enable_src((soc_module_clk_t)src_clk, true); // !!! HARDWARE SHARED RESOURCE !!! // on some ESP chip, different peripheral's clock source setting are mixed in the same register // so we need to make this done in an atomic way @@ -147,7 +147,6 @@ esp_err_t gptimer_select_periph_clock(gptimer_t *timer, gptimer_clock_source_t s timer_ll_set_clock_source(group_id, timer_id, src_clk); timer_ll_enable_clock(group_id, timer_id, true); } - timer->clk_src = src_clk; uint32_t prescale = counter_src_hz / resolution_hz; // potential resolution loss here timer_ll_set_clock_prescale(timer->hal.dev, timer_id, prescale); timer->resolution_hz = counter_src_hz / prescale; // this is the real resolution diff --git a/components/esp_driver_gptimer/src/gptimer_priv.h b/components/esp_driver_gptimer/src/gptimer_priv.h index e9b1030fdc..8abeae4941 100644 --- a/components/esp_driver_gptimer/src/gptimer_priv.h +++ b/components/esp_driver_gptimer/src/gptimer_priv.h @@ -28,6 +28,7 @@ #include "hal/timer_hal.h" #include "hal/timer_ll.h" #include "clk_ctrl_os.h" +#include "esp_private/esp_clk_tree_common.h" #include "esp_private/sleep_retention.h" #include "esp_private/periph_ctrl.h" diff --git a/components/esp_driver_isp/include/esp_private/isp_private.h b/components/esp_driver_isp/include/esp_private/isp_private.h index 9d0ec92e25..7bcb151c1d 100644 --- a/components/esp_driver_isp/include/esp_private/isp_private.h +++ b/components/esp_driver_isp/include/esp_private/isp_private.h @@ -53,6 +53,7 @@ typedef enum { ---------------------------------------------------------------*/ typedef struct isp_processor_t { int proc_id; + isp_clk_src_t clk_src; isp_hal_context_t hal; #if SOC_ISP_SHARE_CSI_BRG int csi_brg_id; diff --git a/components/esp_driver_isp/src/isp_core.c b/components/esp_driver_isp/src/isp_core.c index fd5aa59213..d6dd2bbeae 100644 --- a/components/esp_driver_isp/src/isp_core.c +++ b/components/esp_driver_isp/src/isp_core.c @@ -112,14 +112,13 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_ if (out_clk_freq_hz != proc_config->clk_hz) { ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32"Hz", out_clk_freq_hz); } - ; isp_hal_init(&proc->hal, proc->proc_id); - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true), err, TAG, "clock source enable failed"); PERIPH_RCC_ATOMIC() { isp_ll_select_clk_source(proc->hal.hw, clk_src); isp_ll_set_clock_div(proc->hal.hw, &clk_div); } - + proc->clk_src = clk_src; proc->isp_fsm = ISP_FSM_INIT; proc->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; @@ -197,6 +196,7 @@ esp_err_t esp_isp_del_processor(isp_proc_handle_t proc) #if SOC_ISP_SHARE_CSI_BRG ESP_RETURN_ON_ERROR(mipi_csi_brg_declaim(proc->csi_brg_id), TAG, "declaim csi bridge fail"); #endif + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)(proc->clk_src), false), TAG, "clock source disable failed"); free(proc); return ESP_OK; diff --git a/components/esp_driver_ledc/src/ledc.c b/components/esp_driver_ledc/src/ledc.c index d69a8434ed..9737e06cbf 100644 --- a/components/esp_driver_ledc/src/ledc.c +++ b/components/esp_driver_ledc/src/ledc.c @@ -698,7 +698,7 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n if (p_ledc_obj[speed_mode]->glb_clk != glb_clk) { // TODO: release old glb_clk (if not UNINIT), and acquire new glb_clk [clk_tree] p_ledc_obj[speed_mode]->glb_clk = glb_clk; - esp_clk_tree_enable_src((soc_module_clk_t)glb_clk, true); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)glb_clk, true), LEDC_TAG, "clock source enable failed"); LEDC_FUNC_CLOCK_ATOMIC() { ledc_hal_set_slow_clk_sel(&(p_ledc_obj[speed_mode]->ledc_hal), glb_clk); } @@ -863,7 +863,7 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf) else if (new_speed_mode_ctx_created) { portENTER_CRITICAL(&ledc_spinlock); if (p_ledc_obj[speed_mode]->glb_clk == LEDC_SLOW_CLK_UNINIT) { - esp_clk_tree_enable_src((soc_module_clk_t)LEDC_LL_GLOBAL_CLK_DEFAULT, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)LEDC_LL_GLOBAL_CLK_DEFAULT, true)); ledc_hal_set_slow_clk_sel(&(p_ledc_obj[speed_mode]->ledc_hal), LEDC_LL_GLOBAL_CLK_DEFAULT); } portEXIT_CRITICAL(&ledc_spinlock); diff --git a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c index 0c38ae8425..c6a3a7483e 100644 --- a/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c +++ b/components/esp_driver_ledc/test_apps/ledc/main/test_ledc.c @@ -465,7 +465,7 @@ static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_ } else if (clk_src_freq == 60 * 1000 * 1000) { theoretical_freq = 8993; } - frequency_set_get(speed_mode, timer, 9000, theoretical_freq, 50); + frequency_set_get(speed_mode, timer, 9000, theoretical_freq, 60); #endif // Pause and de-configure the timer so that it won't affect the following test cases diff --git a/components/esp_driver_mcpwm/src/mcpwm_com.c b/components/esp_driver_mcpwm/src/mcpwm_com.c index e13334d9c4..21f7cfbbab 100644 --- a/components/esp_driver_mcpwm/src/mcpwm_com.c +++ b/components/esp_driver_mcpwm/src/mcpwm_com.c @@ -201,7 +201,7 @@ esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_s ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed"); #endif // CONFIG_PM_ENABLE - 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"); MCPWM_CLOCK_SRC_ATOMIC() { mcpwm_ll_group_set_clock_source(group_id, clk_src); } diff --git a/components/esp_driver_parlio/src/parlio_rx.c b/components/esp_driver_parlio/src/parlio_rx.c index de86eb6f47..1ca177cdb2 100644 --- a/components/esp_driver_parlio/src/parlio_rx.c +++ b/components/esp_driver_parlio/src/parlio_rx.c @@ -466,6 +466,7 @@ static esp_err_t parlio_select_periph_clock(parlio_rx_unit_handle_t rx_unit, con { parlio_hal_context_t *hal = &rx_unit->base.group->hal; parlio_clock_source_t clk_src = config->clk_src; + rx_unit->clk_src = clk_src; uint32_t src_freq_hz = 0; uint32_t exp_freq_hz = 0; hal_utils_clk_div_t clk_div = { @@ -510,14 +511,12 @@ static esp_err_t parlio_select_periph_clock(parlio_rx_unit_handle_t rx_unit, con } #endif - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); /* Set clock configuration */ PARLIO_CLOCK_SRC_ATOMIC() { parlio_ll_rx_set_clock_source(hal->regs, clk_src); parlio_ll_rx_set_clock_div(hal->regs, &clk_div); } - rx_unit->clk_src = clk_src; /* warning if precision lost due to division */ if ((clk_src != PARLIO_CLK_SRC_EXTERNAL) && (config->exp_clk_freq_hz != rx_unit->cfg.exp_clk_freq_hz)) { @@ -571,6 +570,9 @@ static esp_err_t parlio_destroy_rx_unit(parlio_rx_unit_handle_t rx_unit) if (rx_unit->base.group) { parlio_unregister_unit_from_group(&rx_unit->base); } + if (rx_unit->clk_src) { + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)rx_unit->clk_src, false), TAG, "clock source disable failed"); + } /* Free the RX unit */ free(rx_unit); return ESP_OK; @@ -637,6 +639,7 @@ esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_un } parlio_ll_rx_start(hal->regs, false); /* parlio_ll_clock_source_t and parlio_clock_source_t are binary compatible if the clock source is from internal */ + 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(parlio_select_periph_clock(unit, config), err, TAG, "set clock source failed"); /* Set the data width */ parlio_ll_rx_set_bus_width(hal->regs, config->data_width); diff --git a/components/esp_driver_parlio/src/parlio_tx.c b/components/esp_driver_parlio/src/parlio_tx.c index 5b3ff50272..f3c0d6b0d1 100644 --- a/components/esp_driver_parlio/src/parlio_tx.c +++ b/components/esp_driver_parlio/src/parlio_tx.c @@ -74,6 +74,9 @@ static esp_err_t parlio_destroy_tx_unit(parlio_tx_unit_t *tx_unit) ESP_RETURN_ON_ERROR(gdma_del_link_list(tx_unit->dma_link[i]), TAG, "delete dma link list failed"); } } + if (tx_unit->clk_src) { + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)tx_unit->clk_src, false), TAG, "clock source disable failed"); + } free(tx_unit); return ESP_OK; } @@ -182,6 +185,7 @@ static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const par { parlio_hal_context_t *hal = &tx_unit->base.group->hal; parlio_clock_source_t clk_src = config->clk_src; + tx_unit->clk_src = clk_src; if (config->clk_in_gpio_num >= 0 && clk_src != PARLIO_CLK_SRC_EXTERNAL) { ESP_LOGW(TAG, "input clock GPIO is set, use external clk src"); clk_src = PARLIO_CLK_SRC_EXTERNAL; @@ -223,7 +227,6 @@ static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const par #else tx_unit->out_clk_freq_hz = hal_utils_calc_clk_div_integer(&clk_info, &clk_div.integer); #endif - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); PARLIO_CLOCK_SRC_ATOMIC() { // turn on the tx module clock to sync the clock divider configuration because of the CDC (Cross Domain Crossing) parlio_ll_tx_enable_clock(hal->regs, true); @@ -235,8 +238,6 @@ static esp_err_t parlio_select_periph_clock(parlio_tx_unit_t *tx_unit, const par if (tx_unit->out_clk_freq_hz != config->output_clk_freq_hz) { ESP_LOGW(TAG, "precision loss, real output frequency: %"PRIu32, tx_unit->out_clk_freq_hz); } - tx_unit->clk_src = clk_src; - return ESP_OK; } @@ -284,6 +285,7 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un parlio_group_t *group = unit->base.group; parlio_hal_context_t *hal = &group->hal; // select the clock source + 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(parlio_select_periph_clock(unit, config), err, TAG, "set clock source failed"); // install interrupt service diff --git a/components/esp_driver_rmt/src/rmt_common.c b/components/esp_driver_rmt/src/rmt_common.c index 83d4b6eb3d..449b46a573 100644 --- a/components/esp_driver_rmt/src/rmt_common.c +++ b/components/esp_driver_rmt/src/rmt_common.c @@ -240,7 +240,7 @@ esp_err_t rmt_select_periph_clock(rmt_channel_handle_t chan, rmt_clock_source_t ESP_RETURN_ON_ERROR(ret, TAG, "create pm lock failed"); #endif // CONFIG_PM_ENABLE - 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"); uint32_t real_div; #if SOC_RMT_CHANNEL_CLK_INDEPENDENT uint32_t periph_src_clk_hz = 0; diff --git a/components/esp_driver_sdmmc/src/sd_host_sdmmc.c b/components/esp_driver_sdmmc/src/sd_host_sdmmc.c index 9fa2eb95f3..2defb6e717 100644 --- a/components/esp_driver_sdmmc/src/sd_host_sdmmc.c +++ b/components/esp_driver_sdmmc/src/sd_host_sdmmc.c @@ -987,7 +987,7 @@ static esp_err_t sd_host_reset(sd_host_sdmmc_ctlr_t *ctlr) */ static void sd_host_set_clk_div(sd_host_sdmmc_ctlr_t *ctlr, soc_periph_sdmmc_clk_src_t src, int div) { - esp_clk_tree_enable_src((soc_module_clk_t)src, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)src, true)); SD_HOST_SDMMC_CLK_SRC_ATOMIC() { sdmmc_ll_set_clock_div(ctlr->hal.dev, div); sdmmc_ll_select_clk_source(ctlr->hal.dev, src); diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index daf953fb92..1a0519724f 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -424,7 +424,7 @@ esp_err_t spi_bus_add_device(spi_host_device_t host_id, const spi_device_interfa spi_clock_source_t clk_src = dev_config->clock_source ? dev_config->clock_source : SPI_CLK_SRC_DEFAULT; uint32_t clock_source_hz = 0; uint32_t clock_source_div = 1; - esp_clk_tree_enable_src(clk_src, true); + 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_SUPPORT_CLK_SRC_PRE_DIV SPI_CHECK((dev_config->clock_speed_hz > 0) && (dev_config->clock_speed_hz <= MIN(clock_source_hz / 2, (80 * 1000000))), "invalid sclk speed", ESP_ERR_INVALID_ARG); @@ -601,7 +601,7 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle) periph_rtc_dig_clk8m_disable(); } #endif - esp_clk_tree_enable_src(handle->hal_dev.timing_conf.clock_source, false); + 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); //return int spics_io_num = handle->cfg.spics_io_num; diff --git a/components/esp_driver_twai/esp_twai_onchip.c b/components/esp_driver_twai/esp_twai_onchip.c index 2fe116d8ef..7e7b97d0a1 100644 --- a/components/esp_driver_twai/esp_twai_onchip.c +++ b/components/esp_driver_twai/esp_twai_onchip.c @@ -376,6 +376,8 @@ static esp_err_t _node_set_bit_timing(twai_node_handle_t node, const twai_timing #endif if (new_clock_src != twai_ctx->curr_clk_src) { + // TODO: IDF-13144 + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)(new_clock_src), true)); twai_ctx->curr_clk_src = new_clock_src; _twai_rcc_clock_sel(twai_ctx->ctrlr_id, new_clock_src); } diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 12733ec167..8eb9caa1eb 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -109,6 +109,7 @@ static const char *UART_TAG = "uart"; #define UART_CONTEXT_INIT_DEF(uart_num) { \ .port_id = uart_num, \ .hal.dev = UART_LL_GET_HW(uart_num), \ + .sclk_sel = -1, \ INIT_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) \ .hw_enabled = false, \ .tx_io_num = -1, \ @@ -175,6 +176,7 @@ typedef struct uart_context_t { _lock_t mutex; /*!< Protect uart_module_enable, uart_module_disable, retention, etc. */ uart_port_t port_id; uart_hal_context_t hal; /*!< UART hal context*/ + soc_module_clk_t sclk_sel; /*!< UART port clock source selection*/ DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) bool hw_enabled; int tx_io_num; @@ -973,6 +975,56 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf uart_module_enable(uart_num); + soc_module_clk_t uart_sclk_sel = 0; // initialize to an invalid module clock ID + if (uart_num < SOC_UART_HP_NUM) { + uart_sclk_sel = (soc_module_clk_t)((uart_config->source_clk) ? uart_config->source_clk : UART_SCLK_DEFAULT); // if no specifying the clock source (soc_module_clk_t starts from 1), then just use the default clock + } +#if (SOC_UART_LP_NUM >= 1) + else { + uart_sclk_sel = (soc_module_clk_t)((uart_config->lp_source_clk) ? uart_config->lp_source_clk : LP_UART_SCLK_DEFAULT); + } +#endif + uint32_t sclk_freq; + ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(uart_sclk_sel, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), UART_TAG, "invalid src_clk"); + + // Enable the newly selected clock source. + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(uart_sclk_sel, true), UART_TAG, "clock source enable failed"); +#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)); + soc_module_clk_t uart_old_sclk_sel = uart_context[uart_num].sclk_sel; + uart_context[uart_num].sclk_sel = uart_sclk_sel; + uart_hal_init(&(uart_context[uart_num].hal), uart_num); + if (uart_num < SOC_UART_HP_NUM) { + HP_UART_SRC_CLK_ATOMIC() { + uart_hal_set_sclk(&(uart_context[uart_num].hal), uart_sclk_sel); + success = uart_hal_set_baudrate(&(uart_context[uart_num].hal), uart_config->baud_rate, sclk_freq); + } + } +#if (SOC_UART_LP_NUM >= 1) + else { + LP_UART_SRC_CLK_ATOMIC() { + lp_uart_ll_set_source_clk(uart_context[uart_num].hal.dev, (soc_periph_lp_uart_clk_src_t)uart_sclk_sel); + } + success = lp_uart_ll_set_baudrate(uart_context[uart_num].hal.dev, uart_config->baud_rate, sclk_freq); + } +#endif + // Disable the previously selected clock source + uart_hal_set_parity(&(uart_context[uart_num].hal), uart_config->parity); + uart_hal_set_data_bit_num(&(uart_context[uart_num].hal), uart_config->data_bits); + uart_hal_set_stop_bits(&(uart_context[uart_num].hal), uart_config->stop_bits); + uart_hal_set_tx_idle_num(&(uart_context[uart_num].hal), UART_TX_IDLE_NUM_DEFAULT); + uart_hal_set_hw_flow_ctrl(&(uart_context[uart_num].hal), uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh); + UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); + uart_hal_rxfifo_rst(&(uart_context[uart_num].hal)); + uart_hal_txfifo_rst(&(uart_context[uart_num].hal)); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(uart_old_sclk_sel, false), UART_TAG, "clock source disable failed"); + ESP_RETURN_ON_FALSE(success, ESP_FAIL, UART_TAG, "baud rate unachievable"); #if SOC_UART_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // Create sleep retention link if desired if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) { @@ -994,52 +1046,6 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf _lock_release(&(uart_context[uart_num].mutex)); } #endif - - soc_module_clk_t uart_sclk_sel = 0; // initialize to an invalid module clock ID - if (uart_num < SOC_UART_HP_NUM) { - uart_sclk_sel = (soc_module_clk_t)((uart_config->source_clk) ? uart_config->source_clk : UART_SCLK_DEFAULT); // if no specifying the clock source (soc_module_clk_t starts from 1), then just use the default clock - } -#if (SOC_UART_LP_NUM >= 1) - else { - uart_sclk_sel = (soc_module_clk_t)((uart_config->lp_source_clk) ? uart_config->lp_source_clk : LP_UART_SCLK_DEFAULT); - } -#endif - -#if SOC_UART_SUPPORT_RTC_CLK - if (uart_sclk_sel == (soc_module_clk_t)UART_SCLK_RTC) { - periph_rtc_dig_clk8m_enable(); - } -#endif - uint32_t sclk_freq; - ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(uart_sclk_sel, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), UART_TAG, "invalid src_clk"); - - bool success = false; - UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - uart_hal_init(&(uart_context[uart_num].hal), uart_num); - if (uart_num < SOC_UART_HP_NUM) { - esp_clk_tree_enable_src((soc_module_clk_t)uart_sclk_sel, true); - HP_UART_SRC_CLK_ATOMIC() { - uart_hal_set_sclk(&(uart_context[uart_num].hal), uart_sclk_sel); - success = uart_hal_set_baudrate(&(uart_context[uart_num].hal), uart_config->baud_rate, sclk_freq); - } - } -#if (SOC_UART_LP_NUM >= 1) - else { - LP_UART_SRC_CLK_ATOMIC() { - lp_uart_ll_set_source_clk(uart_context[uart_num].hal.dev, (soc_periph_lp_uart_clk_src_t)uart_sclk_sel); - } - success = lp_uart_ll_set_baudrate(uart_context[uart_num].hal.dev, uart_config->baud_rate, sclk_freq); - } -#endif - uart_hal_set_parity(&(uart_context[uart_num].hal), uart_config->parity); - uart_hal_set_data_bit_num(&(uart_context[uart_num].hal), uart_config->data_bits); - uart_hal_set_stop_bits(&(uart_context[uart_num].hal), uart_config->stop_bits); - uart_hal_set_tx_idle_num(&(uart_context[uart_num].hal), UART_TX_IDLE_NUM_DEFAULT); - uart_hal_set_hw_flow_ctrl(&(uart_context[uart_num].hal), uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh); - UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); - uart_hal_rxfifo_rst(&(uart_context[uart_num].hal)); - uart_hal_txfifo_rst(&(uart_context[uart_num].hal)); - ESP_RETURN_ON_FALSE(success, ESP_FAIL, UART_TAG, "baud rate unachievable"); return ESP_OK; } @@ -1910,6 +1916,7 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) uart_free_driver_obj(p_uart_obj[uart_num]); p_uart_obj[uart_num] = NULL; + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(uart_context[uart_num].sclk_sel, false), UART_TAG, "clock source disable failed"); #if SOC_UART_SUPPORT_RTC_CLK soc_module_clk_t sclk = 0; uart_hal_get_sclk(&(uart_context[uart_num].hal), &sclk); @@ -2118,7 +2125,7 @@ esp_err_t uart_detect_bitrate_start(uart_port_t uart_num, const uart_bitrate_det uart_sclk_sel = (soc_module_clk_t)((config->source_clk) ? config->source_clk : UART_SCLK_DEFAULT); // if no specifying the clock source (soc_module_clk_t starts from 1), then just use the default clock 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); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src(uart_sclk_sel, true), err, UART_TAG, "clock source enable failed"); #if SOC_UART_SUPPORT_RTC_CLK if (uart_sclk_sel == (soc_module_clk_t)UART_SCLK_RTC) { periph_rtc_dig_clk8m_enable(); @@ -2180,6 +2187,7 @@ esp_err_t uart_detect_bitrate_stop(uart_port_t uart_num, bool deinit, uart_bitra if (deinit) { // release the port uart_release_pin(uart_num); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(uart_context[uart_num].sclk_sel, false), UART_TAG, "clock source disable failed"); #if SOC_UART_SUPPORT_RTC_CLK if (src_clk == (soc_module_clk_t)UART_SCLK_RTC) { periph_rtc_dig_clk8m_disable(); diff --git a/components/esp_eth/src/mac/esp_eth_mac_esp.c b/components/esp_eth/src/mac/esp_eth_mac_esp.c index 0b7dc19268..c9f9084b8e 100644 --- a/components/esp_eth/src/mac/esp_eth_mac_esp.c +++ b/components/esp_eth/src/mac/esp_eth_mac_esp.c @@ -521,7 +521,7 @@ static esp_err_t emac_config_pll_clock(emac_esp32_t *emac) real_freq /= div; } // Enable 50MHz MPLL derived clock - esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F50M, true); + ESP_RETURN_ON_ERROR(esp_clk_tree_enable_src(SOC_MOD_CLK_PLL_F50M, true), TAG, "clock source enable failed"); #endif // If the difference of real RMII CLK frequency is not within 50 ppm, i.e. 2500 Hz, the (A/M)PLL is unusable ESP_RETURN_ON_FALSE(abs((int)real_freq - (int)expt_freq) <= 2500, diff --git a/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h b/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h index 7b57285062..5755cd8232 100644 --- a/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h +++ b/components/esp_hw_support/include/esp_private/esp_clk_tree_common.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -84,11 +84,6 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec * @param[in] clk_src Clock source available to modules, in soc_module_clk_t * @param[in] enable Enable / Disable the clock gate * - * @note !!! WARNING !!! - * There's no reference counter to protect the clock source status, the caller should use the interface - * with CAUTION to disable the clock source to avoid damaging other peripherals that are dependent on - * the clock source. - * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index 8e98b61f37..57a0f1baa9 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -171,7 +171,7 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi modem_clock_hal.syscon_dev = &MODEM_SYSCON; modem_clock_hal.lpcon_dev = &MODEM_LPCON; #if SOC_CLOCK_TREE_MANAGEMENT_SUPPORTED - esp_clk_tree_enable_src(SOC_MOD_CLK_MODEM_APB, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src(SOC_MOD_CLK_MODEM_APB, true)); #endif } return &modem_clock_context; diff --git a/components/esp_hw_support/port/esp32c5/io_mux.c b/components/esp_hw_support/port/esp32c5/io_mux.c index e6e53ee3ba..6e00bb0da5 100644 --- a/components/esp_hw_support/port/esp32c5/io_mux.c +++ b/components/esp_hw_support/port/esp32c5/io_mux.c @@ -41,7 +41,7 @@ esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src) return ESP_ERR_INVALID_STATE; } - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true)); gpio_ll_iomux_set_clk_src(clk_src); return ESP_OK; diff --git a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c index 9e46ca5877..102ea66476 100644 --- a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -91,6 +91,11 @@ esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_sr esp_err_t esp_clk_tree_enable_src(soc_module_clk_t clk_src, bool enable) { + if(!enable) { + // TODO: remove it after reference counter supported + return ESP_OK; + } + PERIPH_RCC_ATOMIC() { switch (clk_src) { case SOC_MOD_CLK_PLL_F20M: diff --git a/components/esp_hw_support/port/esp32p4/io_mux.c b/components/esp_hw_support/port/esp32p4/io_mux.c index e74205bf8d..89befcb95e 100644 --- a/components/esp_hw_support/port/esp32p4/io_mux.c +++ b/components/esp_hw_support/port/esp32p4/io_mux.c @@ -44,7 +44,7 @@ esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src) return ESP_ERR_INVALID_STATE; } - esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_src, true)); PERIPH_RCC_ATOMIC() { gpio_ll_iomux_set_clk_src(clk_src); } diff --git a/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c b/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c index 90af97617a..1c188b3ffb 100644 --- a/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c +++ b/components/esp_lcd/dsi/esp_lcd_mipi_dsi_bus.c @@ -48,7 +48,7 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc if (phy_clk_src == 0) { phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT; } - esp_clk_tree_enable_src((soc_module_clk_t)phy_clk_src, true); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)phy_clk_src, true), err, TAG, "clock source enable failed"); // enable the clock source for DSI PHY DSI_CLOCK_SRC_ATOMIC() { // set clock source for DSI PHY diff --git a/components/esp_lcd/dsi/esp_lcd_panel_dpi.c b/components/esp_lcd/dsi/esp_lcd_panel_dpi.c index f6d307a6a0..cb0cd9e77b 100644 --- a/components/esp_lcd/dsi/esp_lcd_panel_dpi.c +++ b/components/esp_lcd/dsi/esp_lcd_panel_dpi.c @@ -262,7 +262,7 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_ &dpi_clk_src_freq_hz), err, TAG, "get clock source frequency failed"); // divide the source clock to get the final DPI clock uint32_t dpi_div = mipi_dsi_hal_host_dpi_calculate_divider(hal, dpi_clk_src_freq_hz / 1000 / 1000, panel_config->dpi_clock_freq_mhz); - esp_clk_tree_enable_src((soc_module_clk_t)dpi_clk_src, true); + ESP_GOTO_ON_ERROR(esp_clk_tree_enable_src((soc_module_clk_t)dpi_clk_src, true), err, TAG, "clock source enable failed"); // set the clock source, set the divider, and enable the dpi clock DSI_CLOCK_SRC_ATOMIC() { mipi_dsi_ll_set_dpi_clock_source(bus_id, dpi_clk_src); diff --git a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c index 35a14a0ba5..a607e1e825 100644 --- a/components/esp_lcd/i80/esp_lcd_panel_io_i80.c +++ b/components/esp_lcd/i80/esp_lcd_panel_io_i80.c @@ -582,7 +582,7 @@ static esp_err_t lcd_i80_select_periph_clock(esp_lcd_i80_bus_handle_t bus, lcd_c 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"); - 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"); LCD_CLOCK_SRC_ATOMIC() { lcd_ll_select_clk_src(bus->hal.dev, clk_src); // force to use integer division, as fractional division might lead to clock jitter diff --git a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c index dc5b5e52b0..87a334d772 100644 --- a/components/esp_lcd/rgb/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/rgb/esp_lcd_panel_rgb.c @@ -786,7 +786,7 @@ static esp_err_t lcd_rgb_panel_select_clock_src(esp_rgb_panel_t *rgb_panel, lcd_ 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_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"); LCD_CLOCK_SRC_ATOMIC() { lcd_ll_select_clk_src(rgb_panel->hal.dev, clk_src); } diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index a576d0d1ac..9277d8b183 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -926,7 +926,7 @@ void esp_pm_impl_init(void) ; } - esp_clk_tree_enable_src((soc_module_clk_t)clk_source, true); + ESP_ERROR_CHECK(esp_clk_tree_enable_src((soc_module_clk_t)clk_source, true)); /* When DFS is enabled, override system setting and use REFTICK as UART clock source */ HP_UART_SRC_CLK_ATOMIC() { uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), (soc_module_clk_t)clk_source);