]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: phy: air_an8801: ensure maximum available speed link use
authorLouis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
Tue, 26 May 2026 14:58:11 +0000 (16:58 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 28 May 2026 01:39:24 +0000 (18:39 -0700)
To ensure that the Airoha AN8801R PHY uses the maximum available link
speed, an additional register write is needed to configure the function
mode for either 1G or 100M/10M operation after link detection.

So, in air_an8801 driver, implement a custom read_status callback, that
after genphy_read_status determines the link speed, sets the bit 0 of
the link mode register (REG_LINK_MODE) if the detected speed is 1Gbps,
or unsets it otherwise.

Signed-off-by: Louis-Alexis Eyraud <louisalexis.eyraud@collabora.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20260526-add-airoha-an8801-support-v5-6-01aea8dee69b@collabora.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/phy/air_an8801.c

index aa24bb182d64522610449a78ed2f5634e5b490f3..f97c78e430237e4645129d19249ff5503d6a58aa 100644 (file)
@@ -996,6 +996,41 @@ static int an8801r_config_init(struct phy_device *phydev)
        return 0;
 }
 
+static int an8801r_read_status(struct phy_device *phydev)
+{
+       int prev_speed, ret;
+       u32 val;
+
+       prev_speed = phydev->speed;
+
+       ret = genphy_read_status(phydev);
+       if (ret)
+               return ret;
+
+       if (!phydev->link) {
+               phydev->speed = SPEED_UNKNOWN;
+               return 0;
+       }
+
+       if (prev_speed != phydev->speed) {
+               /* Ensure that PHY switches to 1G speed when available,
+                * by configuring the function mode for either 1G or 100M/10M
+                * operation.
+                * Therefore, set the link mode register, after read_status
+                * determines the link speed.
+                */
+               val = phydev->speed == SPEED_1000 ?
+                     AN8801_BPBUS_LINK_MODE_1000 : 0;
+
+               return an8801_buckpbus_reg_rmw(phydev,
+                                              AN8801_BPBUS_REG_LINK_MODE,
+                                              AN8801_BPBUS_LINK_MODE_1000,
+                                              val);
+       }
+
+       return 0;
+}
+
 static int an8801r_probe(struct phy_device *phydev)
 {
        struct device *dev = &phydev->mdio.dev;
@@ -1093,6 +1128,7 @@ static struct phy_driver airoha_driver[] = {
        .suspend                = an8801r_suspend,
        .resume                 = an8801r_resume,
        .config_aneg            = genphy_config_aneg,
+       .read_status            = an8801r_read_status,
        .config_intr            = an8801r_config_intr,
        .handle_interrupt       = an8801r_handle_interrupt,
        .set_wol                = an8801r_set_wol,