From 2fbc3fb588a3e77fd470facd3cb0f65210c9e620 Mon Sep 17 00:00:00 2001 From: Ondrej Kosta Date: Tue, 26 May 2026 16:28:33 +0200 Subject: [PATCH] feat(esp_eth): generic 802.3 driver to check if 1000M is supported --- .../esp_eth/include/eth_phy_802_3_regs.h | 16 ++++++++ .../esp_eth/src/phy/esp_eth_phy_802_3.c | 40 ++++++++++++++----- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/components/esp_eth/include/eth_phy_802_3_regs.h b/components/esp_eth/include/eth_phy_802_3_regs.h index 858b8b06179..e9091f63a39 100644 --- a/components/esp_eth/include/eth_phy_802_3_regs.h +++ b/components/esp_eth/include/eth_phy_802_3_regs.h @@ -211,6 +211,22 @@ typedef union { } mmdad_reg_t; #define ETH_PHY_MMDAD_REG_ADDR (0x0E) +/** + * @brief EXSR(Extended Status Register) + * + */ +typedef union { + struct { + uint32_t reserved : 12; /*!< Reserved */ + uint32_t base1000_t : 1; /*!< 1000BASE-T Half Duplex ability */ + uint32_t base1000_t_fd : 1; /*!< 1000BASE-T Full Duplex ability */ + uint32_t base1000_x : 1; /*!< 1000BASE-X Half Duplex ability */ + uint32_t base1000_x_fd : 1; /*!< 1000BASE-X Full Duplex ability */ + }; + uint32_t val; +} exsr_reg_t; +#define ETH_PHY_EXSR_REG_ADDR (0x0F) + #ifdef __cplusplus } #endif diff --git a/components/esp_eth/src/phy/esp_eth_phy_802_3.c b/components/esp_eth/src/phy/esp_eth_phy_802_3.c index 23f1baafe7c..7d5d407d029 100644 --- a/components/esp_eth/src/phy/esp_eth_phy_802_3.c +++ b/components/esp_eth/src/phy/esp_eth_phy_802_3.c @@ -241,16 +241,20 @@ esp_err_t esp_eth_phy_802_3_updt_link_dup_spd(phy_802_3_t *phy_802_3) if (bmcr.en_auto_nego) { bool need_anar_mode = false; if (bmsr.ext_status) { - if (eth->phy_reg_read(eth, addr, ETH_PHY_GBCR_REG_ADDR, &(gbcr.val)) == ESP_OK && - eth->phy_reg_read(eth, addr, ETH_PHY_GBSR_REG_ADDR, &(gbsr.val)) == ESP_OK) { - if (gbcr.base1000_t_fd && gbsr.lp_base1000_t_fd) { - speed = ETH_SPEED_1000M; - duplex = ETH_DUPLEX_FULL; - } else if (gbcr.base1000_t && gbsr.lp_base1000_t) { - speed = ETH_SPEED_1000M; - duplex = ETH_DUPLEX_HALF; - } else { - need_anar_mode = true; + exsr_reg_t exsr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_EXSR_REG_ADDR, &(exsr.val)), err, TAG, "read EXSR failed"); + if (exsr.base1000_t || exsr.base1000_t_fd) { + if (eth->phy_reg_read(eth, addr, ETH_PHY_GBCR_REG_ADDR, &(gbcr.val)) == ESP_OK && + eth->phy_reg_read(eth, addr, ETH_PHY_GBSR_REG_ADDR, &(gbsr.val)) == ESP_OK) { + if (gbcr.base1000_t_fd && gbsr.lp_base1000_t_fd) { + speed = ETH_SPEED_1000M; + duplex = ETH_DUPLEX_FULL; + } else if (gbcr.base1000_t && gbsr.lp_base1000_t) { + speed = ETH_SPEED_1000M; + duplex = ETH_DUPLEX_HALF; + } else { + need_anar_mode = true; + } } } } @@ -400,11 +404,25 @@ esp_err_t esp_eth_phy_802_3_set_speed(phy_802_3_t *phy_802_3, eth_speed_t speed) /* Set speed */ bmcr_reg_t bmcr; ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed"); + bmsr_reg_t bmsr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed"); + bool is_1000_capable = false; + if (bmsr.ext_status) { + exsr_reg_t exsr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_EXSR_REG_ADDR, &(exsr.val)), err, TAG, "read EXSR failed"); + is_1000_capable = exsr.base1000_t || exsr.base1000_t_fd; + } if (speed == ETH_SPEED_1000M) { + if (!is_1000_capable) { + ret = ESP_ERR_NOT_SUPPORTED; + goto err; + } bmcr.speed_1000 = 1; bmcr.speed_select = 0; } else { - bmcr.speed_1000 = 0; + if (is_1000_capable) { + bmcr.speed_1000 = 0; + } bmcr.speed_select = speed == ETH_SPEED_100M ? 1 : 0; } ESP_GOTO_ON_ERROR(eth->phy_reg_write(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, bmcr.val), err, TAG, "write BMCR failed");