فهرست منبع

Merge branch 'feature/add_esp32h2_target' into 'master'

esp32h2: add esp32h2 build target

See merge request espressif/esp-idf!13944
Michael (XIAO Xufeng) 4 سال پیش
والد
کامیت
0e31332693
100فایلهای تغییر یافته به همراه9568 افزوده شده و 23 حذف شده
  1. 9 0
      Kconfig
  2. 1 1
      components/bootloader/subproject/main/CMakeLists.txt
  3. 189 0
      components/bootloader/subproject/main/ld/esp32h2/bootloader.ld
  4. 4 1
      components/bootloader_support/component.mk
  5. 2 0
      components/bootloader_support/include/bootloader_common.h
  6. 1 0
      components/bootloader_support/include/esp_app_format.h
  7. 3 0
      components/bootloader_support/include/esp_secure_boot.h
  8. 2 0
      components/bootloader_support/src/bootloader_clock_init.c
  9. 2 0
      components/bootloader_support/src/bootloader_common.c
  10. 3 0
      components/bootloader_support/src/bootloader_console.c
  11. 20 0
      components/bootloader_support/src/bootloader_efuse_esp32h2.c
  12. 31 1
      components/bootloader_support/src/bootloader_flash.c
  13. 75 0
      components/bootloader_support/src/bootloader_flash_config_esp32h2.c
  14. 24 0
      components/bootloader_support/src/bootloader_random_esp32h2.c
  15. 24 0
      components/bootloader_support/src/bootloader_utility.c
  16. 327 0
      components/bootloader_support/src/esp32h2/bootloader_esp32h2.c
  17. 40 0
      components/bootloader_support/src/esp32h2/bootloader_sha.c
  18. 346 0
      components/bootloader_support/src/esp32h2/flash_encrypt.c
  19. 289 0
      components/bootloader_support/src/esp32h2/secure_boot.c
  20. 3 0
      components/bootloader_support/src/esp_image_format.c
  21. 2 2
      components/bootloader_support/src/flash_encrypt.c
  22. 2 0
      components/bootloader_support/src/flash_partitions.c
  23. 2 0
      components/bootloader_support/src/flash_qio_mode.c
  24. 9 0
      components/driver/CMakeLists.txt
  25. 717 0
      components/driver/esp32h2/adc.c
  26. 31 0
      components/driver/esp32h2/adc2_init_cal.c
  27. 93 0
      components/driver/esp32h2/include/driver/adc.h
  28. 91 0
      components/driver/esp32h2/include/driver/temp_sensor.h
  29. 151 0
      components/driver/esp32h2/rtc_tempsensor.c
  30. 1 1
      components/driver/include/driver/adc2_wifi_private.h
  31. 10 10
      components/driver/include/driver/adc_common.h
  32. 2 0
      components/driver/include/driver/gpio.h
  33. 2 0
      components/driver/periph_ctrl.c
  34. 2 0
      components/driver/uart.c
  35. 63 0
      components/efuse/esp32h2/esp_efuse_fields.c
  36. 89 0
      components/efuse/esp32h2/esp_efuse_rtc_calib.c
  37. 1128 0
      components/efuse/esp32h2/esp_efuse_table.c
  38. 165 0
      components/efuse/esp32h2/esp_efuse_table.csv
  39. 141 0
      components/efuse/esp32h2/esp_efuse_utility.c
  40. 79 0
      components/efuse/esp32h2/include/esp_efuse.h
  41. 54 0
      components/efuse/esp32h2/include/esp_efuse_rtc_calib.h
  42. 144 0
      components/efuse/esp32h2/include/esp_efuse_table.h
  43. 21 0
      components/efuse/esp32h2/private_include/esp_efuse_utility.h
  44. 4 0
      components/efuse/esp32h2/sources.cmake
  45. 2 0
      components/efuse/include/esp_efuse.h
  46. 1 1
      components/esp-tls/Kconfig
  47. 66 0
      components/esp32h2/CMakeLists.txt
  48. 205 0
      components/esp32h2/Kconfig
  49. 1 0
      components/esp32h2/Makefile.projbuild
  50. 4 0
      components/esp32h2/component.mk
  51. 25 0
      components/esp32h2/dport_access.c
  52. 83 0
      components/esp32h2/esp_crypto_lock.c
  53. 232 0
      components/esp32h2/esp_ds.c
  54. 132 0
      components/esp32h2/esp_hmac.c
  55. 42 0
      components/esp32h2/include/esp32h2/dport_access.h
  56. 455 0
      components/esp32h2/include/esp32h2/memprot.h
  57. 40 0
      components/esp32h2/include/esp32h2/rtc.h
  58. 76 0
      components/esp32h2/include/esp_crypto_lock.h
  59. 218 0
      components/esp32h2/include/esp_ds.h
  60. 67 0
      components/esp32h2/include/esp_hmac.h
  61. 118 0
      components/esp32h2/ld/esp32h2.ld
  62. 30 0
      components/esp32h2/ld/esp32h2.peripherals.ld
  63. 392 0
      components/esp32h2/ld/esp32h2.project.ld.in
  64. 616 0
      components/esp32h2/memprot.c
  65. 5 0
      components/esp32h2/project_include.cmake
  66. 9 0
      components/esp32h2/test/CMakeLists.txt
  67. 4 0
      components/esp32h2/test/component.mk
  68. 49 0
      components/esp32h2/test/digital_signature_test_cases.h
  69. 382 0
      components/esp32h2/test/test_ds.c
  70. 80 0
      components/esp32h2/test/test_sha.c
  71. 5 0
      components/esp_adc_cal/CMakeLists.txt
  72. 1 1
      components/esp_adc_cal/component.mk
  73. 170 0
      components/esp_adc_cal/esp_adc_cal_esp32h2.c
  74. 7 1
      components/esp_event/event_send.c
  75. 124 0
      components/esp_gdbstub/esp32h2/gdbstub_esp32h2.c
  76. 15 0
      components/esp_gdbstub/esp32h2/gdbstub_target_config.h
  77. 2 1
      components/esp_hw_support/cpu_util.c
  78. 6 2
      components/esp_hw_support/esp_clk.c
  79. 2 0
      components/esp_hw_support/hw_random.c
  80. 2 0
      components/esp_hw_support/include/esp_chip_info.h
  81. 3 0
      components/esp_hw_support/include/esp_mac.h
  82. 16 0
      components/esp_hw_support/include/soc/esp32h2/clk.h
  83. 2 0
      components/esp_hw_support/include/soc_log.h
  84. 1 1
      components/esp_hw_support/linker.lf
  85. 24 0
      components/esp_hw_support/port/esp32h2/CMakeLists.txt
  86. 18 0
      components/esp_hw_support/port/esp32h2/Kconfig.mac
  87. 26 0
      components/esp_hw_support/port/esp32h2/chip_info.c
  88. 112 0
      components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.c
  89. 30 0
      components/esp_hw_support/port/esp32h2/i2c_brownout.h
  90. 48 0
      components/esp_hw_support/port/esp32h2/i2c_rtc_clk.h
  91. 183 0
      components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h
  92. 30 0
      components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h
  93. 30 0
      components/esp_hw_support/port/esp32h2/private_include/regi2c_brownout.h
  94. 68 0
      components/esp_hw_support/port/esp32h2/private_include/regi2c_dig_reg.h
  95. 63 0
      components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h
  96. 87 0
      components/esp_hw_support/port/esp32h2/private_include/regi2c_saradc.h
  97. 109 0
      components/esp_hw_support/port/esp32h2/regi2c_ctrl.h
  98. 507 0
      components/esp_hw_support/port/esp32h2/rtc_clk.c
  99. 57 0
      components/esp_hw_support/port/esp32h2/rtc_clk_common.h
  100. 88 0
      components/esp_hw_support/port/esp32h2/rtc_clk_init.c

+ 9 - 0
Kconfig

@@ -11,6 +11,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
     config IDF_ENV_FPGA
         # This option is for internal use only
         bool
+        default "y" if IDF_TARGET="esp32h2" # ESP32H2-TODO: IDF-3378
         option env="IDF_ENV_FPGA"
 
     config IDF_TARGET_ARCH_RISCV
@@ -51,6 +52,12 @@ mainmenu "Espressif IoT Development Framework Configuration"
         select FREERTOS_UNICORE
         select IDF_TARGET_ARCH_RISCV
 
+    config IDF_TARGET_ESP32H2
+        bool
+        default "y" if IDF_TARGET="esp32h2"
+        select FREERTOS_UNICORE
+        select IDF_TARGET_ARCH_RISCV
+
     config IDF_TARGET_LINUX
         bool
         default "y" if IDF_TARGET="linux"
@@ -61,6 +68,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
         default 0x0002 if IDF_TARGET_ESP32S2
         default 0x0005 if IDF_TARGET_ESP32C3
         default 0x0009 if IDF_TARGET_ESP32S3
+        default 0x000A if IDF_TARGET_ESP32H2 # ESP32H2-TODO: IDF-3475
         default 0xFFFF
 
     menu "SDK tool configuration"
@@ -70,6 +78,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
             default "xtensa-esp32s2-elf-" if IDF_TARGET_ESP32S2
             default "xtensa-esp32s3-elf-" if IDF_TARGET_ESP32S3
             default "riscv32-esp-elf-" if IDF_TARGET_ESP32C3
+            default "riscv32-esp-elf-" if IDF_TARGET_ESP32H2
 
             help
                 The prefix/path that is used to call the toolchain. The default setting assumes

+ 1 - 1
components/bootloader/subproject/main/CMakeLists.txt

@@ -4,7 +4,7 @@ idf_component_register(SRCS "bootloader_start.c"
 idf_build_get_property(target IDF_TARGET)
 set(scripts "ld/${target}/bootloader.ld")
 
-if(NOT CONFIG_IDF_TARGET_ESP32C3)
+if(NOT CONFIG_IDF_TARGET_ESP32C3 AND NOT CONFIG_IDF_TARGET_ESP32H2)
     list(APPEND scripts "ld/${target}/bootloader.rom.ld")
 endif()
 

+ 189 - 0
components/bootloader/subproject/main/ld/esp32h2/bootloader.ld

@@ -0,0 +1,189 @@
+/** Simplified memory map for the bootloader.
+ *  Make sure the bootloader can load into main memory without overwriting itself.
+ *  We put 2nd bootloader in the high address space (before ROM stack/data/bss).
+ *  See memory usage for ROM bootloader at the end of this file.
+ */
+
+MEMORY
+{
+  iram_seg (RWX) :                  org = 0x403CE000, len = 0x2000
+  iram_loader_seg (RWX) :           org = 0x403D0000, len = 0x6000
+  dram_seg (RW) :                   org = 0x3FCD6000, len = 0x4000
+}
+
+/* Default entry point: */
+ENTRY(call_start_cpu0);
+
+SECTIONS
+{
+
+  .iram_loader.text :
+  {
+    . = ALIGN (16);
+    _loader_text_start = ABSOLUTE(.);
+    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+     *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
+    *liblog.a:(.literal .text .literal.* .text.*)
+    *libgcc.a:(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
+    *libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
+    *libbootloader_support.a:bootloader_efuse_esp32h2.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
+    *libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
+    *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
+    *libspi_flash.a:*.*(.literal .text .literal.* .text.*)
+    *libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
+    *libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
+    *libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
+    *libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
+    *libefuse.a:*.*(.literal .text .literal.* .text.*)
+    *(.fini.literal)
+    *(.fini)
+    *(.gnu.version)
+    _loader_text_end = ABSOLUTE(.);
+  } > iram_loader_seg
+
+  .iram.text :
+  {
+    . = ALIGN (16);
+    *(.entry.text)
+    *(.init.literal)
+    *(.init)
+  } > iram_seg
+
+
+  /* Shared RAM */
+  .dram0.bss (NOLOAD) :
+  {
+    . = ALIGN (8);
+    _dram_start = ABSOLUTE(.);
+    _bss_start = ABSOLUTE(.);
+    *(.dynsbss)
+    *(.sbss)
+    *(.sbss.*)
+    *(.gnu.linkonce.sb.*)
+    *(.scommon)
+    *(.sbss2)
+    *(.sbss2.*)
+    *(.gnu.linkonce.sb2.*)
+    *(.dynbss)
+    *(.bss)
+    *(.bss.*)
+    *(.gnu.linkonce.b.*)
+    *(COMMON)
+    . = ALIGN (8);
+    _bss_end = ABSOLUTE(.);
+  } > dram_seg
+
+  .dram0.data :
+  {
+    _data_start = ABSOLUTE(.);
+    *(.data)
+    *(.data.*)
+    *(.gnu.linkonce.d.*)
+    *(.data1)
+    *(.sdata)
+    *(.sdata.*)
+    *(.gnu.linkonce.s.*)
+    *(.sdata2)
+    *(.sdata2.*)
+    *(.gnu.linkonce.s2.*)
+    *(.jcr)
+    _data_end = ABSOLUTE(.);
+  } > dram_seg
+
+  .dram0.rodata :
+  {
+    _rodata_start = ABSOLUTE(.);
+    *(.rodata)
+    *(.rodata.*)
+    *(.gnu.linkonce.r.*)
+    *(.rodata1)
+    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
+    *(.xt_except_table)
+    *(.gcc_except_table)
+    *(.gnu.linkonce.e.*)
+    *(.gnu.version_r)
+    *(.eh_frame)
+    . = (. + 3) & ~ 3;
+    /* C++ constructor and destructor tables, properly ordered: */
+    __init_array_start = ABSOLUTE(.);
+    KEEP (*crtbegin.*(.ctors))
+    KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+    __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)
+    _rodata_end = ABSOLUTE(.);
+    /* Literals are also RO data. */
+    _lit4_start = ABSOLUTE(.);
+    *(*.lit4)
+    *(.lit4.*)
+    *(.gnu.linkonce.lit4.*)
+    _lit4_end = ABSOLUTE(.);
+    . = ALIGN(4);
+    _dram_end = ABSOLUTE(.);
+  } > dram_seg
+
+  .iram.text :
+  {
+    _stext = .;
+    _text_start = ABSOLUTE(.);
+    *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+    *(.iram .iram.*) /* catch stray IRAM_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
+      */
+    . += 16;
+
+    _text_end = ABSOLUTE(.);
+    _etext = .;
+  } > iram_seg
+
+}
+
+/**
+ *  Appendix: Memory Usage of ROM bootloader
+ *
+ *  +--------+--------------+------+ 0x3FCC_B900
+ *  |        ^              |
+ *  |        |              |
+ *  |        | data/bss     |
+ *  |        |              |
+ *  |        v              |
+ *  +------------------------------+ 0x3FCD_D210
+ *  |        ^              |
+ *  |        |              |
+ *  |        | stack        |
+ *  |        |              |
+ *  |        v              |
+ *  +------------------------------+ 0x3FCD_F210
+ */

+ 4 - 1
components/bootloader_support/component.mk

@@ -31,12 +31,15 @@ endif
 COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \
 			src/bootloader_flash_config_esp32s3.o \
 			src/bootloader_flash_config_esp32c3.o \
+			src/bootloader_flash_config_esp32h2.o \
 			src/bootloader_efuse_esp32s2.o \
 			src/bootloader_efuse_esp32s3.o \
 			src/bootloader_efuse_esp32c3.o \
+			src/bootloader_efuse_esp32h2.o \
 			src/bootloader_random_esp32s2.o \
 			src/bootloader_random_esp32s3.o \
-			src/bootloader_random_esp32c3.o
+			src/bootloader_random_esp32c3.o \
+			src/bootloader_random_esp32h2.o
 
 ifdef IS_BOOTLOADER_BUILD
 	ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME

+ 2 - 0
components/bootloader_support/include/bootloader_common.h

@@ -17,6 +17,8 @@
 #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"
 #endif
 
 #ifdef __cplusplus

+ 1 - 0
components/bootloader_support/include/esp_app_format.h

@@ -16,6 +16,7 @@ typedef enum {
     ESP_CHIP_ID_ESP32S2 = 0x0002,  /*!< chip ID: ESP32-S2 */
     ESP_CHIP_ID_ESP32C3 = 0x0005, /*!< chip ID: ESP32-C3 */
     ESP_CHIP_ID_ESP32S3 = 0x0009, /*!< chip ID: ESP32-S3 */
+    ESP_CHIP_ID_ESP32H2 = 0x000A, /*!< chip ID: ESP32-H2 */  // ESP32H2-TODO: IDF-3475
     ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
 } __attribute__((packed)) esp_chip_id_t;
 

+ 3 - 0
components/bootloader_support/include/esp_secure_boot.h

@@ -25,6 +25,9 @@
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/efuse.h"
 #include "esp32s3/rom/secure_boot.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/secure_boot.h"
 #endif
 
 #ifdef CONFIG_SECURE_BOOT_V1_ENABLED

+ 2 - 0
components/bootloader_support/src/bootloader_clock_init.c

@@ -22,6 +22,8 @@
 #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"
 #endif
 #include "esp_rom_uart.h"
 

+ 2 - 0
components/bootloader_support/src/bootloader_common.c

@@ -17,6 +17,8 @@
 #include "esp32s3/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #endif
 #include "esp_rom_crc.h"
 #include "esp_rom_gpio.h"

+ 3 - 0
components/bootloader_support/src/bootloader_console.c

@@ -22,6 +22,9 @@
 #include "esp32c3/rom/uart.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/uart.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/uart.h"
 #endif
 #include "esp_rom_gpio.h"
 #include "esp_rom_uart.h"

+ 20 - 0
components/bootloader_support/src/bootloader_efuse_esp32h2.c

@@ -0,0 +1,20 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+#include "soc/efuse_reg.h"
+
+uint8_t bootloader_common_get_chip_revision(void)
+{
+    // should return the same value as esp_efuse_get_chip_ver()
+    return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_WAFER_VERSION);
+}
+
+uint32_t bootloader_common_get_chip_ver_pkg(void)
+{
+    // should return the same value as esp_efuse_get_pkg_ver()
+    return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
+}

+ 31 - 1
components/bootloader_support/src/bootloader_flash.c

@@ -29,6 +29,8 @@
 #include "esp32s3/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #endif
 
 #ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
@@ -124,6 +126,10 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
 #include "esp32c3/rom/spi_flash.h"
 #include "esp32c3/rom/cache.h"
 #include "soc/cache_memory.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/cache.h"
+#include "soc/cache_memory.h"
 #endif
 static const char *TAG = "bootloader_flash";
 
@@ -188,6 +194,9 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
 #elif CONFIG_IDF_TARGET_ESP32C3
     uint32_t autoload = Cache_Suspend_ICache();
     Cache_Invalidate_ICache_All();
+#elif CONFIG_IDF_TARGET_ESP32H2
+    uint32_t autoload = Cache_Suspend_ICache();
+    Cache_Invalidate_ICache_All();
 #endif
     ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
              src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
@@ -195,7 +204,7 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
     int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
 #elif CONFIG_IDF_TARGET_ESP32S2
     int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
-#else // S3, C3
+#else // S3, C3, H2
     int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
 #endif
     if (e != 0) {
@@ -208,6 +217,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
         Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
         Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+        Cache_Resume_ICache(autoload);
 #endif
         return NULL;
     }
@@ -219,6 +230,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
     Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
     Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    Cache_Resume_ICache(autoload);
 #endif
 
     mapped = true;
@@ -248,6 +261,10 @@ void bootloader_munmap(const void *mapping)
         Cache_Suspend_ICache();
         Cache_Invalidate_ICache_All();
         Cache_MMU_Init();
+#elif CONFIG_IDF_TARGET_ESP32H2
+        Cache_Suspend_ICache();
+        Cache_Invalidate_ICache_All();
+        Cache_MMU_Init();
 #endif
         mapped = false;
         current_read_mapping = UINT32_MAX;
@@ -279,6 +296,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
     uint32_t autoload = Cache_Suspend_DCache();
 #elif CONFIG_IDF_TARGET_ESP32C3
     uint32_t autoload = Cache_Suspend_ICache();
+#elif CONFIG_IDF_TARGET_ESP32H2
+    uint32_t autoload = Cache_Suspend_ICache();
 #endif
     esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
 #if CONFIG_IDF_TARGET_ESP32
@@ -289,6 +308,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
     Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
     Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    Cache_Resume_ICache(autoload);
 #endif
 
     return spi_to_esp_err(r);
@@ -316,6 +337,9 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
 #elif CONFIG_IDF_TARGET_ESP32C3
             uint32_t autoload = Cache_Suspend_ICache();
             Cache_Invalidate_ICache_All();
+#elif CONFIG_IDF_TARGET_ESP32H2
+            uint32_t autoload = Cache_Suspend_ICache();
+            Cache_Invalidate_ICache_All();
 #endif
             ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
 #if CONFIG_IDF_TARGET_ESP32
@@ -326,6 +350,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
             int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
 #elif CONFIG_IDF_TARGET_ESP32C3
             int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
+#elif CONFIG_IDF_TARGET_ESP32H2
+            int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
 #endif
             if (e != 0) {
                 ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
@@ -337,6 +363,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
                 Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
                 Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+                Cache_Resume_ICache(autoload);
 #endif
                 return ESP_FAIL;
             }
@@ -349,6 +377,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
             Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
             Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+            Cache_Resume_ICache(autoload);
 #endif
         }
         map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));

+ 75 - 0
components/bootloader_support/src/bootloader_flash_config_esp32h2.c

@@ -0,0 +1,75 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdbool.h>
+#include <assert.h>
+#include "string.h"
+#include "sdkconfig.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp32h2/rom/gpio.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/efuse.h"
+#include "soc/gpio_periph.h"
+#include "soc/efuse_reg.h"
+#include "soc/spi_reg.h"
+#include "soc/spi_mem_reg.h"
+#include "soc/soc_caps.h"
+#include "flash_qio_mode.h"
+#include "bootloader_flash_config.h"
+#include "bootloader_common.h"
+
+#define FLASH_IO_MATRIX_DUMMY_40M   0
+#define FLASH_IO_MATRIX_DUMMY_80M   0
+
+void bootloader_flash_update_id()
+{
+    esp_rom_spiflash_chip_t *chip = &rom_spiflash_legacy_data->chip;
+    chip->device_id = bootloader_read_flash_id();
+}
+
+void IRAM_ATTR bootloader_flash_cs_timing_config()
+{
+    SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
+    SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
+    SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
+    SET_PERI_REG_MASK(SPI_MEM_USER_REG(1), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
+    SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S);
+    SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
+}
+
+void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
+{
+    uint32_t spi_clk_div = 0;
+    switch (pfhdr->spi_speed) {
+    case ESP_IMAGE_SPI_SPEED_80M:
+        spi_clk_div = 1;
+        break;
+    case ESP_IMAGE_SPI_SPEED_40M:
+        spi_clk_div = 2;
+        break;
+    case ESP_IMAGE_SPI_SPEED_26M:
+        spi_clk_div = 3;
+        break;
+    case ESP_IMAGE_SPI_SPEED_20M:
+        spi_clk_div = 4;
+        break;
+    default:
+        break;
+    }
+    esp_rom_spiflash_config_clk(spi_clk_div, 0);
+}
+
+void IRAM_ATTR bootloader_flash_set_dummy_out(void)
+{
+    REG_SET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
+    REG_SET_BIT(SPI_MEM_CTRL_REG(1), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
+}
+
+void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t *pfhdr)
+{
+    bootloader_configure_spi_pins(1);
+    bootloader_flash_set_dummy_out();
+}

+ 24 - 0
components/bootloader_support/src/bootloader_random_esp32h2.c

@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "sdkconfig.h"
+#include "bootloader_random.h"
+#include "esp_log.h"
+#include "soc/syscon_reg.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/apb_saradc_reg.h"
+#include "soc/system_reg.h"
+#include "regi2c_ctrl.h"
+
+// ESP32H2-TODO: IDF-3381
+void bootloader_random_enable(void)
+{
+
+}
+
+void bootloader_random_disable(void)
+{
+
+}

+ 24 - 0
components/bootloader_support/src/bootloader_utility.c

@@ -45,6 +45,18 @@
 #include "esp32c3/rom/secure_boot.h"
 #include "soc/extmem_reg.h"
 #include "soc/cache_memory.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/cache.h"
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/crc.h"
+#include "esp32h2/rom/rtc.h"
+#include "esp32h2/rom/uart.h"
+#include "esp32h2/rom/gpio.h"
+#include "esp32h2/rom/secure_boot.h"
+#include "soc/extmem_reg.h"
+#include "soc/cache_memory.h"
 #else // CONFIG_IDF_TARGET_*
 #error "Unsupported IDF_TARGET"
 #endif
@@ -700,6 +712,9 @@ static void set_cache_and_start_app(
 #elif CONFIG_IDF_TARGET_ESP32C3
     uint32_t autoload = Cache_Suspend_ICache();
     Cache_Invalidate_ICache_All();
+#elif CONFIG_IDF_TARGET_ESP32H2
+    uint32_t autoload = Cache_Suspend_ICache();
+    Cache_Invalidate_ICache_All();
 #endif
 
     /* Clear the MMU entries that are already set up,
@@ -726,6 +741,8 @@ static void set_cache_and_start_app(
     rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
 #elif CONFIG_IDF_TARGET_ESP32C3
     rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
 #endif
     ESP_LOGV(TAG, "rc=%d", rc);
 #if CONFIG_IDF_TARGET_ESP32
@@ -753,6 +770,8 @@ static void set_cache_and_start_app(
     rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
 #elif CONFIG_IDF_TARGET_ESP32C3
     rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
 #endif
     ESP_LOGV(TAG, "rc=%d", rc);
 #if CONFIG_IDF_TARGET_ESP32
@@ -776,6 +795,9 @@ static void set_cache_and_start_app(
 #elif CONFIG_IDF_TARGET_ESP32C3
     REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
     REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
 #endif
 #if CONFIG_IDF_TARGET_ESP32
     Cache_Read_Enable(0);
@@ -785,6 +807,8 @@ static void set_cache_and_start_app(
     Cache_Resume_DCache(autoload);
 #elif CONFIG_IDF_TARGET_ESP32C3
     Cache_Resume_ICache(autoload);
+#elif CONFIG_IDF_TARGET_ESP32H2
+    Cache_Resume_ICache(autoload);
 #endif
     // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
 

+ 327 - 0
components/bootloader_support/src/esp32h2/bootloader_esp32h2.c

@@ -0,0 +1,327 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <stdint.h>
+#include "sdkconfig.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_image_format.h"
+#include "flash_qio_mode.h"
+#include "esp_rom_gpio.h"
+#include "esp_rom_efuse.h"
+#include "esp_rom_uart.h"
+#include "esp_rom_sys.h"
+#include "soc/efuse_reg.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/io_mux_reg.h"
+#include "soc/assist_debug_reg.h"
+#include "soc/cpu.h"
+#include "soc/rtc.h"
+#include "soc/spi_periph.h"
+#include "soc/extmem_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/system_reg.h"
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/cache.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/spi_flash.h"
+#include "esp32h2/rom/rtc.h"
+#include "bootloader_common.h"
+#include "bootloader_init.h"
+#include "bootloader_clock.h"
+#include "bootloader_flash_config.h"
+#include "bootloader_mem.h"
+#include "regi2c_ctrl.h"
+#include "bootloader_console.h"
+#include "bootloader_flash_priv.h"
+
+static const char *TAG = "boot.esp32h2";
+
+void IRAM_ATTR bootloader_configure_spi_pins(int drv)
+{
+    const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
+    uint8_t wp_pin = esp_rom_efuse_get_flash_wp_gpio();
+    uint8_t clk_gpio_num = SPI_CLK_GPIO_NUM;
+    uint8_t q_gpio_num   = SPI_Q_GPIO_NUM;
+    uint8_t d_gpio_num   = SPI_D_GPIO_NUM;
+    uint8_t cs0_gpio_num = SPI_CS0_GPIO_NUM;
+    uint8_t hd_gpio_num  = SPI_HD_GPIO_NUM;
+    uint8_t wp_gpio_num  = SPI_WP_GPIO_NUM;
+    if (spiconfig == 0) {
+
+    } else {
+        clk_gpio_num = spiconfig         & 0x3f;
+        q_gpio_num = (spiconfig >> 6)    & 0x3f;
+        d_gpio_num = (spiconfig >> 12)   & 0x3f;
+        cs0_gpio_num = (spiconfig >> 18) & 0x3f;
+        hd_gpio_num = (spiconfig >> 24)  & 0x3f;
+        wp_gpio_num = wp_pin;
+    }
+    esp_rom_gpio_pad_set_drv(clk_gpio_num, drv);
+    esp_rom_gpio_pad_set_drv(q_gpio_num,   drv);
+    esp_rom_gpio_pad_set_drv(d_gpio_num,   drv);
+    esp_rom_gpio_pad_set_drv(cs0_gpio_num, drv);
+    if (hd_gpio_num <= MAX_PAD_GPIO_NUM) {
+        esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
+    }
+    if (wp_gpio_num <= MAX_PAD_GPIO_NUM) {
+        esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
+    }
+}
+
+static void bootloader_reset_mmu(void)
+{
+    Cache_Suspend_ICache();
+    Cache_Invalidate_ICache_All();
+    Cache_MMU_Init();
+
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
+    REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
+}
+
+static void update_flash_config(const esp_image_header_t *bootloader_hdr)
+{
+    uint32_t size;
+    switch (bootloader_hdr->spi_size) {
+    case ESP_IMAGE_FLASH_SIZE_1MB:
+        size = 1;
+        break;
+    case ESP_IMAGE_FLASH_SIZE_2MB:
+        size = 2;
+        break;
+    case ESP_IMAGE_FLASH_SIZE_4MB:
+        size = 4;
+        break;
+    case ESP_IMAGE_FLASH_SIZE_8MB:
+        size = 8;
+        break;
+    case ESP_IMAGE_FLASH_SIZE_16MB:
+        size = 16;
+        break;
+    default:
+        size = 2;
+    }
+    uint32_t autoload = Cache_Suspend_ICache();
+    // Set flash chip size
+    esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);    // TODO: set mode
+    Cache_Resume_ICache(autoload);
+}
+
+static void print_flash_info(const esp_image_header_t *bootloader_hdr)
+{
+    ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
+    ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
+    ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
+    ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
+    ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
+
+    const char *str;
+    switch (bootloader_hdr->spi_speed) {
+    case ESP_IMAGE_SPI_SPEED_40M:
+        str = "40MHz";
+        break;
+    case ESP_IMAGE_SPI_SPEED_26M:
+        str = "26.7MHz";
+        break;
+    case ESP_IMAGE_SPI_SPEED_20M:
+        str = "20MHz";
+        break;
+    case ESP_IMAGE_SPI_SPEED_80M:
+        str = "80MHz";
+        break;
+    default:
+        str = "20MHz";
+        break;
+    }
+    ESP_LOGI(TAG, "SPI Speed      : %s", str);
+
+    /* SPI mode could have been set to QIO during boot already,
+       so test the SPI registers not the flash header */
+    uint32_t spi_ctrl = REG_READ(SPI_MEM_CTRL_REG(0));
+    if (spi_ctrl & SPI_MEM_FREAD_QIO) {
+        str = "QIO";
+    } else if (spi_ctrl & SPI_MEM_FREAD_QUAD) {
+        str = "QOUT";
+    } else if (spi_ctrl & SPI_MEM_FREAD_DIO) {
+        str = "DIO";
+    } else if (spi_ctrl & SPI_MEM_FREAD_DUAL) {
+        str = "DOUT";
+    } else if (spi_ctrl & SPI_MEM_FASTRD_MODE) {
+        str = "FAST READ";
+    } else {
+        str = "SLOW READ";
+    }
+    ESP_LOGI(TAG, "SPI Mode       : %s", str);
+
+    switch (bootloader_hdr->spi_size) {
+    case ESP_IMAGE_FLASH_SIZE_1MB:
+        str = "1MB";
+        break;
+    case ESP_IMAGE_FLASH_SIZE_2MB:
+        str = "2MB";
+        break;
+    case ESP_IMAGE_FLASH_SIZE_4MB:
+        str = "4MB";
+        break;
+    case ESP_IMAGE_FLASH_SIZE_8MB:
+        str = "8MB";
+        break;
+    case ESP_IMAGE_FLASH_SIZE_16MB:
+        str = "16MB";
+        break;
+    default:
+        str = "2MB";
+        break;
+    }
+    ESP_LOGI(TAG, "SPI Flash Size : %s", str);
+}
+
+static void IRAM_ATTR bootloader_init_flash_configure(void)
+{
+    bootloader_flash_dummy_config(&bootloader_image_hdr);
+    bootloader_flash_cs_timing_config();
+}
+
+static void bootloader_spi_flash_resume(void)
+{
+    bootloader_execute_flash_command(CMD_RESUME, 0, 0, 0);
+    esp_rom_spiflash_wait_idle(&g_rom_flashchip);
+}
+
+static esp_err_t bootloader_init_spi_flash(void)
+{
+    bootloader_init_flash_configure();
+#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
+    const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
+    if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
+        ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
+        return ESP_FAIL;
+    }
+#endif
+
+    bootloader_spi_flash_resume();
+    esp_rom_spiflash_unlock();
+
+#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
+    bootloader_enable_qio_mode();
+#endif
+
+    print_flash_info(&bootloader_image_hdr);
+    update_flash_config(&bootloader_image_hdr);
+    //ensure the flash is write-protected
+    bootloader_enable_wp();
+    return ESP_OK;
+}
+
+static void wdt_reset_cpu0_info_enable(void)
+{
+    REG_SET_BIT(SYSTEM_CPU_PERI_CLK_EN_REG, SYSTEM_CLK_EN_ASSIST_DEBUG);
+    REG_CLR_BIT(SYSTEM_CPU_PERI_RST_EN_REG, SYSTEM_RST_EN_ASSIST_DEBUG);
+    REG_WRITE(ASSIST_DEBUG_CORE_0_RCD_EN_REG, ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN | ASSIST_DEBUG_CORE_0_RCD_RECORDEN);
+}
+
+static void wdt_reset_info_dump(int cpu)
+{
+    (void) cpu;
+    // saved PC was already printed by the ROM bootloader.
+    // nothing to do here.
+}
+
+static void bootloader_check_wdt_reset(void)
+{
+    int wdt_rst = 0;
+    RESET_REASON rst_reas[2];
+
+    rst_reas[0] = rtc_get_reset_reason(0);
+    if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
+            rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
+        ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
+        wdt_rst = 1;
+    }
+    if (wdt_rst) {
+        // if reset by WDT dump info from trace port
+        wdt_reset_info_dump(0);
+    }
+    wdt_reset_cpu0_info_enable();
+}
+
+static void bootloader_super_wdt_auto_feed(void)
+{
+    REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, RTC_CNTL_SWD_WKEY_VALUE);
+    REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN);
+    REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0);
+}
+
+static inline void bootloader_hardware_init(void)
+{
+    // This check is always included in the bootloader so it can
+    // print the minimum revision error message later in the boot
+    if (bootloader_common_get_chip_revision() < 3) {
+        REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
+        REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
+    }
+}
+
+static inline void bootloader_glitch_reset_disable(void)
+{
+    /*
+      For origin chip & ECO1: only support swt reset;
+      For ECO2: fix brownout reset bug, support swt & brownout reset;
+      For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset.
+    */
+    uint8_t chip_version = bootloader_common_get_chip_revision();
+    if (chip_version < 2) {
+        REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST);
+    } else if (chip_version == 2) {
+        REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST);
+    }
+}
+
+esp_err_t bootloader_init(void)
+{
+    esp_err_t ret = ESP_OK;
+
+    bootloader_hardware_init();
+    bootloader_glitch_reset_disable();
+    bootloader_super_wdt_auto_feed();
+    // protect memory region
+    bootloader_init_mem();
+    /* check that static RAM is after the stack */
+    assert(&_bss_start <= &_bss_end);
+    assert(&_data_start <= &_data_end);
+    // clear bss section
+    bootloader_clear_bss_section();
+    // reset MMU
+    bootloader_reset_mmu();
+    // config clock
+    bootloader_clock_configure();
+    // initialize console, from now on, we can use esp_log
+    bootloader_console_init();
+    /* print 2nd bootloader banner */
+    bootloader_print_banner();
+    // update flash ID
+    bootloader_flash_update_id();
+    // read bootloader header
+    if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
+        goto err;
+    }
+    // read chip revision and check if it's compatible to bootloader
+    if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
+        goto err;
+    }
+    // initialize spi flash
+    if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
+        goto err;
+    }
+    // check whether a WDT reset happend
+    bootloader_check_wdt_reset();
+    // config WDT
+    bootloader_config_wdt();
+    // enable RNG early entropy source
+    bootloader_enable_random();
+err:
+    return ret;
+}

+ 40 - 0
components/bootloader_support/src/esp32h2/bootloader_sha.c

