diff --git a/arch/xtensa/src/esp32/esp32_clockconfig.c b/arch/xtensa/src/esp32/esp32_clockconfig.c index 7a9b52123ae..d05c2312d18 100644 --- a/arch/xtensa/src/esp32/esp32_clockconfig.c +++ b/arch/xtensa/src/esp32/esp32_clockconfig.c @@ -98,6 +98,34 @@ static inline void esp32_uart_tx_wait_idle(uint8_t uart_no) ****************************************************************************/ extern uint32_t g_ticks_per_us_pro; +#ifdef CONFIG_SMP +extern uint32_t g_ticks_per_us_app; +#endif + +/**************************************************************************** + * Name: esp32_update_cpu_freq + * + * Description: + * Set the real CPU ticks per us to the ets, so that ets_delay_us + * will be accurate. Call this function when CPU frequency is changed. + * + * Input Parameters: + * ticks_per_us - CPU ticks per us + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_update_cpu_freq(uint32_t ticks_per_us) +{ + /* Update scale factors used by esp_rom_delay_us */ + + g_ticks_per_us_pro = ticks_per_us; +#ifdef CONFIG_SMP + g_ticks_per_us_app = ticks_per_us; +#endif +} /**************************************************************************** * Name: esp32_set_cpu_freq diff --git a/arch/xtensa/src/esp32/esp32_clockconfig.h b/arch/xtensa/src/esp32/esp32_clockconfig.h index f489172d98e..1e4f91852ca 100644 --- a/arch/xtensa/src/esp32/esp32_clockconfig.h +++ b/arch/xtensa/src/esp32/esp32_clockconfig.h @@ -46,6 +46,23 @@ * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: esp32_update_cpu_freq + * + * Description: + * Set the real CPU ticks per us to the ets, so that ets_delay_us + * will be accurate. Call this function when CPU frequency is changed. + * + * Input Parameters: + * ticks_per_us - CPU ticks per us + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_update_cpu_freq(uint32_t ticks_per_us); + /**************************************************************************** * Name: esp32_set_cpu_freq * diff --git a/arch/xtensa/src/esp32/esp32_pm.c b/arch/xtensa/src/esp32/esp32_pm.c index 18a44857d6b..71e25d5e859 100644 --- a/arch/xtensa/src/esp32/esp32_pm.c +++ b/arch/xtensa/src/esp32/esp32_pm.c @@ -562,7 +562,7 @@ static int IRAM_ATTR esp32_sleep_start(uint32_t pd_flags) /* Save current frequency and switch to XTAL */ - cur_freq = esp_clk_cpu_freq() / MHZ; + cur_freq = esp_rtc_clk_get_cpu_freq(); esp32_rtc_cpu_freq_set_xtal(); /* Enter sleep */ @@ -851,6 +851,7 @@ void esp32_sleep_enable_timer_wakeup(uint64_t time_in_us) int esp32_light_sleep_start(void) { + irqstate_t flags; uint32_t pd_flags; uint32_t flash_enable_time_us; #ifndef CONFIG_ESP32_SPIRAM @@ -859,6 +860,7 @@ int esp32_light_sleep_start(void) struct rtc_vddsdio_config_s vddsdio_config; int ret = OK; + flags = enter_critical_section(); s_config.rtc_ticks_at_sleep_start = esp32_rtc_time_get(); /* Decide which power domains can be powered down */ @@ -896,7 +898,7 @@ int esp32_light_sleep_start(void) ret = esp32_light_sleep_inner(pd_flags, flash_enable_time_us, vddsdio_config); - + leave_critical_section(flags); return ret; } diff --git a/arch/xtensa/src/esp32/esp32_rtc.c b/arch/xtensa/src/esp32/esp32_rtc.c index a23cec991e4..2f0171fd29c 100644 --- a/arch/xtensa/src/esp32/esp32_rtc.c +++ b/arch/xtensa/src/esp32/esp32_rtc.c @@ -23,8 +23,10 @@ ****************************************************************************/ #include +#include #include "esp32_rtc.h" +#include "esp32_clockconfig.h" #include "hardware/esp32_rtccntl.h" #include "hardware/esp32_dport.h" #include "hardware/esp32_i2s.h" @@ -622,22 +624,23 @@ void IRAM_ATTR esp32_rtc_update_to_xtal(int freq, int div) { uint32_t value = (((freq * MHZ) >> 12) & UINT16_MAX) | ((((freq * MHZ) >> 12) & UINT16_MAX) << 16); - putreg32(value, RTC_APB_FREQ_REG); + esp32_update_cpu_freq(freq); /* set divider from XTAL to APB clock */ REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, div - 1); - /* switch clock source */ - - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, - RTC_CNTL_SOC_CLK_SEL_XTL); - /* adjust ref_tick */ modifyreg32(APB_CTRL_XTAL_TICK_CONF_REG, 0, (freq * MHZ) / REF_CLK_FREQ - 1); + /* switch clock source */ + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, + RTC_CNTL_SOC_CLK_SEL_XTL); + putreg32(value, RTC_APB_FREQ_REG); + /* lower the voltage */ if (freq <= 2) @@ -1152,6 +1155,77 @@ void IRAM_ATTR esp32_rtc_cpu_freq_set_xtal(void) esp32_rtc_bbpll_disable(); } +/**************************************************************************** + * Name: esp_rtc_clk_get_cpu_freq + * + * Description: + * Get the currently used CPU frequency configuration. + * + * Input Parameters: + * None + * + * Returned Value: + * CPU frequency + * + ****************************************************************************/ + +int IRAM_ATTR esp_rtc_clk_get_cpu_freq(void) +{ + uint32_t source_freq_mhz; + uint32_t div; + uint32_t soc_clk_sel; + uint32_t cpuperiod_sel; + int freq_mhz = 0; + + soc_clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL); + switch (soc_clk_sel) + { + case RTC_CNTL_SOC_CLK_SEL_XTL: + { + div = REG_GET_FIELD(APB_CTRL_SYSCLK_CONF_REG, + APB_CTRL_PRE_DIV_CNT) + 1; + source_freq_mhz = (uint32_t) esp32_rtc_clk_xtal_freq_get(); + freq_mhz = source_freq_mhz / div; + } + break; + + case RTC_CNTL_SOC_CLK_SEL_PLL: + { + cpuperiod_sel = REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, + DPORT_CPUPERIOD_SEL); + if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80) + { + freq_mhz = 80; + } + else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_160) + { + freq_mhz = 160; + } + else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_240) + { + freq_mhz = 240; + } + else + { + DEBUGASSERT(0); + } + } + break; + + case RTC_CNTL_SOC_CLK_SEL_8M: + { + freq_mhz = 8; + } + break; + + case RTC_CNTL_SOC_CLK_SEL_APLL: + default: + DEBUGASSERT(0); + } + + return freq_mhz; +} + /**************************************************************************** * Name: esp32_rtc_sleep_init * @@ -1327,6 +1401,17 @@ void IRAM_ATTR esp32_rtc_sleep_init(uint32_t flags) modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, 0); } + /* Keep the RTC8M_CLK on in light_sleep mode if the + * ledc low-speed channel is clocked by RTC8M_CLK. + */ + + if (!cfg.deep_slp && GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, + RTC_CNTL_DIG_CLK8M_EN_M)) + { + REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD); + REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); + } + /* enable VDDSDIO control by state machine */ modifyreg32(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE, 0); diff --git a/arch/xtensa/src/esp32/esp32_rtc.h b/arch/xtensa/src/esp32/esp32_rtc.h index 9615e0ff1e0..9fa886b4d24 100644 --- a/arch/xtensa/src/esp32/esp32_rtc.h +++ b/arch/xtensa/src/esp32/esp32_rtc.h @@ -258,6 +258,22 @@ void esp32_rtc_wait_for_slow_cycle(void); void esp32_rtc_cpu_freq_set_xtal(void); +/**************************************************************************** + * Name: esp_rtc_clk_get_cpu_freq + * + * Description: + * Get the currently used CPU frequency configuration. + * + * Input Parameters: + * None + * + * Returned Value: + * CPU frequency + * + ****************************************************************************/ + +int esp_rtc_clk_get_cpu_freq(void); + /**************************************************************************** * Name: esp32_rtc_sleep_init *