Răsfoiți Sursa

esp32c6: add esp_system support

wuzhenghui 3 ani în urmă
părinte
comite
ab09c07fdd

+ 3 - 0
components/esp_system/Kconfig

@@ -91,6 +91,7 @@ menu "ESP System Settings"
         default y if IDF_TARGET_ESP32C3
         default y if IDF_TARGET_ESP32S3
         default y if IDF_TARGET_ESP32H2
+        default y if IDF_TARGET_ESP32C6
         depends on !IDF_TARGET_ESP32C2
 
     config ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
@@ -301,6 +302,7 @@ menu "ESP System Settings"
         default 1 if IDF_TARGET_ESP32
         default 20 if IDF_TARGET_ESP32C2
         default 21 if IDF_TARGET_ESP32C3
+        default 16 if IDF_TARGET_ESP32C6
         default 43
         help
              This GPIO is used for console UART TX output in the ESP-IDF Bootloader and the app (including
@@ -316,6 +318,7 @@ menu "ESP System Settings"
         default 3 if IDF_TARGET_ESP32
         default 19 if IDF_TARGET_ESP32C2
         default 20 if IDF_TARGET_ESP32C3
+        default 17 if IDF_TARGET_ESP32C6
         default 44
         help
             This GPIO is used for UART RX input in the ESP-IDF Bootloader and the app (including

+ 5 - 5
components/esp_system/crosscore_int.c

@@ -21,7 +21,7 @@
 
 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
 #include "soc/dport_reg.h"
-#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+#else
 #include "soc/system_reg.h"
 #endif
 
@@ -29,7 +29,7 @@
 #define REASON_FREQ_SWITCH      BIT(1)
 #define REASON_GDB_CALL         BIT(3)
 
-#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2
+#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2 && !IDF_TARGET_ESP32C6
 #define REASON_PRINT_BACKTRACE  BIT(2)
 #define REASON_TWDT_ABORT       BIT(4)
 #endif
@@ -66,7 +66,7 @@ static void IRAM_ATTR esp_crosscore_isr(void *arg) {
     } else {
         WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, 0);
     }
-#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
     WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
 #endif
 
@@ -145,7 +145,7 @@ static void IRAM_ATTR esp_crosscore_int_send(int core_id, uint32_t reason_mask)
     } else {
         WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_1_REG, SYSTEM_CPU_INTR_FROM_CPU_1);
     }
-#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
     WRITE_PERI_REG(SYSTEM_CPU_INTR_FROM_CPU_0_REG, SYSTEM_CPU_INTR_FROM_CPU_0);
 #endif
 }
@@ -165,7 +165,7 @@ void IRAM_ATTR esp_crosscore_int_send_gdb_call(int core_id)
     esp_crosscore_int_send(core_id, REASON_GDB_CALL);
 }
 
-#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2
+#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !IDF_TARGET_ESP32C2 && !IDF_TARGET_ESP32C6
 void IRAM_ATTR esp_crosscore_int_send_print_backtrace(int core_id)
 {
     esp_crosscore_int_send(core_id, REASON_PRINT_BACKTRACE);

+ 0 - 1
components/esp_system/esp_system.c

@@ -11,7 +11,6 @@
 #include "freertos/task.h"
 #include "esp_cpu.h"
 #include "soc/rtc.h"
-#include "soc/rtc_cntl_reg.h"
 #include "esp_private/panic_internal.h"
 #include "esp_rom_uart.h"
 #include "esp_rom_sys.h"

+ 17 - 10
components/esp_system/fpga_overrides.c

@@ -9,7 +9,21 @@
 #include "soc/system_reg.h"
 #endif // not CONFIG_IDF_TARGET_ESP32
 #include "soc/rtc.h"
-#include "soc/rtc_cntl_reg.h"
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32C3
+#include "esp32c3/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32C2
+#include "esp32c2/rom/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32C6
+#include "esp32c6/rom/rtc.h"
+#endif
 #include "esp_log.h"
 #include "esp_rom_sys.h"
 #include "esp_rom_uart.h"
@@ -17,13 +31,6 @@
 
 static const char *TAG = "fpga";
 
-#ifdef CONFIG_IDF_TARGET_ESP32
-#include "esp32/rom/rtc.h"
-#endif
-#ifdef CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/rom/rtc.h"
-#endif
-
 extern void ets_update_cpu_frequency(uint32_t ticks_per_us);
 
 static void s_warn(void)
@@ -42,13 +49,13 @@ void bootloader_clock_configure(void)
 #elif CONFIG_IDF_TARGET_ESP32H2
     uint32_t apb_freq_hz = 32000000;
 #else
-    uint32_t apb_freq_hz = 40000000;
+    uint32_t apb_freq_hz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000;
 #endif // CONFIG_IDF_TARGET_ESP32S2
     ets_update_cpu_frequency(apb_freq_hz / 1000000);
 #ifdef RTC_APB_FREQ_REG
     REG_WRITE(RTC_APB_FREQ_REG, (apb_freq_hz >> 12) | ((apb_freq_hz >> 12) << 16));
 #endif
-    REG_WRITE(RTC_CNTL_STORE4_REG, (xtal_freq_mhz) | ((xtal_freq_mhz) << 16));
+    REG_WRITE(RTC_XTAL_FREQ_REG, (xtal_freq_mhz) | ((xtal_freq_mhz) << 16));
 }
 
 /* Placed in IRAM since test_apps expects it to be */

+ 1 - 1
components/esp_system/include/esp_private/crosscore_int.h

@@ -50,7 +50,7 @@ void esp_crosscore_int_send_freq_switch(int core_id);
 
 void esp_crosscore_int_send_gdb_call(int core_id);
 
