Переглянути джерело

esp32c6: add esp_hw_support

wuzhenghui 3 роки тому
батько
коміт
23e37393a7
30 змінених файлів з 1836 додано та 6 видалено
  1. 7 0
      components/esp_hw_support/CMakeLists.txt
  2. 3 1
      components/esp_hw_support/Kconfig
  3. 102 1
      components/esp_hw_support/cpu.c
  4. 4 1
      components/esp_hw_support/esp_clk.c
  5. 1 0
      components/esp_hw_support/include/esp_chip_info.h
  6. 2 0
      components/esp_hw_support/include/esp_mac.h
  7. 68 0
      components/esp_hw_support/include/soc/esp32c6/esp_crypto_lock.h
  8. 220 0
      components/esp_hw_support/include/soc/esp32c6/esp_ds.h
  9. 92 0
      components/esp_hw_support/include/soc/esp32c6/esp_hmac.h
  10. 32 0
      components/esp_hw_support/include/soc/esp32c6/rtc.h
  11. 175 0
      components/esp_hw_support/include/soc/esp32c6/soc_memprot_types.h
  12. 4 3
      components/esp_hw_support/linker.lf
  13. 25 0
      components/esp_hw_support/port/esp32c6/CMakeLists.txt
  14. 15 0
      components/esp_hw_support/port/esp32c6/Kconfig.hw_support
  15. 43 0
      components/esp_hw_support/port/esp32c6/Kconfig.mac
  16. 40 0
      components/esp_hw_support/port/esp32c6/Kconfig.rtc
  17. 18 0
      components/esp_hw_support/port/esp32c6/chip_info.c
  18. 75 0
      components/esp_hw_support/port/esp32c6/esp_crypto_lock.c
  19. 224 0
      components/esp_hw_support/port/esp32c6/esp_ds.c
  20. 182 0
      components/esp_hw_support/port/esp32c6/esp_hmac.c
  21. 9 0
      components/esp_hw_support/port/esp32c6/esp_memprot.c
  22. 226 0
      components/esp_hw_support/port/esp32c6/rtc_clk.c
  23. 84 0
      components/esp_hw_support/port/esp32c6/rtc_clk_init.c
  24. 7 0
      components/esp_hw_support/port/esp32c6/rtc_init.c
  25. 7 0
      components/esp_hw_support/port/esp32c6/rtc_pm.c
  26. 7 0
      components/esp_hw_support/port/esp32c6/rtc_sleep.c
  27. 103 0
      components/esp_hw_support/port/esp32c6/rtc_time.c
  28. 22 0
      components/esp_hw_support/port/esp32c6/systimer.c
  29. 24 0
      components/esp_hw_support/rtc_module.c
  30. 15 0
      components/esp_hw_support/sleep_modes.c

+ 7 - 0
components/esp_hw_support/CMakeLists.txt

@@ -45,6 +45,13 @@ if(NOT BOOTLOADER_BUILD)
         list(APPEND srcs "port/${target}/systimer.c")
     endif()
 
+    # ESP32C6-TODO
+    if(CONFIG_IDF_TARGET_ESP32C6)
+        list(REMOVE_ITEM srcs
+                "adc_share_hw_ctrl.c" # TODO: IDF-5312
+            )
+    endif()
+
 else()
     # Requires "_esp_error_check_failed()" function
     list(APPEND priv_requires "esp_system")

+ 3 - 1
components/esp_hw_support/Kconfig

@@ -40,7 +40,7 @@ menu "Hardware Settings"
 
         config ESP_SLEEP_GPIO_RESET_WORKAROUND
             bool "light sleep GPIO reset workaround"
-            default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3
+            default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 # TODO: IDF-5641 (esp32c6)
             select PM_SLP_DISABLE_GPIO if FREERTOS_USE_TICKLESS_IDLE
             help
                 esp32c2, esp32c3 and esp32s3 will reset at wake-up if GPIO is received a small electrostatic
@@ -165,6 +165,7 @@ menu "Hardware Settings"
 
         config MMU_PAGE_MODE
             string
+            default "8KB" if MMU_PAGE_SIZE_8KB
             default "16KB" if MMU_PAGE_SIZE_16KB
             default "32KB" if MMU_PAGE_SIZE_32KB
             default "64KB" if MMU_PAGE_SIZE_64KB
@@ -176,6 +177,7 @@ menu "Hardware Settings"
             # use of small flash sizes (reducing the wasted space due to alignment), we
             # need to use the smallest possible MMU page size for the given flash size.
             hex
+            default 0x2000 if MMU_PAGE_SIZE_8KB
             default 0x4000 if MMU_PAGE_SIZE_16KB
             default 0x8000 if MMU_PAGE_SIZE_32KB
             default 0x10000 if MMU_PAGE_SIZE_64KB

+ 102 - 1
components/esp_hw_support/cpu.c

@@ -9,7 +9,17 @@
 #include <assert.h>
 #include "soc/soc.h"
 #include "soc/soc_caps.h"
+
+// TODO: IDF-5645
+#if CONFIG_IDF_TARGET_ESP32C6
+#include "soc/lp_aon_reg.h"
+#include "soc/pcr_reg.h"
+#define SYSTEM_CPU_PER_CONF_REG PCR_CPU_WAITI_CONF_REG
+#define SYSTEM_CPU_WAIT_MODE_FORCE_ON PCR_CPU_WAIT_MODE_FORCE_ON
+#else
 #include "soc/rtc_cntl_reg.h"
+#endif
+
 #include "hal/soc_hal.h"
 #include "hal/mpu_hal.h"
 #include "esp_bit_defs.h"