@@ -0,0 +1,40 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include "bootloader_sha.h"
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/param.h>
+
+#include "esp32h2/rom/sha.h"
+
+static SHA_CTX ctx;
+
+bootloader_sha256_handle_t bootloader_sha256_start()
+{
+    // Enable SHA hardware
+    ets_sha_enable();
+    ets_sha_init(&ctx, SHA2_256);
+    return &ctx; // Meaningless non-NULL value
+}
+
+void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
+{
+    assert(handle != NULL);
+    assert(data_len % 4 == 0);
+    ets_sha_update(&ctx, data, data_len, false);
+}
+
+void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
+{
+    assert(handle != NULL);
+
+    if (digest == NULL) {
+        bzero(&ctx, sizeof(ctx));
+        return;
+    }
+    ets_sha_finish(&ctx, digest);
+}

+ 346 - 0
components/bootloader_support/src/esp32h2/flash_encrypt.c

@@ -0,0 +1,346 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <strings.h>
+#include "bootloader_flash_priv.h"
+#include "bootloader_random.h"
+#include "bootloader_utility.h"
+#include "esp_image_format.h"
+#include "esp_flash_encrypt.h"
+#include "esp_flash_partitions.h"
+#include "esp_secure_boot.h"
+#include "esp_log.h"
+#include "esp32h2/rom/secure_boot.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+#include "hal/wdt_hal.h"
+
+static const char *TAG = "flash_encrypt";
+
+/* Static functions for stages of flash encryption */
+static esp_err_t initialise_flash_encryption(void);
+static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis) __attribute__((unused));
+static esp_err_t encrypt_bootloader(void);
+static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
+static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
+
+esp_err_t esp_flash_encrypt_check_and_update(void)
+{
+    uint8_t flash_crypt_wr_dis = 0;
+    uint32_t flash_crypt_cnt = 0;
+
+    esp_efuse_read_field_blob(ESP_EFUSE_SPI_BOOT_CRYPT_CNT, &flash_crypt_cnt, 3);
+    esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT, &flash_crypt_wr_dis, 1);
+
+    ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", flash_crypt_cnt);
+    ESP_LOGV(TAG, "EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT 0x%x", flash_crypt_wr_dis);
+
+    if (__builtin_parity(flash_crypt_cnt) == 1) {
+        /* Flash is already encrypted */
+        int left = (flash_crypt_cnt == 1) ? 1 : 0;
+        if (flash_crypt_wr_dis) {
+            left = 0; /* can't update FLASH_CRYPT_CNT, no more flashes */
+        }
+        ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
+        return ESP_OK;
+    } else {
+#ifndef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
+        /* Flash is not encrypted, so encrypt it! */
+        return encrypt_flash_contents(flash_crypt_cnt, flash_crypt_wr_dis);
+#else
+        ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED "
+                      "is set, refusing to boot.");
+        return ESP_ERR_INVALID_STATE;
+#endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
+    }
+}
+
+static esp_err_t check_and_generate_encryption_keys(void)
+{
+    esp_efuse_block_t aes_128_key_block;
+
+    bool has_key = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY,   &aes_128_key_block);
+    bool dis_write = false;
+    bool dis_read = false;
+
+    // If there are keys set, they must be write and read protected!
+    if(has_key) {
+        dis_write = esp_efuse_get_key_dis_write(aes_128_key_block);
+        dis_read  = esp_efuse_get_key_dis_read(aes_128_key_block);
+    }
+
+
+    if(has_key && (!dis_read || !dis_write)) {
+        ESP_LOGE(TAG, "Invalid key state, a key was set but not read and write protected.");
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if(!has_key && !dis_write && !dis_read) {
+        ESP_LOGI(TAG, "Generating new flash encryption key...");
+
+        enum { BLOCKS_NEEDED = 1 };
+        esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = {
+            ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY,
+        };
+
+        uint8_t keys[BLOCKS_NEEDED][32] = { 0 };
+        for (int i = 0; i < BLOCKS_NEEDED; ++i) {
+            bootloader_fill_random(keys[i], 32);
+        }
+
+        esp_err_t err = esp_efuse_write_keys(purposes, keys, BLOCKS_NEEDED);
+        if (err != ESP_OK) {
+            if (err == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) {
+                ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
+            } else {
+                ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", err);
+            }
+            return err;
+        }
+        ESP_LOGD(TAG, "Key generation complete");
+        return ESP_OK;
+
+    } else {
+        ESP_LOGI(TAG, "Using pre-existing key in efuse");
+        return ESP_OK;
+    }
+}
+
+
+static esp_err_t initialise_flash_encryption(void)
+{
+    esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
+
+    esp_err_t key_state = check_and_generate_encryption_keys();
+    if(key_state != ESP_OK) {
+        esp_efuse_batch_write_cancel();
+        return key_state;
+    }
+
+#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
+    ESP_LOGI(TAG, "Disable UART bootloader encryption...");
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
+#else
+    ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
+#endif
+
+#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
+    ESP_LOGI(TAG, "Disable UART bootloader cache...");
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
+#else
+    ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED");
+#endif
+
+#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
+    ESP_LOGI(TAG, "Disable JTAG...");
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
+#else
+    ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
+#endif
+
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
+
+    esp_err_t err = esp_efuse_batch_write_commit();
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err);
+    }
+
+    return err;
+}
+
+/* Encrypt all flash data that should be encrypted */
+static esp_err_t encrypt_flash_contents(uint32_t spi_boot_crypt_cnt, bool flash_crypt_wr_dis)
+{
+    esp_err_t err;
+    esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
+    int num_partitions;
+
+    /* If the last spi_boot_crypt_cnt bit is burned or write-disabled, the
+       device can't re-encrypt itself. */
+    if (flash_crypt_wr_dis || spi_boot_crypt_cnt == EFUSE_SPI_BOOT_CRYPT_CNT) {
+        ESP_LOGE(TAG, "Cannot re-encrypt data SPI_BOOT_CRYPT_CNT 0x%02x write disabled %d", spi_boot_crypt_cnt, flash_crypt_wr_dis);
+        return ESP_FAIL;
+    }
+
+    if (spi_boot_crypt_cnt == 0) {
+        /* Very first flash of encrypted data: generate keys, etc. */
+        err = initialise_flash_encryption();
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+
+    err = encrypt_bootloader();
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    err = encrypt_and_load_partition_table(partition_table, &num_partitions);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    /* Now iterate the just-loaded partition table, looking for entries to encrypt
+     */
+
+    /* Go through each partition and encrypt if necessary */
+    for (int i = 0; i < num_partitions; i++) {
+        err = encrypt_partition(i, &partition_table[i]);
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+
+    ESP_LOGD(TAG, "All flash regions checked for encryption pass");
+
+    /* Set least significant 0-bit in spi_boot_crypt_cnt */
+    int ffs_inv = __builtin_ffs((~spi_boot_crypt_cnt) & 0x7);
+    /* ffs_inv shouldn't be zero, as zero implies spi_boot_crypt_cnt == 0xFF */
+    uint32_t new_spi_boot_crypt_cnt = (1 << (ffs_inv - 1));
+    ESP_LOGD(TAG, "SPI_BOOT_CRYPT_CNT 0x%x -> 0x%x", spi_boot_crypt_cnt, new_spi_boot_crypt_cnt + spi_boot_crypt_cnt);
+
+    esp_efuse_write_field_blob(ESP_EFUSE_SPI_BOOT_CRYPT_CNT, &new_spi_boot_crypt_cnt, 3);
+
+#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
+    //Secure SPI boot cnt after its update if needed.
+    const uint32_t spi_boot_cnt_wr_dis = 1;
+    ESP_LOGI(TAG, "Write protecting SPI_CRYPT_CNT eFuse");
+    esp_efuse_write_field_blob(ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT, &spi_boot_cnt_wr_dis, 1);
+#endif
+    ESP_LOGI(TAG, "Flash encryption completed");
+
+    return ESP_OK;
+}
+
+static esp_err_t encrypt_bootloader(void)
+{
+    esp_err_t err;
+    uint32_t image_length;
+    /* Check for plaintext bootloader (verification will fail if it's already encrypted) */
+    if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
+        ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
+
+#if CONFIG_SECURE_BOOT_V2_ENABLED
+        /* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
+        if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
+            ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
+            return ESP_ERR_INVALID_SIZE;
+        }
+#endif // CONFIG_SECURE_BOOT_V2_ENABLED
+
+        err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
+        if (err != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
+            return err;
+        }
+
+        ESP_LOGI(TAG, "bootloader encrypted successfully");
+        return err;
+    }
+    else {
+        ESP_LOGW(TAG, "no valid bootloader was found");
+        return ESP_ERR_NOT_FOUND;
+    }
+}
+
+static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
+{
+    esp_err_t err;
+    /* Check for plaintext partition table */
+    err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to read partition table data");
+        return err;
+    }
+    if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
+        ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
+        esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
+                        FLASH_SECTOR_SIZE);
+        if (err != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
+            return err;
+        }
+    } else {
+        ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    /* Valid partition table loaded */
+    ESP_LOGI(TAG, "partition table encrypted and loaded successfully");
+    return ESP_OK;
+}
+
+
+static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
+{
+    esp_err_t err;
+    bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
+
+    if (partition->type == PART_TYPE_APP) {
+        /* check if the partition holds a valid unencrypted app */
+        esp_image_metadata_t data_ignored;
+        err = esp_image_verify(ESP_IMAGE_VERIFY,
+                               &partition->pos,
+                               &data_ignored);
+        should_encrypt = (err == ESP_OK);
+    } else if (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA) {
+        /* check if we have ota data partition and the partition should be encrypted unconditionally */
+        should_encrypt = true;
+    }
+
+    if (!should_encrypt) {
+        return ESP_OK;
+    } else {
+        /* should_encrypt */
+        ESP_LOGI(TAG, "Encrypting partition %d at offset 0x%x (length 0x%x)...", index, partition->pos.offset, partition->pos.size);
+
+        err = esp_flash_encrypt_region(partition->pos.offset, partition->pos.size);
+        ESP_LOGI(TAG, "Done encrypting");
+        if (err != ESP_OK) {
+            ESP_LOGE(TAG, "Failed to encrypt partition %d", index);
+        }
+        return err;
+    }
+}
+
+
+esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
+{
+    esp_err_t err;
+    uint32_t buf[FLASH_SECTOR_SIZE / sizeof(uint32_t)];
+
+    if (src_addr % FLASH_SECTOR_SIZE != 0) {
+        ESP_LOGE(TAG, "esp_flash_encrypt_region bad src_addr 0x%x", src_addr);
+        return ESP_FAIL;
+    }
+
+    wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
+    for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
+        wdt_hal_write_protect_disable(&rtc_wdt_ctx);
+        wdt_hal_feed(&rtc_wdt_ctx);
+        wdt_hal_write_protect_enable(&rtc_wdt_ctx);
+
+        uint32_t sec_start = i + src_addr;
+        err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
+        if (err != ESP_OK) {
+            goto flash_failed;
+        }
+        err = bootloader_flash_erase_sector(sec_start / FLASH_SECTOR_SIZE);
+        if (err != ESP_OK) {
+            goto flash_failed;
+        }
+        err = bootloader_flash_write(sec_start, buf, FLASH_SECTOR_SIZE, true);
+        if (err != ESP_OK) {
+            goto flash_failed;
+        }
+    }
+    return ESP_OK;
+
+flash_failed:
+    ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
+    return err;
+}

+ 289 - 0
components/bootloader_support/src/esp32h2/secure_boot.c

@@ -0,0 +1,289 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#include <string.h>
+
+#include "esp_log.h"
+#include "esp_secure_boot.h"
+#include "soc/efuse_reg.h"
+
+#include "bootloader_flash_priv.h"
+#include "bootloader_sha.h"
+#include "bootloader_utility.h"
+
+#include "esp_rom_crc.h"
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/secure_boot.h"
+
+static const char *TAG = "secure_boot_v2";
+#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
+
+/* A signature block is valid when it has correct magic byte, crc and image digest. */
+static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
+{
+    uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
+    if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
+        // All signature blocks have been parsed, no new signature block present.
+        ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
+        return ESP_FAIL;
+    }
+    if (block->block_crc != crc) {
+        ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
+        return ESP_FAIL;
+    }
+    if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
+        ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
+        return ESP_FAIL;
+    } else {
+        ESP_LOGD(TAG, "valid signature block(%d) found", block_num);
+        return ESP_OK;
+    }
+
+    return ESP_FAIL;
+}
+
+/* Generates the public key digests of the valid public keys in an image's
+   signature block, verifies each signature, and stores the key digests in the
+   public_key_digests structure.
+
+   @param flash_offset Image offset in flash
+   @param flash_size Image size in flash (not including signature block)
+   @param[out] public_key_digests Pointer to structure to hold the key digests for valid sig blocks
+
+
+   Note that this function doesn't read any eFuses, so it doesn't know if the
+   keys are ultimately trusted by the hardware or not
+
+   @return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
+           - ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
+*/
+static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
+{
+    esp_err_t ret;
+    uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
+    uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
+    size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
+
+    ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
+
+    bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
+
+    ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "error generating image digest, %d", ret);
+        return ret;
+    }
+
+    ESP_LOGD(TAG, "reading signatures");
+    const ets_secure_boot_signature_t *signatures = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t));
+    if (signatures == NULL) {
+        ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
+        return ESP_FAIL;
+    }
+
+    for (int i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
+        const ets_secure_boot_sig_block_t *block = &signatures->block[i];
+
+        ret = validate_signature_block(block, i, image_digest);
+        if (ret != ESP_OK) {
+            ret = ESP_OK;  // past the last valid signature block
+            break;
+        }
+
+        /* Generating the SHA of the public key components in the signature block */
+        bootloader_sha256_handle_t sig_block_sha;
+        sig_block_sha = bootloader_sha256_start();
+        bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key));
+        bootloader_sha256_finish(sig_block_sha, key_digest);
+
+        // Check we can verify the image using this signature and this key
+        uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
+        bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
+
+        if (!verified) {
+            /* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid,
+               so this is a fatal error
+            */
+            ret = ESP_FAIL;
+            ESP_LOGE(TAG, "Secure boot key (%d) verification failed.", i);
+            break;
+        }
+        ESP_LOGD(TAG, "Signature block (%d) is verified", i);
+        /* Copy the key digest to the buffer provided by the caller */
+        memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
+        public_key_digests->num_digests++;
+    }
+
+    if (ret == ESP_OK && public_key_digests->num_digests > 0) {
+        ESP_LOGI(TAG, "Digests successfully calculated, %d valid signatures (image offset 0x%x)",
+                 public_key_digests->num_digests, flash_offset);
+    }
+
+    bootloader_munmap(signatures);
+    return ret;
+}
+
+static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t *image_data)
+{
+    esp_err_t ret;
+    /* Verify the bootloader */
+    esp_image_metadata_t bootloader_data = { 0 };
+    ret = esp_image_verify_bootloader_data(&bootloader_data);
+    if (ret != ESP_OK) {
+        ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret);
+        return ret;
+    }
+
+    /* Check if secure boot digests are present */
+    bool has_secure_boot_digest = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL);
+    has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL);
+    has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL);
+    ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
+
+    if (!has_secure_boot_digest) {
+        esp_image_sig_public_key_digests_t boot_key_digests = {0};
+        esp_image_sig_public_key_digests_t app_key_digests = {0};
+
+        /* Generate the bootloader public key digests */
+        ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
+        if (ret != ESP_OK) {
+            ESP_LOGE(TAG, "Bootloader signature block is invalid");
+            return ret;
+        }
+
+        if (boot_key_digests.num_digests == 0) {
+            ESP_LOGE(TAG, "No valid bootloader signature blocks found.");
+            return ESP_FAIL;
+        }
+        ESP_LOGI(TAG, "%d signature block(s) found appended to the bootloader.", boot_key_digests.num_digests);
+
+        esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = {
+            ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0,
+            ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1,
+            ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2,
+        };
+
+        ret = esp_efuse_write_keys(secure_boot_key_purpose, boot_key_digests.key_digests, boot_key_digests.num_digests);
+        if (ret) {
+            if (ret == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) {
+                ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots.", boot_key_digests.num_digests);
+            } else {
+                ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", ret);
+            }
+            return ret;
+        }
+
+        /* Generate the application public key digests */
+        ret = s_calculate_image_public_key_digests(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, &app_key_digests);
+        if (ret != ESP_OK) {
+            ESP_LOGE(TAG, "App signature block is invalid.");
+            return ret;
+        }
+
+        if (app_key_digests.num_digests == 0) {
+            ESP_LOGE(TAG, "No valid applications signature blocks found.");
+            return ESP_FAIL;
+        }
+
+        ESP_LOGI(TAG, "%d signature block(s) found appended to the app.", app_key_digests.num_digests);
+        if (app_key_digests.num_digests > boot_key_digests.num_digests) {
+            ESP_LOGW(TAG, "App has %d signature blocks but bootloader only has %d. Some keys missing from bootloader?");
+        }
+
+        /* Confirm if at least one public key from the application matches a public key in the bootloader
+           (Also, ensure if that public revoke bit is not set for the matched key) */
+        bool match = false;
+
+        for (int i = 0; i < boot_key_digests.num_digests; i++) {
+
+            if (esp_efuse_get_digest_revoke(i)) {
+                ESP_LOGI(TAG, "Key block(%d) has been revoked.", i);
+                continue; // skip if the key block is revoked
+            }
+
+            for (int j = 0; j < app_key_digests.num_digests; j++) {
+                if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
+                    ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
+                    match = true;
+                }
+            }
+        }
+
+        if (match == false) {
+            ESP_LOGE(TAG, "No application key digest matches the bootloader key digest.");
+            return ESP_FAIL;
+        }
+
+        /* Revoke the empty signature blocks */
+        if (boot_key_digests.num_digests < SECURE_BOOT_NUM_BLOCKS) {
+            /* The revocation index can be 0, 1, 2. Bootloader count can be 1,2,3. */
+            for (uint8_t i = boot_key_digests.num_digests; i < SECURE_BOOT_NUM_BLOCKS; i++) {
+                ESP_LOGI(TAG, "Revoking empty key digest slot (%d)...", i);
+                esp_efuse_set_digest_revoke(i);
+            }
+        }
+    }
+    return ESP_OK;
+}
+
+esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
+{
+    ESP_LOGI(TAG, "enabling secure boot v2...");
+
+    if (esp_secure_boot_enabled()) {
+        ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing..");
+        return ESP_OK;
+    }
+
+    esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
+
+    esp_err_t key_state = check_and_generate_secure_boot_keys(image_data);
+    if (key_state != ESP_OK) {
+        esp_efuse_batch_write_cancel();
+        return key_state;
+    }
+
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
+
+#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
+    ESP_LOGI(TAG, "Enabling Security download mode...");
+    esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD);
+#else
+    ESP_LOGW(TAG, "Not enabling Security download mode - SECURITY COMPROMISED");
+#endif
+
+#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
+    ESP_LOGI(TAG, "Disable hardware & software JTAG...");
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
+    esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
+    esp_efuse_write_field_bit(ESP_EFUSE_SOFT_DIS_JTAG);
+#else
+    ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
+#endif
+
+#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
+    esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
+#endif
+
+    esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
+
+    esp_err_t err = esp_efuse_batch_write_commit();
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err);
+        return err;
+    }
+
+#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
+    assert(ets_efuse_secure_boot_aggressive_revoke_enabled());
+#endif
+
+    assert(esp_rom_efuse_is_secure_boot_enabled());
+    ESP_LOGI(TAG, "Secure boot permanently enabled");
+
+    return ESP_OK;
+}

+ 3 - 0
components/bootloader_support/src/esp_image_format.c

@@ -30,6 +30,9 @@
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/rtc.h"
 #include "esp32c3/rom/secure_boot.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/rtc.h"
+#include "esp32h2/rom/secure_boot.h"
 #endif
 
 /* Checking signatures as part of verifying images is necessary:

+ 2 - 2
components/bootloader_support/src/flash_encrypt.c

@@ -86,7 +86,7 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
     uint8_t dis_dl_enc = 0;
     uint8_t dis_dl_icache = 0;
     uint8_t dis_dl_dcache = 0;
-#elif CONFIG_IDF_TARGET_ESP32C3
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
     uint8_t dis_dl_enc = 0;
     uint8_t dis_dl_icache = 0;
 #endif
@@ -123,7 +123,7 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
             if (dis_dl_enc && dis_dl_icache && dis_dl_dcache) {
                 mode = ESP_FLASH_ENC_MODE_RELEASE;
             }
-#elif CONFIG_IDF_TARGET_ESP32C3
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
             dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
             dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
 

+ 2 - 0
components/bootloader_support/src/flash_partitions.c

@@ -13,6 +13,8 @@
 #include "esp32s2/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #else
 #include "esp32/rom/spi_flash.h"
 #endif

+ 2 - 0
components/bootloader_support/src/flash_qio_mode.c

@@ -21,6 +21,8 @@
 #include "esp32s3/rom/spi_flash.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/spi_flash.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/spi_flash.h"
 #endif
 #include "soc/efuse_periph.h"
 #include "soc/io_mux_reg.h"

+ 9 - 0
components/driver/CMakeLists.txt

@@ -74,6 +74,15 @@ if(IDF_TARGET STREQUAL "esp32c3")
                      "esp32c3/rtc_tempsensor.c")
 endif()
 
+if(IDF_TARGET STREQUAL "esp32h2")
+    list(APPEND srcs "gdma.c"
+                     "spi_slave_hd.c"
+                     "adc_common.c"
+                     "esp32h2/adc.c"
+                     "esp32h2/adc2_init_cal.c"
+                     "esp32h2/rtc_tempsensor.c")
+endif()
+
 idf_component_register(SRCS "${srcs}"
                     INCLUDE_DIRS ${includes}
                     PRIV_INCLUDE_DIRS "include/driver"

+ 717 - 0
components/driver/esp32h2/adc.c

@@ -0,0 +1,717 @@
+/*
+ * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_types.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "sdkconfig.h"
+#include "esp_intr_alloc.h"
+#include "esp_log.h"
+#include "esp_pm.h"
+#include "sys/lock.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "freertos/timers.h"
+#include "freertos/ringbuf.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "driver/periph_ctrl.h"
+#include "driver/gpio.h"
+#include "driver/adc.h"
+#include "hal/adc_types.h"
+#include "hal/adc_hal.h"
+#include "hal/dma_types.h"
+#include "esp_efuse_rtc_calib.h"
+#include "esp_private/gdma.h"
+
+#define ADC_CHECK_RET(fun_ret) ({                           \
+    if (fun_ret != ESP_OK) {                                \
+        ESP_LOGE(ADC_TAG,"%s(%d)",__FUNCTION__,__LINE__);   \
+        return ESP_FAIL;                                    \
+    }                                                       \
+})
+
+static const char *ADC_TAG = "ADC";
+
+#define ADC_CHECK(a, str, ret_val) ({                                               \
+    if (!(a)) {                                                                     \
+        ESP_LOGE(ADC_TAG,"%s(%d) :%s", __FUNCTION__, __LINE__, str);                \
+        return (ret_val);                                                           \
+    }                                                                               \
+})
+
+#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
+
+#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
+
+extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
+#define ADC_ENTER_CRITICAL()  portENTER_CRITICAL(&rtc_spinlock)
+#define ADC_EXIT_CRITICAL()  portEXIT_CRITICAL(&rtc_spinlock)
+
+/**
+ * 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module.
+ * 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On H2, it is controlled by the digital controller
+ *    and PWDET controller.
+ * 3. adc_reg_lock:  this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode.
+ */
+static _lock_t sar_adc1_lock;
+#define SAR_ADC1_LOCK_ACQUIRE()    _lock_acquire(&sar_adc1_lock)
+#define SAR_ADC1_LOCK_RELEASE()    _lock_release(&sar_adc1_lock)
+static _lock_t sar_adc2_lock;
+#define SAR_ADC2_LOCK_ACQUIRE()    _lock_acquire(&sar_adc2_lock)
+#define SAR_ADC2_LOCK_RELEASE()    _lock_release(&sar_adc2_lock)
+portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
+#define ADC_REG_LOCK_ENTER()       portENTER_CRITICAL(&adc_reg_lock)
+#define ADC_REG_LOCK_EXIT()        portEXIT_CRITICAL(&adc_reg_lock)
+
+#define INTERNAL_BUF_NUM 5
+#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF
+
+/*---------------------------------------------------------------
+                    Digital Controller Context
+---------------------------------------------------------------*/
+typedef struct adc_digi_context_t {
+    uint8_t                 *rx_dma_buf;                //dma buffer
+    adc_hal_context_t       hal;                        //hal context
+    gdma_channel_handle_t   rx_dma_channel;             //dma rx channel handle
+    RingbufHandle_t         ringbuf_hdl;                //RX ringbuffer handler
+    intptr_t                rx_eof_desc_addr;           //eof descriptor address of RX channel
+    bool                    ringbuf_overflow_flag;      //1: ringbuffer overflow
+    bool                    driver_start_flag;          //1: driver is started; 0: driver is stoped
+    bool                    use_adc1;                   //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
+    bool                    use_adc2;                   //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not.
+    adc_atten_t             adc1_atten;                 //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
+    adc_atten_t             adc2_atten;                 //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
+    adc_digi_config_t       digi_controller_config;     //Digital Controller Configuration
+    esp_pm_lock_handle_t    pm_lock;                    //For power management
+} adc_digi_context_t;
+
+static adc_digi_context_t *s_adc_digi_ctx = NULL;
+
+static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten);
+
+/*---------------------------------------------------------------
+                   ADC Continuous Read Mode (via DMA)
+---------------------------------------------------------------*/
+static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
+
+static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel)
+{
+    return adc_channel_io_map[adc_unit][adc_channel];
+}
+
+static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
+{
+    esp_err_t ret = ESP_OK;
+    uint64_t gpio_mask = 0;
+    uint32_t n = 0;
+    int8_t io = 0;
+
+    while (channel_mask) {
+        if (channel_mask & 0x1) {
+            io = adc_digi_get_io_num(adc_unit, n);
+            if (io < 0) {
+                return ESP_ERR_INVALID_ARG;
+            }
+            gpio_mask |= BIT64(io);
+        }
+        channel_mask = channel_mask >> 1;
+        n++;
+    }
+
+    gpio_config_t cfg = {
+        .pin_bit_mask = gpio_mask,
+        .mode = GPIO_MODE_DISABLE,
+    };
+    ret = gpio_config(&cfg);
+
+    return ret;
+}
+
+esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
+{
+    esp_err_t ret = ESP_OK;
+
+    s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t));
+    if (s_adc_digi_ctx == NULL) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //ringbuffer
+    s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF);
+    if (!s_adc_digi_ctx->ringbuf_hdl) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //malloc internal buffer used by DMA
+    s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
+    if (!s_adc_digi_ctx->rx_dma_buf) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //malloc dma descriptor
+    s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA);
+    if (!s_adc_digi_ctx->hal.rx_desc) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+    //malloc pattern table
+    s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t));
+    if (!s_adc_digi_ctx->digi_controller_config.adc_pattern) {
+        ret = ESP_ERR_NO_MEM;
+        goto cleanup;
+    }
+
+#if CONFIG_PM_ENABLE
+    ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_ctx->pm_lock);
+    if (ret != ESP_OK) {
+        goto cleanup;
+    }
+#endif //CONFIG_PM_ENABLE
+
+    //init gpio pins
+    if (init_config->adc1_chan_mask) {
+        ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask);
+        if (ret != ESP_OK) {
+            goto cleanup;
+        }
+    }
+    if (init_config->adc2_chan_mask) {
+        ret = adc_digi_gpio_init(ADC_NUM_2, init_config->adc2_chan_mask);
+        if (ret != ESP_OK) {
+            goto cleanup;
+        }
+    }
+
+    //alloc rx gdma channel
+    gdma_channel_alloc_config_t rx_alloc_config = {
+        .direction = GDMA_CHANNEL_DIRECTION_RX,
+    };
+    ret = gdma_new_channel(&rx_alloc_config, &s_adc_digi_ctx->rx_dma_channel);
+    if (ret != ESP_OK) {
+        goto cleanup;
+    }
+    gdma_connect(s_adc_digi_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
+
+    gdma_strategy_config_t strategy_config = {
+        .auto_update_desc = true,
+        .owner_check = true
+    };
+    gdma_apply_strategy(s_adc_digi_ctx->rx_dma_channel, &strategy_config);
+
+    gdma_rx_event_callbacks_t cbs = {
+        .on_recv_eof = adc_dma_in_suc_eof_callback
+    };
+    gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx);
+
+    int dma_chan;
+    gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan);
+
+    adc_hal_config_t config = {
+        .desc_max_num = INTERNAL_BUF_NUM,
+        .dma_chan = dma_chan,
+        .eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV
+    };
+    adc_hal_context_config(&s_adc_digi_ctx->hal, &config);
+
+    //enable SARADC module clock
+    periph_module_enable(PERIPH_SARADC_MODULE);
+
+    adc_hal_calibration_init(ADC_NUM_1);
+    adc_hal_calibration_init(ADC_NUM_2);
+
+    return ret;
+
+cleanup:
+    adc_digi_deinitialize();
+    return ret;
+
+}
+
+static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
+
+static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
+{
+    assert(event_data);
+    adc_digi_context_t *adc_digi_ctx = (adc_digi_context_t *)user_data;
+    adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
+    return adc_dma_intr(adc_digi_ctx);
+}
+
+static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
+{
+    portBASE_TYPE taskAwoken = 0;
+    BaseType_t ret;
+    adc_hal_dma_desc_status_t status = false;
+    dma_descriptor_t *current_desc = NULL;
+
+    while (1) {
+        status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, &current_desc);
+        if (status != ADC_HAL_DMA_DESC_VALID) {
+            break;
+        }
+
+        ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
+        if (ret == pdFALSE) {
+            //ringbuffer overflow
+            adc_digi_ctx->ringbuf_overflow_flag = 1;
+        }
+    }
+
+    if (status == ADC_HAL_DMA_DESC_NULL) {
+        //start next turns of dma operation
+        adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
+    }
+
+    return (taskAwoken == pdTRUE);
+}
+
+esp_err_t adc_digi_start(void)
+{
+    if (s_adc_digi_ctx->driver_start_flag != 0) {
+        ESP_LOGE(ADC_TAG, "The driver is already started");
+        return ESP_ERR_INVALID_STATE;
+    }
+    adc_power_acquire();
+    //reset flags
+    s_adc_digi_ctx->ringbuf_overflow_flag = 0;
+    s_adc_digi_ctx->driver_start_flag = 1;
+    if (s_adc_digi_ctx->use_adc1) {
+        SAR_ADC1_LOCK_ACQUIRE();
+    }
+    if (s_adc_digi_ctx->use_adc2) {
+        SAR_ADC2_LOCK_ACQUIRE();
+    }
+
+#if CONFIG_PM_ENABLE
+    // Lock APB frequency while ADC driver is in use
+    esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
+#endif
+
+    adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
+    if (s_adc_digi_ctx->use_adc1) {
+        uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten);
+        adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
+    }
+    if (s_adc_digi_ctx->use_adc2) {
+        uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten);
+        adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
+    }
+
+    adc_hal_init();
+    adc_hal_arbiter_config(&config);
+    adc_hal_digi_init(&s_adc_digi_ctx->hal);
+    adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config);
+
+    //reset ADC and DMA
+    adc_hal_fifo_reset(&s_adc_digi_ctx->hal);
+    //start DMA
+    adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
+    //start ADC
+    adc_hal_digi_start(&s_adc_digi_ctx->hal);
+
+    return ESP_OK;
+}
+
+esp_err_t adc_digi_stop(void)
+{
+    if (s_adc_digi_ctx->driver_start_flag != 1) {
+        ESP_LOGE(ADC_TAG, "The driver is already stopped");
+        return ESP_ERR_INVALID_STATE;
+    }
+    s_adc_digi_ctx->driver_start_flag = 0;
+
+    //disable the in suc eof intrrupt
+    adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
+    //clear the in suc eof interrupt
+    adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
+    //stop ADC
+    adc_hal_digi_stop(&s_adc_digi_ctx->hal);
+    //stop DMA
+    adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal);
+    adc_hal_digi_deinit();
+#if CONFIG_PM_ENABLE
+    if (s_adc_digi_ctx->pm_lock) {
+        esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
+    }
+#endif  //CONFIG_PM_ENABLE
+
+    if (s_adc_digi_ctx->use_adc1) {
+        SAR_ADC1_LOCK_RELEASE();
+    }
+    if (s_adc_digi_ctx->use_adc2) {
+        SAR_ADC2_LOCK_RELEASE();
+    }
+    adc_power_release();
+
+    return ESP_OK;
+}
+
+esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms)
+{
+    TickType_t ticks_to_wait;
+    esp_err_t ret = ESP_OK;
+    uint8_t *data = NULL;
+    size_t size = 0;
+
+    ticks_to_wait = timeout_ms / portTICK_RATE_MS;
+    if (timeout_ms == ADC_MAX_DELAY) {
+        ticks_to_wait = portMAX_DELAY;
+    }
+
+    data = xRingbufferReceiveUpTo(s_adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max);
+    if (!data) {
+        ESP_LOGV(ADC_TAG, "No data, increase timeout or reduce conv_num_each_intr");
+        ret = ESP_ERR_TIMEOUT;
+        *out_length = 0;
+        return ret;
+    }
+
+    memcpy(buf, data, size);
+    vRingbufferReturnItem(s_adc_digi_ctx->ringbuf_hdl, data);
+    assert((size % 4) == 0);
+    *out_length = size;
+
+    if (s_adc_digi_ctx->ringbuf_overflow_flag) {
+        ret = ESP_ERR_INVALID_STATE;
+    }
+
+    return ret;
+}
+
+esp_err_t adc_digi_deinitialize(void)
+{
+    if (!s_adc_digi_ctx) {
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if (s_adc_digi_ctx->driver_start_flag != 0) {
+        ESP_LOGE(ADC_TAG, "The driver is not stopped");
+        return ESP_ERR_INVALID_STATE;
+    }
+
+    if (s_adc_digi_ctx->ringbuf_hdl) {
+        vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
+        s_adc_digi_ctx->ringbuf_hdl = NULL;
+    }
+
+#if CONFIG_PM_ENABLE
+    if (s_adc_digi_ctx->pm_lock) {
+        esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
+    }
+#endif  //CONFIG_PM_ENABLE
+
+    free(s_adc_digi_ctx->rx_dma_buf);
+    free(s_adc_digi_ctx->hal.rx_desc);
+    free(s_adc_digi_ctx->digi_controller_config.adc_pattern);
+    gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
+    gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
+
+    free(s_adc_digi_ctx);
+    s_adc_digi_ctx = NULL;
+
+    periph_module_disable(PERIPH_SARADC_MODULE);
+
+    return ESP_OK;
+}
+
+/*---------------------------------------------------------------
+                    ADC Single Read Mode
+---------------------------------------------------------------*/
+static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX];    //Array saving attenuate of each channel of ADC1, used by single read API
+static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX];    //Array saving attenuate of each channel of ADC2, used by single read API
+
+esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
+{
+    esp_err_t ret;
+    uint32_t channel = ADC2_CHANNEL_MAX;
+    if (adc_unit == ADC_UNIT_2) {
+        for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
+            if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) {
+                channel = i;
+                break;
+            }
+        }
+        if (channel == ADC2_CHANNEL_MAX) {
+            return ESP_ERR_INVALID_ARG;
+        }
+    }
+
+    adc_power_acquire();
+    if (adc_unit & ADC_UNIT_1) {
+        ADC_ENTER_CRITICAL();
+        adc_hal_vref_output(ADC_NUM_1, channel, true);
+        ADC_EXIT_CRITICAL()
+    } else if (adc_unit & ADC_UNIT_2) {
+        ADC_ENTER_CRITICAL();
+        adc_hal_vref_output(ADC_NUM_2, channel, true);
+        ADC_EXIT_CRITICAL()
+    }
+
+    ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
+
+    return ret;
+}
+
+esp_err_t adc1_config_width(adc_bits_width_t width_bit)
+{
+    //On ESP32H2, the data width is always 12-bits.
+    if (width_bit != ADC_WIDTH_BIT_12) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
+{
+    ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
+    ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
+
+    esp_err_t ret = ESP_OK;
+    s_atten1_single[channel] = atten;
+    ret = adc_digi_gpio_init(ADC_NUM_1, BIT(channel));
+
+    adc_hal_calibration_init(ADC_NUM_1);
+
+    return ret;
+}
+
+int adc1_get_raw(adc1_channel_t channel)
+{
+    int raw_out = 0;
+
+    periph_module_enable(PERIPH_SARADC_MODULE);
+    adc_power_acquire();
+
+    SAR_ADC1_LOCK_ACQUIRE();
+
+    adc_atten_t atten = s_atten1_single[channel];
+    uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, channel, atten);
+    adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
+
+    ADC_REG_LOCK_ENTER();
+    adc_hal_set_atten(ADC_NUM_2, channel, atten);
+    adc_hal_convert(ADC_NUM_1, channel, &raw_out);
+    ADC_REG_LOCK_EXIT();
+
+    SAR_ADC1_LOCK_RELEASE();
+
+    adc_power_release();
+    periph_module_disable(PERIPH_SARADC_MODULE);
+
+    return raw_out;
+}
+
+esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
+{
+    ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
+    ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
+
+    esp_err_t ret = ESP_OK;
+    s_atten2_single[channel] = atten;
+    ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
+
+    adc_hal_calibration_init(ADC_NUM_2);
+
+    return ret;
+}
+
+esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
+{
+    //On ESP32H2, the data width is always 12-bits.
+    if (width_bit != ADC_WIDTH_BIT_12) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    esp_err_t ret = ESP_OK;
+
+    periph_module_enable(PERIPH_SARADC_MODULE);
+    adc_power_acquire();
+
+    SAR_ADC2_LOCK_ACQUIRE();
+
+    adc_atten_t atten = s_atten2_single[channel];
+    uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, channel, atten);
+    adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
+
+    ADC_REG_LOCK_ENTER();
+    adc_hal_set_atten(ADC_NUM_2, channel, atten);
+    ret = adc_hal_convert(ADC_NUM_2, channel, raw_out);
+    ADC_REG_LOCK_EXIT();
+
+    SAR_ADC2_LOCK_RELEASE();
+
+    adc_power_release();
+    periph_module_disable(PERIPH_SARADC_MODULE);
+
+    return ret;
+}
+
+
+/*---------------------------------------------------------------
+                    Digital controller setting
+---------------------------------------------------------------*/
+esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
+{
+    if (!s_adc_digi_ctx) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    ADC_CHECK(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, "ADC sampling frequency out of range", ESP_ERR_INVALID_ARG);
+
+    s_adc_digi_ctx->digi_controller_config.conv_limit_en = config->conv_limit_en;
+    s_adc_digi_ctx->digi_controller_config.conv_limit_num = config->conv_limit_num;
+    s_adc_digi_ctx->digi_controller_config.adc_pattern_len = config->adc_pattern_len;
+    s_adc_digi_ctx->digi_controller_config.sample_freq_hz = config->sample_freq_hz;
+    memcpy(s_adc_digi_ctx->digi_controller_config.adc_pattern, config->adc_pattern, config->adc_pattern_len * sizeof(adc_digi_pattern_table_t));
+
+    const int atten_uninitialised = 999;
+    s_adc_digi_ctx->adc1_atten = atten_uninitialised;
+    s_adc_digi_ctx->adc2_atten = atten_uninitialised;
+    s_adc_digi_ctx->use_adc1 = 0;
+    s_adc_digi_ctx->use_adc2 = 0;
+    for (int i = 0; i < config->adc_pattern_len; i++) {
+        const adc_digi_pattern_table_t *pat = &config->adc_pattern[i];
+        if (pat->unit == ADC_NUM_1) {
+            s_adc_digi_ctx->use_adc1 = 1;
+
+            if (s_adc_digi_ctx->adc1_atten == atten_uninitialised) {
+                s_adc_digi_ctx->adc1_atten = pat->atten;
+            } else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
+                return ESP_ERR_INVALID_ARG;
+            }
+        } else if (pat->unit == ADC_NUM_2) {
+            //See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
+            s_adc_digi_ctx->use_adc2 = 1;
+
+            if (s_adc_digi_ctx->adc2_atten == atten_uninitialised) {
+                s_adc_digi_ctx->adc2_atten = pat->atten;
+            } else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
+                return ESP_ERR_INVALID_ARG;
+            }
+        }
+    }
+
+    return ESP_OK;
+}
+
+/*************************************/
+/* Digital controller filter setting */
+/*************************************/
+
+esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
+{
+    ADC_ENTER_CRITICAL();
+    adc_hal_digi_filter_reset(idx);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
+{
+    ADC_ENTER_CRITICAL();
+    adc_hal_digi_filter_set_factor(idx, config);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
+{
+    ADC_ENTER_CRITICAL();
+    adc_hal_digi_filter_get_factor(idx, config);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
+{
+    ADC_ENTER_CRITICAL();
+    adc_hal_digi_filter_enable(idx, enable);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+/**************************************/
+/* Digital controller monitor setting */
+/**************************************/
+
+esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
+{
+    ADC_ENTER_CRITICAL();
+    adc_hal_digi_monitor_config(idx, config);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
+{
+
+    ADC_ENTER_CRITICAL();
+    adc_hal_digi_monitor_enable(idx, enable);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}
+
+/*---------------------------------------------------------------
+                    RTC controller setting
+---------------------------------------------------------------*/
+
+static uint16_t s_adc_cali_param[ADC_UNIT_MAX][ADC_ATTEN_MAX] = {};
+
+//NOTE: according to calibration version, different types of lock may be taken during the process:
+//  1. Semaphore when reading efuse
+//  2. Lock (Spinlock, or Mutex) if we actually do ADC calibration in the future
+//This function shoudn't be called inside critical section or ISR
+static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
+{
+    const bool no_cal = false;
+    if (s_adc_cali_param[adc_n][atten]) {
+        return (uint32_t)s_adc_cali_param[adc_n][atten];
+    }
+
+    if (no_cal) {
+        return 0;   //indicating failure
+    }
+
+    // check if we can fetch the values from eFuse.
+    int version = esp_efuse_rtc_calib_get_ver();
+
+    uint32_t init_code = 0;
+    if (version == 1) {
+        //for calibration v1, both ADC units use the same init code (calibrated by ADC1)
+        init_code = esp_efuse_rtc_calib_get_init_code(version, atten);
+        ESP_LOGD(ADC_TAG, "Calib(V%d) ADC0, 1 atten=%d: %04X", version, atten, init_code);
+        s_adc_cali_param[0][atten] = init_code;
+        s_adc_cali_param[1][atten] = init_code;
+    } else {
+        adc_power_acquire();
+        ADC_ENTER_CRITICAL();
+        const bool internal_gnd = true;
+        init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
+        ADC_EXIT_CRITICAL();
+        adc_power_release();
+
+        ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
+        s_adc_cali_param[adc_n][atten] = init_code;
+    }
+
+    return init_code;
+}
+
+// Internal function to calibrate PWDET for WiFi
+esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
+{
+    adc_hal_calibration_init(adc_n);
+    uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten);
+    ADC_ENTER_CRITICAL();
+    adc_hal_set_calibration_param(adc_n, cal_val);
+    ADC_EXIT_CRITICAL();
+    return ESP_OK;
+}

+ 31 - 0
components/driver/esp32h2/adc2_init_cal.c

@@ -0,0 +1,31 @@
+/*
+ * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/* This file is used to get `adc2_init_code_calibration` executed before the APP when the ADC2 is used by Wi-Fi or other drivers.
+The linker will link constructor (adc2_init_code_calibration) only when any sections inside the same file (adc2_cal_include) is used.
+Don't put any other code into this file. */
+
+#include "adc2_wifi_private.h"
+#include "hal/adc_hal.h"
+#include "esp_private/adc_cali.h"
+
+/**
+ * @brief Set initial code to ADC2 after calibration. ADC2 RTC and ADC2 PWDET controller share the initial code.
+ *        This API be called in before `app_main()`.
+ */
+static __attribute__((constructor)) void adc2_init_code_calibration(void)
+{
+    const adc_ll_num_t adc_n = ADC_NUM_2;
+    const adc_atten_t atten = ADC_ATTEN_DB_11;
+    const adc_channel_t channel = 0;
+    adc_cal_offset(adc_n, channel, atten);
+}
+
+/** Don't call `adc2_cal_include` in user code. */
+void adc2_cal_include(void)
+{
+    /* When this empty function is called, the `adc2_init_code_calibration` constructor will be linked and executed before the app.*/
+}

+ 93 - 0
components/driver/esp32h2/include/driver/adc.h

@@ -0,0 +1,93 @@
+/*
+ * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "driver/adc_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------
+                    Common setting
+---------------------------------------------------------------*/
+/*************************************/
+/* Digital controller filter setting */
+/*************************************/
+/**
+ * @brief Reset adc digital controller filter.
+ *
+ * @param idx Filter index.
+ *
+ * @return
+ *      - ESP_OK Success
+ */
+esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
+
+/**
+ * @brief Set adc digital controller filter configuration.
+ *
+ * @param idx Filter index.
+ * @param config See ``adc_digi_filter_t``.
+ *
+ * @return
+ *      - ESP_OK Success
+ */
+esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
+
+/**
+ * @brief Get adc digital controller filter configuration.
+ *
+ * @param idx Filter index.
+ * @param config See ``adc_digi_filter_t``.
+ *
+ * @return
+ *      - ESP_OK Success
+ */
+esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
+
+/**
+ * @brief Enable/disable adc digital controller filter.
+ *        Filtering the ADC data to obtain smooth data at higher sampling rates.
+ *
+ * @param idx Filter index.
+ * @param enable Enable/Disable filter.
+ *
+ * @return
+ *      - ESP_OK Success
+ */
+esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
+
+/**************************************/
+/* Digital controller monitor setting */
+/**************************************/
+
+/**
+ * @brief Config monitor of adc digital controller.
+ *
+ * @param idx Monitor index.
+ * @param config See ``adc_digi_monitor_t``.
+ *
+ * @return
+ *      - ESP_OK Success
+ */
+esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
+
+/**
+ * @brief Enable/disable monitor of adc digital controller.
+ *
+ * @param idx Monitor index.
+ * @param enable True or false enable monitor.
+ *
+ * @return
+ *      - ESP_OK Success
+ */
+esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
+
+#ifdef __cplusplus
+}
+#endif

+ 91 - 0
components/driver/esp32h2/include/driver/temp_sensor.h

@@ -0,0 +1,91 @@
+/*
+ * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */
+    TSENS_DAC_L1,     /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */
+    TSENS_DAC_L2,     /*!< offset =  0, measure range:-10℃ ~  80℃, error < 1℃. */
+    TSENS_DAC_L3,     /*!< offset =  1, measure range:-30℃ ~  50℃, error < 2℃. */
+    TSENS_DAC_L4,     /*!< offset =  2, measure range:-40℃ ~  20℃, error < 3℃. */
+    TSENS_DAC_MAX,
+    TSENS_DAC_DEFAULT = TSENS_DAC_L2,
+} temp_sensor_dac_offset_t;
+
+/**
+ * @brief Configuration for temperature sensor reading
+ */
+typedef struct {
+    temp_sensor_dac_offset_t dac_offset;    /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */
+    uint8_t clk_div;                        /*!< Default: 6 */
+} temp_sensor_config_t;
+
+#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \
+                                .clk_div = 6}
+
+/**
+ * @brief Set parameter of temperature sensor.
+ * @param tsens
+ * @return
+ *     - ESP_OK Success
+ */
+esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens);
+
+/**
+ * @brief Get parameter of temperature sensor.
+ * @param tsens
+ * @return
+ *     - ESP_OK Success
+ */
+esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens);
+
+/**
+ * @brief Start temperature sensor measure.
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG
+ */
+esp_err_t temp_sensor_start(void);
+
+/**
+ * @brief Stop temperature sensor measure.
+ * @return
+ *     - ESP_OK Success
+ */
+esp_err_t temp_sensor_stop(void);
+
+/**
+ * @brief Read temperature sensor raw data.
+ * @param tsens_out Pointer to raw data, Range: 0 ~ 255
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG `tsens_out` is NULL
+ *     - ESP_ERR_INVALID_STATE temperature sensor dont start
+ */
+esp_err_t temp_sensor_read_raw(uint32_t *tsens_out);
+
+/**
+ * @brief Read temperature sensor data that is converted to degrees Celsius.
+ * @note  Should not be called from interrupt.
+ * @param celsius The measure output value.
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG ARG is NULL.
+ *     - ESP_ERR_INVALID_STATE The ambient temperature is out of range.
+ */
+esp_err_t temp_sensor_read_celsius(float *celsius);
+
+#ifdef __cplusplus
+}
+#endif

