mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
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:
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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)
|
||||
|
||||
/* CPLL grid: f = 40 MHz XTAL * fb_div / ref_div (clk_ll_cpll_*); model fb_div 1..N with ref_div 1 => 40 MHz steps.
|
||||
* Max CPLL 320 MHz => N = 8. */
|
||||
#define EMAC_CPLL_GRID_STEP_HZ (40000000)
|
||||
#define EMAC_CPLL_GRID_MAX_STEPS (8)
|
||||
|
||||
static const emac_clk_info_t emac_clk_cpll = {
|
||||
.clk_id = SOC_MOD_CLK_CPLL,
|
||||
.step_hz = EMAC_CPLL_GRID_STEP_HZ,
|
||||
.max_steps = EMAC_CPLL_GRID_MAX_STEPS,
|
||||
.clk_name = "CPLL",
|
||||
};
|
||||
|
||||
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",
|
||||
};
|
||||
|
||||
static const emac_clk_info_t emac_clk_apll = {
|
||||
.clk_id = SOC_MOD_CLK_APLL,
|
||||
.step_hz = -1,
|
||||
.max_steps = -1,
|
||||
.clk_name = "APLL",
|
||||
};
|
||||
|
||||
// Order matters! Position can be used to determine the clock source selection
|
||||
static const emac_clk_info_t *emac_clk_internal_src[] = {
|
||||
&emac_clk_mpll,
|
||||
&emac_clk_cpll,
|
||||
&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,
|
||||
};
|
||||
|
||||
// Order matters! Position can be used to determine the clock source selection
|
||||
const emac_clk_info_t *emac_clk_phy_ref_src[] = {
|
||||
&emac_clk_cpll,
|
||||
&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,
|
||||
};
|
||||
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* EMAC peripheral GPIO pin mappings for ESP32S31.
|
||||
*
|
||||
* GPIO signal names use GMAC_ prefix in S31 (vs EMAC_ in P4).
|
||||
*
|
||||
*/
|
||||
#include "hal/emac_periph.h"
|
||||
#include "hal/config.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#if __has_include("soc/emac_reg.h")
|
||||
#include "soc/emac_reg.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* In emac_periph terms, `SIG_GPIO_OUT_IDX` indicates that the EMAC signal cannot be connected
|
||||
* via the GPIO Matrix (i.e. such connection doesn't exist for the function), so it should
|
||||
* stay in the default "unconnected state".
|
||||
*
|
||||
* Note: `SIG_GPIO_OUT_IDX` is defined for all targets and is usually used to signify "disconnect
|
||||
* from peripheral signal" (a default unconnected peripheral state).
|
||||
*/
|
||||
const emac_io_info_t emac_io_idx = {
|
||||
.mdc_idx = GMII_MDC_PAD_OUT_IDX,
|
||||
.mdo_idx = GMII_MDO_PAD_OUT_IDX,
|
||||
.mdi_idx = GMII_MDI_PAD_IN_IDX,
|
||||
.mii_tx_clk_i_idx = GMAC_TX_CLK_PAD_IN_IDX,
|
||||
.mii_tx_en_o_idx = GMAC_PHY_TXEN_PAD_OUT_IDX,
|
||||
.mii_txd0_o_idx = GMAC_PHY_TXD0_PAD_OUT_IDX,
|
||||
.mii_txd1_o_idx = GMAC_PHY_TXD1_PAD_OUT_IDX,
|
||||
.mii_txd2_o_idx = GMAC_PHY_TXD2_PAD_OUT_IDX,
|
||||
.mii_txd3_o_idx = GMAC_PHY_TXD3_PAD_OUT_IDX,
|
||||
.mii_rx_clk_i_idx = GMAC_RX_CLK_PAD_IN_IDX,
|
||||
.mii_rx_dv_i_idx = GMAC_PHY_RXDV_PAD_IN_IDX,
|
||||
.mii_rxd0_i_idx = GMAC_PHY_RXD0_PAD_IN_IDX,
|
||||
.mii_rxd1_i_idx = GMAC_PHY_RXD1_PAD_IN_IDX,
|
||||
.mii_rxd2_i_idx = GMAC_PHY_RXD2_PAD_IN_IDX,
|
||||
.mii_rxd3_i_idx = GMAC_PHY_RXD3_PAD_IN_IDX,
|
||||
.mii_col_i_idx = GMAC_PHY_COL_PAD_IN_IDX,
|
||||
.mii_crs_i_idx = GMAC_PHY_CRS_PAD_IN_IDX,
|
||||
.mii_tx_er_o_idx = GMAC_PHY_TXER_PAD_OUT_IDX,
|
||||
.mii_rx_er_i_idx = GMAC_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,
|
||||
.ptp_pps_idx = EMAC_PTP_PPS_PAD_OUT_IDX,
|
||||
};
|
||||
|
||||
/*
|
||||
* ESP32S31 has two sets of GMAC I/O pads (as shown in the GMAC I/O table):
|
||||
* - Set 1: GPIO8-19 (first set, some in CNNT domain for wake-up)
|
||||
* - Set 2: GPIO36-47 (second set)
|
||||
*
|
||||
* CNNT domain pads (GPIO13-19): These 7 IOs remain operational when the TOP domain
|
||||
* is powered down, supporting GMAC wake-up functionality. To use them, set
|
||||
* CNNT_IO_MUX_CTRL_REG.gmac_pad_pin_ctrl_ded_sel = 1.
|
||||
*/
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_clki[] = {
|
||||
[0] = {
|
||||
.gpio_num = 13,
|
||||
.func = FUNC_GPIO13_GMAC_RMII_CLK_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 43,
|
||||
.func = FUNC_GPIO43_GMAC_RMII_CLK_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX, // indicates end of list
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_clko[] = {
|
||||
[0] = {
|
||||
.gpio_num = 13,
|
||||
.func = FUNC_GPIO13_GMAC_RMII_CLK_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 43,
|
||||
.func = FUNC_GPIO43_GMAC_RMII_CLK_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_tx_en[] = {
|
||||
[0] = {
|
||||
.gpio_num = 12,
|
||||
.func = FUNC_GPIO12_GMAC_PHY_TXEN_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 37,
|
||||
.func = FUNC_GPIO37_GMAC_PHY_TXEN_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_txd0[] = {
|
||||
[0] = {
|
||||
.gpio_num = 8,
|
||||
.func = FUNC_GPIO8_GMAC_PHY_TXD0_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 44,
|
||||
.func = FUNC_GPIO44_GMAC_PHY_TXD0_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_txd1[] = {
|
||||
[0] = {
|
||||
.gpio_num = 9,
|
||||
.func = FUNC_GPIO9_GMAC_PHY_TXD1_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 45,
|
||||
.func = FUNC_GPIO45_GMAC_PHY_TXD1_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_crs_dv[] = {
|
||||
[0] = {
|
||||
.gpio_num = 15,
|
||||
.func = FUNC_GPIO15_GMAC_PHY_RXDV_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 36,
|
||||
.func = FUNC_GPIO36_GMAC_PHY_RXDV_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_rxd0[] = {
|
||||
[0] = {
|
||||
.gpio_num = 19,
|
||||
.func = FUNC_GPIO19_GMAC_PHY_RXD0_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 41,
|
||||
.func = FUNC_GPIO41_GMAC_PHY_RXD0_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_rxd1[] = {
|
||||
[0] = {
|
||||
.gpio_num = 18,
|
||||
.func = FUNC_GPIO18_GMAC_PHY_RXD1_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 40,
|
||||
.func = FUNC_GPIO40_GMAC_PHY_RXD1_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
/* tx_er and rx_er - no dedicated IOMUX functions. They can be routed via GPIO matrix instead. */
|
||||
static const emac_iomux_info_t emac_rmii_iomux_tx_er[] = {
|
||||
[0] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rmii_iomux_rx_er[] = {
|
||||
[0] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
/* ------------------end of rmii iomux info ------------------*/
|
||||
|
||||
/* ------------------start of rgmii iomux info ------------------*/
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_clki[] = {
|
||||
[0] = {
|
||||
.gpio_num = 14,
|
||||
.func = FUNC_GPIO14_GMAC_RX_CLK_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 42,
|
||||
.func = FUNC_GPIO42_GMAC_RX_CLK_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX, // indicates end of list
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_clko[] = {
|
||||
[0] = {
|
||||
.gpio_num = 13,
|
||||
.func = FUNC_GPIO13_GMAC_RMII_CLK_PAD,
|
||||
},
|
||||
|
||||
[1] = {
|
||||
.gpio_num = 43,
|
||||
.func = FUNC_GPIO43_GMAC_RMII_CLK_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_tx_ctl[] = {
|
||||
[0] = {
|
||||
.gpio_num = 12,
|
||||
.func = FUNC_GPIO12_GMAC_PHY_TXEN_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 37,
|
||||
.func = FUNC_GPIO37_GMAC_PHY_TXEN_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_txd0[] = {
|
||||
[0] = {
|
||||
.gpio_num = 8,
|
||||
.func = FUNC_GPIO8_GMAC_PHY_TXD0_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 44,
|
||||
.func = FUNC_GPIO44_GMAC_PHY_TXD0_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_txd1[] = {
|
||||
[0] = {
|
||||
.gpio_num = 9,
|
||||
.func = FUNC_GPIO9_GMAC_PHY_TXD1_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 45,
|
||||
.func = FUNC_GPIO45_GMAC_PHY_TXD1_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_txd2[] = {
|
||||
[0] = {
|
||||
.gpio_num = 10,
|
||||
.func = FUNC_GPIO10_GMAC_PHY_TXD2_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 46,
|
||||
.func = FUNC_GPIO46_GMAC_PHY_TXD2_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_txd3[] = {
|
||||
[0] = {
|
||||
.gpio_num = 11,
|
||||
.func = FUNC_GPIO11_GMAC_PHY_TXD3_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 47,
|
||||
.func = FUNC_GPIO47_GMAC_PHY_TXD3_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_rx_ctl[] = {
|
||||
[0] = {
|
||||
.gpio_num = 15,
|
||||
.func = FUNC_GPIO15_GMAC_PHY_RXDV_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 36,
|
||||
.func = FUNC_GPIO36_GMAC_PHY_RXDV_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_rxd0[] = {
|
||||
[0] = {
|
||||
.gpio_num = 19,
|
||||
.func = FUNC_GPIO19_GMAC_PHY_RXD0_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 41,
|
||||
.func = FUNC_GPIO41_GMAC_PHY_RXD0_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_rxd1[] = {
|
||||
[0] = {
|
||||
.gpio_num = 18,
|
||||
.func = FUNC_GPIO18_GMAC_PHY_RXD1_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 40,
|
||||
.func = FUNC_GPIO40_GMAC_PHY_RXD1_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_rxd2[] = {
|
||||
[0] = {
|
||||
.gpio_num = 17,
|
||||
.func = FUNC_GPIO17_GMAC_PHY_RXD2_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 39,
|
||||
.func = FUNC_GPIO39_GMAC_PHY_RXD2_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
static const emac_iomux_info_t emac_rgmii_iomux_rxd3[] = {
|
||||
[0] = {
|
||||
.gpio_num = 16,
|
||||
.func = FUNC_GPIO16_GMAC_PHY_RXD3_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = 38,
|
||||
.func = FUNC_GPIO38_GMAC_PHY_RXD3_PAD,
|
||||
},
|
||||
[2] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
/* ---end of rgmii iomux info ------------------*/
|
||||
|
||||
/* ---start of ref clk iomux info ------------------*/
|
||||
static const emac_iomux_info_t emac_ref_clk_iomux_phy_ref_clk[] = {
|
||||
[0] = {
|
||||
.gpio_num = 35,
|
||||
.func = FUNC_GPIO35_REF_GMAC_CLK_PAD,
|
||||
},
|
||||
[1] = {
|
||||
.gpio_num = GPIO_NUM_MAX,
|
||||
}
|
||||
};
|
||||
|
||||
/* ---end of ref clk iomux info ------------------*/
|
||||
|
||||
const emac_rmii_iomux_info_t emac_rmii_iomux_pins = {
|
||||
.clki = emac_rmii_iomux_clki,
|
||||
.clko = emac_rmii_iomux_clko,
|
||||
.tx_en = emac_rmii_iomux_tx_en,
|
||||
.txd0 = emac_rmii_iomux_txd0,
|
||||
.txd1 = emac_rmii_iomux_txd1,
|
||||
.crs_dv = emac_rmii_iomux_crs_dv,
|
||||
.rxd0 = emac_rmii_iomux_rxd0,
|
||||
.rxd1 = emac_rmii_iomux_rxd1,
|
||||
.tx_er = emac_rmii_iomux_tx_er,
|
||||
.rx_er = emac_rmii_iomux_rx_er,
|
||||
};
|
||||
|
||||
const emac_rgmii_iomux_info_t emac_rgmii_iomux_pins = {
|
||||
.clk_tx = emac_rgmii_iomux_clko,
|
||||
.tx_ctl = emac_rgmii_iomux_tx_ctl,
|
||||
.txd0 = emac_rgmii_iomux_txd0,
|
||||
.txd1 = emac_rgmii_iomux_txd1,
|
||||
.txd2 = emac_rgmii_iomux_txd2,
|
||||
.txd3 = emac_rgmii_iomux_txd3,
|
||||
.clk_rx = emac_rgmii_iomux_clki,
|
||||
.rx_ctl = emac_rgmii_iomux_rx_ctl,
|
||||
.rxd0 = emac_rgmii_iomux_rxd0,
|
||||
.rxd1 = emac_rgmii_iomux_rxd1,
|
||||
.rxd2 = emac_rgmii_iomux_rxd2,
|
||||
.rxd3 = emac_rgmii_iomux_rxd3,
|
||||
};
|
||||
|
||||
const emac_ref_clk_iomux_info_t emac_ref_clk_iomux_pins = {
|
||||
.phy_ref_clk = emac_ref_clk_iomux_phy_ref_clk,
|
||||
};
|
||||
|
||||
const emac_mii_iomux_info_t emac_mii_iomux_pins = { 0 };
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user