feat(esp_hw_support): add esp32p4 sleep initial support

pull/13306/head
wuzhenghui 2023-12-22 19:36:24 +08:00 zatwierdzone przez BOT
rodzic 856f043331
commit 65e9d0ddb9
14 zmienionych plików z 200 dodań i 57 usunięć

Wyświetl plik

@ -165,7 +165,6 @@ if(NOT BOOTLOADER_BUILD)
if(CONFIG_IDF_TARGET_ESP32P4)
list(REMOVE_ITEM srcs
"sleep_cpu.c" # TODO: IDF-7528, IDF-7529
"sleep_modes.c" # TODO: IDF-7528, IDF-7529
"sleep_wake_stub.c" # TODO: IDF-7529
"sleep_gpio.c" # TODO: IDF-7528, IDF-7529
)

Wyświetl plik

@ -241,7 +241,16 @@ void pmu_sleep_increase_ldo_volt(void) {
void pmu_sleep_shutdown_dcdc(void) {
SET_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable
REG_SET_BIT(PMU_DCM_CTRL_REG, PMU_DCDC_OFF_REQ);
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 28); // decrease hp_ldo voltage
// Decrease the DCDC voltage to reduce the voltage difference between the DCDC and the LDO to avoid overshooting the DCDC voltage during wake-up.
REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, 24);
// Decrease hp_ldo voltage.
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 24);
}
void pmu_sleep_enable_dcdc(void) {
CLEAR_PERI_REG_MASK(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_LP_FIB_DCDC_SWITCH); //0: enable, 1: disable
SET_PERI_REG_MASK(PMU_DCM_CTRL_REG, PMU_DCDC_ON_REQ);
REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, 27);
}
void pmu_sleep_shutdown_ldo(void) {
@ -274,6 +283,15 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
TCM_IRAM_ATTR bool pmu_sleep_finish(void)
{
REG_SET_FIELD(PMU_HP_ACTIVE_BIAS_REG, PMU_HP_ACTIVE_DCM_VSET, 27);
if (pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
// If sleep is rejected, the hardware wake-up process that turns on DCDC
// is skipped, and software is used to enable DCDC here.
pmu_sleep_enable_dcdc();
esp_rom_delay_us(950);
}
pmu_sleep_shutdown_ldo();
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);

Wyświetl plik

@ -234,17 +234,16 @@ static void rtc_clk_cpu_freq_to_cpll_mhz(int cpu_freq_mhz, hal_utils_clk_div_t *
abort();
}
// Update bit does not control CPU clock sel mux. Therefore, there may be a middle state during the switch (CPU rises)
// We will switch cpu clock source first, and then set the desired dividers.
// It is likely that the hardware will automatically adjust dividers to meet mem_clk, apb_clk freq constraints when
// cpu clock source is set.
// However, the desired dividers will be written into registers anyways afterwards.
// This ensures the final confguration is the desired one.
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL);
// Since this is upscaling, we need to configure the frequency division coefficient before switching the clock source.
// Otherwise, an intermediate state will occur, in the intermediate state, the frequency of APB/MEM does not meet the
// timing requirements. If there are periperals/CPU access that depend on these two clocks at this moment, some exception
// might occur.
clk_ll_cpu_set_divider(div->integer, div->numerator, div->denominator);
clk_ll_mem_set_divider(mem_divider);
clk_ll_sys_set_divider(sys_divider);
clk_ll_apb_set_divider(apb_divider);
clk_ll_bus_update();
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL);
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
}

Wyświetl plik