+ 151 - 0
components/driver/esp32h2/rtc_tempsensor.c

@@ -0,0 +1,151 @@
+/*
+ * SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_types.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <math.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "esp_log.h"
+#include "hal/adc_ll.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/apb_saradc_struct.h"
+#include "soc/apb_saradc_reg.h"
+#include "soc/system_reg.h"
+#include "driver/temp_sensor.h"
+#include "regi2c_ctrl.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp_efuse_rtc_calib.h"
+
+static const char *TAG = "tsens";
+
+#define TSENS_CHECK(res, ret_val) ({                                    \
+    if (!(res)) {                                                       \
+        ESP_LOGE(TAG, "%s(%d)", __FUNCTION__, __LINE__);                \
+        return (ret_val);                                               \
+    }                                                                   \
+})
+#define TSENS_XPD_WAIT_DEFAULT 0xFF   /* Set wait cycle time(8MHz) from power up to reset enable. */
+#define TSENS_ADC_FACTOR  (0.4386)
+#define TSENS_DAC_FACTOR  (27.88)
+#define TSENS_SYS_OFFSET  (20.52)
+
+typedef struct {
+    int index;
+    int offset;
+    int set_val;
+    int range_min;
+    int range_max;
+    int error_max;
+} tsens_dac_offset_t;
+
+static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = {
+    /*     DAC     Offset reg_val  min  max  error */
+    {TSENS_DAC_L0,   -2,     5,    50,  125,   3},
+    {TSENS_DAC_L1,   -1,     7,    20,  100,   2},
+    {TSENS_DAC_L2,    0,    15,   -10,   80,   1},
+    {TSENS_DAC_L3,    1,    11,   -30,   50,   2},
+    {TSENS_DAC_L4,    2,    10,   -40,   20,   3},
+};
+
+static float s_deltaT = NAN; // unused number
+
+esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
+{
+    REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN);
+    CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD);
+    SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU);
+    REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, dac_offset[tsens.dac_offset].set_val);
+    APB_SARADC.apb_tsens_ctrl.tsens_clk_div = tsens.clk_div;
+    APB_SARADC.apb_tsens_ctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT;
+    APB_SARADC.apb_tsens_ctrl2.tsens_xpd_force = 1;
+    ESP_LOGD(TAG, "Config temperature range [%d°C ~ %d°C], error < %d°C",
+             dac_offset[tsens.dac_offset].range_min,
+             dac_offset[tsens.dac_offset].range_max,
+             dac_offset[tsens.dac_offset].error_max);
+    return ESP_OK;
+}
+
+esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens)
+{
+    TSENS_CHECK(tsens != NULL, ESP_ERR_INVALID_ARG);
+    CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD);
+    SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU);
+    tsens->dac_offset = REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC);
+    for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) {
+        if (tsens->dac_offset == dac_offset[i].set_val) {
+            tsens->dac_offset = dac_offset[i].index;
+            break;
+        }
+    }
+    tsens->clk_div = APB_SARADC.apb_tsens_ctrl.tsens_clk_div;
+    return ESP_OK;
+}
+
+esp_err_t temp_sensor_start(void)
+{
+    REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN);
+    APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 1;
+    APB_SARADC.apb_tsens_ctrl.tsens_pu = 1;
+    return ESP_OK;
+}
+
+esp_err_t temp_sensor_stop(void)
+{
+    APB_SARADC.apb_tsens_ctrl.tsens_pu = 0;
+    APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 0;
+    return ESP_OK;
+}
+
+esp_err_t temp_sensor_read_raw(uint32_t *tsens_out)
+{
+    TSENS_CHECK(tsens_out != NULL, ESP_ERR_INVALID_ARG);
+    *tsens_out = APB_SARADC.apb_tsens_ctrl.tsens_out;
+    return ESP_OK;
+}
+
+static void read_delta_t_from_efuse(void)
+{
+    uint32_t version = esp_efuse_rtc_calib_get_ver();
+    if (version == 1) {
+        // fetch calibration value for temp sensor from eFuse
+        s_deltaT = esp_efuse_rtc_calib_get_cal_temp(version);
+    } else {
+        // no value to fetch, use 0.
+        s_deltaT = 0;
+    }
+    ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT);
+}
+
+static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset)
+{
+    if (isnan(s_deltaT)) { //suggests that the value is not initialized
+        read_delta_t_from_efuse();
+    }
+    float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT / 10.0;
+    return result;
+}
+
+esp_err_t temp_sensor_read_celsius(float *celsius)
+{
+    TSENS_CHECK(celsius != NULL, ESP_ERR_INVALID_ARG);
+    temp_sensor_config_t tsens;
+    uint32_t tsens_out = 0;
+    esp_err_t ret = temp_sensor_get_config(&tsens);
+    if (ret == ESP_OK) {
+        ret = temp_sensor_read_raw(&tsens_out);
+        printf("tsens_out %d\r\n", tsens_out);
+        TSENS_CHECK(ret == ESP_OK, ret);
+        const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset];
+        *celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset);
+        if (*celsius < dac->range_min || *celsius > dac->range_max) {
+            ESP_LOGW(TAG, "Exceeding the temperature range!");
+            ret = ESP_ERR_INVALID_STATE;
+        }
+    }
+    return ret;
+}

+ 1 - 1
components/driver/include/driver/adc2_wifi_private.h

@@ -35,7 +35,7 @@ esp_err_t adc2_wifi_acquire(void);
  */
 esp_err_t adc2_wifi_release(void);
 
-#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
+#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 /**
  * @brief This API help ADC2 calibration constructor be linked.
  *

+ 10 - 10
components/driver/include/driver/adc_common.h

@@ -45,7 +45,7 @@ typedef enum {
     ADC1_CHANNEL_9,     /*!< ADC1 channel 9 is GPIO10 */
     ADC1_CHANNEL_MAX,
 } adc1_channel_t;
-#elif CONFIG_IDF_TARGET_ESP32C3
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 /**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
 typedef enum {
     ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */
@@ -72,7 +72,7 @@ typedef enum {
     ADC2_CHANNEL_9,     /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */
     ADC2_CHANNEL_MAX,
 } adc2_channel_t;
-#elif CONFIG_IDF_TARGET_ESP32C3
+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 /**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
 typedef enum {
     ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
@@ -103,7 +103,7 @@ typedef enum {
 #define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
 #define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
 
-#if CONFIG_IDF_TARGET_ESP32C3
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 /**
  * @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
  */
@@ -121,7 +121,7 @@ typedef enum {
     ADC_ENCODE_MAX,
 } adc_i2s_encode_t;
 
-#if CONFIG_IDF_TARGET_ESP32C3
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 //This feature is currently supported on ESP32C3, will be supported on other chips soon
 /**
  * @brief Digital ADC DMA configuration
@@ -167,7 +167,7 @@ void adc_power_acquire(void);
  */
 void adc_power_release(void);
 
-#if !CONFIG_IDF_TARGET_ESP32C3
+#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
 /**
  * @brief Initialize ADC pad
  * @param adc_unit ADC unit index
@@ -177,7 +177,7 @@ void adc_power_release(void);
  *     - ESP_ERR_INVALID_ARG Parameter error
  */
 esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
-#endif //#if !CONFIG_IDF_TARGET_ESP32C3
+#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
 
 /*---------------------------------------------------------------
                     ADC Single Read Setting
@@ -276,7 +276,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
  */
 int adc1_get_raw(adc1_channel_t channel);
 
-#if !CONFIG_IDF_TARGET_ESP32C3
+#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
 /**
  * @brief Set ADC data invert
  * @param adc_unit ADC unit index
@@ -317,7 +317,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
  * to be called to configure ADC1 channels, before ADC1 is used by the ULP.
  */
 void adc1_ulp_enable(void);
-#endif  //#if !CONFIG_IDF_TARGET_ESP32C3
+#endif  //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
 
 /**
  * @brief Get the GPIO number of a specific ADC2 channel.
@@ -477,7 +477,7 @@ esp_err_t adc_digi_deinit(void);
  */
 esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
 
-#if CONFIG_IDF_TARGET_ESP32C3
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 //This feature is currently supported on ESP32C3, will be supported on other chips soon
 /*---------------------------------------------------------------
                     DMA setting
@@ -537,7 +537,7 @@ esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_l
  */
 esp_err_t adc_digi_deinitialize(void);
 
-#endif //#if CONFIG_IDF_TARGET_ESP32C3
+#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
 
 #ifdef __cplusplus
 }

+ 2 - 0
components/driver/include/driver/gpio.h

@@ -33,6 +33,8 @@
 #include "esp32c3/rom/gpio.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/gpio.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/gpio.h"
 #endif
 
 #ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS

+ 2 - 0
components/driver/periph_ctrl.c

@@ -42,6 +42,7 @@ void periph_module_reset(periph_module_t periph)
     portEXIT_CRITICAL_SAFE(&periph_spinlock);
 }
 