-#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C2
+#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C2 && !CONFIG_IDF_TARGET_ESP32C6
 /**
  * Send an interrupt to a CPU indicating it should print its current backtrace
  *

+ 149 - 0
components/esp_system/ld/esp32c6/memory.ld.in

@@ -0,0 +1,149 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ *                    ESP32-C6 Linker Script Memory Layout
+ * This file describes the memory layout (memory blocks) by virtual memory addresses.
+ * This linker script is passed through the C preprocessor to include configuration options.
+ * Please use preprocessor features sparingly!
+ * Restrict to simple macros with numeric values, and/or #if/#endif blocks.
+ */
+
+#include "sdkconfig.h"
+#include "ld.common"
+
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
+#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
+#else
+#define ESP_BOOTLOADER_RESERVE_RTC 0
+#endif
+
+/**
+ * physical memory is mapped twice to the vritual address (IRAM and DRAM).
+ * `I_D_SRAM_OFFSET` is the offset between the two locations of the same physical memory
+ */
+#define SRAM_IRAM_START     0x40800000
+#define SRAM_DRAM_START     0x40800000
+
+#define I_D_SRAM_OFFSET     (SRAM_IRAM_START - SRAM_DRAM_START)
+#define SRAM_DRAM_END       0x40880000 - I_D_SRAM_OFFSET  /* 2nd stage bootloader iram_loader_seg start address */
+
+#define SRAM_IRAM_ORG       (SRAM_IRAM_START)
+#define SRAM_DRAM_ORG       (SRAM_DRAM_START)
+
+#define I_D_SRAM_SIZE       SRAM_DRAM_END - SRAM_DRAM_ORG
+
+#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+/*
+ * IDRAM0_2_SEG_SIZE_DEFAULT is used when page size is 64KB
+ */
+#define IDRAM0_2_SEG_SIZE   (CONFIG_MMU_PAGE_SIZE << 8)
+#endif
+
+#if CONFIG_ESP32C6_USE_FIXED_STATIC_RAM_SIZE
+ASSERT((CONFIG_ESP32C6_FIXED_STATIC_RAM_SIZE <= I_D_SRAM_SIZE), "Fixed static ram data does not fit.")
+#define DRAM0_0_SEG_LEN CONFIG_ESP3C6_FIXED_STATIC_RAM_SIZE
+#else
+#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
+#endif // CONFIG_ESP32C6_USE_FIXED_STATIC_RAM_SIZE
+MEMORY
+{
+  /**
+   *  All these values assume the flash cache is on, and have the blocks this uses subtracted from the length
+   *  of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but
+   *  are connected to the data port of the CPU and eg allow byte-wise access.
+   */
+
+  /* IRAM for PRO CPU. */
+  iram0_0_seg (RX) :                 org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
+
+#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+  /* Flash mapped instruction data */
+  iram0_2_seg (RX) :                 org = 0x42000020, len = (IDRAM0_2_SEG_SIZE >> 1) -0x20
+
+  /**
+   * (0x20 offset above is a convenience for the app binary image generation.
+   * Flash cache has 64KB pages. The .bin file which is flashed to the chip
+   * has a 0x18 byte file header, and each segment has a 0x08 byte segment
+   * header. Setting this offset makes it simple to meet the flash cache MMU's
+   * constraint that (paddr % 64KB == vaddr % 64KB).)
+   */
+#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+
+  /**
+   * Shared data RAM, excluding memory reserved for ROM bss/data/stack.
+   * Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available.
+   */
+  dram0_0_seg (RW) :                 org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
+
+#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+  /* Flash mapped constant data */
+  drom0_0_seg (R) :                  org = 0x42000020 + (IDRAM0_2_SEG_SIZE >> 1), len = (IDRAM0_2_SEG_SIZE >> 1)-0x20
+
+  /* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
+#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+
+  /**
+   * lp ram memory (RWX). Persists over deep sleep. // TODO: IDF-5667
+   */
+#if CONFIG_ULP_COPROC_ENABLED
+  lp_ram_seg(RW)  :                 org = 0x50000000 + CONFIG_ULP_COPROC_RESERVE_MEM,
+                                    len = 0x4000 - CONFIG_ULP_COPROC_RESERVE_MEM
+#else
+  lp_ram_seg(RW)  :                 org = 0x50000000 , len = 0x4000
+#endif // CONFIG_ULP_COPROC_ENABLED
+
+}
+
+#if CONFIG_ESP32C6_USE_FIXED_STATIC_RAM_SIZE
+/* static data ends at defined address */
+_static_data_end = 0x40820000 + DRAM0_0_SEG_LEN;
+#else
+_static_data_end = _bss_end;
+#endif // CONFIG_ESP32C6_USE_FIXED_STATIC_RAM_SIZE
+
+/* Heap ends at top of dram0_0_seg */
+_heap_end = 0x40000000;
+
+_data_seg_org = ORIGIN(rtc_data_seg);
+
+/**
+ *  The lines below define location alias for .rtc.data section
+ *  C6 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section
+ *  Thus, the following region segments are not configurable like on other targets
+ */
+REGION_ALIAS("rtc_iram_seg", lp_ram_seg );
+REGION_ALIAS("rtc_data_seg", rtc_iram_seg );
+REGION_ALIAS("rtc_slow_seg", rtc_iram_seg );
+REGION_ALIAS("rtc_data_location", rtc_iram_seg );
+
+#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+  REGION_ALIAS("default_code_seg", iram0_2_seg);
+#else
+  REGION_ALIAS("default_code_seg", iram0_0_seg);
+#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+
+#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+  REGION_ALIAS("default_rodata_seg", drom0_0_seg);
+#else
+  REGION_ALIAS("default_rodata_seg", dram0_0_seg);
+#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+
+/**
+ *  If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must
+ *  also be first in the segment.
+ */
+#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+  ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg),
+         ".flash_rodata_dummy section must be placed at the beginning of the rodata segment.")
+#endif
+
+#if CONFIG_ESP_SYSTEM_USE_EH_FRAME
+    ASSERT ((__eh_frame_end > __eh_frame), "Error: eh_frame size is null!");
+    ASSERT ((__eh_frame_hdr_end > __eh_frame_hdr), "Error: eh_frame_hdr size is null!");
+#endif

+ 410 - 0
components/esp_system/ld/esp32c6/sections.ld.in