@@ -81,6 +91,9 @@ void esp_cpu_unstall(int core_id)
 
 void esp_cpu_reset(int core_id)
 {
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
+    SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
+#else
     assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
 #if SOC_CPU_CORES_NUM > 1
     /*
@@ -93,6 +106,7 @@ void esp_cpu_reset(int core_id)
     int rtc_cntl_rst_m = RTC_CNTL_SW_PROCPU_RST_M;
 #endif // SOC_CPU_CORES_NUM > 1
     SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_rst_m);
+#endif
 }
 
 void esp_cpu_wait_for_intr(void)
@@ -100,6 +114,7 @@ void esp_cpu_wait_for_intr(void)
 #if __XTENSA__
     xt_utils_wait_for_intr();
 #else
+    // TODO: IDF-5645 (better to implement with ll) C6 register names converted in the #include section at the top
     if (esp_cpu_dbgr_is_attached() && DPORT_REG_GET_BIT(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPU_WAIT_MODE_FORCE_ON) == 0) {
         /* when SYSTEM_CPU_WAIT_MODE_FORCE_ON is disabled in WFI mode SBA access to memory does not work for debugger,
            so do not enter that mode when debugger is connected */
@@ -125,7 +140,13 @@ static bool is_intr_num_resv(int intr_num)
 {
     // Workaround to reserve interrupt number 1 for Wi-Fi, 5,8 for Bluetooth, 6 for "permanently disabled interrupt"
     // [TODO: IDF-2465]
-    const uint32_t reserved = BIT(1) | BIT(5) | BIT(6) | BIT(8);
+    uint32_t reserved = BIT(1) | BIT(5) | BIT(6) | BIT(8);
+
+    // int_num 0,3,4,7 are inavaliable for PULP cpu
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5728 replace with a better macro name
+    reserved |= BIT(0) | BIT(3) | BIT(4) | BIT(7);
+#endif
+
     if (reserved & BIT(intr_num)) {
         return true;
     }
@@ -501,6 +522,86 @@ void esp_cpu_configure_region_protection(void)
     PMP_ENTRY_CFG_SET(14, NONE);
     PMP_ENTRY_CFG_SET(15, PMP_TOR | NONE);
 }
+#elif CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5642
+void esp_cpu_configure_region_protection(void)
+{
+    /* Notes on implementation:
+     *
+     * 1) Note: ESP32-C6 CPU doesn't support overlapping PMP regions
+     *
+     * 2) Therefore, we use TOR (top of range) entries to map the whole address
+     * space, bottom to top.
+     *
+     * 3) There are not enough entries to describe all the memory regions 100% accurately.
+     *
+     * 4) This means some gaps (invalid memory) are accessible. Priority for extending regions
+     * to cover gaps is to extend read-only or read-execute regions or read-only regions only
+     * (executing unmapped addresses should always fault with invalid instruction, read-only means
+     * stores will correctly fault even if reads may return some invalid value.)
+     *
+     * 5) Entries are grouped in order with some static asserts to try and verify everything is
+     * correct.
+     */
+    const unsigned NONE = PMP_L | PMP_TOR;
+    const unsigned RW      = PMP_L | PMP_TOR | PMP_R | PMP_W;
+    const unsigned RX      = PMP_L | PMP_TOR | PMP_R | PMP_X;
+    const unsigned RWX     = PMP_L | PMP_TOR | PMP_R | PMP_W | PMP_X;
+
+    // 1. Gap at bottom of address space
+    PMP_ENTRY_SET(0, SOC_DEBUG_LOW, NONE);
+
+    // 2. Debug region
+    PMP_ENTRY_SET(1, SOC_DEBUG_HIGH, RWX);
+    _Static_assert(SOC_DEBUG_LOW < SOC_DEBUG_HIGH, "Invalid CPU debug region");
+
+    // 3. Gap between debug region & IROM
+    PMP_ENTRY_SET(2, SOC_IROM_MASK_LOW, NONE);
+    _Static_assert(SOC_DEBUG_HIGH < SOC_IROM_MASK_LOW, "Invalid PMP entry order");
+
+    // 4. ROM
+    PMP_ENTRY_SET(3, SOC_DROM_MASK_HIGH, RX);
+    _Static_assert(SOC_IROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid ROM region");
+
+    // 5. Gap between ROM & RAM
+    PMP_ENTRY_SET(4, SOC_IRAM_LOW, NONE);
+    _Static_assert(SOC_DROM_MASK_HIGH < SOC_IRAM_LOW, "Invalid PMP entry order");
+
+    // 6. RAM
+    PMP_ENTRY_SET(5, SOC_IRAM_HIGH, RWX);
+    _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
+
+    // 7. Gap between DRAM and I_Cache
+    PMP_ENTRY_SET(6, SOC_IROM_LOW, NONE);
+    _Static_assert(SOC_IRAM_HIGH < SOC_IROM_LOW, "Invalid PMP entry order");
+
+    // 8. I_Cache (flash)
+    PMP_ENTRY_SET(7, SOC_IROM_HIGH, RWX);
+    _Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I_Cache region");
+
+    // 9. D_Cache (flash)
+    PMP_ENTRY_SET(8, SOC_DROM_HIGH, RW);
+    _Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid D_Cache region");
+
+    // 10. Gap between D_Cache & LP_RAM
+    PMP_ENTRY_SET(9, SOC_RTC_IRAM_LOW, NONE);
+    _Static_assert(SOC_DROM_HIGH < SOC_RTC_IRAM_LOW, "Invalid PMP entry order");
+
+    // 16. LP memory
+    PMP_ENTRY_SET(10, SOC_RTC_IRAM_HIGH, RWX);
+    _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
+
+    // 17. Gap between LP memory & peripheral addresses
+    PMP_ENTRY_SET(11, SOC_PERIPHERAL_LOW, NONE);
+    _Static_assert(SOC_RTC_IRAM_HIGH < SOC_PERIPHERAL_LOW, "Invalid PMP entry order");
+
+    // 18. Peripheral addresses
+    PMP_ENTRY_SET(12, SOC_PERIPHERAL_HIGH, RW);
+    _Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
+
+    // 19. End of address space
+    PMP_ENTRY_SET(13, UINT32_MAX, NONE); // all but last 4 bytes
+    PMP_ENTRY_SET(14, UINT32_MAX, PMP_L | PMP_NA4);  // last 4 bytes
+}
 #endif
 
 /* ---------------------------------------------------- Debugging ------------------------------------------------------

+ 4 - 1
components/esp_hw_support/esp_clk.c

@@ -35,6 +35,9 @@
 #elif CONFIG_IDF_TARGET_ESP32C2
 #include "esp32c2/rom/rtc.h"
 #include "esp32c2/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32C6
+#include "esp32c6/rom/rtc.h"
+#include "esp32c6/rtc.h"
 #endif
 
 #define MHZ (1000000)
@@ -76,7 +79,7 @@ int IRAM_ATTR esp_clk_xtal_freq(void)
     return rtc_clk_xtal_freq_get() * MHZ;
 }
 
-#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C2
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESPS3
 void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
 {
     /* Update scale factors used by esp_rom_delay_us */

+ 1 - 0
components/esp_hw_support/include/esp_chip_info.h

@@ -26,6 +26,7 @@ typedef enum {
     CHIP_ESP32C3 = 5, //!< ESP32-C3
     CHIP_ESP32H2 = 6, //!< ESP32-H2
     CHIP_ESP32C2 = 12, //!< ESP32-C2
+    CHIP_ESP32C6 = 13, //!< ESP32-C6
 } esp_chip_model_t;
 
 /* Chip feature flags, used in esp_chip_info_t */

+ 2 - 0
components/esp_hw_support/include/esp_mac.h

@@ -41,6 +41,8 @@ typedef enum {
 #define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32H2_UNIVERSAL_MAC_ADDRESSES
 #elif CONFIG_IDF_TARGET_ESP32C2
 #define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32C2_UNIVERSAL_MAC_ADDRESSES
+#elif CONFIG_IDF_TARGET_ESP32C6
+#define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32C6_UNIVERSAL_MAC_ADDRESSES
 #endif
 /** @endcond */
 

+ 68 - 0
components/esp_hw_support/include/soc/esp32c6/esp_crypto_lock.h

@@ -0,0 +1,68 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Acquire lock for HMAC cryptography peripheral
+ *
+ * Internally also locks the SHA peripheral, as the HMAC depends on the SHA peripheral
+ */
+void esp_crypto_hmac_lock_acquire(void);
+
+/**
+ * @brief Release lock for HMAC cryptography peripheral
+ *
+ * Internally also releases the SHA peripheral, as the HMAC depends on the SHA peripheral
+ */
+void esp_crypto_hmac_lock_release(void);
+
+/**
+ * @brief Acquire lock for DS cryptography peripheral
+ *
+ * Internally also locks the HMAC (which locks SHA), AES and MPI  peripheral, as the DS depends on these peripherals
+ */
+void esp_crypto_ds_lock_acquire(void);
+
+/**
+ * @brief Release lock for DS cryptography peripheral
+ *
+ * Internally also releases the HMAC (which locks SHA), AES and MPI  peripheral, as the DS depends on these peripherals
+ */
+void esp_crypto_ds_lock_release(void);
+
+/**
+ * @brief Acquire lock for the SHA and AES cryptography peripheral.
+ *
+ */
+void esp_crypto_sha_aes_lock_acquire(void);
+
+/**
+ * @brief Release lock for the SHA and AES cryptography peripheral.
+ *
+ */
+void esp_crypto_sha_aes_lock_release(void);
+
+
+/**
+ * @brief Acquire lock for the mpi cryptography peripheral.
+ *
+ */
+void esp_crypto_mpi_lock_acquire(void);
+
+/**
+ * @brief Release lock for the mpi/rsa cryptography peripheral.
+ *
+ */
+void esp_crypto_mpi_lock_release(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 220 - 0
components/esp_hw_support/include/soc/esp32c6/esp_ds.h

@@ -0,0 +1,220 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "esp_hmac.h"
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESP32C6_ERR_HW_CRYPTO_DS_HMAC_FAIL           ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
+#define ESP32C6_ERR_HW_CRYPTO_DS_INVALID_KEY         ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
+                                                                                HMAC peripheral problem */
+#define ESP32C6_ERR_HW_CRYPTO_DS_INVALID_DIGEST      ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
+                                                                                result is invalid */
+#define ESP32C6_ERR_HW_CRYPTO_DS_INVALID_PADDING     ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result
+                                                                                   is produced anyway and can be read*/
+
+#define ESP_DS_IV_BIT_LEN 128
+#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
+#define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072
+#define ESP_DS_SIGNATURE_MD_BIT_LEN 256
+#define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32
+#define ESP_DS_SIGNATURE_L_BIT_LEN 32
+#define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64
+
+/* Length of parameter 'C' stored in flash, in bytes
+   - Operands Y, M and r_bar; each 3072 bits
+   - Operand MD (message digest); 256 bits
+   - Operands M' and L; each 32 bits
+   - Operand beta (padding value; 64 bits
+*/
+#define ESP_DS_C_LEN (((ESP_DS_SIGNATURE_MAX_BIT_LEN * 3 \
+        + ESP_DS_SIGNATURE_MD_BIT_LEN   \
+        + ESP_DS_SIGNATURE_M_PRIME_BIT_LEN   \
+        + ESP_DS_SIGNATURE_L_BIT_LEN   \
+        + ESP_DS_SIGNATURE_PADDING_BIT_LEN) / 8))
+
+typedef struct esp_ds_context esp_ds_context_t;
+
+typedef enum {
+    ESP_DS_RSA_1024 = (1024 / 32) - 1,
+    ESP_DS_RSA_2048 = (2048 / 32) - 1,
+    ESP_DS_RSA_3072 = (3072 / 32) - 1
+} esp_digital_signature_length_t;
+
+/**
+ * Encrypted private key data. Recommended to store in flash in this format.
+ *
+ * @note This struct has to match to one from the ROM code! This documentation is mostly taken from there.
+ */
+typedef struct esp_digital_signature_data {
+    /**
+     * RSA LENGTH register parameters
+     * (number of words in RSA key & operands, minus one).
+     *
+     * Max value 127 (for RSA 3072).
+     *
+     * This value must match the length field encrypted and stored in 'c',
+     * or invalid results will be returned. (The DS peripheral will
+     * always use the value in 'c', not this value, so an attacker can't
+     * alter the DS peripheral results this way, it will just truncate or
+     * extend the message and the resulting signature in software.)
+     *
+     * @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably.
+     *       See the ROM code for the original declaration of struct \c ets_ds_data_t.
+     */
+    esp_digital_signature_length_t rsa_length;
+
+    /**
+     * IV value used to encrypt 'c'
+     */
+    uint32_t iv[ESP_DS_IV_BIT_LEN / 32];
+
+    /**
+     * Encrypted Digital Signature parameters. Result of AES-CBC encryption
+     * of plaintext values. Includes an encrypted message digest.
+     */
+    uint8_t c[ESP_DS_C_LEN];
+} esp_ds_data_t;
+
+/**
+ * Plaintext parameters used by Digital Signature.
+ *
+ * This is only used for encrypting the RSA parameters by calling esp_ds_encrypt_params().
+ * Afterwards, the result can be stored in flash or in other persistent memory.
+ * The encryption is a prerequisite step before any signature operation can be done.
+ */
+typedef struct {
+    uint32_t  Y[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA exponent
+    uint32_t  M[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA modulus
+    uint32_t Rb[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA r inverse operand
+    uint32_t M_prime;                               //!< RSA M prime operand
+    uint32_t length;                                //!< RSA length in words (32 bit)
+} esp_ds_p_data_t;
+
+/**
+ * @brief Sign the message with a hardware key from specific key slot.
+ * The function calculates a plain RSA signature with help of the DS peripheral.
+ * The RSA encryption operation is as follows:
+ * Z = XY mod M where,
+ * Z is the signature, X is the input message,
+ * Y and M are the RSA private key parameters.
+ *
+ * This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them
+ * in parallel.
+ * It blocks until the signing is finished and then returns the signature.
+ *
+ * @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time.
+ *
+ * @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
+ * @param data the encrypted signing key data (AES encrypted RSA key + IV)
+ * @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
+ *        signing key data
+ * @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
+ *
+ * @return
+ *      - ESP_OK if successful, the signature was written to the parameter \c signature.
+ *      - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
+ *      - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
+ *      - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
+ *      - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
+ *      - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
+ *      - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
+ *        since the message digest matches.
+ */
+esp_err_t esp_ds_sign(const void *message,
+        const esp_ds_data_t *data,
+        hmac_key_id_t key_id,
+        void *signature);
+
+/**
+ * @brief Start the signing process.
+ *
+ * This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
+ * process.
+ * The function calculates a plain RSA signature with help of the DS peripheral.
+ * The RSA encryption operation is as follows:
+ * Z = XY mod M where,
+ * Z is the signature, X is the input message,
+ * Y and M are the RSA private key parameters.
+ *
+ * @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
+ *       \c esp_ds_finish_sign() in a timely manner.
+ *
+ * @param message the message to be signed; its length should be (data->rsa_length + 1)*4 bytes
+ * @param data the encrypted signing key data (AES encrypted RSA key + IV)
+ * @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
+ *        signing key data
+ * @param esp_ds_ctx the context object which is needed for finishing the signing process later
+ *
+ * @return
+ *      - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign()
+ *      - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
+ *      - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
+ *      - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
+ *      - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
+ */
+esp_err_t esp_ds_start_sign(const void *message,
+        const esp_ds_data_t *data,
+        hmac_key_id_t key_id,
+        esp_ds_context_t **esp_ds_ctx);
+
+/**
+ * Return true if the DS peripheral is busy, otherwise false.
+ *
+ * @note Only valid if \c esp_ds_start_sign() was called before.
+ */
+bool esp_ds_is_busy(void);
+
+/**
+ * @brief Finish the signing process.
+ *
+ * @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
+ * @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign()
+ *
+ * @return
+ *      - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
+ *      - ESP_ERR_INVALID_ARG if one of the parameters is NULL
+ *      - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
+ *        This means that the encrypted RSA key parameters are invalid, indicating that they may have been tampered
+ *        with or indicating a flash error, etc.
+ *      - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
+ *        since the message digest matches (see TRM for more details).
+ */
+esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx);
+
+/**
+ * @brief Encrypt the private key parameters.
+ *
+ * The encryption is a prerequisite step before any signature operation can be done.
+ * It is not strictly necessary to use this encryption function, the encryption could also happen on an external
+ * device.
+ *
+ * @param data Output buffer to store encrypted data, suitable for later use generating signatures.
+ *        The allocated memory must be in internal memory and word aligned since it's filled by DMA. Both is asserted
+ *        at run time.
+ * @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time.
+ * @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process
+ *        is done and 'data' is stored.
+ * @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the
+ *        corresponding HMAC key will be stored to efuse and then permanently erased.
+ *
+ * @return
+ *      - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
+ *      - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long
+ */
+esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
+        const void *iv,
+        const esp_ds_p_data_t *p_data,
+        const void *key);
+
+#ifdef __cplusplus
+}
+#endif

+ 92 - 0
components/esp_hw_support/include/soc/esp32c6/esp_hmac.h

@@ -0,0 +1,92 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _ESP_HMAC_H_
+#define _ESP_HMAC_H_
+
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The possible efuse keys for the HMAC peripheral
+ */
+typedef enum {
+    HMAC_KEY0 = 0,
+    HMAC_KEY1,
+    HMAC_KEY2,
+    HMAC_KEY3,
+    HMAC_KEY4,
+    HMAC_KEY5,
+    HMAC_KEY_MAX
+} hmac_key_id_t;
+
+/**
+ * @brief
+ * Calculate the HMAC of a given message.
+ *
+ * Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
+ * SHA256 is used for the calculation (fixed on ESP32S2).
+ *
+ * @note Uses the HMAC peripheral in "upstream" mode.
+ *
+ * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
+ *        The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
+ * @param message the message for which to calculate the HMAC
+ * @param message_len message length
+ *             return ESP_ERR_INVALID_STATE if unsuccessful
+ * @param [out] hmac the hmac result; the buffer behind the provided pointer must be a writeable buffer of 32 bytes
+ *
+ * @return
+ *      * ESP_OK, if the calculation was successful,
+ *      * ESP_ERR_INVALID_ARG if message or hmac is a nullptr or if key_id out of range
+ *      * ESP_FAIL, if the hmac calculation failed
+ */
+esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
+        const void *message,
+        size_t message_len,
+        uint8_t *hmac);
+
+/**
+ * @brief Use HMAC peripheral in Downstream mode to re-enable the JTAG, if it is not permanently disabled by HW.
+ *        In downstream mode, HMAC calculations performed by peripheral are used internally and not provided back to user.
+ *
+ * @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calculation.
+ *        The corresponding purpose field of the key block in the efuse must be set to HMAC downstream purpose.
+ *
+ * @param token Pre calculated HMAC value of the 32-byte 0x00 using SHA-256 and the known private HMAC key. The key is already
+ *        programmed to a eFuse key block. The key block number is provided as the first parameter to this function.
+ *
+ * @return
+ *      * ESP_OK, if the key_purpose of the key_id matches to HMAC downstread mode,
+ *                The API returns success even if calculated HMAC does not match with the provided token.
+ *                However, The JTAG will be re-enabled only if the calculated HMAC value matches with provided token,
+ *                otherwise JTAG will remain disabled.
+ *      * ESP_FAIL, if the key_purpose of the key_id is not set to HMAC downstream purpose
+ *                  or JTAG is permanently disabled by EFUSE_HARD_DIS_JTAG eFuse parameter.
+ *      * ESP_ERR_INVALID_ARG, invalid input arguments
+ *
+ * @note  Return value of the API does not indicate the JTAG status.
+ */
+esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token);
+
+/**
+ *  @brief Disable the JTAG which might be enabled using the HMAC downstream mode. This function just clears the result generated
+ *         by calling esp_hmac_jtag_enable() API.
+ *
+ *  @return
+ *       * ESP_OK return ESP_OK after writing the HMAC_SET_INVALIDATE_JTAG_REG with value 1.
+ */
+esp_err_t esp_hmac_jtag_disable(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _ESP_HMAC_H_

+ 32 - 0
components/esp_hw_support/include/soc/esp32c6/rtc.h

@@ -0,0 +1,32 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file esp32c6/rtc.h
+ *
+ * This file contains declarations of rtc related functions.
+ */
+
+/**
+ * @brief Get current value of RTC counter in microseconds
+ *
+ * Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute
+ *
+ * @return current value of RTC counter in microseconds
+ */
+uint64_t esp_rtc_get_time_us(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 175 - 0
components/esp_hw_support/include/soc/esp32c6/soc_memprot_types.h

@@ -0,0 +1,175 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//////////////////////////////////////////////////////////
+// ESP32-C6 PMS memory protection types
+//
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Memory types recognized by PMS
+ */
+typedef enum {
+    MEMPROT_TYPE_NONE                           = 0x00000000,
+    MEMPROT_TYPE_IRAM0_SRAM                     = 0x00000001,
+    MEMPROT_TYPE_DRAM0_SRAM                     = 0x00000002,
+    MEMPROT_TYPE_IRAM0_RTCFAST                  = 0x00000004,
+    MEMPROT_TYPE_ALL                            = 0x7FFFFFFF,
+    MEMPROT_TYPE_INVALID                        = 0x80000000,
+    MEMPROT_TYPE_IRAM0_ANY                      = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_IRAM0_RTCFAST
+} esp_mprot_mem_t;
+
+/**
+ * @brief Splitting address (line) type
+ */
+typedef enum {
+    MEMPROT_SPLIT_ADDR_NONE                     = 0x00000000,
+    MEMPROT_SPLIT_ADDR_IRAM0_DRAM0              = 0x00000001,
+    MEMPROT_SPLIT_ADDR_IRAM0_LINE_0             = 0x00000002,
+    MEMPROT_SPLIT_ADDR_IRAM0_LINE_1             = 0x00000004,
+    MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0         = 0x00000008,
+    MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1         = 0x00000010,
+    MEMPROT_SPLIT_ADDR_ALL                      = 0x7FFFFFFF,
+    MEMPROT_SPLIT_ADDR_INVALID                  = 0x80000000,
+    MEMPROT_SPLIT_ADDR_MAIN                     = MEMPROT_SPLIT_ADDR_IRAM0_DRAM0
+} esp_mprot_split_addr_t;
+
+/**
+ * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
+ */
+typedef enum {
+    MEMPROT_PMS_AREA_NONE                       = 0x00000000,
+    MEMPROT_PMS_AREA_IRAM0_0                    = 0x00000001,
+    MEMPROT_PMS_AREA_IRAM0_1                    = 0x00000002,
+    MEMPROT_PMS_AREA_IRAM0_2                    = 0x00000004,
+    MEMPROT_PMS_AREA_IRAM0_3                    = 0x00000008,
+    MEMPROT_PMS_AREA_DRAM0_0                    = 0x00000010,
+    MEMPROT_PMS_AREA_DRAM0_1                    = 0x00000020,
+    MEMPROT_PMS_AREA_DRAM0_2                    = 0x00000040,
+    MEMPROT_PMS_AREA_DRAM0_3                    = 0x00000080,
+    MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO           = 0x00000100,
+    MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI           = 0x00000200,
+    MEMPROT_PMS_AREA_ALL                        = 0x7FFFFFFF,
+    MEMPROT_PMS_AREA_INVALID                    = 0x80000000
+} esp_mprot_pms_area_t;
+
+/**
+* @brief Memory protection configuration
+*/
+typedef struct {
+    bool invoke_panic_handler;  /*!< Register PMS violation interrupt for panic-handling */
+    bool lock_feature;          /*!< Lock all PMS settings */
+    void *split_addr;           /*!< Main I/D splitting address */
+    uint32_t mem_type_mask;     /*!< Memory types required to protect. See esp_mprot_mem_t enum */
+} esp_memp_config_t;
+
+#define ESP_MEMPROT_DEFAULT_CONFIG() { \
+    .invoke_panic_handler = true, \
+    .lock_feature = true, \
+    .split_addr = NULL, \
+    .mem_type_mask = MEMPROT_TYPE_ALL \
+}
+
+/**
+ * @brief Converts Memory protection type to string
+ *
+ * @param mem_type Memory protection type
+ */
+static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_NONE:
+        return "NONE";
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        return "IRAM0_SRAM";
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        return "DRAM0_SRAM";
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        return "IRAM0_RTCFAST";
+    case MEMPROT_TYPE_IRAM0_ANY:
+        return "IRAM0_ANY";
+    case MEMPROT_TYPE_ALL:
+        return "ALL";
+    default:
+        return "INVALID";
+    }
+}
+
+/**
+ * @brief Converts Splitting address type to string
+ *
+ * @param line_type Split line type
+ */
+static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
+{
+    switch (line_type) {
+    case MEMPROT_SPLIT_ADDR_NONE:
+        return "SPLIT_ADDR_NONE";
+    case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
+        return "SPLIT_ADDR_IRAM0_DRAM0";
+    case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
+        return "SPLIT_ADDR_IRAM0_LINE_0";
+    case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
+        return "SPLIT_ADDR_IRAM0_LINE_1";
+    case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
+        return "SPLIT_ADDR_DRAM0_DMA_LINE_0";
+    case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
+        return "SPLIT_ADDR_DRAM0_DMA_LINE_1";
+    case MEMPROT_SPLIT_ADDR_ALL:
+        return "SPLIT_ADDR_ALL";
+    default:
+        return "SPLIT_ADDR_INVALID";
+    }
+}
+
+/**
+ * @brief Converts PMS Area type to string
+ *
+ * @param area_type PMS Area type
+ */
+static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
+{
+    switch (area_type) {
+    case MEMPROT_PMS_AREA_NONE:
+        return "PMS_AREA_NONE";
+    case MEMPROT_PMS_AREA_IRAM0_0:
+        return "PMS_AREA_IRAM0_0";
+    case MEMPROT_PMS_AREA_IRAM0_1:
+        return "PMS_AREA_IRAM0_1";
+    case MEMPROT_PMS_AREA_IRAM0_2:
+        return "PMS_AREA_IRAM0_2";
+    case MEMPROT_PMS_AREA_IRAM0_3:
+        return "PMS_AREA_IRAM0_3";
+    case MEMPROT_PMS_AREA_DRAM0_0:
+        return "PMS_AREA_DRAM0_0";
+    case MEMPROT_PMS_AREA_DRAM0_1:
+        return "PMS_AREA_DRAM0_1";
+    case MEMPROT_PMS_AREA_DRAM0_2:
+        return "PMS_AREA_DRAM0_2";
+    case MEMPROT_PMS_AREA_DRAM0_3:
+        return "PMS_AREA_DRAM0_3";
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
+        return "PMS_AREA_IRAM0_RTCFAST_LO";
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
+        return "PMS_AREA_IRAM0_RTCFAST_HI";
+    case MEMPROT_PMS_AREA_ALL:
+        return "PMS_AREA_ALL";
+    default:
+        return "PMS_AREA_INVALID";
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 4 - 3
components/esp_hw_support/linker.lf

@@ -13,9 +13,10 @@ entries:
     cpu: esp_cpu_compare_and_set (noflash)
     esp_memory_utils (noflash)
     rtc_clk (noflash)
-    rtc_init:rtc_vddsdio_set_config (noflash)
-    rtc_pm (noflash_text)
-    rtc_sleep (noflash_text)
+    if IDF_TARGET_ESP32C6 = n: # TODO: IDF-5645
+        rtc_init:rtc_vddsdio_set_config (noflash)
+        rtc_pm (noflash_text)
+        rtc_sleep (noflash_text)
     rtc_time (noflash_text)
     if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y:
         rtc_wdt (noflash_text)

+ 25 - 0
components/esp_hw_support/port/esp32c6/CMakeLists.txt

@@ -0,0 +1,25 @@
+set(srcs "rtc_clk_init.c"
+         "rtc_clk.c"
+        #  "rtc_init.c" // TODO: IDF-5645
+        #  "rtc_pm.c" // TODO: IDF-5645
+        #  "rtc_sleep.c" // TODO: IDF-5645
+         "rtc_time.c"
+         "chip_info.c"
+         )
+
+if(NOT BOOTLOADER_BUILD)
+    # list(APPEND srcs "esp_hmac.c" // TODO: IDF-5355
+    #                  "esp_crypto_lock.c"
+    #                  "esp_ds.c") // TODO: IDF-5360
+
+    if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
+        list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c")
+    endif()
+
+endif()
+
+add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
+
+target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
+target_include_directories(${COMPONENT_LIB} PUBLIC . private_include)
+target_include_directories(${COMPONENT_LIB} PRIVATE ../hal)

+ 15 - 0
components/esp_hw_support/port/esp32c6/Kconfig.hw_support

@@ -0,0 +1,15 @@
+choice ESP32C6_REV_MIN
+    prompt "Minimum Supported ESP32-C6 Revision"
+    default ESP32C6_REV_MIN_0
+    help
+        Minimum revision that ESP-IDF would support.
+
+        Only supporting higher chip revisions can reduce binary size.
+
+    config ESP32C6_REV_MIN_0
+        bool "Rev 0"
+endchoice
+
+config ESP32C6_REV_MIN
+    int
+    default 0 if ESP32C6_REV_MIN_0

+ 43 - 0
components/esp_hw_support/port/esp32c6/Kconfig.mac

@@ -0,0 +1,43 @@
+choice ESP32C6_UNIVERSAL_MAC_ADDRESSES
+    bool "Number of universally administered (by IEEE) MAC address"
+    default ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR
+    help
+        Configure the number of universally administered (by IEEE) MAC addresses.
+
+        During initialization, MAC addresses for each network interface are generated or derived from a
+        single base MAC address.
+
+        If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap,
+        Bluetooth and Ethernet) receive a universally administered MAC address. These are generated
+        sequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address.
+
+        If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth)
+        receive a universally administered MAC address. These are generated sequentially by adding 0
+        and 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet)
+        receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC
+        addresses, respectively.
+
+        When using the default (Espressif-assigned) base MAC address, either setting can be used. When using
+        a custom universal MAC address range, the correct setting will depend on the allocation of MAC
+        addresses in this range (either 2 or 4 per device.)
+
+        Note that ESP32-C6 has no integrated Ethernet MAC. Although it's possible to use the esp_read_mac()
+        API to return a MAC for Ethernet, this can only be used with an external MAC peripheral.
+
+    config ESP32C6_UNIVERSAL_MAC_ADDRESSES_TWO
+        bool "Two"
+        select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
+        select ESP_MAC_ADDR_UNIVERSE_BT
+
+    config ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR
+        bool "Four"
+        select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
+        select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
+        select ESP_MAC_ADDR_UNIVERSE_BT
+        select ESP_MAC_ADDR_UNIVERSE_ETH
+endchoice
+
+config ESP32C6_UNIVERSAL_MAC_ADDRESSES
+    int
+    default 2 if ESP32C6_UNIVERSAL_MAC_ADDRESSES_TWO
+    default 4 if ESP32C6_UNIVERSAL_MAC_ADDRESSES_FOUR