+#if CONFIG_ESP32_WIFI_ENABLED
 IRAM_ATTR void wifi_bt_common_module_enable(void)
 {
     portENTER_CRITICAL_SAFE(&periph_spinlock);
@@ -71,3 +72,4 @@ void wifi_module_disable(void)
 {
     periph_ll_wifi_module_disable_clk_set_rst();
 }
+#endif // CONFIG_ESP32_WIFI_ENABLED

+ 2 - 0
components/driver/uart.c

@@ -32,6 +32,8 @@
 #include "esp32s3/clk.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/clk.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/clk.h"
 #endif
 
 #ifdef CONFIG_UART_ISR_IN_IRAM

+ 63 - 0
components/efuse/esp32h2/esp_efuse_fields.c

@@ -0,0 +1,63 @@
+/*
+ * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_efuse.h"
+#include "esp_efuse_utility.h"
+#include "esp_efuse_table.h"
+#include "stdlib.h"
+#include "esp_types.h"
+#include "esp32h2/rom/efuse.h"
+#include "assert.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "soc/efuse_periph.h"
+#include "bootloader_random.h"
+#include "sys/param.h"
+
+static __attribute__((unused)) const char *TAG = "efuse";
+
+// Contains functions that provide access to efuse fields which are often used in IDF.
+
+// Returns chip version from efuse
+uint8_t esp_efuse_get_chip_ver(void)
+{
+    uint32_t chip_ver = 0;
+    esp_efuse_read_field_blob(ESP_EFUSE_WAFER_VERSION, &chip_ver, ESP_EFUSE_WAFER_VERSION[0]->bit_count);
+    return chip_ver;
+}
+
+// Returns chip package from efuse
+uint32_t esp_efuse_get_pkg_ver(void)
+{
+    uint32_t pkg_ver = 0;
+    esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, ESP_EFUSE_PKG_VERSION[0]->bit_count);
+    return pkg_ver;
+}
+
+
+esp_err_t esp_efuse_set_rom_log_scheme(esp_efuse_rom_log_scheme_t log_scheme)
+{
+    int cur_log_scheme = 0;
+    esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, 2);
+    if (!cur_log_scheme) { // not burned yet
+        return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, 2);
+    } else {
+        return ESP_ERR_INVALID_STATE;
+    }
+}
+
+esp_err_t esp_efuse_disable_rom_download_mode(void)
+{
+    return esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE);
+}
+
+esp_err_t esp_efuse_enable_rom_secure_download_mode(void)
+{
+    if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE)) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    return esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD);
+}

+ 89 - 0
components/efuse/esp32h2/esp_efuse_rtc_calib.c

@@ -0,0 +1,89 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_bit_defs.h>
+#include "esp_efuse.h"
+#include "esp_efuse_table.h"
+
+int esp_efuse_rtc_calib_get_ver(void)
+{
+    uint32_t result = 0;
+    esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &result, 3);
+    return result;
+}
+
+uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten)
+{
+    assert(version == 1);
+    const esp_efuse_desc_t** init_code_efuse;
+    assert(atten < 4);
+    if (atten == 0) {
+        init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN0;
+    } else if (atten == 1) {
+        init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN1;
+    } else if (atten == 2) {
+        init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN2;
+    } else {
+        init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN3;
+    }
+
+    int init_code_size = esp_efuse_get_field_size(init_code_efuse);
+    assert(init_code_size == 10);
+
+    uint32_t init_code = 0;
+    ESP_ERROR_CHECK(esp_efuse_read_field_blob(init_code_efuse, &init_code, init_code_size));
+    return init_code + 1000;    // version 1 logic
+}
+
+esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* out_digi, uint32_t* out_vol_mv)
+{
+    const esp_efuse_desc_t** cal_vol_efuse;
+    uint32_t calib_vol_expected_mv;
+    if (version != 1) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (atten >= 4) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (atten == 0) {
+        cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN0;
+        calib_vol_expected_mv = 400;
+    } else if (atten == 1) {
+        cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN1;
+        calib_vol_expected_mv = 550;
+    } else if (atten == 2) {
+        cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN2;
+        calib_vol_expected_mv = 750;
+    } else {
+        cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN3;
+        calib_vol_expected_mv = 1370;
+    }
+
+    assert(cal_vol_efuse[0]->bit_count == 10);
+
+    uint32_t cal_vol = 0;
+    ESP_ERROR_CHECK(esp_efuse_read_field_blob(cal_vol_efuse, &cal_vol, cal_vol_efuse[0]->bit_count));
+
+    *out_digi = 2000 + ((cal_vol & BIT(9))? -(cal_vol & ~BIT9): cal_vol);
+    *out_vol_mv = calib_vol_expected_mv;
+    return ESP_OK;
+}
+
+float esp_efuse_rtc_calib_get_cal_temp(int version)
+{
+    assert(version == 1);
+    const esp_efuse_desc_t** cal_temp_efuse;
+    cal_temp_efuse = ESP_EFUSE_TEMP_CALIB;
+    int cal_temp_size = esp_efuse_get_field_size(cal_temp_efuse);
+    assert(cal_temp_size == 9);
+
+    uint32_t cal_temp = 0;
+    esp_err_t err = esp_efuse_read_field_blob(cal_temp_efuse, &cal_temp, cal_temp_size);
+    assert(err == ESP_OK);
+    (void)err;
+    // BIT(8) stands for sign: 1: negtive, 0: positive
+    return ((cal_temp & BIT(8)) != 0)? -(uint8_t)cal_temp: (uint8_t)cal_temp;
+}

+ 1128 - 0
components/efuse/esp32h2/esp_efuse_table.c

@@ -0,0 +1,1128 @@
+/*
+ * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "sdkconfig.h"
+#include "esp_efuse.h"
+#include <assert.h>
+#include "esp_efuse_table.h"
+
+// md5_digest_table 9e42b2f9dd879191ca75ad0cf50841a1
+// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
+// If you want to change some fields, you need to change esp_efuse_table.csv file
+// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
+// To show efuse_table run the command 'show_efuse_table'.
+
+static const esp_efuse_desc_t WR_DIS[] = {
+    {EFUSE_BLK0, 0, 32}, 	 // Write protection,
+};
+
+static const esp_efuse_desc_t WR_DIS_RD_DIS[] = {
+    {EFUSE_BLK0, 0, 1}, 	 // Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2,
+};
+
+static const esp_efuse_desc_t WR_DIS_GROUP_1[] = {
+    {EFUSE_BLK0, 2, 1}, 	 // Write protection for DIS_ICACHE DIS_DOWNLOAD_ICACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT,
+};
+
+static const esp_efuse_desc_t WR_DIS_GROUP_2[] = {
+    {EFUSE_BLK0, 3, 1}, 	 // Write protection for WDT_DELAY_SEL,
+};
+
+static const esp_efuse_desc_t WR_DIS_SPI_BOOT_CRYPT_CNT[] = {
+    {EFUSE_BLK0, 4, 1}, 	 // Write protection for SPI_BOOT_CRYPT_CNT,
+};
+
+static const esp_efuse_desc_t WR_DIS_SECURE_BOOT_KEY_REVOKE0[] = {
+    {EFUSE_BLK0, 5, 1}, 	 // Write protection for SECURE_BOOT_KEY_REVOKE0,
+};
+
+static const esp_efuse_desc_t WR_DIS_SECURE_BOOT_KEY_REVOKE1[] = {
+    {EFUSE_BLK0, 6, 1}, 	 // Write protection for SECURE_BOOT_KEY_REVOKE1,
+};
+
+static const esp_efuse_desc_t WR_DIS_SECURE_BOOT_KEY_REVOKE2[] = {
+    {EFUSE_BLK0, 7, 1}, 	 // Write protection for SECURE_BOOT_KEY_REVOKE2,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY0_PURPOSE[] = {
+    {EFUSE_BLK0, 8, 1}, 	 // Write protection for key_purpose. KEY0,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY1_PURPOSE[] = {
+    {EFUSE_BLK0, 9, 1}, 	 // Write protection for key_purpose. KEY1,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY2_PURPOSE[] = {
+    {EFUSE_BLK0, 10, 1}, 	 // Write protection for key_purpose. KEY2,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY3_PURPOSE[] = {
+    {EFUSE_BLK0, 11, 1}, 	 // Write protection for key_purpose. KEY3,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY4_PURPOSE[] = {
+    {EFUSE_BLK0, 12, 1}, 	 // Write protection for key_purpose. KEY4,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY5_PURPOSE[] = {
+    {EFUSE_BLK0, 13, 1}, 	 // Write protection for key_purpose. KEY5,
+};
+
+static const esp_efuse_desc_t WR_DIS_SECURE_BOOT_EN[] = {
+    {EFUSE_BLK0, 15, 1}, 	 // Write protection for SECURE_BOOT_EN,
+};
+
+static const esp_efuse_desc_t WR_DIS_SECURE_BOOT_AGGRESSIVE_REVOKE[] = {
+    {EFUSE_BLK0, 16, 1}, 	 // Write protection for SECURE_BOOT_AGGRESSIVE_REVOKE,
+};
+
+static const esp_efuse_desc_t WR_DIS_GROUP_3[] = {
+    {EFUSE_BLK0, 18, 1}, 	 // Write protection for FLASH_TPUW DIS_DOWNLOAD_MODE DIS_LEGACY_SPI_BOOT UART_PRINT_CHANNEL DIS_TINY_BASIC DIS_USB_DOWNLOAD_MODE ENABLE_SECURITY_DOWNLOAD UART_PRINT_CONTROL PIN_POWER_SELECTION FLASH_TYPE FORCE_SEND_RESUME SECURE_VERSION,
+};
+
+static const esp_efuse_desc_t WR_DIS_BLK1[] = {
+    {EFUSE_BLK0, 20, 1}, 	 // Write protection for EFUSE_BLK1.  MAC_SPI_8M_SYS,
+};
+
+static const esp_efuse_desc_t WR_DIS_SYS_DATA_PART1[] = {
+    {EFUSE_BLK0, 21, 1}, 	 // Write protection for EFUSE_BLK2.  SYS_DATA_PART1,
+};
+
+static const esp_efuse_desc_t WR_DIS_USER_DATA[] = {
+    {EFUSE_BLK0, 22, 1}, 	 // Write protection for EFUSE_BLK3.  USER_DATA,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY0[] = {
+    {EFUSE_BLK0, 23, 1}, 	 // Write protection for EFUSE_BLK4.  KEY0,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY1[] = {
+    {EFUSE_BLK0, 24, 1}, 	 // Write protection for EFUSE_BLK5.  KEY1,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY2[] = {
+    {EFUSE_BLK0, 25, 1}, 	 // Write protection for EFUSE_BLK6.  KEY2,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY3[] = {
+    {EFUSE_BLK0, 26, 1}, 	 // Write protection for EFUSE_BLK7.  KEY3,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY4[] = {
+    {EFUSE_BLK0, 27, 1}, 	 // Write protection for EFUSE_BLK8.  KEY4,
+};
+
+static const esp_efuse_desc_t WR_DIS_KEY5[] = {
+    {EFUSE_BLK0, 28, 1}, 	 // Write protection for EFUSE_BLK9.  KEY5,
+};
+
+static const esp_efuse_desc_t WR_DIS_SYS_DATA_PART2[] = {
+    {EFUSE_BLK0, 29, 1}, 	 // Write protection for EFUSE_BLK10. SYS_DATA_PART2,
+};
+
+static const esp_efuse_desc_t RD_DIS[] = {
+    {EFUSE_BLK0, 32, 7}, 	 // Read protection,
+};
+
+static const esp_efuse_desc_t RD_DIS_KEY0[] = {
+    {EFUSE_BLK0, 32, 1}, 	 // Read protection for EFUSE_BLK4.  KEY0,
+};
+
+static const esp_efuse_desc_t RD_DIS_KEY1[] = {
+    {EFUSE_BLK0, 33, 1}, 	 // Read protection for EFUSE_BLK5.  KEY1,
+};
+
+static const esp_efuse_desc_t RD_DIS_KEY2[] = {
+    {EFUSE_BLK0, 34, 1}, 	 // Read protection for EFUSE_BLK6.  KEY2,
+};
+
+static const esp_efuse_desc_t RD_DIS_KEY3[] = {
+    {EFUSE_BLK0, 35, 1}, 	 // Read protection for EFUSE_BLK7.  KEY3,
+};
+
+static const esp_efuse_desc_t RD_DIS_KEY4[] = {
+    {EFUSE_BLK0, 36, 1}, 	 // Read protection for EFUSE_BLK8.  KEY4,
+};
+
+static const esp_efuse_desc_t RD_DIS_KEY5[] = {
+    {EFUSE_BLK0, 37, 1}, 	 // Read protection for EFUSE_BLK9.  KEY5,
+};
+
+static const esp_efuse_desc_t RD_DIS_SYS_DATA_PART2[] = {
+    {EFUSE_BLK0, 38, 1}, 	 // Read protection for EFUSE_BLK10. SYS_DATA_PART2,
+};
+
+static const esp_efuse_desc_t DIS_RTC_RAM_BOOT[] = {
+    {EFUSE_BLK0, 39, 1}, 	 // Disable boot from RTC RAM,
+};
+
+static const esp_efuse_desc_t DIS_ICACHE[] = {
+    {EFUSE_BLK0, 40, 1}, 	 // Disable Icache,
+};
+
+static const esp_efuse_desc_t DIS_USB_JTAG[] = {
+    {EFUSE_BLK0, 41, 1}, 	 // Disable USB JTAG,
+};
+
+static const esp_efuse_desc_t DIS_DOWNLOAD_ICACHE[] = {
+    {EFUSE_BLK0, 42, 1}, 	 // Disable Icache in download mode,
+};
+
+static const esp_efuse_desc_t DIS_USB_DEVICE[] = {
+    {EFUSE_BLK0, 43, 1}, 	 // Disable USB_DEVICE,
+};
+
+static const esp_efuse_desc_t DIS_FORCE_DOWNLOAD[] = {
+    {EFUSE_BLK0, 44, 1}, 	 // Disable force chip go to download mode function,
+};
+
+static const esp_efuse_desc_t DIS_USB[] = {
+    {EFUSE_BLK0, 45, 1}, 	 // Disable USB function,
+};
+
+static const esp_efuse_desc_t DIS_CAN[] = {
+    {EFUSE_BLK0, 46, 1}, 	 // Disable CAN function,
+};
+
+static const esp_efuse_desc_t JTAG_SEL_ENABLE[] = {
+    {EFUSE_BLK0, 47, 1}, 	 // Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0.,
+};
+
+static const esp_efuse_desc_t SOFT_DIS_JTAG[] = {
+    {EFUSE_BLK0, 48, 2}, 	 // Set these bits to disable JTAG in the soft way (odd number 1 means disable). JTAG can be enabled in HMAC module.,
+};
+
+static const esp_efuse_desc_t DIS_PAD_JTAG[] = {
+    {EFUSE_BLK0, 51, 1}, 	 // Disable JTAG in the hard way. JTAG is disabled permanently.,
+};
+
+static const esp_efuse_desc_t DIS_DOWNLOAD_MANUAL_ENCRYPT[] = {
+    {EFUSE_BLK0, 52, 1}, 	 // Disable flash encryption when in download boot modes.,
+};
+
+static const esp_efuse_desc_t USB_DREFH[] = {
+    {EFUSE_BLK0, 53, 2}, 	 // Controls single-end input threshold vrefh 1.76 V to 2 V with step of 80 mV stored in eFuse.,
+};
+
+static const esp_efuse_desc_t USB_DREFL[] = {
+    {EFUSE_BLK0, 55, 2}, 	 // Controls single-end input threshold vrefl 0.8 V to 1.04 V with step of 80 mV stored in eFuse.,
+};
+
+static const esp_efuse_desc_t USB_EXCHG_PINS[] = {
+    {EFUSE_BLK0, 57, 1}, 	 // Exchange D+ D- pins,
+};
+
+static const esp_efuse_desc_t VDD_SPI_AS_GPIO[] = {
+    {EFUSE_BLK0, 58, 1}, 	 // Set this bit to vdd spi pin function as gpio,
+};
+
+static const esp_efuse_desc_t BTLC_GPIO_ENABLE[] = {
+    {EFUSE_BLK0, 59, 2}, 	 // Enable btlc gpio,
+};
+
+static const esp_efuse_desc_t POWERGLITCH_EN[] = {
+    {EFUSE_BLK0, 61, 1}, 	 // Set this bit to enable power glitch function,
+};
+
+static const esp_efuse_desc_t POWER_GLITCH_DSENSE[] = {
+    {EFUSE_BLK0, 62, 2}, 	 // Sample delay configuration of power glitch,
+};
+
+static const esp_efuse_desc_t WDT_DELAY_SEL[] = {
+    {EFUSE_BLK0, 80, 2}, 	 // Select RTC WDT time out threshold,
+};
+
+static const esp_efuse_desc_t SPI_BOOT_CRYPT_CNT[] = {
+    {EFUSE_BLK0, 82, 3}, 	 // SPI boot encrypt decrypt enable. odd number 1 enable. even number 1 disable,
+};
+
+static const esp_efuse_desc_t SECURE_BOOT_KEY_REVOKE0[] = {
+    {EFUSE_BLK0, 85, 1}, 	 // Enable revoke first secure boot key,
+};
+
+static const esp_efuse_desc_t SECURE_BOOT_KEY_REVOKE1[] = {
+    {EFUSE_BLK0, 86, 1}, 	 // Enable revoke second secure boot key,
+};
+
+static const esp_efuse_desc_t SECURE_BOOT_KEY_REVOKE2[] = {
+    {EFUSE_BLK0, 87, 1}, 	 // Enable revoke third secure boot key,
+};
+
+static const esp_efuse_desc_t KEY_PURPOSE_0[] = {
+    {EFUSE_BLK0, 88, 4}, 	 // Key0 purpose,
+};
+
+static const esp_efuse_desc_t KEY_PURPOSE_1[] = {
+    {EFUSE_BLK0, 92, 4}, 	 // Key1 purpose,
+};
+
+static const esp_efuse_desc_t KEY_PURPOSE_2[] = {
+    {EFUSE_BLK0, 96, 4}, 	 // Key2 purpose,
+};
+
+static const esp_efuse_desc_t KEY_PURPOSE_3[] = {
+    {EFUSE_BLK0, 100, 4}, 	 // Key3 purpose,
+};
+
+static const esp_efuse_desc_t KEY_PURPOSE_4[] = {
+    {EFUSE_BLK0, 104, 4}, 	 // Key4 purpose,
+};
+
+static const esp_efuse_desc_t KEY_PURPOSE_5[] = {
+    {EFUSE_BLK0, 108, 4}, 	 // Key5 purpose,
+};
+
+static const esp_efuse_desc_t SECURE_BOOT_EN[] = {
+    {EFUSE_BLK0, 116, 1}, 	 // Secure boot enable,
+};
+
+static const esp_efuse_desc_t SECURE_BOOT_AGGRESSIVE_REVOKE[] = {
+    {EFUSE_BLK0, 117, 1}, 	 // Enable aggressive secure boot revoke,
+};
+
+static const esp_efuse_desc_t FLASH_TPUW[] = {
+    {EFUSE_BLK0, 124, 4}, 	 // Flash wait time after power up. (unit is ms). When value is 15. the time is 30 ms,
+};
+
+static const esp_efuse_desc_t DIS_DOWNLOAD_MODE[] = {
+    {EFUSE_BLK0, 128, 1}, 	 // Disble download mode include boot_mode[3:0] is 0 1 2 3 6 7,
+};
+
+static const esp_efuse_desc_t DIS_LEGACY_SPI_BOOT[] = {
+    {EFUSE_BLK0, 129, 1}, 	 // Disable_Legcy_SPI_boot mode include boot_mode[3:0] is 4,
+};
+
+static const esp_efuse_desc_t UART_PRINT_CHANNEL[] = {
+    {EFUSE_BLK0, 130, 1}, 	 // 0: UART0. 1: UART1,
+};
+
+static const esp_efuse_desc_t FLASH_ECC_MODE[] = {
+    {EFUSE_BLK0, 131, 1}, 	 // Set this bit to set flsah ecc mode. 0:flash ecc 16to18 byte mode. 1:flash ecc 16to17 byte mode,
+};
+
+static const esp_efuse_desc_t DIS_USB_DOWNLOAD_MODE[] = {
+    {EFUSE_BLK0, 132, 1}, 	 // Disable download through USB,
+};
+
+static const esp_efuse_desc_t ENABLE_SECURITY_DOWNLOAD[] = {
+    {EFUSE_BLK0, 133, 1}, 	 // Enable security download mode,
+};
+
+static const esp_efuse_desc_t UART_PRINT_CONTROL[] = {
+    {EFUSE_BLK0, 134, 2}, 	 // b00:force print. b01:control by GPIO8 - low level print. b10:control by GPIO8 - high level print. b11:force disable print.,
+};
+
+static const esp_efuse_desc_t PIN_POWER_SELECTION[] = {
+    {EFUSE_BLK0, 136, 1}, 	 // GPIO33-GPIO37 power supply selection in ROM code. 0:VDD3P3_CPU. 1:VDD_SPI.,
+};
+
+static const esp_efuse_desc_t FLASH_TYPE[] = {
+    {EFUSE_BLK0, 137, 1}, 	 // Connected Flash interface type. 0: 4 data line. 1: 8 data line,
+};
+
+static const esp_efuse_desc_t FLASH_PAGE_SIZE[] = {
+    {EFUSE_BLK0, 138, 2}, 	 // Flash page size,
+};
+
+static const esp_efuse_desc_t FLASH_ECC_EN[] = {
+    {EFUSE_BLK0, 140, 1}, 	 // Enable ECC for flash boot,
+};
+
+static const esp_efuse_desc_t FORCE_SEND_RESUME[] = {
+    {EFUSE_BLK0, 141, 1}, 	 // Force ROM code to send a resume command during SPI boot,
+};
+
+static const esp_efuse_desc_t SECURE_VERSION[] = {
+    {EFUSE_BLK0, 142, 16}, 	 // Secure version for anti-rollback,
+};
+
+static const esp_efuse_desc_t MAC_FACTORY[] = {
+    {EFUSE_BLK1, 40, 8}, 	 // Factory MAC addr [0],
+    {EFUSE_BLK1, 32, 8}, 	 // Factory MAC addr [1],
+    {EFUSE_BLK1, 24, 8}, 	 // Factory MAC addr [2],
+    {EFUSE_BLK1, 16, 8}, 	 // Factory MAC addr [3],
+    {EFUSE_BLK1, 8, 8}, 	 // Factory MAC addr [4],
+    {EFUSE_BLK1, 0, 8}, 	 // Factory MAC addr [5],
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_CLK[] = {
+    {EFUSE_BLK1, 48, 6}, 	 // SPI_PAD_configure CLK,
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_Q_D1[] = {
+    {EFUSE_BLK1, 54, 6}, 	 // SPI_PAD_configure Q(D1),
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_D_D0[] = {
+    {EFUSE_BLK1, 60, 6}, 	 // SPI_PAD_configure D(D0),
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_CS[] = {
+    {EFUSE_BLK1, 66, 6}, 	 // SPI_PAD_configure CS,
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_HD_D3[] = {
+    {EFUSE_BLK1, 72, 6}, 	 // SPI_PAD_configure HD(D3),
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_WP_D2[] = {
+    {EFUSE_BLK1, 78, 6}, 	 // SPI_PAD_configure WP(D2),
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_DQS[] = {
+    {EFUSE_BLK1, 84, 6}, 	 // SPI_PAD_configure DQS,
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_D4[] = {
+    {EFUSE_BLK1, 90, 6}, 	 // SPI_PAD_configure D4,
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_D5[] = {
+    {EFUSE_BLK1, 96, 6}, 	 // SPI_PAD_configure D5,
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_D6[] = {
+    {EFUSE_BLK1, 102, 6}, 	 // SPI_PAD_configure D6,
+};
+
+static const esp_efuse_desc_t SPI_PAD_CONFIG_D7[] = {
+    {EFUSE_BLK1, 108, 6}, 	 // SPI_PAD_configure D7,
+};
+
+static const esp_efuse_desc_t WAFER_VERSION[] = {
+    {EFUSE_BLK1, 114, 3}, 	 // WAFER version,
+};
+
+static const esp_efuse_desc_t PKG_VERSION[] = {
+    {EFUSE_BLK1, 117, 3}, 	 // Package version 0:ESP32H2,
+};
+
+static const esp_efuse_desc_t BLOCK1_VERSION[] = {
+    {EFUSE_BLK1, 120, 3}, 	 // BLOCK1 efuse version,
+};
+
+static const esp_efuse_desc_t OPTIONAL_UNIQUE_ID[] = {
+    {EFUSE_BLK2, 0, 128}, 	 // Optional unique 128-bit ID,
+};
+
+static const esp_efuse_desc_t BLOCK2_VERSION[] = {
+    {EFUSE_BLK2, 128, 3}, 	 // Version of BLOCK2,
+};
+
+static const esp_efuse_desc_t TEMP_CALIB[] = {
+    {EFUSE_BLK2, 131, 9}, 	 // Temperature calibration data,
+};
+
+static const esp_efuse_desc_t OCODE[] = {
+    {EFUSE_BLK2, 140, 8}, 	 // ADC OCode,
+};
+
+static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN0[] = {
+    {EFUSE_BLK2, 148, 10}, 	 // ADC1 init code at atten0,
+};
+
+static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN1[] = {
+    {EFUSE_BLK2, 158, 10}, 	 // ADC1 init code at atten1,
+};
+
+static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN2[] = {
+    {EFUSE_BLK2, 168, 10}, 	 // ADC1 init code at atten2,
+};
+
+static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN3[] = {
+    {EFUSE_BLK2, 178, 10}, 	 // ADC1 init code at atten3,
+};
+
+static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN0[] = {
+    {EFUSE_BLK2, 188, 10}, 	 // ADC1 calibration voltage at atten0,
+};
+
+static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN1[] = {
+    {EFUSE_BLK2, 198, 10}, 	 // ADC1 calibration voltage at atten1,
+};
+
+static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN2[] = {
+    {EFUSE_BLK2, 208, 10}, 	 // ADC1 calibration voltage at atten2,
+};
+
+static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN3[] = {
+    {EFUSE_BLK2, 218, 10}, 	 // ADC1 calibration voltage at atten3,
+};
+
+static const esp_efuse_desc_t USER_DATA[] = {
+    {EFUSE_BLK3, 0, 256}, 	 // User data,
+};
+
+static const esp_efuse_desc_t KEY0[] = {
+    {EFUSE_BLK4, 0, 256}, 	 // Key0 or user data,
+};
+
+static const esp_efuse_desc_t KEY1[] = {
+    {EFUSE_BLK5, 0, 256}, 	 // Key1 or user data,
+};
+
+static const esp_efuse_desc_t KEY2[] = {
+    {EFUSE_BLK6, 0, 256}, 	 // Key2 or user data,
+};
+
+static const esp_efuse_desc_t KEY3[] = {
+    {EFUSE_BLK7, 0, 256}, 	 // Key3 or user data,
+};
+
+static const esp_efuse_desc_t KEY4[] = {
+    {EFUSE_BLK8, 0, 256}, 	 // Key4 or user data,
+};
+
+static const esp_efuse_desc_t KEY5[] = {
+    {EFUSE_BLK9, 0, 256}, 	 // Key5 or user data,
+};
+
+static const esp_efuse_desc_t SYS_DATA_PART2[] = {
+    {EFUSE_BLK10, 0, 256}, 	 // System configuration,
+};
+
+static const esp_efuse_desc_t K_RTC_LDO[] = {
+    {EFUSE_BLK1, 135, 7}, 	 // BLOCK1 K_RTC_LDO,
+};
+
+static const esp_efuse_desc_t K_DIG_LDO[] = {
+    {EFUSE_BLK1, 142, 7}, 	 // BLOCK1 K_DIG_LDO,
+};
+
+static const esp_efuse_desc_t V_RTC_DBIAS20[] = {
+    {EFUSE_BLK1, 149, 8}, 	 // BLOCK1 voltage of rtc dbias20,
+};
+
+static const esp_efuse_desc_t V_DIG_DBIAS20[] = {
+    {EFUSE_BLK1, 157, 8}, 	 // BLOCK1 voltage of digital dbias20,
+};
+
+static const esp_efuse_desc_t DIG_DBIAS_HVT[] = {
+    {EFUSE_BLK1, 165, 5}, 	 // BLOCK1 digital dbias when hvt,
+};
+
+static const esp_efuse_desc_t THRES_HVT[] = {
+    {EFUSE_BLK1, 170, 10}, 	 // BLOCK1 pvt threshold when hvt,
+};
+
+
+
+
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS[] = {
+    &WR_DIS[0],    		// Write protection
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[] = {
+    &WR_DIS_RD_DIS[0],    		// Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[] = {
+    &WR_DIS_GROUP_1[0],    		// Write protection for DIS_ICACHE DIS_DOWNLOAD_ICACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_2[] = {
+    &WR_DIS_GROUP_2[0],    		// Write protection for WDT_DELAY_SEL
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT[] = {
+    &WR_DIS_SPI_BOOT_CRYPT_CNT[0],    		// Write protection for SPI_BOOT_CRYPT_CNT
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0[] = {
+    &WR_DIS_SECURE_BOOT_KEY_REVOKE0[0],    		// Write protection for SECURE_BOOT_KEY_REVOKE0
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1[] = {
+    &WR_DIS_SECURE_BOOT_KEY_REVOKE1[0],    		// Write protection for SECURE_BOOT_KEY_REVOKE1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2[] = {
+    &WR_DIS_SECURE_BOOT_KEY_REVOKE2[0],    		// Write protection for SECURE_BOOT_KEY_REVOKE2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0_PURPOSE[] = {
+    &WR_DIS_KEY0_PURPOSE[0],    		// Write protection for key_purpose. KEY0
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1_PURPOSE[] = {
+    &WR_DIS_KEY1_PURPOSE[0],    		// Write protection for key_purpose. KEY1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2_PURPOSE[] = {
+    &WR_DIS_KEY2_PURPOSE[0],    		// Write protection for key_purpose. KEY2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3_PURPOSE[] = {
+    &WR_DIS_KEY3_PURPOSE[0],    		// Write protection for key_purpose. KEY3
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4_PURPOSE[] = {
+    &WR_DIS_KEY4_PURPOSE[0],    		// Write protection for key_purpose. KEY4
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5_PURPOSE[] = {
+    &WR_DIS_KEY5_PURPOSE[0],    		// Write protection for key_purpose. KEY5
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_EN[] = {
+    &WR_DIS_SECURE_BOOT_EN[0],    		// Write protection for SECURE_BOOT_EN
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_AGGRESSIVE_REVOKE[] = {
+    &WR_DIS_SECURE_BOOT_AGGRESSIVE_REVOKE[0],    		// Write protection for SECURE_BOOT_AGGRESSIVE_REVOKE
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_3[] = {
+    &WR_DIS_GROUP_3[0],    		// Write protection for FLASH_TPUW DIS_DOWNLOAD_MODE DIS_LEGACY_SPI_BOOT UART_PRINT_CHANNEL DIS_TINY_BASIC DIS_USB_DOWNLOAD_MODE ENABLE_SECURITY_DOWNLOAD UART_PRINT_CONTROL PIN_POWER_SELECTION FLASH_TYPE FORCE_SEND_RESUME SECURE_VERSION
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[] = {
+    &WR_DIS_BLK1[0],    		// Write protection for EFUSE_BLK1.  MAC_SPI_8M_SYS
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART1[] = {
+    &WR_DIS_SYS_DATA_PART1[0],    		// Write protection for EFUSE_BLK2.  SYS_DATA_PART1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_USER_DATA[] = {
+    &WR_DIS_USER_DATA[0],    		// Write protection for EFUSE_BLK3.  USER_DATA
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0[] = {
+    &WR_DIS_KEY0[0],    		// Write protection for EFUSE_BLK4.  KEY0
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1[] = {
+    &WR_DIS_KEY1[0],    		// Write protection for EFUSE_BLK5.  KEY1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2[] = {
+    &WR_DIS_KEY2[0],    		// Write protection for EFUSE_BLK6.  KEY2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3[] = {
+    &WR_DIS_KEY3[0],    		// Write protection for EFUSE_BLK7.  KEY3
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4[] = {
+    &WR_DIS_KEY4[0],    		// Write protection for EFUSE_BLK8.  KEY4
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5[] = {
+    &WR_DIS_KEY5[0],    		// Write protection for EFUSE_BLK9.  KEY5
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART2[] = {
+    &WR_DIS_SYS_DATA_PART2[0],    		// Write protection for EFUSE_BLK10. SYS_DATA_PART2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS[] = {
+    &RD_DIS[0],    		// Read protection
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY0[] = {
+    &RD_DIS_KEY0[0],    		// Read protection for EFUSE_BLK4.  KEY0
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY1[] = {
+    &RD_DIS_KEY1[0],    		// Read protection for EFUSE_BLK5.  KEY1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY2[] = {
+    &RD_DIS_KEY2[0],    		// Read protection for EFUSE_BLK6.  KEY2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[] = {
+    &RD_DIS_KEY3[0],    		// Read protection for EFUSE_BLK7.  KEY3
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[] = {
+    &RD_DIS_KEY4[0],    		// Read protection for EFUSE_BLK8.  KEY4
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[] = {
+    &RD_DIS_KEY5[0],    		// Read protection for EFUSE_BLK9.  KEY5
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[] = {
+    &RD_DIS_SYS_DATA_PART2[0],    		// Read protection for EFUSE_BLK10. SYS_DATA_PART2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[] = {
+    &DIS_RTC_RAM_BOOT[0],    		// Disable boot from RTC RAM
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[] = {
+    &DIS_ICACHE[0],    		// Disable Icache
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_JTAG[] = {
+    &DIS_USB_JTAG[0],    		// Disable USB JTAG
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[] = {
+    &DIS_DOWNLOAD_ICACHE[0],    		// Disable Icache in download mode
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_DEVICE[] = {
+    &DIS_USB_DEVICE[0],    		// Disable USB_DEVICE
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_FORCE_DOWNLOAD[] = {
+    &DIS_FORCE_DOWNLOAD[0],    		// Disable force chip go to download mode function
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_USB[] = {
+    &DIS_USB[0],    		// Disable USB function
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_CAN[] = {
+    &DIS_CAN[0],    		// Disable CAN function
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_JTAG_SEL_ENABLE[] = {
+    &JTAG_SEL_ENABLE[0],    		// Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SOFT_DIS_JTAG[] = {
+    &SOFT_DIS_JTAG[0],    		// Set these bits to disable JTAG in the soft way (odd number 1 means disable). JTAG can be enabled in HMAC module.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_PAD_JTAG[] = {
+    &DIS_PAD_JTAG[0],    		// Disable JTAG in the hard way. JTAG is disabled permanently.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT[] = {
+    &DIS_DOWNLOAD_MANUAL_ENCRYPT[0],    		// Disable flash encryption when in download boot modes.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_USB_DREFH[] = {
+    &USB_DREFH[0],    		// Controls single-end input threshold vrefh 1.76 V to 2 V with step of 80 mV stored in eFuse.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_USB_DREFL[] = {
+    &USB_DREFL[0],    		// Controls single-end input threshold vrefl 0.8 V to 1.04 V with step of 80 mV stored in eFuse.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_USB_EXCHG_PINS[] = {
+    &USB_EXCHG_PINS[0],    		// Exchange D+ D- pins
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_AS_GPIO[] = {
+    &VDD_SPI_AS_GPIO[0],    		// Set this bit to vdd spi pin function as gpio
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_BTLC_GPIO_ENABLE[] = {
+    &BTLC_GPIO_ENABLE[0],    		// Enable btlc gpio
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_POWERGLITCH_EN[] = {
+    &POWERGLITCH_EN[0],    		// Set this bit to enable power glitch function
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_POWER_GLITCH_DSENSE[] = {
+    &POWER_GLITCH_DSENSE[0],    		// Sample delay configuration of power glitch
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WDT_DELAY_SEL[] = {
+    &WDT_DELAY_SEL[0],    		// Select RTC WDT time out threshold
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_BOOT_CRYPT_CNT[] = {
+    &SPI_BOOT_CRYPT_CNT[0],    		// SPI boot encrypt decrypt enable. odd number 1 enable. even number 1 disable
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0[] = {
+    &SECURE_BOOT_KEY_REVOKE0[0],    		// Enable revoke first secure boot key
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1[] = {
+    &SECURE_BOOT_KEY_REVOKE1[0],    		// Enable revoke second secure boot key
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2[] = {
+    &SECURE_BOOT_KEY_REVOKE2[0],    		// Enable revoke third secure boot key
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_0[] = {
+    &KEY_PURPOSE_0[0],    		// Key0 purpose
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_1[] = {
+    &KEY_PURPOSE_1[0],    		// Key1 purpose
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_2[] = {
+    &KEY_PURPOSE_2[0],    		// Key2 purpose
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_3[] = {
+    &KEY_PURPOSE_3[0],    		// Key3 purpose
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_4[] = {
+    &KEY_PURPOSE_4[0],    		// Key4 purpose
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_5[] = {
+    &KEY_PURPOSE_5[0],    		// Key5 purpose
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_EN[] = {
+    &SECURE_BOOT_EN[0],    		// Secure boot enable
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE[] = {
+    &SECURE_BOOT_AGGRESSIVE_REVOKE[0],    		// Enable aggressive secure boot revoke
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_FLASH_TPUW[] = {
+    &FLASH_TPUW[0],    		// Flash wait time after power up. (unit is ms). When value is 15. the time is 30 ms
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MODE[] = {
+    &DIS_DOWNLOAD_MODE[0],    		// Disble download mode include boot_mode[3:0] is 0 1 2 3 6 7
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_LEGACY_SPI_BOOT[] = {
+    &DIS_LEGACY_SPI_BOOT[0],    		// Disable_Legcy_SPI_boot mode include boot_mode[3:0] is 4
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CHANNEL[] = {
+    &UART_PRINT_CHANNEL[0],    		// 0: UART0. 1: UART1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_FLASH_ECC_MODE[] = {
+    &FLASH_ECC_MODE[0],    		// Set this bit to set flsah ecc mode. 0:flash ecc 16to18 byte mode. 1:flash ecc 16to17 byte mode
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_DOWNLOAD_MODE[] = {
+    &DIS_USB_DOWNLOAD_MODE[0],    		// Disable download through USB
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD[] = {
+    &ENABLE_SECURITY_DOWNLOAD[0],    		// Enable security download mode
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CONTROL[] = {
+    &UART_PRINT_CONTROL[0],    		// b00:force print. b01:control by GPIO8 - low level print. b10:control by GPIO8 - high level print. b11:force disable print.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_PIN_POWER_SELECTION[] = {
+    &PIN_POWER_SELECTION[0],    		// GPIO33-GPIO37 power supply selection in ROM code. 0:VDD3P3_CPU. 1:VDD_SPI.
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_FLASH_TYPE[] = {
+    &FLASH_TYPE[0],    		// Connected Flash interface type. 0: 4 data line. 1: 8 data line
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_FLASH_PAGE_SIZE[] = {
+    &FLASH_PAGE_SIZE[0],    		// Flash page size
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_FLASH_ECC_EN[] = {
+    &FLASH_ECC_EN[0],    		// Enable ECC for flash boot
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_FORCE_SEND_RESUME[] = {
+    &FORCE_SEND_RESUME[0],    		// Force ROM code to send a resume command during SPI boot
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SECURE_VERSION[] = {
+    &SECURE_VERSION[0],    		// Secure version for anti-rollback
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[] = {
+    &MAC_FACTORY[0],    		// Factory MAC addr [0]
+    &MAC_FACTORY[1],    		// Factory MAC addr [1]
+    &MAC_FACTORY[2],    		// Factory MAC addr [2]
+    &MAC_FACTORY[3],    		// Factory MAC addr [3]
+    &MAC_FACTORY[4],    		// Factory MAC addr [4]
+    &MAC_FACTORY[5],    		// Factory MAC addr [5]
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CLK[] = {
+    &SPI_PAD_CONFIG_CLK[0],    		// SPI_PAD_configure CLK
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_Q_D1[] = {
+    &SPI_PAD_CONFIG_Q_D1[0],    		// SPI_PAD_configure Q(D1)
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D_D0[] = {
+    &SPI_PAD_CONFIG_D_D0[0],    		// SPI_PAD_configure D(D0)
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CS[] = {
+    &SPI_PAD_CONFIG_CS[0],    		// SPI_PAD_configure CS
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_HD_D3[] = {
+    &SPI_PAD_CONFIG_HD_D3[0],    		// SPI_PAD_configure HD(D3)
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_WP_D2[] = {
+    &SPI_PAD_CONFIG_WP_D2[0],    		// SPI_PAD_configure WP(D2)
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_DQS[] = {
+    &SPI_PAD_CONFIG_DQS[0],    		// SPI_PAD_configure DQS
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D4[] = {
+    &SPI_PAD_CONFIG_D4[0],    		// SPI_PAD_configure D4
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D5[] = {
+    &SPI_PAD_CONFIG_D5[0],    		// SPI_PAD_configure D5
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D6[] = {
+    &SPI_PAD_CONFIG_D6[0],    		// SPI_PAD_configure D6
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D7[] = {
+    &SPI_PAD_CONFIG_D7[0],    		// SPI_PAD_configure D7
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[] = {
+    &WAFER_VERSION[0],    		// WAFER version
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[] = {
+    &PKG_VERSION[0],    		// Package version 0:ESP32C3
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[] = {
+    &BLOCK1_VERSION[0],    		// BLOCK1 efuse version
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_OPTIONAL_UNIQUE_ID[] = {
+    &OPTIONAL_UNIQUE_ID[0],    		// Optional unique 128-bit ID
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[] = {
+    &BLOCK2_VERSION[0],    		// Version of BLOCK2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_TEMP_CALIB[] = {
+    &TEMP_CALIB[0],    		// Temperature calibration data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_OCODE[] = {
+    &OCODE[0],    		// ADC OCode
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN0[] = {
+    &ADC1_INIT_CODE_ATTEN0[0],    		// ADC1 init code at atten0
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN1[] = {
+    &ADC1_INIT_CODE_ATTEN1[0],    		// ADC1 init code at atten1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN2[] = {
+    &ADC1_INIT_CODE_ATTEN2[0],    		// ADC1 init code at atten2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN3[] = {
+    &ADC1_INIT_CODE_ATTEN3[0],    		// ADC1 init code at atten3
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN0[] = {
+    &ADC1_CAL_VOL_ATTEN0[0],    		// ADC1 calibration voltage at atten0
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[] = {
+    &ADC1_CAL_VOL_ATTEN1[0],    		// ADC1 calibration voltage at atten1
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[] = {
+    &ADC1_CAL_VOL_ATTEN2[0],    		// ADC1 calibration voltage at atten2
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[] = {
+    &ADC1_CAL_VOL_ATTEN3[0],    		// ADC1 calibration voltage at atten3
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[] = {
+    &USER_DATA[0],    		// User data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY0[] = {
+    &KEY0[0],    		// Key0 or user data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY1[] = {
+    &KEY1[0],    		// Key1 or user data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY2[] = {
+    &KEY2[0],    		// Key2 or user data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY3[] = {
+    &KEY3[0],    		// Key3 or user data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY4[] = {
+    &KEY4[0],    		// Key4 or user data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_KEY5[] = {
+    &KEY5[0],    		// Key5 or user data
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART2[] = {
+    &SYS_DATA_PART2[0],    		// System configuration
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_K_RTC_LDO[] = {
+    &K_RTC_LDO[0],    		// BLOCK1 K_RTC_LDO
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_K_DIG_LDO[] = {
+    &K_DIG_LDO[0],    		// BLOCK1 K_DIG_LDO
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_V_RTC_DBIAS20[] = {
+    &V_RTC_DBIAS20[0],    		// BLOCK1 voltage of rtc dbias20
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_V_DIG_DBIAS20[] = {
+    &V_DIG_DBIAS20[0],    		// BLOCK1 voltage of digital dbias20
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_DIG_DBIAS_HVT[] = {
+    &DIG_DBIAS_HVT[0],    		// BLOCK1 digital dbias when hvt
+    NULL
+};
+
+const esp_efuse_desc_t* ESP_EFUSE_THRES_HVT[] = {
+    &THRES_HVT[0],    		// BLOCK1 pvt threshold when hvt
+    NULL
+};

+ 165 - 0
components/efuse/esp32h2/esp_efuse_table.csv

@@ -0,0 +1,165 @@
+# field_name,       |    efuse_block, | bit_start, | bit_count, |comment #
+#                   |    (EFUSE_BLK0  | (0..255)   | (1..-)     |        #
+#                   |     EFUSE_BLK1  |            |MAX_BLK_LEN*|        #
+#                   |        ...      |            |            |        #
+#                   |     EFUSE_BLK10)|            |            |        #
+##########################################################################
+# *) The value MAX_BLK_LEN depends on CONFIG_EFUSE_MAX_BLK_LEN, will be replaced with "None" - 256. "3/4" - 192. "REPEAT" - 128.
+# !!!!!!!!!!! #
+# After editing this file, run the command manually "make efuse_common_table" or "idf.py efuse_common_table"
+# this will generate new source files, next rebuild all the sources.
+# !!!!!!!!!!! #
+
+# ESP32H2-TODO: IDF-3390
+# EFUSE_RD_REPEAT_DATA BLOCK #
+##############################
+    # EFUSE_RD_WR_DIS_REG #
+        WR_DIS,                           EFUSE_BLK0,   0,    32,     Write protection
+            WR_DIS.RD_DIS,                EFUSE_BLK0,   0,    1,      Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2
+            WR_DIS.GROUP_1,               EFUSE_BLK0,   2,    1,      Write protection for DIS_ICACHE DIS_DOWNLOAD_ICACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT
+            WR_DIS.GROUP_2,               EFUSE_BLK0,   3,    1,      Write protection for WDT_DELAY_SEL
+            WR_DIS.SPI_BOOT_CRYPT_CNT,    EFUSE_BLK0,   4,    1,      Write protection for SPI_BOOT_CRYPT_CNT
+            WR_DIS.SECURE_BOOT_KEY_REVOKE0,EFUSE_BLK0,  5,    1,      Write protection for SECURE_BOOT_KEY_REVOKE0
+            WR_DIS.SECURE_BOOT_KEY_REVOKE1,EFUSE_BLK0,  6,    1,      Write protection for SECURE_BOOT_KEY_REVOKE1
+            WR_DIS.SECURE_BOOT_KEY_REVOKE2,EFUSE_BLK0,  7,    1,      Write protection for SECURE_BOOT_KEY_REVOKE2
+            WR_DIS.KEY0_PURPOSE,          EFUSE_BLK0,   8,    1,      Write protection for key_purpose. KEY0
+            WR_DIS.KEY1_PURPOSE,          EFUSE_BLK0,   9,    1,      Write protection for key_purpose. KEY1
+            WR_DIS.KEY2_PURPOSE,          EFUSE_BLK0,  10,    1,      Write protection for key_purpose. KEY2
+            WR_DIS.KEY3_PURPOSE,          EFUSE_BLK0,  11,    1,      Write protection for key_purpose. KEY3
+            WR_DIS.KEY4_PURPOSE,          EFUSE_BLK0,  12,    1,      Write protection for key_purpose. KEY4
+            WR_DIS.KEY5_PURPOSE,          EFUSE_BLK0,  13,    1,      Write protection for key_purpose. KEY5
+            WR_DIS.SECURE_BOOT_EN,        EFUSE_BLK0,  15,    1,      Write protection for SECURE_BOOT_EN
+            WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE,EFUSE_BLK0, 16, 1,   Write protection for SECURE_BOOT_AGGRESSIVE_REVOKE
+            WR_DIS.GROUP_3,               EFUSE_BLK0,  18,    1,      Write protection for FLASH_TPUW DIS_DOWNLOAD_MODE DIS_LEGACY_SPI_BOOT UART_PRINT_CHANNEL DIS_TINY_BASIC DIS_USB_DOWNLOAD_MODE ENABLE_SECURITY_DOWNLOAD UART_PRINT_CONTROL PIN_POWER_SELECTION FLASH_TYPE FORCE_SEND_RESUME SECURE_VERSION
+            WR_DIS.BLK1,                  EFUSE_BLK0,  20,    1,      Write protection for EFUSE_BLK1.  MAC_SPI_8M_SYS
+            WR_DIS.SYS_DATA_PART1,        EFUSE_BLK0,  21,    1,      Write protection for EFUSE_BLK2.  SYS_DATA_PART1
+            WR_DIS.USER_DATA,             EFUSE_BLK0,  22,    1,      Write protection for EFUSE_BLK3.  USER_DATA
+            WR_DIS.KEY0,                  EFUSE_BLK0,  23,    1,      Write protection for EFUSE_BLK4.  KEY0
+            WR_DIS.KEY1,                  EFUSE_BLK0,  24,    1,      Write protection for EFUSE_BLK5.  KEY1
+            WR_DIS.KEY2,                  EFUSE_BLK0,  25,    1,      Write protection for EFUSE_BLK6.  KEY2
+            WR_DIS.KEY3,                  EFUSE_BLK0,  26,    1,      Write protection for EFUSE_BLK7.  KEY3
+            WR_DIS.KEY4,                  EFUSE_BLK0,  27,    1,      Write protection for EFUSE_BLK8.  KEY4
+            WR_DIS.KEY5,                  EFUSE_BLK0,  28,    1,      Write protection for EFUSE_BLK9.  KEY5
+            WR_DIS.SYS_DATA_PART2,        EFUSE_BLK0,  29,    1,      Write protection for EFUSE_BLK10. SYS_DATA_PART2
+
+    # EFUSE_RD_REPEAT_DATA0_REG #
+        RD_DIS,                           EFUSE_BLK0,   32,    7,     Read protection
+            RD_DIS.KEY0,                  EFUSE_BLK0,   32,    1,     Read protection for EFUSE_BLK4.  KEY0
+            RD_DIS.KEY1,                  EFUSE_BLK0,   33,    1,     Read protection for EFUSE_BLK5.  KEY1
+            RD_DIS.KEY2,                  EFUSE_BLK0,   34,    1,     Read protection for EFUSE_BLK6.  KEY2
+            RD_DIS.KEY3,                  EFUSE_BLK0,   35,    1,     Read protection for EFUSE_BLK7.  KEY3
+            RD_DIS.KEY4,                  EFUSE_BLK0,   36,    1,     Read protection for EFUSE_BLK8.  KEY4
+            RD_DIS.KEY5,                  EFUSE_BLK0,   37,    1,     Read protection for EFUSE_BLK9.  KEY5
+            RD_DIS.SYS_DATA_PART2,        EFUSE_BLK0,   38,    1,     Read protection for EFUSE_BLK10. SYS_DATA_PART2
+        DIS_RTC_RAM_BOOT,                 EFUSE_BLK0,   39,    1,     Disable boot from RTC RAM
+        DIS_ICACHE,                       EFUSE_BLK0,   40,    1,     Disable Icache
+        DIS_USB_JTAG,                     EFUSE_BLK0,   41,    1,     Disable USB JTAG
+        DIS_DOWNLOAD_ICACHE,              EFUSE_BLK0,   42,    1,     Disable Icache in download mode
+        DIS_USB_DEVICE,                   EFUSE_BLK0,   43,    1,     Disable USB_DEVICE
+        DIS_FORCE_DOWNLOAD,               EFUSE_BLK0,   44,    1,     Disable force chip go to download mode function
+        DIS_USB,                          EFUSE_BLK0,   45,    1,     Disable USB function
+        DIS_CAN,                          EFUSE_BLK0,   46,    1,     Disable CAN function
+        JTAG_SEL_ENABLE,                  EFUSE_BLK0,   47,    1,     Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0.
+        SOFT_DIS_JTAG,                    EFUSE_BLK0,   48,    2,     Set these bits to disable JTAG in the soft way (odd number 1 means disable). JTAG can be enabled in HMAC module.
+        DIS_PAD_JTAG,                     EFUSE_BLK0,   51,    1,     Disable JTAG in the hard way. JTAG is disabled permanently.
+        DIS_DOWNLOAD_MANUAL_ENCRYPT,      EFUSE_BLK0,   52,    1,     Disable flash encryption when in download boot modes.
+        USB_DREFH,                        EFUSE_BLK0,   53,    2,     Controls single-end input threshold vrefh 1.76 V to 2 V with step of 80 mV stored in eFuse.
+        USB_DREFL,                        EFUSE_BLK0,   55,    2,     Controls single-end input threshold vrefl 0.8 V to 1.04 V with step of 80 mV stored in eFuse.
+        USB_EXCHG_PINS,                   EFUSE_BLK0,   57,    1,     Exchange D+ D- pins
+        VDD_SPI_AS_GPIO,                  EFUSE_BLK0,   58,    1,     Set this bit to vdd spi pin function as gpio
+        BTLC_GPIO_ENABLE,                 EFUSE_BLK0,   59,    2,     Enable btlc gpio
+        POWERGLITCH_EN,                   EFUSE_BLK0,   61,    1,     Set this bit to enable power glitch function
+        POWER_GLITCH_DSENSE,              EFUSE_BLK0,   62,    2,     Sample delay configuration of power glitch
+
+    # EFUSE_RD_REPEAT_DATA1_REG #
+        WDT_DELAY_SEL,                    EFUSE_BLK0,   80,    2,     Select RTC WDT time out threshold
+        SPI_BOOT_CRYPT_CNT,               EFUSE_BLK0,   82,    3,     SPI boot encrypt decrypt enable. odd number 1 enable. even number 1 disable
+        SECURE_BOOT_KEY_REVOKE0,          EFUSE_BLK0,   85,    1,     Enable revoke first secure boot key
+        SECURE_BOOT_KEY_REVOKE1,          EFUSE_BLK0,   86,    1,     Enable revoke second secure boot key
+        SECURE_BOOT_KEY_REVOKE2,          EFUSE_BLK0,   87,    1,     Enable revoke third secure boot key
+        KEY_PURPOSE_0,                    EFUSE_BLK0,   88,    4,     Key0 purpose
+        KEY_PURPOSE_1,                    EFUSE_BLK0,   92,    4,     Key1 purpose
+
+    # EFUSE_RD_REPEAT_DATA2_REG #
+        KEY_PURPOSE_2,                    EFUSE_BLK0,   96,    4,     Key2 purpose
+        KEY_PURPOSE_3,                    EFUSE_BLK0,  100,    4,     Key3 purpose
+        KEY_PURPOSE_4,                    EFUSE_BLK0,  104,    4,     Key4 purpose
+        KEY_PURPOSE_5,                    EFUSE_BLK0,  108,    4,     Key5 purpose
+        SECURE_BOOT_EN,                   EFUSE_BLK0,  116,    1,     Secure boot enable
+        SECURE_BOOT_AGGRESSIVE_REVOKE,    EFUSE_BLK0,  117,    1,     Enable aggressive secure boot revoke
+        FLASH_TPUW,                       EFUSE_BLK0,  124,    4,     Flash wait time after power up. (unit is ms). When value is 15. the time is 30 ms
+
+    # EFUSE_RD_REPEAT_DATA3_REG #
+        DIS_DOWNLOAD_MODE,                EFUSE_BLK0,  128,    1,     Disble download mode include boot_mode[3:0] is 0 1 2 3 6 7
+        DIS_LEGACY_SPI_BOOT,              EFUSE_BLK0,  129,    1,     Disable_Legcy_SPI_boot mode include boot_mode[3:0] is 4
+        UART_PRINT_CHANNEL,               EFUSE_BLK0,  130,    1,     0: UART0. 1: UART1
+        FLASH_ECC_MODE,                   EFUSE_BLK0,  131,    1,     Set this bit to set flsah ecc mode. 0:flash ecc 16to18 byte mode. 1:flash ecc 16to17 byte mode
+        DIS_USB_DOWNLOAD_MODE,            EFUSE_BLK0,  132,    1,     Disable download through USB
+        ENABLE_SECURITY_DOWNLOAD,         EFUSE_BLK0,  133,    1,     Enable security download mode
+        UART_PRINT_CONTROL,               EFUSE_BLK0,  134,    2,     b00:force print. b01:control by GPIO8 - low level print. b10:control by GPIO8 - high level print. b11:force disable print.
+        PIN_POWER_SELECTION,              EFUSE_BLK0,  136,    1,     GPIO33-GPIO37 power supply selection in ROM code. 0:VDD3P3_CPU. 1:VDD_SPI.
+        FLASH_TYPE,                       EFUSE_BLK0,  137,    1,     Connected Flash interface type. 0: 4 data line. 1: 8 data line
+        FLASH_PAGE_SIZE,                  EFUSE_BLK0,  138,    2,     Flash page size
+        FLASH_ECC_EN,                     EFUSE_BLK0,  140,    1,     Enable ECC for flash boot
+        FORCE_SEND_RESUME,                EFUSE_BLK0,  141,    1,     Force ROM code to send a resume command during SPI boot
+        SECURE_VERSION,                   EFUSE_BLK0,  142,   16,     Secure version for anti-rollback
+
+    # EFUSE_RD_REPEAT_DATA4_REG #
+
+
+# MAC_SPI_SYS BLOCK#
+#######################
+    MAC_FACTORY,                          EFUSE_BLK1,   40,    8,     Factory MAC addr [0]
+    ,                                     EFUSE_BLK1,   32,    8,     Factory MAC addr [1]
+    ,                                     EFUSE_BLK1,   24,    8,     Factory MAC addr [2]
+    ,                                     EFUSE_BLK1,   16,    8,     Factory MAC addr [3]
+    ,                                     EFUSE_BLK1,    8,    8,     Factory MAC addr [4]
+    ,                                     EFUSE_BLK1,    0,    8,     Factory MAC addr [5]
+    SPI_PAD_CONFIG_CLK,                   EFUSE_BLK1,   48,    6,     SPI_PAD_configure CLK
+    SPI_PAD_CONFIG_Q_D1,                  EFUSE_BLK1,   54,    6,     SPI_PAD_configure Q(D1)
+    SPI_PAD_CONFIG_D_D0,                  EFUSE_BLK1,   60,    6,     SPI_PAD_configure D(D0)
+    SPI_PAD_CONFIG_CS,                    EFUSE_BLK1,   66,    6,     SPI_PAD_configure CS
+    SPI_PAD_CONFIG_HD_D3,                 EFUSE_BLK1,   72,    6,     SPI_PAD_configure HD(D3)
+    SPI_PAD_CONFIG_WP_D2,                 EFUSE_BLK1,   78,    6,     SPI_PAD_configure WP(D2)
+    SPI_PAD_CONFIG_DQS,                   EFUSE_BLK1,   84,    6,     SPI_PAD_configure DQS
+    SPI_PAD_CONFIG_D4,                    EFUSE_BLK1,   90,    6,     SPI_PAD_configure D4
+    SPI_PAD_CONFIG_D5,                    EFUSE_BLK1,   96,    6,     SPI_PAD_configure D5
+    SPI_PAD_CONFIG_D6,                    EFUSE_BLK1,  102,    6,     SPI_PAD_configure D6
+    SPI_PAD_CONFIG_D7,                    EFUSE_BLK1,  108,    6,     SPI_PAD_configure D7
+    WAFER_VERSION,                        EFUSE_BLK1,  114,    3,     WAFER version
+    PKG_VERSION,                          EFUSE_BLK1,  117,    3,     Package version 0:ESP32H2
+    BLOCK1_VERSION,                       EFUSE_BLK1,  120,    3,     BLOCK1 efuse version
+
+# SYS_DATA_PART1 BLOCK# - System configuration
+#######################
+    OPTIONAL_UNIQUE_ID,                   EFUSE_BLK2,    0,  128,     Optional unique 128-bit ID
+    BLOCK2_VERSION,                       EFUSE_BLK2,  128,    3,     Version of BLOCK2
+    TEMP_CALIB,                           EFUSE_BLK2,  131,    9,     Temperature calibration data
+    OCODE,                                EFUSE_BLK2,  140,    8,     ADC OCode
+    ADC1_INIT_CODE_ATTEN0,                EFUSE_BLK2,  148,   10,     ADC1 init code at atten0
+    ADC1_INIT_CODE_ATTEN1,                EFUSE_BLK2,  158,   10,     ADC1 init code at atten1
+    ADC1_INIT_CODE_ATTEN2,                EFUSE_BLK2,  168,   10,     ADC1 init code at atten2
+    ADC1_INIT_CODE_ATTEN3,                EFUSE_BLK2,  178,   10,     ADC1 init code at atten3
+    ADC1_CAL_VOL_ATTEN0,                  EFUSE_BLK2,  188,   10,     ADC1 calibration voltage at atten0
+    ADC1_CAL_VOL_ATTEN1,                  EFUSE_BLK2,  198,   10,     ADC1 calibration voltage at atten1
+    ADC1_CAL_VOL_ATTEN2,                  EFUSE_BLK2,  208,   10,     ADC1 calibration voltage at atten2
+    ADC1_CAL_VOL_ATTEN3,                  EFUSE_BLK2,  218,   10,     ADC1 calibration voltage at atten3
+
+################
+USER_DATA,                                EFUSE_BLK3,    0,  256,     User data
+KEY0,                                     EFUSE_BLK4,    0,  256,     Key0 or user data
+KEY1,                                     EFUSE_BLK5,    0,  256,     Key1 or user data
+KEY2,                                     EFUSE_BLK6,    0,  256,     Key2 or user data
+KEY3,                                     EFUSE_BLK7,    0,  256,     Key3 or user data
+KEY4,                                     EFUSE_BLK8,    0,  256,     Key4 or user data
+KEY5,                                     EFUSE_BLK9,    0,  256,     Key5 or user data
+SYS_DATA_PART2,                           EFUSE_BLK10,   0,  256,     System configuration
+
+# AUTO CONFIG DIG&RTC DBIAS#
+################
+K_RTC_LDO,                              EFUSE_BLK1,    135,    7,      BLOCK1 K_RTC_LDO
+K_DIG_LDO,                              EFUSE_BLK1,    142,    7,      BLOCK1 K_DIG_LDO
+V_RTC_DBIAS20,                          EFUSE_BLK1,    149,    8,      BLOCK1 voltage of rtc dbias20
+V_DIG_DBIAS20,                          EFUSE_BLK1,    157,    8,      BLOCK1 voltage of digital dbias20
+DIG_DBIAS_HVT,                          EFUSE_BLK1,    165,    5,      BLOCK1 digital dbias when hvt
+THRES_HVT,                              EFUSE_BLK1,    170,    10,     BLOCK1 pvt threshold when hvt

+ 141 - 0
components/efuse/esp32h2/esp_efuse_utility.c

@@ -0,0 +1,141 @@
+/*
+ * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <sys/param.h>
+#include "sdkconfig.h"
+#include "esp_log.h"
+#include "assert.h"
+#include "esp_efuse_utility.h"
+#include "soc/efuse_periph.h"
+#include "esp32h2/clk.h"
+#include "esp32h2/rom/efuse.h"
+
+static const char *TAG = "efuse";
+
+#ifdef CONFIG_EFUSE_VIRTUAL
+extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
+#endif // CONFIG_EFUSE_VIRTUAL
+
+/*Range addresses to read blocks*/
+const esp_efuse_range_addr_t range_read_addr_blocks[] = {
+    {EFUSE_RD_WR_DIS_REG,       EFUSE_RD_REPEAT_DATA4_REG},      // range address of EFUSE_BLK0  REPEAT
+    {EFUSE_RD_MAC_SPI_SYS_0_REG, EFUSE_RD_MAC_SPI_SYS_5_REG},      // range address of EFUSE_BLK1  MAC_SPI_8M
+    {EFUSE_RD_SYS_PART1_DATA0_REG,    EFUSE_RD_SYS_PART1_DATA7_REG},         // range address of EFUSE_BLK2  SYS_DATA
+    {EFUSE_RD_USR_DATA0_REG,    EFUSE_RD_USR_DATA7_REG},         // range address of EFUSE_BLK3  USR_DATA
+    {EFUSE_RD_KEY0_DATA0_REG,   EFUSE_RD_KEY0_DATA7_REG},        // range address of EFUSE_BLK4  KEY0
+    {EFUSE_RD_KEY1_DATA0_REG,   EFUSE_RD_KEY1_DATA7_REG},        // range address of EFUSE_BLK5  KEY1
+    {EFUSE_RD_KEY2_DATA0_REG,   EFUSE_RD_KEY2_DATA7_REG},        // range address of EFUSE_BLK6  KEY2
+    {EFUSE_RD_KEY3_DATA0_REG,   EFUSE_RD_KEY3_DATA7_REG},        // range address of EFUSE_BLK7  KEY3
+    {EFUSE_RD_KEY4_DATA0_REG,   EFUSE_RD_KEY4_DATA7_REG},        // range address of EFUSE_BLK8  KEY4
+    {EFUSE_RD_KEY5_DATA0_REG,   EFUSE_RD_KEY5_DATA7_REG},        // range address of EFUSE_BLK9  KEY5
+    {EFUSE_RD_SYS_PART2_DATA0_REG,   EFUSE_RD_SYS_PART2_DATA7_REG}         // range address of EFUSE_BLK10 KEY6
+};
+
+static uint32_t write_mass_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK] = { 0 };
+
+/*Range addresses to write blocks (it is not real regs, it is buffer) */
+const esp_efuse_range_addr_t range_write_addr_blocks[] = {
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK0][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK0][5]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK1][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK1][5]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK2][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK2][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK3][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK3][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK4][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK4][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK5][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK5][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK6][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK6][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK7][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK7][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK8][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK8][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK9][0],  (uint32_t) &write_mass_blocks[EFUSE_BLK9][7]},
+    {(uint32_t) &write_mass_blocks[EFUSE_BLK10][0], (uint32_t) &write_mass_blocks[EFUSE_BLK10][7]},
+};
+
+#ifndef CONFIG_EFUSE_VIRTUAL
+// Update Efuse timing configuration
+static esp_err_t esp_efuse_set_timing(void)
+{
+    // efuse clock is fixed in ESP32-C3, so the ets_efuse_set_timing() function
+    // takes an argument for compatibility with older ROM functions but it's ignored.
+    int res = ets_efuse_set_timing(0);
+    assert(res == 0);
+    (void)res;
+
+    REG_SET_FIELD(EFUSE_WR_TIM_CONF2_REG, EFUSE_PWR_OFF_NUM, 0x60);
+
+    return ESP_OK;
+}
+#endif // ifndef CONFIG_EFUSE_VIRTUAL
+
+// Efuse read operation: copies data from physical efuses to efuse read registers.
+void esp_efuse_utility_clear_program_registers(void)
+{
+    ets_efuse_read();
+    ets_efuse_clear_program_registers();
+}
+
+// Burn values written to the efuse write registers
+void esp_efuse_utility_burn_chip(void)
+{
+#ifdef CONFIG_EFUSE_VIRTUAL
+    ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
+    for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
+        int subblock = 0;
+        for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
+            virt_blocks[num_block][subblock++] |= REG_READ(addr_wr_block);
+        }
+    }
+#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
+    esp_efuse_utility_write_efuses_to_flash();
+#endif
+#else
+    if (esp_efuse_set_timing() != ESP_OK) {
+        ESP_LOGE(TAG, "Efuse fields are not burnt");
+    } else {
+        // Permanently update values written to the efuse write registers
+        // It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks.
+        for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
+            for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
+                if (REG_READ(addr_wr_block) != 0) {
+                    if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
+                        uint8_t block_rs[12];
+                        ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
+                        memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
+                    }
+                    int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
+                    memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len);
+                    ets_efuse_program(num_block);
+                    break;
+                }
+            }
+        }
+    }
+#endif // CONFIG_EFUSE_VIRTUAL
+    esp_efuse_utility_reset();
+}
+
+// After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values.
+// This function reads EFUSE_BLKx_WDATAx_REG registers, and checks possible to write these data with RS coding scheme.
+// The RS coding scheme does not require data changes for the encoded data. esp32s2 has special registers for this.
+// They will be filled during the burn operation.
+esp_err_t esp_efuse_utility_apply_new_coding_scheme()
+{
+    // start with EFUSE_BLK1. EFUSE_BLK0 - always uses EFUSE_CODING_SCHEME_NONE.
+    for (int num_block = EFUSE_BLK1; num_block < EFUSE_BLK_MAX; num_block++) {
+        if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
+            for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
+                if (REG_READ(addr_wr_block)) {
+                    int num_reg = 0;
+                    for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4, ++num_reg) {
+                        if (esp_efuse_utility_read_reg(num_block, num_reg)) {
+                            ESP_LOGE(TAG, "Bits are not empty. Write operation is forbidden.");
+                            return ESP_ERR_CODING;
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+    }
+    return ESP_OK;
+}

+ 79 - 0
components/efuse/esp32h2/include/esp_efuse.h

@@ -0,0 +1,79 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Type of eFuse blocks ESP32H2
+ */
+typedef enum {
+    EFUSE_BLK0                 = 0,   /**< Number of eFuse BLOCK0. REPEAT_DATA */
+
+    EFUSE_BLK1                 = 1,   /**< Number of eFuse BLOCK1. MAC_SPI_8M_SYS */
+
+    EFUSE_BLK2                 = 2,   /**< Number of eFuse BLOCK2. SYS_DATA_PART1 */
+    EFUSE_BLK_SYS_DATA_PART1   = 2,   /**< Number of eFuse BLOCK2. SYS_DATA_PART1 */
+
+    EFUSE_BLK3                 = 3,   /**< Number of eFuse BLOCK3. USER_DATA*/
+    EFUSE_BLK_USER_DATA        = 3,   /**< Number of eFuse BLOCK3. USER_DATA*/
+
+    EFUSE_BLK4                 = 4,   /**< Number of eFuse BLOCK4. KEY0 */
+    EFUSE_BLK_KEY0             = 4,   /**< Number of eFuse BLOCK4. KEY0 */
+
+    EFUSE_BLK5                 = 5,   /**< Number of eFuse BLOCK5. KEY1 */
+    EFUSE_BLK_KEY1             = 5,   /**< Number of eFuse BLOCK5. KEY1 */
+
+    EFUSE_BLK6                 = 6,   /**< Number of eFuse BLOCK6. KEY2 */
+    EFUSE_BLK_KEY2             = 6,   /**< Number of eFuse BLOCK6. KEY2 */
+
+    EFUSE_BLK7                 = 7,   /**< Number of eFuse BLOCK7. KEY3 */
+    EFUSE_BLK_KEY3             = 7,   /**< Number of eFuse BLOCK7. KEY3 */
+
+    EFUSE_BLK8                 = 8,   /**< Number of eFuse BLOCK8. KEY4 */
+    EFUSE_BLK_KEY4             = 8,   /**< Number of eFuse BLOCK8. KEY4 */
+
+    EFUSE_BLK9                 = 9,   /**< Number of eFuse BLOCK9. KEY5 */
+    EFUSE_BLK_KEY5             = 9,   /**< Number of eFuse BLOCK9. KEY5 */
+    EFUSE_BLK_KEY_MAX          = 10,
+
+    EFUSE_BLK10                = 10,  /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */
+    EFUSE_BLK_SYS_DATA_PART2   = 10,  /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */
+
+    EFUSE_BLK_MAX
+} esp_efuse_block_t;
+
+/**
+ * @brief Type of coding scheme
+ */
+typedef enum {
+    EFUSE_CODING_SCHEME_NONE    = 0,    /**< None */
+    EFUSE_CODING_SCHEME_RS      = 3,    /**< Reed-Solomon coding */
+} esp_efuse_coding_scheme_t;
+
+/**
+ * @brief Type of key purpose
+ */
+typedef enum {
+    ESP_EFUSE_KEY_PURPOSE_USER = 0,                         /**< User purposes (software-only use) */
+    ESP_EFUSE_KEY_PURPOSE_RESERVED = 1,                     /**< Reserved */
+    ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY = 4,              /**< XTS_AES_128_KEY (flash/PSRAM encryption) */
+    ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5,                /**< HMAC Downstream mode */
+    ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6,               /**< JTAG soft enable key (uses HMAC Downstream mode) */
+    ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE = 7,  /**< Digital Signature peripheral key (uses HMAC Downstream mode) */
+    ESP_EFUSE_KEY_PURPOSE_HMAC_UP = 8,                      /**< HMAC Upstream mode */
+    ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0 = 9,          /**< SECURE_BOOT_DIGEST0 (Secure Boot key digest) */
+    ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1 = 10,         /**< SECURE_BOOT_DIGEST1 (Secure Boot key digest) */
+    ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 = 11,         /**< SECURE_BOOT_DIGEST2 (Secure Boot key digest) */
+    ESP_EFUSE_KEY_PURPOSE_MAX,                              /**< MAX PURPOSE */
+} esp_efuse_purpose_t;
+
+#ifdef __cplusplus
+}
+#endif

+ 54 - 0
components/efuse/esp32h2/include/esp_efuse_rtc_calib.h

@@ -0,0 +1,54 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <esp_types.h>
+#include <esp_err.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Get the RTC calibration efuse version
+ *
+ * @return Version of the stored efuse
+ */
+int esp_efuse_rtc_calib_get_ver(void);
+
+/**
+ * @brief Get the init code in the efuse, for the corresponding attenuation.
+ *
+ * @param version Version of the stored efuse
+ * @param atten  Attenuation of the init code
+ * @return The init code stored in efuse
+ */
+uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten);
+
+/**
+ * @brief Get the calibration digits stored in the efuse, and the corresponding voltage.
+ *
+ * @param version Version of the stored efuse
+ * @param atten         Attenuation to use
+ * @param out_digi      Output buffer of the digits
+ * @param out_vol_mv    Output of the voltage, in mV
+ * @return
+ *      - ESP_ERR_INVALID_ARG: If efuse version or attenuation is invalid
+ *      - ESP_OK: if success
+ */
+esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* out_digi, uint32_t* out_vol_mv);
+
+/**
+ * @brief Get the temperature sensor calibration number delta_T stored in the efuse.
+ *
+ * @param version Version of the stored efuse
+ *
+ * @return The specification of temperature sensor calibration number in efuse.
+ */
+float esp_efuse_rtc_calib_get_cal_temp(int version);
+
+#ifdef __cplusplus
+}
+#endif