@@ -0,0 +1,410 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* Default entry point */
+ENTRY(call_start_cpu0);
+
+SECTIONS
+{
+  /**
+   * RTC fast memory holds RTC wake stub code,
+   * including from any source file named rtc_wake_stub*.c
+   */
+  .rtc.text :
+  {
+    . = ALIGN(4);
+    _rtc_fast_start = ABSOLUTE(.);
+
+    mapping[rtc_text]
+
+    *rtc_wake_stub*.*(.literal .text .literal.* .text.*)
+    *(.rtc_text_end_test)
+
+    /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */
+    . += _esp_memprot_prefetch_pad_size;
+    . = ALIGN(4);
+
+    _rtc_text_end = ABSOLUTE(.);
+  } > lp_ram_seg
+
+  /**
+   * This section located in RTC FAST Memory area.
+   * It holds data marked with RTC_FAST_ATTR attribute.
+   * See the file "esp_attr.h" for more information.
+   */
+  .rtc.force_fast :
+  {
+    . = ALIGN(4);
+    _rtc_force_fast_start = ABSOLUTE(.);
+
+    mapping[rtc_force_fast]
+
+    *(.rtc.force_fast .rtc.force_fast.*)
+    . = ALIGN(4) ;
+    _rtc_force_fast_end = ABSOLUTE(.);
+  } > lp_ram_seg
+
+  /**
+   * RTC data section holds RTC wake stub
+   * data/rodata, including from any source file
+   * named rtc_wake_stub*.c and the data marked with
+   * RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
+   */
+  .rtc.data :
+  {
+    _rtc_data_start = ABSOLUTE(.);
+
+    mapping[rtc_data]
+
+    *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
+    _rtc_data_end = ABSOLUTE(.);
+  } > lp_ram_seg
+
+  /* RTC bss, from any source file named rtc_wake_stub*.c */
+  .rtc.bss (NOLOAD) :
+  {
+    _rtc_bss_start = ABSOLUTE(.);
+    *rtc_wake_stub*.*(.bss .bss.*)
+    *rtc_wake_stub*.*(COMMON)
+
+    mapping[rtc_bss]
+
+    _rtc_bss_end = ABSOLUTE(.);
+  } > lp_ram_seg
+
+  /**
+   * This section holds data that should not be initialized at power up
+   * and will be retained during deep sleep.
+   * User data marked with RTC_NOINIT_ATTR will be placed
+   * into this section. See the file "esp_attr.h" for more information.
+   */
+  .rtc_noinit (NOLOAD):
+  {
+    . = ALIGN(4);
+    _rtc_noinit_start = ABSOLUTE(.);
+    *(.rtc_noinit .rtc_noinit.*)
+    . = ALIGN(4) ;
+    _rtc_noinit_end = ABSOLUTE(.);
+  } > lp_ram_seg
+
+  /**
+   * This section located in RTC SLOW Memory area.
+   * It holds data marked with RTC_SLOW_ATTR attribute.
+   * See the file "esp_attr.h" for more information.
+   */
+  .rtc.force_slow :
+  {
+    . = ALIGN(4);
+    _rtc_force_slow_start = ABSOLUTE(.);
+    *(.rtc.force_slow .rtc.force_slow.*)
+    . = ALIGN(4) ;
+    _rtc_force_slow_end = ABSOLUTE(.);
+  } > lp_ram_seg
+
+  /* Get size of rtc slow data based on rtc_data_location alias */
+  _rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
+                        ? (_rtc_force_slow_end - _rtc_data_start)
+                        : (_rtc_force_slow_end - _rtc_force_slow_start);
+
+  _rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
+                        ? (_rtc_force_fast_end - _rtc_fast_start)
+                        : (_rtc_noinit_end - _rtc_fast_start);
+
+  ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
+          "RTC_SLOW segment data does not fit.")
+
+  ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
+          "RTC_FAST segment data does not fit.")
+
+  .iram0.text :
+  {
+    _iram_start = ABSOLUTE(.);
+    /* Vectors go to start of IRAM */
+    ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
+    KEEP(*(.exception_vectors.text));
+    . = ALIGN(4);
+
+    _invalid_pc_placeholder = ABSOLUTE(.);
+
+    /* Code marked as running out of IRAM */
+    _iram_text_start = ABSOLUTE(.);
+
+    mapping[iram0_text]
+
+  } > iram0_0_seg
+
+  /* Marks the end of IRAM code segment */
+  .iram0.text_end (NOLOAD) :
+  {
+    /* ESP32-C6 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */
+    . += _esp_memprot_prefetch_pad_size;
+    . = ALIGN(_esp_memprot_align_size);
+    /* iram_end_test section exists for use by memprot unit tests only */
+    *(.iram_end_test)
+    _iram_text_end = ABSOLUTE(.);
+  } > iram0_0_seg
+
+  .iram0.data :
+  {
+    . = ALIGN(16);
+    _iram_data_start = ABSOLUTE(.);
+
+    mapping[iram0_data]
+
+    _iram_data_end = ABSOLUTE(.);
+  } > iram0_0_seg
+
+  .iram0.bss (NOLOAD) :
+  {
+    . = ALIGN(16);
+    _iram_bss_start = ABSOLUTE(.);
+
+    mapping[iram0_bss]
+
+    _iram_bss_end = ABSOLUTE(.);
+    . = ALIGN(16);
+    _iram_end = ABSOLUTE(.);
+  } > iram0_0_seg
+
+  /**
+   * This section is required to skip .iram0.text area because iram0_0_seg and
+   * dram0_0_seg reflect the same address space on different buses.
+   */
+  .dram0.dummy (NOLOAD):
+  {
+    . = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
+  } > dram0_0_seg
+
+  .dram0.data :
+  {
+    _data_start = ABSOLUTE(.);
+    *(.gnu.linkonce.d.*)
+    *(.data1)
+    __global_pointer$ = . + 0x800;
+    *(.sdata)
+    *(.sdata.*)
+    *(.gnu.linkonce.s.*)
+    *(.gnu.linkonce.s2.*)
+    *(.jcr)
+
+    mapping[dram0_data]
+
+    _data_end = ABSOLUTE(.);
+    . = ALIGN(4);
+  } > dram0_0_seg
+
+  /**
+   * This section holds data that should not be initialized at power up.
+   * The section located in Internal SRAM memory region. The macro _NOINIT
+   * can be used as attribute to place data into this section.
+   * See the "esp_attr.h" file for more information.
+   */
+  .noinit (NOLOAD):
+  {
+    . = ALIGN(4);
+    _noinit_start = ABSOLUTE(.);
+    *(.noinit .noinit.*)
+    . = ALIGN(4) ;
+    _noinit_end = ABSOLUTE(.);
+  } > dram0_0_seg
+
+  /* Shared RAM */
+  .dram0.bss (NOLOAD) :
+  {
+    . = ALIGN (8);
+    _bss_start = ABSOLUTE(.);
+
+    mapping[dram0_bss]
+
+    *(.dynsbss)
+    *(.sbss)
+    *(.sbss.*)
+    *(.gnu.linkonce.sb.*)
+    *(.scommon)
+    *(.sbss2)
+    *(.sbss2.*)
+    *(.gnu.linkonce.sb2.*)
+    *(.dynbss)
+    *(.share.mem)
+    *(.gnu.linkonce.b.*)
+
+    . = ALIGN (8);
+    _bss_end = ABSOLUTE(.);
+  } > dram0_0_seg
+
+  ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
+
+  .flash.text :
+  {
+    _stext = .;
+    _instruction_reserved_start = ABSOLUTE(.);
+    _text_start = ABSOLUTE(.);
+
+    mapping[flash_text]
+
+    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+    *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
+    *(.fini.literal)
+    *(.fini)
+    *(.gnu.version)
+
+    /** CPU will try to prefetch up to 16 bytes of
+      * of instructions. This means that any configuration (e.g. MMU, PMS) must allow
+      * safe access to up to 16 bytes after the last real instruction, add
+      * dummy bytes to ensure this
+      */
+    . += _esp_flash_mmap_prefetch_pad_size;
+
+    _text_end = ABSOLUTE(.);
+    _instruction_reserved_end = ABSOLUTE(.);
+    _etext = .;
+
+    /**
+     * Similar to _iram_start, this symbol goes here so it is
+     * resolved by addr2line in preference to the first symbol in
+     * the flash.text segment.
+     */
+    _flash_cache_start = ABSOLUTE(0);
+  } > default_code_seg
+
+  /**
+   * This dummy section represents the .flash.text section but in default_rodata_seg.
+   * Thus, it must have its alignment and (at least) its size.
+   */
+  .flash_rodata_dummy (NOLOAD):
+  {
+    _flash_rodata_dummy_start = .;
+    /* Start at the same alignment constraint than .flash.text */
+    . = ALIGN(ALIGNOF(.flash.text));
+    /* Create an empty gap as big as .flash.text section */
+    . = . + SIZEOF(.flash.text);
+    /* Prepare the alignment of the section above. Few bytes (0x20) must be
+     * added for the mapping header. */
+    . = ALIGN(0x10000) + 0x20;
+    _rodata_reserved_start = .;
+  } > default_rodata_seg
+
+  .flash.appdesc : ALIGN(0x10)
+  {
+    _rodata_start = ABSOLUTE(.);
+
+    *(.rodata_desc .rodata_desc.*)               /* Should be the first.  App version info.        DO NOT PUT ANYTHING BEFORE IT! */
+    *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
+
+    /* Create an empty gap within this section. Thanks to this, the end of this
+     * section will match .flash.rodata's begin address. Thus, both sections
+     * will be merged when creating the final bin image. */
+    . = ALIGN(ALIGNOF(.flash.rodata));
+  } >default_rodata_seg
+
+  .flash.rodata : ALIGN(0x10)
+  {
+    _flash_rodata_start = ABSOLUTE(.);
+
+    mapping[flash_rodata]
+
+    *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
+    *(.gnu.linkonce.r.*)
+    *(.rodata1)
+    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+    *(.xt_except_table)
+    *(.gcc_except_table .gcc_except_table.*)
+    *(.gnu.linkonce.e.*)
+    *(.gnu.version_r)
+    . = (. + 7) & ~ 3;
+    /*
+     * C++ constructor and destructor tables
+     * Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt.
+     *
+     * RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead.
+     * But the init_priority sections will be sorted for iteration in ascending order during startup.
+     * The rest of the init_array sections is sorted for iteration in descending order during startup, however.
+     * Hence a different section is generated for the init_priority functions which is iterated in
+     * ascending order during startup. The corresponding code can be found in startup.c.
+     */
+    __init_priority_array_start = ABSOLUTE(.);
+    KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))
+    __init_priority_array_end = ABSOLUTE(.);
+    __init_array_start = ABSOLUTE(.);
+    KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array))
+    __init_array_end = ABSOLUTE(.);
+    KEEP (*crtbegin.*(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+    /* C++ exception handlers table: */
+    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
+    *(.xt_except_desc)
+    *(.gnu.linkonce.h.*)
+    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
+    *(.xt_except_desc_end)
+    *(.dynamic)
+    *(.gnu.version_d)
+    /* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */
+    soc_reserved_memory_region_start = ABSOLUTE(.);
+    KEEP (*(.reserved_memory_address))
+    soc_reserved_memory_region_end = ABSOLUTE(.);
+    /* System init functions registered via ESP_SYSTEM_INIT_FN */
+    _esp_system_init_fn_array_start = ABSOLUTE(.);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*)))
+    _esp_system_init_fn_array_end = ABSOLUTE(.);
+    _rodata_end = ABSOLUTE(.);
+    /* Literals are also RO data. */
+    _lit4_start = ABSOLUTE(.);
+    *(*.lit4)
+    *(.lit4.*)
+    *(.gnu.linkonce.lit4.*)
+    _lit4_end = ABSOLUTE(.);
+    . = ALIGN(4);
+    _thread_local_start = ABSOLUTE(.);
+    *(.tdata)
+    *(.tdata.*)
+    *(.tbss)
+    *(.tbss.*)
+    _thread_local_end = ABSOLUTE(.);
+    _rodata_reserved_end = ABSOLUTE(.);
+    . = ALIGN(ALIGNOF(.eh_frame));
+  } > default_rodata_seg
+
+  /* Keep this section shall be at least aligned on 4 */
+  .eh_frame : ALIGN(8)
+  {
+    __eh_frame = ABSOLUTE(.);
+    KEEP (*(.eh_frame))
+    __eh_frame_end = ABSOLUTE(.);
+    /* Guarantee that this section and the next one will be merged by making
+     * them adjacent. */
+    . = ALIGN(ALIGNOF(.eh_frame_hdr));
+  } > default_rodata_seg
+
+  /* To avoid any exception in C++ exception frame unwinding code, this section
+   * shall be aligned on 8. */
+  .eh_frame_hdr : ALIGN(8)
+  {
+    __eh_frame_hdr = ABSOLUTE(.);
+    KEEP (*(.eh_frame_hdr))
+    __eh_frame_hdr_end = ABSOLUTE(.);
+  } > default_rodata_seg
+
+  .flash.rodata_noload (NOLOAD) :
+  {
+    . = ALIGN (4);
+    mapping[rodata_noload]
+  } > default_rodata_seg
+
+  /* Marks the end of data, bss and possibly rodata  */
+  .dram0.heap_start (NOLOAD) :
+  {
+    . = ALIGN (16);
+    _heap_start = ABSOLUTE(.);
+  } > dram0_0_seg
+}
+
+ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
+          "IRAM0 segment data does not fit.")
+
+ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
+          "DRAM segment data does not fit.")