+ 40 - 0
components/esp_hw_support/port/esp32c6/Kconfig.rtc

@@ -0,0 +1,40 @@
+choice RTC_CLK_SRC
+    # TODO: IDF-5346
+    prompt "RTC clock source"
+    default RTC_CLK_SRC_INT_RC
+    help
+        Choose which clock is used as RTC clock source.
+
+    config RTC_CLK_SRC_INT_RC
+        bool "Internal 136kHz RC oscillator"
+    config RTC_CLK_SRC_EXT_CRYS
+        bool "External 32kHz crystal"
+        select ESP_SYSTEM_RTC_EXT_XTAL
+    config RTC_CLK_SRC_EXT_OSC
+        bool "External 32kHz oscillator at 32K_XP pin"
+        select ESP_SYSTEM_RTC_EXT_OSC
+    config RTC_CLK_SRC_INT_8MD256
+        bool "Internal 17.5MHz oscillator, divided by 256"
+endchoice
+
+config RTC_CLK_CAL_CYCLES
+    int "Number of cycles for RTC_SLOW_CLK calibration"
+    default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256
+    default 1024 if RTC_CLK_SRC_INT_RC
+    range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_8MD256
+    range 0 32766 if RTC_CLK_SRC_INT_RC
+    help
+        When the startup code initializes RTC_SLOW_CLK, it can perform
+        calibration by comparing the RTC_SLOW_CLK frequency with main XTAL
+        frequency. This option sets the number of RTC_SLOW_CLK cycles measured
+        by the calibration routine. Higher numbers increase calibration
+        precision, which may be important for applications which spend a lot of
+        time in deep sleep. Lower numbers reduce startup time.
+
+        When this option is set to 0, clock calibration will not be performed at
+        startup, and approximate clock frequencies will be assumed:
+
+        - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024.
+        - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more.
+            In case more value will help improve the definition of the launch of the crystal.
+            If the crystal could not start, it will be switched to internal RC.

