From e2945871b731b8e59ff718a9eec7962777fc6e6b Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Fri, 15 Dec 2023 10:57:53 +0000 Subject: [PATCH] fix(esp_eth): dp83848: correct link detection to use BMSR Reading the link state via PHYSTS was incorrect, as it only reflects the link state bit from BMSR. BMSR latches link down events, and are not cleared without being read. (See 802.3-2008 section 2, section 22.2.4.2.13) This leads to the original DP828xx code only supporting link up, then a single link down event. Switch to reading the link state via BMSR, but continuing to read the negotiation results via PHYSTS and ANLPAR. This is inline with LAN8720x, RTL8201, KSZ80xx phy drivers, and other opensource drivers for the DP838xx family of devices. Tested on a private board with a DP83825i PHY. No publically available boards using the original DP83848 are known of for testing. Signed-off-by: Karl Palsson --- components/esp_eth/src/esp_eth_phy_dp83848.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/esp_eth/src/esp_eth_phy_dp83848.c b/components/esp_eth/src/esp_eth_phy_dp83848.c index fc771b072f..7ae69b24bf 100644 --- a/components/esp_eth/src/esp_eth_phy_dp83848.c +++ b/components/esp_eth/src/esp_eth_phy_dp83848.c @@ -77,13 +77,15 @@ static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848) uint32_t peer_pause_ability = false; anlpar_reg_t anlpar; physts_reg_t physts; - ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed"); - ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed"); - eth_link_t link = physts.link_status ? ETH_LINK_UP : ETH_LINK_DOWN; + bmsr_reg_t bmsr; + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed"); + eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN; /* check if link status changed */ if (dp83848->phy_802_3.link_status != link) { /* when link up, read negotiation result */ if (link == ETH_LINK_UP) { + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed"); + ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed"); if (physts.speed_status) { speed = ETH_SPEED_10M; } else {