+ 4 - 0
components/esp_system/panic.c

@@ -61,7 +61,11 @@
 bool g_panic_abort = false;
 static char *s_panic_abort_details = NULL;
 
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5653
+static wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &LP_WDT};
+#else
 static wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
+#endif
 
 #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
 

+ 2 - 0
components/esp_system/port/arch/riscv/panic_arch.c

@@ -76,6 +76,7 @@ static inline bool test_and_print_register_bits(const uint32_t status,
  */
 static inline void print_cache_err_details(const void *frame)
 {
+#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5657
     /* Define the array that contains the status (bits) to test on the register
      * EXTMEM_CORE0_ACS_CACHE_INT_ST_REG. each bit is accompanied by a small
      * message.
@@ -148,6 +149,7 @@ static inline void print_cache_err_details(const void *frame)
             panic_print_str("\r\n");
         }
     }
+#endif
 }
 
 

+ 4 - 0
components/esp_system/port/brownout.c

@@ -76,7 +76,11 @@ void esp_brownout_init(void)
 
     brownout_hal_config(&cfg);
     brownout_hal_intr_clear();
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
+    rtc_isr_register(rtc_brownout_isr_handler, NULL, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_ENA_M, RTC_INTR_FLAG_IRAM);
+#else
     rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM);
+#endif
     brownout_hal_intr_enable(true);
 
 #else // brownout without interrupt

+ 11 - 3
components/esp_system/port/cpu_start.c

@@ -47,6 +47,10 @@
 #include "esp32c3/rom/cache.h"
 #include "esp32c3/rom/secure_boot.h"
 #include "esp_memprot.h"
+#elif CONFIG_IDF_TARGET_ESP32C6
+#include "esp32c6/rtc.h"
+#include "esp32c6/rom/cache.h"
+#include "esp_memprot.h"
 #elif CONFIG_IDF_TARGET_ESP32H2
 #include "esp32h2/rtc.h"
 #include "esp32h2/rom/cache.h"
@@ -287,7 +291,11 @@ void IRAM_ATTR call_start_cpu0(void)
             || rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0
 #endif
        ) {
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5653
+        wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &LP_WDT};
+#else
         wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
+#endif
         wdt_hal_write_protect_disable(&rtc_wdt_ctx);
         wdt_hal_disable(&rtc_wdt_ctx);
         wdt_hal_write_protect_enable(&rtc_wdt_ctx);
@@ -341,7 +349,7 @@ void IRAM_ATTR call_start_cpu0(void)
         esp_restart();
     }
 
-#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
     /* Configure the Cache MMU size for instruction and rodata in flash. */
     extern uint32_t Cache_Set_IDROM_MMU_Size(uint32_t irom_size, uint32_t drom_size);
     extern int _rodata_reserved_start;
@@ -354,7 +362,7 @@ void IRAM_ATTR call_start_cpu0(void)
 #endif
 
     Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
-#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2
+#endif // CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C6
 
 #if CONFIG_ESPTOOLPY_OCT_FLASH
     bool efuse_opflash_en = efuse_ll_get_flash_type();
@@ -473,7 +481,7 @@ void IRAM_ATTR call_start_cpu0(void)
 #endif
 
 #if CONFIG_IDF_TARGET_ESP32C2
-// TODO : IDF-4194
+// TODO : IDF-5020
 #if CONFIG_ESP32C2_INSTRUCTION_CACHE_WRAP
     extern void esp_enable_cache_wrap(uint32_t icache_wrap_enable);
     esp_enable_cache_wrap(1);

+ 12 - 0
components/esp_system/port/soc/esp32c6/CMakeLists.txt

@@ -0,0 +1,12 @@
+set(srcs "clk.c"
+         "reset_reason.c"
+         "system_internal.c"
+         "cache_err_int.c"
+         "../../arch/riscv/expression_with_stack.c"
+         "../../arch/riscv/expression_with_stack_asm.S"
+         "../../arch/riscv/panic_arch.c"
+         "../../arch/riscv/debug_stubs.c")
+
+add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
+
+target_sources(${COMPONENT_LIB} PRIVATE ${srcs})

+ 21 - 0
components/esp_system/port/soc/esp32c6/Kconfig.cpu

@@ -0,0 +1,21 @@
+choice ESP_DEFAULT_CPU_FREQ_MHZ
+    prompt "CPU frequency"
+    default ESP_DEFAULT_CPU_FREQ_MHZ_40 if IDF_ENV_FPGA
+    default ESP_DEFAULT_CPU_FREQ_MHZ_160
+    help
+        CPU frequency to be set on application startup.
+
+    config ESP_DEFAULT_CPU_FREQ_MHZ_40
+        bool "40 MHz"
+        depends on IDF_ENV_FPGA
+    config ESP_DEFAULT_CPU_FREQ_MHZ_80
+        bool "80 MHz"
+    config ESP_DEFAULT_CPU_FREQ_MHZ_160
+        bool "160 MHz"
+endchoice
+
+config ESP_DEFAULT_CPU_FREQ_MHZ
+    int
+    default 40 if ESP_DEFAULT_CPU_FREQ_MHZ_40
+    default 80 if ESP_DEFAULT_CPU_FREQ_MHZ_80
+    default 160 if ESP_DEFAULT_CPU_FREQ_MHZ_160

+ 45 - 0
components/esp_system/port/soc/esp32c6/Kconfig.system

@@ -0,0 +1,45 @@
+menu "Brownout Detector"
+    config ESP_BROWNOUT_DET
+        bool "Hardware brownout detect & reset"
+        depends on !IDF_ENV_FPGA
+        default y
+        help
+            The ESP32-C6 has a built-in brownout detector which can detect if the voltage is lower than
+            a specific value. If this happens, it will reset the chip in order to prevent unintended
+            behaviour.
+
+    choice ESP_BROWNOUT_DET_LVL_SEL
+        prompt "Brownout voltage level"
+        depends on ESP_BROWNOUT_DET
+        default ESP_BROWNOUT_DET_LVL_SEL_7
+        help
+            The brownout detector will reset the chip when the supply voltage is approximately
+            below this level. Note that there may be some variation of brownout voltage level
+            between each chip.
+
+            #The voltage levels here are estimates, more work needs to be done to figure out the exact voltages
+            #of the brownout threshold levels.
+        config ESP_BROWNOUT_DET_LVL_SEL_7
+            bool "2.51V"
+        config ESP_BROWNOUT_DET_LVL_SEL_6
+            bool "2.64V"
+        config ESP_BROWNOUT_DET_LVL_SEL_5
+            bool "2.76V"
+        config ESP_BROWNOUT_DET_LVL_SEL_4
+            bool "2.92V"
+        config ESP_BROWNOUT_DET_LVL_SEL_3
+            bool "3.10V"
+        config ESP_BROWNOUT_DET_LVL_SEL_2
+            bool "3.27V"
+    endchoice
+
+    config ESP_BROWNOUT_DET_LVL
+        int
+        default 2 if ESP_BROWNOUT_DET_LVL_SEL_2
+        default 3 if ESP_BROWNOUT_DET_LVL_SEL_3
+        default 4 if ESP_BROWNOUT_DET_LVL_SEL_4
+        default 5 if ESP_BROWNOUT_DET_LVL_SEL_5
+        default 6 if ESP_BROWNOUT_DET_LVL_SEL_6
+        default 7 if ESP_BROWNOUT_DET_LVL_SEL_7
+
+endmenu

+ 81 - 0
components/esp_system/port/soc/esp32c6/cache_err_int.c

@@ -0,0 +1,81 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/*
+ The cache has an interrupt that can be raised as soon as an access to a cached
+ region (flash) is done without the cache being enabled. We use that here
+ to panic the CPU, which from a debugging perspective is better than grabbing bad
+ data from the bus.
+*/
+#include "esp_rom_sys.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_intr_alloc.h"
+#include "soc/periph_defs.h"
+#include "riscv/interrupt.h"
+#include "hal/cache_ll.h"
+
+static const char *TAG = "CACHE_ERR";
+
+void esp_cache_err_int_init(void)
+{
+    ESP_EARLY_LOGW(TAG, "esp_cache_err_int_init() has not been implemented yet");
+#if 0 // TODO: IDF-5656
+    const uint32_t core_id = 0;
+
+    /* Disable cache interrupts if enabled. */
+    ESP_INTR_DISABLE(ETS_CACHEERR_INUM);
+
+    /**
+     *  Bind all cache errors to ETS_CACHEERR_INUM interrupt. we will deal with
+     * them in handler by different types
+     * I) Cache access error
+     *     1. dbus trying to write to icache
+     *     2. dbus authentication fail
+     *     3. cpu access icache while dbus is disabled [1]
+     *     4. ibus authentication fail
+     *     5. ibus trying to write icache
+     *     6. cpu access icache while ibus is disabled
+     * II) Cache illegal error
+     *     1. dbus counter overflow
+     *     2. ibus counter overflow
+     *     3. mmu entry fault
+     *     4. icache preload configurations fault
+     *     5. icache sync configuration fault
+     *
+     * [1]: On ESP32C6 boards, the caches are shared but buses are still
+     * distinct. So, we have an ibus and a dbus sharing the same cache.
+     * This error can occur if the dbus performs a request but the icache
+     * (or simply cache) is disabled.
+     */
+    esp_rom_route_intr_matrix(core_id, ETS_CACHE_IA_INTR_SOURCE, ETS_CACHEERR_INUM);
+    esp_rom_route_intr_matrix(core_id, ETS_CACHE_CORE0_ACS_INTR_SOURCE, ETS_CACHEERR_INUM);
+
+    /* Set the type and priority to cache error interrupts. */
+    esprv_intc_int_set_type(BIT(ETS_CACHEERR_INUM), INTR_TYPE_LEVEL);
+    esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
+
+    ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
+    /* On the hardware side, start by clearing all the bits reponsible for cache access error */
+    cache_ll_l1_clear_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
+    /* Then enable cache access error interrupts. */
+    cache_ll_l1_enable_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
+
+    /* Same goes for cache illegal error: start by clearing the bits and then
+    * set them back. */
+    ESP_DRAM_LOGV(TAG, "illegal error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ILG_EVENT_MASK);
+    cache_ll_l1_clear_illegal_error_intr(0, CACHE_LL_L1_ILG_EVENT_MASK);
+    cache_ll_l1_enable_illegal_error_intr(0, CACHE_LL_L1_ILG_EVENT_MASK);
+
+    /* Enable the interrupts for cache error. */
+    ESP_INTR_ENABLE(ETS_CACHEERR_INUM);
+#endif
+}
+
+int IRAM_ATTR esp_cache_err_get_cpuid(void)
+{
+    return 0;
+}

+ 305 - 0
components/esp_system/port/soc/esp32c6/clk.c

@@ -0,0 +1,305 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include "sdkconfig.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_clk_internal.h"
+#include "esp32c6/rom/ets_sys.h"
+#include "esp32c6/rom/uart.h"
+// #include "soc/system_reg.h"
+#include "soc/soc.h"
+#include "soc/rtc.h"
+#include "soc/rtc_periph.h"
+#include "soc/i2s_reg.h"
+#include "esp_cpu.h"
+#include "hal/wdt_hal.h"
+#include "esp_private/periph_ctrl.h"
+#include "esp_private/esp_clk.h"
+#include "bootloader_clock.h"
+// #include "soc/syscon_reg.h"
+#include "esp_rom_uart.h"
+#include "esp_rom_sys.h"
+
+/* 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     CONFIG_RTC_CLK_CAL_CYCLES
+
+#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
+
+/* Indicates that this 32k oscillator gets input from external oscillator, rather
+ * than a crystal.
+ */
+#define EXT_OSC_FLAG    BIT(3)
+
+/* This is almost the same as soc_rtc_slow_clk_src_t, except that we define
+ * an extra enum member for the external 32k oscillator.
+ * For convenience, lower 2 bits should correspond to soc_rtc_slow_clk_src_t values.
+ */
+typedef enum {
+    SLOW_CLK_RTC = SOC_RTC_SLOW_CLK_SRC_RC_SLOW,                       //!< Internal 150 kHz RC oscillator
+    SLOW_CLK_32K_XTAL = SOC_RTC_SLOW_CLK_SRC_XTAL32K,                  //!< External 32 kHz XTAL
+    SLOW_CLK_8MD256 = SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256,               //!< Internal 8 MHz RC oscillator, divided by 256
+    SLOW_CLK_32K_EXT_OSC = SOC_RTC_SLOW_CLK_SRC_XTAL32K | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin
+} slow_clk_sel_t;
+
+static void select_rtc_slow_clk(slow_clk_sel_t slow_clk);
+
+static const char *TAG = "clk";
+
+
+ __attribute__((weak)) void esp_clk_init(void)
+{
+#if !CONFIG_IDF_ENV_FPGA
+    rtc_config_t cfg = RTC_CONFIG_DEFAULT();
+    soc_reset_reason_t rst_reas;
+    rst_reas = esp_rom_get_reset_reason(0);
+    if (rst_reas == RESET_REASON_CHIP_POWER_ON) {
+        cfg.cali_ocode = 1;
+    }
+    rtc_init(cfg);
+
+    assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M);
+
+    bool rc_fast_d256_is_enabled = rtc_clk_8md256_enabled();
+    rtc_clk_8m_enable(true, rc_fast_d256_is_enabled);
+    rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST);
+#endif
+
+#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
+    // WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
+    // If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times.
+    // Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
+    // This prevents excessive delay before resetting in case the supply voltage is drawdown.
+    // (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec).
+    wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &LP_WDT}; // TODO: IDF-5653
+    uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
+    wdt_hal_write_protect_disable(&rtc_wdt_ctx);
+    wdt_hal_feed(&rtc_wdt_ctx);
+    //Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same
+    wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
+    wdt_hal_write_protect_enable(&rtc_wdt_ctx);
+#endif
+
+#if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS)
+    select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
+#elif defined(CONFIG_RTC_CLK_SRC_EXT_OSC)
+    select_rtc_slow_clk(SLOW_CLK_32K_EXT_OSC);
+#elif defined(CONFIG_RTC_CLK_SRC_INT_8MD256)
+    select_rtc_slow_clk(SLOW_CLK_8MD256);
+#else
+    select_rtc_slow_clk(SLOW_CLK_RTC);
+#endif
+
+#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
+    // After changing a frequency WDT timeout needs to be set for new frequency.
+    stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000);
+    wdt_hal_write_protect_disable(&rtc_wdt_ctx);
+    wdt_hal_feed(&rtc_wdt_ctx);
+    wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
+    wdt_hal_write_protect_enable(&rtc_wdt_ctx);
+#endif
+
+    rtc_cpu_freq_config_t old_config, new_config;
+    rtc_clk_cpu_freq_get_config(&old_config);
+    const uint32_t old_freq_mhz = old_config.freq_mhz;
+    const uint32_t new_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
+
+    bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config);
+    assert(res);
+
+    // Wait for UART TX to finish, otherwise some UART output will be lost
+    // when switching APB frequency
+    esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
+
+    if (res)  {
+        rtc_clk_cpu_freq_set_config(&new_config);
+    }
+
+    // Re calculate the ccount to make time calculation correct.
+    esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz );
+}
+
+static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
+{
+    ESP_EARLY_LOGW(TAG, "select_rtc_slow_clk() has not been implemented yet");
+#if 0 // TODO: IDF-5645
+    soc_rtc_slow_clk_src_t rtc_slow_clk_src = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
+    uint32_t cal_val = 0;
+    /* number of times to repeat 32k XTAL calibration
+     * before giving up and switching to the internal RC
+     */
+    int retry_32k_xtal = 3;
+
+    do {
+        if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
+            /* 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.
+             */
+            ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
+            if (slow_clk == SLOW_CLK_32K_XTAL) {
+                rtc_clk_32k_enable(true);
+            } else if (slow_clk == SLOW_CLK_32K_EXT_OSC) {
+                rtc_clk_32k_enable_external();
+            }
+            // When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
+            if (SLOW_CLK_CAL_CYCLES > 0) {
+                cal_val = 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;
+                    }
+                    ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 150 kHz oscillator");
+                    rtc_slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW;
+                }
+            }
+        } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
+            rtc_clk_8m_enable(true, true);
+        }
+        rtc_clk_slow_src_set(rtc_slow_clk_src);
+
+        if (SLOW_CLK_CAL_CYCLES > 0) {
+            /* TODO: 32k XTAL oscillator has some frequency drift at startup.
+             * Improve calibration routine to wait until the frequency is stable.
+             */
+            cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
+        } else {
+            const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
+            cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
+        }
+    } while (cal_val == 0);
+    ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
+    esp_clk_slowclk_cal_set(cal_val);
+#endif
+}
+
+void rtc_clk_select_rtc_slow_clk(void)
+{
+    select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
+}
+
+/* This function is not exposed as an API at this point.
+ * All peripheral clocks are default enabled after chip is powered on.
+ * This function disables some peripheral clocks when cpu starts.
+ * These peripheral clocks are enabled when the peripherals are initialized
+ * and disabled when they are de-initialized.
+ */
+__attribute__((weak)) void esp_perip_clk_init(void)
+{
+    ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet");
+#if 0 // TODO: IDF-5658
+    uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
+    uint32_t common_perip_clk1 = 0;
+
+    soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
+
+    /* For reason that only reset CPU, do not disable the clocks
+     * that have been enabled before reset.
+     */
+    if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW ||
+            rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) {
+        common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG);
+        hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG);
+        wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG);
+    } else {
+        common_perip_clk = SYSTEM_WDG_CLK_EN |
+                           SYSTEM_I2S0_CLK_EN |
+#if CONFIG_ESP_CONSOLE_UART_NUM != 0
+                           SYSTEM_UART_CLK_EN |
+#endif
+#if CONFIG_ESP_CONSOLE_UART_NUM != 1
+                           SYSTEM_UART1_CLK_EN |
+#endif
+                           SYSTEM_SPI2_CLK_EN |
+                           SYSTEM_I2C_EXT0_CLK_EN |
+                           SYSTEM_UHCI0_CLK_EN |
+                           SYSTEM_RMT_CLK_EN |
+                           SYSTEM_LEDC_CLK_EN |
+                           SYSTEM_TIMERGROUP1_CLK_EN |
+                           SYSTEM_SPI3_CLK_EN |
+                           SYSTEM_SPI4_CLK_EN |
+                           SYSTEM_TWAI_CLK_EN |
+                           SYSTEM_I2S1_CLK_EN |
+                           SYSTEM_SPI2_DMA_CLK_EN |
+                           SYSTEM_SPI3_DMA_CLK_EN;
+
+        common_perip_clk1 = 0;
+        hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN |
+                             SYSTEM_CRYPTO_SHA_CLK_EN |
+                             SYSTEM_CRYPTO_RSA_CLK_EN;
+        wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN |
+                           SYSTEM_WIFI_CLK_BT_EN_M |
+                           SYSTEM_WIFI_CLK_UNUSED_BIT5 |
+                           SYSTEM_WIFI_CLK_UNUSED_BIT12;
+    }
+
+    //Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
+    common_perip_clk |= SYSTEM_I2S0_CLK_EN |
+#if CONFIG_ESP_CONSOLE_UART_NUM != 0
+                        SYSTEM_UART_CLK_EN |
+#endif
+#if CONFIG_ESP_CONSOLE_UART_NUM != 1
+                        SYSTEM_UART1_CLK_EN |
+#endif
+                        SYSTEM_SPI2_CLK_EN |
+                        SYSTEM_I2C_EXT0_CLK_EN |
+                        SYSTEM_UHCI0_CLK_EN |
+                        SYSTEM_RMT_CLK_EN |
+                        SYSTEM_UHCI1_CLK_EN |
+                        SYSTEM_SPI3_CLK_EN |
+                        SYSTEM_SPI4_CLK_EN |
+                        SYSTEM_I2C_EXT1_CLK_EN |
+                        SYSTEM_I2S1_CLK_EN |
+                        SYSTEM_SPI2_DMA_CLK_EN |
+                        SYSTEM_SPI3_DMA_CLK_EN;
+    common_perip_clk1 = 0;
+
+    /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
+     * the current is not reduced when disable I2S clock.
+     */
+    // TOCK(check replacement)
+    // REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
+    // REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
+
+    /* Disable some peripheral clocks. */
+    CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk);
+    SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk);
+
+    CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1);
+    SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, common_perip_clk1);
+
+    /* Disable hardware crypto clocks. */
+    CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk);
+    SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk);
+
+    /* Disable WiFi/BT/SDIO clocks. */
+    CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
+    SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN);
+
+    /* Set WiFi light sleep clock source to RTC slow clock */
+    REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0);
+    CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M);
+    SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW);
+
+    /* Enable RNG clock. */
+    periph_module_enable(PERIPH_RNG_MODULE);
+#endif
+}

