You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/05/12 13:15:13 UTC

[incubator-nuttx] branch master updated: risc-v/esp32c3: Support ESP32-C3 PM standby and sleep

This is an automated email from the ASF dual-hosted git repository.

acassis 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 1666793  risc-v/esp32c3: Support ESP32-C3 PM standby and sleep
1666793 is described below

commit 16667930cba1265dee2e7a5ef7cf92cc6d954d21
Author: chenwen <ch...@espressif.com>
AuthorDate: Wed Apr 28 18:40:56 2021 +0800

    risc-v/esp32c3: Support ESP32-C3 PM standby and sleep
---
 arch/risc-v/src/esp32c3/Make.defs                  |    9 +
 arch/risc-v/src/esp32c3/esp32c3_idle.c             |  129 +-
 arch/risc-v/src/esp32c3/esp32c3_pm.c               | 1266 ++++++++++++
 arch/risc-v/src/esp32c3/esp32c3_pm.h               |  155 ++
 .../{esp32c3_idle.c => esp32c3_pminitialize.c}     |   42 +-
 arch/risc-v/src/esp32c3/esp32c3_rtc.c              | 2099 ++++++++++++++++++++
 arch/risc-v/src/esp32c3/esp32c3_rtc.h              |  437 ++++
 arch/risc-v/src/esp32c3/hardware/apb_ctrl_reg.h    |   73 +
 arch/risc-v/src/esp32c3/hardware/bb_reg.h          |   49 +
 arch/risc-v/src/esp32c3/hardware/esp32c3_soc.h     |   38 +
 arch/risc-v/src/esp32c3/hardware/esp32c3_uart.h    |   21 +
 arch/risc-v/src/esp32c3/hardware/extmem_reg.h      |   57 +
 arch/risc-v/src/esp32c3/hardware/fe_reg.h          |   50 +
 arch/risc-v/src/esp32c3/hardware/nrx_reg.h         |   52 +
 arch/risc-v/src/esp32c3/hardware/regi2c_bbpll.h    |   75 +
 arch/risc-v/src/esp32c3/hardware/regi2c_ctrl.h     |   69 +
 arch/risc-v/src/esp32c3/hardware/regi2c_dig_reg.h  |   59 +
 arch/risc-v/src/esp32c3/hardware/regi2c_lp_bias.h  |   40 +
 arch/risc-v/src/esp32c3/hardware/spi_mem_reg.h     |   46 +
 boards/risc-v/esp32c3/esp32c3-devkit/Kconfig       |   32 +
 .../esp32c3/esp32c3-devkit/configs/pm/defconfig    |   47 +
 .../esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld  |    4 +-
 22 files changed, 4816 insertions(+), 33 deletions(-)

diff --git a/arch/risc-v/src/esp32c3/Make.defs b/arch/risc-v/src/esp32c3/Make.defs
index 369dceb..a65498b 100644
--- a/arch/risc-v/src/esp32c3/Make.defs
+++ b/arch/risc-v/src/esp32c3/Make.defs
@@ -112,6 +112,15 @@ ifeq ($(CONFIG_ESP32C3_DMA),y)
 CHIP_CSRCS += esp32c3_dma.c
 endif
 
+ifeq ($(CONFIG_PM),y)
+ifneq ($(CONFIG_ARCH_CUSTOM_PMINIT),y)
+CHIP_CSRCS += esp32c3_pminitialize.c
+endif
+CHIP_CSRCS += esp32c3_pm.c
+endif
+
+CHIP_CSRCS += esp32c3_rtc.c
+
 ifeq ($(CONFIG_ESP32C3_WIRELESS),y)
 WIRELESS_DRV_UNPACK  = esp-wireless-drivers-3rdparty
 WIRELESS_DRV_ID      = 2b53111
diff --git a/arch/risc-v/src/esp32c3/esp32c3_idle.c b/arch/risc-v/src/esp32c3/esp32c3_idle.c
index 079bfd4..2807612 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_idle.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_idle.c
@@ -28,19 +28,142 @@
 #include <nuttx/power/pm.h>
 
 #include "esp32c3.h"
+#include "esp32c3_pm.h"
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* Values for the RTC Alarm to wake up from the PM_STANDBY mode
+ * (which corresponds to ESP32-C3 stop mode).  If this alarm expires,
+ * the logic in this file will wakeup from PM_STANDBY mode and
+ * transition to PM_SLEEP mode (ESP32-C3 standby mode).
+ */
+
+#ifdef CONFIG_PM
+#ifndef CONFIG_PM_ALARM_SEC
+#  define CONFIG_PM_ALARM_SEC 15
+#endif
+
+#ifndef CONFIG_PM_ALARM_NSEC
+#  define CONFIG_PM_ALARM_NSEC 0
+#endif
+
+#ifndef CONFIG_PM_SLEEP_WAKEUP_SEC
+#  define CONFIG_PM_SLEEP_WAKEUP_SEC 20
+#endif
+
+#ifndef CONFIG_PM_SLEEP_WAKEUP_NSEC
+#  define CONFIG_PM_SLEEP_WAKEUP_NSEC 0
+#endif
+
+#define PM_IDLE_DOMAIN 0 /* Revisit */
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Public 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(NULL);
+
+      /* Perform board-specific, state-dependent logic here */
+
+      _info("newstate= %d oldstate=%d\n", newstate, oldstate);
+
+      /* Then force the global state change */
+
+      ret = pm_changestate(PM_IDLE_DOMAIN, newstate);
+      if (ret < 0)
+        {
+          /* The new state change failed, revert to the preceding state */
+
+          pm_changestate(PM_IDLE_DOMAIN, oldstate);
+        }
+      else
+        {
+          /* Save the new state */
+
+          oldstate = newstate;
+        }
+
+      spin_unlock_irqrestore(NULL, flags);
+
+      /* MCU-specific power management logic */
+
+      switch (newstate)
+        {
+        case PM_NORMAL:
+          break;
+
+        case PM_IDLE:
+          break;
+
+        case PM_STANDBY:
+          {
+            /* Enter Force-sleep mode */
+
+            esp32c3_pmstandby(CONFIG_PM_ALARM_SEC * 1000000 +
+                                  CONFIG_PM_ALARM_NSEC / 1000);
+          }
+          break;
+
+        case PM_SLEEP:
+          {
+            /* Enter Deep-sleep mode */
+
+            esp32c3_pmsleep(CONFIG_PM_SLEEP_WAKEUP_SEC * 1000000 +
+                                CONFIG_PM_SLEEP_WAKEUP_NSEC / 1000);
+          }
+          break;
+
+        default:
+          break;
+        }
+    }
+  else
+    {
+      if (oldstate == PM_NORMAL)
+        {
+          /* Relax normal operation */
+
+          pm_relax(PM_IDLE_DOMAIN, PM_NORMAL);
+        }
+
+#ifdef CONFIG_WATCHDOG
+      /* Announce the power management state change to feed watchdog */
+
+      pm_changestate(PM_IDLE_DOMAIN, PM_NORMAL);
+#endif
+    }
+}
+#else
+#  define up_idlepm()
+#endif
+
 /****************************************************************************
  * Name: up_idle
  *
@@ -69,5 +192,9 @@ void up_idle(void)
 
   asm("WFI");
 
+  /* Perform IDLE mode power management */
+
+  up_idlepm();
+
 #endif
 }