+ 18 - 0
components/esp_hw_support/port/esp32c6/chip_info.c

@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include "esp_chip_info.h"
+#include "hal/efuse_hal.h"
+
+void esp_chip_info(esp_chip_info_t *out_info)
+{
+    memset(out_info, 0, sizeof(*out_info));
+    out_info->model = CHIP_ESP32C6;
+    out_info->revision = efuse_hal_chip_revision();
+    out_info->cores = 1;
+    out_info->features = CHIP_FEATURE_WIFI_BGN | CHIP_FEATURE_BLE;
+}

+ 75 - 0
components/esp_hw_support/port/esp32c6/esp_crypto_lock.c

@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/lock.h>
+
+#include "esp_crypto_lock.h"
+
+/* Lock overview:
+SHA: peripheral independent, but DMA is shared with AES
+AES: peripheral independent, but DMA is shared with SHA
+MPI/RSA: independent
+HMAC: needs SHA
+DS: needs HMAC (which needs SHA), AES and MPI
+*/
+
+/* Lock for DS peripheral */
+static _lock_t s_crypto_ds_lock;
+
+/* Lock for HMAC peripheral */
+static _lock_t s_crypto_hmac_lock;
+
+/* Lock for the MPI/RSA peripheral, also used by the DS peripheral */
+static _lock_t s_crypto_mpi_lock;
+
+/* Single lock for SHA and AES, sharing a reserved GDMA channel */
+static _lock_t s_crypto_sha_aes_lock;
+
+void esp_crypto_hmac_lock_acquire(void)
+{
+    _lock_acquire(&s_crypto_hmac_lock);
+    esp_crypto_sha_aes_lock_acquire();
+}
+
+void esp_crypto_hmac_lock_release(void)
+{
+    esp_crypto_sha_aes_lock_release();
+    _lock_release(&s_crypto_hmac_lock);
+}
+
+void esp_crypto_ds_lock_acquire(void)
+{
+    _lock_acquire(&s_crypto_ds_lock);
+    esp_crypto_hmac_lock_acquire();
+    esp_crypto_mpi_lock_acquire();
+}
+
+void esp_crypto_ds_lock_release(void)
+{
+    esp_crypto_mpi_lock_release();
+    esp_crypto_hmac_lock_release();
+    _lock_release(&s_crypto_ds_lock);
+}
+
+void esp_crypto_sha_aes_lock_acquire(void)
+{
+    _lock_acquire(&s_crypto_sha_aes_lock);
+}
+
+void esp_crypto_sha_aes_lock_release(void)
+{
+    _lock_release(&s_crypto_sha_aes_lock);
+}
+
+void esp_crypto_mpi_lock_acquire(void)
+{
+    _lock_acquire(&s_crypto_mpi_lock);
+}
+
+void esp_crypto_mpi_lock_release(void)
+{
+    _lock_release(&s_crypto_mpi_lock);
+}

