feat(esp_eth): add ESP32-S31 EMAC support

Add internal EMAC support for ESP32-S31, including:
- HAL/LL layer: emac_ll, emac_hal, emac_clk, emac_periph for S31
- SOC layer: register structs, soc_caps, peripherals linker script,
  interrupt definitions
- MAC driver: clock source configuration via Kconfig, GPIO/DMA
  adaptations, PHY register defs for clause-45 MDIO
- Ethernet examples updated for S31 (basic, build-test-rules, PTP
  readme)
- Refactored existing ESP32/ESP32-P4 EMAC code for shared patterns
  (emac_clk extraction, struct alignment, periph descriptor cleanup)
This commit is contained in:
Ondrej Kosta
2026-05-21 15:59:42 +08:00
parent c7d6c41198
commit edbf8856ae
39 changed files with 3558 additions and 173 deletions
@@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/emac_clk.h"
/* MPLL VCO frequency step for targets that program MPLL from the 40 MHz XTAL (see clk_ll_mpll_set_*). */
#define EMAC_MPLL_GRID_STEP_HZ (20000000)
#define EMAC_MPLL_GRID_MAX_STEPS (32)
static const emac_clk_info_t emac_clk_mpll = {
.clk_id = SOC_MOD_CLK_MPLL,
.step_hz = EMAC_MPLL_GRID_STEP_HZ,
.max_steps = EMAC_MPLL_GRID_MAX_STEPS,
.clk_name = "MPLL",
};
const emac_clk_internal_info_t emac_clk_internal = {
.clk_count = 0,
.clk_src = NULL,
};
const emac_clk_info_t *emac_clk_phy_ref_src[] = {
&emac_clk_mpll,
};
const emac_clk_phy_ref_info_t emac_clk_phy_ref = {
.derived_clk_id = SOC_MOD_CLK_PLL_F50M,
.clk_count = sizeof(emac_clk_phy_ref_src) / sizeof(emac_clk_phy_ref_src[0]),
.clk_src = emac_clk_phy_ref_src,
};
@@ -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
*/
@@ -41,6 +41,7 @@ const emac_io_info_t emac_io_idx = {
.mii_rx_er_i_idx = EMAC_PHY_RXER_PAD_IN_IDX,
.rmii_refclk_i_idx = SIG_GPIO_OUT_IDX,
.rmii_refclk_o_idx = SIG_GPIO_OUT_IDX,
.phy_ref_clk_o_idx = SIG_GPIO_OUT_IDX,
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
.ptp_pps_idx = EMAC_PTP_PPS_PAD_OUT_IDX,
#else
@@ -66,7 +67,7 @@ static const emac_iomux_info_t emac_rmii_iomux_clki[] = {
}
};
static const emac_iomux_info_t emac_rmii_iomux_clko[] = {
static const emac_iomux_info_t emac_rmii_iomux_phy_ref_clk[] = {
[0] = {
.gpio_num = 23,
.func = FUNC_GPIO23_REF_50M_CLK_PAD,
@@ -91,7 +92,7 @@ static const emac_iomux_info_t emac_rmii_iomux_tx_en[] = {
},
[2] = {
.gpio_num = 49,
.func = FUNC_GPIO40_EMAC_PHY_TXEN_PAD,
.func = FUNC_GPIO49_EMAC_PHY_TXEN_PAD,
},
[3] = {
.gpio_num = GPIO_NUM_MAX,
@@ -214,7 +215,7 @@ static const emac_iomux_info_t emac_rmii_iomux_rx_er[] = {
const emac_rmii_iomux_info_t emac_rmii_iomux_pins = {
.clki = emac_rmii_iomux_clki,
.clko = emac_rmii_iomux_clko,
.clko = NULL,
.tx_en = emac_rmii_iomux_tx_en,
.txd0 = emac_rmii_iomux_txd0,
.txd1 = emac_rmii_iomux_txd1,
@@ -225,6 +226,10 @@ const emac_rmii_iomux_info_t emac_rmii_iomux_pins = {
.rx_er = emac_rmii_iomux_rx_er,
};
const emac_ref_clk_iomux_info_t emac_ref_clk_iomux_pins = {
.phy_ref_clk = emac_rmii_iomux_phy_ref_clk,
};
const emac_mii_iomux_info_t emac_mii_iomux_pins = { 0 };
/* Registers in retention context:
@@ -94,6 +94,7 @@ extern "C" {
#define EMAC_LL_DMADESC_OWNER_CPU (0)
#define EMAC_LL_DMADESC_OWNER_DMA (1)
#define EMAC_LL_DMA_MEM_ALIGNMENT (4)
/* Time stamp status flags */
#define EMAC_LL_TS_SECONDS_OVERFLOW 0x00000001U
@@ -672,6 +673,12 @@ static inline uint32_t emac_ll_get_hw_feat(emac_dma_dev_t *dma_regs)
return dma_regs->hwfeat;
}
/* emacstatus */
static inline uint32_t emac_ll_get_gmii_status(emac_mac_dev_t *mac_regs)
{
return mac_regs->emaccstatus.val;
}
/*************** End of dma regs operation *********************/
/************** Start of ptp regs operation ********************/
@@ -980,10 +987,29 @@ static inline void emac_ll_clock_enable_rmii_input(void *ext_regs)
emac_ll_clock_enable_rmii_input(__VA_ARGS__); \
} while(0)
// ESP32P4 uses phy_ref_clk_output only
static inline void emac_ll_clock_enable_rmii_output(void *ext_regs)
{
(void)ext_regs;
}
static inline void emac_ll_enable_phy_ref_clock_output(void *ext_regs)
{
HP_SYS_CLKRST.peri_clk_ctrl00.reg_pad_emac_ref_clk_en = 1;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define emac_ll_enable_phy_ref_clock_output(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
emac_ll_enable_phy_ref_clock_output(__VA_ARGS__); \
} while(0)
static inline void emac_ll_clock_rmii_rx_tx_div(void *ext_regs, int div)
{
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl01, reg_emac_rx_clk_div_num, div);
HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl01, reg_emac_tx_clk_div_num, div);
}
/// use a macro to wrap the function, force the caller to use it in a critical section
@@ -993,19 +1019,28 @@ static inline void emac_ll_clock_rmii_rx_tx_div(void *ext_regs, int div)
emac_ll_clock_rmii_rx_tx_div(__VA_ARGS__); \
} while(0)
static inline void emac_ll_clock_enable_rmii_output(void *ext_regs)
static inline bool emac_ll_ref_clock_supported(void)
{
HP_SYSTEM.sys_gmac_ctrl0.sys_phy_intf_sel = 0x4; // set RMII
HP_SYS_CLKRST.peri_clk_ctrl00.reg_pad_emac_ref_clk_en = 1;
return false;
}
/// use a macro to wrap the function, force the caller to use it in a critical section
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
#define emac_ll_clock_enable_rmii_output(...) do { \
(void)__DECLARE_RCC_ATOMIC_ENV; \
emac_ll_clock_enable_rmii_output(__VA_ARGS__); \
} while(0)
static inline void emac_ll_ref_clock_enable(void *ext_regs, bool enable)
{
(void)ext_regs;
(void)enable;
}
static inline void emac_ll_ref_clock_select(void *ext_regs, int sel)
{
(void)ext_regs;
(void)sel;
}
static inline void emac_ll_ref_clock_div(void *ext_regs, int div)
{
(void)ext_regs;
(void)div;
}
static inline void emac_ll_clock_enable_ptp(void *ext_regs, soc_periph_emac_ptp_clk_src_t clk_src, bool enable)
{
@@ -1038,6 +1073,12 @@ static inline void emac_ll_pause_frame_enable(void *ext_regs, bool enable)
HP_SYSTEM.sys_gmac_ctrl0.sys_sbd_flowctrl = enable;
}
static inline void emac_ll_gpio_init(void *ext_regs, uint32_t gpio_num)
{
(void)ext_regs;
(void)gpio_num;
}
#ifdef __cplusplus
}
#endif