@ -143,6 +143,7 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
}
}
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_PERI_CLK_CTRL21_REG, HP_SYS_CLKRST_REG_TIMERGRP0_TGRT_CLK_DIV_NUM_M);
/* 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) {

Wyświetl plik

@ -22,11 +22,7 @@
#include "hal/rtc_io_hal.h"
#include "soc/rtc_io_periph.h"
#if SOC_LP_AON_SUPPORTED
#include "hal/lp_aon_hal.h"
#else
#include "hal/rtc_hal.h"
#endif
#include "esp_private/gpio.h"
#include "esp_private/sleep_gpio.h"

Wyświetl plik

@ -30,12 +30,10 @@
#include "esp_private/pm_impl.h"
#endif
#if SOC_LP_AON_SUPPORTED
#include "hal/lp_aon_hal.h"
#else
#if !SOC_PMU_SUPPORTED
#include "hal/rtc_cntl_ll.h"
#include "hal/rtc_hal.h"
#endif
#include "hal/rtc_hal.h"
#include "soc/rtc.h"
#include "soc/soc_caps.h"
@ -90,6 +88,9 @@
#include "esp32h2/rom/rtc.h"
#include "soc/extmem_reg.h"
#include "hal/gpio_ll.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/rtc.h"
#include "hal/gpio_ll.h"
#endif
#if SOC_LP_TIMER_SUPPORTED
@ -138,11 +139,11 @@
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
#elif CONFIG_IDF_TARGET_ESP32H2
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)// TODO: IDF-6267
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
#elif CONFIG_IDF_TARGET_ESP32P4
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)// TODO: IDF-6267
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (324)// TODO: IDF-7528
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (240)
#define LDO_POWER_TAKEOVER_PREPARATION_TIME_US (185)
#endif
@ -275,7 +276,7 @@ static void touch_wakeup_prepare(void);
static void gpio_deep_sleep_wakeup_prepare(void);
#endif
#if SOC_RTC_FAST_MEM_SUPPORTED
#if SOC_RTC_FAST_MEM_SUPPORTED && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7529
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
static RTC_FAST_ATTR esp_deep_sleep_wake_stub_fn_t wake_stub_fn_handler = NULL;
@ -568,10 +569,12 @@ FORCE_INLINE_ATTR void misc_modules_sleep_prepare(bool deep_sleep)
#endif
}
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-6496
// TODO: IDF-7370
if (!(deep_sleep && s_adc_tsen_enabled)){
sar_periph_ctrl_power_disable();
}
#endif
}
/**
@ -582,7 +585,11 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(void)
#if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP
sleep_console_usj_pad_restore();
#endif
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-6496
sar_periph_ctrl_power_enable();
#endif
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
sleep_disable_cpu_retention();
#endif
@ -822,7 +829,9 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7529
esp_set_deep_sleep_wake_stub_default_entry();
#endif
// Enter Deep Sleep
#if SOC_PMU_SUPPORTED
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
@ -1086,15 +1095,6 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
esp_rom_delay_us(flash_enable_time_us);
}
#if SOC_DCDC_SUPPORTED
uint32_t dcdc_ready_hw_waited_time_us = pmu_sleep_calculate_hp_hw_wait_time(pd_flags, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period);
uint32_t dcdc_ready_sw_waited_time_us = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / MHZ);
if (dcdc_ready_hw_waited_time_us + dcdc_ready_sw_waited_time_us < DCDC_POWER_STARTUP_TIME_US) {
esp_rom_delay_us(DCDC_POWER_STARTUP_TIME_US - dcdc_ready_hw_waited_time_us - dcdc_ready_sw_waited_time_us);
}
pmu_sleep_shutdown_ldo();
#endif
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
/* Cache Resume 2: flash is ready now, we can resume the cache and access flash safely after */

Wyświetl plik

@ -36,7 +36,8 @@ entries:
sleep_system_peripheral:peripheral_domain_pd_allowed (noflash)
sleep_modem:modem_domain_pd_allowed (noflash)
sleep_modem:periph_inform_out_light_sleep_overhead (noflash)
sar_periph_ctrl:sar_periph_ctrl_power_disable (noflash)
if IDF_TARGET_ESP32P4 = n: # TODO: IDF-6496
sar_periph_ctrl:sar_periph_ctrl_power_disable (noflash)
[mapping:esp_system_pm]
archive: libesp_system.a

Wyświetl plik