diff --git a/arch/risc-v/src/esp32c3/esp32c3_pm.c b/arch/risc-v/src/esp32c3/esp32c3_pm.c
new file mode 100644
index 0000000..e1957d7
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_pm.c
@@ -0,0 +1,1266 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_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>
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+
+#ifdef CONFIG_PM
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#include "chip.h"
+#include "riscv_arch.h"
+
+#include "hardware/esp32c3_rtccntl.h"
+#include "hardware/esp32c3_system.h"
+#include "hardware/esp32c3_syscon.h"
+#include "hardware/esp32c3_soc.h"
+#include "hardware/esp32c3_uart.h"
+#include "hardware/esp32c3_gpio.h"
+
+#include "esp32c3_attr.h"
+#include "esp32c3_rtc.h"
+#include "esp32c3_clockconfig.h"
+#include "esp32c3_pm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* If light sleep time is less than that, don't power down flash */
+
+#define FLASH_PD_MIN_SLEEP_TIME_US 2000
+
+/* Minimal amount of time we can sleep for. */
+
+#define LIGHT_SLEEP_MIN_TIME_US    200
+
+#define RTC_MODULE_SLEEP_PREPARE_CYCLES (6)
+
+#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      (37)
+
+#ifdef CONFIG_ESP32C3_CPU_FREQ_MHZ
+#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32C3_CPU_FREQ_MHZ
+#else
+#define DEFAULT_CPU_FREQ_MHZ (160)
+#endif
+
+#define DEFAULT_SLEEP_OUT_OVERHEAD_US       (105)
+#define DEEP_SLEEP_TIME_OVERHEAD_US         (250 + 100 * 240 / DEFAULT_CPU_FREQ_MHZ)
+
+#define DEEP_SLEEP_WAKEUP_DELAY     0
+
+#define RTC_VDDSDIO_TIEH_1_8V       0  /* TIEH field value for 1.8V VDDSDIO */
+#define RTC_VDDSDIO_TIEH_3_3V       1  /* TIEH field value for 3.3V VDDSDIO */
+
+#define RTC_GPIO_TRIG_EN          BIT(2)  /* GPIO wakeup */
+#define RTC_TIMER_TRIG_EN         BIT(3)  /* Timer wakeup */
+#define RTC_WIFI_TRIG_EN          BIT(5)  /* Wi-Fi wakeup (light sleep only) */
+#define RTC_UART0_TRIG_EN         BIT(6)  /* UART0 wakeup (light sleep only) */
+#define RTC_UART1_TRIG_EN         BIT(7)  /* UART1 wakeup (light sleep only) */
+#define RTC_BT_TRIG_EN            BIT(10) /* BT wakeup (light sleep only) */
+#define RTC_XTAL32K_DEAD_TRIG_EN  BIT(12)
+#define RTC_USB_TRIG_EN           BIT(14)
+#define RTC_BROWNOUT_DET_TRIG_EN  BIT(16)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Power down options */
+
+enum esp32c3_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 esp32c3_sleep_pd_domain_e
+{
+  ESP_PD_DOMAIN_RTC_PERIPH = 0,  /* RTC IO, sensors */
+  ESP_PD_DOMAIN_RTC_SLOW_MEM,    /* RTC slow memory */
+  ESP_PD_DOMAIN_RTC_FAST_MEM,    /* RTC fast memory */
+  ESP_PD_DOMAIN_XTAL,            /* XTAL oscillator */
+  ESP_PD_DOMAIN_CPU,             /* CPU core */
+  ESP_PD_DOMAIN_MAX              /* Number of domains */
+};
+
+enum esp32c3_periph_module_e
+{
+  PERIPH_LEDC_MODULE = 0,
+  PERIPH_UART0_MODULE,
+  PERIPH_UART1_MODULE,
+  PERIPH_USB_DEVICE_MODULE,
+  PERIPH_I2C0_MODULE,
+  PERIPH_I2S1_MODULE,
+  PERIPH_TIMG0_MODULE,
+  PERIPH_TIMG1_MODULE,
+  PERIPH_UHCI0_MODULE,
+  PERIPH_RMT_MODULE,
+  PERIPH_SPI_MODULE,
+  PERIPH_SPI2_MODULE,
+  PERIPH_TWAI_MODULE,
+  PERIPH_RNG_MODULE,
+  PERIPH_WIFI_MODULE,
+  PERIPH_BT_MODULE,
+  PERIPH_WIFI_BT_COMMON_MODULE,
+  PERIPH_BT_BASEBAND_MODULE,
+  PERIPH_BT_LC_MODULE,
+  PERIPH_RSA_MODULE,
+  PERIPH_AES_MODULE,
+  PERIPH_SHA_MODULE,
+  PERIPH_HMAC_MODULE,
+  PERIPH_DS_MODULE,
+  PERIPH_GDMA_MODULE,
+  PERIPH_SYSTIMER_MODULE,
+  PERIPH_SARADC_MODULE,
+  PERIPH_MODULE_MAX
+};
+
+/* Internal structure which holds all requested deep sleep parameters. */
+
+struct esp32c3_sleep_config_s
+{
+  enum esp32c3_sleep_pd_option_e pd_options[ESP_PD_DOMAIN_MAX];
+  uint64_t sleep_duration;
+  uint32_t wakeup_triggers : 15;
+  uint32_t ext1_trigger_mode : 1;
+  uint32_t ext1_rtc_gpio_mask : 18;
+  uint32_t ext0_trigger_level : 1;
+  uint32_t ext0_rtc_gpio_num : 5;
+  uint32_t gpio_wakeup_mask : 6;
+  uint32_t gpio_trigger_mode : 6;
+  uint32_t sleep_time_adjustment;
+  uint32_t ccount_ticks_record;
+  uint32_t sleep_time_overhead_out;
+  uint32_t rtc_clk_cal_period;
+  uint64_t rtc_ticks_at_sleep_start;
+  void     *cpu_pd_mem;
+};
+
+/* Structure describing vddsdio configuration. */
+
+struct esp32c3_rtc_vddsdio_config_s
+{
+  uint32_t force : 1;     /* If 1, use configuration from RTC registers;
+                           * if 0, use EFUSE/bootstrapping pins.
+                           */
+  uint32_t enable : 1;    /* Enable VDDSDIO regulator */
+  uint32_t tieh  : 1;     /* Select VDDSDIO voltage. One of
+                           * RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V
+                           */
+  uint32_t drefh : 2;     /* Tuning parameter for VDDSDIO regulator */
+  uint32_t drefm : 2;     /* Tuning parameter for VDDSDIO regulator */
+  uint32_t drefl : 2;     /* Tuning parameter for VDDSDIO regulator */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline uint32_t esp32c3_periph_ll_get_rst_en_mask
+              (enum esp32c3_periph_module_e periph, bool enable);
+static uint32_t IRAM_ATTR esp32c3_periph_ll_get_rst_en_reg(
+                            enum esp32c3_periph_module_e periph);
+static uint32_t IRAM_ATTR esp32c3_periph_ll_get_clk_en_reg(
+                            enum esp32c3_periph_module_e periph);
+static inline uint32_t esp32c3_periph_ll_get_clk_en_mask(
+                            enum esp32c3_periph_module_e periph);
+static inline bool IRAM_ATTR esp32c3_periph_ll_periph_enabled(
+                                     enum esp32c3_periph_module_e periph);
+static inline void esp32c3_uart_tx_wait_idle(uint8_t uart_no);
+static void IRAM_ATTR esp32c3_flush_uarts(void);
+static void IRAM_ATTR esp32c3_suspend_uarts(void);
+static void IRAM_ATTR esp32c3_resume_uarts(void);
+static void esp32c3_timer_wakeup_prepare(void);
+static uint32_t esp32c3_get_power_down_flags(void);
+static void IRAM_ATTR esp32c3_set_vddsdio_config(
+                      struct esp32c3_rtc_vddsdio_config_s config);
+static int IRAM_ATTR esp32c3_get_vddsdio_config(
+                      struct esp32c3_rtc_vddsdio_config_s *config);
+static int IRAM_ATTR esp32c3_light_sleep_inner(uint32_t pd_flags,
+            uint32_t time_us, struct esp32c3_rtc_vddsdio_config_s config);
+static int IRAM_ATTR esp32c3_sleep_start(uint32_t pd_flags);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct esp32c3_sleep_config_s s_config =
+{
+  .pd_options =
+            { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO,
+              ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO,
+              ESP_PD_OPTION_AUTO
+            },
+  .ccount_ticks_record = 0,
+  .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US,
+  .wakeup_triggers = 0
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Set the real CPU ticks per us to the ets,
+ * so that ets_delay_us will be accurate.
+ */
+
+extern void ets_update_cpu_frequency(uint32_t ticks_per_us);
+
+/* Pauses execution for us microseconds. */
+
+extern void esp_rom_delay_us(uint32_t us);
+
+/****************************************************************************
+ * Name: esp32c3_periph_ll_get_rst_en_mask
+ *
+ * Description:
+ *   Get system reset bit through periph module
+ *
+ * Input Parameters:
+ *   periph - Periph module (one of enum esp32c3_periph_module_e values)
+ *   enable - Whether hardware acceleration is enabled
+ *
+ * Returned Value:
+ *   System reset bit
+ *
+ ****************************************************************************/
+
+static inline uint32_t esp32c3_periph_ll_get_rst_en_mask
+              (enum esp32c3_periph_module_e periph, bool enable)
+{
+  switch (periph)
+    {
+      case PERIPH_SARADC_MODULE:
+        return SYSTEM_APB_SARADC_RST;
+
+      case PERIPH_RMT_MODULE:
+        return SYSTEM_RMT_RST;
+
+      case PERIPH_LEDC_MODULE:
+        return SYSTEM_LEDC_RST;
+
+      case PERIPH_UART0_MODULE:
+        return SYSTEM_UART_RST;
+
+      case PERIPH_UART1_MODULE:
+        return SYSTEM_UART1_RST;
+
+      case PERIPH_I2C0_MODULE:
+        return SYSTEM_I2C_EXT0_RST;
+
+      case PERIPH_I2S1_MODULE:
+        return SYSTEM_I2S1_RST;
+
+      case PERIPH_TIMG0_MODULE:
+        return SYSTEM_TIMERGROUP_RST;
+
+      case PERIPH_TIMG1_MODULE:
+        return SYSTEM_TIMERGROUP1_RST;
+
+      case PERIPH_UHCI0_MODULE:
+        return SYSTEM_UHCI0_RST;
+
+      case PERIPH_SYSTIMER_MODULE:
+        return SYSTEM_SYSTIMER_RST;
+
+      case PERIPH_GDMA_MODULE:
+        return SYSTEM_DMA_RST;
+
+      case PERIPH_SPI_MODULE:
+        return SYSTEM_SPI01_RST;
+
+      case PERIPH_SPI2_MODULE:
+        return SYSTEM_SPI2_RST;
+
+      case PERIPH_TWAI_MODULE:
+        return SYSTEM_TWAI_RST;
+
+      case PERIPH_HMAC_MODULE:
+        return SYSTEM_CRYPTO_HMAC_RST;
+
+      case PERIPH_AES_MODULE:
+        if (enable == true)
+          {
+            /* Clear reset on digital signature,
+              * otherwise AES unit is held in reset also.
+              */
+
+            return (SYSTEM_CRYPTO_AES_RST | SYSTEM_CRYPTO_DS_RST);
+          }
+
+        /* Don't return other units to reset,
+         * as this pulls reset on RSA & SHA units, respectively.
+         */
+
+        return SYSTEM_CRYPTO_AES_RST;
+
+      case PERIPH_SHA_MODULE:
+        if (enable == true)
+          {
+            /* Clear reset on digital signature and HMAC,
+             * otherwise SHA is held in reset
+             */
+
+            return (SYSTEM_CRYPTO_SHA_RST |
+                    SYSTEM_CRYPTO_DS_RST | SYSTEM_CRYPTO_HMAC_RST);
+          }
+
+        /* Don't assert reset on secure boot,
+         * otherwise AES is held in reset
+         */
+
+        return SYSTEM_CRYPTO_SHA_RST;
+
+      case PERIPH_RSA_MODULE:
+        if (enable == true)
+          {
+          /* also clear reset on digital signature,
+           * otherwise RSA is held in reset
+           */
+
+            return (SYSTEM_CRYPTO_RSA_RST | SYSTEM_CRYPTO_DS_RST);
+          }
+
+        /* don't reset digital signature unit,
+         * as this resets AES also.
+         */
+
+        return SYSTEM_CRYPTO_RSA_RST;
+
+      case PERIPH_DS_MODULE:
+        return SYSTEM_CRYPTO_DS_RST;
+
+      default:
+        return 0;
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_periph_ll_get_rst_en_reg
+ *
+ * Description:
+ *   Get system reset register through periph module
+ *
+ * Input Parameters:
+ *   periph - Periph module (one of enum esp32c3_periph_module_e values)
+ *
+ * Returned Value:
+ *   System reset register
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR esp32c3_periph_ll_get_rst_en_reg(
+                            enum esp32c3_periph_module_e periph)
+{
+  switch (periph)
+    {
+      case PERIPH_RNG_MODULE:
+      case PERIPH_WIFI_MODULE:
+      case PERIPH_BT_MODULE:
+      case PERIPH_WIFI_BT_COMMON_MODULE:
+      case PERIPH_BT_BASEBAND_MODULE:
+      case PERIPH_BT_LC_MODULE:
+        return SYSTEM_WIFI_RST_EN_REG;
+
+      case PERIPH_HMAC_MODULE:
+      case PERIPH_DS_MODULE:
+      case PERIPH_AES_MODULE:
+      case PERIPH_RSA_MODULE:
+      case PERIPH_SHA_MODULE:
+      case PERIPH_GDMA_MODULE:
+        return SYSTEM_PERIP_RST_EN1_REG;
+
+      default:
+        return SYSTEM_PERIP_RST_EN0_REG;
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_periph_ll_get_clk_en_reg
+ *
+ * Description:
+ *   Get module clock register through periph module
+ *
+ * Input Parameters:
+ *   periph - Periph module (one of enum esp32c3_periph_module_e values)
+ *
+ * Returned Value:
+ *   Module clock register
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR esp32c3_periph_ll_get_clk_en_reg(
+                             enum esp32c3_periph_module_e periph)
+{
+  switch (periph)
+    {
+      case PERIPH_RNG_MODULE:
+      case PERIPH_WIFI_MODULE:
+      case PERIPH_BT_MODULE:
+      case PERIPH_WIFI_BT_COMMON_MODULE:
+      case PERIPH_BT_BASEBAND_MODULE:
+      case PERIPH_BT_LC_MODULE:
+        return SYSTEM_WIFI_CLK_EN_REG;
+
+      case PERIPH_HMAC_MODULE:
+      case PERIPH_DS_MODULE:
+      case PERIPH_AES_MODULE:
+      case PERIPH_RSA_MODULE:
+      case PERIPH_SHA_MODULE:
+      case PERIPH_GDMA_MODULE:
+        return SYSTEM_PERIP_CLK_EN1_REG;
+
+      default:
+        return SYSTEM_PERIP_CLK_EN0_REG;
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_periph_ll_get_clk_en_mask
+ *
+ * Description:
+ *   Get module clock bit through periph module
+ *
+ * Input Parameters:
+ *   periph - Periph module (one of enum esp32c3_periph_module_e values)
+ *
+ * Returned Value:
+ *   Module clock bit
+ *
+ ****************************************************************************/
+
+static inline uint32_t esp32c3_periph_ll_get_clk_en_mask(
+                               enum esp32c3_periph_module_e periph)
+{
+  switch (periph)
+    {
+      case PERIPH_SARADC_MODULE:
+        return SYSTEM_APB_SARADC_CLK_EN;
+
+      case PERIPH_RMT_MODULE:
+        return SYSTEM_RMT_CLK_EN;
+
+      case PERIPH_LEDC_MODULE:
+        return SYSTEM_LEDC_CLK_EN;
+
+      case PERIPH_UART0_MODULE:
+        return SYSTEM_UART_CLK_EN;
+
+      case PERIPH_UART1_MODULE:
+        return SYSTEM_UART1_CLK_EN;
+
+      case PERIPH_I2C0_MODULE:
+        return SYSTEM_I2C_EXT0_CLK_EN;
+
+      case PERIPH_I2S1_MODULE:
+        return SYSTEM_I2S1_CLK_EN;
+
+      case PERIPH_TIMG0_MODULE:
+        return SYSTEM_TIMERGROUP_CLK_EN;
+
+      case PERIPH_TIMG1_MODULE:
+        return SYSTEM_TIMERGROUP1_CLK_EN;
+
+      case PERIPH_UHCI0_MODULE:
+        return SYSTEM_UHCI0_CLK_EN;
+
+      case PERIPH_SYSTIMER_MODULE:
+        return SYSTEM_SYSTIMER_CLK_EN;
+
+      case PERIPH_SPI_MODULE:
+        return SYSTEM_SPI01_CLK_EN;
+
+      case PERIPH_SPI2_MODULE:
+        return SYSTEM_SPI2_CLK_EN;
+
+      case PERIPH_TWAI_MODULE:
+        return SYSTEM_TWAI_CLK_EN;
+
+      case PERIPH_GDMA_MODULE:
+        return SYSTEM_DMA_CLK_EN;
+
+      case PERIPH_AES_MODULE:
+        return SYSTEM_CRYPTO_AES_CLK_EN;
+
+      case PERIPH_SHA_MODULE:
+        return SYSTEM_CRYPTO_SHA_CLK_EN;
+
+      case PERIPH_RSA_MODULE:
+        return SYSTEM_CRYPTO_RSA_CLK_EN;
+
+      case PERIPH_HMAC_MODULE:
+        return SYSTEM_CRYPTO_HMAC_CLK_EN;
+
+      case PERIPH_DS_MODULE:
+        return SYSTEM_CRYPTO_DS_CLK_EN;
+
+      case PERIPH_RNG_MODULE:
+        return SYSTEM_WIFI_CLK_RNG_EN;
+
+      case PERIPH_WIFI_MODULE:
+        return SYSTEM_WIFI_CLK_WIFI_EN_M;
+
+      case PERIPH_BT_MODULE:
+        return SYSTEM_WIFI_CLK_BT_EN_M;
+
+      case PERIPH_WIFI_BT_COMMON_MODULE:
+        return SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M;
+
+      case PERIPH_BT_BASEBAND_MODULE:
+        return SYSTEM_BT_BASEBAND_EN;
+
+      case PERIPH_BT_LC_MODULE:
+        return SYSTEM_BT_LC_EN;
+
+      default:
+        return 0;
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_periph_ll_periph_enabled
+ *
+ * Description:
+ *   Whether the current Periph module is enabled
+ *
+ * Input Parameters:
+ *   periph - Periph module (one of enum esp32c3_periph_module_e values)
+ *
+ * Returned Value:
+ *   Periph module is enabled or not
+ *
+ ****************************************************************************/
+
+static inline bool IRAM_ATTR esp32c3_periph_ll_periph_enabled(
+                                     enum esp32c3_periph_module_e periph)
+{
+  return ((getreg32(esp32c3_periph_ll_get_rst_en_reg(periph)) &
+           esp32c3_periph_ll_get_rst_en_mask(periph, false)) == 0) &&
+         ((getreg32(esp32c3_periph_ll_get_clk_en_reg(periph)) &
+           esp32c3_periph_ll_get_clk_en_mask(periph)) != 0);
+}
+
+/****************************************************************************
+ * Name: esp32c3_uart_tx_wait_idle
+ *
+ * Description:
+ *   Wait until uart tx full empty and the last char send ok.
+ *
+ * Input Parameters:
+ *   uart_no   - 0 for UART0, 1 for UART1, 2 for UART2
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static inline void IRAM_ATTR esp32c3_uart_tx_wait_idle(uint8_t uart_no)
+{
+  uint32_t status;
+  do
+    {
+      status = getreg32(UART_STATUS_REG(uart_no));
+    }
+  while ((status & (UART_ST_UTX_OUT_M | UART_TXFIFO_CNT_M)) != 0);
+}
+
+/****************************************************************************
+ * Name: esp32c3_flush_uarts
+ *
+ * Description:
+ *   Wait until UART0/UART1 tx full empty and the last char send ok
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_flush_uarts(void)
+{
+  int i;
+
+  for (i = 0; i < ESP32C3_NUARTS; ++i)
+    {
+      if (esp32c3_periph_ll_periph_enabled(PERIPH_UART0_MODULE + i))
+        {
+          esp32c3_uart_tx_wait_idle(i);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_suspend_uarts
+ *
+ * Description:
+ *   Suspend UART0/UART1 output
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_suspend_uarts(void)
+{
+  int i;
+  uint32_t uart_fsm = 0;
+
+  for (i = 0; i < ESP32C3_NUARTS; ++i)
+    {
+      if (!esp32c3_periph_ll_periph_enabled(PERIPH_UART0_MODULE + i))
+        {
+          continue;
+        }
+
+      modifyreg32(UART_FLOW_CONF_REG(i), 0, UART_FORCE_XOFF);
+      do
+        {
+          uart_fsm = REG_GET_FIELD(UART_STATUS_REG(i), UART_ST_UTX_OUT);
+        }
+      while (!(uart_fsm == UART_FSM_IDLE ||
+               uart_fsm == UART_FSM_TX_WAIT_SEND));
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_resume_uarts
+ *
+ * Description:
+ *   Re-enable UART0/UART1/UART2 output
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_resume_uarts(void)
+{
+  int i;
+
+  for (i = 0; i < ESP32C3_NUARTS; ++i)
+    {
+      if (!esp32c3_periph_ll_periph_enabled(PERIPH_UART0_MODULE + i))
+        {
+          continue;
+        }
+
+      REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF);
+      REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
+      REG_CLR_BIT(UART_FLOW_CONF_REG(i),
+                  UART_SW_FLOW_CON_EN | UART_FORCE_XON);
+      REG_SET_BIT(UART_ID_REG(i), UART_UPDATE);
+    }
+}
+
+/****************************************************************************
+ * Name:  esp32c3_get_power_down_flags
+ *
+ * Description:
+ *   Get power domains that can be powered down
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Power domains
+ *
+ ****************************************************************************/
+
+static uint32_t esp32c3_get_power_down_flags(void)
+{
+  uint32_t pd_flags = 0;
+
+  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_GPIO_TRIG_EN)
+        {
+          s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] =
+                                              ESP_PD_OPTION_ON;
+        }
+      else
+        {
+          s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] =
+                                              ESP_PD_OPTION_OFF;
+        }
+    }
+
+  if (s_config.cpu_pd_mem == NULL)
+    {
+      s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON;
+    }
+
+  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_PERIPH] != ESP_PD_OPTION_ON)
+    {
+      pd_flags |= RTC_SLEEP_PD_RTC_PERIPH;
+    }
+
+  if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON)
+    {
+      pd_flags |= RTC_SLEEP_PD_CPU;
+    }
+
+  return pd_flags;
+}
+
+/****************************************************************************
+ * Name:  esp32c3_timer_wakeup_prepare
+ *
+ * Description:
+ *   Configure timer to wake-up
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_timer_wakeup_prepare(void)
+{
+  int64_t ticks;
+  int64_t sleep_duration = (int64_t)s_config.sleep_duration -
+                           (int64_t) s_config.sleep_time_adjustment;
+  if (sleep_duration < 0)
+    {
+      sleep_duration = 0;
+    }
+
+  ticks = esp32c3_rtc_time_us_to_slowclk(sleep_duration,
+                           s_config.rtc_clk_cal_period);
+  esp32c3_rtc_sleep_set_wakeup_time(s_config.rtc_ticks_at_sleep_start
+                                                             + ticks);
+}
+
+/****************************************************************************
+ * Name: esp32c3_set_vddsdio_config
+ *
+ * Description:
+ *   Set new VDDSDIO configuration using RTC registers.
+ *
+ * Input Parameters:
+ *   New VDDSDIO configuration
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_set_vddsdio_config(
+                      struct esp32c3_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: esp32c3_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 esp32c3_get_vddsdio_config(
+                     struct esp32c3_rtc_vddsdio_config_s *config)
+{
+  struct esp32c3_rtc_vddsdio_config_s *result = config;
+  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;
+    }
+
+  /* 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: esp32c3_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 esp32c3_sleep_start(uint32_t pd_flags)
+{
+  int result;
+  struct esp32c3_cpu_freq_config_s cpu_freq_config;
+  bool deep_sleep = pd_flags & RTC_SLEEP_PD_DIG;
+
+  /* Stop UART output so that output is not lost due to APB frequency change.
+   * For light sleep, suspend UART output — it will resume after wakeup.
+   * For deep sleep, wait for the contents of UART FIFO to be sent.
+   */
+
+  if (deep_sleep)
+    {
+      esp32c3_flush_uarts();
+    }
+  else
+    {
+      esp32c3_suspend_uarts();
+    }
+
+  /* Save current frequency and switch to XTAL */
+
+  esp32c3_rtc_clk_cpu_freq_get_config(&cpu_freq_config);
+  esp32c3_rtc_cpu_freq_set_xtal();
+
+  /* Enter sleep */
+
+  esp32c3_rtc_sleep_init(pd_flags);
+
+  esp32c3_rtc_sleep_low_init(s_config.rtc_clk_cal_period);
+
+  /* Set state machine time for light sleep */
+
+  if (deep_sleep == false)
+    {
+      esp32c3_rtc_sleep_low_init(s_config.rtc_clk_cal_period);
+    }
+
+  /* Configure timer wakeup */
+
+  if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN)
+                     && s_config.sleep_duration > 0)
+    {
+      esp32c3_timer_wakeup_prepare();
+    }
+
+  if (deep_sleep)
+    {
+      /* Otherwise, need to call the dedicated soc function for this */
+
+      result = esp32c3_rtc_deep_sleep_start(s_config.wakeup_triggers, 0);
+    }
+  else
+    {
+      result = esp32c3_rtc_sleep_start(s_config.wakeup_triggers, 0, 1);
+    }
+
+  /* Restore CPU frequency */
+
+  esp32c3_rtc_clk_cpu_freq_set_config(&cpu_freq_config);
+
+  if (!deep_sleep)
+    {
+      s_config.ccount_ticks_record = esp32c3_cpu_cycle_count();
+    }
+
+  REG_CLR_BIT(RTC_CNTL_RETENTION_CTRL_REG, RTC_CNTL_RETENTION_EN);
+
+  /* Re-enable UART output */
+
+  esp32c3_resume_uarts();
+
+  return result;
+}
+
+/****************************************************************************
+ * Name: esp32c3_light_sleep_inner
+ *
+ * Description:
+ *   Enter low power mode, then wait for flash to be ready on wakeup
+ *
+ * Input Parameters:
+ *   pd_flags - Power domains
+ *   time_us  - Time to wait for spi_flash become ready
+ *   config   -  VDDSDIO configuration
+ *
+ * Returned Value:
+ *   0 is returned on success or a negated errno value is returned
+ *
+ ****************************************************************************/
+
+static int IRAM_ATTR esp32c3_light_sleep_inner(uint32_t pd_flags,
+        uint32_t time_us, struct esp32c3_rtc_vddsdio_config_s config)
+{
+  /* Enter sleep */
+
+  int err = esp32c3_sleep_start(pd_flags);
+
+  /* If VDDSDIO regulator was controlled by RTC registers before sleep.
+   * restore the configuration.
+   */
+
+  if (config.force)
+    {
+      esp32c3_set_vddsdio_config(config);
+    }
+
+  /* If SPI flash was powered down, wait for it to become ready. */
+
+  if (pd_flags & RTC_SLEEP_PD_VDDSDIO)
+    {
+      /* Wait for the flash chip to start up. */
+
+      esp_rom_delay_us(time_us);
+    }
+
+  return err;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name:  esp32c3_sleep_enable_timer_wakeup
+ *
+ * Description:
+ *   Configure wake-up interval
+ *
+ * Input Parameters:
+ *   time_in_us - Configure wake-up time interval
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_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:  esp32c3_light_sleep_start
+ *
+ * Description:
+ *   Enter light sleep mode
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   0 is returned on success or a negated errno value is returned
+ *
+ ****************************************************************************/
+
+int esp32c3_light_sleep_start(void)
+{
+  int ret = OK;
+  irqstate_t flags;
+  uint32_t pd_flags;
+  uint32_t flash_enable_time_us;
+  uint32_t vddsdio_pd_sleep_duration;
+  struct esp32c3_rtc_vddsdio_config_s vddsdio_config;
+  uint32_t rtc_cntl_xtl_buf_wait_cycles;
+  uint32_t sleep_time_overhead_in;
+  uint32_t ccount_at_sleep_start;
+
+  flags = enter_critical_section();
+
+  s_config.ccount_ticks_record = esp32c3_cpu_cycle_count();
+  s_config.rtc_ticks_at_sleep_start = esp32c3_rtc_time_get();
+  ccount_at_sleep_start = esp32c3_cpu_cycle_count();
+  sleep_time_overhead_in = (ccount_at_sleep_start -
+    s_config.ccount_ticks_record) / (esp32c3_clk_cpu_freq() / 1000000ULL);
+
+  /* Decide which power domains can be powered down */
+
+  pd_flags = esp32c3_get_power_down_flags();
+
+  s_config.rtc_clk_cal_period =
+        esp32c3_rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
+
+  /* Adjustment time consists of parts below:
+   * 1. Hardware time waiting for internal 8M oscilate clock and XTAL;
+   * 2. Hardware state swithing time of the rtc main state machine;
+   * 3. Code execution time when clock is not stable;
+   * 4. Code execution time which can be measured;
+   */
+
+  rtc_cntl_xtl_buf_wait_cycles = esp32c3_rtc_time_us_to_slowclk(
+        RTC_CNTL_XTL_BUF_WAIT_SLP_US, s_config.rtc_clk_cal_period);
+
+  s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US +
+        sleep_time_overhead_in + s_config.sleep_time_overhead_out
+        + esp32c3_rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_cycles +
+        RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES,
+        s_config.rtc_clk_cal_period);
+
+  /* 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
+                         + DEEP_SLEEP_WAKEUP_DELAY;
+
+  /* When SPIRAM is disabled in menuconfig, the minimum sleep time of the
+   * system needs to meet the sum below:
+   * 1. Wait time for the flash power-on after waking up;
+   * 2. The execution time of codes between RTC Timer get start time
+   *    with hardware starts to switch state to sleep;
+   * 3. The hardware state switching time of the rtc state machine during
+   *    sleep and wake-up. This process requires 6 cycles to complete.
+   *    The specific hardware state switching process and the cycles
+   *    consumed are rtc_cpu_run_stall(1), cut_pll_rtl(2), cut_8m(1),
+   *    min_protect(2);
+   * 4. All the adjustment time which is
+   *    s_config.sleep_time_adjustment below.
+   */
+
+  vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
+      flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US +
+      s_config.sleep_time_adjustment + esp32c3_rtc_time_slowclk_to_us(
+        RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period));
+
+  if (s_config.sleep_duration > vddsdio_pd_sleep_duration)
+    {
+      pd_flags |= RTC_SLEEP_PD_VDDSDIO;
+      if (s_config.sleep_time_overhead_out < flash_enable_time_us)
+        {
+          s_config.sleep_time_adjustment += flash_enable_time_us;
+        }
+    }
+  else
+    {
+      if (s_config.sleep_time_overhead_out > flash_enable_time_us)
+        {
+          s_config.sleep_time_adjustment -= flash_enable_time_us;
+        }
+    }
+
+  esp32c3_get_vddsdio_config(&vddsdio_config);
+
+  /* Enter sleep, then wait for flash to be ready on wakeup */
+
+  ret = esp32c3_light_sleep_inner(pd_flags, flash_enable_time_us,
+                                               vddsdio_config);
+  s_config.sleep_time_overhead_out = (esp32c3_cpu_cycle_count() -
+       s_config.ccount_ticks_record) / (esp32c3_clk_cpu_freq() / 1000000ULL);
+
+  leave_critical_section(flags);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: esp32c3_pminit
+ *
+ * Description:
+ *   Initialize force sleep parameters.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_pminit(void)
+{
+  /* Initialize RTC parameters */
+
+  esp32c3_rtc_init();
+  esp32c3_rtc_clk_set();
+}
+
+/****************************************************************************
+ * Name: esp32c3_pmstandby
+ *
+ * Description:
+ *   Enter force sleep.
+ *
+ * Input Parameters:
+ *   time_in_us - force sleep time interval
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_pmstandby(uint64_t time_in_us)
+{
+  /* don't power down XTAL — powering it up takes different time on. */
+
+  fflush(stdout);
+  esp32c3_sleep_enable_timer_wakeup(time_in_us);
+  esp32c3_light_sleep_start();
+}
+
+/****************************************************************************
+ * Name:  esp32c3_deep_sleep_start
+ *
+ * Description:
+ *   Enter deep sleep mode
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_deep_sleep_start(void)
+{
+  uint32_t pd_flags;
+
+  /* record current RTC time */
+
+  s_config.rtc_ticks_at_sleep_start = esp32c3_rtc_time_get();
+
+  /* Decide which power domains can be powered down */
+
+  pd_flags = esp32c3_get_power_down_flags();
+  s_config.rtc_clk_cal_period = getreg32(RTC_SLOW_CLK_CAL_REG);
+
+  /* Correct the sleep time */
+
+  s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
+
+  /* Enter deep sleep */
+
+  esp32c3_sleep_start(RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | pd_flags);
+
+  /* Because RTC is in a slower clock domain than the CPU, it
+   * can take several CPU cycles for the sleep mode to start.
+   */
+
+  while (1);
+}
+
+/****************************************************************************
+ * Name: esp32c3_pmsleep
+ *
+ * Description:
+ *   Enter deep sleep.
+ *
+ * Input Parameters:
+ *   time_in_us - deep sleep time interval
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_pmsleep(uint64_t time_in_us)
+{
+  fflush(stdout);
+  esp32c3_sleep_enable_timer_wakeup(time_in_us);
+  esp32c3_deep_sleep_start();
+}
+
+#endif /* CONFIG_PM */
\ No newline at end of file
diff --git a/arch/risc-v/src/esp32c3/esp32c3_pm.h b/arch/risc-v/src/esp32c3/esp32c3_pm.h
new file mode 100644
index 0000000..7081b04
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_pm.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_PM_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_PM_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:  esp32c3_sleep_enable_timer_wakeup
+ *
+ * Description:
+ *   Configure wake-up interval
+ *
+ * Input Parameters:
+ *   time_in_us - Configure wake-up time interval
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_sleep_enable_timer_wakeup(uint64_t time_in_us);
+
+/****************************************************************************
+ * Name:  esp32c3_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 esp32c3_light_sleep_start(void);
+
+/****************************************************************************
+ * Name: esp32c3_pminit
+ *
+ * Description:
+ *   Initialize force sleep parameters.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_pminit(void);
+
+/****************************************************************************
+ * Name: esp32c3_pmstandby
+ *
+ * Description:
+ *   Enter force sleep time interval.
+ *
+ * Input Parameters:
+ *   time_in_us - force sleep time interval
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_pmstandby(uint64_t time_in_us);
+
+/****************************************************************************
+ * Name:  esp32c3_deep_sleep_start
+ *
+ * Description:
+ *   Enter deep sleep mode
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_deep_sleep_start(void);
+
+/****************************************************************************
+ * Name: esp32c3_pmsleep
+ *
+ * Description:
+ *   Enter deep sleep.
+ *
+ * Input Parameters:
+ *   time_in_us - deep sleep time interval
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_pmsleep(uint64_t time_in_us);
+
+#endif /* CONFIG_PM */
+
+#ifdef __cplusplus
+}
+#endif
+#undef EXTERN
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_PM_H */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_idle.c b/arch/risc-v/src/esp32c3/esp32c3_pminitialize.c
similarity index 54%
copy from arch/risc-v/src/esp32c3/esp32c3_idle.c
copy to arch/risc-v/src/esp32c3/esp32c3_pminitialize.c
index 079bfd4..ad1e87a 100644
--- a/arch/risc-v/src/esp32c3/esp32c3_idle.c
+++ b/arch/risc-v/src/esp32c3/esp32c3_pminitialize.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * arch/risc-v/src/esp32c3/esp32c3_idle.c
+ * arch/risc-v/src/esp32c3/esp32c3_pminitialize.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -23,51 +23,33 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
-#include <nuttx/irq.h>
-#include <nuttx/arch.h>
 #include <nuttx/power/pm.h>
 