+ 144 - 0
components/efuse/esp32h2/include/esp_efuse_table.h

@@ -0,0 +1,144 @@
+/*
+ * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// md5_digest_table 9e42b2f9dd879191ca75ad0cf50841a1
+// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
+// If you want to change some fields, you need to change esp_efuse_table.csv file
+// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
+// To show efuse_table run the command 'show_efuse_table'.
+
+
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0_PURPOSE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1_PURPOSE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2_PURPOSE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3_PURPOSE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4_PURPOSE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5_PURPOSE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_EN[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_AGGRESSIVE_REVOKE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_USER_DATA[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[];
+extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_JTAG[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_DEVICE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_FORCE_DOWNLOAD[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_CAN[];
+extern const esp_efuse_desc_t* ESP_EFUSE_JTAG_SEL_ENABLE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SOFT_DIS_JTAG[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_PAD_JTAG[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT[];
+extern const esp_efuse_desc_t* ESP_EFUSE_USB_DREFH[];
+extern const esp_efuse_desc_t* ESP_EFUSE_USB_DREFL[];
+extern const esp_efuse_desc_t* ESP_EFUSE_USB_EXCHG_PINS[];
+extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_AS_GPIO[];
+extern const esp_efuse_desc_t* ESP_EFUSE_BTLC_GPIO_ENABLE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_POWERGLITCH_EN[];
+extern const esp_efuse_desc_t* ESP_EFUSE_POWER_GLITCH_DSENSE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WDT_DELAY_SEL[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_BOOT_CRYPT_CNT[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_4[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_5[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_EN[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_TPUW[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MODE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_LEGACY_SPI_BOOT[];
+extern const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CHANNEL[];
+extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_ECC_MODE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_DOWNLOAD_MODE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD[];
+extern const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CONTROL[];
+extern const esp_efuse_desc_t* ESP_EFUSE_PIN_POWER_SELECTION[];
+extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_TYPE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_PAGE_SIZE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_ECC_EN[];
+extern const esp_efuse_desc_t* ESP_EFUSE_FORCE_SEND_RESUME[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_VERSION[];
+extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CLK[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_Q_D1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D_D0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CS[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_HD_D3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_WP_D2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_DQS[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D4[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D5[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D6[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D7[];
+extern const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[];
+extern const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[];
+extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[];
+extern const esp_efuse_desc_t* ESP_EFUSE_OPTIONAL_UNIQUE_ID[];
+extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[];
+extern const esp_efuse_desc_t* ESP_EFUSE_TEMP_CALIB[];
+extern const esp_efuse_desc_t* ESP_EFUSE_OCODE[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY1[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY3[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY4[];
+extern const esp_efuse_desc_t* ESP_EFUSE_KEY5[];
+extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART2[];
+extern const esp_efuse_desc_t* ESP_EFUSE_K_RTC_LDO[];
+extern const esp_efuse_desc_t* ESP_EFUSE_K_DIG_LDO[];
+extern const esp_efuse_desc_t* ESP_EFUSE_V_RTC_DBIAS20[];
+extern const esp_efuse_desc_t* ESP_EFUSE_V_DIG_DBIAS20[];
+extern const esp_efuse_desc_t* ESP_EFUSE_DIG_DBIAS_HVT[];
+extern const esp_efuse_desc_t* ESP_EFUSE_THRES_HVT[];
+
+#ifdef __cplusplus
+}
+#endif

+ 21 - 0
components/efuse/esp32h2/private_include/esp_efuse_utility.h

@@ -0,0 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define COUNT_EFUSE_REG_PER_BLOCK 8      /* The number of registers per block. */
+
+#define ESP_EFUSE_SECURE_VERSION_NUM_BLOCK EFUSE_BLK0
+
+#define ESP_EFUSE_FIELD_CORRESPONDS_CODING_SCHEME(scheme, max_num_bit)
+
+#ifdef __cplusplus
+}
+#endif

+ 4 - 0
components/efuse/esp32h2/sources.cmake

@@ -0,0 +1,4 @@
+set(EFUSE_SOC_SRCS  "esp_efuse_table.c"
+                    "esp_efuse_fields.c"
+                    "esp_efuse_rtc_calib.c"
+                    "esp_efuse_utility.c")

+ 2 - 0
components/efuse/include/esp_efuse.h

@@ -25,6 +25,8 @@ extern "C" {
 #include "esp32c3/rom/secure_boot.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rom/secure_boot.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/secure_boot.h"
 #endif
 
 #define ESP_ERR_EFUSE                              0x1600                     /*!< Base error code for efuse api. */

+ 1 - 1
components/esp-tls/Kconfig

@@ -26,7 +26,7 @@ menu "ESP-TLS"
 
     config ESP_TLS_USE_DS_PERIPHERAL
         bool "Use Digital Signature (DS) Peripheral with ESP-TLS"
-        depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2) && ESP_TLS_USING_MBEDTLS
+        depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2) && ESP_TLS_USING_MBEDTLS
         default y
         help
             Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral

+ 66 - 0
components/esp32h2/CMakeLists.txt

@@ -0,0 +1,66 @@
+idf_build_get_property(target IDF_TARGET)
+idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER)
+if(NOT "${target}" STREQUAL "esp32h2")
+    return()
+endif()
+
+if(BOOTLOADER_BUILD)
+    # For bootloader, all we need from esp32h2 is headers
+    idf_component_register(INCLUDE_DIRS include REQUIRES riscv)
+    target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32h2.peripherals.ld")
+else()
+    # Regular app build
+
+    set(srcs "dport_access.c"
+             "esp_hmac.c"
+             "esp_ds.c"
+             "esp_crypto_lock.c"
+             "memprot.c")
+    set(include_dirs "include")
+
+    set(requires driver efuse soc riscv) #unfortunately rom/uart uses SOC registers directly
+
+    # driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
+    # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
+    # esp_timer is added here because cpu_start.c uses esp_timer
+    set(priv_requires
+        app_trace app_update bootloader_support log mbedtls nvs_flash
+        pthread spi_flash vfs espcoredump esp_common esp_timer)
+
+    idf_component_register(SRCS "${srcs}"
+                        INCLUDE_DIRS "${include_dirs}"
+                        REQUIRES "${requires}"
+                        PRIV_REQUIRES "${priv_requires}"
+                        REQUIRED_IDF_TARGETS esp32h2)
+
+    target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/esp32h2_out.ld")
+
+    # Process the template file through the linker script generation mechanism, and use the output for linking the
+    # final binary
+    target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32h2.project.ld.in"
+            PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32h2.project.ld")
+    target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32h2.peripherals.ld")
+
+    target_link_libraries(${COMPONENT_LIB} PUBLIC gcc)
+    target_link_libraries(${COMPONENT_LIB} INTERFACE "-u call_user_start_cpu0")
+
+    idf_build_get_property(config_dir CONFIG_DIR)
+    # Preprocess esp32h2.ld linker script to include configuration, becomes esp32h2_out.ld
+    set(LD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ld)
+    add_custom_command(
+        OUTPUT esp32h2_out.ld
+        COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o esp32h2_out.ld -I ${config_dir} ${LD_DIR}/esp32h2.ld
+        MAIN_DEPENDENCY ${LD_DIR}/esp32h2.ld
+        DEPENDS ${sdkconfig_header}
+        COMMENT "Generating linker script..."
+        VERBATIM)
+
+    add_custom_target(esp32h2_linker_script DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/esp32h2_out.ld)
+    add_dependencies(${COMPONENT_LIB} esp32h2_linker_script)
+
+    # disable stack protection in files which are involved in initialization of that feature
+    set_source_files_properties(
+        cpu_start.c
+        PROPERTIES COMPILE_FLAGS
+        -fno-stack-protector)
+endif()

+ 205 - 0
components/esp32h2/Kconfig

@@ -0,0 +1,205 @@
+menu "ESP32H2-Specific"
+    visible if IDF_TARGET_ESP32H2
+
+    choice ESP32H2_DEFAULT_CPU_FREQ_MHZ
+        prompt "CPU frequency"
+        default ESP32H2_DEFAULT_CPU_FREQ_64 if IDF_ENV_FPGA
+        default ESP32H2_DEFAULT_CPU_FREQ_96 if !IDF_ENV_FPGA
+        help
+            CPU frequency to be set on application startup.
+
+        config ESP32H2_DEFAULT_CPU_FREQ_16
+            bool "16 MHz"
+        config ESP32H2_DEFAULT_CPU_FREQ_32
+            bool "32 MHz"
+        config ESP32H2_DEFAULT_CPU_FREQ_64
+            bool "64 MHz"
+        config ESP32H2_DEFAULT_CPU_FREQ_96
+            bool "96 MHz"
+            depends on !IDF_ENV_FPGA
+    endchoice
+
+    config ESP32H2_DEFAULT_CPU_FREQ_MHZ
+        int
+        default 16 if ESP32H2_DEFAULT_CPU_FREQ_16
+        default 32 if ESP32H2_DEFAULT_CPU_FREQ_32
+        default 64 if ESP32H2_DEFAULT_CPU_FREQ_64
+        default 96 if ESP32H2_DEFAULT_CPU_FREQ_96
+
+    choice ESP32H2_REV_MIN
+        prompt "Minimum Supported ESP32-H2 Revision"
+        default ESP32H2_REV_MIN_0
+        help
+            Minimum revision that ESP-IDF would support.
+
+            Only supporting higher chip revisions can reduce binary size.
+
+        config ESP32H2_REV_MIN_0
+            bool "Rev 0"
+    endchoice
+
+    config ESP32H2_REV_MIN
+        int
+        default 0 if ESP32H2_REV_MIN_0
+
+    config ESP32H2_DEBUG_OCDAWARE
+        bool "Make exception and panic handlers JTAG/OCD aware"
+        default y
+        select FREERTOS_DEBUG_OCDAWARE
+        help
+            The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and
+            instead of panicking, have the debugger stop on the offending instruction.
+
+    config ESP32H2_DEBUG_STUBS_ENABLE
+        bool "OpenOCD debug stubs"
+        default COMPILER_OPTIMIZATION_LEVEL_DEBUG
+        depends on !ESP32H2_TRAX
+        help
+            Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging,
+            e.g. GCOV data dump.
+
+    config ESP32H2_BROWNOUT_DET
+        bool "Hardware brownout detect & reset"
+        default y
+        help
+            The ESP32-C3 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 ESP32H2_BROWNOUT_DET_LVL_SEL
+        prompt "Brownout voltage level"
+        depends on ESP32H2_BROWNOUT_DET
+        default ESP32H2_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 ESP32H2_BROWNOUT_DET_LVL_SEL_7
+            bool "2.51V"
+        config ESP32H2_BROWNOUT_DET_LVL_SEL_6
+            bool "2.64V"
+        config ESP32H2_BROWNOUT_DET_LVL_SEL_5
+            bool "2.76V"
+        config ESP32H2_BROWNOUT_DET_LVL_SEL_4
+            bool "2.92V"
+        config ESP32H2_BROWNOUT_DET_LVL_SEL_3
+            bool "3.10V"
+        config ESP32H2_BROWNOUT_DET_LVL_SEL_2
+            bool "3.27V"
+    endchoice
+
+    config ESP32H2_BROWNOUT_DET_LVL
+        int
+        default 2 if ESP32H2_BROWNOUT_DET_LVL_SEL_2
+        default 3 if ESP32H2_BROWNOUT_DET_LVL_SEL_3
+        default 4 if ESP32H2_BROWNOUT_DET_LVL_SEL_4
+        default 5 if ESP32H2_BROWNOUT_DET_LVL_SEL_5
+        default 6 if ESP32H2_BROWNOUT_DET_LVL_SEL_6
+        default 7 if ESP32H2_BROWNOUT_DET_LVL_SEL_7
+
+    choice ESP32H2_TIME_SYSCALL
+        prompt "Timers used for gettimeofday function"
+        default ESP32H2_TIME_SYSCALL_USE_RTC_SYSTIMER
+        help
+            This setting defines which hardware timers are used to
+            implement 'gettimeofday' and 'time' functions in C library.
+
+            - If both high-resolution (systimer) and RTC timers are used, timekeeping will
+              continue in deep sleep. Time will be reported at 1 microsecond
+              resolution. This is the default, and the recommended option.
+            - If only high-resolution timer (systimer) is used, gettimeofday will
+              provide time at microsecond resolution.
+              Time will not be preserved when going into deep sleep mode.
+            - If only RTC timer is used, timekeeping will continue in
+              deep sleep, but time will be measured at 6.(6) microsecond
+              resolution. Also the gettimeofday function itself may take
+              longer to run.
+            - If no timers are used, gettimeofday and time functions
+              return -1 and set errno to ENOSYS.
+            - When RTC is used for timekeeping, two RTC_STORE registers are
+              used to keep time in deep sleep mode.
+
+        config ESP32H2_TIME_SYSCALL_USE_RTC_SYSTIMER
+            bool "RTC and high-resolution timer"
+            select ESP_TIME_FUNCS_USE_RTC_TIMER
+            select ESP_TIME_FUNCS_USE_ESP_TIMER
+        config ESP32H2_TIME_SYSCALL_USE_RTC
+            bool "RTC"
+            select ESP_TIME_FUNCS_USE_RTC_TIMER
+        config ESP32H2_TIME_SYSCALL_USE_SYSTIMER
+            bool "High-resolution timer"
+            select ESP_TIME_FUNCS_USE_ESP_TIMER
+        config ESP32H2_TIME_SYSCALL_USE_NONE
+            bool "None"
+            select ESP_TIME_FUNCS_USE_NONE
+    endchoice
+
+    choice ESP32H2_RTC_CLK_SRC
+        prompt "RTC clock source"
+        default ESP32H2_RTC_CLK_SRC_INT_RC
+        help
+            Choose which clock is used as RTC clock source.
+
+        config ESP32H2_RTC_CLK_SRC_INT_RC
+            bool "Internal 150kHz RC oscillator"
+        config ESP32H2_RTC_CLK_SRC_EXT_CRYS
+            bool "External 32kHz crystal"
+            select ESP_SYSTEM_RTC_EXT_XTAL
+        config ESP32H2_RTC_CLK_SRC_EXT_OSC
+            bool "External 32kHz oscillator at 32K_XP pin"
+        config ESP32H2_RTC_CLK_SRC_INT_8MD256
+            bool "Internal 8MHz oscillator, divided by 256 (~32kHz)"
+    endchoice
+
+    config ESP32H2_RTC_CLK_CAL_CYCLES
+        int "Number of cycles for RTC_SLOW_CLK calibration"
+        default 3000 if ESP32H2_RTC_CLK_SRC_EXT_CRYS || ESP32H2_RTC_CLK_SRC_EXT_OSC || ESP32H2_RTC_CLK_SRC_INT_8MD256
+        default 576 if ESP32H2_RTC_CLK_SRC_INT_RC
+        range 0 125000
+        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.
+
+    config ESP32H2_NO_BLOBS
+        bool "No Binary Blobs"
+        depends on !BT_ENABLED
+        default n
+        help
+            If enabled, this disables the linking of binary libraries in the application build. Note
+            that after enabling this Wi-Fi/Bluetooth will not work.
+
+    config ESP32H2_LIGHTSLEEP_GPIO_RESET_WORKAROUND
+        bool "light sleep GPIO reset workaround"
+        default y
+        select PM_SLP_DISABLE_GPIO if FREERTOS_USE_TICKLESS_IDLE
+        help
+            ESP32H2 will reset at wake-up if GPIO is received a small electrostatic pulse during
+            light sleep, with specific condition
+
+            - GPIO needs to be configured as input-mode only
+            - The pin receives a small electrostatic pulse, and reset occurs when the pulse
+              voltage is higher than 6 V
+
+            For GPIO set to input mode only, it is not a good practice to leave it open/floating,
+            The hardware design needs to controlled it with determined supply or ground voltage
+            is necessary.
+
+            This option provides a software workaround for this issue. Configure to isolate all
+            GPIO pins in sleep state.
+
+endmenu  # ESP32H2-Specific

+ 1 - 0
components/esp32h2/Makefile.projbuild

@@ -0,0 +1 @@
+# ESP32-H2 is not supported in the GNU Make build system.

+ 4 - 0
components/esp32h2/component.mk

@@ -0,0 +1,4 @@
+#
+# Component Makefile
+#
+COMPONENT_CONFIG_ONLY := 1

+ 25 - 0
components/esp32h2/dport_access.c

