diff --git a/.gitlab/ci/host-test.yml b/.gitlab/ci/host-test.yml index cc1348d41f..66e945b6e4 100644 --- a/.gitlab/ci/host-test.yml +++ b/.gitlab/ci/host-test.yml @@ -34,6 +34,7 @@ check_public_headers: - IDF_TARGET=esp32p4 python tools/ci/check_public_headers.py --jobs 4 --prefix riscv32-esp-elf- - IDF_TARGET=esp32c61 python tools/ci/check_public_headers.py --jobs 4 --prefix riscv32-esp-elf- - IDF_TARGET=esp32h21 python tools/ci/check_public_headers.py --jobs 4 --prefix riscv32-esp-elf- + - IDF_TARGET=esp32h4 python tools/ci/check_public_headers.py --jobs 4 --prefix riscv32-esp-elf- test_nvs_coverage: extends: diff --git a/components/bootloader_support/include/esp_app_format.h b/components/bootloader_support/include/esp_app_format.h index 18d5b1345f..7eeeeda13b 100644 --- a/components/bootloader_support/include/esp_app_format.h +++ b/components/bootloader_support/include/esp_app_format.h @@ -26,6 +26,9 @@ typedef enum { ESP_CHIP_ID_ESP32H2 = 0x0010, /*!< chip ID: ESP32-H2 */ ESP_CHIP_ID_ESP32P4 = 0x0012, /*!< chip ID: ESP32-P4 */ ESP_CHIP_ID_ESP32C5 = 0x0017, /*!< chip ID: ESP32-C5 */ + ESP_CHIP_ID_ESP32C61= 0x0014, /*!< chip ID: ESP32-C61 */ + ESP_CHIP_ID_ESP32H21= 0x0019, /*!< chip ID: ESP32-H21 */ + ESP_CHIP_ID_ESP32H4 = 0x001C, /*!< chip ID: ESP32-H4 */ 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; diff --git a/components/driver/deprecated/driver/adc_types_legacy.h b/components/driver/deprecated/driver/adc_types_legacy.h index bf094d8911..57ec49565a 100644 --- a/components/driver/deprecated/driver/adc_types_legacy.h +++ b/components/driver/deprecated/driver/adc_types_legacy.h @@ -70,7 +70,7 @@ typedef enum { ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */ ADC1_CHANNEL_MAX, } adc1_channel_t; -#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32H21 +#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32H21 || CONFIG_IDF_TARGET_ESP32H4 typedef enum { ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */ ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */ diff --git a/components/efuse/esp32h4/esp_efuse_table.c b/components/efuse/esp32h4/esp_efuse_table.c index 771ad91a10..f6c50815a7 100644 --- a/components/efuse/esp32h4/esp_efuse_table.c +++ b/components/efuse/esp32h4/esp_efuse_table.c @@ -9,7 +9,7 @@ #include #include "esp_efuse_table.h" -// md5_digest_table 6bfa2ae917ac6cbce5b70a55ea6a78bd +// md5_digest_table 39c442690c2273d557b5bb0db99fbe04 // 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. @@ -183,6 +183,10 @@ static const esp_efuse_desc_t WR_DIS_HUK_GEN_STATE[] = { {EFUSE_BLK0, 19, 1}, // [] wr_dis of HUK_GEN_STATE, }; +static const esp_efuse_desc_t WR_DIS_BLK1[] = { + {EFUSE_BLK0, 20, 1}, // [] wr_dis of BLOCK1, +}; + static const esp_efuse_desc_t WR_DIS_MAC[] = { {EFUSE_BLK0, 20, 1}, // [WR_DIS.MAC_FACTORY] wr_dis of MAC, }; @@ -227,6 +231,10 @@ static const esp_efuse_desc_t WR_DIS_FLASH_LDO_POWER_SEL[] = { {EFUSE_BLK0, 20, 1}, // [] wr_dis of FLASH_LDO_POWER_SEL, }; +static const esp_efuse_desc_t WR_DIS_SYS_DATA_PART1[] = { + {EFUSE_BLK0, 21, 1}, // [] wr_dis of BLOCK2, +}; + static const esp_efuse_desc_t WR_DIS_BLOCK_USR_DATA[] = { {EFUSE_BLK0, 22, 1}, // [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA, }; @@ -521,7 +529,8 @@ static const esp_efuse_desc_t MAC[] = { }; static const esp_efuse_desc_t MAC_EXT[] = { - {EFUSE_BLK1, 48, 16}, // [] Represents the extended bits of MAC address, + {EFUSE_BLK1, 56, 8}, // [] Stores the extended bits of MAC address, + {EFUSE_BLK1, 48, 8}, // [] Stores the extended bits of MAC address, }; static const esp_efuse_desc_t PVT_LIMIT[] = { @@ -810,6 +819,11 @@ const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_HUK_GEN_STATE[] = { NULL }; +const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[] = { + &WR_DIS_BLK1[0], // [] wr_dis of BLOCK1 + NULL +}; + const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_MAC[] = { &WR_DIS_MAC[0], // [WR_DIS.MAC_FACTORY] wr_dis of MAC NULL @@ -865,6 +879,11 @@ const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FLASH_LDO_POWER_SEL[] = { NULL }; +const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART1[] = { + &WR_DIS_SYS_DATA_PART1[0], // [] wr_dis of BLOCK2 + NULL +}; + const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLOCK_USR_DATA[] = { &WR_DIS_BLOCK_USR_DATA[0], // [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA NULL @@ -1231,7 +1250,8 @@ const esp_efuse_desc_t* ESP_EFUSE_MAC[] = { }; const esp_efuse_desc_t* ESP_EFUSE_MAC_EXT[] = { - &MAC_EXT[0], // [] Represents the extended bits of MAC address + &MAC_EXT[0], // [] Stores the extended bits of MAC address + &MAC_EXT[1], // [] Stores the extended bits of MAC address NULL }; diff --git a/components/efuse/esp32h4/esp_efuse_table.csv b/components/efuse/esp32h4/esp_efuse_table.csv index 6ea3f2112d..79b91f8788 100644 --- a/components/efuse/esp32h4/esp_efuse_table.csv +++ b/components/efuse/esp32h4/esp_efuse_table.csv @@ -53,6 +53,7 @@ WR_DIS.UART_PRINT_CONTROL, EFUSE_BLK0, 18, 1, [] wr_dis WR_DIS.FORCE_SEND_RESUME, EFUSE_BLK0, 18, 1, [] wr_dis of FORCE_SEND_RESUME WR_DIS.SECURE_VERSION, EFUSE_BLK0, 18, 1, [] wr_dis of SECURE_VERSION WR_DIS.HUK_GEN_STATE, EFUSE_BLK0, 19, 1, [] wr_dis of HUK_GEN_STATE +WR_DIS.BLK1, EFUSE_BLK0, 20, 1, [] wr_dis of BLOCK1 WR_DIS.MAC, EFUSE_BLK0, 20, 1, [WR_DIS.MAC_FACTORY] wr_dis of MAC WR_DIS.MAC_EXT, EFUSE_BLK0, 20, 1, [] wr_dis of MAC_EXT WR_DIS.PVT_LIMIT, EFUSE_BLK0, 20, 1, [] wr_dis of PVT_LIMIT @@ -64,6 +65,7 @@ WR_DIS.HYS_EN_PAD, EFUSE_BLK0, 20, 1, [] wr_dis WR_DIS.PVT_GLITCH_CHARGE_RESET, EFUSE_BLK0, 20, 1, [] wr_dis of PVT_GLITCH_CHARGE_RESET WR_DIS.VDD_SPI_LDO_ADJUST, EFUSE_BLK0, 20, 1, [] wr_dis of VDD_SPI_LDO_ADJUST WR_DIS.FLASH_LDO_POWER_SEL, EFUSE_BLK0, 20, 1, [] wr_dis of FLASH_LDO_POWER_SEL +WR_DIS.SYS_DATA_PART1, EFUSE_BLK0, 21, 1, [] wr_dis of BLOCK2 WR_DIS.BLOCK_USR_DATA, EFUSE_BLK0, 22, 1, [WR_DIS.USER_DATA] wr_dis of BLOCK_USR_DATA WR_DIS.CUSTOM_MAC, EFUSE_BLK0, 22, 1, [WR_DIS.MAC_CUSTOM WR_DIS.USER_DATA_MAC_CUSTOM] wr_dis of CUSTOM_MAC WR_DIS.BLOCK_KEY0, EFUSE_BLK0, 23, 1, [WR_DIS.KEY0] wr_dis of BLOCK_KEY0 @@ -141,7 +143,8 @@ MAC, EFUSE_BLK1, 40, 8, [MAC_FACT , EFUSE_BLK1, 16, 8, [MAC_FACTORY] MAC address , EFUSE_BLK1, 8, 8, [MAC_FACTORY] MAC address , EFUSE_BLK1, 0, 8, [MAC_FACTORY] MAC address -MAC_EXT, EFUSE_BLK1, 48, 16, [] Represents the extended bits of MAC address +MAC_EXT, EFUSE_BLK1, 56, 8, [] Stores the extended bits of MAC address +, EFUSE_BLK1, 48, 8, [] Stores the extended bits of MAC address PVT_LIMIT, EFUSE_BLK1, 64, 16, [] Power glitch monitor threthold PVT_CELL_SELECT, EFUSE_BLK1, 80, 7, [] Power glitch monitor PVT cell select PVT_PUMP_LIMIT, EFUSE_BLK1, 87, 8, [] Use to configure voltage monitor limit for charge pump diff --git a/components/efuse/esp32h4/include/esp_efuse_table.h b/components/efuse/esp32h4/include/esp_efuse_table.h index 36163bc224..962ed586eb 100644 --- a/components/efuse/esp32h4/include/esp_efuse_table.h +++ b/components/efuse/esp32h4/include/esp_efuse_table.h @@ -10,7 +10,7 @@ extern "C" { #include "esp_efuse.h" -// md5_digest_table 6bfa2ae917ac6cbce5b70a55ea6a78bd +// md5_digest_table 39c442690c2273d557b5bb0db99fbe04 // 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. @@ -65,6 +65,7 @@ extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_UART_PRINT_CONTROL[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FORCE_SEND_RESUME[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_VERSION[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_HUK_GEN_STATE[]; +extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_MAC[]; #define ESP_EFUSE_WR_DIS_MAC_FACTORY ESP_EFUSE_WR_DIS_MAC extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_MAC_EXT[]; @@ -77,6 +78,7 @@ extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_HYS_EN_PAD[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_PVT_GLITCH_CHARGE_RESET[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_VDD_SPI_LDO_ADJUST[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_FLASH_LDO_POWER_SEL[]; +extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART1[]; extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLOCK_USR_DATA[]; #define ESP_EFUSE_WR_DIS_USER_DATA ESP_EFUSE_WR_DIS_BLOCK_USR_DATA extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_CUSTOM_MAC[]; diff --git a/components/esp_adc/esp32h4/include/.gitkeep b/components/esp_adc/esp32h4/include/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/components/esp_adc/esp32h4/include/adc_cali_schemes.h b/components/esp_adc/esp32h4/include/adc_cali_schemes.h new file mode 100644 index 0000000000..c7c3c697d3 --- /dev/null +++ b/components/esp_adc/esp32h4/include/adc_cali_schemes.h @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @file adc_cali_schemes.h + * + * @brief Supported calibration schemes + */ + +//TODO: [ESP32H4] IDF-12369 +// #define ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED 1 diff --git a/components/esp_hw_support/port/esp32h4/CMakeLists.txt b/components/esp_hw_support/port/esp32h4/CMakeLists.txt index e69de29bb2..783b2f8b17 100644 --- a/components/esp_hw_support/port/esp32h4/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32h4/CMakeLists.txt @@ -0,0 +1,28 @@ +set(srcs "rtc_clk.c" + "rtc_time.c" + "chip_info.c" + ) + +if(CONFIG_SOC_PMU_SUPPORTED) + list(APPEND srcs + "rtc_clk_init.c" + "pmu_param.c" + "pmu_init.c" + "pmu_sleep.c" + ) +endif() + +if(NOT BOOTLOADER_BUILD) + # list(APPEND srcs "sar_periph_ctrl.c") // TODO: [ESP32H4] IDF-12368 + + if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE) + list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c") + endif() + +endif() + +add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}") + +target_sources(${COMPONENT_LIB} PRIVATE "${srcs}") +target_include_directories(${COMPONENT_LIB} PUBLIC . private_include include) +target_include_directories(${COMPONENT_LIB} PRIVATE ../hal) diff --git a/components/esp_hw_support/port/esp32h4/chip_info.c b/components/esp_hw_support/port/esp32h4/chip_info.c new file mode 100644 index 0000000000..1283920f72 --- /dev/null +++ b/components/esp_hw_support/port/esp32h4/chip_info.c @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_chip_info.h" +#include "hal/efuse_hal.h" + +void esp_chip_info(esp_chip_info_t *out_info) +{ + memset(out_info, 0, sizeof(*out_info)); + out_info->model = CHIP_ESP32H4; + out_info->revision = efuse_hal_chip_revision(); + out_info->cores = 2; + out_info->features = CHIP_FEATURE_BLE | CHIP_FEATURE_IEEE802154; +} diff --git a/components/esp_hw_support/port/esp32h4/include/soc/rtc.h b/components/esp_hw_support/port/esp32h4/include/soc/rtc.h new file mode 100644 index 0000000000..f5f47a2aa8 --- /dev/null +++ b/components/esp_hw_support/port/esp32h4/include/soc/rtc.h @@ -0,0 +1,448 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include +#include "soc/soc.h" +#include "soc/clk_tree_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************************/ +/***************** THIS FILE IS CONSIDERED AS A PRIVATE HEADER FILE *****************/ +/*** IT IS NOT RECOMMENDED TO USE THE APIS IN THIS FILE DIRECTLY IN APPLICATIONS ****/ +/************************************************************************************/ + +/** + * @file rtc.h + * @brief Low-level RTC power, clock functions. + * + * Functions in this file facilitate configuration of ESP32H4's RTC_CNTL peripheral. + * RTC_CNTL peripheral handles many functions: + * - enables/disables clocks and power to various parts of the chip; this is + * done using direct register access (forcing power up or power down) or by + * allowing state machines to control power and clocks automatically + * - handles sleep and wakeup functions + * - maintains a 48-bit counter which can be used for timekeeping + * + * These functions are not thread safe, and should not be viewed as high level + * APIs. For example, while this file provides a function which can switch + * CPU frequency, this function is on its own is not sufficient to implement + * frequency switching in ESP-IDF context: some coordination with RTOS, + * peripheral drivers, and WiFi/BT stacks is also required. + * + * These functions will normally not be used in applications directly. + * ESP-IDF provides, or will provide, drivers and other facilities to use + * RTC subsystem functionality. + * + * The functions are loosely split into the following groups: + * - rtc_clk: clock switching, calibration + * - rtc_time: reading RTC counter, conversion between counter values and time + */ + +#define MHZ (1000000) + +#define RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(cycles) (cycles << 10) +#define RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12) +#define RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(cycles) (TIMG_RTC_CALI_TIMEOUT_THRES_V) // Just use the max timeout thres value + +#define OTHER_BLOCKS_POWERUP 1 +#define OTHER_BLOCKS_WAIT 1 + +/* Delays for various clock sources to be enabled/switched. + * All values are in microseconds. + */ +#define SOC_DELAY_RTC_FAST_CLK_SWITCH 3 +#define SOC_DELAY_RTC_SLOW_CLK_SWITCH 300 +#define SOC_DELAY_RC_FAST_ENABLE 50 +#define SOC_DELAY_RC_FAST_DIGI_SWITCH 5 +#define SOC_DELAY_RC32K_ENABLE 300 + +#define RTC_CNTL_PLL_BUF_WAIT_DEFAULT 20 +#define RTC_CNTL_XTL_BUF_WAIT_DEFAULT 100 +#define RTC_CNTL_CK8M_WAIT_DEFAULT 20 +#define RTC_CK8M_ENABLE_WAIT_DEFAULT 5 + +#define RTC_CNTL_CK8M_DFREQ_DEFAULT 100 +#define RTC_CNTL_SCK_DCAP_DEFAULT 128 +#define RTC_CNTL_RC32K_DFREQ_DEFAULT 700 + +/* Various delays to be programmed into power control state machines */ +#define RTC_CNTL_XTL_BUF_WAIT_SLP_US (250) +#define RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES (1) +#define RTC_CNTL_CK8M_WAIT_SLP_CYCLES (4) +#define RTC_CNTL_WAKEUP_DELAY_CYCLES (5) +#define RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES (1) +#define RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES (1) +#define RTC_CNTL_MIN_SLP_VAL_MIN (2) + +/* +set sleep_init default param +*/ +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT 5 +#define RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP 0 +#define RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT 15 +#define RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT 0 +#define RTC_CNTL_BIASSLP_MONITOR_DEFAULT 0 +#define RTC_CNTL_BIASSLP_SLEEP_ON 0 +#define RTC_CNTL_BIASSLP_SLEEP_DEFAULT 1 +#define RTC_CNTL_PD_CUR_MONITOR_DEFAULT 0 +#define RTC_CNTL_PD_CUR_SLEEP_ON 0 +#define RTC_CNTL_PD_CUR_SLEEP_DEFAULT 1 +#define RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT 254 + +/* +The follow value is used to get a reasonable rtc voltage dbias value according to digital dbias & some other value +storing in efuse (based on ATE 5k ECO3 chips) +*/ +#define K_RTC_MID_MUL10000 215 +#define K_DIG_MID_MUL10000 213 +#define V_RTC_MID_MUL10000 10800 +#define V_DIG_MID_MUL10000 10860 + +/** + * @brief CPU clock configuration structure + */ +typedef struct rtc_cpu_freq_config_s { + soc_cpu_clk_src_t source; //!< The clock from which CPU clock is derived + uint32_t source_freq_mhz; //!< Source clock frequency + uint32_t div; //!< Divider, freq_mhz = SOC_ROOT_CLK freq_mhz / div + uint32_t freq_mhz; //!< CPU clock frequency +} rtc_cpu_freq_config_t; + +#define RTC_CLK_CAL_FRACT 19 //!< Number of fractional bits in values returned by rtc_clk_cal + +#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO +#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO + + +/** + * @brief Clock source to be calibrated using rtc_clk_cal function + * + * @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL + * However, this is not true on ESP32H4. The conversion to register field values is explicitly done in + * rtc_clk_cal_internal + */ +typedef enum { + RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK + RTC_CAL_RC_SLOW = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, //!< Internal 150kHz RC oscillator + RTC_CAL_RC32K = SOC_RTC_SLOW_CLK_SRC_RC32K, //!< Internal 32kHz RC oscillator, as one type of 32k clock + RTC_CAL_32K_XTAL = SOC_RTC_SLOW_CLK_SRC_XTAL32K, //!< External 32kHz XTAL, as one type of 32k clock + RTC_CAL_32K_OSC_SLOW = SOC_RTC_SLOW_CLK_SRC_OSC_SLOW, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock + RTC_CAL_RC_FAST //!< Internal 20MHz RC oscillator +} rtc_cal_sel_t; + +/** + * Initialization parameters for rtc_clk_init + */ +typedef struct { + soc_xtal_freq_t xtal_freq : 8; //!< Main XTAL frequency + uint32_t cpu_freq_mhz : 10; //!< CPU frequency to set, in MHz + soc_rtc_fast_clk_src_t fast_clk_src : 2; //!< RTC_FAST_CLK clock source to choose + soc_rtc_slow_clk_src_t slow_clk_src : 3; //!< RTC_SLOW_CLK clock source to choose + uint32_t clk_rtc_clk_div : 8; + uint32_t clk_8m_clk_div : 3; //!< RC_FAST clock divider (division is by clk_8m_div+1, i.e. 0 means ~20MHz frequency) + uint32_t slow_clk_dcap : 8; //!< RC_SLOW clock adjustment parameter (higher value leads to lower frequency) + uint32_t clk_8m_dfreq : 10; //!< RC_FAST clock adjustment parameter (higher value leads to higher frequency) + uint32_t rc32k_dfreq : 10; //!< Internal RC32K clock adjustment parameter (higher value leads to higher frequency) +} rtc_clk_config_t; + +/** + * Default initializer for rtc_clk_config_t + */ +#define RTC_CLK_CONFIG_DEFAULT() { \ + .xtal_freq = SOC_XTAL_FREQ_32M, \ + .cpu_freq_mhz = 80, \ + .fast_clk_src = SOC_RTC_FAST_CLK_SRC_RC_FAST, \ + .slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, \ + .clk_rtc_clk_div = 0, \ + .clk_8m_clk_div = 0, \ + .slow_clk_dcap = RTC_CNTL_SCK_DCAP_DEFAULT, \ + .clk_8m_dfreq = RTC_CNTL_CK8M_DFREQ_DEFAULT, \ + .rc32k_dfreq = RTC_CNTL_RC32K_DFREQ_DEFAULT, \ +} + +/** + * Initialize clocks and set CPU frequency + * + * @param cfg clock configuration as rtc_clk_config_t + */ +void rtc_clk_init(rtc_clk_config_t cfg); + +/** + * @brief Get main XTAL frequency + * + * This is the value stored in RTC register RTC_XTAL_FREQ_REG by the bootloader. As passed to + * rtc_clk_init function + * + * @return XTAL frequency, one of soc_xtal_freq_t + */ +soc_xtal_freq_t rtc_clk_xtal_freq_get(void); + +/** + * @brief Update XTAL frequency + * + * Updates the XTAL value stored in RTC_XTAL_FREQ_REG. Usually this value is ignored + * after startup. + * + * @param xtal_freq New frequency value + */ +void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq); + +/** + * @brief Enable or disable 32 kHz XTAL oscillator + * @param en true to enable, false to disable + */ +void rtc_clk_32k_enable(bool en); + +/** + * @brief Configure 32 kHz XTAL oscillator to accept external clock signal + */ +void rtc_clk_32k_enable_external(void); + +/** + * @brief Get the state of 32k XTAL oscillator + * @return true if 32k XTAL oscillator has been enabled + */ +bool rtc_clk_32k_enabled(void); + +/** + * @brief Enable 32k oscillator, configuring it for fast startup time. + * Note: to achieve higher frequency stability, rtc_clk_32k_enable function + * must be called one the 32k XTAL oscillator has started up. This function + * will initially disable the 32k XTAL oscillator, so it should not be called + * when the system is using 32k XTAL as RTC_SLOW_CLK. + * + * @param cycle Number of 32kHz cycles to bootstrap external crystal. + * If 0, no square wave will be used to bootstrap crystal oscillation. + */ +void rtc_clk_32k_bootstrap(uint32_t cycle); + +/** + * @brief Enable or disable 32 kHz internal rc oscillator + * @param en true to enable, false to disable + */ +void rtc_clk_rc32k_enable(bool enable); + +/** + * @brief Enable or disable 8 MHz internal oscillator + * + * @param clk_8m_en true to enable 8MHz generator + */ +void rtc_clk_8m_enable(bool clk_8m_en); + +/** + * @brief Get the state of 8 MHz internal oscillator + * @return true if the oscillator is enabled + */ +bool rtc_clk_8m_enabled(void); + +/** + * @brief Select source for RTC_SLOW_CLK + * @param clk_src clock source (one of soc_rtc_slow_clk_src_t values) + */ +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src); + +/** + * @brief Get the RTC_SLOW_CLK source + * @return currently selected clock source (one of soc_rtc_slow_clk_src_t values) + */ +soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void); + +/** + * @brief Get the approximate frequency of RTC_SLOW_CLK, in Hz + * + * - if SOC_RTC_SLOW_CLK_SRC_RC_SLOW is selected, returns 136000 + * - if SOC_RTC_SLOW_CLK_SRC_XTAL32K is selected, returns 32768 + * - if SOC_RTC_SLOW_CLK_SRC_RC32K is selected, returns 32768 + * - if SOC_RTC_SLOW_CLK_SRC_OSC_SLOW is selected, returns 32768 + * + * rtc_clk_cal function can be used to get more precise value by comparing + * RTC_SLOW_CLK frequency to the frequency of main XTAL. + * + * @return RTC_SLOW_CLK frequency, in Hz + */ +uint32_t rtc_clk_slow_freq_get_hz(void); + +/** + * @brief Select source for RTC_FAST_CLK + * @param clk_src clock source (one of soc_rtc_fast_clk_src_t values) + */ +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src); + +/** + * @brief Get the RTC_FAST_CLK source + * @return currently selected clock source (one of soc_rtc_fast_clk_src_t values) + */ +soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void); + +/** + * @brief Get CPU frequency config for a given frequency + * @param freq_mhz Frequency in MHz + * @param[out] out_config Output, CPU frequency configuration structure + * @return true if frequency can be obtained, false otherwise + */ +bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config); + +/** + * @brief Switch CPU frequency + * + * This function sets CPU frequency according to the given configuration + * structure. It enables PLLs, if necessary. + * + * @note This function in not intended to be called by applications in FreeRTOS + * environment. This is because it does not adjust various timers based on the + * new CPU frequency. + * + * @param config CPU frequency configuration structure + */ +void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config); + +/** + * @brief Switch CPU frequency (optimized for speed) + * + * This function is a faster equivalent of rtc_clk_cpu_freq_set_config. + * It works faster because it does not disable PLLs when switching from PLL to + * XTAL and does not enabled them when switching back. If PLL is not already + * enabled when this function is called to switch from XTAL to PLL frequency, + * or the PLL which is enabled is the wrong one, this function will fall back + * to calling rtc_clk_cpu_freq_set_config. + * + * Unlike rtc_clk_cpu_freq_set_config, this function relies on static data, + * so it is less safe to use it e.g. from a panic handler (when memory might + * be corrupted). + * + * @note This function in not intended to be called by applications in FreeRTOS + * environment. This is because it does not adjust various timers based on the + * new CPU frequency. + * + * @param config CPU frequency configuration structure + */ +void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config); + +/** + * @brief Get the currently used CPU frequency configuration + * @param[out] out_config Output, CPU frequency configuration structure + */ +void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config); + +/** + * @brief Switch CPU clock source to XTAL + * + * Short form for filling in rtc_cpu_freq_config_t structure and calling + * rtc_clk_cpu_freq_set_config when a switch to XTAL is needed. + * Assumes that XTAL frequency has been determined — don't call in startup code. + * + * @note On ESP32H4, this function will check whether BBPLL can be disabled. If there is no consumer, then BBPLL will be + * turned off. The behaviour is the same as using rtc_clk_cpu_freq_set_config to switch cpu clock source to XTAL. + */ +void rtc_clk_cpu_freq_set_xtal(void); + +/** + * @brief Switch root clock source to PLL (only used by sleep) release root clock source locked by PMU + * + * wifi receiving beacon frame in PMU modem state strongly depends on the BBPLL + * clock, PMU will forcibly lock the root clock source as PLL, when the root + * clock source of the software system is selected as PLL, we need to release + * the root clock source locking and switch the root clock source to PLL in the + * sleep process (a critical section). + * + * @param[in] Maximum CPU frequency, in MHz + */ +void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz); + +/** + * @brief Get the current APB frequency. + * @return The calculated APB frequency value, in Hz. + */ +uint32_t rtc_clk_apb_freq_get(void); + +/** + * @brief Measure RTC slow clock's period, based on main XTAL frequency + * + * This function will time out and return 0 if the time for the given number + * of cycles to be counted exceeds the expected time twice. This may happen if + * 32k XTAL is being calibrated, but the oscillator has not started up (due to + * incorrect loading capacitance, board design issue, or lack of 32 XTAL on board). + * + * @note When 32k CLK is being calibrated, this function will check the accuracy + * of the clock. Since the xtal 32k or ext osc 32k is generally very stable, if + * the check fails, then consider this an invalid 32k clock and return 0. This + * check can filter some jamming signal. + * + * @param cal_clk clock to be measured + * @param slow_clk_cycles number of slow clock cycles to average + * @return average slow clock period in microseconds, Q13.19 fixed point format, + * or 0 if calibration has timed out + */ +uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles); + +/** + * @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles + * @param time_in_us Time interval in microseconds + * @param slow_clk_period Period of slow clock in microseconds, Q13.19 + * fixed point format (as returned by rtc_slowck_cali). + * @return number of slow clock cycles + */ +uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period); + +/** + * @brief Convert time interval from RTC_SLOW_CLK to microseconds + * @param time_in_us Time interval in RTC_SLOW_CLK cycles + * @param slow_clk_period Period of slow clock in microseconds, Q13.19 + * fixed point format (as returned by rtc_slowck_cali). + * @return time interval in microseconds + */ +uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period); + +/** + * @brief Get current value of RTC counter + * + * RTC has a 48-bit counter which is incremented by 2 every 2 RTC_SLOW_CLK + * cycles. Counter value is not writable by software. The value is not adjusted + * when switching to a different RTC_SLOW_CLK source. + * + * Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute + * + * @return current value of RTC counter + */ +uint64_t rtc_time_get(void); + +/** + * @brief Enable the rtc digital 8M clock + * + * This function is used to enable the digital rtc 8M clock to support peripherals. + * For enabling the analog 8M clock, using `rtc_clk_8M_enable` function above. + */ +void rtc_dig_clk8m_enable(void); + +/** + * @brief Disable the rtc digital 8M clock + * + * This function is used to disable the digital rtc 8M clock, which is only used to support peripherals. + */ +void rtc_dig_clk8m_disable(void); + +/** + * @brief Get whether the rtc digital 8M clock is enabled + */ +bool rtc_dig_8m_enabled(void); + +/** + * @brief Calculate the real clock value after the clock calibration + * + * @param cal_val Average slow clock period in microseconds, fixed point value as returned from `rtc_clk_cal` + * @return Frequency of the clock in Hz + */ +uint32_t rtc_clk_freq_cal(uint32_t cal_val); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32h4/rtc_clk.c b/components/esp_hw_support/port/esp32h4/rtc_clk.c new file mode 100644 index 0000000000..85bc72eced --- /dev/null +++ b/components/esp_hw_support/port/esp32h4/rtc_clk.c @@ -0,0 +1,407 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "sdkconfig.h" +#include "rom/rtc.h" +#include "soc/rtc.h" +#include "esp_private/rtc_clk.h" +#include "esp_hw_log.h" +#include "esp_rom_sys.h" +#include "hal/clk_tree_ll.h" +#include "hal/regi2c_ctrl_ll.h" +#include "soc/io_mux_reg.h" +#include "soc/lp_aon_reg.h" +#include "esp_private/sleep_event.h" + +static const char *TAG = "rtc_clk"; + +// Current PLL frequency, in 480MHz. Zero if PLL is not enabled. +static int s_cur_pll_freq; + +static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG + +void rtc_clk_bbpll_add_consumer(void) +{ + s_bbpll_digi_consumers_ref_count += 1; +} + +void rtc_clk_bbpll_remove_consumer(void) +{ + s_bbpll_digi_consumers_ref_count -= 1; +} + +void rtc_clk_32k_enable(bool enable) +{ + if (enable) { + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL); + } else { + clk_ll_xtal32k_disable(); + } +} + +void rtc_clk_32k_enable_external(void) +{ + // EXT_OSC_SLOW_GPIO_NUM == GPIO_NUM_0 + PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG); + REG_SET_BIT(LP_AON_GPIO_HOLD0_REG, BIT(EXT_OSC_SLOW_GPIO_NUM)); + clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL); +} + +void rtc_clk_32k_bootstrap(uint32_t cycle) +{ + /* No special bootstrapping needed for ESP32-C6, '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) +{ + return clk_ll_xtal32k_is_enabled(); +} + +void rtc_clk_rc32k_enable(bool enable) +{ + if (enable) { + clk_ll_rc32k_enable(); + esp_rom_delay_us(SOC_DELAY_RC32K_ENABLE); + } else { + clk_ll_rc32k_disable(); + } +} + +void rtc_clk_8m_enable(bool clk_8m_en) +{ + if (clk_8m_en) { + clk_ll_rc_fast_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE); + } else { + clk_ll_rc_fast_disable(); + } +} + +bool rtc_clk_8m_enabled(void) +{ + return clk_ll_rc_fast_is_enabled(); +} + +void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src) +{ + clk_ll_rtc_slow_set_src(clk_src); + esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH); +} + +soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void) +{ + return clk_ll_rtc_slow_get_src(); +} + +uint32_t rtc_clk_slow_freq_get_hz(void) +{ + switch (rtc_clk_slow_src_get()) { + case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_RC32K: return SOC_CLK_RC32K_FREQ_APPROX; + case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: return SOC_CLK_OSC_SLOW_FREQ_APPROX; + default: return 0; + } +} + +void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src) +{ + clk_ll_rtc_fast_set_src(clk_src); + esp_rom_delay_us(SOC_DELAY_RTC_FAST_CLK_SWITCH); +} + +soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void) +{ + return clk_ll_rtc_fast_get_src(); +} + +static void rtc_clk_bbpll_disable(void) +{ + clk_ll_bbpll_disable(); + s_cur_pll_freq = 0; +} + +static void rtc_clk_bbpll_enable(void) +{ + clk_ll_bbpll_enable(); +} + +static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq) +{ + /* Digital part */ + clk_ll_bbpll_set_freq_mhz(pll_freq); + /* Analog part */ + + /* BBPLL CALIBRATION START */ + regi2c_ctrl_ll_bbpll_calibration_start(); + clk_ll_bbpll_set_config(pll_freq, xtal_freq); + /* WAIT CALIBRATION DONE */ + while(!regi2c_ctrl_ll_bbpll_calibration_is_done()); + /* BBPLL CALIBRATION STOP */ + regi2c_ctrl_ll_bbpll_calibration_stop(); + + s_cur_pll_freq = pll_freq; +} + +/** + * Switch to use XTAL as the CPU clock source. + * Must satisfy: cpu_freq = XTAL_FREQ / div. + * Does not disable the PLL. + */ +static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div) +{ + clk_ll_ahb_set_ls_divider(div); + clk_ll_cpu_set_ls_divider(div); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL); + esp_rom_set_cpu_ticks_per_us(cpu_freq); +} + +static void rtc_clk_cpu_freq_to_8m(void) +{ + clk_ll_ahb_set_ls_divider(1); + clk_ll_cpu_set_ls_divider(1); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST); + esp_rom_set_cpu_ticks_per_us(20); +} + +/** + * 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) +{ + clk_ll_cpu_set_hs_divider(CLK_LL_PLL_480M_FREQ_MHZ / cpu_freq_mhz); + clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL); + esp_rom_set_cpu_ticks_per_us(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; + soc_cpu_clk_src_t source; + uint32_t divider; // divider = freq of SOC_ROOT_CLK / freq of CPU_CLK + uint32_t real_freq_mhz; + + uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get(); + if (freq_mhz <= xtal_freq && freq_mhz != 0) { + 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 = SOC_CPU_CLK_SRC_XTAL; + } else if (freq_mhz == 80) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; + divider = 6; + } else if (freq_mhz == 120) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; + divider = 4; + } else if (freq_mhz == 160) { + real_freq_mhz = freq_mhz; + source = SOC_CPU_CLK_SRC_PLL; + source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ; + 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; +} + +__attribute__((weak)) void rtc_clk_set_cpu_switch_to_bbpll(int event_id) +{ +} + +void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config) +{ + soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src(); + if (config->source == SOC_CPU_CLK_SRC_XTAL) { + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll + rtc_clk_bbpll_disable(); + } + } else if (config->source == SOC_CPU_CLK_SRC_PLL) { + if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) { + rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_PLL_EN_START); + 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); + rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_PLL_EN_STOP); + } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { + rtc_clk_cpu_freq_to_8m(); + if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) { + // We don't turn off the bbpll if some consumers depend on bbpll + rtc_clk_bbpll_disable(); + } + } +} + +void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + uint32_t source_freq_mhz; + uint32_t div; // div = freq of SOC_ROOT_CLK / freq of CPU_CLK + uint32_t freq_mhz; + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: { + div = clk_ll_cpu_get_ls_divider(); + source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get(); + freq_mhz = source_freq_mhz / div; + break; + } + case SOC_CPU_CLK_SRC_PLL: { + div = clk_ll_cpu_get_hs_divider(); + source_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + freq_mhz = source_freq_mhz / div; + break; + } + case SOC_CPU_CLK_SRC_RC_FAST: + div = clk_ll_cpu_get_ls_divider(); + source_freq_mhz = 20; + freq_mhz = source_freq_mhz / div; + break; + default: + ESP_HW_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 == SOC_CPU_CLK_SRC_XTAL) { + rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div); + } else if (config->source == SOC_CPU_CLK_SRC_PLL && + s_cur_pll_freq == config->source_freq_mhz) { + rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz); + } else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) { + rtc_clk_cpu_freq_to_8m(); + } else { + /* fallback */ + rtc_clk_cpu_freq_set_config(config); + } +} + +void rtc_clk_cpu_freq_set_xtal(void) +{ + rtc_clk_cpu_set_to_default_config(); + // We don't turn off the bbpll if some consumers depend on bbpll + if (!s_bbpll_digi_consumers_ref_count) { + rtc_clk_bbpll_disable(); + } +} + +void rtc_clk_cpu_set_to_default_config(void) +{ + int freq_mhz = (int)rtc_clk_xtal_freq_get(); + + rtc_clk_cpu_freq_to_xtal(freq_mhz, 1); +} + +void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz) +{ + rtc_clk_cpu_freq_to_pll_mhz(cpu_freq_mhz); + clk_ll_cpu_clk_src_lock_release(); +} + +soc_xtal_freq_t rtc_clk_xtal_freq_get(void) +{ +#if !CONFIG_IDF_ENV_FPGA + uint32_t xtal_freq_mhz = clk_ll_xtal_load_freq_mhz(); + if (xtal_freq_mhz == 0) { + ESP_HW_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value, assume 32MHz"); + return SOC_XTAL_FREQ_32M; + } + return (soc_xtal_freq_t)xtal_freq_mhz; +#else + return SOC_XTAL_FREQ_32M; +#endif +} + +void rtc_clk_xtal_freq_update(soc_xtal_freq_t xtal_freq) +{ + clk_ll_xtal_store_freq_mhz(xtal_freq); +} + +static uint32_t rtc_clk_ahb_freq_get(void) +{ + soc_cpu_clk_src_t source = clk_ll_cpu_get_src(); + uint32_t soc_root_freq_mhz; + uint32_t divider; + switch (source) { + case SOC_CPU_CLK_SRC_XTAL: + soc_root_freq_mhz = rtc_clk_xtal_freq_get(); + divider = clk_ll_ahb_get_ls_divider(); + break; + case SOC_CPU_CLK_SRC_PLL: + soc_root_freq_mhz = clk_ll_bbpll_get_freq_mhz(); + divider = clk_ll_ahb_get_hs_divider(); + break; + case SOC_CPU_CLK_SRC_RC_FAST: + soc_root_freq_mhz = 20; + divider = clk_ll_ahb_get_ls_divider(); + break; + default: + // Unknown SOC_ROOT clock source + soc_root_freq_mhz = 0; + divider = 1; + ESP_HW_LOGE(TAG, "Invalid SOC_ROOT_CLK"); + break; + } + return soc_root_freq_mhz / divider; +} + +uint32_t rtc_clk_apb_freq_get(void) +{ + return rtc_clk_ahb_freq_get() / clk_ll_apb_get_divider() * MHZ; +} + +void rtc_dig_clk8m_enable(void) +{ + clk_ll_rc_fast_digi_enable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); +} + +void rtc_dig_clk8m_disable(void) +{ + clk_ll_rc_fast_digi_disable(); + esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); +} + +bool rtc_dig_8m_enabled(void) +{ + return clk_ll_rc_fast_digi_is_enabled(); +} diff --git a/components/esp_hw_support/port/esp32h4/rtc_time.c b/components/esp_hw_support/port/esp32h4/rtc_time.c new file mode 100644 index 0000000000..df85a59136 --- /dev/null +++ b/components/esp_hw_support/port/esp32h4/rtc_time.c @@ -0,0 +1,275 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "rom/ets_sys.h" +#include "soc/rtc.h" +#include "soc/lp_timer_reg.h" +#include "hal/lp_timer_hal.h" +#include "hal/clk_tree_ll.h" +#include "hal/timer_ll.h" +#include "soc/timer_group_reg.h" +#include "esp_rom_sys.h" +#include "assert.h" +#include "hal/efuse_hal.h" +#include "soc/chip_revision.h" +#include "esp_private/periph_ctrl.h" + +static const char *TAG = "rtc_time"; + +/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. + * This feature counts the number of XTAL clock cycles within a given number of + * RTC_SLOW_CLK cycles. + * + * Slow clock calibration feature has two modes of operation: one-off and cycling. + * In cycling mode (which is enabled by default on SoC reset), counting of XTAL + * cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled + * using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed + * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is + * enabled using TIMG_RTC_CALI_START bit. + */ + +/* On ESP32H4, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2 + * 0: calibrate RC_SLOW clock + * 1: calibrate RC_FAST clock + * 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by lp_pad_gpio0 + */ +#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0 +#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1 +#define TIMG_RTC_CALI_CLK_SEL_32K 2 + +/** + * @brief Clock calibration function used by rtc_clk_cal + * + * Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0. + * This feature counts the number of XTAL clock cycles within a given number of + * RTC_SLOW_CLK cycles. + * + * Slow clock calibration feature has two modes of operation: one-off and cycling. + * In cycling mode (which is enabled by default on SoC reset), counting of XTAL + * cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled + * using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed + * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is + * enabled using TIMG_RTC_CALI_START bit. + * + * @param cal_clk which clock to calibrate + * @param slowclk_cycles number of slow clock cycles to count + * @return number of XTAL clock cycles within the given number of slow clock cycles + */ +static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) +{ + assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V); + + uint32_t cali_clk_sel = 0; + soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get(); + soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target(); + if (cal_clk == RTC_CAL_RTC_MUX) { + cal_clk = (rtc_cal_sel_t)slow_clk_src; + } + if (cal_clk == RTC_CAL_RC_FAST) { + cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST; + } else if (cal_clk == RTC_CAL_RC_SLOW) { + cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW; + } else { + cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K; + clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk); + } + + + /* Enable requested clock (150k clock is always on) */ + // All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock + // Only enable if originally was disabled, and set back to the disable state after calibration is done + // If the clock is already on, then do nothing + bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_enable(); + } + + bool rc_fast_enabled = clk_ll_rc_fast_is_enabled(); + bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled(); + if (cal_clk == RTC_CAL_RC_FAST) { + if (!rc_fast_enabled) { + rtc_clk_8m_enable(true); + } + if (!dig_rc_fast_enabled) { + rtc_dig_clk8m_enable(); + } + } + + bool rc32k_enabled = clk_ll_rc32k_is_enabled(); + bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled(); + if (cal_clk == RTC_CAL_RC32K) { + if (!rc32k_enabled) { + rtc_clk_rc32k_enable(true); + } + if (!dig_rc32k_enabled) { + clk_ll_rc32k_digi_enable(); + } + } + + /* There may be another calibration process already running during we call this function, + * so we should wait the last process is done. + */ + if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) { + /** + * Set a small timeout threshold to accelerate the generation of timeout. + * The internal circuit will be reset when the timeout occurs and will not affect the next calibration. + */ + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, 1); + while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY) + && !GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)); + } + + /* Prepare calibration */ + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel); + CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING); + REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles); + /* Figure out how long to wait for calibration to finish */ + + /* Set timeout reg and expect time delay*/ + uint32_t expected_freq; + if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; + } else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX; + } else { + REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles)); + expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX; + } + uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq); + /* Start calibration */ + CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); + SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); + + /* Wait for calibration to finish up to another us_time_estimate */ + esp_rom_delay_us(us_time_estimate); + uint32_t cal_val; + while (true) { + if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) { + cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE); + + /*The Fosc CLK of calibration circuit is divided by 32 for ECO1. + So we need to multiply the frequency of the Fosc for ECO1 and above chips by 32 times. + And ensure that this modification will not affect ECO0.*/ + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { + if (cal_clk == RTC_CAL_RC_FAST) { + cal_val = cal_val >> 5; + } + } + break; + } + if (GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) { + cal_val = 0; + break; + } + } + CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START); + + /* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */ + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) { + clk_ll_xtal32k_digi_disable(); + } + + if (cal_clk == RTC_CAL_RC_FAST) { + if (!dig_rc_fast_enabled) { + rtc_dig_clk8m_disable(); + } + if (!rc_fast_enabled) { + rtc_clk_8m_enable(false); + } + } + + if (cal_clk == RTC_CAL_RC32K) { + if (!dig_rc32k_enabled) { + clk_ll_rc32k_digi_disable(); + } + if (!rc32k_enabled) { + rtc_clk_rc32k_enable(false); + } + } + + // Always set back the calibration 32kHz clock selection + if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) { + clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel); + } + + return cal_val; +} + +static bool rtc_clk_cal_32k_valid(soc_xtal_freq_t xtal_freq, uint32_t slowclk_cycles, uint64_t actual_xtal_cycles) +{ + uint64_t expected_xtal_cycles = (xtal_freq * 1000000ULL * slowclk_cycles) >> 15; // xtal_freq(hz) * slowclk_cycles / 32768 + uint64_t delta = expected_xtal_cycles / 2000; // 5/10000 = 0.05% error range + return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta)); +} + +uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) +{ + soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get(); + + /*The Fosc CLK of calibration circuit is divided by 32 for ECO1. + So we need to divide the calibrate cycles of the FOSC for ECO1 and above chips by 32 to + avoid excessive calibration time.*/ + if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) { + if (cal_clk == RTC_CAL_RC_FAST) { + slowclk_cycles = slowclk_cycles >> 5; + } + } + + uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles); + + if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid(xtal_freq, slowclk_cycles, xtal_cycles)) { + return 0; + } + + uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles; + uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider; + uint32_t period = (uint32_t)(period_64 & UINT32_MAX); + return period; +} + +uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period) +{ + /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days. + * TODO: fix overflow. + */ + return (time_in_us << RTC_CLK_CAL_FRACT) / period; +} + +uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period) +{ + return (rtc_cycles * period) >> RTC_CLK_CAL_FRACT; +} + +uint64_t rtc_time_get(void) +{ + ESP_EARLY_LOGW(TAG, "rtc_timer has not been implemented yet"); + return 0; + //TODO: [ESP32H4] IDF-11548 + // return lp_timer_hal_get_cycle_count(); +} + +uint32_t rtc_clk_freq_cal(uint32_t cal_val) +{ + if (cal_val == 0) { + return 0; // cal_val will be denominator, return 0 as the symbol of failure. + } + return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val; +} + +/// @brief if the calibration is used, we need to enable the timer group0 first +__attribute__((constructor)) +static void enable_timer_group0_for_calibration(void) +{ + PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_TIMG0_MODULE, ref_count) { + if (ref_count == 0) { + timer_ll_enable_bus_clock(0, true); + timer_ll_reset_register(0); + } + } +} diff --git a/components/esp_hw_support/port/esp32h4/systimer.c b/components/esp_hw_support/port/esp32h4/systimer.c new file mode 100644 index 0000000000..e198f77588 --- /dev/null +++ b/components/esp_hw_support/port/esp32h4/systimer.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_private/systimer.h" + +/** + * @brief When systimer's clock source is XTAL (32MHz), it has a fixed fractional divider (2). + * So the resolution of the systimer is 32MHz/2 = 16MHz. + */ +uint64_t systimer_ticks_to_us(uint64_t ticks) +{ + return ticks / 16; +} + +uint64_t systimer_us_to_ticks(uint64_t us) +{ + return us * 16; +} diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/.gitkeep b/components/esp_rom/esp32h4/include/esp32h4/rom/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/gpio.h b/components/esp_rom/esp32h4/include/esp32h4/rom/gpio.h index e75705a5d6..eb647fb3f1 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/gpio.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/gpio.h @@ -6,6 +6,10 @@ #pragma once +#include +#include +#include "soc/gpio_reg.h" + //TODO: [ESP32H4] IDF-12390 inherit from verification branch, need check #ifdef __cplusplus diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/rtc.h b/components/esp_rom/esp32h4/include/esp32h4/rom/rtc.h index 33702103c7..d27c73a695 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/rtc.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/rtc.h @@ -102,7 +102,6 @@ typedef enum { ESP_STATIC_ASSERT((soc_reset_reason_t)POWERON_RESET == RESET_REASON_CHIP_POWER_ON, "POWERON_RESET != RESET_REASON_CHIP_POWER_ON"); ESP_STATIC_ASSERT((soc_reset_reason_t)RTC_SW_SYS_RESET == RESET_REASON_CORE_SW, "RTC_SW_SYS_RESET != RESET_REASON_CORE_SW"); ESP_STATIC_ASSERT((soc_reset_reason_t)DEEPSLEEP_RESET == RESET_REASON_CORE_DEEP_SLEEP, "DEEPSLEEP_RESET != RESET_REASON_CORE_DEEP_SLEEP"); -ESP_STATIC_ASSERT((soc_reset_reason_t)SDIO_RESET == RESET_REASON_CORE_SDIO, "SDIO_RESET != RESET_REASON_CORE_SDIO"); ESP_STATIC_ASSERT((soc_reset_reason_t)TG0WDT_SYS_RESET == RESET_REASON_CORE_MWDT0, "TG0WDT_SYS_RESET != RESET_REASON_CORE_MWDT0"); ESP_STATIC_ASSERT((soc_reset_reason_t)TG1WDT_SYS_RESET == RESET_REASON_CORE_MWDT1, "TG1WDT_SYS_RESET != RESET_REASON_CORE_MWDT1"); ESP_STATIC_ASSERT((soc_reset_reason_t)RTCWDT_SYS_RESET == RESET_REASON_CORE_RTC_WDT, "RTCWDT_SYS_RESET != RESET_REASON_CORE_RTC_WDT"); diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h b/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h index 2e4b3ce904..3e67bf0993 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/secure_boot.h @@ -10,7 +10,6 @@ #include #include "ets_sys.h" #include "ecdsa.h" -#include "rsa_pss.h" #include "esp_assert.h" #ifdef __cplusplus diff --git a/components/hal/esp32h4/include/hal/cache_ll.h b/components/hal/esp32h4/include/hal/cache_ll.h index acfc4a0194..7400517e71 100644 --- a/components/hal/esp32h4/include/hal/cache_ll.h +++ b/components/hal/esp32h4/include/hal/cache_ll.h @@ -13,7 +13,7 @@ #include "soc/ext_mem_defs.h" #include "hal/cache_types.h" #include "hal/assert.h" -#include "esp32h4/rom/cache.h" +#include "rom/cache.h" //TODO: [ESP32H4] IDF-12289 inherited from verification branch, need check diff --git a/components/hal/esp32h4/include/hal/lpwdt_ll.h b/components/hal/esp32h4/include/hal/lpwdt_ll.h index a16dfc1cca..89e1d2975e 100644 --- a/components/hal/esp32h4/include/hal/lpwdt_ll.h +++ b/components/hal/esp32h4/include/hal/lpwdt_ll.h @@ -24,7 +24,7 @@ extern "C" { #include "esp_attr.h" #include "esp_assert.h" -#include "esp32h4/rom/ets_sys.h" +#include "rom/ets_sys.h" /* The value that needs to be written to LP_WDT_WPROTECT_REG to write-enable the wdt registers */ #define LP_WDT_WKEY_VALUE 0x50D83AA1 diff --git a/components/hal/include/hal/rtc_hal.h b/components/hal/include/hal/rtc_hal.h index d744dfde89..7c1946e3a6 100644 --- a/components/hal/include/hal/rtc_hal.h +++ b/components/hal/include/hal/rtc_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,11 +11,10 @@ #include "hal/gpio_types.h" #include "sdkconfig.h" -#if !CONFIG_IDF_TARGET_ESP32H21 //TODO: [ESP32H21] IDF-11512 -#if !SOC_LP_TIMER_SUPPORTED +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #include "hal/rtc_cntl_ll.h" #endif -#endif //#if !CONFIG_IDF_TARGET_ESP32H21 + #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED #include "hal/rtc_io_ll.h" #endif diff --git a/components/hal/include/hal/sha_types.h b/components/hal/include/hal/sha_types.h index 2d74f8e9ed..360cda5636 100644 --- a/components/hal/include/hal/sha_types.h +++ b/components/hal/include/hal/sha_types.h @@ -31,6 +31,8 @@ #include "esp32h21/rom/sha.h" #elif CONFIG_IDF_TARGET_ESP32P4 #include "esp32p4/rom/sha.h" +#elif CONFIG_IDF_TARGET_ESP32H4 +#include "esp32h4/rom/sha.h" #endif #ifdef __cplusplus diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 9778efba9f..b2809034da 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -139,6 +139,14 @@ config SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP bool default y +config SOC_GPIO_IN_RANGE_MAX + int + default 39 + +config SOC_GPIO_OUT_RANGE_MAX + int + default 39 + config SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK int default 0 diff --git a/components/soc/esp32h4/include/soc/gdma_channel.h b/components/soc/esp32h4/include/soc/gdma_channel.h new file mode 100644 index 0000000000..1cfa7a9fcb --- /dev/null +++ b/components/soc/esp32h4/include/soc/gdma_channel.h @@ -0,0 +1,5 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index 1a01330449..ec4dd9fd20 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -203,6 +203,10 @@ #define SOC_GPIO_VALID_GPIO_MASK ((1ULL<