+ 110 - 0
components/esp_system/port/soc/esp32c6/reset_reason.c

@@ -0,0 +1,110 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_system.h"
+#include "esp_rom_sys.h"
+#include "esp_private/system_internal.h"
+#include "soc/rtc_periph.h"
+#include "esp32c6/rom/rtc.h"
+
+static void esp_reset_reason_clear_hint(void);
+
+static esp_reset_reason_t s_reset_reason;
+
+static esp_reset_reason_t get_reset_reason(soc_reset_reason_t rtc_reset_reason, esp_reset_reason_t reset_reason_hint)
+{
+    switch (rtc_reset_reason) {
+    case RESET_REASON_CHIP_POWER_ON:
+        return ESP_RST_POWERON;
+
+    case RESET_REASON_CPU0_SW:
+    case RESET_REASON_CORE_SW:
+        if (reset_reason_hint == ESP_RST_PANIC ||
+            reset_reason_hint == ESP_RST_BROWNOUT ||
+            reset_reason_hint == ESP_RST_TASK_WDT ||
+            reset_reason_hint == ESP_RST_INT_WDT) {
+            return reset_reason_hint;
+        }
+        return ESP_RST_SW;
+
+    case RESET_REASON_CORE_DEEP_SLEEP:
+        return ESP_RST_DEEPSLEEP;
+
+    case RESET_REASON_CORE_MWDT0:
+        return ESP_RST_TASK_WDT;
+
+    case RESET_REASON_CORE_MWDT1:
+        return ESP_RST_INT_WDT;
+
+    case RESET_REASON_CORE_RTC_WDT:
+    case RESET_REASON_SYS_RTC_WDT:
+    case RESET_REASON_SYS_SUPER_WDT:
+    case RESET_REASON_CPU0_RTC_WDT:
+    case RESET_REASON_CPU0_MWDT0:
+    case RESET_REASON_CPU0_MWDT1:
+        return ESP_RST_WDT;
+
+    case RESET_REASON_SYS_BROWN_OUT:
+        return ESP_RST_BROWNOUT;
+
+    default:
+        return ESP_RST_UNKNOWN;
+    }
+}
+
+static void __attribute__((constructor)) esp_reset_reason_init(void)
+{
+    esp_reset_reason_t hint = esp_reset_reason_get_hint();
+    s_reset_reason = get_reset_reason(esp_rom_get_reset_reason(PRO_CPU_NUM), hint);
+    if (hint != ESP_RST_UNKNOWN) {
+        esp_reset_reason_clear_hint();
+    }
+}
+
+esp_reset_reason_t esp_reset_reason(void)
+{
+    return s_reset_reason;
+}
+
+/* Reset reason hint is stored in RTC_RESET_CAUSE_REG, a.k.a. RTC_CNTL_STORE6_REG,
+ * a.k.a. RTC_ENTRY_ADDR_REG. It is safe to use this register both for the
+ * deep sleep wake stub entry address and for reset reason hint, since wake stub
+ * is only used for deep sleep reset, and in this case the reason provided by
+ * esp_rom_get_reset_reason is unambiguous.
+ *
+ * Same layout is used as for RTC_APB_FREQ_REG (a.k.a. RTC_CNTL_STORE5_REG):
+ * the value is replicated in low and high half-words. In addition to that,
+ * MSB is set to 1, which doesn't happen when RTC_CNTL_STORE6_REG contains
+ * deep sleep wake stub address.
+ */
+
+#define RST_REASON_BIT  0x80000000
+#define RST_REASON_MASK 0x7FFF
+#define RST_REASON_SHIFT 16
+
+/* in IRAM, can be called from panic handler */
+void IRAM_ATTR esp_reset_reason_set_hint(esp_reset_reason_t hint)
+{
+    assert((hint & (~RST_REASON_MASK)) == 0);
+    uint32_t val = hint | (hint << RST_REASON_SHIFT) | RST_REASON_BIT;
+    REG_WRITE(RTC_RESET_CAUSE_REG, val);
+}
+
+/* in IRAM, can be called from panic handler */
+esp_reset_reason_t IRAM_ATTR esp_reset_reason_get_hint(void)
+{
+    uint32_t reset_reason_hint = REG_READ(RTC_RESET_CAUSE_REG);
+    uint32_t high = (reset_reason_hint >> RST_REASON_SHIFT) & RST_REASON_MASK;
+    uint32_t low = reset_reason_hint & RST_REASON_MASK;
+    if ((reset_reason_hint & RST_REASON_BIT) == 0 || high != low) {
+        return ESP_RST_UNKNOWN;
+    }
+    return (esp_reset_reason_t) low;
+}
+static inline void esp_reset_reason_clear_hint(void)
+{
+    REG_WRITE(RTC_RESET_CAUSE_REG, 0);
+}