@@ -0,0 +1,25 @@
+// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+#include <string.h>
+#include "soc/dport_access.h"
+
+// Read a sequence of DPORT registers to the buffer.
+void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words)
+{
+    for (uint32_t i = 0; i < num_words; ++i) {
+        buff_out[i] = DPORT_SEQUENCE_REG_READ(address + i * 4);
+    }
+}

+ 83 - 0
components/esp32h2/esp_crypto_lock.c

@@ -0,0 +1,83 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#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);
+}

+ 232 - 0
components/esp32h2/esp_ds.c

@@ -0,0 +1,232 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "driver/periph_ctrl.h"
+#include "esp_crypto_lock.h"
+#include "hal/ds_hal.h"
+#include "hal/ds_ll.h"
+#include "hal/hmac_hal.h"
+#include "esp32h2/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 ESP32H2_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 ESP32H2_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 = ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
+    }
+
+    if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
+        return_value = ESP32H2_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;
+}

+ 132 - 0
components/esp32h2/esp_hmac.c

@@ -0,0 +1,132 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string.h>
+#include "driver/periph_ctrl.h"
+#include "esp32h2/rom/hmac.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp_hmac.h"
+#include "esp_crypto_lock.h"
+
+#include "hal/hmac_hal.h"
+
+#define SHA256_BLOCK_SZ 64
+#define SHA256_PAD_SZ 8
+
+/**
+ * @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 ESP32H2, 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 ESP32H2 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;
+}

+ 42 - 0
components/esp32h2/include/esp32h2/dport_access.h

@@ -0,0 +1,42 @@
+// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _ESP_DPORT_ACCESS_H_
+#define _ESP_DPORT_ACCESS_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Read a sequence of DPORT registers to the buffer.
+ *
+ * @param[out] buff_out  Contains the read data.
+ * @param[in]  address   Initial address for reading registers.
+ * @param[in]  num_words The number of words.
+ */
+void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words);
+
+#define DPORT_STALL_OTHER_CPU_START()
+#define DPORT_STALL_OTHER_CPU_END()
+#define DPORT_INTERRUPT_DISABLE()
+#define DPORT_INTERRUPT_RESTORE()
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ESP_DPORT_ACCESS_H_ */

+ 455 - 0
components/esp32h2/include/esp32h2/memprot.h

@@ -0,0 +1,455 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/* INTERNAL API
+ * generic interface to PMS memory protection features
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include "esp_attr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef IRAM_SRAM_START
+#define IRAM_SRAM_START             0x4037C000
+#endif
+
+#ifndef DRAM_SRAM_START
+#define DRAM_SRAM_START             0x3FC7C000
+#endif
+
+#ifndef MAP_DRAM_TO_IRAM
+#define MAP_DRAM_TO_IRAM(addr)       (addr - DRAM_SRAM_START + IRAM_SRAM_START)
+#endif
+
+#ifndef MAP_IRAM_TO_DRAM
+#define MAP_IRAM_TO_DRAM(addr)       (addr - IRAM_SRAM_START + DRAM_SRAM_START)
+#endif
+
+typedef enum {
+    MEMPROT_NONE =              0x00000000,
+    MEMPROT_IRAM0_SRAM =        0x00000001,
+    MEMPROT_DRAM0_SRAM =        0x00000002,
+    MEMPROT_ALL =               0xFFFFFFFF
+} mem_type_prot_t;
+
+typedef enum {
+    MEMPROT_SPLITLINE_NONE = 0,
+    MEMPROT_IRAM0_DRAM0_SPLITLINE,
+    MEMPROT_IRAM0_LINE_0_SPLITLINE,
+    MEMPROT_IRAM0_LINE_1_SPLITLINE,
+    MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE,
+    MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE
+} split_line_t;
+
+typedef enum {
+    MEMPROT_PMS_AREA_NONE = 0,
+    MEMPROT_IRAM0_PMS_AREA_0,
+    MEMPROT_IRAM0_PMS_AREA_1,
+    MEMPROT_IRAM0_PMS_AREA_2,
+    MEMPROT_IRAM0_PMS_AREA_3,
+    MEMPROT_DRAM0_PMS_AREA_0,
+    MEMPROT_DRAM0_PMS_AREA_1,
+    MEMPROT_DRAM0_PMS_AREA_2,
+    MEMPROT_DRAM0_PMS_AREA_3
+} pms_area_t;
+
+typedef enum
+{
+    MEMPROT_PMS_WORLD_0 = 0,
+    MEMPROT_PMS_WORLD_1,
+    MEMPROT_PMS_WORLD_2,
+    MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF
+} pms_world_t;
+
+typedef enum
+{
+    MEMPROT_PMS_OP_READ = 0,
+    MEMPROT_PMS_OP_WRITE,
+    MEMPROT_PMS_OP_FETCH,
+    MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF
+} pms_operation_type_t;
+
+/**
+ * @brief Converts Memory protection type to string
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ */
+const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type);
+
+/**
+ * @brief Converts Split line type to string
+ *
+ * @param line_type Split line type (see split_line_t enum)
+ */
+const char *esp_memprot_split_line_to_str(split_line_t line_type);
+
+/**
+ * @brief Converts PMS Area type to string
+ *
+ * @param area_type PMS Area type (see pms_area_t enum)
+ */
+const char *esp_memprot_pms_to_str(pms_area_t area_type);
+
+/**
+ * @brief Returns PMS splitting address for given Split line type
+ *
+ * The value is taken from PMS configuration registers (IRam0 range)
+ * For details on split lines see 'esp_memprot_set_prot_int' function description
+ *
+ * @param line_type Split line type (see split_line_t enum)
+ *
+ * @return appropriate split line address
+ */
+uint32_t *esp_memprot_get_split_addr(split_line_t line_type);
+
+/**
+ * @brief Returns default main IRAM/DRAM splitting address
+ *
+ * The address value is given by _iram_text_end global (IRam0 range)
+
+ * @return Main I/D split line (IRam0_DRam0_Split_Addr)
+ */
+void *esp_memprot_get_default_main_split_addr(void);
+
+/**
+ * @brief Sets a lock for the main IRAM/DRAM splitting address
+ *
+ * Locks can be unlocked only by digital system reset
+ */
+void esp_memprot_set_split_line_lock(void);
+
+/**
+ * @brief Gets a lock status for the main IRAM/DRAM splitting address
+ *
+ * @return true/false (locked/unlocked)
+ */
+bool esp_memprot_get_split_line_lock(void);
+
+/**
+ * @brief Sets required split line address
+ *
+ * @param line_type Split line type (see split_line_t enum)
+ * @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM)
+ */
+void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
+
+/**
+ * @brief Sets a lock for PMS Area settings of required Memory type
+ *
+ * Locks can be unlocked only by digital system reset
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ */
+void esp_memprot_set_pms_lock(mem_type_prot_t mem_type);
+
+/**
+ * @brief Gets a lock status for PMS Area settings of required Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return true/false (locked/unlocked)
+ */
+bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
+
+/**
+ * @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
+ *
+ * @param area_type IRam0 PMS Area type (see pms_area_t enum)
+ * @param r Read permission flag
+ * @param w Write permission flag
+ * @param x Execute permission flag
+ */
+void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
+
+/**
+ * @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
+ *
+ * @param area_type IRam0 PMS Area type (see pms_area_t enum)
+ * @param r Read permission flag holder
+ * @param w Write permission flag holder
+ * @param x Execute permission flag holder
+ */
+void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x);
+
+/**
+ * @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
+ *
+ * @param area_type DRam0 PMS Area type (see pms_area_t enum)
+ * @param r Read permission flag
+ * @param w Write permission flag
+ */
+void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
+
+/**
+ * @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
+ *
+ * @param area_type DRam0 PMS Area type (see pms_area_t enum)
+ * @param r Read permission flag holder
+ * @param w Write permission flag holder
+ */
+void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w);
+
+/**
+ * @brief Sets a lock for PMS interrupt monitor settings of required Memory type
+ *
+ * Locks can be unlocked only by digital system reset
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ */
+void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type);
+
+/**
+ * @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return true/false (locked/unlocked)
+ */
+bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
+
+/**
+ * @brief Enable PMS violation interrupt monitoring of required Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ * @param enable/disable
+ */
+void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
+
+/**
+ * @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return true/false (enabled/disabled)
+ */
+bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
+
+/**
+ * @brief Gets CPU ID for currently active PMS violation interrupt
+ *
+ * @return CPU ID (CPU_PRO for ESP32H2)
+ */
+int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
+
+/**
+ * @brief Clears current interrupt ON flag for given Memory type
+ *
+ * Interrupt clearing happens in two steps:
+ *      1. Interrupt CLR flag is set (to clear the interrupt ON status)
+ *      2. Interrupt CLR flag is reset (to allow further monitoring)
+ * This operation is non-atomic by PMS module design
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ */
+void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
+
+/**
+ * @brief Returns active PMS violation interrupt (if any)
+ *
+ * This function iterates through supported Memory type status registers
+ * and returns the first interrupt-on flag. If none is found active,
+ * MEMPROT_NONE is returned.
+ * Order of checking (in current version):
+ *      1. MEMPROT_IRAM0_SRAM
+ *      2. MEMPROT_DRAM0_SRAM
+ *
+ * @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum)
+ */
+mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
+
+/**
+ * @brief Checks whether any violation interrupt is active
+ *
+ * @return true/false (yes/no)
+ */
+bool IRAM_ATTR esp_memprot_is_locked_any(void);
+
+/**
+ * @brief Checks whether any violation interrupt is enabled
+ *
+ * @return true/false (yes/no)
+ */
+bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
+
+/**
+ * @brief Checks whether any violation interrupt is enabled
+ *
+ * @return true/false (yes/no)
+ */
+bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
+
+/**
+ * @brief Returns the address which caused the violation interrupt (if any)
+ *
+ * The address is taken from appropriate PMS violation status register, based given Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return faulting address
+ */
+uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
+
+/**
+ * @brief Returns the World identifier of the code causing the violation interrupt (if any)
+ *
+ * The value is taken from appropriate PMS violation status register, based given Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return World identifier (see pms_world_t enum)
+ */
+pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
+
+/**
+ * @brief Returns Read or Write operation type which caused the violation interrupt (if any)
+ *
+ * The value (bit) is taken from appropriate PMS violation status register, based given Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t)
+ */
+pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
+
+/**
+ * @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any)
+ *
+ * The value (bit) is taken from appropriate PMS violation status register, based given Memory type
+ * Effective only on IRam0 access
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return true/false (LoadStore bit on/off)
+ */
+bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
+
+/**
+ * @brief Returns byte-enables for the address which caused the violation interrupt (if any)
+ *
+ * The value is taken from appropriate PMS violation status register, based given Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return byte-enables
+ */
+uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
+
+/**
+ * @brief Returns raw contents of DRam0 status register 1
+ *
+ * @return 32-bit register value
+ */
+uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void);
+
+/**
+ * @brief Returns raw contents of DRam0 status register 2
+ *
+ * @return 32-bit register value
+ */
+uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void);
+
+/**
+ * @brief Returns raw contents of IRam0 status register
+ *
+ * @return 32-bit register value
+ */
+uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void);
+
+/**
+ * @brief Register PMS violation interrupt in global interrupt matrix for given Memory type
+ *
+ * Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM
+ * The registration makes the panic-handler routine being called when the interrupt appears
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ */
+void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
+
+/**
+ * @brief Convenient routine for setting the PMS defaults
+ *
+ * Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings
+ * For implementation details see 'esp_memprot_set_prot_int' description
+ *
+ * @param invoke_panic_handler register all interrupts for panic handling (true/false)
+ * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
+ * @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int')
+ */
+void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
+
+/**
+ * @brief Internal routine for setting the PMS defaults
+ *
+ * Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address
+ * (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line
+ * is used (&_iram_text_end) and all the remaining lines share the same address.
+ * The function sets all the split lines and PMS areas to the same space,
+ * ie there is a single instruction space and single data space at the end.
+ * The PMS split lines and permission areas scheme described below:
+ *
+ *                            DRam0/DMA                                     IRam0
+ *                              -----------------------------------------------
+ *                    ...       |                 IRam0_PMS_0                 |
+ *               DRam0_PMS_0   -----------------------------------------------    IRam0_line1_Split_addr
+ *                    ...       |                 IRam0_PMS_1                 |
+ *                    ...       -----------------------------------------------   IRam0_line0_Split_addr
+ *                              |                 IRam0_PMS_2                 |
+ *                              ===============================================   IRam0_DRam0_Split_addr (main I/D)
+ *                              |                 DRam0_PMS_1                 |
+ * DRam0_DMA_line0_Split_addr   -----------------------------------------------       ...
+ *                              |                 DRam0_PMS_2                 |       ...
+ * DRam0_DMA_line1_Split_addr   -----------------------------------------------   IRam0_PMS_3
+ *                              |                 DRam0_PMS_3                 |       ...
+ *                              -----------------------------------------------
+ *
+ * Default settings provided by 'esp_memprot_set_prot_int' are as follows:
+ *
+ *                            DRam0/DMA                                     IRam0
+ *                              -----------------------------------------------
+ *                              |   IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2   |
+ *                              |                 DRam0_PMS_0                 |   IRam0_line1_Split_addr
+ * DRam0_DMA_line0_Split_addr   |                                             |             =
+ *               =              ===============================================   IRam0_line0_Split_addr
+ * DRam0_DMA_line1_Split_addr   |                                             |             =
+ *                              |   DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3   |   IRam0_DRam0_Split_addr (main I/D)
+ *                              |                 IRam0_PMS_3                 |
+ *                              -----------------------------------------------
+ *
+ * Once the memprot feature is locked, it can be unlocked only by digital system reset
+ *
+ * @param invoke_panic_handler register all the violation interrupts for panic handling (true/false)
+ * @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
+ * @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end)
+ * @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t)
+ */
+void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
+
+/**
+ * @brief Returns raw contents of PMS interrupt monitor register for given Memory type
+ *
+ * @param mem_type Memory protection type (see mem_type_prot_t enum)
+ *
+ * @return 32-bit register value
+ */
+uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type);
+
+#ifdef __cplusplus
+}
+#endif

+ 40 - 0
components/esp32h2/include/esp32h2/rtc.h

@@ -0,0 +1,40 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file esp32h2/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

+ 76 - 0
components/esp32h2/include/esp_crypto_lock.h

@@ -0,0 +1,76 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#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

+ 218 - 0
components/esp32h2/include/esp_ds.h

@@ -0,0 +1,218 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "esp_hmac.h"
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL           ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
+#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_KEY         ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
+                                                                                HMAC peripheral problem */
+#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST      ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
+                                                                                result is invalid */
+#define ESP32H2_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.
+ *
+ * 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 is determined by data->rsa_length
+ * @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.
+ *
+ * @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 is determined by data->rsa_length
+ * @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

+ 67 - 0
components/esp32h2/include/esp_hmac.h

@@ -0,0 +1,67 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef _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 32 bytes long
+ *
+ * @return
+ *      * ESP_OK, if the calculation was successful,
+ *      * 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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _ESP_HMAC_H_

+ 118 - 0
components/esp32h2/ld/esp32h2.ld

@@ -0,0 +1,118 @@
+/**
+ *                    ESP32-H2 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"
+
+#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
+
+#define SRAM_IRAM_START     0x4037C000
+#define SRAM_DRAM_START     0x3FC7C000
+#define ICACHE_SIZE         0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */
+#define I_D_SRAM_OFFSET     (SRAM_IRAM_START - SRAM_DRAM_START)
+#define SRAM_DRAM_END       0x403D0000 - I_D_SRAM_OFFSET  /* 2nd stage bootloader iram_loader_seg start address */
+
+#define SRAM_IRAM_ORG       (SRAM_IRAM_START + ICACHE_SIZE)
+#define SRAM_DRAM_ORG       (SRAM_DRAM_START + ICACHE_SIZE)
+
+#define I_D_SRAM_SIZE       SRAM_DRAM_END - SRAM_DRAM_ORG
+
+#if CONFIG_ESP32H2_USE_FIXED_STATIC_RAM_SIZE
+ASSERT((CONFIG_ESP32H2_FIXED_STATIC_RAM_SIZE <= I_D_SRAM_SIZE), "Fixed static ram data does not fit.")
+#define DRAM0_0_SEG_LEN CONFIG_ESP3C3_FIXED_STATIC_RAM_SIZE
+#else
+#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
+#endif // CONFIG_ESP32H2_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 = 0x8000000-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 = 0x3C000020, len = 0x8000000-0x20
+
+  /* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
+#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
+
+  /**
+   * RTC fast memory (executable). Persists over deep sleep.
+   */
+  rtc_iram_seg(RWX) :                org = 0x50000000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC
+}
+
+#if CONFIG_ESP32H2_USE_FIXED_STATIC_RAM_SIZE
+/* static data ends at defined address */
+_static_data_end = 0x3FCA0000 + DRAM0_0_SEG_LEN;
+#else
+_static_data_end = _bss_end;
+#endif // CONFIG_ESP32H2_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
+ *  As C3 only has RTC fast memory, this is not configurable like on other targets
+ */
+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

+ 30 - 0
components/esp32h2/ld/esp32h2.peripherals.ld

@@ -0,0 +1,30 @@
+PROVIDE ( UART0 = 0x60000000 );
+PROVIDE ( UART1 = 0x60010000 );
+PROVIDE ( SPIMEM1 = 0x60002000 );
+PROVIDE ( SPIMEM0 = 0x60003000 );
+PROVIDE ( GPIO = 0x60004000 );
+PROVIDE ( SIGMADELTA = 0x60004f00 );
+PROVIDE ( RTCCNTL = 0x60008000 );
+PROVIDE ( RTCIO = 0x60008400 );
+PROVIDE ( HINF = 0x6000B000 );
+PROVIDE ( I2S1  = 0x6002d000 );
+PROVIDE ( I2C0  = 0x60013000 );
+PROVIDE ( UHCI0  = 0x60014000 );
+PROVIDE ( UHCI1  = 0x6000c000 );
+PROVIDE ( HOST = 0x60015000 );
+PROVIDE ( RMT = 0x60016000 );
+PROVIDE ( RMTMEM = 0x60016400 );
+PROVIDE ( PCNT = 0x60017000 );
+PROVIDE ( SLC = 0x60018000 );
+PROVIDE ( LEDC = 0x60019000 );
+PROVIDE ( TIMERG0 = 0x6001F000 );
+PROVIDE ( TIMERG1 = 0x60020000 );
+PROVIDE ( SYSTIMER = 0x60023000 );
+PROVIDE ( GPSPI2  = 0x60024000 );
+PROVIDE ( GPSPI3  = 0x60025000 );
+PROVIDE ( SYSCON = 0x60026000 );
+PROVIDE ( TWAI   = 0x6002B000 );
+PROVIDE ( GPSPI4 = 0x60037000 );
+PROVIDE ( APB_SARADC = 0x60040000 );
+PROVIDE ( USB_SERIAL_JTAG = 0x60043000 );
+PROVIDE ( GDMA    = 0x6003F000 );

+ 392 - 0
components/esp32h2/ld/esp32h2.project.ld.in

@@ -0,0 +1,392 @@
+/* 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);
+
+    mapping[rtc_text]
+
+    *rtc_wake_stub*.*(.literal .text .literal.* .text.*)
+    _rtc_text_end = ABSOLUTE(.);
+  } > rtc_iram_seg
+
+  /**
+   * This section is required to skip rtc.text area because rtc_iram_seg and
+   * rtc_data_seg are reflect the same address space on different buses.
+   */
+  .rtc.dummy :
+  {
+    _rtc_dummy_start = ABSOLUTE(.);
+    _rtc_fast_start = ABSOLUTE(.);
+    . = SIZEOF(.rtc.text);
+    _rtc_dummy_end = ABSOLUTE(.);
+  } > rtc_data_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(.);
+  } > rtc_data_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.
+   * The memory location of the data is dependent on
+   * CONFIG_ESP32H2_RTCDATA_IN_FAST_MEM option.
+   */
+  .rtc.data :
+  {
+    _rtc_data_start = ABSOLUTE(.);
+
+    mapping[rtc_data]
+
+    *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
+    _rtc_data_end = ABSOLUTE(.);
+  } > rtc_data_location
+
+  /* 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(.);
+  } > rtc_data_location
+
+  /**
+   * 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.
+   * The memory location of the data is dependent on CONFIG_ESP32H2_RTCDATA_IN_FAST_MEM option.
+   */
+  .rtc_noinit (NOLOAD):
+  {
+    . = ALIGN(4);
+    _rtc_noinit_start = ABSOLUTE(.);
+    *(.rtc_noinit .rtc_noinit.*)
+    . = ALIGN(4) ;
+    _rtc_noinit_end = ABSOLUTE(.);
+  } > rtc_data_location
+
+  /**
+   * 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(.);
+  } > rtc_slow_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
+
+  /**
+   * 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.*)
+    *(.sdata2)
+    *(.sdata2.*)
+    *(.gnu.linkonce.s2.*)
+    *(.jcr)
+
+    _esp_system_init_fn_array_start = ABSOLUTE(.);
+    KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*)))
+    _esp_system_init_fn_array_end = ABSOLUTE(.);
+
+    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
+      */
+    . += 16;
+
+    _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 alignement and (at least) its size.
+   */
+  .flash_rodata_dummy (NOLOAD):
+  {
+    _flash_rodata_dummy_start = .;
+    /* Start at the same alignement constraint than .flash.text */
+    . = ALIGN(ALIGNOF(.flash.text));
+    /* Create an empty gap as big as .flash.text section */
+    . = . + SIZEOF(.flash.text);
+    /* Prepare the alignement 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)
+    . = (. + 3) & ~ 3;
+    __eh_frame = ABSOLUTE(.);
+    KEEP(*(.eh_frame))
+    . = (. + 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(.);
+    _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.*)
+    *(.srodata)
+    *(.srodata.*)
+    _thread_local_end = ABSOLUTE(.);
+    _rodata_reserved_end = ABSOLUTE(.);
+    . = ALIGN(4);
+  } > default_rodata_seg
+
+  /* Marks the end of IRAM code segment */
+  .iram0.text_end (NOLOAD) :
+  {
+    /* C3 memprot requires 512 B alignment for split lines */
+    . = ALIGN (0x200);
+    /* 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
+
+  /* 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.")

+ 616 - 0
components/esp32h2/memprot.c

@@ -0,0 +1,616 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/* INTERNAL API
+ * implementation of PMS memory protection features
+ */
+
+#include <stdio.h>
+#include "sdkconfig.h"
+#include "soc/sensitive_reg.h"
+#include "soc/dport_access.h"
+#include "soc/periph_defs.h"
+#include "esp_intr_alloc.h"
+#include "hal/memprot_ll.h"
+#include "esp32h2/memprot.h"
+#include "riscv/interrupt.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp_log.h"
+
+extern int _iram_text_end;
+static const char *TAG = "memprot";
+
+const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_NONE:
+        return "NONE";
+    case MEMPROT_IRAM0_SRAM:
+        return "IRAM0_SRAM";
+    case MEMPROT_DRAM0_SRAM:
+        return "DRAM0_SRAM";
+    case MEMPROT_ALL:
+        return "ALL";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+const char *esp_memprot_split_line_to_str(split_line_t line_type)
+{
+    switch (line_type) {
+    case MEMPROT_IRAM0_DRAM0_SPLITLINE:
+        return "MEMPROT_IRAM0_DRAM0_SPLITLINE";
+    case MEMPROT_IRAM0_LINE_0_SPLITLINE:
+        return "MEMPROT_IRAM0_LINE_0_SPLITLINE";
+    case MEMPROT_IRAM0_LINE_1_SPLITLINE:
+        return "MEMPROT_IRAM0_LINE_1_SPLITLINE";
+    case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
+        return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE";
+    case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
+        return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+const char *esp_memprot_pms_to_str(pms_area_t area_type)
+{
+    switch (area_type) {
+    case MEMPROT_IRAM0_PMS_AREA_0:
+        return "MEMPROT_IRAM0_PMS_AREA_0";
+    case MEMPROT_IRAM0_PMS_AREA_1:
+        return "MEMPROT_IRAM0_PMS_AREA_1";
+    case MEMPROT_IRAM0_PMS_AREA_2:
+        return "MEMPROT_IRAM0_PMS_AREA_2";
+    case MEMPROT_IRAM0_PMS_AREA_3:
+        return "MEMPROT_IRAM0_PMS_AREA_3";
+    case MEMPROT_DRAM0_PMS_AREA_0:
+        return "MEMPROT_DRAM0_PMS_AREA_0";
+    case MEMPROT_DRAM0_PMS_AREA_1:
+        return "MEMPROT_DRAM0_PMS_AREA_1";
+    case MEMPROT_DRAM0_PMS_AREA_2:
+        return "MEMPROT_DRAM0_PMS_AREA_2";
+    case MEMPROT_DRAM0_PMS_AREA_3:
+        return "MEMPROT_DRAM0_PMS_AREA_3";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+
+/* split lines */
+
+void *esp_memprot_get_default_main_split_addr()
+{
+    return &_iram_text_end;
+}
+
+uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
+{
+    switch ( line_type ) {
+        case MEMPROT_IRAM0_DRAM0_SPLITLINE:
+            return memprot_ll_get_iram0_split_line_main_I_D();
+        case MEMPROT_IRAM0_LINE_0_SPLITLINE:
+            return memprot_ll_get_iram0_split_line_I_0();
+        case MEMPROT_IRAM0_LINE_1_SPLITLINE:
+            return memprot_ll_get_iram0_split_line_I_1();
+        case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
+            return memprot_ll_get_dram0_split_line_D_0();
+        case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
+            return memprot_ll_get_dram0_split_line_D_1();
+        default:
+            abort();
+    }
+}
+
+void esp_memprot_set_split_line_lock()
+{
+    memprot_ll_set_iram0_dram0_split_line_lock();
+}
+
+bool esp_memprot_get_split_line_lock()
+{
+    return memprot_ll_get_iram0_dram0_split_line_lock();
+}
+
+void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
+{
+    ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr);
+
+    //split-line must be divisible by 512 (PMS module restriction)
+    assert( ((uint32_t)line_addr) % 0x200 == 0 );
+
+    switch ( line_type ) {
+    case MEMPROT_IRAM0_DRAM0_SPLITLINE:
+        memprot_ll_set_iram0_split_line_main_I_D(line_addr);
+        break;
+    case MEMPROT_IRAM0_LINE_0_SPLITLINE:
+        memprot_ll_set_iram0_split_line_I_0(line_addr);
+        break;
+    case MEMPROT_IRAM0_LINE_1_SPLITLINE:
+        memprot_ll_set_iram0_split_line_I_1(line_addr);
+        break;
+    case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
+        memprot_ll_set_dram0_split_line_D_0(line_addr);
+        break;
+    case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
+        memprot_ll_set_dram0_split_line_D_1(line_addr);
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr);
+        abort();
+    }
+}
+
+
+/* PMS */
+
+void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        memprot_ll_iram0_set_pms_lock();
+        break;
+    case MEMPROT_DRAM0_SRAM:
+        memprot_ll_dram0_set_pms_lock();
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_pms_lock();
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_pms_lock();
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x);
+
+    switch ( area_type ) {
+    case MEMPROT_IRAM0_PMS_AREA_0:
+        memprot_ll_iram0_set_pms_area_0(r, w, x);
+        break;
+    case MEMPROT_IRAM0_PMS_AREA_1:
+        memprot_ll_iram0_set_pms_area_1(r, w, x);
+        break;
+    case MEMPROT_IRAM0_PMS_AREA_2:
+        memprot_ll_iram0_set_pms_area_2(r, w, x);
+        break;
+    case MEMPROT_IRAM0_PMS_AREA_3:
+        memprot_ll_iram0_set_pms_area_3(r, w, x);
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
+        abort();
+    }
+}
+
+void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
+
+    switch ( area_type ) {
+    case MEMPROT_IRAM0_PMS_AREA_0:
+        memprot_ll_iram0_get_pms_area_0(r, w, x);
+        break;
+    case MEMPROT_IRAM0_PMS_AREA_1:
+        memprot_ll_iram0_get_pms_area_1(r, w, x);
+        break;
+    case MEMPROT_IRAM0_PMS_AREA_2:
+        memprot_ll_iram0_get_pms_area_2(r, w, x);
+        break;
+    case MEMPROT_IRAM0_PMS_AREA_3:
+        memprot_ll_iram0_get_pms_area_3(r, w, x);
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
+        abort();
+    }
+}
+
+void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
+
+    switch ( area_type ) {
+    case MEMPROT_DRAM0_PMS_AREA_0:
+        memprot_ll_dram0_set_pms_area_0(r, w);
+        break;
+    case MEMPROT_DRAM0_PMS_AREA_1:
+        memprot_ll_dram0_set_pms_area_1(r, w);
+        break;
+    case MEMPROT_DRAM0_PMS_AREA_2:
+        memprot_ll_dram0_set_pms_area_2(r, w);
+        break;
+    case MEMPROT_DRAM0_PMS_AREA_3:
+        memprot_ll_dram0_set_pms_area_3(r, w);
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
+        abort();
+    }
+}
+
+void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
+
+    switch ( area_type ) {
+    case MEMPROT_DRAM0_PMS_AREA_0:
+        memprot_ll_dram0_get_pms_area_0(r, w);
+        break;
+    case MEMPROT_DRAM0_PMS_AREA_1:
+        memprot_ll_dram0_get_pms_area_1(r, w);
+        break;
+    case MEMPROT_DRAM0_PMS_AREA_2:
+        memprot_ll_dram0_get_pms_area_2(r, w);
+        break;
+    case MEMPROT_DRAM0_PMS_AREA_3:
+        memprot_ll_dram0_get_pms_area_3(r, w);
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
+        abort();
+    }
+}
+
+
+/* monitor */
+
+void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        memprot_ll_iram0_set_monitor_lock();
+        break;
+    case MEMPROT_DRAM0_SRAM:
+        memprot_ll_dram0_set_monitor_lock();
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_monitor_lock();
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_monitor_lock();
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        memprot_ll_iram0_set_monitor_en(enable);
+        break;
+    case MEMPROT_DRAM0_SRAM:
+        memprot_ll_dram0_set_monitor_en(enable);
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_monitor_en();
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_monitor_en();
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+bool esp_memprot_is_intr_ena_any()
+{
+    return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM);
+}
+
+void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        memprot_ll_iram0_clear_monitor_intr();
+        memprot_ll_iram0_reset_clear_monitor_intr();
+        break;
+    case MEMPROT_DRAM0_SRAM:
+        memprot_ll_dram0_clear_monitor_intr();
+        memprot_ll_dram0_reset_clear_monitor_intr();
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+mem_type_prot_t esp_memprot_get_active_intr_memtype()
+{
+    if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) {
+        return MEMPROT_IRAM0_SRAM;
+    } else if ( memprot_ll_dram0_get_monitor_status_intr() ) {
+        return MEMPROT_DRAM0_SRAM;
+    }
+
+    return MEMPROT_NONE;
+}
+
+bool esp_memprot_is_locked_any()
+{
+    return
+        esp_memprot_get_split_line_lock() ||
+        esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) ||
+        esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) ||
+        esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) ||
+        esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
+}
+
+bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
+{
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_monitor_status_intr() == 1;
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_monitor_status_intr() == 1;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
+{
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_monitor_status_fault_addr();
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_monitor_status_fault_addr();
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
+{
+    uint32_t world = 0;
+
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        world = memprot_ll_iram0_get_monitor_status_fault_world();
+        break;
+    case MEMPROT_DRAM0_SRAM:
+        world = memprot_ll_dram0_get_monitor_status_fault_world();
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+
+    switch ( world ) {
+        case 0x01: return MEMPROT_PMS_WORLD_0;
+        case 0x10: return MEMPROT_PMS_WORLD_1;
+        default: return MEMPROT_PMS_WORLD_INVALID;
+    }
+}
+
+pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
+{
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
+{
+    switch ( mem_type ) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
+{
+    switch ( mem_type ) {
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_monitor_status_fault_byte_en();
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+}
+
+int esp_memprot_intr_get_cpuid()
+{
+    return PRO_CPU_NUM;
+}
+
+void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type));
+
+    ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
+
+    switch (mem_type) {
+    case MEMPROT_IRAM0_SRAM:
+        intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
+        break;
+    case MEMPROT_DRAM0_SRAM:
+        intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
+        break;
+    default:
+        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
+        abort();
+    }
+
+    /* Set the type and priority to cache error interrupts. */
+    esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
+    esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
+
+    ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
+}
+
+void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask)
+{
+    esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask);
+}
+
+void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask)
+{
+    ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask);
+
+    uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask;
+    bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM;
+    bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM;
+
+    if (required_mem_prot == MEMPROT_NONE) {
+        return;
+    }
+
+    //disable protection
+    if (use_iram0) {
+        esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false);
+    }
+    if (use_dram0) {
+        esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false);
+    }
+
+    //panic handling
+    if (invoke_panic_handler) {
+        if (use_iram0) {
+            esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM);
+        }
+        if (use_dram0) {
+            esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM);
+        }
+    }
+
+    //set split lines (must-have for all mem_types)
+    const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
+    esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
+    esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
+    esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
+    esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
+    esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
+
+    //set permissions
+    if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
+        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true);
+        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true);
+        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true);
+        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false);
+    }
+    if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
+        esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, true, false );
+        esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true);
+        esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true);
+        esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true);
+    }
+
+    //reenable protection
+    if (use_iram0) {
+        esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM);
+        esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true);
+    }
+    if (use_dram0) {
+        esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM);
+        esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true);
+    }
+
+    //lock if required
+    if (lock_feature) {
+        esp_memprot_set_split_line_lock();
+        if (use_iram0) {
+            esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
+            esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
+        }
+        if (use_dram0) {
+            esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
+            esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
+        }
+    }
+}
+
+uint32_t esp_memprot_get_dram_status_reg_1()
+{
+    return memprot_ll_dram0_get_monitor_status_register_1();
+}
+
+uint32_t esp_memprot_get_dram_status_reg_2()
+{
+    return memprot_ll_dram0_get_monitor_status_register_2();
+}
+
+uint32_t esp_memprot_get_iram_status_reg()
+{
+    return memprot_ll_iram0_get_monitor_status_register();
+}
+
+uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_IRAM0_SRAM:
+        return memprot_ll_iram0_get_monitor_enable_register();
+    case MEMPROT_DRAM0_SRAM:
+        return memprot_ll_dram0_get_monitor_enable_register();
+    default:
+        abort();
+    }
+}

+ 5 - 0
components/esp32h2/project_include.cmake

@@ -0,0 +1,5 @@
+set(compile_options "-Wno-error=format="
+                    "-nostartfiles"
+                    "-Wno-format")
+
+idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)

+ 9 - 0
components/esp32h2/test/CMakeLists.txt

@@ -0,0 +1,9 @@
+if(IDF_TARGET STREQUAL "esp32h2")
+    idf_component_register(SRC_DIRS .
+                        INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR}
+                        REQUIRES unity test_utils esp_common mbedtls
+                        )
+
+    idf_build_set_property(COMPILE_DEFINITIONS "-DESP_TIMER_DYNAMIC_OVERFLOW_VAL" APPEND)
+    target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_test_dport_xt_highint5")
+endif()

+ 4 - 0
components/esp32h2/test/component.mk

@@ -0,0 +1,4 @@
+#
+# Component Makefile (not used for tests, but CI checks test parity between GNU Make & CMake)
+#
+COMPONENT_CONFIG_ONLY := 1

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 49 - 0
components/esp32h2/test/digital_signature_test_cases.h


+ 382 - 0
components/esp32h2/test/test_ds.c