-#include "esp32c3.h"
+#include "esp32c3_pm.h"
 
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
+#ifdef CONFIG_PM
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: up_idle
+ * Name: xtensa_pminitialize
  *
  * 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.
+ *   Initialize the power management subsystem.
  *
  ****************************************************************************/
 
-void up_idle(void)
+void riscv_pminitialize(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.
-   */
+  /* Initialize RTC parameters */
 
-  nxsched_process_timer();
-#else
-  /* 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
-   */
+  esp32c3_pminit();
 
-  asm("WFI");
+  /* Then initialize the NuttX power management subsystem proper */
 
-#endif
+  pm_initialize();
 }
+
+#endif /* CONFIG_PM */
diff --git a/arch/risc-v/src/esp32c3/esp32c3_rtc.c b/arch/risc-v/src/esp32c3/esp32c3_rtc.c
new file mode 100644
index 0000000..f1947a6
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_rtc.c
@@ -0,0 +1,2099 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_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 <assert.h>
+
+#include "riscv_arch.h"
+
+#include "hardware/esp32c3_rtccntl.h"
+#include "hardware/esp32c3_soc.h"
+#include "hardware/esp32c3_system.h"
+#include "hardware/esp32c3_tim.h"
+#include "hardware/apb_ctrl_reg.h"
+#include "hardware/bb_reg.h"
+#include "hardware/nrx_reg.h"
+#include "hardware/fe_reg.h"
+#include "hardware/regi2c_lp_bias.h"
+#include "hardware/regi2c_dig_reg.h"
+#include "hardware/regi2c_bbpll.h"
+#include "hardware/regi2c_ctrl.h"
+#include "hardware/extmem_reg.h"
+#include "hardware/spi_mem_reg.h"
+
+#include "esp32c3_rtc.h"
+#include "esp32c3_clockconfig.h"
+#include "esp32c3_attr.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define OTHER_BLOCKS_POWERUP        1
+#define OTHER_BLOCKS_WAIT           1
+
+#define STR2(X) #X
+#define STR(X) STR2(X)
+
+#define MHZ                        (1000000)
+
+/* Lower threshold for a reasonably-looking calibration value for a 32k XTAL.
+ * The ideal value (assuming 32768 Hz frequency)
+ * is 1000000/32768*(2**19) = 16*10^6.
+ */
+
+#define MIN_32K_XTAL_CAL_VAL        15000000L
+#define DELAY_FAST_CLK_SWITCH       3
+#define DELAY_SLOW_CLK_SWITCH       300
+#define DELAY_8M_ENABLE             50
+
+/* Indicates that this 32k oscillator gets input from external oscillator,
+ * rather than a crystal.
+ */
+
+#define EXT_OSC_FLAG    BIT(3)
+
+/* 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
+
+#define RTC_FAST_CLK_FREQ_8M        8500000
+
+/* With the default value of CK8M_DFREQ,
+ * 8M clock frequency is 8.5 MHz +/- 7%.
+ */
+
+#define RTC_FAST_CLK_FREQ_APPROX    8500000
+
+#define RTC_PLL_FREQ_320M   320
+#define RTC_PLL_FREQ_480M   480
+
+#define RTC_SLOW_CLK_FREQ_90K      90000
+#define RTC_SLOW_CLK_FREQ_8MD256    (RTC_FAST_CLK_FREQ_APPROX / 256)
+#define RTC_SLOW_CLK_FREQ_32K       32768
+
+#define RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(cycles)   (cycles << 12)
+#define RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(cycles) (cycles << 12)
+#define RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(cycles)   (cycles << 10)
+
+/* Number of fractional bits in values returned by rtc_clk_cal */
+
+#define RTC_CLK_CAL_FRACT  19
+
+/* set sleep_init default param. */
+
+#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT  3
+#define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT  15
+#define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT  0
+#define RTC_CNTL_BIASSLP_MONITOR_DEFAULT  0
+#define RTC_CNTL_BIASSLP_SLEEP_DEFAULT  1
+#define RTC_CNTL_PD_CUR_MONITOR_DEFAULT  0
+#define RTC_CNTL_PD_CUR_SLEEP_DEFAULT  1
+#define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 254
+
+#define RTC_CK8M_ENABLE_WAIT_DEFAULT 5
+
+/* 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_SLP  0
+#define RTC_CNTL_DBIAS_0V90 13
+#define RTC_CNTL_DBIAS_0V95 16
+#define RTC_CNTL_DBIAS_1V00 18
+#define RTC_CNTL_DBIAS_1V05 20
+#define RTC_CNTL_DBIAS_1V10 23
+#define RTC_CNTL_DBIAS_1V15 25
+#define RTC_CNTL_DBIAS_1V20 28
+#define RTC_CNTL_DBIAS_1V25 30
+#define RTC_CNTL_DBIAS_1V30 31
+
+#define DIG_DBIAS_XTAL      RTC_CNTL_DBIAS_1V10
+#define DIG_DBIAS_2M        RTC_CNTL_DBIAS_1V00
+
+#define DIG_DBIAS_80M   RTC_CNTL_DBIAS_1V20
+#define DIG_DBIAS_160M  RTC_CNTL_DBIAS_1V20
+
+/* Default initializer for esp32c3_rtc_sleep_config_s
+ * 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_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 = ((sleep_flags) & RTC_SLEEP_PD_WIFI) ? 1 : 0, \
+  .bt_pd_en = ((sleep_flags) & RTC_SLEEP_PD_BT) ? 1 : 0, \
+  .cpu_pd_en = ((sleep_flags) & RTC_SLEEP_PD_CPU) ? 1 : 0, \
+  .dig_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_DIG_PERIPH) ? 1 : 0, \
+  .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \
+  .wdt_flashboot_mod_en = 0, \
+  .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \
+  .dig_dbias_slp = RTC_CNTL_DBIAS_SLP, \
+  .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \
+  .rtc_dbias_slp = RTC_CNTL_DBIAS_SLP, \
+  .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \
+  .deep_slp_reject = 1, \
+  .light_slp_reject = 1 \
+};
+
+#define X32K_CONFIG_DEFAULT() { \
+  .dac = 3, \
+  .dres = 3, \
+  .dgm = 3, \
+  .dbuf = 1, \
+}
+
+/* Initializer for struct esp32c3_rtc_sleep_pu_config_s
+ * which sets all flags to the same value
+ */
+
+#define RTC_SLEEP_PU_CONFIG_ALL(val) {\
+  .dig_fpu = (val), \
+  .rtc_fpu = (val), \
+  .cpu_fpu = (val), \
+  .i2s_fpu = (val), \
+  .bb_fpu = (val), \
+  .nrx_fpu = (val), \
+  .fe_fpu = (val), \
+  .sram_fpu = (val), \
+  .rom_ram_fpu = (val), \
+}
+
+#define RTC_INIT_CONFIG_DEFAULT() { \
+  .wifi_powerup_cycles = OTHER_BLOCKS_POWERUP, \
+  .wifi_wait_cycles = OTHER_BLOCKS_WAIT, \
+  .bt_powerup_cycles = OTHER_BLOCKS_POWERUP, \
+  .bt_wait_cycles = OTHER_BLOCKS_WAIT, \
+  .cpu_top_powerup_cycles = OTHER_BLOCKS_POWERUP, \
+  .cpu_top_wait_cycles = OTHER_BLOCKS_WAIT, \
+  .dg_wrap_powerup_cycles = OTHER_BLOCKS_POWERUP, \
+  .dg_wrap_wait_cycles = OTHER_BLOCKS_WAIT, \
+  .dg_peri_powerup_cycles = OTHER_BLOCKS_POWERUP, \
+  .dg_peri_wait_cycles = OTHER_BLOCKS_WAIT, \
+}
+
+/* Default initializer of struct esp32c3_rtc_config_s.
+ * This initializer sets all fields to "reasonable" values
+ * (e.g. suggested for production use).
+ */
+
+#define RTC_CONFIG_DEFAULT() {\
+    .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, \
+    .xtal_fpu = 0, \
+    .bbpll_fpu = 0, \
+    .cpu_waiti_clk_gate = 1, \
+    .cali_ocode = 0\
+}
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This is almost the same as esp32c3_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 esp32c3_rtc_slow_freq_e values.
+ */
+
+enum esp32c3_slow_clk_sel_e
+{
+  /* Internal 90 kHz RC oscillator */
+
+  SLOW_CLK_RTC = 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
+};
+
+/* RTC FAST_CLK frequency values */
+
+enum esp32c3_rtc_fast_freq_e
+{
+  RTC_FAST_FREQ_XTALD4 = 0,   /* Main XTAL, divided by 4 */
+  RTC_FAST_FREQ_8M = 1,       /* Internal 8 MHz RC oscillator */
+};
+
+struct esp32c3_x32k_config_s
+{
+  uint32_t dac : 6;
+  uint32_t dres : 3;
+  uint32_t dgm : 3;
+  uint32_t dbuf: 1;
+};
+
+/* Power down flags for rtc_sleep_pd function */
+
+struct esp32c3_rtc_sleep_pu_config_s
+{
+  uint32_t dig_fpu : 1;     /* Set to 1 to power UP digital part in sleep */
+  uint32_t rtc_fpu : 1;     /* Set to 1 to power UP RTC memories in sleep */
+  uint32_t cpu_fpu : 1;     /* Set to 1 to power UP digital memories and
+                             * CPU in sleep
+                             */
+  uint32_t i2s_fpu : 1;     /* Set to 1 to power UP I2S in sleep */
+  uint32_t bb_fpu : 1;      /* Set to 1 to power UP WiFi in sleep */
+  uint32_t nrx_fpu : 1;     /* Set to 1 to power UP WiFi in sleep */
+  uint32_t fe_fpu : 1;      /* Set to 1 to power UP WiFi in sleep */
+  uint32_t sram_fpu : 1;    /* Set to 1 to power UP SRAM in sleep */
+  uint32_t rom_ram_fpu : 1; /* Set to 1 to power UP ROM/IRAM0_DRAM0 in sleep */
+};
+
+struct esp32c3_rtc_init_config_s
+{
+  uint16_t wifi_powerup_cycles : 7;
+  uint16_t wifi_wait_cycles : 9;
+  uint16_t bt_powerup_cycles : 7;
+  uint16_t bt_wait_cycles : 9;
+  uint16_t cpu_top_powerup_cycles : 7;
+  uint16_t cpu_top_wait_cycles : 9;
+  uint16_t dg_wrap_powerup_cycles : 7;
+  uint16_t dg_wrap_wait_cycles : 9;
+  uint16_t dg_peri_powerup_cycles : 7;
+  uint16_t dg_peri_wait_cycles : 9;
+};
+
+/* RTC power and clock control initialization settings */
+
+struct esp32c3_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 */
+    uint32_t xtal_fpu : 1;
+    uint32_t bbpll_fpu : 1;
+    uint32_t cpu_waiti_clk_gate : 1;
+    uint32_t cali_ocode : 1;      /* Calibrate Ocode to make bangap voltage more precise. */
+};
+
+/* sleep configuration for rtc_sleep_init function */
+
+struct esp32c3_rtc_sleep_config_s
+{
+  uint32_t lslp_mem_inf_fpu : 1;       /* force normal voltage in sleep mode */
+  uint32_t rtc_mem_inf_follow_cpu : 1; /* keep low voltage in sleep mode */
+  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 bt_pd_en : 1;               /* power down BT */
+  uint32_t cpu_pd_en : 1;              /* power down CPU, but not
+                                        * restart when lightsleep.
+                                        */
+  uint32_t dig_peri_pd_en : 1;         /* power down digital peripherals */
+  uint32_t deep_slp : 1;               /* power down digital domain */
+  uint32_t wdt_flashboot_mod_en : 1;   /* enable WDT flashboot mode */
+  uint32_t dig_dbias_wak : 5;          /* set bias for digital domain,
+                                        * in active mode
+                                        */
+  uint32_t dig_dbias_slp : 5;          /* set bias for digital domain,
+                                        * in sleep mode
+                                        */
+  uint32_t rtc_dbias_wak : 5;          /* set bias for RTC domain, in active mode */
+  uint32_t rtc_dbias_slp : 5;          /* set bias for RTC domain, in sleep mode */
+  uint32_t vddsdio_pd_en : 1;          /* power down VDDSDIO regulator */
+  uint32_t deep_slp_reject : 1;
+  uint32_t light_slp_reject : 1;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_sleep_pu(
+                      struct esp32c3_rtc_sleep_pu_config_s cfg);
+static inline bool esp32c3_clk_val_is_valid(uint32_t val);
+static uint32_t IRAM_ATTR esp32c3_rtc_clk_cal_internal(
+                enum esp32c3_rtc_cal_sel_e cal_clk, uint32_t slowclk_cycles);
+static void IRAM_ATTR esp32c3_rtc_clk_32k_enable(bool enable);
+static void IRAM_ATTR esp32c3_rtc_clk_8m_enable(
+                                bool clk_8m_en, bool d256_en);
+static uint32_t IRAM_ATTR esp32c3_rtc_clk_slow_freq_get_hz(void);
+static void IRAM_ATTR esp32c3_select_rtc_slow_clk(
+                      enum esp32c3_slow_clk_sel_e slow_clk);
+static void IRAM_ATTR esp32c3_rtc_clk_fast_freq_set(
+                      enum esp32c3_rtc_fast_freq_e fast_freq);
+static uint32_t IRAM_ATTR esp32c3_rtc_sleep_finish(uint32_t
+                                          lslp_mem_inf_fpu);
+static void IRAM_ATTR esp32c3_rtc_clk_apb_freq_update(uint32_t apb_freq);
+static void IRAM_ATTR esp32c3_wait_dig_dbias_valid(uint64_t rtc_cycles);
+static void IRAM_ATTR esp32c3_rtc_update_to_xtal(int freq, int div);
+static void IRAM_ATTR esp32c3_rtc_clk_bbpll_disable(void);
+static void IRAM_ATTR esp32c3_rtc_clk_set_xtal_wait(void);
+static void IRAM_ATTR esp32c3_rtc_bbpll_configure(
+                     enum esp32c3_rtc_xtal_freq_e xtal_freq, int pll_freq);
+static void IRAM_ATTR esp32c3_rtc_clk_cpu_freq_to_8m(void);
+static void IRAM_ATTR esp32c3_rtc_clk_cpu_freq_to_pll_mhz(
+                                             int cpu_freq_mhz);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Pauses execution for us microseconds */
+
+extern void esp_rom_delay_us(uint32_t us);
+
+/* Set the real CPU ticks per us to the ets, so that ets_delay_us
+ * will be accurate. Call this function when CPU frequency is changed.
+ */
+
+extern void ets_update_cpu_frequency(uint32_t ticks_per_us);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_sleep_pu
+ *
+ * Description:
+ *   Configure whether certain peripherals are powered down in deep sleep.
+ *
+ * Input Parameters:
+ *   cfg - power down flags as esp32c3_rtc_sleep_pu_config_s structure
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_sleep_pu(
+                 struct esp32c3_rtc_sleep_pu_config_s cfg)
+{
+  REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG,
+                RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.dig_fpu);
+  REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, cfg.rtc_fpu);
+  REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG,
+                APB_CTRL_DC_MEM_FORCE_PU, cfg.fe_fpu);
+  REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG,
+                APB_CTRL_PBUS_MEM_FORCE_PU, cfg.fe_fpu);
+  REG_SET_FIELD(APB_CTRL_FRONT_END_MEM_PD_REG,
+                APB_CTRL_AGC_MEM_FORCE_PU, cfg.fe_fpu);
+  REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, cfg.bb_fpu);
+  REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, cfg.bb_fpu);
+  REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, cfg.nrx_fpu);
+  REG_SET_FIELD(NRXPD_CTRL, NRX_VIT_FORCE_PU, cfg.nrx_fpu);
+  REG_SET_FIELD(NRXPD_CTRL, NRX_DEMAP_FORCE_PU, cfg.nrx_fpu);
+  REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, cfg.fe_fpu);
+  REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, cfg.fe_fpu);
+  if (cfg.sram_fpu)
+    {
+      REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG,
+                    APB_CTRL_SRAM_POWER_UP, APB_CTRL_SRAM_POWER_UP);
+    }
+  else
+    {
+      REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG,
+                    APB_CTRL_SRAM_POWER_UP, 0);
+    }
+
+  if (cfg.rom_ram_fpu)
+    {
+      REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG,
+                    APB_CTRL_ROM_POWER_UP, APB_CTRL_ROM_POWER_UP);
+    }
+  else
+    {
+      REG_SET_FIELD(APB_CTRL_MEM_POWER_UP_REG,
+                    APB_CTRL_ROM_POWER_UP, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_fast_freq_set
+ *
+ * Description:
+ *   Select source for RTC_FAST_CLK.
+ *
+ * Input Parameters:
+ *   fast_freq - Clock source (one of enum esp32c3_rtc_fast_freq_e values)
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_fast_freq_set(
+                      enum esp32c3_rtc_fast_freq_e fast_freq)
+{
+  REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG,
+                RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq);
+  esp_rom_delay_us(DELAY_FAST_CLK_SWITCH);
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_clk_val_is_valid(uint32_t val)
+{
+  return (val & 0xffff) == ((val >> 16) & 0xffff)
+                        && val != 0 && val != UINT32_MAX;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_rtc_clk_cal_internal(
+                enum esp32c3_rtc_cal_sel_e cal_clk, uint32_t slowclk_cycles)
+{
+  uint32_t cal_val;
+  uint32_t expected_freq;
+  uint32_t us_time_estimate;
+  int dig_32k_xtal_state;
+  enum esp32c3_rtc_slow_freq_e slow_freq;
+  if (cal_clk == RTC_CAL_RTC_MUX)
+    {
+      slow_freq = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG,
+                                RTC_CNTL_ANA_CLK_RTC_SEL);
+      if (slow_freq == RTC_SLOW_FREQ_32K_XTAL)
+        {
+          cal_clk = RTC_CAL_32K_XTAL;
+        }
+      else if (slow_freq == RTC_SLOW_FREQ_8MD256)
+        {
+          cal_clk = RTC_CAL_8MD256;
+        }
+    }
+
+  /* Enable requested clock (150k clock is always on) */
+
+  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);
+
+  /* There may be another calibration process already running during we
+   * call this function, so we should wait the last process is done.
+   */
+
+  if ((getreg32(TIMG_RTCCALICFG2_REG(0)) & TIMG_RTC_CALI_TIMEOUT) == 0)
+    {
+      if (getreg32(TIMG_RTCCALICFG_REG(0)) & TIMG_RTC_CALI_START_CYCLING)
+        {
+          while ((getreg32(TIMG_RTCCALICFG_REG(0)) &
+                  TIMG_RTC_CALI_RDY) == 0);
+        }
+    }
+
+  modifyreg32(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING, 0);
+  REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
+
+  /* Set timeout reg and expect time delay */
+
+  if (cal_clk == RTC_CAL_32K_XTAL)
+    {
+      REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES,
+                    RTC_SLOW_CLK_X32K_CAL_TIMEOUT_THRES(slowclk_cycles));
+      expected_freq = RTC_SLOW_CLK_FREQ_32K;
+    }
+  else if (cal_clk == RTC_CAL_8MD256)
+    {
+      REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES,
+                    RTC_SLOW_CLK_8MD256_CAL_TIMEOUT_THRES(slowclk_cycles));
+      expected_freq = RTC_SLOW_CLK_FREQ_8MD256;
+    }
+  else
+    {
+      REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES,
+                    RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
+      expected_freq = RTC_SLOW_CLK_FREQ_90K;
+    }
+
+  us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) *
+                                          MHZ / expected_freq);
+
+  /* Start calibration */
+
+  modifyreg32(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START, 0);
+  modifyreg32(TIMG_RTCCALICFG_REG(0), 0, TIMG_RTC_CALI_START);
+
+  /* Wait for calibration to finish up to another us_time_estimate */
+
+  esp_rom_delay_us(us_time_estimate);
+  while (1)
+    {
+      if (getreg32(TIMG_RTCCALICFG_REG(0)) & TIMG_RTC_CALI_RDY)
+        {
+          cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0),
+                                  TIMG_RTC_CALI_VALUE);
+          break;
+        }
+
+      if (getreg32(TIMG_RTCCALICFG2_REG(0)) & TIMG_RTC_CALI_TIMEOUT)
+        {
+          cal_val = 0;
+          break;
+        }
+    }
+
+  modifyreg32(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START, 0);
+  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);
+    }
+
+  return cal_val;
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_32k_enable
+ *
+ * Description:
+ *   Enable or disable 32 kHz XTAL oscillator
+ *
+ * Input Parameters:
+ *   enable - true to enable, false to disable
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_32k_enable(bool enable)
+{
+  struct esp32c3_x32k_config_s cfg = X32K_CONFIG_DEFAULT();
+  if (enable)
+    {
+      REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG,
+                    RTC_CNTL_DAC_XTAL_32K, cfg.dac);
+      REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG,
+                    RTC_CNTL_DRES_XTAL_32K, cfg.dres);
+      REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG,
+                    RTC_CNTL_DGM_XTAL_32K, cfg.dgm);
+      REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG,
+                    RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf);
+      modifyreg32(RTC_CNTL_EXT_XTL_CONF_REG, 0,
+                  RTC_CNTL_XPD_XTAL_32K);
+    }
+  else
+    {
+      modifyreg32(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K,
+                  RTC_CNTL_XTAL32K_XPD_FORCE);
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_8m_enable
+ *
+ * Description:
+ *   Enable or disable 8 MHz internal oscillator
+ *
+ * Input Parameters:
+ *   clk_8m_en - true to enable 8MHz generator, false to disable
+ *   d256_en   - true to enable /256 divider, false to disable
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
+{
+  if (clk_8m_en)
+    {
+      modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M, 0);
+
+      /* no need to wait once enabled by software */
+
+      REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT,
+                    RTC_CK8M_ENABLE_WAIT_DEFAULT);
+      esp_rom_delay_us(DELAY_8M_ENABLE);
+    }
+  else
+    {
+      modifyreg32(RTC_CNTL_CLK_CONF_REG, 0, RTC_CNTL_ENB_CK8M);
+      REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT,
+                    RTC_CNTL_CK8M_WAIT_DEFAULT);
+    }
+
+  /* d256 should be independent configured with 8M
+   * Maybe we can split this function into 8m and dmd256
+   */
+
+  if (d256_en)
+    {
+      modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV, 0);
+    }
+  else
+    {
+      modifyreg32(RTC_CNTL_CLK_CONF_REG, 0, RTC_CNTL_ENB_CK8M_DIV);
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_slow_freq_get_hz
+ *
+ * Description:
+ *   Get the approximate frequency of RTC_SLOW_CLK, in Hz
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   slow_clk_freq - RTC_SLOW_CLK frequency, in Hz
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR esp32c3_rtc_clk_slow_freq_get_hz(void)
+{
+  enum esp32c3_rtc_slow_freq_e slow_clk_freq =
+                               esp32c3_rtc_clk_slow_freq_get();
+  switch (slow_clk_freq)
+    {
+      case RTC_SLOW_FREQ_RTC:
+        return RTC_SLOW_CLK_FREQ_90K;
+
+      case RTC_SLOW_FREQ_32K_XTAL:
+        return RTC_SLOW_CLK_FREQ_32K;
+
+      case RTC_SLOW_FREQ_8MD256:
+        return RTC_SLOW_CLK_FREQ_8MD256;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 IRAM_ATTR esp32c3_select_rtc_slow_clk(
+                      enum esp32c3_slow_clk_sel_e slow_clk)
+{
+  uint32_t cal_val = 0;
+  int retry_32k_xtal = 3;
+  uint64_t cal_dividend;
+  enum esp32c3_rtc_slow_freq_e rtc_slow_freq = slow_clk &
+                             RTC_CNTL_ANA_CLK_RTC_SEL_V;
+  do
+    {
+      if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL)
+        {
+          /* 32k XTAL oscillator needs to be enabled and running before
+           * it can be used. Hardware doesn't have a direct way of checking
+           * if the oscillator is running. Here we use rtc_clk_cal function
+           * to count the number of main XTAL cycles in the given number of
+           * 32k XTAL oscillator cycles. If the 32k XTAL has not started up,
+           * calibration will time out, returning 0.
+           */
+
+          if (slow_clk == SLOW_CLK_32K_XTAL ||
+              slow_clk == SLOW_CLK_32K_EXT_OSC)
+            {
+              esp32c3_rtc_clk_32k_enable(true);
+            }
+
+          if (SLOW_CLK_CAL_CYCLES > 0)
+            {
+              cal_val = esp32c3_rtc_clk_cal(RTC_CAL_32K_XTAL,
+                                            SLOW_CLK_CAL_CYCLES);
+              if (cal_val == 0 || cal_val < MIN_32K_XTAL_CAL_VAL)
+                {
+                  if (retry_32k_xtal-- > 0)
+                    {
+                      continue;
+                    }
+
+                  rtc_slow_freq = RTC_SLOW_FREQ_RTC;
+                }
+            }
+        }
+      else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256)
+        {
+          esp32c3_rtc_clk_8m_enable(true, true);
+        }
+
+      esp32c3_rtc_clk_slow_freq_set(rtc_slow_freq);
+      if (SLOW_CLK_CAL_CYCLES > 0)
+        {
+          /* 32k XTAL oscillator has some frequency drift at startup. Improve
+           * calibration routine to wait until the frequency is stable.
+           */
+
+          cal_val = esp32c3_rtc_clk_cal(RTC_CAL_RTC_MUX,
+                                        SLOW_CLK_CAL_CYCLES);
+        }
+      else
+        {
+          cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
+          cal_val = (uint32_t) (cal_dividend /
+                                esp32c3_rtc_clk_slow_freq_get_hz());
+        }
+    }
+  while (cal_val == 0);
+
+  putreg32((uint32_t)cal_val, RTC_SLOW_CLK_CAL_REG);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_sleep_finish
+ *
+ * Description:
+ *   Wake up from sleep.
+ *
+ * Input Parameters:
+ *   lslp_mem_inf_fpu - If non-zero then the low power config
+ *                      is restored immediately on wake
+ *
+ * Returned Value:
+ *   non-zero if sleep was rejected by hardware
+ *
+ ****************************************************************************/
+
+static uint32_t IRAM_ATTR esp32c3_rtc_sleep_finish(uint32_t lslp_mem_inf_fpu)
+{
+  uint32_t reject;
+  struct esp32c3_rtc_sleep_pu_config_s pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
+
+  /* In deep sleep mode, we never get here */
+
+  reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW);
+  modifyreg32(RTC_CNTL_INT_CLR_REG, 0,
+              RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
+
+  /* restore config if it is a light sleep */
+
+  if (lslp_mem_inf_fpu)
+    {
+      esp32c3_rtc_sleep_pu(pu_cfg);
+    }
+
+  return reject;
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_apb_freq_update
+ *
+ * Description:
+ *   Store new APB frequency value into RTC_APB_FREQ_REG
+ *
+ * Input Parameters:
+ *   apb_freq - New APB frequency, in Hz
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_apb_freq_update(uint32_t apb_freq)
+{
+  uint32_t val = ((apb_freq >> 12) & UINT16_MAX) |
+                 (((apb_freq >> 12) & UINT16_MAX) << 16);
+  putreg32(val, RTC_APB_FREQ_REG);
+}
+
+/****************************************************************************
+ * Name: esp32c3_wait_dig_dbias_valid
+ *
+ * Description:
+ *   Wait digtial dbias valid
+ *
+ * Input Parameters:
+ *   rtc_cycles - RTC count
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_wait_dig_dbias_valid(uint64_t rtc_cycles)
+{
+  enum esp32c3_rtc_slow_freq_e slow_clk_freq =
+                                    esp32c3_rtc_clk_slow_freq_get();
+  enum esp32c3_rtc_cal_sel_e cal_clk = RTC_CAL_RTC_MUX;
+  if (slow_clk_freq == RTC_SLOW_FREQ_32K_XTAL)
+    {
+      cal_clk = RTC_CAL_32K_XTAL;
+    }
+  else if (slow_clk_freq == RTC_SLOW_FREQ_8MD256)
+    {
+      cal_clk = RTC_CAL_8MD256;
+    }
+
+  esp32c3_rtc_clk_cal(cal_clk, rtc_cycles);
+}
+
+/****************************************************************************
+ * Name: esp32c3_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
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_update_to_xtal(int freq, int div)
+{
+  int origin_soc_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                                     SYSTEM_SOC_CLK_SEL);
+  int origin_div_cnt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                                     SYSTEM_PRE_DIV_CNT);
+  ets_update_cpu_frequency(freq);
+
+  /* lower the voltage */
+
+  if (freq <= 2)
+    {
+      REGI2C_WRITE_MASK(I2C_DIG_REG,
+                        I2C_DIG_REG_EXT_DIG_DREG, DIG_DBIAS_2M);
+    }
+  else
+    {
+      REGI2C_WRITE_MASK(I2C_DIG_REG,
+                        I2C_DIG_REG_EXT_DIG_DREG, DIG_DBIAS_XTAL);
+    }
+
+  if ((DPORT_SOC_CLK_SEL_XTAL == origin_soc_clk)
+                        && (origin_div_cnt > 0))
+    {
+      esp32c3_wait_dig_dbias_valid(2);
+    }
+
+  /* Set divider from XTAL to APB clock.
+   * Need to set divider to 1 (reg. value 0) first.
+   */
+
+  REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
+  REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1);
+
+  /* No need to adjust the REF_TICK.
+   * Switch clock source.
+   */
+
+  REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL);
+  esp32c3_rtc_clk_apb_freq_update(freq * MHZ);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_bbpll_disable
+ *
+ * Description:
+ *   disable BBPLL.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_bbpll_disable(void)
+{
+  modifyreg32(RTC_CNTL_OPTIONS0_REG, 0, RTC_CNTL_BB_I2C_FORCE_PD |
+              RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_set_xtal_wait
+ *
+ * Description:
+ *   Set XTAL wait cycles by RTC slow clock's period
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_set_xtal_wait(void)
+{
+  uint32_t slow_clk_period;
+
+  /* the `xtal_wait` time need 1ms, so we need calibrate slow clk period,
+   * and `RTC_CNTL_XTL_BUF_WAIT` depend on it.
+   */
+
+  uint32_t xtal_wait_1ms = 100;
+  enum esp32c3_rtc_slow_freq_e slow_clk_freq =
+                                      esp32c3_rtc_clk_slow_freq_get();
+  enum esp32c3_rtc_cal_sel_e cal_clk = RTC_CAL_RTC_MUX;
+  if (slow_clk_freq == RTC_SLOW_FREQ_32K_XTAL)
+    {
+      cal_clk = RTC_CAL_32K_XTAL;
+    }
+  else if (slow_clk_freq == RTC_SLOW_FREQ_8MD256)
+    {
+      cal_clk  = RTC_CAL_8MD256;
+    }
+
+  slow_clk_period = esp32c3_rtc_clk_cal(cal_clk, 2000);
+  if (slow_clk_period)
+    {
+      xtal_wait_1ms = (1000 << RTC_CLK_CAL_FRACT) / slow_clk_period;
+    }
+
+  REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, xtal_wait_1ms);
+}
+
+/****************************************************************************
+ * Name: esp32c3_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
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_bbpll_configure(
+                      enum esp32c3_rtc_xtal_freq_e xtal_freq, int pll_freq)
+{
+  uint8_t div_ref;
+  uint8_t div7_0;
+  uint8_t dr1;
+  uint8_t dr3;
+  uint8_t dchgp;
+  uint8_t dcur;
+  uint8_t dbias;
+  uint8_t i2c_bbpll_lref;
+  uint8_t i2c_bbpll_div_7_0;
+  uint8_t i2c_bbpll_dcur;
+
+  modifyreg32(I2C_MST_ANA_CONF0_REG,
+              I2C_MST_BBPLL_STOP_FORCE_HIGH,  0);
+  modifyreg32(I2C_MST_ANA_CONF0_REG, 0, I2C_MST_BBPLL_STOP_FORCE_LOW);
+  if (pll_freq == RTC_PLL_FREQ_480M)
+    {
+      /* Set this register to let the digital part know 480M PLL is used */
+
+      modifyreg32(SYSTEM_CPU_PER_CONF_REG, 0, SYSTEM_PLL_FREQ_SEL);
+
+      /* Configure 480M PLL */
+
+      switch (xtal_freq)
+        {
+          case RTC_XTAL_FREQ_40M:
+            {
+              div_ref = 0;
+              div7_0 = 8;
+              dr1 = 0;
+              dr3 = 0;
+              dchgp = 5;
+              dcur = 3;
+              dbias = 2;
+            }
+            break;
+
+          case RTC_XTAL_FREQ_32M:
+            {
+              div_ref = 1;
+              div7_0 = 26;
+              dr1 = 1;
+              dr3 = 1;
+              dchgp = 4;
+              dcur = 0;
+              dbias = 2;
+            }
+            break;
+
+          default:
+            {
+              div_ref = 0;
+              div7_0 = 8;
+              dr1 = 0;
+              dr3 = 0;
+              dchgp = 5;
+              dcur = 3;
+              dbias = 2;
+            }
+            break;
+        }
+
+      REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6b);
+    }
+  else
+    {
+      /* Clear this register to let the digital part know 320M PLL is used */
+
+      modifyreg32(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL,  0);
+
+      /* Configure 320M PLL */
+
+      switch (xtal_freq)
+        {
+          case RTC_XTAL_FREQ_40M:
+            {
+              div_ref = 0;
+              div7_0 = 4;
+              dr1 = 0;
+              dr3 = 0;
+              dchgp = 5;
+              dcur = 3;
+              dbias = 2;
+            }
+            break;
+
+          case RTC_XTAL_FREQ_32M:
+            {
+              div_ref = 1;
+              div7_0 = 6;
+              dr1 = 0;
+              dr3 = 0;
+              dchgp = 5;
+              dcur = 3;
+              dbias = 2;
+            }
+            break;
+
+          default:
+            {
+              div_ref = 0;
+              div7_0 = 4;
+              dr1 = 0;
+              dr3 = 0;
+              dchgp = 5;
+              dcur = 3;
+              dbias = 2;
+            }
+            break;
+        }
+
+      REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69);
+    }
+
+  i2c_bbpll_lref  = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref);
+  i2c_bbpll_div_7_0 = div7_0;
+  i2c_bbpll_dcur = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB)
+                    | (1 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
+  REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref);
+  REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
+  REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1);
+  REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3);
+  REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
+  REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_cpu_freq_to_8m
+ *
+ * Description:
+ *   Switch CPU frequency to 8 Mhz.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_cpu_freq_to_8m(void)
+{
+  int origin_soc_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                                        SYSTEM_SOC_CLK_SEL);
+  int origin_div_cnt = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                                        SYSTEM_PRE_DIV_CNT);
+  ets_update_cpu_frequency(8);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG,
+                                          DIG_DBIAS_XTAL);
+  if ((DPORT_SOC_CLK_SEL_XTAL == origin_soc_clk)
+                            && (origin_div_cnt > 4))
+    {
+      esp32c3_wait_dig_dbias_valid(2);
+    }
+
+  REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
+  REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL,
+                DPORT_SOC_CLK_SEL_8M);
+  esp32c3_rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_cpu_freq_to_pll_mhz
+ *
+ * Description:
+ *   Switch to one of PLL-based frequencies.
+ *
+ * Input Parameters:
+ *   cpu_freq_mhz - CPU frequency
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+static void IRAM_ATTR esp32c3_rtc_clk_cpu_freq_to_pll_mhz(
+                                             int cpu_freq_mhz)
+{
+  int origin_soc_clk = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                                        SYSTEM_SOC_CLK_SEL);
+  int origin_cpuperiod_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG,
+                                              SYSTEM_CPUPERIOD_SEL);
+  int dbias = DIG_DBIAS_80M;
+  int per_conf = DPORT_CPUPERIOD_SEL_80;
+  if (cpu_freq_mhz == 160)
+    {
+      dbias = DIG_DBIAS_160M;
+      per_conf = DPORT_CPUPERIOD_SEL_160;
+    }
+  else
+    {
+      ASSERT(cpu_freq_mhz != 80);
+    }
+
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, dbias);
+  if ((origin_soc_clk == DPORT_SOC_CLK_SEL_XTAL)
+      || (origin_soc_clk == DPORT_SOC_CLK_SEL_8M)
+      || (((origin_soc_clk == DPORT_SOC_CLK_SEL_PLL)
+      && (0 == origin_cpuperiod_sel))))
+    {
+      esp32c3_wait_dig_dbias_valid(2);
+    }
+
+  REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf);
+  REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
+  REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL,
+                DPORT_SOC_CLK_SEL_PLL);
+  esp32c3_rtc_clk_apb_freq_update(80 * MHZ);
+  ets_update_cpu_frequency(cpu_freq_mhz);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_xtal_freq_get
+ *
+ * Description:
+ *   Get main XTAL frequency
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   XTAL frequency (one of enum esp32c3_rtc_xtal_freq_e values)
+ *
+ ****************************************************************************/
+
+enum esp32c3_rtc_xtal_freq_e IRAM_ATTR
+            esp32c3_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 (!esp32c3_clk_val_is_valid(xtal_freq_reg))
+    {
+      return RTC_XTAL_FREQ_40M;
+    }
+
+  return (xtal_freq_reg & UINT16_MAX);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_slow_freq_set
+ *
+ * Description:
+ *   Select source for RTC_SLOW_CLK
+ *
+ * Input Parameters:
+ *   slow_freq - clock source (one of esp32c3_rtc_slow_freq_e values)
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_rtc_clk_slow_freq_set(
+                           enum esp32c3_rtc_slow_freq_e slow_freq)
+{
+  REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq);
+
+  /* Why we need to connect this clock to digital? Or maybe this clock
+   * should be connected to digital when xtal 32k clock is enabled instead?
+   */
+
+  REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN,
+                (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0);
+
+  /* The clk_8m_d256 will be closed when rtc_state in SLEEP,
+   * so if the slow_clk is 8md256, clk_8m must be force power on
+   */
+
+  REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU,
+               (slow_freq == RTC_SLOW_FREQ_8MD256) ? 1 : 0);
+  esp32c3_rtc_clk_set_xtal_wait();
+  esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_slow_freq_get
+ *
+ * Description:
+ *   Get the RTC_SLOW_CLK source
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Currently selected clock source
+ *   (one of enum esp32c3_rtc_slow_freq_e values)
+ *
+ ****************************************************************************/
+
+enum esp32c3_rtc_slow_freq_e IRAM_ATTR esp32c3_rtc_clk_slow_freq_get(void)
+{
+  return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
+}
+
+/****************************************************************************
+ * Name: esp32c3_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
+ *
+ ****************************************************************************/
+
+uint32_t IRAM_ATTR esp32c3_rtc_clk_cal(enum esp32c3_rtc_cal_sel_e cal_clk,
+                                                     uint32_t slowclk_cycles)
+{
+  enum esp32c3_rtc_xtal_freq_e xtal_freq;
+  uint64_t xtal_cycles;
+  uint64_t divider;
+  uint64_t period_64;
+  uint32_t period;
+
+  xtal_freq = esp32c3_rtc_clk_xtal_freq_get();
+  xtal_cycles = esp32c3_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: esp32c3_rtc_clk_set
+ *
+ * Description:
+ *   Set RTC CLK frequency.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_clk_set()
+{
+  esp32c3_rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
+  esp32c3_select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_init
+ *
+ * Description:
+ *   Initialize RTC clock and power control related functions.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_rtc_init()
+{
+  struct esp32c3_rtc_priv_s cfg = RTC_CONFIG_DEFAULT();
+  struct esp32c3_rtc_init_config_s rtc_init_cfg = RTC_INIT_CONFIG_DEFAULT();
+
+  /* If this pd_cfg is set to 1, all memory won't
+   * enter low power mode during light sleep.
+   * If this pd_cfg is set to 0, all memory will
+   * enter low power mode during light sleep
+   */
+
+  struct esp32c3_rtc_sleep_pu_config_s pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(0);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
+  modifyreg32(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU, 0);
+  esp32c3_rtc_clk_set_xtal_wait();
+  REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait);
+  REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait);
+  REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL,
+                RTC_CNTL_MIN_SLP_VAL_MIN);
+
+  /* set default powerup & wait time */
+
+  REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER,
+                rtc_init_cfg.wifi_powerup_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER,
+                rtc_init_cfg.wifi_wait_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_BT_POWERUP_TIMER,
+                rtc_init_cfg.bt_powerup_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_BT_WAIT_TIMER,
+                rtc_init_cfg.bt_wait_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_CPU_TOP_POWERUP_TIMER,
+                rtc_init_cfg.cpu_top_powerup_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_CPU_TOP_WAIT_TIMER,
+                rtc_init_cfg.cpu_top_wait_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER,
+                rtc_init_cfg.dg_wrap_powerup_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER,
+                rtc_init_cfg.dg_wrap_wait_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER6_REG, RTC_CNTL_DG_PERI_POWERUP_TIMER,
+                rtc_init_cfg.dg_peri_powerup_cycles);
+  REG_SET_FIELD(RTC_CNTL_TIMER6_REG, RTC_CNTL_DG_PERI_WAIT_TIMER,
+                rtc_init_cfg.dg_peri_wait_cycles);
+
+  /* Reset RTC bias to default value (needed if waking up from deep sleep) */
+
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP,
+                    RTC_CNTL_DBIAS_1V10);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG,
+                    RTC_CNTL_DBIAS_1V10);
+  if (cfg.clkctl_init)
+    {
+      /* clear CMMU clock force on */
+
+      modifyreg32(EXTMEM_CACHE_MMU_POWER_CTRL_REG,
+                  EXTMEM_CACHE_MMU_MEM_FORCE_ON, 0);
+
+      /* clear tag clock force on */
+
+      modifyreg32(EXTMEM_ICACHE_TAG_POWER_CTRL_REG,
+                  EXTMEM_ICACHE_TAG_MEM_FORCE_ON, 0);
+
+      /* clear register clock force on */
+
+      modifyreg32(SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLK_EN, 0);
+      modifyreg32(SPI_MEM_CLOCK_GATE_REG(1), SPI_MEM_CLK_EN, 0);
+    }
+
+  if (cfg.pwrctl_init)
+    {
+      modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, 0);
+
+      /* cancel xtal force pu if no need to force power up
+       * cannot cancel xtal force pu if pll is force power on
+       */
+
+      if (!(cfg.xtal_fpu | cfg.bbpll_fpu))
+        {
+          modifyreg32(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, 0);
+        }
+      else
+        {
+          modifyreg32(RTC_CNTL_OPTIONS0_REG, 0, RTC_CNTL_XTL_FORCE_PU);
+        }
+
+      /* force pd APLL */
+
+      modifyreg32(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, 0);
+      modifyreg32(RTC_CNTL_ANA_CONF_REG, 0, RTC_CNTL_PLLA_FORCE_PD);
+
+      /* open sar_i2c protect function to avoid sar_i2c
+       * reset when rtc_ldo is low.
+       */
+
+      modifyreg32(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_I2C_RESET_POR_FORCE_PD, 0);
+
+      /* cancel bbpll force pu if setting no force power up */
+
+      if (!cfg.bbpll_fpu)
+        {
+          modifyreg32(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_FORCE_PU |
+              RTC_CNTL_BBPLL_I2C_FORCE_PU | RTC_CNTL_BB_I2C_FORCE_PU, 0);
+        }
+      else
+        {
+          modifyreg32(RTC_CNTL_OPTIONS0_REG, 0, RTC_CNTL_BBPLL_FORCE_PU |
+              RTC_CNTL_BBPLL_I2C_FORCE_PU | RTC_CNTL_BB_I2C_FORCE_PU);
+        }
+
+      modifyreg32(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU |
+                  RTC_CNTL_DBOOST_FORCE_PU, 0);
+      if (cfg.rtc_dboost_fpd)
+        {
+          modifyreg32(RTC_CNTL_REG, 0, RTC_CNTL_DBOOST_FORCE_PD);
+        }
+      else
+        {
+          modifyreg32(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD, 0);
+        }
+
+      /* If this mask is enabled, all soc memories
+       * cannot enter power down mode.
+       * We should control soc memory power down mode from RTC,
+       * so we will not touch this register any more.
+       */
+
+      modifyreg32(SYSTEM_MEM_PD_MASK_REG, SYSTEM_LSLP_MEM_PD_MASK, 0);
+      esp32c3_rtc_sleep_pu(pu_cfg);
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU |
+                  RTC_CNTL_WIFI_FORCE_PU | RTC_CNTL_BT_FORCE_PU |
+                  RTC_CNTL_CPU_TOP_FORCE_PU | RTC_CNTL_DG_PERI_FORCE_PU , 0);
+
+      modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_WRAP_FORCE_NOISO |
+            RTC_CNTL_WIFI_FORCE_NOISO | RTC_CNTL_BT_FORCE_NOISO |
+            RTC_CNTL_CPU_TOP_FORCE_NOISO | RTC_CNTL_DG_PERI_FORCE_NOISO , 0);
+
+      /* cancel digital PADS force no iso */
+
+      if (cfg.cpu_waiti_clk_gate)
+        {
+          modifyreg32(SYSTEM_CPU_PER_CONF_REG,
+                      SYSTEM_CPU_WAIT_MODE_FORCE_ON, 0);
+        }
+      else
+        {
+          modifyreg32(SYSTEM_CPU_PER_CONF_REG, 0,
+                      SYSTEM_CPU_WAIT_MODE_FORCE_ON);
+        }
+
+      /* if SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0 ,
+       * the cpu clk will be closed when cpu enter WAITI mode.
+       */
+
+      modifyreg32(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD |
+                  RTC_CNTL_DG_PAD_FORCE_NOISO, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_time_get
+ *
+ * Description:
+ *   Get current value of RTC counter.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   current value of RTC counter
+ *
+ ****************************************************************************/
+
+uint64_t IRAM_ATTR esp32c3_rtc_time_get(void)
+{
+  uint64_t rtc_time;
+
+  modifyreg32(RTC_CNTL_TIME_UPDATE_REG, 0, RTC_CNTL_TIME_UPDATE);
+  rtc_time = getreg32(RTC_CNTL_TIME0_REG);
+  rtc_time |= ((uint64_t) getreg32(RTC_CNTL_TIME1_REG)) << 32;
+
+  return rtc_time;
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_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: esp32c3_rtc_time_slowclk_to_us
+ *
+ * Description:
+ *   Convert time interval from RTC_SLOW_CLK to microseconds
+ *
+ * Input Parameters:
+ *   rtc_cycles - Time interval in RTC_SLOW_CLK cycles
+ *   period     - Period of slow clock in microseconds
+ *
+ * Returned Value:
+ *   time interval in microseconds
+ *
+ ****************************************************************************/
+
+uint64_t IRAM_ATTR esp32c3_rtc_time_slowclk_to_us(uint64_t rtc_cycles,
+                                                  uint32_t period)
+{
+  return (rtc_cycles * period) >> RTC_CLK_CAL_FRACT;
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_cpu_freq_set_xtal
+ *
+ * Description:
+ *   Switch CPU clock source to XTAL
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_rtc_cpu_freq_set_xtal(void)
+{
+  int freq_mhz = (int) esp32c3_rtc_clk_xtal_freq_get();
+  esp32c3_rtc_update_to_xtal(freq_mhz, 1);
+  esp32c3_rtc_clk_bbpll_disable();
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_sleep_init
+ *
+ * Description:
+ *   Prepare the chip to enter sleep mode
+ *
+ * Input Parameters:
+ *   flags - sleep mode configuration
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_rtc_sleep_init(uint32_t flags)
+{
+  struct esp32c3_rtc_sleep_config_s cfg = RTC_SLEEP_CONFIG_DEFAULT(flags);
+  struct esp32c3_rtc_sleep_pu_config_s pu_cfg = RTC_SLEEP_PU_CONFIG_ALL(1);
+  if (cfg.lslp_mem_inf_fpu)
+    {
+      esp32c3_rtc_sleep_pu(pu_cfg);
+    }
+
+  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.bt_pd_en)
+    {
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_BT_PD_EN);
+    }
+  else
+    {
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_PD_EN, 0);
+    }
+
+  if (cfg.cpu_pd_en)
+    {
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_CPU_TOP_PD_EN);
+    }
+  else
+    {
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_TOP_PD_EN, 0);
+    }
+
+  if (cfg.dig_peri_pd_en)
+    {
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_DG_PERI_PD_EN);
+    }
+  else
+    {
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_PERI_PD_EN, 0);
+    }
+
+  REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_MONITOR,
+                RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT);
+  REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_MONITOR,
+                RTC_CNTL_BIASSLP_MONITOR_DEFAULT);
+  REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_BIAS_SLEEP_DEEP_SLP,
+                RTC_CNTL_BIASSLP_SLEEP_DEFAULT);
+  REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_MONITOR,
+                RTC_CNTL_PD_CUR_MONITOR_DEFAULT);
+  REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_PD_CUR_DEEP_SLP,
+                RTC_CNTL_PD_CUR_SLEEP_DEFAULT);
+  if (cfg.deep_slp)
+    {
+      REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_CK, 0);
+      modifyreg32(RTC_CNTL_REG, RTC_CNTL_REGULATOR_FORCE_PU, 0);
+
+      /* It's only a temporary configuration to set dbg 0 to make
+       * deepsleep run successfully when in high temperature.
+       * We will restore it to RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT
+       * when ECO chip come back. TODO ESP32-C3 IDF-2568
+       */
+
+      REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP, 0);
+      modifyreg32(RTC_CNTL_DIG_PWC_REG, 0, RTC_CNTL_DG_WRAP_PD_EN);
+      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_BIAS_CONF_REG, 0, RTC_CNTL_DG_VDD_DRV_B_SLP_EN);
+      REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DG_VDD_DRV_B_SLP,
+                    RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT);
+      modifyreg32(RTC_CNTL_REG, 0, RTC_CNTL_REGULATOR_FORCE_PU);
+      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_DEEP_SLP,
+                    RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT);
+    }
+
+  /* enable VDDSDIO control by state machine */
+
+  REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
+  REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN,
+                cfg.vddsdio_pd_en);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP,
+                    cfg.rtc_dbias_slp);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG,
+                    cfg.rtc_dbias_wak);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG_SLEEP,
+                    cfg.dig_dbias_slp);
+  REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG,
+                    cfg.dig_dbias_wak);
+  REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_DEEP_SLP_REJECT_EN,
+                cfg.deep_slp_reject);
+  REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG, RTC_CNTL_LIGHT_SLP_REJECT_EN,
+                cfg.light_slp_reject);
+
+  /* gating XTAL clock */
+
+  REG_CLR_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_XTAL_GLOBAL_FORCE_NOGATING);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_deep_sleep_start
+ *
+ * Description:
+ *   Enter deep 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
+ *
+ ****************************************************************************/
+
+uint32_t IRAM_ATTR esp32c3_rtc_deep_sleep_start(uint32_t wakeup_opt,
+                                                uint32_t reject_opt)
+{
+  /* Values used to set the SYSTEM_RTC_FASTMEM_CONFIG_REG value */
+
+  const unsigned CRC_START_ADDR = 0;
+  const unsigned CRC_LEN = 0x7ff;
+
+  REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
+  putreg32(reject_opt, RTC_CNTL_SLP_REJECT_CONF_REG);
+
+  /* Calculate RTC Fast Memory CRC (for wake stub) & go to deep sleep
+   * Because we may be running from RTC memory as stack, we can't easily
+   * call any functions to do this (as registers will spill to stack,
+   * corrupting the CRC). Instead, load all the values we need into registers
+   * then use register ops only to calculate the CRC value, write it to the
+   * RTC CRC value register, and immediately go into deep sleep.
+   */
+
+  asm volatile(
+
+  /* Start CRC calculation */
+
+    "sw %1, 0(%0)\n"
+    "or t0, %1, %2\n"
+    "sw t0, 0(%0)\n"
+
+  /* Wait for the CRC calculation to finish */
+
+    ".Lwaitcrc:\n"
+    "fence\n"
+    "lw t0, 0(%0)\n"
+    "li t1, "STR(SYSTEM_RTC_MEM_CRC_FINISH)"\n"
+    "and t0, t0, t1\n"
+    "beqz t0, .Lwaitcrc\n"
+    "not %2, %2\n"
+    "and t0, t0, %2\n"
+    "sw t0, 0(%0)\n"
+    "fence\n"
+    "not %2, %2\n"
+
+  /* Store the calculated value in RTC_MEM_CRC_REG */
+
+    "lw t0, 0(%3)\n"
+    "sw t0, 0(%4)\n"
+    "fence\n"
+
+  /* Set register bit to go into deep sleep */
+
+    "lw t0, 0(%5)\n"
+    "or   t0, t0, %6\n"
+    "sw t0, 0(%5)\n"
+    "fence\n"
+
+  /* Wait for sleep reject interrupt (never finishes if successful) */
+
+    ".Lwaitsleep:"
+    "fence\n"
+    "lw t0, 0(%7)\n"
+    "and t0, t0, %8\n"
+    "beqz t0, .Lwaitsleep\n"
+
+    :
+    :
+      "r" (SYSTEM_RTC_FASTMEM_CONFIG_REG),
+      "r" ((CRC_START_ADDR << SYSTEM_RTC_MEM_CRC_START_S)
+            | (CRC_LEN << SYSTEM_RTC_MEM_CRC_LEN_S)),
+      "r" (SYSTEM_RTC_MEM_CRC_START),
+      "r" (SYSTEM_RTC_FASTMEM_CRC_REG),
+      "r" (RTC_MEMORY_CRC_REG),
+      "r" (RTC_CNTL_STATE0_REG),
+      "r" (RTC_CNTL_SLEEP_EN),
+      "r" (RTC_CNTL_INT_RAW_REG),
+      "r" (RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW)
+    : "t0", "t1"
+  );
+
+  return esp32c3_rtc_sleep_finish(0);
+}
+
+/****************************************************************************
+ * Name: esp32c3_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
+ *
+ ****************************************************************************/
+
+uint32_t IRAM_ATTR esp32c3_rtc_sleep_start(uint32_t wakeup_opt,
+                            uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)
+{
+  REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
+  REG_SET_FIELD(RTC_CNTL_SLP_REJECT_CONF_REG,
+                RTC_CNTL_SLEEP_REJECT_ENA, reject_opt);
+
+  /* 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);
+
+  return esp32c3_rtc_sleep_finish(lslp_mem_inf_fpu);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_cpu_freq_set_config
+ *
+ * Description:
+ *   Set CPU frequency configuration.
+ *
+ * Input Parameters:
+ *   config - CPU frequency configuration
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_rtc_clk_cpu_freq_set_config(
+               const struct esp32c3_cpu_freq_config_s *config)
+{
+  uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                                          SYSTEM_SOC_CLK_SEL);
+  if (config->source == RTC_CPU_FREQ_SRC_XTAL)
+    {
+      esp32c3_rtc_update_to_xtal(config->freq_mhz, config->div);
+      if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL)
+        {
+          esp32c3_rtc_clk_bbpll_disable();
+        }
+    }
+  else if (config->source == RTC_CPU_FREQ_SRC_PLL)
+    {
+      if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL)
+        {
+          modifyreg32(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
+                RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD,  0);
+          esp32c3_rtc_bbpll_configure(esp32c3_rtc_clk_xtal_freq_get(),
+                                             config->source_freq_mhz);
+        }
+
+      esp32c3_rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
+    }
+  else if (config->source == RTC_CPU_FREQ_SRC_8M)
+    {
+      esp32c3_rtc_clk_cpu_freq_to_8m();
+      if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL)
+        {
+          esp32c3_rtc_clk_bbpll_disable();
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_sleep_low_init
+ *
+ * Description:
+ *   Low level initialize for rtc state machine waiting
+ *   cycles after waking up.
+ *
+ * Input Parameters:
+ *   slowclk_period - Re-calibrated slow clock period
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_rtc_sleep_low_init(uint32_t slowclk_period)
+{
+  /* Set 5 PWC state machine times to fit in main state machine time */
+
+  REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT,
+                          RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES);
+  REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT,
+                          esp32c3_rtc_time_us_to_slowclk(
+                          RTC_CNTL_XTL_BUF_WAIT_SLP_US, slowclk_period));
+  REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT,
+                          RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
+}
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_cpu_freq_get_config
+ *
+ * Description:
+ *   Get the currently used CPU frequency configuration.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   CPU clock configuration structure
+ *
+ ****************************************************************************/
+
+void IRAM_ATTR esp32c3_rtc_clk_cpu_freq_get_config(
+                           struct esp32c3_cpu_freq_config_s *out_config)
+{
+  uint32_t div = 3;
+  uint32_t freq_mhz = 160;
+  uint32_t source_freq_mhz = RTC_PLL_FREQ_480M;
+  enum esp32c3_rtc_cpu_freq_src_e source = RTC_CPU_FREQ_SRC_PLL;
+  uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                                       SYSTEM_SOC_CLK_SEL);
+  switch (soc_clk_sel)
+    {
+      case DPORT_SOC_CLK_SEL_XTAL:
+        {
+          source = RTC_CPU_FREQ_SRC_XTAL;
+          div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG,
+                              SYSTEM_PRE_DIV_CNT) + 1;
+          source_freq_mhz = (uint32_t) esp32c3_rtc_clk_xtal_freq_get();
+          freq_mhz = source_freq_mhz / div;
+        }
+        break;
+
+      case DPORT_SOC_CLK_SEL_PLL:
+        {
+          uint32_t cpuperiod_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG,
+                                                   SYSTEM_CPUPERIOD_SEL);
+          uint32_t pllfreq_sel = REG_GET_FIELD(SYSTEM_CPU_PER_CONF_REG,
+                                                   SYSTEM_PLL_FREQ_SEL);
+          source = RTC_CPU_FREQ_SRC_PLL;
+          source_freq_mhz = (pllfreq_sel) ?
+                             RTC_PLL_FREQ_480M : RTC_PLL_FREQ_320M;
+          if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_80)
+            {
+              div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 6 : 4;
+              freq_mhz = 80;
+            }
+          else if (cpuperiod_sel == DPORT_CPUPERIOD_SEL_160)
+            {
+              div = (source_freq_mhz == RTC_PLL_FREQ_480M) ? 3 : 2;
+              div = 3;
+              freq_mhz = 160;
+            }
+          else
+            {
+              ASSERT(0);
+            }
+        }
+        break;
+
+      case DPORT_SOC_CLK_SEL_8M:
+        {
+          source = RTC_CPU_FREQ_SRC_8M;
+          source_freq_mhz = 8;
+          div = 1;
+          freq_mhz = source_freq_mhz;
+        }
+        break;
+
+      default:
+        ASSERT(0);
+    }
+
+  *out_config = (struct esp32c3_cpu_freq_config_s)
+    {
+      .source = source,
+      .source_freq_mhz = source_freq_mhz,
+      .div = div,
+      .freq_mhz = freq_mhz
+    };
+}
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_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);
+  modifyreg32(RTC_CNTL_INT_CLR_REG, 0, RTC_CNTL_MAIN_TIMER_INT_CLR_M);
+  modifyreg32(RTC_CNTL_SLP_TIMER1_REG, 0, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
+}
diff --git a/arch/risc-v/src/esp32c3/esp32c3_rtc.h b/arch/risc-v/src/esp32c3/esp32c3_rtc.h
new file mode 100644
index 0000000..ab5fdec
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/esp32c3_rtc.h
@@ -0,0 +1,437 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/esp32c3_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_RISCV_SRC_ESP32C3_ESP32C3_RTC_H
+#define __ARCH_RISCV_SRC_ESP32C3_ESP32C3_RTC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "hardware/esp32c3_soc.h"
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Cycles for RTC Timer clock source (internal oscillator) calibrate */
+
+#define RTC_CLK_SRC_CAL_CYCLES           (10)
+
+/* Various delays to be programmed into power control state machines */
+
+#define RTC_CNTL_XTL_BUF_WAIT_SLP_US            (250)
+#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES        (1)
+#define RTC_CNTL_CK8M_WAIT_SLP_CYCLES           (4)
+#define RTC_CNTL_WAKEUP_DELAY_CYCLES            (5)
+
+#define RTC_SLOW_CLK_CAL_REG    RTC_CNTL_STORE1_REG
+#define RTC_BOOT_TIME_LOW_REG   RTC_CNTL_STORE2_REG
+#define RTC_BOOT_TIME_HIGH_REG  RTC_CNTL_STORE3_REG
+#define RTC_XTAL_FREQ_REG       RTC_CNTL_STORE4_REG
+#define RTC_APB_FREQ_REG        RTC_CNTL_STORE5_REG
+#define RTC_ENTRY_ADDR_REG      RTC_CNTL_STORE6_REG
+#define RTC_RESET_CAUSE_REG     RTC_CNTL_STORE6_REG
+#define RTC_MEMORY_CRC_REG      RTC_CNTL_STORE7_REG
+
+#define RTC_SLEEP_PD_DIG                BIT(0)  /* Deep sleep */
+#define RTC_SLEEP_PD_RTC_PERIPH         BIT(1)  /* Power down RTC peripherals */
+#define RTC_SLEEP_PD_RTC_SLOW_MEM       BIT(2)  /* Power down RTC SLOW memory */
+#define RTC_SLEEP_PD_RTC_FAST_MEM       BIT(3)  /* Power down RTC FAST memory */
+
+/* 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)
+#define RTC_SLEEP_PD_VDDSDIO            BIT(5)  /* Power down VDDSDIO regulator */
+#define RTC_SLEEP_PD_WIFI               BIT(6)  /* Power down Wi-Fi */
+#define RTC_SLEEP_PD_BT                 BIT(7)  /* Power down BT */
+#define RTC_SLEEP_PD_CPU                BIT(8)  /* Power down CPU when in light-sleep */
+#define RTC_SLEEP_PD_DIG_PERIPH         BIT(9)  /* Power down DIG peripherals */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Clock source to be calibrated using rtc_clk_cal function */
+
+enum esp32c3_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 */
+};
+
+/* CPU clock source */
+
+enum esp32c3_rtc_cpu_freq_src_e
+{
+  RTC_CPU_FREQ_SRC_XTAL,  /* XTAL */
+  RTC_CPU_FREQ_SRC_PLL,   /* PLL (480M or 320M) */
+  RTC_CPU_FREQ_SRC_8M,    /* Internal 8M RTC oscillator */
+  RTC_CPU_FREQ_SRC_APLL   /* APLL */
+};
+
+/* Possible main XTAL frequency values.
+ * Enum values should be equal to frequency in MHz.
+ */
+
+enum esp32c3_rtc_xtal_freq_e
+{
+  RTC_XTAL_FREQ_32M = 32,
+  RTC_XTAL_FREQ_40M = 40,
+};
+
+/* RTC SLOW_CLK frequency values */
+
+enum esp32c3_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 */
+};
+
+/* CPU clock configuration structure */
+
+struct esp32c3_cpu_freq_config_s
+{
+  /* The clock from which CPU clock is derived */
+
+  enum esp32c3_rtc_cpu_freq_src_e source;
+  uint32_t source_freq_mhz;    /* Source clock frequency */
+  uint32_t div;                /* Divider, freq_mhz = source_freq_mhz / div */
+  uint32_t freq_mhz;           /* CPU clock frequency */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_xtal_freq_get
+ *
+ * Description:
+ *   Get main XTAL frequency
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   XTAL frequency (one of enum esp32c3_rtc_xtal_freq_e values)
+ *
+ ****************************************************************************/
+
+enum esp32c3_rtc_xtal_freq_e esp32c3_rtc_clk_xtal_freq_get(void);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_slow_freq_get
+ *
+ * Description:
+ *   Get the RTC_SLOW_CLK source
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Currently selected clock source
+ *   (one of enum esp32c3_rtc_slow_freq_e values)
+ *
+ ****************************************************************************/
+
+enum esp32c3_rtc_slow_freq_e esp32c3_rtc_clk_slow_freq_get(void);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_slow_freq_set
+ *
+ * Description:
+ *   Select source for RTC_SLOW_CLK
+ *
+ * Input Parameters:
+ *   slow_freq - clock source (one of esp32c3_rtc_slow_freq_e values)
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_clk_slow_freq_set(enum esp32c3_rtc_slow_freq_e slow_freq);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_set
+ *
+ * Description:
+ *   Set RTC CLK frequency.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_clk_set(void);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_init
+ *
+ * Description:
+ *   Initialize RTC clock and power control related functions.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_init(void);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_time_get
+ *
+ * Description:
+ *   Get current value of RTC counter.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   current value of RTC counter
+ *
+ ****************************************************************************/
+
+uint64_t esp32c3_rtc_time_get(void);
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_rtc_time_us_to_slowclk(uint64_t time_in_us,
+                                        uint32_t period);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_cpu_freq_set_xtal
+ *
+ * Description:
+ *   Switch CPU clock source to XTAL
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_cpu_freq_set_xtal(void);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_sleep_init
+ *
+ * Description:
+ *   Prepare the chip to enter sleep mode
+ *
+ * Input Parameters:
+ *   flags - sleep mode configuration
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_sleep_init(uint32_t flags);
+
+/****************************************************************************
+ * Name: esp32c3_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
+ *
+ ****************************************************************************/
+
+uint32_t esp32c3_rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
+                                 uint32_t lslp_mem_inf_fpu);
+
+/****************************************************************************
+ * Name: esp32c3_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
+ *
+ ****************************************************************************/
+
+uint32_t esp32c3_rtc_clk_cal(enum esp32c3_rtc_cal_sel_e cal_clk,
+                             uint32_t slowclk_cycles);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_time_slowclk_to_us
+ *
+ * Description:
+ *   Convert time interval from RTC_SLOW_CLK to microseconds
+ *
+ * Input Parameters:
+ *   rtc_cycles - Time interval in RTC_SLOW_CLK cycles
+ *   period     - Period of slow clock in microseconds
+ *
+ * Returned Value:
+ *   time interval in microseconds
+ *
+ ****************************************************************************/
+
+uint64_t esp32c3_rtc_time_slowclk_to_us(uint64_t rtc_cycles,
+                                                  uint32_t period);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_deep_sleep_start
+ *
+ * Description:
+ *   Enter deep 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
+ *
+ ****************************************************************************/
+
+uint32_t esp32c3_rtc_deep_sleep_start(uint32_t wakeup_opt,
+                                                uint32_t reject_opt);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_cpu_freq_set_config
+ *
+ * Description:
+ *   Set CPU frequency configuration.
+ *
+ * Input Parameters:
+ *   config - CPU frequency configuration
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_clk_cpu_freq_set_config(
+               const struct esp32c3_cpu_freq_config_s *config);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_sleep_low_init
+ *
+ * Description:
+ *   Low level initialize for rtc state machine waiting
+ *   cycles after waking up.
+ *
+ * Input Parameters:
+ *   slowclk_period - Re-calibrated slow clock period
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_sleep_low_init(uint32_t slowclk_period);
+
+/****************************************************************************
+ * Name: esp32c3_rtc_clk_cpu_freq_get_config
+ *
+ * Description:
+ *   Get the currently used CPU frequency configuration.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   CPU clock configuration structure
+ *
+ ****************************************************************************/
+
+void esp32c3_rtc_clk_cpu_freq_get_config(
+             struct esp32c3_cpu_freq_config_s *out_config);
+
+/****************************************************************************
+ * Name: esp32c3_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 esp32c3_rtc_sleep_set_wakeup_time(uint64_t t);
+
+#ifdef __cplusplus
+}
+#endif
+#undef EXTERN
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_RISCV_SRC_ESP32C3_ESP32C3_RTC_H */
diff --git a/arch/risc-v/src/esp32c3/hardware/apb_ctrl_reg.h b/arch/risc-v/src/esp32c3/hardware/apb_ctrl_reg.h
new file mode 100644
index 0000000..1800a5c
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/apb_ctrl_reg.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/apb_ctrl_reg.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_APB_CTRL_REG_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_APB_CTRL_REG_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "esp32c3_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define APB_CTRL_FRONT_END_MEM_PD_REG      (DR_REG_APB_CTRL_BASE + 0x09C)
+
+#define APB_CTRL_MEM_POWER_UP_REG          (DR_REG_APB_CTRL_BASE + 0x0AC)
+
+/* APB_CTRL_DC_MEM_FORCE_PU : R/W ;bitpos:[4] ;default: 1'b1 ; */
+
+#define APB_CTRL_DC_MEM_FORCE_PU  (BIT(4))
+#define APB_CTRL_DC_MEM_FORCE_PU_M  (BIT(4))
+#define APB_CTRL_DC_MEM_FORCE_PU_V  0x1
+#define APB_CTRL_DC_MEM_FORCE_PU_S  4
+
+/* APB_CTRL_PBUS_MEM_FORCE_PU : R/W ;bitpos:[2] ;default: 1'b1 ; */
+
+#define APB_CTRL_PBUS_MEM_FORCE_PU  (BIT(2))
+#define APB_CTRL_PBUS_MEM_FORCE_PU_M  (BIT(2))
+#define APB_CTRL_PBUS_MEM_FORCE_PU_V  0x1
+#define APB_CTRL_PBUS_MEM_FORCE_PU_S  2
+
+/* APB_CTRL_AGC_MEM_FORCE_PU : R/W ;bitpos:[0] ;default: 1'b1 ; */
+
+#define APB_CTRL_AGC_MEM_FORCE_PU  (BIT(0))
+#define APB_CTRL_AGC_MEM_FORCE_PU_M  (BIT(0))
+#define APB_CTRL_AGC_MEM_FORCE_PU_V  0x1
+#define APB_CTRL_AGC_MEM_FORCE_PU_S  0
+
+/* APB_CTRL_SRAM_POWER_UP : R/W ;bitpos:[5:2] ;default: ~4'b0 ; */
+
+#define APB_CTRL_SRAM_POWER_UP  0x0000000F
+#define APB_CTRL_SRAM_POWER_UP_M  ((APB_CTRL_SRAM_POWER_UP_V)<<(APB_CTRL_SRAM_POWER_UP_S))
+#define APB_CTRL_SRAM_POWER_UP_V  0xF
+#define APB_CTRL_SRAM_POWER_UP_S  2
+
+/* APB_CTRL_ROM_POWER_UP : R/W ;bitpos:[1:0] ;default: ~2'b0 ; */
+
+#define APB_CTRL_ROM_POWER_UP  0x00000003
+#define APB_CTRL_ROM_POWER_UP_M  ((APB_CTRL_ROM_POWER_UP_V)<<(APB_CTRL_ROM_POWER_UP_S))
+#define APB_CTRL_ROM_POWER_UP_V  0x3
+#define APB_CTRL_ROM_POWER_UP_S  0
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_APB_CTRL_REG_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/bb_reg.h b/arch/risc-v/src/esp32c3/hardware/bb_reg.h
new file mode 100644
index 0000000..262814e
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/bb_reg.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/bb_reg.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_BB_REG_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_BB_REG_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "esp32c3_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* 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_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
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_BB_REG_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/esp32c3_soc.h b/arch/risc-v/src/esp32c3/hardware/esp32c3_soc.h
index efb5bf3..9e1ba5b 100644
--- a/arch/risc-v/src/esp32c3/hardware/esp32c3_soc.h
+++ b/arch/risc-v/src/esp32c3/hardware/esp32c3_soc.h
@@ -264,5 +264,43 @@
 /* Helper to place a value in a field */
 
 #define VALUE_TO_FIELD(_value, _field) (((_value) << (_field##_S)) & (_field##_M))
