diff --git a/components/esp_hal_clock/esp32h21/clk_tree_hal.c b/components/esp_hal_clock/esp32h21/clk_tree_hal.c index bc2f1059ea7..0b589731821 100644 --- a/components/esp_hal_clock/esp32h21/clk_tree_hal.c +++ b/components/esp_hal_clock/esp32h21/clk_tree_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -65,3 +65,13 @@ uint32_t clk_hal_xtal_get_freq_mhz(void) HAL_ASSERT(freq == SOC_XTAL_FREQ_32M); return freq; } + +void clk_hal_clock_output_setup(soc_clkout_sig_id_t clk_sig, clock_out_channel_t channel_id) +{ + clk_ll_bind_output_channel(clk_sig, channel_id); +} + +void clk_hal_clock_output_teardown(clock_out_channel_t channel_id) +{ + clk_ll_bind_output_channel(0, channel_id); +} diff --git a/components/esp_hal_clock/esp32h21/include/hal/clk_tree_ll.h b/components/esp_hal_clock/esp32h21/include/hal/clk_tree_ll.h index 2c938c289a4..76bcab352b4 100644 --- a/components/esp_hal_clock/esp32h21/include/hal/clk_tree_ll.h +++ b/components/esp_hal_clock/esp32h21/include/hal/clk_tree_ll.h @@ -10,7 +10,9 @@ #include "soc/soc.h" #include "soc/clk_tree_defs.h" #include "soc/pcr_struct.h" +#include "soc/gpio_ext_reg.h" #include "soc/lp_clkrst_struct.h" +#include "hal/clkout_channel.h" #include "soc/pmu_reg.h" #include "hal/regi2c_ctrl.h" #include "soc/regi2c_bbpll.h" @@ -622,6 +624,69 @@ static inline __attribute__((always_inline)) uint32_t clk_ll_rtc_slow_load_cal(v return REG_READ(RTC_SLOW_CLK_CAL_REG); } +/************************** CLOCK OUTPUT **************************/ +/** + * @brief Clock output channel configuration + * + * @param clk_sig The clock signal source to be mapped to GPIOs + * @param channel_id The clock output channel ID + */ +static inline __attribute__((always_inline)) void clk_ll_bind_output_channel(soc_clkout_sig_id_t clk_sig, clock_out_channel_t channel_id) +{ + SET_PERI_REG_BITS(GPIO_EXT_PIN_CTRL_REG, CLKOUT_CHANNEL_MASK(channel_id), clk_sig, CLKOUT_CHANNEL_SHIFT(channel_id)); +} + +/** + * @brief Enable the clock output channel + * + * @param channel_id The clock output channel ID + * @param enable Enable or disable the clock output channel + */ +static inline __attribute__((always_inline)) void clk_ll_enable_output_channel(clock_out_channel_t channel_id, bool enable) +{ + // No such gating on the target + (void)channel_id; + (void)enable; +} + +/** + * @brief Output the mapped clock after frequency division + * + * @param channel_id The clock output channel ID + * @param divider Clock frequency division value + */ +static inline __attribute__((always_inline)) void clk_ll_set_output_channel_divider(clock_out_channel_t channel_id, uint32_t divider) +{ + // No divider on the target + HAL_ASSERT(divider == 1); +} + +/** + * @brief Enable/Disable the clock gate for clock output signal source + * + * @param clk_src The clock output signal source + * @param en Enable or disable the clock output signal source + */ +static inline void clk_ll_enable_clkout_source(soc_clkout_sig_id_t clk_src, bool en) +{ + switch (clk_src) { + case CLKOUT_SIG_MODEM_8M: + PCR.ctrl_clk_out_en.clk8_oen = en; + break; + case CLKOUT_SIG_MODEM_16M: + PCR.ctrl_clk_out_en.clk16_oen = en; + break; + case CLKOUT_SIG_MODEM_32M: + PCR.ctrl_clk_out_en.clk32_oen = en; + break; + case CLKOUT_SIG_XTAL: + PCR.ctrl_clk_out_en.clk_xtal_oen = en; + break; + default: + break; + } +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_clock/esp32h21/include/hal/clkout_channel.h b/components/esp_hal_clock/esp32h21/include/hal/clkout_channel.h new file mode 100644 index 00000000000..582c5dda4e7 --- /dev/null +++ b/components/esp_hal_clock/esp32h21/include/hal/clkout_channel.h @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_assert.h" +#include "soc/soc_caps.h" +#include "soc/gpio_ext_reg.h" +#include "soc/gpio_sig_map.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum clock_out_channel { + CLKOUT_CHANNEL_1, + CLKOUT_CHANNEL_2, + CLKOUT_CHANNEL_3, + CLKOUT_CHANNEL_MAX, +} clock_out_channel_t; + +#define CLKOUT_CHANNEL_TO_GPIO_SIG_ID(channel) ((channel == CLKOUT_CHANNEL_1) ? CLK_OUT_OUT1_IDX : \ + (channel == CLKOUT_CHANNEL_2) ? CLK_OUT_OUT2_IDX : \ + (channel == CLKOUT_CHANNEL_3) ? CLK_OUT_OUT3_IDX : SIG_GPIO_OUT_IDX) + +#define CLKOUT_CHANNEL_MASK(channel) ((channel == CLKOUT_CHANNEL_1) ? GPIO_EXT_CLK_OUT1 : \ + (channel == CLKOUT_CHANNEL_2) ? GPIO_EXT_CLK_OUT2 : \ + (channel == CLKOUT_CHANNEL_3) ? GPIO_EXT_CLK_OUT3 : 0) + +#define CLKOUT_CHANNEL_SHIFT(channel) ((channel == CLKOUT_CHANNEL_1) ? GPIO_EXT_CLK_OUT1_S : \ + (channel == CLKOUT_CHANNEL_2) ? GPIO_EXT_CLK_OUT2_S : \ + (channel == CLKOUT_CHANNEL_3) ? GPIO_EXT_CLK_OUT3_S : 0) + +ESP_STATIC_ASSERT(CLKOUT_CHANNEL_MAX == SOC_GPIO_CLOCKOUT_CHANNEL_NUM, "clock_out_channel enumeration mismatch"); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hal_clock/include/hal/clk_tree_hal.h b/components/esp_hal_clock/include/hal/clk_tree_hal.h index 16b05caf19a..b85915fb7ad 100644 --- a/components/esp_hal_clock/include/hal/clk_tree_hal.h +++ b/components/esp_hal_clock/include/hal/clk_tree_hal.h @@ -10,7 +10,7 @@ #include "soc/clk_tree_defs.h" #include "soc/soc_caps.h" -#if SOC_GPIO_CLOCKOUT_CHANNEL_NUM > 0 //TODO: [ESP32H21] IDF-11582 +#if SOC_GPIO_CLOCKOUT_CHANNEL_NUM > 0 #include "hal/clkout_channel.h" #endif @@ -71,7 +71,7 @@ uint32_t clk_hal_xtal_get_freq_mhz(void); uint32_t clk_hal_apll_get_freq_hz(void); #endif //SOC_CLK_APLL_SUPPORTED -#if SOC_GPIO_CLOCKOUT_CHANNEL_NUM > 0 //TODO: [ESP32H21] IDF-11582 +#if SOC_GPIO_CLOCKOUT_CHANNEL_NUM > 0 /** * @brief Set up clock output channel * @param clk_sig The clock signal source to be mapped to GPIOs diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 17f25e4fd10..38d6d3f9f52 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -471,6 +471,18 @@ config SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP bool default y +config SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX + bool + default y + +config SOC_CLOCKOUT_HAS_SOURCE_GATE + bool + default y + +config SOC_GPIO_CLOCKOUT_CHANNEL_NUM + int + default 3 + config SOC_SDM_SUPPORT_SLEEP_RETENTION bool default y diff --git a/components/soc/esp32h21/include/soc/clk_tree_defs.h b/components/soc/esp32h21/include/soc/clk_tree_defs.h index 487cf075a1b..20ff36aaa1e 100644 --- a/components/soc/esp32h21/include/soc/clk_tree_defs.h +++ b/components/soc/esp32h21/include/soc/clk_tree_defs.h @@ -431,17 +431,23 @@ typedef enum { } soc_periph_mwdt_clk_src_t; //////////////////////////////////////////////CLOCK OUTPUT/////////////////////////////////////////////////////////// +/** + * @brief Clock output signal ID + */ typedef enum { - CLKOUT_SIG_XTAL = 5, /*!< Main crystal oscillator clock */ - CLKOUT_SIG_CPU = 16, /*!< CPU clock */ - CLKOUT_SIG_AHB = 17, /*!< AHB clock */ - CLKOUT_SIG_APB = 18, /*!< APB clock */ - CLKOUT_SIG_XTAL32K = 21, /*!< External 32kHz crystal clock */ - CLKOUT_SIG_EXT32K = 22, /*!< External slow clock input through XTAL_32K_P */ - CLKOUT_SIG_RC_FAST = 23, /*!< RC fast clock, about 17.5MHz */ - CLKOUT_SIG_RC_32K = 24, /*!< Internal slow RC oscillator */ - CLKOUT_SIG_RC_SLOW = 25, /*!< RC slow clock, depends on the RTC_CLK_SRC configuration */ - CLKOUT_SIG_INVALID = 0xFF, + CLKOUT_SIG_MODEM_32M = 0x0, /*!< 32MHz clock for modem (clk8M) */ + CLKOUT_SIG_MODEM_16M = 0x1, /*!< 16MHz clock for modem (clk16) */ + CLKOUT_SIG_MODEM_8M = 0x2, /*!< 8MHz clock for modem (clk32) */ + CLKOUT_SIG_XTAL = 0x6, /*!< 32MHz CPU debug mode clock */ + CLKOUT_SIG_RTC_FAST = 0xA, /*!< RTC fast clock from LP system */ + CLKOUT_SIG_CPU = 0xB, /*!< CPU clock */ + CLKOUT_SIG_AHB = 0xC, /*!< AHB clock */ + CLKOUT_SIG_APB = 0xD, /*!< APB clock */ + CLKOUT_SIG_XTAL32K = 0x10, /*!< 32KHz external crystal clock */ + CLKOUT_SIG_EXT32K = 0x11, /*!< 32KHz external slow clock input */ + CLKOUT_SIG_RC_FAST = 0x12, /*!< 20MHz FOSC clock (RTC fast clock) */ + CLKOUT_SIG_RC_SLOW = 0x13, /*!< 600KHz SOSC clock (RTC slow clock) */ + CLKOUT_SIG_INVALID = 0xFF, } soc_clkout_sig_id_t; //////////////////////////////////////////////////FLASH/////////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index f4749010f38..10906954843 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -216,9 +216,9 @@ #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) // The Clock Out signal is route to the pin by GPIO matrix -// #define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1) -// #define SOC_CLOCKOUT_HAS_SOURCE_GATE (1) -// #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) +#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1) +#define SOC_CLOCKOUT_HAS_SOURCE_GATE (1) +#define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) /*-------------------------- Sigma Delta Modulator CAPS -----------------*/ #define SOC_SDM_SUPPORT_SLEEP_RETENTION 1