+ 120 - 0
components/esp_system/port/soc/esp32c6/system_internal.c

@@ -0,0 +1,120 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include "sdkconfig.h"
+#include "esp_system.h"
+#include "esp_private/system_internal.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_rom_sys.h"
+#include "riscv/riscv_interrupts.h"
+#include "riscv/interrupt.h"
+#include "esp_rom_uart.h"
+#include "soc/gpio_reg.h"
+#include "esp_cpu.h"
+#include "soc/rtc.h"
+#include "soc/rtc_periph.h"
+#include "soc/uart_reg.h"
+#include "hal/wdt_hal.h"
+#include "esp_private/cache_err_int.h"
+
+#include "esp32c6/rom/cache.h"
+#include "esp32c6/rom/rtc.h"
+#include "soc/pcr_reg.h"
+
+/* "inner" restart function for after RTOS, interrupts & anything else on this
+ * core are already stopped. Stalls other core, resets hardware,
+ * triggers restart.
+*/
+void IRAM_ATTR esp_restart_noos(void)
+{
+    // Disable interrupts
+    riscv_global_interrupts_disable();
+    // Enable RTC watchdog for 1 second
+    wdt_hal_context_t rtc_wdt_ctx;
+    wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
+    uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
+    wdt_hal_write_protect_disable(&rtc_wdt_ctx);
+    wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
+    wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE1, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
+    //Enable flash boot mode so that flash booting after restart is protected by the RTC WDT.
+    wdt_hal_set_flashboot_en(&rtc_wdt_ctx, true);
+    wdt_hal_write_protect_enable(&rtc_wdt_ctx);
+
+    // C6 is a single core SoC, no need to reset and stall the other CPU
+
+    // Disable TG0/TG1 watchdogs
+    wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
+    wdt_hal_write_protect_disable(&wdt0_context);
+    wdt_hal_disable(&wdt0_context);
+    wdt_hal_write_protect_enable(&wdt0_context);
+
+    wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
+    wdt_hal_write_protect_disable(&wdt1_context);
+    wdt_hal_disable(&wdt1_context);
+    wdt_hal_write_protect_enable(&wdt1_context);
+
+    // Flush any data left in UART FIFOs
+    esp_rom_uart_tx_wait_idle(0);
+    esp_rom_uart_tx_wait_idle(1);
+    // Disable cache
+    Cache_Disable_ICache();
+
+    // 2nd stage bootloader reconfigures SPI flash signals.
+    // Reset them to the defaults expected by ROM.
+    WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30);
+    // TODO: IDF-5659
+    // WRITE_PERI_REG(GPIO_FUNC1_IN_SEL_CFG_REG, 0x30);
+    // WRITE_PERI_REG(GPIO_FUNC2_IN_SEL_CFG_REG, 0x30);
+    // WRITE_PERI_REG(GPIO_FUNC3_IN_SEL_CFG_REG, 0x30);
+    // WRITE_PERI_REG(GPIO_FUNC4_IN_SEL_CFG_REG, 0x30);
+    // WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30);
+
+    // Reset wifi/bluetooth/ethernet/sdio (bb/mac)
+    // Moved to module internal
+    // SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG,
+    //                   SYSTEM_WIFIBB_RST | SYSTEM_FE_RST |            // TODO: IDF-5680 (esp_phy)
+    //                   SYSTEM_WIFIMAC_RST |                           // TODO: IDF-5679 (esp_wifi)
+    //                   SYSTEM_SDIO_RST |                              // SDIO_HINF_HINF_SDIO_RST?
+    //                   SYSTEM_EMAC_RST | SYSTEM_MACPWR_RST |          // TODO: IDF-5325 (ethernet)
+    //                   SYSTEM_BTBB_RST | SYSTEM_BTBB_REG_RST |        // TODO: IDF-5727 (bt)
+    //                   SYSTEM_RW_BTMAC_RST | SYSTEM_RW_BTLP_RST | SYSTEM_RW_BTMAC_REG_RST | SYSTEM_RW_BTLP_REG_RST);
+    // REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0);
+
+    // Set Peripheral clk rst
+    SET_PERI_REG_MASK(PCR_TIMERGROUP0_CONF_REG, PCR_TG0_RST_EN);
+    SET_PERI_REG_MASK(PCR_TIMERGROUP1_CONF_REG, PCR_TG1_RST_EN);
+    SET_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
+    SET_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
+    SET_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
+    SET_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
+    SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
+    SET_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
+    SET_PERI_REG_MASK(PCR_MODEM_APB_CONF_REG, PCR_MODEM_RST_EN);
+
+    // Clear Peripheral clk rst
+    CLEAR_PERI_REG_MASK(PCR_TIMERGROUP0_CONF_REG, PCR_TG0_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_TIMERGROUP1_CONF_REG, PCR_TG1_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
+    CLEAR_PERI_REG_MASK(PCR_MODEM_APB_CONF_REG, PCR_MODEM_RST_EN);
+
+    // Set CPU back to XTAL source, no PLL, same as hard reset
+#if !CONFIG_IDF_ENV_FPGA
+    rtc_clk_cpu_freq_set_xtal();
+#endif
+
+    // Reset PRO CPU
+    esp_rom_software_reset_cpu(0);
+    while (true) {
+        ;
+    }
+}

