diff --git a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst index aa3441d126..8da3f10caa 100644 --- a/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst +++ b/Documentation/platforms/xtensa/esp32s3/boards/esp32s3-devkit/index.rst @@ -325,6 +325,57 @@ To test it, just run the ``oneshot`` example:: Waiting... Finished +pm +------- + +This config demonstrate the use of power management present on the ESP32-S3. +You can use the pmconfig command to test the power management. +Enables PM support. You can define standby mode and sleep mode delay time:: + + $ make menuconfig + -> Board Selection + -> (15) PM_STANDBY delay (seconds) + (0) PM_STANDBY delay (nanoseconds) + (20) PM_SLEEP delay (seconds) + (0) PM_SLEEP delay (nanoseconds) + +Before switching PM status, you need to query the current PM status:: + nsh> pmconfig + Last state 0, Next state 0 + + /proc/pm/state0: + DOMAIN0 WAKE SLEEP TOTAL + normal 0s 00% 0s 00% 0s 00% + idle 0s 00% 0s 00% 0s 00% + standby 0s 00% 0s 00% 0s 00% + sleep 0s 00% 0s 00% 0s 00% + + /proc/pm/wakelock0: + DOMAIN0 STATE COUNT TIME + system normal 2 1s + system idle 1 1s + system standby 1 1s + system sleep 1 1s + +System switch to the PM idle mode, you need to enter:: + + nsh> pmconfig relax normal + nsh> pmconfig relax normal + +System switch to the PM standby mode, you need to enter:: + + nsh> pmconfig relax idle + nsh> pmconfig relax normal + nsh> pmconfig relax normal + +System switch to the PM sleep mode, you need to enter:: + nsh> pmconfig relax standby + nsh> pmconfig relax idle + nsh> pmconfig relax normal + nsh> pmconfig relax normal + +Note: when normal mode COUNT is 0, it will switch to the next PM state where COUNT is not 0. + psram_quad ---------- diff --git a/arch/xtensa/src/esp32s3/Make.defs b/arch/xtensa/src/esp32s3/Make.defs index a0f33b41ab..ccdd05afd1 100644 --- a/arch/xtensa/src/esp32s3/Make.defs +++ b/arch/xtensa/src/esp32s3/Make.defs @@ -186,6 +186,13 @@ ifeq ($(CONFIG_ESP32S3_AES_ACCELERATOR),y) CHIP_CSRCS += esp32s3_aes.c endif +ifeq ($(CONFIG_PM),y) +ifneq ($(CONFIG_ARCH_CUSTOM_PMINIT),y) +CHIP_CSRCS += esp32s3_pminitialize.c +endif +CHIP_CSRCS += esp32s3_pm.c +endif + ############################################################################# # Espressif HAL for 3rd Party Platforms ############################################################################# diff --git a/arch/xtensa/src/esp32s3/esp32s3_idle.c b/arch/xtensa/src/esp32s3/esp32s3_idle.c index 16b714e6af..4835891bdb 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_idle.c +++ b/arch/xtensa/src/esp32s3/esp32s3_idle.c @@ -24,20 +24,141 @@ #include +#include #include #include #include +#include #include "xtensa.h" +#include "esp32s3_pm.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +/* Values for the RTC Alarm to wake up from the PM_STANDBY mode + * (which corresponds to ESP32-C3 stop mode). If this alarm expires, + * the logic in this file will wakeup from PM_STANDBY mode and + * transition to PM_SLEEP mode (ESP32-C3 standby mode). + */ + +#ifdef CONFIG_PM +#ifndef CONFIG_PM_ALARM_SEC +# define CONFIG_PM_ALARM_SEC 15 +#endif + +#ifndef CONFIG_PM_ALARM_NSEC +# define CONFIG_PM_ALARM_NSEC 0 +#endif + +#ifndef CONFIG_PM_SLEEP_WAKEUP_SEC +# define CONFIG_PM_SLEEP_WAKEUP_SEC 20 +#endif + +#ifndef CONFIG_PM_SLEEP_WAKEUP_NSEC +# define CONFIG_PM_SLEEP_WAKEUP_NSEC 0 +#endif + +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_idlepm + * + * Description: + * Perform IDLE state power management. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void up_idlepm(void) +{ + irqstate_t flags; + static enum pm_state_e oldstate = PM_NORMAL; + enum pm_state_e newstate; + int ret; + + /* Decide, which power saving level can be obtained */ + + newstate = pm_checkstate(PM_IDLE_DOMAIN); + + /* Check for state changes */ + + if (newstate != oldstate) + { + flags = spin_lock_irqsave(NULL); + + /* Perform board-specific, state-dependent logic here */ + + _info("newstate= %d oldstate=%d\n", newstate, oldstate); + + /* Then force the global state change */ + + ret = pm_changestate(PM_IDLE_DOMAIN, newstate); + if (ret < 0) + { + /* The new state change failed, revert to the preceding state */ + + pm_changestate(PM_IDLE_DOMAIN, oldstate); + } + else + { + /* Save the new state */ + + oldstate = newstate; + } + + spin_unlock_irqrestore(NULL, flags); + + /* MCU-specific power management logic */ + + switch (newstate) + { + case PM_NORMAL: + break; + + case PM_IDLE: + break; + + case PM_STANDBY: + { + /* Enter Force-sleep mode */ + + esp32s3_pmstandby(CONFIG_PM_ALARM_SEC * 1000000 + + CONFIG_PM_ALARM_NSEC / 1000); + } + break; + + case PM_SLEEP: + { + /* Enter Deep-sleep mode */ + + esp32s3_pmsleep(CONFIG_PM_SLEEP_WAKEUP_SEC * 1000000 + + CONFIG_PM_SLEEP_WAKEUP_NSEC / 1000); + } + break; + + default: + break; + } + } + else + { +#ifdef CONFIG_WATCHDOG + /* Announce the power management state change to feed watchdog */ + + pm_changestate(PM_IDLE_DOMAIN, PM_NORMAL); +#endif + } +} +#else +# define up_idlepm() +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -86,6 +207,10 @@ void up_idle(void) # if XCHAL_HAVE_INTERRUPTS __asm__ __volatile__ ("waiti 0"); # endif + + /* Perform IDLE mode power management */ + + up_idlepm(); #endif /* CONFIG_SUPPRESS_INTERRUPTS || CONFIG_SUPPRESS_TIMER_INTS */ #ifdef CONFIG_ESP32S3_SPEED_UP_ISR diff --git a/arch/xtensa/src/esp32s3/esp32s3_pm.c b/arch/xtensa/src/esp32s3/esp32s3_pm.c new file mode 100644 index 0000000000..b89aadb405 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_pm.c @@ -0,0 +1,1158 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_pm.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#ifdef CONFIG_PM + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" +#include "xtensa.h" +#include "hardware/esp32s3_rtccntl.h" +#include "hardware/esp32s3_system.h" +#include "hardware/esp32s3_syscon.h" +#include "hardware/esp32s3_soc.h" +#include "hardware/esp32s3_uart.h" +#include "hardware/esp32s3_gpio.h" + +#include "esp32s3_rtc.h" +#include "esp32s3_pm.h" + +#include "soc/periph_defs.h" +#include "hal/clk_gate_ll.h" +#include "esp_private/esp_clk.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* If light sleep time is less than that, don't power down flash */ + +#define FLASH_PD_MIN_SLEEP_TIME_US (2000) + +/* Minimal amount of time we can sleep for. */ + +#define LIGHT_SLEEP_MIN_TIME_US (200) + +#define RTC_MODULE_SLEEP_PREPARE_CYCLES (6) + +/* Time from VDD_SDIO power up to first flash read in ROM code */ + +#define VDD_SDIO_POWERUP_TO_FLASH_READ_US (700) + +/* Extra time it takes to enter and exit light sleep and deep sleep */ + +#define LIGHT_SLEEP_TIME_OVERHEAD_US (133) + +#ifdef CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ +#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ +#else +#define DEFAULT_CPU_FREQ_MHZ (160) +#endif + +#define DEFAULT_SLEEP_OUT_OVERHEAD_US (382) +#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ) + +#define DEEP_SLEEP_WAKEUP_DELAY (2000) + +#define RTC_VDDSDIO_TIEH_1_8V 0 /* TIEH field value for 1.8V VDDSDIO */ +#define RTC_VDDSDIO_TIEH_3_3V 1 /* TIEH field value for 3.3V VDDSDIO */ + +#define RTC_GPIO_TRIG_EN BIT(2) /* GPIO wakeup */ +#define RTC_TIMER_TRIG_EN BIT(3) /* Timer wakeup */ +#define RTC_WIFI_TRIG_EN BIT(5) /* Wi-Fi wakeup (light sleep only) */ +#define RTC_UART0_TRIG_EN BIT(6) /* UART0 wakeup (light sleep only) */ +#define RTC_UART1_TRIG_EN BIT(7) /* UART1 wakeup (light sleep only) */ +#define RTC_BT_TRIG_EN BIT(10) /* BT wakeup (light sleep only) */ +#define RTC_XTAL32K_DEAD_TRIG_EN BIT(12) +#define RTC_USB_TRIG_EN BIT(14) +#define RTC_BROWNOUT_DET_TRIG_EN BIT(16) + +#define PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO (1) +#define PERIPH_SKIP_SLEEP_NO (1) + +#define UART_FSM_IDLE (0x0) +#define UART_FSM_TX_WAIT_SEND (0xf) + +#define ESP32S3_NUARTS (3) /* UART0-2 */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Power down options */ + +enum esp32s3_sleep_pd_option_e +{ + /* Power down the power domain in sleep mode */ + + ESP_PD_OPTION_OFF, + + /* Keep power domain enabled during sleep mode */ + + ESP_PD_OPTION_ON, + + /* Keep power domain enabled in sleep mode if it is needed + * by one of the wakeup options, otherwise power it down. + */ + + ESP_PD_OPTION_AUTO +}; + +/* Power domains which can be powered down in sleep mode. */ + +enum esp32s3_sleep_pd_domain_e +{ + ESP_PD_DOMAIN_RTC_PERIPH = 0, /* RTC IO, sensors */ + ESP_PD_DOMAIN_RTC_SLOW_MEM, /* RTC slow memory */ + ESP_PD_DOMAIN_RTC_FAST_MEM, /* RTC fast memory */ + ESP_PD_DOMAIN_XTAL, /* XTAL oscillator */ + ESP_PD_DOMAIN_CPU, /* CPU core */ + ESP_PD_DOMAIN_RTC8M, /* Internal 8M oscillator */ + ESP_PD_DOMAIN_VDDSDIO, /* VDD_SDIO */ + ESP_PD_DOMAIN_MAX /* Number of domains */ +}; + +/* Internal structure which holds all requested deep sleep parameters. */ + +struct esp32s3_sleep_config_s +{ + enum esp32s3_sleep_pd_option_e pd_options[ESP_PD_DOMAIN_MAX]; + uint64_t sleep_duration; + uint32_t wakeup_triggers : 15; + uint32_t ext1_trigger_mode : 1; + uint32_t ext1_rtc_gpio_mask : 22; + uint32_t ext0_trigger_level : 1; + uint32_t ext0_rtc_gpio_num : 5; + uint32_t gpio_wakeup_mask : 6; + uint32_t gpio_trigger_mode : 6; + uint32_t sleep_time_adjustment; + uint32_t ccount_ticks_record; + uint32_t sleep_time_overhead_out; + uint32_t rtc_clk_cal_period; + uint64_t rtc_ticks_at_sleep_start; +}; + +/* Structure describing vddsdio configuration. */ + +struct esp32s3_rtc_vddsdio_config_s +{ + uint32_t force : 1; /* If 1, use configuration from RTC registers; + * if 0, use EFUSE/bootstrapping pins. + */ + uint32_t enable : 1; /* Enable VDDSDIO regulator */ + uint32_t tieh : 1; /* Select VDDSDIO voltage. One of + * RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V + */ + uint32_t drefh : 2; /* Tuning parameter for VDDSDIO regulator */ + uint32_t drefm : 2; /* Tuning parameter for VDDSDIO regulator */ + uint32_t drefl : 2; /* Tuning parameter for VDDSDIO regulator */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void IRAM_ATTR esp32s3_uart_tx_wait_idle(uint8_t uart_no); +static void IRAM_ATTR esp32s3_flush_uarts(void); +static void IRAM_ATTR esp32s3_suspend_uarts(void); +static void IRAM_ATTR esp32s3_resume_uarts(void); +static void IRAM_ATTR esp32s3_timer_wakeup_prepare(void); +static uint32_t IRAM_ATTR esp32s3_get_power_down_flags(void); +static void IRAM_ATTR esp32s3_set_vddsdio_config( + struct esp32s3_rtc_vddsdio_config_s config); +static int IRAM_ATTR esp32s3_get_vddsdio_config( + struct esp32s3_rtc_vddsdio_config_s *config); +static int IRAM_ATTR esp32s3_light_sleep_inner(uint32_t pd_flags, + uint32_t time_us, struct esp32s3_rtc_vddsdio_config_s config); +static int IRAM_ATTR esp32s3_sleep_start(uint32_t pd_flags); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct esp32s3_sleep_config_s g_config = +{ + .pd_options = + { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, + ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, + ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, + ESP_PD_OPTION_AUTO + }, + .ccount_ticks_record = 0, + .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, + .wakeup_triggers = 0 +}; + +static _Atomic uint32_t pm_wakelock = 0; + +/* Inform peripherals of light sleep wakeup overhead time */ + +inform_out_sleep_overhead_cb_t + g_periph_inform_out_sleep_overhead_cb[PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO]; + +/* Indicates if light sleep shoule be skipped by peripherals. */ + +skip_light_sleep_cb_t g_periph_skip_sleep_cb[PERIPH_SKIP_SLEEP_NO]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Pauses execution for us microseconds. */ + +extern void esp_rom_delay_us(uint32_t us); + +/**************************************************************************** + * Name: esp32s3_uart_tx_wait_idle + * + * Description: + * Wait until uart tx full empty and the last char send ok. + * + * Input Parameters: + * uart_no - 0 for UART0, 1 for UART1, 2 for UART2 + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void IRAM_ATTR esp32s3_uart_tx_wait_idle(uint8_t uart_no) +{ + uint32_t status; + do + { + status = getreg32(UART_STATUS_REG(uart_no)); + } + while ((status & (UART_ST_UTX_OUT_M | UART_TXFIFO_CNT_M)) != 0); +} + +/**************************************************************************** + * Name: esp32s3_flush_uarts + * + * Description: + * Wait until UART0/UART1 tx full empty and the last char send ok + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32s3_flush_uarts(void) +{ + int i; + + for (i = 0; i < ESP32S3_NUARTS; ++i) + { + if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) + { + esp32s3_uart_tx_wait_idle(i); + } + } +} + +/**************************************************************************** + * Name: esp32s3_suspend_uarts + * + * Description: + * Suspend UART0/UART1 output + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32s3_suspend_uarts(void) +{ + int i; + uint32_t uart_fsm = 0; + + for (i = 0; i < ESP32S3_NUARTS; ++i) + { + if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) + { + continue; + } + + modifyreg32(UART_FLOW_CONF_REG(i), UART_FORCE_XON, + UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); + do + { + uart_fsm = REG_GET_FIELD(UART_STATUS_REG(i), UART_ST_UTX_OUT); + } + while (!(uart_fsm == UART_FSM_IDLE || + uart_fsm == UART_FSM_TX_WAIT_SEND)); + } +} + +/**************************************************************************** + * Name: esp32s3_resume_uarts + * + * Description: + * Re-enable UART0/UART1/UART2 output + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32s3_resume_uarts(void) +{ + int i; + + for (i = 0; i < ESP32S3_NUARTS; ++i) + { + if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) + { + continue; + } + + modifyreg32(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF, 0); + modifyreg32(UART_FLOW_CONF_REG(i), 0, UART_FORCE_XON); + modifyreg32(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | + UART_FORCE_XON, 0); + } +} + +/**************************************************************************** + * Name: esp32s3_get_power_down_flags + * + * Description: + * Get power domains that can be powered down + * + * Input Parameters: + * None + * + * Returned Value: + * Power domains + * + ****************************************************************************/ + +static uint32_t IRAM_ATTR esp32s3_get_power_down_flags(void) +{ + uint32_t pd_flags = 0; + + g_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON; + + if (g_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) + { + if (g_config.wakeup_triggers & RTC_GPIO_TRIG_EN) + { + g_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = + ESP_PD_OPTION_ON; + } + else + { + g_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = + ESP_PD_OPTION_OFF; + } + } + + g_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; + + /* Prepare flags based on the selected options */ + + if (g_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM; + } + + if (g_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM; + } + + if (g_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_RTC_PERIPH; + } + + if (g_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_CPU; + } + + if (g_config.pd_options[ESP_PD_DOMAIN_RTC8M] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_INT_8M; + } + + if (g_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_XTAL; + } + + g_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] = ESP_PD_OPTION_ON; + + return pd_flags; +} + +/**************************************************************************** + * Name: esp32s3_timer_wakeup_prepare + * + * Description: + * Configure timer to wake-up + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32s3_timer_wakeup_prepare(void) +{ + int64_t ticks; + int64_t sleep_duration = (int64_t)g_config.sleep_duration - + (int64_t)g_config.sleep_time_adjustment; + if (sleep_duration < 0) + { + sleep_duration = 0; + } + + ticks = esp32s3_rtc_time_us_to_slowclk(sleep_duration, + g_config.rtc_clk_cal_period); + esp32s3_rtc_sleep_set_wakeup_time(g_config.rtc_ticks_at_sleep_start + + ticks); +} + +/**************************************************************************** + * Name: esp32s3_set_vddsdio_config + * + * Description: + * Set new VDDSDIO configuration using RTC registers. + * + * Input Parameters: + * config - New VDDSDIO configuration + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32s3_set_vddsdio_config( + struct esp32s3_rtc_vddsdio_config_s config) +{ + uint32_t val = 0; + val |= (config.force << RTC_CNTL_SDIO_FORCE_S); + val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S); + val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S); + val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S); + val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S); + val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S); + val |= RTC_CNTL_SDIO_REG_PD_EN; + putreg32((uint32_t)val, RTC_CNTL_RTC_SDIO_CONF_REG); +} + +/**************************************************************************** + * Name: esp32s3_get_vddsdio_config + * + * Description: + * Get current VDDSDIO configuration. + * + * Input Parameters: + * config - Incoming parameter address of VDDSDIO configuration to be saved + * + * Returned Value: + * Zero (OK) is returned on success. + * + ****************************************************************************/ + +static int IRAM_ATTR esp32s3_get_vddsdio_config( + struct esp32s3_rtc_vddsdio_config_s *config) +{ + struct esp32s3_rtc_vddsdio_config_s *result = config; + uint32_t strap_reg; + uint32_t sdio_conf_reg = getreg32(RTC_CNTL_RTC_SDIO_CONF_REG); + + result->drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) + >> RTC_CNTL_DREFH_SDIO_S; + result->drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) + >> RTC_CNTL_DREFM_SDIO_S; + result->drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) + >> RTC_CNTL_DREFL_SDIO_S; + + if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) + { + /* Get configuration from RTC */ + + result->force = 1; + result->enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) + >> RTC_CNTL_XPD_SDIO_REG_S; + result->tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) + >> RTC_CNTL_SDIO_TIEH_S; + + return OK; + } + + /* Otherwise, VDD_SDIO is controlled by bootstrapping pin */ + + strap_reg = getreg32(GPIO_STRAP_REG); + result->force = 0; + result->tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V + : RTC_VDDSDIO_TIEH_3_3V; + result->enable = 1; + + return OK; +} + +/**************************************************************************** + * Name: esp32s3_sleep_start + * + * Description: + * Enter low power mode. + * + * Input Parameters: + * pd_flags - Power domains + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +static int IRAM_ATTR esp32s3_sleep_start(uint32_t pd_flags) +{ + int result; + struct esp32s3_cpu_freq_config_s cpu_freq_config; + bool deep_sleep = pd_flags & RTC_SLEEP_PD_DIG; + + /* Stop UART output so that output is not lost due to APB frequency change. + * For light sleep, suspend UART output - it will resume after wakeup. + * For deep sleep, wait for the contents of UART FIFO to be sent. + */ + + if (deep_sleep == true) + { + esp32s3_flush_uarts(); + } + else + { + esp32s3_suspend_uarts(); + } + + /* Save current frequency and switch to XTAL */ + + esp32s3_rtc_clk_cpu_freq_get_config(&cpu_freq_config); + esp32s3_rtc_cpu_freq_set_xtal(); + + /* Enter sleep */ + + esp32s3_rtc_sleep_init(pd_flags | RTC_SLEEP_NO_ULTRA_LOW); + + /* Set state machine time for light sleep */ + + if (deep_sleep == false) + { + esp32s3_rtc_sleep_low_init(g_config.rtc_clk_cal_period); + } + + /* Configure timer wakeup */ + + if (g_config.wakeup_triggers & RTC_TIMER_TRIG_EN) + { + esp32s3_timer_wakeup_prepare(); + } + + result = esp32s3_rtc_sleep_start(g_config.wakeup_triggers, 0); + + /* Restore CPU frequency */ + + esp32s3_rtc_clk_cpu_freq_set_config(&cpu_freq_config); + + if (deep_sleep == false) + { + g_config.ccount_ticks_record = XTHAL_GET_CCOUNT(); + } + + /* Re-enable UART output */ + + esp32s3_resume_uarts(); + + return result; +} + +/**************************************************************************** + * Name: esp32s3_light_sleep_inner + * + * Description: + * Enter low power mode, then wait for flash to be ready on wakeup + * + * Input Parameters: + * pd_flags - Power domains + * time_us - Time to wait for spi_flash become ready + * config - VDDSDIO configuration + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +static int IRAM_ATTR esp32s3_light_sleep_inner(uint32_t pd_flags, + uint32_t time_us, struct esp32s3_rtc_vddsdio_config_s config) +{ + /* Enter sleep */ + + int err = esp32s3_sleep_start(pd_flags); + + /* If VDDSDIO regulator was controlled by RTC registers before sleep. + * restore the configuration. + */ + + if (config.force) + { + esp32s3_set_vddsdio_config(config); + } + + /* If SPI flash was powered down, wait for it to become ready. */ + + if (pd_flags & RTC_SLEEP_PD_VDDSDIO) + { + /* Wait for the flash chip to start up. */ + + esp_rom_delay_us(time_us); + } + + return err; +} + +/**************************************************************************** + * Name: esp32s3_periph_should_skip_sleep + * + * Description: + * Indicates if light sleep shoule be skipped by peripherals + * + * Input Parameters: + * None + * + * Returned Value: + * True is returned on success. Otherwise false. + * + ****************************************************************************/ + +static inline bool IRAM_ATTR esp32s3_periph_should_skip_sleep(void) +{ + for (int i = 0; i < PERIPH_SKIP_SLEEP_NO; i++) + { + if (g_periph_skip_sleep_cb[i]) + { + if (g_periph_skip_sleep_cb[i]() == true) + { + return true; + } + } + } + + return false; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s3_pm_register_skip_sleep_callback + * + * Description: + * Unregister callback function of skipping light sleep. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_register_skip_sleep_callback(skip_light_sleep_cb_t cb) +{ + for (int i = 0; i < PERIPH_SKIP_SLEEP_NO; i++) + { + if (g_periph_skip_sleep_cb[i] == cb) + { + return OK; + } + else if (g_periph_skip_sleep_cb[i] == NULL) + { + g_periph_skip_sleep_cb[i] = cb; + return OK; + } + } + + return ERROR; +} + +/**************************************************************************** + * Name: esp32s3_pm_unregister_skip_sleep_callback + * + * Description: + * Register callback function of skipping light sleep. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_unregister_skip_sleep_callback(skip_light_sleep_cb_t cb) +{ + for (int i = 0; i < PERIPH_SKIP_SLEEP_NO; i++) + { + if (g_periph_skip_sleep_cb[i] == cb) + { + g_periph_skip_sleep_cb[i] = NULL; + return OK; + } + } + + return ERROR; +} + +/**************************************************************************** + * Name: esp32s3_should_skip_light_sleep + * + * Description: + * Indicates if light sleep shoule be skipped. + * + * Input Parameters: + * None + * + * Returned Value: + * True is returned on success. Otherwise false. + * + ****************************************************************************/ + +bool IRAM_ATTR esp32s3_should_skip_light_sleep(void) +{ + if (esp32s3_periph_should_skip_sleep() == true) + { + return true; + } + + return false; +} + +/**************************************************************************** + * Name: esp32s3_pm_register_inform_out_sleep_overhead_callback + * + * Description: + * Register informing peripherals of light sleep wakeup overhead time + * callback function. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_register_inform_out_sleep_overhead_callback( + inform_out_sleep_overhead_cb_t cb) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO; i++) + { + if (g_periph_inform_out_sleep_overhead_cb[i] == cb) + { + return ERROR; + } + else if (g_periph_inform_out_sleep_overhead_cb[i] == NULL) + { + g_periph_inform_out_sleep_overhead_cb[i] = cb; + return OK; + } + } + + return ERROR; +} + +/**************************************************************************** + * Name: esp32s3_pm_unregister_inform_out_sleep_overhead_callback + * + * Description: + * Unregister informing peripherals of light sleep wakeup overhead time + * callback function. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_unregister_inform_out_sleep_overhead_callback( + inform_out_sleep_overhead_cb_t cb) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO; i++) + { + if (g_periph_inform_out_sleep_overhead_cb[i] == cb) + { + g_periph_inform_out_sleep_overhead_cb[i] = NULL; + return OK; + } + } + + return ERROR; +} + +/**************************************************************************** + * Name: esp32s3_periph_inform_out_sleep_overhead + * + * Description: + * Inform peripherals of light sleep wakeup overhead time + * + * Input Parameters: + * us - Light sleep wakeup overhead time + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32s3_periph_inform_out_sleep_overhead(uint32_t us) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_SLEEP_OVERHEAD_NO; i++) + { + if (g_periph_inform_out_sleep_overhead_cb[i]) + { + g_periph_inform_out_sleep_overhead_cb[i](us); + } + } +} + +/**************************************************************************** + * Name: esp32s3_sleep_enable_timer_wakeup + * + * Description: + * Enable wakeup by timer + * + * Input Parameters: + * time_in_us - Configure wake-up time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32s3_sleep_enable_timer_wakeup(uint64_t time_in_us) +{ + g_config.wakeup_triggers |= RTC_TIMER_TRIG_EN; + g_config.sleep_duration = time_in_us; +} + +/**************************************************************************** + * Name: esp32s3_sleep_enable_wifi_wakeup + * + * Description: + * Configure Wi-Fi wake-up source + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_sleep_enable_wifi_wakeup(void) +{ + g_config.wakeup_triggers |= RTC_WIFI_TRIG_EN; +} + +/**************************************************************************** + * Name: esp32s3_light_sleep_start + * + * Description: + * Enter light sleep mode + * + * Input Parameters: + * sleep_time - Actual sleep time + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +int IRAM_ATTR esp32s3_light_sleep_start(uint64_t *sleep_time) +{ + int ret = OK; + irqstate_t flags; + uint32_t pd_flags; + uint32_t flash_enable_time_us; + uint32_t vddsdio_pd_sleep_duration; + struct esp32s3_rtc_vddsdio_config_s vddsdio_config; + uint32_t rtc_cntl_xtl_buf_wait_cycles; + uint32_t sleep_time_overhead_in; + uint32_t ccount_at_sleep_start; + int64_t final_sleep_us; + int64_t min_sleep_us; + + flags = enter_critical_section(); + + g_config.ccount_ticks_record = XTHAL_GET_CCOUNT(); + g_config.rtc_ticks_at_sleep_start = esp32s3_rtc_time_get(); + ccount_at_sleep_start = XTHAL_GET_CCOUNT(); + sleep_time_overhead_in = (ccount_at_sleep_start - + g_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); + + /* Decide which power domains can be powered down */ + + pd_flags = esp32s3_get_power_down_flags(); + pd_flags &= ~RTC_SLEEP_PD_RTC_PERIPH; + g_config.rtc_clk_cal_period = + esp32s3_rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES); + + /* Adjustment time consists of parts below: + * 1. Hardware time waiting for internal 8M oscilate clock and XTAL; + * 2. Hardware state swithing time of the rtc main state machine; + * 3. Code execution time when clock is not stable; + * 4. Code execution time which can be measured; + */ + + rtc_cntl_xtl_buf_wait_cycles = esp32s3_rtc_time_us_to_slowclk( + RTC_CNTL_XTL_BUF_WAIT_SLP_US, g_config.rtc_clk_cal_period); + + g_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + + sleep_time_overhead_in + g_config.sleep_time_overhead_out + + esp32s3_rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_cycles + + RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES, + g_config.rtc_clk_cal_period); + + flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US + + DEEP_SLEEP_WAKEUP_DELAY; + + esp32s3_periph_inform_out_sleep_overhead( + g_config.sleep_time_adjustment - sleep_time_overhead_in); + + esp32s3_get_vddsdio_config(&vddsdio_config); + + final_sleep_us = (int64_t)g_config.sleep_duration - + (int64_t)g_config.sleep_time_adjustment; + min_sleep_us = esp32s3_rtc_time_slowclk_to_us(RTC_CNTL_MIN_SLP_VAL_MIN, + g_config.rtc_clk_cal_period); + + /* If rtc timer wakeup source is enabled, need to compare final + * sleep duration and min sleep duration to avoid late wakeup + */ + + if ((g_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && + (final_sleep_us <= min_sleep_us)) + { + ret = ERROR; + } + else + { + /* Enter sleep, then wait for flash to be ready on wakeup */ + + ret = esp32s3_light_sleep_inner(pd_flags, flash_enable_time_us, + vddsdio_config); + } + + if (sleep_time != NULL) + { + *sleep_time = esp32s3_rtc_time_slowclk_to_us(esp32s3_rtc_time_get() - + g_config.rtc_ticks_at_sleep_start, g_config.rtc_clk_cal_period); + } + + g_config.sleep_time_overhead_out = (XTHAL_GET_CCOUNT() - + g_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); + + leave_critical_section(flags); + + return ret; +} + +/**************************************************************************** + * Name: esp32s3_pmstandby + * + * Description: + * Enter force sleep. + * + * Input Parameters: + * time_in_us - Force sleep time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_pmstandby(uint64_t time_in_us) +{ + uint64_t rtc_diff_us; + + /* Don't power down XTAL - powering it up takes different time on. */ + + esp32s3_sleep_enable_timer_wakeup(time_in_us); + esp32s3_light_sleep_start(&rtc_diff_us); + pwrinfo("Returned from auto-sleep, slept for %" PRIu32 " ms\n", + (uint32_t)(rtc_diff_us) / 1000); +} + +/**************************************************************************** + * Name: esp32s3_deep_sleep_start + * + * Description: + * Enter deep sleep mode + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32s3_deep_sleep_start(void) +{ + uint32_t pd_flags; + + /* Record current RTC time */ + + g_config.rtc_ticks_at_sleep_start = esp32s3_rtc_time_get(); + + /* Decide which power domains can be powered down */ + + pd_flags = esp32s3_get_power_down_flags(); + g_config.rtc_clk_cal_period = getreg32(RTC_SLOW_CLK_CAL_REG); + + /* Correct the sleep time */ + + g_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US; + + pd_flags |= RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | + RTC_SLEEP_PD_INT_8M | RTC_SLEEP_PD_XTAL; + + /* Enter deep sleep */ + + esp32s3_sleep_start(pd_flags); + + /* Because RTC is in a slower clock domain than the CPU, it + * can take several CPU cycles for the sleep mode to start. + */ + + while (1); +} + +/**************************************************************************** + * Name: esp32s3_pmsleep + * + * Description: + * Enter deep sleep. + * + * Input Parameters: + * time_in_us - Deep sleep time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_pmsleep(uint64_t time_in_us) +{ + esp32s3_sleep_enable_timer_wakeup(time_in_us); + esp32s3_deep_sleep_start(); +} + +/**************************************************************************** + * Name: esp32s3_pm_lockacquire + * + * Description: + * Take a power management lock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32s3_pm_lockacquire(void) +{ + ++pm_wakelock; +} + +/**************************************************************************** + * Name: esp32s3_pm_lockrelease + * + * Description: + * Release the lock taken using esp32s3_pm_lockacquire. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32s3_pm_lockrelease(void) +{ + --pm_wakelock; +} + +/**************************************************************************** + * Name: esp32s3_pm_lockstatus + * + * Description: + * Return power management lock status. + * + * Input Parameters: + * None + * + * Returned Value: + * Current pm_wakelock count + * + ****************************************************************************/ + +uint32_t IRAM_ATTR esp32s3_pm_lockstatus(void) +{ + return pm_wakelock; +} + +#endif /* CONFIG_PM */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_pm.h b/arch/xtensa/src/esp32s3/esp32s3_pm.h new file mode 100644 index 0000000000..00076170a3 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_pm.h @@ -0,0 +1,302 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_pm.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_PM_H +#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_PM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_PM + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Callback function type for peripherals to + * know light sleep wakeup overhead. + */ + +typedef void (*inform_out_sleep_overhead_cb_t)(uint32_t); + +/* Callback function type for peripherals to skip light sleep. */ + +typedef bool (*skip_light_sleep_cb_t)(void); + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32s3_sleep_enable_timer_wakeup + * + * Description: + * Configure wake-up interval + * + * Input Parameters: + * time_in_us - Configure wake-up time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_sleep_enable_timer_wakeup(uint64_t time_in_us); + +/**************************************************************************** + * Name: esp32s3_light_sleep_start + * + * Description: + * Enter light sleep mode + * + * Input Parameters: + * sleep_time - Actual sleep time + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +int esp32s3_light_sleep_start(uint64_t *sleep_time); + +/**************************************************************************** + * Name: esp32s3_pmstandby + * + * Description: + * Enter force sleep time interval. + * + * Input Parameters: + * time_in_us - Force sleep time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_pmstandby(uint64_t time_in_us); + +/**************************************************************************** + * Name: esp32s3_deep_sleep_start + * + * Description: + * Enter deep sleep mode + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_deep_sleep_start(void); + +/**************************************************************************** + * Name: esp32s3_pmsleep + * + * Description: + * Enter deep sleep. + * + * Input Parameters: + * time_in_us - Deep sleep time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_pmsleep(uint64_t time_in_us); + +/**************************************************************************** + * Name: esp32s3_pm_lockacquire + * + * Description: + * Take a power management lock + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_pm_lockacquire(void); + +/**************************************************************************** + * Name: esp32s3_pm_lockrelease + * + * Description: + * Release the lock taken using esp32s3_pm_lockacquire. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_pm_lockrelease(void); + +/**************************************************************************** + * Name: esp32s3_pm_lockstatus + * + * Description: + * Return power management lock status. + * + * Input Parameters: + * None + * + * Returned Value: + * Current pm_wakelock count + * + ****************************************************************************/ + +uint32_t esp32s3_pm_lockstatus(void); + +/**************************************************************************** + * Name: esp32s3_sleep_enable_wifi_wakeup + * + * Description: + * Configure Wi-Fi wake-up source + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_sleep_enable_wifi_wakeup(void); + +/**************************************************************************** + * Name: esp32s3_should_skip_light_sleep + * + * Description: + * Indicates if light sleep shoule be skipped. + * + * Input Parameters: + * None + * + * Returned Value: + * True is returned on success. Otherwise false. + * + ****************************************************************************/ + +bool esp32s3_should_skip_light_sleep(void); + +/**************************************************************************** + * Name: esp32s3_pm_register_inform_out_sleep_overhead_callback + * + * Description: + * Register informing peripherals of light sleep wakeup overhead time + * callback function. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_register_inform_out_sleep_overhead_callback( + inform_out_sleep_overhead_cb_t cb); + +/**************************************************************************** + * Name: esp32s3_pm_unregister_inform_out_sleep_overhead_callback + * + * Description: + * Unregister informing peripherals of light sleep wakeup overhead time + * callback function. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_unregister_inform_out_sleep_overhead_callback( + inform_out_sleep_overhead_cb_t cb); + +/**************************************************************************** + * Name: esp32s3_pm_register_skip_sleep_callback + * + * Description: + * Unregister callback function of skipping light sleep. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_register_skip_sleep_callback(skip_light_sleep_cb_t cb); + +/**************************************************************************** + * Name: esp32s3_pm_unregister_skip_sleep_callback + * + * Description: + * Register callback function of skipping light sleep. + * + * Input Parameters: + * cb - Callback function + * + * Returned Value: + * Zero (OK) is returned on success. Otherwise -1 (ERROR). + * + ****************************************************************************/ + +int esp32s3_pm_unregister_skip_sleep_callback(skip_light_sleep_cb_t cb); + +#endif /* CONFIG_PM */ + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_PM_H */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_pminitialize.c b/arch/xtensa/src/esp32s3/esp32s3_pminitialize.c new file mode 100644 index 0000000000..9b759c9056 --- /dev/null +++ b/arch/xtensa/src/esp32s3/esp32s3_pminitialize.c @@ -0,0 +1,49 @@ +/**************************************************************************** + * arch/xtensa/src/esp32s3/esp32s3_pminitialize.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#ifdef CONFIG_PM + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: xtensa_pminitialize + * + * Description: + * Initialize the power management subsystem. + * + ****************************************************************************/ + +void xtensa_pminitialize(void) +{ + /* Initialize the NuttX power management subsystem proper */ + + pm_initialize(); +} + +#endif /* CONFIG_PM */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.c b/arch/xtensa/src/esp32s3/esp32s3_rtc.c index 0c688d84fe..dd68de4263 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.c +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.c @@ -33,6 +33,7 @@ #include "esp32s3_clockconfig.h" #include "esp32s3_rt_timer.h" +#include "esp32s3_reset_reasons.h" #include "hardware/esp32s3_bb.h" #include "hardware/esp32s3_nrx.h" @@ -118,18 +119,24 @@ #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) -/* set sleep_init default param. */ +/* Set sleep_init default param */ -#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT 5 -#define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT 15 -#define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT 0 -#define RTC_CNTL_BIASSLP_MONITOR_DEFAULT 0 -#define RTC_CNTL_BIASSLP_SLEEP_ON 0 -#define RTC_CNTL_BIASSLP_SLEEP_DEFAULT 1 -#define RTC_CNTL_PD_CUR_MONITOR_DEFAULT 1 -#define RTC_CNTL_PD_CUR_SLEEP_ON 0 -#define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 -#define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 0xf +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT (5) +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP (0) +#define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT (14) +#define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_ULTRA_LOW (15) +#define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP (0) +#define RTC_CNTL_BIASSLP_SLEEP_DEFAULT (1) +#define RTC_CNTL_BIASSLP_SLEEP_ON (0) +#define RTC_CNTL_PD_CUR_SLEEP_DEFAULT (1) +#define RTC_CNTL_PD_CUR_SLEEP_ON (0) +#define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT (0xf) + +#define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT (0) +#define RTC_CNTL_BIASSLP_MONITOR_DEFAULT (1) +#define RTC_CNTL_BIASSLP_MONITOR_ON (0) +#define RTC_CNTL_PD_CUR_MONITOR_DEFAULT (1) +#define RTC_CNTL_PD_CUR_MONITOR_ON (0) /* Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP, * RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values. @@ -164,22 +171,15 @@ .wifi_pd_en = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \ .bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \ .cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \ - .int_8m_pd_en = is_dslp(sleep_flags) ? 1 : ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \ + .int_8m_pd_en = ((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? 1 : 0, \ .dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \ .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \ .wdt_flashboot_mod_en = 0, \ - .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .dig_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ - : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ - : RTC_CNTL_DBIAS_SLP, \ - .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ - .rtc_dbias_slp = is_dslp(sleep_flags) ? RTC_CNTL_DBIAS_SLP \ - : !((sleep_flags) & RTC_SLEEP_PD_INT_8M) ? RTC_CNTL_DBIAS_1V10 \ - : RTC_CNTL_DBIAS_SLP, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ - .xtal_fpu = is_dslp(sleep_flags) ? 0 : ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ + .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1, \ .deep_slp_reject = 1, \ - .light_slp_reject = 1 \ + .light_slp_reject = 1, \ + .rtc_dbias_slp = RTC_CNTL_DBIAS_1V10, \ } #define X32K_CONFIG_DEFAULT() { \ @@ -220,7 +220,7 @@ .xtal_fpu = 0, \ .bbpll_fpu = 0, \ .cpu_waiti_clk_gate = 1, \ - .cali_ocode = 0\ + .cali_ocode = 0 \ } /* The magic data for the struct esp32s3_rtc_backup_s that is in RTC slow @@ -276,12 +276,16 @@ struct esp32s3_rtc_sleep_config_s uint32_t dig_peri_pd_en : 1; /* power down digital peripherals */ uint32_t deep_slp : 1; /* power down digital domain */ uint32_t wdt_flashboot_mod_en : 1; /* enable WDT flashboot mode */ - uint32_t dig_dbias_wak : 5; /* set bias for digital domain, in active mode */ uint32_t dig_dbias_slp : 5; /* set bias for digital domain, in sleep mode */ - uint32_t rtc_dbias_wak : 5; /* set bias for RTC domain, in active mode */ uint32_t rtc_dbias_slp : 5; /* set bias for RTC domain, in sleep mode */ + uint32_t bias_sleep_monitor : 1; /* circuit control parameter, in monitor mode */ + uint32_t dbg_atten_slp : 4; /* voltage parameter, in sleep mode */ + uint32_t bias_sleep_slp : 1; /* circuit control parameter, in sleep mode */ + uint32_t pd_cur_monitor : 1; /* circuit control parameter, in monitor mode */ + uint32_t pd_cur_slp : 1; /* circuit control parameter, in sleep mode */ uint32_t vddsdio_pd_en : 1; /* power down VDDSDIO regulator */ uint32_t xtal_fpu : 1; /* keep main XTAL powered up in sleep */ + uint32_t rtc_regulator_fpu : 1; /* keep rtc regulator powered up in sleep */ uint32_t deep_slp_reject : 1; uint32_t light_slp_reject : 1; }; @@ -349,6 +353,8 @@ static RTC_DATA_ATTR struct esp32s3_rtc_backup_s rtc_saved_data; static struct esp32s3_rtc_backup_s *g_rtc_save; static bool g_rt_timer_enabled = false; +static uint32_t g_dig_dbias_pvt_non_240m = 27; +static uint32_t g_rtc_dbias_pvt_non_240m = 27; /**************************************************************************** * Private Function Prototypes @@ -407,6 +413,10 @@ extern void ets_update_cpu_frequency(uint32_t ticks_per_us); extern void esp_rom_delay_us(uint32_t us); +/* Get the reset reason for CPU. */ + +extern soc_reset_reason_t esp_rom_get_reset_reason(int cpu_no); + /**************************************************************************** * Name: esp32s3_rtc_sleep_pu * @@ -414,7 +424,7 @@ extern void esp_rom_delay_us(uint32_t us); * Configure whether certain peripherals are powered up in deep sleep. * * Input Parameters: - * cfg - power down flags as rtc_sleep_pu_config_t structure + * cfg - Power down flags as rtc_sleep_pu_config_t structure * * Returned Value: * None @@ -496,7 +506,7 @@ static void IRAM_ATTR esp32s3_rtc_clk_fast_freq_set( * These are the routines to work with such a representation. * * Input Parameters: - * val - register value + * val - Register value * * Returned Value: * true: Valid register value. @@ -517,8 +527,8 @@ static inline bool esp32s3_clk_val_is_valid(uint32_t val) * Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio * * Input Parameters: - * cal_clk - which clock to calibrate - * slowclk_cycles - number of slow clock cycles to count. + * cal_clk - Which clock to calibrate + * slowclk_cycles - Number of slow clock cycles to count. * * Returned Value: * Number of XTAL clock cycles within the given number of slow clock @@ -590,7 +600,7 @@ static uint32_t IRAM_ATTR esp32s3_rtc_clk_cal_internal( if (cal_clk == RTC_CAL_32K_XTAL || slow_freq == RTC_SLOW_FREQ_32K_XTAL) { - expected_freq = 32768; /* standard 32k XTAL */ + expected_freq = 32768; /* Standard 32k XTAL */ } else if (cal_clk == RTC_CAL_8MD256 || slow_freq == RTC_SLOW_FREQ_8MD256) { @@ -664,8 +674,8 @@ static void esp32s3_wait_dig_dbias_valid(uint64_t rtc_cycles) * Switch to XTAL frequency, does not disable the PLL * * Input Parameters: - * freq - XTAL frequency - * div - REF_TICK divider + * freq - XTAL frequency + * div - REF_TICK divider * * Returned Value: * none @@ -676,7 +686,7 @@ void IRAM_ATTR esp32s3_rtc_update_to_xtal(int freq, int div) { ets_update_cpu_frequency(freq); - /* set digital voltage for different cpu freq from xtal */ + /* Set digital voltage for different cpu freq from xtal */ if (freq <= 2) { @@ -740,7 +750,7 @@ static void IRAM_ATTR esp32s3_rtc_clk_slow_freq_set( * Enable 32 kHz XTAL oscillator * * Input Parameters: - * enable - boolean Enable/Disable + * enable - True to enable, false to disable * * Returned Value: * None @@ -781,8 +791,8 @@ static void IRAM_ATTR esp32s3_rtc_clk_32k_enable(bool enable) * Enable or disable 8 MHz internal oscillator * * Input Parameters: - * clk_8m_en - true to enable 8MHz generator, false to disable - * d256_en - true to enable /256 divider, false to disable + * clk_8m_en - True to enable 8MHz generator, false to disable + * d256_en - True to enable /256 divider, false to disable * * Returned Value: * None @@ -1225,8 +1235,8 @@ enum esp32s3_rtc_slow_freq_e IRAM_ATTR esp32s3_rtc_get_slow_clk(void) * Measure RTC slow clock's period, based on main XTAL frequency * * Input Parameters: - * cal_clk - clock to be measured - * slowclk_cycles - number of slow clock cycles to average + * cal_clk - Clock to be measured + * slowclk_cycles - Number of slow clock cycles to average * * Returned Value: * Average slow clock period in microseconds, Q13.19 fixed point format @@ -1285,7 +1295,7 @@ enum esp32s3_rtc_xtal_freq_e IRAM_ATTR esp32s3_rtc_clk_xtal_freq_get(void) * Name: esp32s3_rtc_clk_bbpll_disable * * Description: - * disable BBPLL. + * Disable BBPLL. * * Input Parameters: * None @@ -1508,17 +1518,27 @@ void esp32s3_rtc_clk_set(void) void IRAM_ATTR esp32s3_rtc_init(void) { struct esp32s3_rtc_priv_s cfg = RTC_CONFIG_DEFAULT(); + soc_reset_reason_t rst_reas = esp_rom_get_reset_reason(0); + + /* When power on, we need to set `cali_ocode` to 1, to do a OCode + * calibration, which will calibrate the rtc reference voltage to a + * tested value + */ + + if (rst_reas == RESET_REASON_CHIP_POWER_ON) + { + cfg.cali_ocode = 1; + } REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); modifyreg32(RTC_CNTL_RTC_ANA_CONF_REG, RTC_CNTL_PVTMON_PU, 0); - modifyreg32(RTC_CNTL_RTC_TIMER1_REG, 0, - cfg.pll_wait ? RTC_CNTL_PLL_BUF_WAIT : 0); - - modifyreg32(RTC_CNTL_RTC_TIMER1_REG, 0, - cfg.ck8m_wait ? RTC_CNTL_CK8M_WAIT : 0); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, + cfg.pll_wait); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER1_REG, RTC_CNTL_CK8M_WAIT, + cfg.ck8m_wait); /* Moved from rtc sleep to rtc init to save sleep function running time */ @@ -1537,6 +1557,21 @@ void IRAM_ATTR esp32s3_rtc_init(void) REG_SET_FIELD(RTC_CNTL_RTC_TIMER3_REG, RTC_CNTL_BT_POWERUP_TIMER, 1); REG_SET_FIELD(RTC_CNTL_RTC_TIMER3_REG, RTC_CNTL_BT_WAIT_TIMER, 1); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER6_REG, RTC_CNTL_CPU_TOP_POWERUP_TIMER, 1); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER6_REG, RTC_CNTL_CPU_TOP_WAIT_TIMER, 1); + + /* Set rtc peri timer */ + + REG_SET_FIELD(RTC_CNTL_RTC_TIMER4_REG, RTC_CNTL_RTC_POWERUP_TIMER, 1); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER4_REG, RTC_CNTL_RTC_WAIT_TIMER, 1); + + /* Set digital wrap timer */ + + REG_SET_FIELD(RTC_CNTL_RTC_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER, 1); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER, 1); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER6_REG, RTC_CNTL_DG_PERI_POWERUP_TIMER, 1); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER6_REG, RTC_CNTL_DG_PERI_WAIT_TIMER, 1); + /* Reset RTC bias to default value (needed if waking up from deep sleep) */ REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, @@ -1544,6 +1579,10 @@ void IRAM_ATTR esp32s3_rtc_init(void) REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, RTC_CNTL_DBIAS_1V10); + /* Set the wait time to the default value. */ + + REG_SET_FIELD(RTC_CNTL_RTC_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, + RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT); if (cfg.cali_ocode) { /* TODO: Use calibration from efuse if configured */ @@ -1551,6 +1590,10 @@ void IRAM_ATTR esp32s3_rtc_init(void) esp32s3_rtc_calibrate_ocode(); } + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, + g_rtc_dbias_pvt_non_240m); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, + g_dig_dbias_pvt_non_240m); if (cfg.clkctl_init) { /* clear CMMU clock force on */ @@ -1700,6 +1743,13 @@ void IRAM_ATTR esp32s3_rtc_init(void) modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD | RTC_CNTL_DG_PAD_FORCE_NOISO, 0); } + + /* force power down wifi and bt power domain */ + + modifyreg32(RTC_CNTL_DIG_ISO_REG, 0, RTC_CNTL_WIFI_FORCE_ISO); + modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_WIFI_FORCE_PD); + putreg32(0, RTC_CNTL_INT_ENA_RTC_REG); + putreg32(UINT32_MAX, RTC_CNTL_INT_CLR_RTC_REG); } /**************************************************************************** @@ -1809,7 +1859,7 @@ uint32_t IRAM_ATTR esp32s3_clk_slowclk_cal_get(void) * Set target value of RTC counter for RTC_TIMER_TRIG_EN wakeup source. * * Input Parameters: - * t - value of RTC counter at which wakeup from sleep will happen. + * t - Value of RTC counter at which wakeup from sleep will happen. * * Returned Value: * None @@ -1820,6 +1870,10 @@ void IRAM_ATTR esp32s3_rtc_sleep_set_wakeup_time(uint64_t t) { putreg32(t & UINT32_MAX, RTC_CNTL_RTC_SLP_TIMER0_REG); putreg32((uint32_t)(t >> 32), RTC_CNTL_RTC_SLP_TIMER1_REG); + modifyreg32(RTC_CNTL_INT_CLR_RTC_REG, 0, + RTC_CNTL_RTC_MAIN_TIMER_INT_CLR_M); + modifyreg32(RTC_CNTL_RTC_SLP_TIMER1_REG, 0, + RTC_CNTL_RTC_MAIN_TIMER_ALARM_EN_M); } /**************************************************************************** @@ -1993,6 +2047,126 @@ int IRAM_ATTR esp_rtc_clk_get_cpu_freq(void) void IRAM_ATTR esp32s3_rtc_sleep_init(uint32_t flags) { struct esp32s3_rtc_sleep_config_s cfg = RTC_SLEEP_CONFIG_DEFAULT(flags); + if (flags & RTC_SLEEP_PD_DIG) + { + DEBUGASSERT(flags & RTC_SLEEP_PD_XTAL); + cfg.dig_dbias_slp = 0; + + /* RTC voltage from high to low */ + + if ((flags & RTC_SLEEP_USE_ADC_TESEN_MONITOR) || + (!(flags & RTC_SLEEP_PD_INT_8M))) + { + /* RTC voltage in sleep mode >= 0.9v if 8MD256 select as RTC + * slow clock src, only need dbg_atten_slp set to 0 + * Support all features: + * - 8MD256 as RTC slow clock src + * - ADC/Temperature sensor in monitor mode (ULP) + * (also need pd_cur_monitor = 0) + * - RTC IO as input + * - RTC Memory at high temperature + * - ULP + * - Touch sensor + */ + + cfg.rtc_regulator_fpu = 1; + cfg.dbg_atten_slp = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP; + } + else if (flags & RTC_SLEEP_NO_ULTRA_LOW) + { + /* RTC voltage in sleep mode >= 0.7v (default mode): + * Support follow features: + * - RTC IO as input + * - RTC Memory at high temperature + * - ULP + * - Touch sensor + */ + + cfg.rtc_regulator_fpu = 1; + cfg.dbg_atten_slp = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT; + } + else + { + /* RTC regulator not opened and rtc voltage is about 0.66v + * (ultra low power). + * Support follow features: + * - ULP + * - Touch sensor + */ + + cfg.rtc_regulator_fpu = 0; + cfg.dbg_atten_slp = RTC_CNTL_DBG_ATTEN_DEEPSLEEP_ULTRA_LOW; + } + } + else + { + cfg.rtc_regulator_fpu = 1; + + /* Voltage from high to low */ + + if ((flags & RTC_SLEEP_DIG_USE_8M) || !(flags & RTC_SLEEP_PD_XTAL)) + { + /* digital voltage not less than 1.1v, rtc voltage is about 1.1v + * Support all features: + * - XTAL + * - RC 8M used by digital system + * - 8MD256 as RTC slow clock src (only need dbg_atten_slp to 0) + * - ADC/Temperature sensor in monitor mode (ULP) + * (also need pd_cur_monitor = 0) + * - ULP + * - Touch sensor + */ + + cfg.dbg_atten_slp = RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP; + cfg.dig_dbias_slp = RTC_CNTL_DBIAS_1V10; + } + else if (!(flags & RTC_SLEEP_PD_INT_8M)) + { + /* dbg_atten_slp need to set to 0. + * digital voltage is about 0.67v, rtc voltage is about 1.1v + * Support features: + * - 8MD256 as RTC slow clock src + * - ADC/Temperature sensor in monitor mode (ULP) + * (also need pd_cur_monitor = 0) + * - ULP + * - Touch sensor + */ + + cfg.dbg_atten_slp = RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP; + cfg.dig_dbias_slp = 0; + } + else + { + /* digital voltage not less than 0.6v, rtc voltage is about 0.95v + * Support features: + * - ADC/Temperature sensor in monitor mode (ULP) + * (also need pd_cur_monitor = 0) + * - ULP + * - Touch sensor + */ + + cfg.dbg_atten_slp = RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT; + cfg.dig_dbias_slp = RTC_CNTL_DBIAS_SLP; + } + } + + if (!(flags & RTC_SLEEP_PD_XTAL)) + { + cfg.bias_sleep_monitor = RTC_CNTL_BIASSLP_MONITOR_ON; + cfg.pd_cur_monitor = RTC_CNTL_PD_CUR_MONITOR_ON; + cfg.bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_ON; + cfg.pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_ON; + } + else + { + cfg.bias_sleep_monitor = RTC_CNTL_BIASSLP_MONITOR_DEFAULT; + cfg.pd_cur_monitor = (flags & RTC_SLEEP_USE_ADC_TESEN_MONITOR) ? + RTC_CNTL_PD_CUR_MONITOR_ON : + RTC_CNTL_PD_CUR_MONITOR_DEFAULT; + + cfg.bias_sleep_slp = RTC_CNTL_BIASSLP_SLEEP_DEFAULT; + cfg.pd_cur_slp = RTC_CNTL_PD_CUR_SLEEP_DEFAULT; + } /* Starts here */ @@ -2031,7 +2205,7 @@ void IRAM_ATTR esp32s3_rtc_sleep_init(uint32_t flags) { modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CPU_TOP_FORCE_NOISO | RTC_CNTL_CPU_TOP_FORCE_ISO, 0); - modifyreg32(RTC_CNTL_RTC_PWC_REG, RTC_CNTL_CPU_TOP_FORCE_PU, + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_FORCE_PU, RTC_CNTL_CPU_TOP_PD_EN); } else @@ -2043,103 +2217,94 @@ void IRAM_ATTR esp32s3_rtc_sleep_init(uint32_t flags) { modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PERI_FORCE_NOISO | RTC_CNTL_DG_PERI_FORCE_ISO, 0); - modifyreg32(RTC_CNTL_RTC_PWC_REG, RTC_CNTL_DG_PERI_FORCE_PU, + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_FORCE_PU, RTC_CNTL_DG_PERI_PD_EN); } else { - modifyreg32(RTC_CNTL_RTC_PWC_REG, RTC_CNTL_DG_PERI_PD_EN, 0); + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN, 0); } if (cfg.rtc_peri_pd_en) { - modifyreg32(RTC_CNTL_RTC_PWC_REG, 0, RTC_CNTL_RTC_PD_EN); + modifyreg32(RTC_CNTL_RTC_PWC_REG, RTC_CNTL_RTC_FORCE_NOISO | + RTC_CNTL_RTC_FORCE_ISO | RTC_CNTL_RTC_FORCE_PU, + RTC_CNTL_RTC_PD_EN); } else { modifyreg32(RTC_CNTL_RTC_PWC_REG, RTC_CNTL_RTC_PD_EN, 0); } + DEBUGASSERT(!cfg.pd_cur_monitor || cfg.bias_sleep_monitor); + DEBUGASSERT(!cfg.pd_cur_slp || cfg.bias_sleep_slp); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, + cfg.rtc_dbias_slp); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG_SLEEP, + cfg.dig_dbias_slp); + + REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, + cfg.dbg_atten_slp); + REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, + cfg.bias_sleep_slp); + REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, + cfg.pd_cur_slp); REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR, RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT); REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR, - RTC_CNTL_BIASSLP_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP, - (!cfg.deep_slp && cfg.xtal_fpu) ? - RTC_CNTL_BIASSLP_SLEEP_ON : - RTC_CNTL_BIASSLP_SLEEP_DEFAULT); + cfg.bias_sleep_monitor); REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR, - RTC_CNTL_PD_CUR_MONITOR_DEFAULT); - REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP, - (!cfg.deep_slp && cfg.xtal_fpu) ? RTC_CNTL_PD_CUR_SLEEP_ON : - RTC_CNTL_PD_CUR_SLEEP_DEFAULT); + cfg.pd_cur_monitor); if (cfg.deep_slp) { - modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_ISO | - RTC_CNTL_DG_PAD_FORCE_NOISO, 0); - - /* Shut down parts of RTC which may have been left - * enabled by the wireless drivers. - */ - + modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_DG_WRAP_PD_EN); modifyreg32(RTC_CNTL_RTC_ANA_CONF_REG, RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU | RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU, 0); } else { + REG_SET_FIELD(RTC_CNTL_RTC_REGULATOR_DRV_CTRL_REG, + RTC_CNTL_DG_VDD_DRV_B_SLP, + RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT); modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN, 0); - REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, - RTC_CNTL_DBG_ATTEN_DEEP_SLP, 0); } - REG_SET_FIELD(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, - cfg.xtal_fpu); + /* Mem force pu */ - if (REG_GET_FIELD(RTC_CNTL_RTC_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL) == - RTC_SLOW_FREQ_8MD256) + modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_LSLP_MEM_FORCE_PU); + modifyreg32(RTC_CNTL_RTC_PWC_REG, 0, RTC_CNTL_RTC_FASTMEM_FORCE_LPU | + RTC_CNTL_RTC_SLOWMEM_FORCE_LPU); + REG_SET_FIELD(RTC_CNTL_RTC_REG, RTC_CNTL_RTC_REGULATOR_FORCE_PU, + cfg.rtc_regulator_fpu); + if (!cfg.int_8m_pd_en) { - modifyreg32(RTC_CNTL_RTC_CLK_CONF_REG, 0, RTC_CNTL_CK8M_FORCE_PU); + REG_SET_BIT(RTC_CNTL_RTC_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); } else { - modifyreg32(RTC_CNTL_RTC_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, 0); + REG_CLR_BIT(RTC_CNTL_RTC_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); } - /* Keep the RTC8M_CLK on in light_sleep mode if the - * ledc low-speed channel is clocked by RTC8M_CLK. - */ + /* Enable VDDSDIO control by state machine */ - if (!cfg.deep_slp && GET_PERI_REG_MASK(RTC_CNTL_RTC_CLK_CONF_REG, - RTC_CNTL_DIG_CLK8M_EN_M)) - { - REG_CLR_BIT(RTC_CNTL_RTC_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PD); - REG_SET_BIT(RTC_CNTL_RTC_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU); - } - - /* enable VDDSDIO control by state machine */ - - modifyreg32(RTC_CNTL_RTC_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE, 0); + REG_CLR_BIT(RTC_CNTL_RTC_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE); REG_SET_FIELD(RTC_CNTL_RTC_SDIO_CONF_REG, RTC_CNTL_SDIO_REG_PD_EN, cfg.vddsdio_pd_en); - - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, - cfg.rtc_dbias_slp); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, - cfg.rtc_dbias_wak); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG_SLEEP, - cfg.dig_dbias_slp); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, - cfg.dig_dbias_wak); - REG_SET_FIELD(RTC_CNTL_RTC_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN, cfg.deep_slp_reject); REG_SET_FIELD(RTC_CNTL_RTC_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN, cfg.light_slp_reject); - REG_SET_FIELD(RTC_CNTL_RTC_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, - cfg.xtal_fpu); + /* Set wait cycle for touch or COCPU after deep sleep and light sleep. */ + + REG_SET_FIELD(RTC_CNTL_RTC_TIMER2_REG, + RTC_CNTL_ULPCP_TOUCH_START_WAIT, + RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP); + + REG_SET_FIELD(RTC_CNTL_RTC_OPTIONS0_REG, + RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); REG_SET_FIELD(RTC_CNTL_RTC_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING, cfg.xtal_fpu); } @@ -2151,8 +2316,8 @@ void IRAM_ATTR esp32s3_rtc_sleep_init(uint32_t flags) * Enter force sleep mode. * * Input Parameters: - * wakeup_opt - bit mask wake up reasons to enable - * reject_opt - bit mask of sleep reject reasons. + * wakeup_opt - Bit mask wake up reasons to enable + * reject_opt - Bit mask of sleep reject reasons. * * Returned Value: * non-zero if sleep was rejected by hardware @@ -2165,7 +2330,11 @@ int IRAM_ATTR esp32s3_rtc_sleep_start(uint32_t wakeup_opt, int reject; REG_SET_FIELD(RTC_CNTL_RTC_WAKEUP_STATE_REG, RTC_CNTL_RTC_WAKEUP_ENA, wakeup_opt); - putreg32((uint32_t)reject_opt, RTC_CNTL_RTC_SLP_REJECT_CONF_REG); + REG_SET_FIELD(RTC_CNTL_RTC_SLP_REJECT_CONF_REG, + RTC_CNTL_RTC_SLEEP_REJECT_ENA, reject_opt); + + modifyreg32(RTC_CNTL_INT_CLR_RTC_REG, 0, + RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR); /* Start entry into sleep mode */ @@ -2182,10 +2351,11 @@ int IRAM_ATTR esp32s3_rtc_sleep_start(uint32_t wakeup_opt, modifyreg32(RTC_CNTL_INT_CLR_RTC_REG, 0, RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR); - /* restore DBG_ATTEN to the default value */ + /* Recover default wait cycle for touch or COCPU after wakeup. */ + + REG_SET_FIELD(RTC_CNTL_RTC_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT, + RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT); - REG_SET_FIELD(RTC_CNTL_RTC_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, - RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT); return reject; } @@ -2405,6 +2575,34 @@ void IRAM_ATTR esp32s3_rtc_bbpll_disable(void) RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); } +/**************************************************************************** + * Name: esp32c3_rtc_sleep_low_init + * + * Description: + * Low level initialize for rtc state machine waiting + * cycles after waking up. + * + * Input Parameters: + * slowclk_period - Re-calibrated slow clock period + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32s3_rtc_sleep_low_init(uint32_t slowclk_period) +{ + /* Set 5 PWC state machine times to fit in main state machine time */ + + REG_SET_FIELD(RTC_CNTL_RTC_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, + RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, + esp32s3_rtc_time_us_to_slowclk( + RTC_CNTL_XTL_BUF_WAIT_SLP_US, slowclk_period)); + REG_SET_FIELD(RTC_CNTL_RTC_TIMER1_REG, RTC_CNTL_CK8M_WAIT, + RTC_CNTL_CK8M_WAIT_SLP_CYCLES); +} + /**************************************************************************** * Name: esp32s3_rtc_set_boot_time * @@ -2412,7 +2610,7 @@ void IRAM_ATTR esp32s3_rtc_bbpll_disable(void) * Set time to RTC register to replace the original boot time. * * Input Parameters: - * time_us - set time in microseconds. + * time_us - Set time in microseconds. * * Returned Value: * None @@ -2435,7 +2633,7 @@ void IRAM_ATTR esp32s3_rtc_set_boot_time(uint64_t time_us) * None * * Returned Value: - * time_us - get time in microseconds. + * time_us - Get time in microseconds. * ****************************************************************************/ @@ -2540,7 +2738,7 @@ time_t up_rtc_time(void) * able to set their time based on a standard timespec. * * Input Parameters: - * ts - the time to use + * ts - The time to use * * Returned Value: * Zero (OK) on success; a negated errno on failure diff --git a/arch/xtensa/src/esp32s3/esp32s3_rtc.h b/arch/xtensa/src/esp32s3/esp32s3_rtc.h index 0adcfb5939..7ad11eec4d 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_rtc.h +++ b/arch/xtensa/src/esp32s3/esp32s3_rtc.h @@ -68,6 +68,21 @@ extern "C" #define RTC_CLK_CAL_FRACT 19 +/* Cycles for RTC Timer clock source (internal oscillator) calibrate */ + +#define RTC_CLK_SRC_CAL_CYCLES (10) + +#define RTC_CNTL_XTL_BUF_WAIT_SLP_US (250) +#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES (1) +#define RTC_CNTL_CK8M_WAIT_SLP_CYCLES (4) +#define RTC_CNTL_WAKEUP_DELAY_CYCLES (4) + +#define RTC_CNTL_CK8M_DFREQ_DEFAULT 100 +#define RTC_CNTL_SCK_DCAP_DEFAULT 255 + +#define RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP (0xFF) +#define RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT (0x10) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -350,6 +365,23 @@ void esp32s3_rtc_init(void); uint64_t esp32s3_rtc_time_get(void); +/**************************************************************************** + * Name: esp32s3_rtc_sleep_low_init + * + * Description: + * Low level initialize for rtc state machine waiting + * cycles after waking up. + * + * Input Parameters: + * slowclk_period - Re-calibrated slow clock period + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32s3_rtc_sleep_low_init(uint32_t slowclk_period); + /**************************************************************************** * Name: esp32s3_rtc_time_us_to_slowclk * diff --git a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h index df327581af..3a8ab206f0 100644 --- a/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h +++ b/arch/xtensa/src/esp32s3/hardware/esp32s3_rtccntl.h @@ -5893,4 +5893,15 @@ #define RTC_SLEEP_PD_XTAL BIT(11) +/* These flags are not power domains, but will affect some sleep parameters */ + +#define RTC_SLEEP_DIG_USE_8M BIT(16) +#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17) + +/* Avoid using ultra low power in deep sleep, in which RTCIO cannot + * be used as input, and RTCMEM can't work under high temperature + */ + +#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) + #endif /* __ARCH_XTENSA_SRC_ESP32S3_HARDWARE_ESP32S3_RTCCNTL_H */ diff --git a/arch/xtensa/src/esp32s3/hardware/esp32s3_uart.h b/arch/xtensa/src/esp32s3/hardware/esp32s3_uart.h index 5258b439ae..b893811de1 100644 --- a/arch/xtensa/src/esp32s3/hardware/esp32s3_uart.h +++ b/arch/xtensa/src/esp32s3/hardware/esp32s3_uart.h @@ -860,7 +860,7 @@ * Rx Filter configuration */ -#define UART_RX_FILT_REG (DR_REG_UART_BASE + 0x18) +#define UART_RX_FILT_REG(i) (REG_UART_BASE(i) + 0x18) /* UART_GLITCH_FILT_EN : R/W; bitpos: [8]; default: 0; * Set this bit to enable Rx signal filter. @@ -1280,7 +1280,7 @@ * Autobaud minimum low pulse duration register */ -#define UART_LOWPULSE_REG (DR_REG_UART_BASE + 0x28) +#define UART_LOWPULSE_REG(i) (REG_UART_BASE(i) + 0x28) /* UART_LOWPULSE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; * This register stores the value of the minimum duration time of the low @@ -1296,7 +1296,7 @@ * Autobaud minimum high pulse duration register */ -#define UART_HIGHPULSE_REG (DR_REG_UART_BASE + 0x2c) +#define UART_HIGHPULSE_REG(i) (REG_UART_BASE(i) + 0x2c) /* UART_HIGHPULSE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; * This register stores the value of the maximum duration time for the high @@ -1312,7 +1312,7 @@ * Autobaud edge change count register */ -#define UART_RXD_CNT_REG (DR_REG_UART_BASE + 0x30) +#define UART_RXD_CNT_REG(i) (REG_UART_BASE(i) + 0x30) /* UART_RXD_EDGE_CNT : RO; bitpos: [9:0]; default: 0; * This register stores the count of rxd edge change. It is used in baud @@ -1328,7 +1328,7 @@ * Software flow-control configuration */ -#define UART_FLOW_CONF_REG (DR_REG_UART_BASE + 0x34) +#define UART_FLOW_CONF_REG(i) (REG_UART_BASE(i) + 0x34) /* UART_SEND_XOFF : R/W/SS/SC; bitpos: [5]; default: 0; * Set this bit to send Xoff char. It is cleared by hardware automatically. @@ -1389,7 +1389,7 @@ * Sleep-mode configuration */ -#define UART_SLEEP_CONF_REG (DR_REG_UART_BASE + 0x38) +#define UART_SLEEP_CONF_REG(i) (REG_UART_BASE(i) + 0x38) /* UART_ACTIVE_THRESHOLD : R/W; bitpos: [9:0]; default: 240; * The uart is activated from light sleeping mode when the input rxd edge @@ -1405,7 +1405,7 @@ * Software flow-control character configuration */ -#define UART_SWFC_CONF0_REG (DR_REG_UART_BASE + 0x3c) +#define UART_SWFC_CONF0_REG(i) (REG_UART_BASE(i) + 0x3c) /* UART_XOFF_CHAR : R/W; bitpos: [17:10]; default: 19; * This register stores the Xoff flow control char. @@ -1430,7 +1430,7 @@ * Software flow-control character configuration */ -#define UART_SWFC_CONF1_REG (DR_REG_UART_BASE + 0x40) +#define UART_SWFC_CONF1_REG(i) (REG_UART_BASE(i) + 0x40) /* UART_XON_CHAR : R/W; bitpos: [17:10]; default: 17; * This register stores the Xon flow control char. @@ -1455,7 +1455,7 @@ * Tx Break character configuration */ -#define UART_TXBRK_CONF_REG (DR_REG_UART_BASE + 0x44) +#define UART_TXBRK_CONF_REG(i) (REG_UART_BASE(i) + 0x44) /* UART_TX_BRK_NUM : R/W; bitpos: [7:0]; default: 10; * This register is used to configure the number of 0 to be sent after the @@ -1567,7 +1567,7 @@ * Pre-sequence timing configuration */ -#define UART_AT_CMD_PRECNT_REG (DR_REG_UART_BASE + 0x50) +#define UART_AT_CMD_PRECNT_REG(i) (REG_UART_BASE(i) + 0x50) /* UART_PRE_IDLE_NUM : R/W; bitpos: [15:0]; default: 2305; * This register is used to configure the idle duration time before the @@ -1583,7 +1583,7 @@ * Post-sequence timing configuration */ -#define UART_AT_CMD_POSTCNT_REG (DR_REG_UART_BASE + 0x54) +#define UART_AT_CMD_POSTCNT_REG(i) (REG_UART_BASE(i) + 0x54) /* UART_POST_IDLE_NUM : R/W; bitpos: [15:0]; default: 2305; * This register is used to configure the duration time between the last @@ -1599,7 +1599,7 @@ * Timeout configuration */ -#define UART_AT_CMD_GAPTOUT_REG (DR_REG_UART_BASE + 0x58) +#define UART_AT_CMD_GAPTOUT_REG(i) (REG_UART_BASE(i) + 0x58) /* UART_RX_GAP_TOUT : R/W; bitpos: [15:0]; default: 11; * This register is used to configure the duration time between the at_cmd @@ -1615,7 +1615,7 @@ * AT escape sequence detection configuration */ -#define UART_AT_CMD_CHAR_REG (DR_REG_UART_BASE + 0x5c) +#define UART_AT_CMD_CHAR_REG(i) (REG_UART_BASE(i) + 0x5c) /* UART_CHAR_NUM : R/W; bitpos: [15:8]; default: 3; * This register is used to configure the num of continuous at_cmd chars @@ -1705,7 +1705,7 @@ * Tx-FIFO write and read offset address. */ -#define UART_MEM_TX_STATUS_REG (DR_REG_UART_BASE + 0x64) +#define UART_MEM_TX_STATUS_REG(i) (REG_UART_BASE(i) + 0x64) /* UART_TX_RADDR : RO; bitpos: [20:11]; default: 0; * This register stores the offset address in Tx-FIFO when Tx-FSM reads data @@ -1731,7 +1731,7 @@ * Rx-FIFO write and read offset address. */ -#define UART_MEM_RX_STATUS_REG (DR_REG_UART_BASE + 0x68) +#define UART_MEM_RX_STATUS_REG(i) (REG_UART_BASE(i) + 0x68) /* UART_RX_WADDR : RO; bitpos: [20:11]; default: 512; * This register stores the offset address in Rx-FIFO when Rx-FIFO_Ctrl @@ -1758,7 +1758,7 @@ * UART transmit and receive status. */ -#define UART_FSM_STATUS_REG (DR_REG_UART_BASE + 0x6c) +#define UART_FSM_STATUS_REG(i) (REG_UART_BASE(i) + 0x6c) /* UART_ST_UTX_OUT : RO; bitpos: [7:4]; default: 0; * This is the status register of transmitter. @@ -1782,7 +1782,7 @@ * Autobaud high pulse register */ -#define UART_POSPULSE_REG (DR_REG_UART_BASE + 0x70) +#define UART_POSPULSE_REG(i) (REG_UART_BASE(i) + 0x70) /* UART_POSEDGE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; * This register stores the minimal input clock count between two positive @@ -1798,7 +1798,7 @@ * Autobaud low pulse register */ -#define UART_NEGPULSE_REG (DR_REG_UART_BASE + 0x74) +#define UART_NEGPULSE_REG(i) (REG_UART_BASE(i) + 0x74) /* UART_NEGEDGE_MIN_CNT : RO; bitpos: [11:0]; default: 4095; * This register stores the minimal input clock count between two negative @@ -1910,7 +1910,7 @@ * UART Version register */ -#define UART_DATE_REG (DR_REG_UART_BASE + 0x7c) +#define UART_DATE_REG(i) (REG_UART_BASE(i) + 0x7c) /* UART_DATE : R/W; bitpos: [31:0]; default: 33587824; * This is the version register. @@ -1925,7 +1925,7 @@ * UART ID register */ -#define UART_ID_REG (DR_REG_UART_BASE + 0x80) +#define UART_ID_REG(i) (REG_UART_BASE(i) + 0x80) /* UART_REG_UPDATE : R/W/SC; bitpos: [31]; default: 0; * Software write 1 would synchronize registers into UART Core clock domain diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig b/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig index d08044077b..a16b296840 100644 --- a/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig +++ b/boards/xtensa/esp32s3/esp32s3-devkit/Kconfig @@ -60,4 +60,36 @@ config ESP32S3_SPIFLASH_LITTLEFS endchoice # ESP32S3_SPIFLASH_FS +if PM + +config PM_ALARM_SEC + int "PM_STANDBY delay (seconds)" + default 15 + depends on PM + ---help--- + Number of seconds to wait in PM_STANDBY before going to PM_STANDBY mode. + +config PM_ALARM_NSEC + int "PM_STANDBY delay (nanoseconds)" + default 0 + depends on PM + ---help--- + Number of additional nanoseconds to wait in PM_STANDBY before going to PM_STANDBY mode. + +config PM_SLEEP_WAKEUP_SEC + int "PM_SLEEP delay (seconds)" + default 20 + depends on PM + ---help--- + Number of seconds to wait in PM_SLEEP. + +config PM_SLEEP_WAKEUP_NSEC + int "PM_SLEEP delay (nanoseconds)" + default 0 + depends on PM + ---help--- + Number of additional nanoseconds to wait in PM_SLEEP. + +endif # PM + endif # ARCH_BOARD_ESP32S3_DEVKIT diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/pm/defconfig b/boards/xtensa/esp32s3/esp32s3-devkit/configs/pm/defconfig new file mode 100644 index 0000000000..4db0b72d68 --- /dev/null +++ b/boards/xtensa/esp32s3/esp32s3-devkit/configs/pm/defconfig @@ -0,0 +1,52 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_LEDS is not set +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32s3-devkit" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32S3_DEVKIT=y +CONFIG_ARCH_CHIP="esp32s3" +CONFIG_ARCH_CHIP_ESP32S3=y +CONFIG_ARCH_CHIP_ESP32S3WROOM1=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_ESP32S3_UART0=y +CONFIG_FS_PROCFS=y +CONFIG_FS_PROCFS_REGISTER=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_LINELEN=64 +CONFIG_NSH_READLINE=y +CONFIG_PM=y +CONFIG_PM_GOVERNOR_EXPLICIT_RELAX=-1 +CONFIG_PM_GOVERNOR_GREEDY=y +CONFIG_PM_PROCFS=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSLOG_BUFFER=y +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y