+ 224 - 0
components/esp_hw_support/port/esp32c6/esp_ds.c

@@ -0,0 +1,224 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_private/periph_ctrl.h"
+#include "esp_crypto_lock.h"
+#include "hal/ds_hal.h"
+#include "hal/ds_ll.h"
+#include "hal/hmac_hal.h"
+#include "esp32c6/rom/digital_signature.h"
+#include "esp_timer.h"
+#include "esp_ds.h"
+
+struct esp_ds_context {
+    const esp_ds_data_t *data;
+};
+
+/**
+ * The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
+ */
+#define ESP_DS_SIGN_TASK_DELAY_MS 10
+
+#define RSA_LEN_MAX 127
+
+/*
+ * esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
+ * Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
+ */
+_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
+        "The size of esp_digital_signature_length_t and unsigned has to be the same");
+
+/*
+ * esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t.
+ * Check esp_ds_data_t's width here because it's converted using raw casts.
+ */
+_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
+        "The size of esp_ds_data_t and ets_ds_data_t has to be the same");
+
+static void ds_acquire_enable(void)
+{
+    esp_crypto_ds_lock_acquire();
+
+    // We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS.
+    periph_module_enable(PERIPH_HMAC_MODULE);
+    periph_module_enable(PERIPH_SHA_MODULE);
+    periph_module_enable(PERIPH_DS_MODULE);
+
+    hmac_hal_start();
+}
+
+static void ds_disable_release(void)
+{
+    ds_hal_finish();
+
+    periph_module_disable(PERIPH_DS_MODULE);
+    periph_module_disable(PERIPH_SHA_MODULE);
+    periph_module_disable(PERIPH_HMAC_MODULE);
+
+    esp_crypto_ds_lock_release();
+}
+
+esp_err_t esp_ds_sign(const void *message,
+        const esp_ds_data_t *data,
+        hmac_key_id_t key_id,
+        void *signature)
+{
+    // Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
+    // but the signing isn't uninitialized and the mutex is still locked.
+    if (!signature) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    esp_ds_context_t *context;
+    esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
+    if (result != ESP_OK) {
+        return result;
+    }
+
+    while (esp_ds_is_busy())
+        vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
+
+    return esp_ds_finish_sign(signature, context);
+}
+
+esp_err_t esp_ds_start_sign(const void *message,
+        const esp_ds_data_t *data,
+        hmac_key_id_t key_id,
+        esp_ds_context_t **esp_ds_ctx)
+{
+    if (!message || !data || !esp_ds_ctx) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    if (key_id >= HMAC_KEY_MAX) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    if (!(data->rsa_length == ESP_DS_RSA_1024
+            || data->rsa_length == ESP_DS_RSA_2048
+            || data->rsa_length == ESP_DS_RSA_3072)) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    ds_acquire_enable();
+
+    // initiate hmac
+    uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
+    if (conf_error) {
+        ds_disable_release();
+        return ESP32C6_ERR_HW_CRYPTO_DS_HMAC_FAIL;
+    }
+
+    ds_hal_start();
+
+    // check encryption key from HMAC
+    int64_t start_time = esp_timer_get_time();
+    while (ds_ll_busy() != 0) {
+        if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
+            ds_disable_release();
+            return ESP32C6_ERR_HW_CRYPTO_DS_INVALID_KEY;
+        }
+    }
+
+    esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
+    if (!context) {
+        ds_disable_release();
+        return ESP_ERR_NO_MEM;
+    }
+
+    size_t rsa_len = (data->rsa_length + 1) * 4;
+    ds_hal_write_private_key_params(data->c);
+    ds_hal_configure_iv(data->iv);
+    ds_hal_write_message(message, rsa_len);
+
+    // initiate signing
+    ds_hal_start_sign();
+
+    context->data = data;
+    *esp_ds_ctx = context;
+
+    return ESP_OK;
+}
+
+bool esp_ds_is_busy(void)
+{
+    return ds_hal_busy();
+}
+
+esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
+{
+    if (!signature || !esp_ds_ctx) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    const esp_ds_data_t *data = esp_ds_ctx->data;
+    unsigned rsa_len = (data->rsa_length + 1) * 4;
+
+    while (ds_hal_busy()) { }
+
+    ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t*) signature, (size_t) rsa_len);
+
+    esp_err_t return_value = ESP_OK;
+
+    if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
+        return_value = ESP32C6_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
+    }
+
+    if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
+        return_value = ESP32C6_ERR_HW_CRYPTO_DS_INVALID_PADDING;
+    }
+
+    free(esp_ds_ctx);
+
+    hmac_hal_clean();
+
+    ds_disable_release();
+
+    return return_value;
+}
+
+esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
+        const void *iv,
+        const esp_ds_p_data_t *p_data,
+        const void *key)
+{
+    if (!p_data) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    esp_err_t result = ESP_OK;
+
+    esp_crypto_ds_lock_acquire();
+    periph_module_enable(PERIPH_AES_MODULE);
+    periph_module_enable(PERIPH_DS_MODULE);
+    periph_module_enable(PERIPH_SHA_MODULE);
+    periph_module_enable(PERIPH_HMAC_MODULE);
+    periph_module_enable(PERIPH_RSA_MODULE);
+
+    ets_ds_data_t *ds_data = (ets_ds_data_t*) data;
+    const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t*) p_data;
+
+    ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
+
+    if (ets_result == ETS_DS_INVALID_PARAM) {
+        result = ESP_ERR_INVALID_ARG;
+    }
+
+    periph_module_disable(PERIPH_RSA_MODULE);
+    periph_module_disable(PERIPH_HMAC_MODULE);
+    periph_module_disable(PERIPH_SHA_MODULE);
+    periph_module_disable(PERIPH_DS_MODULE);
+    periph_module_disable(PERIPH_AES_MODULE);
+    esp_crypto_ds_lock_release();
+
+    return result;
+}

