summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerge Semin <fancer.lancer@gmail.com>2023-08-14 23:31:16 +0300
committerSerge Semin <fancer.lancer@gmail.com>2026-08-13 20:38:18 +0300
commitcc67886881f55520147cbdf37b8cd122fbbfb084 (patch)
treeb37cfa5708eacaa0132046cecbed57837a5be6fc
parentdf9d70712eb6b483c8d658b114addafccdd90192 (diff)
downloadlinux-cc67886881f55520147cbdf37b8cd122fbbfb084.tar.gz
linux-cc67886881f55520147cbdf37b8cd122fbbfb084.zip
net: phy: marvell-88x2222: Read latched flags twice
Prepare the driver to adding the interrupts support by making sure that the actual status is handled during the network link state machine work. Currently it concerns the link status flags in various PHY MMD registers. They are latched-low so the respective CSRs need to be read twice to get the actual flag state at the moment of the event handling. Note there are other latched flags can be discovered in the Marvell 88x2222 registers. For instance AN Page Received status or 1GBase-X Remote fault status. Since the semantic of the respective events handling may differ from the link up/down handling procedure, the mv2222_read_mmd_latched() function is defined to accept an additional argument forcing the registers double read if it's required by the caller. Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
-rw-r--r--drivers/net/phy/marvell-88x2222.c31
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c
index 441626312142d..9d21aa3e3d673 100644
--- a/drivers/net/phy/marvell-88x2222.c
+++ b/drivers/net/phy/marvell-88x2222.c
@@ -347,12 +347,32 @@ static int mv2222_config_aneg(struct phy_device *phydev)
return mv2222_enable_aneg(phydev);
}
+/* The link state and some other fields in the status registers are latched
+ * low/high so that the momentary events could be detected. Do not double-read
+ * the status in polling mode to detect such a short flag changes except when
+ * it's forced to be required (i.e. when the link was already down).
+ */
+static int mv2222_read_mmd_latched(struct phy_device *phydev, int devad, u32 reg,
+ bool force)
+{
+ int ret;
+
+ if (!phy_polling_mode(phydev) || force) {
+ ret = phy_read_mmd(phydev, devad, reg);
+ if (ret < 0)
+ return ret;
+ }
+
+ return phy_read_mmd(phydev, devad, reg);
+}
+
static int mv2222_aneg_done(struct phy_device *phydev)
{
int ret;
if (mv2222_is_10g_capable(phydev)) {
- ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1);
+ ret = mv2222_read_mmd_latched(phydev, MDIO_MMD_PCS, MDIO_STAT1,
+ !phydev->link);
if (ret < 0)
return ret;
@@ -373,7 +393,8 @@ static int mv2222_read_status_10g(struct phy_device *phydev)
static int timeout;
int val, link = 0;
- val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1);
+ val = mv2222_read_mmd_latched(phydev, MDIO_MMD_PCS, MDIO_STAT1,
+ !phydev->link);
if (val < 0)
return val;
@@ -409,7 +430,8 @@ static int mv2222_read_status_1g(struct phy_device *phydev)
static int timeout;
int val, link = 0;
- val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT);
+ val = mv2222_read_mmd_latched(phydev, MDIO_MMD_PCS, MV_1GBX_STAT,
+ !phydev->link);
if (val < 0)
return val;
@@ -471,7 +493,8 @@ static bool mv2222_iface_is_operational(struct phy_device *phydev)
return false;
}
- val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, reg);
+ val = mv2222_read_mmd_latched(phydev, MDIO_MMD_PHYXS, reg,
+ !phydev->link);
if (val < 0 || !(val & MDIO_STAT1_LSTATUS))
return false;