diff --git a/drivers/net/phy/air_an8801.c b/drivers/net/phy/air_an8801.c index aa24bb182d64..f97c78e43023 100644 --- a/drivers/net/phy/air_an8801.c +++ b/drivers/net/phy/air_an8801.c @@ -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,