2024-04-26 12:27:54 +02:00
/*
2025-03-23 20:22:25 -04:00
* SPDX - FileCopyrightText : 2019 - 2025 Espressif Systems ( Shanghai ) CO LTD
2024-04-26 12:27:54 +02:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
# pragma once
# include <stdbool.h>
# include "soc/soc_caps.h"
# include "esp_eth_com.h"
# include "esp_eth_mac.h"
# include "sdkconfig.h"
# ifdef __cplusplus
extern " C " {
# endif
# if CONFIG_ETH_USE_ESP32_EMAC
/**
* @ brief RMII Clock Mode Options
*
*/
typedef enum {
/**
* @ brief Default values configured using Kconfig are going to be used when " Default " selected .
*
* @ warning Deprecated option . Clock configuration using Kconfig is limitedly supported only for ESP32 SoC via @ c ETH_ESP32_EMAC_DEFAULT_CONFIG
* and is going to be reevaluated in the next major release .
* Clock mode and clock GPIO number is supposed to be defined in ` EMAC specific configuration ` structure from user ' s code .
*
*/
EMAC_CLK_DEFAULT __attribute__ ( ( deprecated ) ) , // IDF-9724
/**
* @ brief Input RMII Clock from external . EMAC Clock GPIO number needs to be configured when this option is selected .
*
* @ note MAC will get RMII clock from outside . Note that ESP32 only supports GPIO0 to input the RMII clock .
*
*/
EMAC_CLK_EXT_IN ,
/**
* @ brief Output RMII Clock from internal ( A / M ) PLL Clock . EMAC Clock GPIO number needs to be configured when this option is selected .
*
*/
EMAC_CLK_OUT
} emac_rmii_clock_mode_t ;
# if CONFIG_IDF_TARGET_ESP32
/**
* @ brief RMII Clock GPIO number Options for ESP32
*
2024-08-09 15:53:08 +02:00
* @ warning If you want the Ethernet to work with WiFi , don ’ t select ESP32 as RMII CLK output as it would result in clock instability .
*
2024-04-26 12:27:54 +02:00
*/
typedef enum {
/**
* @ brief MAC will get RMII clock from outside at this GPIO .
*
* @ note ESP32 only supports GPIO0 to input the RMII clock .
*
*/
EMAC_CLK_IN_GPIO = 0 ,
/**
* @ brief Output RMII Clock from internal APLL Clock available at GPIO0
*
2024-08-09 15:53:08 +02:00
* @ note GPIO0 can be set to output a pre - divided PLL clock . Enabling this option will configure GPIO0 to output a 50 MHz clock .
* In fact this clock doesn ’ t have directly relationship with EMAC peripheral . Sometimes this clock may not work well with your PHY chip .
2024-04-26 12:27:54 +02:00
*
*/
EMAC_APPL_CLK_OUT_GPIO = 0 ,
/**
* @ brief Output RMII Clock from internal APLL Clock available at GPIO16
*
*/
EMAC_CLK_OUT_GPIO = 16 ,
/**
* @ brief Inverted Output RMII Clock from internal APLL Clock available at GPIO17
*
*/
EMAC_CLK_OUT_180_GPIO = 17
} emac_rmii_clock_gpio_t ;
# else
/**
* @ brief RMII Clock GPIO number
*
*/
typedef int emac_rmii_clock_gpio_t ;
# endif // CONFIG_IDF_TARGET_ESP32
/**
* @ brief Ethernet MAC Clock Configuration
*
*/
typedef union {
struct {
// MII interface is not fully implemented...
// Reserved for GPIO number, clock source, etc. in MII mode
} mii ; /*!< EMAC MII Clock Configuration */
struct {
emac_rmii_clock_mode_t clock_mode ; /*!< RMII Clock Mode Configuration */
emac_rmii_clock_gpio_t clock_gpio ; /*!< RMII Clock GPIO Configuration */
} rmii ; /*!< EMAC RMII Clock Configuration */
} eth_mac_clock_config_t ;
/**
* @ brief EMAC SMI GPIO configuration
*/
typedef struct {
int mdc_num ; /*!< SMI MDC GPIO number, set to -1 could bypass the SMI GPIO configuration */
int mdio_num ; /*!< SMI MDIO GPIO number, set to -1 could bypass the SMI GPIO configuration */
} emac_esp_smi_gpio_config_t ;
/**
* @ brief EMAC MII data interface GPIO configuration
*/
typedef struct {
int tx_clk_num ; /*!< TX_CLK GPIO number */
int tx_en_num ; /*!< TX_EN GPIO number */
int txd0_num ; /*!< TXD0 GPIO number */
int txd1_num ; /*!< TXD1 GPIO number */
int txd2_num ; /*!< TXD2 GPIO number */
int txd3_num ; /*!< TXD3 GPIO number */
int rx_clk_num ; /*!< RX_CLK GPIO number */
int rx_dv_num ; /*!< RX_DV GPIO number */
int rxd0_num ; /*!< RXD0 GPIO number */
int rxd1_num ; /*!< RXD1 GPIO number */
int rxd2_num ; /*!< RXD2 GPIO number */
int rxd3_num ; /*!< RXD3 GPIO number */
int col_in_num ; /*!< COL_IN GPIO number */
int crs_in_num ; /*!< CRS_IN GPIO number */
int tx_er_num ; /*!< TX_ER GPIO number */
int rx_er_num ; /*!< RX_ER GPIO number */
} eth_mac_mii_gpio_config_t ;
/**
* @ brief EMAC RMII data interface GPIO configuration
*/
typedef struct {
int tx_en_num ; /*!< TX_EN GPIO number */
int txd0_num ; /*!< TXD0 GPIO number */
int txd1_num ; /*!< TXD1 GPIO number */
int crs_dv_num ; /*!< CRS_DV GPIO number */
int rxd0_num ; /*!< RXD0 GPIO number */
int rxd1_num ; /*!< RXD1 GPIO number */
} eth_mac_rmii_gpio_config_t ;
# if SOC_EMAC_USE_MULTI_IO_MUX || SOC_EMAC_MII_USE_GPIO_MATRIX
/**
* @ brief Ethernet MAC MII / RMII data plane GPIO configuration
*
*/
typedef union {
eth_mac_mii_gpio_config_t mii ; /*!< EMAC MII Data GPIO Configuration */
eth_mac_rmii_gpio_config_t rmii ; /*!< EMAC RMII Data GPIO Configuration */
} eth_mac_dataif_gpio_config_t ;
# endif // SOC_EMAC_USE_MULTI_IO_MUX
/**
* @ brief EMAC specific configuration
*
*/
typedef struct {
union {
emac_esp_smi_gpio_config_t smi_gpio ; /*!< SMI GPIO numbers */
struct {
int smi_mdc_gpio_num __attribute__ ( ( deprecated ( " Please use smi_gpio instead " ) ) ) ; /*!< SMI MDC GPIO number, set to -1 could bypass the SMI GPIO configuration */
int smi_mdio_gpio_num __attribute__ ( ( deprecated ( " Please use smi_gpio instead " ) ) ) ; /*!< SMI MDIO GPIO number, set to -1 could bypass the SMI GPIO configuration */
} ;
} ;
eth_data_interface_t interface ; /*!< EMAC Data interface to PHY (MII/RMII) */
eth_mac_clock_config_t clock_config ; /*!< EMAC Interface clock configuration */
eth_mac_dma_burst_len_t dma_burst_len ; /*!< EMAC DMA burst length for both Tx and Rx */
int intr_priority ; /*!< EMAC interrupt priority, if set to 0 or a negative value, the driver will try to allocate an interrupt with a default priority */
# if SOC_EMAC_USE_MULTI_IO_MUX || SOC_EMAC_MII_USE_GPIO_MATRIX
eth_mac_dataif_gpio_config_t emac_dataif_gpio ; /*!< EMAC MII/RMII data plane GPIO configuration */
# endif // SOC_EMAC_USE_MULTI_IO_MUX
# if !SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK
eth_mac_clock_config_t clock_config_out_in ; /*!< EMAC input clock configuration for internally generated output clock (when output clock is looped back externally) */
# endif //SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK
} eth_esp32_emac_config_t ;
/**
* @ brief List of ESP EMAC specific commands for ioctl API
*
*/
typedef enum {
ETH_MAC_ESP_CMD_SET_TDES0_CFG_BITS = ETH_CMD_CUSTOM_MAC_CMDS_OFFSET , /*!< Set Transmit Descriptor Word 0 control bit mask (debug option)*/
ETH_MAC_ESP_CMD_CLEAR_TDES0_CFG_BITS , /*!< Clear Transmit Descriptor Word 0 control bit mask (debug option)*/
ETH_MAC_ESP_CMD_PTP_ENABLE , /*!< Enable IEEE1588 Time stamping */
2024-06-26 15:40:32 +02:00
ETH_MAC_ESP_CMD_S_PTP_TIME , /*!< Set PTP time in the module */
ETH_MAC_ESP_CMD_G_PTP_TIME , /*!< Get PTP time from the module */
ETH_MAC_ESP_CMD_ADJ_PTP_FREQ , /*!< Adjust current PTP time frequency increment by scale factor */
ETH_MAC_ESP_CMD_ADJ_PTP_TIME , /*!< Adjust base PTP time frequency increment by PPS */
ETH_MAC_ESP_CMD_S_TARGET_TIME , /*!< Set Target Time at which interrupt is invoked when PTP time exceeds this value*/
2025-06-04 13:14:14 +02:00
ETH_MAC_ESP_CMD_S_TARGET_CB , /*!< Set pointer to a callback function invoked when PTP time exceeds Target Time */
ETH_MAC_ESP_CMD_ENABLE_TS4ALL /*!< Enable timestamp for all received frames */
2024-04-26 12:27:54 +02:00
} eth_mac_esp_io_cmd_t ;
2024-06-26 15:40:32 +02:00
# ifdef SOC_EMAC_IEEE1588V2_SUPPORTED
/**
* @ brief Type of callback function invoked under Time Stamp target time exceeded interrupt
*
* @ warning Time stamping is currently Experimental Feature ! Be aware that API may change .
*
* @ param eth : mediator of Ethernet driver
* @ param user_args user specific arguments ( placeholder - IDF - 11429 )
*
* @ return
* - TRUE when high priority task has been woken by this function
* - FALSE no high priority task was woken by this function
*/
typedef bool ( * ts_target_exceed_cb_from_isr_t ) ( esp_eth_mediator_t * eth , void * user_args ) ;
# endif // SOC_EMAC_IEEE1588V2_SUPPORTED
2024-04-26 12:27:54 +02:00
/**
* @ brief Default ESP32 ' s EMAC specific configuration
*
*/
# if CONFIG_IDF_TARGET_ESP32
# if CONFIG_ETH_RMII_CLK_INPUT // IDF-9724
# define DEFAULT_RMII_CLK_MODE EMAC_CLK_EXT_IN
# if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
# define DEFAULT_RMII_CLK_GPIO CONFIG_ETH_RMII_CLK_IN_GPIO
# else
# error "ESP32 EMAC only support input RMII clock to GPIO0"
# endif // CONFIG_ETH_RMII_CLK_IN_GPIO == 0
# elif CONFIG_ETH_RMII_CLK_OUTPUT
# define DEFAULT_RMII_CLK_MODE EMAC_CLK_OUT
# if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
# define DEFAULT_RMII_CLK_GPIO EMAC_APPL_CLK_OUT_GPIO
# else
# define DEFAULT_RMII_CLK_GPIO CONFIG_ETH_RMII_CLK_OUT_GPIO
# endif // CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
# else
# error "Unsupported RMII clock mode"
# endif // CONFIG_ETH_RMII_CLK_INPUT
2024-07-30 12:32:34 +02:00
# define ETH_ESP32_EMAC_DEFAULT_CONFIG() \
{ \
. smi_gpio = \
{ \
. mdc_num = 23 , \
. mdio_num = 18 \
} , \
. interface = EMAC_DATA_INTERFACE_RMII , \
. clock_config = \
{ \
. rmii = \
{ \
. clock_mode = DEFAULT_RMII_CLK_MODE , \
. clock_gpio = ( emac_rmii_clock_gpio_t ) DEFAULT_RMII_CLK_GPIO \
} \
} , \
. dma_burst_len = ETH_DMA_BURST_LEN_32 , \
. intr_priority = 0 , \
2024-04-26 12:27:54 +02:00
}
# elif CONFIG_IDF_TARGET_ESP32P4
2024-07-30 12:32:34 +02:00
# define ETH_ESP32_EMAC_DEFAULT_CONFIG() \
{ \
. smi_gpio = \
{ \
. mdc_num = 31 , \
2024-06-26 15:40:32 +02:00
. mdio_num = 52 \
2024-07-30 12:32:34 +02:00
} , \
. interface = EMAC_DATA_INTERFACE_RMII , \
. clock_config = \
{ \
. rmii = \
{ \
. clock_mode = EMAC_CLK_EXT_IN , \
. clock_gpio = ( emac_rmii_clock_gpio_t ) 50 \
} \
} , \
. dma_burst_len = ETH_DMA_BURST_LEN_32 , \
. intr_priority = 0 , \
. emac_dataif_gpio = \
{ \
. rmii = \
{ \
. tx_en_num = 49 , \
. txd0_num = 34 , \
. txd1_num = 35 , \
. crs_dv_num = 28 , \
. rxd0_num = 29 , \
. rxd1_num = 30 \
} \
} , \
2025-03-23 20:22:25 -04:00
. clock_config_out_in = \
{ \
. rmii = \
{ \
. clock_mode = EMAC_CLK_EXT_IN , \
. clock_gpio = ( emac_rmii_clock_gpio_t ) - 1 \
} \
} , \
2024-04-26 12:27:54 +02:00
}
# endif // CONFIG_IDF_TARGET_ESP32P4
/**
* @ brief Create ESP32 Ethernet MAC instance
*
* @ param esp32_config : EMAC specific configuration
* @ param config : Ethernet MAC configuration
*
* @ return
* - instance : create MAC instance successfully
* - NULL : create MAC instance failed because some error occurred
*/
esp_eth_mac_t * esp_eth_mac_new_esp32 ( const eth_esp32_emac_config_t * esp32_config , const eth_mac_config_t * config ) ;
# endif // CONFIG_ETH_USE_ESP32_EMAC
# ifdef __cplusplus
}
# endif