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
+30
View File
@@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/emac_clk.h"
static const emac_clk_info_t emac_clk_apll = {
.clk_id = SOC_MOD_CLK_APLL,
.step_hz = -1,
.max_steps = -1,
.clk_name = "APLL",
};
static const emac_clk_info_t *emac_clk_internal_src[] = {
&emac_clk_apll,
};
const emac_clk_internal_info_t emac_clk_internal = {
.clk_count = sizeof(emac_clk_internal_src) / sizeof(emac_clk_internal_src[0]),
.clk_src = emac_clk_internal_src,
};
/* ESP32 does not support EMAC PHY_REF_CLK derived clock. */
const emac_clk_phy_ref_info_t emac_clk_phy_ref = {
.derived_clk_id = SOC_MOD_CLK_INVALID,
.clk_count = 0,
.clk_src = NULL,
};
+10 -1
View File
@@ -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
*/
@@ -37,6 +37,7 @@ const emac_io_info_t emac_io_idx = {
.mii_rx_er_i_idx = SIG_GPIO_OUT_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,
.ptp_pps_idx = SIG_GPIO_OUT_IDX,
};
@@ -60,6 +61,10 @@ static const emac_iomux_info_t emac_rmii_iomux_clko[] = {
.func = FUNC_GPIO17_EMAC_CLK_OUT_180,
},
[2] = {
.gpio_num = 0,
.func = FUNC_GPIO0_CLK_OUT1,
},
[3] = {
.gpio_num = GPIO_NUM_MAX,
}
};
@@ -218,6 +223,10 @@ const emac_rmii_iomux_info_t emac_rmii_iomux_pins = {
.rx_er = emac_rmii_mii_iomux_rx_er,
};
const emac_ref_clk_iomux_info_t emac_ref_clk_iomux_pins = {
.phy_ref_clk = NULL,
};
const emac_mii_iomux_info_t emac_mii_iomux_pins = {
.clk_tx = emac_mii_iomux_clk_tx,
.tx_en = emac_rmii_mii_iomux_tx_en,
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -91,6 +91,7 @@ extern "C" {
#define EMAC_LL_DMADESC_OWNER_CPU (0)
#define EMAC_LL_DMADESC_OWNER_DMA (1)
#define EMAC_LL_DMA_MEM_ALIGNMENT (4)
/* Interrupt flags (referring to dmastatus register in emac_dma_struct.h) */
#define EMAC_LL_DMA_TRANSMIT_FINISH_INTR 0x00000001U
@@ -696,6 +697,12 @@ static inline void emac_ll_receive_poll_demand(emac_dma_dev_t *dma_regs, uint32_
dma_regs->dmarxpolldemand = val;
}
/* 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 ext regs operation ********************/
@@ -724,6 +731,7 @@ static inline void emac_ll_clock_enable_rmii_input(emac_ext_dev_t *ext_regs)
config pin as output to generate ref clk by esp32 mac layer or input to obtain the clock from external crystal */
ext_regs->ex_clk_ctrl.ext_en = 1;
ext_regs->ex_clk_ctrl.int_en = 0;
// 0 for internal clock, 1 for external clock
ext_regs->ex_oscclk_conf.clk_sel = 1;
}
@@ -735,8 +743,34 @@ static inline void emac_ll_clock_enable_rmii_output(emac_ext_dev_t *ext_regs)
config pin as output to generate ref clk by esp32 mac layer or input to obtain the clock from external crystal */
ext_regs->ex_clk_ctrl.ext_en = 0;
ext_regs->ex_clk_ctrl.int_en = 1;
// 0 for internal clock, 1 for external clock
ext_regs->ex_oscclk_conf.clk_sel = 0;
ext_regs->ex_clkout_conf.div_num = 0;
}
static inline bool emac_ll_ref_clock_supported(void)
{
return true;
}
static inline void emac_ll_ref_clock_enable(emac_ext_dev_t *ext_regs, bool enable)
{
// do nothing as the ref clock can't be gated
(void)ext_regs;
(void)enable;
}
static inline void emac_ll_ref_clock_select(emac_ext_dev_t *ext_regs, int sel)
{
// do nothing as there is only one internal clock source
(void)ext_regs;
(void)sel;
}
static inline void emac_ll_ref_clock_div(emac_ext_dev_t *ext_regs, int div)
{
// N_eff ~= integer_part + (half_part / 2)
// half part is currently not used
ext_regs->ex_clkout_conf.div_num = div;
ext_regs->ex_clkout_conf.h_div_num = 0;
}
@@ -744,6 +778,7 @@ static inline void emac_ll_pause_frame_enable(emac_ext_dev_t *ext_regs, bool ena
{
ext_regs->ex_phyinf_conf.sbd_flowctrl = enable;
}
/*************** End of ext regs operation *********************/
static inline soc_module_clk_t emac_ll_get_csr_clk_src(void)
@@ -752,6 +787,12 @@ static inline soc_module_clk_t emac_ll_get_csr_clk_src(void)
return SOC_MOD_CLK_APB;
}
static inline void emac_ll_gpio_init(void *ext_regs, uint32_t gpio_num)
{
(void)ext_regs;
(void)gpio_num;
}
#ifdef __cplusplus
}
#endif