+#define DPORT_CPUPERIOD_SEL_80      0
+#define DPORT_CPUPERIOD_SEL_160     1
+
+#define DPORT_SOC_CLK_SEL_XTAL    0
+#define DPORT_SOC_CLK_SEL_PLL    1
+#define DPORT_SOC_CLK_SEL_8M     2
+
+/* Write value to register */
+
+#define REG_WRITE(_r, _v)    (*(volatile uint32_t *)(_r)) = (_v)
+
+/* Read value from register */
+
+#define REG_READ(_r) (*(volatile uint32_t *)(_r))
+
+/* Get bit or get bits from register */
+
+#define REG_GET_BIT(_r, _b)  (*(volatile uint32_t*)(_r) & (_b))
+
+/* Set bit or set bits to register */
+
+#define REG_SET_BIT(_r, _b)  (*(volatile uint32_t*)(_r) |= (_b))
+
+/* Clear bit or clear bits of register */
+
+#define REG_CLR_BIT(_r, _b)  (*(volatile uint32_t*)(_r) &= ~(_b))
+
+/* Get field from register,
+ * used when _f is not left shifted by _f##_S
+ */
+
+#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##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S)))))
 
 #endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_ESP32C3_SOC_H */
diff --git a/arch/risc-v/src/esp32c3/hardware/esp32c3_uart.h b/arch/risc-v/src/esp32c3/hardware/esp32c3_uart.h
index e31343e..511104f 100644
--- a/arch/risc-v/src/esp32c3/hardware/esp32c3_uart.h
+++ b/arch/risc-v/src/esp32c3/hardware/esp32c3_uart.h
@@ -2182,4 +2182,25 @@
 #define UART_REG_UPDATE_V  0x00000001
 #define UART_REG_UPDATE_S  31
 
