diff --git a/components/esp32/clk.c b/components/esp32/clk.c index ab589fcdc..f9be8dac5 100644 --- a/components/esp32/clk.c +++ b/components/esp32/clk.c @@ -25,6 +25,8 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" +#include "soc/dport_reg.h" +#include "soc/i2s_reg.h" /* Number of cycles to wait from the 32k XTAL oscillator to consider it running. * Larger values increase startup delay. Smaller values may cause false positive @@ -125,3 +127,89 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk) ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val); esp_clk_slowclk_cal_set(cal_val); } + +/* This function is not exposed as an API at this point. + * All peripheral clocks are default enabled after chip is powered on. + * This function disables some peripheral clocks when cpu starts. + * These peripheral clocks are enabled when the peripherals are initialized + * and disabled when they are de-initialized. + */ +void esp_perip_clk_init(void) +{ + uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; + +#if CONFIG_FREERTOS_UNICORE + RESET_REASON rst_reas[1]; +#else + RESET_REASON rst_reas[2]; +#endif + + rst_reas[0] = rtc_get_reset_reason(0); + +#if !CONFIG_FREERTOS_UNICORE + rst_reas[1] = rtc_get_reset_reason(1); +#endif + + /* For reason that only reset CPU, do not disable the clocks + * that have been enabled before reset. + */ + if ((rst_reas[0] >= TGWDT_CPU_RESET && rst_reas[0] <= RTCWDT_CPU_RESET) +#if !CONFIG_FREERTOS_UNICORE + || (rst_reas[1] >= TGWDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET) +#endif + ) { + common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG); + hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERI_CLK_EN_REG); + wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG); + } + else { + common_perip_clk = DPORT_WDG_CLK_EN | + DPORT_I2S0_CLK_EN | + DPORT_UART1_CLK_EN | + DPORT_SPI_CLK_EN | + DPORT_I2C_EXT0_CLK_EN | + DPORT_UHCI0_CLK_EN | + DPORT_RMT_CLK_EN | + DPORT_PCNT_CLK_EN | + DPORT_LEDC_CLK_EN | + DPORT_UHCI1_CLK_EN | + DPORT_TIMERGROUP1_CLK_EN | + DPORT_SPI_CLK_EN_2 | + DPORT_PWM0_CLK_EN | + DPORT_I2C_EXT1_CLK_EN | + DPORT_CAN_CLK_EN | + DPORT_PWM1_CLK_EN | + DPORT_I2S1_CLK_EN | + DPORT_SPI_DMA_CLK_EN | + DPORT_UART2_CLK_EN | + DPORT_PWM2_CLK_EN | + DPORT_PWM3_CLK_EN; + hwcrypto_perip_clk = DPORT_PERI_EN_AES | + DPORT_PERI_EN_SHA | + DPORT_PERI_EN_RSA | + DPORT_PERI_EN_SECUREBOOT; + wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN | + DPORT_WIFI_CLK_BT_EN_M | + DPORT_WIFI_CLK_UNUSED_BIT5 | + DPORT_WIFI_CLK_UNUSED_BIT12 | + DPORT_WIFI_CLK_SDIOSLAVE_EN | + DPORT_WIFI_CLK_SDIO_HOST_EN | + DPORT_WIFI_CLK_EMAC_EN; + } + /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, + * the current is not reduced when disable I2S clock. + */ + DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA); + DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA); + + /* Disable some peripheral clocks. */ + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk); + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk); + + /* Disable hardware crypto clocks. */ + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk); + DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk); + + /* Disable WiFi/BT/SDIO clocks. */ + DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); +} diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 02745f3c1..0e8a65475 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -239,6 +239,7 @@ void start_cpu0_default(void) trax_start_trace(TRAX_DOWNCOUNT_WORDS); #endif esp_clk_init(); + esp_perip_clk_init(); intr_matrix_clear(); #ifndef CONFIG_CONSOLE_UART_NONE uart_div_modify(CONFIG_CONSOLE_UART_NUM, (rtc_clk_apb_freq_get() << 4) / CONFIG_CONSOLE_UART_BAUDRATE); diff --git a/components/esp32/include/esp_clk.h b/components/esp32/include/esp_clk.h index 7b9c64c69..5c6f5cb87 100644 --- a/components/esp32/include/esp_clk.h +++ b/components/esp32/include/esp_clk.h @@ -54,3 +54,11 @@ uint32_t esp_clk_slowclk_cal_get(); */ void esp_clk_slowclk_cal_set(uint32_t value); +/** + * @brief Disables clock of some peripherals + * + * Called from cpu_start.c, not intended to be called from other places. + * This function disables clock of useless peripherals when cpu starts. + */ +void esp_perip_clk_init(void); + diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index 56e18246d..98e603652 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -1055,6 +1055,8 @@ #define DPORT_WIFI_CLK_BT_EN_S 11 /* Remaining single bit clock masks */ #define DPORT_WIFI_CLK_SDIOSLAVE_EN BIT(4) +#define DPORT_WIFI_CLK_UNUSED_BIT5 BIT(5) +#define DPORT_WIFI_CLK_UNUSED_BIT12 BIT(12) #define DPORT_WIFI_CLK_SDIO_HOST_EN BIT(13) #define DPORT_WIFI_CLK_EMAC_EN BIT(14) #define DPORT_WIFI_CLK_RNG_EN BIT(15)