diff --git a/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h b/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h index 1325c262c81..1eb756b4ac2 100644 --- a/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h +++ b/components/esp_hal_clock/esp32h4/include/hal/clk_gate_ll.h @@ -92,6 +92,20 @@ FORCE_INLINE_ATTR void _clk_gate_ll_ref_96m_clk_en(bool enable) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define clk_gate_ll_ref_96m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_96m_clk_en(__VA_ARGS__) +/** + * @brief Set system bus clock gate bypass + * + * @param enable true: bypass bus clock gating (force clocks on); + * false: allow hardware auto clock gating to decrease power consumption + */ +FORCE_INLINE_ATTR void clk_gate_ll_set_bus_clock_gate_bypass(bool enable) +{ + PCR.bus_clock_gate_bypass.ahb_clk_gating_bypass = enable; + PCR.bus_clock_gate_bypass.apb_clk_gating_bypass = enable; + PCR.bus_clock_gate_bypass.axi_clk_gating_bypass = enable; + PCR.bus_clock_gate_bypass.mem_clk_gating_bypass = enable; +} + /** * @brief Configuration structure for peripheral clock gate settings */ diff --git a/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h b/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h index 9c0c219e399..4f2f2f723fc 100644 --- a/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h +++ b/components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h @@ -70,6 +70,21 @@ FORCE_INLINE_ATTR void _clk_gate_ll_ref_25m_clk_en(bool enable) HP_SYS_CLKRST.ref_25m_ctrl0.reg_ref_25m_clk_en = enable; } +/** + * @brief Set system bus clock gate bypass + * + * @param enable true: bypass bus clock gating (force clocks on); + * false: allow hardware auto clock gating to decrease power consumption + */ +FORCE_INLINE_ATTR void clk_gate_ll_set_bus_clock_gate_bypass(bool enable) +{ + HP_ALIVE_SYS.bus_clock_gate_bypass.ahb_clk_gating_bypass = enable; + HP_ALIVE_SYS.bus_clock_gate_bypass.apb_clk_gating_bypass = enable; + HP_ALIVE_SYS.bus_clock_gate_bypass.axi_clk_gating_bypass = enable; + HP_ALIVE_SYS.bus_clock_gate_bypass.mem_clk_gating_bypass = enable; + HP_ALIVE_SYS.bus_clock_gate_bypass.ahb_mtx_clk_gating_bypass = enable; +} + typedef struct { bool disable_uart0_clk; ///< Gate UART0 when it is not the console UART bool disable_uart1_clk; ///< Gate UART1 when it is not the console UART diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index df350168ca1..c1e58392873 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -337,6 +337,22 @@ menu "Hardware Settings" help If enabled, this option will perform additional checks on modem clock configuration to ensure proper operation and detect potential configuration issues. + + config ESP_BUS_ENABLE_AUTO_GATE + bool "Enable bus clock auto-gate" + depends on SOC_PM_SUPPORT_BUS_CLK_AUTO_GATE + default y if IDF_CI_BUILD + default n + help + Enable this option to use bus clock auto-gate for the system bus. + + When enabled, AHB/APB/AXI/MEM bus clock gating bypass is cleared, so the bus + clocks are no longer forced on. Hardware then automatically gates these clocks + when there is no bus access, reducing power consumption. + + This option has risk: auto-gating may cause unexpected bus access failures or + system instability on some peripherals/scenarios. Enable with caution and + verify thoroughly. endmenu rsource "./etm/Kconfig.etm" diff --git a/components/esp_system/port/soc/esp32h4/clk.c b/components/esp_system/port/soc/esp32h4/clk.c index 810d819454c..ac424c21053 100644 --- a/components/esp_system/port/soc/esp32h4/clk.c +++ b/components/esp_system/port/soc/esp32h4/clk.c @@ -223,4 +223,9 @@ __attribute__((weak)) void esp_perip_clk_init(void) #endif periph_ll_clk_gate_set_default(rst_reason, &clk_gate_config); + +#if CONFIG_ESP_BUS_ENABLE_AUTO_GATE + // Clear bus clock gating bypass so hardware can auto-gate idle bus clocks + clk_gate_ll_set_bus_clock_gate_bypass(false); +#endif } diff --git a/components/esp_system/port/soc/esp32s31/clk.c b/components/esp_system/port/soc/esp32s31/clk.c index 5655994b386..810bfb43d71 100644 --- a/components/esp_system/port/soc/esp32s31/clk.c +++ b/components/esp_system/port/soc/esp32s31/clk.c @@ -229,4 +229,9 @@ __attribute__((weak)) void esp_perip_clk_init(void) #endif periph_ll_clk_gate_set_default(rst_reason, &clk_gate_config); + +#if CONFIG_ESP_BUS_ENABLE_AUTO_GATE + // Clear bus clock gating bypass so hardware can auto-gate idle bus clocks + clk_gate_ll_set_bus_clock_gate_bypass(false); +#endif } diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 13697e9bfb7..4c0c4684adb 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -1215,6 +1215,10 @@ config SOC_PM_FLASH_KEEP_POWER_IN_LSLP bool default y +config SOC_PM_SUPPORT_BUS_CLK_AUTO_GATE + bool + default y + config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 96cca8455ee..bac32073a76 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -509,6 +509,7 @@ #define SOC_PM_MODEM_LOCK_CLK_WORKAROUND (1) // In ESP32H4, the modem lock will lock the xtalx2, bbpll and other xpd state during modem2active. #define SOC_PM_FLASH_KEEP_POWER_IN_LSLP (1) /*!