Merge branch 'feat/esp_idf_h21_clock_output_support' into 'master'

feat(esp_hw_support): support clock output in esp32h21

Closes PM-785 and IDF-11582

See merge request espressif/esp-idf!49393
This commit is contained in:
He Binglin
2026-06-09 15:26:34 +08:00
7 changed files with 150 additions and 16 deletions
@@ -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);
}
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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///////////////////////////////////////////////////////////////////
@@ -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