@@ -0,0 +1,382 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "unity.h"
+#include "esp32h2/rom/efuse.h"
+#include "esp32h2/rom/digital_signature.h"
+#include "esp32h2/rom/hmac.h"
+#include <string.h>
+
+#include "esp_ds.h"
+
+#define NUM_RESULTS 10
+#define DS_MAX_BITS (ETS_DS_MAX_BITS)
+
+typedef struct {
+    uint8_t iv[ETS_DS_IV_LEN];
+    ets_ds_p_data_t p_data;
+    uint8_t expected_c[ETS_DS_C_LEN];
+    uint8_t hmac_key_idx;
+    uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS/32];
+} encrypt_testcase_t;
+
+// Generated header (components/esp32s2/test/gen_digital_signature_tests.py) defines
+// NUM_HMAC_KEYS, test_hmac_keys, NUM_MESSAGES, NUM_CASES, test_messages[], test_cases[]
+#include "digital_signature_test_cases.h"
+
+_Static_assert(NUM_RESULTS == NUM_MESSAGES, "expected_results size should be the same as NUM_MESSAGES in generated header");
+
+TEST_CASE("Digital Signature Parameter Encryption data NULL", "[hw_crypto] [ds]")
+{
+    const char iv [32];
+    esp_ds_p_data_t p_data;
+    const char key [32];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(NULL, iv, &p_data, key));
+}
+
+TEST_CASE("Digital Signature Parameter Encryption iv NULL", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t data;
+    esp_ds_p_data_t p_data;
+    const char key [32];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, NULL, &p_data, key));
+}
+
+TEST_CASE("Digital Signature Parameter Encryption p_data NULL", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t data;
+    const char iv [32];
+    const char key [32];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, NULL, key));
+}
+
+TEST_CASE("Digital Signature Parameter Encryption key NULL", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t data;
+    const char iv [32];
+    esp_ds_p_data_t p_data;
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, &p_data, NULL));
+}
+
+TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]")
+{
+    for (int i = 0; i < NUM_CASES; i++) {
+        printf("Encrypting test case %d...\n", i);
+        const encrypt_testcase_t *t = &test_cases[i];
+        esp_ds_data_t result = { };
+        esp_ds_p_data_t p_data;
+
+        memcpy(p_data.Y,   t->p_data.Y, ESP_DS_SIGNATURE_MAX_BIT_LEN/8);
+        memcpy(p_data.M,   t->p_data.M, ESP_DS_SIGNATURE_MAX_BIT_LEN/8);
+        memcpy(p_data.Rb, t->p_data.Rb, ESP_DS_SIGNATURE_MAX_BIT_LEN/8);
+        p_data.M_prime = t->p_data.M_prime;
+        p_data.length = t->p_data.length;
+
+        esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data,
+                                                  test_hmac_keys[t->hmac_key_idx]);
+        printf("Encrypting test case %d done\n", i);
+
+        TEST_ASSERT_EQUAL(ESP_OK, r);
+        TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length);
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(t->iv, result.iv, ETS_DS_IV_LEN);
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_c, result.c, ETS_DS_C_LEN);
+    }
+}
+
+TEST_CASE("Digital Signature start Invalid message", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = { };
+    ds_data.rsa_length = ESP_DS_RSA_3072;
+    esp_ds_context_t *ctx;
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(NULL, &ds_data, HMAC_KEY1, &ctx));
+}
+
+TEST_CASE("Digital Signature start Invalid data", "[hw_crypto] [ds]")
+{
+    const char *message = "test";
+    esp_ds_context_t *ctx;
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, NULL, HMAC_KEY1, &ctx));
+}
+
+TEST_CASE("Digital Signature start Invalid context", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = ESP_DS_RSA_3072;
+    const char *message = "test";
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
+}
+
+TEST_CASE("Digital Signature RSA length 0", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = 0;
+    const char *message = "test";
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
+}
+
+TEST_CASE("Digital Signature RSA length too long", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = 128;
+    const char *message = "test";
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
+}
+
+TEST_CASE("Digital Signature start HMAC key out of range", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = ESP_DS_RSA_3072;
+    esp_ds_context_t *ctx;
+    const char *message = "test";
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY5 + 1, &ctx));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY0 - 1, &ctx));
+}
+
+TEST_CASE("Digital Signature finish Invalid signature ptr", "[hw_crypto] [ds]")
+{
+    esp_ds_context_t *ctx = NULL;
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(NULL, ctx));
+}
+
+TEST_CASE("Digital Signature finish Invalid context", "[hw_crypto] [ds]")
+{
+    uint8_t signature_data [128 * 4];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(signature_data, NULL));
+}
+
+TEST_CASE("Digital Signature Blocking Invalid message", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = { };
+    ds_data.rsa_length = ESP_DS_RSA_3072;
+    uint8_t signature_data [128 * 4];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(NULL, &ds_data, HMAC_KEY1, signature_data));
+}
+
+TEST_CASE("Digital Signature Blocking Invalid data", "[hw_crypto] [ds]")
+{
+    const char *message = "test";
+    uint8_t signature_data [128 * 4];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, NULL, HMAC_KEY1, signature_data));
+}
+
+TEST_CASE("Digital Signature Blocking Invalid signature ptr", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = ESP_DS_RSA_3072;
+    const char *message = "test";
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, NULL));
+}
+
+TEST_CASE("Digital Signature Blocking RSA length 0", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = 0;
+    const char *message = "test";
+    uint8_t signature_data [128 * 4];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
+}
+
+TEST_CASE("Digital Signature Blocking RSA length too long", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = 128;
+    const char *message = "test";
+    uint8_t signature_data [128 * 4];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
+}
+
+TEST_CASE("Digital Signature Blocking HMAC key out of range", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = 127;
+    const char *message = "test";
+    uint8_t signature_data [128 * 4];
+
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY5 + 1, signature_data));
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY0 - 1, signature_data));
+}
+
+#if CONFIG_IDF_ENV_FPGA
+
+// Burn eFuse blocks 1, 2 and 3. Block 0 is used for HMAC tests already.
+static void burn_hmac_keys(void)
+{
+    printf("Burning %d HMAC keys to efuse...\n", NUM_HMAC_KEYS);
+    for (int i = 0; i < NUM_HMAC_KEYS; i++) {
+        // TODO: vary the purpose across the keys
+        ets_efuse_purpose_t purpose = ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE;
+        ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY1 + i,
+                            purpose,
+                            test_hmac_keys[i], 32);
+    }
+    /* verify the keys are what we expect (possibly they're already burned, doesn't matter but they have to match) */
+    uint8_t block_compare[32];
+    for (int i = 0; i < NUM_HMAC_KEYS; i++) {
+        printf("Checking key %d...\n", i);
+        memcpy(block_compare, (void *)ets_efuse_get_read_register_address(ETS_EFUSE_BLOCK_KEY1 + i), 32);
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(test_hmac_keys[i], block_compare, 32);
+    }
+}
+
+// This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
+// HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
+TEST_CASE("Digital Signature wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = ESP_DS_RSA_3072;
+    esp_ds_context_t *ctx;
+    const char *message = "test";
+
+    // HMAC fails in that case because it checks for the correct purpose
+    TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx));
+}
+
+// This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
+// HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
+TEST_CASE("Digital Signature Blocking wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
+{
+    esp_ds_data_t ds_data = {};
+    ds_data.rsa_length = ESP_DS_RSA_3072;
+    const char *message = "test";
+    uint8_t signature_data [128 * 4];
+
+    // HMAC fails in that case because it checks for the correct purpose
+    TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data));
+}
+
+TEST_CASE("Digital Signature Operation (FPGA only)", "[hw_crypto] [ds]")
+{
+    burn_hmac_keys();
+
+    for (int i = 0; i < NUM_CASES; i++) {
+        printf("Running test case %d...\n", i);
+        const encrypt_testcase_t *t = &test_cases[i];
+
+        // copy encrypt parameter test case into ds_data structure
+        esp_ds_data_t ds_data = { };
+        memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
+        memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
+        ds_data.rsa_length = t->p_data.length;
+
+        for (int j = 0; j < NUM_MESSAGES; j++) {
+            uint8_t signature[DS_MAX_BITS/8] = { 0 };
+            printf(" ... message %d\n", j);
+
+            esp_ds_context_t *esp_ds_ctx;
+            esp_err_t ds_r = esp_ds_start_sign(test_messages[j],
+                    &ds_data,
+                    t->hmac_key_idx + 1,
+                    &esp_ds_ctx);
+            TEST_ASSERT_EQUAL(ESP_OK, ds_r);
+
+            ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
+            TEST_ASSERT_EQUAL(ESP_OK, ds_r);
+
+            TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[j], signature, sizeof(signature));
+        }
+
+        ets_hmac_invalidate_downstream(ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
+    }
+}
+
+TEST_CASE("Digital Signature Blocking Operation (FPGA only)", "[hw_crypto] [ds]")
+{
+    burn_hmac_keys();
+
+    for (int i = 0; i < NUM_CASES; i++) {
+        printf("Running test case %d...\n", i);
+        const encrypt_testcase_t *t = &test_cases[i];
+
+        // copy encrypt parameter test case into ds_data structure
+        esp_ds_data_t ds_data = { };
+        memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
+        memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
+        ds_data.rsa_length = t->p_data.length;
+
+        uint8_t signature[DS_MAX_BITS/8] = { 0 };
+
+        esp_err_t ds_r = esp_ds_sign(test_messages[0],
+                &ds_data,
+                t->hmac_key_idx + 1,
+                signature);
+        TEST_ASSERT_EQUAL(ESP_OK, ds_r);
+
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[0], signature, sizeof(signature));
+    }
+}
+
+TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]")
+{
+    burn_hmac_keys();
+
+    // Set up a valid test case
+    const encrypt_testcase_t *t = &test_cases[0];
+    esp_ds_data_t ds_data = { };
+    memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
+    memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
+    ds_data.rsa_length = t->p_data.length;
+
+    uint8_t signature[DS_MAX_BITS/8] = { 0 };
+    const uint8_t zero[DS_MAX_BITS/8] = { 0 };
+
+    // Corrupt the IV one bit at a time, rerun and expect failure
+    for (int bit = 0; bit < 128; bit++) {
+        printf("Corrupting IV bit %d...\n", bit);
+        ds_data.iv[bit / 8] ^= 1 << (bit % 8);
+        esp_ds_context_t *esp_ds_ctx;
+
+        esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
+        TEST_ASSERT_EQUAL(ESP_OK, ds_r);
+        ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
+        TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8);
+
+        ds_data.iv[bit / 8] ^= 1 << (bit % 8);
+    }
+
+    // Corrupt encrypted key data one bit at a time, rerun and expect failure
+    printf("Corrupting C...\n");
+    for (int bit = 0; bit < ETS_DS_C_LEN * 8; bit++) {
+        printf("Corrupting C bit %d...\n", bit);
+        ds_data.c[bit / 8] ^= 1 << (bit % 8);
+        esp_ds_context_t *esp_ds_ctx;
+
+        esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
+        TEST_ASSERT_EQUAL(ESP_OK, ds_r);
+        ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
+        TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
+        TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8);
+
+        ds_data.c[bit / 8] ^= 1 << (bit % 8);
+    }
+}
+
+#endif // CONFIG_IDF_ENV_FPGA

+ 80 - 0
components/esp32h2/test/test_sha.c

@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "esp_types.h"
+#include "esp32h2/clk.h"
+#include "esp_log.h"
+#include "esp_timer.h"
+#include "esp_heap_caps.h"
+#include "idf_performance.h"
+
+#include "unity.h"
+#include "test_utils.h"
+#include "mbedtls/sha1.h"
+#include "mbedtls/sha256.h"
+#include "sha/sha_dma.h"
+
+/* Note: Most of the SHA functions are called as part of mbedTLS, so
+are tested as part of mbedTLS tests. Only esp_sha() is different.
+*/
+
+#define TAG "sha_test"
+
+TEST_CASE("Test esp_sha()", "[hw_crypto]")
+{
+    const size_t BUFFER_SZ = 32 * 1024 + 6; // NB: not an exact multiple of SHA block size
+
+    int64_t begin, end;
+    uint32_t us_sha1;
+    uint8_t sha1_result[20] = { 0 };
+    void *buffer = heap_caps_malloc(BUFFER_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
+    TEST_ASSERT_NOT_NULL(buffer);
+    memset(buffer, 0xEE, BUFFER_SZ);
+
+    const uint8_t sha1_expected[20] = { 0xc7, 0xbb, 0xd3, 0x74, 0xf2, 0xf6, 0x20, 0x86,
+                                        0x61, 0xf4, 0x50, 0xd5, 0xf5, 0x18, 0x44, 0xcc,
+                                        0x7a, 0xb7, 0xa5, 0x4a };
+
+    begin = esp_timer_get_time();
+    esp_sha(SHA1, buffer, BUFFER_SZ, sha1_result);
+    end = esp_timer_get_time();
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(sha1_expected, sha1_result, sizeof(sha1_expected));
+    us_sha1 = end - begin;
+    ESP_LOGI(TAG, "esp_sha() 32KB SHA1 in %u us", us_sha1);
+
+    free(buffer);
+
+    TEST_PERFORMANCE_CCOMP_LESS_THAN(TIME_SHA1_32KB, "%dus", us_sha1);
+}
+
+TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]")
+{
+    const void* ptr;
+    spi_flash_mmap_handle_t handle;
+    uint8_t sha1_espsha[20] = { 0 };
+    uint8_t sha1_mbedtls[20] = { 0 };
+    uint8_t sha256_espsha[32] = { 0 };
+    uint8_t sha256_mbedtls[32] = { 0 };
+
+    const size_t LEN = 1024 * 1024;
+
+    /* mmap() 1MB of flash, we don't care what it is really */
+    esp_err_t err = spi_flash_mmap(0x0, LEN, SPI_FLASH_MMAP_DATA, &ptr, &handle);
+
+    TEST_ASSERT_EQUAL_HEX32(ESP_OK, err);
+    TEST_ASSERT_NOT_NULL(ptr);
+
+    /* Compare esp_sha() result to the mbedTLS result, should always be the same */
+
+    esp_sha(SHA1, ptr, LEN, sha1_espsha);
+    int r = mbedtls_sha1_ret(ptr, LEN, sha1_mbedtls);
+    TEST_ASSERT_EQUAL(0, r);
+
+    esp_sha(SHA2_256, ptr, LEN, sha256_espsha);
+    r = mbedtls_sha256_ret(ptr, LEN, sha256_mbedtls, 0);
+    TEST_ASSERT_EQUAL(0, r);
+
+    TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_espsha, sha1_mbedtls, sizeof(sha1_espsha), "SHA1 results should match");
+
+    TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_espsha, sha256_mbedtls, sizeof(sha256_espsha), "SHA256 results should match");
+}

+ 5 - 0
components/esp_adc_cal/CMakeLists.txt

@@ -14,4 +14,9 @@ elseif(${target} STREQUAL "esp32c3")
     idf_component_register(SRCS "esp_adc_cal_esp32c3.c"
                     INCLUDE_DIRS "include"
                     REQUIRES driver efuse)
+
+elseif(${target} STREQUAL "esp32h2")
+    idf_component_register(SRCS "esp_adc_cal_esp32h2.c"
+                    INCLUDE_DIRS "include"
+                    REQUIRES driver efuse)
 endif()

+ 1 - 1
components/esp_adc_cal/component.mk

@@ -3,4 +3,4 @@
 #
 
 COMPONENT_ADD_INCLUDEDIRS := include
-COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o
+COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o esp_adc_cal_esp32h2.o

+ 170 - 0
components/esp_adc_cal/esp_adc_cal_esp32h2.c

@@ -0,0 +1,170 @@
+// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "esp_types.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "driver/adc.h"
+#include "hal/adc_ll.h"
+#include "esp_efuse_rtc_calib.h"
+#include "esp_adc_cal.h"
+
+
+#define ADC_CALIB_CHECK(cond, err_msg, ret) do {\
+             if (!(cond)) { \
+                ESP_LOGE(LOG_TAG, err_msg); \
+                return (ret); \
+            } \
+        } while(0)
+
+const static char LOG_TAG[] = "adc_calib";
+
+
+/* ------------------------ Characterization Constants ---------------------- */
+
+// coeff_a and coeff_b are actually floats
+// they are scaled to put them into uint32_t so that the headers do not have to be changed
+static const int coeff_a_scaling = 65536;
+static const int coeff_b_scaling = 1024;
+/* -------------------- Characterization Helper Data Types ------------------ */
+typedef struct {
+    uint32_t voltage;
+    uint32_t digi;
+} adc_calib_data_ver1;
+
+typedef struct {
+    char version_num;
+    adc_unit_t adc_num;
+    adc_atten_t atten_level;
+    union {
+        adc_calib_data_ver1 ver1;
+    } efuse_data;
+} adc_calib_parsed_info;
+
+static esp_err_t prepare_calib_data_for(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_parsed_info *parsed_data_storage)
+{
+    assert(version_num == 1);
+    esp_err_t ret;
+
+    parsed_data_storage->version_num = version_num;
+    parsed_data_storage->adc_num = adc_num;
+    parsed_data_storage->atten_level = atten;
+    // V1 we don't have calibration data for ADC2, using the efuse data of ADC1
+    uint32_t voltage, digi;
+    ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, atten, &digi, &voltage);
+    if (ret != ESP_OK) {
+        return ret;
+    }
+    parsed_data_storage->efuse_data.ver1.voltage = voltage;
+    parsed_data_storage->efuse_data.ver1.digi = digi;
+    return ret;
+}
+
+/* ----------------------- Characterization Functions ----------------------- */
+/*
+ * Estimate the (assumed) linear relationship btwn the measured raw value and the voltage
+ * with the previously done measurement when the chip was manufactured.
+ */
+static void calculate_characterization_coefficients(const adc_calib_parsed_info *parsed_data, esp_adc_cal_characteristics_t *chars)
+{
+    ESP_LOGD(LOG_TAG, "Calib V1, Cal Voltage = %d, Digi out = %d\n", parsed_data->efuse_data.ver1.voltage, parsed_data->efuse_data.ver1.digi);
+
+    chars->coeff_a = coeff_a_scaling * parsed_data->efuse_data.ver1.voltage / parsed_data->efuse_data.ver1.digi;
+    chars->coeff_b = 0;
+}
+
+/* ------------------------- Public API ------------------------------------- */
+esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
+{
+    if (source != ESP_ADC_CAL_VAL_EFUSE_TP) {
+        return ESP_ERR_NOT_SUPPORTED;
+    }
+    uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
+    if (adc_encoding_version != 1) {
+        // current version only accepts encoding ver 1.
+        return ESP_ERR_INVALID_VERSION;
+    }
+    return ESP_OK;
+}
+
+esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
+        adc_atten_t atten,
+        adc_bits_width_t bit_width,
+        uint32_t default_vref,
+        esp_adc_cal_characteristics_t *chars)
+{
+    esp_err_t ret;
+    adc_calib_parsed_info efuse_parsed_data = {0};
+    // Check parameters
+    ADC_CALIB_CHECK(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, "Invalid unit num", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
+    ADC_CALIB_CHECK(chars != NULL, "Invalid characteristic", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
+    ADC_CALIB_CHECK(bit_width == ADC_WIDTH_BIT_12, "Invalid bit_width", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
+    ADC_CALIB_CHECK(atten < 4, "Invalid attenuation", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
+
+    int version_num = esp_efuse_rtc_calib_get_ver();
+    ADC_CALIB_CHECK(version_num == 1, "No calibration efuse burnt", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
+
+    memset(chars, 0, sizeof(esp_adc_cal_characteristics_t));
+
+    // make sure adc is calibrated.
+    ret = prepare_calib_data_for(version_num, adc_num, atten, &efuse_parsed_data);
+    if (ret != ESP_OK) {
+        abort();
+    }
+
+    calculate_characterization_coefficients(&efuse_parsed_data, chars);
+    ESP_LOGD(LOG_TAG, "adc%d (atten leven %d) calibration done: A:%d B:%d\n", adc_num, atten, chars->coeff_a, chars->coeff_b);
+
+    // Initialize remaining fields
+    chars->adc_num = adc_num;
+    chars->atten = atten;
+    chars->bit_width = bit_width;
+
+    // in esp32h2 we only use the two point method to calibrate the adc.
+    return ESP_ADC_CAL_VAL_EFUSE_TP;
+}
+
+uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
+{
+    ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG);
+
+    return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling;
+}
+
+esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
+                                  const esp_adc_cal_characteristics_t *chars,
+                                  uint32_t *voltage)
+{
+    // Check parameters
+    ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG);
+    ADC_CALIB_CHECK(voltage != NULL, "No output buffer.", ESP_ERR_INVALID_ARG);
+
+    int adc_reading;
+    if (chars->adc_num == ADC_UNIT_1) {
+        //Check if channel is valid on ADC1
+        ADC_CALIB_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG);
+        adc_reading = adc1_get_raw(channel);
+    } else {
+        //Check if channel is valid on ADC2
+        ADC_CALIB_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG);
+        if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) {
+            return ESP_ERR_TIMEOUT;     //Timed out waiting for ADC2
+        }
+    }
+    *voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
+    return ESP_OK;
+}

+ 7 - 1
components/esp_event/event_send.c

@@ -28,6 +28,7 @@ esp_err_t esp_event_send_noop(system_event_t *event)
     return ESP_OK;
 }
 
+#if CONFIG_ESP32_WIFI_ENABLED
 static system_event_id_t esp_event_legacy_wifi_event_id(int32_t event_id)
 {
     switch (event_id) {
@@ -102,6 +103,7 @@ static system_event_id_t esp_event_legacy_wifi_event_id(int32_t event_id)
         return SYSTEM_EVENT_MAX;
     }
 }
