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"