Merge branch 'feat/support_s31_clock_output' into 'master'

feat(esp_hw_support): support esp32s31 esp_clock_output

Closes IDF-14733

See merge request espressif/esp-idf!47271
This commit is contained in:
Wu Zheng Hui
2026-04-14 21:24:29 +08:00
6 changed files with 251 additions and 17 deletions
@@ -84,3 +84,15 @@ uint32_t clk_hal_apll_get_freq_hz(void)
uint32_t apll_freq_hz = (uint32_t)((xtal_freq_hz * numerator) / denominator);
return apll_freq_hz;
}
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);
clk_ll_set_output_channel_divider(channel_id, 1);
clk_ll_enable_output_channel(channel_id, true);
}
void clk_hal_clock_output_teardown(clock_out_channel_t channel_id)
{
clk_ll_enable_output_channel(channel_id, false);
}
@@ -17,6 +17,7 @@
#include "soc/hp_alive_sys_reg.h"
#include "soc/hp_alive_sys_struct.h"
#include "soc/pmu_reg.h"
#include "hal/clkout_channel.h"
#include "hal/assert.h"
#include "hal/log.h"
#include "esp32s31/rom/rtc.h"
@@ -900,6 +901,81 @@ static inline __attribute__((always_inline)) void clk_ll_rc_slow_set_divider(uin
HAL_ASSERT(divider == 1);
}
/************************** CLOCK OUTPUT **************************/
/**
* @brief Clock output channel configuration
*
* @param clk_sig The clock signal source to be mapped to GPIOs (raw `reg_dbg_chX_sel` mux index)
* @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)
{
switch (channel_id) {
case CLKOUT_CHANNEL_1:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg0_clk_ctrl0, reg_dbg_ch0_sel, clk_sig);
break;
case CLKOUT_CHANNEL_2:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg1_clk_ctrl0, reg_dbg_ch1_sel, clk_sig);
break;
case CLKOUT_CHANNEL_3:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg2_clk_ctrl0, reg_dbg_ch2_sel, clk_sig);
break;
default:
HAL_ASSERT(false && "invalid clock output channel");
break;
}
}
/**
* @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)
{
switch (channel_id) {
case CLKOUT_CHANNEL_1:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg0_clk_ctrl0, reg_dbg_ch0_en, enable);
break;
case CLKOUT_CHANNEL_2:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg1_clk_ctrl0, reg_dbg_ch1_en, enable);
break;
case CLKOUT_CHANNEL_3:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg2_clk_ctrl0, reg_dbg_ch2_en, enable);
break;
default:
HAL_ASSERT(false && "invalid clock output channel");
break;
}
}
/**
* @brief Output the mapped clock after frequency division
*
* @param channel_id The clock output channel ID
* @param div_num Divider value N such that output frequency is (input / N). Written to hardware as (N - 1).
* Must be in [1, 256] to match the 8-bit `reg_dbg_chX_div_num` field.
*/
static inline __attribute__((always_inline)) void clk_ll_set_output_channel_divider(clock_out_channel_t channel_id, uint32_t div_num)
{
HAL_ASSERT(div_num >= 1 && div_num <= 256);
switch (channel_id) {
case CLKOUT_CHANNEL_1:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg0_clk_ctrl0, reg_dbg_ch0_div_num, div_num - 1);
break;
case CLKOUT_CHANNEL_2:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg1_clk_ctrl0, reg_dbg_ch1_div_num, div_num - 1);
break;
case CLKOUT_CHANNEL_3:
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.dbg2_clk_ctrl0, reg_dbg_ch2_div_num, div_num - 1);
break;
default:
HAL_ASSERT(false && "invalid clock output channel");
break;
}
}
/************************** LP STORAGE REGISTER STORE/LOAD **************************/
/**
* @brief Store RTC_SLOW_CLK calibration value in RTC storage register
@@ -0,0 +1,34 @@
/*
* 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/io_mux_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) ? DBG_CH0_CLK_IDX : \
(channel == CLKOUT_CHANNEL_2) ? DBG_CH1_CLK_IDX : \
(channel == CLKOUT_CHANNEL_3) ? DBG_CH2_CLK_IDX : \
SIG_GPIO_OUT_IDX)
ESP_STATIC_ASSERT(CLKOUT_CHANNEL_MAX == SOC_GPIO_CLOCKOUT_CHANNEL_NUM, "clock_out_channel enumeration mismatch");
#ifdef __cplusplus
}
#endif
@@ -359,6 +359,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_GPIO_CLOCKOUT_CHANNEL_NUM
int
default 3
config SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER
bool
default y
config SOC_RTCIO_PIN_COUNT
int
default 8
@@ -399,23 +399,118 @@ typedef enum {
//////////////////////////////////////////////CLOCK OUTPUT///////////////////////////////////////////////////////////
typedef enum {
CLKOUT_SIG_MPLL = 0, /*!< MPLL is from 40MHz XTAL oscillator frequency multipliers */
CLKOUT_SIG_BBPLL = 1, /*!< BBPLL is from 40MHz XTAL oscillator frequency multipliers, its default frequency is 480MHz */
CLKOUT_SIG_CPLL = 2, /*!< CPLL_CLK is the output of 40MHz crystal oscillator frequency multiplier, can be 320MHz */
CLKOUT_SIG_XTAL = 3, /*!< External 40MHz crystal */
CLKOUT_SIG_RC_FAST = 4, /*!< Internal 17.5MHz RC oscillator */
CLKOUT_SIG_RC_SLOW = 5, /*!< Internal 136kHz RC oscillator */
CLKOUT_SIG_RC_32K = 6, /*!< Internal 32kHz RC oscillator */
CLKOUT_SIG_XTAL32K = 7, /*!< External 32kHz crystal clock */
CLKOUT_SIG_I2S0 = 16, /*!< I2S0 clock, depends on the i2s driver configuration */
CLKOUT_SIG_I2S1 = 17, /*!< I2S1 clock, depends on the i2s driver configuration */
CLKOUT_SIG_I2S2 = 18, /*!< I2S2 clock, depends on the i2s driver configuration */
CLKOUT_SIG_CPU = 26, /*!< CPU clock */
CLKOUT_SIG_MEM = 27, /*!< MEM clock */
CLKOUT_SIG_SYS = 28, /*!< SYS clock */
CLKOUT_SIG_APB = 29, /*!< APB clock */
CLKOUT_SIG_PLL_F80M = 105, /*!< From PLL, usually be 80MHz */
CLKOUT_SIG_INVALID = 0xFF,
CLKOUT_SIG_MPLL_500M = 0, /*!< MPLL output at 500MHz */
CLKOUT_SIG_BBPLL_480M = 1, /*!< BBPLL output at 480MHz */
CLKOUT_SIG_CPLL_300M = 2, /*!< CPLL output at 300MHz */
CLKOUT_SIG_XTAL_40M = 3, /*!< Main crystal clock at 40MHz */
CLKOUT_SIG_FOSC_20M = 4, /*!< Fast RC oscillator ; nominally ~20MHz */
CLKOUT_SIG_SOSC_600KD4 = 5, /*!< Slow RC oscillator ; ~150kHz before RTC divider path, used for RTC slow timing */
CLKOUT_SIG_RC_32K = 6, /*!< Internal ~32kHz RC oscillator output (low-precision; not recommended for applications) */
CLKOUT_SIG_XTAL_32K = 7, /*!< External 32kHz crystal clock (XTAL32K on XTAL_32K_P/N) */
CLKOUT_SIG_ANA_PLL_80M = 8, /*!< 80MHz analog PLL */
CLKOUT_SIG_USB_OTGHS_PHYREF = 9, /*!< USB OTG HS PHY reference clock output for the high-speed PHY */
CLKOUT_SIG_USB_OTGHS_ULPI = 10, /*!< USB OTG HS ULPI interface clock output */
CLKOUT_SIG_MCPWM2 = 11, /*!< MCPWM 2 module clock */
CLKOUT_SIG_MCPWM3 = 12, /*!< MCPWM 3 module clock */
CLKOUT_SIG_CORE0_CLIC = 13, /*!< Core 0 clock */
CLKOUT_SIG_CORE1_CLIC = 14, /*!< Core 1 clock */
CLKOUT_SIG_AUDIO_PLL = 15, /*!< Audio PLL (APLL) output; frequency set via APLL configuration registers */
CLKOUT_SIG_PAD_I2S0_MCLK = 16, /*!< I2S0 master clock */
CLKOUT_SIG_PAD_I2S1_MCLK = 17, /*!< I2S1 master clock */
CLKOUT_SIG_USB_DEVICE_INTPHY = 18, /*!< Full-speed USB device internal PHY clock */
CLKOUT_SIG_PAD_UART0_SLP = 19, /*!< UART0 sleep pad clock */
CLKOUT_SIG_PAD_UART1_SLP = 20, /*!< UART1 sleep pad clock */
CLKOUT_SIG_PAD_UART2_SLP = 21, /*!< UART2 sleep pad clock */
CLKOUT_SIG_PAD_UART3_SLP = 22, /*!< UART3 sleep pad clock */
CLKOUT_SIG_USB_DEVICE_48M = 23, /*!< USB device 48MHz functional clock output */
CLKOUT_SIG_PAD_PARLIO_RX = 24, /*!< Parallel IO (PARLIO) RX clock */
CLKOUT_SIG_PAD_PARLIO_TX = 25, /*!< Parallel IO (PARLIO) TX clock */
CLKOUT_SIG_TCELL_CPU = 26, /*!< CPU domain clock */
CLKOUT_SIG_TCELL_MEM = 27, /*!< memory subsystem clock */
CLKOUT_SIG_TCELL_SYS = 28, /*!< system bus clock */
CLKOUT_SIG_TCELL_APB = 29, /*!< APB peripheral bus clock */
CLKOUT_SIG_FLASH_PLL = 30, /*!< MSPI flash PLL */
CLKOUT_SIG_FLASH_CORE = 31, /*!< MSPI flash controller core clock */
CLKOUT_SIG_PSRAM_PLL = 32, /*!< MSPI PSRAM PLL clock */
CLKOUT_SIG_PSRAM_CORE = 33, /*!< MSPI PSRAM controller core clock */
CLKOUT_SIG_ULPI_CLK_PAD_OUT = 34, /*!< ULPI clock forwarded to pad output */
CLKOUT_SIG_SDIO_SLF = 38, /*!< SDIO slave */
CLKOUT_SIG_SDIO_DRV = 39, /*!< sdio_drv_clk_o */
CLKOUT_SIG_SDIO_SAM = 40, /*!< sdio_sam_clk_o */
CLKOUT_SIG_I2C0 = 44, /*!< I2C0 peripheral module clock */
CLKOUT_SIG_I2C1 = 45, /*!< I2C1 peripheral module clock */
CLKOUT_SIG_I2S0_RX = 46, /*!< I2S0 rx clock */
CLKOUT_SIG_I2S0_TX = 47, /*!< I2S0 tx clock */
CLKOUT_SIG_I2S1_RX = 48, /*!< I2S1 rx clock */
CLKOUT_SIG_I2S1_TX = 49, /*!< I2S1 tx clock */
CLKOUT_SIG_LCD = 52, /*!< LCD controller module clock */
CLKOUT_SIG_UART0_SCLK = 53, /*!< UART0 source clock */
CLKOUT_SIG_UART0_FCLK = 54, /*!< UART0 functional clock */
CLKOUT_SIG_UART0_SLP = 55, /*!< UART0 sleep clock */
CLKOUT_SIG_UART1_SCLK = 56, /*!< UART1 source clock */
CLKOUT_SIG_UART1_FCLK = 57, /*!< UART1 functional clock */
CLKOUT_SIG_UART1_SLP = 58, /*!< UART1 sleep clock */
CLKOUT_SIG_UART2_SCLK = 59, /*!< UART2 source clock */
CLKOUT_SIG_UART2_FCLK = 60, /*!< UART2 functional clock */
CLKOUT_SIG_UART2_SLP = 61, /*!< UART2 sleep clock */
CLKOUT_SIG_UART3_SCLK = 62, /*!< UART3 source clock */
CLKOUT_SIG_UART3_FCLK = 63, /*!< UART3 functional clock */
CLKOUT_SIG_UART3_SLP = 64, /*!< UART3 sleep clock */
CLKOUT_SIG_CORDIC_CORE = 65, /*!< CORDIC accelerator core clock */
CLKOUT_SIG_ZERO_DET_CORE = 66, /*!< Zero-cross / zero-detection peripheral core clock */
CLKOUT_SIG_TWAI0 = 68, /*!< TWAI0 module clock */
CLKOUT_SIG_TWAI1 = 69, /*!< TWAI1 module clock */
CLKOUT_SIG_GPSPI2_HS = 71, /*!< SPI2 high-speed clock */
CLKOUT_SIG_GPSPI2_MST = 72, /*!< SPI2 master functional clock */
CLKOUT_SIG_GPSPI3_HS = 73, /*!< SPI3 high-speed clock */
CLKOUT_SIG_GPSPI3_MST = 74, /*!< SPI3 master functional clock */
CLKOUT_SIG_PARLIO_RX = 75, /*!< PARLIO RX clock */
CLKOUT_SIG_PARLIO_TX = 76, /*!< PARLIO TX clock */
CLKOUT_SIG_MCPWM0 = 78, /*!< MCPWM0 module clock */
CLKOUT_SIG_MCPWM1 = 79, /*!< MCPWM1 module clock */
CLKOUT_SIG_TIMERGRP0_T0 = 80, /*!< Timer group 0, timer 0 module clock */
CLKOUT_SIG_TIMERGRP0_T1 = 81, /*!< Timer group 0, timer 1 module clock */
CLKOUT_SIG_TIMERGRP0_WDT = 82, /*!< Timer group 0 watchdog module clock */
CLKOUT_SIG_TIMERGRP1_T0 = 83, /*!< Timer group 1, timer 0 module clock */
CLKOUT_SIG_TIMERGRP1_T1 = 84, /*!< Timer group 1, timer 1 module clock */
CLKOUT_SIG_TIMERGRP1_WDT = 85, /*!< Timer group 1 watchdog module clock */
CLKOUT_SIG_SYSTIMER = 86, /*!< System timer module clock */
CLKOUT_SIG_LEDC0 = 87, /*!< LED PWM controller instance 0 module clock */
CLKOUT_SIG_RMT = 88, /*!< RMT peripheral module clock */
CLKOUT_SIG_ADC = 89, /*!< ADC module clock */
CLKOUT_SIG_ADC_SAR1 = 90, /*!< SAR_ADC1 clock */
CLKOUT_SIG_ADC_SAR2 = 91, /*!< SAR_ADC2 clock */
CLKOUT_SIG_ADC_SAR1_GCLK = 92, /*!< SAR_ADC1 GCLK */
CLKOUT_SIG_ADC_SAR2_GCLK = 93, /*!< SAR_ADC2 GCLK */
CLKOUT_SIG_PVT = 94, /*!< PVT module clock */
CLKOUT_SIG_PVT_PERI_GROUP1 = 95, /*!< PVT peripheral group 1 clock */
CLKOUT_SIG_CRYPTO_SEC = 96, /*!< Security / crypto accelerator module clock */
CLKOUT_SIG_LEDC1 = 97, /*!< LED PWM controller instance 1 module clock */
CLKOUT_SIG_IOMUX = 98, /*!< IO MUX clock */
CLKOUT_SIG_REF_50M = 99, /*!< 50MHz reference clock */
CLKOUT_SIG_REF_120M = 100, /*!< 120MHz reference clock */
CLKOUT_SIG_REF_160M = 101, /*!< 160MHz reference clock */
CLKOUT_SIG_REF_20M = 102, /*!< 20MHz reference clock */
CLKOUT_SIG_REF_240M = 103, /*!< 240MHz reference clock */
CLKOUT_SIG_REF_25M = 104, /*!< 25MHz reference clock */
CLKOUT_SIG_REF_80M = 105, /*!< 80MHz reference clock */
CLKOUT_SIG_REF_60M = 106, /*!< 60MHz reference clock */
/* Short / legacy aliases (identical mux index as the primary names above) */
CLKOUT_SIG_MPLL = CLKOUT_SIG_MPLL_500M, /*!< Legacy short name; same mux as CLKOUT_SIG_MPLL_500M */
CLKOUT_SIG_BBPLL = CLKOUT_SIG_BBPLL_480M, /*!< Legacy short name; same mux as CLKOUT_SIG_BBPLL_480M */
CLKOUT_SIG_CPLL = CLKOUT_SIG_CPLL_300M, /*!< Legacy short name; same mux as CLKOUT_SIG_CPLL_300M */
CLKOUT_SIG_XTAL = CLKOUT_SIG_XTAL_40M, /*!< Legacy short name; same mux as CLKOUT_SIG_XTAL_40M */
CLKOUT_SIG_RC_FAST = CLKOUT_SIG_FOSC_20M, /*!< Legacy name for RC_FAST / FOSC domain; same mux as CLKOUT_SIG_FOSC_20M */
CLKOUT_SIG_RC_SLOW = CLKOUT_SIG_SOSC_600KD4, /*!< Legacy name for RC_SLOW / SOSC domain; same mux as CLKOUT_SIG_SOSC_600KD4 */
CLKOUT_SIG_XTAL32K = CLKOUT_SIG_XTAL_32K, /*!< Legacy short name; same mux as CLKOUT_SIG_XTAL_32K */
CLKOUT_SIG_I2S0 = CLKOUT_SIG_PAD_I2S0_MCLK, /*!< Legacy short name; same mux as CLKOUT_SIG_PAD_I2S0_MCLK */
CLKOUT_SIG_I2S1 = CLKOUT_SIG_PAD_I2S1_MCLK, /*!< Legacy short name; same mux as CLKOUT_SIG_PAD_I2S1_MCLK */
CLKOUT_SIG_CPU = CLKOUT_SIG_TCELL_CPU, /*!< Legacy short name; same mux as CLKOUT_SIG_TCELL_CPU */
CLKOUT_SIG_MEM = CLKOUT_SIG_TCELL_MEM, /*!< Legacy short name; same mux as CLKOUT_SIG_TCELL_MEM */
CLKOUT_SIG_SYS = CLKOUT_SIG_TCELL_SYS, /*!< Legacy short name; same mux as CLKOUT_SIG_TCELL_SYS */
CLKOUT_SIG_APB = CLKOUT_SIG_TCELL_APB, /*!< Legacy short name; same mux as CLKOUT_SIG_TCELL_APB */
CLKOUT_SIG_PLL_F80M = CLKOUT_SIG_REF_80M, /*!< Legacy name; same mux as CLKOUT_SIG_REF_80M (80MHz reference tap) */
CLKOUT_SIG_INVALID = 0xFF, /*!< Invalid mux value; channel disabled or not connected */
} soc_clkout_sig_id_t;
//////////////////////////////////////CLOCK FREQUENCY CALCULATION////////////////////////////////////////////////////
@@ -195,6 +195,11 @@
// Support to hold a single digital I/O when the digital domain is powered off
#define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1)
// Clock-out routed to GPIO via the GPIO matrix
#define SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX (1)
#define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3)
#define SOC_CLOCKOUT_SUPPORT_CHANNEL_DIVIDER (1)
/*-------------------------- RTCIO CAPS --------------------------------------*/
#define SOC_RTCIO_PIN_COUNT 8
#define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 /* This macro indicates that the target has separate RTC IOMUX hardware feature,