mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/bringup_esp32c6_light_sleep_pd_cpu' into 'master'
esp32c6: support light_sleep (Stage 1: support CPU power down) See merge request espressif/esp-idf!21985
This commit is contained in:
commit
33ae2e1073
@ -94,6 +94,7 @@ menu "Bootloader config"
|
||||
choice BOOTLOADER_VDDSDIO_BOOST
|
||||
bool "VDDSDIO LDO voltage"
|
||||
default BOOTLOADER_VDDSDIO_BOOST_1_9V
|
||||
depends on SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
||||
help
|
||||
If this option is enabled, and VDDSDIO LDO is set to 1.8V (using eFuse
|
||||
or MTDI bootstrapping pin), bootloader will change LDO settings to
|
||||
|
@ -27,7 +27,7 @@ bootloader_usable_dram_end = 0x4087c610;
|
||||
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
|
||||
bootloader_dram_seg_len = 0x5000;
|
||||
bootloader_iram_loader_seg_len = 0x7000;
|
||||
bootloader_iram_seg_len = 0x2000;
|
||||
bootloader_iram_seg_len = 0x2100;
|
||||
|
||||
/* Start of the lower region is determined by region size and the end of the higher region */
|
||||
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
|
||||
|
@ -95,8 +95,8 @@ __attribute__((weak)) void bootloader_clock_configure(void)
|
||||
CLEAR_PERI_REG_MASK(LP_TIMER_LP_INT_ENA_REG, LP_TIMER_MAIN_TIMER_LP_INT_ENA); /* MAIN_TIMER */
|
||||
CLEAR_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_ENA_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */
|
||||
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */
|
||||
// CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); // TODO: IDF-5348 /* SLP_REJECT */
|
||||
// CLEAR_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_ENA, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
|
||||
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */
|
||||
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
|
||||
// SET CLR
|
||||
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */
|
||||
SET_PERI_REG_MASK(LP_TIMER_LP_INT_CLR_REG, LP_TIMER_MAIN_TIMER_LP_INT_CLR); /* MAIN_TIMER */
|
||||
@ -108,13 +108,13 @@ __attribute__((weak)) void bootloader_clock_configure(void)
|
||||
CLEAR_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_ENA_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */
|
||||
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */
|
||||
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */
|
||||
CLEAR_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_ENA, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
|
||||
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
|
||||
// SET CLR
|
||||
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */
|
||||
SET_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_CLR_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */
|
||||
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
|
||||
// SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); // TODO: IDF-5348 /* SLP_REJECT */
|
||||
// SET_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_CLR, PMU_SOC_SLEEP_REJECT_INT_CLR); /* SLP_WAKEUP */
|
||||
SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */
|
||||
SET_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_CLR, PMU_SOC_SLEEP_REJECT_INT_CLR); /* SLP_WAKEUP */
|
||||
#else
|
||||
REG_WRITE(RTC_CNTL_INT_ENA_REG, 0);
|
||||
REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -237,8 +237,8 @@ static inline void bootloader_hardware_init(void)
|
||||
esp_rom_spiflash_fix_dummylen(1, 1);
|
||||
#endif
|
||||
|
||||
// TODO: IDF-5990 need update, enable i2c mst clk by force on temporarily
|
||||
SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_FORCE_ON_REG, MODEM_LPCON_CLK_I2C_MST_FO);
|
||||
/* Enable analog i2c master clock */
|
||||
SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
|
||||
SET_PERI_REG_MASK(MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M);
|
||||
}
|
||||
|
||||
|
@ -844,7 +844,7 @@ TEST_CASE("GPIO_USB_DP_pin_pullup_disable_test", "[gpio]")
|
||||
}
|
||||
#endif //SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) // TODO: IDF-5348, IDF-6267 Remove when light sleep is supported
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2) // TODO: IDF-6267 Remove when light sleep is supported
|
||||
// Ignored in CI because it needs manually connect TEST_GPIO_INPUT_LEVEL_LOW_PIN to 3.3v to wake up from light sleep
|
||||
TEST_CASE("GPIO_light_sleep_wake_up_test", "[gpio][ignore]")
|
||||
{
|
||||
|
@ -470,7 +470,7 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
|
||||
p_twai_obj_dummy->module = twai_controller_periph_signals.controllers[controller_id].module;
|
||||
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#if CONFIG_PM_ENABLE && SOC_TWAI_CLK_SUPPORT_APB
|
||||
if (clk_src == TWAI_CLK_SRC_APB) {
|
||||
// TODO: pm_lock name should also reflect the controller ID
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "twai", &(p_twai_obj_dummy->pm_lock));
|
||||
@ -478,7 +478,7 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
#endif //CONFIG_PM_ENABLE && SOC_TWAI_CLK_SUPPORT_APB
|
||||
|
||||
//Initialize TWAI peripheral registers, and allocate interrupt
|
||||
TWAI_ENTER_CRITICAL();
|
||||
|
@ -30,8 +30,8 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"port/${target}/clk_tree.c"
|
||||
"port/clk_tree_common.c")
|
||||
|
||||
if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2)
|
||||
list(APPEND srcs "sleep_retention.c")
|
||||
if(CONFIG_SOC_PM_SUPPORT_CPU_PD)
|
||||
list(APPEND srcs "sleep_cpu.c")
|
||||
endif()
|
||||
|
||||
# [refactor-todo]: requires "driver" for GPIO and RTC (by sleep_gpio and sleep_modes)
|
||||
@ -73,6 +73,14 @@ if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "esp_ds.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_PM_CPU_RETENTION_BY_SW)
|
||||
list(APPEND srcs "sleep_cpu_asm.S")
|
||||
set_property(TARGET ${COMPONENT_LIB}
|
||||
APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u rv_core_critical_regs_save")
|
||||
set_property(TARGET ${COMPONENT_LIB}
|
||||
APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u rv_core_critical_regs_restore")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT)
|
||||
list(APPEND srcs "modem_clock.c")
|
||||
endif()
|
||||
|
@ -67,7 +67,7 @@ menu "Hardware Settings"
|
||||
|
||||
config ESP_SLEEP_GPIO_RESET_WORKAROUND
|
||||
bool "light sleep GPIO reset workaround"
|
||||
default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 # TODO: IDF-5641 (esp32c6)
|
||||
default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6
|
||||
select PM_SLP_DISABLE_GPIO if FREERTOS_USE_TICKLESS_IDLE
|
||||
help
|
||||
esp32c2, esp32c3 and esp32s3 will reset at wake-up if GPIO is received a small electrostatic
|
||||
|
220
components/esp_hw_support/include/esp_private/esp_pmu.h
Normal file
220
components/esp_hw_support/include/esp_private/esp_pmu.h
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
#include "hal/pmu_hal.h"
|
||||
#include "pmu_param.h"
|
||||
|
||||
#define RTC_SLEEP_PD_DIG PMU_SLEEP_PD_TOP //!< Deep sleep (power down digital domain)
|
||||
#define RTC_SLEEP_PD_RTC_PERIPH PMU_SLEEP_PD_LP_PERIPH //!< Power down RTC peripherals
|
||||
// #define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) //!< Power down RTC SLOW memory
|
||||
// #define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory
|
||||
// #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU
|
||||
#define RTC_SLEEP_PD_VDDSDIO PMU_SLEEP_PD_VDDSDIO //!< Power down VDDSDIO regulator
|
||||
#define RTC_SLEEP_PD_CPU PMU_SLEEP_PD_CPU //!< Power down CPU when in lightsleep, but not restart
|
||||
#define RTC_SLEEP_PD_DIG_PERIPH PMU_SLEEP_PD_HP_PERIPH //!< Power down DIG peripherals
|
||||
#define RTC_SLEEP_PD_INT_8M PMU_SLEEP_PD_RC_FAST //!< Power down Internal 20M oscillator
|
||||
#define RTC_SLEEP_PD_XTAL PMU_SLEEP_PD_XTAL //!< Power down main XTAL
|
||||
|
||||
//These flags are not power domains, but will affect some sleep parameters
|
||||
#define RTC_SLEEP_DIG_USE_8M BIT(16)
|
||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
|
||||
|
||||
#define RTC_GPIO_TRIG_EN PMU_GPIO_WAKEUP_EN //!< GPIO wakeup
|
||||
#define RTC_TIMER_TRIG_EN PMU_LP_TIMER_WAKEUP_EN //!< Timer wakeup
|
||||
#define RTC_WIFI_TRIG_EN PMU_WIFI_SOC_WAKEUP_EN //!< WIFI wakeup (light sleep only)
|
||||
#define RTC_UART0_TRIG_EN PMU_UART0_WAKEUP_EN //!< UART0 wakeup (light sleep only)
|
||||
#define RTC_UART1_TRIG_EN PMU_UART1_WAKEUP_EN //!< UART1 wakeup (light sleep only)
|
||||
#define RTC_BT_TRIG_EN PMU_BLE_SOC_WAKEUP_EN //!< BT wakeup (light sleep only)
|
||||
#define RTC_USB_TRIG_EN PMU_USB_WAKEUP_EN
|
||||
#define RTC_XTAL32K_DEAD_TRIG_EN 0 // TODO
|
||||
#define RTC_BROWNOUT_DET_TRIG_EN 0 // TODO
|
||||
|
||||
/**
|
||||
* RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip
|
||||
*/
|
||||
#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | \
|
||||
RTC_TIMER_TRIG_EN | \
|
||||
RTC_WIFI_TRIG_EN | \
|
||||
RTC_UART0_TRIG_EN | \
|
||||
RTC_UART1_TRIG_EN | \
|
||||
RTC_BT_TRIG_EN | \
|
||||
RTC_XTAL32K_DEAD_TRIG_EN | \
|
||||
RTC_USB_TRIG_EN | \
|
||||
RTC_BROWNOUT_DET_TRIG_EN)
|
||||
|
||||
|
||||
#define PMU_GPIO_WAKEUP_EN BIT(2)
|
||||
#define PMU_WIFI_BEACON_WAKEUP_EN BIT(3)
|
||||
#define PMU_LP_TIMER_WAKEUP_EN BIT(4)
|
||||
#define PMU_WIFI_SOC_WAKEUP_EN BIT(5)
|
||||
#define PMU_UART0_WAKEUP_EN BIT(6)
|
||||
#define PMU_UART1_WAKEUP_EN BIT(7)
|
||||
#define PMU_SDIO_WAKEUP_EN BIT(8)
|
||||
#define PMU_BLE_SOC_WAKEUP_EN BIT(10)
|
||||
#define PMU_USB_WAKEUP_EN BIT(14)
|
||||
|
||||
|
||||
#define PMU_SLEEP_PD_TOP BIT(0)
|
||||
#define PMU_SLEEP_PD_VDDSDIO BIT(1)
|
||||
#define PMU_SLEEP_PD_MODEM BIT(2)
|
||||
#define PMU_SLEEP_PD_HP_PERIPH BIT(3)
|
||||
#define PMU_SLEEP_PD_CPU BIT(4)
|
||||
#define PMU_SLEEP_PD_AON BIT(5)
|
||||
#define PMU_SLEEP_PD_MEM_G0 BIT(6)
|
||||
#define PMU_SLEEP_PD_MEM_G1 BIT(7)
|
||||
#define PMU_SLEEP_PD_MEM_G2 BIT(8)
|
||||
#define PMU_SLEEP_PD_MEM_G3 BIT(9)
|
||||
#define PMU_SLEEP_PD_XTAL BIT(10)
|
||||
#define PMU_SLEEP_PD_RC_FAST BIT(11)
|
||||
#define PMU_SLEEP_PD_XTAL32K BIT(12)
|
||||
#define PMU_SLEEP_PD_RC32K BIT(13)
|
||||
#define PMU_SLEEP_PD_LP_PERIPH BIT(14)
|
||||
|
||||
typedef struct {
|
||||
pmu_hal_context_t *hal;
|
||||
void *mc;
|
||||
} pmu_context_t;
|
||||
|
||||
pmu_context_t * PMU_instance(void);
|
||||
|
||||
typedef enum pmu_hp_sysclk_src {
|
||||
PMU_HP_SYSCLK_XTAL = 0,
|
||||
PMU_HP_SYSCLK_PLL,
|
||||
PMU_HP_SYSCLK_FOSC
|
||||
} pmu_hp_sysclk_src_t;
|
||||
|
||||
typedef enum pmu_sleep_protect_mode {
|
||||
PMU_SLEEP_PROTECT_HP_SLEEP = 0,
|
||||
PMU_SLEEP_PROTECT_XTAL,
|
||||
PMU_SLEEP_PROTECT_HP_LP_SLEEP,
|
||||
PMU_SLEEP_PROTECT_DISABLE
|
||||
} pmu_sleep_protect_mode_t;
|
||||
|
||||
typedef enum pmu_sleep_regdma_entry {
|
||||
PMU_SLEEP_REGDMA_ENTRY_0 = 0,
|
||||
PMU_SLEEP_REGDMA_ENTRY_1,
|
||||
PMU_SLEEP_REGDMA_ENTRY_2,
|
||||
PMU_SLEEP_REGDMA_ENTRY_3,
|
||||
PMU_SLEEP_REGDMA_ENTRY_MAX
|
||||
} pmu_sleep_regdma_entry_t;
|
||||
|
||||
/**
|
||||
* @brief PMU ICG modem code of HP system
|
||||
*/
|
||||
typedef enum {
|
||||
PMU_HP_ICG_MODEM_CODE_SLEEP = 0,
|
||||
PMU_HP_ICG_MODEM_CODE_MODEM = 1,
|
||||
PMU_HP_ICG_MODEM_CODE_ACTIVE = 2,
|
||||
} pmu_hp_icg_modem_mode_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable_regdma_backup.
|
||||
*/
|
||||
void pmu_sleep_enable_regdma_backup(void);
|
||||
|
||||
/**
|
||||
* @brief Disable_regdma_backup.
|
||||
*/
|
||||
void pmu_sleep_disable_regdma_backup(void);
|
||||
|
||||
/**
|
||||
* @brief Calculate the hardware time overhead during sleep to compensate for sleep time
|
||||
*
|
||||
* @param pd_flags flags indicates the power domain that will be powered down
|
||||
* @param slowclk_period re-calibrated slow clock period
|
||||
* @param fastclk_period re-calibrated fast clock period
|
||||
*
|
||||
* @return hardware time overhead in us
|
||||
*/
|
||||
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period);
|
||||
|
||||
/**
|
||||
* @brief Get default sleep configuration
|
||||
* @param config pmu_sleep_config instance
|
||||
* @param pd_flags flags indicates the power domain that will be powered down
|
||||
* @param adjustment total software and hardware time overhead
|
||||
* @param slowclk_period re-calibrated slow clock period in microseconds,
|
||||
* Q13.19 fixed point format
|
||||
* @param fastclk_period re-calibrated fast clock period in microseconds,
|
||||
* Q13.19 fixed point format
|
||||
* @param dslp configuration for deep sleep mode
|
||||
|
||||
* @return hardware time overhead in us
|
||||
*/
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, uint32_t pd_flags, uint32_t adjustment, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp);
|
||||
|
||||
/**
|
||||
* @brief Prepare the chip to enter sleep mode
|
||||
*
|
||||
* This function configures various power/analog parameters and lp/lp system configuration
|
||||
* used in sleep state machines
|
||||
*
|
||||
* This function does not actually enter sleep mode; this is done using
|
||||
* pmu_sleep_start function. Software may do some other actions between
|
||||
* pmu_sleep_init and pmu_sleep_start, such as set wakeup timer and configure
|
||||
* wakeup sources.
|
||||
*
|
||||
* @param config sleep mode configuration
|
||||
*
|
||||
* @param dslp is initialize for deep sleep mode
|
||||
*/
|
||||
void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp);
|
||||
|
||||
/**
|
||||
* @brief Enter deep or light sleep mode
|
||||
*
|
||||
* This function enters the sleep mode previously configured using pmu_sleep_init
|
||||
* function. Before entering sleep, software should configure wake up sources
|
||||
* appropriately (set up GPIO wakeup registers, timer wakeup registers,
|
||||
* and so on).
|
||||
*
|
||||
* If deep sleep mode was configured using pmu_sleep_init, and sleep is not
|
||||
* rejected by hardware (based on reject_opt flags), this function never returns.
|
||||
* When the chip wakes up from deep sleep, CPU is reset and execution starts
|
||||
* from ROM bootloader.
|
||||
*
|
||||
* If light sleep mode was configured using pmu_sleep_init, this function
|
||||
* returns on wakeup, or if sleep is rejected by hardware.
|
||||
*
|
||||
* @param wakeup_opt bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags
|
||||
* combined with OR)
|
||||
* @param reject_opt bit mask of sleep reject reasons, used to
|
||||
* prevent wakeup source set before the sleep request)
|
||||
* @param lslp_mem_inf_fpu If non-zero then the low power config is restored
|
||||
* immediately on wake. Recommended for light sleep,
|
||||
* has no effect if the system goes into deep sleep.
|
||||
*
|
||||
* @return non-zero if sleep was rejected by hardware
|
||||
*/
|
||||
uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
|
||||
|
||||
/**
|
||||
* @brief Initialize PMU related power/clock/digital parameters and functions
|
||||
*/
|
||||
void pmu_init(void);
|
||||
|
||||
|
||||
#endif //#if SOC_PMU_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
63
components/esp_hw_support/include/esp_private/sleep_cpu.h
Normal file
63
components/esp_hw_support/include/esp_private/sleep_cpu.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file sleep_cpu.h
|
||||
*
|
||||
* This file contains declarations of cpu retention related functions in light sleep mode.
|
||||
*/
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
|
||||
/**
|
||||
* @brief Whether to allow the cpu power domain to be powered off.
|
||||
*
|
||||
* In light sleep mode, only when the system can provide enough memory
|
||||
* for cpu retention, the cpu power domain can be powered off.
|
||||
*/
|
||||
bool cpu_domain_pd_allowed(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
|
||||
/**
|
||||
* @brief Enable cpu retention of some modules.
|
||||
*
|
||||
* In light sleep mode, before the system goes to sleep, enable the cpu
|
||||
* retention of modules such as CPU and I/D-cache tag memory.
|
||||
*/
|
||||
void sleep_enable_cpu_retention(void);
|
||||
|
||||
/**
|
||||
* @brief Disable cpu retention of some modules.
|
||||
*
|
||||
* In light sleep mode, after the system exits sleep, disable the cpu
|
||||
* retention of moudles such as CPU and I/D-cache tag memory.
|
||||
*/
|
||||
void sleep_disable_cpu_retention(void);
|
||||
|
||||
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
|
||||
|
||||
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file sleep_retention.h
|
||||
*
|
||||
* This file contains declarations of memory retention related functions in light sleeo mode.
|
||||
*/
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
|
||||
/**
|
||||
* @brief Whether to allow the cpu power domain to be powered off.
|
||||
*
|
||||
* In light sleep mode, only when the system can provide enough memory
|
||||
* for cpu retention, the cpu power domain can be powered off.
|
||||
*/
|
||||
bool cpu_domain_pd_allowed(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
|
||||
|
||||
/**
|
||||
* @brief Enable memory retention of some modules.
|
||||
*
|
||||
* In light sleep mode, before the system goes to sleep, enable the memory
|
||||
* retention of modules such as CPU and I/D-cache tag memory.
|
||||
*/
|
||||
void sleep_enable_memory_retention(void);
|
||||
|
||||
/**
|
||||
* @brief Disable memory retention of some modules.
|
||||
*
|
||||
* In light sleep mode, after the system exits sleep, disable the memory
|
||||
* retention of moudles such as CPU and I/D-cache tag memory.
|
||||
*/
|
||||
void sleep_disable_memory_retention(void);
|
||||
|
||||
#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -48,10 +48,10 @@ typedef enum {
|
||||
#endif
|
||||
ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator
|
||||
#if SOC_PM_SUPPORT_XTAL32K_PD
|
||||
ESP_PD_DOMAIN_XTAL32K,
|
||||
ESP_PD_DOMAIN_XTAL32K, //!< External 32 kHz XTAL oscillator
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RC32K_PD
|
||||
ESP_PD_DOMAIN_RC32K,
|
||||
ESP_PD_DOMAIN_RC32K, //!< Internal 32 kHz RC oscillator
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RC_FAST_PD
|
||||
ESP_PD_DOMAIN_RC_FAST, //!< Internal Fast oscillator
|
||||
@ -59,7 +59,9 @@ typedef enum {
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
ESP_PD_DOMAIN_CPU, //!< CPU core
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
ESP_PD_DOMAIN_VDDSDIO, //!< VDD_SDIO
|
||||
#endif
|
||||
ESP_PD_DOMAIN_MAX //!< Number of domains
|
||||
} esp_sleep_pd_domain_t;
|
||||
|
||||
@ -484,15 +486,44 @@ void esp_default_wake_deep_sleep(void);
|
||||
void esp_deep_sleep_disable_rom_logging(void);
|
||||
|
||||
#ifdef SOC_PM_SUPPORT_CPU_PD
|
||||
|
||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
/**
|
||||
* @brief CPU Power down low-level initialize
|
||||
*
|
||||
* @param enable enable or disable CPU power down during light sleep
|
||||
* @brief CPU Power down low-level initialize, enable CPU power down during light sleep
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM not enough retention memory
|
||||
*/
|
||||
esp_err_t esp_sleep_cpu_pd_low_init(bool enable);
|
||||
esp_err_t esp_sleep_cpu_pd_low_init(void);
|
||||
|
||||
/**
|
||||
* @brief CPU Power down low-level deinitialize, disable CPU power down during light sleep
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM not enough retention memory
|
||||
*/
|
||||
esp_err_t esp_sleep_cpu_pd_low_deinit(void);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CPU Power down initialize
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM not enough retention memory
|
||||
*/
|
||||
esp_err_t esp_sleep_cpu_retention_init(void);
|
||||
|
||||
/**
|
||||
* @brief CPU Power down de-initialize
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*
|
||||
* Release system retention memory.
|
||||
*/
|
||||
esp_err_t esp_sleep_cpu_retention_deinit(void);
|
||||
#endif
|
||||
|
||||
#if SOC_GPIO_SUPPORT_SLP_SWITCH
|
||||
|
@ -13,11 +13,14 @@ entries:
|
||||
cpu: esp_cpu_compare_and_set (noflash)
|
||||
esp_memory_utils (noflash)
|
||||
rtc_clk (noflash)
|
||||
if IDF_TARGET_ESP32C6 = n && IDF_TARGET_ESP32H2 = n: # TODO: IDF-5645
|
||||
if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED:
|
||||
rtc_init:rtc_vddsdio_set_config (noflash)
|
||||
if IDF_TARGET_ESP32C6 = n && IDF_TARGET_ESP32H2 = n: # TODO: IDF-5645
|
||||
rtc_pm (noflash_text)
|
||||
rtc_sleep (noflash_text)
|
||||
rtc_time (noflash_text)
|
||||
if SOC_PMU_SUPPORTED = y:
|
||||
pmu_sleep (noflash)
|
||||
if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y:
|
||||
rtc_wdt (noflash_text)
|
||||
if PERIPH_CTRL_FUNC_IN_IRAM = y:
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -13,6 +13,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#include "esp_private/esp_modem_clock.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
// Please define the frequently called modules in the low bit,
|
||||
@ -136,30 +137,25 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi
|
||||
return &modem_clock_context;
|
||||
}
|
||||
|
||||
|
||||
// TODO: IDF-5351: move to esp_pmu.h after support pmu driver
|
||||
#define PMU_SLEEP 0
|
||||
#define PMU_MODEM 1
|
||||
#define PMU_ACTIVE 2
|
||||
#define SLEEP_MODE BIT(PMU_SLEEP)
|
||||
#define MODEM_MODE BIT(PMU_MODEM)
|
||||
#define ACTIVE_MODE BIT(PMU_ACTIVE)
|
||||
|
||||
static void IRAM_ATTR modem_clock_domain_power_state_icg_map_init(modem_clock_context_t *ctx)
|
||||
{
|
||||
#define ICG_NOGATING_SLEEP (BIT(PMU_HP_ICG_MODEM_CODE_SLEEP))
|
||||
#define ICG_NOGATING_MODEM (BIT(PMU_HP_ICG_MODEM_CODE_MODEM))
|
||||
#define ICG_NOGATING_ACTIVE (BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE))
|
||||
|
||||
/* the ICG code's bit 0, 1 and 2 indicates the ICG state
|
||||
* of pmu SLEEP, MODEM and ACTIVE mode respectively */
|
||||
const uint32_t code[MODEM_CLOCK_DOMAIN_MAX] = {
|
||||
[MODEM_CLOCK_DOMAIN_MODEM_APB] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_WIFI] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_BT] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_FE] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_IEEE802154] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_LP_APB] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_I2C_MASTER] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_COEX] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_WIFIPWR] = MODEM_MODE | ACTIVE_MODE,
|
||||
[MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE,
|
||||
[MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
[MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM,
|
||||
};
|
||||
for (modem_clock_domain_t domain = MODEM_CLOCK_DOMAIN_MODEM_APB; domain < MODEM_CLOCK_DOMAIN_MAX; domain++) {
|
||||
modem_clock_hal_set_clock_domain_icg_bitmap(ctx->hal, domain, code[domain]);
|
||||
@ -167,16 +163,8 @@ static void IRAM_ATTR modem_clock_domain_power_state_icg_map_init(modem_clock_co
|
||||
}
|
||||
|
||||
|
||||
#include "soc/pmu_reg.h"
|
||||
void modem_clock_domain_pmu_state_icg_map_init(void)
|
||||
{
|
||||
// Set modem clock ICG code map, should implement with pmu driver // TODO: IDF-5351
|
||||
REG_SET_FIELD(PMU_HP_SLEEP_ICG_MODEM_REG, PMU_HP_SLEEP_DIG_ICG_MODEM_CODE, PMU_SLEEP);
|
||||
REG_SET_FIELD(PMU_HP_MODEM_ICG_MODEM_REG, PMU_HP_MODEM_DIG_ICG_MODEM_CODE, PMU_MODEM);
|
||||
REG_SET_FIELD(PMU_HP_ACTIVE_ICG_MODEM_REG, PMU_HP_ACTIVE_DIG_ICG_MODEM_CODE, PMU_ACTIVE);
|
||||
REG_SET_BIT(PMU_IMM_MODEM_ICG_REG, PMU_UPDATE_DIG_ICG_MODEM_EN);
|
||||
REG_SET_BIT(PMU_IMM_SLEEP_SYSCLK_REG, PMU_UPDATE_DIG_ICG_SWITCH);
|
||||
|
||||
modem_clock_domain_power_state_icg_map_init(MODEM_CLOCK_instance());
|
||||
}
|
||||
|
||||
|
@ -129,16 +129,6 @@ void rtc_init(rtc_config_t cfg)
|
||||
#endif
|
||||
}
|
||||
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void)
|
||||
{
|
||||
rtc_vddsdio_config_t result = {0};
|
||||
return result;
|
||||
}
|
||||
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config)
|
||||
{
|
||||
}
|
||||
|
||||
static void set_ocode_by_efuse(int ocode_scheme_ver)
|
||||
{
|
||||
assert(ocode_scheme_ver == 1);
|
||||
|
@ -159,43 +159,6 @@ void rtc_init(rtc_config_t cfg)
|
||||
#endif
|
||||
}
|
||||
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void)
|
||||
{
|
||||
rtc_vddsdio_config_t result;
|
||||
uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG);
|
||||
result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S;
|
||||
result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S;
|
||||
result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S;
|
||||
if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) {
|
||||
// Get configuration from RTC
|
||||
result.force = 1;
|
||||
result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S;
|
||||
result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S;
|
||||
return result;
|
||||
} else {
|
||||
result.force = 0;
|
||||
}
|
||||
|
||||
// Otherwise, VDD_SDIO is controlled by bootstrapping pin
|
||||
uint32_t strap_reg = REG_READ(GPIO_STRAP_REG);
|
||||
result.force = 0;
|
||||
result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V;
|
||||
result.enable = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
val |= (config.force << RTC_CNTL_SDIO_FORCE_S);
|
||||
val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S);
|
||||
val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S);
|
||||
val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S);
|
||||
val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S);
|
||||
val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S);
|
||||
val |= RTC_CNTL_SDIO_PD_EN;
|
||||
REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val);
|
||||
}
|
||||
|
||||
static void set_ocode_by_efuse(int calib_version)
|
||||
{
|
||||
|
@ -1,10 +1,11 @@
|
||||
set(srcs "rtc_clk_init.c"
|
||||
"rtc_clk.c"
|
||||
"rtc_init.c"
|
||||
# "rtc_pm.c" // TODO: IDF-5645
|
||||
# "rtc_sleep.c" // TODO: IDF-5645
|
||||
"pmu_param.c"
|
||||
"pmu_init.c"
|
||||
"pmu_sleep.c"
|
||||
"rtc_time.c"
|
||||
"chip_info.c")
|
||||
"chip_info.c"
|
||||
)
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "sar_periph_ctrl.c"
|
||||
|
207
components/esp_hw_support/port/esp32c6/pmu_init.c
Normal file
207
components/esp_hw_support/port/esp32c6/pmu_init.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
#include "pmu_param.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "pmu_init";
|
||||
|
||||
typedef struct {
|
||||
const pmu_hp_system_power_param_t *power;
|
||||
const pmu_hp_system_clock_param_t *clock;
|
||||
const pmu_hp_system_digital_param_t *digital;
|
||||
const pmu_hp_system_analog_param_t *analog;
|
||||
const pmu_hp_system_retention_param_t *retent;
|
||||
} pmu_hp_system_param_t;
|
||||
|
||||
typedef struct {
|
||||
const pmu_lp_system_power_param_t *power;
|
||||
const pmu_lp_system_analog_param_t *analog;
|
||||
} pmu_lp_system_param_t;
|
||||
|
||||
pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
{
|
||||
/* It should be explicitly defined in the internal RAM, because this
|
||||
* instance will be used in pmu_sleep.c */
|
||||
static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU };
|
||||
static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT();
|
||||
static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc };
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
|
||||
{
|
||||
const pmu_hp_system_power_param_t *power = param->power;
|
||||
const pmu_hp_system_clock_param_t *clock = param->clock;
|
||||
const pmu_hp_system_digital_param_t *dig = param->digital;
|
||||
const pmu_hp_system_analog_param_t *anlg = param->analog;
|
||||
const pmu_hp_system_retention_param_t *ret = param->retent;
|
||||
|
||||
assert(ctx->hal);
|
||||
/* Default configuration of hp-system power in active, modem and sleep modes */
|
||||
pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val);
|
||||
pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val);
|
||||
pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal);
|
||||
|
||||
/* Default configuration of hp-system clock in active, modem and sleep modes */
|
||||
pmu_ll_hp_set_icg_func (ctx->hal->dev, mode, clock->icg_func);
|
||||
pmu_ll_hp_set_icg_apb (ctx->hal->dev, mode, clock->icg_apb);
|
||||
pmu_ll_hp_set_icg_modem (ctx->hal->dev, mode, clock->icg_modem.code);
|
||||
pmu_ll_hp_set_sysclk_nodiv (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_nodiv);
|
||||
pmu_ll_hp_set_icg_sysclk_enable (ctx->hal->dev, mode, clock->sysclk.icg_sysclk_en);
|
||||
pmu_ll_hp_set_sysclk_slp_sel (ctx->hal->dev, mode, clock->sysclk.sysclk_slp_sel);
|
||||
pmu_ll_hp_set_icg_sysclk_slp_sel(ctx->hal->dev, mode, clock->sysclk.icg_slp_sel);
|
||||
pmu_ll_hp_set_dig_sysclk (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_sel);
|
||||
|
||||
/* Default configuration of hp-system digital sub-system in active, modem
|
||||
* and sleep modes */
|
||||
pmu_ll_hp_set_uart_wakeup_enable(ctx->hal->dev, mode, dig->syscntl.uart_wakeup_en);
|
||||
pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, mode, dig->syscntl.lp_pad_hold_all);
|
||||
pmu_ll_hp_set_hold_all_hp_pad (ctx->hal->dev, mode, dig->syscntl.hp_pad_hold_all);
|
||||
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, mode, dig->syscntl.dig_pad_slp_sel);
|
||||
pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, mode, dig->syscntl.dig_pause_wdt);
|
||||
pmu_ll_hp_set_cpu_stall (ctx->hal->dev, mode, dig->syscntl.dig_cpu_stall);
|
||||
|
||||
/* Default configuration of hp-system analog sub-system in active, modem and
|
||||
* sleep modes */
|
||||
pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias);
|
||||
pmu_ll_hp_set_dbg_atten (ctx->hal->dev, mode, anlg->bias.dbg_atten);
|
||||
pmu_ll_hp_set_current_power_off (ctx->hal->dev, mode, anlg->bias.pd_cur);
|
||||
pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias);
|
||||
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias);
|
||||
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
|
||||
|
||||
/* Default configuration of hp-system retention sub-system in active, modem
|
||||
* and sleep modes */
|
||||
pmu_ll_hp_set_retention_param(ctx->hal->dev, mode, ret->retention.val);
|
||||
pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, ret->backup_clk);
|
||||
|
||||
/* Some PMU initial parameter configuration */
|
||||
pmu_ll_imm_update_dig_icg_modem_code(ctx->hal->dev, true);
|
||||
pmu_ll_imm_update_dig_icg_switch(ctx->hal->dev, true);
|
||||
|
||||
pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP);
|
||||
}
|
||||
|
||||
void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
|
||||
{
|
||||
const pmu_lp_system_power_param_t *power = param->power;
|
||||
const pmu_lp_system_analog_param_t *anlg = param->analog;
|
||||
|
||||
assert(ctx->hal);
|
||||
/* Default configuration of lp-system power in active and sleep modes */
|
||||
pmu_ll_lp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val);
|
||||
pmu_ll_lp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val);
|
||||
pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, power->xtal.xpd_xtal);
|
||||
|
||||
/* Default configuration of lp-system analog sub-system in active and
|
||||
* sleep modes */
|
||||
pmu_ll_lp_set_bias_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.xpd_bias);
|
||||
pmu_ll_lp_set_dbg_atten (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.dbg_atten);
|
||||
pmu_ll_lp_set_current_power_off (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.pd_cur);
|
||||
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.bias_sleep);
|
||||
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_xpd);
|
||||
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
|
||||
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_dbias);
|
||||
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias);
|
||||
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
|
||||
}
|
||||
|
||||
static inline void pmu_power_domain_force_default(pmu_context_t *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
// for bypass reserved power domain
|
||||
const pmu_hp_power_domain_t pmu_hp_domains[] = {
|
||||
PMU_HP_PD_TOP,
|
||||
PMU_HP_PD_AON,
|
||||
PMU_HP_PD_CPU,
|
||||
PMU_HP_PD_WIFI
|
||||
};
|
||||
|
||||
for (uint8_t idx = 0; idx < (sizeof(pmu_hp_domains) / sizeof(pmu_hp_power_domain_t)); idx++) {
|
||||
pmu_ll_hp_set_power_force_reset (ctx->hal->dev, pmu_hp_domains[idx], false);
|
||||
pmu_ll_hp_set_power_force_isolate (ctx->hal->dev, pmu_hp_domains[idx], false);
|
||||
pmu_ll_hp_set_power_force_power_up (ctx->hal->dev, pmu_hp_domains[idx], false);
|
||||
pmu_ll_hp_set_power_force_no_reset (ctx->hal->dev, pmu_hp_domains[idx], false);
|
||||
pmu_ll_hp_set_power_force_no_isolate(ctx->hal->dev, pmu_hp_domains[idx], false);
|
||||
pmu_ll_hp_set_power_force_power_down(ctx->hal->dev, pmu_hp_domains[idx], false);
|
||||
}
|
||||
/* Isolate all memory banks while sleeping, avoid memory leakage current */
|
||||
pmu_ll_hp_set_memory_no_isolate (ctx->hal->dev, 0);
|
||||
|
||||
pmu_ll_lp_set_power_force_reset (ctx->hal->dev, false);
|
||||
pmu_ll_lp_set_power_force_isolate (ctx->hal->dev, false);
|
||||
pmu_ll_lp_set_power_force_power_up (ctx->hal->dev, false);
|
||||
pmu_ll_lp_set_power_force_no_reset (ctx->hal->dev, false);
|
||||
pmu_ll_lp_set_power_force_no_isolate(ctx->hal->dev, false);
|
||||
pmu_ll_lp_set_power_force_power_down(ctx->hal->dev, false);
|
||||
}
|
||||
|
||||
static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
|
||||
{
|
||||
param->power = pmu_hp_system_power_param_default(mode);
|
||||
param->clock = pmu_hp_system_clock_param_default(mode);
|
||||
param->digital = pmu_hp_system_digital_param_default(mode);
|
||||
param->analog = pmu_hp_system_analog_param_default(mode);
|
||||
param->retent = pmu_hp_system_retention_param_default(mode);
|
||||
}
|
||||
|
||||
static void pmu_hp_system_init_default(pmu_context_t *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
pmu_hp_system_param_t param = { 0 };
|
||||
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
|
||||
pmu_hp_system_param_default(mode, ¶m);
|
||||
pmu_hp_system_init(ctx, mode, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
|
||||
{
|
||||
param->power = pmu_lp_system_power_param_default(mode);
|
||||
param->analog = pmu_lp_system_analog_param_default(mode);
|
||||
}
|
||||
|
||||
static void pmu_lp_system_init_default(pmu_context_t *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
pmu_lp_system_param_t param;
|
||||
for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) {
|
||||
pmu_lp_system_param_default(mode, ¶m);
|
||||
pmu_lp_system_init(ctx, mode, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
void pmu_init(void)
|
||||
{
|
||||
/* Peripheral reg i2c power up */
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
|
||||
|
||||
pmu_hp_system_init_default(PMU_instance());
|
||||
pmu_lp_system_init_default(PMU_instance());
|
||||
|
||||
pmu_power_domain_force_default(PMU_instance());
|
||||
}
|
441
components/esp_hw_support/port/esp32c6/pmu_param.c
Normal file
441
components/esp_hw_support/port/esp32c6/pmu_param.c
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "pmu_param.h"
|
||||
#include "soc/pmu_icg_mapping.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
#define PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT() { \
|
||||
.dig_power = { \
|
||||
.vdd_spi_pd_en = 0, \
|
||||
.mem_dslp = 0, \
|
||||
.mem_pd_en = 0, \
|
||||
.wifi_pd_en = 0, \
|
||||
.cpu_pd_en = 0, \
|
||||
.aon_pd_en = 0, \
|
||||
.top_pd_en = 0 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 0, \
|
||||
.i2c_retention = 0, \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_bbpll_i2c = 1, \
|
||||
.xpd_bbpll = 1 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_MODEM_POWER_CONFIG_DEFAULT() { \
|
||||
.dig_power = { \
|
||||
.vdd_spi_pd_en = 0, \
|
||||
.mem_dslp = 0, \
|
||||
.mem_pd_en = 0, \
|
||||
.wifi_pd_en = 0, \
|
||||
.cpu_pd_en = 1, \
|
||||
.aon_pd_en = 0, \
|
||||
.top_pd_en = 0 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 0, \
|
||||
.i2c_retention = 0, \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_bbpll_i2c = 1, \
|
||||
.xpd_bbpll = 1 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() { \
|
||||
.dig_power = { \
|
||||
.vdd_spi_pd_en = 1, \
|
||||
.mem_dslp = 0, \
|
||||
.mem_pd_en = 0, \
|
||||
.wifi_pd_en = 1, \
|
||||
.cpu_pd_en = 0, \
|
||||
.aon_pd_en = 0, \
|
||||
.top_pd_en = 0 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 1, \
|
||||
.i2c_retention = 1, \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_bbpll_i2c = 0, \
|
||||
.xpd_bbpll = 0, \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 0 \
|
||||
} \
|
||||
}
|
||||
|
||||
const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mode_t mode)
|
||||
{
|
||||
static const pmu_hp_system_power_param_t hp_power[] = {
|
||||
PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT(),
|
||||
PMU_HP_MODEM_POWER_CONFIG_DEFAULT(),
|
||||
PMU_HP_SLEEP_POWER_CONFIG_DEFAULT()
|
||||
};
|
||||
assert(mode < ARRAY_SIZE(hp_power));
|
||||
return &hp_power[mode];
|
||||
}
|
||||
|
||||
#define PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT() { \
|
||||
.icg_func = 0xffffffff, \
|
||||
.icg_apb = 0xffffffff, \
|
||||
.icg_modem = { \
|
||||
.code = PMU_HP_ICG_MODEM_CODE_ACTIVE \
|
||||
}, \
|
||||
.sysclk = { \
|
||||
.dig_sysclk_nodiv = 0, \
|
||||
.icg_sysclk_en = 1, \
|
||||
.sysclk_slp_sel = 0, \
|
||||
.icg_slp_sel = 0, \
|
||||
.dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT() { \
|
||||
.icg_func = 0, \
|
||||
.icg_apb = 0, \
|
||||
.icg_modem = { \
|
||||
.code = PMU_HP_ICG_MODEM_CODE_MODEM \
|
||||
}, \
|
||||
.sysclk = { \
|
||||
.dig_sysclk_nodiv = 0, \
|
||||
.icg_sysclk_en = 1, \
|
||||
.sysclk_slp_sel = 1, \
|
||||
.icg_slp_sel = 1, \
|
||||
.dig_sysclk_sel = PMU_HP_SYSCLK_PLL \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() { \
|
||||
.icg_func = 0, \
|
||||
.icg_apb = 0, \
|
||||
.icg_modem = { \
|
||||
.code = PMU_HP_ICG_MODEM_CODE_SLEEP \
|
||||
}, \
|
||||
.sysclk = { \
|
||||
.dig_sysclk_nodiv = 0, \
|
||||
.icg_sysclk_en = 0, \
|
||||
.sysclk_slp_sel = 1, \
|
||||
.icg_slp_sel = 1, \
|
||||
.dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \
|
||||
} \
|
||||
}
|
||||
|
||||
const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mode_t mode)
|
||||
{
|
||||
static const pmu_hp_system_clock_param_t hp_clock[] = {
|
||||
PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT(),
|
||||
PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT(),
|
||||
PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT()
|
||||
};
|
||||
assert(mode < ARRAY_SIZE(hp_clock));
|
||||
return &hp_clock[mode];
|
||||
}
|
||||
|
||||
#define PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT() { \
|
||||
.syscntl = { \
|
||||
.uart_wakeup_en = 0, \
|
||||
.lp_pad_hold_all = 0, \
|
||||
.hp_pad_hold_all = 0, \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.dig_pause_wdt = 0, \
|
||||
.dig_cpu_stall = 0 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT() { \
|
||||
.syscntl = { \
|
||||
.uart_wakeup_en = 1, \
|
||||
.lp_pad_hold_all = 0, \
|
||||
.hp_pad_hold_all = 0, \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.dig_pause_wdt = 1, \
|
||||
.dig_cpu_stall = 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \
|
||||
.syscntl = { \
|
||||
.uart_wakeup_en = 1, \
|
||||
.lp_pad_hold_all = 0, \
|
||||
.hp_pad_hold_all = 0, \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = 1, \
|
||||
.dig_cpu_stall = 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp_mode_t mode)
|
||||
{
|
||||
static const pmu_hp_system_digital_param_t hp_digital[] = {
|
||||
PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT(),
|
||||
PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT(),
|
||||
PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT()
|
||||
};
|
||||
assert(mode < ARRAY_SIZE(hp_digital));
|
||||
return &hp_digital[mode];
|
||||
}
|
||||
|
||||
#define PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \
|
||||
.bias = { \
|
||||
.xpd_bias = 1, \
|
||||
.dbg_atten = 0x0, \
|
||||
.pd_cur = 0, \
|
||||
.bias_sleep = 0 \
|
||||
}, \
|
||||
.regulator0 = { \
|
||||
.lp_dbias_vol = 0xd, \
|
||||
.hp_dbias_vol = 0x1c,\
|
||||
.dbias_sel = 1, \
|
||||
.dbias_init = 1, \
|
||||
.slp_mem_xpd = 0, \
|
||||
.slp_logic_xpd = 0, \
|
||||
.xpd = 1, \
|
||||
.slp_mem_dbias = 0xc, \
|
||||
.slp_logic_dbias = 0xc, \
|
||||
.dbias = 0x19 \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT() { \
|
||||
.bias = { \
|
||||
.xpd_bias = 0, \
|
||||
.dbg_atten = 0x0, \
|
||||
.pd_cur = 0, \
|
||||
.bias_sleep = 0 \
|
||||
}, \
|
||||
.regulator0 = { \
|
||||
.slp_mem_xpd = 0, \
|
||||
.slp_logic_xpd = 0, \
|
||||
.xpd = 1, \
|
||||
.slp_mem_dbias = 0xc, \
|
||||
.slp_logic_dbias = 0xc, \
|
||||
.dbias = 0x1a \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \
|
||||
.bias = { \
|
||||
.xpd_bias = 0, \
|
||||
.dbg_atten = 0x0, \
|
||||
.pd_cur = 0, \
|
||||
.bias_sleep = 0 \
|
||||
}, \
|
||||
.regulator0 = { \
|
||||
.slp_mem_xpd = 1, \
|
||||
.slp_logic_xpd = 1, \
|
||||
.xpd = 0, \
|
||||
.slp_mem_dbias = 0x4, \
|
||||
.slp_logic_dbias = 0x4, \
|
||||
.dbias = 0x1a \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
}
|
||||
|
||||
const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_mode_t mode)
|
||||
{
|
||||
static const pmu_hp_system_analog_param_t hp_analog[] = {
|
||||
PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT(),
|
||||
PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT(),
|
||||
PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT()
|
||||
};
|
||||
assert(mode < ARRAY_SIZE(hp_analog));
|
||||
return &hp_analog[mode];
|
||||
}
|
||||
|
||||
#define PMU_HP_RETENTION_REGDMA_CONFIG(dir, entry) ((((dir)<<2) | (entry & 0x3)) & 0x7)
|
||||
|
||||
#define PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT() { \
|
||||
.retention = { \
|
||||
.hp_sleep2active_backup_modem_clk_code = 2, \
|
||||
.hp_modem2active_backup_modem_clk_code = 2, \
|
||||
.hp_active_retention_mode = 0, \
|
||||
.hp_sleep2active_retention_en = 0, \
|
||||
.hp_modem2active_retention_en = 0, \
|
||||
.hp_sleep2active_backup_clk_sel = 0, \
|
||||
.hp_modem2active_backup_clk_sel = 0, \
|
||||
.hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \
|
||||
.hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \
|
||||
.hp_sleep2active_backup_en = 0, \
|
||||
.hp_modem2active_backup_en = 0, \
|
||||
}, \
|
||||
.backup_clk = ( \
|
||||
BIT(PMU_ICG_FUNC_ENA_REGDMA) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG1) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_HPBUS) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_MSPI) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_IOMUX) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_SPI2) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_UART0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \
|
||||
) \
|
||||
}
|
||||
|
||||
#define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \
|
||||
.retention = { \
|
||||
.hp_sleep2modem_backup_modem_clk_code = 1, \
|
||||
.hp_modem_retention_mode = 0, \
|
||||
.hp_sleep2modem_retention_en = 0, \
|
||||
.hp_sleep2modem_backup_clk_sel = 0, \
|
||||
.hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \
|
||||
.hp_sleep2modem_backup_en = 0, \
|
||||
}, \
|
||||
.backup_clk = ( \
|
||||
BIT(PMU_ICG_FUNC_ENA_REGDMA) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG1) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_HPBUS) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_MSPI) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_IOMUX) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_SPI2) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_UART0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \
|
||||
) \
|
||||
}
|
||||
|
||||
#define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \
|
||||
.retention = { \
|
||||
.hp_modem2sleep_backup_modem_clk_code = 0, \
|
||||
.hp_active2sleep_backup_modem_clk_code = 2, \
|
||||
.hp_sleep_retention_mode = 0, \
|
||||
.hp_modem2sleep_retention_en = 0, \
|
||||
.hp_active2sleep_retention_en = 0, \
|
||||
.hp_modem2sleep_backup_clk_sel = 0, \
|
||||
.hp_active2sleep_backup_clk_sel = 0, \
|
||||
.hp_modem2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 1), \
|
||||
.hp_active2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 0), \
|
||||
.hp_modem2sleep_backup_en = 0, \
|
||||
.hp_active2sleep_backup_en = 0, \
|
||||
}, \
|
||||
.backup_clk = ( \
|
||||
BIT(PMU_ICG_FUNC_ENA_REGDMA) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_TG1) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_HPBUS) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_MSPI) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_IOMUX) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_SPI2) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_UART0) | \
|
||||
BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \
|
||||
) \
|
||||
}
|
||||
|
||||
const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode)
|
||||
{
|
||||
static const pmu_hp_system_retention_param_t hp_retention[] = {
|
||||
PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT(),
|
||||
PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT(),
|
||||
PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT()
|
||||
};
|
||||
assert(mode < ARRAY_SIZE(hp_retention));
|
||||
return &hp_retention[mode];
|
||||
}
|
||||
|
||||
|
||||
/** LP system default parameter */
|
||||
|
||||
#define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \
|
||||
.dig_power = { \
|
||||
.mem_dslp = 0, \
|
||||
.peri_pd_en = 0, \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.xpd_xtal32k = 1, \
|
||||
.xpd_rc32k = 1, \
|
||||
.xpd_fosc = 1, \
|
||||
.pd_osc = 0 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() { \
|
||||
.dig_power = { \
|
||||
.mem_dslp = 1, \
|
||||
.peri_pd_en = 0, \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.xpd_xtal32k = 0, \
|
||||
.xpd_rc32k = 0, \
|
||||
.xpd_fosc = 0, \
|
||||
.pd_osc = 0 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 0 \
|
||||
} \
|
||||
}
|
||||
|
||||
const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mode_t mode)
|
||||
{
|
||||
static const pmu_lp_system_power_param_t lp_power[] = {
|
||||
PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT(),
|
||||
PMU_LP_SLEEP_POWER_CONFIG_DEFAULT()
|
||||
};
|
||||
assert(mode < ARRAY_SIZE(lp_power));
|
||||
return &lp_power[mode];
|
||||
}
|
||||
|
||||
#define PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \
|
||||
.regulator0 = { \
|
||||
.slp_xpd = 0, \
|
||||
.xpd = 1, \
|
||||
.slp_dbias = 0x0, \
|
||||
.dbias = 0x1a \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \
|
||||
.bias = { \
|
||||
.xpd_bias = 0, \
|
||||
.dbg_atten = 0x0, \
|
||||
.pd_cur = 1, \
|
||||
.bias_sleep = 1, \
|
||||
}, \
|
||||
.regulator0 = { \
|
||||
.slp_xpd = 1, \
|
||||
.xpd = 0, \
|
||||
.slp_dbias = 0x0, \
|
||||
.dbias = 0x12 \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
}
|
||||
|
||||
const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode)
|
||||
{
|
||||
static const pmu_lp_system_analog_param_t lp_analog[] = {
|
||||
PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT(),
|
||||
PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT()
|
||||
};
|
||||
assert(mode < ARRAY_SIZE(lp_analog));
|
||||
return &lp_analog[mode];
|
||||
}
|
256
components/esp_hw_support/port/esp32c6/pmu_sleep.c
Normal file
256
components/esp_hw_support/port/esp32c6/pmu_sleep.c
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
|
||||
#define HP(state) (PMU_MODE_HP_ ## state)
|
||||
#define LP(state) (PMU_MODE_LP_ ## state)
|
||||
|
||||
void pmu_sleep_enable_regdma_backup(void)
|
||||
{
|
||||
assert(PMU_instance()->hal);
|
||||
/* entry 0, 1, 2 is used by pmu HP_SLEEP and HP_ACTIVE, HP_SLEEP
|
||||
* and HP_MODEM or HP_MODEM and HP_ACTIVE states switching,
|
||||
* respectively. entry 3 is reserved, not used yet! */
|
||||
pmu_hal_hp_set_sleep_active_backup_enable(PMU_instance()->hal);
|
||||
pmu_hal_hp_set_sleep_modem_backup_enable(PMU_instance()->hal);
|
||||
pmu_hal_hp_set_modem_active_backup_enable(PMU_instance()->hal);
|
||||
}
|
||||
|
||||
void pmu_sleep_disable_regdma_backup(void)
|
||||
{
|
||||
assert(PMU_instance()->hal);
|
||||
pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal);
|
||||
pmu_hal_hp_set_sleep_modem_backup_disable(PMU_instance()->hal);
|
||||
pmu_hal_hp_set_modem_active_backup_disable(PMU_instance()->hal);
|
||||
}
|
||||
|
||||
uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
|
||||
/* LP core hardware wait time, microsecond */
|
||||
const int lp_wakeup_wait_time = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period);
|
||||
const int lp_clk_switch_time = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period);
|
||||
const int lp_clk_power_on_wait_time = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_ms \
|
||||
: rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period);
|
||||
|
||||
const int lp_hw_wait_time = mc->lp.min_slp_time_ms + mc->lp.analog_wait_time_ms + lp_clk_power_on_wait_time \
|
||||
+ lp_wakeup_wait_time + lp_clk_switch_time + mc->lp.power_supply_wait_time_ms \
|
||||
+ mc->lp.power_up_wait_time_ms;
|
||||
|
||||
/* HP core hardware wait time, microsecond */
|
||||
const int hp_digital_power_up_wait_time_ms = mc->hp.power_supply_wait_time_ms + mc->hp.power_up_wait_time_ms;
|
||||
const int hp_regdma_wait_time = MAX(mc->hp.regdma_s2m_work_time_ms + mc->hp.regdma_m2a_work_time_ms, mc->hp.regdma_s2a_work_time_ms);
|
||||
const int hp_clock_wait_time = mc->hp.xtal_wait_stable_time_ms + mc->hp.pll_wait_stable_time_ms;
|
||||
|
||||
const int hp_hw_wait_time = mc->hp.analog_wait_time_ms + MAX(hp_digital_power_up_wait_time_ms + hp_regdma_wait_time, hp_clock_wait_time);
|
||||
|
||||
/* When the SOC wakeup (lp timer or GPIO wakeup) and Modem wakeup (Beacon wakeup) complete, the soc
|
||||
* wakeup will be delayed until the RF is turned on in Modem state.
|
||||
*
|
||||
* modem wakeup TBTT, RF on by HW
|
||||
* | |
|
||||
* \|/ \|/
|
||||
* PMU_HP_ACTIVE /------
|
||||
* PMU_HP_MODEM /------------//////////////////
|
||||
* PMU_HP_SLEEP ----------------------//////////////////
|
||||
* /|\ /|\ /|\ /|\ /|\ /|\
|
||||
* |<- some hw wait ->| | | |<- M2A switch ->|
|
||||
* | slow cycles & | soc wakeup | |
|
||||
* | FOSC cycles |<- S2M switch ->| |
|
||||
* | |
|
||||
* |<-- PMU guard time, also the maximum time for the SOC -->|
|
||||
* | wake-up delay |
|
||||
*/
|
||||
#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_AUTO_BEACON_ENABLE
|
||||
const int rf_on_protect_time = mc->hp.regdma_rf_on_work_time_ms;
|
||||
const int total_hw_wait_time = lp_hw_wait_time + hp_hw_wait_time + mc->hp.clock_domain_sync_time_ms;
|
||||
#else
|
||||
const int rf_on_protect_time = 0;
|
||||
const int total_hw_wait_time = lp_hw_wait_time + hp_hw_wait_time;
|
||||
#endif
|
||||
return total_hw_wait_time + rf_on_protect_time;
|
||||
}
|
||||
|
||||
#define rtc_time_us_to_fastclk(time_us, period) rtc_time_us_to_slowclk((time_us), (period))
|
||||
|
||||
static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
pmu_sleep_param_config_t *param,
|
||||
pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */
|
||||
const uint32_t pd_flags,
|
||||
const uint32_t adjustment,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
|
||||
param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_ms, slowclk_period);
|
||||
param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_ms, fastclk_period);
|
||||
param->hp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_supply_wait_time_ms, fastclk_period);
|
||||
param->hp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_up_wait_time_ms, fastclk_period);
|
||||
param->hp_sys.pll_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.pll_wait_stable_time_ms, fastclk_period);
|
||||
|
||||
const int hw_wait_time = pmu_sleep_calculate_hw_wait_time(pd_flags, slowclk_period, fastclk_period);
|
||||
const int modem_state_skip_time = mc->hp.regdma_m2a_work_time_ms + mc->hp.system_dfs_up_work_time_ms + mc->lp.min_slp_time_ms;
|
||||
const int modem_wakeup_wait_time = adjustment - hw_wait_time + modem_state_skip_time + mc->hp.regdma_rf_on_work_time_ms;
|
||||
param->hp_sys.modem_wakeup_wait_cycle = rtc_time_us_to_fastclk(modem_wakeup_wait_time, fastclk_period);
|
||||
|
||||
param->lp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.min_slp_time_ms, slowclk_period);
|
||||
param->lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(mc->lp.analog_wait_time_ms, slowclk_period);
|
||||
param->lp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_supply_wait_time_ms, fastclk_period);
|
||||
param->lp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_up_wait_time_ms, fastclk_period);
|
||||
|
||||
if (power->hp_sys.xtal.xpd_xtal) {
|
||||
param->hp_lp.xtal_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_ms, fastclk_period);
|
||||
} else {
|
||||
param->hp_lp.xtal_stable_wait_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.xtal_wait_stable_time_ms, slowclk_period);
|
||||
}
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t pd_flags,
|
||||
uint32_t adjustment,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
{
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags);
|
||||
|
||||
uint32_t iram_pd_flags = 0;
|
||||
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G0) ? BIT(0) : 0;
|
||||
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0;
|
||||
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0;
|
||||
iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0;
|
||||
config->power = power_default;
|
||||
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period);
|
||||
|
||||
if (dslp) {
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags);
|
||||
config->analog = analog_default;
|
||||
} else {
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags);
|
||||
if (!(pd_flags & PMU_SLEEP_PD_MODEM)){
|
||||
analog_default.hp_sys.analog.slp_logic_dbias += 2;
|
||||
}
|
||||
if (!(pd_flags & PMU_SLEEP_PD_TOP)){
|
||||
analog_default.hp_sys.analog.slp_logic_dbias += 2;
|
||||
}
|
||||
config->analog = analog_default;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_config_t *power, bool dslp)
|
||||
{
|
||||
pmu_ll_hp_set_dig_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.dig_power.val);
|
||||
pmu_ll_hp_set_clk_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.clk_power.val);
|
||||
pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, HP(SLEEP), power->hp_sys.xtal.xpd_xtal);
|
||||
|
||||
pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].dig_power.val);
|
||||
pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].clk_power.val);
|
||||
|
||||
pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].dig_power.val);
|
||||
pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].clk_power.val);
|
||||
pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].xtal.xpd_xtal);
|
||||
|
||||
if (dslp) {
|
||||
// TODO: IDF-5349
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
|
||||
{
|
||||
assert(ctx->hal);
|
||||
pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur);
|
||||
pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_dbias);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias);
|
||||
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
|
||||
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
|
||||
|
||||
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias);
|
||||
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias);
|
||||
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b);
|
||||
|
||||
pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
|
||||
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep);
|
||||
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd);
|
||||
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_dbias);
|
||||
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias);
|
||||
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.drv_b);
|
||||
|
||||
if (dslp) {
|
||||
// TODO: IDF-5349
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
static void pmu_sleep_param_init(pmu_context_t *ctx, const pmu_sleep_param_config_t *param, bool dslp)
|
||||
{
|
||||
assert(ctx->hal);
|
||||
pmu_ll_hp_set_min_sleep_cycle(ctx->hal->dev, param->hp_sys.min_slp_slow_clk_cycle);
|
||||
pmu_ll_lp_set_min_sleep_cycle(ctx->hal->dev, param->lp_sys.min_slp_slow_clk_cycle);
|
||||
|
||||
pmu_ll_hp_set_analog_wait_target_cycle(ctx->hal->dev, param->hp_sys.analog_wait_target_cycle);
|
||||
pmu_ll_lp_set_analog_wait_target_cycle(ctx->hal->dev, param->lp_sys.analog_wait_target_cycle);
|
||||
|
||||
pmu_hal_hp_set_digital_power_up_wait_cycle(ctx->hal, param->hp_sys.digital_power_supply_wait_cycle, param->hp_sys.digital_power_up_wait_cycle);
|
||||
pmu_hal_lp_set_digital_power_up_wait_cycle(ctx->hal, param->lp_sys.digital_power_supply_wait_cycle, param->lp_sys.digital_power_up_wait_cycle);
|
||||
|
||||
pmu_ll_set_modem_wait_target_cycle(ctx->hal->dev, param->hp_sys.modem_wakeup_wait_cycle);
|
||||
pmu_ll_set_xtal_stable_wait_cycle(ctx->hal->dev, param->hp_lp.xtal_stable_wait_slow_clk_cycle);
|
||||
pmu_ll_set_pll_stable_wait_cycle(ctx->hal->dev, param->hp_sys.pll_stable_wait_cycle);
|
||||
}
|
||||
|
||||
void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp)
|
||||
{
|
||||
assert(PMU_instance());
|
||||
pmu_sleep_power_init(PMU_instance(), &config->power, dslp);
|
||||
pmu_sleep_analog_init(PMU_instance(), &config->analog, dslp);
|
||||
pmu_sleep_param_init(PMU_instance(), &config->param, dslp);
|
||||
}
|
||||
|
||||
uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
assert(PMU_instance()->hal);
|
||||
pmu_ll_hp_set_wakeup_enable(PMU_instance()->hal->dev, wakeup_opt);
|
||||
pmu_ll_hp_set_reject_enable(PMU_instance()->hal->dev, reject_opt);
|
||||
|
||||
pmu_ll_hp_clear_wakeup_intr_status(PMU_instance()->hal->dev);
|
||||
pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev);
|
||||
pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev);
|
||||
|
||||
/* Start entry into sleep mode */
|
||||
pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev);
|
||||
|
||||
while (!pmu_ll_hp_is_sleep_wakeup(PMU_instance()->hal->dev) &&
|
||||
!pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) {
|
||||
;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_dig_power_reg_t dig_power;
|
||||
pmu_hp_clk_power_reg_t clk_power;
|
||||
pmu_hp_xtal_reg_t xtal;
|
||||
} pmu_hp_system_power_param_t;
|
||||
|
||||
const pmu_hp_system_power_param_t* pmu_hp_system_power_param_default(pmu_hp_mode_t mode);
|
||||
|
||||
typedef struct {
|
||||
uint32_t icg_func;
|
||||
uint32_t icg_apb;
|
||||
pmu_hp_icg_modem_reg_t icg_modem;
|
||||
pmu_hp_sysclk_reg_t sysclk;
|
||||
} pmu_hp_system_clock_param_t;
|
||||
|
||||
const pmu_hp_system_clock_param_t* pmu_hp_system_clock_param_default(pmu_hp_mode_t mode);
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_sys_cntl_reg_t syscntl;
|
||||
} pmu_hp_system_digital_param_t;
|
||||
|
||||
const pmu_hp_system_digital_param_t* pmu_hp_system_digital_param_default(pmu_hp_mode_t mode);
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_bias_reg_t bias;
|
||||
pmu_hp_regulator0_reg_t regulator0;
|
||||
pmu_hp_regulator1_reg_t regulator1;
|
||||
} pmu_hp_system_analog_param_t;
|
||||
|
||||
const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mode_t mode);
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_backup_reg_t retention;
|
||||
uint32_t backup_clk;
|
||||
} pmu_hp_system_retention_param_t;
|
||||
|
||||
const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode);
|
||||
|
||||
typedef struct {
|
||||
pmu_lp_dig_power_reg_t dig_power;
|
||||
pmu_lp_clk_power_reg_t clk_power;
|
||||
pmu_lp_xtal_reg_t xtal;
|
||||
} pmu_lp_system_power_param_t;
|
||||
|
||||
const pmu_lp_system_power_param_t* pmu_lp_system_power_param_default(pmu_lp_mode_t mode);
|
||||
|
||||
typedef struct {
|
||||
pmu_lp_bias_reg_t bias;
|
||||
pmu_lp_regulator0_reg_t regulator0;
|
||||
pmu_lp_regulator1_reg_t regulator1;
|
||||
} pmu_lp_system_analog_param_t;
|
||||
|
||||
const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode);
|
||||
|
||||
#define PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES (10)
|
||||
#define PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES (10)
|
||||
|
||||
#define PMU_HP_WAKEUP_DELAY_CYCLES (0)
|
||||
#define PMU_HP_XTAL_STABLE_WAIT_CYCLES (3155) /* Not used, Fast OSC as PMU work clock source is about 201 us, corresponding to PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES */
|
||||
#define PMU_HP_PLL_STABLE_WAIT_CYCLES (2)
|
||||
#define PMU_HP_ANALOG_WAIT_TARGET_CYCLES (2419) /* Fast OSC as PMU work clock source is about 154 us */
|
||||
#define PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32)
|
||||
#define PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES (32)
|
||||
#define PMU_HP_MODEM_WAKEUP_WAIT_CYCLES (20700) /* Fast OSC as PMU work clock source is about 1318.6 us */
|
||||
|
||||
#define PMU_LP_WAKEUP_DELAY_CYCLES (0)
|
||||
#define PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES (30) /* Slow OSC as PMU slow clock source is about 201 us */
|
||||
#define PMU_LP_ANALOG_WAIT_TARGET_CYCLES (23) /* Slow OSC as PMU slow clock source is about 154 us */
|
||||
#define PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */
|
||||
#define PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
pmu_hp_power_t dig_power;
|
||||
pmu_hp_power_t clk_power;
|
||||
pmu_hp_power_t xtal;
|
||||
} hp_sys;
|
||||
struct {
|
||||
pmu_lp_power_t dig_power;
|
||||
pmu_lp_power_t clk_power;
|
||||
pmu_lp_power_t xtal;
|
||||
} lp_sys[PMU_MODE_LP_MAX];
|
||||
} pmu_sleep_power_config_t;
|
||||
|
||||
#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \
|
||||
.hp_sys = { \
|
||||
.dig_power = { \
|
||||
.vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \
|
||||
.wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
|
||||
.cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
|
||||
.aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_AON) ? 1 : 0, \
|
||||
.top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
|
||||
.mem_pd_en = 0, \
|
||||
.mem_dslp = 0 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 1, \
|
||||
.i2c_retention = 1, \
|
||||
.xpd_bb_i2c = 0, \
|
||||
.xpd_bbpll_i2c = 0, \
|
||||
.xpd_bbpll = 0 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
|
||||
.dig_power = { \
|
||||
.peri_pd_en = 0, \
|
||||
.mem_dslp = 0 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.xpd_xtal32k = 1, \
|
||||
.xpd_rc32k = 1, \
|
||||
.xpd_fosc = 1 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_SLEEP] = { \
|
||||
.dig_power = { \
|
||||
.peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
|
||||
.mem_dslp = 1 \
|
||||
}, \
|
||||
.clk_power = { \
|
||||
.xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
|
||||
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \
|
||||
.xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
pmu_hp_analog_t analog;
|
||||
} hp_sys;
|
||||
struct {
|
||||
pmu_lp_analog_t analog;
|
||||
} lp_sys[PMU_MODE_LP_MAX];
|
||||
} pmu_sleep_analog_config_t;
|
||||
|
||||
#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \
|
||||
.hp_sys = { \
|
||||
.analog = { \
|
||||
.xpd_bias = 0x0, \
|
||||
.dbg_atten = 0x0, \
|
||||
.pd_cur = 1, \
|
||||
.bias_sleep = 1, \
|
||||
.slp_mem_xpd = 1, \
|
||||
.slp_logic_xpd = 1, \
|
||||
.slp_mem_dbias = 0x4, \
|
||||
.slp_logic_dbias = 0x4, \
|
||||
.xpd = 0, \
|
||||
.dbias = 0, \
|
||||
.drv_b = 0 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
|
||||
.analog = { \
|
||||
.slp_xpd = 0, \
|
||||
.slp_dbias = 0xc, \
|
||||
.xpd = 1, \
|
||||
.dbias = 0x1a, \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_SLEEP] = { \
|
||||
.analog = { \
|
||||
.xpd_bias = 0, \
|
||||
.dbg_atten = 0x0, \
|
||||
.pd_cur = 1, \
|
||||
.bias_sleep = 1, \
|
||||
.xpd = 0, \
|
||||
.dbias = 0x1c, \
|
||||
.slp_xpd = 1, \
|
||||
.slp_dbias = 0x3, \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
|
||||
.hp_sys = { \
|
||||
.analog = { \
|
||||
.xpd_bias = 0, \
|
||||
.dbg_atten = 0x3, \
|
||||
.pd_cur = 1, \
|
||||
.bias_sleep = 1, \
|
||||
.xpd = 0, \
|
||||
.dbias = 0x15, \
|
||||
.slp_mem_xpd = 1, \
|
||||
.slp_mem_dbias = 0xc, \
|
||||
.slp_logic_xpd = 1, \
|
||||
.slp_logic_dbias = 0x5, \
|
||||
.drv_b = 0x18c \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
|
||||
.analog = { \
|
||||
.xpd = 1, \
|
||||
.dbias = 0x1a, \
|
||||
.slp_xpd = 0, \
|
||||
.slp_dbias = 0, \
|
||||
.drv_b = 0x7 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_SLEEP] = { \
|
||||
.analog = { \
|
||||
.xpd_bias = 0, \
|
||||
.dbg_atten = 0xe, \
|
||||
.pd_cur = 1, \
|
||||
.bias_sleep = 1, \
|
||||
.xpd = 0, \
|
||||
.dbias = 0, \
|
||||
.slp_xpd = 1, \
|
||||
.slp_dbias = 0xe, \
|
||||
.drv_b = 0 \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_param_t hp_sys;
|
||||
pmu_lp_param_t lp_sys;
|
||||
pmu_hp_lp_param_t hp_lp;
|
||||
} pmu_sleep_param_config_t;
|
||||
|
||||
#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \
|
||||
.hp_sys = { \
|
||||
.min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \
|
||||
.analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \
|
||||
.digital_power_supply_wait_cycle = PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \
|
||||
.digital_power_up_wait_cycle = PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES, \
|
||||
.modem_wakeup_wait_cycle = PMU_HP_MODEM_WAKEUP_WAIT_CYCLES, \
|
||||
.pll_stable_wait_cycle = PMU_HP_PLL_STABLE_WAIT_CYCLES \
|
||||
}, \
|
||||
.lp_sys = { \
|
||||
.min_slp_slow_clk_cycle = PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES, \
|
||||
.analog_wait_target_cycle = PMU_LP_ANALOG_WAIT_TARGET_CYCLES, \
|
||||
.digital_power_supply_wait_cycle = PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \
|
||||
.digital_power_up_wait_cycle = PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES \
|
||||
}, \
|
||||
.hp_lp = { \
|
||||
.xtal_stable_wait_slow_clk_cycle = PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES \
|
||||
} \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
pmu_sleep_power_config_t power;
|
||||
pmu_sleep_analog_config_t analog;
|
||||
pmu_sleep_param_config_t param;
|
||||
} pmu_sleep_config_t;
|
||||
|
||||
typedef struct pmu_sleep_machine_constant {
|
||||
struct {
|
||||
uint16_t min_slp_time_ms; /* Mininum sleep protection time (unit: microsecond) */
|
||||
uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */
|
||||
uint8_t reserved0;
|
||||
uint16_t reserved1;
|
||||
uint16_t analog_wait_time_ms; /* LP LDO power up wait time (unit: microsecond) */
|
||||
uint16_t xtal_wait_stable_time_ms; /* Main XTAL stabilization wait time (unit: microsecond) */
|
||||
uint8_t clk_switch_cycle; /* Clock switch to FOSC (unit: slow clock cycle) */
|
||||
uint8_t clk_power_on_wait_cycle; /* Clock power on wait cycle (unit: slow clock cycle) */
|
||||
uint16_t power_supply_wait_time_ms; /* (unit: microsecond) */
|
||||
uint16_t power_up_wait_time_ms; /* (unit: microsecond) */
|
||||
} lp;
|
||||
struct {
|
||||
uint16_t min_slp_time_ms; /* Mininum sleep protection time (unit: microsecond) */
|
||||
uint16_t clock_domain_sync_time_ms; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */
|
||||
uint16_t system_dfs_up_work_time_ms; /* System DFS up scaling work time (unit: microsecond) */
|
||||
uint16_t analog_wait_time_ms; /* HP LDO power up wait time (unit: microsecond) */
|
||||
uint16_t power_supply_wait_time_ms; /* (unit: microsecond) */
|
||||
uint16_t power_up_wait_time_ms; /* (unit: microsecond) */
|
||||
uint16_t regdma_s2m_work_time_ms; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */
|
||||
uint16_t regdma_s2a_work_time_ms; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */
|
||||
uint16_t regdma_m2a_work_time_ms; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */
|
||||
uint16_t regdma_a2s_work_time_ms; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */
|
||||
uint16_t regdma_rf_on_work_time_ms; /* The REGDMA work time of RF enable (unit: microsecond) */
|
||||
uint16_t regdma_rf_off_work_time_ms; /* The REGDMA work time of RF disable (unit: microsecond) */
|
||||
uint16_t xtal_wait_stable_time_ms; /* Main XTAL stabilization wait time (unit: microsecond) */
|
||||
uint16_t pll_wait_stable_time_ms; /* PLL stabilization wait time (unit: microsecond) */
|
||||
} hp;
|
||||
} pmu_sleep_machine_constant_t;
|
||||
|
||||
#define PMU_SLEEP_MC_DEFAULT() { \
|
||||
.lp = { \
|
||||
.min_slp_time_ms = 450, \
|
||||
.wakeup_wait_cycle = 4, \
|
||||
.analog_wait_time_ms = 154, \
|
||||
.xtal_wait_stable_time_ms = 250, \
|
||||
.clk_switch_cycle = 1, \
|
||||
.clk_power_on_wait_cycle = 1, \
|
||||
.power_supply_wait_time_ms = 2, \
|
||||
.power_up_wait_time_ms = 2 \
|
||||
}, \
|
||||
.hp = { \
|
||||
.min_slp_time_ms = 450, \
|
||||
.clock_domain_sync_time_ms = 150, \
|
||||
.system_dfs_up_work_time_ms = 124, \
|
||||
.analog_wait_time_ms = 154, \
|
||||
.power_supply_wait_time_ms = 2, \
|
||||
.power_up_wait_time_ms = 2, \
|
||||
.regdma_s2m_work_time_ms = 172, \
|
||||
.regdma_s2a_work_time_ms = 430, \
|
||||
.regdma_m2a_work_time_ms = 265, \
|
||||
.regdma_a2s_work_time_ms = 338, \
|
||||
.regdma_rf_on_work_time_ms = 70, \
|
||||
.regdma_rf_off_work_time_ms = 23, \
|
||||
.xtal_wait_stable_time_ms = 250, \
|
||||
.pll_wait_stable_time_ms = 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -19,14 +19,47 @@
|
||||
#include "esp_hw_log.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/pmu_ll.h"
|
||||
#include "hal/modem_syscon_ll.h"
|
||||
#include "hal/modem_lpcon_ll.h"
|
||||
|
||||
static const char *TAG = "rtc_clk_init";
|
||||
|
||||
/**
|
||||
* Initialize the ICG map of some modem clock domains in the PMU_ACTIVE state
|
||||
*
|
||||
* A pre-initialization interface is used to initialize the ICG map of the
|
||||
* MODEM_APB, I2C_MST and LP_APB clock domains in the PMU_ACTIVE state, and
|
||||
* disable the clock gating of these clock domains in the PMU_ACTIVE state,
|
||||
* because the system clock source (PLL) in the system boot up process needs
|
||||
* to use the i2c master peripheral.
|
||||
*
|
||||
* ICG map of all modem clock domains under different power states (PMU_ACTIVE,
|
||||
* PMU_MODEM and PMU_SLEEP) will be initialized in esp_perip_clk_init().
|
||||
*/
|
||||
static void rtc_clk_modem_clock_domain_active_state_icg_map_preinit(void)
|
||||
{
|
||||
/* Configure modem ICG code in PMU_ACTIVE state */
|
||||
pmu_ll_hp_set_icg_modem(&PMU, PMU_MODE_HP_ACTIVE, PMU_HP_ICG_MODEM_CODE_ACTIVE);
|
||||
|
||||
/* Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in PMU_ACTIVE state */
|
||||
modem_syscon_ll_set_modem_apb_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
|
||||
modem_lpcon_ll_set_i2c_master_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
|
||||
modem_lpcon_ll_set_lp_apb_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE));
|
||||
|
||||
/* Software trigger force update modem ICG code and ICG switch */
|
||||
pmu_ll_imm_update_dig_icg_modem_code(&PMU, true);
|
||||
pmu_ll_imm_update_dig_icg_switch(&PMU, true);
|
||||
}
|
||||
|
||||
void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
{
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
|
||||
rtc_clk_modem_clock_domain_active_state_icg_map_preinit();
|
||||
|
||||
/* Set tuning parameters for RC_FAST, RC_SLOW, and RC32K clocks.
|
||||
* Note: this doesn't attempt to set the clocks to precise frequencies.
|
||||
* Instead, we calibrate these clocks against XTAL frequency later, when necessary.
|
||||
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/pmu_reg.h"
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
|
||||
// TODO: IDF-5781
|
||||
|
||||
void rtc_init(rtc_config_t cfg)
|
||||
{
|
||||
/* Peripheral reg i2c power up */
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
|
||||
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
|
||||
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 25);
|
||||
REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, 26);
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// TODO: IDF-5645
|
@ -8,8 +8,8 @@
|
||||
#include "esp32c6/rom/ets_sys.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/lp_timer_reg.h"
|
||||
#include "hal/lp_timer_hal.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "assert.h"
|
||||
@ -207,7 +207,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
|
||||
|
||||
uint64_t rtc_time_get(void)
|
||||
{
|
||||
return rtc_cntl_ll_get_rtc_time();
|
||||
return lp_timer_hal_get_cycle_count(0);
|
||||
}
|
||||
|
||||
uint64_t rtc_light_slp_time_get(void)
|
||||
|
@ -174,40 +174,3 @@ void dslp_osc_pd(void){
|
||||
REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG,RTC_CNTL_RC32K_XPD, 0);
|
||||
REG_SET_FIELD(RTC_CNTL_PLL8M_REG, RTC_CNTL_XPD_PLL8M, 0);
|
||||
}
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void)
|
||||
{
|
||||
rtc_vddsdio_config_t result;
|
||||
uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG);
|
||||
result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S;
|
||||
result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S;
|
||||
result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S;
|
||||
if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) {
|
||||
// Get configuration from RTC
|
||||
result.force = 1;
|
||||
result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S;
|
||||
result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S;
|
||||
return result;
|
||||
} else {
|
||||
result.force = 0;
|
||||
}
|
||||
|
||||
// Otherwise, VDD_SDIO is controlled by bootstrapping pin
|
||||
uint32_t strap_reg = REG_READ(GPIO_STRAP_REG);
|
||||
result.force = 0;
|
||||
result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V;
|
||||
result.enable = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
val |= (config.force << RTC_CNTL_SDIO_FORCE_S);
|
||||
val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S);
|
||||
val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S);
|
||||
val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S);
|
||||
val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S);
|
||||
val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S);
|
||||
val |= RTC_CNTL_SDIO_PD_EN;
|
||||
REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val);
|
||||
}
|
||||
|
646
components/esp_hw_support/sleep_cpu.c
Normal file
646
components/esp_hw_support/sleep_cpu.c
Normal file
@ -0,0 +1,646 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if !SOC_PMU_SUPPORTED
|
||||
#include "hal/rtc_hal.h"
|
||||
#endif
|
||||
|
||||
#include "soc/rtc_periph.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/rtc.h"
|
||||
#include "riscv/rvsleep-frames.h"
|
||||
#include "soc/intpri_reg.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/plic_reg.h"
|
||||
#include "soc/clint_reg.h"
|
||||
#include "esp32c6/rom/cache.h"
|
||||
#endif
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "sleep";
|
||||
|
||||
typedef struct {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
} cpu_domain_dev_regs_region_t;
|
||||
|
||||
typedef struct {
|
||||
cpu_domain_dev_regs_region_t *region;
|
||||
int region_num;
|
||||
uint32_t *regs_frame;
|
||||
} cpu_domain_dev_sleep_frame_t;
|
||||
|
||||
/**
|
||||
* Internal structure which holds all requested light sleep cpu retention parameters
|
||||
*/
|
||||
typedef struct {
|
||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
rtc_cntl_sleep_retent_t retent;
|
||||
#elif SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||
struct {
|
||||
RvCoreCriticalSleepFrame *critical_frame;
|
||||
RvCoreNonCriticalSleepFrame *non_critical_frame;
|
||||
cpu_domain_dev_sleep_frame_t *intpri_frame;
|
||||
cpu_domain_dev_sleep_frame_t *cache_config_frame;
|
||||
cpu_domain_dev_sleep_frame_t *plic_frame;
|
||||
cpu_domain_dev_sleep_frame_t *clint_frame;
|
||||
} retent;
|
||||
#endif
|
||||
} sleep_cpu_retention_t;
|
||||
|
||||
static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
||||
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
static uint32_t cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size)
|
||||
{
|
||||
uint32_t sets; /* i/d-cache total set counts */
|
||||
uint32_t index; /* virtual address mapping i/d-cache row offset */
|
||||
uint32_t waysgrp;
|
||||
uint32_t icache_tagmem_blk_gs, dcache_tagmem_blk_gs;
|
||||
struct cache_mode imode = { .icache = 1 };
|
||||
struct cache_mode dmode = { .icache = 0 };
|
||||
|
||||
/* calculate/prepare i-cache tag memory retention parameters */
|
||||
Cache_Get_Mode(&imode);
|
||||
sets = imode.cache_size / imode.cache_ways / imode.cache_line_size;
|
||||
index = (code_seg_vaddr / imode.cache_line_size) % sets;
|
||||
waysgrp = imode.cache_ways >> 2;
|
||||
|
||||
code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size);
|
||||
|
||||
s_cpu_retention.retent.tagmem.icache.start_point = index;
|
||||
s_cpu_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff;
|
||||
s_cpu_retention.retent.tagmem.icache.vld_size = s_cpu_retention.retent.tagmem.icache.size;
|
||||
if (code_seg_size < imode.cache_size / imode.cache_ways) {
|
||||
s_cpu_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp;
|
||||
}
|
||||
s_cpu_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0;
|
||||
icache_tagmem_blk_gs = s_cpu_retention.retent.tagmem.icache.vld_size ? s_cpu_retention.retent.tagmem.icache.vld_size : sets * waysgrp;
|
||||
icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs);
|
||||
ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10),
|
||||
imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs);
|
||||
|
||||
/* calculate/prepare d-cache tag memory retention parameters */
|
||||
Cache_Get_Mode(&dmode);
|
||||
sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size;
|
||||
index = (data_seg_vaddr / dmode.cache_line_size) % sets;
|
||||
waysgrp = dmode.cache_ways >> 2;
|
||||
|
||||
data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size);
|
||||
|
||||
s_cpu_retention.retent.tagmem.dcache.start_point = index;
|
||||
s_cpu_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff;
|
||||
s_cpu_retention.retent.tagmem.dcache.vld_size = s_cpu_retention.retent.tagmem.dcache.size;
|
||||
#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB
|
||||
if (data_seg_size < dmode.cache_size / dmode.cache_ways) {
|
||||
s_cpu_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp;
|
||||
}
|
||||
s_cpu_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0;
|
||||
#else
|
||||
s_cpu_retention.retent.tagmem.dcache.enable = 1;
|
||||
#endif
|
||||
dcache_tagmem_blk_gs = s_cpu_retention.retent.tagmem.dcache.vld_size ? s_cpu_retention.retent.tagmem.dcache.vld_size : sets * waysgrp;
|
||||
dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs);
|
||||
ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10),
|
||||
dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs);
|
||||
|
||||
/* For I or D cache tagmem retention, backup and restore are performed through
|
||||
* RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache
|
||||
* tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically
|
||||
* aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4
|
||||
* i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */
|
||||
return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3);
|
||||
}
|
||||
#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
|
||||
static esp_err_t esp_sleep_tagmem_pd_low_init(void)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
if (s_cpu_retention.retent.tagmem.link_addr == NULL) {
|
||||
extern char _stext[], _etext[];
|
||||
uint32_t code_start = (uint32_t)_stext;
|
||||
uint32_t code_size = (uint32_t)(_etext - _stext);
|
||||
#if !(CONFIG_SPIRAM && CONFIG_SOC_PM_SUPPORT_TAGMEM_PD)
|
||||
extern char _rodata_start[], _rodata_reserved_end[];
|
||||
uint32_t data_start = (uint32_t)_rodata_start;
|
||||
uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start);
|
||||
#else
|
||||
uint32_t data_start = SOC_DROM_LOW;
|
||||
uint32_t data_size = SOC_EXTRAM_DATA_SIZE;
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Code start at 0x%08"PRIx32", total %"PRIu32", data start at 0x%08"PRIx32", total %"PRIu32" Bytes",
|
||||
code_start, code_size, data_start, data_size);
|
||||
uint32_t tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size);
|
||||
void *buf = heap_caps_aligned_calloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, 1,
|
||||
tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE,
|
||||
MALLOC_CAP_RETENTION);
|
||||
if (buf) {
|
||||
s_cpu_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf,
|
||||
buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL);
|
||||
} else {
|
||||
s_cpu_retention.retent.tagmem.icache.enable = 0;
|
||||
s_cpu_retention.retent.tagmem.dcache.enable = 0;
|
||||
s_cpu_retention.retent.tagmem.link_addr = NULL;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
s_cpu_retention.retent.tagmem.icache.enable = 0;
|
||||
s_cpu_retention.retent.tagmem.dcache.enable = 0;
|
||||
s_cpu_retention.retent.tagmem.link_addr = NULL;
|
||||
#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t esp_sleep_tagmem_pd_low_deinit(void)
|
||||
{
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
if (s_cpu_retention.retent.tagmem.link_addr) {
|
||||
heap_caps_free(s_cpu_retention.retent.tagmem.link_addr);
|
||||
s_cpu_retention.retent.tagmem.icache.enable = 0;
|
||||
s_cpu_retention.retent.tagmem.dcache.enable = 0;
|
||||
s_cpu_retention.retent.tagmem.link_addr = NULL;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
|
||||
esp_err_t esp_sleep_cpu_pd_low_init(void)
|
||||
{
|
||||
if (s_cpu_retention.retent.cpu_pd_mem == NULL) {
|
||||
void *buf = heap_caps_aligned_calloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, 1,
|
||||
SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
|
||||
MALLOC_CAP_RETENTION);
|
||||
if (buf) {
|
||||
s_cpu_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
|
||||
buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
|
||||
} else {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
if (esp_sleep_tagmem_pd_low_init() != ESP_OK) {
|
||||
#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB
|
||||
esp_sleep_cpu_pd_low_deinit();
|
||||
return ESP_ERR_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_cpu_pd_low_deinit(void)
|
||||
{
|
||||
if (s_cpu_retention.retent.cpu_pd_mem) {
|
||||
heap_caps_free(s_cpu_retention.retent.cpu_pd_mem);
|
||||
s_cpu_retention.retent.cpu_pd_mem = NULL;
|
||||
}
|
||||
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
if (esp_sleep_tagmem_pd_low_deinit() != ESP_OK) {
|
||||
#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB
|
||||
esp_sleep_cpu_pd_low_deinit();
|
||||
return ESP_ERR_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void sleep_enable_cpu_retention(void)
|
||||
{
|
||||
rtc_cntl_hal_enable_cpu_retention(&s_cpu_retention.retent);
|
||||
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
rtc_cntl_hal_enable_tagmem_retention(&s_cpu_retention.retent);
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR sleep_disable_cpu_retention(void)
|
||||
{
|
||||
rtc_cntl_hal_disable_cpu_retention(&s_cpu_retention.retent);
|
||||
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
rtc_cntl_hal_disable_tagmem_retention(&s_cpu_retention.retent);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||
|
||||
#define CUSTOM_CSR_PCER_MACHINE 0x7e0
|
||||
#define CUSTOM_CSR_PCMR_MACHINE 0x7e1
|
||||
#define CUSTOM_CSR_PCCR_MACHINE 0x7e2
|
||||
#define CUSTOM_CSR_CPU_TESTBUS_CTRL 0x7e3
|
||||
#define CUSTOM_CSR_PCER_USER 0x800
|
||||
#define CUSTOM_CSR_PCMR_USER 0x801
|
||||
#define CUSTOM_CSR_PCCR_USER 0x802
|
||||
#define CUSTOM_CSR_GPIO_OEN_USER 0x803
|
||||
#define CUSTOM_CSR_GPIO_IN_USER 0x804
|
||||
#define CUSTOM_CSR_GPIO_OUT_USER 0x805
|
||||
#define CUSTOM_CSR_CO_EXCEPTION_CAUSE 0x7f0
|
||||
#define CUSTOM_CSR_CO_HWLP 0x7f1
|
||||
#define CUSTOM_CSR_CO_AIA 0x7f2
|
||||
|
||||
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame;
|
||||
|
||||
static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num)
|
||||
{
|
||||
const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num;
|
||||
int regs_frame_sz = 0;
|
||||
for (int num = 0; num < region_num; num++) {
|
||||
regs_frame_sz += regions[num].end - regions[num].start;
|
||||
}
|
||||
void *frame = heap_caps_malloc(sizeof(cpu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame) {
|
||||
cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t));
|
||||
memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t));
|
||||
void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz;
|
||||
memset(regs_frame, 0, regs_frame_sz);
|
||||
*(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) {
|
||||
.region = region,
|
||||
.region_num = region_num,
|
||||
.regs_frame = (uint32_t *)regs_frame
|
||||
};
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
static inline void * cpu_domain_intpri_sleep_frame_alloc_and_init(void)
|
||||
{
|
||||
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||
{ .start = INTPRI_CORE0_CPU_INT_ENABLE_REG, .end = INTPRI_RND_ECO_LOW_REG + 4 },
|
||||
{ .start = INTPRI_RND_ECO_HIGH_REG, .end = INTPRI_RND_ECO_HIGH_REG + 4 }
|
||||
};
|
||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
||||
}
|
||||
|
||||
static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void)
|
||||
{
|
||||
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||
{ .start = EXTMEM_DCACHE_CTRL_REG, .end = EXTMEM_DCACHE_CTRL_REG + 4 },
|
||||
{ .start = EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, .end = EXTMEM_CACHE_WRAP_AROUND_CTRL_REG + 4 }
|
||||
};
|
||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
||||
}
|
||||
|
||||
static inline void * cpu_domain_plic_sleep_frame_alloc_and_init(void)
|
||||
{
|
||||
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||
{ .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 },
|
||||
{ .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 },
|
||||
{ .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 },
|
||||
{ .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_REG + 4 }
|
||||
};
|
||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
||||
}
|
||||
|
||||
static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(void)
|
||||
{
|
||||
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||
{ .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 },
|
||||
{ .start = CLINT_UINT_SIP_REG, .end = CLINT_UINT_UTIMECMP_H_REG + 4 }
|
||||
};
|
||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
||||
}
|
||||
|
||||
static esp_err_t esp_sleep_cpu_retention_init_impl(void)
|
||||
{
|
||||
if (s_cpu_retention.retent.critical_frame == NULL) {
|
||||
void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
s_cpu_retention.retent.critical_frame = (RvCoreCriticalSleepFrame *)frame;
|
||||
rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame;
|
||||
}
|
||||
if (s_cpu_retention.retent.non_critical_frame == NULL) {
|
||||
void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
s_cpu_retention.retent.non_critical_frame = (RvCoreNonCriticalSleepFrame *)frame;
|
||||
}
|
||||
if (s_cpu_retention.retent.intpri_frame == NULL) {
|
||||
void *frame = cpu_domain_intpri_sleep_frame_alloc_and_init();
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
s_cpu_retention.retent.intpri_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
if (s_cpu_retention.retent.cache_config_frame == NULL) {
|
||||
void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init();
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
s_cpu_retention.retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
if (s_cpu_retention.retent.plic_frame == NULL) {
|
||||
void *frame = cpu_domain_plic_sleep_frame_alloc_and_init();
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
s_cpu_retention.retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
if (s_cpu_retention.retent.clint_frame == NULL) {
|
||||
void *frame = cpu_domain_clint_sleep_frame_alloc_and_init();
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
s_cpu_retention.retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
return ESP_OK;
|
||||
err:
|
||||
esp_sleep_cpu_retention_deinit();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
static esp_err_t esp_sleep_cpu_retention_deinit_impl(void)
|
||||
{
|
||||
if (s_cpu_retention.retent.critical_frame) {
|
||||
heap_caps_free((void *)s_cpu_retention.retent.critical_frame);
|
||||
s_cpu_retention.retent.critical_frame = NULL;
|
||||
rv_core_critical_regs_frame = NULL;
|
||||
}
|
||||
if (s_cpu_retention.retent.non_critical_frame) {
|
||||
heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame);
|
||||
s_cpu_retention.retent.non_critical_frame = NULL;
|
||||
}
|
||||
if (s_cpu_retention.retent.intpri_frame) {
|
||||
heap_caps_free((void *)s_cpu_retention.retent.intpri_frame);
|
||||
s_cpu_retention.retent.intpri_frame = NULL;
|
||||
}
|
||||
if (s_cpu_retention.retent.cache_config_frame) {
|
||||
heap_caps_free((void *)s_cpu_retention.retent.cache_config_frame);
|
||||
s_cpu_retention.retent.cache_config_frame = NULL;
|
||||
}
|
||||
if (s_cpu_retention.retent.plic_frame) {
|
||||
heap_caps_free((void *)s_cpu_retention.retent.plic_frame);
|
||||
s_cpu_retention.retent.plic_frame = NULL;
|
||||
}
|
||||
if (s_cpu_retention.retent.clint_frame) {
|
||||
heap_caps_free((void *)s_cpu_retention.retent.clint_frame);
|
||||
s_cpu_retention.retent.clint_frame = NULL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static inline IRAM_ATTR uint32_t save_mstatus_and_disable_global_int(void)
|
||||
{
|
||||
uint32_t mstatus;
|
||||
__asm__ __volatile__ (
|
||||
"csrr %0, mstatus\n"
|
||||
"csrci mstatus, 0x8\n"
|
||||
: "=r"(mstatus)
|
||||
);
|
||||
return mstatus;
|
||||
}
|
||||
|
||||
static inline IRAM_ATTR void restore_mstatus(uint32_t mstatus)
|
||||
{
|
||||
__asm__ __volatile__ ("csrw mstatus, %0\n" :: "r"(mstatus));
|
||||
}
|
||||
|
||||
static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
|
||||
{
|
||||
assert(s_cpu_retention.retent.non_critical_frame);
|
||||
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame;
|
||||
frame->mscratch = RV_READ_CSR(mscratch);
|
||||
frame->mideleg = RV_READ_CSR(mideleg);
|
||||
frame->misa = RV_READ_CSR(misa);
|
||||
frame->tselect = RV_READ_CSR(tselect);
|
||||
frame->tdata1 = RV_READ_CSR(tdata1);
|
||||
frame->tdata2 = RV_READ_CSR(tdata2);
|
||||
frame->tcontrol = RV_READ_CSR(tcontrol);
|
||||
frame->pmpcfg0 = RV_READ_CSR(pmpcfg0);
|
||||
frame->pmpcfg1 = RV_READ_CSR(pmpcfg1);
|
||||
frame->pmpcfg2 = RV_READ_CSR(pmpcfg2);
|
||||
frame->pmpcfg3 = RV_READ_CSR(pmpcfg3);
|
||||
frame->pmpaddr0 = RV_READ_CSR(pmpaddr0);
|
||||
frame->pmpaddr1 = RV_READ_CSR(pmpaddr1);
|
||||
frame->pmpaddr2 = RV_READ_CSR(pmpaddr2);
|
||||
frame->pmpaddr3 = RV_READ_CSR(pmpaddr3);
|
||||
frame->pmpaddr4 = RV_READ_CSR(pmpaddr4);
|
||||
frame->pmpaddr5 = RV_READ_CSR(pmpaddr5);
|
||||
frame->pmpaddr6 = RV_READ_CSR(pmpaddr6);
|
||||
frame->pmpaddr7 = RV_READ_CSR(pmpaddr7);
|
||||
frame->pmpaddr8 = RV_READ_CSR(pmpaddr8);
|
||||
frame->pmpaddr9 = RV_READ_CSR(pmpaddr9);
|
||||
frame->pmpaddr10 = RV_READ_CSR(pmpaddr10);
|
||||
frame->pmpaddr11 = RV_READ_CSR(pmpaddr11);
|
||||
frame->pmpaddr12 = RV_READ_CSR(pmpaddr12);
|
||||
frame->pmpaddr13 = RV_READ_CSR(pmpaddr13);
|
||||
frame->pmpaddr14 = RV_READ_CSR(pmpaddr14);
|
||||
frame->pmpaddr15 = RV_READ_CSR(pmpaddr15);
|
||||
|
||||
frame->utvec = RV_READ_CSR(utvec);
|
||||
frame->ustatus = RV_READ_CSR(ustatus);
|
||||
frame->uepc = RV_READ_CSR(uepc);
|
||||
frame->ucause = RV_READ_CSR(ucause);
|
||||
|
||||
frame->mpcer = RV_READ_CSR(CUSTOM_CSR_PCER_MACHINE);
|
||||
frame->mpcmr = RV_READ_CSR(CUSTOM_CSR_PCMR_MACHINE);
|
||||
frame->mpccr = RV_READ_CSR(CUSTOM_CSR_PCCR_MACHINE);
|
||||
frame->cpu_testbus_ctrl = RV_READ_CSR(CUSTOM_CSR_CPU_TESTBUS_CTRL);
|
||||
frame->upcer = RV_READ_CSR(CUSTOM_CSR_PCER_USER);
|
||||
frame->upcmr = RV_READ_CSR(CUSTOM_CSR_PCMR_USER);
|
||||
frame->upccr = RV_READ_CSR(CUSTOM_CSR_PCCR_USER);
|
||||
frame->ugpio_oen = RV_READ_CSR(CUSTOM_CSR_GPIO_OEN_USER);
|
||||
frame->ugpio_in = RV_READ_CSR(CUSTOM_CSR_GPIO_IN_USER);
|
||||
frame->ugpio_out = RV_READ_CSR(CUSTOM_CSR_GPIO_OUT_USER);
|
||||
return frame;
|
||||
}
|
||||
|
||||
static IRAM_ATTR void rv_core_noncritical_regs_restore(RvCoreNonCriticalSleepFrame *frame)
|
||||
{
|
||||
assert(frame);
|
||||
RV_WRITE_CSR(mscratch, frame->mscratch);
|
||||
RV_WRITE_CSR(mideleg, frame->mideleg);
|
||||
RV_WRITE_CSR(misa, frame->misa);
|
||||
RV_WRITE_CSR(tselect, frame->tselect);
|
||||
RV_WRITE_CSR(tdata1, frame->tdata1);
|
||||
RV_WRITE_CSR(tdata2, frame->tdata2);
|
||||
RV_WRITE_CSR(tcontrol, frame->tcontrol);
|
||||
RV_WRITE_CSR(pmpcfg0, frame->pmpcfg0);
|
||||
RV_WRITE_CSR(pmpcfg1, frame->pmpcfg1);
|
||||
RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2);
|
||||
RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3);
|
||||
RV_WRITE_CSR(pmpaddr0, frame->pmpaddr0);
|
||||
RV_WRITE_CSR(pmpaddr1, frame->pmpaddr1);
|
||||
RV_WRITE_CSR(pmpaddr2, frame->pmpaddr2);
|
||||
RV_WRITE_CSR(pmpaddr3, frame->pmpaddr3);
|
||||
RV_WRITE_CSR(pmpaddr4, frame->pmpaddr4);
|
||||
RV_WRITE_CSR(pmpaddr5, frame->pmpaddr5);
|
||||
RV_WRITE_CSR(pmpaddr6, frame->pmpaddr6);
|
||||
RV_WRITE_CSR(pmpaddr7, frame->pmpaddr7);
|
||||
RV_WRITE_CSR(pmpaddr8, frame->pmpaddr8);
|
||||
RV_WRITE_CSR(pmpaddr9, frame->pmpaddr9);
|
||||
RV_WRITE_CSR(pmpaddr10,frame->pmpaddr10);
|
||||
RV_WRITE_CSR(pmpaddr11,frame->pmpaddr11);
|
||||
RV_WRITE_CSR(pmpaddr12,frame->pmpaddr12);
|
||||
RV_WRITE_CSR(pmpaddr13,frame->pmpaddr13);
|
||||
RV_WRITE_CSR(pmpaddr14,frame->pmpaddr14);
|
||||
RV_WRITE_CSR(pmpaddr15,frame->pmpaddr15);
|
||||
|
||||
RV_WRITE_CSR(utvec, frame->utvec);
|
||||
RV_WRITE_CSR(ustatus, frame->ustatus);
|
||||
RV_WRITE_CSR(uepc, frame->uepc);
|
||||
RV_WRITE_CSR(ucause, frame->ucause);
|
||||
|
||||
RV_WRITE_CSR(CUSTOM_CSR_PCER_MACHINE, frame->mpcer);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_PCMR_MACHINE, frame->mpcmr);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_PCCR_MACHINE, frame->mpccr);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_CPU_TESTBUS_CTRL, frame->cpu_testbus_ctrl);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_PCER_USER, frame->upcer);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_PCMR_USER, frame->upcmr);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_PCCR_USER, frame->upccr);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_GPIO_OEN_USER,frame->ugpio_oen);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_GPIO_IN_USER, frame->ugpio_in);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_GPIO_OUT_USER,frame->ugpio_out);
|
||||
}
|
||||
|
||||
static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame)
|
||||
{
|
||||
assert(frame);
|
||||
cpu_domain_dev_regs_region_t *region = frame->region;
|
||||
uint32_t *regs_frame = frame->regs_frame;
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < frame->region_num; i++) {
|
||||
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
|
||||
regs_frame[offset++] = *(uint32_t *)addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame)
|
||||
{
|
||||
assert(frame);
|
||||
cpu_domain_dev_regs_region_t *region = frame->region;
|
||||
uint32_t *regs_frame = frame->regs_frame;
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < frame->region_num; i++) {
|
||||
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
|
||||
*(uint32_t *)addr = regs_frame[offset++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void);
|
||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
|
||||
typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool);
|
||||
|
||||
static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save();
|
||||
if ((frame->pmufunc & 0x3) == 0x1) {
|
||||
REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */
|
||||
REG_WRITE(LIGHT_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
|
||||
return (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
uint32_t mstatus = save_mstatus_and_disable_global_int();
|
||||
|
||||
/* wait cache idle */
|
||||
Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY);
|
||||
Cache_Freeze_ICache_Disable();
|
||||
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.plic_frame);
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.clint_frame);
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.intpri_frame);
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.cache_config_frame);
|
||||
RvCoreNonCriticalSleepFrame *frame = rv_core_noncritical_regs_save();
|
||||
|
||||
esp_err_t err = do_cpu_retention(goto_sleep, wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||
|
||||
rv_core_noncritical_regs_restore(frame);
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame);
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame);
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_frame);
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.plic_frame);
|
||||
|
||||
restore_mstatus(mstatus);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention_init(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
err = esp_sleep_cpu_pd_low_init();
|
||||
#elif SOC_PM_CPU_RETENTION_BY_SW
|
||||
err = esp_sleep_cpu_retention_init_impl();
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention_deinit(void)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
err = esp_sleep_cpu_pd_low_deinit();
|
||||
#elif SOC_PM_CPU_RETENTION_BY_SW
|
||||
err = esp_sleep_cpu_retention_deinit_impl();
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
bool cpu_domain_pd_allowed(void)
|
||||
{
|
||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
return (s_cpu_retention.retent.cpu_pd_mem != NULL);
|
||||
#elif SOC_PM_CPU_RETENTION_BY_SW
|
||||
return (s_cpu_retention.retent.critical_frame != NULL) && \
|
||||
(s_cpu_retention.retent.non_critical_frame != NULL) && \
|
||||
(s_cpu_retention.retent.intpri_frame != NULL) && \
|
||||
(s_cpu_retention.retent.cache_config_frame != NULL) && \
|
||||
(s_cpu_retention.retent.plic_frame != NULL) && \
|
||||
(s_cpu_retention.retent.clint_frame != NULL);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
239
components/esp_hw_support/sleep_cpu_asm.S
Normal file
239
components/esp_hw_support/sleep_cpu_asm.S
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "riscv/rvsleep-frames.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "soc/lp_aon_reg.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#endif
|
||||
|
||||
.section .data1,"aw"
|
||||
.global rv_core_critical_regs_frame
|
||||
.type rv_core_critical_regs_frame,@object
|
||||
.align 4
|
||||
rv_core_critical_regs_frame:
|
||||
.word 0
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
This assembly subroutine is used to save the critical registers of the CPU
|
||||
core to the internal RAM before sleep, and modify the PMU control flag to
|
||||
indicate that the system needs to sleep. When the subroutine returns, it
|
||||
will return the memory pointer that saves the context information of the CPU
|
||||
critical registers.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.section .iram1,"ax"
|
||||
.global rv_core_critical_regs_save
|
||||
.type rv_core_critical_regs_save,@function
|
||||
.align 4
|
||||
|
||||
rv_core_critical_regs_save:
|
||||
|
||||
/* arrived here in critical section. we need:
|
||||
save riscv core critical registers to RvCoreCriticalSleepFrame
|
||||
*/
|
||||
csrw mscratch, t0 /* use mscratch as temp storage */
|
||||
la t0, rv_core_critical_regs_frame
|
||||
lw t0, 0(t0) /* t0 pointer to RvCoreCriticalSleepFrame object */
|
||||
|
||||
sw ra, RV_SLP_CTX_RA(t0)
|
||||
sw sp, RV_SLP_CTX_SP(t0)
|
||||
sw gp, RV_SLP_CTX_GP(t0)
|
||||
sw tp, RV_SLP_CTX_TP(t0)
|
||||
sw t1, RV_SLP_CTX_T1(t0)
|
||||
sw t2, RV_SLP_CTX_T2(t0)
|
||||
sw s0, RV_SLP_CTX_S0(t0)
|
||||
sw s1, RV_SLP_CTX_S1(t0)
|
||||
sw a0, RV_SLP_CTX_A0(t0)
|
||||
|
||||
/* !! WARNING, do not use the a0 register below, a0 carries important sleep
|
||||
* information and will be returned as the return value !! */
|
||||
mv a0, t0
|
||||
|
||||
sw a1, RV_SLP_CTX_A1(t0)
|
||||
sw a2, RV_SLP_CTX_A2(t0)
|
||||
sw a3, RV_SLP_CTX_A3(t0)
|
||||
sw a4, RV_SLP_CTX_A4(t0)
|
||||
sw a5, RV_SLP_CTX_A5(t0)
|
||||
sw a6, RV_SLP_CTX_A6(t0)
|
||||
sw a7, RV_SLP_CTX_A7(t0)
|
||||
sw s2, RV_SLP_CTX_S2(t0)
|
||||
sw s3, RV_SLP_CTX_S3(t0)
|
||||
sw s4, RV_SLP_CTX_S4(t0)
|
||||
sw s5, RV_SLP_CTX_S5(t0)
|
||||
sw s6, RV_SLP_CTX_S6(t0)
|
||||
sw s7, RV_SLP_CTX_S7(t0)
|
||||
sw s8, RV_SLP_CTX_S8(t0)
|
||||
sw s9, RV_SLP_CTX_S9(t0)
|
||||
sw s10, RV_SLP_CTX_S10(t0)
|
||||
sw s11, RV_SLP_CTX_S11(t0)
|
||||
sw t3, RV_SLP_CTX_T3(t0)
|
||||
sw t4, RV_SLP_CTX_T4(t0)
|
||||
sw t5, RV_SLP_CTX_T5(t0)
|
||||
sw t6, RV_SLP_CTX_T6(t0)
|
||||
|
||||
csrr t1, mstatus
|
||||
sw t1, RV_SLP_CTX_MSTATUS(t0)
|
||||
csrr t2, mtvec
|
||||
sw t2, RV_SLP_CTX_MTVEC(t0)
|
||||
csrr t3, mcause
|
||||
sw t3, RV_SLP_CTX_MCAUSE(t0)
|
||||
|
||||
csrr t1, mtval
|
||||
sw t1, RV_SLP_CTX_MTVAL(t0)
|
||||
csrr t2, mie
|
||||
sw t2, RV_SLP_CTX_MIE(t0)
|
||||
csrr t3, mip
|
||||
sw t3, RV_SLP_CTX_MIP(t0)
|
||||
csrr t1, mepc
|
||||
sw t1, RV_SLP_CTX_MEPC(t0)
|
||||
|
||||
/*
|
||||
!!! Let idf knows it's going to sleep !!!
|
||||
|
||||
RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or
|
||||
has just been awakened. We use the lowest 2 bits as indication information,
|
||||
3 means being awakened, 1 means going to sleep.
|
||||
*/
|
||||
li t1, ~0x3
|
||||
lw t2, RV_SLP_CTX_PMUFUNC(t0)
|
||||
and t2, t1, t2
|
||||
ori t2, t2, 0x1
|
||||
sw t2, RV_SLP_CTX_PMUFUNC(t0)
|
||||
|
||||
mv t3, t0
|
||||
csrr t0, mscratch
|
||||
sw t0, RV_SLP_CTX_T0(t3)
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6
|
||||
/* writeback dcache is required here!!! */
|
||||
la t0, EXTMEM_CACHE_SYNC_MAP_REG
|
||||
li t1, 0x10
|
||||
sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */
|
||||
la t2, EXTMEM_CACHE_SYNC_ADDR_REG
|
||||
sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */
|
||||
la t0, EXTMEM_CACHE_SYNC_SIZE_REG
|
||||
sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */
|
||||
|
||||
la t1, EXTMEM_CACHE_SYNC_CTRL_REG
|
||||
lw t2, 0x0(t1)
|
||||
ori t2, t2, 0x4
|
||||
sw t2, 0x0(t1)
|
||||
|
||||
li t0, 0x10 /* SYNC_DONE bit */
|
||||
wait_sync_done:
|
||||
lw t2, 0x0(t1)
|
||||
and t2, t0, t2
|
||||
beqz t2, wait_sync_done
|
||||
#endif
|
||||
|
||||
lw t0, RV_SLP_CTX_T0(t3)
|
||||
lw t1, RV_SLP_CTX_T1(t3)
|
||||
lw t2, RV_SLP_CTX_T2(t3)
|
||||
lw t3, RV_SLP_CTX_T3(t3)
|
||||
|
||||
ret
|
||||
|
||||
.size rv_core_critical_regs_save, . - rv_core_critical_regs_save
|
||||
|
||||
|
||||
#define CSR_PCER_U 0x800
|
||||
#define CSR_PCMR_U 0x801
|
||||
#define PCER_CYCLES (1<<0) /* count clock cycles */
|
||||
#define PCMR_GLOBAL_EN (1<<0) /* enable count */
|
||||
#define pcer CSR_PCER_U
|
||||
#define pcmr CSR_PCMR_U
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
This assembly subroutine is used to restore the CPU core critical register
|
||||
context before sleep after system wakes up, modify the PMU control
|
||||
information, and return the critical register context memory object pointer.
|
||||
After the subroutine returns, continue to restore other modules of the
|
||||
system.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.section .iram1,"ax"
|
||||
.global rv_core_critical_regs_restore
|
||||
.type rv_core_critical_regs_restore,@function
|
||||
.align 4
|
||||
|
||||
rv_core_critical_regs_restore:
|
||||
|
||||
la t0, rv_core_critical_regs_frame
|
||||
lw t0, 0(t0) /* t0 pointer to RvCoreCriticalSleepFrame object */
|
||||
beqz t0, .skip_restore /* make sure we do not jump to zero address */
|
||||
|
||||
/*
|
||||
!!! Let idf knows it's sleep awake. !!!
|
||||
|
||||
RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or
|
||||
has just been awakened. We use the lowest 2 bits as indication information,
|
||||
3 means being awakened, 1 means going to sleep.
|
||||
*/
|
||||
lw t1, RV_SLP_CTX_PMUFUNC(t0)
|
||||
ori t1, t1, 0x3
|
||||
sw t1, RV_SLP_CTX_PMUFUNC(t0)
|
||||
|
||||
lw t2, RV_SLP_CTX_MEPC(t0)
|
||||
csrw mepc, t2
|
||||
lw t3, RV_SLP_CTX_MIP(t0)
|
||||
csrw mip, t3
|
||||
lw t1, RV_SLP_CTX_MIE(t0)
|
||||
csrw mie, t1
|
||||
lw t2, RV_SLP_CTX_MSTATUS(t0)
|
||||
csrw mstatus, t2
|
||||
|
||||
lw t3, RV_SLP_CTX_MTVEC(t0)
|
||||
csrw mtvec, t3
|
||||
lw t1, RV_SLP_CTX_MCAUSE(t0)
|
||||
csrw mcause, t1
|
||||
lw t2, RV_SLP_CTX_MTVAL(t0)
|
||||
csrw mtval, t2
|
||||
|
||||
lw t6, RV_SLP_CTX_T6(t0)
|
||||
lw t5, RV_SLP_CTX_T5(t0)
|
||||
lw t4, RV_SLP_CTX_T4(t0)
|
||||
lw t3, RV_SLP_CTX_T3(t0)
|
||||
lw s11, RV_SLP_CTX_S11(t0)
|
||||
lw s10, RV_SLP_CTX_S10(t0)
|
||||
lw s9, RV_SLP_CTX_S9(t0)
|
||||
lw s8, RV_SLP_CTX_S8(t0)
|
||||
lw s7, RV_SLP_CTX_S7(t0)
|
||||
lw s6, RV_SLP_CTX_S6(t0)
|
||||
lw s5, RV_SLP_CTX_S5(t0)
|
||||
lw s4, RV_SLP_CTX_S4(t0)
|
||||
lw s3, RV_SLP_CTX_S3(t0)
|
||||
lw s2, RV_SLP_CTX_S2(t0)
|
||||
lw a7, RV_SLP_CTX_A7(t0)
|
||||
lw a6, RV_SLP_CTX_A6(t0)
|
||||
lw a5, RV_SLP_CTX_A5(t0)
|
||||
lw a4, RV_SLP_CTX_A4(t0)
|
||||
lw a3, RV_SLP_CTX_A3(t0)
|
||||
lw a2, RV_SLP_CTX_A2(t0)
|
||||
lw a1, RV_SLP_CTX_A1(t0)
|
||||
lw a0, RV_SLP_CTX_A0(t0)
|
||||
lw s1, RV_SLP_CTX_S1(t0)
|
||||
lw s0, RV_SLP_CTX_S0(t0)
|
||||
lw t2, RV_SLP_CTX_T2(t0)
|
||||
lw t1, RV_SLP_CTX_T1(t0)
|
||||
lw tp, RV_SLP_CTX_TP(t0)
|
||||
lw gp, RV_SLP_CTX_GP(t0)
|
||||
lw sp, RV_SLP_CTX_SP(t0)
|
||||
lw ra, RV_SLP_CTX_RA(t0)
|
||||
lw t0, RV_SLP_CTX_T0(t0)
|
||||
|
||||
.skip_restore:
|
||||
ret
|
||||
|
||||
.size rv_core_critical_regs_restore, . - rv_core_critical_regs_restore
|
@ -20,10 +20,15 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "hal/rtc_io_hal.h"
|
||||
|
||||
#if !SOC_PMU_SUPPORTED
|
||||
#include "hal/rtc_hal.h"
|
||||
#endif
|
||||
|
||||
#include "esp_private/gpio.h"
|
||||
#include "esp_private/sleep_gpio.h"
|
||||
#include "esp_private/spi_flash_os.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "bootloader_flash.h"
|
||||
|
||||
static const char *TAG = "sleep";
|
||||
@ -180,3 +185,15 @@ void esp_deep_sleep_wakeup_io_reset(void)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO
|
||||
ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, BIT(0), 105)
|
||||
{
|
||||
// Configure to isolate (disable the Input/Output/Pullup/Pulldown
|
||||
// function of the pin) all GPIO pins in sleep state
|
||||
esp_sleep_config_gpio_isolate();
|
||||
// Enable automatic switching of GPIO configuration
|
||||
esp_sleep_enable_gpio_switch(true);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
@ -24,7 +24,11 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "hal/rtc_io_hal.h"
|
||||
|
||||
#if !SOC_PMU_SUPPORTED
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#include "hal/rtc_hal.h"
|
||||
#endif
|
||||
|
||||
#include "driver/uart.h"
|
||||
|
||||
@ -33,7 +37,6 @@
|
||||
#include "regi2c_ctrl.h" //For `REGI2C_ANA_CALI_PD_WORKAROUND`, temp
|
||||
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "hal/rtc_hal.h"
|
||||
#include "hal/uart_hal.h"
|
||||
#if SOC_TOUCH_SENSOR_SUPPORTED
|
||||
#include "hal/touch_sensor_hal.h"
|
||||
@ -46,9 +49,8 @@
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_private/brownout.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "esp_private/esp_task_wdt.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
@ -72,6 +74,8 @@
|
||||
#include "esp32c2/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/rtc.h"
|
||||
#include "hal/lp_timer_hal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/rtc.h"
|
||||
#include "esp32h2/rom/cache.h"
|
||||
@ -87,6 +91,7 @@
|
||||
|
||||
// Cycles for RTC Timer clock source (internal oscillator) calibrate
|
||||
#define RTC_CLK_SRC_CAL_CYCLES (10)
|
||||
#define FAST_CLK_SRC_CAL_CYCLES (2000) /* ~ 127.4 us */
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (212)
|
||||
@ -107,8 +112,8 @@
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)// TODO: IDF-5348
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
|
||||
#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_HARDWARE_OUT_OVERHEAD_US (9)
|
||||
@ -141,7 +146,12 @@ extern void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time
|
||||
* Internal structure which holds all requested deep sleep parameters
|
||||
*/
|
||||
typedef struct {
|
||||
esp_sleep_pd_option_t pd_options[ESP_PD_DOMAIN_MAX];
|
||||
struct {
|
||||
esp_sleep_pd_option_t pd_option;
|
||||
int16_t refs;
|
||||
uint16_t reserved; /* reserved for 4 bytes aligned */
|
||||
} domain[ESP_PD_DOMAIN_MAX];
|
||||
portMUX_TYPE lock;
|
||||
uint64_t sleep_duration;
|
||||
uint32_t wakeup_triggers : 15;
|
||||
uint32_t ext1_trigger_mode : 1;
|
||||
@ -154,6 +164,7 @@ typedef struct {
|
||||
uint32_t ccount_ticks_record;
|
||||
uint32_t sleep_time_overhead_out;
|
||||
uint32_t rtc_clk_cal_period;
|
||||
uint32_t fast_clk_cal_period;
|
||||
uint64_t rtc_ticks_at_sleep_start;
|
||||
} sleep_config_t;
|
||||
|
||||
@ -161,7 +172,13 @@ typedef struct {
|
||||
_Static_assert(22 >= SOC_RTCIO_PIN_COUNT, "Chip has more RTCIOs than 22, should increase ext1_rtc_gpio_mask field size");
|
||||
|
||||
static sleep_config_t s_config = {
|
||||
.pd_options = {[0 ... ESP_PD_DOMAIN_MAX - 1] = ESP_PD_OPTION_AUTO,},
|
||||
.domain = {
|
||||
[0 ... ESP_PD_DOMAIN_MAX - 1] = {
|
||||
.pd_option = ESP_PD_OPTION_AUTO,
|
||||
.refs = 0
|
||||
}
|
||||
},
|
||||
.lock = portMUX_INITIALIZER_UNLOCKED,
|
||||
.ccount_ticks_record = 0,
|
||||
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
|
||||
.wakeup_triggers = 0
|
||||
@ -169,9 +186,7 @@ static sleep_config_t s_config = {
|
||||
|
||||
/* Internal variable used to track if light sleep wakeup sources are to be
|
||||
expected when determining wakeup cause. */
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
|
||||
static bool s_light_sleep_wakeup = false;
|
||||
#endif
|
||||
|
||||
/* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc()
|
||||
is not thread-safe, so we need to disable interrupts before going to deep sleep. */
|
||||
@ -194,13 +209,11 @@ static uint32_t get_power_down_flags(void);
|
||||
static void ext0_wakeup_prepare(void);
|
||||
static void ext1_wakeup_prepare(void);
|
||||
#endif
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
|
||||
static void timer_wakeup_prepare(void);
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
static void touch_wakeup_prepare(void);
|
||||
#endif
|
||||
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
|
||||
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
||||
static void gpio_deep_sleep_wakeup_prepare(void);
|
||||
#endif
|
||||
|
||||
@ -292,7 +305,6 @@ void esp_deep_sleep(uint64_t time_in_us)
|
||||
}
|
||||
|
||||
// [refactor-todo] provide target logic for body of uart functions below
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
|
||||
static void IRAM_ATTR flush_uarts(void)
|
||||
{
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
@ -337,7 +349,6 @@ static void IRAM_ATTR resume_uarts(void)
|
||||
uart_ll_force_xon(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* These save-restore workaround should be moved to lower layer
|
||||
@ -350,8 +361,8 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(void)
|
||||
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
|
||||
gpio_sleep_mode_config_apply();
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
|
||||
sleep_enable_memory_retention();
|
||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
sleep_enable_cpu_retention();
|
||||
#endif
|
||||
#if REGI2C_ANA_CALI_PD_WORKAROUND
|
||||
regi2c_analog_cali_reg_read();
|
||||
@ -363,8 +374,8 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(void)
|
||||
*/
|
||||
inline static void IRAM_ATTR misc_modules_wake_prepare(void)
|
||||
{
|
||||
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
|
||||
sleep_disable_memory_retention();
|
||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
sleep_disable_cpu_retention();
|
||||
#endif
|
||||
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
|
||||
gpio_sleep_mode_config_unapply();
|
||||
@ -377,7 +388,7 @@ inline static void IRAM_ATTR misc_modules_wake_prepare(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu);
|
||||
inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp);
|
||||
|
||||
inline static bool is_light_sleep(uint32_t pd_flags)
|
||||
{
|
||||
@ -386,9 +397,6 @@ inline static bool is_light_sleep(uint32_t pd_flags)
|
||||
|
||||
static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
return 0; // TODO: WIFI-5150
|
||||
#else
|
||||
// Stop UART output so that output is not lost due to APB frequency change.
|
||||
// For light sleep, suspend UART output — it will resume after wakeup.
|
||||
// For deep sleep, wait for the contents of UART FIFO to be sent.
|
||||
@ -492,6 +500,12 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
}
|
||||
|
||||
// Enter sleep
|
||||
#if SOC_PMU_SUPPORTED
|
||||
pmu_sleep_config_t config;
|
||||
pmu_sleep_init(pmu_sleep_config_default(&config, pd_flags, s_config.sleep_time_adjustment,
|
||||
s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period,
|
||||
deep_sleep), deep_sleep);
|
||||
#else
|
||||
rtc_sleep_config_t config;
|
||||
rtc_sleep_get_default_config(sleep_flags, &config);
|
||||
rtc_sleep_init(config);
|
||||
@ -500,6 +514,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
if (!deep_sleep) {
|
||||
rtc_sleep_low_init(s_config.rtc_clk_cal_period);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Configure timer wakeup
|
||||
if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) {
|
||||
@ -513,6 +528,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
esp_sleep_isolate_digital_gpio();
|
||||
#endif
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349
|
||||
|
||||
#if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
||||
extern char _rtc_text_start[];
|
||||
#if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM
|
||||
@ -523,7 +540,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start;
|
||||
#endif
|
||||
esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length);
|
||||
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu);
|
||||
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, 0);
|
||||
#else
|
||||
#if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
/* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */
|
||||
@ -531,14 +548,26 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
// RTC has no rtc memory, IDF-3901
|
||||
set_rtc_memory_crc();
|
||||
#endif
|
||||
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu);
|
||||
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, 0);
|
||||
#else
|
||||
/* Otherwise, need to call the dedicated soc function for this */
|
||||
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
|
||||
#endif
|
||||
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
||||
|
||||
#else
|
||||
result = ESP_OK;
|
||||
#endif
|
||||
} else {
|
||||
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu);
|
||||
#if SOC_PM_CPU_RETENTION_BY_SW
|
||||
if (pd_flags & PMU_SLEEP_PD_CPU) {
|
||||
result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
|
||||
} else {
|
||||
result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
|
||||
}
|
||||
#else
|
||||
result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Restore CPU frequency
|
||||
@ -553,13 +582,14 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
resume_uarts();
|
||||
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu)
|
||||
inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
return rtc_sleep_start(s_config.wakeup_triggers, reject_triggers);
|
||||
#elif SOC_PMU_SUPPORTED
|
||||
return pmu_sleep_start(s_config.wakeup_triggers, reject_triggers, lslp_mem_inf_fpu, dslp);
|
||||
#else
|
||||
return rtc_sleep_start(s_config.wakeup_triggers, reject_triggers, lslp_mem_inf_fpu);
|
||||
#endif
|
||||
@ -624,26 +654,23 @@ void IRAM_ATTR esp_deep_sleep_start(void)
|
||||
* Helper function which handles entry to and exit from light sleep
|
||||
* Placed into IRAM as flash may need some time to be powered on.
|
||||
*/
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
|
||||
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
uint32_t flash_enable_time_us,
|
||||
rtc_vddsdio_config_t vddsdio_config) IRAM_ATTR __attribute__((noinline));
|
||||
uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline));
|
||||
|
||||
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
uint32_t flash_enable_time_us,
|
||||
rtc_vddsdio_config_t vddsdio_config)
|
||||
uint32_t flash_enable_time_us)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
return ESP_ERR_NOT_SUPPORTED; // TODO: WIFI-5150
|
||||
#else
|
||||
// Enter sleep
|
||||
uint32_t reject = esp_sleep_start(pd_flags);
|
||||
|
||||
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
||||
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
||||
// If VDDSDIO regulator was controlled by RTC registers before sleep,
|
||||
// restore the configuration.
|
||||
if (vddsdio_config.force) {
|
||||
rtc_vddsdio_set_config(vddsdio_config);
|
||||
}
|
||||
#endif
|
||||
|
||||
// If SPI flash was powered down, wait for it to become ready
|
||||
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
||||
@ -652,9 +679,7 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
}
|
||||
|
||||
return reject ? ESP_ERR_SLEEP_REJECT : ESP_OK;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vddsdio is used for power supply of spi flash
|
||||
@ -665,18 +690,16 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
* x | 1 | pd flash with relaxed conditions(force_pd)
|
||||
* 1 | 0 | pd flash with strict conditions(safe_pd)
|
||||
*/
|
||||
static inline bool can_power_down_vddsdio(const uint32_t vddsdio_pd_sleep_duration)
|
||||
static inline bool can_power_down_vddsdio(uint32_t pd_flags, const uint32_t vddsdio_pd_sleep_duration)
|
||||
{
|
||||
bool force_pd = !(s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) || (s_config.sleep_duration > vddsdio_pd_sleep_duration);
|
||||
bool safe_pd = (s_config.wakeup_triggers == RTC_TIMER_TRIG_EN) && (s_config.sleep_duration > vddsdio_pd_sleep_duration);
|
||||
return (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] == ESP_PD_OPTION_OFF) ? force_pd : safe_pd;
|
||||
return (pd_flags & RTC_SLEEP_PD_VDDSDIO) ? force_pd : safe_pd;
|
||||
}
|
||||
|
||||
esp_err_t esp_light_sleep_start(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
return ESP_ERR_NOT_SUPPORTED; // TODO: WIFI-5150
|
||||
#else
|
||||
s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
|
||||
#if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
esp_err_t timerret = ESP_OK;
|
||||
|
||||
@ -684,9 +707,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
timerret = esp_task_wdt_stop();
|
||||
#endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
|
||||
s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
|
||||
static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL(&light_sleep_lock);
|
||||
portENTER_CRITICAL(&s_config.lock);
|
||||
/*
|
||||
Note: We are about to stall the other CPU via the esp_ipc_isr_stall_other_cpu(). However, there is a chance of
|
||||
deadlock if after stalling the other CPU, we attempt to take spinlocks already held by the other CPU that is.
|
||||
@ -710,7 +731,11 @@ esp_err_t esp_light_sleep_start(void)
|
||||
*/
|
||||
esp_clk_private_lock();
|
||||
|
||||
#if SOC_LP_TIMER_SUPPORTED
|
||||
s_config.rtc_ticks_at_sleep_start = lp_timer_hal_get_cycle_count(0);
|
||||
#else
|
||||
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
|
||||
#endif
|
||||
uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count();
|
||||
uint64_t high_res_time_at_start = esp_timer_get_time();
|
||||
uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
|
||||
@ -751,9 +776,16 @@ esp_err_t esp_light_sleep_start(void)
|
||||
* 4. Code execution time which can be measured;
|
||||
*/
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
s_config.fast_clk_cal_period = rtc_clk_cal(RTC_CAL_RC_FAST, FAST_CLK_SRC_CAL_CYCLES);
|
||||
int sleep_time_sw_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out;
|
||||
int sleep_time_hw_adjustment = pmu_sleep_calculate_hw_wait_time(pd_flags, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period);
|
||||
s_config.sleep_time_adjustment = sleep_time_sw_adjustment + sleep_time_hw_adjustment;
|
||||
#else
|
||||
uint32_t rtc_cntl_xtl_buf_wait_slp_cycles = rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, s_config.rtc_clk_cal_period);
|
||||
s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out
|
||||
+ rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_slp_cycles + RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES, s_config.rtc_clk_cal_period);
|
||||
#endif
|
||||
|
||||
// Decide if VDD_SDIO needs to be powered down;
|
||||
// If it needs to be powered down, adjust sleep time.
|
||||
@ -781,7 +813,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US + s_config.sleep_time_adjustment
|
||||
+ rtc_time_slowclk_to_us(RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period));
|
||||
|
||||
if (can_power_down_vddsdio(vddsdio_pd_sleep_duration)) {
|
||||
if (can_power_down_vddsdio(pd_flags, vddsdio_pd_sleep_duration)) {
|
||||
if (s_config.sleep_time_overhead_out < flash_enable_time_us) {
|
||||
s_config.sleep_time_adjustment += flash_enable_time_us;
|
||||
}
|
||||
@ -799,8 +831,6 @@ esp_err_t esp_light_sleep_start(void)
|
||||
|
||||
periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in);
|
||||
|
||||
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
||||
|
||||
// Safety net: enable WDT in case exit from light sleep fails
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-5653
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &LP_WDT};
|
||||
@ -829,14 +859,18 @@ esp_err_t esp_light_sleep_start(void)
|
||||
err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION;
|
||||
} else {
|
||||
// Enter sleep, then wait for flash to be ready on wakeup
|
||||
err = esp_light_sleep_inner(pd_flags, flash_enable_time_us, vddsdio_config);
|
||||
err = esp_light_sleep_inner(pd_flags, flash_enable_time_us);
|
||||
}
|
||||
|
||||
// light sleep wakeup flag only makes sense after a successful light sleep
|
||||
s_light_sleep_wakeup = (err == ESP_OK);
|
||||
|
||||
// System timer has been stopped for the duration of the sleep, correct for that.
|
||||
#if SOC_LP_TIMER_SUPPORTED
|
||||
uint64_t rtc_ticks_at_end = lp_timer_hal_get_cycle_count(0);
|
||||
#else
|
||||
uint64_t rtc_ticks_at_end = rtc_time_get();
|
||||
#endif
|
||||
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period);
|
||||
|
||||
/**
|
||||
@ -856,8 +890,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
}
|
||||
portEXIT_CRITICAL(&light_sleep_lock);
|
||||
s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
|
||||
portEXIT_CRITICAL(&s_config.lock);
|
||||
|
||||
#if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
/* Restart the Task Watchdog timer as it was stopped before sleeping. */
|
||||
@ -866,8 +899,8 @@ esp_err_t esp_light_sleep_start(void)
|
||||
}
|
||||
#endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER
|
||||
|
||||
s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL);
|
||||
return err;
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
|
||||
@ -945,7 +978,6 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
|
||||
static void timer_wakeup_prepare(void)
|
||||
{
|
||||
int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment;
|
||||
@ -954,9 +986,13 @@ static void timer_wakeup_prepare(void)
|
||||
}
|
||||
|
||||
int64_t ticks = rtc_time_us_to_slowclk(sleep_duration, s_config.rtc_clk_cal_period);
|
||||
|
||||
#if SOC_LP_TIMER_SUPPORTED
|
||||
lp_timer_hal_set_alarm_target(0, s_config.rtc_ticks_at_sleep_start + ticks);
|
||||
#else
|
||||
rtc_hal_set_wakeup_timer(s_config.rtc_ticks_at_sleep_start + ticks);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
/* In deep sleep mode, only the sleep channel is supported, and other touch channels should be turned off. */
|
||||
@ -1092,7 +1128,7 @@ static void ext1_wakeup_prepare(void)
|
||||
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
// Pad configuration depends on RTC_PERIPH state in sleep mode
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) {
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option != ESP_PD_OPTION_ON) {
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
// RTC_PERIPH will be powered down, so RTC_IO_ registers will
|
||||
// loose their state. Lock pad configuration.
|
||||
@ -1139,16 +1175,20 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void)
|
||||
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
||||
uint64_t esp_sleep_get_gpio_wakeup_status(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349
|
||||
return 0;
|
||||
#else
|
||||
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_GPIO) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rtc_hal_gpio_get_wakeup_status();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150
|
||||
static void gpio_deep_sleep_wakeup_prepare(void)
|
||||
{
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349
|
||||
for (gpio_num_t gpio_idx = GPIO_NUM_0; gpio_idx < GPIO_NUM_MAX; gpio_idx++) {
|
||||
if (((1ULL << gpio_idx) & s_config.gpio_wakeup_mask) == 0) {
|
||||
continue;
|
||||
@ -1164,8 +1204,8 @@ static void gpio_deep_sleep_wakeup_prepare(void)
|
||||
}
|
||||
// Clear state from previous wakeup
|
||||
rtc_hal_gpio_clear_wakeup_status();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode)
|
||||
{
|
||||
@ -1265,14 +1305,18 @@ esp_err_t esp_sleep_disable_bt_wakeup(void)
|
||||
|
||||
esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-5645
|
||||
#if CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-5645
|
||||
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
#else
|
||||
if (esp_rom_get_reset_reason(0) != RESET_REASON_CORE_DEEP_SLEEP && !s_light_sleep_wakeup) {
|
||||
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU);
|
||||
#else
|
||||
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
|
||||
#endif
|
||||
|
||||
if (wakeup_cause & RTC_TIMER_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_TIMER;
|
||||
@ -1314,13 +1358,20 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,
|
||||
esp_sleep_pd_option_t option)
|
||||
esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_t option)
|
||||
{
|
||||
if (domain >= ESP_PD_DOMAIN_MAX || option > ESP_PD_OPTION_AUTO) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
s_config.pd_options[domain] = option;
|
||||
portENTER_CRITICAL_SAFE(&s_config.lock);
|
||||
int refs = (option == ESP_PD_OPTION_ON) ? s_config.domain[domain].refs++ \
|
||||
: (option == ESP_PD_OPTION_OFF) ? --s_config.domain[domain].refs \
|
||||
: s_config.domain[domain].refs;
|
||||
if (refs == 0) {
|
||||
s_config.domain[domain].pd_option = option;
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&s_config.lock);
|
||||
assert(refs >= 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -1342,9 +1393,9 @@ static uint32_t get_power_down_flags(void)
|
||||
*/
|
||||
volatile size_t rtc_slow_mem_used = (size_t)&_rtc_slow_length;
|
||||
|
||||
if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) &&
|
||||
if ((s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option == ESP_PD_OPTION_AUTO) &&
|
||||
(rtc_slow_mem_used > 0 || (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON;
|
||||
s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option = ESP_PD_OPTION_ON;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1353,27 +1404,27 @@ static uint32_t get_power_down_flags(void)
|
||||
/* RTC_FAST_MEM is needed for deep sleep stub.
|
||||
If RTC_FAST_MEM is Auto, keep it powered on, so that deep sleep stub can run.
|
||||
In the new chip revision, deep sleep stub will be optional, and this can be changed. */
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] == ESP_PD_OPTION_AUTO) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON;
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option == ESP_PD_OPTION_AUTO) {
|
||||
s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON;
|
||||
}
|
||||
#else
|
||||
/* If RTC_FAST_MEM is used for heap, force RTC_FAST_MEM to be powered on. */
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON;
|
||||
s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
// RTC_PERIPH is needed for EXT0 wakeup and GPIO wakeup.
|
||||
// If RTC_PERIPH is left auto (EXT0/GPIO aren't enabled), RTC_PERIPH will be powered off by default.
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) {
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option == ESP_PD_OPTION_AUTO) {
|
||||
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN)) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON;
|
||||
s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option = ESP_PD_OPTION_ON;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
else if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
||||
// On ESP32, forcing power up of RTC_PERIPH
|
||||
// prevents ULP timer and touch FSMs from working correctly.
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_OFF;
|
||||
s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option = ESP_PD_OPTION_OFF;
|
||||
}
|
||||
#endif //CONFIG_IDF_TARGET_ESP32
|
||||
}
|
||||
@ -1381,56 +1432,9 @@ static uint32_t get_power_down_flags(void)
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
if (!cpu_domain_pd_allowed()) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON;
|
||||
s_config.domain[ESP_PD_DOMAIN_CPU].pd_option = ESP_PD_OPTION_ON;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF;
|
||||
#endif
|
||||
|
||||
const __attribute__((unused)) char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */};
|
||||
/* This function is called from a critical section, log with ESP_EARLY_LOGD. */
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
ESP_EARLY_LOGD(TAG, "RTC_PERIPH: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]]);
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_MEM: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]]);
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
||||
ESP_EARLY_LOGD(TAG, "RTC_FAST_MEM: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]);
|
||||
#endif
|
||||
|
||||
// Prepare flags based on the selected options
|
||||
uint32_t pd_flags = 0;
|
||||
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_PERIPH;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_CPU;
|
||||
}
|
||||
#endif
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RC_FAST] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_INT_8M;
|
||||
}
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_XTAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* VDD_SDIO power domain shall be kept on during the light sleep
|
||||
* when CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set and off when it is set.
|
||||
@ -1440,15 +1444,80 @@ static uint32_t get_power_down_flags(void)
|
||||
* In deep sleep mode, the power domain will be turned off, regardless the
|
||||
* value of this field.
|
||||
*/
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] == ESP_PD_OPTION_AUTO) {
|
||||
#if SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option == ESP_PD_OPTION_AUTO) {
|
||||
#ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH
|
||||
s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] = ESP_PD_OPTION_ON;
|
||||
s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] != ESP_PD_OPTION_ON) {
|
||||
#if SOC_PM_SUPPORT_XTAL_PD
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option = ESP_PD_OPTION_OFF;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const __attribute__((unused)) char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */};
|
||||
/* This function is called from a critical section, log with ESP_EARLY_LOGD. */
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
ESP_EARLY_LOGD(TAG, "RTC_PERIPH: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option]);
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_MEM: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option]);
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
||||
ESP_EARLY_LOGD(TAG, "RTC_FAST_MEM: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option]);
|
||||
#endif
|
||||
|
||||
// Prepare flags based on the selected options
|
||||
uint32_t pd_flags = 0;
|
||||
#if SOC_PM_SUPPORT_RTC_FAST_MEM_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_PERIPH;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_CPU].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_CPU;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_XTAL32K_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_XTAL32K].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= PMU_SLEEP_PD_XTAL32K;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RC32K_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RC32K].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= PMU_SLEEP_PD_RC32K;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_RC_FAST_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_RC_FAST].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_INT_8M;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_XTAL_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_XTAL;
|
||||
}
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((defined CONFIG_RTC_CLK_SRC_EXT_CRYS) && (defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT) && (SOC_PM_SUPPORT_RTC_PERIPH_PD))
|
||||
if ((s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) == 0) {
|
||||
@ -1474,15 +1543,3 @@ void rtc_sleep_enable_ultra_low(bool enable)
|
||||
{
|
||||
s_ultra_low_enabled = enable;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO
|
||||
ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, BIT(0), 105)
|
||||
{
|
||||
// Configure to isolate (disable the Input/Output/Pullup/Pulldown
|
||||
// function of the pin) all GPIO pins in sleep state
|
||||
esp_sleep_config_gpio_isolate();
|
||||
// Enable automatic switching of GPIO configuration
|
||||
esp_sleep_enable_gpio_switch(true);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,219 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/rtc_hal.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#endif
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "sleep";
|
||||
|
||||
/**
|
||||
* Internal structure which holds all requested light sleep memory retention parameters
|
||||
*/
|
||||
typedef struct {
|
||||
rtc_cntl_sleep_retent_t retent;
|
||||
} sleep_retention_t;
|
||||
|
||||
static DRAM_ATTR __attribute__((unused)) sleep_retention_t s_retention;
|
||||
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size)
|
||||
{
|
||||
int sets; /* i/d-cache total set counts */
|
||||
int index; /* virtual address mapping i/d-cache row offset */
|
||||
int waysgrp;
|
||||
int icache_tagmem_blk_gs, dcache_tagmem_blk_gs;
|
||||
struct cache_mode imode = { .icache = 1 };
|
||||
struct cache_mode dmode = { .icache = 0 };
|
||||
|
||||
/* calculate/prepare i-cache tag memory retention parameters */
|
||||
Cache_Get_Mode(&imode);
|
||||
sets = imode.cache_size / imode.cache_ways / imode.cache_line_size;
|
||||
index = (code_seg_vaddr / imode.cache_line_size) % sets;
|
||||
waysgrp = imode.cache_ways >> 2;
|
||||
|
||||
code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size);
|
||||
|
||||
s_retention.retent.tagmem.icache.start_point = index;
|
||||
s_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff;
|
||||
s_retention.retent.tagmem.icache.vld_size = s_retention.retent.tagmem.icache.size;
|
||||
if (code_seg_size < imode.cache_size / imode.cache_ways) {
|
||||
s_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp;
|
||||
}
|
||||
s_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0;
|
||||
icache_tagmem_blk_gs = s_retention.retent.tagmem.icache.vld_size ? s_retention.retent.tagmem.icache.vld_size : sets * waysgrp;
|
||||
icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs);
|
||||
ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10),
|
||||
imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs);
|
||||
|
||||
/* calculate/prepare d-cache tag memory retention parameters */
|
||||
Cache_Get_Mode(&dmode);
|
||||
sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size;
|
||||
index = (data_seg_vaddr / dmode.cache_line_size) % sets;
|
||||
waysgrp = dmode.cache_ways >> 2;
|
||||
|
||||
data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size);
|
||||
|
||||
s_retention.retent.tagmem.dcache.start_point = index;
|
||||
s_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff;
|
||||
s_retention.retent.tagmem.dcache.vld_size = s_retention.retent.tagmem.dcache.size;
|
||||
#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB
|
||||
if (data_seg_size < dmode.cache_size / dmode.cache_ways) {
|
||||
s_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp;
|
||||
}
|
||||
s_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0;
|
||||
#else
|
||||
s_retention.retent.tagmem.dcache.enable = 1;
|
||||
#endif
|
||||
dcache_tagmem_blk_gs = s_retention.retent.tagmem.dcache.vld_size ? s_retention.retent.tagmem.dcache.vld_size : sets * waysgrp;
|
||||
dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs);
|
||||
ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10),
|
||||
dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs);
|
||||
|
||||
/* For I or D cache tagmem retention, backup and restore are performed through
|
||||
* RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache
|
||||
* tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically
|
||||
* aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4
|
||||
* i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */
|
||||
return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3);
|
||||
}
|
||||
#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
|
||||
static esp_err_t esp_sleep_tagmem_pd_low_init(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
if (s_retention.retent.tagmem.link_addr == NULL) {
|
||||
extern char _stext[], _etext[];
|
||||
uint32_t code_start = (uint32_t)_stext;
|
||||
uint32_t code_size = (uint32_t)(_etext - _stext);
|
||||
#if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32S3)
|
||||
extern char _rodata_start[], _rodata_reserved_end[];
|
||||
uint32_t data_start = (uint32_t)_rodata_start;
|
||||
uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start);
|
||||
#else
|
||||
uint32_t data_start = SOC_DROM_LOW;
|
||||
uint32_t data_size = SOC_EXTRAM_DATA_SIZE;
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB",
|
||||
code_start, (float)code_size/1024, data_start, (float)data_size/1024);
|
||||
int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size);
|
||||
void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN,
|
||||
tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE,
|
||||
MALLOC_CAP_RETENTION);
|
||||
if (buf) {
|
||||
memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE);
|
||||
s_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf,
|
||||
buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL);
|
||||
} else {
|
||||
s_retention.retent.tagmem.icache.enable = 0;
|
||||
s_retention.retent.tagmem.dcache.enable = 0;
|
||||
s_retention.retent.tagmem.link_addr = NULL;
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
s_retention.retent.tagmem.icache.enable = 0;
|
||||
s_retention.retent.tagmem.dcache.enable = 0;
|
||||
s_retention.retent.tagmem.link_addr = NULL;
|
||||
#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||
} else {
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
if (s_retention.retent.tagmem.link_addr) {
|
||||
heap_caps_free(s_retention.retent.tagmem.link_addr);
|
||||
s_retention.retent.tagmem.icache.enable = 0;
|
||||
s_retention.retent.tagmem.dcache.enable = 0;
|
||||
s_retention.retent.tagmem.link_addr = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif // SOC_PM_SUPPORT_TAGMEM_PD
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
|
||||
esp_err_t esp_sleep_cpu_pd_low_init(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
if (s_retention.retent.cpu_pd_mem == NULL) {
|
||||
void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN,
|
||||
SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
|
||||
MALLOC_CAP_RETENTION);
|
||||
if (buf) {
|
||||
memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE);
|
||||
s_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
|
||||
buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
|
||||
} else {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (s_retention.retent.cpu_pd_mem) {
|
||||
heap_caps_free(s_retention.retent.cpu_pd_mem);
|
||||
s_retention.retent.cpu_pd_mem = NULL;
|
||||
}
|
||||
}
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
if (esp_sleep_tagmem_pd_low_init(enable) != ESP_OK) {
|
||||
#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB
|
||||
esp_sleep_cpu_pd_low_init(false);
|
||||
return ESP_ERR_NO_MEM;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool cpu_domain_pd_allowed(void)
|
||||
{
|
||||
return (s_retention.retent.cpu_pd_mem != NULL);
|
||||
}
|
||||
|
||||
#endif // SOC_PM_SUPPORT_CPU_PD
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
|
||||
|
||||
void sleep_enable_memory_retention(void)
|
||||
{
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
rtc_cntl_hal_enable_cpu_retention(&s_retention.retent);
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
rtc_cntl_hal_enable_tagmem_retention(&s_retention.retent);
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR sleep_disable_memory_retention(void)
|
||||
{
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
rtc_cntl_hal_disable_cpu_retention(&s_retention.retent);
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||
rtc_cntl_hal_disable_tagmem_retention(&s_retention.retent);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD
|
@ -15,9 +15,19 @@
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#include "hal/uart_ll.h"
|
||||
|
||||
#if SOC_LP_TIMER_SUPPORTED
|
||||
#include "hal/lp_timer_ll.h"
|
||||
#include "hal/lp_timer_hal.h"
|
||||
#else
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#endif
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
#include "hal/pmu_ll.h"
|
||||
#endif
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_rom_sys.h"
|
||||
@ -57,7 +67,12 @@ void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub)
|
||||
#endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_MEM
|
||||
|
||||
// Go to sleep.
|
||||
#if SOC_PMU_SUPPORTED
|
||||
pmu_ll_hp_set_sleep_enable(&PMU);
|
||||
#else
|
||||
rtc_cntl_ll_sleep_enable();
|
||||
#endif
|
||||
|
||||
// A few CPU cycles may be necessary for the sleep to start...
|
||||
while (true) {};
|
||||
// never reaches here.
|
||||
@ -70,12 +85,23 @@ void RTC_IRAM_ATTR esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no)
|
||||
|
||||
void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us)
|
||||
{
|
||||
#if SOC_LP_TIMER_SUPPORTED
|
||||
uint64_t rtc_count_delta = lp_timer_ll_time_to_count(time_in_us);
|
||||
uint64_t rtc_curr_count = lp_timer_hal_get_cycle_count(0);
|
||||
lp_timer_hal_set_alarm_target(0, rtc_curr_count + rtc_count_delta);
|
||||
#else
|
||||
uint64_t rtc_count_delta = rtc_cntl_ll_time_to_count(time_in_us);
|
||||
uint64_t rtc_curr_count = rtc_cntl_ll_get_rtc_time();
|
||||
rtc_cntl_ll_set_wakeup_timer(rtc_curr_count + rtc_count_delta);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
uint32_t RTC_IRAM_ATTR esp_wake_stub_get_wakeup_cause(void)
|
||||
{
|
||||
#if SOC_PMU_SUPPORTED
|
||||
return pmu_ll_hp_get_wakeup_cause(&PMU);
|
||||
#else
|
||||
return rtc_cntl_ll_get_wakeup_cause();
|
||||
#endif
|
||||
}
|
||||
|
@ -2,10 +2,10 @@ menu "Power Management"
|
||||
config PM_ENABLE
|
||||
bool "Support for power management"
|
||||
# SMP FreeRTOS currently does not support power management IDF-4997
|
||||
# ESP32C6 currently does not support power management IDF-5347 IDF-6270
|
||||
# Note. Disabling this option for C6 will also cause all sdkconfig.release test cases run without pm enabled
|
||||
# ORed with __DOXYGEN__ to pass C6 docs build, need to remove when pm is supported on C6
|
||||
depends on (!FREERTOS_SMP && !IDF_TARGET_ESP32C6 && !IDF_TARGET_ESP32H2) || __DOXYGEN__
|
||||
# ESP32H2 currently does not support power management IDF-6270
|
||||
# Note. Disabling this option for H2 will also cause all sdkconfig.release test cases run without pm enabled
|
||||
# ORed with __DOXYGEN__ to pass H2 docs build, need to remove when pm is supported on H2
|
||||
depends on (!FREERTOS_SMP && !IDF_TARGET_ESP32H2) || __DOXYGEN__
|
||||
default n
|
||||
help
|
||||
If enabled, application is compiled with support for power management.
|
||||
@ -87,7 +87,7 @@ menu "Power Management"
|
||||
|
||||
config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
||||
bool "Power down CPU in light sleep"
|
||||
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6
|
||||
select PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB
|
||||
default y
|
||||
help
|
||||
|
@ -15,16 +15,17 @@ entries:
|
||||
sleep_modes:esp_sleep_enable_timer_wakeup (noflash)
|
||||
sleep_modes:timer_wakeup_prepare (noflash)
|
||||
sleep_modes:get_power_down_flags (noflash)
|
||||
rtc_init:rtc_vddsdio_get_config (noflash)
|
||||
if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED:
|
||||
rtc_init:rtc_vddsdio_get_config (noflash)
|
||||
esp_clk:esp_clk_slowclk_cal_set (noflash)
|
||||
esp_clk:esp_clk_slowclk_cal_get (noflash)
|
||||
esp_clk:esp_rtc_get_time_us (noflash)
|
||||
if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y:
|
||||
sleep_gpio:gpio_sleep_mode_config_apply (noflash)
|
||||
if SOC_PM_SUPPORT_CPU_PD = y || SOC_PM_SUPPORT_TAGMEM_PD = y:
|
||||
sleep_retention:sleep_enable_memory_retention (noflash)
|
||||
if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y && (SOC_PM_SUPPORT_CPU_PD = y || SOC_PM_SUPPORT_TAGMEM_PD = y):
|
||||
sleep_cpu:sleep_enable_cpu_retention (noflash)
|
||||
if SOC_PM_SUPPORT_CPU_PD = y:
|
||||
sleep_retention:cpu_domain_pd_allowed (noflash)
|
||||
sleep_cpu:cpu_domain_pd_allowed (noflash)
|
||||
|
||||
[mapping:esp_system_pm]
|
||||
archive: libesp_system.a
|
||||
@ -86,7 +87,8 @@ entries:
|
||||
gpio_hal_workaround:gpio_hal_sleep_pupd_config_unapply (noflash)
|
||||
gpio_hal_workaround:gpio_hal_sleep_mode_setup_wrapper (noflash)
|
||||
gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash)
|
||||
if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y:
|
||||
rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash)
|
||||
if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y:
|
||||
rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash)
|
||||
if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y:
|
||||
if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y:
|
||||
rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash)
|
||||
if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y:
|
||||
rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash)
|
||||
|
@ -288,6 +288,13 @@ esp_err_t esp_pm_configure(const void* vconfig)
|
||||
*/
|
||||
apb_max_freq = 80;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
/* Maximum SOC APB clock frequency is 40 MHz, maximum Modem (WiFi,
|
||||
* Bluetooth, etc..) APB clock frequency is 80 MHz */
|
||||
const int soc_apb_clk_freq = esp_clk_apb_freq() / MHZ;
|
||||
const int modem_apb_clk_freq = MODEM_APB_CLK_FREQ / MHZ;
|
||||
const int apb_clk_freq = MAX(soc_apb_clk_freq, modem_apb_clk_freq);
|
||||
int apb_max_freq = MIN(max_freq_mhz, apb_clk_freq); /* CPU frequency in APB_MAX mode */
|
||||
#else
|
||||
int apb_max_freq = MIN(max_freq_mhz, 80); /* CPU frequency in APB_MAX mode */
|
||||
#endif
|
||||
@ -320,9 +327,12 @@ esp_err_t esp_pm_configure(const void* vconfig)
|
||||
#endif
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_SUPPORT_CPU_PD
|
||||
esp_err_t ret = esp_sleep_cpu_pd_low_init(config->light_sleep_enable);
|
||||
if (config->light_sleep_enable && ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep.");
|
||||
if (config->light_sleep_enable) {
|
||||
if (esp_sleep_cpu_retention_init() != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep.");
|
||||
}
|
||||
} else {
|
||||
esp_sleep_cpu_retention_deinit();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -32,7 +32,7 @@ extern "C" {
|
||||
* Please do not use reserved or used rtc memory or registers. *
|
||||
* *
|
||||
*************************************************************************************
|
||||
* RTC Memory & Store Register usage
|
||||
* LP Memory & Store Register usage
|
||||
*************************************************************************************
|
||||
* rtc memory addr type size usage
|
||||
* 0x3f421000(0x50000000) Slow SIZE_CP Co-Processor code/Reset Entry
|
||||
@ -42,25 +42,29 @@ extern "C" {
|
||||
*
|
||||
*************************************************************************************
|
||||
* RTC store registers usage
|
||||
* RTC_CNTL_STORE0_REG Reserved
|
||||
* RTC_CNTL_STORE1_REG RTC_SLOW_CLK calibration value
|
||||
* RTC_CNTL_STORE2_REG Boot time, low word
|
||||
* RTC_CNTL_STORE3_REG Boot time, high word
|
||||
* RTC_CNTL_STORE4_REG External XTAL frequency
|
||||
* RTC_CNTL_STORE5_REG APB bus frequency
|
||||
* RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY
|
||||
* RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC
|
||||
* LP_AON_STORE0_REG Reserved
|
||||
* LP_AON_STORE1_REG RTC_SLOW_CLK calibration value
|
||||
* LP_AON_STORE2_REG Boot time, low word
|
||||
* LP_AON_STORE3_REG Boot time, high word
|
||||
* LP_AON_STORE4_REG External XTAL frequency
|
||||
* LP_AON_STORE5_REG FAST_RTC_MEMORY_LENGTH
|
||||
* LP_AON_STORE6_REG FAST_RTC_MEMORY_ENTRY
|
||||
* LP_AON_STORE7_REG FAST_RTC_MEMORY_CRC
|
||||
* LP_AON_STORE8_REG Store light sleep wake stub addr
|
||||
* LP_AON_STORE9_REG Store the sleep mode at bit[0] (0:light sleep 1:deep sleep)
|
||||
*************************************************************************************
|
||||
*/
|
||||
|
||||
#define RTC_SLOW_CLK_CAL_REG LP_AON_STORE1_REG
|
||||
#define RTC_BOOT_TIME_LOW_REG LP_AON_STORE2_REG
|
||||
#define RTC_BOOT_TIME_HIGH_REG LP_AON_STORE3_REG
|
||||
#define RTC_XTAL_FREQ_REG LP_AON_STORE4_REG
|
||||
#define RTC_APB_FREQ_REG LP_AON_STORE5_REG
|
||||
#define RTC_ENTRY_ADDR_REG LP_AON_STORE6_REG
|
||||
#define RTC_RESET_CAUSE_REG LP_AON_STORE6_REG
|
||||
#define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG
|
||||
#define RTC_SLOW_CLK_CAL_REG LP_AON_STORE1_REG
|
||||
#define RTC_BOOT_TIME_LOW_REG LP_AON_STORE2_REG
|
||||
#define RTC_BOOT_TIME_HIGH_REG LP_AON_STORE3_REG
|
||||
#define RTC_XTAL_FREQ_REG LP_AON_STORE4_REG
|
||||
#define RTC_ENTRY_LENGTH_REG LP_AON_STORE5_REG
|
||||
#define RTC_ENTRY_ADDR_REG LP_AON_STORE6_REG
|
||||
#define RTC_RESET_CAUSE_REG LP_AON_STORE6_REG
|
||||
#define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG
|
||||
#define LIGHT_SLEEP_WAKE_STUB_ADDR_REG LP_AON_STORE8_REG
|
||||
#define SLEEP_MODE_REG LP_AON_STORE9_REG
|
||||
|
||||
#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code.
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "esp32c2/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/rtc.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/rtc.h"
|
||||
#endif
|
||||
@ -72,6 +73,9 @@ void IRAM_ATTR bootloader_fill_random(void *buffer, size_t length)
|
||||
void esp_clk_init(void)
|
||||
{
|
||||
s_warn();
|
||||
#if SOC_PMU_SUPPORTED
|
||||
pmu_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void esp_perip_clk_init(void)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -23,6 +23,7 @@
|
||||
#include "esp_private/esp_modem_clock.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
@ -42,13 +43,7 @@ static const char *TAG = "clk";
|
||||
__attribute__((weak)) void esp_clk_init(void)
|
||||
{
|
||||
#if !CONFIG_IDF_ENV_FPGA
|
||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||
soc_reset_reason_t rst_reas;
|
||||
rst_reas = esp_rom_get_reset_reason(0);
|
||||
if (rst_reas == RESET_REASON_CHIP_POWER_ON) {
|
||||
cfg.cali_ocode = 1;
|
||||
}
|
||||
rtc_init(cfg);
|
||||
pmu_init();
|
||||
|
||||
assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M);
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on BIT(0)
|
||||
|
||||
# esp_sleep doesn't have init dependencies
|
||||
105: esp_sleep_startup_init in components/esp_hw_support/sleep_modes.c on BIT(0)
|
||||
105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0)
|
||||
|
||||
# app_trace has to be initialized before systemview
|
||||
115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "soc/rtc.h" // for wakeup trigger defines
|
||||
#include "soc/rtc_periph.h" // for read rtc registers directly (cause)
|
||||
#include "soc/soc.h" // for direct register read macros
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "test_utils.h"
|
||||
#include "sdkconfig.h"
|
||||
@ -29,6 +28,12 @@
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_random.h"
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#else
|
||||
#include "hal/rtc_cntl_ll.h"
|
||||
#endif
|
||||
|
||||
#define ESP_EXT0_WAKEUP_LEVEL_LOW 0
|
||||
#define ESP_EXT0_WAKEUP_LEVEL_HIGH 1
|
||||
|
||||
@ -445,7 +450,11 @@ __attribute__((unused)) static float get_time_ms(void)
|
||||
|
||||
__attribute__((unused)) static uint32_t get_cause(void)
|
||||
{
|
||||
#if SOC_PMU_SUPPORTED
|
||||
uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU);
|
||||
#else
|
||||
uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause();
|
||||
#endif
|
||||
return wakeup_cause;
|
||||
}
|
||||
|
||||
@ -590,4 +599,4 @@ TEST_CASE("wake up using GPIO (2 or 4 low)", "[deepsleep][ignore]")
|
||||
}
|
||||
#endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2)
|
||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) TODO: IDF-5348, IDF-5349
|
||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) TODO: IDF-5349
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -33,7 +33,6 @@
|
||||
#include "esp_phy_init.h"
|
||||
#include "soc/rtc_cntl_periph.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "phy_init_data.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
|
@ -118,6 +118,10 @@ if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "${target}/modem_clock_hal.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_LP_TIMER_SUPPORTED)
|
||||
list(APPEND srcs "${target}/lp_timer_hal.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_BOD_SUPPORTED)
|
||||
list(APPEND srcs "brownout_hal.c")
|
||||
endif()
|
||||
@ -138,6 +142,10 @@ if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "sdio_slave_hal.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_PMU_SUPPORTED)
|
||||
list(APPEND srcs "${target}/pmu_hal.c")
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "esp32")
|
||||
list(APPEND srcs
|
||||
"touch_sensor_hal.c"
|
||||
@ -198,7 +206,6 @@ if(NOT BOOTLOADER_BUILD)
|
||||
if(${target} STREQUAL "esp32c6")
|
||||
list(APPEND srcs
|
||||
"spi_flash_hal_gpspi.c"
|
||||
"esp32c6/rtc_cntl_hal.c"
|
||||
"hmac_hal.c"
|
||||
"ds_hal.c")
|
||||
|
||||
|
47
components/hal/esp32c6/include/hal/lp_timer_hal.h
Normal file
47
components/hal/esp32c6/include/hal/lp_timer_hal.h
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "soc/soc.h"
|
||||
#include "hal/lp_timer_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* @brief set alarm target value
|
||||
*
|
||||
* @param timer_id timer num of lp_timer, 0 or 1 for esp32c6
|
||||
*
|
||||
* @param value when counter reaches alarm value, alarm event will be triggered
|
||||
*/
|
||||
void lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value);
|
||||
|
||||
/**
|
||||
* @brief get current counter value
|
||||
*
|
||||
* @param timer_id timer num of lp_timer, 0 or 1 for esp32c6
|
||||
*/
|
||||
uint64_t lp_timer_hal_get_cycle_count(uint8_t timer_id);
|
||||
|
||||
/**
|
||||
* @brief clear alarm interrupt status
|
||||
*/
|
||||
void lp_timer_hal_clear_alarm_intr_status(void);
|
||||
|
||||
/**
|
||||
* @brief clear overflow interrupt status
|
||||
*/
|
||||
void lp_timer_hal_clear_overflow_intr_status(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
66
components/hal/esp32c6/include/hal/lp_timer_ll.h
Normal file
66
components/hal/esp32c6/include/hal/lp_timer_ll.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for ESP32-C6 LP_Timer register operations
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/lp_timer_struct.h"
|
||||
#include "soc/lp_aon_reg.h"
|
||||
#include "hal/lp_timer_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FORCE_INLINE_ATTR void lp_timer_ll_set_alarm_target(lp_timer_dev_t *dev, uint8_t timer_id, uint64_t value)
|
||||
{
|
||||
dev->target[timer_id].hi.target_hi = (value >> 32) & 0xFFFF;
|
||||
dev->target[timer_id].lo.target_lo = value & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void lp_timer_ll_set_target_enable(lp_timer_dev_t *dev, uint8_t timer_id, bool en)
|
||||
{
|
||||
dev->target[timer_id].hi.enable = en;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_low(lp_timer_dev_t *dev, uint8_t timer_id)
|
||||
{
|
||||
return dev->counter[timer_id].lo.counter_lo;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_high(lp_timer_dev_t *dev, uint8_t timer_id)
|
||||
{
|
||||
return dev->counter[timer_id].hi.counter_hi;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void lp_timer_ll_counter_snapshot(lp_timer_dev_t *dev)
|
||||
{
|
||||
dev->update.update = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void lp_timer_ll_clear_alarm_intr_status(lp_timer_dev_t *dev)
|
||||
{
|
||||
dev->int_clr.alarm = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void lp_timer_ll_clear_overflow_intr_status(lp_timer_dev_t *dev)
|
||||
{
|
||||
dev->int_clr.overflow = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us)
|
||||
{
|
||||
uint32_t slow_clk_value = REG_READ(LP_AON_STORE1_REG);
|
||||
return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
45
components/hal/esp32c6/include/hal/pmu_hal.h
Normal file
45
components/hal/esp32c6/include/hal/pmu_hal.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The HAL layer for PMU
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/pmu_ll.h"
|
||||
#include "hal/pmu_types.h"
|
||||
|
||||
typedef struct {
|
||||
pmu_dev_t *dev;
|
||||
} pmu_hal_context_t;
|
||||
|
||||
void pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle);
|
||||
|
||||
uint32_t pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal);
|
||||
|
||||
void pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle);
|
||||
|
||||
uint32_t pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal);
|
||||
|
||||
void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal);
|
||||
|
||||
void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal);
|
||||
|
||||
void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal);
|
||||
|
||||
void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal);
|
||||
|
||||
void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal);
|
||||
|
||||
void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
666
components/hal/esp32c6/include/hal/pmu_ll.h
Normal file
666
components/hal/esp32c6/include/hal/pmu_ll.h
Normal file
@ -0,0 +1,666 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for ESP32-C6 PMU register operations
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "esp_attr.h"
|
||||
#include "hal/assert.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the power domain that needs to be powered down in the digital power
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param mode The pmu mode
|
||||
* @param flag Digital power domain flag
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t flag)
|
||||
{
|
||||
hw->hp_sys[mode].dig_power.val = flag;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func)
|
||||
{
|
||||
hw->hp_sys[mode].icg_func = icg_func;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_apb(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t bitmap)
|
||||
{
|
||||
hw->hp_sys[mode].icg_apb = bitmap;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_modem(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t code)
|
||||
{
|
||||
hw->hp_sys[mode].icg_modem.code = code;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_uart_wakeup_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool wakeup_en)
|
||||
{
|
||||
hw->hp_sys[mode].syscntl.uart_wakeup_en = wakeup_en;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_lp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all)
|
||||
{
|
||||
hw->hp_sys[mode].syscntl.lp_pad_hold_all = hold_all;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_hp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all)
|
||||
{
|
||||
hw->hp_sys[mode].syscntl.hp_pad_hold_all = hold_all;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_pad_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel)
|
||||
{
|
||||
hw->hp_sys[mode].syscntl.dig_pad_slp_sel = slp_sel;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_pause_watchdog(pmu_dev_t *hw, pmu_hp_mode_t mode, bool pause_wdt)
|
||||
{
|
||||
hw->hp_sys[mode].syscntl.dig_pause_wdt = pause_wdt;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_cpu_stall(pmu_dev_t *hw, pmu_hp_mode_t mode, bool cpu_stall)
|
||||
{
|
||||
hw->hp_sys[mode].syscntl.dig_cpu_stall = cpu_stall;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the power domain that needs to be powered down in the clock power
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param mode The pmu mode
|
||||
* @param flag Clock power domain flag
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_clk_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t xpd_flag)
|
||||
{
|
||||
hw->hp_sys[mode].clk_power.val = xpd_flag;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_xtal_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_xtal)
|
||||
{
|
||||
hw->hp_sys[mode].xtal.xpd_xtal = xpd_xtal;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_bias)
|
||||
{
|
||||
hw->hp_sys[mode].bias.xpd_bias = xpd_bias;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_dbg_atten(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t value)
|
||||
{
|
||||
hw->hp_sys[mode].bias.dbg_atten = value;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_current_power_off(pmu_dev_t *hw, pmu_hp_mode_t mode, bool off)
|
||||
{
|
||||
hw->hp_sys[mode].bias.pd_cur = off;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool en)
|
||||
{
|
||||
hw->hp_sys[mode].bias.bias_sleep = en;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_retention_param(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t param)
|
||||
{
|
||||
hw->hp_sys[mode].backup.val = param;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_enable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_sleep2active_backup_en = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_disable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_sleep2active_backup_en = 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_enable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_disable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_enable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_MODEM].backup.hp_sleep2modem_backup_en = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_disable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_MODEM].backup.hp_sleep2modem_backup_en = 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_enable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_en = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_disable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_en = 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_enable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_disable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_backup_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func)
|
||||
{
|
||||
hw->hp_sys[mode].backup_clk = icg_func;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_nodiv(pmu_dev_t *hw, pmu_hp_mode_t mode, bool sysclk_nodiv)
|
||||
{
|
||||
hw->hp_sys[mode].sysclk.dig_sysclk_nodiv = sysclk_nodiv;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool icg_sysclk_en)
|
||||
{
|
||||
hw->hp_sys[mode].sysclk.icg_sysclk_en = icg_sysclk_en;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel)
|
||||
{
|
||||
hw->hp_sys[mode].sysclk.sysclk_slp_sel = slp_sel;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel)
|
||||
{
|
||||
hw->hp_sys[mode].sysclk.icg_slp_sel = slp_sel;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_sysclk(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t sysclk_sel)
|
||||
{
|
||||
hw->hp_sys[mode].sysclk.dig_sysclk_sel = sysclk_sel;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd)
|
||||
{
|
||||
hw->hp_sys[mode].regulator0.slp_logic_xpd = slp_xpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd)
|
||||
{
|
||||
hw->hp_sys[mode].regulator0.slp_mem_xpd = slp_xpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd)
|
||||
{
|
||||
hw->hp_sys[mode].regulator0.xpd = xpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias)
|
||||
{
|
||||
hw->hp_sys[mode].regulator0.slp_logic_dbias = slp_dbias;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias)
|
||||
{
|
||||
hw->hp_sys[mode].regulator0.slp_mem_dbias = slp_dbias;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dbias)
|
||||
{
|
||||
hw->hp_sys[mode].regulator0.dbias = dbias;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t drv_b)
|
||||
{
|
||||
hw->hp_sys[mode].regulator1.drv_b = drv_b;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_slp_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool slp_xpd)
|
||||
{
|
||||
hw->lp_sys[mode].regulator0.slp_xpd = slp_xpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd)
|
||||
{
|
||||
hw->lp_sys[mode].regulator0.xpd = xpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_sleep_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t slp_dbias)
|
||||
{
|
||||
hw->lp_sys[mode].regulator0.slp_dbias = slp_dbias;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t dbias)
|
||||
{
|
||||
hw->lp_sys[mode].regulator0.dbias = dbias;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t drv_b)
|
||||
{
|
||||
hw->lp_sys[mode].regulator1.drv_b = drv_b;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_xtal_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_xtal)
|
||||
{
|
||||
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
|
||||
hw->lp_sys[mode].xtal.xpd_xtal = xpd_xtal;
|
||||
}
|
||||
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_dig_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t flag)
|
||||
{
|
||||
hw->lp_sys[mode].dig_power.val = flag;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t xpd_flag)
|
||||
{
|
||||
hw->lp_sys[mode].clk_power.val = xpd_flag;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode)
|
||||
{
|
||||
return hw->lp_sys[mode].clk_power.val;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_bias)
|
||||
{
|
||||
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
|
||||
hw->lp_sys[mode].bias.xpd_bias = xpd_bias;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_dbg_atten(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t value)
|
||||
{
|
||||
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
|
||||
hw->lp_sys[mode].bias.dbg_atten = value;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_current_power_off(pmu_dev_t *hw, pmu_lp_mode_t mode, bool off)
|
||||
{
|
||||
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
|
||||
hw->lp_sys[mode].bias.pd_cur = off;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_lp_mode_t mode, bool en)
|
||||
{
|
||||
HAL_ASSERT(mode == PMU_MODE_LP_SLEEP);
|
||||
hw->lp_sys[mode].bias.bias_sleep = en;
|
||||
}
|
||||
|
||||
|
||||
/****/
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_set_clk_power(pmu_dev_t *hw, uint32_t flag)
|
||||
{
|
||||
hw->imm.clk_power.val = flag;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_set_icg_slp_sel(pmu_dev_t *hw, bool slp_sel)
|
||||
{
|
||||
if (slp_sel) {
|
||||
hw->imm.sleep_sysclk.tie_high_icg_slp_sel = 1;
|
||||
} else {
|
||||
hw->imm.sleep_sysclk.tie_low_icg_slp_sel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_sysclk_sel(pmu_dev_t *hw, bool update)
|
||||
{
|
||||
hw->imm.sleep_sysclk.update_dig_sysclk_sel = update;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_switch(pmu_dev_t *hw, bool update)
|
||||
{
|
||||
hw->imm.sleep_sysclk.update_dig_icg_switch = update;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_func(pmu_dev_t *hw, bool icg_func_update)
|
||||
{
|
||||
hw->imm.hp_func_icg.update_dig_icg_func_en = icg_func_update;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_apb(pmu_dev_t *hw, bool icg_apb_update)
|
||||
{
|
||||
hw->imm.hp_apb_icg.update_dig_icg_apb_en = icg_apb_update;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_modem_code(pmu_dev_t *hw, bool icg_modem_update)
|
||||
{
|
||||
hw->imm.modem_icg.update_dig_icg_modem_en = icg_modem_update;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_rootclk_sel(pmu_dev_t *hw, bool rootclk_sel)
|
||||
{
|
||||
if (rootclk_sel) {
|
||||
hw->imm.lp_icg.tie_high_lp_rootclk_sel = 1;
|
||||
} else {
|
||||
hw->imm.lp_icg.tie_low_lp_rootclk_sel = 1;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_set_hp_pad_hold_all(pmu_dev_t *hw, bool hold_all)
|
||||
{
|
||||
if (hold_all) {
|
||||
hw->imm.pad_hold_all.tie_high_hp_pad_hold_all = 1;
|
||||
} else {
|
||||
hw->imm.pad_hold_all.tie_low_hp_pad_hold_all = 1;
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_pad_hold_all(pmu_dev_t *hw, bool hold_all)
|
||||
{
|
||||
if (hold_all) {
|
||||
hw->imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
|
||||
} else {
|
||||
hw->imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*** */
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool rst)
|
||||
{
|
||||
hw->power.hp_pd[domain].force_reset = rst;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool iso)
|
||||
{
|
||||
hw->power.hp_pd[domain].force_iso = iso;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_up(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpu)
|
||||
{
|
||||
hw->power.hp_pd[domain].force_pu = fpu;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_rst)
|
||||
{
|
||||
hw->power.hp_pd[domain].force_no_reset = no_rst;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_iso)
|
||||
{
|
||||
hw->power.hp_pd[domain].force_no_iso = no_iso;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_down(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpd)
|
||||
{
|
||||
hw->power.hp_pd[domain].force_pd = fpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_reset(pmu_dev_t *hw, bool rst)
|
||||
{
|
||||
hw->power.lp_peri.force_reset = rst;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_isolate(pmu_dev_t *hw, bool iso)
|
||||
{
|
||||
hw->power.lp_peri.force_iso = iso;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_up(pmu_dev_t *hw, bool fpu)
|
||||
{
|
||||
hw->power.lp_peri.force_pu = fpu;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_reset(pmu_dev_t *hw, bool no_rst)
|
||||
{
|
||||
hw->power.lp_peri.force_no_reset = no_rst;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_isolate(pmu_dev_t *hw, bool no_iso)
|
||||
{
|
||||
hw->power.lp_peri.force_no_iso = no_iso;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_down(pmu_dev_t *hw, bool fpd)
|
||||
{
|
||||
hw->power.lp_peri.force_pd = fpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_isolate(pmu_dev_t *hw, uint32_t iso)
|
||||
{
|
||||
hw->power.mem_cntl.force_hp_mem_iso = iso;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_down(pmu_dev_t *hw, uint32_t fpd)
|
||||
{
|
||||
hw->power.mem_cntl.force_hp_mem_pd = fpd;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_no_isolate(pmu_dev_t *hw, uint32_t no_iso)
|
||||
{
|
||||
hw->power.mem_cntl.force_hp_mem_no_iso = no_iso;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_up(pmu_dev_t *hw, uint32_t fpu)
|
||||
{
|
||||
hw->power.mem_cntl.force_hp_mem_pu = fpu;
|
||||
}
|
||||
|
||||
/*** */
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_enable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->wakeup.cntl0.sleep_req = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_enable(pmu_dev_t *hw, uint32_t reject)
|
||||
{
|
||||
hw->wakeup.cntl1.sleep_reject_ena = reject;
|
||||
hw->wakeup.cntl1.slp_reject_en = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_disable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->wakeup.cntl1.slp_reject_en = 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_wakeup_enable(pmu_dev_t *hw, uint32_t wakeup)
|
||||
{
|
||||
hw->wakeup.cntl2 = wakeup;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_protect_mode(pmu_dev_t *hw, int mode)
|
||||
{
|
||||
hw->wakeup.cntl3.sleep_prt_sel = mode;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
||||
{
|
||||
hw->wakeup.cntl3.hp_min_slp_val = slow_clk_cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_cause(pmu_dev_t *hw)
|
||||
{
|
||||
hw->wakeup.cntl4.slp_reject_cause_clr = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_wakeup(pmu_dev_t *hw)
|
||||
{
|
||||
return (hw->hp_ext.int_raw.wakeup == 1);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_reject(pmu_dev_t *hw)
|
||||
{
|
||||
return (hw->hp_ext.int_raw.reject == 1);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_clear_wakeup_intr_status(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_ext.int_clr.wakeup = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw)
|
||||
{
|
||||
hw->hp_ext.int_clr.reject = 1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->wakeup.status0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_reject_cause(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->wakeup.status1;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
||||
{
|
||||
hw->wakeup.cntl3.lp_min_slp_val = slow_clk_cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_modify_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->hp_ext.clk_cntl.modify_icg_cntl_wait = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_modify_icg_cntl_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->hp_ext.clk_cntl.modify_icg_cntl_wait;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_switch_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->hp_ext.clk_cntl.switch_icg_cntl_wait = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_switch_icg_cntl_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->hp_ext.clk_cntl.switch_icg_cntl_wait;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.wait_timer0.powerdown_timer = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_down_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.wait_timer0.powerdown_timer;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.wait_timer1.powerdown_timer = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_down_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.wait_timer1.powerdown_timer;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
||||
{
|
||||
hw->wakeup.cntl5.lp_ana_wait_target = slow_clk_cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->wakeup.cntl5.lp_ana_wait_target;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_set_modem_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->wakeup.cntl5.modem_wait_target = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_get_modem_wait_target_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->wakeup.cntl5.modem_wait_target;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.clk_wait.wait_xtal_stable = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_get_xtal_stable_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.clk_wait.wait_xtal_stable;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_set_pll_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.clk_wait.wait_pll_stable = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_get_pll_stable_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.clk_wait.wait_pll_stable;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.wait_timer1.wait_timer = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.wait_timer1.wait_timer;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.wait_timer1.powerup_timer = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_up_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.wait_timer1.powerup_timer;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->wakeup.cntl7.ana_wait_target = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_analog_wait_target_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->wakeup.cntl7.ana_wait_target;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.wait_timer0.wait_timer = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.wait_timer0.wait_timer;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle)
|
||||
{
|
||||
hw->power.wait_timer0.powerup_timer = cycle;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t *hw)
|
||||
{
|
||||
return hw->power.wait_timer0.powerup_timer;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/lp_aon_reg.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
|
||||
{
|
||||
// TODO: IDF-5645
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void)
|
||||
{
|
||||
// TODO: IDF-5645
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_status(void)
|
||||
{
|
||||
// TODO: IDF-5645
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr)
|
||||
{
|
||||
// TODO: IDF-5718 has removed the retention feature
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention_clock(void)
|
||||
{
|
||||
// TODO: IDF-5718 has removed the retention feature
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(void)
|
||||
{
|
||||
// TODO: IDF-5718 has removed the retention feature
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void)
|
||||
{
|
||||
// TODO: IDF-5718 has removed the retention feature
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void)
|
||||
{
|
||||
REG_SET_BIT(LP_AON_SYS_CFG_REG, LP_AON_HPSYS_SW_RESET);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no)
|
||||
{
|
||||
REG_SET_BIT(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void)
|
||||
{
|
||||
// TODO: IDF-6064
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void)
|
||||
{
|
||||
// TODO: IDF-6064
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us)
|
||||
{
|
||||
// TODO: IDF-6064
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void)
|
||||
{
|
||||
// TODO: IDF-6064
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -247,7 +247,7 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num)
|
||||
*/
|
||||
static inline void rtcio_ll_deep_sleep_hold_en_all(void)
|
||||
{
|
||||
PMU.imm_pad_hold_all.tie_high_lp_pad_hold_all = 1;
|
||||
PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -255,7 +255,7 @@ static inline void rtcio_ll_deep_sleep_hold_en_all(void)
|
||||
*/
|
||||
static inline void rtcio_ll_deep_sleep_hold_dis_all(void)
|
||||
{
|
||||
PMU.imm_pad_hold_all.tie_low_lp_pad_hold_all = 1;
|
||||
PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -76,7 +76,7 @@ typedef enum {
|
||||
UART_INTR_RS485_FRM_ERR = (0x1 << 16),
|
||||
UART_INTR_RS485_CLASH = (0x1 << 17),
|
||||
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
|
||||
// UART_INTR_WAKEUP = (0x1 << 19), // TODO: Test UART wakeup while supporting sleep
|
||||
UART_INTR_WAKEUP = (0x1 << 19),
|
||||
} uart_intr_t;
|
||||
|
||||
/**
|
||||
|
46
components/hal/esp32c6/lp_timer_hal.c
Normal file
46
components/hal/esp32c6/lp_timer_hal.c
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc.h"
|
||||
#include "hal/lp_timer_ll.h"
|
||||
|
||||
static DRAM_ATTR struct {
|
||||
lp_timer_dev_t *dev;
|
||||
} lp_timer_context = { .dev = &LP_TIMER };
|
||||
|
||||
void IRAM_ATTR lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value)
|
||||
{
|
||||
lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev);
|
||||
lp_timer_ll_set_alarm_target(lp_timer_context.dev, timer_id, value);
|
||||
lp_timer_ll_set_target_enable(lp_timer_context.dev, timer_id, true);
|
||||
}
|
||||
|
||||
uint64_t IRAM_ATTR lp_timer_hal_get_cycle_count(uint8_t timer_id)
|
||||
{
|
||||
lp_timer_ll_counter_snapshot(lp_timer_context.dev);
|
||||
uint32_t lo = lp_timer_ll_get_counter_value_low(lp_timer_context.dev, timer_id);
|
||||
uint32_t hi = lp_timer_ll_get_counter_value_high(lp_timer_context.dev, timer_id);
|
||||
lp_timer_counter_value_t result = {
|
||||
.lo = lo,
|
||||
.hi = hi
|
||||
};
|
||||
return result.val;
|
||||
}
|
||||
|
||||
void IRAM_ATTR lp_timer_hal_clear_alarm_intr_status(void)
|
||||
{
|
||||
lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev);
|
||||
}
|
||||
|
||||
void IRAM_ATTR lp_timer_hal_clear_overflow_intr_status(void)
|
||||
{
|
||||
lp_timer_ll_clear_overflow_intr_status(lp_timer_context.dev);
|
||||
}
|
70
components/hal/esp32c6/pmu_hal.c
Normal file
70
components/hal/esp32c6/pmu_hal.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The HAL layer for PMU (ESP32-C6 specific part)
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "esp_attr.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
#include "hal/pmu_types.h"
|
||||
|
||||
void IRAM_ATTR pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle)
|
||||
{
|
||||
pmu_ll_hp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle);
|
||||
pmu_ll_hp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle);
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal)
|
||||
{
|
||||
uint32_t power_supply_wait_cycle = pmu_ll_hp_get_digital_power_supply_wait_cycle(hal->dev);
|
||||
uint32_t power_up_wait_cycle = pmu_ll_hp_get_digital_power_up_wait_cycle(hal->dev);
|
||||
return power_supply_wait_cycle + power_up_wait_cycle;
|
||||
}
|
||||
|
||||
void IRAM_ATTR pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle)
|
||||
{
|
||||
pmu_ll_lp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle);
|
||||
pmu_ll_lp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle);
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal)
|
||||
{
|
||||
uint32_t power_supply_wait_cycle = pmu_ll_lp_get_digital_power_supply_wait_cycle(hal->dev);
|
||||
uint32_t power_up_wait_cycle = pmu_ll_lp_get_digital_power_up_wait_cycle(hal->dev);
|
||||
return power_supply_wait_cycle + power_up_wait_cycle;
|
||||
}
|
||||
|
||||
void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal)
|
||||
{
|
||||
pmu_ll_hp_set_active_to_sleep_backup_enable(hal->dev);
|
||||
pmu_ll_hp_set_sleep_to_active_backup_enable(hal->dev);
|
||||
}
|
||||
|
||||
void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal)
|
||||
{
|
||||
pmu_ll_hp_set_sleep_to_active_backup_disable(hal->dev);
|
||||
pmu_ll_hp_set_active_to_sleep_backup_disable(hal->dev);
|
||||
}
|
||||
|
||||
void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal)
|
||||
{
|
||||
pmu_ll_hp_set_sleep_to_modem_backup_enable(hal->dev);
|
||||
}
|
||||
|
||||
void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal)
|
||||
{
|
||||
pmu_ll_hp_set_sleep_to_modem_backup_disable(hal->dev);
|
||||
}
|
||||
|
||||
void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal)
|
||||
{
|
||||
pmu_ll_hp_set_modem_to_active_backup_enable(hal->dev);
|
||||
}
|
||||
|
||||
void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal)
|
||||
{
|
||||
pmu_ll_hp_set_modem_to_active_backup_disable(hal->dev);
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The HAL layer for RTC CNTL (common part)
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/lldesc.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/rtc_hal.h"
|
||||
#include "hal/assert.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */
|
||||
|
||||
typedef struct rtc_cntl_link_buf_conf {
|
||||
uint32_t cfg[4]; /* 4 word for dma link buffer configuration */
|
||||
} rtc_cntl_link_buf_conf_t;
|
||||
|
||||
void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next)
|
||||
{
|
||||
HAL_ASSERT(elem != NULL);
|
||||
HAL_ASSERT(buff != NULL);
|
||||
HAL_ASSERT(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN);
|
||||
|
||||
lldesc_t *plink = (lldesc_t *)elem;
|
||||
|
||||
plink->eof = next ? 0 : 1;
|
||||
plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||
plink->size = size >> 4; /* in unit of 16 bytes */
|
||||
plink->length = size >> 4;
|
||||
plink->buf = buff;
|
||||
plink->offset = 0;
|
||||
plink->sosf = 0;
|
||||
STAILQ_NEXT(plink, qe) = next;
|
||||
return (void *)plink;
|
||||
}
|
||||
|
||||
#if SOC_PM_SUPPORT_CPU_PD
|
||||
|
||||
void rtc_cntl_hal_enable_cpu_retention(void *addr)
|
||||
{
|
||||
// TODO: IDF-5718 has removed the retention feature
|
||||
}
|
||||
|
||||
void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr)
|
||||
{
|
||||
// TODO: IDF-5718 has removed the retention feature
|
||||
}
|
||||
|
||||
#endif // SOC_PM_SUPPORT_CPU_PD
|
32
components/hal/include/hal/lp_timer_types.h
Normal file
32
components/hal/include/hal/lp_timer_types.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
/**
|
||||
* @brief The structure of the counter value in lower power timer
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t lo: SOC_LP_TIMER_BIT_WIDTH_LO; /*!< Low part of counter value */
|
||||
uint32_t hi: SOC_LP_TIMER_BIT_WIDTH_HI; /*!< High part of counter value */
|
||||
uint32_t reserved: 16;
|
||||
};
|
||||
uint64_t val; /*!< counter value */
|
||||
};
|
||||
} lp_timer_counter_value_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
166
components/hal/include/hal/pmu_types.h
Normal file
166
components/hal/include/hal/pmu_types.h
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief PMU modes of HP system
|
||||
*/
|
||||
typedef enum {
|
||||
PMU_MODE_HP_ACTIVE = 0, /*!< PMU in HP_ACTIVE mode */
|
||||
PMU_MODE_HP_MODEM, /*!< PMU in HP_MODEM mode */
|
||||
PMU_MODE_HP_SLEEP, /*!< PMU in HP_SLEEP mode */
|
||||
PMU_MODE_HP_MAX,
|
||||
} pmu_hp_mode_t;
|
||||
|
||||
/**
|
||||
* @brief PMU modes of LP system
|
||||
*/
|
||||
typedef enum {
|
||||
PMU_MODE_LP_ACTIVE = 0, /*!< PMU in LP_ACTIVE mode */
|
||||
PMU_MODE_LP_SLEEP, /*!< PMU in LP_SLEEP mode */
|
||||
PMU_MODE_LP_MAX,
|
||||
} pmu_lp_mode_t;
|
||||
|
||||
typedef enum {
|
||||
PMU_HP_PD_TOP = 0, /* Power domain of digital top */
|
||||
PMU_HP_PD_AON, /* Power domain of always-on */
|
||||
PMU_HP_PD_CPU, /* Power domain of HP CPU */
|
||||
PMU_HP_PD_RESERVED, /* Reserved power domain*/
|
||||
PMU_HP_PD_WIFI, /* Power domain of WIFI */
|
||||
PMU_HP_PD_MAX
|
||||
} pmu_hp_power_domain_t;
|
||||
|
||||
|
||||
/* Software configuration instance type from pmu_struct.h */
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved0 : 21;
|
||||
uint32_t vdd_spi_pd_en: 1;
|
||||
uint32_t mem_dslp : 1;
|
||||
uint32_t mem_pd_en : 4;
|
||||
uint32_t wifi_pd_en : 1;
|
||||
uint32_t reserved1 : 1;
|
||||
uint32_t cpu_pd_en : 1;
|
||||
uint32_t aon_pd_en : 1;
|
||||
uint32_t top_pd_en : 1;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved2 : 26;
|
||||
uint32_t i2c_iso_en : 1;
|
||||
uint32_t i2c_retention: 1;
|
||||
uint32_t xpd_bb_i2c : 1;
|
||||
uint32_t xpd_bbpll_i2c: 1;
|
||||
uint32_t xpd_bbpll : 1;
|
||||
uint32_t reserved3 : 1;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved4 : 31;
|
||||
uint32_t xpd_xtal : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} pmu_hp_power_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved0 : 30;
|
||||
uint32_t mem_dslp : 1;
|
||||
uint32_t peri_pd_en: 1;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved1 : 28;
|
||||
uint32_t xpd_xtal32k: 1;
|
||||
uint32_t xpd_rc32k : 1;
|
||||
uint32_t xpd_fosc : 1;
|
||||
uint32_t pd_osc : 1;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved2 : 31;
|
||||
uint32_t xpd_xtal : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} pmu_lp_power_t;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
uint32_t reserved0 : 25;
|
||||
uint32_t xpd_bias : 1;
|
||||
uint32_t dbg_atten : 4;
|
||||
uint32_t pd_cur : 1;
|
||||
uint32_t bias_sleep: 1;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved1 : 16;
|
||||
uint32_t slp_mem_xpd : 1;
|
||||
uint32_t slp_logic_xpd : 1;
|
||||
uint32_t xpd : 1;
|
||||
uint32_t slp_mem_dbias : 4;
|
||||
uint32_t slp_logic_dbias: 4;
|
||||
uint32_t dbias : 5;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved2: 8;
|
||||
uint32_t drv_b : 24;
|
||||
};
|
||||
} pmu_hp_analog_t;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
uint32_t reserved0 : 25;
|
||||
uint32_t xpd_bias : 1;
|
||||
uint32_t dbg_atten : 4;
|
||||
uint32_t pd_cur : 1;
|
||||
uint32_t bias_sleep: 1;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved1: 21;
|
||||
uint32_t slp_xpd : 1;
|
||||
uint32_t xpd : 1;
|
||||
uint32_t slp_dbias: 4;
|
||||
uint32_t dbias : 5;
|
||||
};
|
||||
struct {
|
||||
uint32_t reserved2: 28;
|
||||
uint32_t drv_b : 4;
|
||||
};
|
||||
} pmu_lp_analog_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t modem_wakeup_wait_cycle;
|
||||
uint16_t analog_wait_target_cycle;
|
||||
uint16_t digital_power_down_wait_cycle;
|
||||
uint16_t digital_power_supply_wait_cycle;
|
||||
uint16_t digital_power_up_wait_cycle;
|
||||
uint16_t pll_stable_wait_cycle;
|
||||
uint8_t modify_icg_cntl_wait_cycle;
|
||||
uint8_t switch_icg_cntl_wait_cycle;
|
||||
uint8_t min_slp_slow_clk_cycle;
|
||||
} pmu_hp_param_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t digital_power_supply_wait_cycle;
|
||||
uint8_t min_slp_slow_clk_cycle;
|
||||
uint8_t analog_wait_target_cycle;
|
||||
uint8_t digital_power_down_wait_cycle;
|
||||
uint8_t digital_power_up_wait_cycle;
|
||||
} pmu_lp_param_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
uint16_t xtal_stable_wait_slow_clk_cycle;
|
||||
uint16_t xtal_stable_wait_cycle;
|
||||
};
|
||||
} pmu_hp_lp_param_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
153
components/riscv/include/riscv/rvsleep-frames.h
Normal file
153
components/riscv/include/riscv/rvsleep-frames.h
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __RVSLEEP_FRAMES_H__
|
||||
#define __RVSLEEP_FRAMES_H__
|
||||
|
||||
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
|
||||
#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
|
||||
|
||||
#ifdef STRUCT_BEGIN
|
||||
#undef STRUCT_BEGIN
|
||||
#undef STRUCT_FIELD
|
||||
#undef STRUCT_AFIELD
|
||||
#undef STRUCT_END
|
||||
#endif
|
||||
|
||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||
#ifdef __clang__
|
||||
#define STRUCT_BEGIN .set RV_STRUCT_OFFSET, 0
|
||||
#define STRUCT_FIELD(ctype,size,asname,name) .set asname, RV_STRUCT_OFFSET; .set RV_STRUCT_OFFSET, asname + size
|
||||
#define STRUCT_AFIELD(ctype,size,asname,name,n) .set asname, RV_STRUCT_OFFSET;\
|
||||
.set RV_STRUCT_OFFSET, asname + (size)*(n);
|
||||
#define STRUCT_END(sname) .set sname##Size, RV_STRUCT_OFFSET;
|
||||
#else // __clang__
|
||||
#define STRUCT_BEGIN .pushsection .text; .struct 0
|
||||
#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
|
||||
#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
|
||||
#define STRUCT_END(sname) sname##Size:; .popsection
|
||||
#endif // __clang__
|
||||
#else
|
||||
#define STRUCT_BEGIN typedef struct {
|
||||
#define STRUCT_FIELD(ctype,size,asname,name) ctype name;
|
||||
#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
|
||||
#define STRUCT_END(sname) } sname;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------------
|
||||
* RISC-V CORE CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP
|
||||
* -------------------------------------------------------------------------------
|
||||
*/
|
||||
STRUCT_BEGIN
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MEPC, mepc) /* Machine Exception Program Counter */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_RA, ra) /* Return address */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_SP, sp) /* Stack pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_GP, gp) /* Global pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TP, tp) /* Thread pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T0, t0) /* Temporary/alternate link register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T1, t1) /* t1-2: Temporaries */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T2, t2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S0, s0) /* Saved register/frame pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S1, s1) /* Saved register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A0, a0) /* a0-1: Function arguments/return address */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A1, a1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A2, a2) /* a2-7: Function arguments */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A3, a3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A4, a4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A5, a5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A6, a6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A7, a7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S2, s2) /* s2-11: Saved registers */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S3, s3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S4, s4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S5, s5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S6, s6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S7, s7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S8, s8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S9, s9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S10, s10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S11, s11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T3, t3) /* t3-6: Temporaries */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T4, t4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T5, t5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T6, t6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSTATUS, mstatus) /* Machine Status */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVEC, mtvec) /* Machine Trap-Vector Base Address */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MCAUSE, mcause) /* Machine Trap Cause */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVAL, mtval) /* Machine Trap Value */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIE, mie) /* Machine intr enable */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIP, mip) /* Machine intr pending */
|
||||
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMUFUNC, pmufunc) /* A field is used to identify whether it is going
|
||||
* to sleep or has just been awakened. We use the
|
||||
* lowest 2 bits as indication infomation, 3 means
|
||||
* being awakened, 1 means going to sleep */
|
||||
STRUCT_END(RvCoreCriticalSleepFrame)
|
||||
|
||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||
#define RV_SLEEP_CTX_SZ1 RvCoreCriticalSleepFrameSize
|
||||
#else
|
||||
#define RV_SLEEP_CTX_SZ1 sizeof(RvCoreCriticalSleepFrame)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sleep stack frame size, after align up to 16 bytes boundary
|
||||
*/
|
||||
#define RV_SLEEP_CTX_FRMSZ (ALIGNUP(0x10, RV_SLEEP_CTX_SZ1))
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------------
|
||||
* RISC-V CORE NON-CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP
|
||||
* -------------------------------------------------------------------------------
|
||||
*/
|
||||
STRUCT_BEGIN
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSCRATCH, mscratch)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIDELEG, mideleg)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MISA, misa)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TSELECT, tselect)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA1, tdata1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA2, tdata2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TCONTROL, tcontrol)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG0, pmpcfg0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG1, pmpcfg1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR0, pmpaddr0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR1, pmpaddr1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR2, pmpaddr2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR3, pmpaddr3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR4, pmpaddr4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR5, pmpaddr5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR6, pmpaddr6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR7, pmpaddr7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR8, pmpaddr8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR9, pmpaddr9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR10, pmpaddr10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR11, pmpaddr11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR12, pmpaddr12)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR13, pmpaddr13)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR14, pmpaddr14)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR15, pmpaddr15)
|
||||
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UTVEC, utvec)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_USTATUS, ustatus)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UEPC, uepc)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UCAUSE, ucause)
|
||||
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCER, mpcer)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCMR, mpcmr)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCCR, mpccr)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_CPU_TESTBUS_CTRL, cpu_testbus_ctrl)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCER, upcer)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCMR, upcmr)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCCR, upccr)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OEN, ugpio_oen)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_IN, ugpio_in)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OUT, ugpio_out)
|
||||
STRUCT_END(RvCoreNonCriticalSleepFrame)
|
||||
|
||||
#endif /* #ifndef __RVSLEEP_FRAMES_H__ */
|
@ -743,6 +743,14 @@ config SOC_PM_SUPPORT_RC_FAST_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_APLL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -373,6 +373,9 @@
|
||||
#define SOC_PM_SUPPORT_RTC_FAST_MEM_PD (1)
|
||||
#define SOC_PM_SUPPORT_RTC_SLOW_MEM_PD (1)
|
||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||
|
||||
#define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1)
|
||||
|
||||
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
||||
#define SOC_CLK_APLL_SUPPORTED (1)
|
||||
|
@ -607,6 +607,10 @@ config SOC_PM_SUPPORT_RC_FAST_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_RC_FAST_D256_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -722,37 +722,6 @@ typedef struct {
|
||||
*/
|
||||
void rtc_init(rtc_config_t cfg);
|
||||
|
||||
/**
|
||||
* Structure describing vddsdio configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins.
|
||||
uint32_t enable : 1; //!< Enable VDDSDIO regulator
|
||||
uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V
|
||||
uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
} rtc_vddsdio_config_t;
|
||||
|
||||
/**
|
||||
* Get current VDDSDIO configuration
|
||||
* If VDDSDIO configuration is overridden by RTC, get values from RTC
|
||||
* Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE
|
||||
* Otherwise, use default values and the level of MTDI bootstrapping pin.
|
||||
* @return currently used VDDSDIO configuration
|
||||
*/
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void);
|
||||
|
||||
/**
|
||||
* Set new VDDSDIO configuration using RTC registers.
|
||||
* If config.force == 1, this overrides configuration done using bootstrapping
|
||||
* pins and EFUSE.
|
||||
*
|
||||
* @param config new VDDSDIO configuration
|
||||
*/
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
|
||||
|
||||
// -------------------------- CLOCK TREE DEFS ALIAS ----------------------------
|
||||
// **WARNING**: The following are only for backwards compatibility.
|
||||
// Please use the declarations in soc/clk_tree_defs.h instead.
|
||||
|
@ -289,6 +289,7 @@
|
||||
#define SOC_PM_SUPPORT_WIFI_PD (0)
|
||||
#define SOC_PM_SUPPORT_BT_PD (0)
|
||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||
|
||||
/*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */
|
||||
#define SOC_CLK_RC_FAST_D256_SUPPORTED (1)
|
||||
|
@ -863,6 +863,14 @@ config SOC_PM_SUPPORT_RC_FAST_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_RC_FAST_D256_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -764,37 +764,6 @@ typedef struct {
|
||||
*/
|
||||
void rtc_init(rtc_config_t cfg);
|
||||
|
||||
/**
|
||||
* Structure describing vddsdio configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins.
|
||||
uint32_t enable : 1; //!< Enable VDDSDIO regulator
|
||||
uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V
|
||||
uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
} rtc_vddsdio_config_t;
|
||||
|
||||
/**
|
||||
* Get current VDDSDIO configuration
|
||||
* If VDDSDIO configuration is overridden by RTC, get values from RTC
|
||||
* Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE
|
||||
* Otherwise, use default values and the level of MTDI bootstrapping pin.
|
||||
* @return currently used VDDSDIO configuration
|
||||
*/
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void);
|
||||
|
||||
/**
|
||||
* Set new VDDSDIO configuration using RTC registers.
|
||||
* If config.force == 1, this overrides configuration done using bootstrapping
|
||||
* pins and EFUSE.
|
||||
*
|
||||
* @param config new VDDSDIO configuration
|
||||
*/
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
|
||||
|
||||
// -------------------------- CLOCK TREE DEFS ALIAS ----------------------------
|
||||
// **WARNING**: The following are only for backwards compatibility.
|
||||
// Please use the declarations in soc/clk_tree_defs.h instead.
|
||||
|
@ -383,6 +383,9 @@
|
||||
#define SOC_PM_SUPPORT_WIFI_PD (1)
|
||||
#define SOC_PM_SUPPORT_BT_PD (1)
|
||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||
|
||||
#define SOC_PM_CPU_RETENTION_BY_RTCCNTL (1)
|
||||
|
||||
/*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */
|
||||
#define SOC_CLK_RC_FAST_D256_SUPPORTED (1)
|
||||
|
@ -147,6 +147,14 @@ config SOC_APM_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PMU_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_TIMER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_XTAL_SUPPORT_40M
|
||||
bool
|
||||
default y
|
||||
@ -659,14 +667,6 @@ config SOC_MCPWM_CLK_SUPPORT_XTAL
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH
|
||||
int
|
||||
default 128
|
||||
|
||||
config SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM
|
||||
int
|
||||
default 108
|
||||
|
||||
config SOC_RSA_MAX_BIT_LEN
|
||||
int
|
||||
default 3072
|
||||
@ -839,6 +839,14 @@ config SOC_SYSTIMER_SUPPORT_ETM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_TIMER_BIT_WIDTH_LO
|
||||
int
|
||||
default 32
|
||||
|
||||
config SOC_LP_TIMER_BIT_WIDTH_HI
|
||||
int
|
||||
default 16
|
||||
|
||||
config SOC_TIMER_GROUPS
|
||||
int
|
||||
default 2
|
||||
@ -963,6 +971,10 @@ config SOC_UART_SUPPORT_XTAL_CLK
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_UART_SUPPORT_WAKEUP_INT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
|
||||
bool
|
||||
default y
|
||||
@ -991,11 +1003,7 @@ config SOC_PM_SUPPORT_CPU_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_WIFI_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_BT_PD
|
||||
config SOC_PM_SUPPORT_MODEM_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
@ -1011,10 +1019,18 @@ config SOC_PM_SUPPORT_RC_FAST_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_CPU_RETENTION_BY_SW
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
|
||||
bool
|
||||
default y
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -10,346 +10,99 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Group: configure_register */
|
||||
/** Type of tar0_low register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_tar_low0 : R/W; bitpos: [31:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_tar_low0:32;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_tar0_low_reg_t;
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t target_lo: 32;
|
||||
};
|
||||
uint32_t val;
|
||||
} lo;
|
||||
union {
|
||||
struct {
|
||||
uint32_t target_hi: 16;
|
||||
uint32_t reserved0: 15;
|
||||
uint32_t enable : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} hi;
|
||||
} lp_timer_target_reg_t;
|
||||
|
||||
/** Type of tar0_high register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_tar_high0 : R/W; bitpos: [15:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_tar_high0:16;
|
||||
uint32_t reserved_16:15;
|
||||
/** main_timer_tar_en0 : WT; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_tar_en0:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_tar0_high_reg_t;
|
||||
|
||||
/** Type of tar1_low register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_tar_low1 : R/W; bitpos: [31:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_tar_low1:32;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_tar1_low_reg_t;
|
||||
|
||||
/** Type of tar1_high register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_tar_high1 : R/W; bitpos: [15:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_tar_high1:16;
|
||||
uint32_t reserved_16:15;
|
||||
/** main_timer_tar_en1 : WT; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_tar_en1:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_tar1_high_reg_t;
|
||||
|
||||
/** Type of update register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:28;
|
||||
/** main_timer_update : WT; bitpos: [28]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_update:1;
|
||||
/** main_timer_xtal_off : R/W; bitpos: [29]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_xtal_off:1;
|
||||
/** main_timer_sys_stall : R/W; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_sys_stall:1;
|
||||
/** main_timer_sys_rst : R/W; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_sys_rst:1;
|
||||
uint32_t reserved0: 28;
|
||||
uint32_t update : 1;
|
||||
uint32_t xtal_off : 1;
|
||||
uint32_t sys_stall: 1;
|
||||
uint32_t sys_rst : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_update_reg_t;
|
||||
|
||||
/** Type of main_buf0_low register
|
||||
* need_des
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
uint32_t counter_lo: 32;
|
||||
};
|
||||
uint32_t val;
|
||||
} lo;
|
||||
union {
|
||||
struct {
|
||||
uint32_t counter_hi: 16;
|
||||
uint32_t reserved0 : 16;
|
||||
};
|
||||
uint32_t val;
|
||||
} hi;
|
||||
} lp_timer_counter_reg_t;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_buf0_low : RO; bitpos: [31:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_buf0_low:32;
|
||||
uint32_t reserved0: 31;
|
||||
uint32_t trigger : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_main_buf0_low_reg_t;
|
||||
} lp_timer_overflow_reg_t;
|
||||
|
||||
/** Type of main_buf0_high register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_buf0_high : RO; bitpos: [15:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_buf0_high:16;
|
||||
uint32_t reserved_16:16;
|
||||
uint32_t reserved0: 30;
|
||||
uint32_t overflow : 1;
|
||||
uint32_t alarm : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_main_buf0_high_reg_t;
|
||||
} lp_timer_intr_reg_t;
|
||||
|
||||
/** Type of main_buf1_low register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_buf1_low : RO; bitpos: [31:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_buf1_low:32;
|
||||
uint32_t reserved0: 30;
|
||||
uint32_t overflow : 1;
|
||||
uint32_t alarm : 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_main_buf1_low_reg_t;
|
||||
} lp_timer_lp_intr_reg_t;
|
||||
|
||||
/** Type of main_buf1_high register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** main_timer_buf1_high : RO; bitpos: [15:0]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_buf1_high:16;
|
||||
uint32_t reserved_16:16;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_main_buf1_high_reg_t;
|
||||
typedef volatile struct lp_timer_dev_t{
|
||||
lp_timer_target_reg_t target[2];
|
||||
lp_timer_update_reg_t update;
|
||||
lp_timer_counter_reg_t counter[2];
|
||||
lp_timer_overflow_reg_t overflow;
|
||||
lp_timer_intr_reg_t int_raw;
|
||||
lp_timer_intr_reg_t int_st;
|
||||
lp_timer_intr_reg_t int_en;
|
||||
lp_timer_intr_reg_t int_clr;
|
||||
lp_timer_lp_intr_reg_t lp_int_raw;
|
||||
lp_timer_lp_intr_reg_t lp_int_st;
|
||||
lp_timer_lp_intr_reg_t lp_int_en;
|
||||
lp_timer_lp_intr_reg_t lp_int_clr;
|
||||
|
||||
/** Type of main_overflow register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:31;
|
||||
/** main_timer_alarm_load : WT; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_alarm_load:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_main_overflow_reg_t;
|
||||
uint32_t reserved[237];
|
||||
|
||||
/** Type of int_raw register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** overflow_raw : R/WTC/SS; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t overflow_raw:1;
|
||||
/** soc_wakeup_int_raw : R/WTC/SS; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t soc_wakeup_int_raw:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_int_raw_reg_t;
|
||||
|
||||
/** Type of int_st register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** overflow_st : RO; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t overflow_st:1;
|
||||
/** soc_wakeup_int_st : RO; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t soc_wakeup_int_st:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_int_st_reg_t;
|
||||
|
||||
/** Type of int_ena register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** overflow_ena : R/W; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t overflow_ena:1;
|
||||
/** soc_wakeup_int_ena : R/W; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t soc_wakeup_int_ena:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_int_ena_reg_t;
|
||||
|
||||
/** Type of int_clr register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** overflow_clr : WT; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t overflow_clr:1;
|
||||
/** soc_wakeup_int_clr : WT; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t soc_wakeup_int_clr:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_int_clr_reg_t;
|
||||
|
||||
/** Type of lp_int_raw register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** main_timer_overflow_lp_int_raw : R/WTC/SS; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_overflow_lp_int_raw:1;
|
||||
/** main_timer_lp_int_raw : R/WTC/SS; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_lp_int_raw:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_lp_int_raw_reg_t;
|
||||
|
||||
/** Type of lp_int_st register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** main_timer_overflow_lp_int_st : RO; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_overflow_lp_int_st:1;
|
||||
/** main_timer_lp_int_st : RO; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_lp_int_st:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_lp_int_st_reg_t;
|
||||
|
||||
/** Type of lp_int_ena register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** main_timer_overflow_lp_int_ena : R/W; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_overflow_lp_int_ena:1;
|
||||
/** main_timer_lp_int_ena : R/W; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_lp_int_ena:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_lp_int_ena_reg_t;
|
||||
|
||||
/** Type of lp_int_clr register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t reserved_0:30;
|
||||
/** main_timer_overflow_lp_int_clr : WT; bitpos: [30]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_overflow_lp_int_clr:1;
|
||||
/** main_timer_lp_int_clr : WT; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t main_timer_lp_int_clr:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_lp_int_clr_reg_t;
|
||||
|
||||
/** Type of date register
|
||||
* need_des
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
/** date : R/W; bitpos: [30:0]; default: 34672976;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t date:31;
|
||||
/** clk_en : R/W; bitpos: [31]; default: 0;
|
||||
* need_des
|
||||
*/
|
||||
uint32_t clk_en:1;
|
||||
};
|
||||
uint32_t val;
|
||||
} lp_timer_date_reg_t;
|
||||
|
||||
|
||||
typedef struct lp_timer_dev_t {
|
||||
volatile lp_timer_tar0_low_reg_t tar0_low;
|
||||
volatile lp_timer_tar0_high_reg_t tar0_high;
|
||||
volatile lp_timer_tar1_low_reg_t tar1_low;
|
||||
volatile lp_timer_tar1_high_reg_t tar1_high;
|
||||
volatile lp_timer_update_reg_t update;
|
||||
volatile lp_timer_main_buf0_low_reg_t main_buf0_low;
|
||||
volatile lp_timer_main_buf0_high_reg_t main_buf0_high;
|
||||
volatile lp_timer_main_buf1_low_reg_t main_buf1_low;
|
||||
volatile lp_timer_main_buf1_high_reg_t main_buf1_high;
|
||||
volatile lp_timer_main_overflow_reg_t main_overflow;
|
||||
volatile lp_timer_int_raw_reg_t int_raw;
|
||||
volatile lp_timer_int_st_reg_t int_st;
|
||||
volatile lp_timer_int_ena_reg_t int_ena;
|
||||
volatile lp_timer_int_clr_reg_t int_clr;
|
||||
volatile lp_timer_lp_int_raw_reg_t lp_int_raw;
|
||||
volatile lp_timer_lp_int_st_reg_t lp_int_st;
|
||||
volatile lp_timer_lp_int_ena_reg_t lp_int_ena;
|
||||
volatile lp_timer_lp_int_clr_reg_t lp_int_clr;
|
||||
uint32_t reserved_048[237];
|
||||
volatile lp_timer_date_reg_t date;
|
||||
union {
|
||||
struct {
|
||||
uint32_t date : 31;
|
||||
uint32_t clk_en: 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} date;
|
||||
} lp_timer_dev_t;
|
||||
|
||||
extern lp_timer_dev_t LP_TIMER;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,7 @@ extern "C" {
|
||||
|
||||
/**
|
||||
* @file rtc.h
|
||||
* @brief Low-level RTC power, clock, and sleep functions.
|
||||
* @brief Low-level RTC power, clock functions.
|
||||
*
|
||||
* Functions in this file facilitate configuration of ESP32's RTC_CNTL peripheral.
|
||||
* RTC_CNTL peripheral handles many functions:
|
||||
@ -514,204 +514,8 @@ bool rtc_dig_8m_enabled(void);
|
||||
*/
|
||||
uint32_t rtc_clk_freq_cal(uint32_t cal_val);
|
||||
|
||||
/**
|
||||
* @brief Power down flags for rtc_sleep_pd function
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t dig_fpu : 1; //!< Set to 1 to power UP digital part in sleep
|
||||
uint32_t rtc_fpu : 1; //!< Set to 1 to power UP RTC memories in sleep
|
||||
uint32_t cpu_fpu : 1; //!< Set to 1 to power UP digital memories and CPU in sleep
|
||||
uint32_t i2s_fpu : 1; //!< Set to 1 to power UP I2S in sleep
|
||||
uint32_t bb_fpu : 1; //!< Set to 1 to power UP WiFi in sleep
|
||||
uint32_t nrx_fpu : 1; //!< Set to 1 to power UP WiFi in sleep
|
||||
uint32_t fe_fpu : 1; //!< Set to 1 to power UP WiFi in sleep
|
||||
uint32_t sram_fpu : 1; //!< Set to 1 to power UP SRAM in sleep
|
||||
uint32_t rom_ram_fpu : 1; //!< Set to 1 to power UP ROM/IRAM0_DRAM0 in sleep
|
||||
} rtc_sleep_pu_config_t;
|
||||
|
||||
/**
|
||||
* Initializer for rtc_sleep_pu_config_t which sets all flags to the same value
|
||||
*/
|
||||
#define RTC_SLEEP_PU_CONFIG_ALL(val) {\
|
||||
.dig_fpu = (val), \
|
||||
.rtc_fpu = (val), \
|
||||
.cpu_fpu = (val), \
|
||||
.i2s_fpu = (val), \
|
||||
.bb_fpu = (val), \
|
||||
.nrx_fpu = (val), \
|
||||
.fe_fpu = (val), \
|
||||
.sram_fpu = (val), \
|
||||
.rom_ram_fpu = (val), \
|
||||
}
|
||||
|
||||
void rtc_sleep_pu(rtc_sleep_pu_config_t cfg);
|
||||
|
||||
/**
|
||||
* @brief sleep configuration for rtc_sleep_init function
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t lslp_mem_inf_fpu : 1; //!< force normal voltage in sleep mode (digital domain memory)
|
||||
uint32_t rtc_mem_inf_follow_cpu : 1;//!< keep low voltage in sleep mode (even if ULP/touch is used)
|
||||
uint32_t rtc_fastmem_pd_en : 1; //!< power down RTC fast memory
|
||||
uint32_t rtc_slowmem_pd_en : 1; //!< power down RTC slow memory
|
||||
uint32_t rtc_peri_pd_en : 1; //!< power down RTC peripherals
|
||||
uint32_t wifi_pd_en : 1; //!< power down WiFi
|
||||
uint32_t bt_pd_en : 1; //!< power down BT
|
||||
uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep.
|
||||
uint32_t int_8m_pd_en : 1; //!< Power down Internal 8M oscillator
|
||||
uint32_t dig_peri_pd_en : 1; //!< power down digital peripherals
|
||||
uint32_t deep_slp : 1; //!< power down digital domain
|
||||
uint32_t wdt_flashboot_mod_en : 1; //!< enable WDT flashboot mode
|
||||
uint32_t dig_dbias_wak : 5; //!< set bias for digital domain, in active mode
|
||||
uint32_t dig_dbias_slp : 5; //!< set bias for digital domain, in sleep mode
|
||||
uint32_t rtc_dbias_wak : 5; //!< set bias for RTC domain, in active mode
|
||||
uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode
|
||||
uint32_t dbg_atten_monitor : 4; //!< voltage parameter, in monitor mode
|
||||
uint32_t bias_sleep_monitor : 1; //!< circuit control parameter, in monitor mode
|
||||
uint32_t dbg_atten_slp : 4; //!< voltage parameter, in sleep mode
|
||||
uint32_t bias_sleep_slp : 1; //!< circuit control parameter, in sleep mode
|
||||
uint32_t pd_cur_monitor : 1; //!< circuit control parameter, in monitor mode
|
||||
uint32_t pd_cur_slp : 1; //!< circuit control parameter, in sleep mode
|
||||
uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator
|
||||
uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep
|
||||
uint32_t deep_slp_reject : 1; //!< enable deep sleep reject
|
||||
uint32_t light_slp_reject : 1; //!< enable light sleep reject
|
||||
} rtc_sleep_config_t;
|
||||
|
||||
#define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain)
|
||||
#define RTC_SLEEP_PD_RTC_PERIPH BIT(1) //!< Power down RTC peripherals
|
||||
#define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) //!< Power down RTC SLOW memory
|
||||
#define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory
|
||||
#define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU
|
||||
#define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator
|
||||
#define RTC_SLEEP_PD_WIFI BIT(6) //!< Power down WIFI
|
||||
#define RTC_SLEEP_PD_BT BIT(7) //!< Power down BT
|
||||
#define RTC_SLEEP_PD_CPU BIT(8) //!< Power down CPU when in lightsleep, but not restart
|
||||
#define RTC_SLEEP_PD_DIG_PERIPH BIT(9) //!< Power down DIG peripherals
|
||||
#define RTC_SLEEP_PD_INT_8M BIT(10) //!< Power down Internal 8M oscillator
|
||||
#define RTC_SLEEP_PD_XTAL BIT(11) //!< Power down main XTAL
|
||||
|
||||
//These flags are not power domains, but will affect some sleep parameters
|
||||
#define RTC_SLEEP_DIG_USE_8M BIT(16)
|
||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature
|
||||
|
||||
/**
|
||||
* Default initializer for rtc_sleep_config_t
|
||||
*
|
||||
* This initializer sets all fields to "reasonable" values (e.g. suggested for
|
||||
* production use) based on a combination of RTC_SLEEP_PD_x flags.
|
||||
*
|
||||
* @param RTC_SLEEP_PD_x flags combined using bitwise OR
|
||||
*/
|
||||
void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_config);
|
||||
|
||||
/**
|
||||
* @brief Prepare the chip to enter sleep mode
|
||||
*
|
||||
* This function configures various power control state machines to handle
|
||||
* entry into light sleep or deep sleep mode, switches APB and CPU clock source
|
||||
* (usually to XTAL), and sets bias voltages for digital and RTC power domains.
|
||||
*
|
||||
* This function does not actually enter sleep mode; this is done using
|
||||
* rtc_sleep_start function. Software may do some other actions between
|
||||
* rtc_sleep_init and rtc_sleep_start, such as set wakeup timer and configure
|
||||
* wakeup sources.
|
||||
* @param cfg sleep mode configuration
|
||||
*/
|
||||
void rtc_sleep_init(rtc_sleep_config_t cfg);
|
||||
|
||||
/**
|
||||
* @brief Low level initialize for rtc state machine waiting cycles after waking up
|
||||
*
|
||||
* This function configures the cycles chip need to wait for internal 8MHz
|
||||
* oscillator and external 40MHz crystal. As we configure fixed time for waiting
|
||||
* crystal, we need to pass period to calculate cycles. Now this function only
|
||||
* used in lightsleep mode.
|
||||
*
|
||||
* @param slowclk_period re-calibrated slow clock period
|
||||
*/
|
||||
void rtc_sleep_low_init(uint32_t slowclk_period);
|
||||
|
||||
/**
|
||||
* @brief Set target value of RTC counter for RTC_TIMER_TRIG_EN wakeup source
|
||||
* @param t value of RTC counter at which wakeup from sleep will happen;
|
||||
* only the lower 48 bits are used
|
||||
*/
|
||||
void rtc_sleep_set_wakeup_time(uint64_t t);
|
||||
|
||||
#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup
|
||||
#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup
|
||||
#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only)
|
||||
#define RTC_UART0_TRIG_EN BIT(6) //!< UART0 wakeup (light sleep only)
|
||||
#define RTC_UART1_TRIG_EN BIT(7) //!< UART1 wakeup (light sleep only)
|
||||
#define RTC_BT_TRIG_EN BIT(10) //!< BT wakeup (light sleep only)
|
||||
#define RTC_XTAL32K_DEAD_TRIG_EN BIT(12)
|
||||
#define RTC_USB_TRIG_EN BIT(14)
|
||||
#define RTC_BROWNOUT_DET_TRIG_EN BIT(16)
|
||||
|
||||
/**
|
||||
* RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip
|
||||
*/
|
||||
#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | \
|
||||
RTC_TIMER_TRIG_EN | \
|
||||
RTC_WIFI_TRIG_EN | \
|
||||
RTC_UART0_TRIG_EN | \
|
||||
RTC_UART1_TRIG_EN | \
|
||||
RTC_BT_TRIG_EN | \
|
||||
RTC_XTAL32K_DEAD_TRIG_EN | \
|
||||
RTC_USB_TRIG_EN | \
|
||||
RTC_BROWNOUT_DET_TRIG_EN)
|
||||
|
||||
/**
|
||||
* @brief Enter deep or light sleep mode
|
||||
*
|
||||
* This function enters the sleep mode previously configured using rtc_sleep_init
|
||||
* function. Before entering sleep, software should configure wake up sources
|
||||
* appropriately (set up GPIO wakeup registers, timer wakeup registers,
|
||||
* and so on).
|
||||
*
|
||||
* If deep sleep mode was configured using rtc_sleep_init, and sleep is not
|
||||
* rejected by hardware (based on reject_opt flags), this function never returns.
|
||||
* When the chip wakes up from deep sleep, CPU is reset and execution starts
|
||||
* from ROM bootloader.
|
||||
*
|
||||
* If light sleep mode was configured using rtc_sleep_init, this function
|
||||
* returns on wakeup, or if sleep is rejected by hardware.
|
||||
*
|
||||
* @param wakeup_opt bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags
|
||||
* combined with OR)
|
||||
* @param reject_opt bit mask of sleep reject reasons:
|
||||
* - RTC_CNTL_GPIO_REJECT_EN
|
||||
* - RTC_CNTL_SDIO_REJECT_EN
|
||||
* These flags are used to prevent entering sleep when e.g.
|
||||
* an external host is communicating via SDIO slave
|
||||
* @return non-zero if sleep was rejected by hardware
|
||||
*/
|
||||
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu);
|
||||
|
||||
/**
|
||||
* @brief Enter deep sleep mode
|
||||
*
|
||||
* Similar to rtc_sleep_start(), but additionally uses hardware to calculate the CRC value
|
||||
* of RTC FAST memory. On wake, this CRC is used to determine if a deep sleep wake
|
||||
* stub is valid to execute (if a wake address is set).
|
||||
*
|
||||
* No RAM is accessed while calculating the CRC and going into deep sleep, which makes
|
||||
* this function safe to use even if the caller's stack is in RTC FAST memory.
|
||||
*
|
||||
* @note If no deep sleep wake stub address is set then calling rtc_sleep_start() will
|
||||
* have the same effect and takes less time as CRC calculation is skipped.
|
||||
*
|
||||
* @note This function should only be called after rtc_sleep_init() has been called to
|
||||
* configure the system for deep sleep.
|
||||
*
|
||||
* @param wakeup_opt - same as for rtc_sleep_start
|
||||
* @param reject_opt - same as for rtc_sleep_start
|
||||
*
|
||||
* @return non-zero if sleep was rejected by hardware
|
||||
*/
|
||||
uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt);
|
||||
|
||||
/**
|
||||
* RTC power and clock control initialization settings
|
||||
@ -754,37 +558,6 @@ typedef struct {
|
||||
*/
|
||||
void rtc_init(rtc_config_t cfg);
|
||||
|
||||
/**
|
||||
* Structure describing vddsdio configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins.
|
||||
uint32_t enable : 1; //!< Enable VDDSDIO regulator
|
||||
uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V
|
||||
uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
} rtc_vddsdio_config_t;
|
||||
|
||||
/**
|
||||
* Get current VDDSDIO configuration
|
||||
* If VDDSDIO configuration is overridden by RTC, get values from RTC
|
||||
* Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE
|
||||
* Otherwise, use default values and the level of MTDI bootstrapping pin.
|
||||
* @return currently used VDDSDIO configuration
|
||||
*/
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void);
|
||||
|
||||
/**
|
||||
* Set new VDDSDIO configuration using RTC registers.
|
||||
* If config.force == 1, this overrides configuration done using bootstrapping
|
||||
* pins and EFUSE.
|
||||
*
|
||||
* @param config new VDDSDIO configuration
|
||||
*/
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
|
||||
|
||||
// -------------------------- CLOCK TREE DEFS ALIAS ----------------------------
|
||||
// **WARNING**: The following are only for backwards compatibility.
|
||||
// Please use the declarations in soc/clk_tree_defs.h instead.
|
||||
|
@ -141,6 +141,7 @@
|
||||
#define EFUSE_CLK_FREQ_ROM ( 20*1000000)
|
||||
#define CPU_CLK_FREQ APB_CLK_FREQ
|
||||
#define APB_CLK_FREQ ( 40*1000000 )
|
||||
#define MODEM_APB_CLK_FREQ ( 80*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
#define RTC_CLK_FREQ (20*1000000)
|
||||
#define XTAL_CLK_FREQ (40*1000000)
|
||||
|
@ -63,6 +63,8 @@
|
||||
#define SOC_SDIO_SLAVE_SUPPORTED 1
|
||||
#define SOC_BOD_SUPPORTED 1
|
||||
#define SOC_APM_SUPPORTED 1
|
||||
#define SOC_PMU_SUPPORTED 1
|
||||
#define SOC_LP_TIMER_SUPPORTED 1
|
||||
|
||||
/*-------------------------- XTAL CAPS ---------------------------------------*/
|
||||
#define SOC_XTAL_SUPPORT_40M 1
|
||||
@ -281,15 +283,6 @@
|
||||
#define SOC_MCPWM_CLK_SUPPORT_PLL160M (1) ///< Support PLL160M as clock source
|
||||
#define SOC_MCPWM_CLK_SUPPORT_XTAL (1) ///< Support XTAL as clock source
|
||||
|
||||
// TODO: IDF-5348 (Copy from esp32c3, need check)
|
||||
/*-------------------------- RTC CAPS --------------------------------------*/
|
||||
#define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128)
|
||||
#define SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM (108)
|
||||
#define SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)
|
||||
#define SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)
|
||||
|
||||
#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3))
|
||||
|
||||
// TODO: IDF-5359 (Copy from esp32c3, need check)
|
||||
/*--------------------------- RSA CAPS ---------------------------------------*/
|
||||
#define SOC_RSA_MAX_BIT_LEN (3072)
|
||||
@ -368,6 +361,10 @@
|
||||
#define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current)
|
||||
#define SOC_SYSTIMER_SUPPORT_ETM 1 // Systimer comparator can generate ETM event
|
||||
|
||||
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
|
||||
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part
|
||||
#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part
|
||||
|
||||
/*--------------------------- TIMER GROUP CAPS ---------------------------------------*/
|
||||
#define SOC_TIMER_GROUPS (2)
|
||||
#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (1U)
|
||||
@ -410,14 +407,13 @@
|
||||
// TODO: IDF-5338 (Copy from esp32c3, need check)
|
||||
/*-------------------------- UART CAPS ---------------------------------------*/
|
||||
// ESP32-C6 has 2 UARTs
|
||||
#define SOC_UART_NUM (2)
|
||||
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
|
||||
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
|
||||
|
||||
#define SOC_UART_SUPPORT_PLL_F80M_CLK (1) /*!< Support PLL_DIV as the clock source */
|
||||
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
|
||||
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
|
||||
// #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ // TODO: Test UART wakeup while supporting sleep
|
||||
#define SOC_UART_NUM (2)
|
||||
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
|
||||
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */
|
||||
#define SOC_UART_SUPPORT_PLL_F80M_CLK (1) /*!< Support PLL_DIV as the clock source */
|
||||
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
|
||||
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
|
||||
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ // TODO: Test UART wakeup while supporting sleep
|
||||
|
||||
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
|
||||
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
|
||||
@ -438,14 +434,16 @@
|
||||
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
|
||||
#define SOC_PM_SUPPORT_BT_WAKEUP (1)
|
||||
#define SOC_PM_SUPPORT_CPU_PD (1)
|
||||
#define SOC_PM_SUPPORT_WIFI_PD (1)
|
||||
#define SOC_PM_SUPPORT_BT_PD (1)
|
||||
#define SOC_PM_SUPPORT_MODEM_PD (1)
|
||||
#define SOC_PM_SUPPORT_XTAL32K_PD (1)
|
||||
#define SOC_PM_SUPPORT_RC32K_PD (1)
|
||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||
|
||||
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
|
||||
|
||||
#define SOC_PM_CPU_RETENTION_BY_SW (1)
|
||||
|
||||
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
||||
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
|
||||
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (1)
|
||||
|
@ -835,6 +835,14 @@ config SOC_PM_SUPPORT_RC_FAST_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
||||
bool
|
||||
default y
|
||||
|
@ -769,37 +769,6 @@ typedef struct {
|
||||
*/
|
||||
void rtc_init(rtc_config_t cfg);
|
||||
|
||||
/**
|
||||
* Structure describing vddsdio configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins.
|
||||
uint32_t enable : 1; //!< Enable VDDSDIO regulator
|
||||
uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V
|
||||
uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
} rtc_vddsdio_config_t;
|
||||
|
||||
/**
|
||||
* Get current VDDSDIO configuration
|
||||
* If VDDSDIO configuration is overridden by RTC, get values from RTC
|
||||
* Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE
|
||||
* Otherwise, use default values and the level of MTDI bootstrapping pin.
|
||||
* @return currently used VDDSDIO configuration
|
||||
*/
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void);
|
||||
|
||||
/**
|
||||
* Set new VDDSDIO configuration using RTC registers.
|
||||
* If config.force == 1, this overrides configuration done using bootstrapping
|
||||
* pins and EFUSE.
|
||||
*
|
||||
* @param config new VDDSDIO configuration
|
||||
*/
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
|
||||
|
||||
// -------------------------- CLOCK TREE DEFS ALIAS ----------------------------
|
||||
// **WARNING**: The following are only for backwards compatibility.
|
||||
// Please use the declarations in soc/clk_tree_defs.h instead.
|
||||
|
@ -419,7 +419,8 @@
|
||||
#define SOC_PM_SUPPORT_WIFI_PD (1)
|
||||
#define SOC_PM_SUPPORT_BT_PD (1)
|
||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||
|
||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||
#define SOC_PM_CPU_RETENTION_BY_RTCCNTL (1)
|
||||
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
|
||||
|
||||
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
||||
|
@ -854,36 +854,6 @@ typedef struct {
|
||||
*/
|
||||
void rtc_init(rtc_config_t cfg);
|
||||
|
||||
/**
|
||||
* Structure describing vddsdio configuration
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins.
|
||||
uint32_t enable : 1; //!< Enable VDDSDIO regulator
|
||||
uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V
|
||||
uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator
|
||||
} rtc_vddsdio_config_t;
|
||||
|
||||
/**
|
||||
* Get current VDDSDIO configuration
|
||||
* If VDDSDIO configuration is overridden by RTC, get values from RTC
|
||||
* Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE
|
||||
* Otherwise, use default values and the level of MTDI bootstrapping pin.
|
||||
* @return currently used VDDSDIO configuration
|
||||
*/
|
||||
rtc_vddsdio_config_t rtc_vddsdio_get_config(void);
|
||||
|
||||
/**
|
||||
* Set new VDDSDIO configuration using RTC registers.
|
||||
* If config.force == 1, this overrides configuration done using bootstrapping
|
||||
* pins and EFUSE.
|
||||
*
|
||||
* @param config new VDDSDIO configuration
|
||||
*/
|
||||
void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
|
||||
|
||||
/**
|
||||
* Regulator config
|
||||
*/
|
||||
|
@ -955,6 +955,14 @@ config SOC_PM_SUPPORT_RC_FAST_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_APLL_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -415,6 +415,9 @@
|
||||
#define SOC_PM_SUPPORT_RTC_FAST_MEM_PD (1)
|
||||
#define SOC_PM_SUPPORT_RTC_SLOW_MEM_PD (1)
|
||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||
|
||||
#define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1)
|
||||
|
||||
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
||||
#define SOC_CLK_APLL_SUPPORTED (1)
|
||||
|
@ -1003,10 +1003,22 @@ config SOC_PM_SUPPORT_RC_FAST_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_RC_FAST_D256_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
@ -411,9 +411,13 @@
|
||||
#define SOC_PM_SUPPORT_TAGMEM_PD (1)
|
||||
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
|
||||
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
|
||||
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
|
||||
|
||||
#define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1)
|
||||
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
|
||||
|
||||
#define SOC_PM_CPU_RETENTION_BY_RTCCNTL (1)
|
||||
|
||||
/*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */
|
||||
#define SOC_CLK_RC_FAST_D256_SUPPORTED (1)
|
||||
#define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 (1)
|
||||
|
@ -106,7 +106,7 @@ examples/system/ipc/ipc_isr:
|
||||
|
||||
examples/system/light_sleep:
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"]
|
||||
- if: IDF_TARGET in ["esp32c2", "esp32h2"]
|
||||
temporary: true
|
||||
reason: target(s) not supported yet
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- |
|
||||
|
||||
# Light Sleep Example
|
||||
|
||||
|
@ -12,7 +12,8 @@
|
||||
/* Most development boards have "boot" button attached to GPIO0.
|
||||
* You can also change this to another pin.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4 \
|
||||
|| CONFIG_IDF_TARGET_ESP32C6
|
||||
#define BOOT_BUTTON_NUM 9
|
||||
#else
|
||||
#define BOOT_BUTTON_NUM 0
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import logging
|
||||
@ -13,6 +13,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.generic
|
||||
def test_light_sleep(dut: Dut) -> None:
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@ -27,6 +27,7 @@
|
||||
#include "cmd_system.h"
|
||||
#include "wifi_cmd.h"
|
||||
#include "esp_wifi_he.h"
|
||||
#include "esp_pm.h"
|
||||
|
||||
/*******************************************************
|
||||
* Constants
|
||||
@ -244,10 +245,7 @@ void app_main(void)
|
||||
}
|
||||
|
||||
// TODO: WIFI-5150
|
||||
#if CONFIG_PM_ENABLE
|
||||
io_toggle_pmu_internal_signal_map_to_io_init();
|
||||
io_toggle_gpio_init();
|
||||
|
||||
#if CONFIG_PM_ENABLE && 0
|
||||
sleep_clock_system_retention_init();
|
||||
sleep_clock_modem_retention_init();
|
||||
sleep_peripheral_retention_init();
|
||||
|
@ -105,6 +105,8 @@ void app_main(void)
|
||||
esp_pm_config_esp32s3_t pm_config = {
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
esp_pm_config_esp32c2_t pm_config = {
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
esp_pm_config_esp32c6_t pm_config = {
|
||||
#endif
|
||||
.max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ,
|
||||
.min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ,
|
||||
|
@ -156,3 +156,4 @@ components/espcoredump/include/port/xtensa/esp_core_dump_summary_port.h
|
||||
components/riscv/include/esp_private/panic_reason.h
|
||||
components/riscv/include/riscv/interrupt.h
|
||||
components/riscv/include/riscv/rvruntime-frames.h
|
||||
components/riscv/include/riscv/rvsleep-frames.h
|
||||
|
Loading…
x
Reference in New Issue
Block a user