+#endif // CONFIG_ESP32_WIFI_ENABLED
 
 static system_event_id_t esp_event_legacy_ip_event_id(int32_t event_id)
 {
@@ -133,9 +135,13 @@ static system_event_id_t esp_event_legacy_ip_event_id(int32_t event_id)
 
 static system_event_id_t esp_event_legacy_event_id(esp_event_base_t event_base, int32_t event_id)
 {
+#if CONFIG_ESP32_WIFI_ENABLED
     if (event_base == WIFI_EVENT) {
         return esp_event_legacy_wifi_event_id(event_id);
-    } else if (event_base == IP_EVENT) {
+    }
+#endif
+
+	if (event_base == IP_EVENT) {
         return esp_event_legacy_ip_event_id(event_id);
     } else {
         ESP_LOGE(TAG, "invalid event base %s", event_base);

+ 124 - 0
components/esp_gdbstub/esp32h2/gdbstub_esp32h2.c

@@ -0,0 +1,124 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "soc/uart_periph.h"
+#include "soc/gpio_periph.h"
+#include "soc/soc.h"
+#include "soc/usb_serial_jtag_struct.h"
+#include "hal/usb_serial_jtag_ll.h"
+#include "esp_gdbstub_common.h"
+#include "sdkconfig.h"
+
+#define UART_NUM CONFIG_ESP_CONSOLE_UART_NUM
+
+#define GDBSTUB_MEM_REGION_COUNT 9
+
+#define UART_REG_FIELD_LEN 0x84
+
+typedef struct {
+    intptr_t lower;
+    intptr_t upper;
+} mem_bound_t;
+
+static const mem_bound_t mem_region_table [GDBSTUB_MEM_REGION_COUNT] =
+{
+    {SOC_DROM_LOW, SOC_DROM_HIGH},
+    {SOC_IROM_LOW, SOC_IROM_HIGH},
+    {SOC_IRAM_LOW, SOC_IRAM_HIGH},
+    {SOC_DRAM_LOW, SOC_DRAM_HIGH},
+    {SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH},
+    {SOC_DROM_MASK_LOW, SOC_DROM_MASK_HIGH},
+    {SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH},
+    // RTC DRAM and RTC DATA are identical with RTC IRAM, hence we skip them
+    // We shouldn't read the uart registers since it will disturb the debugging via UART,
+    // so skip UART part of the peripheral registers.
+    {DR_REG_UART_BASE + UART_REG_FIELD_LEN, SOC_PERIPHERAL_HIGH},
+    {SOC_DEBUG_LOW, SOC_DEBUG_HIGH},
+};
+
+static inline bool check_inside_valid_region(intptr_t addr)
+{
+    for (size_t i = 0; i < GDBSTUB_MEM_REGION_COUNT; i++) {
+        if (addr >= mem_region_table[i].lower && addr < mem_region_table[i].upper) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void esp_gdbstub_target_init()
+{
+}
+
+#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
+
+int esp_gdbstub_getchar()
+{
+    uint8_t c;
+    //retry the read until we succeed
+    while (usb_serial_jtag_ll_read_rxfifo(&c, 1)==0) ;
+    return c;
+}
+
+void esp_gdbstub_putchar(int c)
+{
+    uint8_t cc=c;
+    //retry the write until we succeed
+    while (usb_serial_jtag_ll_write_txfifo(&cc, 1)<1) ;
+}
+
+void esp_gdbstub_flush()
+{
+    usb_serial_jtag_ll_txfifo_flush();
+}
+
+
+#else
+
+//assume UART gdbstub channel
+
+int esp_gdbstub_getchar()
+{
+    while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_RXFIFO_CNT) == 0) {
+        ;
+    }
+    return REG_READ(UART_FIFO_AHB_REG(UART_NUM));
+}
+
+void esp_gdbstub_putchar(int c)
+{
+    while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_TXFIFO_CNT) >= 126) {
+        ;
+    }
+    REG_WRITE(UART_FIFO_AHB_REG(UART_NUM), c);
+}
+
+void esp_gdbstub_flush()
+{
+    //not needed for uart
+}
+
+#endif
+
+int esp_gdbstub_readmem(intptr_t addr)
+{
+    if (!check_inside_valid_region(addr)) {
+        /* see esp_cpu_configure_region_protection */
+        return -1;
+    }
+    uint32_t val_aligned = *(uint32_t *)(addr & (~3));
+    uint32_t shift = (addr & 3) * 8;
+    return (val_aligned >> shift) & 0xff;
+}

+ 15 - 0
components/esp_gdbstub/esp32h2/gdbstub_target_config.h

@@ -0,0 +1,15 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once

+ 2 - 1
components/esp_hw_support/cpu_util.c

@@ -81,7 +81,8 @@ bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
 #if CONFIG_ESP32_DEBUG_OCDAWARE || \
     CONFIG_ESP32S2_DEBUG_OCDAWARE || \
     CONFIG_ESP32S3_DEBUG_OCDAWARE || \
-    CONFIG_ESP32C3_DEBUG_OCDAWARE
+    CONFIG_ESP32C3_DEBUG_OCDAWARE || \
+    CONFIG_ESP32H2_DEBUG_OCDAWARE
     return cpu_ll_is_debugger_attached();
 #else
     return false; // Always return false if "OCD aware" is disabled

+ 6 - 2
components/esp_hw_support/esp_clk.c

@@ -36,6 +36,10 @@
 #include "esp32c3/rom/rtc.h"
 #include "esp32c3/clk.h"
 #include "esp32c3/rtc.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/rtc.h"
+#include "esp32h2/clk.h"
+#include "esp32h2/rtc.h"
 #endif
 
 #define MHZ (1000000)
@@ -53,7 +57,7 @@ static RTC_DATA_ATTR uint64_t s_esp_rtc_time_us = 0, s_rtc_last_ticks = 0;
 
 inline static int IRAM_ATTR s_get_cpu_freq_mhz(void)
 {
-#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
     return ets_get_cpu_frequency();
 #else
     return g_ticks_per_us_pro;
@@ -75,7 +79,7 @@ int IRAM_ATTR esp_clk_xtal_freq(void)
     return rtc_clk_xtal_freq_get() * MHZ;
 }
 
-#ifndef CONFIG_IDF_TARGET_ESP32C3
+#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
 void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
 {
     /* Update scale factors used by esp_rom_delay_us */

+ 2 - 0
components/esp_hw_support/hw_random.c

@@ -29,6 +29,8 @@
 #include "esp32s3/clk.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/clk.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/clk.h"
 #endif
 
 uint32_t IRAM_ATTR esp_random(void)

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

@@ -32,6 +32,7 @@ typedef enum {
     CHIP_ESP32S2 = 2, //!< ESP32-S2
     CHIP_ESP32S3 = 4, //!< ESP32-S3
     CHIP_ESP32C3 = 5, //!< ESP32-C3
+    CHIP_ESP32H2 = 6, //!< ESP32-H2
 } esp_chip_model_t;
 
 /* Chip feature flags, used in esp_chip_info_t */
@@ -39,6 +40,7 @@ typedef enum {
 #define CHIP_FEATURE_WIFI_BGN       BIT(1)      //!< Chip has 2.4GHz WiFi
 #define CHIP_FEATURE_BLE            BIT(4)      //!< Chip has Bluetooth LE
 #define CHIP_FEATURE_BT             BIT(5)      //!< Chip has Bluetooth Classic
+#define CHIP_FEATURE_IEEE802154     BIT(6)      //!< Chip has IEEE 802.15.4
 
 /**
  * @brief The structure represents information about the chip

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

@@ -26,6 +26,7 @@ typedef enum {
     ESP_MAC_WIFI_SOFTAP,
     ESP_MAC_BT,
     ESP_MAC_ETH,
+    ESP_MAC_IEEE802154,
 } esp_mac_type_t;
 
 /** @cond */
@@ -39,6 +40,8 @@ typedef enum {
 #define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES
 #elif CONFIG_IDF_TARGET_ESP32C3
 #define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES
+#elif CONFIG_IDF_TARGET_ESP32H2
+#define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32H2_UNIVERSAL_MAC_ADDRESSES
 #endif
 /** @endcond */
 

+ 16 - 0
components/esp_hw_support/include/soc/esp32h2/clk.h

@@ -0,0 +1,16 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+#include "esp_private/esp_clk.h"

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

@@ -41,6 +41,8 @@
 #include "esp32s3/rom/ets_sys.h"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #include "esp32c3/rom/ets_sys.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/ets_sys.h"
 #endif
 
 #define SOC_LOGE(tag, fmt, ...) esp_rom_printf("%s(err): " fmt, tag, ##__VA_ARGS__)

+ 1 - 1
components/esp_hw_support/linker.lf

@@ -9,5 +9,5 @@ entries:
     rtc_pm (noflash_text)
     rtc_sleep (noflash_text)
     rtc_time (noflash_text)
-    if IDF_TARGET_ESP32C3 = n:
+    if IDF_TARGET_ESP32C3 = n && IDF_TARGET_ESP32H2 = n:
         rtc_wdt (noflash_text)

+ 24 - 0
components/esp_hw_support/port/esp32h2/CMakeLists.txt

@@ -0,0 +1,24 @@
+set(srcs "cpu_util_esp32h2.c"
+         "rtc_clk_init.c"
+         "rtc_clk.c"
+         "rtc_init.c"
+         "rtc_pm.c"
+         "rtc_sleep.c"
+         "rtc_time.c"
+         "chip_info.c"
+         )
+
+if(NOT BOOTLOADER_BUILD)
+    list(APPEND srcs "../async_memcpy_impl_gdma.c")
+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)
+
+if(NOT CMAKE_BUILD_EARLY_EXPANSION)
+    set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/rtc_clk.c" PROPERTIES
+                                COMPILE_FLAGS "-fno-jump-tables -fno-tree-switch-conversion")
+endif()

+ 18 - 0
components/esp_hw_support/port/esp32h2/Kconfig.mac

@@ -0,0 +1,18 @@
+# ESP32H2-TODO: IDF-3390
+choice ESP32H2_UNIVERSAL_MAC_ADDRESSES
+    bool "Number of universally administered (by IEEE) MAC address"
+    default ESP32H2_UNIVERSAL_MAC_ADDRESSES_TWO
+    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.
+
+    config ESP32H2_UNIVERSAL_MAC_ADDRESSES_TWO
+        bool "Two"
+        select ESP_MAC_ADDR_UNIVERSE_IEEE802154
+        select ESP_MAC_ADDR_UNIVERSE_BT
+endchoice
+
+config ESP32H2_UNIVERSAL_MAC_ADDRESSES
+    int
+    default 2 if ESP32H2_UNIVERSAL_MAC_ADDRESSES_TWO

+ 26 - 0
components/esp_hw_support/port/esp32h2/chip_info.c

@@ -0,0 +1,26 @@
+// Copyright 2013-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string.h>
+#include "esp_chip_info.h"
+#include "esp_efuse.h"
+
+void esp_chip_info(esp_chip_info_t *out_info)
+{
+    memset(out_info, 0, sizeof(*out_info));
+    out_info->model = CHIP_ESP32H2;
+    out_info->revision = esp_efuse_get_chip_ver();
+    out_info->cores = 1;
+    out_info->features = CHIP_FEATURE_IEEE802154 | CHIP_FEATURE_BLE;
+}

+ 112 - 0
components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.c

@@ -0,0 +1,112 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <assert.h>
+#include "soc/cpu.h"
+
+void esp_cpu_configure_region_protection(void)
+{
+    /* Notes on implementation:
+     *
+     * 1) Note: ESP32-C3 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 R       = PMP_L | PMP_TOR | PMP_R;
+    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 & DROM (flash cache)
+    PMP_ENTRY_SET(2, SOC_DROM_LOW, NONE);
+    _Static_assert(SOC_DEBUG_HIGH < SOC_DROM_LOW, "Invalid PMP entry order");
+
+    // 4. DROM (flash cache)
+    // 5. Gap between DROM & DRAM
+    // (Note: To save PMP entries these two are merged into one read-only region)
+    PMP_ENTRY_SET(3, SOC_DRAM_LOW, R);
+    _Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid DROM region");
+    _Static_assert(SOC_DROM_HIGH < SOC_DRAM_LOW, "Invalid PMP entry order");
+
+    // 6. DRAM
+    PMP_ENTRY_SET(4, SOC_DRAM_HIGH, RW);
+    _Static_assert(SOC_DRAM_LOW < SOC_DRAM_HIGH, "Invalid DRAM region");
+
+    // 7. Gap between DRAM and Mask DROM
+    // 8. Mask DROM
+    // (Note: to save PMP entries these two are merged into one read-only region)
+    PMP_ENTRY_SET(5, SOC_DROM_MASK_HIGH, R);
+    _Static_assert(SOC_DRAM_HIGH < SOC_DROM_MASK_LOW, "Invalid PMP entry order");
+    _Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid mask DROM region");
+
+    // 9. Gap between mask DROM and mask IROM
+    // 10. Mask IROM
+    // (Note: to save PMP entries these two are merged into one RX region)
+    PMP_ENTRY_SET(6, SOC_IROM_MASK_HIGH, RX);
+    _Static_assert(SOC_DROM_MASK_HIGH < SOC_IROM_MASK_LOW, "Invalid PMP entry order");
+    _Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid mask IROM region");
+
+    // 11. Gap between mask IROM & IRAM
+    PMP_ENTRY_SET(7, SOC_IRAM_LOW, NONE);
+    _Static_assert(SOC_IROM_MASK_HIGH < SOC_IRAM_LOW, "Invalid PMP entry order");
+
+    // 12. IRAM
+    PMP_ENTRY_SET(8, SOC_IRAM_HIGH, RWX);
+    _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid IRAM region");
+
+    // 13. Gap between IRAM and IROM
+    // 14. IROM (flash cache)
+    // (Note: to save PMP entries these two are merged into one RX region)
+    PMP_ENTRY_SET(9, SOC_IROM_HIGH, RX);
+    _Static_assert(SOC_IRAM_HIGH < SOC_IROM_LOW, "Invalid PMP entry order");
+    _Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid IROM region");
+
+    // 15. Gap between IROM & RTC slow memory
+    PMP_ENTRY_SET(10, SOC_RTC_IRAM_LOW, NONE);
+    _Static_assert(SOC_IROM_HIGH < SOC_RTC_IRAM_LOW, "Invalid PMP entry order");
+
+    // 16. RTC fast memory
+    PMP_ENTRY_SET(11, SOC_RTC_IRAM_HIGH, RWX);
+    _Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
+
+    // 17. Gap between RTC fast memory & peripheral addresses
+    PMP_ENTRY_SET(12, SOC_PERIPHERAL_LOW, NONE);
+    _Static_assert(SOC_RTC_IRAM_HIGH < SOC_PERIPHERAL_LOW, "Invalid PMP entry order");
+
+    // 18. Peripheral addresses
+    PMP_ENTRY_SET(13, SOC_PERIPHERAL_HIGH, RW);
+    _Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
+
+    // 19. End of address space
+    PMP_ENTRY_SET(14, UINT32_MAX, NONE); // all but last 4 bytes
+    PMP_ENTRY_SET(15, UINT32_MAX, PMP_L | PMP_NA4);  // last 4 bytes
+}

+ 30 - 0
components/esp_hw_support/port/esp32h2/i2c_brownout.h

@@ -0,0 +1,30 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/**
+ * @file i2c_brownout.h
+ * @brief Register definitions for brownout detector
+ *
+ * This file lists register fields of the brownout detector, located on an internal configuration
+ * bus. These definitions are used via macros defined in i2c_rtc_clk.h.
+ */
+
+#define I2C_BOD            0x61
+#define I2C_BOD_HOSTID     1
+
+#define I2C_BOD_THRESHOLD           0x5
+#define I2C_BOD_THRESHOLD_MSB       2
+#define I2C_BOD_THRESHOLD_LSB       0

+ 48 - 0
components/esp_hw_support/port/esp32h2/i2c_rtc_clk.h

@@ -0,0 +1,48 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdint.h>
+#include "regi2c_ctrl.h"
+
+/* Analog function control register */
+#define ANA_CONFIG_REG  0x6000E044
+#define ANA_CONFIG_S    (8)
+#define ANA_CONFIG_M    (0x3FF)
+/* Clear to enable APLL */
+#define I2C_APLL_M      (BIT(14))
+/* Clear to enable BBPLL */
+#define I2C_BBPLL_M     (BIT(17))
+
+/* ROM functions which read/write internal control bus */
+uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
+uint8_t rom_i2c_readReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
+void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
+void rom_i2c_writeReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
+
+/* Convenience macros for the above functions, these use register definitions
+ * from i2c_apll.h/i2c_bbpll.h header files.
+ */
+#define I2C_WRITEREG_MASK_RTC(block, reg_add, indata) \
+      rom_i2c_writeReg_Mask(block, block##_HOSTID,  reg_add,  reg_add##_MSB,  reg_add##_LSB,  indata)
+
+#define I2C_READREG_MASK_RTC(block, reg_add) \
+      rom_i2c_readReg_Mask(block, block##_HOSTID,  reg_add,  reg_add##_MSB,  reg_add##_LSB)
+
+#define I2C_WRITEREG_RTC(block, reg_add, indata) \
+      rom_i2c_writeReg(block, block##_HOSTID,  reg_add, indata)
+
+#define I2C_READREG_RTC(block, reg_add) \
+      rom_i2c_readReg(block, block##_HOSTID,  reg_add)

+ 183 - 0
components/esp_hw_support/port/esp32h2/private_include/regi2c_bbpll.h

@@ -0,0 +1,183 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/**
+ * @file regi2c_bbpll.h
+ * @brief Register definitions for digital PLL (BBPLL)
+ *
+ * This file lists register fields of BBPLL, located on an internal configuration
+ * bus. These definitions are used via macros defined in regi2c_ctrl.h, by
+ * rtc_clk_cpu_freq_set function in rtc_clk.c.
+ */
+
+#define I2C_BBPLL           0x66
+#define I2C_BBPLL_HOSTID    0
+
+#define I2C_BBPLL_IR_CAL_DELAY        0
+#define I2C_BBPLL_IR_CAL_DELAY_MSB    3
+#define I2C_BBPLL_IR_CAL_DELAY_LSB    0
+
+#define I2C_BBPLL_IR_CAL_CK_DIV        0
+#define I2C_BBPLL_IR_CAL_CK_DIV_MSB    7
+#define I2C_BBPLL_IR_CAL_CK_DIV_LSB    4
+
+#define I2C_BBPLL_IR_CAL_EXT_CAP        1
+#define I2C_BBPLL_IR_CAL_EXT_CAP_MSB    3
+#define I2C_BBPLL_IR_CAL_EXT_CAP_LSB    0
+
+#define I2C_BBPLL_IR_CAL_ENX_CAP        1
+#define I2C_BBPLL_IR_CAL_ENX_CAP_MSB    4
+#define I2C_BBPLL_IR_CAL_ENX_CAP_LSB    4
+
+#define I2C_BBPLL_IR_CAL_RSTB        1
+#define I2C_BBPLL_IR_CAL_RSTB_MSB    5
+#define I2C_BBPLL_IR_CAL_RSTB_LSB    5
+
+#define I2C_BBPLL_IR_CAL_START        1
+#define I2C_BBPLL_IR_CAL_START_MSB    6
+#define I2C_BBPLL_IR_CAL_START_LSB    6
+
+#define I2C_BBPLL_IR_CAL_UNSTOP        1
+#define I2C_BBPLL_IR_CAL_UNSTOP_MSB    7
+#define I2C_BBPLL_IR_CAL_UNSTOP_LSB    7
+
+#define I2C_BBPLL_OC_REF_DIV        2
+#define I2C_BBPLL_OC_REF_DIV_MSB    3
+#define I2C_BBPLL_OC_REF_DIV_LSB    0
+
+#define I2C_BBPLL_OC_DCHGP        2
+#define I2C_BBPLL_OC_DCHGP_MSB    6
+#define I2C_BBPLL_OC_DCHGP_LSB    4
+
+#define I2C_BBPLL_OC_ENB_FCAL        2
+#define I2C_BBPLL_OC_ENB_FCAL_MSB    7
+#define I2C_BBPLL_OC_ENB_FCAL_LSB    7
+
+#define I2C_BBPLL_OC_DIV_7_0        3
+#define I2C_BBPLL_OC_DIV_7_0_MSB    7
+#define I2C_BBPLL_OC_DIV_7_0_LSB    0
+
+#define I2C_BBPLL_RSTB_DIV_ADC        4
+#define I2C_BBPLL_RSTB_DIV_ADC_MSB    0
+#define I2C_BBPLL_RSTB_DIV_ADC_LSB    0
+
+#define I2C_BBPLL_MODE_HF        4
+#define I2C_BBPLL_MODE_HF_MSB    1
+#define I2C_BBPLL_MODE_HF_LSB    1
+
+#define I2C_BBPLL_DIV_ADC        4
+#define I2C_BBPLL_DIV_ADC_MSB    3
+#define I2C_BBPLL_DIV_ADC_LSB    2
+
+#define I2C_BBPLL_DIV_DAC        4
+#define I2C_BBPLL_DIV_DAC_MSB    4
+#define I2C_BBPLL_DIV_DAC_LSB    4
+
+#define I2C_BBPLL_DIV_CPU        4
+#define I2C_BBPLL_DIV_CPU_MSB    5
+#define I2C_BBPLL_DIV_CPU_LSB    5
+
+#define I2C_BBPLL_OC_ENB_VCON        4
+#define I2C_BBPLL_OC_ENB_VCON_MSB    6
+#define I2C_BBPLL_OC_ENB_VCON_LSB    6
+
+#define I2C_BBPLL_OC_TSCHGP        4
+#define I2C_BBPLL_OC_TSCHGP_MSB    7
+#define I2C_BBPLL_OC_TSCHGP_LSB    7
+
+#define I2C_BBPLL_OC_DR1        5
+#define I2C_BBPLL_OC_DR1_MSB    2
+#define I2C_BBPLL_OC_DR1_LSB    0
+
+#define I2C_BBPLL_OC_DR3        5
+#define I2C_BBPLL_OC_DR3_MSB    6
+#define I2C_BBPLL_OC_DR3_LSB    4
+
+#define I2C_BBPLL_EN_USB        5
+#define I2C_BBPLL_EN_USB_MSB    7
+#define I2C_BBPLL_EN_USB_LSB    7
+
+#define I2C_BBPLL_OC_DCUR        6
+#define I2C_BBPLL_OC_DCUR_MSB    2
+#define I2C_BBPLL_OC_DCUR_LSB    0
+
+#define I2C_BBPLL_INC_CUR        6
+#define I2C_BBPLL_INC_CUR_MSB    3
+#define I2C_BBPLL_INC_CUR_LSB    3
+
+#define I2C_BBPLL_OC_DHREF_SEL        6
+#define I2C_BBPLL_OC_DHREF_SEL_MSB    5
+#define I2C_BBPLL_OC_DHREF_SEL_LSB    4
+
+#define I2C_BBPLL_OC_DLREF_SEL        6
+#define I2C_BBPLL_OC_DLREF_SEL_MSB    7
+#define I2C_BBPLL_OC_DLREF_SEL_LSB    6
+
+#define I2C_BBPLL_OR_CAL_CAP        8
+#define I2C_BBPLL_OR_CAL_CAP_MSB    3
+#define I2C_BBPLL_OR_CAL_CAP_LSB    0
+
+#define I2C_BBPLL_OR_CAL_UDF        8
+#define I2C_BBPLL_OR_CAL_UDF_MSB    4
+#define I2C_BBPLL_OR_CAL_UDF_LSB    4
+
+#define I2C_BBPLL_OR_CAL_OVF        8
+#define I2C_BBPLL_OR_CAL_OVF_MSB    5
+#define I2C_BBPLL_OR_CAL_OVF_LSB    5
+
+#define I2C_BBPLL_OR_CAL_END        8
+#define I2C_BBPLL_OR_CAL_END_MSB    6
+#define I2C_BBPLL_OR_CAL_END_LSB    6
+
+#define I2C_BBPLL_OR_LOCK        8
+#define I2C_BBPLL_OR_LOCK_MSB    7
+#define I2C_BBPLL_OR_LOCK_LSB    7
+
+#define I2C_BBPLL_OC_VCO_DBIAS        9
+#define I2C_BBPLL_OC_VCO_DBIAS_MSB    1
+#define I2C_BBPLL_OC_VCO_DBIAS_LSB    0
+
+#define I2C_BBPLL_BBADC_DELAY2        9
+#define I2C_BBPLL_BBADC_DELAY2_MSB    3
+#define I2C_BBPLL_BBADC_DELAY2_LSB    2
+
+#define I2C_BBPLL_BBADC_DVDD        9
+#define I2C_BBPLL_BBADC_DVDD_MSB    5
+#define I2C_BBPLL_BBADC_DVDD_LSB    4
+
+#define I2C_BBPLL_BBADC_DREF        9
+#define I2C_BBPLL_BBADC_DREF_MSB    7
+#define I2C_BBPLL_BBADC_DREF_LSB    6
+
+#define I2C_BBPLL_BBADC_DCUR        10
+#define I2C_BBPLL_BBADC_DCUR_MSB    1
+#define I2C_BBPLL_BBADC_DCUR_LSB    0
+
+#define I2C_BBPLL_BBADC_INPUT_SHORT        10
+#define I2C_BBPLL_BBADC_INPUT_SHORT_MSB    2
+#define I2C_BBPLL_BBADC_INPUT_SHORT_LSB    2
+
+#define I2C_BBPLL_ENT_PLL        10
+#define I2C_BBPLL_ENT_PLL_MSB    3
+#define I2C_BBPLL_ENT_PLL_LSB    3
+
+#define I2C_BBPLL_DTEST        10
+#define I2C_BBPLL_DTEST_MSB    5
+#define I2C_BBPLL_DTEST_LSB    4
+
+#define I2C_BBPLL_ENT_ADC        10
+#define I2C_BBPLL_ENT_ADC_MSB    7
+#define I2C_BBPLL_ENT_ADC_LSB    6

+ 30 - 0
components/esp_hw_support/port/esp32h2/private_include/regi2c_bias.h

@@ -0,0 +1,30 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/**
+ * @file regi2c_bias.h
+ * @brief Register definitions for bias
+ *
+ * This file lists register fields of BIAS. These definitions are used via macros defined in regi2c_ctrl.h, by
+ * bootloader_hardware_init function in bootloader_esp32c3.c.
+ */
+
+#define I2C_BIAS            0X6A
+#define I2C_BIAS_HOSTID     0
+
+#define I2C_BIAS_DREG_1P1_PVT 1
+#define I2C_BIAS_DREG_1P1_PVT_MSB 3
+#define I2C_BIAS_DREG_1P1_PVT_LSB 0

+ 30 - 0
components/esp_hw_support/port/esp32h2/private_include/regi2c_brownout.h

@@ -0,0 +1,30 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/**
+ * @file regi2c_brownout.h
+ * @brief Register definitions for brownout detector
+ *
+ * This file lists register fields of the brownout detector, located on an internal configuration
+ * bus. These definitions are used via macros defined in regi2c_ctrl.h.
+ */
+
+#define I2C_BOD            0x61
+#define I2C_BOD_HOSTID     0
+
+#define I2C_BOD_THRESHOLD           0x5
+#define I2C_BOD_THRESHOLD_MSB       2
+#define I2C_BOD_THRESHOLD_LSB       0

+ 68 - 0
components/esp_hw_support/port/esp32h2/private_include/regi2c_dig_reg.h

@@ -0,0 +1,68 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/**
+ * @file regi2c_dig_reg.h
+ * @brief Register definitions for digital to get rtc voltage & digital voltage
+ *        by setting rtc_dbias_Wak & dig_dbias_wak or by analog self-calibration.
+ */
+
+#define I2C_DIG_REG 0x6D
+#define I2C_DIG_REG_HOSTID 0
+
+#define I2C_DIG_REG_EXT_RTC_DREG    4
+#define I2C_DIG_REG_EXT_RTC_DREG_MSB    4
+#define I2C_DIG_REG_EXT_RTC_DREG_LSB    0
+
+#define I2C_DIG_REG_ENX_RTC_DREG    4
+#define I2C_DIG_REG_ENX_RTC_DREG_MSB    7
+#define I2C_DIG_REG_ENX_RTC_DREG_LSB    7
+
+#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP    5
+#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_MSB    4
+#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_LSB    0
+
+#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP    5
+#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_MSB    7
+#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_LSB    7
+
+#define I2C_DIG_REG_EXT_DIG_DREG    6
+#define I2C_DIG_REG_EXT_DIG_DREG_MSB    4
+#define I2C_DIG_REG_EXT_DIG_DREG_LSB    0
+
+#define I2C_DIG_REG_ENX_DIG_DREG    6
+#define I2C_DIG_REG_ENX_DIG_DREG_MSB    7
+#define I2C_DIG_REG_ENX_DIG_DREG_LSB    7
+
+#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP    7
+#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_MSB    4
+#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_LSB    0
+
+#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP    7
+#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP_MSB    7
+#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP_LSB    7
+
+#define I2C_DIG_REG_OR_EN_CONT_CAL 9
+#define I2C_DIG_REG_OR_EN_CONT_CAL_MSB 7
+#define I2C_DIG_REG_OR_EN_CONT_CAL_LSB 7
+
+#define I2C_DIG_REG_XPD_RTC_REG 13
+#define I2C_DIG_REG_XPD_RTC_REG_MSB 2
+#define I2C_DIG_REG_XPD_RTC_REG_LSB 2
+
+#define I2C_DIG_REG_XPD_DIG_REG 13
+#define I2C_DIG_REG_XPD_DIG_REG_MSB 3
+#define I2C_DIG_REG_XPD_DIG_REG_LSB 3

+ 63 - 0
components/esp_hw_support/port/esp32h2/private_include/regi2c_lp_bias.h

@@ -0,0 +1,63 @@
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/**
+ * @file regi2c_lp_bias.h
+ * @brief Register definitions for analog to calibrate o_code for getting a more precise voltage.
+ *
+ * This file lists register fields of low power dbais, located on an internal configuration
+ * bus. These definitions are used via macros defined in regi2c_ctrl.h, by
+ * rtc_init function in rtc_init.c.
+ */
+
+#define I2C_ULP 0x61
+#define I2C_ULP_HOSTID 0
+
+#define I2C_ULP_IR_RESETB 0
+#define I2C_ULP_IR_RESETB_MSB 0
+#define I2C_ULP_IR_RESETB_LSB 0
+
+#define I2C_ULP_IR_FORCE_XPD_CK 0
+#define I2C_ULP_IR_FORCE_XPD_CK_MSB 2
+#define I2C_ULP_IR_FORCE_XPD_CK_LSB 2
+
+#define I2C_ULP_IR_FORCE_XPD_IPH 0
+#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 4
+#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 4
+
+#define I2C_ULP_IR_DISABLE_WATCHDOG_CK 0
+#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_MSB 6
+#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_LSB 6
+
+#define I2C_ULP_O_DONE_FLAG 3
+#define I2C_ULP_O_DONE_FLAG_MSB 0
+#define I2C_ULP_O_DONE_FLAG_LSB 0
+
+#define I2C_ULP_BG_O_DONE_FLAG 3
+#define I2C_ULP_BG_O_DONE_FLAG_MSB 3
+#define I2C_ULP_BG_O_DONE_FLAG_LSB 3
+
+#define I2C_ULP_OCODE 4
+#define I2C_ULP_OCODE_MSB 7
+#define I2C_ULP_OCODE_LSB 0
+
+#define I2C_ULP_IR_FORCE_CODE 5
+#define I2C_ULP_IR_FORCE_CODE_MSB 6
+#define I2C_ULP_IR_FORCE_CODE_LSB 6
+
+#define I2C_ULP_EXT_CODE 6
+#define I2C_ULP_EXT_CODE_MSB 7
+#define I2C_ULP_EXT_CODE_LSB 0

+ 87 - 0
components/esp_hw_support/port/esp32h2/private_include/regi2c_saradc.h

@@ -0,0 +1,87 @@
+// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+/**
+ * @file regi2c_saradc.h
+ * @brief Register definitions for analog to calibrate initial code for getting a more precise voltage of SAR ADC.
+ *
+ * This file lists register fields of SAR, located on an internal configuration
+ * bus. These definitions are used via macros defined in regi2c_ctrl.h, by
+ * function in adc_ll.h.
+ */
+
+#define I2C_SAR_ADC            0X69
+#define I2C_SAR_ADC_HOSTID     0
+
+#define ADC_SAR1_ENCAL_GND_ADDR 0x7
+#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5
+#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5
+
+#define ADC_SAR2_ENCAL_GND_ADDR 0x7
+#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7
+#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7
+
+#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR 0x1
+#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3
+#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0
+
+#define ADC_SAR1_INITIAL_CODE_LOW_ADDR  0x0
+#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB  0x7
+#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB  0x0
+
+#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4
+#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3
+#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0
+
+#define ADC_SAR2_INITIAL_CODE_LOW_ADDR  0x3
+#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB  0x7
+#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB  0x0
+
+#define ADC_SAR1_DREF_ADDR  0x2
+#define ADC_SAR1_DREF_ADDR_MSB  0x6
+#define ADC_SAR1_DREF_ADDR_LSB  0x4
+
+#define ADC_SAR2_DREF_ADDR  0x5
+#define ADC_SAR2_DREF_ADDR_MSB  0x6
+#define ADC_SAR2_DREF_ADDR_LSB  0x4
+
+#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2
+#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
+#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0
+
+#define ADC_SARADC_DTEST_RTC_ADDR 0x7
+#define ADC_SARADC_DTEST_RTC_ADDR_MSB 1
+#define ADC_SARADC_DTEST_RTC_ADDR_LSB 0
+
+#define ADC_SARADC_ENT_TSENS_ADDR 0x7
+#define ADC_SARADC_ENT_TSENS_ADDR_MSB 2
+#define ADC_SARADC_ENT_TSENS_ADDR_LSB 2
+
+#define ADC_SARADC_ENT_RTC_ADDR 0x7
+#define ADC_SARADC_ENT_RTC_ADDR_MSB 3
+#define ADC_SARADC_ENT_RTC_ADDR_LSB 3
+
+#define ADC_SARADC1_ENCAL_REF_ADDR 0x7
+#define ADC_SARADC1_ENCAL_REF_ADDR_MSB 4
+#define ADC_SARADC1_ENCAL_REF_ADDR_LSB 4
+
+#define ADC_SARADC2_ENCAL_REF_ADDR 0x7
+#define ADC_SARADC2_ENCAL_REF_ADDR_MSB 6
+#define ADC_SARADC2_ENCAL_REF_ADDR_LSB 6
+
+#define I2C_SARADC_TSENS_DAC 0x6
+#define I2C_SARADC_TSENS_DAC_MSB 3
+#define I2C_SARADC_TSENS_DAC_LSB 0

+ 109 - 0
components/esp_hw_support/port/esp32h2/regi2c_ctrl.h

@@ -0,0 +1,109 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdint.h>
+#include "regi2c_bbpll.h"
+#include "regi2c_lp_bias.h"
+#include "regi2c_dig_reg.h"
+#include "regi2c_bias.h"
+#include "regi2c_saradc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Analog function control register */
+#define I2C_MST_ANA_CONF0_REG  0x6000E040
+#define I2C_MST_BBPLL_STOP_FORCE_HIGH  (BIT(2))
+#define I2C_MST_BBPLL_STOP_FORCE_LOW  (BIT(3))
+
+#define ANA_CONFIG_REG  0x6000E044
+#define ANA_CONFIG_S    (8)
+#define ANA_CONFIG_M    (0x3FF)
+
+#define ANA_I2C_SAR_FORCE_PD BIT(18)
+#define ANA_I2C_BBPLL_M      BIT(17) /* Clear to enable BBPLL */
+#define ANA_I2C_APLL_M       BIT(14) /* Clear to enable APLL */
+
+
+#define ANA_CONFIG2_REG  0x6000E048
+#define ANA_CONFIG2_M    BIT(18)
+
+#define ANA_I2C_SAR_FORCE_PU BIT(16)
+
+/* ROM functions which read/write internal control bus */
+uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
+uint8_t rom_i2c_readReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
+void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
+void rom_i2c_writeReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
+
+#ifdef BOOTLOADER_BUILD
+
+/**
+ * If compiling for the bootloader, ROM functions can be called directly,
+ * without the need of a lock.
+ */
+#define regi2c_ctrl_read_reg         rom_i2c_readReg
+#define regi2c_ctrl_read_reg_mask    rom_i2c_readReg_Mask
+#define regi2c_ctrl_write_reg        rom_i2c_writeReg
+#define regi2c_ctrl_write_reg_mask   rom_i2c_writeReg_Mask
+
+#else
+
+#define i2c_read_reg_raw        rom_i2c_readReg
+#define i2c_read_reg_mask_raw   rom_i2c_readReg_Mask
+#define i2c_write_reg_raw       rom_i2c_writeReg
+#define i2c_write_reg_mask_raw  rom_i2c_writeReg_Mask
+
+uint8_t regi2c_ctrl_read_reg(uint8_t block, uint8_t host_id, uint8_t reg_add);
+uint8_t regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
+void regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
+void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
+
+#endif // BOOTLOADER_BUILD
+
+/* Convenience macros for the above functions, these use register definitions
+ * from regi2c_bbpll.h/regi2c_dig_reg.h/regi2c_lp_bias.h/regi2c_bias.h header files.
+ */
+#define REGI2C_WRITE_MASK(block, reg_add, indata) \
+      regi2c_ctrl_write_reg_mask(block, block##_HOSTID,  reg_add,  reg_add##_MSB,  reg_add##_LSB,  indata)
+
+#define REGI2C_READ_MASK(block, reg_add) \
+      regi2c_ctrl_read_reg_mask(block, block##_HOSTID,  reg_add,  reg_add##_MSB,  reg_add##_LSB)
+
+#define REGI2C_WRITE(block, reg_add, indata) \
+      regi2c_ctrl_write_reg(block, block##_HOSTID,  reg_add, indata)
+
+#define REGI2C_READ(block, reg_add) \
+      regi2c_ctrl_read_reg(block, block##_HOSTID,  reg_add)
+
+#ifdef __cplusplus
+}
+#endif

+ 507 - 0
components/esp_hw_support/port/esp32h2/rtc_clk.c

@@ -0,0 +1,507 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+#include <stdlib.h>
+#include "sdkconfig.h"
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/rtc.h"
+#include "esp32h2/rom/uart.h"
+#include "esp32h2/rom/gpio.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/efuse_reg.h"
+#include "soc/syscon_reg.h"
+#include "soc/system_reg.h"
+#include "regi2c_ctrl.h"
+#include "soc_log.h"
+#include "rtc_clk_common.h"
+#include "esp_rom_sys.h"
+
+static const char *TAG = "rtc_clk";
+
+#define RTC_PLL_FREQ_320M   320
+#define RTC_PLL_FREQ_480M   480
+#define DELAY_RTC_CLK_SWITCH 5
+
+// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
+static int s_cur_pll_freq;
+
+static void rtc_clk_cpu_freq_to_8m(void);
+
+void rtc_clk_32k_enable_internal(x32k_config_t cfg)
+{
+    REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac);
+    REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres);
+    REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm);
+    REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf);
+    SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
+}
+
+void rtc_clk_32k_enable(bool enable)
+{
+    if (enable) {
+        x32k_config_t cfg = X32K_CONFIG_DEFAULT();
+        rtc_clk_32k_enable_internal(cfg);
+    } else {
+        SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
+    }
+}
+
+void rtc_clk_32k_enable_external(void)
+{
+    /* TODO ESP32-C3 IDF-2408: external 32k source may need different settings */
+    x32k_config_t cfg = X32K_CONFIG_DEFAULT();
+    rtc_clk_32k_enable_internal(cfg);
+}
+
+void rtc_clk_32k_bootstrap(uint32_t cycle)
+{
+    /* No special bootstrapping needed for ESP32-C3, 'cycle' argument is to keep the signature
+     * same as for the ESP32. Just enable the XTAL here.
+     */
+    (void) cycle;
+    rtc_clk_32k_enable(true);
+}
+
+bool rtc_clk_32k_enabled(void)
+{
+    uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG);
+    /* If xtal xpd is controlled by software */
+    bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S;
+    /* If xtal xpd software control is on */
+    bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S;
+    bool disabled = xtal_xpd_sw && !xtal_xpd_st;
+    return !disabled;
+}
+
+void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
+{
+    if (clk_8m_en) {
+        // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); // ESP32H2-TODO: IDF-3396
+        /* no need to wait once enabled by software */
+        REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT);
+        esp_rom_delay_us(DELAY_8M_ENABLE);
+    } else {
+        // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M);
+        REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT);
+    }
+    /* d256 should be independent configured with 8M
+     * Maybe we can split this function into 8m and dmd256
+     */
+    if (d256_en) {
+        // CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
+    } else {
+        // SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
+    }
+}
+
+bool rtc_clk_8m_enabled(void)
+{
+    return false;
+    // return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; // ESP32H2-TODO: IDF-3396
+}
+
+bool rtc_clk_8md256_enabled(void)
+{
+    return false;
+    // return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; // ESP32H2-TODO: IDF-3396
+}
+
+void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
+{
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq);
+
+    /* Why we need to connect this clock to digital?
+     * Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
+     */
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN,
+                  (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0);
+
+    /* The clk_8m_d256 will be closed when rtc_state in SLEEP,
+    so if the slow_clk is 8md256, clk_8m must be force power on
+    */
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, (slow_freq == RTC_SLOW_FREQ_8MD256) ? 1 : 0);
+    esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH);
+}
+
+rtc_slow_freq_t rtc_clk_slow_freq_get(void)
+{
+    return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
+}
+
+uint32_t rtc_clk_slow_freq_get_hz(void)
+{
+    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;
+    }
+    return 0;
+}
+
+void rtc_clk_fast_freq_set(rtc_fast_freq_t fast_freq)
+{
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq);
+    esp_rom_delay_us(DELAY_FAST_CLK_SWITCH);
+}
+
+rtc_fast_freq_t rtc_clk_fast_freq_get(void)
+{
+    return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL);
+}
+
+static void rtc_clk_bbpll_disable(void)
+{
+    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
+                      RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
+    s_cur_pll_freq = 0;
+}
+
+static void rtc_clk_bbpll_enable(void)
+{
+    CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
+                        RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
+}
+
+void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
+{
+    uint8_t div_ref;
+    uint8_t div7_0;
+    uint8_t dr1;
+    uint8_t dr3;
+    uint8_t dchgp;
+    uint8_t dcur;
+    uint8_t dbias;
+
+    CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH);
+    SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW);
+    if (pll_freq == RTC_PLL_FREQ_480M) {
+        /* Set this register to let the digital part know 480M PLL is used */
+        // SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396
+        /* Configure 480M PLL */
+        switch (xtal_freq) {
+        case RTC_XTAL_FREQ_40M:
+            div_ref = 0;
+            div7_0 = 8;
+            dr1 = 0;
+            dr3 = 0;
+            dchgp = 5;
+            dcur = 3;
+            dbias = 2;
+            break;
+        case RTC_XTAL_FREQ_32M:
+            div_ref = 1;
+            div7_0 = 26;
+            dr1 = 1;
+            dr3 = 1;
+            dchgp = 4;
+            dcur = 0;
+            dbias = 2;
+            break;
+        default:
+            div_ref = 0;
+            div7_0 = 8;
+            dr1 = 0;
+            dr3 = 0;
+            dchgp = 5;
+            dcur = 3;
+            dbias = 2;
+            break;
+        }
+        REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B);
+    } else {
+        /* Clear this register to let the digital part know 320M PLL is used */
+        // CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396
+        /* Configure 320M PLL */
+        switch (xtal_freq) {
+        case RTC_XTAL_FREQ_40M:
+            div_ref = 0;
+            div7_0 = 4;
+            dr1 = 0;
+            dr3 = 0;
+            dchgp = 5;
+            dcur = 3;
+            dbias = 2;
+            break;
+        case RTC_XTAL_FREQ_32M:
+            div_ref = 1;
+            div7_0 = 6;
+            dr1 = 0;
+            dr3 = 0;
+            dchgp = 5;
+            dcur = 3;
+            dbias = 2;
+            break;
+        default:
+            div_ref = 0;
+            div7_0 = 4;
+            dr1 = 0;
+            dr3 = 0;
+            dchgp = 5;
+            dcur = 3;
+            dbias = 2;
+            break;
+        }
+        REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69);
+    }
+    uint8_t i2c_bbpll_lref  = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref);
+    uint8_t i2c_bbpll_div_7_0 = div7_0;
+    uint8_t i2c_bbpll_dcur = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
+    REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref);
+    REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
+    REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1);
+    REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3);
+    REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
+    REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias);
+    REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 2);
+    REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1);
+
+    s_cur_pll_freq = pll_freq;
+}
+
+/**
+ * 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)
+{
+    // int per_conf = DPORT_CPUPERIOD_SEL_80;
+    if (cpu_freq_mhz == 80) {
+        /* nothing to do */
+    } else if (cpu_freq_mhz == 160) {
+    //    per_conf = DPORT_CPUPERIOD_SEL_160;
+    } else {
+        SOC_LOGE(TAG, "invalid frequency");
+        abort();
+    }
+    // REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); // ESP32H2-TODO: IDF-3396
+    REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
+    REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL);
+    rtc_clk_apb_freq_update(80 * MHZ);
+    ets_update_cpu_frequency(cpu_freq_mhz);
+}
+
+bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
+{
+    uint32_t source_freq_mhz;
+    rtc_cpu_freq_src_t source;
+    uint32_t divider;
+    uint32_t real_freq_mhz;
+
+    uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get();
+    if (freq_mhz <= xtal_freq) {
+        divider = xtal_freq / freq_mhz;
+        real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */
+        if (real_freq_mhz != freq_mhz) {
+            // no suitable divider
+            return false;
+        }
+
+        source_freq_mhz = xtal_freq;
+        source = RTC_CPU_FREQ_SRC_XTAL;
+    } else if (freq_mhz == 80) {
+        real_freq_mhz = freq_mhz;
+        source = RTC_CPU_FREQ_SRC_PLL;
+        source_freq_mhz = RTC_PLL_FREQ_480M;
+        divider = 6;
+    } else if (freq_mhz == 160) {
+        real_freq_mhz = freq_mhz;
+        source = RTC_CPU_FREQ_SRC_PLL;
+        source_freq_mhz = RTC_PLL_FREQ_480M;
+        divider = 3;
+    } else {
+        // unsupported frequency
+        return false;
+    }
+    *out_config = (rtc_cpu_freq_config_t) {
+        .source = source,
+        .div = divider,
+        .source_freq_mhz = source_freq_mhz,
+        .freq_mhz = real_freq_mhz
+    };
+    return true;
+}
+
+void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
+{
+    uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
+    if (config->source == RTC_CPU_FREQ_SRC_XTAL) {
+        rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
+        if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) {
+            rtc_clk_bbpll_disable();
+        }
+    } else if (config->source == RTC_CPU_FREQ_SRC_PLL) {
+        if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) {
+            rtc_clk_bbpll_enable();
+            rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
+        }
+        rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
+    } else if (config->source == RTC_CPU_FREQ_SRC_8M) {
+        rtc_clk_cpu_freq_to_8m();
+        if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) {
+            rtc_clk_bbpll_disable();
+        }
+    }
+}
+
+void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
+{
+    rtc_cpu_freq_src_t source;
+    uint32_t source_freq_mhz;
+    uint32_t div;
+    uint32_t freq_mhz;
+    uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
+    switch (soc_clk_sel) {
+    case DPORT_SOC_CLK_SEL_XTAL: {
+        source = RTC_CPU_FREQ_SRC_XTAL;
+        div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1;
+        source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get();
+        freq_mhz = source_freq_mhz / div;
+    }
+    break;
+    case DPORT_SOC_CLK_SEL_PLL: {
+        // ESP32H2-TODO: IDF-3396
+        source = 0;
+        div = 0;
+        source_freq_mhz = 0;
+        freq_mhz = 0;
+        break;
+    }
+    case DPORT_SOC_CLK_SEL_8M:
+        source = RTC_CPU_FREQ_SRC_8M;
+        source_freq_mhz = 8;
+        div = 1;
+        freq_mhz = source_freq_mhz;
+        break;
+    default:
+        SOC_LOGE(TAG, "unsupported frequency configuration");
+        abort();
+    }
+    *out_config = (rtc_cpu_freq_config_t) {
+        .source = source,
+        .source_freq_mhz = source_freq_mhz,
+        .div = div,
+        .freq_mhz = freq_mhz
+    };
+}
+
+void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
+{
+    if (config->source == RTC_CPU_FREQ_SRC_XTAL) {
+        rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
+    } else if (config->source == RTC_CPU_FREQ_SRC_PLL &&
+               s_cur_pll_freq == config->source_freq_mhz) {
+        rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
+    } else {
+        /* fallback */
+        rtc_clk_cpu_freq_set_config(config);
+    }
+}
+
+void rtc_clk_cpu_freq_set_xtal(void)
+{
+    int freq_mhz = (int) rtc_clk_xtal_freq_get();
+
+    rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
+    rtc_clk_bbpll_disable();
+}
+
+/**
+ * Switch to XTAL frequency. Does not disable the PLL.
+ */
+void rtc_clk_cpu_freq_to_xtal(int freq, int div)
+{
+    ets_update_cpu_frequency(freq);
+    /* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */
+    REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
+    REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1);
+    /* no need to adjust the REF_TICK */
+    /* switch clock source */
+    REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL);
+    rtc_clk_apb_freq_update(freq * MHZ);
+}
+
+static void rtc_clk_cpu_freq_to_8m(void)
+{
+    ets_update_cpu_frequency(8);
+    REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
+    REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M);
+    rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M);
+}
+
+rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
+{
+    uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG);
+    if (!clk_val_is_valid(xtal_freq_reg)) {
+        SOC_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg);
+        return RTC_XTAL_FREQ_40M;
+    }
+    return reg_val_to_clk_val(xtal_freq_reg);
+}
+
+void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
+{
+    WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq));
+}
+
+void rtc_clk_apb_freq_update(uint32_t apb_freq)
+{
+    WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12));
+}
+
+uint32_t rtc_clk_apb_freq_get(void)
+{
+    uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12;
+    // round to the nearest MHz
+    freq_hz += MHZ / 2;
+    uint32_t remainder = freq_hz % MHZ;
+    return freq_hz - remainder;
+}
+
+void rtc_clk_divider_set(uint32_t div)
+{
+    CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
+    REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div);
+    SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
+}
+
+void rtc_clk_8m_divider_set(uint32_t div)
+{
+    CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div);
+    SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
+}
+
+void rtc_dig_clk8m_enable(void)
+{
+    SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
+    esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
+}
+
+void rtc_dig_clk8m_disable(void)
+{
+    CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
+    esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
+}
+
+/* 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")));

+ 57 - 0
components/esp_hw_support/port/esp32h2/rtc_clk_common.h

@@ -0,0 +1,57 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define MHZ (1000000)
+
+#define DPORT_CPUPERIOD_SEL_80      0
+#define DPORT_CPUPERIOD_SEL_160     1
+
+#define DPORT_SOC_CLK_SEL_XTAL    0
+#define DPORT_SOC_CLK_SEL_PLL    1
+#define DPORT_SOC_CLK_SEL_8M     2
+
+#define RTC_FAST_CLK_FREQ_8M        8500000
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void rtc_clk_cpu_freq_to_xtal(int freq, int div);
+
+/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in
+ * lower and upper 16-bit halves. These are the routines to work with such a
+ * representation.
+ */
+static inline bool clk_val_is_valid(uint32_t val)
+{
+    return (val & 0xffff) == ((val >> 16) & 0xffff) &&
+           val != 0 &&
+           val != UINT32_MAX;
+}
+
+static inline uint32_t reg_val_to_clk_val(uint32_t val)
+{
+    return val & UINT16_MAX;
+}
+
+static inline uint32_t clk_val_to_reg_val(uint32_t val)
+{
+    return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 88 - 0
components/esp_hw_support/port/esp32h2/rtc_clk_init.c

@@ -0,0 +1,88 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include "esp32h2/rom/ets_sys.h"
+#include "esp32h2/rom/rtc.h"
+#include "esp32h2/rom/uart.h"
+#include "soc/rtc.h"
+#include "soc/rtc_periph.h"
+#include "soc/efuse_periph.h"
+#include "soc/apb_ctrl_reg.h"
+#include "hal/cpu_hal.h"
+#include "regi2c_ctrl.h"
+#include "soc_log.h"
+#include "sdkconfig.h"
+#include "rtc_clk_common.h"
+#include "esp_rom_uart.h"
+
+static const char *TAG = "rtc_clk_init";
+
+void rtc_clk_init(rtc_clk_config_t cfg)
+{
+    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);
+
+    /* Enable the internal bus used to configure PLLs */
+    SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S);
+    CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_APLL_M | ANA_I2C_BBPLL_M);
+
+    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) {
+        SOC_LOGE(TAG, "invalid CPU frequency value");
+        abort();
+    }
+    rtc_clk_cpu_freq_set_config(&new_config);
+
+    /* Re-calculate the ccount to make time calculation correct. */
+    cpu_hal_set_cycle_count( (uint64_t)cpu_hal_get_cycle_count() * cfg.cpu_freq_mhz / freq_before );
+
+    /* Slow & fast clocks setup */
+    if (cfg.slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
+        rtc_clk_32k_enable(true);
+    }
+    if (cfg.fast_freq == RTC_FAST_FREQ_8M) {
+        bool need_8md256 = cfg.slow_freq == RTC_SLOW_FREQ_8MD256;
+        rtc_clk_8m_enable(true, need_8md256);
+    }
+    rtc_clk_fast_freq_set(cfg.fast_freq);
+    rtc_clk_slow_freq_set(cfg.slow_freq);
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است