+ 182 - 0
components/esp_hw_support/port/esp32c6/esp_hmac.c

@@ -0,0 +1,182 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// TODO: IDF-5355 Copy frome C3
+
+#include <string.h>
+#include "esp_private/periph_ctrl.h"
+#include "esp32c6/rom/hmac.h"
+#include "esp32c6/rom/ets_sys.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+#include "esp_hmac.h"
+#include "esp_log.h"
+#include "esp_crypto_lock.h"
+#include "soc/hwcrypto_reg.h"
+
+#include "hal/hmac_hal.h"
+
+#define SHA256_BLOCK_SZ 64
+#define SHA256_PAD_SZ 8
+
+static const char *TAG = "esp_hmac";
+
+/**
+ * @brief Apply the HMAC padding without the embedded length.
+ *
+ * @note This function does not check the data length, it is the responsibility of the other functions in this
+ * module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
+ * Otherwise, this function has undefined behavior.
+ * Note however, that for the actual HMAC implementation on ESP32C6, the length also needs to be applied at the end
+ * of the block. This function alone deosn't do that.
+ */
+static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
+{
+    memcpy(block, data, data_len);
+    // Apply a one bit, followed by zero bits (refer to the ESP32C6 TRM).
+    block[data_len] = 0x80;
+    bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
+}
+
+esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
+                             const void *message,
+                             size_t message_len,
+                             uint8_t *hmac)
+{
+    const uint8_t *message_bytes = (const uint8_t *)message;
+
+    if (!message || !hmac) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (key_id >= HMAC_KEY_MAX) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    esp_crypto_hmac_lock_acquire();
+
+    // We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
+    periph_module_enable(PERIPH_HMAC_MODULE);
+    periph_module_enable(PERIPH_SHA_MODULE);
+    periph_module_enable(PERIPH_DS_MODULE);
+
+    hmac_hal_start();
+
+    uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
+    if (conf_error) {
+        esp_crypto_hmac_lock_release();
+        return ESP_FAIL;
+    }
+
+    if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
+        // If message including padding is only one block...
+        // Last message block, so apply SHA-256 padding rules in software
+        uint8_t block[SHA256_BLOCK_SZ];
+        uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
+
+        write_and_padd(block, message_bytes, message_len);
+        // Final block: append the bit length in this block and signal padding to peripheral
+        memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
+               &bit_len, sizeof(bit_len));
+        hmac_hal_write_one_block_512(block);
+    } else {
+        // If message including padding is needs more than one block
+
+        // write all blocks without padding except the last one
+        size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
+        for (int i = 1; i < remaining_blocks; i++) {
+            hmac_hal_write_block_512(message_bytes);
+            message_bytes += SHA256_BLOCK_SZ;
+            hmac_hal_next_block_normal();
+        }
+
+        // If message fits into one block but without padding, we must not write another block.
+        if (remaining_blocks) {
+            hmac_hal_write_block_512(message_bytes);
+            message_bytes += SHA256_BLOCK_SZ;
+        }
+
+        size_t remaining = message_len % SHA256_BLOCK_SZ;
+        // Last message block, so apply SHA-256 padding rules in software
+        uint8_t block[SHA256_BLOCK_SZ];
+        uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
+
+        // If the remaining message and appended padding doesn't fit into a single block, we have to write an
+        // extra block with the rest of the message and potential padding first.
+        if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
+            write_and_padd(block, message_bytes, remaining);
+            hmac_hal_next_block_normal();
+            hmac_hal_write_block_512(block);
+            bzero(block, SHA256_BLOCK_SZ);
+        } else {
+            write_and_padd(block, message_bytes, remaining);
+        }
+        memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
+               &bit_len, sizeof(bit_len));
+        hmac_hal_next_block_padding();
+        hmac_hal_write_block_512(block);
+    }
+
+    // Read back result (bit swapped)
+    hmac_hal_read_result_256(hmac);
+
+    periph_module_disable(PERIPH_DS_MODULE);
+    periph_module_disable(PERIPH_SHA_MODULE);
+    periph_module_disable(PERIPH_HMAC_MODULE);
+
+    esp_crypto_hmac_lock_release();
+
+    return ESP_OK;
+}
+
+static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) {
+    return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id;
+}
+
+esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
+{
+    int ets_status;
+    esp_err_t err = ESP_OK;
+
+    if ((!token) || (key_id >= HMAC_KEY_MAX))
+        return ESP_ERR_INVALID_ARG;
+
+    /* Check if JTAG is permanently disabled by HW Disable eFuse */
+    if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG)) {
+        ESP_LOGE(TAG, "JTAG disabled permanently.");
+        return ESP_FAIL;
+    }
+
+    esp_crypto_hmac_lock_acquire();
+
+    ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id));
+
+    if (ets_status != ETS_OK) {
+        // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL
+        err = ESP_FAIL;
+        ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err);
+    }
+
+    ESP_LOGD(TAG, "HMAC computation in downstream mode is completed.");
+
+    ets_hmac_disable();
+
+    esp_crypto_hmac_lock_release();
+
+    return err;
+}
+
+esp_err_t esp_hmac_jtag_disable()
+{
+    esp_crypto_hmac_lock_acquire();
+
+    REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_SET_INVALIDATE_JTAG);
+
+    esp_crypto_hmac_lock_release();
+
+    ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
+
+    return ESP_OK;
+}