+/* ESP32-C3 have 2 UART: UART0-1 */
+
+#define ESP32C3_NUARTS 2
+
+/* UART has an extra TX_WAIT_SEND state when the
+ * FIFO is not empty and XOFF is enabled.
+ */
+
+#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND   (1)
+#define UART_FSM_IDLE                       (0x0)
+#define UART_FSM_TX_WAIT_SEND               (0xf)
+
+/* Software write 1 would synchronize registers into UART Core clock
+ * domain and would be cleared by hardware after synchronization is done.
+ */
+
+#define UART_UPDATE    (BIT(31))
+#define UART_UPDATE_M  (BIT(31))
+#define UART_UPDATE_V  0x1
+#define UART_UPDATE_S  31
+
 #endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_ESP32C3_UART_H */
\ No newline at end of file
diff --git a/arch/risc-v/src/esp32c3/hardware/extmem_reg.h b/arch/risc-v/src/esp32c3/hardware/extmem_reg.h
new file mode 100644
index 0000000..88ce7f7
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/extmem_reg.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/extmem_reg.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_EXTMEM_REG_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_EXTMEM_REG_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "esp32c3_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define EXTMEM_CACHE_MMU_POWER_CTRL_REG     (DR_REG_EXTMEM_BASE + 0x0AC)
+#define EXTMEM_ICACHE_TAG_POWER_CTRL_REG    (DR_REG_EXTMEM_BASE + 0x008)
+
+/* EXTMEM_CACHE_MMU_MEM_FORCE_ON : R/W ;bitpos:[0] ;default: 1'b1.
+ * The bit is used to enable clock gating to save
+ * power when access mmu memory  0: enable  1: disable
+ */
+
+#define EXTMEM_CACHE_MMU_MEM_FORCE_ON    (BIT(0))
+#define EXTMEM_CACHE_MMU_MEM_FORCE_ON_M  (BIT(0))
+#define EXTMEM_CACHE_MMU_MEM_FORCE_ON_V  0x1
+#define EXTMEM_CACHE_MMU_MEM_FORCE_ON_S  0
+
+/* EXTMEM_ICACHE_TAG_MEM_FORCE_ON : R/W ;bitpos:[0] ;default: 1'b1.
+ * description: The bit is used to close clock gating of  icache tag memory.
+ * 1: close gating  0: open clock gating.
+ */
+
+#define EXTMEM_ICACHE_TAG_MEM_FORCE_ON    (BIT(0))
+#define EXTMEM_ICACHE_TAG_MEM_FORCE_ON_M  (BIT(0))
+#define EXTMEM_ICACHE_TAG_MEM_FORCE_ON_V  0x1
+#define EXTMEM_ICACHE_TAG_MEM_FORCE_ON_S  0
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_EXTMEM_REG_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/fe_reg.h b/arch/risc-v/src/esp32c3/hardware/fe_reg.h
new file mode 100644
index 0000000..97e6049
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/fe_reg.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/fe_reg.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_FE_REG_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_FE_REG_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "esp32c3_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* 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 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
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_FE_REG_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/nrx_reg.h b/arch/risc-v/src/esp32c3/hardware/nrx_reg.h
new file mode 100644
index 0000000..68a55cc
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/nrx_reg.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/nrx_reg.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_NRX_REG_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_NRX_REG_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "esp32c3_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Some of the Wi-Fi 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_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_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
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_NRX_REG_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/regi2c_bbpll.h b/arch/risc-v/src/esp32c3/hardware/regi2c_bbpll.h
new file mode 100644
index 0000000..375dc1a
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/regi2c_bbpll.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/regi2c_bbpll.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_BBPLL_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_BBPLL_H_
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register definitions for digital PLL (BBPLL). This file lists
+ * register fields of BBPLL, located on an internal configuration bus.
+ */
+
+#define I2C_BBPLL           0x66
+#define I2C_BBPLL_HOSTID    0
+
+#define I2C_BBPLL_MODE_HF        4
+#define I2C_BBPLL_MODE_HF_MSB    1
+#define I2C_BBPLL_MODE_HF_LSB    1
+
+#define I2C_BBPLL_OC_DCUR        6
+#define I2C_BBPLL_OC_DCUR_MSB    2
+#define I2C_BBPLL_OC_DCUR_LSB    0
+
+#define I2C_BBPLL_OC_DR1        5
+#define I2C_BBPLL_OC_DR1_MSB    2
+#define I2C_BBPLL_OC_DR1_LSB    0
+
+#define I2C_BBPLL_OC_DR3        5
+#define I2C_BBPLL_OC_DR3_MSB    6
+#define I2C_BBPLL_OC_DR3_LSB    4
+
+#define I2C_BBPLL_OC_VCO_DBIAS        9
+#define I2C_BBPLL_OC_VCO_DBIAS_MSB    1
+#define I2C_BBPLL_OC_VCO_DBIAS_LSB    0
+
+#define I2C_BBPLL_OC_DCHGP        2
+#define I2C_BBPLL_OC_DCHGP_MSB    6
+#define I2C_BBPLL_OC_DCHGP_LSB    4
+
+#define I2C_BBPLL_OC_DLREF_SEL        6
+#define I2C_BBPLL_OC_DLREF_SEL_MSB    7
+#define I2C_BBPLL_OC_DLREF_SEL_LSB    6
+
+#define I2C_BBPLL_OC_DHREF_SEL        6
+#define I2C_BBPLL_OC_DHREF_SEL_MSB    5
+#define I2C_BBPLL_OC_DHREF_SEL_LSB    4
+
+#define I2C_BBPLL_OC_REF_DIV        2
+#define I2C_BBPLL_OC_REF_DIV_MSB    3
+#define I2C_BBPLL_OC_REF_DIV_LSB    0
+
+#define I2C_BBPLL_OC_DIV_7_0        3
+#define I2C_BBPLL_OC_DIV_7_0_MSB    7
+#define I2C_BBPLL_OC_DIV_7_0_LSB    0
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_BBPLL_H_ */
\ No newline at end of file
diff --git a/arch/risc-v/src/esp32c3/hardware/regi2c_ctrl.h b/arch/risc-v/src/esp32c3/hardware/regi2c_ctrl.h
new file mode 100644
index 0000000..24807b3
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/regi2c_ctrl.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/regi2c_ctrl.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_CTRL_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_CTRL_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+#include "esp32c3_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Analog function control register */
+
+#define I2C_MST_ANA_CONF0_REG          0x6000E040
+#define I2C_MST_BBPLL_STOP_FORCE_HIGH  (BIT(2))
+#define I2C_MST_BBPLL_STOP_FORCE_LOW   (BIT(3))
+
+/* ROM functions which read/write internal control bus */
+
+extern uint8_t rom_i2c_readreg(uint8_t block, uint8_t host_id,
+                               uint8_t reg_add);
+extern uint8_t rom_i2c_readreg_mask(uint8_t block, uint8_t host_id,
+                        uint8_t reg_add, uint8_t msb, uint8_t lsb);
+extern void rom_i2c_writereg(uint8_t block, uint8_t host_id,
+                             uint8_t reg_add, uint8_t data);
+extern void rom_i2c_writereg_mask(uint8_t block, uint8_t host_id,
+                   uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
+
+/* Convenience macros for the above functions, these use register
+ * definitions from regi2c_bbpll.h/regi2c_dig_reg.h/regi2c_lp_bias.h/
+ * regi2c_bias.h header files.
+ */
+
+#define REGI2C_WRITE_MASK(block, reg_add, indata) \
+      rom_i2c_writereg_mask(block, block##_HOSTID,  reg_add,  reg_add##_MSB,  reg_add##_LSB,  indata)
+
+#define REGI2C_READ_MASK(block, reg_add) \
+      rom_i2c_readreg_mask(block, block##_HOSTID,  reg_add,  reg_add##_MSB,  reg_add##_LSB)
+
+#define REGI2C_WRITE(block, reg_add, indata) \
+      rom_i2c_writereg(block, block##_HOSTID,  reg_add, indata)
+
+#define REGI2C_READ(block, reg_add) \
+      rom_i2c_readreg(block, block##_HOSTID,  reg_add)
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_CTRL_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/regi2c_dig_reg.h b/arch/risc-v/src/esp32c3/hardware/regi2c_dig_reg.h
new file mode 100644
index 0000000..027f425
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/regi2c_dig_reg.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/regi2c_dig_reg.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_DIG_REG_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_DIG_REG_H_
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register definitions for digital to get rtc voltage & digital voltage
+ * by setting rtc_dbias_Wak & dig_dbias_wak or by analog self-calibration.
+ */
+
+#define I2C_DIG_REG 0x6D
+#define I2C_DIG_REG_HOSTID 0
+
+#define I2C_DIG_REG_EXT_RTC_DREG    4
+#define I2C_DIG_REG_EXT_RTC_DREG_MSB    4
+#define I2C_DIG_REG_EXT_RTC_DREG_LSB    0
+
+#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP    5
+#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_MSB    4
+#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_LSB    0
+
+#define I2C_DIG_REG_EXT_DIG_DREG    6
+#define I2C_DIG_REG_EXT_DIG_DREG_MSB    4
+#define I2C_DIG_REG_EXT_DIG_DREG_LSB    0
+
+#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP    7
+#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_MSB    4
+#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_LSB    0
+
+#define I2C_DIG_REG_XPD_RTC_REG 13
+#define I2C_DIG_REG_XPD_RTC_REG_MSB 2
+#define I2C_DIG_REG_XPD_RTC_REG_LSB 2
+
+#define I2C_DIG_REG_XPD_DIG_REG 13
+#define I2C_DIG_REG_XPD_DIG_REG_MSB 3
+#define I2C_DIG_REG_XPD_DIG_REG_LSB 3
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_DIG_REG_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/regi2c_lp_bias.h b/arch/risc-v/src/esp32c3/hardware/regi2c_lp_bias.h
new file mode 100644
index 0000000..4029863
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/regi2c_lp_bias.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/regi2c_lp_bias.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_LP_BIAS_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_LP_BIAS_H_
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register definitions for analog to calibrate o_code for getting a more
+ * precise voltage. This file lists register fields of low power dbais,
+ * located on an internal configuration bus.
+ */
+
+#define I2C_ULP 0x61
+#define I2C_ULP_HOSTID 0
+
+#define I2C_ULP_IR_FORCE_XPD_CK 0
+#define I2C_ULP_IR_FORCE_XPD_CK_MSB 2
+#define I2C_ULP_IR_FORCE_XPD_CK_LSB 2
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_REGI2C_LP_BIAS_H_ */
diff --git a/arch/risc-v/src/esp32c3/hardware/spi_mem_reg.h b/arch/risc-v/src/esp32c3/hardware/spi_mem_reg.h
new file mode 100644
index 0000000..0e479a6
--- /dev/null
+++ b/arch/risc-v/src/esp32c3/hardware/spi_mem_reg.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * arch/risc-v/src/esp32c3/hardware/spi_mem_reg.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.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_RISCV_SRC_ESP32C3_HARDWARE_SPI_MEM_REG_H_
+#define __ARCH_RISCV_SRC_ESP32C3_HARDWARE_SPI_MEM_REG_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "esp32c3_soc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define SPI_MEM_CMD_REG(i)          (REG_SPI_MEM_BASE(i) + 0x000)
+#define SPI_MEM_CLOCK_GATE_REG(i)   (REG_SPI_MEM_BASE(i) + 0x0DC)
+
+/* SPI_MEM_CLK_EN : R/W ;bitpos:[0] ;default: 1'b1.
+ * Register clock gate enable signal. 1: Enable. 0: Disable.
+ */
+
+#define SPI_MEM_CLK_EN    (BIT(0))
+#define SPI_MEM_CLK_EN_M  (BIT(0))
+#define SPI_MEM_CLK_EN_V  0x1
+#define SPI_MEM_CLK_EN_S  0
+
+#endif /* __ARCH_RISCV_SRC_ESP32C3_HARDWARE_SPI_MEM_REG_H_ */
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig b/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
index 6259575..e26862b 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/Kconfig
@@ -5,6 +5,38 @@
 
 if ARCH_BOARD_ESP32C3_DEVKIT
 
+if PM
+
+config PM_ALARM_SEC
+	int "PM_STANDBY delay (seconds)"
+	default 15
+	depends on PM
+	---help---
+		Number of seconds to wait in PM_STANDBY before going to PM_STANDBY mode.
+
+config PM_ALARM_NSEC
+	int "PM_STANDBY delay (nanoseconds)"
+	default 0
+	depends on PM
+	---help---
+		Number of additional nanoseconds to wait in PM_STANDBY before going to PM_STANDBY mode.
+
+config PM_SLEEP_WAKEUP_SEC
+	int "PM_SLEEP delay (seconds)"
+	default 20
+	depends on PM
+	---help---
+		Number of seconds to wait in PM_SLEEP.
+
+config PM_SLEEP_WAKEUP_NSEC
+	int "PM_SLEEP delay (nanoseconds)"
+	default 0
+	depends on PM
+	---help---
+		Number of additional nanoseconds to wait in PM_SLEEP.
+
+endif # PM
+
 config ESP32C3_DEVKIT_RUN_IRAM
 	bool "Run from IRAM"
 	default n
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/pm/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/pm/defconfig
new file mode 100644
index 0000000..72139d4
--- /dev/null
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/pm/defconfig
@@ -0,0 +1,47 @@
+#
+# 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="risc-v"
+CONFIG_ARCH_BOARD="esp32c3-devkit"
+CONFIG_ARCH_BOARD_ESP32C3_DEVKIT=y
+CONFIG_ARCH_CHIP="esp32c3"
+CONFIG_ARCH_CHIP_ESP32C3=y
+CONFIG_ARCH_CHIP_ESP32C3WROOM02=y
+CONFIG_ARCH_INTERRUPTSTACK=1536
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARD_LOOPSPERMSEC=15000
+CONFIG_BUILTIN=y
+CONFIG_DEV_ZERO=y
+CONFIG_FS_PROCFS=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_MAX_TASKS=8
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_PM=y
+CONFIG_PM_GOVERNOR_EXPLICIT_RELAX=y
+CONFIG_PM_GOVERNOR_GREEDY=y
+CONFIG_PREALLOC_TIMERS=0
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=29
+CONFIG_START_MONTH=11
+CONFIG_START_YEAR=2019
+CONFIG_SYSTEM_NSH=y
+CONFIG_UART0_SERIAL_CONSOLE=y
+CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
index c4cc218..55dc5f3 100644
--- a/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
+++ b/boards/risc-v/esp32c3/esp32c3-devkit/scripts/esp32c3_rom.ld
@@ -1815,9 +1815,9 @@ rom_get_i2c_read_mask = 0x40001948;
 rom_get_pwctrl_correct = 0x4000194c;
 rom_get_rf_gain_qdb = 0x40001950;
 rom_i2c_readreg = 0x40001954;
-rom_i2c_readreg_Mask = 0x40001958;
+rom_i2c_readreg_mask = 0x40001958;
 rom_i2c_writereg = 0x4000195c;
-rom_i2c_writereg_Mask = 0x40001960;
+rom_i2c_writereg_mask = 0x40001960;
 rom_index_to_txbbgain = 0x40001964;
 rom_iq_est_disable = 0x40001968;
 rom_iq_est_enable = 0x4000196c;