mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
Merge branch 'feat/esp_idf_h4_retention_clk_icg' into 'master'
feat(esp_hw_support): refactor PMU sleep icg and support retention ICG See merge request espressif/esp-idf!48915
This commit is contained in:
@@ -188,7 +188,7 @@ extern "C" {
|
||||
typedef struct {
|
||||
pmu_hal_context_t *hal;
|
||||
void *mc;
|
||||
#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA || CONFIG_PM_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
void *priv;
|
||||
#endif
|
||||
#if SOC_SPI_FLASH_HAS_DEDICATED_LDO
|
||||
@@ -198,6 +198,18 @@ typedef struct {
|
||||
|
||||
pmu_context_t * PMU_instance(void);
|
||||
|
||||
/**
|
||||
* @brief Runtime pmu sleep extra arguments
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t sleep_flags; //!< Power domains to power down and sleep sub-mode flags
|
||||
uint32_t clk_flags[2]; //!< Sleep clock ICG flags: [0]=bits[31:0], [1]=bits[63:32]
|
||||
uint32_t adjustment; //!< Total software and hardware time overhead (us)
|
||||
soc_rtc_slow_clk_src_t slowclk_src; //!< RTC slow clock source used by PMU timing
|
||||
uint32_t slowclk_period; //!< Recalibrated slow clock period (us, Q13.19)
|
||||
uint32_t fastclk_period; //!< Recalibrated fast clock period (us, Q13.19)
|
||||
} pmu_sleep_extra_args_t;
|
||||
|
||||
typedef enum pmu_sleep_protect_mode {
|
||||
PMU_SLEEP_PROTECT_HP_SLEEP = 0,
|
||||
PMU_SLEEP_PROTECT_XTAL,
|
||||
@@ -267,19 +279,12 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
/**
|
||||
* @brief Get default sleep configuration
|
||||
* @param config pmu_sleep_config instance
|
||||
* @param sleep_flags flags indicates the power domain that will be powered down and the sleep submode
|
||||
* @param clk_flags indicates the clock ICG cell that will be ungated
|
||||
* @param adjustment total software and hardware time overhead
|
||||
* @param slowclk_src slow clock source of pmu
|
||||
* @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 args pmu sleep runtime arguments
|
||||
* @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 sleep_flags, pmu_sleep_clk_icg_flags_t clk_flags, uint32_t adjustment, soc_rtc_slow_clk_src_t slowclk_src, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp);
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp);
|
||||
|
||||
/**
|
||||
* @brief Prepare the chip to enter sleep mode
|
||||
|
||||
@@ -32,6 +32,13 @@ typedef struct {
|
||||
void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sleep internal runtime arguments
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t clk_flags[2]; //!< Sleep clock ICG flags.
|
||||
} esp_sleep_extra_args_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_SLEEP_RTC_USE_RC_FAST_MODE, //!< The mode requested by RTC peripherals to keep RC_FAST clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (Will override the RC_FAST domain config by esp_sleep_pd_config)
|
||||
ESP_SLEEP_DIG_USE_RC_FAST_MODE, //!< The mode requested by digital peripherals to keep RC_FAST clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the RC_FAST domain config by esp_sleep_pd_config)
|
||||
@@ -213,6 +220,33 @@ void esp_deep_sleep_deregister_phy_hook(esp_deep_sleep_cb_t old_dslp_cb);
|
||||
*/
|
||||
void esp_sleep_overhead_out_time_refresh(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enter the sleep configuration critical section (task context only)
|
||||
*
|
||||
* Protects sleep configuration state. Must be paired with esp_sleep_exit_critical().
|
||||
* Do not call from ISR; use esp_sleep_enter_critical_safe() instead.
|
||||
*/
|
||||
void esp_sleep_enter_critical(void);
|
||||
|
||||
/**
|
||||
* @brief Exit the sleep configuration critical section entered by esp_sleep_enter_critical()
|
||||
*/
|
||||
void esp_sleep_exit_critical(void);
|
||||
|
||||
/**
|
||||
* @brief Enter the sleep configuration critical section (safe for task or ISR context)
|
||||
*
|
||||
* Protects sleep configuration state (e.g. power domain options, sub-mode refs, clk icg refs...).
|
||||
* Must be paired with esp_sleep_exit_critical_safe().
|
||||
*/
|
||||
void esp_sleep_enter_critical_safe(void);
|
||||
|
||||
/**
|
||||
* @brief Exit the sleep configuration critical section entered by esp_sleep_enter_critical_safe()
|
||||
*/
|
||||
void esp_sleep_exit_critical_safe(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_macros.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
#include "soc/pmu_icg_mapping.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
|
||||
#include "esp_private/sleep_retention.h"
|
||||
|
||||
/**
|
||||
* @brief Convert one or more PMU_ICG_FUNC_ENA_xxx cells into an ICG bitmask
|
||||
*/
|
||||
#define PMU_CLK_ICG(clock) PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_##clock)
|
||||
#define PMU_CLK_ICGS_1(a) PMU_CLK_ICG(a)
|
||||
#define PMU_CLK_ICGS_2(a, b) PMU_CLK_ICG(a) | PMU_CLK_ICG(b)
|
||||
#define PMU_CLK_ICGS_3(a, b, c) PMU_CLK_ICG(a) | PMU_CLK_ICGS_2(b, c)
|
||||
#define PMU_CLK_ICGS_4(a, b, c, d) PMU_CLK_ICG(a) | PMU_CLK_ICGS_3(b, c, d)
|
||||
#define PMU_CLK_ICGS_5(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_1(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_6(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_2(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_7(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_3(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_8(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_4(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_9(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_5(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_10(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_6(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_11(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_7(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_12(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_8(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_13(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_9(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS_14(a, b, c, d, ...) PMU_CLK_ICGS_4(a, b, c, d) | PMU_CLK_ICGS_10(__VA_ARGS__)
|
||||
|
||||
#define PMU_CLK_ICGS_N(n) PMU_CLK_ICGS_##n
|
||||
#define PMU_CLK_ICGS_DISPATCH(n, ...) PMU_CLK_ICGS_N(n)(__VA_ARGS__)
|
||||
#define PMU_CLK_ICGS(...) \
|
||||
PMU_CLK_ICGS_DISPATCH(ESP_VA_NARG(__VA_ARGS__), __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Program HP backup ICG registers from PMU sleep data
|
||||
*
|
||||
* @param data pointer to pmu_sleep_data_t
|
||||
* @param ctx pointer to pmu_context_t
|
||||
*/
|
||||
void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx);
|
||||
|
||||
/**
|
||||
* @brief Recompute the backup clock ICG mask from the current retention module bitmap
|
||||
*
|
||||
* Called whenever the REGDMA retention module bitmap changes (module created/destroyed/
|
||||
* attached/detached), so that the backup ICG flags always reflect which peripherals
|
||||
* currently participate in retention.
|
||||
*
|
||||
* @param module_bitmap pointer to current retention module bitmap
|
||||
*/
|
||||
void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap);
|
||||
|
||||
#endif /* SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG */
|
||||
|
||||
/**
|
||||
* @brief Convert sleep clock ICG reference counts to PMU ICG flags for HP sleep mode
|
||||
*
|
||||
* Caller must zero-initialize both outputs; this function only ORs bits into them.
|
||||
*
|
||||
* @param clk_icg0_flags ICG flags bits[31:0]
|
||||
* @param clk_icg1_flags ICG flags bits[63:32] (untouched if the target only has 32-bit ICG)
|
||||
*/
|
||||
void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags);
|
||||
|
||||
#endif /* SOC_PM_SUPPORT_PMU_CLK_ICG */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -40,6 +40,10 @@ if((CONFIG_SOC_PM_SUPPORT_MODEM_PD OR CONFIG_SOC_PM_SUPPORT_TOP_PD) AND CONFIG_S
|
||||
list(APPEND srcs "port/${target}/sleep_clock.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_PM_SUPPORT_PMU_CLK_ICG)
|
||||
list(APPEND srcs "port/${target}/sleep_clock_icg.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_PM_SUPPORT_REGDMA_TRIGGERED_PHY)
|
||||
list(APPEND srcs "port/${target}/sleep_phy.c")
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
|
||||
(void)clk_icg1_flags;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
|
||||
/* Starting from C6ECO1 and later versions, when BLE RTC is configured to use
|
||||
* MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL,the actual slow clock source is the WiFi power clock.
|
||||
* As all 32 bits of ICG_FUNC are occupied, the ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK
|
||||
* has been remapped to PMU_ICG_FUNC_ENA_RETENTION.*/
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_RETENTION);
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)clk_icg1_flags;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
#if SOC_UART_HP_NUM > 2
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2);
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)clk_icg1_flags;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
|
||||
(void)clk_icg1_flags;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "hal/pmu_ll.h"
|
||||
#include "pmu_param.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM == 0
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART0 )
|
||||
#elif CONFIG_ESP_CONSOLE_UART_NUM == 1
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART1 )
|
||||
#else
|
||||
#define RETENTION_CONSOLE_UART 0
|
||||
#endif
|
||||
#else
|
||||
#define RETENTION_CONSOLE_UART 0
|
||||
#endif
|
||||
|
||||
#define RETENTION_SYS_CLK PMU_CLK_ICGS( HPBUS )
|
||||
|
||||
#define RETENTION_COMMON PMU_CLK_ICGS( REGDMA, HPCORE ) | RETENTION_SYS_CLK
|
||||
|
||||
static const uint32_t s_retention_module_retention_clocks[SLEEP_RETENTION_MODULE_MAX + 1] = {
|
||||
[SLEEP_RETENTION_MODULE_NULL] = 0,
|
||||
[SLEEP_RETENTION_MODULE_CLOCK_SYSTEM] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_SYS_PERIPH] = RETENTION_COMMON | PMU_CLK_ICGS( IOMUX, SYSTIMER, SEC, MSPI ) | RETENTION_CONSOLE_UART,
|
||||
[SLEEP_RETENTION_MODULE_TG0_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ),
|
||||
[SLEEP_RETENTION_MODULE_TG1_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ),
|
||||
[SLEEP_RETENTION_MODULE_TG0_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ),
|
||||
[SLEEP_RETENTION_MODULE_TG1_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_ADC] = RETENTION_COMMON | PMU_CLK_ICG ( SARADC ),
|
||||
[SLEEP_RETENTION_MODULE_I2C0] = RETENTION_COMMON | PMU_CLK_ICG ( I2C0 ),
|
||||
[SLEEP_RETENTION_MODULE_I2C1] = RETENTION_COMMON | PMU_CLK_ICG ( I2C0 ),
|
||||
[SLEEP_RETENTION_MODULE_RMT0] = RETENTION_COMMON | PMU_CLK_ICG ( RMT ),
|
||||
[SLEEP_RETENTION_MODULE_UART0] = RETENTION_COMMON | PMU_CLK_ICG ( UART0 ),
|
||||
[SLEEP_RETENTION_MODULE_UART1] = RETENTION_COMMON | PMU_CLK_ICG ( UART1 ),
|
||||
[SLEEP_RETENTION_MODULE_I2S0] = RETENTION_COMMON | PMU_CLK_ICGS( I2S_RX, I2S_TX ),
|
||||
[SLEEP_RETENTION_MODULE_ETM0] = RETENTION_COMMON | PMU_CLK_ICG ( SOC_ETM ),
|
||||
[SLEEP_RETENTION_MODULE_TEMP_SENSOR] = RETENTION_COMMON | PMU_CLK_ICG ( TSENS ),
|
||||
[SLEEP_RETENTION_MODULE_TWAI0] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI0 ),
|
||||
[SLEEP_RETENTION_MODULE_PARLIO0] = RETENTION_COMMON | PMU_CLK_ICGS( PARL_TX, PARL_RX ),
|
||||
[SLEEP_RETENTION_MODULE_GPSPI2] = RETENTION_COMMON | PMU_CLK_ICG ( SPI2 ),
|
||||
[SLEEP_RETENTION_MODULE_LEDC] = RETENTION_COMMON | PMU_CLK_ICG ( LEDC0 ),
|
||||
[SLEEP_RETENTION_MODULE_MCPWM0] = RETENTION_COMMON | PMU_CLK_ICG ( PWM ),
|
||||
[SLEEP_RETENTION_MODULE_SDM0] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_CLOCK_MODEM] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_BLE_MAC] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_BT_BB] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_802154_MAC] = RETENTION_COMMON,
|
||||
};
|
||||
|
||||
void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap)
|
||||
{
|
||||
static DRAM_ATTR uint32_t s_retention_icg_flags = 0;
|
||||
pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv;
|
||||
if (data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] == NULL) {
|
||||
data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] = &s_retention_icg_flags;
|
||||
}
|
||||
|
||||
/* Check if the last word holds bit above MODULE_MAX. */
|
||||
assert(!module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1] ||
|
||||
((31 - __builtin_clz(module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1])) +
|
||||
((SLEEP_RETENTION_MODULE_BITMAP_SZ - 1) << 5)) <= SLEEP_RETENTION_MODULE_MAX);
|
||||
|
||||
uint32_t clocks_mask = 0;
|
||||
sleep_retention_module_t module = 0;
|
||||
for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) {
|
||||
for (uint32_t remain = module_bitmap->bitmap[i]; remain; remain &= (remain - 1)) {
|
||||
module = (__builtin_ctz(remain) + (i << 5));
|
||||
clocks_mask |= s_retention_module_retention_clocks[module];
|
||||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_SECURE_ENABLE_TEE
|
||||
clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_SEC);
|
||||
#endif
|
||||
|
||||
esp_sleep_enter_critical_safe();
|
||||
s_retention_icg_flags = clocks_mask;
|
||||
esp_sleep_exit_critical_safe();
|
||||
}
|
||||
|
||||
FORCE_IRAM_ATTR void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx)
|
||||
{
|
||||
pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data;
|
||||
if (!data_ctx || !ctx || !data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t *flags = (uint32_t *)data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK];
|
||||
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
|
||||
pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, *flags);
|
||||
}
|
||||
}
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
|
||||
(void)clk_icg1_flags;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "hal/pmu_ll.h"
|
||||
#include "pmu_param.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM == 0
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART0 )
|
||||
#elif CONFIG_ESP_CONSOLE_UART_NUM == 1
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART1 )
|
||||
#else
|
||||
#define RETENTION_CONSOLE_UART 0
|
||||
#endif
|
||||
#else
|
||||
#define RETENTION_CONSOLE_UART 0
|
||||
#endif
|
||||
|
||||
#define RETENTION_SYS_CLK PMU_CLK_ICGS( HPBUS )
|
||||
|
||||
#define RETENTION_COMMON PMU_CLK_ICGS( HPCORE ) | RETENTION_SYS_CLK
|
||||
|
||||
static const uint32_t s_retention_module_retention_clocks[SLEEP_RETENTION_MODULE_MAX + 1] = {
|
||||
[SLEEP_RETENTION_MODULE_NULL] = 0,
|
||||
[SLEEP_RETENTION_MODULE_CLOCK_SYSTEM] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_SYS_PERIPH] = RETENTION_COMMON | PMU_CLK_ICGS( IOMUX, SYSTIMER, SEC, MSPI ) | RETENTION_CONSOLE_UART,
|
||||
[SLEEP_RETENTION_MODULE_TG0_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ),
|
||||
[SLEEP_RETENTION_MODULE_TG1_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ),
|
||||
[SLEEP_RETENTION_MODULE_TG0_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ),
|
||||
[SLEEP_RETENTION_MODULE_TG1_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH3] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_GDMA_CH4] = RETENTION_COMMON | PMU_CLK_ICG ( GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_ADC] = RETENTION_COMMON | PMU_CLK_ICG ( SARADC ),
|
||||
[SLEEP_RETENTION_MODULE_I2C0] = RETENTION_COMMON | PMU_CLK_ICG ( I2C ),
|
||||
[SLEEP_RETENTION_MODULE_I2C1] = RETENTION_COMMON | PMU_CLK_ICG ( I2C ),
|
||||
[SLEEP_RETENTION_MODULE_RMT0] = RETENTION_COMMON | PMU_CLK_ICG ( RMT ),
|
||||
[SLEEP_RETENTION_MODULE_UART0] = RETENTION_COMMON | PMU_CLK_ICGS( UART0 ),
|
||||
[SLEEP_RETENTION_MODULE_UART1] = RETENTION_COMMON | PMU_CLK_ICGS( UART1 ),
|
||||
[SLEEP_RETENTION_MODULE_I2S0] = RETENTION_COMMON | PMU_CLK_ICGS( I2S_RX, I2S_TX ),
|
||||
[SLEEP_RETENTION_MODULE_ETM0] = RETENTION_COMMON | PMU_CLK_ICG ( SOC_ETM ),
|
||||
[SLEEP_RETENTION_MODULE_TEMP_SENSOR] = RETENTION_COMMON | PMU_CLK_ICG ( TSENS ),
|
||||
[SLEEP_RETENTION_MODULE_TWAI0] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI0 ),
|
||||
[SLEEP_RETENTION_MODULE_PARLIO0] = RETENTION_COMMON | PMU_CLK_ICGS( PARL_TX, PARL_RX ),
|
||||
[SLEEP_RETENTION_MODULE_GPSPI2] = RETENTION_COMMON | PMU_CLK_ICG ( SPI2 ),
|
||||
[SLEEP_RETENTION_MODULE_GPSPI3] = RETENTION_COMMON | PMU_CLK_ICGS( SPI2 ),
|
||||
[SLEEP_RETENTION_MODULE_LEDC] = RETENTION_COMMON | PMU_CLK_ICGS( LEDC0 ),
|
||||
[SLEEP_RETENTION_MODULE_MCPWM0] = RETENTION_COMMON | PMU_CLK_ICG ( PWM ),
|
||||
[SLEEP_RETENTION_MODULE_MCPWM1] = RETENTION_COMMON | PMU_CLK_ICG ( PWM ),
|
||||
[SLEEP_RETENTION_MODULE_SDM0] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_CLOCK_MODEM] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_BLE_MAC] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_BT_BB] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_802154_MAC] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_POWER] = RETENTION_COMMON,
|
||||
};
|
||||
|
||||
void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap)
|
||||
{
|
||||
static DRAM_ATTR uint32_t s_retention_icg_flags = 0;
|
||||
pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv;
|
||||
if (data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] == NULL) {
|
||||
data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] = &s_retention_icg_flags;
|
||||
}
|
||||
|
||||
/* Check if the last word holds bit above MODULE_MAX. */
|
||||
assert(!module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1] ||
|
||||
((31 - __builtin_clz(module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1])) +
|
||||
((SLEEP_RETENTION_MODULE_BITMAP_SZ - 1) << 5)) <= SLEEP_RETENTION_MODULE_MAX);
|
||||
|
||||
uint32_t clocks_mask = 0;
|
||||
sleep_retention_module_t module = 0;
|
||||
for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) {
|
||||
for (uint32_t remain = module_bitmap->bitmap[i]; remain; remain &= (remain - 1)) {
|
||||
module = (__builtin_ctz(remain) + (i << 5));
|
||||
clocks_mask |= s_retention_module_retention_clocks[module];
|
||||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_SECURE_ENABLE_TEE
|
||||
clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_SEC);
|
||||
#endif
|
||||
|
||||
esp_sleep_enter_critical_safe();
|
||||
s_retention_icg_flags = clocks_mask;
|
||||
esp_sleep_exit_critical_safe();
|
||||
}
|
||||
|
||||
FORCE_IRAM_ATTR void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx)
|
||||
{
|
||||
pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data;
|
||||
if (!data_ctx || !ctx || !data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t *flags = (uint32_t *)data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK];
|
||||
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
|
||||
pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, *flags);
|
||||
}
|
||||
}
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
|
||||
(void)clk_icg1_flags;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
ESP_LOG_ATTR_TAG(TAG, "sleep_clock_icg");
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
#if SOC_UART_HP_NUM > 2
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2);
|
||||
}
|
||||
#endif
|
||||
#if SOC_UART_HP_NUM > 3
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART3] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART3);
|
||||
}
|
||||
#endif
|
||||
#if SOC_UART_HP_NUM > 4
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART4] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART4);
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)clk_icg1_flags;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !CONFIG_PM_SLEEP_CLK_ICG_ENABLE
|
||||
static bool warned;
|
||||
if (!warned) {
|
||||
warned = true;
|
||||
ESP_LOGW(TAG, "PM_SLEEP_CLK_ICG_ENABLE is disabled. "
|
||||
"Clock ungate requests may not be honored during sleep.");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "hal/pmu_ll.h"
|
||||
#include "pmu_param.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if CONFIG_PM_SLP_IRAM_OPT
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR FORCE_IRAM_ATTR
|
||||
#else
|
||||
#define SLEEP_CLOCK_ICG_FN_ATTR
|
||||
#endif
|
||||
|
||||
static int16_t s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM == 0
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART0 )
|
||||
#elif CONFIG_ESP_CONSOLE_UART_NUM == 1
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART1 )
|
||||
#elif CONFIG_ESP_CONSOLE_UART_NUM == 2
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART2 )
|
||||
#elif CONFIG_ESP_CONSOLE_UART_NUM == 3
|
||||
#define RETENTION_CONSOLE_UART PMU_CLK_ICG( UART3 )
|
||||
#else
|
||||
#define RETENTION_CONSOLE_UART 0
|
||||
#endif
|
||||
#else
|
||||
#define RETENTION_CONSOLE_UART 0
|
||||
#endif
|
||||
|
||||
#define RETENTION_SYS_CLK PMU_CLK_ICGS( BUS )
|
||||
|
||||
#define RETENTION_COMMON PMU_CLK_ICGS( REGDMA, HPCORE0, HPCORE1 ) | RETENTION_SYS_CLK
|
||||
|
||||
static const uint64_t s_retention_module_retention_clocks[SLEEP_RETENTION_MODULE_MAX + 1] = {
|
||||
[SLEEP_RETENTION_MODULE_NULL] = 0,
|
||||
[SLEEP_RETENTION_MODULE_CLOCK_SYSTEM] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_SYS_PERIPH] = RETENTION_COMMON | PMU_CLK_ICGS( IOMUX, SYSTIMER, SEC, MSPI_FLASH, MSPI_PSRAM ) | RETENTION_CONSOLE_UART,
|
||||
[SLEEP_RETENTION_MODULE_TG0_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ),
|
||||
[SLEEP_RETENTION_MODULE_TG1_WDT] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ),
|
||||
[SLEEP_RETENTION_MODULE_TG0_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ),
|
||||
[SLEEP_RETENTION_MODULE_TG0_TIMER1] = RETENTION_COMMON | PMU_CLK_ICG ( TG0 ),
|
||||
[SLEEP_RETENTION_MODULE_TG1_TIMER0] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ),
|
||||
[SLEEP_RETENTION_MODULE_TG1_TIMER1] = RETENTION_COMMON | PMU_CLK_ICG ( TG1 ),
|
||||
[SLEEP_RETENTION_MODULE_AHB_DMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_AHB_DMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_AHB_DMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_AHB_DMA_CH3] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_AHB_DMA_CH4] = RETENTION_COMMON | PMU_CLK_ICG ( AHB_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_AXI_DMA_CH0] = RETENTION_COMMON | PMU_CLK_ICG ( AXI_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_AXI_DMA_CH1] = RETENTION_COMMON | PMU_CLK_ICG ( AXI_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_AXI_DMA_CH2] = RETENTION_COMMON | PMU_CLK_ICG ( AXI_GDMA ),
|
||||
[SLEEP_RETENTION_MODULE_LP_AHB_DMA_CH0] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_LP_AHB_DMA_CH1] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_UART0] = RETENTION_COMMON | PMU_CLK_ICG ( UART0 ),
|
||||
[SLEEP_RETENTION_MODULE_UART1] = RETENTION_COMMON | PMU_CLK_ICG ( UART1 ),
|
||||
[SLEEP_RETENTION_MODULE_UART2] = RETENTION_COMMON | PMU_CLK_ICG ( UART2 ),
|
||||
[SLEEP_RETENTION_MODULE_UART3] = RETENTION_COMMON | PMU_CLK_ICG ( UART3 ),
|
||||
[SLEEP_RETENTION_MODULE_RMT0] = RETENTION_COMMON | PMU_CLK_ICG ( RMT ),
|
||||
[SLEEP_RETENTION_MODULE_I2S0] = RETENTION_COMMON | PMU_CLK_ICG ( I2S0 ),
|
||||
[SLEEP_RETENTION_MODULE_I2S1] = RETENTION_COMMON | PMU_CLK_ICG ( I2S1 ),
|
||||
[SLEEP_RETENTION_MODULE_I2C0] = RETENTION_COMMON | PMU_CLK_ICG ( I2C0 ),
|
||||
[SLEEP_RETENTION_MODULE_I2C1] = RETENTION_COMMON | PMU_CLK_ICG ( I2C1 ),
|
||||
[SLEEP_RETENTION_MODULE_ETM0] = RETENTION_COMMON | PMU_CLK_ICG ( ETM ),
|
||||
[SLEEP_RETENTION_MODULE_TWAI0] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI0 ),
|
||||
[SLEEP_RETENTION_MODULE_TWAI1] = RETENTION_COMMON | PMU_CLK_ICG ( TWAI1 ),
|
||||
[SLEEP_RETENTION_MODULE_PARLIO0] = RETENTION_COMMON | PMU_CLK_ICG ( PARL ),
|
||||
[SLEEP_RETENTION_MODULE_GPSPI2] = RETENTION_COMMON | PMU_CLK_ICG ( SPI2 ),
|
||||
[SLEEP_RETENTION_MODULE_GPSPI3] = RETENTION_COMMON | PMU_CLK_ICG ( SPI3 ),
|
||||
[SLEEP_RETENTION_MODULE_LEDC0] = RETENTION_COMMON | PMU_CLK_ICG ( LEDC0 ),
|
||||
[SLEEP_RETENTION_MODULE_LEDC1] = RETENTION_COMMON | PMU_CLK_ICG ( LEDC1 ),
|
||||
[SLEEP_RETENTION_MODULE_MCPWM0] = RETENTION_COMMON | PMU_CLK_ICG ( PWM0 ),
|
||||
[SLEEP_RETENTION_MODULE_MCPWM1] = RETENTION_COMMON | PMU_CLK_ICG ( PWM1 ),
|
||||
[SLEEP_RETENTION_MODULE_MCPWM2] = RETENTION_COMMON | PMU_CLK_ICG ( PWM2 ),
|
||||
[SLEEP_RETENTION_MODULE_MCPWM3] = RETENTION_COMMON | PMU_CLK_ICG ( PWM3 ),
|
||||
[SLEEP_RETENTION_MODULE_SDM0] = RETENTION_COMMON | PMU_CLK_ICG ( SDMMC ),
|
||||
[SLEEP_RETENTION_MODULE_LCDCAM] = RETENTION_COMMON | PMU_CLK_ICG ( LCDCAM ),
|
||||
[SLEEP_RETENTION_MODULE_JPEG] = RETENTION_COMMON | PMU_CLK_ICG ( JPEG ),
|
||||
[SLEEP_RETENTION_MODULE_DMA2D] = RETENTION_COMMON | PMU_CLK_ICG ( 2DDMA ),
|
||||
[SLEEP_RETENTION_MODULE_PPA] = RETENTION_COMMON | PMU_CLK_ICG ( PPA ),
|
||||
[SLEEP_RETENTION_MODULE_WIFI_MAC] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_WIFI_BB] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_BLE_MAC] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_BT_BB] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_802154_MAC] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_CLOCK_MODEM] = RETENTION_COMMON,
|
||||
[SLEEP_RETENTION_MODULE_MODEM_PHY] = RETENTION_COMMON,
|
||||
};
|
||||
|
||||
void sleep_clock_icg_retention_clock_config(sleep_retention_module_bitmap_t *module_bitmap)
|
||||
{
|
||||
static DRAM_ATTR uint32_t s_retention_icg_flags[2] = {0, 0};
|
||||
pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv;
|
||||
if (data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] == NULL) {
|
||||
data->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK] = s_retention_icg_flags;
|
||||
}
|
||||
|
||||
/* Check if the last word holds bit above MODULE_MAX. */
|
||||
assert(!module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1] ||
|
||||
((31 - __builtin_clz(module_bitmap->bitmap[SLEEP_RETENTION_MODULE_BITMAP_SZ - 1])) +
|
||||
((SLEEP_RETENTION_MODULE_BITMAP_SZ - 1) << 5)) <= SLEEP_RETENTION_MODULE_MAX);
|
||||
|
||||
uint64_t clocks_mask = 0;
|
||||
sleep_retention_module_t module = 0;
|
||||
for (int i = 0; i < SLEEP_RETENTION_MODULE_BITMAP_SZ; i++) {
|
||||
for (uint32_t remain = module_bitmap->bitmap[i]; remain; remain &= (remain - 1)) {
|
||||
module = (__builtin_ctz(remain) + (i << 5));
|
||||
clocks_mask |= s_retention_module_retention_clocks[module];
|
||||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_SPIRAM
|
||||
clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_MSPI_PSRAM);
|
||||
#endif
|
||||
#if !CONFIG_SECURE_ENABLE_TEE
|
||||
clocks_mask &= ~PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_SEC);
|
||||
#endif
|
||||
|
||||
esp_sleep_enter_critical_safe();
|
||||
s_retention_icg_flags[0] = PMU_SLEEP_CLK_ICG_FUNC_LO(clocks_mask);
|
||||
s_retention_icg_flags[1] = PMU_SLEEP_CLK_ICG_FUNC_HI(clocks_mask);
|
||||
esp_sleep_exit_critical_safe();
|
||||
}
|
||||
|
||||
FORCE_IRAM_ATTR void pmu_sleep_retention_clock_icg_config(void *data, pmu_context_t *ctx)
|
||||
{
|
||||
pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data;
|
||||
if (!data_ctx || !ctx || !data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK]) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t *flags = (uint32_t *)data_ctx->func[PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK];
|
||||
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
|
||||
pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, flags[0], flags[1]);
|
||||
}
|
||||
}
|
||||
|
||||
SLEEP_CLOCK_ICG_FN_ATTR void sleep_clock_icg_get_icg_flags(uint32_t *clk_icg0_flags, uint32_t *clk_icg1_flags)
|
||||
{
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_FUNC_LO(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX));
|
||||
*clk_icg1_flags |= PMU_SLEEP_CLK_ICG_FUNC_HI(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX));
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_FUNC_LO(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0));
|
||||
*clk_icg1_flags |= PMU_SLEEP_CLK_ICG_FUNC_HI(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0));
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_FUNC_LO(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0));
|
||||
*clk_icg1_flags |= PMU_SLEEP_CLK_ICG_FUNC_HI(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0));
|
||||
}
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_FUNC_LO(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1));
|
||||
*clk_icg1_flags |= PMU_SLEEP_CLK_ICG_FUNC_HI(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1));
|
||||
}
|
||||
#if SOC_UART_HP_NUM > 2
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_FUNC_LO(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2));
|
||||
*clk_icg1_flags |= PMU_SLEEP_CLK_ICG_FUNC_HI(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2));
|
||||
}
|
||||
#endif
|
||||
#if SOC_UART_HP_NUM > 3
|
||||
if (s_sleep_clock_icg_refs[ESP_SLEEP_CLOCK_UART3] > 0) {
|
||||
*clk_icg0_flags |= PMU_SLEEP_CLK_ICG_FUNC_LO(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART3));
|
||||
*clk_icg1_flags |= PMU_SLEEP_CLK_ICG_FUNC_HI(PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART3));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_sleep_enter_critical_safe();
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_sleep_clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_sleep_clock_icg_refs[clock] \
|
||||
: s_sleep_clock_icg_refs[clock];
|
||||
esp_sleep_exit_critical_safe();
|
||||
assert(refs >= 0);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "modem/modem_clock_impl.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
|
||||
|
||||
@@ -44,7 +44,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
* 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 };
|
||||
static DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = NULL,
|
||||
#endif
|
||||
};
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
|
||||
@@ -188,14 +188,15 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
const uint32_t adjustment = args->adjustment;
|
||||
const soc_rtc_slow_clk_src_t slowclk_src = args->slowclk_src;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
#if (SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED && SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP)
|
||||
const uint32_t slowclk_period_fixed = (slowclk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? rtc_clk_freq_to_period(SOC_CLK_RC_SLOW_FREQ_APPROX) : slowclk_period;
|
||||
@@ -231,23 +232,15 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
|
||||
if (dslp) {
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, args->slowclk_period);
|
||||
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
|
||||
config->digital = digital_default;
|
||||
|
||||
@@ -257,7 +250,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
|
||||
config->analog = analog_default;
|
||||
} else {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -297,7 +290,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
|
||||
config->power = power_default;
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_src, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ typedef struct {
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = (uint32_t)(clk_flags) \
|
||||
.icg_func = (clk_flags)[0] \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -45,7 +45,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
* 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 };
|
||||
static DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = NULL,
|
||||
#endif
|
||||
};
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -176,14 +176,15 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
const uint32_t adjustment = args->adjustment;
|
||||
const soc_rtc_slow_clk_src_t slowclk_src = args->slowclk_src;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
#if (SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED && SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP)
|
||||
const uint32_t slowclk_period_fixed = (slowclk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? rtc_clk_freq_to_period(SOC_CLK_RC_SLOW_FREQ_APPROX) : slowclk_period;
|
||||
@@ -215,27 +216,19 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
config->power = power_default;
|
||||
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_src, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
|
||||
if (dslp) {
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, args->slowclk_period);
|
||||
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -244,7 +237,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
|
||||
config->analog = analog_default;
|
||||
} else {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
|
||||
@@ -328,7 +328,7 @@ typedef struct {
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = (uint32_t)(clk_flags) \
|
||||
.icg_func = (clk_flags)[0] \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
|
||||
@@ -45,7 +45,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
* 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 };
|
||||
static DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = NULL,
|
||||
#endif
|
||||
};
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,14 +182,15 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
const uint32_t adjustment = args->adjustment;
|
||||
const soc_rtc_slow_clk_src_t slowclk_src = args->slowclk_src;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
#if (SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED && SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP)
|
||||
const uint32_t slowclk_period_fixed = (slowclk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? rtc_clk_freq_to_period(SOC_CLK_RC_SLOW_FREQ_APPROX) : slowclk_period;
|
||||
@@ -225,27 +226,19 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
config->power = power_default;
|
||||
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_src, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
|
||||
if (dslp) {
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, args->slowclk_period);
|
||||
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -253,7 +246,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_dslp_lp_dbias();
|
||||
config->analog = analog_default;
|
||||
} else {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
|
||||
@@ -328,7 +328,7 @@ typedef struct {
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = (uint32_t)(clk_flags) \
|
||||
.icg_func = (clk_flags)[0] \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -40,7 +40,13 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
* 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 };
|
||||
static DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = NULL,
|
||||
#endif
|
||||
};
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -101,13 +101,12 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period);
|
||||
param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_us, fastclk_period);
|
||||
@@ -128,20 +127,12 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
if (dslp) {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -153,7 +144,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
power_default.lp_sys[PMU_MODE_LP_SLEEP].dig_power.bod_source_sel = 1;
|
||||
}
|
||||
} else {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -176,7 +167,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
}
|
||||
config->power = power_default;
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
@@ -320,7 +320,7 @@ typedef struct {
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = (uint32_t)(clk_flags) \
|
||||
.icg_func = (clk_flags)[0] \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
|
||||
@@ -40,7 +40,16 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
* 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 };
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
static DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 };
|
||||
#endif
|
||||
static DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = &pmu_data,
|
||||
#endif
|
||||
};
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/lp_aon_hal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "pmu_param.h"
|
||||
#include "hal/efuse_ll.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
@@ -110,13 +111,12 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period);
|
||||
param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_us, fastclk_period);
|
||||
@@ -141,32 +141,24 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
config->power = power_default;
|
||||
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
|
||||
if (dslp) {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
analog_default.lp_sys[LP(SLEEP)].analog.dbias = get_slp_lp_dbias();
|
||||
config->analog = analog_default;
|
||||
} else {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -215,11 +207,12 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi
|
||||
|
||||
static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig, bool dslp)
|
||||
{
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->sleep_icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->sleep_icg_func);
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
if (!dslp) {
|
||||
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
pmu_sleep_retention_clock_icg_config(ctx->priv, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
|
||||
@@ -54,6 +56,7 @@ extern "C" {
|
||||
uint32_t get_act_hp_drvb(void);
|
||||
uint32_t get_act_lp_dbias(void);
|
||||
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_dig_power_reg_t dig_power;
|
||||
pmu_hp_clk_power_reg_t clk_power;
|
||||
@@ -108,7 +111,20 @@ typedef struct {
|
||||
|
||||
const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode);
|
||||
|
||||
/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */
|
||||
#define PMU_SLEEP_PRIV_ENABLED (SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG)
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
enum {
|
||||
#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK,
|
||||
#endif
|
||||
PMU_SLEEP_PRIV_MAX,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *func[PMU_SLEEP_PRIV_MAX];
|
||||
} pmu_sleep_data_t;
|
||||
#endif
|
||||
|
||||
/* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/
|
||||
typedef union {
|
||||
@@ -348,7 +364,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_sys_cntl_reg_t syscntl;
|
||||
uint32_t icg_func;
|
||||
uint32_t sleep_icg_func;
|
||||
} pmu_sleep_digital_config_t;
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
@@ -356,15 +372,15 @@ typedef struct {
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = (uint32_t)(clk_flags) \
|
||||
.sleep_icg_func = (uint32_t)((clk_flags)[0]), \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
.sleep_icg_func = 0, \
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,17 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
* 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 };
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
static DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 };
|
||||
#endif
|
||||
static DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = &pmu_data,
|
||||
#endif
|
||||
};
|
||||
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "hal/lp_aon_hal.h"
|
||||
#include "hal/efuse_ll.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "pmu_param.h"
|
||||
#if !SOC_APM_SUPPORTED
|
||||
#include "hal/apm_hal.h"
|
||||
@@ -95,13 +96,12 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period);
|
||||
param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_us, fastclk_period);
|
||||
@@ -126,34 +126,26 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
config->power = power_default;
|
||||
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
|
||||
if (dslp) {
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, args->slowclk_period);
|
||||
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
config->analog = analog_default;
|
||||
} else {
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -205,10 +197,11 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi
|
||||
static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig, bool dslp)
|
||||
{
|
||||
pmu_ll_hp_set_pause_watchdog(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func);
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), (dig->sleep_icg_func != 0));
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->sleep_icg_func);
|
||||
if (!dslp) {
|
||||
pmu_ll_hp_set_dig_pad_slp_sel(ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
pmu_sleep_retention_clock_icg_config(ctx->priv, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,19 +101,21 @@ ESP_SYSTEM_INIT_FN(sleep_power_startup_init, SECONDARY, BIT(0), 108)
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "failed to init power retention module, err=%d", err);
|
||||
} else {
|
||||
PMU_instance()->priv = &ana_wait_ctx;
|
||||
pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv;
|
||||
data->func[PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT] = &ana_wait_ctx;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void pmu_sleep_power_analog_wait_config(void *ana_wait_context, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM])
|
||||
void pmu_sleep_power_analog_wait_config(void *data, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM])
|
||||
{
|
||||
if (!ana_wait_context) {
|
||||
pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data;
|
||||
if (!data_ctx || !data_ctx->func[PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT]) {
|
||||
return;
|
||||
}
|
||||
|
||||
pmu_sleep_power_ana_wait_context_t *ana_wait_ctx = (pmu_sleep_power_ana_wait_context_t *)ana_wait_context;
|
||||
pmu_sleep_power_ana_wait_context_t *ana_wait_ctx = (pmu_sleep_power_ana_wait_context_t *)data_ctx->func[PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT];
|
||||
for (int i = 0; i < ANALOG_WAIT_CTRL_NUM; i++) {
|
||||
if (!ana_wait_ctx->regdma_desc[i]) {
|
||||
continue;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
|
||||
@@ -115,10 +117,28 @@ const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mo
|
||||
/**
|
||||
* @brief Update content of selected analog wait ctrl REGDMA links.
|
||||
*
|
||||
* @param ana_wait_context Analog wait ctrl context.
|
||||
* @param data PMU sleep data context.
|
||||
* @param analog_wait Update analog wait values at S2M, M2S, M2A retention links.
|
||||
*/
|
||||
void pmu_sleep_power_analog_wait_config(void *ana_wait_context, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM]);
|
||||
void pmu_sleep_power_analog_wait_config(void *data, const uint16_t analog_wait[ANALOG_WAIT_CTRL_NUM]);
|
||||
#endif
|
||||
|
||||
/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */
|
||||
#define PMU_SLEEP_PRIV_ENABLED (CONFIG_PM_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT || SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG)
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
enum {
|
||||
#if CONFIG_PM_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT
|
||||
PMU_SLEEP_PRIV_SKIP_MODEM_TO_ACTIVE_ANALOG_WAIT,
|
||||
#endif
|
||||
#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK,
|
||||
#endif
|
||||
PMU_SLEEP_PRIV_MAX,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *func[PMU_SLEEP_PRIV_MAX];
|
||||
} pmu_sleep_data_t;
|
||||
#endif
|
||||
|
||||
/* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/
|
||||
@@ -361,7 +381,7 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_sys_cntl_reg_t syscntl;
|
||||
uint32_t icg_func;
|
||||
uint32_t sleep_icg_func;
|
||||
} pmu_sleep_digital_config_t;
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
@@ -369,15 +389,15 @@ typedef struct {
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = (uint32_t)(clk_flags) \
|
||||
.sleep_icg_func = (uint32_t)((clk_flags)[0]), \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = 0 \
|
||||
.sleep_icg_func = 0, \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -45,7 +45,16 @@ pmu_context_t * __attribute__((weak)) SPM_IRAM_ATTR PMU_instance(void)
|
||||
* instance will be used in pmu_sleep.c */
|
||||
static SPM_DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU };
|
||||
static SPM_DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT();
|
||||
static SPM_DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc };
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
static SPM_DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 };
|
||||
#endif
|
||||
static SPM_DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = &pmu_data,
|
||||
#endif
|
||||
};
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,14 +129,12 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_us, slowclk_period);
|
||||
param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(mc->hp.analog_wait_time_us, slowclk_period);
|
||||
@@ -157,25 +155,17 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
|
||||
power_default.hp_sys.dig_power.cpu_pd_en = (sleep_flags & PMU_SLEEP_PD_CPU) ? 1 : 0;
|
||||
#endif
|
||||
if (dslp) {
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, args->slowclk_period);
|
||||
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
@@ -192,7 +182,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
}
|
||||
} else {
|
||||
// Get light sleep digital_default
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
// Get light sleep analog default
|
||||
@@ -247,7 +237,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
|
||||
config->power = power_default;
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_src, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "soc/hp_sys_clkrst_reg.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_private/startup_internal.h"
|
||||
#include "pmu_param.h"
|
||||
|
||||
ESP_LOG_ATTR_TAG(TAG, "sleep_clock");
|
||||
|
||||
@@ -166,17 +167,22 @@ ESP_SYSTEM_INIT_FN(sleep_clock_icg_startup_init, SECONDARY, BIT(0), 106)
|
||||
}
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
PMU_instance()->priv = (void *)&clock_icg_context;
|
||||
pmu_sleep_data_t *data = (pmu_sleep_data_t *)PMU_instance()->priv;
|
||||
data->func[PMU_SLEEP_PRIV_SW_ICG_CLK] = (void *)&clock_icg_context;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to initialize system sleep clock ICG context");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void pmu_sleep_clock_icg_config(void *icg_context, const uint32_t icg_func)
|
||||
void pmu_sleep_clock_icg_config(void *data, const uint32_t icg_func)
|
||||
{
|
||||
assert(icg_context);
|
||||
pmu_sleep_clock_icg_context_t *clock_icg = (pmu_sleep_clock_icg_context_t *)icg_context;
|
||||
pmu_sleep_data_t *data_ctx = (pmu_sleep_data_t *)data;
|
||||
if (!data_ctx || !data_ctx->func[PMU_SLEEP_PRIV_SW_ICG_CLK]) {
|
||||
return;
|
||||
}
|
||||
|
||||
pmu_sleep_clock_icg_context_t *clock_icg = (pmu_sleep_clock_icg_context_t *)data_ctx->func[PMU_SLEEP_PRIV_SW_ICG_CLK];
|
||||
/* Locking is not required here because this function is always invoked
|
||||
* within esp_light_sleep_start(), where the necessary lock has already been acquired. */
|
||||
if (icg_func & BIT(PMU_ICG_FUNC_ENA_IOMUX)) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
#include "sdkconfig.h"
|
||||
@@ -21,6 +22,21 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */
|
||||
#define PMU_SLEEP_PRIV_ENABLED (SOC_PM_SLEEP_CLK_ICG_USE_REGDMA)
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
enum {
|
||||
#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA
|
||||
PMU_SLEEP_PRIV_SW_ICG_CLK,
|
||||
#endif
|
||||
PMU_SLEEP_PRIV_MAX,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *func[PMU_SLEEP_PRIV_MAX];
|
||||
} pmu_sleep_data_t;
|
||||
#endif
|
||||
|
||||
#define HP_CALI_ACTIVE_DCM_VSET_DEFAULT 27 // For DCDC, about 1.25v
|
||||
#define HP_CALI_ACTIVE_DBIAS_DEFAULT 24 // For HP regulator
|
||||
#define LP_CALI_ACTIVE_DBIAS_DEFAULT 29 // For LP regulator
|
||||
@@ -117,7 +133,7 @@ const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mo
|
||||
|
||||
|
||||
#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !defined(CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
void pmu_sleep_clock_icg_config(void *icg_context, const uint32_t icg_func);
|
||||
void pmu_sleep_clock_icg_config(void *data, const uint32_t icg_func);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -357,7 +373,7 @@ typedef struct {
|
||||
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = { 0, (uint32_t)(clk_flags) } \
|
||||
.icg_func = { (clk_flags)[1], (clk_flags)[0] } \
|
||||
}
|
||||
#else // !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
@@ -373,7 +389,7 @@ typedef struct {
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
}, \
|
||||
.icg_func = { 0, (uint32_t)(clk_flags) } \
|
||||
.icg_func = { (clk_flags)[1], (clk_flags)[0] } \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -44,7 +44,16 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
* instance will be used in pmu_sleep.c */
|
||||
static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = NULL };
|
||||
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 };
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
static DRAM_ATTR pmu_sleep_data_t pmu_data = { 0 };
|
||||
#endif
|
||||
static DRAM_ATTR pmu_context_t pmu_context = {
|
||||
.hal = &pmu_hal,
|
||||
.mc = (void *)&pmu_mc,
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
.priv = &pmu_data,
|
||||
#endif
|
||||
};
|
||||
|
||||
if (pmu_hal.dev == NULL) {
|
||||
pmu_hal.dev = &PMU;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#include "pmu_param.h"
|
||||
#include "hal/clk_tree_hal.h"
|
||||
#include "hal/lp_aon_hal.h"
|
||||
@@ -151,14 +152,15 @@ uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t sleep_flags, soc_rtc_slow_clk
|
||||
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 sleep_flags,
|
||||
const uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
const uint32_t slowclk_period,
|
||||
const uint32_t fastclk_period
|
||||
pmu_sleep_extra_args_t *args
|
||||
)
|
||||
{
|
||||
const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc;
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
const uint32_t adjustment = args->adjustment;
|
||||
const soc_rtc_slow_clk_src_t slowclk_src = args->slowclk_src;
|
||||
const uint32_t slowclk_period = args->slowclk_period;
|
||||
const uint32_t fastclk_period = args->fastclk_period;
|
||||
|
||||
#if (SOC_PM_PMU_MIN_SLP_SLOW_CLK_CYCLE_FIXED && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP)
|
||||
const uint32_t slowclk_period_fixed = (slowclk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) ? rtc_clk_freq_to_period(SOC_CLK_RC_SLOW_FREQ_APPROX) : slowclk_period;
|
||||
@@ -194,21 +196,13 @@ static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default(
|
||||
return param;
|
||||
}
|
||||
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
pmu_sleep_config_t *config,
|
||||
uint32_t sleep_flags,
|
||||
pmu_sleep_clk_icg_flags_t clk_flags,
|
||||
uint32_t adjustment,
|
||||
soc_rtc_slow_clk_src_t slowclk_src,
|
||||
uint32_t slowclk_period,
|
||||
uint32_t fastclk_period,
|
||||
bool dslp
|
||||
)
|
||||
const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, pmu_sleep_extra_args_t *args, bool dslp)
|
||||
{
|
||||
const uint32_t sleep_flags = args->sleep_flags;
|
||||
pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(sleep_flags);
|
||||
|
||||
if (dslp) {
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, slowclk_period);
|
||||
config->param.lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US, args->slowclk_period);
|
||||
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
config->digital = digital_default;
|
||||
@@ -217,7 +211,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
config->analog = analog_default;
|
||||
} else {
|
||||
// Get light sleep digital_default
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags);
|
||||
pmu_sleep_digital_config_t digital_default = PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, args->clk_flags);
|
||||
config->digital = digital_default;
|
||||
|
||||
// Get light sleep analog default
|
||||
@@ -258,7 +252,7 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
|
||||
config->power = power_default;
|
||||
pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_src, slowclk_period, fastclk_period);
|
||||
config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, args);
|
||||
|
||||
return config;
|
||||
}
|
||||
@@ -284,17 +278,19 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi
|
||||
pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].xtal.xpd_xtal);
|
||||
}
|
||||
|
||||
static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig)
|
||||
static void pmu_sleep_digital_init(pmu_context_t *ctx, const pmu_sleep_digital_config_t *dig, bool dslp)
|
||||
{
|
||||
const bool icg_func_enabled = (dig->icg_func.clock[0] != 0) || (dig->icg_func.clock[1] != 0);
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), icg_func_enabled);
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func.clock[0], dig->icg_func.clock[1]);
|
||||
pmu_ll_hp_set_icg_apb(ctx->hal->dev, HP(SLEEP), dig->icg_apb.clock[0], dig->icg_apb.clock[1]);
|
||||
pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pad_slp_sel);
|
||||
pmu_ll_hp_set_hold_all_hp_pad (ctx->hal->dev, HP(SLEEP), dig->syscntl.hp_pad_hold_all);
|
||||
pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, HP(SLEEP), dig->syscntl.lp_pad_hold_all);
|
||||
pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, HP(SLEEP), dig->syscntl.dig_pause_wdt);
|
||||
pmu_ll_hp_set_c_channel_enable (ctx->hal->dev, HP(SLEEP), dig->syscntl.c_channel);
|
||||
if (!dslp) {
|
||||
const bool icg_func_enabled = (dig->icg_func.clock[0] != 0) || (dig->icg_func.clock[1] != 0);
|
||||
pmu_ll_hp_set_icg_sysclk_enable(ctx->hal->dev, HP(SLEEP), icg_func_enabled);
|
||||
pmu_ll_hp_set_icg_func(ctx->hal->dev, HP(SLEEP), dig->icg_func.clock[0], dig->icg_func.clock[1]);
|
||||
pmu_sleep_retention_clock_icg_config(ctx->priv, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
|
||||
@@ -344,7 +340,7 @@ 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_digital_init(PMU_instance(), &config->digital);
|
||||
pmu_sleep_digital_init(PMU_instance(), &config->digital, dslp);
|
||||
pmu_sleep_analog_init(PMU_instance(), &config->analog, dslp);
|
||||
pmu_sleep_param_init(PMU_instance(), &config->param, dslp);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
#include "soc/pmu_icg_mapping.h"
|
||||
@@ -111,6 +113,20 @@ typedef struct {
|
||||
|
||||
const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode);
|
||||
|
||||
/* Enabled when this chip needs any pmu_sleep_data_t priv slot; conditions differ per chip. */
|
||||
#define PMU_SLEEP_PRIV_ENABLED (SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG)
|
||||
#if PMU_SLEEP_PRIV_ENABLED
|
||||
enum {
|
||||
#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
PMU_SLEEP_PRIV_HW_RETENTION_ICG_CLK,
|
||||
#endif
|
||||
PMU_SLEEP_PRIV_MAX,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *func[PMU_SLEEP_PRIV_MAX];
|
||||
} pmu_sleep_data_t;
|
||||
#endif
|
||||
|
||||
/* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/
|
||||
typedef union {
|
||||
@@ -328,9 +344,6 @@ typedef struct {
|
||||
struct {
|
||||
uint32_t clock[2];
|
||||
} icg_func;
|
||||
struct {
|
||||
uint32_t clock[2];
|
||||
} icg_apb;
|
||||
} pmu_sleep_digital_config_t;
|
||||
|
||||
|
||||
@@ -345,7 +358,7 @@ typedef struct {
|
||||
.icg_func = { .clock = { 0, 0 } }, \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags, clk_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.lp_pad_hold_all = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
|
||||
@@ -354,8 +367,7 @@ typedef struct {
|
||||
.c_channel = (sleep_flags & PMU_SLEEP_PD_TOP) ? 0 : 1 \
|
||||
}, \
|
||||
.icg_func = { \
|
||||
.clock = { PMU_SLEEP_CLK_ICG_FUNC_LO(clk_flags), \
|
||||
PMU_SLEEP_CLK_ICG_FUNC_HI(clk_flags) } \
|
||||
.clock = { (clk_flags)[0], (clk_flags)[1] } \
|
||||
}, \
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,10 @@
|
||||
#include "esp_private/sleep_clock.h"
|
||||
#endif
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#endif
|
||||
|
||||
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#endif
|
||||
@@ -281,10 +285,6 @@ typedef struct {
|
||||
int16_t refs;
|
||||
uint16_t reserved; /* reserved for 4 bytes aligned */
|
||||
} domain[ESP_PD_DOMAIN_MAX];
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
int16_t clock_icg_refs[ESP_SLEEP_CLOCK_MAX];
|
||||
pmu_sleep_clk_icg_flags_t sleep_clk_icg_flags;
|
||||
#endif
|
||||
portMUX_TYPE lock;
|
||||
uint64_t sleep_duration;
|
||||
uint32_t wakeup_triggers;
|
||||
@@ -334,10 +334,6 @@ static sleep_config_t s_config = {
|
||||
.refs = 0
|
||||
}
|
||||
},
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
.clock_icg_refs[0 ... ESP_SLEEP_CLOCK_MAX - 1] = 0,
|
||||
.sleep_clk_icg_flags = 0,
|
||||
#endif
|
||||
.lock = portMUX_INITIALIZER_UNLOCKED,
|
||||
.ccount_ticks_record = 0,
|
||||
.sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
|
||||
@@ -360,18 +356,35 @@ RTC_SLOW_ATTR
|
||||
#endif
|
||||
static int32_t s_sleep_sub_mode_ref_cnt[ESP_SLEEP_MODE_MAX] = { 0 };
|
||||
|
||||
void esp_sleep_overhead_out_time_refresh(void)
|
||||
void esp_sleep_enter_critical(void)
|
||||
{
|
||||
esp_os_enter_critical(&s_config.lock);
|
||||
s_config.overhead_out_need_remeasure = true;
|
||||
}
|
||||
|
||||
void esp_sleep_exit_critical(void)
|
||||
{
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
}
|
||||
|
||||
void esp_sleep_enter_critical_safe(void)
|
||||
{
|
||||
esp_os_enter_critical_safe(&s_config.lock);
|
||||
}
|
||||
|
||||
void esp_sleep_exit_critical_safe(void)
|
||||
{
|
||||
esp_os_exit_critical_safe(&s_config.lock);
|
||||
}
|
||||
|
||||
void esp_sleep_overhead_out_time_refresh(void)
|
||||
{
|
||||
esp_sleep_enter_critical();
|
||||
s_config.overhead_out_need_remeasure = true;
|
||||
esp_sleep_exit_critical();
|
||||
}
|
||||
|
||||
static uint32_t get_power_down_flags(void);
|
||||
static uint32_t get_sleep_flags(uint32_t pd_flags, bool deepsleep);
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
static void sleep_update_clk_icg_flags(void);
|
||||
#endif
|
||||
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP && SOC_RTC_WDT_SUPPORTED
|
||||
static uint32_t get_sleep_rtc_wdt_timeout(uint64_t sleep_duration);
|
||||
static uint32_t calc_sleep_slow_clk_required_cycles(uint32_t timeout, uint32_t rtc_slow_clk_cal_period);
|
||||
@@ -521,28 +534,28 @@ esp_err_t esp_deep_sleep_try(uint64_t time_in_us)
|
||||
|
||||
static esp_err_t s_sleep_hook_register(esp_deep_sleep_cb_t new_cb, esp_deep_sleep_cb_t s_cb_array[MAX_DSLP_HOOKS])
|
||||
{
|
||||
esp_os_enter_critical(&s_config.lock);
|
||||
esp_sleep_enter_critical();
|
||||
for (int n = 0; n < MAX_DSLP_HOOKS; n++) {
|
||||
if (s_cb_array[n]==NULL || s_cb_array[n]==new_cb) {
|
||||
s_cb_array[n]=new_cb;
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
esp_sleep_exit_critical();
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
esp_sleep_exit_critical();
|
||||
ESP_LOGE(TAG, "Registered deepsleep callbacks exceeds MAX_DSLP_HOOKS");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
static void s_sleep_hook_deregister(esp_deep_sleep_cb_t old_cb, esp_deep_sleep_cb_t s_cb_array[MAX_DSLP_HOOKS])
|
||||
{
|
||||
esp_os_enter_critical(&s_config.lock);
|
||||
esp_sleep_enter_critical();
|
||||
for (int n = 0; n < MAX_DSLP_HOOKS; n++) {
|
||||
if(s_cb_array[n] == old_cb) {
|
||||
s_cb_array[n] = NULL;
|
||||
}
|
||||
}
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
esp_sleep_exit_critical();
|
||||
}
|
||||
|
||||
esp_err_t esp_deep_sleep_register_hook(esp_deep_sleep_cb_t new_dslp_cb)
|
||||
@@ -1014,7 +1027,7 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
return result;
|
||||
}
|
||||
|
||||
static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection)
|
||||
static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_mode_t mode, bool allow_sleep_rejection, esp_sleep_extra_args_t *args)
|
||||
{
|
||||
// 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.
|
||||
@@ -1155,12 +1168,18 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, esp_sleep_m
|
||||
}
|
||||
#endif
|
||||
|
||||
pmu_sleep_extra_args_t sleep_extra_args = {
|
||||
.sleep_flags = sleep_flags,
|
||||
.clk_flags = { args->clk_flags[0], args->clk_flags[1] },
|
||||
.adjustment = s_config.sleep_time_adjustment,
|
||||
.slowclk_src = rtc_clk_slow_src_get(),
|
||||
.slowclk_period = s_config.rtc_clk_cal_period,
|
||||
.fastclk_period = s_config.fast_clk_cal_period
|
||||
};
|
||||
pmu_sleep_config_t config;
|
||||
pmu_sleep_clk_icg_flags_t clk_flags = deep_sleep ? 0 : s_config.sleep_clk_icg_flags;
|
||||
pmu_sleep_init(pmu_sleep_config_default(&config, sleep_flags, clk_flags, s_config.sleep_time_adjustment,
|
||||
rtc_clk_slow_src_get(), s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period,
|
||||
deep_sleep), deep_sleep);
|
||||
pmu_sleep_init(pmu_sleep_config_default(&config, &sleep_extra_args, deep_sleep), deep_sleep);
|
||||
#else
|
||||
(void) args;
|
||||
rtc_sleep_config_t config;
|
||||
rtc_sleep_get_default_config(sleep_flags, &config);
|
||||
rtc_sleep_init(config);
|
||||
@@ -1277,7 +1296,7 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
/* Disable interrupts and stall another core in case another task writes
|
||||
* to RTC memory while we calculate RTC memory CRC.
|
||||
*/
|
||||
esp_os_enter_critical(&s_config.lock);
|
||||
esp_sleep_enter_critical();
|
||||
#if CONFIG_FREERTOS_PORT_THREAD_SAFE_CLAIM
|
||||
esp_ipc_isr_stall_other_cpu();
|
||||
#else
|
||||
@@ -1308,9 +1327,9 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
}
|
||||
#endif // ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB
|
||||
|
||||
esp_sleep_extra_args_t extra_args = { 0 };
|
||||
// Decide which power domains can be powered down
|
||||
uint32_t pd_flags = get_power_down_flags();
|
||||
|
||||
// Re-calibrate the RTC clock
|
||||
sleep_low_power_clock_calibration(true);
|
||||
|
||||
@@ -1361,7 +1380,7 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
uint32_t sleep_flags = get_sleep_flags(force_pd_flags | pd_flags, true);
|
||||
// Enter sleep
|
||||
esp_err_t err = ESP_OK;
|
||||
if (esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_DEEP_SLEEP, allow_sleep_rejection) == ESP_ERR_SLEEP_REJECT) {
|
||||
if (esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_DEEP_SLEEP, allow_sleep_rejection, &extra_args) == ESP_ERR_SLEEP_REJECT) {
|
||||
err = ESP_ERR_SLEEP_REJECT;
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
|
||||
/* Cache Resume 2: if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is enabled, cache has been suspended in esp_sleep_start */
|
||||
@@ -1392,7 +1411,7 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
esp_int_wdt_livelock_workaround(true);
|
||||
#endif
|
||||
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
esp_sleep_exit_critical();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1415,17 +1434,19 @@ esp_err_t FORCE_IRAM_ATTR esp_deep_sleep_try_to_start(void)
|
||||
* Placed into IRAM as flash may need some time to be powered on.
|
||||
*/
|
||||
static esp_err_t esp_light_sleep_inner(uint32_t sleep_flags,
|
||||
uint32_t flash_enable_time_us) __attribute__((noinline));
|
||||
uint32_t flash_enable_time_us,
|
||||
esp_sleep_extra_args_t *args) __attribute__((noinline));
|
||||
|
||||
static SLEEP_FN_ATTR esp_err_t esp_light_sleep_inner(uint32_t sleep_flags,
|
||||
uint32_t flash_enable_time_us)
|
||||
uint32_t flash_enable_time_us,
|
||||
esp_sleep_extra_args_t *args)
|
||||
{
|
||||
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
||||
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
||||
#endif
|
||||
|
||||
// Enter sleep
|
||||
esp_err_t reject = esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, true);
|
||||
esp_err_t reject = esp_sleep_start(sleep_flags, ESP_SLEEP_MODE_LIGHT_SLEEP, true, args);
|
||||
|
||||
#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED
|
||||
// If VDDSDIO regulator was controlled by RTC registers before sleep,
|
||||
@@ -1530,7 +1551,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
s_config.ccount_ticks_record = esp_cpu_get_cycle_count();
|
||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_GOTO_SLEEP, (void *)0);
|
||||
|
||||
esp_os_enter_critical(&s_config.lock);
|
||||
esp_sleep_enter_critical();
|
||||
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
|
||||
uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count();
|
||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_TIME_START, (void *)0);
|
||||
@@ -1545,7 +1566,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
if (sleep_smp_cpu_sleep_prepare() != ESP_OK) {
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
esp_sleep_exit_critical();
|
||||
return ESP_ERR_SLEEP_REJECT;
|
||||
}
|
||||
#endif
|
||||
@@ -1585,11 +1606,10 @@ esp_err_t esp_light_sleep_start(void)
|
||||
uint32_t pd_flags = get_power_down_flags();
|
||||
// Append flags to indicate the sleep sub-mode and modify the pd_flags according to sub-mode attributes.
|
||||
uint32_t sleep_flags = get_sleep_flags(pd_flags, false);
|
||||
// Decide which clock can be ungate during sleep
|
||||
esp_sleep_extra_args_t extra_args = { 0 };
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
sleep_update_clk_icg_flags();
|
||||
sleep_clock_icg_get_icg_flags(&extra_args.clk_flags[0], &extra_args.clk_flags[1]);
|
||||
#endif
|
||||
|
||||
// Re-calibrate the RTC clock
|
||||
sleep_low_power_clock_calibration(false);
|
||||
|
||||
@@ -1739,7 +1759,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
#endif
|
||||
else {
|
||||
// Enter sleep, then wait for flash to be ready on wakeup
|
||||
err = esp_light_sleep_inner(sleep_flags, flash_enable_time_us);
|
||||
err = esp_light_sleep_inner(sleep_flags, flash_enable_time_us, &extra_args);
|
||||
}
|
||||
|
||||
// light sleep wakeup flag only makes sense after a successful light sleep
|
||||
@@ -1814,7 +1834,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
s_config.overhead_out_need_remeasure = false;
|
||||
}
|
||||
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
esp_sleep_exit_critical();
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1935,10 +1955,10 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
esp_os_enter_critical(&s_config.lock);
|
||||
esp_sleep_enter_critical();
|
||||
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
|
||||
s_config.sleep_duration = time_in_us;
|
||||
esp_os_exit_critical(&s_config.lock);
|
||||
esp_sleep_exit_critical();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -2729,7 +2749,7 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
esp_err_t err = ESP_OK;
|
||||
esp_os_enter_critical_safe(&s_config.lock);
|
||||
esp_sleep_enter_critical_safe();
|
||||
int refs = 0;
|
||||
if (s_config.domain[domain].pd_option == ESP_PD_OPTION_AUTO) {
|
||||
// If domain is currently in auto mode, transition to the new mode directly
|
||||
@@ -2768,7 +2788,7 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_
|
||||
}
|
||||
}
|
||||
}
|
||||
esp_os_exit_critical_safe(&s_config.lock);
|
||||
esp_sleep_exit_critical_safe();
|
||||
if (err == ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGE(TAG, "Domain is already in ESP_PD_OPTION_OFF state, please check whether the domain pd_option is managed symmetrically.");
|
||||
}
|
||||
@@ -2796,7 +2816,7 @@ esp_err_t esp_sleep_sub_mode_config(esp_sleep_sub_mode_t mode, bool activate)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_os_enter_critical_safe(&s_config.lock);
|
||||
esp_sleep_enter_critical_safe();
|
||||
if (activate) {
|
||||
s_sleep_sub_mode_ref_cnt[mode]++;
|
||||
} else {
|
||||
@@ -2806,7 +2826,7 @@ esp_err_t esp_sleep_sub_mode_config(esp_sleep_sub_mode_t mode, bool activate)
|
||||
ESP_EARLY_LOGW(TAG, "%s disabled multiple times!! (If this log appears only once after OTA upgrade, it can be ignored.)", s_submode2str[mode]);
|
||||
s_sleep_sub_mode_ref_cnt[mode] = 0;
|
||||
}
|
||||
esp_os_exit_critical_safe(&s_config.lock);
|
||||
esp_sleep_exit_critical_safe();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -2816,9 +2836,9 @@ esp_err_t esp_sleep_sub_mode_force_disable(esp_sleep_sub_mode_t mode)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_os_enter_critical_safe(&s_config.lock);
|
||||
esp_sleep_enter_critical_safe();
|
||||
s_sleep_sub_mode_ref_cnt[mode] = 0;
|
||||
esp_os_exit_critical_safe(&s_config.lock);
|
||||
esp_sleep_exit_critical_safe();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -2834,32 +2854,6 @@ int32_t* esp_sleep_sub_mode_dump_config(FILE *stream) {
|
||||
return s_sleep_sub_mode_ref_cnt;
|
||||
}
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
esp_err_t esp_sleep_clock_config(esp_sleep_clock_t clock, esp_sleep_clock_option_t option)
|
||||
{
|
||||
#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA && !CONFIG_PM_SLEEP_CLK_ICG_ENABLE
|
||||
static bool warned;
|
||||
if (!warned) {
|
||||
warned = true;
|
||||
ESP_LOGW(TAG, "PM_SLEEP_CLK_ICG_ENABLE is disabled. "
|
||||
"Clock ungate requests may not be honored during sleep.");
|
||||
}
|
||||
#endif
|
||||
if (clock >= ESP_SLEEP_CLOCK_MAX || option >= ESP_SLEEP_CLOCK_OPTION_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
int __attribute__((unused)) refs;
|
||||
esp_os_enter_critical_safe(&s_config.lock);
|
||||
refs = (option == ESP_SLEEP_CLOCK_OPTION_UNGATE) ? s_config.clock_icg_refs[clock]++ \
|
||||
: (option == ESP_SLEEP_CLOCK_OPTION_GATE) ? --s_config.clock_icg_refs[clock] \
|
||||
: s_config.clock_icg_refs[clock];
|
||||
esp_os_exit_critical_safe(&s_config.lock);
|
||||
assert(refs >= 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The modules in the CPU and modem power domains still depend on the top power domain.
|
||||
* To be safe, the CPU and Modem power domains must also be powered off and saved when
|
||||
@@ -3176,51 +3170,6 @@ static SLEEP_FN_ATTR uint32_t get_sleep_flags(uint32_t sleep_flags, bool deepsle
|
||||
return sleep_flags;
|
||||
}
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
SLEEP_FN_ATTR static void sleep_update_clk_icg_flags(void)
|
||||
{
|
||||
pmu_sleep_clk_icg_flags_t clk_flags = 0;
|
||||
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_IOMUX] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_IOMUX);
|
||||
}
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_LEDC0] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_LEDC0);
|
||||
}
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART0] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART0);
|
||||
}
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART1] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART1);
|
||||
}
|
||||
#if SOC_UART_HP_NUM > 2
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART2] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART2);
|
||||
}
|
||||
#endif
|
||||
#if SOC_UART_HP_NUM > 3
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART3] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART3);
|
||||
}
|
||||
#endif
|
||||
#if SOC_UART_HP_NUM > 4
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_UART4] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_UART4);
|
||||
}
|
||||
#endif
|
||||
#if SOC_BLE_USE_WIFI_PWR_CLK_WORKAROUND
|
||||
/* Starting from C6ECO1 and later versions, when BLE RTC is configured to use
|
||||
* MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL,the actual slow clock source is the WiFi power clock.
|
||||
* As all 32 bits of ICG_FUNC are occupied, the ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK
|
||||
* has been remapped to PMU_ICG_FUNC_ENA_RETENTION.*/
|
||||
if (s_config.clock_icg_refs[ESP_SLEEP_CLOCK_BT_USE_WIFI_PWR_CLK] > 0) {
|
||||
clk_flags |= PMU_SLEEP_CLK_ICG_BIT(PMU_ICG_FUNC_ENA_RETENTION);
|
||||
}
|
||||
#endif
|
||||
s_config.sleep_clk_icg_flags = clk_flags;
|
||||
}
|
||||
#endif /* SOC_PM_SUPPORT_PMU_CLK_ICG */
|
||||
|
||||
#if CONFIG_ESP_SLEEP_ENABLE_RTC_WDT_IN_SLEEP && SOC_RTC_WDT_SUPPORTED
|
||||
/* TODO: PM-609 */
|
||||
/* Calculate drift cycles of rtc slow clock in long-term working scenarios. */
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_pmu.h"
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
#include "esp_private/sleep_clock_icg.h"
|
||||
#endif
|
||||
|
||||
#if SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
|
||||
#include "soc/pmu_reg.h" // for PMU_DATE_REG, it can provide full 32 bit read and write access
|
||||
#endif
|
||||
@@ -620,6 +624,8 @@ static void entries_do_destroy(sleep_retention_module_t module)
|
||||
memset(&next_entries, 0, sizeof(sleep_retention_entries_t));
|
||||
|
||||
_lock_acquire_recursive(&s_retention.lock);
|
||||
s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
s_retention.created_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
int index = module_runtime_attach(instance(module)) ? 1 : 0;
|
||||
struct module_sleep_retention_context *ctx = &s_retention.context[index];
|
||||
regdma_link_priority_t priority = 0;
|
||||
@@ -636,8 +642,6 @@ static void entries_do_destroy(sleep_retention_module_t module)
|
||||
priority++;
|
||||
}
|
||||
} while (priority < SLEEP_RETENTION_REGDMA_LINK_NR_PRIORITIES);
|
||||
s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
s_retention.created_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
@@ -780,6 +784,11 @@ static void retention_entries_join(void)
|
||||
pmu_sleep_disable_regdma_backup();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
sleep_clock_icg_retention_clock_config(&s_retention.retention_modules);
|
||||
#endif
|
||||
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
}
|
||||
|
||||
@@ -1160,9 +1169,9 @@ static esp_err_t passive_module_attach(sleep_retention_module_t module)
|
||||
assert(module_runtime_attach(instance(module)) && "Illegal dependency");
|
||||
assert(module_is_inited(module) && "All passive module must be inited first!");
|
||||
if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) {
|
||||
module_entries_move(module, &s_retention.context[1], &s_retention.retention);
|
||||
s_retention.attached_modules.bitmap[module >> 5] |= BIT(module % 32);
|
||||
s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32);
|
||||
module_entries_move(module, &s_retention.context[1], &s_retention.retention);
|
||||
err = module_action_wrapper(module, (BIT(31) | action(3)), passive_module_attach);
|
||||
}
|
||||
_lock_release_recursive(&s_retention.lock);
|
||||
@@ -1180,9 +1189,9 @@ esp_err_t sleep_retention_module_attach(sleep_retention_module_t module)
|
||||
if (!module_is_passive(instance(module))) {
|
||||
if (module_is_inited(module) && module_is_created(module) && !module_is_retained(module)) {
|
||||
if (module_runtime_attach(instance(module))) {
|
||||
module_entries_move(module, &s_retention.context[1], &s_retention.retention);
|
||||
s_retention.attached_modules.bitmap[module >> 5] |= BIT(module % 32);
|
||||
s_retention.retention_modules.bitmap[module >> 5] |= BIT(module % 32);
|
||||
module_entries_move(module, &s_retention.context[1], &s_retention.retention);
|
||||
err = module_action_wrapper(module, action(3), passive_module_attach);
|
||||
} else {
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
@@ -1208,9 +1217,9 @@ static esp_err_t passive_module_detach(sleep_retention_module_t module)
|
||||
assert(module_is_inited(module) && "All passive module must be inited first!");
|
||||
if (module_is_inited(module) && module_is_created(module) && module_is_retained(module)) {
|
||||
if (refarray_zero(instance(module), 1)) {
|
||||
module_entries_move(module, &s_retention.retention, &s_retention.context[1]);
|
||||
s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
s_retention.attached_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
module_entries_move(module, &s_retention.retention, &s_retention.context[1]);
|
||||
err = module_action_wrapper(module, (BIT(31) | action(4)), passive_module_detach);
|
||||
}
|
||||
}
|
||||
@@ -1229,9 +1238,9 @@ esp_err_t sleep_retention_module_detach(sleep_retention_module_t module)
|
||||
if (!module_is_passive(instance(module))) {
|
||||
if (module_is_inited(module) && module_is_created(module) && module_is_retained(module)) {
|
||||
if (module_runtime_attach(instance(module))) {
|
||||
module_entries_move(module, &s_retention.retention, &s_retention.context[1]);
|
||||
s_retention.retention_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
s_retention.attached_modules.bitmap[module >> 5] &= ~BIT(module % 32);
|
||||
module_entries_move(module, &s_retention.retention, &s_retention.context[1]);
|
||||
err = module_action_wrapper(module, action(4), passive_module_detach);
|
||||
} else {
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
|
||||
@@ -73,8 +73,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint32_t)1) << (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -72,8 +72,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint32_t)1) << (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -60,8 +60,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint32_t)1) << (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -69,8 +69,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint32_t)1) << (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1043,6 +1043,10 @@ config SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_FLASH_KEEP_POWER_IN_LSLP
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -71,8 +71,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint32_t)1) << (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -456,6 +456,7 @@
|
||||
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
|
||||
|
||||
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
|
||||
#define SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG (1)
|
||||
|
||||
#define SOC_PM_FLASH_KEEP_POWER_IN_LSLP (1) /*!<Keep flash on in light sleep to reduce wake latency*/
|
||||
|
||||
|
||||
@@ -1171,6 +1171,10 @@ config SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_MODEM_CLOCK_DOMAIN_ICG
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -72,8 +72,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint32_t)1) << (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -493,6 +493,7 @@
|
||||
// #define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE
|
||||
|
||||
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
|
||||
#define SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG (1)
|
||||
#define SOC_PM_SUPPORT_MODEM_CLOCK_DOMAIN_ICG (1)
|
||||
|
||||
#define SOC_PM_CPU_RETENTION_BY_SW (1)
|
||||
|
||||
@@ -68,8 +68,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint32_t)1) << (b))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1515,6 +1515,10 @@ config SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -107,8 +107,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint64_t pmu_sleep_clk_icg_flags_t;
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((pmu_sleep_clk_icg_flags_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_BIT(b) (((uint64_t)1) << (b))
|
||||
#define PMU_SLEEP_CLK_ICG_FUNC_LO(f) ((uint32_t)(f))
|
||||
#define PMU_SLEEP_CLK_ICG_FUNC_HI(f) ((uint32_t)((f) >> 32))
|
||||
|
||||
|
||||
@@ -561,6 +561,7 @@
|
||||
#define SOC_PM_SUPPORT_MODEM_CLOCK_DOMAIN_ICG (1)
|
||||
|
||||
#define SOC_PM_SUPPORT_PMU_CLK_ICG (1)
|
||||
#define SOC_PM_SUPPORT_PMU_RETENTION_CLK_ICG (1)
|
||||
|
||||
#define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*!<Supports CRC only the stub code in RTC memory */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user