+ 9 - 0
components/esp_hw_support/port/esp32c6/esp_memprot.c

@@ -0,0 +1,9 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// TODO: IDF-5684
+// ESP32C6 has no memory permission management mechanism based on dividing lines,
+// TEE-based implementation can be added here

+ 226 - 0
components/esp_hw_support/port/esp32c6/rtc_clk.c

@@ -0,0 +1,226 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "sdkconfig.h"
+#include "esp32c6/rom/ets_sys.h"
+#include "esp32c6/rom/rtc.h"
+#include "soc/rtc.h"
+#include "esp_hw_log.h"
+#include "esp_rom_sys.h"
+#include "hal/usb_serial_jtag_ll.h"
+#include "hal/clk_tree_ll.h"
+#include "hal/regi2c_ctrl_ll.h"
+#include "soc/lp_clkrst_reg.h"
+
+static const char *TAG = "rtc_clk";
+
+void rtc_clk_32k_enable(bool enable)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_clk_32k_enable_external(void)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_clk_32k_bootstrap(uint32_t cycle)
+{
+    // TODO: IDF-5645
+}
+
+bool rtc_clk_32k_enabled(void)
+{
+    // TODO: IDF-5645
+    return 0;
+}
+
+void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
+{
+    // TODO: IDF-5645
+}
+
+bool rtc_clk_8m_enabled(void)
+{
+    // TODO: IDF-5645
+    return 0;
+}
+
+bool rtc_clk_8md256_enabled(void)
+{
+    // TODO: IDF-5645
+    return 0;
+}
+
+void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
+{
+    // TODO: IDF-5645
+}
+
+soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void)
+{
+    // TODO: IDF-5645
+    return REG_GET_FIELD(LP_CLKRST_LP_CLK_CONF_REG, LP_CLKRST_SLOW_CLK_SEL);
+}
+
+uint32_t rtc_clk_slow_freq_get_hz(void)
+{
+    // TODO: IDF-5645
+    switch (rtc_clk_slow_freq_get()) {
+        case RTC_SLOW_FREQ_RTC: return RTC_SLOW_CLK_FREQ_150K;
+        case RTC_SLOW_FREQ_32K_XTAL: return RTC_SLOW_CLK_FREQ_32K;
+        case RTC_SLOW_FREQ_8MD256: return RTC_SLOW_CLK_FREQ_8MD256;
+        default: return 0;
+    }
+}
+
+void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src)
+{
+    // TODO: IDF-5645
+}
+
+soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void)
+{
+    // TODO: IDF-5645
+    return 0;
+}
+
+#if 0
+static void rtc_clk_bbpll_disable(void)
+{
+    // TODO: IDF-5645
+}
+
+static void rtc_clk_bbpll_enable(void)
+{
+    // TODO: IDF-5645
+}
+
+static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
+{
+    // TODO: IDF-5645
+}
+
+/**
+ * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
+ * PLL must already be enabled.
+ * @param cpu_freq new CPU frequency
+ */
+static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
+{
+    // TODO: IDF-5645
+}
+#endif
+
+bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
+{
+    // TODO: IDF-5645
+    return 0;
+}
+
+void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_clk_cpu_freq_set_xtal(void)
+{
+    ESP_EARLY_LOGW(TAG, "rtc_clk_cpu_freq_set_xtal() has not been implemented yet");
+    // TODO: IDF-5645
+}
+
+#if 0
+/**
+ * Switch to XTAL frequency. Does not disable the PLL.
+ */
+static void rtc_clk_cpu_freq_to_xtal(int freq, int div)
+{
+    // TODO: IDF-5645
+}
+
+static void rtc_clk_cpu_freq_to_8m(void)
+{
+    // TODO: IDF-5645
+}
+#endif
+
+rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
+{
+    ESP_EARLY_LOGW(TAG, "rtc_clk_xtal_freq_get() has not been implemented yet");
+    // TODO: IDF-5645
+    return 40;
+}
+
+void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_clk_apb_freq_update(uint32_t apb_freq)
+{
+    // TODO: IDF-5645
+}
+
+uint32_t rtc_clk_apb_freq_get(void)
+{
+    ESP_EARLY_LOGW(TAG, "rtc_clk_apb_freq_get() has not been implemented yet");
+    // TODO: IDF-5645
+    return 0;
+}
+
+void rtc_clk_divider_set(uint32_t div)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_clk_8m_divider_set(uint32_t div)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_dig_clk8m_enable(void)
+{
+    // TODO: IDF-5645
+}
+
+void rtc_dig_clk8m_disable(void)
+{
+    // TODO: IDF-5645
+}
+
+bool rtc_dig_8m_enabled(void)
+{
+    // TODO: IDF-5645
+    return 0;
+}
+
+#if 0
+static bool rtc_clk_set_bbpll_always_on(void)
+{
+    // TODO: IDF-5645
+    return 0;
+}
+#endif
+
+/* Name used in libphy.a:phy_chip_v7.o
+ * TODO: update the library to use rtc_clk_xtal_freq_get
+ */
+rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));

+ 84 - 0
components/esp_hw_support/port/esp32c6/rtc_clk_init.c

@@ -0,0 +1,84 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "esp32c6/rom/ets_sys.h"
+#include "esp32c6/rom/rtc.h"
+#include "esp32c6/rom/uart.h"
+#include "soc/rtc.h"
+#include "soc/efuse_periph.h"
+#include "esp_cpu.h"
+#include "hal/regi2c_ctrl_ll.h"
+#include "esp_hw_log.h"
+#include "sdkconfig.h"
+#include "esp_rom_uart.h"
+
+static const char *TAG = "rtc_clk_init";
+
+void rtc_clk_init(rtc_clk_config_t cfg)
+{
+    ESP_HW_LOGW(TAG, "rtc_clk_init() has not been implemented yet");
+#if 0 // TODO: IDF-5645
+    rtc_cpu_freq_config_t old_config, new_config;
+
+    /* Set tuning parameters for 8M and 150k clocks.
+     * Note: this doesn't attempt to set the clocks to precise frequencies.
+     * Instead, we calibrate these clocks against XTAL frequency later, when necessary.
+     * - SCK_DCAP value controls tuning of 150k clock.
+     *   The higher the value of DCAP is, the lower is the frequency.
+     * - CK8M_DFREQ value controls tuning of 8M clock.
+     *   CLK_8M_DFREQ constant gives the best temperature characteristics.
+     */
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, cfg.slow_clk_dcap);
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq);
+
+    /* Configure 150k clock division */
+    rtc_clk_divider_set(cfg.clk_rtc_clk_div);
+
+    /* Configure 8M clock division */
+    rtc_clk_8m_divider_set(cfg.clk_8m_clk_div);
+
+    /* Reset (disable) i2c internal bus for all regi2c registers */
+    regi2c_ctrl_ll_i2c_reset(); // TODO: This should be move out from rtc_clk_init
+    /* Enable the internal bus used to configure BBPLL */
+    regi2c_ctrl_ll_i2c_bbpll_enable(); // TODO: This should be moved to bbpll_set_config
+
+    rtc_xtal_freq_t xtal_freq = cfg.xtal_freq;
+    esp_rom_uart_tx_wait_idle(0);
+    rtc_clk_xtal_freq_update(xtal_freq);
+    rtc_clk_apb_freq_update(xtal_freq * MHZ);
+
+    /* Set CPU frequency */
+    rtc_clk_cpu_freq_get_config(&old_config);
+    uint32_t freq_before = old_config.freq_mhz;
+    bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config);
+    if (!res) {
+        ESP_HW_LOGE(TAG, "invalid CPU frequency value");
+        abort();
+    }
+    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() * cfg.cpu_freq_mhz / freq_before );
+
+    /* Slow & fast clocks setup */
+    // We will not power off RC_FAST in bootloader stage even if it is not being used as any
+    // cpu / rtc_fast / rtc_slow clock sources, this is because RNG always needs it in the bootloader stage.
+    bool need_rc_fast_en = true;
+    bool need_rc_fast_d256_en = false;
+    if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
+        rtc_clk_32k_enable(true);
+    } else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) {
+        need_rc_fast_d256_en = true;
+    }
+    rtc_clk_8m_enable(need_rc_fast_en, need_rc_fast_d256_en);
+    rtc_clk_fast_src_set(cfg.fast_clk_src);
+    rtc_clk_slow_src_set(cfg.slow_clk_src);
+#endif
+}

