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 */