You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ag...@apache.org on 2020/09/20 16:23:18 UTC
[incubator-nuttx] branch master updated: xtensa/esp32: Add power
management of force-sleep
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 <ch...@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"