+ 7 - 0
components/esp_hw_support/port/esp32c6/rtc_init.c

@@ -0,0 +1,7 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// TODO: IDF-5645

+ 7 - 0
components/esp_hw_support/port/esp32c6/rtc_pm.c

@@ -0,0 +1,7 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// TODO: IDF-5645

+ 7 - 0
components/esp_hw_support/port/esp32c6/rtc_sleep.c

@@ -0,0 +1,7 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// TODO: IDF-5645

+ 103 - 0
components/esp_hw_support/port/esp32c6/rtc_time.c

@@ -0,0 +1,103 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include "esp32c6/rom/ets_sys.h"
+#include "soc/rtc.h"
+// #include "soc/rtc_cntl_reg.h"
+#include "hal/clk_tree_ll.h"
+#include "soc/timer_group_reg.h"
+#include "esp_rom_sys.h"
+
+/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
+ * This feature counts the number of XTAL clock cycles within a given number of
+ * RTC_SLOW_CLK cycles.
+ *
+ * Slow clock calibration feature has two modes of operation: one-off and cycling.
+ * In cycling mode (which is enabled by default on SoC reset), counting of XTAL
+ * cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
+ * using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
+ * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
+ * enabled using TIMG_RTC_CALI_START bit.
+ */
+
+/**
+ * @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
+ * @param cal_clk which clock to calibrate
+ * @param slowclk_cycles number of slow clock cycles to count
+ * @return number of XTAL clock cycles within the given number of slow clock cycles
+ */
+// TODO: IDF-5645
+static const char *TAG = "rtc_time";
+
+uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_clk_cal_internal() has not been implemented yet");
+    return 0;
+}
+
+uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_clk_cal_ratio() has not been implemented yet");
+    return 0;
+}
+
+uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_clk_cal() has not been implemented yet");
+    return 0;
+}
+
+uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_time_us_to_slowclk() has not been implemented yet");
+    return 0;
+}
+
+uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_time_slowclk_to_us() has not been implemented yet");
+    return 0;
+}
+
+uint64_t rtc_time_get(void)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_time_get() has not been implemented yet");
+    return 0;
+}
+
+uint64_t rtc_light_slp_time_get(void)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_light_slp_time_get() has not been implemented yet");
+    return 0;
+}
+
+uint64_t rtc_deep_slp_time_get(void)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_deep_slp_time_get() has not been implemented yet");
+    return 0;
+}
+
+void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any more
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_clk_wait_for_slow_cycle() has not been implemented yet");
+}
+
+uint32_t rtc_clk_freq_cal(uint32_t cal_val)
+{
+    // TODO: IDF-5645
+    ESP_EARLY_LOGW(TAG, "rtc_clk_freq_cal() has not been implemented yet");
+    return 0;
+}

+ 22 - 0
components/esp_hw_support/port/esp32c6/systimer.c

@@ -0,0 +1,22 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_private/systimer.h"
+
+/**
+ * @brief systimer's clock source is fixed to XTAL (40MHz), and has a fixed fractional divider (2.5).
+ *        So the resolution of the systimer is 40MHz/2.5 = 16MHz.
+ */
+
+uint64_t systimer_ticks_to_us(uint64_t ticks)
+{
+    return ticks / 16;
+}
+
+uint64_t systimer_us_to_ticks(uint64_t us)
+{
+    return us * 16;
+}

+ 24 - 0
components/esp_hw_support/rtc_module.c

@@ -27,6 +27,12 @@
 #endif
 #include "sys/queue.h"
 
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
+static const char *TAG = "rtc_module";
+#endif
+
+#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
+
 #define NOT_REGISTERED      (-1)
 
 portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
@@ -90,9 +96,14 @@ out:
     portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
     return err;
 }
+#endif // !CONFIG_IDF_TARGET_ESP32C6 TODO: IDF-5645
 
 esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t rtc_intr_mask, uint32_t flags)
 {
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
+    ESP_LOGW(TAG, "rtc_isr_register() has not been implemented yet");
+    return ESP_OK;
+#else
     esp_err_t err = rtc_isr_ensure_installed();
     if (err != ESP_OK) {
         return err;
@@ -115,10 +126,15 @@ esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t r
     SLIST_INSERT_HEAD(&s_rtc_isr_handler_list, item, next);
     portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
     return ESP_OK;
+#endif
 }
 
 esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
 {
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
+    ESP_LOGW(TAG, "rtc_isr_deregister() has not been implemented yet");
+    return ESP_OK;
+#else
     rtc_isr_handler_t* it;
     rtc_isr_handler_t* prev = NULL;
     bool found = false;
@@ -141,8 +157,10 @@ esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
     }
     portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
     return found ? ESP_OK : ESP_ERR_INVALID_STATE;
+#endif
 }
 
+#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
 /**
  * @brief This helper function can be used to avoid the interrupt to be triggered with cache disabled.
  *        There are lots of different signals on RTC module (i.e. sleep_wakeup, wdt, brownout_detect, etc.)
@@ -160,19 +178,25 @@ static void s_rtc_isr_noniram_hook_relieve(uint32_t rtc_intr_mask)
 {
     rtc_intr_cache &= ~rtc_intr_mask;
 }
+#endif
+
 
 IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu)
 {
+#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
     if (rtc_isr_cpu == cpu) {
         rtc_intr_enabled |= RTCCNTL.int_ena.val;
         RTCCNTL.int_ena.val &= rtc_intr_cache;
     }
+#endif
 }
 
 IRAM_ATTR void rtc_isr_noniram_enable(uint32_t cpu)
 {
+#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
     if (rtc_isr_cpu == cpu) {
         RTCCNTL.int_ena.val = rtc_intr_enabled;
         rtc_intr_enabled = 0;
     }
+#endif
 }

+ 15 - 0
components/esp_hw_support/sleep_modes.c

@@ -78,6 +78,10 @@
 #include "esp32c2/rom/cache.h"
 #include "esp32c2/rom/rtc.h"
 #include "soc/extmem_reg.h"
+#elif CONFIG_IDF_TARGET_ESP32C6
+#include "esp32c6/rom/cache.h"
+#include "esp32c6/rom/rtc.h"
+#include "soc/extmem_reg.h"
 #endif
 
 // If light sleep time is less than that, don't power down flash
@@ -107,6 +111,9 @@
 #elif CONFIG_IDF_TARGET_ESP32C2
 #define DEFAULT_SLEEP_OUT_OVERHEAD_US       (118)
 #define DEFAULT_HARDWARE_OUT_OVERHEAD_US    (9)
+#elif CONFIG_IDF_TARGET_ESP32C6
+#define DEFAULT_SLEEP_OUT_OVERHEAD_US       (118)// TODO: IDF-5348
+#define DEFAULT_HARDWARE_OUT_OVERHEAD_US    (9)
 #endif
 
 #define LIGHT_SLEEP_TIME_OVERHEAD_US        DEFAULT_HARDWARE_OUT_OVERHEAD_US
@@ -789,7 +796,11 @@ esp_err_t esp_light_sleep_start(void)
     rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
 
     // Safety net: enable WDT in case exit from light sleep fails
+#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
     bool wdt_was_enabled = wdt_hal_is_enabled(&rtc_wdt_ctx);    // If WDT was enabled in the user code, then do not change it here.
     if (!wdt_was_enabled) {
         wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
@@ -1231,6 +1242,9 @@ esp_err_t esp_sleep_disable_bt_wakeup(void)
 
 esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
 {
+#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5645
+    return ESP_SLEEP_WAKEUP_UNDEFINED;
+#else
     if (esp_rom_get_reset_reason(0) != RESET_REASON_CORE_DEEP_SLEEP && !s_light_sleep_wakeup) {
         return ESP_SLEEP_WAKEUP_UNDEFINED;
     }
@@ -1278,6 +1292,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
     } else {
         return ESP_SLEEP_WAKEUP_UNDEFINED;
     }
+#endif
 }
 
 esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,