diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 64dc1203ef..56ad26c2f8 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -35,7 +35,7 @@ if(NOT BOOTLOADER_BUILD) endif() if(CONFIG_SOC_PAU_SUPPORTED) - list(APPEND srcs "sleep_retention.c" "sleep_peripheral.c") + list(APPEND srcs "sleep_retention.c" "sleep_peripheral.c" "sleep_clock.c") endif() # [refactor-todo]: requires "driver" for GPIO and RTC (by sleep_gpio and sleep_modes) diff --git a/components/esp_hw_support/include/esp_private/sleep_clock.h b/components/esp_hw_support/include/esp_private/sleep_clock.h new file mode 100644 index 0000000000..5b204c1856 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/sleep_clock.h @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include +#include "sdkconfig.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sleep_clock.h + * + * This file contains declarations of digital peripheral clock retention related functions in light sleep mode. + */ + +/** + * @brief Whether to allow the TOP power domain to be powered off. + * + * In light sleep mode, only when the system can provide enough memory + * for digital peripheral clock retention, the TOP power domain can be + * powered off. + * + * @return True to allow power off + */ +bool clock_domain_pd_allowed(void); + +/** + * @brief PCR module power down initialize + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args + * No memory for the retention link + */ +esp_err_t sleep_clock_system_retention_init(void); + +/** + * @brief PCR module power down deinitialize + */ +void sleep_clock_system_retention_deinit(void); + +/** + * @brief Modem syscon module power down initialize + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on invalid sleep_retention_entries_create args + * No memory for the retention link + */ +esp_err_t sleep_clock_modem_retention_init(void); + +/** + * @brief Modem syscon module power down deinitialize + */ +void sleep_clock_modem_retention_deinit(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c new file mode 100644 index 0000000000..cc48d28b61 --- /dev/null +++ b/components/esp_hw_support/sleep_clock.c @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "sdkconfig.h" +#include "soc/soc_caps.h" + +#include "esp_err.h" +#include "esp_log.h" +#include "esp_attr.h" +#include "esp_check.h" +#include "esp_regdma.h" +#include "esp_private/startup_internal.h" +#include "esp_private/sleep_retention.h" +#include "esp_private/sleep_clock.h" + +#include "soc/pcr_reg.h" +#include "modem/modem_syscon_reg.h" + +static __attribute__((unused)) const char *TAG = "sleep_clock"; + +esp_err_t sleep_clock_system_retention_init(void) +{ + #define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_REG - DR_REG_PCR_BASE) / 4) + 1) + + const static sleep_retention_entries_config_t pcr_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, N_REGS_PCR(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* pcr */ + }; + + esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_1, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention"); + ESP_LOGI(TAG, "System Power, Clock and Reset sleep retention initialization"); + return ESP_OK; +} + +void sleep_clock_system_retention_deinit(void) +{ + sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM); +} + +esp_err_t sleep_clock_modem_retention_init(void) +{ + #define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1) + + const static sleep_retention_entries_config_t modem_regs_retention[] = { + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) } /* MODEM SYSCON */ + }; + + esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_2, SLEEP_RETENTION_MODULE_CLOCK_MODEM); + ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (SYSCON) retention"); + ESP_LOGI(TAG, "Modem Power, Clock and Reset sleep retention initialization"); + return ESP_OK; +} + +void sleep_clock_modem_retention_deinit(void) +{ + sleep_retention_entries_destroy(SLEEP_RETENTION_MODULE_CLOCK_MODEM); +} + +bool IRAM_ATTR clock_domain_pd_allowed(void) +{ + const uint32_t modules = sleep_retention_get_modules(); + const uint32_t mask = (const uint32_t) ( + SLEEP_RETENTION_MODULE_CLOCK_SYSTEM +#if CONFIG_MAC_BB_PD + | SLEEP_RETENTION_MODULE_CLOCK_MODEM +#endif + ); + return ((modules & mask) == mask); +} + +#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP || CONFIG_MAC_BB_PD +ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, BIT(0), 106) +{ + sleep_clock_system_retention_init(); +#if CONFIG_MAC_BB_PD + sleep_clock_modem_retention_init(); +#endif + return ESP_OK; +} +#endif diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index b41ef71469..e8454171af 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -19,6 +19,7 @@ # esp_sleep doesn't have init dependencies 105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0) 106: sleep_clock_startup_init in components/esp_hw_support/sleep_clock.c on BIT(0) +107: sleep_peripheral_startup_init in components/esp_hw_support/sleep_peripheral.c on BIT(0) # app_trace has to be initialized before systemview 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES