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 --- drivers/net/phy/air_an8801.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/net/phy/air_an8801.c b/drivers/net/phy/air_an8801.c index a0f164cbf92b..af46951b1a33 100644 --- a/drivers/net/phy/air_an8801.c +++ b/drivers/net/phy/air_an8801.c @@ -964,6 +964,36 @@ 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 && 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; @@ -1061,6 +1091,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, -- 2.54.0