+ 4 - 0
components/esp_system/startup.c

@@ -459,7 +459,11 @@ static void start_cpu0_default(void)
 
     // Now that the application is about to start, disable boot watchdog
 #ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5653
+    wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &LP_WDT};
+#else
     wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
+#endif
     wdt_hal_write_protect_disable(&rtc_wdt_ctx);
     wdt_hal_disable(&rtc_wdt_ctx);
     wdt_hal_write_protect_enable(&rtc_wdt_ctx);

+ 2 - 0
components/esp_system/system_time.c

@@ -25,6 +25,8 @@
 #include "esp32h2/rtc.h"
 #elif CONFIG_IDF_TARGET_ESP32C2
 #include "esp32c2/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32C6
+#include "esp32c6/rtc.h"
 #endif
 
 #include "esp_private/startup_internal.h"

+ 0 - 4
components/soc/esp32c6/include/soc/Kconfig.soc_caps.in

@@ -31,10 +31,6 @@ config SOC_EFUSE_KEY_PURPOSE_FIELD
     bool
     default y
 
-config SOC_EFUSE_HAS_EFUSE_RST_BUG
-    bool
-    default y
-
 config SOC_RTC_FAST_MEM_SUPPORTED
     bool
     default y

+ 0 - 1
components/soc/esp32c6/include/soc/soc_caps.h

@@ -37,7 +37,6 @@
 #define SOC_SUPPORTS_SECURE_DL_MODE     1
 //#define SOC_RISCV_COPROC_SUPPORTED       1 // TODO: IDF-5816
 #define SOC_EFUSE_KEY_PURPOSE_FIELD     1
-#define SOC_EFUSE_HAS_EFUSE_RST_BUG     1
 #define SOC_RTC_FAST_MEM_SUPPORTED      1
 #define SOC_RTC_MEM_SUPPORTED           1
 // #define SOC_I2S_SUPPORTED               1 // TODO: IDF-5314