@ -64,6 +64,16 @@ extern "C" {
#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code.
/*
* Use LP_SYS_LP_STORE8_REG to store light sleep wake stub addr and sleep mode
*
* bit[31: 2] Wake restore func addr
* bit[0]:
* 0 -- light sleep
* 1 -- deep sleep
*/
#define SLEEP_MODE_REG LP_SYSTEM_REG_LP_STORE8_REG
typedef enum {
AWAKE = 0, //<CPU ON
LIGHT_SLEEP = BIT0, //CPU waiti, PLL ON. We don't need explicitly set this mode.

Wyświetl plik

@ -8,10 +8,12 @@
#include "hal/lp_aon_ll.h"
#define rtc_hal_ext1_get_wakeup_status() lp_aon_ll_ext1_get_wakeup_status()
#define rtc_hal_ext1_clear_wakeup_status() lp_aon_ll_ext1_clear_wakeup_status()
#define rtc_hal_ext1_set_wakeup_pins(io_mask, mode_mask) lp_aon_ll_ext1_set_wakeup_pins(io_mask, mode_mask)
#define rtc_hal_ext1_clear_wakeup_pins() lp_aon_ll_ext1_clear_wakeup_pins()
#define rtc_hal_ext1_get_wakeup_pins() lp_aon_ll_ext1_get_wakeup_pins()
#ifdef __cplusplus
extern "C" {
#endif
#define lp_aon_hal_inform_wakeup_type(dslp) lp_aon_ll_inform_wakeup_type(dslp)
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -8,10 +8,12 @@
#include "hal/lp_aon_ll.h"
#define rtc_hal_ext1_get_wakeup_status() lp_aon_ll_ext1_get_wakeup_status()
#define rtc_hal_ext1_clear_wakeup_status() lp_aon_ll_ext1_clear_wakeup_status()
#define rtc_hal_ext1_set_wakeup_pins(io_mask, mode_mask) lp_aon_ll_ext1_set_wakeup_pins(io_mask, mode_mask)
#define rtc_hal_ext1_clear_wakeup_pins() lp_aon_ll_ext1_clear_wakeup_pins()
#define rtc_hal_ext1_get_wakeup_pins() lp_aon_ll_ext1_get_wakeup_pins()
#ifdef __cplusplus
extern "C" {
#endif
#define lp_aon_hal_inform_wakeup_type(dslp) lp_aon_ll_inform_wakeup_type(dslp)
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -678,12 +678,12 @@ __attribute__((always_inline))
static inline void cache_ll_l1_freeze_icache(uint32_t cache_id)
{
if (cache_id == 0) {
Cache_Freeze_L1_ICache0_Enable(CACHE_FREEZE_ACK_BUSY);
rom_cache_internal_table_ptr->freeze_l1_icache0_enable(CACHE_FREEZE_ACK_BUSY);
} else if (cache_id == 1) {
Cache_Freeze_L1_ICache1_Enable(CACHE_FREEZE_ACK_BUSY);
rom_cache_internal_table_ptr->freeze_l1_icache1_enable(CACHE_FREEZE_ACK_BUSY);
} else if (cache_id == CACHE_LL_ID_ALL) {
Cache_Freeze_L1_ICache0_Enable(CACHE_FREEZE_ACK_BUSY);
Cache_Freeze_L1_ICache1_Enable(CACHE_FREEZE_ACK_BUSY);
rom_cache_internal_table_ptr->freeze_l1_icache0_enable(CACHE_FREEZE_ACK_BUSY);
rom_cache_internal_table_ptr->freeze_l1_icache1_enable(CACHE_FREEZE_ACK_BUSY);
}
}
@ -696,7 +696,7 @@ __attribute__((always_inline))
static inline void cache_ll_l1_freeze_dcache(uint32_t cache_id)
{
if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) {
Cache_Freeze_L1_DCache_Enable(CACHE_FREEZE_ACK_BUSY);
rom_cache_internal_table_ptr->freeze_l1_dcache_enable(CACHE_FREEZE_ACK_BUSY);
}
}
@ -709,7 +709,7 @@ __attribute__((always_inline))
static inline void cache_ll_l2_freeze_cache(uint32_t cache_id)
{
if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) {
Cache_Freeze_L2_Cache_Enable(CACHE_FREEZE_ACK_BUSY);
rom_cache_internal_table_ptr->freeze_l2_cache_enable(CACHE_FREEZE_ACK_BUSY);
}
}
@ -755,12 +755,12 @@ __attribute__((always_inline))
static inline void cache_ll_l1_unfreeze_icache(uint32_t cache_id)
{
if (cache_id == 0) {
Cache_Freeze_L1_ICache0_Disable();
rom_cache_internal_table_ptr->freeze_l1_icache0_disable();
} else if (cache_id == 1) {
Cache_Freeze_L1_ICache1_Disable();
rom_cache_internal_table_ptr->freeze_l1_icache1_disable();
} else if (cache_id == CACHE_LL_ID_ALL) {
Cache_Freeze_L1_ICache1_Disable();
Cache_Freeze_L1_ICache0_Disable();
rom_cache_internal_table_ptr->freeze_l1_icache1_disable();
rom_cache_internal_table_ptr->freeze_l1_icache0_disable();
}
}
@ -773,7 +773,7 @@ __attribute__((always_inline))
static inline void cache_ll_l1_unfreeze_dcache(uint32_t cache_id)
{
if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) {
Cache_Freeze_L1_DCache_Disable();
rom_cache_internal_table_ptr->freeze_l1_dcache_disable();
}
}
@ -786,7 +786,7 @@ __attribute__((always_inline))
static inline void cache_ll_l2_unfreeze_cache(uint32_t cache_id)
{
if (cache_id == 0 || cache_id == CACHE_LL_ID_ALL) {
Cache_Freeze_L2_Cache_Disable();
rom_cache_internal_table_ptr->freeze_l2_cache_disable();
}
}

Wyświetl plik

@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "hal/lp_sys_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
#define lp_aon_hal_inform_wakeup_type(dslp) lp_sys_ll_inform_wakeup_type(dslp)
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -0,0 +1,89 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-C6 LP_SYS register operations
#pragma once
#include <stdlib.h>
#include "soc/soc.h"
#include "soc/lp_system_struct.h"
#include "hal/misc.h"
#include "esp32p4/rom/rtc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get ext1 wakeup source status
* @return The lower 8 bits of the returned value are the bitmap of
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
*/
static inline uint32_t lp_sys_ll_ext1_get_wakeup_status(void)
{
// TODO: IDF-7529
return 0;
}
/**
* @brief Clear the ext1 wakeup source status
*/
static inline void lp_sys_ll_ext1_clear_wakeup_status(void)
{
// TODO: IDF-7529
}
/**
* @brief Set the wake-up LP_IO of the ext1 wake-up source
* @param mask wakeup LP_IO bitmap, bit 0~7 corresponds to LP_IO 0~7
* @param mode 0: Wake the chip when all selected GPIOs go low
* 1: Wake the chip when any of the selected GPIOs go high
*/
static inline void lp_sys_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
{
// TODO: IDF-7529
}
/**
* @brief Clear all ext1 wakup-source setting
*/
static inline void lp_sys_ll_ext1_clear_wakeup_pins(void)
{
// TODO: IDF-7529
}
/**
* @brief Get ext1 wakeup source setting
* @return The lower 8 bits of the returned value are the bitmap of
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
*/
static inline uint32_t lp_sys_ll_ext1_get_wakeup_pins(void)
{
// TODO: IDF-7529
return 0;
}
/**
* @brief ROM obtains the wake-up type through LP_SYS_STORE9_REG[0].
* Set the flag to inform
* @param true: deepsleep false: lightsleep
*/
static inline void lp_sys_ll_inform_wakeup_type(bool dslp)
{
if (dslp) {
REG_SET_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run deep sleep wake stub */
} else {
REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */
}
}
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -20,6 +20,10 @@
#include "hal/rtc_io_ll.h"
#endif
#if SOC_LP_AON_SUPPORTED
#include "hal/lp_aon_ll.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -51,16 +55,19 @@ typedef struct rtc_cntl_sleep_retent {
#if SOC_PM_SUPPORT_EXT1_WAKEUP
#if SOC_LP_AON_SUPPORTED
#define rtc_hal_ext1_get_wakeup_status() lp_aon_ll_ext1_get_wakeup_status()
#define rtc_hal_ext1_clear_wakeup_status() lp_aon_ll_ext1_clear_wakeup_status()
#define rtc_hal_ext1_set_wakeup_pins(io_mask, mode_mask) lp_aon_ll_ext1_set_wakeup_pins(io_mask, mode_mask)
#define rtc_hal_ext1_clear_wakeup_pins() lp_aon_ll_ext1_clear_wakeup_pins()
#define rtc_hal_ext1_get_wakeup_pins() lp_aon_ll_ext1_get_wakeup_pins()
#else
#define rtc_hal_ext1_get_wakeup_status() rtc_cntl_ll_ext1_get_wakeup_status()
#define rtc_hal_ext1_clear_wakeup_status() rtc_cntl_ll_ext1_clear_wakeup_status()
#define rtc_hal_ext1_set_wakeup_pins(io_mask, mode_mask) rtc_cntl_ll_ext1_set_wakeup_pins(io_mask, mode_mask)
#define rtc_hal_ext1_clear_wakeup_pins() rtc_cntl_ll_ext1_clear_wakeup_pins()
#define rtc_hal_ext1_get_wakeup_pins() rtc_cntl_ll_ext1_get_wakeup_pins()
#endif
#endif // SOC_PM_SUPPORT_EXT1_WAKEUP
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT == 0)