mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
Merge branch 'feat/support_s31_sleep_features' into 'master'
feat(esp_hw_support): support esp32s31 lowpower features Closes IDF-5660, IDF-14643, IDF-14645, IDF-14647, IDF-14648, IDF-14784, PM-708, and PM-714 See merge request espressif/esp-idf!47216
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "soc/rtc_wdt_reg.h"
|
||||
#include "hal/rwdt_ll.h"
|
||||
#endif
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "soc/pmu_reg.h"
|
||||
#include "hal/regi2c_ctrl_ll.h"
|
||||
#include "hal/modem_lpcon_ll.h"
|
||||
@@ -35,8 +36,13 @@ ESP_LOG_ATTR_TAG(TAG, "boot.esp32s31");
|
||||
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
/* Disable RF pll by default */
|
||||
REG_SET_FIELD(PMU_RF_PWC_REG, PMU_XPD_RF_CIRCUIT, 0xFFFF);
|
||||
/* GPIO 41 is not bonded out to the package, Isolate it to suppress
|
||||
* floating leakage.*/
|
||||
gpio_ll_input_disable(&GPIO, 41);
|
||||
gpio_ll_output_disable(&GPIO, 41);
|
||||
gpio_ll_pullup_dis(&GPIO, 41);
|
||||
gpio_ll_pulldown_dis(&GPIO, 41);
|
||||
gpio_ll_func_sel(&GPIO, 41, PIN_FUNC_GPIO);
|
||||
|
||||
modem_lpcon_ll_enable_bus_clock(true);
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "gdma_priv.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#define GDMA_INVALID_PERIPH_TRIG (0x3F)
|
||||
#define SEARCH_REQUEST_RX_CHANNEL (1 << 0)
|
||||
@@ -87,11 +88,15 @@ static esp_err_t do_allocate_gdma_channel(const gdma_channel_search_info_t *sear
|
||||
TAG, "invalid interrupt priority:%d", config->intr_priority);
|
||||
}
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
// retention module is per GDMA pair, before we allocate the pair object, some common registers are already configured in "hal_init"
|
||||
// if a light sleep happens and powers off the gdma module, those registers will get lost
|
||||
// to work around it, we can acquire a power lock first, before any register configuration
|
||||
sleep_retention_power_lock_acquire();
|
||||
#else
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15640
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Determine search code based on which channels are requested
|
||||
@@ -237,8 +242,12 @@ err:
|
||||
free(alloc_rx_channel);
|
||||
}
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
sleep_retention_power_lock_release();
|
||||
#else
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_AUTO); //IDF-15640
|
||||
#endif
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@@ -874,9 +883,13 @@ static esp_err_t gdma_del_tx_channel(gdma_channel_t *dma_channel)
|
||||
free(tx_chan);
|
||||
ESP_LOGV(TAG, "del tx channel (%d,%d)", group_id, pair_id);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
// release sleep retention lock
|
||||
gdma_release_sleep_retention(pair);
|
||||
#else
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_AUTO); //IDF-15640
|
||||
#endif
|
||||
#endif
|
||||
// release pair handle (will free pair if both channels are deleted)
|
||||
gdma_try_free_pair_handle(pair);
|
||||
@@ -909,9 +922,13 @@ static esp_err_t gdma_del_rx_channel(gdma_channel_t *dma_channel)
|
||||
free(rx_chan);
|
||||
ESP_LOGV(TAG, "del rx channel (%d,%d)", group_id, pair_id);
|
||||
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
#if SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
// release sleep retention lock
|
||||
gdma_release_sleep_retention(pair);
|
||||
#else
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_AUTO); //IDF-15640
|
||||
#endif
|
||||
#endif
|
||||
// release pair handle (will free pair if both channels are deleted)
|
||||
gdma_try_free_pair_handle(pair);
|
||||
|
||||
@@ -1143,9 +1143,9 @@ esp_err_t gpio_dump_io_configuration(FILE *out_stream, uint64_t io_bit_mask)
|
||||
fprintf(out_stream, "IO[%"PRIu32"]%s -\n", gpio_num, esp_gpio_is_reserved(BIT64(gpio_num)) ? " **RESERVED**" : "");
|
||||
fprintf(out_stream, " Pullup: %d, Pulldown: %d, DriveCap: %"PRIu32"\n", io_config.pu, io_config.pd, (uint32_t)io_config.drv);
|
||||
fprintf(out_stream, " InputEn: %d, OutputEn: %s%s, OpenDrain: %d\n", io_config.ie, oe_str, ((io_config.fun_sel == PIN_FUNC_GPIO) && (io_config.oe_inv)) ? " (inversed)" : "", io_config.od);
|
||||
fprintf(out_stream, " FuncSel: %"PRIu32" (%s)\n", io_config.fun_sel, (io_config.fun_sel == PIN_FUNC_GPIO) ? "GPIO" : "IOMUX");
|
||||
fprintf(out_stream, " FuncSel: %"PRIu32" (%s)\n", (uint32_t)io_config.fun_sel, (io_config.fun_sel == PIN_FUNC_GPIO) ? "GPIO" : "IOMUX");
|
||||
if (io_config.fun_sel == PIN_FUNC_GPIO) {
|
||||
fprintf(out_stream, " GPIO Matrix SigOut ID: %"PRIu32"%s\n", io_config.sig_out, (io_config.sig_out == SIG_GPIO_OUT_IDX) ? " (simple GPIO output)" : "");
|
||||
fprintf(out_stream, " GPIO Matrix SigOut ID: %"PRIu32"%s\n", (uint32_t)io_config.sig_out, (io_config.sig_out == SIG_GPIO_OUT_IDX) ? " (simple GPIO output)" : "");
|
||||
}
|
||||
if (io_config.ie && io_config.fun_sel == PIN_FUNC_GPIO) {
|
||||
uint32_t cnt = 0;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "driver/gptimer.h"
|
||||
#include "gptimer_priv.h"
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
static void gptimer_default_isr(void *args);
|
||||
|
||||
@@ -155,6 +156,10 @@ esp_err_t gptimer_new_timer(const gptimer_config_t *config, gptimer_handle_t *re
|
||||
#if GPTIMER_USE_RETENTION_LINK
|
||||
gptimer_create_retention_module(timer);
|
||||
#endif // GPTIMER_USE_RETENTION_LINK
|
||||
} else {
|
||||
#if !SOC_TIMER_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15641
|
||||
#endif
|
||||
}
|
||||
|
||||
// initialize HAL layer
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "hal/i2c_ll.h"
|
||||
#include "hal/i2c_periph.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "i2c_private.h"
|
||||
|
||||
static const char *TAG = "i2c.master";
|
||||
@@ -1045,6 +1046,9 @@ esp_err_t i2c_new_master_bus(const i2c_master_bus_config_t *bus_config, i2c_mast
|
||||
|
||||
#if !SOC_I2C_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(bus_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15642
|
||||
#endif
|
||||
#endif // SOC_I2C_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
i2c_master = heap_caps_calloc(1, sizeof(i2c_master_bus_t) + 20 * sizeof(i2c_transaction_t), I2C_MEM_ALLOC_CAPS);
|
||||
|
||||
@@ -43,8 +43,8 @@ static void s_test_i2s_enter_light_sleep(int sec, bool allow_power_down)
|
||||
printf("Woke up from light sleep\n");
|
||||
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
#if SOC_HAS(PAU)
|
||||
// check if the power domain also is powered down
|
||||
#if SOC_HAS(PAU) && SOC_GDMA_SUPPORT_SLEEP_RETENTION
|
||||
// check if the power domain also is powered down (if GDMA retention is not supported, TOP pd will be rejected)
|
||||
TEST_ASSERT_EQUAL(allow_power_down ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
|
||||
#endif
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
extern const uint8_t image_esp1080_jpg_start[] asm("_binary_esp1080_jpg_start");
|
||||
extern const uint8_t image_esp1080_jpg_end[] asm("_binary_esp1080_jpg_end");
|
||||
|
||||
#define JPEG_SLEEP_RETENTION_TIMEOUT_MS 50
|
||||
|
||||
#if SOC_LIGHT_SLEEP_SUPPORTED && CONFIG_PM_ENABLE
|
||||
static void test_jpeg_sleep_retention(bool allow_pd)
|
||||
{
|
||||
@@ -33,7 +35,7 @@ static void test_jpeg_sleep_retention(bool allow_pd)
|
||||
|
||||
jpeg_decode_engine_cfg_t decode_eng_cfg = {
|
||||
.intr_priority = 0,
|
||||
.timeout_ms = 40,
|
||||
.timeout_ms = JPEG_SLEEP_RETENTION_TIMEOUT_MS,
|
||||
.flags = {
|
||||
.allow_pd = allow_pd,
|
||||
},
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "hal/ledc_hal.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_private/gpio.h"
|
||||
@@ -877,6 +878,9 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf)
|
||||
LEDC_ARG_CHECK(ledc_conf->sleep_mode < LEDC_SLEEP_MODE_INVALID, "sleep_mode");
|
||||
#if !SOC_LEDC_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(ledc_conf->sleep_mode != LEDC_SLEEP_MODE_NO_ALIVE_ALLOW_PD, ESP_ERR_NOT_SUPPORTED, LEDC_TAG, "register back up is not supported");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15643
|
||||
#endif
|
||||
#endif
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "esp_memory_utils.h"
|
||||
#include "driver/mcpwm_cap.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/gpio.h"
|
||||
|
||||
static void mcpwm_capture_default_isr(void *args);
|
||||
@@ -73,6 +74,9 @@ esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mc
|
||||
|
||||
#if !SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15644
|
||||
#endif
|
||||
#endif // SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
cap_timer = heap_caps_calloc(1, sizeof(mcpwm_cap_timer_t), MCPWM_MEM_ALLOC_CAPS);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "esp_memory_utils.h"
|
||||
#include "hal/mcpwm_ll.h"
|
||||
#include "driver/mcpwm_timer.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/mcpwm.h"
|
||||
|
||||
static void mcpwm_timer_default_isr(void *args);
|
||||
@@ -83,6 +84,9 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
|
||||
|
||||
#if !SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15644
|
||||
#endif
|
||||
#endif // SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
timer = heap_caps_calloc(1, sizeof(mcpwm_timer_t), MCPWM_MEM_ALLOC_CAPS);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/parlio_rx.h"
|
||||
#include "parlio_priv.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
@@ -614,6 +615,9 @@ esp_err_t parlio_new_rx_unit(const parlio_rx_unit_config_t *config, parlio_rx_un
|
||||
|
||||
#if !SOC_PARLIO_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15645
|
||||
#endif
|
||||
#endif // SOC_PARLIO_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
/* Allocate unit memory */
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/parlio_tx.h"
|
||||
#include "parlio_priv.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#if SOC_PARLIO_TX_SUPPORT_LOOP_TRANSMISSION
|
||||
static bool parlio_tx_gdma_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
|
||||
@@ -273,6 +274,9 @@ esp_err_t parlio_new_tx_unit(const parlio_tx_unit_config_t *config, parlio_tx_un
|
||||
|
||||
#if !SOC_PARLIO_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15645
|
||||
#endif
|
||||
#endif // SOC_PARLIO_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// allocate unit from internal memory because it contains atomic member
|
||||
|
||||
@@ -125,7 +125,7 @@ static void test_pcnt_sleep_retention(void)
|
||||
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
|
||||
TEST_ASSERT_EQUAL(20, count_value);
|
||||
// check the register value
|
||||
reg_value = pcnt_ll_get_count(&PCNT, i);
|
||||
reg_value = pcnt_ll_get_count(PCNT_LL_GET_HW(unit_config.group_id), i);
|
||||
TEST_ASSERT_EQUAL(20, reg_value);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/rmt_rx.h"
|
||||
#include "rmt_private.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
static esp_err_t rmt_del_rx_channel(rmt_channel_handle_t channel);
|
||||
static esp_err_t rmt_rx_demodulate_carrier(rmt_channel_handle_t channel, const rmt_carrier_config_t *config);
|
||||
@@ -206,6 +207,9 @@ esp_err_t rmt_new_rx_channel(const rmt_rx_channel_config_t *config, rmt_channel_
|
||||
|
||||
#if !SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15646
|
||||
#endif
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// allocate channel memory from internal memory because it contains atomic variable
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/rmt_tx.h"
|
||||
#include "rmt_private.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
struct rmt_sync_manager_t {
|
||||
rmt_group_t *group; // which group the synchro belongs to
|
||||
@@ -273,6 +274,9 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_
|
||||
|
||||
#if !SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15646
|
||||
#endif
|
||||
#endif // SOC_RMT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// allocate channel memory from internal memory because it contains atomic variable
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_clk_tree.h"
|
||||
@@ -276,6 +277,9 @@ esp_err_t sdm_new_channel(const sdm_config_t *config, sdm_channel_handle_t *ret_
|
||||
[[maybe_unused]] bool allow_pd = config->flags.allow_pd == 1;
|
||||
#if !SOC_SDM_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(allow_pd == false, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15647
|
||||
#endif
|
||||
#endif // SOC_SDM_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// allocate channel memory from internal memory because it contains atomic variable
|
||||
|
||||
@@ -966,7 +966,7 @@ TEST_CASE("test_spi_slave_hd_sleep_retention", "[spi]")
|
||||
printf("Waked up!\n");
|
||||
// check if the sleep happened as expected
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && SOC_GDMA_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
// check if the power domain also is powered down
|
||||
TEST_ASSERT_EQUAL((bus_cfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
|
||||
#endif
|
||||
@@ -1044,7 +1044,7 @@ TEST_CASE("test_spi_slave_hd_append_sleep_retention", "[spi]")
|
||||
printf("Waked up!\n");
|
||||
// check if the sleep happened as expected
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
#if SOC_SPI_SUPPORT_SLEEP_RETENTION && SOC_GDMA_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
|
||||
// check if the power domain also is powered down
|
||||
TEST_ASSERT_EQUAL((bus_cfg.flags & SPICOMMON_BUSFLAG_SLP_ALLOW_PD) ? PMU_SLEEP_PD_TOP : 0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
|
||||
#endif
|
||||
|
||||
@@ -145,6 +145,9 @@ esp_err_t temperature_sensor_install(const temperature_sensor_config_t *tsens_co
|
||||
|
||||
#if !SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(tsens_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15648
|
||||
#endif
|
||||
#endif // SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
#if SOC_TEMPERATURE_SENSOR_SUPPORT_SLEEP_RETENTION && !SOC_TEMPERATURE_SENSOR_UNDER_PD_TOP_DOMAIN
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "twai_private.h"
|
||||
#include "hal/twai_periph.h"
|
||||
#include "hal/twai_hal.h"
|
||||
#include "esp_sleep.h"
|
||||
#if SOC_HAS(TWAI_FD)
|
||||
#include "hal/twaifd_ll.h"
|
||||
#endif
|
||||
@@ -664,6 +665,9 @@ esp_err_t twai_new_node_onchip(const twai_onchip_node_config_t *node_config, twa
|
||||
ESP_RETURN_ON_FALSE(!node_config->intr_priority || (BIT(node_config->intr_priority) & ESP_INTR_FLAG_LOWMED), ESP_ERR_INVALID_ARG, TAG, "Invalid intr_priority level");
|
||||
#if !SOC_TWAI_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(!node_config->flags.sleep_allow_pd, ESP_ERR_NOT_SUPPORTED, TAG, "sleep retention is not supported on this target");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15649
|
||||
#endif
|
||||
#endif
|
||||
// Allocate TWAI node from internal memory because it contains atomic variable
|
||||
twai_onchip_ctx_t *node = heap_caps_calloc(1, sizeof(twai_onchip_ctx_t) + twai_hal_get_mem_requirment(), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "esp_private/gpio.h"
|
||||
#include "esp_private/esp_gpio_reserve.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
@@ -1067,6 +1068,9 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
|
||||
bool allow_pd __attribute__((unused)) = (uart_config->flags.allow_pd || uart_config->flags.backup_before_sleep);
|
||||
#if !SOC_UART_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(allow_pd == 0, ESP_ERR_NOT_SUPPORTED, UART_TAG, "not able to power down in light sleep");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15650
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uart_module_enable(uart_num);
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32C61
|
||||
#define DEFAULT_UART1_TX_IO_NUM GPIO_NUM_4
|
||||
#define DEFAULT_UART1_RX_IO_NUM GPIO_NUM_5
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32S31
|
||||
#define DEFAULT_UART1_TX_IO_NUM GPIO_NUM_2
|
||||
#define DEFAULT_UART1_RX_IO_NUM GPIO_NUM_3
|
||||
#elif CONFIG_IDF_TARGET_ESP32H21
|
||||
|
||||
@@ -55,11 +55,11 @@ TEST_CASE("uart restored correctly after auto light sleep", "[uart][hp-uart-only
|
||||
// Ensure UART is fully idle before starting loopback RX/TX test
|
||||
TEST_ESP_OK(uart_wait_tx_done(uart_num, portMAX_DELAY));
|
||||
vTaskDelay(pdMS_TO_TICKS(20)); // make sure last byte has flushed from TX FIFO
|
||||
TEST_ESP_OK(uart_flush_input(uart_num));
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
char tx_data[20] = {0};
|
||||
char rx_data[20] = {0};
|
||||
TEST_ESP_OK(uart_flush_input(uart_num));
|
||||
int len = sprintf(tx_data, "Hello World %d!\n", i);
|
||||
uart_write_bytes(uart_num, tx_data, len);
|
||||
int size = 0;
|
||||
@@ -97,6 +97,7 @@ TEST_CASE("uart restored correctly after manually enter light sleep", "[uart][hp
|
||||
for (int i = 0; i < 5; i++) {
|
||||
char tx_data[20] = {0};
|
||||
char rx_data[20] = {0};
|
||||
TEST_ESP_OK(uart_flush_input(uart_num));
|
||||
int len = sprintf(tx_data, "Hello World %d!\n", i);
|
||||
uart_write_bytes(uart_num, tx_data, len);
|
||||
int size = uart_read_bytes(uart_num, rx_data, len, pdMS_TO_TICKS(20));
|
||||
|
||||
38
components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h
Normal file
38
components/esp_hal_clock/esp32s31/include/hal/clk_gate_ll.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/reset_reasons.h"
|
||||
#include "soc/lp_clkrst_struct.h"
|
||||
#include "soc/lp_clkrst_reg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Enable or disable the clock gate for rtc fast to lp periph
|
||||
* @param enable Enable / disable
|
||||
*/
|
||||
FORCE_INLINE_ATTR void _clk_gate_ll_rtc_fast_to_lp_periph_en(bool enable)
|
||||
{
|
||||
LP_CLKRST.root_clk_conf.fosc_clk_force_on = enable;
|
||||
}
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define clk_gate_ll_rtc_fast_to_lp_periph_en(...) do { \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||
_clk_gate_ll_rtc_fast_to_lp_periph_en(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -153,6 +153,7 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_enable(void)
|
||||
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_GLOBAL_MPLL_ICG) ;
|
||||
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_HIGH_XPD_MPLL | PMU_TIE_HIGH_XPD_MPLL_I2C);
|
||||
SET_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_MPLL_500M_CLK_EN);
|
||||
SET_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_MPLL_I2C | PMU_HP_ACTIVE_XPD_MPLL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,6 +164,7 @@ static inline __attribute__((always_inline)) void clk_ll_mpll_disable(void)
|
||||
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_GLOBAL_MPLL_ICG) ;
|
||||
SET_PERI_REG_MASK(PMU_IMM_HP_CK_POWER_1_REG, PMU_TIE_LOW_XPD_MPLL | PMU_TIE_LOW_XPD_MPLL_I2C);
|
||||
CLEAR_PERI_REG_MASK(HP_ALIVE_SYS_HP_CLK_CTRL_REG, HP_ALIVE_SYS_HP_MPLL_500M_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_CK_POWER_REG, PMU_HP_ACTIVE_XPD_MPLL_I2C | PMU_HP_ACTIVE_XPD_MPLL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,6 +57,7 @@ extern "C" {
|
||||
* @param gpio_num GPIO number
|
||||
* @param[out] io_config Pointer to the structure that saves the specific IO configuration
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio_io_config_t *io_config)
|
||||
{
|
||||
uint32_t bit_shift = (gpio_num < 32) ? gpio_num : (gpio_num - 32);
|
||||
@@ -74,6 +75,79 @@ static inline void gpio_ll_get_io_config(gpio_dev_t *hw, uint32_t gpio_num, gpio
|
||||
io_config->slp_sel = IO_MUX.gpio[gpio_num].slp_sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 64-bit mask of all digital GPIOs that are currently held.
|
||||
* Reads the two hold control registers once, avoiding per-pin register access.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address (unused, hold regs are in LP_SYS).
|
||||
* @return Bitmask where bit N is set if GPIO N is held. Only digital IO bits are meaningful.
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline uint64_t gpio_ll_get_digital_gpio_hold_mask(gpio_dev_t *hw)
|
||||
{
|
||||
(void)hw;
|
||||
uint32_t hold0 = LP_SYS.hp_gpio_o_hold_ctrl0.hp_gpio_0_hold_ctrl0;
|
||||
uint32_t hold1 = LP_SYS.hp_gpio_o_hold_ctrl1.hp_gpio_0_hold_ctrl1;
|
||||
return ((uint64_t)hold0 << SOC_RTCIO_PIN_COUNT) |
|
||||
((uint64_t)hold1 << (32 + SOC_RTCIO_PIN_COUNT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Backup IOMUX pad configuration for sleep isolate.
|
||||
* Only fills pu, pd, ie, fun_sel in io_config from a single IOMUX register read.
|
||||
*
|
||||
* @param gpio_num GPIO number
|
||||
* @param[out] io_config Pointer to the IO configuration structure
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void gpio_ll_backup_pad_config_for_sleep_isolate(uint32_t gpio_num, gpio_io_config_t *io_config)
|
||||
{
|
||||
uint32_t iomux_reg_val = IO_MUX.gpio[gpio_num].val;
|
||||
io_config->pu = (iomux_reg_val & FUN_PU_M) >> FUN_PU_S;
|
||||
io_config->pd = (iomux_reg_val & FUN_PD_M) >> FUN_PD_S;
|
||||
io_config->ie = (iomux_reg_val & FUN_IE_M) >> FUN_IE_S;
|
||||
io_config->fun_sel = (iomux_reg_val & MCU_SEL_M) >> MCU_SEL_S;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set pad configuration for sleep isolate with minimal register writes.
|
||||
* Reads pu, pd, ie, oe, fun_sel from io_config and writes them to hardware registers
|
||||
* in a single IOMUX read-modify-write plus one GPIO enable write.
|
||||
*
|
||||
* @param gpio_num GPIO number
|
||||
* @param io_config Pointer to the IO configuration structure
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void gpio_ll_set_pad_config_for_sleep_isolate(uint32_t gpio_num, gpio_io_config_t *io_config)
|
||||
{
|
||||
uint32_t iomux_reg_val = IO_MUX.gpio[gpio_num].val;
|
||||
iomux_reg_val &= ~(FUN_PU_M | FUN_PD_M | FUN_IE_M | MCU_SEL_M);
|
||||
if (io_config->pu) {
|
||||
iomux_reg_val |= FUN_PU_M;
|
||||
}
|
||||
if (io_config->pd) {
|
||||
iomux_reg_val |= FUN_PD_M;
|
||||
}
|
||||
if (io_config->ie) {
|
||||
iomux_reg_val |= FUN_IE_M;
|
||||
}
|
||||
iomux_reg_val |= (io_config->fun_sel << MCU_SEL_S) & MCU_SEL_M;
|
||||
IO_MUX.gpio[gpio_num].val = iomux_reg_val;
|
||||
if (io_config->oe) {
|
||||
if (gpio_num < 32) {
|
||||
GPIO.enable_w1ts.enable_w1ts = (0x1 << gpio_num);
|
||||
} else {
|
||||
GPIO.enable1_w1ts.enable1_w1ts = (0x1 << (gpio_num - 32));
|
||||
}
|
||||
} else {
|
||||
if (gpio_num < 32) {
|
||||
GPIO.enable_w1tc.enable_w1tc = (0x1 << gpio_num);
|
||||
} else {
|
||||
GPIO.enable1_w1tc.enable1_w1tc = (0x1 << (gpio_num - 32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable pull-up on GPIO.
|
||||
*
|
||||
@@ -354,6 +428,23 @@ static inline void gpio_ll_output_enable(gpio_dev_t *hw, uint32_t gpio_num)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if GPIO output is enabled.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
* @return true if output is enabled, false otherwise
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline bool gpio_ll_output_is_enabled(gpio_dev_t *hw, uint32_t gpio_num)
|
||||
{
|
||||
if (gpio_num < 32) {
|
||||
return (hw->enable.val >> gpio_num) & 0x1;
|
||||
} else {
|
||||
return (hw->enable1.val >> (gpio_num - 32)) & 0x1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable open-drain mode on GPIO.
|
||||
*
|
||||
|
||||
@@ -157,17 +157,17 @@ typedef enum {
|
||||
* @brief Structure that contains the configuration of an IO
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t fun_sel; /*!< Value of IOMUX function selection */
|
||||
uint32_t sig_out; /*!< Index of the outputting peripheral signal */
|
||||
gpio_drive_cap_t drv; /*!< Value of drive strength */
|
||||
bool pu; /*!< Status of pull-up enabled or not */
|
||||
bool pd; /*!< Status of pull-down enabled or not */
|
||||
bool ie; /*!< Status of input enabled or not */
|
||||
bool oe; /*!< Status of output enabled or not */
|
||||
bool oe_ctrl_by_periph; /*!< True if use output enable signal from peripheral, otherwise False */
|
||||
bool oe_inv; /*!< Whether the output enable signal is inversed or not */
|
||||
bool od; /*!< Status of open-drain enabled or not */
|
||||
bool slp_sel; /*!< Status of pin sleep mode enabled or not */
|
||||
gpio_drive_cap_t drv; /*!< Value of drive strength */
|
||||
uint32_t fun_sel : 8; /*!< Value of IOMUX function selection */
|
||||
uint32_t sig_out : 16;/*!< Index of the outputting peripheral signal */
|
||||
uint32_t pu : 1; /*!< Status of pull-up enabled or not */
|
||||
uint32_t pd : 1; /*!< Status of pull-down enabled or not */
|
||||
uint32_t ie : 1; /*!< Status of input enabled or not */
|
||||
uint32_t oe : 1; /*!< Status of output enabled or not */
|
||||
uint32_t oe_ctrl_by_periph : 1; /*!< True if use output enable signal from peripheral, otherwise False */
|
||||
uint32_t oe_inv : 1; /*!< Whether the output enable signal is inversed or not */
|
||||
uint32_t od : 1; /*!< Status of open-drain enabled or not */
|
||||
uint32_t slp_sel : 1; /*!< Status of pin sleep mode enabled or not */
|
||||
} gpio_io_config_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
// On S31, SPI pins defined here are all wrong. these pins are individual pins, don't use normal GPIO pins anymore.
|
||||
#define GPIO_NUM_INVALID -1
|
||||
#define MSPI_IOMUX_PIN_NUM_CS1 GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_HD GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_WP GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_CS0 GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_CLK GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_MISO GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_MOSI GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_HD 30
|
||||
#define MSPI_IOMUX_PIN_NUM_WP 28
|
||||
#define MSPI_IOMUX_PIN_NUM_CS0 26
|
||||
#define MSPI_IOMUX_PIN_NUM_CLK 31
|
||||
#define MSPI_IOMUX_PIN_NUM_MISO 27
|
||||
#define MSPI_IOMUX_PIN_NUM_MOSI 32
|
||||
#define MSPI_IOMUX_PIN_NUM_D4 GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_D5 GPIO_NUM_INVALID
|
||||
#define MSPI_IOMUX_PIN_NUM_D6 GPIO_NUM_INVALID
|
||||
|
||||
@@ -802,7 +802,7 @@ static inline void mspi_ll_unhold_all_flash_pins(void)
|
||||
* Sets all PSRAM pins (pin_group0, dqs0, pin_group1, dqs1) to hold status
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void mspi_ll_hold_all_psram_pins(void)
|
||||
static inline void mspi_ll_psram_hold_all_pins(void)
|
||||
{
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 // Only rev3+ chips support mspi pad holding.
|
||||
LP_SYS.ded_pad_rtc_hold_ctrl.ded_pad_rtc_hold_ctrl |= 0x3FFFFC0;
|
||||
@@ -814,7 +814,7 @@ static inline void mspi_ll_hold_all_psram_pins(void)
|
||||
* Releases hold status for all PSRAM pins (pin_group0, dqs0, pin_group1, dqs1)
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void mspi_ll_unhold_all_psram_pins(void)
|
||||
static inline void mspi_ll_psram_unhold_all_pins(void)
|
||||
{
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300 // Only rev3+ chips support mspi pad holding.
|
||||
LP_SYS.ded_pad_rtc_hold_ctrl.ded_pad_rtc_hold_ctrl &= ~0x3FFFFC0;
|
||||
|
||||
@@ -304,6 +304,46 @@ static inline void mspi_ll_psram_enable_axi_access(uint8_t spi_num, bool enable)
|
||||
SPIMEM2.mem_cache_fctrl.close_axi_inf_en = !enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hold all PSRAM pins
|
||||
* Sets all PSRAM pins (pin_group0, dqs0, pin_group1, dqs1) to hold status
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void mspi_ll_psram_hold_all_pins(void)
|
||||
{
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[0].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[1].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[2].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[3].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[4].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[5].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[6].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[7].reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.dqs0.reg_psram_dqs_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_clk.reg_psram_pin_hold = 1;
|
||||
MSPI_IOMUX.psram_pin_group.pin_cs.reg_psram_pin_hold = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unhold all PSRAM pins
|
||||
* Releases hold status for all PSRAM pins (pin_group0, dqs0, pin_group1, dqs1)
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline void mspi_ll_psram_unhold_all_pins(void)
|
||||
{
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[0].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[1].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[2].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[3].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[4].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[5].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[6].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_group0[7].reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.dqs0.reg_psram_dqs_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_clk.reg_psram_pin_hold = 0;
|
||||
MSPI_IOMUX.psram_pin_group.pin_cs.reg_psram_pin_hold = 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -514,6 +514,25 @@ FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_up(pmu_dev_t *hw, uint32_t fpu
|
||||
hw->power.mem_cntl.force_hp_mem_pu = fpu;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_on_mask(pmu_dev_t *hw, uint32_t mem_mask)
|
||||
{
|
||||
hw->power.mem_mask.mem0_mask = (mem_mask & BIT(0)) ? 0x1F : 0;
|
||||
hw->power.mem_mask.mem1_mask = (mem_mask & BIT(1)) ? 0x1F : 0;
|
||||
hw->power.mem_mask.mem2_mask = (mem_mask & BIT(2)) ? 0x1F : 0;
|
||||
if (mem_mask & BIT(3)) {
|
||||
hw->power.mem_cntl.force_hp_mem_pu |= (mem_mask & BIT(3));
|
||||
} else {
|
||||
hw->power.mem_cntl.force_hp_mem_pu &= ~(mem_mask & BIT(3));
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_off_mask(pmu_dev_t *hw, uint32_t mem0_pd_mask, uint32_t mem1_pd_mask, uint32_t mem2_pd_mask)
|
||||
{
|
||||
hw->power.mem_mask.mem0_pd_mask = mem0_pd_mask;
|
||||
hw->power.mem_mask.mem1_pd_mask = mem1_pd_mask;
|
||||
hw->power.mem_mask.mem2_pd_mask = mem2_pd_mask;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_enable(pmu_dev_t *hw)
|
||||
{
|
||||
hw->wakeup.cntl0.sleep_req = 1;
|
||||
@@ -755,12 +774,17 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_get_sysclk_sleep_select_state(pmu_dev_t *hw)
|
||||
return hw->clk_state0.sysclk_slp_sel;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void pmu_ll_set_rf_power_control(pmu_dev_t *hw, uint16_t val)
|
||||
{
|
||||
hw->hp_ext.rf_pwc.xpd_rf_circuit = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get ext1 wakeup source status
|
||||
* @return The lower 8 bits of the returned value are the bitmap of
|
||||
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
|
||||
*/
|
||||
static inline uint32_t pmu_ll_ext1_get_wakeup_status(void)
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_ext1_get_wakeup_status(void)
|
||||
{
|
||||
return REG_GET_FIELD(PMU_EXT_WAKEUP_ST_REG, PMU_EXT_WAKEUP_STATUS);
|
||||
}
|
||||
@@ -768,9 +792,10 @@ static inline uint32_t pmu_ll_ext1_get_wakeup_status(void)
|
||||
/**
|
||||
* @brief Clear the ext1 wakeup source status
|
||||
*/
|
||||
static inline void pmu_ll_ext1_clear_wakeup_status(void)
|
||||
FORCE_INLINE_ATTR void pmu_ll_ext1_clear_wakeup_status(void)
|
||||
{
|
||||
REG_SET_BIT(PMU_EXT_WAKEUP_CNTL_REG, PMU_EXT_WAKEUP_STATUS_CLR);
|
||||
REG_CLR_BIT(PMU_EXT_WAKEUP_CNTL_REG, PMU_EXT_WAKEUP_STATUS_CLR);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,7 +804,7 @@ static inline void pmu_ll_ext1_clear_wakeup_status(void)
|
||||
* @param level_mask 0: Wake the chip when all selected GPIOs go low
|
||||
* 1: Wake the chip when any of the selected GPIOs go high
|
||||
*/
|
||||
static inline void pmu_ll_ext1_set_wakeup_pins(uint32_t io_mask, int level_mask)
|
||||
FORCE_INLINE_ATTR void pmu_ll_ext1_set_wakeup_pins(uint32_t io_mask, int level_mask)
|
||||
{
|
||||
REG_SET_FIELD(PMU_EXT_WAKEUP_SEL_REG, PMU_EXT_WAKEUP_SEL, io_mask);
|
||||
REG_SET_FIELD(PMU_EXT_WAKEUP_LV_REG, PMU_EXT_WAKEUP_LV, level_mask);
|
||||
@@ -788,7 +813,7 @@ static inline void pmu_ll_ext1_set_wakeup_pins(uint32_t io_mask, int level_mask
|
||||
/**
|
||||
* @brief Clear all ext1 wakup-source setting
|
||||
*/
|
||||
static inline void pmu_ll_ext1_clear_wakeup_pins(void)
|
||||
FORCE_INLINE_ATTR void pmu_ll_ext1_clear_wakeup_pins(void)
|
||||
{
|
||||
REG_SET_FIELD(PMU_EXT_WAKEUP_SEL_REG, PMU_EXT_WAKEUP_SEL, 0);
|
||||
}
|
||||
@@ -798,7 +823,7 @@ static inline void pmu_ll_ext1_clear_wakeup_pins(void)
|
||||
* @return The lower 8 bits of the returned value are the bitmap of
|
||||
* the wakeup source status, bit 0~7 corresponds to LP_IO 0~7
|
||||
*/
|
||||
static inline uint32_t pmu_ll_ext1_get_wakeup_pins(void)
|
||||
FORCE_INLINE_ATTR uint32_t pmu_ll_ext1_get_wakeup_pins(void)
|
||||
{
|
||||
return REG_GET_FIELD(PMU_EXT_WAKEUP_SEL_REG, PMU_EXT_WAKEUP_SEL);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ if(NOT non_os_build)
|
||||
endif()
|
||||
if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED)
|
||||
list(APPEND srcs "sleep_modem.c"
|
||||
"sleep_cache.c"
|
||||
"sleep_modes.c"
|
||||
"sleep_uart.c"
|
||||
"sleep_console.c"
|
||||
|
||||
@@ -82,7 +82,7 @@ menu "Hardware Settings"
|
||||
select PM_SLP_IRAM_OPT
|
||||
select ESP_PERIPH_CTRL_FUNC_IN_IRAM
|
||||
select ESP_REGI2C_CTRL_FUNC_IN_IRAM
|
||||
depends on !SPIRAM || ESP_LDO_RESERVE_PSRAM
|
||||
depends on !SPIRAM || ESP_LDO_RESERVE_PSRAM || SOC_PSRAM_HAS_DEDICATED_LDO
|
||||
depends on !(IDF_TARGET_ESP32P4 && (ESP32P4_REV_MIN_FULL < 100))
|
||||
default n
|
||||
help
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "freertos/task.h"
|
||||
#include "hal/etm_periph.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_etm.h"
|
||||
@@ -246,6 +247,9 @@ esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_ch
|
||||
[[maybe_unused]] bool allow_pd = config->flags.allow_pd == 1;
|
||||
#if !SOC_ETM_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "not able to power down in light sleep");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15651
|
||||
#endif
|
||||
#endif // SOC_ETM_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// allocate channel memory from internal memory because it contains atomic variable
|
||||
|
||||
@@ -123,8 +123,8 @@ typedef enum {
|
||||
#define RTC_USB_TRIG_EN PMU_USB_WAKEUP_EN
|
||||
|
||||
#if SOC_LP_CORE_SUPPORTED
|
||||
#define RTC_LP_CORE_TRIG_EN PMU_LP_CORE_WAKEUP_EN //!< LP core wakeup
|
||||
#define RTC_LP_CORE_TRAP_TRIG_EN PMU_LP_CORE_TRAP_WAKEUP_EN //!< LP core trap (exception) wakeup
|
||||
#define RTC_LP_CORE_TRIG_EN PMU_LP_CORE_WAKEUP_HP_EN //!< LP core wakeup
|
||||
#define RTC_LP_CORE_TRAP_TRIG_EN PMU_LP_CORE_TRAP_WAKEUP_EN //!< LP core trap (exception) wakeup
|
||||
#else
|
||||
#define RTC_LP_CORE_TRIG_EN 0
|
||||
#define RTC_LP_CORE_TRAP_TRIG_EN 0
|
||||
@@ -199,6 +199,9 @@ typedef struct {
|
||||
#if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA
|
||||
void *priv;
|
||||
#endif
|
||||
#if SOC_SPI_FLASH_HAS_DEDICATED_LDO
|
||||
bool flash_ldo_volt_1v8;
|
||||
#endif
|
||||
} pmu_context_t;
|
||||
|
||||
pmu_context_t * PMU_instance(void);
|
||||
|
||||
@@ -97,14 +97,36 @@ esp_err_t esp_sleep_acquire_lp_use_xtal(void);
|
||||
esp_err_t esp_sleep_release_lp_use_xtal(void);
|
||||
#endif
|
||||
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
/**
|
||||
* @brief Isolate all digital IOs except those that are held during deep sleep
|
||||
* @brief Soft-isolate valid digital IO pads (SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK) for leakage control
|
||||
*
|
||||
* Reduce digital IOs current leakage during deep sleep.
|
||||
* Skips pads that are digitally held and pads reserved by the driver.
|
||||
* MSPI signal pads are not in this pass; use esp_sleep_isolate_mspi_gpio() after cache/MSPI idle.
|
||||
*
|
||||
* @param do_backup If true, back up each pad's pu/pd/ie/oe/fun_sel before isolating so that
|
||||
* esp_sleep_restore_isolated_digital_gpio() can restore them later.
|
||||
* Pass false when restore is not needed (e.g. deep sleep).
|
||||
*/
|
||||
void esp_sleep_isolate_digital_gpio(void);
|
||||
#endif
|
||||
void esp_sleep_isolate_digital_gpio(bool do_backup);
|
||||
|
||||
/**
|
||||
* @brief Backup and isolate (or pull up) the five base MSPI lines (CLK/Q/D/HD/WP)
|
||||
*
|
||||
* If CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU && !SOC_MSPI_HAS_INDEPENT_IOMUX, enables pull-up only;
|
||||
* otherwise full pad isolate like esp_sleep_isolate_digital_gpio. Intended after SPI bus is idle
|
||||
* (e.g. light sleep with TOP power-down).
|
||||
*/
|
||||
void esp_sleep_isolate_mspi_gpio(void);
|
||||
|
||||
/**
|
||||
* @brief Restore pu/pd/ie/oe and IOMUX fun_sel for every GPIO in the soft-isolate backup bitmap
|
||||
*
|
||||
* Reverses esp_sleep_isolate_digital_gpio / esp_sleep_isolate_mspi_gpio. Call after wake before
|
||||
* normal Flash access.
|
||||
*/
|
||||
void esp_sleep_restore_isolated_digital_gpio(void);
|
||||
#endif // !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
|
||||
#if SOC_PM_SUPPORT_PMU_CLK_ICG
|
||||
/**
|
||||
|
||||
36
components/esp_hw_support/include/esp_private/sleep_cache.h
Normal file
36
components/esp_hw_support/include/esp_private/sleep_cache.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Nestable suspend: disable external-mem cache on the first call (refcounted). Critical section; pair with @ref sleep_cache_resume.
|
||||
*/
|
||||
void sleep_cache_suspend(void);
|
||||
|
||||
/**
|
||||
* @brief Nestable resume: restore cache when the refcount returns to zero. Must match @ref sleep_cache_suspend.
|
||||
*/
|
||||
void sleep_cache_resume(void);
|
||||
|
||||
#if !CONFIG_SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE && CONFIG_SPIRAM
|
||||
/**
|
||||
* @brief Cache writeback before sleep when CPU/cache may power down (SPIRAM / PAU paths; Kconfig-driven).
|
||||
* @param sleep_flags Same flags as light sleep, e.g. @c PMU_SLEEP_PD_CPU when relevant.
|
||||
*/
|
||||
void sleep_cache_safe_writeback(uint32_t sleep_flags);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -37,6 +37,7 @@ entries:
|
||||
rtc_sleep:rtc_sleep_pd (noflash)
|
||||
if IDF_TARGET_ESP32S3 = y || IDF_TARGET_ESP32C2 = y || IDF_TARGET_ESP32C3 = y:
|
||||
rtc_sleep:rtc_sleep_pu (noflash)
|
||||
sleep_cache (noflash)
|
||||
if SOC_PMU_SUPPORTED = y:
|
||||
if SPIRAM_FLASH_LOAD_TO_PSRAM = y:
|
||||
pmu_init (noflash)
|
||||
@@ -46,7 +47,7 @@ entries:
|
||||
if SOC_PM_SLEEP_CLK_ICG_USE_REGDMA = y && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP != y:
|
||||
pmu_sleep_clock_icg:pmu_sleep_clock_icg_config (noflash)
|
||||
sleep_mspi (noflash)
|
||||
if PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32P4 != y:
|
||||
if PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32S31 != y:
|
||||
pmu_param:get_act_lp_dbias (noflash)
|
||||
if IDF_TARGET_ESP32H4 || IDF_TARGET_ESP32H21 = y:
|
||||
pmu_param:get_act_hp_drvb (noflash)
|
||||
@@ -85,6 +86,8 @@ entries:
|
||||
sleep_modes: esp_sleep_enable_vbat_under_volt_wakeup (noflash)
|
||||
sleep_modes: esp_sleep_sub_mode_config (noflash)
|
||||
sleep_modes: esp_sleep_sub_mode_force_disable (noflash)
|
||||
if (SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP = n || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD = y):
|
||||
esp_gpio_reserve (noflash)
|
||||
|
||||
[mapping:hal_gpio_pm]
|
||||
archive: libesp_hal_gpio.a
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __RVSLEEP_FRAMES_H__
|
||||
#define __RVSLEEP_FRAMES_H__
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
|
||||
#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
|
||||
|
||||
#ifdef STRUCT_BEGIN
|
||||
#undef STRUCT_BEGIN
|
||||
#undef STRUCT_FIELD
|
||||
#undef STRUCT_AFIELD
|
||||
#undef STRUCT_END
|
||||
#endif
|
||||
|
||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||
#ifdef __clang__
|
||||
#define STRUCT_BEGIN .set RV_STRUCT_OFFSET, 0
|
||||
#define STRUCT_FIELD(ctype,size,asname,name) .set asname, RV_STRUCT_OFFSET; .set RV_STRUCT_OFFSET, asname + size
|
||||
#define STRUCT_AFIELD(ctype,size,asname,name,n) .set asname, RV_STRUCT_OFFSET;\
|
||||
.set RV_STRUCT_OFFSET, asname + (size)*(n);
|
||||
#define STRUCT_END(sname) .set sname##Size, RV_STRUCT_OFFSET;
|
||||
#else // __clang__
|
||||
#define STRUCT_BEGIN .pushsection .text; .struct 0
|
||||
#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
|
||||
#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
|
||||
#define STRUCT_END(sname) sname##Size:; .popsection
|
||||
#endif // __clang__
|
||||
#else
|
||||
#define STRUCT_BEGIN typedef struct {
|
||||
#define STRUCT_FIELD(ctype,size,asname,name) ctype name;
|
||||
#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
|
||||
#define STRUCT_END(sname) } sname;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------------
|
||||
* RISC-V CORE CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP
|
||||
* -------------------------------------------------------------------------------
|
||||
*/
|
||||
STRUCT_BEGIN
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MEPC, mepc) /* Machine Exception Program Counter */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_RA, ra) /* Return address */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_SP, sp) /* Stack pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_GP, gp) /* Global pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TP, tp) /* Thread pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T0, t0) /* Temporary/alternate link register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T1, t1) /* t1-2: Temporaries */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T2, t2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S0, s0) /* Saved register/frame pointer */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S1, s1) /* Saved register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A0, a0) /* a0-1: Function arguments/return address */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A1, a1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A2, a2) /* a2-7: Function arguments */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A3, a3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A4, a4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A5, a5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A6, a6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_A7, a7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S2, s2) /* s2-11: Saved registers */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S3, s3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S4, s4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S5, s5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S6, s6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S7, s7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S8, s8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S9, s9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S10, s10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_S11, s11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T3, t3) /* t3-6: Temporaries */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T4, t4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T5, t5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_T6, t6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSTATUS, mstatus) /* Machine Status */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVEC, mtvec) /* Machine Trap-Vector Base Address */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MCAUSE, mcause) /* Machine Trap Cause */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVAL, mtval) /* Machine Trap Value */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIE, mie) /* Machine intr enable */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIP, mip) /* Machine intr pending */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MINTTHRESH, mintthresh) /* Machine intr threshold */
|
||||
|
||||
/* FPU context */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT0, fpu_ft0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT1, fpu_ft1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT2, fpu_ft2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT3, fpu_ft3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT4, fpu_ft4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT5, fpu_ft5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT6, fpu_ft6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT7, fpu_ft7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS0, fpu_fs0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS1, fpu_fs1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA0, fpu_fa0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA1, fpu_fa1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA2, fpu_fa2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA3, fpu_fa3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA4, fpu_fa4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA5, fpu_fa5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA6, fpu_fa6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FA7, fpu_fa7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS2, fpu_fs2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS3, fpu_fs3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS4, fpu_fs4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS5, fpu_fs5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS6, fpu_fs6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS7, fpu_fs7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS8, fpu_fs8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS9, fpu_fs9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS10, fpu_fs10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FS11, fpu_fs11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT8, fpu_ft8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT9, fpu_ft9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT10, fpu_ft10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FT11, fpu_ft11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_FPU_FCSR, fpu_fcsr)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMUFUNC, pmufunc) /* A field is used to identify whether it is going
|
||||
* to sleep or has just been awakened. We use the
|
||||
* lowest 2 bits as indication information, 3 means
|
||||
* being awakened, 1 means going to sleep */
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CSF_CTX_CRC, frame_crc) /* Used to check RvCoreCriticalSleepFrame integrity */
|
||||
#endif
|
||||
STRUCT_END(RvCoreCriticalSleepFrame)
|
||||
|
||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||
#define RV_SLEEP_CTX_SZ1 RvCoreCriticalSleepFrameSize
|
||||
#else
|
||||
#define RV_SLEEP_CTX_SZ1 sizeof(RvCoreCriticalSleepFrame)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Sleep stack frame size, after align up to 16 bytes boundary
|
||||
*/
|
||||
#define RV_SLEEP_CTX_FRMSZ (ALIGNUP(0x10, RV_SLEEP_CTX_SZ1))
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------------------------
|
||||
* RISC-V CORE NON-CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP
|
||||
* -------------------------------------------------------------------------------
|
||||
*/
|
||||
STRUCT_BEGIN
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSCRATCH, mscratch)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MISA, misa)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVT, mtvt) /* Machine mode vector interrupt base address register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSCRATCHCSW, mscratchcsw) /* Machine mode multi-mode data backup register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSCRATCHCSWL, mscratchcswl) /* Machine mode interrupt data backup register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MXSTATUS, mxstatus) /* Extended status register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MHCR, mhcr) /* Hardware control register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MHINT, mhint) /* Implicit operation register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MRADDR, mraddr) /* Processor reset start address indication register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MEXSTATUS, mexstatus) /* Extended exception status register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_JVT, jvt) /* Table Jump base vector and control register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MEDELEG, medeleg) /* Table Jump base vector and control register */
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TSELECT, tselect)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA1, tdata1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA2, tdata2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_TCONTROL, tcontrol)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR0, pmpaddr0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR1, pmpaddr1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR2, pmpaddr2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR3, pmpaddr3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR4, pmpaddr4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR5, pmpaddr5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR6, pmpaddr6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR7, pmpaddr7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR8, pmpaddr8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR9, pmpaddr9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR10, pmpaddr10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR11, pmpaddr11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR12, pmpaddr12)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR13, pmpaddr13)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR14, pmpaddr14)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR15, pmpaddr15)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG0, pmpcfg0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG1, pmpcfg1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3)
|
||||
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR0, pmaaddr0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR1, pmaaddr1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR2, pmaaddr2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR3, pmaaddr3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR4, pmaaddr4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR5, pmaaddr5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR6, pmaaddr6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR7, pmaaddr7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR8, pmaaddr8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR9, pmaaddr9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR10, pmaaddr10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR11, pmaaddr11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR12, pmaaddr12)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR13, pmaaddr13)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR14, pmaaddr14)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR15, pmaaddr15)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG0, pmacfg0)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG1, pmacfg1)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG2, pmacfg2)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG3, pmacfg3)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG4, pmacfg4)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG5, pmacfg5)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG6, pmacfg6)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG7, pmacfg7)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG8, pmacfg8)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG9, pmacfg9)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG10, pmacfg10)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG11, pmacfg11)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG12, pmacfg12)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG13, pmacfg13)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG14, pmacfg14)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG15, pmacfg15)
|
||||
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MCYCLE, mcycle)
|
||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MCYCLEH, mcycleh)
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
STRUCT_FIELD (long, 4, RV_SLP_NCSF_CTX_CRC, frame_crc) /* Used to check RvCoreNonCriticalSleepFrame integrity */
|
||||
#endif
|
||||
STRUCT_END(RvCoreNonCriticalSleepFrame)
|
||||
|
||||
#endif /* #ifndef __RVSLEEP_FRAMES_H__ */
|
||||
525
components/esp_hw_support/lowpower/port/esp32s31/sleep_cpu.c
Normal file
525
components/esp_hw_support/lowpower/port/esp32s31/sleep_cpu.c
Normal file
@@ -0,0 +1,525 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_ipc_isr.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_crc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "riscv/csr.h"
|
||||
#include "soc/clic_reg.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/hp_sys_clkrst_reg.h"
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#include "esp_private/sleep_event.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
|
||||
#include "esp32s31/rom/ets_sys.h"
|
||||
#include "esp32s31/rom/rtc.h"
|
||||
#include "rvsleep-frames.h"
|
||||
#include "sleep_cpu_retention.h"
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
#include "esp_private/system_internal.h"
|
||||
#include "hal/uart_hal.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
static DRAM_ATTR smp_retention_state_t s_smp_retention_state[portNUM_PROCESSORS];
|
||||
#endif
|
||||
|
||||
static bool s_fpu_saved[portNUM_PROCESSORS];
|
||||
|
||||
ESP_LOG_ATTR_TAG(TAG, "sleep");
|
||||
|
||||
static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
||||
|
||||
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
||||
|
||||
FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void)
|
||||
{
|
||||
return RV_READ_MSTATUS_AND_DISABLE_INTR();
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR void restore_mstatus(uint32_t mstatus_val)
|
||||
{
|
||||
RV_WRITE_CSR(mstatus, mstatus_val);
|
||||
}
|
||||
|
||||
#define CUSTOM_CSR_MTVT (0x307)
|
||||
#define CUSTOM_CSR_MSCRATCHCSW (0x348)
|
||||
#define CUSTOM_CSR_MSCRATCHCSWL (0x349)
|
||||
#define CUSTOM_CSR_MXSTATUS (0x7c0)
|
||||
#define CUSTOM_CSR_MHCR (0x7c1)
|
||||
#define CUSTOM_CSR_MHINT (0x7c5)
|
||||
#define CUSTOM_CSR_MRADDR (0x7e0)
|
||||
#define CUSTOM_CSR_MEXSTATUS (0x7e1)
|
||||
#define CUSTOM_CSR_JVT (0x017)
|
||||
#define CUSTOM_CSR_UINTTHRESH (0x047)
|
||||
#define CUSTOM_CSR_UINTSTATUS (0xCB1)
|
||||
|
||||
static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
|
||||
{
|
||||
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()];
|
||||
|
||||
frame->mscratch = RV_READ_CSR(mscratch);
|
||||
frame->misa = RV_READ_CSR(misa);
|
||||
frame->mtvt = RV_READ_CSR(CUSTOM_CSR_MTVT);
|
||||
frame->mscratchcsw = RV_READ_CSR(CUSTOM_CSR_MSCRATCHCSW);
|
||||
frame->mscratchcswl = RV_READ_CSR(CUSTOM_CSR_MSCRATCHCSWL);
|
||||
frame->mxstatus = RV_READ_CSR(CUSTOM_CSR_MXSTATUS);
|
||||
frame->mhcr = RV_READ_CSR(CUSTOM_CSR_MHCR);
|
||||
frame->mhint = RV_READ_CSR(CUSTOM_CSR_MHINT);
|
||||
frame->mraddr = RV_READ_CSR(CUSTOM_CSR_MRADDR);
|
||||
frame->mexstatus = RV_READ_CSR(CUSTOM_CSR_MEXSTATUS);
|
||||
frame->jvt = RV_READ_CSR(CUSTOM_CSR_JVT);
|
||||
frame->medeleg = RV_READ_CSR(medeleg);
|
||||
frame->tselect = RV_READ_CSR(tselect);
|
||||
frame->tdata1 = RV_READ_CSR(tdata1);
|
||||
frame->tdata2 = RV_READ_CSR(tdata2);
|
||||
frame->tcontrol = RV_READ_CSR(tcontrol);
|
||||
|
||||
frame->pmpaddr0 = RV_READ_CSR(pmpaddr0);
|
||||
frame->pmpaddr1 = RV_READ_CSR(pmpaddr1);
|
||||
frame->pmpaddr2 = RV_READ_CSR(pmpaddr2);
|
||||
frame->pmpaddr3 = RV_READ_CSR(pmpaddr3);
|
||||
frame->pmpaddr4 = RV_READ_CSR(pmpaddr4);
|
||||
frame->pmpaddr5 = RV_READ_CSR(pmpaddr5);
|
||||
frame->pmpaddr6 = RV_READ_CSR(pmpaddr6);
|
||||
frame->pmpaddr7 = RV_READ_CSR(pmpaddr7);
|
||||
frame->pmpaddr8 = RV_READ_CSR(pmpaddr8);
|
||||
frame->pmpaddr9 = RV_READ_CSR(pmpaddr9);
|
||||
frame->pmpaddr10 = RV_READ_CSR(pmpaddr10);
|
||||
frame->pmpaddr11 = RV_READ_CSR(pmpaddr11);
|
||||
frame->pmpaddr12 = RV_READ_CSR(pmpaddr12);
|
||||
frame->pmpaddr13 = RV_READ_CSR(pmpaddr13);
|
||||
frame->pmpaddr14 = RV_READ_CSR(pmpaddr14);
|
||||
frame->pmpaddr15 = RV_READ_CSR(pmpaddr15);
|
||||
frame->pmpcfg0 = RV_READ_CSR(pmpcfg0);
|
||||
frame->pmpcfg1 = RV_READ_CSR(pmpcfg1);
|
||||
frame->pmpcfg2 = RV_READ_CSR(pmpcfg2);
|
||||
frame->pmpcfg3 = RV_READ_CSR(pmpcfg3);
|
||||
|
||||
frame->pmaaddr0 = RV_READ_CSR(CSR_PMAADDR(0));
|
||||
frame->pmaaddr1 = RV_READ_CSR(CSR_PMAADDR(1));
|
||||
frame->pmaaddr2 = RV_READ_CSR(CSR_PMAADDR(2));
|
||||
frame->pmaaddr3 = RV_READ_CSR(CSR_PMAADDR(3));
|
||||
frame->pmaaddr4 = RV_READ_CSR(CSR_PMAADDR(4));
|
||||
frame->pmaaddr5 = RV_READ_CSR(CSR_PMAADDR(5));
|
||||
frame->pmaaddr6 = RV_READ_CSR(CSR_PMAADDR(6));
|
||||
frame->pmaaddr7 = RV_READ_CSR(CSR_PMAADDR(7));
|
||||
frame->pmaaddr8 = RV_READ_CSR(CSR_PMAADDR(8));
|
||||
frame->pmaaddr9 = RV_READ_CSR(CSR_PMAADDR(9));
|
||||
frame->pmaaddr10 = RV_READ_CSR(CSR_PMAADDR(10));
|
||||
frame->pmaaddr11 = RV_READ_CSR(CSR_PMAADDR(11));
|
||||
frame->pmaaddr12 = RV_READ_CSR(CSR_PMAADDR(12));
|
||||
frame->pmaaddr13 = RV_READ_CSR(CSR_PMAADDR(13));
|
||||
frame->pmaaddr14 = RV_READ_CSR(CSR_PMAADDR(14));
|
||||
frame->pmaaddr15 = RV_READ_CSR(CSR_PMAADDR(15));
|
||||
frame->pmacfg0 = RV_READ_CSR(CSR_PMACFG(0));
|
||||
frame->pmacfg1 = RV_READ_CSR(CSR_PMACFG(1));
|
||||
frame->pmacfg2 = RV_READ_CSR(CSR_PMACFG(2));
|
||||
frame->pmacfg3 = RV_READ_CSR(CSR_PMACFG(3));
|
||||
frame->pmacfg4 = RV_READ_CSR(CSR_PMACFG(4));
|
||||
frame->pmacfg5 = RV_READ_CSR(CSR_PMACFG(5));
|
||||
frame->pmacfg6 = RV_READ_CSR(CSR_PMACFG(6));
|
||||
frame->pmacfg7 = RV_READ_CSR(CSR_PMACFG(7));
|
||||
frame->pmacfg8 = RV_READ_CSR(CSR_PMACFG(8));
|
||||
frame->pmacfg9 = RV_READ_CSR(CSR_PMACFG(9));
|
||||
frame->pmacfg10 = RV_READ_CSR(CSR_PMACFG(10));
|
||||
frame->pmacfg11 = RV_READ_CSR(CSR_PMACFG(11));
|
||||
frame->pmacfg12 = RV_READ_CSR(CSR_PMACFG(12));
|
||||
frame->pmacfg13 = RV_READ_CSR(CSR_PMACFG(13));
|
||||
frame->pmacfg14 = RV_READ_CSR(CSR_PMACFG(14));
|
||||
frame->pmacfg15 = RV_READ_CSR(CSR_PMACFG(15));
|
||||
|
||||
frame->mcycle = RV_READ_CSR(mcycle);
|
||||
frame->mcycleh = RV_READ_CSR(mcycleh);
|
||||
return frame;
|
||||
}
|
||||
|
||||
static IRAM_ATTR void rv_core_noncritical_regs_restore(void)
|
||||
{
|
||||
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()];
|
||||
|
||||
RV_WRITE_CSR(CSR_PMAADDR(0), frame->pmaaddr0);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(1), frame->pmaaddr1);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(2), frame->pmaaddr2);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(3), frame->pmaaddr3);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(4), frame->pmaaddr4);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(5), frame->pmaaddr5);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(6), frame->pmaaddr6);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(7), frame->pmaaddr7);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(8), frame->pmaaddr8);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(9), frame->pmaaddr9);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(10),frame->pmaaddr10);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(11),frame->pmaaddr11);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(12),frame->pmaaddr12);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(13),frame->pmaaddr13);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(14),frame->pmaaddr14);
|
||||
RV_WRITE_CSR(CSR_PMAADDR(15),frame->pmaaddr15);
|
||||
RV_WRITE_CSR(CSR_PMACFG(0), frame->pmacfg0);
|
||||
RV_WRITE_CSR(CSR_PMACFG(1), frame->pmacfg1);
|
||||
RV_WRITE_CSR(CSR_PMACFG(2), frame->pmacfg2);
|
||||
RV_WRITE_CSR(CSR_PMACFG(3), frame->pmacfg3);
|
||||
RV_WRITE_CSR(CSR_PMACFG(4), frame->pmacfg4);
|
||||
RV_WRITE_CSR(CSR_PMACFG(5), frame->pmacfg5);
|
||||
RV_WRITE_CSR(CSR_PMACFG(6), frame->pmacfg6);
|
||||
RV_WRITE_CSR(CSR_PMACFG(7), frame->pmacfg7);
|
||||
RV_WRITE_CSR(CSR_PMACFG(8), frame->pmacfg8);
|
||||
RV_WRITE_CSR(CSR_PMACFG(9), frame->pmacfg9);
|
||||
RV_WRITE_CSR(CSR_PMACFG(10), frame->pmacfg10);
|
||||
RV_WRITE_CSR(CSR_PMACFG(11), frame->pmacfg11);
|
||||
RV_WRITE_CSR(CSR_PMACFG(12), frame->pmacfg12);
|
||||
RV_WRITE_CSR(CSR_PMACFG(13), frame->pmacfg13);
|
||||
RV_WRITE_CSR(CSR_PMACFG(14), frame->pmacfg14);
|
||||
RV_WRITE_CSR(CSR_PMACFG(15), frame->pmacfg15);
|
||||
|
||||
RV_WRITE_CSR(mscratch, frame->mscratch);
|
||||
RV_WRITE_CSR(misa, frame->misa);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MTVT, frame->mtvt);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MSCRATCHCSW, frame->mscratchcsw);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MSCRATCHCSWL, frame->mscratchcswl);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MXSTATUS, frame->mxstatus);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MHCR, frame->mhcr);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MHINT, frame->mhint);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MRADDR, frame->mraddr);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_MEXSTATUS, frame->mexstatus);
|
||||
RV_WRITE_CSR(CUSTOM_CSR_JVT, frame->jvt);
|
||||
RV_WRITE_CSR(medeleg, frame->medeleg);
|
||||
RV_WRITE_CSR(tselect, frame->tselect);
|
||||
RV_WRITE_CSR(tdata1, frame->tdata1);
|
||||
RV_WRITE_CSR(tdata2, frame->tdata2);
|
||||
RV_WRITE_CSR(tcontrol, frame->tcontrol);
|
||||
|
||||
RV_WRITE_CSR(pmpaddr0, frame->pmpaddr0);
|
||||
RV_WRITE_CSR(pmpaddr1, frame->pmpaddr1);
|
||||
RV_WRITE_CSR(pmpaddr2, frame->pmpaddr2);
|
||||
RV_WRITE_CSR(pmpaddr3, frame->pmpaddr3);
|
||||
RV_WRITE_CSR(pmpaddr4, frame->pmpaddr4);
|
||||
RV_WRITE_CSR(pmpaddr5, frame->pmpaddr5);
|
||||
RV_WRITE_CSR(pmpaddr6, frame->pmpaddr6);
|
||||
RV_WRITE_CSR(pmpaddr7, frame->pmpaddr7);
|
||||
RV_WRITE_CSR(pmpaddr8, frame->pmpaddr8);
|
||||
RV_WRITE_CSR(pmpaddr9, frame->pmpaddr9);
|
||||
RV_WRITE_CSR(pmpaddr10, frame->pmpaddr10);
|
||||
RV_WRITE_CSR(pmpaddr11, frame->pmpaddr11);
|
||||
RV_WRITE_CSR(pmpaddr12, frame->pmpaddr12);
|
||||
RV_WRITE_CSR(pmpaddr13, frame->pmpaddr13);
|
||||
RV_WRITE_CSR(pmpaddr14, frame->pmpaddr14);
|
||||
RV_WRITE_CSR(pmpaddr15, frame->pmpaddr15);
|
||||
RV_WRITE_CSR(pmpcfg0, frame->pmpcfg0);
|
||||
RV_WRITE_CSR(pmpcfg1, frame->pmpcfg1);
|
||||
RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2);
|
||||
RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3);
|
||||
|
||||
RV_WRITE_CSR(mcycle, frame->mcycle);
|
||||
RV_WRITE_CSR(mcycleh, frame->mcycleh);
|
||||
}
|
||||
|
||||
static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame)
|
||||
{
|
||||
assert(frame);
|
||||
cpu_domain_dev_regs_region_t *region = frame->region;
|
||||
uint32_t *regs_frame = frame->regs_frame;
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < frame->region_num; i++) {
|
||||
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
|
||||
regs_frame[offset++] = *(uint32_t *)addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame)
|
||||
{
|
||||
assert(frame);
|
||||
cpu_domain_dev_regs_region_t *region = frame->region;
|
||||
uint32_t *regs_frame = frame->regs_frame;
|
||||
|
||||
int offset = 0;
|
||||
for (int i = 0; i < frame->region_num; i++) {
|
||||
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
|
||||
*(uint32_t *)addr = regs_frame[offset++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
{
|
||||
*(frame_crc_ptr) = esp_rom_crc32_le(0, (void *)frame_ptr, frame_check_size);
|
||||
}
|
||||
|
||||
static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||
{
|
||||
if(*(frame_crc_ptr) != esp_rom_crc32_le(0, (void *)(frame_ptr), frame_check_size)){
|
||||
// resume uarts
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
if (!uart_ll_is_enabled(i)) {
|
||||
continue;
|
||||
}
|
||||
uart_ll_force_xon(i);
|
||||
}
|
||||
|
||||
/* Since it is still in the critical now, use ESP_EARLY_LOG */
|
||||
ESP_EARLY_LOGE(TAG, "Sleep retention frame is corrupted");
|
||||
esp_restart_noos();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void);
|
||||
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
|
||||
extern void rv_core_fpu_save(RvCoreCriticalSleepFrame *frame);
|
||||
extern void rv_core_fpu_restore(RvCoreCriticalSleepFrame *frame);
|
||||
typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool);
|
||||
|
||||
static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
bool reject = false;
|
||||
RvCoreCriticalSleepFrame *frame = s_cpu_retention.retent.critical_frame[core_id];
|
||||
/* mstatus is core privated CSR, do it near the core critical regs restore */
|
||||
uint32_t mstatus = save_mstatus_and_disable_global_int();
|
||||
s_fpu_saved[core_id] = xPortFPUContextIsDirty(core_id);
|
||||
if (s_fpu_saved[core_id]) {
|
||||
rv_core_fpu_save(frame);
|
||||
}
|
||||
rv_core_critical_regs_save();
|
||||
if ((frame->pmufunc & 0x3) == 0x1) {
|
||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0);
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
/* Minus 2 * sizeof(long) is for bypass `pmufunc` and `frame_crc` field */
|
||||
update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
REG_WRITE(RTC_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
|
||||
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_DONE);
|
||||
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_BACKUP_DONE) {
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
reject = (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||
}
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
else {
|
||||
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
}
|
||||
#endif
|
||||
if (s_fpu_saved[core_id]) {
|
||||
rv_core_fpu_restore(frame);
|
||||
}
|
||||
restore_mstatus(mstatus);
|
||||
return reject ? reject : pmu_sleep_finish(dslp);
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0);
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START);
|
||||
#endif
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.clic_frame[core_id]);
|
||||
rv_core_noncritical_regs_save();
|
||||
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[core_id];
|
||||
/* Minus sizeof(long) is for bypass `frame_crc` field */
|
||||
update_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
|
||||
esp_err_t err = do_cpu_retention(goto_sleep, wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||
validate_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
// Start core1
|
||||
if (core_id == 0) {
|
||||
REG_SET_BIT(HP_SYS_CLKRST_HPCORE1_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_CPU_CLK_EN);
|
||||
REG_CLR_BIT(HP_SYS_CLKRST_HPCORE1_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_GLOBAL_RST_EN);
|
||||
}
|
||||
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_START);
|
||||
#endif
|
||||
if (err == ESP_OK) {
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]);
|
||||
rv_core_noncritical_regs_restore();
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention_init(void)
|
||||
{
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
return esp_sleep_cpu_retention_init_impl(& s_cpu_retention, s_smp_retention_state);
|
||||
#else
|
||||
return esp_sleep_cpu_retention_init_impl(& s_cpu_retention);
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention_deinit(void)
|
||||
{
|
||||
return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention);
|
||||
}
|
||||
|
||||
bool cpu_domain_pd_allowed(void)
|
||||
{
|
||||
bool allowed = true;
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
allowed &= (s_cpu_retention.retent.critical_frame[core_id] != NULL);
|
||||
allowed &= (s_cpu_retention.retent.non_critical_frame[core_id] != NULL);
|
||||
}
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
allowed &= (s_cpu_retention.retent.clic_frame[core_id] != NULL);
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||
{
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU
|
||||
if (light_sleep_enable) {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||
} else {
|
||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_deinit(), TAG, "Failed to release CPU retention memory");
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU
|
||||
static IRAM_ATTR void smp_core_do_retention(void)
|
||||
{
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
|
||||
if (core_id == 0) {
|
||||
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_2_REG, 0);
|
||||
} else {
|
||||
WRITE_PERI_REG(HP_SYSTEM_CPU_INT_FROM_CPU_3_REG, 0);
|
||||
}
|
||||
|
||||
// Wait another core start to do retention
|
||||
bool smp_skip_retention = false;
|
||||
smp_retention_state_t another_core_state;
|
||||
ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-infinite-loop")
|
||||
while (1) {
|
||||
another_core_state = atomic_load(&s_smp_retention_state[!core_id]);
|
||||
if (another_core_state == SMP_SKIP_RETENTION) {
|
||||
// If another core skips the retention, the current core should also have to skip it.
|
||||
smp_skip_retention = true;
|
||||
break;
|
||||
} else if (another_core_state == SMP_BACKUP_START) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-infinite-loop")
|
||||
|
||||
if (!smp_skip_retention) {
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START);
|
||||
rv_core_noncritical_regs_save();
|
||||
cpu_domain_dev_regs_save(s_cpu_retention.retent.clic_frame[core_id]);
|
||||
RvCoreCriticalSleepFrame *frame_critical = s_cpu_retention.retent.critical_frame[core_id];
|
||||
uint32_t mstatus = save_mstatus_and_disable_global_int();
|
||||
s_fpu_saved[core_id] = xPortFPUContextIsDirty(core_id);
|
||||
if (s_fpu_saved[core_id]) {
|
||||
rv_core_fpu_save(frame_critical);
|
||||
}
|
||||
rv_core_critical_regs_save();
|
||||
if ((frame_critical->pmufunc & 0x3) == 0x1) {
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_DONE);
|
||||
// wait another core trigger sleep and wakeup
|
||||
while (1) {
|
||||
// If another core's sleep request is rejected by the hardware, jumps out of blocking.
|
||||
another_core_state = atomic_load(&s_smp_retention_state[!core_id]);
|
||||
if (another_core_state == SMP_SKIP_RETENTION) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Start core1
|
||||
if (core_id == 0) {
|
||||
REG_SET_BIT(HP_SYS_CLKRST_HPCORE1_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_CPU_CLK_EN);
|
||||
REG_CLR_BIT(HP_SYS_CLKRST_HPCORE1_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_GLOBAL_RST_EN);
|
||||
}
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_START);
|
||||
if (s_fpu_saved[core_id]) {
|
||||
rv_core_fpu_restore(frame_critical);
|
||||
}
|
||||
restore_mstatus(mstatus);
|
||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]);
|
||||
rv_core_noncritical_regs_restore();
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE);
|
||||
}
|
||||
}
|
||||
// wait another core out sleep
|
||||
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_IDLE) {
|
||||
;
|
||||
}
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_IDLE);
|
||||
}
|
||||
|
||||
|
||||
IRAM_ATTR void esp_sleep_cpu_skip_retention(void) {
|
||||
atomic_store(&s_smp_retention_state[esp_cpu_get_core_id()], SMP_SKIP_RETENTION);
|
||||
}
|
||||
#endif
|
||||
|
||||
void sleep_smp_cpu_sleep_prepare(void)
|
||||
{
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU
|
||||
while (atomic_load(&s_smp_retention_state[!esp_cpu_get_core_id()]) != SMP_IDLE) {
|
||||
;
|
||||
}
|
||||
esp_ipc_isr_call((esp_ipc_isr_func_t)smp_core_do_retention, NULL);
|
||||
#else
|
||||
esp_ipc_isr_stall_other_cpu();
|
||||
#endif
|
||||
}
|
||||
|
||||
void sleep_smp_cpu_wakeup_prepare(void)
|
||||
{
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU
|
||||
uint8_t core_id = esp_cpu_get_core_id();
|
||||
if (atomic_load(&s_smp_retention_state[core_id]) == SMP_RESTORE_DONE) {
|
||||
ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-infinite-loop")
|
||||
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_RESTORE_DONE) {
|
||||
;
|
||||
}
|
||||
ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-infinite-loop")
|
||||
}
|
||||
atomic_store(&s_smp_retention_state[core_id], SMP_IDLE);
|
||||
#else
|
||||
esp_ipc_isr_release_other_cpu();
|
||||
#endif
|
||||
}
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
219
components/esp_hw_support/lowpower/port/esp32s31/sleep_cpu_asm.S
Normal file
219
components/esp_hw_support/lowpower/port/esp32s31/sleep_cpu_asm.S
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "rvsleep-frames.h"
|
||||
#include "freertos/FreeRTOSConfig.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "riscv/csr_clic.h"
|
||||
|
||||
.section .data1,"aw"
|
||||
.global rv_core_critical_regs_frame
|
||||
.type rv_core_critical_regs_frame,@object
|
||||
.align 4
|
||||
rv_core_critical_regs_frame:
|
||||
.rept (portNUM_PROCESSORS)
|
||||
.word 0
|
||||
.endr
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
This assembly subroutine is used to save the critical registers of the CPU
|
||||
core to the internal RAM before sleep, and modify the PMU control flag to
|
||||
indicate that the system needs to sleep. When the subroutine returns, it
|
||||
will return the memory pointer that saves the context information of the CPU
|
||||
critical registers.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.section .iram1,"ax"
|
||||
.global rv_core_critical_regs_save
|
||||
.type rv_core_critical_regs_save,@function
|
||||
.align 4
|
||||
|
||||
rv_core_critical_regs_save:
|
||||
|
||||
/* arrived here in critical section. we need:
|
||||
save riscv core critical registers to RvCoreCriticalSleepFrame
|
||||
*/
|
||||
csrw mscratch, t0 /* use mscratch as temp storage */
|
||||
la a0, rv_core_critical_regs_frame
|
||||
csrr t1, mhartid
|
||||
slli t1, t1, 2
|
||||
add a0, a0, t1
|
||||
lw t0, 0(a0) /* t0 pointer to RvCoreCriticalSleepFrame object */
|
||||
|
||||
sw ra, RV_SLP_CTX_RA(t0)
|
||||
sw sp, RV_SLP_CTX_SP(t0)
|
||||
sw gp, RV_SLP_CTX_GP(t0)
|
||||
sw tp, RV_SLP_CTX_TP(t0)
|
||||
sw t1, RV_SLP_CTX_T1(t0)
|
||||
sw t2, RV_SLP_CTX_T2(t0)
|
||||
sw s0, RV_SLP_CTX_S0(t0)
|
||||
sw s1, RV_SLP_CTX_S1(t0)
|
||||
|
||||
/* a0 is caller saved, so it does not need to be saved, but it should be the
|
||||
pointer value of RvCoreCriticalSleepFrame for return.
|
||||
*/
|
||||
mv a0, t0
|
||||
sw a0, RV_SLP_CTX_A0(t0)
|
||||
sw a1, RV_SLP_CTX_A1(t0)
|
||||
sw a2, RV_SLP_CTX_A2(t0)
|
||||
sw a3, RV_SLP_CTX_A3(t0)
|
||||
sw a4, RV_SLP_CTX_A4(t0)
|
||||
sw a5, RV_SLP_CTX_A5(t0)
|
||||
sw a6, RV_SLP_CTX_A6(t0)
|
||||
sw a7, RV_SLP_CTX_A7(t0)
|
||||
sw s2, RV_SLP_CTX_S2(t0)
|
||||
sw s3, RV_SLP_CTX_S3(t0)
|
||||
sw s4, RV_SLP_CTX_S4(t0)
|
||||
sw s5, RV_SLP_CTX_S5(t0)
|
||||
sw s6, RV_SLP_CTX_S6(t0)
|
||||
sw s7, RV_SLP_CTX_S7(t0)
|
||||
sw s8, RV_SLP_CTX_S8(t0)
|
||||
sw s9, RV_SLP_CTX_S9(t0)
|
||||
sw s10, RV_SLP_CTX_S10(t0)
|
||||
sw s11, RV_SLP_CTX_S11(t0)
|
||||
sw t3, RV_SLP_CTX_T3(t0)
|
||||
sw t4, RV_SLP_CTX_T4(t0)
|
||||
sw t5, RV_SLP_CTX_T5(t0)
|
||||
sw t6, RV_SLP_CTX_T6(t0)
|
||||
|
||||
csrr t1, mstatus
|
||||
sw t1, RV_SLP_CTX_MSTATUS(t0)
|
||||
csrr t2, mtvec
|
||||
sw t2, RV_SLP_CTX_MTVEC(t0)
|
||||
csrr t3, mcause
|
||||
sw t3, RV_SLP_CTX_MCAUSE(t0)
|
||||
csrr t1, mtval
|
||||
sw t1, RV_SLP_CTX_MTVAL(t0)
|
||||
csrr t2, mie
|
||||
sw t2, RV_SLP_CTX_MIE(t0)
|
||||
csrr t3, mip
|
||||
sw t3, RV_SLP_CTX_MIP(t0)
|
||||
csrr t1, mepc
|
||||
sw t1, RV_SLP_CTX_MEPC(t0)
|
||||
csrr t2, MINTTHRESH_CSR
|
||||
sw t2, RV_SLP_CTX_MINTTHRESH(t0)
|
||||
|
||||
/*
|
||||
!!! Let idf knows it's going to sleep !!!
|
||||
|
||||
RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or
|
||||
has just been awakened. We use the lowest 2 bits as indication information,
|
||||
3 means being awakened, 1 means going to sleep.
|
||||
*/
|
||||
li t1, ~0x3
|
||||
lw t2, RV_SLP_CTX_PMUFUNC(t0)
|
||||
and t2, t1, t2
|
||||
ori t2, t2, 0x1
|
||||
sw t2, RV_SLP_CTX_PMUFUNC(t0)
|
||||
|
||||
mv t3, t0
|
||||
csrr t0, mscratch
|
||||
sw t0, RV_SLP_CTX_T0(t3)
|
||||
lw t1, RV_SLP_CTX_T1(t3)
|
||||
lw t2, RV_SLP_CTX_T2(t3)
|
||||
lw t3, RV_SLP_CTX_T3(t3)
|
||||
|
||||
ret
|
||||
|
||||
.size rv_core_critical_regs_save, . - rv_core_critical_regs_save
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
This assembly subroutine is used to restore the CPU core critical register
|
||||
context before sleep after system wakes up, modify the PMU control
|
||||
information, and return the critical register context memory object pointer.
|
||||
After the subroutine returns, continue to restore other modules of the
|
||||
system.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.section .iram1,"ax"
|
||||
.global rv_core_critical_regs_restore
|
||||
.weak rv_core_critical_regs_restore
|
||||
.type rv_core_critical_regs_restore,@function
|
||||
.global _rv_core_critical_regs_restore
|
||||
.type _rv_core_critical_regs_restore,@function
|
||||
.align 4
|
||||
|
||||
_rv_core_critical_regs_restore: /* export a strong symbol to jump to here, used
|
||||
* for a static callback */
|
||||
nop
|
||||
|
||||
rv_core_critical_regs_restore:
|
||||
la t0, rv_core_critical_regs_frame
|
||||
csrr t1, mhartid
|
||||
slli t1, t1, 2
|
||||
add t0, t0, t1
|
||||
lw t0, 0(t0) /* t0 pointer to RvCoreCriticalSleepFrame object */
|
||||
beqz t0, .skip_restore /* make sure we do not jump to zero address */
|
||||
|
||||
/*
|
||||
!!! Let idf knows it's sleep awake. !!!
|
||||
|
||||
RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or
|
||||
has just been awakened. We use the lowest 2 bits as indication information,
|
||||
3 means being awakened, 1 means going to sleep.
|
||||
*/
|
||||
lw t1, RV_SLP_CTX_PMUFUNC(t0)
|
||||
ori t1, t1, 0x3
|
||||
sw t1, RV_SLP_CTX_PMUFUNC(t0)
|
||||
|
||||
lw t2, RV_SLP_CTX_MINTTHRESH(t0)
|
||||
csrw MINTTHRESH_CSR, t2
|
||||
lw t2, RV_SLP_CTX_MEPC(t0)
|
||||
csrw mepc, t2
|
||||
lw t3, RV_SLP_CTX_MIP(t0)
|
||||
csrw mip, t3
|
||||
lw t1, RV_SLP_CTX_MIE(t0)
|
||||
csrw mie, t1
|
||||
lw t2, RV_SLP_CTX_MSTATUS(t0)
|
||||
csrw mstatus, t2
|
||||
lw t3, RV_SLP_CTX_MTVEC(t0)
|
||||
csrw mtvec, t3
|
||||
lw t1, RV_SLP_CTX_MCAUSE(t0)
|
||||
csrw mcause, t1
|
||||
lw t2, RV_SLP_CTX_MTVAL(t0)
|
||||
csrw mtval, t2
|
||||
|
||||
lw t6, RV_SLP_CTX_T6(t0)
|
||||
lw t5, RV_SLP_CTX_T5(t0)
|
||||
lw t4, RV_SLP_CTX_T4(t0)
|
||||
lw t3, RV_SLP_CTX_T3(t0)
|
||||
lw s11, RV_SLP_CTX_S11(t0)
|
||||
lw s10, RV_SLP_CTX_S10(t0)
|
||||
lw s9, RV_SLP_CTX_S9(t0)
|
||||
lw s8, RV_SLP_CTX_S8(t0)
|
||||
lw s7, RV_SLP_CTX_S7(t0)
|
||||
lw s6, RV_SLP_CTX_S6(t0)
|
||||
lw s5, RV_SLP_CTX_S5(t0)
|
||||
lw s4, RV_SLP_CTX_S4(t0)
|
||||
lw s3, RV_SLP_CTX_S3(t0)
|
||||
lw s2, RV_SLP_CTX_S2(t0)
|
||||
lw a7, RV_SLP_CTX_A7(t0)
|
||||
lw a6, RV_SLP_CTX_A6(t0)
|
||||
lw a5, RV_SLP_CTX_A5(t0)
|
||||
lw a4, RV_SLP_CTX_A4(t0)
|
||||
lw a3, RV_SLP_CTX_A3(t0)
|
||||
lw a2, RV_SLP_CTX_A2(t0)
|
||||
lw a1, RV_SLP_CTX_A1(t0)
|
||||
lw a0, RV_SLP_CTX_A0(t0)
|
||||
lw s1, RV_SLP_CTX_S1(t0)
|
||||
lw s0, RV_SLP_CTX_S0(t0)
|
||||
lw t2, RV_SLP_CTX_T2(t0)
|
||||
lw t1, RV_SLP_CTX_T1(t0)
|
||||
lw tp, RV_SLP_CTX_TP(t0)
|
||||
lw gp, RV_SLP_CTX_GP(t0)
|
||||
lw sp, RV_SLP_CTX_SP(t0)
|
||||
lw ra, RV_SLP_CTX_RA(t0)
|
||||
lw t0, RV_SLP_CTX_T0(t0)
|
||||
|
||||
.skip_restore:
|
||||
ret
|
||||
|
||||
.size rv_core_critical_regs_restore, . - rv_core_critical_regs_restore
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_check.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#include "soc/clic_reg.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
#include "rvsleep-frames.h"
|
||||
#include "sleep_cpu_retention.h"
|
||||
|
||||
|
||||
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
||||
|
||||
static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num)
|
||||
{
|
||||
const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num;
|
||||
int regs_frame_sz = 0;
|
||||
for (int num = 0; num < region_num; num++) {
|
||||
regs_frame_sz += regions[num].end - regions[num].start;
|
||||
}
|
||||
void *frame = heap_caps_malloc(sizeof(cpu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame) {
|
||||
cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t));
|
||||
memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t));
|
||||
void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz;
|
||||
memset(regs_frame, 0, regs_frame_sz);
|
||||
*(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) {
|
||||
.region = region,
|
||||
.region_num = region_num,
|
||||
.regs_frame = (uint32_t *)regs_frame
|
||||
};
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id)
|
||||
{
|
||||
const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][3] = {
|
||||
[0 ... portNUM_PROCESSORS - 1] = {
|
||||
{ .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_CONFIG_REG + 4 },
|
||||
{ .start = CLIC_INT_THRESH_REG, .end = CLIC_INT_THRESH_REG + 4 },
|
||||
{ .start = CLIC_INT_CTRL_REG(0), .end = CLIC_INT_CTRL_REG(47) + 4 },
|
||||
}
|
||||
};
|
||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(cpu_domain_dev_regs_region_t));
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state)
|
||||
{
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||
void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||
}
|
||||
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||
void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame;
|
||||
}
|
||||
}
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
}
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
atomic_init(&s_smp_retention_state[core_id], SMP_IDLE);
|
||||
}
|
||||
return ESP_OK;
|
||||
err:
|
||||
esp_sleep_cpu_retention_deinit();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
#else
|
||||
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||
{
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||
void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||
}
|
||||
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||
void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame;
|
||||
}
|
||||
}
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||
if (frame == NULL) {
|
||||
goto err;
|
||||
}
|
||||
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
err:
|
||||
esp_sleep_cpu_retention_deinit();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||
{
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id]) {
|
||||
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.critical_frame[core_id]);
|
||||
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = NULL;
|
||||
rv_core_critical_regs_frame[core_id] = NULL;
|
||||
}
|
||||
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]) {
|
||||
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]);
|
||||
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = NULL;
|
||||
}
|
||||
}
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id]) {
|
||||
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clic_frame[core_id]);
|
||||
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = NULL;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SLEEP_CPU_RETENTION_H__
|
||||
#define __SLEEP_CPU_RETENTION_H__
|
||||
|
||||
#include "rvsleep-frames.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
#include <stdatomic.h>
|
||||
#include "soc/hp_system_reg.h"
|
||||
typedef enum {
|
||||
SMP_IDLE,
|
||||
SMP_BACKUP_START,
|
||||
SMP_BACKUP_DONE,
|
||||
SMP_RESTORE_START,
|
||||
SMP_RESTORE_DONE,
|
||||
SMP_SKIP_RETENTION,
|
||||
} smp_retention_state_t;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
} cpu_domain_dev_regs_region_t;
|
||||
|
||||
typedef struct {
|
||||
cpu_domain_dev_regs_region_t *region;
|
||||
int region_num;
|
||||
uint32_t *regs_frame;
|
||||
} cpu_domain_dev_sleep_frame_t;
|
||||
|
||||
/**
|
||||
* Internal structure which holds all requested light sleep cpu retention parameters
|
||||
*/
|
||||
typedef struct {
|
||||
struct {
|
||||
RvCoreCriticalSleepFrame *critical_frame[portNUM_PROCESSORS];
|
||||
RvCoreNonCriticalSleepFrame *non_critical_frame[portNUM_PROCESSORS];
|
||||
cpu_domain_dev_sleep_frame_t *clic_frame[portNUM_PROCESSORS];
|
||||
} retent;
|
||||
} sleep_cpu_retention_t;
|
||||
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state);
|
||||
#else
|
||||
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr);
|
||||
#endif
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr);
|
||||
|
||||
#endif /* #ifndef __SLEEP_CPU_RETENTION_H__ */
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_check.h"
|
||||
#include "soc/clic_reg.h"
|
||||
|
||||
#include "rvsleep-frames.h"
|
||||
#include "sleep_cpu_retention.h"
|
||||
|
||||
|
||||
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
||||
|
||||
#define R_CONCAT(s1, s2) _R_CONCAT(s1, s2)
|
||||
#define _R_CONCAT(s1, s2) s1 ## s2
|
||||
|
||||
#define CPU_DOMAIN_DEV_SZ0 (CPU_DOMAIN_DEV_END_ADDR0 - CPU_DOMAIN_DEV_START_ADDR0)
|
||||
#define CPU_DOMAIN_DEV_SZ1 (CPU_DOMAIN_DEV_END_ADDR1 - CPU_DOMAIN_DEV_START_ADDR1)
|
||||
#define CPU_DOMAIN_DEV_SZ2 (CPU_DOMAIN_DEV_END_ADDR2 - CPU_DOMAIN_DEV_START_ADDR2)
|
||||
#define CPU_DOMAIN_DEV_SZ3 (CPU_DOMAIN_DEV_END_ADDR3 - CPU_DOMAIN_DEV_START_ADDR3)
|
||||
#define CPU_DOMAIN_DEV_SZ4 (CPU_DOMAIN_DEV_END_ADDR4 - CPU_DOMAIN_DEV_START_ADDR4)
|
||||
#define CPU_DOMAIN_DEV_SZ5 (CPU_DOMAIN_DEV_END_ADDR5 - CPU_DOMAIN_DEV_START_ADDR5)
|
||||
#define CPU_DOMAIN_DEV_SZ6 (CPU_DOMAIN_DEV_END_ADDR6 - CPU_DOMAIN_DEV_START_ADDR6)
|
||||
#define CPU_DOMAIN_DEV_SZ7 (CPU_DOMAIN_DEV_END_ADDR7 - CPU_DOMAIN_DEV_START_ADDR7)
|
||||
|
||||
#define CPU_DOMAIN_DEV_TOTAL_SZ(n) (R_CONCAT(__TOTAL_SZ, n))
|
||||
|
||||
#define __TOTAL_SZ0 (sizeof(cpu_domain_dev_sleep_frame_t))
|
||||
#define __TOTAL_SZ1 ((__TOTAL_SZ0) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ0)
|
||||
#define __TOTAL_SZ2 ((__TOTAL_SZ1) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ1)
|
||||
#define __TOTAL_SZ3 ((__TOTAL_SZ2) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ2)
|
||||
#define __TOTAL_SZ4 ((__TOTAL_SZ3) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ3)
|
||||
#define __TOTAL_SZ5 ((__TOTAL_SZ4) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ4)
|
||||
#define __TOTAL_SZ6 ((__TOTAL_SZ5) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ5)
|
||||
#define __TOTAL_SZ7 ((__TOTAL_SZ6) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ6)
|
||||
#define __TOTAL_SZ8 ((__TOTAL_SZ7) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ7)
|
||||
|
||||
|
||||
static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num, void * frame)
|
||||
{
|
||||
const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num;
|
||||
int regs_frame_sz = 0;
|
||||
for (int num = 0; num < region_num; num++) {
|
||||
regs_frame_sz += regions[num].end - regions[num].start;
|
||||
}
|
||||
if (frame) {
|
||||
cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t));
|
||||
memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t));
|
||||
void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz;
|
||||
memset(regs_frame, 0, regs_frame_sz);
|
||||
*(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) {
|
||||
.region = region,
|
||||
.region_num = region_num,
|
||||
.regs_frame = (uint32_t *)regs_frame
|
||||
};
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id)
|
||||
{
|
||||
static DRAM_ATTR cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][2] = {
|
||||
[0 ... portNUM_PROCESSORS - 1] = {
|
||||
{ .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_CONFIG_REG + 4 },
|
||||
{ .start = CLIC_INT_THRESH_REG, .end = CLIC_INT_THRESH_REG + 4 },
|
||||
{ .start = CLIC_INT_CTRL_REG(0), .end = CLIC_INT_CTRL_REG(47) + 4 },
|
||||
}
|
||||
};
|
||||
static DRAM_ATTR uint8_t sleep_frame[portNUM_PROCESSORS][CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4)));
|
||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0]), sleep_frame[core_id]);
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state)
|
||||
{
|
||||
static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ * portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||
static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)* portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||
void * regs = rv_core_critical_regs + core_id * RV_SLEEP_CTX_FRMSZ;
|
||||
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||
}
|
||||
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)(rv_core_non_critical_regs+core_id * sizeof(RvCoreNonCriticalSleepFrame));
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
}
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
atomic_init(&s_smp_retention_state[core_id], SMP_IDLE);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#else
|
||||
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||
{
|
||||
static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ * portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||
static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)* portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||
void * regs = rv_core_critical_regs + core_id * RV_SLEEP_CTX_FRMSZ;
|
||||
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||
}
|
||||
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)(rv_core_non_critical_regs+core_id * sizeof(RvCoreNonCriticalSleepFrame));
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||
{
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id]) {
|
||||
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = NULL;
|
||||
rv_core_critical_regs_frame[core_id] = NULL;
|
||||
}
|
||||
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]) {
|
||||
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = NULL;
|
||||
}
|
||||
}
|
||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id]) {
|
||||
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = NULL;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
118
components/esp_hw_support/lowpower/port/esp32s31/sleep_fpu_asm.S
Normal file
118
components/esp_hw_support/lowpower/port/esp32s31/sleep_fpu_asm.S
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "rvsleep-frames.h"
|
||||
#include "freertos/FreeRTOSConfig.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
.section .iram1,"ax"
|
||||
.global rv_core_fpu_save
|
||||
.type rv_core_fpu_save,@function
|
||||
.align 4
|
||||
|
||||
/* Bit to set in mstatus to enable the FPU */
|
||||
#define CSR_MSTATUS_FPU_ENABLE (1 << 13)
|
||||
/* Bit to clear in mstatus to disable the FPU */
|
||||
#define CSR_MSTATUS_FPU_DISABLE (3 << 13)
|
||||
|
||||
.macro fpu_enable reg
|
||||
li \reg, CSR_MSTATUS_FPU_ENABLE
|
||||
csrs mstatus, \reg
|
||||
.endm
|
||||
|
||||
rv_core_fpu_save:
|
||||
fpu_enable t0
|
||||
mv t0, a0 /* t0 = frame (arg0) */
|
||||
fsw ft0, RV_SLP_CTX_FPU_FT0(t0)
|
||||
fsw ft1, RV_SLP_CTX_FPU_FT1(t0)
|
||||
fsw ft2, RV_SLP_CTX_FPU_FT2(t0)
|
||||
fsw ft3, RV_SLP_CTX_FPU_FT3(t0)
|
||||
fsw ft4, RV_SLP_CTX_FPU_FT4(t0)
|
||||
fsw ft5, RV_SLP_CTX_FPU_FT5(t0)
|
||||
fsw ft6, RV_SLP_CTX_FPU_FT6(t0)
|
||||
fsw ft7, RV_SLP_CTX_FPU_FT7(t0)
|
||||
fsw fs0, RV_SLP_CTX_FPU_FS0(t0)
|
||||
fsw fs1, RV_SLP_CTX_FPU_FS1(t0)
|
||||
fsw fa0, RV_SLP_CTX_FPU_FA0(t0)
|
||||
fsw fa1, RV_SLP_CTX_FPU_FA1(t0)
|
||||
fsw fa2, RV_SLP_CTX_FPU_FA2(t0)
|
||||
fsw fa3, RV_SLP_CTX_FPU_FA3(t0)
|
||||
fsw fa4, RV_SLP_CTX_FPU_FA4(t0)
|
||||
fsw fa5, RV_SLP_CTX_FPU_FA5(t0)
|
||||
fsw fa6, RV_SLP_CTX_FPU_FA6(t0)
|
||||
fsw fa7, RV_SLP_CTX_FPU_FA7(t0)
|
||||
fsw fs2, RV_SLP_CTX_FPU_FS2(t0)
|
||||
fsw fs3, RV_SLP_CTX_FPU_FS3(t0)
|
||||
fsw fs4, RV_SLP_CTX_FPU_FS4(t0)
|
||||
fsw fs5, RV_SLP_CTX_FPU_FS5(t0)
|
||||
fsw fs6, RV_SLP_CTX_FPU_FS6(t0)
|
||||
fsw fs7, RV_SLP_CTX_FPU_FS7(t0)
|
||||
fsw fs8, RV_SLP_CTX_FPU_FS8(t0)
|
||||
fsw fs9, RV_SLP_CTX_FPU_FS9(t0)
|
||||
fsw fs10, RV_SLP_CTX_FPU_FS10(t0)
|
||||
fsw fs11, RV_SLP_CTX_FPU_FS11(t0)
|
||||
fsw ft8, RV_SLP_CTX_FPU_FT8(t0)
|
||||
fsw ft9, RV_SLP_CTX_FPU_FT9(t0)
|
||||
fsw ft10, RV_SLP_CTX_FPU_FT10(t0)
|
||||
fsw ft11, RV_SLP_CTX_FPU_FT11(t0)
|
||||
csrr t1, fcsr
|
||||
sw t1, RV_SLP_CTX_FPU_FCSR(t0)
|
||||
/* Chip will go to sleep and FPU will be powered down, not necessary to disable FPU here. */
|
||||
ret
|
||||
|
||||
.size rv_core_fpu_save, . - rv_core_fpu_save
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
FPU restore: a0 = RvCoreCriticalSleepFrame *. Restore all FP registers from the frame.
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
.section .iram1,"ax"
|
||||
.global rv_core_fpu_restore
|
||||
.type rv_core_fpu_restore,@function
|
||||
.align 4
|
||||
|
||||
rv_core_fpu_restore:
|
||||
fpu_enable t0
|
||||
mv t0, a0 /* t0 = frame (arg0) */
|
||||
flw ft0, RV_SLP_CTX_FPU_FT0(t0)
|
||||
flw ft1, RV_SLP_CTX_FPU_FT1(t0)
|
||||
flw ft2, RV_SLP_CTX_FPU_FT2(t0)
|
||||
flw ft3, RV_SLP_CTX_FPU_FT3(t0)
|
||||
flw ft4, RV_SLP_CTX_FPU_FT4(t0)
|
||||
flw ft5, RV_SLP_CTX_FPU_FT5(t0)
|
||||
flw ft6, RV_SLP_CTX_FPU_FT6(t0)
|
||||
flw ft7, RV_SLP_CTX_FPU_FT7(t0)
|
||||
flw fs0, RV_SLP_CTX_FPU_FS0(t0)
|
||||
flw fs1, RV_SLP_CTX_FPU_FS1(t0)
|
||||
flw fa0, RV_SLP_CTX_FPU_FA0(t0)
|
||||
flw fa1, RV_SLP_CTX_FPU_FA1(t0)
|
||||
flw fa2, RV_SLP_CTX_FPU_FA2(t0)
|
||||
flw fa3, RV_SLP_CTX_FPU_FA3(t0)
|
||||
flw fa4, RV_SLP_CTX_FPU_FA4(t0)
|
||||
flw fa5, RV_SLP_CTX_FPU_FA5(t0)
|
||||
flw fa6, RV_SLP_CTX_FPU_FA6(t0)
|
||||
flw fa7, RV_SLP_CTX_FPU_FA7(t0)
|
||||
flw fs2, RV_SLP_CTX_FPU_FS2(t0)
|
||||
flw fs3, RV_SLP_CTX_FPU_FS3(t0)
|
||||
flw fs4, RV_SLP_CTX_FPU_FS4(t0)
|
||||
flw fs5, RV_SLP_CTX_FPU_FS5(t0)
|
||||
flw fs6, RV_SLP_CTX_FPU_FS6(t0)
|
||||
flw fs7, RV_SLP_CTX_FPU_FS7(t0)
|
||||
flw fs8, RV_SLP_CTX_FPU_FS8(t0)
|
||||
flw fs9, RV_SLP_CTX_FPU_FS9(t0)
|
||||
flw fs10, RV_SLP_CTX_FPU_FS10(t0)
|
||||
flw fs11, RV_SLP_CTX_FPU_FS11(t0)
|
||||
flw ft8, RV_SLP_CTX_FPU_FT8(t0)
|
||||
flw ft9, RV_SLP_CTX_FPU_FT9(t0)
|
||||
flw ft10, RV_SLP_CTX_FPU_FT10(t0)
|
||||
flw ft11, RV_SLP_CTX_FPU_FT11(t0)
|
||||
lw t1, RV_SLP_CTX_FPU_FCSR(t0)
|
||||
csrw fcsr, t1
|
||||
/* Caller restores mstatus (and thus FPU state); not necessary to disable FPU here. */
|
||||
ret
|
||||
|
||||
.size rv_core_fpu_restore, . - rv_core_fpu_restore
|
||||
@@ -19,9 +19,10 @@ extern "C" {
|
||||
#define PMU_UART0_WAKEUP_EN BIT(6)
|
||||
#define PMU_UART1_WAKEUP_EN BIT(7)
|
||||
#define PMU_BLE_SOC_WAKEUP_EN BIT(10)
|
||||
#define PMU_LP_CORE_WAKEUP_EN BIT(11)
|
||||
#define PMU_LP_CORE_WAKEUP_HP_EN BIT(11)
|
||||
#define PMU_LP_CORE_TRAP_WAKEUP_EN BIT(12)
|
||||
#define PMU_USB_WAKEUP_EN BIT(14)
|
||||
#define PMU_MODEM_WAKEUP_PROTECT BIT(16)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ extern "C" {
|
||||
#define PMU_UART1_WAKEUP_EN BIT(7)
|
||||
#define PMU_SDIO_WAKEUP_EN BIT(8)
|
||||
#define PMU_BLE_SOC_WAKEUP_EN BIT(10)
|
||||
#define PMU_LP_CORE_WAKEUP_EN BIT(11)
|
||||
#define PMU_LP_CORE_WAKEUP_HP_EN BIT(11)
|
||||
#define PMU_LP_CORE_TRAP_WAKEUP_EN BIT(12)
|
||||
#define PMU_USB_WAKEUP_EN BIT(14)
|
||||
|
||||
#define PMU_MODEM_WAKEUP_PROTECT BIT(16)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -20,8 +20,9 @@ extern "C" {
|
||||
#define PMU_UART1_WAKEUP_EN BIT(7)
|
||||
#define PMU_UART2_WAKEUP_EN BIT(9)
|
||||
#define PMU_BLE_SOC_WAKEUP_EN BIT(10)
|
||||
// #define PMU_LP_CORE_WAKEUP_EN BIT(11)
|
||||
#define PMU_LP_CORE_WAKEUP_HP_EN BIT(11)
|
||||
#define PMU_USB_WAKEUP_EN BIT(14)
|
||||
#define PMU_MODEM_WAKEUP_PROTECT BIT(16)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -422,7 +422,7 @@ SPM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
esp_psram_impl_enter_halfsleep_mode();
|
||||
#endif
|
||||
mspi_ll_hold_all_psram_pins();
|
||||
mspi_ll_psram_hold_all_pins();
|
||||
#endif
|
||||
s_mpll_freq_mhz_before_sleep = rtc_clk_mpll_get_freq();
|
||||
if (s_mpll_freq_mhz_before_sleep) {
|
||||
@@ -519,7 +519,7 @@ SPM_IRAM_ATTR bool pmu_sleep_finish(bool dslp)
|
||||
#endif
|
||||
}
|
||||
#if CONFIG_SPIRAM
|
||||
mspi_ll_unhold_all_psram_pins();
|
||||
mspi_ll_psram_unhold_all_pins();
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
esp_psram_impl_exit_halfsleep_mode();
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -11,7 +11,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define PMU_SDIO_WAKEUP_EN BIT(0)
|
||||
#define PMU_LP_CORE_WAKEUP_EN BIT(1)
|
||||
#define PMU_LP_CORE_WAKEUP_HP_EN BIT(1)
|
||||
#define PMU_GPIO_WAKEUP_EN BIT(2)
|
||||
#define PMU_USB_WAKEUP_EN BIT(3)
|
||||
#define PMU_UART4_WAKEUP_EN BIT(4)
|
||||
@@ -31,6 +31,8 @@ extern "C" {
|
||||
#define PMU_LP_TIMER1_WAKEUP_EN BIT(18)
|
||||
#define PMU_LP_I2S_WAKEUP_EN BIT(19)
|
||||
|
||||
#define PMU_INTERRUPT_WAKEUP BIT(23)
|
||||
|
||||
// BIT order in PLL control registers in PMU
|
||||
#define PMU_CPLL_CTRL BIT(0)
|
||||
#define PMU_SPLL_CTRL BIT(1)
|
||||
|
||||
@@ -82,13 +82,15 @@ bool peripheral_domain_pd_allowed(void)
|
||||
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_MCPWM2);
|
||||
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_MCPWM3);
|
||||
|
||||
// ESP32S31 supports PCNT sleep retention
|
||||
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_PCNT0);
|
||||
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_PCNT1);
|
||||
|
||||
// ESP32S31 supports SDM sleep retention
|
||||
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_SDM0);
|
||||
|
||||
// ESP32S31 supports LCDCAM sleep retention
|
||||
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_LCDCAM);
|
||||
|
||||
// ESP32S31 supports JPEG sleep retention
|
||||
RETENTION_MODULE_BITMAP_SET(&mask, SLEEP_RETENTION_MODULE_JPEG);
|
||||
|
||||
const sleep_retention_module_bitmap_t peripheral_domain_inited_modules = sleep_retention_module_bitmap_and(inited_modules, mask);
|
||||
const sleep_retention_module_bitmap_t peripheral_domain_created_modules = sleep_retention_module_bitmap_and(created_modules, mask);
|
||||
return sleep_retention_module_bitmap_eq(peripheral_domain_inited_modules, peripheral_domain_created_modules);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "sdkconfig.h"
|
||||
@@ -13,6 +14,9 @@
|
||||
#include "soc/soc.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "hal/efuse_ll.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
#include "pmu_param.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
@@ -38,9 +42,17 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
{
|
||||
/* It should be explicitly defined in the internal RAM, because this
|
||||
* instance will be used in pmu_sleep.c */
|
||||
static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU };
|
||||
static DRAM_ATTR pmu_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_hal.dev == NULL) {
|
||||
pmu_hal.dev = &PMU;
|
||||
const uint32_t sel = efuse_ll_get_flash_power_sel();
|
||||
const uint32_t en = efuse_ll_get_flash_power_sel_en();
|
||||
const int g36 = gpio_ll_get_level(GPIO_LL_GET_HW(0), (uint32_t)GPIO_NUM_36);
|
||||
pmu_context.flash_ldo_volt_1v8 = (sel == 0 && g36 == 0) || (sel == 1 && en == 0);
|
||||
}
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
@@ -90,14 +102,14 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa
|
||||
pmu_ll_hp_set_regulator_dbias_select (ctx->hal->dev, mode, anlg->regulator0.dbias_sel);
|
||||
pmu_ll_hp_set_regulator_dbias_init (ctx->hal->dev, mode, anlg->regulator0.dig_dbias_init);
|
||||
}
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias);
|
||||
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias);
|
||||
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_connect_enable(ctx->hal->dev, mode, anlg->regulator0.slp_connect_en);
|
||||
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
|
||||
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b);
|
||||
|
||||
/* Default configuration of hp-system retention sub-system in active, modem
|
||||
* and sleep modes */
|
||||
@@ -158,6 +170,8 @@ static inline void pmu_power_domain_force_default(pmu_context_t *ctx)
|
||||
}
|
||||
/* Isolate all memory banks while sleeping, avoid memory leakage current */
|
||||
pmu_ll_hp_set_memory_no_isolate (ctx->hal->dev, 0);
|
||||
/* Disable memory force pu for memory pd during deep sleep */
|
||||
pmu_ll_hp_set_memory_power_up (ctx->hal->dev, 0);
|
||||
|
||||
pmu_ll_lp_set_power_force_power_up (ctx->hal->dev, false);
|
||||
pmu_ll_lp_set_power_force_no_reset (ctx->hal->dev, false);
|
||||
@@ -210,6 +224,4 @@ void pmu_init(void)
|
||||
pmu_hp_system_init_default(PMU_instance());
|
||||
pmu_lp_system_init_default(PMU_instance());
|
||||
pmu_power_domain_force_default(PMU_instance());
|
||||
|
||||
WRITE_PERI_REG(PMU_POWER_PD_MEM_CNTL_REG, 0);
|
||||
}
|
||||
|
||||
@@ -38,9 +38,15 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 0, \
|
||||
.i2c_retention = 0, \
|
||||
.xpd_bb_i2c = 0, \
|
||||
.xpd_pll_i2c = 0x3, \
|
||||
.xpd_pll = 0x3 \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_cpll_i2c = 1, \
|
||||
.xpd_bbpll_i2c = 1, \
|
||||
.xpd_apll_i2c = 0, \
|
||||
.xpd_mpll_i2c = 1, \
|
||||
.xpd_cpll = 1, \
|
||||
.xpd_bbpll = 1, \
|
||||
.xpd_apll = 0, \
|
||||
.xpd_mpll = 1, \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 1 \
|
||||
@@ -62,9 +68,15 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
|
||||
.clk_power = { \
|
||||
.i2c_iso_en = 1, \
|
||||
.i2c_retention = 1, \
|
||||
.xpd_bb_i2c = 0, \
|
||||
.xpd_pll_i2c = 0x3, \
|
||||
.xpd_pll = 0x3 \
|
||||
.xpd_bb_i2c = 1, \
|
||||
.xpd_cpll_i2c = 1, \
|
||||
.xpd_bbpll_i2c = 1, \
|
||||
.xpd_apll_i2c = 0, \
|
||||
.xpd_mpll_i2c = 0, \
|
||||
.xpd_cpll = 1, \
|
||||
.xpd_bbpll = 1, \
|
||||
.xpd_apll = 0, \
|
||||
.xpd_mpll = 0, \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 1 \
|
||||
@@ -87,8 +99,14 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_param");
|
||||
.i2c_iso_en = 1, \
|
||||
.i2c_retention = 1, \
|
||||
.xpd_bb_i2c = 0, \
|
||||
.xpd_pll_i2c = 0, \
|
||||
.xpd_pll = 0 \
|
||||
.xpd_cpll_i2c = 0, \
|
||||
.xpd_bbpll_i2c = 0, \
|
||||
.xpd_apll_i2c = 0, \
|
||||
.xpd_mpll_i2c = 0, \
|
||||
.xpd_cpll = 0, \
|
||||
.xpd_bbpll = 0, \
|
||||
.xpd_apll = 0, \
|
||||
.xpd_mpll = 0, \
|
||||
}, \
|
||||
.xtal = { \
|
||||
.xpd_xtal = 0 \
|
||||
@@ -178,27 +196,21 @@ const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mod
|
||||
.syscntl = { \
|
||||
.c_channel = 1, \
|
||||
.uart_wakeup_en = 0, \
|
||||
.lp_pad_hold_all = 0, \
|
||||
.hp_pad_hold_all = 0, \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.lp_pad_hold_all = 1, \
|
||||
.hp_pad_hold_all = 1, \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.dig_pause_wdt = 1, \
|
||||
.dig_cpu_stall = 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* - hp_pad_hold_all:
|
||||
* - when top off: must set to 1;
|
||||
* - when top on: 0 if use pad; 1 if not use pad
|
||||
* - dig_pad_slp_sel: must set to 1 when sleep
|
||||
*/
|
||||
#define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \
|
||||
.syscntl = { \
|
||||
.c_channel = 0, \
|
||||
.uart_wakeup_en = 1, \
|
||||
.lp_pad_hold_all = 0, \
|
||||
.lp_pad_hold_all = 1, \
|
||||
.hp_pad_hold_all = 1, \
|
||||
.dig_pad_slp_sel = 1, \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.dig_pause_wdt = 1, \
|
||||
.dig_cpu_stall = 1 \
|
||||
} \
|
||||
|
||||
@@ -16,10 +16,21 @@
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#include "pmu_param.h"
|
||||
#include "hal/clk_tree_hal.h"
|
||||
#include "hal/lp_aon_hal.h"
|
||||
#include "hal/efuse_ll.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "hal/mspi_ll.h"
|
||||
#include "esp_hw_log.h"
|
||||
#if CONFIG_SPIRAM
|
||||
#include "esp_private/esp_psram_impl.h"
|
||||
#include "hal/psram_ctrlr_ll.h"
|
||||
#endif
|
||||
#if !SOC_APM_SUPPORTED
|
||||
#include "hal/apm_hal.h"
|
||||
#endif
|
||||
|
||||
#include "esp_private/rtc_clk.h"
|
||||
|
||||
ESP_HW_LOG_ATTR_TAG(TAG, "pmu_sleep");
|
||||
|
||||
@@ -28,6 +39,7 @@ ESP_HW_LOG_ATTR_TAG(TAG, "pmu_sleep");
|
||||
|
||||
|
||||
static bool s_pmu_sleep_regdma_backup_enabled;
|
||||
static uint32_t s_mpll_freq_mhz_before_sleep = 0;
|
||||
|
||||
void pmu_sleep_enable_regdma_backup(void)
|
||||
{
|
||||
@@ -200,6 +212,14 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
// Get light sleep analog default
|
||||
pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(sleep_flags);
|
||||
|
||||
#if !CONFIG_SPIRAM
|
||||
if (PMU_instance()->flash_ldo_volt_1v8)
|
||||
#endif
|
||||
{
|
||||
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
|
||||
analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
|
||||
}
|
||||
|
||||
if (!(sleep_flags & PMU_SLEEP_PD_XTAL))
|
||||
{
|
||||
// Analog parameters in HP_SLEEP
|
||||
@@ -238,6 +258,13 @@ static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_confi
|
||||
pmu_ll_hp_set_clk_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.clk_power.val);
|
||||
pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, HP(SLEEP), power->hp_sys.xtal.xpd_xtal);
|
||||
|
||||
if (dslp) {
|
||||
pmu_ll_hp_set_memory_power_on_mask(ctx->hal->dev, 0);
|
||||
} else {
|
||||
pmu_ll_hp_set_memory_power_on_mask(ctx->hal->dev, 0xf);
|
||||
}
|
||||
|
||||
pmu_ll_set_rf_power_control(ctx->hal->dev, 0);
|
||||
pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].dig_power.val);
|
||||
pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].clk_power.val);
|
||||
|
||||
@@ -249,26 +276,24 @@ 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp)
|
||||
{
|
||||
assert(ctx->hal);
|
||||
pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur);
|
||||
pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias);
|
||||
pmu_ll_hp_set_dbg_atten (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbg_atten);
|
||||
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
|
||||
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
|
||||
|
||||
pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias);
|
||||
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias);
|
||||
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b);
|
||||
pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur);
|
||||
pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep);
|
||||
pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd);
|
||||
pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd);
|
||||
pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias);
|
||||
pmu_ll_hp_set_dbg_atten (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbg_atten);
|
||||
pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias);
|
||||
pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b);
|
||||
|
||||
pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur);
|
||||
pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep);
|
||||
@@ -278,9 +303,6 @@ static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_con
|
||||
pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias);
|
||||
pmu_ll_lp_set_dbg_atten (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbg_atten);
|
||||
pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.drv_b);
|
||||
|
||||
pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_xpd);
|
||||
pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.xpd);
|
||||
}
|
||||
|
||||
static void pmu_sleep_param_init(pmu_context_t *ctx, const pmu_sleep_param_config_t *param, bool dslp)
|
||||
@@ -318,6 +340,16 @@ void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp)
|
||||
|
||||
IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||
{
|
||||
if (!dslp) {
|
||||
#if CONFIG_SPIRAM
|
||||
psram_ctrlr_ll_wait_all_transaction_done();
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
esp_psram_impl_enter_halfsleep_mode();
|
||||
#endif
|
||||
mspi_ll_psram_hold_all_pins();
|
||||
#endif
|
||||
s_mpll_freq_mhz_before_sleep = rtc_clk_mpll_get_freq();
|
||||
}
|
||||
lp_aon_hal_inform_wakeup_type(dslp);
|
||||
|
||||
pmu_ll_hp_set_wakeup_enable(&PMU, wakeup_opt);
|
||||
@@ -352,6 +384,26 @@ IRAM_ATTR bool pmu_sleep_finish(bool dslp)
|
||||
// Wait eFuse memory update done.
|
||||
while(efuse_ll_get_controller_state() != EFUSE_CONTROLLER_STATE_IDLE);
|
||||
#endif
|
||||
|
||||
if (!dslp) {
|
||||
if (s_mpll_freq_mhz_before_sleep) {
|
||||
rtc_clk_mpll_enable();
|
||||
rtc_clk_mpll_configure(clk_hal_xtal_get_freq_mhz(), s_mpll_freq_mhz_before_sleep, false);
|
||||
}
|
||||
#if CONFIG_SPIRAM
|
||||
mspi_ll_psram_unhold_all_pins();
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED
|
||||
esp_psram_impl_exit_halfsleep_mode();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !SOC_APM_SUPPORTED
|
||||
apm_hal_enable_ctrl_filter_all(false);
|
||||
#else
|
||||
ESP_STATIC_ASSERT(0, "TEE/APM retention need to be supported!");
|
||||
#endif
|
||||
|
||||
return pmu_ll_hp_is_sleep_reject(&PMU);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PMU_SDIO_WAKEUP_EN BIT(0)
|
||||
#define PMU_LP_CORE_WAKEUP_EN BIT(1)
|
||||
#define PMU_LP_CORE_WAKEUP_HP_EN BIT(0)
|
||||
#define PMU_HP_CORE_WAKEUP_LP_EN BIT(1)
|
||||
#define PMU_GPIO_WAKEUP_EN BIT(2)
|
||||
#define PMU_USB_WAKEUP_EN BIT(3)
|
||||
#define PMU_UART4_WAKEUP_EN BIT(4)
|
||||
#define PMU_INTERRUPT_WAKEUP BIT(4)
|
||||
#define PMU_UART3_WAKEUP_EN BIT(5)
|
||||
#define PMU_UART2_WAKEUP_EN BIT(6)
|
||||
#define PMU_UART1_WAKEUP_EN BIT(7)
|
||||
@@ -25,14 +25,13 @@ extern "C" {
|
||||
#define PMU_EXT1_WAKEUP_EN BIT(12)
|
||||
#define PMU_RTC_TIMER_WAKEUP_EN BIT(13)
|
||||
#define PMU_BOD_WAKEUP_EN BIT(14)
|
||||
#define PMU_VBAT_UNDERVOLT_WAKEUP_EN BIT(15)
|
||||
#define PMU_LP_CORE_TRAP_WAKEUP_EN BIT(16)
|
||||
#define PMU_ETM_WAKEUP_EN BIT(17)
|
||||
#define PMU_LP_TIMER1_WAKEUP_EN BIT(18)
|
||||
#define PMU_LP_I2S_WAKEUP_EN BIT(19)
|
||||
#define PMU_WIFI_SOC_WAKEUP_EN BIT(22)
|
||||
#define PMU_WIFI_BEACON_WAKEUP_EN BIT(23)
|
||||
#define PMU_BLE_SOC_WAKEUP_EN BIT(24)
|
||||
#define PMU_MODEM_WAKEUP_PROTECT BIT(24)
|
||||
#define PMU_BLE_SOC_WAKEUP_EN BIT(25)
|
||||
|
||||
|
||||
// BIT order in PLL control registers in PMU
|
||||
|
||||
@@ -278,7 +278,7 @@ typedef struct {
|
||||
.pd_modem_top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \
|
||||
.pd_hp_cnnt_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CNNT) ? 1 : 0, \
|
||||
.pd_hp_cpu_pd_en = ((sleep_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \
|
||||
.pd_modem_pwr_pd_en = 0, \
|
||||
.pd_modem_pwr_pd_en = ((sleep_flags) & PMU_SLEEP_PD_MEM) ? 1 : 0, \
|
||||
.pd_top_pd_en = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
|
||||
.pd_hp_mem_pd_en = 0, \
|
||||
.mem_dslp = 0, \
|
||||
@@ -330,15 +330,19 @@ typedef struct {
|
||||
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
|
||||
.lp_pad_hold_all = 1, \
|
||||
.hp_pad_hold_all = 1, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
.c_channel = (sleep_flags & PMU_SLEEP_PD_TOP) ? 0 : 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = 0, \
|
||||
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
|
||||
.dig_pad_slp_sel = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 0 : 1, \
|
||||
.lp_pad_hold_all = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
|
||||
.hp_pad_hold_all = ((sleep_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \
|
||||
.dig_pause_wdt = ((sleep_flags) & RTC_SLEEP_USE_RTC_WDT) ? 0 : 1, \
|
||||
.c_channel = (sleep_flags & PMU_SLEEP_PD_TOP) ? 0 : 1 \
|
||||
} \
|
||||
}
|
||||
@@ -363,15 +367,6 @@ typedef struct {
|
||||
.dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
|
||||
.analog = { \
|
||||
.slp_xpd = 0, \
|
||||
.slp_dbias = 0, \
|
||||
.xpd = 1, \
|
||||
.dbias = 29, \
|
||||
.drv_b = 0x0 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_SLEEP] = { \
|
||||
.analog = { \
|
||||
.drv_b = PMU_LP_DRVB_LIGHTSLEEP, \
|
||||
@@ -395,15 +390,6 @@ typedef struct {
|
||||
.dbg_atten = PMU_DBG_HP_DEEPSLEEP \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_ACTIVE] = { \
|
||||
.analog = { \
|
||||
.xpd = 1, \
|
||||
.dbias = 0x1a, \
|
||||
.slp_xpd = 0, \
|
||||
.slp_dbias = 0, \
|
||||
.drv_b = 0x7 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_SLEEP] = { \
|
||||
.analog = { \
|
||||
.drv_b = PMU_LP_DRVB_DEEPSLEEP, \
|
||||
@@ -501,7 +487,7 @@ typedef struct pmu_sleep_machine_constant {
|
||||
}, \
|
||||
.hp = { \
|
||||
.min_slp_time_us = 450, \
|
||||
.clock_domain_sync_time_us = 150, \
|
||||
.clock_domain_sync_time_us = 2, \
|
||||
.system_dfs_up_work_time_us = 124, \
|
||||
.analog_wait_time_us = 154, \
|
||||
.isolate_wait_time_us = 1, \
|
||||
@@ -509,9 +495,9 @@ typedef struct pmu_sleep_machine_constant {
|
||||
.power_supply_wait_time_us = 2, \
|
||||
.power_up_wait_time_us = 2, \
|
||||
.regdma_s2m_work_time_us = 172, \
|
||||
.regdma_s2a_work_time_us = 685, \
|
||||
.regdma_s2a_work_time_us = 750, \
|
||||
.regdma_m2a_work_time_us = 278, \
|
||||
.regdma_a2s_work_time_us = 382, \
|
||||
.regdma_a2s_work_time_us = 400, \
|
||||
.regdma_rf_on_work_time_us = 70, \
|
||||
.regdma_rf_off_work_time_us = 23, \
|
||||
.xtal_wait_stable_time_us = 250, \
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "esp_private/rtc_clk.h"
|
||||
#include "esp_hw_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "esp_private/sleep_event.h"
|
||||
#include "esp_private/regi2c_ctrl.h"
|
||||
@@ -87,19 +88,13 @@ void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||
{
|
||||
clk_ll_rtc_slow_set_src(clk_src);
|
||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||
// TODO: IDF-14645
|
||||
// #ifndef BOOTLOADER_BUILD
|
||||
// if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_ON);
|
||||
// } else {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_AUTO);
|
||||
// }
|
||||
// if (clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_RC32K, ESP_PD_OPTION_ON);
|
||||
// } else {
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_RC32K, ESP_PD_OPTION_AUTO);
|
||||
// }
|
||||
// #endif
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
if (clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_ON);
|
||||
} else {
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL32K, ESP_PD_OPTION_AUTO);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void)
|
||||
|
||||
81
components/esp_hw_support/sleep_cache.c
Normal file
81
components/esp_hw_support/sleep_cache.c
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_private/sleep_cache.h"
|
||||
#include "esp_private/cache_utils.h"
|
||||
#include "hal/cache_ll.h"
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
#include "esp_private/esp_pmu.h"
|
||||
#endif
|
||||
|
||||
static int s_cache_suspend_cnt = 0;
|
||||
static uint32_t s_cache_state = 0;
|
||||
|
||||
// Must be called from critical sections.
|
||||
void sleep_cache_suspend(void)
|
||||
{
|
||||
s_cache_suspend_cnt++;
|
||||
if (s_cache_suspend_cnt == 1) {
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_IDF_TARGET_ESP32P4
|
||||
// The implementation of P4 L2 cache suspend is to shut down MSPI AXI instead of shutting down Cache BUS.
|
||||
// If the access to external memory hits in the cache, it will not trigger a cache error. So in order to
|
||||
// fully check the access to external memory, writeback & invalidate is needed here.
|
||||
Cache_WriteBack_Invalidate_All(CACHE_MAP_MASK);
|
||||
#endif
|
||||
spi_flash_disable_cache(esp_cpu_get_core_id(), &s_cache_state);
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called from critical sections.
|
||||
void sleep_cache_resume(void)
|
||||
{
|
||||
s_cache_suspend_cnt--;
|
||||
assert(s_cache_suspend_cnt >= 0 && DRAM_STR("cache resume doesn't match suspend ops"));
|
||||
if (s_cache_suspend_cnt == 0) {
|
||||
spi_flash_restore_cache(esp_cpu_get_core_id(), s_cache_state);
|
||||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE && CONFIG_SPIRAM
|
||||
void sleep_cache_safe_writeback(uint32_t sleep_flags)
|
||||
{
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !SOC_PM_CACHE_RETENTION_BY_PAU && SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN
|
||||
#if SOC_PMU_SUPPORTED
|
||||
/* When SPIRAM is using, we need to use Cache_WriteBack_All to protect SPIRAM data
|
||||
because the cache powers down when we power down the CPU */
|
||||
if (sleep_flags & PMU_SLEEP_PD_CPU) {
|
||||
if (s_cache_suspend_cnt) {
|
||||
spi_flash_restore_cache(esp_cpu_get_core_id(), s_cache_state);
|
||||
}
|
||||
Cache_WriteBack_All();
|
||||
if (s_cache_suspend_cnt) {
|
||||
spi_flash_disable_cache(esp_cpu_get_core_id(), &s_cache_state);
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)sleep_flags;
|
||||
#endif
|
||||
#elif CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP && SOC_PM_CACHE_RETENTION_BY_PAU
|
||||
(void)sleep_flags;
|
||||
if (s_cache_suspend_cnt) {
|
||||
spi_flash_restore_cache(esp_cpu_get_core_id(), s_cache_state);
|
||||
}
|
||||
Cache_WriteBack_All(CACHE_MAP_L1_DCACHE);
|
||||
if (s_cache_suspend_cnt) {
|
||||
spi_flash_disable_cache(esp_cpu_get_core_id(), &s_cache_state);
|
||||
}
|
||||
#else
|
||||
(void)sleep_flags;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/param.h>
|
||||
@@ -27,6 +28,7 @@
|
||||
|
||||
#include "hal/rtc_hal.h"
|
||||
|
||||
#include "esp_private/esp_gpio_reserve.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "esp_private/sleep_gpio.h"
|
||||
#include "esp_private/spi_flash_os.h"
|
||||
@@ -173,17 +175,99 @@ void esp_sleep_enable_gpio_switch(bool enable)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
||||
IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
IRAM_ATTR static void sleep_gpio_isolate_one_pin(gpio_num_t gpio_num)
|
||||
{
|
||||
gpio_hal_context_t gpio_hal = {
|
||||
.dev = GPIO_HAL_GET_HW(GPIO_PORT_0)
|
||||
};
|
||||
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
gpio_io_config_t isolate_config = { .pu = 0, .pd = 0, .ie = 0, .oe = 0, .fun_sel = PIN_FUNC_GPIO };
|
||||
gpio_ll_set_pad_config_for_sleep_isolate(gpio_num, &isolate_config);
|
||||
#else
|
||||
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
||||
gpio_hal_input_disable(&gpio_hal, gpio_num);
|
||||
gpio_hal_output_disable(&gpio_hal, gpio_num);
|
||||
gpio_hal_pullup_dis(&gpio_hal, gpio_num);
|
||||
gpio_hal_pulldown_dis(&gpio_hal, gpio_num);
|
||||
gpio_hal_func_sel(&gpio_hal, gpio_num, PIN_FUNC_GPIO);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
typedef struct {
|
||||
uint64_t backuped;
|
||||
uint64_t pu;
|
||||
uint64_t pd;
|
||||
uint64_t ie;
|
||||
uint64_t oe;
|
||||
uint8_t fun_sel[GPIO_NUM_MAX];
|
||||
} gpio_isolate_backup_t;
|
||||
|
||||
static DRAM_ATTR gpio_isolate_backup_t s_gpio_isolate_backup;
|
||||
|
||||
IRAM_ATTR static void sleep_gpio_backup_one_pin(gpio_num_t gpio_num)
|
||||
{
|
||||
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
||||
gpio_io_config_t io_config;
|
||||
gpio_ll_backup_pad_config_for_sleep_isolate(gpio_num, &io_config);
|
||||
if (io_config.pu) {
|
||||
s_gpio_isolate_backup.pu |= (1ULL << gpio_num);
|
||||
}
|
||||
if (io_config.pd) {
|
||||
s_gpio_isolate_backup.pd |= (1ULL << gpio_num);
|
||||
}
|
||||
if (io_config.ie) {
|
||||
s_gpio_isolate_backup.ie |= (1ULL << gpio_num);
|
||||
}
|
||||
if (gpio_ll_output_is_enabled(gpio_hal.dev, gpio_num)) {
|
||||
s_gpio_isolate_backup.oe |= (1ULL << gpio_num);
|
||||
}
|
||||
s_gpio_isolate_backup.fun_sel[gpio_num] = (uint8_t)io_config.fun_sel;
|
||||
s_gpio_isolate_backup.backuped |= (1ULL << gpio_num);
|
||||
}
|
||||
|
||||
IRAM_ATTR void esp_sleep_isolate_mspi_gpio(void)
|
||||
{
|
||||
DRAM_ATTR static const esp_mspi_io_t s_mspi_pins[] = {
|
||||
ESP_MSPI_IO_CLK, ESP_MSPI_IO_Q, ESP_MSPI_IO_D, ESP_MSPI_IO_HD, ESP_MSPI_IO_WP
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(s_mspi_pins) / sizeof(s_mspi_pins[0]); i++) {
|
||||
gpio_num_t gpio_num = (gpio_num_t)esp_mspi_get_io(s_mspi_pins[i]);
|
||||
sleep_gpio_backup_one_pin(gpio_num);
|
||||
#if CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU && !SOC_MSPI_HAS_INDEPENT_IOMUX
|
||||
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
||||
gpio_hal_pullup_en(&gpio_hal, gpio_num);
|
||||
#else
|
||||
sleep_gpio_isolate_one_pin(gpio_num);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
IRAM_ATTR void esp_sleep_restore_isolated_digital_gpio(void)
|
||||
{
|
||||
uint64_t backuped = s_gpio_isolate_backup.backuped;
|
||||
while (backuped) {
|
||||
gpio_num_t gpio_num = (gpio_num_t)__builtin_ctzll(backuped);
|
||||
gpio_io_config_t io_config = {
|
||||
.pu = (s_gpio_isolate_backup.pu >> gpio_num) & 0x1,
|
||||
.pd = (s_gpio_isolate_backup.pd >> gpio_num) & 0x1,
|
||||
.ie = (s_gpio_isolate_backup.ie >> gpio_num) & 0x1,
|
||||
.oe = (s_gpio_isolate_backup.oe >> gpio_num) & 0x1,
|
||||
.fun_sel = (uint32_t)s_gpio_isolate_backup.fun_sel[gpio_num],
|
||||
};
|
||||
gpio_ll_set_pad_config_for_sleep_isolate(gpio_num, &io_config);
|
||||
backuped &= backuped - 1;
|
||||
}
|
||||
}
|
||||
#endif // SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
|
||||
IRAM_ATTR void esp_sleep_isolate_digital_gpio(bool do_backup)
|
||||
{
|
||||
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
||||
/* no need to do isolate if digital IOs are not being held in deep sleep */
|
||||
if (!gpio_hal_deep_sleep_hold_is_en(&gpio_hal)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* there is a situation where we cannot isolate digital IO before deep sleep:
|
||||
@@ -193,42 +277,61 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
|
||||
* the bottom current of deep sleep will be higher than light sleep, and there is no
|
||||
* reason to use deep sleep at this time.
|
||||
*/
|
||||
assert(esp_ptr_internal(&gpio_hal) && "If hold digital IO, the stack of the task calling esp_deep_sleep_start must be in internal ram!");
|
||||
assert(esp_ptr_internal(esp_cpu_get_sp()) && "If hold digital IO, the stack of the task calling esp_deep_sleep_start must be in internal ram!");
|
||||
|
||||
/* isolate digital IO that is not held(keep the configuration of digital IOs held by users) */
|
||||
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
|
||||
if (GPIO_IS_VALID_DIGITAL_IO_PAD(gpio_num) && !gpio_hal_is_digital_io_hold(&gpio_hal, gpio_num)) {
|
||||
|
||||
bool is_mspi_io_pad = false;
|
||||
esp_mspi_io_t mspi_ios[] = { ESP_MSPI_IO_CS0, ESP_MSPI_IO_CLK, ESP_MSPI_IO_Q, ESP_MSPI_IO_D, ESP_MSPI_IO_HD, ESP_MSPI_IO_WP };
|
||||
for (int i = 0; i < sizeof(mspi_ios) / sizeof(mspi_ios[0]); i++) {
|
||||
if (esp_mspi_get_io(mspi_ios[i]) == gpio_num) {
|
||||
is_mspi_io_pad = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Ignore MSPI and default Console UART io pads, When the CPU executes
|
||||
// the following instructions to configure the MSPI IO PAD, access on
|
||||
// the MSPI signal lines (as CPU instruction execution and MSPI access
|
||||
// operations are asynchronous) may cause the SoC to hang.
|
||||
if (is_mspi_io_pad || gpio_num == U0RXD_GPIO_NUM || gpio_num == U0TXD_GPIO_NUM) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* disable I/O */
|
||||
gpio_hal_input_disable(&gpio_hal, gpio_num);
|
||||
gpio_hal_output_disable(&gpio_hal, gpio_num);
|
||||
|
||||
/* disable pull up/down */
|
||||
gpio_hal_pullup_dis(&gpio_hal, gpio_num);
|
||||
gpio_hal_pulldown_dis(&gpio_hal, gpio_num);
|
||||
|
||||
/* make pad work as gpio(otherwise, deep sleep bottom current will rise) */
|
||||
gpio_hal_func_sel(&gpio_hal, gpio_num, PIN_FUNC_GPIO);
|
||||
}
|
||||
DRAM_ATTR static volatile uint64_t s_pad_mask = SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK;
|
||||
uint64_t pad_mask = s_pad_mask;
|
||||
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
if (do_backup) {
|
||||
s_gpio_isolate_backup.backuped = 0;
|
||||
s_gpio_isolate_backup.pu = 0;
|
||||
s_gpio_isolate_backup.pd = 0;
|
||||
s_gpio_isolate_backup.ie = 0;
|
||||
s_gpio_isolate_backup.oe = 0;
|
||||
}
|
||||
|
||||
uint64_t hold_mask = gpio_ll_get_digital_gpio_hold_mask(gpio_hal.dev);
|
||||
gpio_io_config_t isolate_config = { .pu = 0, .pd = 0, .ie = 0, .oe = 0, .fun_sel = PIN_FUNC_GPIO };
|
||||
|
||||
while (pad_mask) {
|
||||
gpio_num_t gpio_num = (gpio_num_t)__builtin_ctzll(pad_mask);
|
||||
if (!(hold_mask & (1ULL << gpio_num)) &&
|
||||
!esp_gpio_is_reserved(BIT64(gpio_num))) {
|
||||
if (do_backup) {
|
||||
gpio_io_config_t io_config;
|
||||
gpio_ll_backup_pad_config_for_sleep_isolate(gpio_num, &io_config);
|
||||
if (io_config.pu) {
|
||||
s_gpio_isolate_backup.pu |= (1ULL << gpio_num);
|
||||
}
|
||||
if (io_config.pd) {
|
||||
s_gpio_isolate_backup.pd |= (1ULL << gpio_num);
|
||||
}
|
||||
if (io_config.ie) {
|
||||
s_gpio_isolate_backup.ie |= (1ULL << gpio_num);
|
||||
}
|
||||
if (gpio_ll_output_is_enabled(gpio_hal.dev, gpio_num)) {
|
||||
s_gpio_isolate_backup.oe |= (1ULL << gpio_num);
|
||||
}
|
||||
s_gpio_isolate_backup.fun_sel[gpio_num] = (uint8_t)io_config.fun_sel;
|
||||
s_gpio_isolate_backup.backuped |= (1ULL << gpio_num);
|
||||
}
|
||||
gpio_ll_set_pad_config_for_sleep_isolate(gpio_num, &isolate_config);
|
||||
}
|
||||
pad_mask &= pad_mask - 1;
|
||||
}
|
||||
#else
|
||||
(void)do_backup;
|
||||
while (pad_mask) {
|
||||
gpio_num_t gpio_num = (gpio_num_t)__builtin_ctzll(pad_mask);
|
||||
if (!gpio_hal_is_digital_io_hold(&gpio_hal, gpio_num) &&
|
||||
!esp_gpio_is_reserved(BIT64(gpio_num))) {
|
||||
sleep_gpio_isolate_one_pin(gpio_num);
|
||||
}
|
||||
pad_mask &= pad_mask - 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
||||
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
|
||||
#if SOC_DEEP_SLEEP_SUPPORTED
|
||||
static void esp_deep_sleep_wakeup_io_reset(void)
|
||||
@@ -250,10 +353,8 @@ static void esp_deep_sleep_wakeup_io_reset(void)
|
||||
#endif
|
||||
|
||||
#if SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP
|
||||
gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
|
||||
uint64_t dslp_io_mask = SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK;
|
||||
gpio_hal_context_t gpio_hal = {
|
||||
.dev = GPIO_HAL_GET_HW(GPIO_PORT_0)
|
||||
};
|
||||
while (dslp_io_mask) {
|
||||
int gpio_num = __builtin_ctzll(dslp_io_mask);
|
||||
bool wakeup_io_enabled = gpio_hal_wakeup_is_enabled_on_hp_periph_powerdown_sleep(&gpio_hal, gpio_num);
|
||||
|
||||
@@ -225,7 +225,7 @@ uint32_t sleep_modem_reject_triggers(void)
|
||||
{
|
||||
uint32_t reject_triggers = 0;
|
||||
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
|
||||
reject_triggers = (s_sleep_modem.wifi.phy_link != NULL) ? BIT(16) : 0;
|
||||
reject_triggers = (s_sleep_modem.wifi.phy_link != NULL) ? PMU_MODEM_WAKEUP_PROTECT : 0;
|
||||
#endif
|
||||
return reject_triggers;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@
|
||||
|
||||
#include "soc/rtc.h"
|
||||
|
||||
#include "hal/cache_ll.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#if SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED || SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
||||
#include "hal/wdt_hal.h"
|
||||
@@ -88,11 +87,11 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_serial_output.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_private/cache_utils.h"
|
||||
#include "esp_private/brownout.h"
|
||||
#include "esp_private/sleep_console.h"
|
||||
#include "esp_private/sleep_uart.h"
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#include "esp_private/sleep_cache.h"
|
||||
#include "esp_private/sleep_modem.h"
|
||||
#include "esp_private/sleep_flash.h"
|
||||
#include "esp_private/sleep_usb.h"
|
||||
@@ -105,7 +104,6 @@
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
@@ -131,21 +129,22 @@
|
||||
#include "hal/gpio_ll.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/rtc.h"
|
||||
#include "esp32h2/rom/cache.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H21
|
||||
#include "esp32h21/rom/rtc.h"
|
||||
#include "esp32h21/rom/cache.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H4
|
||||
#include "esp32h4/rom/rtc.h"
|
||||
#include "esp32h4/rom/cache.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
#include "esp32p4/rom/rtc.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S31
|
||||
#include "esp32s31/rom/rtc.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_INT_WDT && CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||
@@ -245,6 +244,9 @@
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (324)
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (240)
|
||||
#define LDO_POWER_TAKEOVER_PREPARATION_TIME_US (185)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S31
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (324)
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (780)
|
||||
#endif
|
||||
|
||||
// Actually costs 80us, using the fastest slow clock 150K calculation takes about 16 ticks
|
||||
@@ -288,7 +290,7 @@ typedef struct {
|
||||
#endif
|
||||
portMUX_TYPE lock;
|
||||
uint64_t sleep_duration;
|
||||
uint32_t wakeup_triggers : 20;
|
||||
uint32_t wakeup_triggers;
|
||||
#if SOC_PM_SUPPORT_EXT1_WAKEUP
|
||||
uint32_t ext1_trigger_mode : 22; // 22 is the maximum RTCIO number in all chips
|
||||
uint32_t ext1_rtc_gpio_mask : 22;
|
||||
@@ -579,32 +581,6 @@ static void s_do_deep_sleep_phy_callback(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int s_cache_suspend_cnt = 0;
|
||||
static uint32_t s_cache_state = 0;
|
||||
|
||||
// Must be called from critical sections.
|
||||
static void FORCE_IRAM_ATTR suspend_cache(void) {
|
||||
s_cache_suspend_cnt++;
|
||||
if (s_cache_suspend_cnt == 1) {
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_IDF_TARGET_ESP32P4
|
||||
// The implementation of P4 L2 cache suspend is to shut down MSPI AXI instead of shutting down Cache BUS.
|
||||
// If the access to external memory hits in the cache, it will not trigger a cache error. So in order to
|
||||
// fully check the access to external memory, writeback & invalidate is needed here.
|
||||
Cache_WriteBack_Invalidate_All(CACHE_MAP_MASK);
|
||||
#endif
|
||||
spi_flash_disable_cache(esp_cpu_get_core_id(), &s_cache_state);
|
||||
}
|
||||
}
|
||||
|
||||
// Must be called from critical sections.
|
||||
static void FORCE_IRAM_ATTR resume_cache(void) {
|
||||
s_cache_suspend_cnt--;
|
||||
assert(s_cache_suspend_cnt >= 0 && DRAM_STR("cache resume doesn't match suspend ops"));
|
||||
if (s_cache_suspend_cnt == 0) {
|
||||
spi_flash_restore_cache(esp_cpu_get_core_id(), s_cache_state);
|
||||
}
|
||||
}
|
||||
|
||||
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
|
||||
static uint32_t s_stopped_tgwdt_bmap = 0;
|
||||
#endif
|
||||
@@ -694,7 +670,7 @@ static SLEEP_FN_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool
|
||||
// Only avoid USJ pad leakage here, USB OTG pad leakage is prevented through USB Host driver.
|
||||
sleep_console_usj_pad_backup_and_disable();
|
||||
#endif
|
||||
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD
|
||||
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD && SOC_USB_OTG_NEED_SOFTWARE_SUSPEND_BEFORE_SLEEP
|
||||
if (!(sleep_flags & PMU_SLEEP_PD_CNNT)) {
|
||||
sleep_usb_otg_phy_backup_and_disable();
|
||||
}
|
||||
@@ -711,12 +687,8 @@ static SLEEP_FN_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||
sleep_enable_cpu_retention();
|
||||
#endif
|
||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW && SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN && CONFIG_SPIRAM
|
||||
/* When using SPIRAM on the ESP32-C5, we need to use Cache_WriteBack_All to protect SPIRAM data
|
||||
because the cache powers down when we power down the CPU */
|
||||
if(sleep_flags & PMU_SLEEP_PD_CPU) {
|
||||
Cache_WriteBack_All();
|
||||
}
|
||||
#if !SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE && CONFIG_SPIRAM
|
||||
sleep_cache_safe_writeback(sleep_flags);
|
||||
#endif
|
||||
#if ADC_LL_ANA_CALI_REG_PD_WORKAROUND
|
||||
adc_hal_i2c_saradc_reg_backup();
|
||||
@@ -762,7 +734,7 @@ static SLEEP_FN_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags)
|
||||
#if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP
|
||||
sleep_console_usj_pad_restore();
|
||||
#endif
|
||||
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD
|
||||
#if SOC_USB_OTG_SUPPORTED && SOC_PM_SUPPORT_CNNT_PD && SOC_USB_OTG_NEED_SOFTWARE_SUSPEND_BEFORE_SLEEP
|
||||
if (!(sleep_flags & PMU_SLEEP_PD_CNNT)) {
|
||||
sleep_usb_otg_phy_restore();
|
||||
}
|
||||
@@ -883,16 +855,16 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
}
|
||||
#endif
|
||||
if (deep_sleep) {
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
|
||||
esp_sleep_isolate_digital_gpio();
|
||||
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP || SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
esp_sleep_isolate_digital_gpio(false);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4 && CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
if ((sleep_flags & RTC_SLEEP_FLASH_DPD) && (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300))) {
|
||||
/* Switch Flash from standby mode to deep powerdown mode */
|
||||
/* During bootloader phase following wakeup from deepsleep, flash will exit dpd mode */
|
||||
spi_flash_enable_deep_power_down_mode(true);
|
||||
}
|
||||
if ((sleep_flags & RTC_SLEEP_FLASH_DPD) && (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 300))) {
|
||||
/* Switch Flash from standby mode to deep powerdown mode */
|
||||
/* During bootloader phase following wakeup from deepsleep, flash will exit dpd mode */
|
||||
spi_flash_enable_deep_power_down_mode(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB && SOC_DEEP_SLEEP_SUPPORTED
|
||||
@@ -913,7 +885,7 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
#endif
|
||||
|
||||
// Enter Deep Sleep
|
||||
#if!ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB || SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY || !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
#if !ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB || SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY || !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
#if SOC_PMU_SUPPORTED
|
||||
result = call_rtc_sleep_start(reject_triggers, config->power.hp_sys.dig_power.mem_dslp, deep_sleep);
|
||||
#else
|
||||
@@ -924,8 +896,13 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
|
||||
#endif
|
||||
} else {
|
||||
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
if (sleep_flags & RTC_SLEEP_PD_DIG) {
|
||||
esp_sleep_isolate_digital_gpio(true);
|
||||
}
|
||||
#endif
|
||||
/* Cache Suspend 1: will wait cache idle in cache suspend */
|
||||
suspend_cache();
|
||||
sleep_cache_suspend();
|
||||
if (!(sleep_flags & RTC_SLEEP_PD_VDDSDIO)) {
|
||||
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
if (sleep_flags & RTC_SLEEP_FLASH_DPD) {
|
||||
@@ -948,6 +925,9 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
/* Cache suspend also means SPI bus IDLE, then we can hold SPI CS pin safely */
|
||||
gpio_ll_hold_en(&GPIO, MSPI_IOMUX_PIN_NUM_CS1);
|
||||
#endif
|
||||
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
esp_sleep_isolate_mspi_gpio();
|
||||
#endif
|
||||
#endif // !SOC_MSPI_HAS_INDEPENT_IOMUX
|
||||
}
|
||||
#endif
|
||||
@@ -1007,6 +987,11 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
#endif // !SOC_MSPI_HAS_INDEPENT_IOMUX
|
||||
}
|
||||
#endif
|
||||
#if SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
if (sleep_flags & RTC_SLEEP_PD_DIG) {
|
||||
esp_sleep_restore_isolated_digital_gpio();
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_ESP_SLEEP_SET_FLASH_DPD
|
||||
if (sleep_flags & RTC_SLEEP_FLASH_DPD) {
|
||||
//Release Flash out from deep powerdown mode
|
||||
@@ -1014,7 +999,7 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
|
||||
}
|
||||
#endif
|
||||
/* Cache Resume 1: Resume cache for continue running*/
|
||||
resume_cache();
|
||||
sleep_cache_resume();
|
||||
#if CONFIG_PM_SLP_SPIRAM_HALFSLEEP_ENABLED && CONFIG_SPIRAM_XIP_FROM_PSRAM
|
||||
// Code outside of esp_sleep_start_safe may be linked to FLASH, and if CONFIG_SPIRAM_XIP_FROM_PSRAM
|
||||
// is enabled, code in Flash will be copied to PSRAM for execution. We need to wait here until
|
||||
@@ -1199,7 +1184,7 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl
|
||||
if (sleep_flags & RTC_SLEEP_PD_VDDSDIO) {
|
||||
/* Cache Suspend 2: If previous sleep powerdowned the flash, suspend cache here so that the
|
||||
access to flash before flash ready can be explicitly exposed. */
|
||||
suspend_cache();
|
||||
sleep_cache_suspend();
|
||||
}
|
||||
#endif
|
||||
// Restore CPU frequency
|
||||
@@ -1348,7 +1333,7 @@ static esp_err_t FORCE_IRAM_ATTR deep_sleep_start(bool allow_sleep_rejection)
|
||||
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 */
|
||||
resume_cache();
|
||||
sleep_cache_resume();
|
||||
#endif
|
||||
ESP_EARLY_LOGE(TAG, "Deep sleep request is rejected");
|
||||
} else {
|
||||
@@ -1434,7 +1419,7 @@ static SLEEP_FN_ATTR esp_err_t esp_light_sleep_inner(uint32_t sleep_flags, uint3
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
|
||||
if (sleep_flags & RTC_SLEEP_PD_VDDSDIO) {
|
||||
/* Cache Resume 2: flash is ready now, we can resume the cache and access flash safely after */
|
||||
resume_cache();
|
||||
sleep_cache_resume();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1533,7 +1518,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
ignore_check_wakeup_triggers |= RTC_EXT1_TRIG_EN;
|
||||
#endif
|
||||
if (!(s_config.wakeup_triggers & ignore_check_wakeup_triggers)) {
|
||||
suspend_cache();
|
||||
sleep_cache_suspend();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1718,7 +1703,7 @@ esp_err_t esp_light_sleep_start(void)
|
||||
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION && CONFIG_PM_SLP_IRAM_OPT
|
||||
/* Cache Resume 0: sleep process done, resume cache for continue running */
|
||||
if (!(s_config.wakeup_triggers & ignore_check_wakeup_triggers)) {
|
||||
resume_cache();
|
||||
sleep_cache_resume();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_hp_system_retention_in
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_tee_apm_retention_init(void *arg)
|
||||
{
|
||||
/* TBD for ESP32P4 IDF-10020. */
|
||||
#ifndef CONFIG_IDF_TARGET_ESP32P4
|
||||
/* TBD for ESP32S31 IDF-14620. */
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32P4) && !defined(CONFIG_IDF_TARGET_ESP32S31)
|
||||
esp_err_t err = sleep_retention_entries_create(tee_apm_regs_retention, ARRAY_SIZE(tee_apm_regs_retention), REGDMA_LINK_PRI_NON_CRITICAL_TEE_APM, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
if (err == ESP_OK) {
|
||||
err = sleep_retention_entries_create(tee_apm_highpri_regs_retention, ARRAY_SIZE(tee_apm_highpri_regs_retention), REGDMA_LINK_PRI_CRITICAL_TEE_APM, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
@@ -74,7 +75,7 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_flash_spimem_retention
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32P4
|
||||
#if CONFIG_SPIRAM && SOC_PSRAM_MEMSPI_IS_INDEPENDENT
|
||||
/* TODO: PM-205, In the ESP32C5, Flash and PSRAM use the same set of SPIMEM hardware, while in P4, Flash and PSRAM each have their own SPIMEM hardware.
|
||||
* It’s necessary to confirm whether the ESP32C5 can independently manage SPIMEM retention for Flash and PSRAM in software. */
|
||||
static __attribute__((unused)) esp_err_t sleep_sys_periph_psram_spimem_retention_init(void *arg)
|
||||
@@ -99,7 +100,7 @@ esp_err_t sleep_sys_periph_cache_retention_init(void)
|
||||
{
|
||||
esp_err_t err = sleep_retention_entries_create(cache_regs_retention, ARRAY_SIZE(cache_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_HIGH, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for digital peripherals (Cache) retention");
|
||||
ESP_LOGI(TAG, "L2 Cache sleep retention initialization");
|
||||
ESP_LOGD(TAG, "L2 Cache sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -109,7 +110,7 @@ esp_err_t sleep_pau_retention_init(void)
|
||||
{
|
||||
esp_err_t err = sleep_retention_entries_create(pau_regs_retention, ARRAY_SIZE(pau_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PAU) retention");
|
||||
ESP_LOGI(TAG, "PAU sleep retention initialization");
|
||||
ESP_LOGD(TAG, "PAU sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -119,7 +120,7 @@ esp_err_t sleep_pvt_retention_init(void)
|
||||
{
|
||||
esp_err_t err = sleep_retention_entries_create(pvt_regs_retention, ARRAY_SIZE(pvt_regs_retention), REGDMA_LINK_PRI_SYS_PERIPH_LOW, SLEEP_RETENTION_MODULE_SYS_PERIPH);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PVT) retention");
|
||||
ESP_LOGI(TAG, "PVT sleep retention initialization");
|
||||
ESP_LOGD(TAG, "PVT sleep retention initialization");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -147,7 +148,7 @@ static __attribute__((unused)) esp_err_t sleep_sys_periph_retention_init(void *a
|
||||
if(err) goto error;
|
||||
err = sleep_sys_periph_flash_spimem_retention_init(arg);
|
||||
if(err) goto error;
|
||||
#if CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32P4
|
||||
#if CONFIG_SPIRAM && SOC_PSRAM_MEMSPI_IS_INDEPENDENT
|
||||
err = sleep_sys_periph_psram_spimem_retention_init(arg);
|
||||
if(err) goto error;
|
||||
#endif
|
||||
|
||||
@@ -20,18 +20,20 @@ void sleep_usb_otg_phy_backup_and_disable(void)
|
||||
if (!s_usb_utmi_bus_clock_state) {
|
||||
_usb_utmi_ll_enable_bus_clock(true);
|
||||
}
|
||||
usb_dwc_dev_t *hw = USB_DWC_LL_GET_HW(0);
|
||||
// Forcing BVALID low to ignore the hardware-detected VBUS BVALID signal to suppress USB leakage.
|
||||
s_usb_dwc_bvalid_override = usb_dwc_ll_get_bvalid_override(&USB_DWC_HS);
|
||||
usb_dwc_ll_enable_bvalid_override(&USB_DWC_HS, true);
|
||||
s_usb_utmi_stoppclk_state = usb_dwc_ll_get_stoppclk_st(&USB_DWC_HS);
|
||||
usb_dwc_ll_set_stoppclk(&USB_DWC_HS, true);
|
||||
s_usb_dwc_bvalid_override = usb_dwc_ll_get_bvalid_override(hw);
|
||||
usb_dwc_ll_enable_bvalid_override(hw, true);
|
||||
s_usb_utmi_stoppclk_state = usb_dwc_ll_get_stoppclk_st(hw);
|
||||
usb_dwc_ll_set_stoppclk(hw, true);
|
||||
}
|
||||
|
||||
void sleep_usb_otg_phy_restore(void)
|
||||
{
|
||||
_usb_utmi_ll_enable_bus_clock(true);
|
||||
usb_dwc_ll_enable_bvalid_override(&USB_DWC_HS, s_usb_dwc_bvalid_override);
|
||||
usb_dwc_ll_set_stoppclk(&USB_DWC_HS, s_usb_utmi_stoppclk_state);
|
||||
usb_dwc_dev_t *hw = USB_DWC_LL_GET_HW(0);
|
||||
usb_dwc_ll_enable_bvalid_override(hw, s_usb_dwc_bvalid_override);
|
||||
usb_dwc_ll_set_stoppclk(hw, s_usb_utmi_stoppclk_state);
|
||||
if (!s_usb_utmi_bus_clock_state) {
|
||||
_usb_utmi_ll_enable_bus_clock(false);
|
||||
}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | --------- |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "hal/cache_ll.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "esp_sleep.h"
|
||||
|
||||
// Use retention link only when the target supports sleep retention is enabled
|
||||
#define I80_USE_RETENTION_LINK (SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
@@ -128,6 +129,9 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
|
||||
TAG, "invalid bus width:%d", bus_config->bus_width);
|
||||
#if !SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(bus_config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#if SOC_PM_SUPPORT_TOP_PD
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_TOP, ESP_PD_OPTION_ON); //IDF-15652
|
||||
#endif
|
||||
#endif // SOC_LCDCAM_LCD_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
// allocate i80 bus memory
|
||||
|
||||
@@ -40,7 +40,7 @@ entries:
|
||||
esp_clk:esp_clk_private_unlock (noflash)
|
||||
if SOC_SYSTIMER_SUPPORTED = y:
|
||||
systimer (noflash)
|
||||
if IDF_TARGET_ESP32H21 != y && IDF_TARGET_ESP32H4 != y:
|
||||
if SOC_ADC_SUPPORTED = y:
|
||||
sar_periph_ctrl:sar_periph_ctrl_power_disable (noflash)
|
||||
sar_periph_ctrl:adc_reset_lock_acquire (noflash)
|
||||
sar_periph_ctrl:adc_reset_lock_release (noflash)
|
||||
|
||||
@@ -82,27 +82,6 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
/* Minimal divider at which REF_CLK_FREQ can be obtained */
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
/* Minimal divider at which REF_CLK_FREQ can be obtained */
|
||||
#define REF_CLK_DIV_MIN 2 // TODO: IDF-5660
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32C2
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32C61
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32H21
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#elif CONFIG_IDF_TARGET_ESP32H4
|
||||
#define REF_CLK_DIV_MIN 2
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_PROFILING
|
||||
@@ -451,11 +430,13 @@ esp_err_t esp_pm_configure(const void* vconfig)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#ifdef REF_CLK_DIV_MIN
|
||||
int xtal_freq_mhz = esp_clk_xtal_freq() / MHZ;
|
||||
if (min_freq_mhz < xtal_freq_mhz && min_freq_mhz * MHZ / REF_CLK_FREQ < REF_CLK_DIV_MIN) {
|
||||
ESP_LOGW(TAG, "min_freq_mhz should be >= %d", REF_CLK_FREQ * REF_CLK_DIV_MIN / MHZ);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!rtc_clk_cpu_freq_mhz_to_config(max_freq_mhz, &freq_config)) {
|
||||
ESP_LOGW(TAG, "invalid max_freq_mhz value (%d)", max_freq_mhz);
|
||||
@@ -479,7 +460,7 @@ esp_err_t esp_pm_configure(const void* vconfig)
|
||||
/* Maximum SOC APB clock frequency is 40 MHz, maximum Modem (WiFi,
|
||||
* Bluetooth, etc..) APB clock frequency is 80 MHz */
|
||||
int apb_clk_freq = esp_clk_apb_freq() / MHZ;
|
||||
#if (CONFIG_ESP_WIFI_ENABLED || CONFIG_BT_ENABLED || CONFIG_IEEE802154_ENABLED) && SOC_PHY_SUPPORTED
|
||||
#if (CONFIG_ESP_WIFI_ENABLED || CONFIG_BT_ENABLED || CONFIG_IEEE802154_ENABLED) && SOC_PHY_SUPPORTED && !SOC_MODEM_APB_CLOCK_IS_INDEPENDENT
|
||||
apb_clk_freq = MAX(apb_clk_freq, MODEM_REQUIRED_MIN_APB_CLK_FREQ / MHZ);
|
||||
#endif
|
||||
int apb_max_freq = MIN(max_freq_mhz, apb_clk_freq); /* CPU frequency in APB_MAX mode */
|
||||
|
||||
@@ -5,9 +5,9 @@ components/esp_pm/test_apps:
|
||||
- if: INCLUDE_DEFAULT == 1
|
||||
disable:
|
||||
- if: CONFIG_NAME == "pm_pd_top_sleep" and IDF_TARGET not in ["esp32c5", "esp32c6", "esp32h2", "esp32p4"]
|
||||
- if: IDF_TARGET in ["esp32h21", "esp32h4", "esp32s31"]
|
||||
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
|
||||
temporary: true
|
||||
reason: not support yet # TODO: [ESP32H21] IDF-11522, [ESP32H4] IDF-12286 [ESP32S31] IDF-14645
|
||||
reason: not support yet # TODO: [ESP32H21] IDF-11522, [ESP32H4] IDF-12286
|
||||
depends_components:
|
||||
- *common_components
|
||||
- esp_pm
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
@@ -17,7 +17,6 @@ from pytest_embedded_idf.utils import idf_parametrize
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='s31 bringup on this module is not done')
|
||||
def test_esp_pm(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases()
|
||||
|
||||
|
||||
@@ -569,14 +569,15 @@ FORCE_INLINE_ATTR IRAM_ATTR void ext_mem_init(void)
|
||||
MSPI_INIT_ATTR void sys_rtc_init(const soc_reset_reason_t *rst_reas)
|
||||
{
|
||||
#if SOC_RTC_WDT_SUPPORTED
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#if CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32S31
|
||||
#define RWDT_RESET RESET_REASON_CORE_RWDT
|
||||
#define MWDT_RESET RESET_REASON_CORE_MWDT
|
||||
#elif CONFIG_IDF_TARGET_ESP32S31
|
||||
#define RWDT_RESET RESET_REASON_CORE_RWDT
|
||||
#define MWDT_RESET RESET_REASON_CORE_MWDT0
|
||||
#else
|
||||
#define RWDT_RESET RESET_REASON_CORE_RTC_WDT
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#define MWDT_RESET RESET_REASON_CORE_MWDT
|
||||
#else
|
||||
#define MWDT_RESET RESET_REASON_CORE_MWDT0
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -142,6 +142,22 @@ __attribute__((always_inline)) static inline uint32_t efuse_ll_get_controller_st
|
||||
return EFUSE.status.state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flash power select eFuse bit (see VDD_SPI voltage table; not the final rail by itself)
|
||||
*/
|
||||
__attribute__((always_inline)) static inline uint32_t efuse_ll_get_flash_power_sel(void)
|
||||
{
|
||||
return EFUSE.rd_repeat_data6.pmu_flash_power_sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flash power select valid eFuse bit (1: `flash_power_sel` is valid, 0: not)
|
||||
*/
|
||||
__attribute__((always_inline)) static inline uint32_t efuse_ll_get_flash_power_sel_en(void)
|
||||
{
|
||||
return EFUSE.rd_repeat_data6.pmu_flash_power_sel_en;
|
||||
}
|
||||
|
||||
/******************* eFuse control functions *************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -142,7 +142,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ (SOC_XTAL_FREQ_MHZ * 1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 80*1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 40*1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 5
|
||||
#define IOMUX_RETENTION_LINK_LEN 7
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,7 +65,9 @@ const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[4] = {
|
||||
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_RETENTION_MAP_BASE, GPIO_RETENTION_MAP_BASE, GPIO_RETENTION_REGS_CNT, 0, 0,
|
||||
gpio_regs_map[0], gpio_regs_map[1], gpio_regs_map[2], gpio_regs_map[3]), .owner = ENTRY(0) | ENTRY(2)
|
||||
}, \
|
||||
},
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_ENABLE1_REG, GPIO_ENABLE1_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
|
||||
@@ -136,7 +136,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 40*1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 4
|
||||
#define IOMUX_RETENTION_LINK_LEN 6
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,7 +54,9 @@ const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_STATUS_NEXT_REG, GPIO_STATUS_NEXT_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE1_REG, GPIO_ENABLE1_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 40*1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 80*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 7
|
||||
#define IOMUX_RETENTION_LINK_LEN 9
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*/
|
||||
@@ -49,8 +49,6 @@ _Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN
|
||||
#define N_REGS_IOMUX_2() (((GPIO_FUNC121_IN_SEL_CFG_REG - GPIO_FUNC0_IN_SEL_CFG_REG) / 4) + 1)
|
||||
#define N_REGS_IOMUX_3() (SOC_GPIO_PIN_COUNT)
|
||||
#define N_REGS_IOMUX_4() (1)
|
||||
#define N_REGS_IOMUX_5() (1)
|
||||
#define N_REGS_IOMUX_6() (1)
|
||||
|
||||
const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), IO_MUX_GPIO0_REG, IO_MUX_GPIO0_REG, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */
|
||||
@@ -58,8 +56,10 @@ const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_FUNC0_IN_SEL_CFG_REG, GPIO_FUNC0_IN_SEL_CFG_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_STATUS_REG, GPIO_STATUS_REG, N_REGS_IOMUX_4(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_REG, N_REGS_IOMUX_5(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_OUT_REG, GPIO_OUT_REG, N_REGS_IOMUX_6(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_ENABLE1_REG, GPIO_ENABLE1_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x07), GPIO_OUT_REG, GPIO_OUT_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x08), GPIO_OUT1_REG, GPIO_OUT1_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
|
||||
@@ -135,7 +135,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 32*1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 32*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 4
|
||||
#define IOMUX_RETENTION_LINK_LEN 5
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,7 +52,8 @@ const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_STATUS_NEXT_REG, GPIO_STATUS_NEXT_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
|
||||
@@ -137,7 +137,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 32*1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 32*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 4
|
||||
#define IOMUX_RETENTION_LINK_LEN 5
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,6 +65,7 @@ const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), DR_REG_GPIO_BASE, DR_REG_GPIO_BASE, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_FUNC0_IN_SEL_CFG_REG, GPIO_FUNC0_IN_SEL_CFG_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
|
||||
@@ -126,7 +126,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 32*1000000 )
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ ( 32*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -54,7 +54,7 @@ extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 5
|
||||
#define IOMUX_RETENTION_LINK_LEN 7
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,9 @@ const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_FUNC0_IN_SEL_CFG_REG, GPIO_FUNC0_IN_SEL_CFG_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_OUT_REG, GPIO_OUT_REG, N_REGS_IOMUX_4(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_OUT_REG, GPIO_OUT_W1TS_REG, N_REGS_IOMUX_4(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_ENABLE1_REG, GPIO_ENABLE1_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
|
||||
@@ -1171,6 +1171,10 @@ config SOC_USB_FSLS_PHY_NUM
|
||||
int
|
||||
default 1
|
||||
|
||||
config SOC_USB_OTG_NEED_SOFTWARE_SUSPEND_BEFORE_SLEEP
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_USB_UTMI_PHY_NUM
|
||||
int
|
||||
default 1
|
||||
@@ -1407,6 +1411,10 @@ config SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PSRAM_MEMSPI_IS_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_SPI_MEM_FLASH_SUPPORT_HPM
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -133,7 +133,6 @@
|
||||
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ ( 90*1000000 )
|
||||
#define REF_CLK_FREQ ( 1000000 )
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -432,6 +432,7 @@
|
||||
// USB OTG Caps
|
||||
#define SOC_USB_OTG_PERIPH_NUM (2U)
|
||||
#define SOC_USB_FSLS_PHY_NUM (1U)
|
||||
#define SOC_USB_OTG_NEED_SOFTWARE_SUSPEND_BEFORE_SLEEP (1)
|
||||
|
||||
// USB PHY Caps
|
||||
#define SOC_USB_UTMI_PHY_NUM (1U)
|
||||
@@ -533,6 +534,7 @@
|
||||
#define SOC_MSPI_HAS_INDEPENT_IOMUX 1
|
||||
#define SOC_MEMSPI_IS_INDEPENDENT 1
|
||||
#define SOC_MEMSPI_SUPPORT_CONTROL_DUMMY_OUT 1
|
||||
#define SOC_PSRAM_MEMSPI_IS_INDEPENDENT 1
|
||||
|
||||
#define SOC_SPI_MEM_FLASH_SUPPORT_HPM (1) /*!< Support High Performance Mode */
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ extern const regdma_entries_config_t hp_system_regs_retention[HP_SYSTEM_RETENTIO
|
||||
* This is an internal function of the sleep retention driver, and is not
|
||||
* useful for external use.
|
||||
*/
|
||||
#define IOMUX_RETENTION_LINK_LEN 6
|
||||
#define IOMUX_RETENTION_LINK_LEN 8
|
||||
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
|
||||
|
||||
/**
|
||||
|
||||
@@ -116,11 +116,12 @@ const regdma_entries_config_t iomux_regs_retention[] = {
|
||||
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_GPIO_PINx(), 0, 0), .owner = ENTRY(0) },
|
||||
/* GPIO_FUNC1_IN_SEL_CFG_REG ~ GPIO_FUNC255_IN_SEL_CFG_REG & GPIO_FUNC0_OUT_SEL_CFG_REG ~ GPIO_FUNC56_OUT_SEL_CFG_REG */
|
||||
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_FUNC1_IN_SEL_CFG_REG, GPIO_FUNC1_IN_SEL_CFG_REG, N_REGS_GPIO_FUNCx(), 0, 0), .owner = ENTRY(0) },
|
||||
|
||||
[5] = {
|
||||
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_RETENTION_REGS_BASE1, GPIO_RETENTION_REGS_BASE1, GPIO_RETENTION_REGS_CNT1, 0, 0, \
|
||||
gpio_regs_map1[0], gpio_regs_map1[1], gpio_regs_map1[2], gpio_regs_map1[3]), .owner = ENTRY(0)
|
||||
},
|
||||
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_ENABLE_REG, GPIO_ENABLE_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) },
|
||||
[7] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x07), GPIO_ENABLE1_REG, GPIO_ENABLE1_W1TS_REG, 1, 0, 0), .owner = ENTRY(0) },
|
||||
};
|
||||
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
|
||||
|
||||
|
||||
@@ -150,7 +150,6 @@
|
||||
//Periheral Clock {{
|
||||
#define APB_CLK_FREQ (80*1000000)
|
||||
#define MODEM_REQUIRED_MIN_APB_CLK_FREQ (80*1000000)
|
||||
#define REF_CLK_FREQ (1000000)
|
||||
//}}
|
||||
|
||||
/* Overall memory map */
|
||||
|
||||
@@ -227,6 +227,10 @@ config SOC_SPI_FLASH_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_SPI_FLASH_HAS_DEDICATED_LDO
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_TOUCH_SENSOR_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@@ -235,10 +239,22 @@ config SOC_PPA_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LIGHT_SLEEP_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_DEEP_SLEEP_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MODEM_CLOCK_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_BITSCRAMBLER_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@@ -303,6 +319,10 @@ config SOC_XTAL_SUPPORT_40M
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_XTAL_CLOCK_PATH_DEPENDS_ON_TOP_DOMAIN
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ADC_MAX_CHANNEL_NUM
|
||||
int
|
||||
default 10
|
||||
@@ -443,6 +463,10 @@ config SOC_GPIO_SUPPORT_ETM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_IO_HAS_INDEPENDENT_WAKEUP_SOURCE
|
||||
bool
|
||||
default y
|
||||
@@ -459,14 +483,6 @@ config SOC_GPIO_OUT_RANGE_MAX
|
||||
int
|
||||
default 61
|
||||
|
||||
config SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK
|
||||
int
|
||||
default 0
|
||||
|
||||
config SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT
|
||||
int
|
||||
default 8
|
||||
|
||||
config SOC_GPIO_SUPPORT_FORCE_HOLD
|
||||
bool
|
||||
default y
|
||||
@@ -715,7 +731,7 @@ config SOC_SPI_MEM_SUPPORT_TSUS_TRES_SEPERATE_CTR
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MSPI_HAS_INDEPENT_IOMUX
|
||||
config SOC_PSRAM_HAS_DEDICATED_LDO
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -723,6 +739,10 @@ config SOC_MEMSPI_IS_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PSRAM_MEMSPI_IS_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MEMSPI_ENCRYPTION_ALIGNMENT
|
||||
int
|
||||
default 16
|
||||
@@ -967,6 +987,10 @@ config SOC_MODEM_CLOCK_IS_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MODEM_APB_CLOCK_IS_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_MODEM_CLOCK_SOC_PLL_SOURCE_CG_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
@@ -1071,6 +1095,10 @@ config SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_CPU_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_XTAL32K_PD
|
||||
bool
|
||||
default y
|
||||
@@ -1087,6 +1115,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_TOP_PD
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_SUPPORT_HP_AON_PD
|
||||
bool
|
||||
default y
|
||||
@@ -1119,6 +1151,10 @@ config SOC_PM_CPU_RETENTION_BY_SW
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_FPU_RETENTION_BY_SW
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PM_CACHE_RETENTION_BY_PAU
|
||||
bool
|
||||
default y
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user