feat(esp_hw_support): support clock output in esp32h21

This commit is contained in:
hebinglin
2026-06-09 14:16:05 +08:00
parent 76db2bf06d
commit eb6bb0acf0
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