This is an automated email from the ASF dual-hosted git repository. aguettouche pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push: new 64e2f10 xtensa/esp32: Add power management of force-sleep 64e2f10 is described below commit 64e2f102ac90d4ce8244d857ef5e0c0abe5c6b55 Author: chenwen <chen...@espressif.com> AuthorDate: Tue Sep 15 11:49:14 2020 +0800 xtensa/esp32: Add power management of force-sleep --- arch/xtensa/include/xtensa/core_macros.h | 4 + arch/xtensa/src/common/xtensa.h | 10 + arch/xtensa/src/common/xtensa_initialize.c | 2 +- arch/xtensa/src/esp32/Make.defs | 11 +- arch/xtensa/src/esp32/esp32_clockconfig.c | 319 ++--- arch/xtensa/src/esp32/esp32_clockconfig.h | 53 +- arch/xtensa/src/esp32/esp32_idle.c | 185 +++ arch/xtensa/src/esp32/esp32_pm.c | 787 +++++++++++ arch/xtensa/src/esp32/esp32_pm.h | 123 ++ .../esp32/esp32_pminitialize.c} | 38 +- arch/xtensa/src/esp32/esp32_rtc.c | 1378 ++++++++++++++++++++ arch/xtensa/src/esp32/esp32_rtc.h | 300 +++++ arch/xtensa/src/esp32/hardware/esp32_dport.h | 3 + .../esp32/hardware/esp32_i2s.h} | 34 +- arch/xtensa/src/esp32/hardware/esp32_rtccntl.h | 261 +++- arch/xtensa/src/esp32/hardware/esp32_soc.h | 239 +++- boards/xtensa/esp32/esp32-core/Kconfig | 18 + .../xtensa/esp32/esp32-core/configs/pm/defconfig | 50 + 18 files changed, 3507 insertions(+), 308 deletions(-) diff --git a/arch/xtensa/include/xtensa/core_macros.h b/arch/xtensa/include/xtensa/core_macros.h index 7c5b16e..f8f0a4b 100644 --- a/arch/xtensa/include/xtensa/core_macros.h +++ b/arch/xtensa/include/xtensa/core_macros.h @@ -36,4 +36,8 @@ __asm__ __volatile__("rsr.ccount %0":\ "=a"(__ccount)); __ccount; }) +# define XTHAL_SET_CCOUNT(v) do { int __ccount = (int)(v); \ + __asm__ __volatile__("wsr.ccount %0" :: "a"(__ccount):"memory");\ + } while(0) + #endif /* __ARCH_XTENSA_INCUDE_XTENSA_CORE_H */ diff --git a/arch/xtensa/src/common/xtensa.h b/arch/xtensa/src/common/xtensa.h index 5133f53..9e23727 100644 --- a/arch/xtensa/src/common/xtensa.h +++ b/arch/xtensa/src/common/xtensa.h @@ -40,6 +40,8 @@ * Included Files ****************************************************************************/ +#include <nuttx/config.h> + #ifndef __ASSEMBLY__ # include <stdint.h> # include <stdbool.h> @@ -342,6 +344,14 @@ void up_usbuninitialize(void); # define up_usbuninitialize() #endif +/* Power management *********************************************************/ + +#ifdef CONFIG_PM +void xtensa_pminitialize(void); +#else +# define xtensa_pminitialize() +#endif + /* Debug ********************************************************************/ #ifdef CONFIG_STACK_COLORATION diff --git a/arch/xtensa/src/common/xtensa_initialize.c b/arch/xtensa/src/common/xtensa_initialize.c index edf474d..54ee18c 100644 --- a/arch/xtensa/src/common/xtensa_initialize.c +++ b/arch/xtensa/src/common/xtensa_initialize.c @@ -105,7 +105,7 @@ void up_initialize(void) * with the power management subsystem). */ - up_pminitialize(); + xtensa_pminitialize(); #endif #ifdef CONFIG_ARCH_DMA diff --git a/arch/xtensa/src/esp32/Make.defs b/arch/xtensa/src/esp32/Make.defs index ce750f8..9ef9f65 100644 --- a/arch/xtensa/src/esp32/Make.defs +++ b/arch/xtensa/src/esp32/Make.defs @@ -57,7 +57,7 @@ CMN_CSRCS += xtensa_unblocktask.c xtensa_usestack.c # Configuration-dependent common XTENSA files ifneq ($(CONFIG_ARCH_IDLE_CUSTOM),y) - CMN_CSRCS += xtensa_idle.c + CMN_CSRCS += esp32_idle.c endif ifeq ($(CONFIG_DEBUG_ALERT),y) @@ -89,6 +89,15 @@ CHIP_CSRCS += esp32_timerisr.c CHIP_CSRCS += esp32_user.c CHIP_CSRCS += esp32_dma.c +ifeq ($(CONFIG_PM),y) +ifneq ($(CONFIG_ARCH_CUSTOM_PMINIT),y) +CHIP_CSRCS += esp32_pminitialize.c +endif +CHIP_CSRCS += esp32_pm.c +endif + +CHIP_CSRCS += esp32_rtc.c + ifeq ($(CONFIG_ESP32_I2C),y) CHIP_CSRCS += esp32_i2c.c endif diff --git a/arch/xtensa/src/esp32/esp32_clockconfig.c b/arch/xtensa/src/esp32/esp32_clockconfig.c index ef24715..7a9b521 100644 --- a/arch/xtensa/src/esp32/esp32_clockconfig.c +++ b/arch/xtensa/src/esp32/esp32_clockconfig.c @@ -28,12 +28,15 @@ * Included Files ****************************************************************************/ +#include <nuttx/config.h> #include <stdint.h> + #include "xtensa.h" #include "xtensa_attr.h" - #include "hardware/esp32_dport.h" #include "hardware/esp32_soc.h" +#include "hardware/esp32_uart.h" +#include "esp32_rtc.h" /**************************************************************************** * Pre-processor Definitions @@ -43,18 +46,16 @@ #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif +#ifndef CONFIG_ESP_CONSOLE_UART_NUM +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#endif + +#define DEFAULT_CPU_FREQ 80 + /**************************************************************************** * Private Types ****************************************************************************/ -enum xtal_freq_e -{ - XTAL_40M = 40, - XTAL_26M = 26, - XTAL_24M = 24, - XTAL_AUTO = 0 -}; - enum cpu_freq_e { CPU_80M = 0, @@ -66,8 +67,37 @@ enum cpu_freq_e * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: esp32_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 esp32_uart_tx_wait_idle(uint8_t uart_no) +{ + uint32_t status; + do + { + status = getreg32(UART_STATUS_REG(uart_no)); + + /* either tx count or state is non-zero */ + } + while ((status & (UART_ST_UTX_OUT_M | UART_TXFIFO_CNT_M)) != 0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + extern uint32_t g_ticks_per_us_pro; -extern void ets_delay_us(int delay_us); /**************************************************************************** * Name: esp32_set_cpu_freq @@ -84,10 +114,10 @@ extern void ets_delay_us(int delay_us); * ****************************************************************************/ -static void esp32_set_cpu_freq(int cpu_freq_mhz) +void IRAM_ATTR esp32_set_cpu_freq(int cpu_freq_mhz) { int dbias = DIG_DBIAS_80M_160M; - int per_conf; + int per_conf = CPU_240M; uint32_t value; switch (cpu_freq_mhz) @@ -115,234 +145,10 @@ static void esp32_set_cpu_freq(int cpu_freq_mhz) REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, dbias); REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_PLL); + g_ticks_per_us_pro = cpu_freq_mhz; } /**************************************************************************** - * Name: esp32_bbpll_configure - * - * Description: - * Configure main XTAL frequency values according to pll_freq. - * - * Input Parameters: - * xtal_freq - XTAL frequency values - * pll_freq - PLL frequency values - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void esp32_bbpll_configure(enum xtal_freq_e xtal_freq, int pll_freq) -{ - uint8_t div_ref; - uint8_t div7_0; - uint8_t div10_8; - uint8_t lref; - uint8_t dcur; - uint8_t bw; - uint8_t i2c_bbpll_lref; - uint8_t i2c_bbpll_div_7_0; - uint8_t i2c_bbpll_dcur; - - if (pll_freq == RTC_PLL_FREQ_320M) - { - /* Raise the voltage, if needed */ - - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, - DIG_DBIAS_80M_160M); - - /* Configure 320M PLL */ - - switch (xtal_freq) - { - case XTAL_40M: - div_ref = 0; - div7_0 = 32; - div10_8 = 0; - lref = 0; - dcur = 6; - bw = 3; - break; - - case XTAL_26M: - div_ref = 12; - div7_0 = 224; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - - case XTAL_24M: - div_ref = 11; - div7_0 = 224; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - - default: - div_ref = 12; - div7_0 = 224; - div10_8 = 4; - lref = 0; - dcur = 0; - bw = 0; - break; - } - - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_320M); - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, - BBPLL_BBADC_DSMP_VAL_320M); - } - else - { - /* Raise the voltage */ - - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M); - ets_delay_us(DELAY_PLL_DBIAS_RAISE); - - /* Configure 480M PLL */ - - switch (xtal_freq) - { - case XTAL_40M: - div_ref = 0; - div7_0 = 28; - div10_8 = 0; - lref = 0; - dcur = 6; - bw = 3; - break; - - case XTAL_26M: - div_ref = 12; - div7_0 = 144; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - - case XTAL_24M: - div_ref = 11; - div7_0 = 144; - div10_8 = 4; - lref = 1; - dcur = 0; - bw = 1; - break; - - default: - div_ref = 12; - div7_0 = 224; - div10_8 = 4; - lref = 0; - dcur = 0; - bw = 0; - break; - } - - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_480M); - I2C_WRITEREG_RTC(I2C_BBPLL, - I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_480M); - } - - i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref); - i2c_bbpll_div_7_0 = div7_0; - i2c_bbpll_dcur = (bw << 6) | dcur; - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref); - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); -} - -/**************************************************************************** - * Name: esp32_bbpll_enable - * - * Description: - * Reset BBPLL configuration. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void esp32_bbpll_enable(void) -{ - modifyreg32(RTC_CNTL_OPTIONS0_REG, - RTC_CNTL_BIAS_I2C_FORCE_PD | RTC_CNTL_BB_I2C_FORCE_PD | - RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); - - /* reset BBPLL configuration */ - - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY, - BBPLL_IR_CAL_DELAY_VAL); - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, - BBPLL_IR_CAL_EXT_CAP_VAL); - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL, - BBPLL_OC_ENB_FCAL_VAL); - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON, - BBPLL_OC_ENB_VCON_VAL); - I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0, - BBPLL_BBADC_CAL_7_0_VAL); -} - -/**************************************************************************** - * Name: esp32_update_to_xtal - * - * Description: - * Switch to XTAL frequency, does not disable the PLL - * - * Input Parameters: - * freq - XTAL frequency - * div - REF_TICK divider - * - * Returned Value: - * none - * - ****************************************************************************/ - -static void esp32_update_to_xtal(int freq, int div) -{ - uint32_t value = (((freq * MHZ) >> 12) & UINT16_MAX) - | ((((freq * MHZ) >> 12) & UINT16_MAX) << 16); - putreg32(value, RTC_APB_FREQ_REG); - - /* set divider from XTAL to APB clock */ - - REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, div - 1); - - /* switch clock source */ - - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, - RTC_CNTL_SOC_CLK_SEL_XTL); - - /* adjust ref_tick */ - - modifyreg32(APB_CTRL_XTAL_TICK_CONF_REG, 0, - (freq * MHZ) / REF_CLK_FREQ - 1); - - /* lower the voltage */ - - if (freq <= 2) - { - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_2M); - } - else - { - REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); - } -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** * Name: esp32_clockconfig * * Description: @@ -355,8 +161,9 @@ static void esp32_update_to_xtal(int freq, int div) void esp32_clockconfig(void) { uint32_t freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; + uint32_t source_freq_mhz; - enum xtal_freq_e xtal_freq = XTAL_40M; + enum esp32_rtc_xtal_freq_e xtal_freq = RTC_XTAL_FREQ_40M; switch (freq_mhz) { @@ -373,19 +180,47 @@ void esp32_clockconfig(void) return; } - esp32_update_to_xtal(xtal_freq, 1); - esp32_bbpll_enable(); - esp32_bbpll_configure(xtal_freq, source_freq_mhz); + esp32_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); + esp32_rtc_update_to_xtal(xtal_freq, 1); + esp32_rtc_bbpll_enable(); + esp32_rtc_bbpll_configure(xtal_freq, source_freq_mhz); esp32_set_cpu_freq(freq_mhz); } +/**************************************************************************** + * Name: esp_clk_cpu_freq + * + * Description: + * Get CPU frequency + * + * Input Parameters: + * None + * + * Returned Value: + * CPU frequency + * + ****************************************************************************/ + int IRAM_ATTR esp_clk_cpu_freq(void) { return g_ticks_per_us_pro * MHZ; } +/**************************************************************************** + * Name: esp_clk_apb_freq + * + * Description: + * Return current APB clock frequency. + * + * Input Parameters: + * None + * + * Returned Value: + * APB clock frequency, in Hz + * + ****************************************************************************/ + int IRAM_ATTR esp_clk_apb_freq(void) { return MIN(g_ticks_per_us_pro, 80) * MHZ; } - diff --git a/arch/xtensa/src/esp32/esp32_clockconfig.h b/arch/xtensa/src/esp32/esp32_clockconfig.h index 60e8e59..f489172 100644 --- a/arch/xtensa/src/esp32/esp32_clockconfig.h +++ b/arch/xtensa/src/esp32/esp32_clockconfig.h @@ -40,13 +40,30 @@ * Included Files ****************************************************************************/ -#include "xtensa_attr.h" +#include <nuttx/config.h> /**************************************************************************** - * Pre-processor Definitions + * Public Function Prototypes ****************************************************************************/ /**************************************************************************** + * Name: esp32_set_cpu_freq + * + * Description: + * Switch to one of PLL-based frequencies. + * Current frequency can be XTAL or PLL. + * + * Input Parameters: + * cpu_freq_mhz - new CPU frequency + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_set_cpu_freq(int cpu_freq_mhz); + +/**************************************************************************** * Name: esp32_clockconfig * * Description: @@ -58,8 +75,36 @@ void esp32_clockconfig(void); -int IRAM_ATTR esp_clk_cpu_freq(void); +/**************************************************************************** + * Name: esp_clk_cpu_freq + * + * Description: + * Get CPU frequency + * + * Input Parameters: + * None + * + * Returned Value: + * CPU frequency + * + ****************************************************************************/ + +int esp_clk_cpu_freq(void); + +/**************************************************************************** + * Name: esp_clk_apb_freq + * + * Description: + * Return current APB clock frequency. + * + * Input Parameters: + * None + * + * Returned Value: + * APB clock frequency, in Hz + * + ****************************************************************************/ -int IRAM_ATTR esp_clk_apb_freq(void); +int esp_clk_apb_freq(void); #endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_CLOCKCONFIG_H */ diff --git a/arch/xtensa/src/esp32/esp32_idle.c b/arch/xtensa/src/esp32/esp32_idle.c new file mode 100644 index 0000000..357d4d8 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_idle.c @@ -0,0 +1,185 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_idle.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 <nuttx/config.h> +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <nuttx/power/pm.h> + +#include "esp32_pm.h" +#include "xtensa.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Values for the RTC Alarm to wake up from the PM_STANDBY mode + * (which corresponds to ESP32 stop mode). If this alarm expires, + * the logic in this file will wakeup from PM_STANDBY mode and + * transition to PM_SLEEP mode (ESP32 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 + +#define PM_IDLE_DOMAIN 0 /* Revisit */ +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idlepm + * + * Description: + * Perform IDLE state power management. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void up_idlepm(void) +{ + static enum pm_state_e oldstate = PM_NORMAL; + enum pm_state_e newstate; + irqstate_t flags; + 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(); + + /* 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; + } + + /* MCU-specific power management logic */ + + switch (newstate) + { + case PM_NORMAL: + break; + + case PM_IDLE: + break; + + case PM_STANDBY: + { + /* Configure the RTC alarm to Auto Wake the system */ + + esp32_pmstart(CONFIG_PM_ALARM_SEC * 1000000 + + CONFIG_PM_ALARM_NSEC / 1000); + + /* Resume normal operation */ + + pm_relax(PM_IDLE_DOMAIN, PM_STANDBY); + } + break; + + case PM_SLEEP: + { + pm_changestate(PM_IDLE_DOMAIN, PM_NORMAL); + newstate = PM_NORMAL; + } + break; + + default: + break; + } + + spin_unlock_irqrestore(flags); + } +} +#else +# define up_idlepm() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when their is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + nxsched_process_timer(); +#else + + /* Perform IDLE mode power management */ + + up_idlepm(); + + /* This would be an appropriate place to put some MCU-specific logic to + * sleep in a reduced power mode until an interrupt occurs to save power + */ + +#if XCHAL_HAVE_INTERRUPTS + __asm__ __volatile__ ("waiti 0"); +#endif +#endif +} diff --git a/arch/xtensa/src/esp32/esp32_pm.c b/arch/xtensa/src/esp32/esp32_pm.c new file mode 100644 index 0000000..127757c --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_pm.c @@ -0,0 +1,787 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_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 <nuttx/config.h> + +#ifdef CONFIG_PM + +#include <arch/chip/chip.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <errno.h> +#include <sys/time.h> +#include "hardware/esp32_rtccntl.h" +#include "hardware/esp32_uart.h" +#include "xtensa.h" +#include "xtensa_attr.h" +#include "esp32_rtc.h" +#include "esp32_clockconfig.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 + +#ifndef MAX +#define MAX(a,b) a > b ? a : b +#endif + +/* 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 (250 + 30 * 240 / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) + +#define CONFIG_ESP32_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_EXT0_TRIG_EN BIT(0) /* EXT0 GPIO wakeup */ +#define RTC_EXT1_TRIG_EN BIT(1) /* EXT1 GPIO wakeup */ +#define RTC_GPIO_TRIG_EN BIT(2) /* GPIO wakeup (light sleep only) */ +#define RTC_TIMER_TRIG_EN BIT(3) /* Timer wakeup */ +#define RTC_SDIO_TRIG_EN BIT(4) /* SDIO wakeup (light sleep only) */ +#define RTC_MAC_TRIG_EN BIT(5) /* MAC 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_TOUCH_TRIG_EN BIT(8) /* Touch wakeup */ +#define RTC_ULP_TRIG_EN BIT(9) /* ULP wakeup */ +#define RTC_BT_TRIG_EN BIT(10) /* BT wakeup (light sleep only) */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Power down options */ + +enum esp32_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 esp_sleep_pd_domain_e +{ + ESP_PD_DOMAIN_RTC_PERIPH, /* RTC IO, sensors and ULP co-processor */ + 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_MAX /* Number of domains */ +}; + +/* Internal structure which holds all requested deep sleep parameters. */ + +struct esp32_sleep_config_t +{ + enum esp32_sleep_pd_option_e pd_options[ESP_PD_DOMAIN_MAX]; + uint64_t sleep_duration; + uint32_t wakeup_triggers : 11; + uint32_t ext1_trigger_mode : 1; + uint32_t ext1_rtc_gpio_mask : 18; + uint32_t ext0_trigger_level : 1; + uint32_t ext0_rtc_gpio_num : 5; + uint32_t sleep_time_adjustment; + uint64_t rtc_ticks_at_sleep_start; +}; + +/* Structure describing vddsdio configuration. */ + +struct 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 void esp32_timer_wakeup_prepare(void); +static void IRAM_ATTR esp32_flush_uarts(void); +static void IRAM_ATTR esp32_suspend_uarts(void); +static void IRAM_ATTR esp32_resume_uarts(void); +static uint32_t esp32_get_power_down_flags(void); +static inline void esp32_uart_tx_wait_idle(uint8_t uart_no); +static void IRAM_ATTR esp32_set_vddsdio_config( + struct rtc_vddsdio_config_s config); +static int IRAM_ATTR esp32_get_vddsdio_config( + struct rtc_vddsdio_config_s *config); +int IRAM_ATTR esp32_light_sleep_inner(uint32_t pd_flags, + uint32_t time_us, struct rtc_vddsdio_config_s config); +static int IRAM_ATTR esp32_configure_cpu_freq(uint32_t cpu_freq_mhz); + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern uint32_t g_ticks_per_us_pro; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct esp32_sleep_config_t s_config = +{ + .pd_options = + { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO }, + .wakeup_triggers = 0 +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +extern void ets_delay_us(uint32_t us); + +/**************************************************************************** + * Name: esp32_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 esp32_uart_tx_wait_idle(uint8_t uart_no) +{ + uint32_t status; + do + { + status = getreg32(UART_STATUS_REG(uart_no)); + + /* either tx count or state is non-zero */ + } + while ((status & (UART_ST_UTX_OUT_M | UART_TXFIFO_CNT_M)) != 0); +} + +/**************************************************************************** + * Name: esp32_flush_uarts + * + * Description: + * Wait until UART0/UART1/UART2 tx full empty and the last char send ok + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32_flush_uarts(void) +{ + int i; + + for (i = 0; i < ESP32_NUARTS; ++i) + { + esp32_uart_tx_wait_idle(i); + } +} + +/**************************************************************************** + * Name: esp32_suspend_uarts + * + * Description: + * Suspend UART0/UART1/UART2 output + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32_suspend_uarts(void) +{ + int i; + + for (i = 0; i < ESP32_NUARTS; ++i) + { + modifyreg32(UART_FLOW_CONF_REG(i), 0, UART_FORCE_XOFF); + while (REG_GET_FIELD(UART_STATUS_REG(i), UART_ST_UTX_OUT) != 0); + } +} + +/**************************************************************************** + * Name: esp32_resume_uarts + * + * Description: + * Re-enable UART0/UART1/UART2 output + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32_resume_uarts(void) +{ + int i; + + for (i = 0; i < ESP32_NUARTS; ++i) + { + 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_FORCE_XON, 0); + } +} + +/**************************************************************************** + * Name: esp32_get_power_down_flags + * + * Description: + * Get power domains that can be powered down + * + * Input Parameters: + * None + * + * Returned Value: + * Power domains + * + ****************************************************************************/ + +static uint32_t esp32_get_power_down_flags(void) +{ + uint32_t pd_flags = 0; + + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] == ESP_PD_OPTION_AUTO) + { + s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON; + } + + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) + { + if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN)) + { + s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON; + } + else if (s_config.wakeup_triggers & + (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) + { + /* In both rev. 0 and rev. 1 of ESP32, + * forcing power up of prevents ULP timer + * and touch FSMs from working correctly. + */ + + s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_OFF; + } + } + + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) + { + s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; + } + + /* Prepare flags based on the selected options */ + + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM; + } + + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM; + } + + if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_RTC_PERIPH; + } + + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) + { + pd_flags |= RTC_SLEEP_PD_XTAL; + } + + return pd_flags; +} + +/**************************************************************************** + * Name: esp32_timer_wakeup_prepare + * + * Description: + * Configure timer to wake-up + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32_timer_wakeup_prepare(void) +{ + uint32_t period; + int64_t sleep_duration; + int64_t rtc_count_delta; + + period = getreg32(RTC_SLOW_CLK_CAL_REG); + sleep_duration = (int64_t) s_config.sleep_duration - + (int64_t) s_config.sleep_time_adjustment; + + if (sleep_duration < 0) + { + sleep_duration = 0; + } + + rtc_count_delta = esp32_rtc_time_us_to_slowclk(sleep_duration, period); + esp32_rtc_sleep_set_wakeup_time(s_config.rtc_ticks_at_sleep_start + + rtc_count_delta); +} + +/**************************************************************************** + * Name: esp32_set_vddsdio_config + * + * Description: + * Set new VDDSDIO configuration using RTC registers. + * + * Input Parameters: + * New VDDSDIO configuration + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32_set_vddsdio_config( + struct 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_PD_EN; + putreg32((uint32_t)val, RTC_CNTL_SDIO_CONF_REG); +} + +/**************************************************************************** + * Name: esp32_get_vddsdio_config + * + * Description: + * Get current VDDSDIO configuration. + * + * Input Parameters: + * Incoming parameter address of VDDSDIO configuration to be saved + * + * Returned Value: + * Zero (OK) is returned on success. + * + ****************************************************************************/ + +static int IRAM_ATTR esp32_get_vddsdio_config( + struct rtc_vddsdio_config_s *config) +{ + struct rtc_vddsdio_config_s *result = config; + uint32_t efuse_reg; + uint32_t strap_reg; + uint32_t sdio_conf_reg = getreg32(RTC_CNTL_SDIO_CONF_REG); + + result->drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) + >> RTC_CNTL_DREFH_SDIO_S; + result->drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) + >> RTC_CNTL_DREFM_SDIO_S; + result->drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) + >> RTC_CNTL_DREFL_SDIO_S; + + if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) + { + /* Get configuration from RTC */ + + result->force = 1; + result->enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) + >> RTC_CNTL_XPD_SDIO_REG_S; + result->tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) + >> RTC_CNTL_SDIO_TIEH_S; + + return OK; + } + + efuse_reg = getreg32(EFUSE_BLK0_RDATA4_REG); + + if (efuse_reg & EFUSE_RD_SDIO_FORCE) + { + /* Get configuration from EFUSE */ + + result->force = 0; + result->enable = (efuse_reg & EFUSE_RD_XPD_SDIO_REG_M) + >> EFUSE_RD_XPD_SDIO_REG_S; + result->tieh = (efuse_reg & EFUSE_RD_SDIO_TIEH_M) + >> EFUSE_RD_SDIO_TIEH_S; + + if (REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, + EFUSE_RD_BLK3_PART_RESERVE) == 0) + { + result->drefh = (efuse_reg & EFUSE_RD_SDIO_DREFH_M) + >> EFUSE_RD_SDIO_DREFH_S; + result->drefm = (efuse_reg & EFUSE_RD_SDIO_DREFM_M) + >> EFUSE_RD_SDIO_DREFM_S; + result->drefl = (efuse_reg & EFUSE_RD_SDIO_DREFL_M) + >> EFUSE_RD_SDIO_DREFL_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: esp32_sleep_start + * + * Description: + * Enter low power mode. + * + * Input Parameters: + * Power domains + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +static int IRAM_ATTR esp32_sleep_start(uint32_t pd_flags) +{ + int result; + uint32_t cur_freq; + + /* 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 (pd_flags & RTC_SLEEP_PD_DIG) + { + esp32_flush_uarts(); + } + else + { + esp32_suspend_uarts(); + } + + /* Save current frequency and switch to XTAL */ + + cur_freq = esp_clk_cpu_freq() / MHZ; + esp32_rtc_cpu_freq_set_xtal(); + + /* Enter sleep */ + + esp32_rtc_sleep_init(pd_flags); + + /* Configure timer wakeup */ + + if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) + && s_config.sleep_duration > 0) + { + esp32_timer_wakeup_prepare(); + } + + esp32_rtc_sleep_start(s_config.wakeup_triggers, 0); + + /* Restore CPU frequency */ + + result = esp32_configure_cpu_freq(cur_freq); + esp32_resume_uarts(); + + return result; +} + +/**************************************************************************** + * Name: esp32_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 + * + ****************************************************************************/ + +int esp32_light_sleep_inner(uint32_t pd_flags, + uint32_t time_us, struct rtc_vddsdio_config_s config) +{ + /* Enter sleep */ + + int err = esp32_sleep_start(pd_flags); + + /* If VDDSDIO regulator was controlled by RTC registers before sleep. + * restore the configuration. + */ + + if (config.force) + { + esp32_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. */ + + ets_delay_us(time_us); + } + + return err; +} + +/**************************************************************************** + * Name: esp32_configure_cpu_freq + * + * Description: + * Switch to new CPU frequencies. + * + * Input Parameters: + * cpu_freq_mhz - new CPU frequency + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +static int IRAM_ATTR esp32_configure_cpu_freq(uint32_t cpu_freq_mhz) +{ + uint32_t soc_clk_sel; + uint32_t source_freq_mhz; + enum esp32_rtc_xtal_freq_e xtal_freq; + + if (cpu_freq_mhz == 240) + { + source_freq_mhz = RTC_PLL_FREQ_480M; + } + else if(cpu_freq_mhz == 80 || cpu_freq_mhz == 160) + { + source_freq_mhz = RTC_PLL_FREQ_320M; + } + else + { + return EINVAL; + } + + xtal_freq = esp32_rtc_clk_xtal_freq_get(); + soc_clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL); + + if (soc_clk_sel != RTC_CNTL_SOC_CLK_SEL_XTL) + { + esp32_rtc_update_to_xtal(xtal_freq, 1); + esp32_rtc_wait_for_slow_cycle(); + } + + if (soc_clk_sel == RTC_CNTL_SOC_CLK_SEL_PLL) + { + esp32_rtc_bbpll_disable(); + } + + esp32_rtc_bbpll_enable(); + esp32_rtc_wait_for_slow_cycle(); + esp32_rtc_bbpll_configure(xtal_freq, source_freq_mhz); + esp32_set_cpu_freq(cpu_freq_mhz); + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_sleep_enable_timer_wakeup + * + * Description: + * Configure wake-up interval + * + * Input Parameters: + * time_in_us - Configure wake-up time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_sleep_enable_timer_wakeup(uint64_t time_in_us) +{ + s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN; + s_config.sleep_duration = time_in_us; +} + +/**************************************************************************** + * Name: esp32_light_sleep_start + * + * Description: + * Enter sleep mode + * + * Input Parameters: + * None + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +int esp32_light_sleep_start(void) +{ + uint32_t pd_flags; + uint32_t flash_enable_time_us; + uint32_t vddsdio_pd_sleep_duration; + struct rtc_vddsdio_config_s vddsdio_config; + int ret = OK; + + s_config.rtc_ticks_at_sleep_start = esp32_rtc_time_get(); + + /* Decide which power domains can be powered down */ + + pd_flags = esp32_get_power_down_flags(); + + /* Amount of time to subtract from actual sleep time. + * This is spent on entering and leaving light sleep. + */ + + s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US; + + /* Decide if VDD_SDIO needs to be powered down; + * If it needs to be powered down, adjust sleep time. + */ + + flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US + + CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY; + + vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US, + flash_enable_time_us + LIGHT_SLEEP_TIME_OVERHEAD_US + + LIGHT_SLEEP_MIN_TIME_US); + + if (s_config.sleep_duration > vddsdio_pd_sleep_duration) + { + pd_flags |= RTC_SLEEP_PD_VDDSDIO; + s_config.sleep_time_adjustment += flash_enable_time_us; + } + + esp32_get_vddsdio_config(&vddsdio_config); + + /* Enter sleep, then wait for flash to be ready on wakeup */ + + ret = esp32_light_sleep_inner(pd_flags, flash_enable_time_us, + vddsdio_config); + + return ret; +} + +/**************************************************************************** + * Name: esp32_pminit + * + * Description: + * Initialize force sleep parameters. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_pminit(void) +{ + /* Initialize RTC parameters */ + + esp32_rtc_init(); + esp32_rtc_clk_set(); +} + +/**************************************************************************** + * Name: esp32_pmstart + * + * Description: + * Enter force sleep time interval. + * + * Input Parameters: + * time_in_us - force sleep time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_pmstart(uint64_t time_in_us) +{ + /* don't power down XTAL — powering it up takes different time on. */ + + fflush(stdout); + esp32_sleep_enable_timer_wakeup(time_in_us); + esp32_light_sleep_start(); +} + +#endif /* CONFIG_PM */ diff --git a/arch/xtensa/src/esp32/esp32_pm.h b/arch/xtensa/src/esp32/esp32_pm.h new file mode 100644 index 0000000..19e1108 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_pm.h @@ -0,0 +1,123 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_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_ESP32_ESP32_PMSLEEP_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_PMSLEEP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <stdint.h> + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_PM + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_sleep_enable_timer_wakeup + * + * Description: + * Configure wake-up interval + * + * Input Parameters: + * time_in_us - Configure wake-up time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_sleep_enable_timer_wakeup(uint64_t time_in_us); + +/**************************************************************************** + * Name: esp32_light_sleep_start + * + * Description: + * Enter sleep mode + * + * Input Parameters: + * None + * + * Returned Value: + * 0 is returned on success or a negated errno value is returned + * + ****************************************************************************/ + +int esp32_light_sleep_start(void); + +/**************************************************************************** + * Name: esp32_pminit + * + * Description: + * Initialize force sleep parameters. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_pminit(void); + +/**************************************************************************** + * Name: esp32_pmstart + * + * Description: + * Enter force sleep time interval. + * + * Input Parameters: + * time_in_us - force sleep time interval + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_pmstart(uint64_t time_in_us); + +#endif /* CONFIG_PM */ + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_PMSLEEP_H */ diff --git a/arch/xtensa/include/xtensa/core_macros.h b/arch/xtensa/src/esp32/esp32_pminitialize.c similarity index 67% copy from arch/xtensa/include/xtensa/core_macros.h copy to arch/xtensa/src/esp32/esp32_pminitialize.c index 7c5b16e..f040202 100644 --- a/arch/xtensa/include/xtensa/core_macros.h +++ b/arch/xtensa/src/esp32/esp32_pminitialize.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/xtensa/include/xtensa/core_macros.h + * arch/xtensa/src/esp32/esp32_pminitialize.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,22 +18,38 @@ * ****************************************************************************/ -#ifndef __ARCH_XTENSA_INCUDE_XTENSA_CORE_MACRO_H -#define __ARCH_XTENSA_INCUDE_XTENSA_CORE_MACRO_H - /**************************************************************************** * Included Files ****************************************************************************/ -#include <arch/chip/core-isa.h> -#include <arch/chip/tie.h> +#include <nuttx/config.h> +#include <nuttx/power/pm.h> + +#include "esp32_pm.h" + +#ifdef CONFIG_PM /**************************************************************************** - * Pre-processor Definitions + * Public Functions ****************************************************************************/ -#define XTHAL_GET_CCOUNT() ({ int __ccount; \ - __asm__ __volatile__("rsr.ccount %0":\ - "=a"(__ccount)); __ccount; }) +/**************************************************************************** + * Name: xtensa_pminitialize + * + * Description: + * Initialize the power management subsystem. + * + ****************************************************************************/ + +void xtensa_pminitialize(void) +{ + /* Initialize RTC parameters */ + + esp32_pminit(); + + /* Then initialize the NuttX power management subsystem proper */ + + pm_initialize(); +} -#endif /* __ARCH_XTENSA_INCUDE_XTENSA_CORE_H */ +#endif /* CONFIG_PM */ diff --git a/arch/xtensa/src/esp32/esp32_rtc.c b/arch/xtensa/src/esp32/esp32_rtc.c new file mode 100644 index 0000000..bc15c4f --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_rtc.c @@ -0,0 +1,1378 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_rtc.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 <stdint.h> + +#include "esp32_rtc.h" +#include "hardware/esp32_rtccntl.h" +#include "hardware/esp32_dport.h" +#include "hardware/esp32_i2s.h" +#include "xtensa.h" +#include "xtensa_attr.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Various delays to be programmed into power control state machines */ + +#define RTC_CNTL_XTL_BUF_WAIT_SLP 2 +#define RTC_CNTL_CK8M_WAIT_SLP 4 +#define OTHER_BLOCKS_POWERUP 1 +#define OTHER_BLOCKS_WAIT 1 + +#define ROM_RAM_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define ROM_RAM_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define WIFI_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define WIFI_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define RTC_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define RTC_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define DG_WRAP_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define DG_WRAP_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define RTC_MEM_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define RTC_MEM_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define RTC_CNTL_PLL_BUF_WAIT_SLP 2 + +#define DELAY_FAST_CLK_SWITCH 3 + +#define XTAL_32K_DAC_VAL 3 +#define XTAL_32K_DRES_VAL 3 +#define XTAL_32K_DBIAS_VAL 0 + +#define DELAY_SLOW_CLK_SWITCH 300 + +/* Number of fractional bits in values returned by rtc_clk_cal */ + +#define RTC_CLK_CAL_FRACT 19 + +/* With the default value of CK8M_DFREQ, + * 8M clock frequency is 8.5 MHz +/- 7% + */ + +#define RTC_FAST_CLK_FREQ_APPROX 8500000 + +/* Number of cycles to wait from the 32k XTAL oscillator to + * consider it running. Larger values increase startup delay. + * Smaller values may cause false positive detection + * (i.e. oscillator runs for a few cycles and then stops). + */ + +#define SLOW_CLK_CAL_CYCLES 1024 + +/* Disable logging from the ROM code. */ + +#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) +#define EXT_OSC_FLAG BIT(3) + +/* Default initializer for esp32_rtc_sleep_config_t + * This initializer sets all fields to "reasonable" values + * (e.g. suggested for production use) based on a combination + * of RTC_SLEEP_PD_x flags. + */ + +#define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \ + .lslp_mem_inf_fpu = 0, \ + .rtc_mem_inf_fpu = 0, \ + .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0, \ + .rtc_fastmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_FAST_MEM) ? 1 : 0, \ + .rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \ + .rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \ + .wifi_pd_en = 0, \ + .rom_mem_pd_en = 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 = RTC_CNTL_DBIAS_0V90, \ + .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ + .rtc_dbias_slp = RTC_CNTL_DBIAS_0V90, \ + .lslp_meminf_pd = 1, \ + .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1 \ +} + +/* Initializer for rtc_sleep_pd_config_t which + * sets all flags to the same value + */ + +#define RTC_SLEEP_PD_CONFIG_ALL(val) {\ + .dig_pd = (val), \ + .rtc_pd = (val), \ + .cpu_pd = (val), \ + .i2s_pd = (val), \ + .bb_pd = (val), \ + .nrx_pd = (val), \ + .fe_pd = (val), \ +} + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* RTC SLOW_CLK frequency values */ + +enum esp32_rtc_slow_freq_e +{ + RTC_SLOW_FREQ_RTC = 0, /* Internal 150 kHz RC oscillator */ + RTC_SLOW_FREQ_32K_XTAL = 1, /* External 32 kHz XTAL */ + RTC_SLOW_FREQ_8MD256 = 2, /* Internal 8 MHz RC oscillator, divided by 256 */ +}; + +/* RTC FAST_CLK frequency values */ + +enum esp32_rtc_fast_freq_e +{ + RTC_FAST_FREQ_XTALD4 = 0, /* Main XTAL, divided by 4 */ + RTC_FAST_FREQ_8M = 1, /* Internal 8 MHz RC oscillator */ +}; + +/* This is almost the same as esp32_rtc_slow_freq_e, except that we define + * an extra enum member for the external 32k oscillator.For convenience, + * lower 2 bits should correspond to esp32_rtc_slow_freq_e values. + */ + +enum esp32_slow_clk_sel_e +{ + /* Internal 150 kHz RC oscillator */ + + SLOW_CLK_150K = RTC_SLOW_FREQ_RTC, + + /* External 32 kHz XTAL */ + + SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, + + /* Internal 8 MHz RC oscillator, divided by 256 */ + + SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256, + + /* External 32k oscillator connected to 32K_XP pin */ + + SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG +}; + +/* Clock source to be calibrated using rtc_clk_cal function */ + +enum esp32_rtc_cal_sel_e +{ + RTC_CAL_RTC_MUX = 0, /* Currently selected RTC SLOW_CLK */ + RTC_CAL_8MD256 = 1, /* Internal 8 MHz RC oscillator, divided by 256 */ + RTC_CAL_32K_XTAL = 2 /* External 32 kHz XTAL */ +}; + +/* RTC power and clock control initialization settings */ + +struct esp32_rtc_priv_s +{ + uint32_t ck8m_wait : 8; /* Number of rtc_fast_clk cycles to wait for 8M clock to be ready */ + uint32_t xtal_wait : 8; /* Number of rtc_fast_clk cycles to wait for XTAL clock to be ready */ + uint32_t pll_wait : 8; /* Number of rtc_fast_clk cycles to wait for PLL to be ready */ + uint32_t clkctl_init : 1; /* Perform clock control related initialization */ + uint32_t pwrctl_init : 1; /* Perform power control related initialization */ + uint32_t rtc_dboost_fpd : 1; /* Force power down RTC_DBOOST */ +}; + +/* sleep configuration for rtc_sleep_init function */ + +struct esp32_rtc_sleep_config_s +{ + uint32_t lslp_mem_inf_fpu : 1; /* force normal voltage in sleep mode (digital domain memory) */ + uint32_t rtc_mem_inf_fpu : 1; /* force normal voltage in sleep mode (RTC memory) */ + uint32_t rtc_mem_inf_follow_cpu : 1; /* keep low voltage in sleep mode (even if ULP/touch is used) */ + uint32_t rtc_fastmem_pd_en : 1; /* power down RTC fast memory */ + uint32_t rtc_slowmem_pd_en : 1; /* power down RTC slow memory */ + uint32_t rtc_peri_pd_en : 1; /* power down RTC peripherals */ + uint32_t wifi_pd_en : 1; /* power down WiFi */ + uint32_t rom_mem_pd_en : 1; /* power down main RAM and ROM */ + 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 : 3; /* set bias for digital domain, in active mode */ + uint32_t dig_dbias_slp : 3; /* set bias for digital domain, in sleep mode */ + uint32_t rtc_dbias_wak : 3; /* set bias for RTC domain, in active mode */ + uint32_t rtc_dbias_slp : 3; /* set bias for RTC domain, in sleep mode */ + uint32_t lslp_meminf_pd : 1; /* remove all peripheral force power up flags */ + uint32_t vddsdio_pd_en : 1; /* power down VDDSDIO regulator */ + uint32_t xtal_fpu : 1; /* keep main XTAL powered up in sleep */ +}; + +/* Power down flags for rtc_sleep_pd function */ + +struct esp32_rtc_sleep_pd_config_s +{ + uint32_t dig_pd : 1; /* Set to 1 to power down digital part in sleep */ + uint32_t rtc_pd : 1; /* Set to 1 to power down RTC memories in sleep */ + uint32_t cpu_pd : 1; /* Set to 1 to power down digital memories and CPU in sleep */ + uint32_t i2s_pd : 1; /* Set to 1 to power down I2S in sleep */ + uint32_t bb_pd : 1; /* Set to 1 to power down WiFi in sleep */ + uint32_t nrx_pd : 1; /* Set to 1 to power down WiFi in sleep */ + uint32_t fe_pd : 1; /* Set to 1 to power down WiFi in sleep */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void IRAM_ATTR esp32_rtc_sleep_pd( + struct esp32_rtc_sleep_pd_config_s cfg); +static inline bool esp32_clk_val_is_valid(uint32_t val); +static void IRAM_ATTR esp32_rtc_clk_fast_freq_set( + enum esp32_rtc_fast_freq_e fast_freq); +static uint32_t IRAM_ATTR esp32_rtc_clk_cal_internal( + enum esp32_rtc_cal_sel_e cal_clk, uint32_t slowclk_cycles); +static uint32_t IRAM_ATTR esp32_rtc_clk_cal(enum esp32_rtc_cal_sel_e cal_clk, + uint32_t slowclk_cycles); +static void IRAM_ATTR esp32_rtc_clk_slow_freq_set( + enum esp32_rtc_slow_freq_e slow_freq); +static void esp32_select_rtc_slow_clk(enum esp32_slow_clk_sel_e slow_clk); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct esp32_rtc_priv_s esp32_rtc_priv = +{ + .ck8m_wait = RTC_CNTL_CK8M_WAIT_DEFAULT, + .xtal_wait = RTC_CNTL_XTL_BUF_WAIT_DEFAULT, + .pll_wait = RTC_CNTL_PLL_BUF_WAIT_DEFAULT, + .clkctl_init = 1, + .pwrctl_init = 1, + .rtc_dboost_fpd = 1 +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +extern void ets_delay_us(uint32_t us); + +/**************************************************************************** + * Name: esp32_rtc_sleep_pd + * + * Description: + * Configure whether certain peripherals are powered down in deep sleep. + * + * Input Parameters: + * cfg - power down flags as rtc_sleep_pd_config_t structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32_rtc_sleep_pd( + struct esp32_rtc_sleep_pd_config_s cfg) +{ + REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, + RTC_CNTL_LSLP_MEM_FORCE_PU, ~cfg.dig_pd); + REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_LPU, ~cfg.rtc_pd); + REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, ~cfg.rtc_pd); + REG_SET_FIELD(DPORT_MEM_PD_MASK_REG, DPORT_LSLP_MEM_PD_MASK, ~cfg.cpu_pd); + REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_PLC_MEM_FORCE_PU, ~cfg.i2s_pd); + REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_FIFO_FORCE_PU, ~cfg.i2s_pd); + REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, ~cfg.bb_pd); + REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, ~cfg.bb_pd); + REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, ~cfg.nrx_pd); + REG_SET_FIELD(NRXPD_CTRL, NRX_VIT_FORCE_PU, ~cfg.nrx_pd); + REG_SET_FIELD(NRXPD_CTRL, NRX_DEMAP_FORCE_PU, ~cfg.nrx_pd); + REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, ~cfg.fe_pd); + REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, ~cfg.fe_pd); +} + +/**************************************************************************** + * Name: esp32_rtc_clk_fast_freq_set + * + * Description: + * Select source for RTC_FAST_CLK. + * + * Input Parameters: + * cfg - Clock source (one of enum esp32_rtc_fast_freq_e values) + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32_rtc_clk_fast_freq_set( + enum esp32_rtc_fast_freq_e fast_freq) +{ + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq); + ets_delay_us(DELAY_FAST_CLK_SWITCH); +} + +/**************************************************************************** + * Name: esp32_clk_val_is_valid + * + * Description: + * Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are + * stored as two copies in lower and upper 16-bit halves. + * These are the routines to work with such a representation. + * + * Input Parameters: + * val - register value + * + * Returned Value: + * true: Valid register value. + * false: Invalid register value. + * + ****************************************************************************/ + +static inline bool esp32_clk_val_is_valid(uint32_t val) +{ + return (val & 0xffff) == ((val >> 16) & 0xffff) + && val != 0 && val != UINT32_MAX; +} + +/**************************************************************************** + * Name: esp32_rtc_clk_cal_internal + * + * Description: + * 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. + * + * Returned Value: + * Number of XTAL clock cycles within the given number of slow clock cycles + * + ****************************************************************************/ + +static uint32_t IRAM_ATTR esp32_rtc_clk_cal_internal( + enum esp32_rtc_cal_sel_e cal_clk, uint32_t slowclk_cycles) +{ + uint32_t expected_freq; + uint32_t us_time_estimate; + uint32_t us_timer_max; + int timeout_us; + enum esp32_rtc_slow_freq_e slow_freq; + enum esp32_rtc_xtal_freq_e xtal_freq; + + /* Enable requested clock (150k clock is always on) */ + + int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, + RTC_CNTL_DIG_XTAL32K_EN); + + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) + { + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); + } + + if (cal_clk == RTC_CAL_8MD256) + { + modifyreg32(RTC_CNTL_CLK_CONF_REG, 0, RTC_CNTL_DIG_CLK8M_D256_EN); + } + + /* Prepare calibration */ + + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk); + modifyreg32(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING, 0); + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles); + + /* Figure out how long to wait for calibration to finish */ + + slow_freq = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL); + + if (cal_clk == RTC_CAL_32K_XTAL || + (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_32K_XTAL)) + { + expected_freq = 32768; /* standard 32k XTAL */ + } + else if (cal_clk == RTC_CAL_8MD256 || + (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_8MD256)) + { + expected_freq = RTC_FAST_CLK_FREQ_APPROX / 256; + } + else + { + expected_freq = 150000; /* 150k internal oscillator */ + } + + us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * + MHZ / expected_freq); + + /* Check if the required number of slowclk_cycles + * may result in an overflow of TIMG_RTC_CALI_VALUE. + */ + + xtal_freq = esp32_rtc_clk_xtal_freq_get(); + if (xtal_freq == RTC_XTAL_FREQ_AUTO) + { + /* XTAL frequency is not known yet; assume worst case (40 MHz) */ + + xtal_freq = RTC_XTAL_FREQ_40M; + } + + us_timer_max = TIMG_RTC_CALI_VALUE / (uint32_t) xtal_freq; + + if (us_time_estimate >= us_timer_max) + { + return 0; + } + + /* Start calibration */ + + modifyreg32(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START, 0); + modifyreg32(TIMG_RTCCALICFG_REG(0), 0, TIMG_RTC_CALI_START); + + /* Wait the expected time calibration should take. + * TODO: if running under RTOS, and us_time_estimate > RTOS tick, use the + * RTOS delay function. + */ + + ets_delay_us(us_time_estimate); + + /* Wait for calibration to finish up to another us_time_estimate */ + + timeout_us = us_time_estimate; + while (!(getreg32(TIMG_RTCCALICFG_REG(0)) & + TIMG_RTC_CALI_RDY) && (timeout_us > 0)) + { + timeout_us--; + ets_delay_us(1); + } + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, + dig_32k_xtal_state); + + if (cal_clk == RTC_CAL_8MD256) + { + modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN, 0); + } + + if (timeout_us == 0) + { + /* timed out waiting for calibration */ + + return 0; + } + + return REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE); +} + +/**************************************************************************** + * Name: esp32_rtc_clk_cal + * + * Description: + * 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 + * + * Returned Value: + * Average slow clock period in microseconds, Q13.19 fixed point format + * or 0 if calibration has timed out + * + ****************************************************************************/ + +static uint32_t IRAM_ATTR esp32_rtc_clk_cal(enum esp32_rtc_cal_sel_e cal_clk, + uint32_t slowclk_cycles) +{ + enum esp32_rtc_xtal_freq_e xtal_freq; + uint64_t xtal_cycles; + uint64_t divider; + uint64_t period_64; + uint32_t period; + + xtal_freq = esp32_rtc_clk_xtal_freq_get(); + xtal_cycles = esp32_rtc_clk_cal_internal(cal_clk, slowclk_cycles); + divider = ((uint64_t)xtal_freq) * slowclk_cycles; + period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) + / divider; + period = (uint32_t)(period_64 & UINT32_MAX); + + return period; +} + +/**************************************************************************** + * Name: esp32_rtc_clk_slow_freq_set + * + * Description: + * Select source for RTC_SLOW_CLK + * + * Input Parameters: + * slow_freq - Select source for RTC_SLOW_CLK + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void IRAM_ATTR esp32_rtc_clk_slow_freq_set( + enum esp32_rtc_slow_freq_e slow_freq) +{ + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, + (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0); + + ets_delay_us(DELAY_SLOW_CLK_SWITCH); +} + +/**************************************************************************** + * Name: esp32_select_rtc_slow_clk + * + * Description: + * Selects an clock source for RTC. + * + * Input Parameters: + * slow_clk - RTC SLOW_CLK frequency values + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void esp32_select_rtc_slow_clk(enum esp32_slow_clk_sel_e slow_clk) +{ + uint32_t cal_val = 0; + enum esp32_rtc_slow_freq_e rtc_slow_freq = slow_clk & + RTC_CNTL_ANA_CLK_RTC_SEL_V; + + do + { + esp32_rtc_clk_slow_freq_set(rtc_slow_freq); + + /* TODO: 32k XTAL oscillator has some frequency drift at startup. + * Improve calibration routine to wait until the frequency is stable. + */ + + cal_val = esp32_rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES); + } + while (cal_val == 0); + + putreg32((uint32_t)cal_val, RTC_SLOW_CLK_CAL_REG); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +enum esp32_rtc_xtal_freq_e rtc_get_xtal(void) + __attribute__((alias("esp32_rtc_clk_xtal_freq_get"))); + +/**************************************************************************** + * Name: esp32_rtc_clk_xtal_freq_get + * + * Description: + * Get main XTAL frequency + * + * Input Parameters: + * None + * + * Returned Value: + * XTAL frequency (one of enum esp32_rtc_xtal_freq_e values) + * + ****************************************************************************/ + +enum esp32_rtc_xtal_freq_e IRAM_ATTR esp32_rtc_clk_xtal_freq_get(void) +{ + /* We may have already written XTAL value into RTC_XTAL_FREQ_REG */ + + uint32_t xtal_freq_reg = getreg32(RTC_XTAL_FREQ_REG); + + if (!esp32_clk_val_is_valid(xtal_freq_reg)) + { + return RTC_XTAL_FREQ_AUTO; + } + + return (xtal_freq_reg & ~RTC_DISABLE_ROM_LOG) & UINT16_MAX; +} + +/**************************************************************************** + * Name: esp32_rtc_update_to_xtal + * + * Description: + * Switch to XTAL frequency, does not disable the PLL + * + * Input Parameters: + * freq - XTAL frequency + * div - REF_TICK divider + * + * Returned Value: + * none + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_update_to_xtal(int freq, int div) +{ + uint32_t value = (((freq * MHZ) >> 12) & UINT16_MAX) + | ((((freq * MHZ) >> 12) & UINT16_MAX) << 16); + putreg32(value, RTC_APB_FREQ_REG); + + /* set divider from XTAL to APB clock */ + + REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, div - 1); + + /* switch clock source */ + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, + RTC_CNTL_SOC_CLK_SEL_XTL); + + /* adjust ref_tick */ + + modifyreg32(APB_CTRL_XTAL_TICK_CONF_REG, 0, + (freq * MHZ) / REF_CLK_FREQ - 1); + + /* lower the voltage */ + + if (freq <= 2) + { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_2M); + } + else + { + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL); + } +} + +/**************************************************************************** + * Name: esp32_rtc_bbpll_enable + * + * Description: + * Reset BBPLL configuration. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_bbpll_enable(void) +{ + modifyreg32(RTC_CNTL_OPTIONS0_REG, + RTC_CNTL_BIAS_I2C_FORCE_PD | RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD, 0); + + /* reset BBPLL configuration */ + + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_DELAY, + BBPLL_IR_CAL_DELAY_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_IR_CAL_EXT_CAP, + BBPLL_IR_CAL_EXT_CAP_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_FCAL, + BBPLL_OC_ENB_FCAL_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_ENB_VCON, + BBPLL_OC_ENB_VCON_VAL); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_CAL_7_0, + BBPLL_BBADC_CAL_7_0_VAL); +} + +/**************************************************************************** + * Name: esp32_rtc_bbpll_configure + * + * Description: + * Configure main XTAL frequency values according to pll_freq. + * + * Input Parameters: + * xtal_freq - XTAL frequency values + * pll_freq - PLL frequency values + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_bbpll_configure( + enum esp32_rtc_xtal_freq_e xtal_freq, int pll_freq) +{ + static uint8_t div_ref = 0; + static uint8_t div7_0 = 0; + static uint8_t div10_8 = 0; + static uint8_t lref = 0 ; + static uint8_t dcur = 0; + static uint8_t bw = 0; + uint8_t i2c_bbpll_lref = 0; + uint8_t i2c_bbpll_div_7_0 = 0; + uint8_t i2c_bbpll_dcur = 0; + + if (pll_freq == RTC_PLL_FREQ_320M) + { + /* Raise the voltage, if needed */ + + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, + DIG_DBIAS_80M_160M); + + /* Configure 320M PLL */ + + switch (xtal_freq) + { + case RTC_XTAL_FREQ_40M: + { + div_ref = 0; + div7_0 = 32; + div10_8 = 0; + lref = 0; + dcur = 6; + bw = 3; + } + break; + + case RTC_XTAL_FREQ_26M: + { + div_ref = 12; + div7_0 = 224; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + } + break; + + case RTC_XTAL_FREQ_24M: + { + div_ref = 11; + div7_0 = 224; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + } + break; + + default: + { + div_ref = 12; + div7_0 = 224; + div10_8 = 4; + lref = 0; + dcur = 0; + bw = 0; + } + break; + } + + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_320M); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, + BBPLL_BBADC_DSMP_VAL_320M); + } + else + { + /* Raise the voltage */ + + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M); + ets_delay_us(DELAY_PLL_DBIAS_RAISE); + + /* Configure 480M PLL */ + + switch (xtal_freq) + { + case RTC_XTAL_FREQ_40M: + { + div_ref = 0; + div7_0 = 28; + div10_8 = 0; + lref = 0; + dcur = 6; + bw = 3; + } + break; + + case RTC_XTAL_FREQ_26M: + { + div_ref = 12; + div7_0 = 144; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + } + break; + + case RTC_XTAL_FREQ_24M: + { + div_ref = 11; + div7_0 = 144; + div10_8 = 4; + lref = 1; + dcur = 0; + bw = 1; + } + break; + + default: + { + div_ref = 12; + div7_0 = 224; + div10_8 = 4; + lref = 0; + dcur = 0; + bw = 0; + } + break; + } + + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_480M); + I2C_WRITEREG_RTC(I2C_BBPLL, + I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_480M); + } + + i2c_bbpll_lref = (lref << 7) | (div10_8 << 4) | (div_ref); + i2c_bbpll_div_7_0 = div7_0; + i2c_bbpll_dcur = (bw << 6) | dcur; + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); + I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); +} + +/**************************************************************************** + * Name: esp32_rtc_clk_set + * + * Description: + * Set RTC CLK frequency. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_clk_set() +{ + enum esp32_rtc_fast_freq_e fast_freq = RTC_FAST_FREQ_8M; + enum esp32_slow_clk_sel_e slow_clk = RTC_SLOW_FREQ_RTC; + esp32_rtc_clk_fast_freq_set(fast_freq); + esp32_select_rtc_slow_clk(slow_clk); +} + +/**************************************************************************** + * Name: esp32_rtc_init + * + * Description: + * Initialize RTC clock and power control related functions. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_init() +{ + struct esp32_rtc_priv_s *priv = &esp32_rtc_priv; + + modifyreg32(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU | + RTC_CNTL_TXRF_I2C_PU | RTC_CNTL_RFRX_PBUS_PU | + RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU, 0); + + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, priv->pll_wait); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, priv->xtal_wait); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, priv->ck8m_wait); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, + RTC_CNTL_DBG_ATTEN_DEFAULT); + + modifyreg32(RTC_CNTL_BIAS_CONF_REG, 0, + RTC_CNTL_DEC_HEARTBEAT_WIDTH | RTC_CNTL_INC_HEARTBEAT_PERIOD); + + /* Reset RTC bias to default value (needed if waking up from deep sleep) */ + + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_1V10); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, RTC_CNTL_DBIAS_1V10); + if (priv->clkctl_init) + { + /* clear CMMU clock force on */ + + modifyreg32(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CMMU_FORCE_ON, 0); + modifyreg32(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CMMU_FORCE_ON, 0); + + /* clear rom clock force on */ + + modifyreg32(DPORT_ROM_FO_CTRL_REG, + (DPORT_SHARE_ROM_FO << DPORT_SHARE_ROM_FO_S), 0); + modifyreg32(DPORT_ROM_FO_CTRL_REG, DPORT_APP_ROM_FO | + DPORT_PRO_ROM_FO, 0); + + /* clear sram clock force on */ + + modifyreg32(DPORT_SRAM_FO_CTRL_0_REG, DPORT_SRAM_FO_0, 0); + modifyreg32(DPORT_SRAM_FO_CTRL_1_REG, DPORT_SRAM_FO_1, 0); + + /* clear tag clock force on */ + + modifyreg32(DPORT_TAG_FO_CTRL_REG, DPORT_APP_CACHE_TAG_FORCE_ON | + DPORT_PRO_CACHE_TAG_FORCE_ON, 0); + } + + if (priv->pwrctl_init) + { + modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, 0); + + /* cancel xtal force pu */ + + modifyreg32(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, 0); + + /* cancel BIAS force pu */ + + modifyreg32(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_CORE_FORCE_PU | + RTC_CNTL_BIAS_I2C_FORCE_PU | RTC_CNTL_BIAS_FORCE_NOSLEEP, 0); + + /* bias follow 8M */ + + modifyreg32(RTC_CNTL_OPTIONS0_REG, 0, RTC_CNTL_BIAS_CORE_FOLW_8M | + RTC_CNTL_BIAS_I2C_FOLW_8M | RTC_CNTL_BIAS_SLEEP_FOLW_8M); + + /* CLEAR APLL close */ + + modifyreg32(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, + RTC_CNTL_PLLA_FORCE_PD); + modifyreg32(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_FORCE_PU | + RTC_CNTL_BBPLL_I2C_FORCE_PU, 0); + + /* cancel RTC REG force PU */ + + modifyreg32(RTC_CNTL_REG, RTC_CNTL_FORCE_PU | + RTC_CNTL_DBOOST_FORCE_PU, 0); + if (priv->rtc_dboost_fpd) + { + modifyreg32(RTC_CNTL_REG, 0, RTC_CNTL_DBOOST_FORCE_PD); + } + else + { + modifyreg32(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD, 0); + } + + /* cancel digital pu force */ + + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU | + RTC_CNTL_DG_WRAP_FORCE_PU | RTC_CNTL_WIFI_FORCE_PU | + RTC_CNTL_CPU_ROM_RAM_FORCE_PU , 0); + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU | + RTC_CNTL_PWC_FORCE_PU, 0); + modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_WRAP_FORCE_NOISO | + RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_CPU_ROM_RAM_FORCE_NOISO, 0); + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_NOISO | + RTC_CNTL_FORCE_NOISO, 0); + + /* cancel digital PADS force no iso */ + + modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD | + RTC_CNTL_DG_PAD_FORCE_NOISO, 0); + } +} + +/**************************************************************************** + * Name: esp32_rtc_time_get + * + * Description: + * Get current value of RTC counter. + * + * Input Parameters: + * None + * + * Returned Value: + * current value of RTC counter + * + ****************************************************************************/ + +uint64_t IRAM_ATTR esp32_rtc_time_get(void) +{ + uint64_t rtc_time; + + modifyreg32(RTC_CNTL_TIME_UPDATE_REG, 0, RTC_CNTL_TIME_UPDATE); + + /* might take 1 RTC slowclk period, don't flood RTC bus */ + + while ((getreg32(RTC_CNTL_TIME_UPDATE_REG) & RTC_CNTL_TIME_VALID) == 0) + { + ets_delay_us(1); + } + + modifyreg32(RTC_CNTL_INT_CLR_REG, 0, RTC_CNTL_TIME_VALID_INT_CLR); + rtc_time = getreg32(RTC_CNTL_TIME0_REG); + rtc_time |= ((uint64_t) getreg32(RTC_CNTL_TIME1_REG)) << 32; + + return rtc_time; +} + +/**************************************************************************** + * Name: esp32_rtc_time_us_to_slowclk + * + * Description: + * Convert time interval from microseconds to RTC_SLOW_CLK cycles. + * + * Input Parameters: + * time_in_us - Time interval in microseconds + * slow_clk_period - Period of slow clock in microseconds + * + * Returned Value: + * number of slow clock cycles + * + ****************************************************************************/ + +uint64_t IRAM_ATTR esp32_rtc_time_us_to_slowclk(uint64_t time_in_us, + uint32_t period) +{ + /* Overflow will happen in this function if time_in_us >= 2^45, + * which is about 400 days. TODO: fix overflow. + */ + + return (time_in_us << RTC_CLK_CAL_FRACT) / period; +} + +/**************************************************************************** + * Name: esp32_rtc_bbpll_disable + * + * Description: + * disable BBPLL. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_bbpll_disable(void) +{ + uint32_t apll_fpd; + modifyreg32(RTC_CNTL_OPTIONS0_REG, 0, RTC_CNTL_BB_I2C_FORCE_PD | + RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD); + + /* is APLL under force power down? */ + + apll_fpd = REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD); + + if (apll_fpd) + { + /* then also power down the internal I2C bus */ + + modifyreg32(RTC_CNTL_OPTIONS0_REG, 0, RTC_CNTL_BIAS_I2C_FORCE_PD); + } +} + +/**************************************************************************** + * Name: esp32_rtc_sleep_set_wakeup_time + * + * Description: + * 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. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_sleep_set_wakeup_time(uint64_t t) +{ + putreg32(t & UINT32_MAX, RTC_CNTL_SLP_TIMER0_REG); + putreg32((uint32_t)(t >> 32), RTC_CNTL_SLP_TIMER1_REG); +} + +/**************************************************************************** + * Name: esp32_rtc_wait_for_slow_cycle + * + * Description: + * Busy loop until next RTC_SLOW_CLK cycle. + * + * Input Parameters: + * None + * + * Returned Value: + * none + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_wait_for_slow_cycle(void) +{ + modifyreg32(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING | + TIMG_RTC_CALI_START, 0); + modifyreg32(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY, 0); + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, + RTC_CAL_RTC_MUX); + + /* Request to run calibration for 0 slow clock cycles. + * RDY bit will be set on the nearest slow clock cycle. + */ + + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, 0); + modifyreg32(TIMG_RTCCALICFG_REG(0), 0, TIMG_RTC_CALI_START); + + /* RDY needs some time to go low */ + + ets_delay_us(1); + + while (!(getreg32(TIMG_RTCCALICFG_REG(0)) & TIMG_RTC_CALI_RDY)) + { + ets_delay_us(1); + } +} + +/**************************************************************************** + * Name: esp32_rtc_cpu_freq_set_xtal + * + * Description: + * Switch CPU clock source to XTAL + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_cpu_freq_set_xtal(void) +{ + int freq_mhz = (int) esp32_rtc_clk_xtal_freq_get(); + esp32_rtc_update_to_xtal(freq_mhz, 1); + esp32_rtc_wait_for_slow_cycle(); + esp32_rtc_bbpll_disable(); +} + +/**************************************************************************** + * Name: esp32_rtc_sleep_init + * + * Description: + * Prepare the chip to enter sleep mode + * + * Input Parameters: + * flags - sleep mode configuration + * + * Returned Value: + * None + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_sleep_init(uint32_t flags) +{ + struct esp32_rtc_sleep_config_s cfg = RTC_SLEEP_CONFIG_DEFAULT(flags); + + struct esp32_rtc_sleep_pd_config_s pd_cfg = + RTC_SLEEP_PD_CONFIG_ALL(cfg.lslp_meminf_pd); + + /* set 5 PWC state machine times to fit in main state machine time */ + + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, + RTC_CNTL_PLL_BUF_WAIT_SLP); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, + RTC_CNTL_XTL_BUF_WAIT_SLP); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, + RTC_CNTL_CK8M_WAIT_SLP); + + /* set shortest possible sleep time limit */ + + REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, + RTC_CNTL_MIN_SLP_VAL_MIN); + + /* set rom&ram timer */ + + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, + ROM_RAM_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, + ROM_RAM_WAIT_CYCLES); + + /* set wifi timer */ + + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, + WIFI_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, + WIFI_WAIT_CYCLES); + + /* set rtc peri timer */ + + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_POWERUP_TIMER, + RTC_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_WAIT_TIMER, + RTC_WAIT_CYCLES); + + /* set digital wrap timer */ + + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER, + DG_WRAP_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER, + DG_WRAP_WAIT_CYCLES); + + /* set rtc memory timer */ + + REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_POWERUP_TIMER, + RTC_MEM_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_WAIT_TIMER, + RTC_MEM_WAIT_CYCLES); + + REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, + cfg.lslp_mem_inf_fpu); + esp32_rtc_sleep_pd(pd_cfg); + + if (cfg.rtc_mem_inf_fpu) + { + modifyreg32(RTC_CNTL_PWC_REG, 0, RTC_CNTL_MEM_FORCE_PU); + } + else + { + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU, 0); + } + + if (cfg.rtc_mem_inf_follow_cpu) + { + modifyreg32(RTC_CNTL_PWC_REG, 0, RTC_CNTL_MEM_FOLW_CPU); + } + else + { + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FOLW_CPU, 0); + } + + if (cfg.rtc_fastmem_pd_en) + { + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_PU | + RTC_CNTL_FASTMEM_FORCE_NOISO, RTC_CNTL_FASTMEM_PD_EN); + } + else + { + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_PD_EN, + RTC_CNTL_FASTMEM_FORCE_PU | RTC_CNTL_FASTMEM_FORCE_NOISO); + } + + if (cfg.rtc_slowmem_pd_en) + { + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU | + RTC_CNTL_SLOWMEM_FORCE_NOISO, RTC_CNTL_SLOWMEM_PD_EN); + } + else + { + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_PD_EN, + RTC_CNTL_SLOWMEM_FORCE_PU | RTC_CNTL_SLOWMEM_FORCE_NOISO); + } + + if (cfg.rtc_peri_pd_en) + { + modifyreg32(RTC_CNTL_PWC_REG, 0, RTC_CNTL_PD_EN); + } + else + { + modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_PD_EN, 0); + } + + if (cfg.wifi_pd_en) + { + modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_WIFI_PD_EN); + } + else + { + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN, 0); + } + + if (cfg.rom_mem_pd_en) + { + modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_CPU_ROM_RAM_PD_EN); + } + else + { + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_ROM_RAM_PD_EN, 0); + } + + if (cfg.deep_slp) + { + modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_ISO | + RTC_CNTL_DG_PAD_FORCE_NOISO, 0); + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU | + RTC_CNTL_DG_WRAP_FORCE_PD, RTC_CNTL_DG_WRAP_PD_EN); + modifyreg32(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_FORCE_NOSLEEP, 0); + + /* Shut down parts of RTC which may have been left + * enabled by the wireless drivers. + */ + + modifyreg32(RTC_CNTL_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 + { + modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN, 0); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0); + } + + REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); + + if (REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL) == + RTC_SLOW_FREQ_8MD256) + { + modifyreg32(RTC_CNTL_CLK_CONF_REG, 0, RTC_CNTL_CK8M_FORCE_PU); + } + else + { + modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, 0); + } + + /* enable VDDSDIO control by state machine */ + + modifyreg32(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE, 0); + REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, + cfg.vddsdio_pd_en); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, cfg.rtc_dbias_slp); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, cfg.rtc_dbias_wak); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, cfg.dig_dbias_wak); + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_SLP, cfg.dig_dbias_slp); +} + +/**************************************************************************** + * Name: esp32_rtc_sleep_start + * + * Description: + * Enter force sleep mode. + * + * Input Parameters: + * 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 + * + ****************************************************************************/ + +void IRAM_ATTR esp32_rtc_sleep_start(uint32_t wakeup_opt, + uint32_t reject_opt) +{ + REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt); + putreg32((uint32_t)reject_opt, RTC_CNTL_SLP_REJECT_CONF_REG); + + /* Start entry into sleep mode */ + + modifyreg32(RTC_CNTL_STATE0_REG, 0, RTC_CNTL_SLEEP_EN); + + while ((getreg32(RTC_CNTL_INT_RAW_REG) & + (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW)) == 0); + + /* In deep sleep mode, we never get here */ + + modifyreg32(RTC_CNTL_INT_CLR_REG, 0, + RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR); + + /* restore DBG_ATTEN to the default value */ + + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, + RTC_CNTL_DBG_ATTEN_DEFAULT); +} diff --git a/arch/xtensa/src/esp32/esp32_rtc.h b/arch/xtensa/src/esp32/esp32_rtc.h new file mode 100644 index 0000000..bf51407 --- /dev/null +++ b/arch/xtensa/src/esp32/esp32_rtc.h @@ -0,0 +1,300 @@ +/**************************************************************************** + * arch/xtensa/src/esp32/esp32_rtc.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_ESP32_ESP32_RTC_H +#define __ARCH_XTENSA_SRC_ESP32_ESP32_RTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Possible main XTAL frequency values. + * Enum values should be equal to frequency in MHz. + */ + +enum esp32_rtc_xtal_freq_e +{ + RTC_XTAL_FREQ_AUTO = 0, /* Automatic XTAL frequency detection */ + RTC_XTAL_FREQ_40M = 40, /* 40 MHz XTAL */ + RTC_XTAL_FREQ_26M = 26, /* 26 MHz XTAL */ + RTC_XTAL_FREQ_24M = 24, /* 24 MHz XTAL */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp32_rtc_clk_xtal_freq_get + * + * Description: + * Get main XTAL frequency + * + * Input Parameters: + * None + * + * Returned Value: + * XTAL frequency (one of enum esp32_rtc_xtal_freq_e values) + * + ****************************************************************************/ + +enum esp32_rtc_xtal_freq_e esp32_rtc_clk_xtal_freq_get(void); + +/**************************************************************************** + * Name: esp32_rtc_update_to_xtal + * + * Description: + * Switch to XTAL frequency, does not disable the PLL + * + * Input Parameters: + * freq - XTAL frequency + * div - REF_TICK divider + * + * Returned Value: + * none + * + ****************************************************************************/ + +void esp32_rtc_update_to_xtal(int freq, int div); + +/**************************************************************************** + * Name: esp32_rtc_bbpll_enable + * + * Description: + * Reset BBPLL configuration. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_bbpll_enable(void); + +/**************************************************************************** + * Name: esp32_rtc_bbpll_configure + * + * Description: + * Configure main XTAL frequency values according to pll_freq. + * + * Input Parameters: + * xtal_freq - XTAL frequency values + * pll_freq - PLL frequency values + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_bbpll_configure( + enum esp32_rtc_xtal_freq_e xtal_freq, int pll_freq); + +/**************************************************************************** + * Name: esp32_rtc_clk_set + * + * Description: + * Set RTC CLK frequency. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_clk_set(void); + +/**************************************************************************** + * Name: esp32_rtc_init + * + * Description: + * Initialize RTC clock and power control related functions. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_init(void); + +/**************************************************************************** + * Name: esp32_rtc_time_get + * + * Description: + * Get current value of RTC counter. + * + * Input Parameters: + * None + * + * Returned Value: + * current value of RTC counter + * + ****************************************************************************/ + +uint64_t esp32_rtc_time_get(void); + +/**************************************************************************** + * Name: esp32_rtc_time_us_to_slowclk + * + * Description: + * Convert time interval from microseconds to RTC_SLOW_CLK cycles. + * + * Input Parameters: + * time_in_us - Time interval in microseconds + * slow_clk_period - Period of slow clock in microseconds + * + * Returned Value: + * number of slow clock cycles + * + ****************************************************************************/ + +uint64_t esp32_rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period); + +/**************************************************************************** + * Name: esp32_rtc_bbpll_disable + * + * Description: + * disable BBPLL. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_bbpll_disable(void); + +/**************************************************************************** + * Name: esp32_rtc_sleep_set_wakeup_time + * + * Description: + * 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. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_sleep_set_wakeup_time(uint64_t t); + +/**************************************************************************** + * Name: esp32_rtc_wait_for_slow_cycle + * + * Description: + * Busy loop until next RTC_SLOW_CLK cycle. + * + * Input Parameters: + * None + * + * Returned Value: + * none + * + ****************************************************************************/ + +void esp32_rtc_wait_for_slow_cycle(void); + +/**************************************************************************** + * Name: esp32_rtc_cpu_freq_set_xtal + * + * Description: + * Switch CPU clock source to XTAL + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_cpu_freq_set_xtal(void); + +/**************************************************************************** + * Name: esp32_rtc_sleep_init + * + * Description: + * Prepare the chip to enter sleep mode + * + * Input Parameters: + * flags - sleep mode configuration + * + * Returned Value: + * None + * + ****************************************************************************/ + +void esp32_rtc_sleep_init(uint32_t flags); + +/**************************************************************************** + * Name: esp32_rtc_sleep_start + * + * Description: + * Enter force sleep mode. + * + * Input Parameters: + * 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 + * + ****************************************************************************/ + +void esp32_rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt); + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_ESP32_ESP32_RTC_H */ diff --git a/arch/xtensa/src/esp32/hardware/esp32_dport.h b/arch/xtensa/src/esp32/hardware/esp32_dport.h index 7df920b..47989fa 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_dport.h +++ b/arch/xtensa/src/esp32/hardware/esp32_dport.h @@ -201,6 +201,9 @@ #define DPORT_CPUPERIOD_SEL_M ((DPORT_CPUPERIOD_SEL_V)<<(DPORT_CPUPERIOD_SEL_S)) #define DPORT_CPUPERIOD_SEL_V 0x3 #define DPORT_CPUPERIOD_SEL_S 0 +#define DPORT_CPUPERIOD_SEL_80 0 +#define DPORT_CPUPERIOD_SEL_160 1 +#define DPORT_CPUPERIOD_SEL_240 2 #define DPORT_PRO_CACHE_CTRL_REG (DR_REG_DPORT_BASE + 0x040) diff --git a/arch/xtensa/include/xtensa/core_macros.h b/arch/xtensa/src/esp32/hardware/esp32_i2s.h similarity index 59% copy from arch/xtensa/include/xtensa/core_macros.h copy to arch/xtensa/src/esp32/hardware/esp32_i2s.h index 7c5b16e..88c0e49 100644 --- a/arch/xtensa/include/xtensa/core_macros.h +++ b/arch/xtensa/src/esp32/hardware/esp32_i2s.h @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/xtensa/include/xtensa/core_macros.h + * arch/xtensa/src/esp32/esp32_i2s.h * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -18,22 +18,30 @@ * ****************************************************************************/ -#ifndef __ARCH_XTENSA_INCUDE_XTENSA_CORE_MACRO_H -#define __ARCH_XTENSA_INCUDE_XTENSA_CORE_MACRO_H - /**************************************************************************** * Included Files ****************************************************************************/ -#include <arch/chip/core-isa.h> -#include <arch/chip/tie.h> +#ifndef __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_I2S_H +#define __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_I2S_H -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ +#include "esp32_soc.h" + +#define REG_I2S_BASE( i ) (DR_REG_I2S_BASE + ((i)*0x1e000)) +#define I2S_PD_CONF_REG(i) (REG_I2S_BASE(i) + 0x00a4) + +/* I2S_PLC_MEM_FORCE_PU : R/W ;bitpos:[3] ;default: 1'h1 ; */ + +#define I2S_PLC_MEM_FORCE_PU (BIT(3)) +#define I2S_PLC_MEM_FORCE_PU_M (BIT(3)) +#define I2S_PLC_MEM_FORCE_PU_V 0x1 +#define I2S_PLC_MEM_FORCE_PU_S 3 + +/* I2S_FIFO_FORCE_PU : R/W ;bitpos:[1] ;default: 1'h1 ; */ -#define XTHAL_GET_CCOUNT() ({ int __ccount; \ - __asm__ __volatile__("rsr.ccount %0":\ - "=a"(__ccount)); __ccount; }) +#define I2S_FIFO_FORCE_PU (BIT(1)) +#define I2S_FIFO_FORCE_PU_M (BIT(1)) +#define I2S_FIFO_FORCE_PU_V 0x1 +#define I2S_FIFO_FORCE_PU_S 1 -#endif /* __ARCH_XTENSA_INCUDE_XTENSA_CORE_H */ +#endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_I2S_H */ diff --git a/arch/xtensa/src/esp32/hardware/esp32_rtccntl.h b/arch/xtensa/src/esp32/hardware/esp32_rtccntl.h index af7bbe0..2923016 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_rtccntl.h +++ b/arch/xtensa/src/esp32/hardware/esp32_rtccntl.h @@ -479,6 +479,7 @@ #define RTC_CNTL_PLL_BUF_WAIT_M ((RTC_CNTL_PLL_BUF_WAIT_V)<<(RTC_CNTL_PLL_BUF_WAIT_S)) #define RTC_CNTL_PLL_BUF_WAIT_V 0xFF #define RTC_CNTL_PLL_BUF_WAIT_S 24 +#define RTC_CNTL_PLL_BUF_WAIT_DEFAULT 20 /* RTC_CNTL_XTL_BUF_WAIT : R/W ;bitpos:[23:14] ;default: 10'd80 ; */ @@ -488,6 +489,7 @@ #define RTC_CNTL_XTL_BUF_WAIT_M ((RTC_CNTL_XTL_BUF_WAIT_V)<<(RTC_CNTL_XTL_BUF_WAIT_S)) #define RTC_CNTL_XTL_BUF_WAIT_V 0x3FF #define RTC_CNTL_XTL_BUF_WAIT_S 14 +#define RTC_CNTL_XTL_BUF_WAIT_DEFAULT 20 /* RTC_CNTL_CK8M_WAIT : R/W ;bitpos:[13:6] ;default: 8'h10 ; */ @@ -497,6 +499,7 @@ #define RTC_CNTL_CK8M_WAIT_M ((RTC_CNTL_CK8M_WAIT_V)<<(RTC_CNTL_CK8M_WAIT_S)) #define RTC_CNTL_CK8M_WAIT_V 0xFF #define RTC_CNTL_CK8M_WAIT_S 6 +#define RTC_CNTL_CK8M_WAIT_DEFAULT 20 /* RTC_CNTL_CPU_STALL_WAIT : R/W ;bitpos:[5:1] ;default: 5'd1 ; */ @@ -636,12 +639,13 @@ /* RTC_CNTL_MIN_SLP_VAL : R/W ;bitpos:[15:8] ;default: 8'h80 ; */ -/* Description: minimal sleep cycles in slow_clk_rtc */ +/* description: minimal sleep cycles in slow_clk_rtc */ -#define RTC_CNTL_MIN_SLP_VAL 0x000000FF -#define RTC_CNTL_MIN_SLP_VAL_M ((RTC_CNTL_MIN_SLP_VAL_V)<<(RTC_CNTL_MIN_SLP_VAL_S)) -#define RTC_CNTL_MIN_SLP_VAL_V 0xFF -#define RTC_CNTL_MIN_SLP_VAL_S 8 +#define RTC_CNTL_MIN_SLP_VAL 0x000000ff +#define RTC_CNTL_MIN_SLP_VAL_M ((RTC_CNTL_MIN_SLP_VAL_V)<<(RTC_CNTL_MIN_SLP_VAL_S)) +#define RTC_CNTL_MIN_SLP_VAL_V 0xff +#define RTC_CNTL_MIN_SLP_VAL_S 8 +#define RTC_CNTL_MIN_SLP_VAL_MIN 2 /* RTC_CNTL_ULP_CP_SUBTIMER_PREDIV : R/W ;bitpos:[7:0] ;default: 8'd1 ; */ @@ -1138,6 +1142,8 @@ #define RTC_CNTL_STORE1_REG (DR_REG_RTCCNTL_BASE + 0x50) +#define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG + /* RTC_CNTL_SCRATCH1 : R/W ;bitpos:[31:0] ;default: 0 ; */ /* Description: 32-bit general purpose retention register */ @@ -1320,15 +1326,6 @@ #define RTC_CNTL_FAST_CLK_RTC_SEL_V 0x1 #define RTC_CNTL_FAST_CLK_RTC_SEL_S 29 -/* RTC_CNTL_SOC_CLK_SEL : R/W ;bitpos:[28:27] ;default: 2'd0 ; */ - -/* Description: SOC clock sel. 0: XTAL 1: PLL 2: CK8M 3: APLL */ - -#define RTC_CNTL_SOC_CLK_SEL 0x00000003 -#define RTC_CNTL_SOC_CLK_SEL_M ((RTC_CNTL_SOC_CLK_SEL_V)<<(RTC_CNTL_SOC_CLK_SEL_S)) -#define RTC_CNTL_SOC_CLK_SEL_V 0x3 -#define RTC_CNTL_SOC_CLK_SEL_S 27 - /* RTC_CNTL_CK8M_FORCE_PU : R/W ;bitpos:[26] ;default: 1'd0 ; */ /* Description: CK8M force power up */ @@ -1610,6 +1607,7 @@ #define RTC_CNTL_DBG_ATTEN_M ((RTC_CNTL_DBG_ATTEN_V)<<(RTC_CNTL_DBG_ATTEN_S)) #define RTC_CNTL_DBG_ATTEN_V 0x3 #define RTC_CNTL_DBG_ATTEN_S 24 +#define RTC_CNTL_DBG_ATTEN_DEFAULT 3 #define RTC_CNTL_REG (DR_REG_RTCCNTL_BASE + 0x7c) @@ -1678,15 +1676,6 @@ #define RTC_CNTL_SCK_DCAP_V 0xFF #define RTC_CNTL_SCK_DCAP_S 14 -/* RTC_CNTL_DIG_DBIAS_WAK : R/W ;bitpos:[13:11] ;default: 3'd4 ; */ - -/* Description: DIG_REG_DBIAS during wakeup */ - -#define RTC_CNTL_DIG_DBIAS_WAK 0x00000007 -#define RTC_CNTL_DIG_DBIAS_WAK_M ((RTC_CNTL_DIG_DBIAS_WAK_V)<<(RTC_CNTL_DIG_DBIAS_WAK_S)) -#define RTC_CNTL_DIG_DBIAS_WAK_V 0x7 -#define RTC_CNTL_DIG_DBIAS_WAK_S 11 - /* RTC_CNTL_DIG_DBIAS_SLP : R/W ;bitpos:[10:8] ;default: 3'd4 ; */ /* Description: DIG_REG_DBIAS during sleep */ @@ -2962,4 +2951,230 @@ #define RTC_CNTL_CNTL_DATE_S 0 #define RTC_CNTL_RTC_CNTL_DATE_VERSION 0x1604280 +/* Useful groups of RTC_CNTL_DIG_PWC_REG bits */ + +#define RTC_CNTL_CPU_ROM_RAM_PD_EN \ + (RTC_CNTL_INTER_RAM4_PD_EN | RTC_CNTL_INTER_RAM3_PD_EN |\ + RTC_CNTL_INTER_RAM2_PD_EN | RTC_CNTL_INTER_RAM1_PD_EN |\ + RTC_CNTL_INTER_RAM0_PD_EN | RTC_CNTL_ROM0_PD_EN) +#define RTC_CNTL_CPU_ROM_RAM_FORCE_PU \ + (RTC_CNTL_INTER_RAM4_FORCE_PU | RTC_CNTL_INTER_RAM3_FORCE_PU |\ + RTC_CNTL_INTER_RAM2_FORCE_PU | RTC_CNTL_INTER_RAM1_FORCE_PU |\ + RTC_CNTL_INTER_RAM0_FORCE_PU | RTC_CNTL_ROM0_FORCE_PU) +#define RTC_CNTL_CPU_ROM_RAM_FORCE_PD \ + (RTC_CNTL_INTER_RAM4_FORCE_PD | RTC_CNTL_INTER_RAM3_FORCE_PD |\ + RTC_CNTL_INTER_RAM2_FORCE_PD | RTC_CNTL_INTER_RAM1_FORCE_PD |\ + RTC_CNTL_INTER_RAM0_FORCE_PD | RTC_CNTL_ROM0_FORCE_PD + +/* Useful groups of RTC_CNTL_PWC_REG bits */ + +#define RTC_CNTL_MEM_FORCE_ISO \ + (RTC_CNTL_SLOWMEM_FORCE_ISO | RTC_CNTL_FASTMEM_FORCE_ISO) +#define RTC_CNTL_MEM_FORCE_NOISO \ + (RTC_CNTL_SLOWMEM_FORCE_NOISO | RTC_CNTL_FASTMEM_FORCE_NOISO) +#define RTC_CNTL_MEM_PD_EN \ + (RTC_CNTL_SLOWMEM_PD_EN | RTC_CNTL_FASTMEM_PD_EN) +#define RTC_CNTL_MEM_FORCE_PU \ + (RTC_CNTL_SLOWMEM_FORCE_PU | RTC_CNTL_FASTMEM_FORCE_PU) +#define RTC_CNTL_MEM_FORCE_PD \ + (RTC_CNTL_SLOWMEM_FORCE_PD | RTC_CNTL_FASTMEM_FORCE_PD) +#define RTC_CNTL_MEM_FOLW_CPU \ + (RTC_CNTL_SLOWMEM_FOLW_CPU | RTC_CNTL_FASTMEM_FOLW_CPU) +#define RTC_CNTL_MEM_FORCE_LPU \ + (RTC_CNTL_SLOWMEM_FORCE_LPU | RTC_CNTL_FASTMEM_FORCE_LPU) +#define RTC_CNTL_MEM_FORCE_LPD \ + (RTC_CNTL_SLOWMEM_FORCE_LPD | RTC_CNTL_FASTMEM_FORCE_LPD) + +/* Useful groups of RTC_CNTL_DIG_ISO_REG bits */ + +#define RTC_CNTL_CPU_ROM_RAM_FORCE_ISO \ + (RTC_CNTL_INTER_RAM4_FORCE_ISO | RTC_CNTL_INTER_RAM3_FORCE_ISO |\ + RTC_CNTL_INTER_RAM2_FORCE_ISO | RTC_CNTL_INTER_RAM1_FORCE_ISO |\ + RTC_CNTL_INTER_RAM0_FORCE_ISO | RTC_CNTL_ROM0_FORCE_ISO) +#define RTC_CNTL_CPU_ROM_RAM_FORCE_NOISO \ + (RTC_CNTL_INTER_RAM4_FORCE_NOISO | RTC_CNTL_INTER_RAM3_FORCE_NOISO |\ + RTC_CNTL_INTER_RAM2_FORCE_NOISO | RTC_CNTL_INTER_RAM1_FORCE_NOISO |\ + RTC_CNTL_INTER_RAM0_FORCE_NOISO | RTC_CNTL_ROM0_FORCE_NOISO) + +/* Deep sleep (power down digital domain) */ + +#define RTC_SLEEP_PD_DIG BIT(0) + +/* Power down RTC peripherals */ + +#define RTC_SLEEP_PD_RTC_PERIPH BIT(1) + +/* Power down RTC SLOW memory */ + +#define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) + +/* Power down RTC FAST memory */ + +#define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) + +/* RTC FAST and SLOW memories are automatically + * powered up and down along with the CPU + */ + +#define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) + +/* Power down VDDSDIO regulator */ + +#define RTC_SLEEP_PD_VDDSDIO BIT(5) + +/* Power down main XTAL */ + +#define RTC_SLEEP_PD_XTAL BIT(6) + +#define RTC_IO_EXT_WAKEUP0_REG (DR_REG_RTCIO_BASE + 0xbc) + +/* RTC_IO_EXT_WAKEUP0_SEL : R/W ;bitpos:[31:27] ;default: 5'd0 ; */ + +/* description: select the wakeup source Ó0Ó select + * GPIO0 Ó1Ó select GPIO2 ...Ò17Ó select GPIO17 + */ + +#define RTC_IO_EXT_WAKEUP0_SEL 0x0000001f +#define RTC_IO_EXT_WAKEUP0_SEL_M ((RTC_IO_EXT_WAKEUP0_SEL_V)<<(RTC_IO_EXT_WAKEUP0_SEL_S)) +#define RTC_IO_EXT_WAKEUP0_SEL_V 0x1f +#define RTC_IO_EXT_WAKEUP0_SEL_S 27 + +/* RTC_CNTL_WDT_STGX : */ + +/* description: stage action selection values */ + +#define RTC_WDT_STG_SEL_OFF 0 +#define RTC_WDT_STG_SEL_INT 1 +#define RTC_WDT_STG_SEL_RESET_CPU 2 +#define RTC_WDT_STG_SEL_RESET_SYSTEM 3 +#define RTC_WDT_STG_SEL_RESET_RTC 4 + +/* Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, + * RTC_CNTL_DBIAS_SLP, RTC_CNTL_DIG_DBIAS_WAK, + * RTC_CNTL_DIG_DBIAS_SLP values. Valid if RTC_CNTL_DBG_ATTEN is 0. + */ + +#define RTC_CNTL_DBIAS_0V90 0 +#define RTC_CNTL_DBIAS_0V95 1 +#define RTC_CNTL_DBIAS_1V00 2 +#define RTC_CNTL_DBIAS_1V05 3 +#define RTC_CNTL_DBIAS_1V10 4 +#define RTC_CNTL_DBIAS_1V15 5 +#define RTC_CNTL_DBIAS_1V20 6 +#define RTC_CNTL_DBIAS_1V25 7 + +#define RTC_IO_XTAL_32K_PAD_REG (DR_REG_RTCIO_BASE + 0x8c) + +/* RTC_IO_XPD_XTAL_32K : R/W ;bitpos:[19] ;default: 1'd0 ; */ + +/* description: Power up 32kHz crystal oscillator */ + +#define RTC_IO_XPD_XTAL_32K (BIT(19)) +#define RTC_IO_XPD_XTAL_32K_M (BIT(19)) +#define RTC_IO_XPD_XTAL_32K_V 0x1 +#define RTC_IO_XPD_XTAL_32K_S 19 + +/* RTC_IO_X32N_MUX_SEL : R/W ;bitpos:[18] ;default: 1'd0 ; */ + +/* description: Ò1Ó select the digital function Ó0Óslection + * the rtc function + */ + +#define RTC_IO_X32N_MUX_SEL (BIT(18)) +#define RTC_IO_X32N_MUX_SEL_M (BIT(18)) +#define RTC_IO_X32N_MUX_SEL_V 0x1 +#define RTC_IO_X32N_MUX_SEL_S 18 + +/* RTC_IO_X32P_MUX_SEL : R/W ;bitpos:[17] ;default: 1'd0 ; */ + +/* description: Ò1Ó select the digital function Ó0Óslection + * the rtc function + */ + +#define RTC_IO_X32P_MUX_SEL (BIT(17)) +#define RTC_IO_X32P_MUX_SEL_M (BIT(17)) +#define RTC_IO_X32P_MUX_SEL_V 0x1 +#define RTC_IO_X32P_MUX_SEL_S 17 + +/* RTC_IO_X32P_RDE : R/W ;bitpos:[23] ;default: 1'd0 ; */ + +/* description: the pull down enable of the pad */ + +#define RTC_IO_X32P_RDE (BIT(23)) +#define RTC_IO_X32P_RDE_M (BIT(23)) +#define RTC_IO_X32P_RDE_V 0x1 +#define RTC_IO_X32P_RDE_S 23 + +/* RTC_IO_X32P_RUE : R/W ;bitpos:[22] ;default: 1'd0 ; */ + +/* description: the pull up enable of the pad */ + +#define RTC_IO_X32P_RUE (BIT(22)) +#define RTC_IO_X32P_RUE_M (BIT(22)) +#define RTC_IO_X32P_RUE_V 0x1 +#define RTC_IO_X32P_RUE_S 22 + +/* RTC_IO_X32N_RUE : R/W ;bitpos:[27] ;default: 1'd0 ; */ + +/* description: the pull up enable of the pad */ + +#define RTC_IO_X32N_RUE (BIT(27)) +#define RTC_IO_X32N_RUE_M (BIT(27)) +#define RTC_IO_X32N_RUE_V 0x1 +#define RTC_IO_X32N_RUE_S 27 + +/* RTC_IO_X32N_RDE : R/W ;bitpos:[28] ;default: 1'd0 ; */ + +/* description: the pull down enable of the pad */ + +#define RTC_IO_X32N_RDE (BIT(28)) +#define RTC_IO_X32N_RDE_M (BIT(28)) +#define RTC_IO_X32N_RDE_V 0x1 +#define RTC_IO_X32N_RDE_S 28 + +/* RTC_IO_X32N_FUN_IE : R/W ;bitpos:[11] ;default: 1'd0 ; */ + +/* description: the input enable of the pad */ + +#define RTC_IO_X32N_FUN_IE (BIT(11)) +#define RTC_IO_X32N_FUN_IE_M (BIT(11)) +#define RTC_IO_X32N_FUN_IE_V 0x1 +#define RTC_IO_X32N_FUN_IE_S 11 + +/* RTC_IO_X32P_FUN_IE : R/W ;bitpos:[5] ;default: 1'd0 ; */ + +/* description: the input enable of the pad */ + +#define RTC_IO_X32P_FUN_IE (BIT(5)) +#define RTC_IO_X32P_FUN_IE_M (BIT(5)) +#define RTC_IO_X32P_FUN_IE_V 0x1 +#define RTC_IO_X32P_FUN_IE_S 5 + +/* RTC_IO_DAC_XTAL_32K : R/W ;bitpos:[21:20] ;default: 2'b01 ; */ + +/* description: 32K XTAL bias current DAC. */ + +#define RTC_IO_DAC_XTAL_32K 0x00000003 +#define RTC_IO_DAC_XTAL_32K_M ((RTC_IO_DAC_XTAL_32K_V)<<(RTC_IO_DAC_XTAL_32K_S)) +#define RTC_IO_DAC_XTAL_32K_V 0x3 +#define RTC_IO_DAC_XTAL_32K_S 20 + +/* RTC_IO_DRES_XTAL_32K : R/W ;bitpos:[4:3] ;default: 2'b10 ; */ + +/* description: 32K XTAL resistor bias control. */ + +#define RTC_IO_DRES_XTAL_32K 0x00000003 +#define RTC_IO_DRES_XTAL_32K_M ((RTC_IO_DRES_XTAL_32K_V)<<(RTC_IO_DRES_XTAL_32K_S)) +#define RTC_IO_DRES_XTAL_32K_V 0x3 +#define RTC_IO_DRES_XTAL_32K_S 3 + +/* RTC_IO_DBIAS_XTAL_32K : R/W ;bitpos:[2:1] ;default: 2'b00 ; */ + +/* description: 32K XTAL self-bias reference control. */ + +#define RTC_IO_DBIAS_XTAL_32K 0x00000003 +#define RTC_IO_DBIAS_XTAL_32K_M ((RTC_IO_DBIAS_XTAL_32K_V)<<(RTC_IO_DBIAS_XTAL_32K_S)) +#define RTC_IO_DBIAS_XTAL_32K_V 0x3 +#define RTC_IO_DBIAS_XTAL_32K_S 1 + #endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_XTENSA_ESP32_H */ diff --git a/arch/xtensa/src/esp32/hardware/esp32_soc.h b/arch/xtensa/src/esp32/hardware/esp32_soc.h index 0cafbc6..6dc649e 100644 --- a/arch/xtensa/src/esp32/hardware/esp32_soc.h +++ b/arch/xtensa/src/esp32/hardware/esp32_soc.h @@ -110,13 +110,13 @@ * used when _f is not left shifted by _f##_S */ -#define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f)) +#define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f##_V)) /* Set field to register, * used when _f is not left shifted by _f##_S */ -#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f) << (_f##_S)))|(((_v) & (_f))<<(_f##_S))))) +#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S))))) /* Set field value from a variable, * used when _f is not left shifted by _f##_S @@ -207,6 +207,7 @@ #define DR_REG_GPIO_SD_BASE 0x3ff44f00 #define DR_REG_FE2_BASE 0x3ff45000 #define DR_REG_FE_BASE 0x3ff46000 +#define DR_REG_FRC_TIMER_BASE 0x3ff47000 #define DR_REG_RTCCNTL_BASE 0x3ff48000 #define DR_REG_RTCIO_BASE 0x3ff48400 #define DR_REG_SARADC_BASE 0x3ff48800 @@ -214,9 +215,9 @@ #define DR_REG_RTCMEM0_BASE 0x3ff61000 #define DR_REG_RTCMEM1_BASE 0x3ff62000 #define DR_REG_RTCMEM2_BASE 0x3ff63000 -#define DR_REG_HINF_BASE 0x3ff4B000 -#define DR_REG_UHCI1_BASE 0x3ff4C000 -#define DR_REG_I2S_BASE 0x3ff4F000 +#define DR_REG_HINF_BASE 0x3ff4b000 +#define DR_REG_UHCI1_BASE 0x3ff4c000 +#define DR_REG_I2S_BASE 0x3ff4f000 #define DR_REG_UART1_BASE 0x3ff50000 #define DR_REG_BT_BASE 0x3ff51000 #define DR_REG_I2C_EXT_BASE 0x3ff53000 @@ -226,20 +227,22 @@ #define DR_REG_PCNT_BASE 0x3ff57000 #define DR_REG_SLC_BASE 0x3ff58000 #define DR_REG_LEDC_BASE 0x3ff59000 -#define DR_REG_EFUSE_BASE 0x3ff5A000 -#define DR_REG_SPI_ENCRYPT_BASE 0x3ff5B000 -#define DR_REG_PWM_BASE 0x3ff5E000 -#define DR_REG_TIMERGROUP0_BASE 0x3ff5F000 +#define DR_REG_EFUSE_BASE 0x3ff5a000 +#define DR_REG_SPI_ENCRYPT_BASE 0x3ff5b000 +#define DR_REG_NRX_BASE 0x3ff5cc00 +#define DR_REG_BB_BASE 0x3ff5d000 +#define DR_REG_PWM_BASE 0x3ff5e000 +#define DR_REG_TIMERGROUP0_BASE 0x3ff5f000 #define DR_REG_TIMERGROUP1_BASE 0x3ff60000 #define DR_REG_SPI2_BASE 0x3ff64000 #define DR_REG_SPI3_BASE 0x3ff65000 #define DR_REG_I2C1_EXT_BASE 0x3ff67000 #define DR_REG_SDMMC_BASE 0x3ff68000 #define DR_REG_EMAC_BASE 0x3ff69000 -#define DR_REG_PWM1_BASE 0x3ff6C000 -#define DR_REG_I2S1_BASE 0x3ff6D000 -#define DR_REG_UART2_BASE 0x3ff6E000 -#define DR_REG_PWM2_BASE 0x3ff6F000 +#define DR_REG_PWM1_BASE 0x3ff6c000 +#define DR_REG_I2S1_BASE 0x3ff6d000 +#define DR_REG_UART2_BASE 0x3ff6e000 +#define DR_REG_PWM2_BASE 0x3ff6f000 #define DR_REG_PWM3_BASE 0x3ff70000 #define PERIPHS_SPI_ENCRYPT_BASEADDR DR_REG_SPI_ENCRYPT_BASE @@ -317,6 +320,10 @@ #define ETS_MPU_IA_INTR_SOURCE 67 /* Interrupt of MPU Invalid Access, LEVEL */ #define ETS_CACHE_IA_INTR_SOURCE 68 /* Interrupt of Cache Invalied Access, LEVEL */ +#define EFUSE_BLK0_RDATA4_REG (DR_REG_EFUSE_BASE + 0x010) +#define EFUSE_BLK0_RDATA3_REG (DR_REG_EFUSE_BASE + 0x00c) +#define GPIO_STRAP_REG (DR_REG_GPIO_BASE + 0x0038) + /* Interrupt cpu using table */ /**************************************************************************** @@ -418,6 +425,9 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add, #define I2C_WRITEREG_RTC(block, reg_add, indata) \ rom_i2c_writeReg(block, block##_HOSTID, reg_add, indata) +#define I2C_READREG_RTC(block, reg_add) \ + rom_i2c_readReg(block, block##_HOSTID, reg_add) + /* BBPLL configuration values */ #define BBPLL_ENDIV5_VAL_320M 0x43 @@ -432,9 +442,83 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add, #define BBPLL_BBADC_CAL_7_0_VAL 0x00 #define EFUSE_BLK0_RDATA5_REG (DR_REG_EFUSE_BASE + 0x014) + +/* EFUSE_RD_VOL_LEVEL_HP_INV: RO; bitpos:[23:22] */ + +/* description: This field stores the voltage level for + * CPU to run at 240 MHz, or for flash/PSRAM to run at 80 MHz. + * 0x0: level 7; 0x1: level 6; 0x2: level 5; 0x3: level 4. (RO) + */ + #define EFUSE_RD_VOL_LEVEL_HP_INV 0x03 +#define EFUSE_RD_VOL_LEVEL_HP_INV_M ((EFUSE_RD_VOL_LEVEL_HP_INV_V) << (EFUSE_RD_VOL_LEVEL_HP_INV_S)) +#define EFUSE_RD_VOL_LEVEL_HP_INV_V 0x03 #define EFUSE_RD_VOL_LEVEL_HP_INV_S 22 +/* EFUSE_RD_SDIO_FORCE : RO ;bitpos:[16] ;default: 1'b0 ; */ + +/* description: read for sdio_force */ + +#define EFUSE_RD_SDIO_FORCE (BIT(16)) +#define EFUSE_RD_SDIO_FORCE_M (BIT(16)) +#define EFUSE_RD_SDIO_FORCE_V 0x1 +#define EFUSE_RD_SDIO_FORCE_S 16 + +/* EFUSE_RD_XPD_SDIO_REG : RO ;bitpos:[14] ;default: 1'b0 ; */ + +/* description: read for XPD_SDIO_REG */ + +#define EFUSE_RD_XPD_SDIO_REG (BIT(14)) +#define EFUSE_RD_XPD_SDIO_REG_M (BIT(14)) +#define EFUSE_RD_XPD_SDIO_REG_V 0x1 +#define EFUSE_RD_XPD_SDIO_REG_S 14 + +/* EFUSE_RD_SDIO_TIEH : RO ;bitpos:[15] ;default: 1'b0 ; */ + +/* description: read for SDIO_TIEH */ + +#define EFUSE_RD_SDIO_TIEH (BIT(15)) +#define EFUSE_RD_SDIO_TIEH_M (BIT(15)) +#define EFUSE_RD_SDIO_TIEH_V 0x1 +#define EFUSE_RD_SDIO_TIEH_S 15 + +/* EFUSE_RD_BLK3_PART_RESERVE : R/W ; bitpos:[14] ; default: 1'b0; */ + +/* description: If set, this bit indicates that + * BLOCK3[143:96] is reserved for internal use + */ + +#define EFUSE_RD_BLK3_PART_RESERVE (BIT(14)) +#define EFUSE_RD_BLK3_PART_RESERVE_M ((EFUSE_RD_BLK3_PART_RESERVE_V) << (EFUSE_RD_BLK3_PART_RESERVE_S)) +#define EFUSE_RD_BLK3_PART_RESERVE_V 0x1 +#define EFUSE_RD_BLK3_PART_RESERVE_S 14 + +/* EFUSE_RD_SDIO_DREFH : RO ;bitpos:[9:8] ;default: 2'b0 ; */ + +#define EFUSE_RD_SDIO_DREFH 0x00000003 +#define EFUSE_RD_SDIO_DREFH_M ((EFUSE_RD_SDIO_DREFH_V) << (EFUSE_RD_SDIO_DREFH_S)) +#define EFUSE_RD_SDIO_DREFH_V 0x3 +#define EFUSE_RD_SDIO_DREFH_S 8 + +/* EFUSE_RD_SDIO_DREFM : RO ;bitpos:[11:10] ;default: 2'b0 ; */ + +#define EFUSE_RD_SDIO_DREFM 0x00000003 +#define EFUSE_RD_SDIO_DREFM_M ((EFUSE_RD_SDIO_DREFM_V) << (EFUSE_RD_SDIO_DREFM_S)) +#define EFUSE_RD_SDIO_DREFM_V 0x3 +#define EFUSE_RD_SDIO_DREFM_S 10 + +/* Note: EFUSE_ADC_VREF and SDIO_DREFH/M/L share the same address space. + * Newer versions of ESP32 come with EFUSE_ADC_VREF already burned, + * therefore SDIO_DREFH/M/L is only available in older versions of ESP32 + */ + +/* EFUSE_RD_SDIO_DREFL : RO ;bitpos:[13:12] ;default: 2'b0 ; */ + +#define EFUSE_RD_SDIO_DREFL 0x00000003 +#define EFUSE_RD_SDIO_DREFL_M ((EFUSE_RD_SDIO_DREFL_V) << (EFUSE_RD_SDIO_DREFL_S)) +#define EFUSE_RD_SDIO_DREFL_V 0x3 +#define EFUSE_RD_SDIO_DREFL_S 12 + #define REG_TIMG_BASE(i) (DR_REG_TIMERGROUP0_BASE + i*0x1000) #define TIMG_RTCCALICFG_REG(i) (REG_TIMG_BASE(i) + 0x0068) @@ -463,6 +547,8 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add, /* RTC_CNTL_DIG_DBIAS_WAK : R/W ;bitpos:[13:11] ;default: 3'd4 ; */ #define RTC_CNTL_DIG_DBIAS_WAK 0x00000007 +#define RTC_CNTL_DIG_DBIAS_WAK_M ((RTC_CNTL_DIG_DBIAS_WAK_V) << (RTC_CNTL_DIG_DBIAS_WAK_S)) +#define RTC_CNTL_DIG_DBIAS_WAK_V 0x7 #define RTC_CNTL_DIG_DBIAS_WAK_S 11 /* RTC_CNTL_SOC_CLK_SEL : R/W ;bitpos:[28:27] ;default: 2'd0 ; @@ -470,6 +556,8 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add, */ #define RTC_CNTL_SOC_CLK_SEL 0x00000003 +#define RTC_CNTL_SOC_CLK_SEL_M ((RTC_CNTL_SOC_CLK_SEL_V) << (RTC_CNTL_SOC_CLK_SEL_S)) +#define RTC_CNTL_SOC_CLK_SEL_V 0x3 #define RTC_CNTL_SOC_CLK_SEL_S 27 #define RTC_CNTL_SOC_CLK_SEL_XTL 0 #define RTC_CNTL_SOC_CLK_SEL_PLL 1 @@ -492,6 +580,9 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add, #else #define DIG_DBIAS_80M_160M RTC_CNTL_DBIAS_1V10 #endif +#define DIG_DBIAS_240M RTC_CNTL_DBIAS_HP_VOLT +#define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 +#define DIG_DBIAS_2M RTC_CNTL_DBIAS_1V00 #define DIG_DBIAS_240M RTC_CNTL_DBIAS_HP_VOLT #define DIG_DBIAS_XTAL RTC_CNTL_DBIAS_1V10 @@ -536,4 +627,126 @@ extern int rom_i2c_writeReg(int block, int block_id, int reg_add, #define RTC_PLL_FREQ_320M 320 #define RTC_PLL_FREQ_480M 480 +/* TIMG_RTC_CALI_CLK_SEL : R/W ;bitpos:[14:13] ;default: 2'h1 ; */ + +#define TIMG_RTC_CALI_CLK_SEL 0x00000003 +#define TIMG_RTC_CALI_CLK_SEL_M ((TIMG_RTC_CALI_CLK_SEL_V) << (TIMG_RTC_CALI_CLK_SEL_S)) +#define TIMG_RTC_CALI_CLK_SEL_V 0x3 +#define TIMG_RTC_CALI_CLK_SEL_S 13 + +/* TIMG_RTC_CALI_START_CYCLING : R/W ;bitpos:[12] ;default: 1'd1 ; */ + +#define TIMG_RTC_CALI_START_CYCLING (BIT(12)) +#define TIMG_RTC_CALI_START_CYCLING_M (BIT(12)) +#define TIMG_RTC_CALI_START_CYCLING_V 0x1 +#define TIMG_RTC_CALI_START_CYCLING_S 12 + +/* TIMG_RTC_CALI_START : R/W ;bitpos:[31] ;default: 1'h0 ; */ + +#define TIMG_RTC_CALI_START (BIT(31)) +#define TIMG_RTC_CALI_START_M (BIT(31)) +#define TIMG_RTC_CALI_START_V 0x1 +#define TIMG_RTC_CALI_START_S 31 + +/* TIMG_RTC_CALI_MAX : R/W ;bitpos:[30:16] ;default: 15'h1 ; */ + +#define TIMG_RTC_CALI_MAX 0x00007fff +#define TIMG_RTC_CALI_MAX_M ((TIMG_RTC_CALI_MAX_V) << (TIMG_RTC_CALI_MAX_S)) +#define TIMG_RTC_CALI_MAX_V 0x7fff +#define TIMG_RTC_CALI_MAX_S 16 + +/* TIMG_RTC_CALI_VALUE : RO ;bitpos:[31:7] ;default: 25'h0 ; */ + +#define TIMG_RTC_CALI_VALUE 0x01ffffff +#define TIMG_RTC_CALI_VALUE_M ((TIMG_RTC_CALI_VALUE_V) << (TIMG_RTC_CALI_VALUE_S)) +#define TIMG_RTC_CALI_VALUE_V 0x1ffffff +#define TIMG_RTC_CALI_VALUE_S 7 + +/* TIMG_RTC_CALI_RDY : RO ;bitpos:[15] ;default: 1'h0 ; */ + +#define TIMG_RTC_CALI_RDY (BIT(15)) +#define TIMG_RTC_CALI_RDY_M (BIT(15)) +#define TIMG_RTC_CALI_RDY_V 0x1 +#define TIMG_RTC_CALI_RDY_S 15 + +#define TIMG_RTCCALICFG1_REG(i) (REG_TIMG_BASE(i) + 0x006c) + +/* Some of the baseband control registers. + * PU/PD fields defined here are used in sleep related functions. + */ + +#define BBPD_CTRL (DR_REG_BB_BASE + 0x0054) +#define BB_FFT_FORCE_PU (BIT(3)) +#define BB_FFT_FORCE_PU_M (BIT(3)) +#define BB_FFT_FORCE_PU_V 1 +#define BB_FFT_FORCE_PU_S 3 +#define BB_FFT_FORCE_PD (BIT(2)) +#define BB_FFT_FORCE_PD_M (BIT(2)) +#define BB_FFT_FORCE_PD_V 1 +#define BB_FFT_FORCE_PD_S 2 +#define BB_DC_EST_FORCE_PU (BIT(1)) +#define BB_DC_EST_FORCE_PU_M (BIT(1)) +#define BB_DC_EST_FORCE_PU_V 1 +#define BB_DC_EST_FORCE_PU_S 1 +#define BB_DC_EST_FORCE_PD (BIT(0)) +#define BB_DC_EST_FORCE_PD_M (BIT(0)) +#define BB_DC_EST_FORCE_PD_V 1 +#define BB_DC_EST_FORCE_PD_S 0 + +/* Some of the WiFi RX control registers. + * PU/PD fields defined here are used in sleep related functions. + */ + +#define NRXPD_CTRL (DR_REG_NRX_BASE + 0x00d4) +#define NRX_RX_ROT_FORCE_PU (BIT(5)) +#define NRX_RX_ROT_FORCE_PU_M (BIT(5)) +#define NRX_RX_ROT_FORCE_PU_V 1 +#define NRX_RX_ROT_FORCE_PU_S 5 +#define NRX_RX_ROT_FORCE_PD (BIT(4)) +#define NRX_RX_ROT_FORCE_PD_M (BIT(4)) +#define NRX_RX_ROT_FORCE_PD_V 1 +#define NRX_RX_ROT_FORCE_PD_S 4 +#define NRX_VIT_FORCE_PU (BIT(3)) +#define NRX_VIT_FORCE_PU_M (BIT(3)) +#define NRX_VIT_FORCE_PU_V 1 +#define NRX_VIT_FORCE_PU_S 3 +#define NRX_VIT_FORCE_PD (BIT(2)) +#define NRX_VIT_FORCE_PD_M (BIT(2)) +#define NRX_VIT_FORCE_PD_V 1 +#define NRX_VIT_FORCE_PD_S 2 +#define NRX_DEMAP_FORCE_PU (BIT(1)) +#define NRX_DEMAP_FORCE_PU_M (BIT(1)) +#define NRX_DEMAP_FORCE_PU_V 1 +#define NRX_DEMAP_FORCE_PU_S 1 +#define NRX_DEMAP_FORCE_PD (BIT(0)) +#define NRX_DEMAP_FORCE_PD_M (BIT(0)) +#define NRX_DEMAP_FORCE_PD_V 1 +#define NRX_DEMAP_FORCE_PD_S 0 + +/* Some of the RF frontend control registers. + * PU/PD fields defined here are used in sleep related functions. + */ + +#define FE_GEN_CTRL (DR_REG_FE_BASE + 0x0090) +#define FE_IQ_EST_FORCE_PU (BIT(5)) +#define FE_IQ_EST_FORCE_PU_M (BIT(5)) +#define FE_IQ_EST_FORCE_PU_V 1 +#define FE_IQ_EST_FORCE_PU_S 5 +#define FE_IQ_EST_FORCE_PD (BIT(4)) +#define FE_IQ_EST_FORCE_PD_M (BIT(4)) +#define FE_IQ_EST_FORCE_PD_V 1 +#define FE_IQ_EST_FORCE_PD_S 4 + +#define FE2_TX_INTERP_CTRL (DR_REG_FE2_BASE + 0x00f0) +#define FE2_TX_INF_FORCE_PU (BIT(10)) +#define FE2_TX_INF_FORCE_PU_M (BIT(10)) +#define FE2_TX_INF_FORCE_PU_V 1 +#define FE2_TX_INF_FORCE_PU_S 10 +#define FE2_TX_INF_FORCE_PD (BIT(9)) +#define FE2_TX_INF_FORCE_PD_M (BIT(9)) +#define FE2_TX_INF_FORCE_PD_V 1 +#define FE2_TX_INF_FORCE_PD_S 9 + +#define PIN_CTRL (DR_REG_IO_MUX_BASE +0x00) + #endif /* __ARCH_XTENSA_SRC_ESP32_HARDWARE_ESP32_SOC_H */ diff --git a/boards/xtensa/esp32/esp32-core/Kconfig b/boards/xtensa/esp32/esp32-core/Kconfig index 11b1fbc..6371130 100644 --- a/boards/xtensa/esp32/esp32-core/Kconfig +++ b/boards/xtensa/esp32/esp32-core/Kconfig @@ -63,4 +63,22 @@ choice depends on FS_LITTLEFS endchoice +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. + +endif # PM + endif # ARCH_BOARD_ESP32CORE diff --git a/boards/xtensa/esp32/esp32-core/configs/pm/defconfig b/boards/xtensa/esp32/esp32-core/configs/pm/defconfig new file mode 100644 index 0000000..0f3b639 --- /dev/null +++ b/boards/xtensa/esp32/esp32-core/configs/pm/defconfig @@ -0,0 +1,50 @@ +# +# 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_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +# CONFIG_NSH_CMDPARMS is not set +CONFIG_ARCH="xtensa" +CONFIG_ARCH_BOARD="esp32-core" +CONFIG_ARCH_BOARD_ESP32CORE=y +CONFIG_ARCH_CHIP="esp32" +CONFIG_ARCH_CHIP_ESP32=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_ARCH_XTENSA=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_ESP32_UART0=y +CONFIG_EXPERIMENTAL=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_MAX_TASKS=16 +CONFIG_MM_REGIONS=2 +CONFIG_NFILE_DESCRIPTORS=8 +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_GREEDY=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_SDCLONE_DISABLE=y +CONFIG_SPI=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_SYSTEM_NSH=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_USER_ENTRYPOINT="nsh_main"