--- zzzz-none-000/linux-4.9.218/drivers/net/phy/aquantia.c 2020-04-02 15:20:41.000000000 +0000 +++ seale-7590ax-750/linux-4.9.218/drivers/net/phy/aquantia.c 2023-03-29 10:59:07.000000000 +0000 @@ -21,19 +21,114 @@ #define PHY_ID_AQ1202 0x03a1b445 #define PHY_ID_AQ2104 0x03a1b460 #define PHY_ID_AQR105 0x03a1b4a2 +#define PHY_ID_AQR107 0x03a1b4e0 #define PHY_ID_AQR405 0x03a1b4b0 +#define AQ_MDIO_AN_VENDOR_1 0xC400 +#define AQ_MDIO_AN_VENDOR_1_ADV1G 0x8000 + #define PHY_AQUANTIA_FEATURES (SUPPORTED_10000baseT_Full | \ SUPPORTED_1000baseT_Full | \ SUPPORTED_100baseT_Full | \ PHY_DEFAULT_FEATURES) +static int aquantia_c45_restart_aneg(struct phy_device *phydev) +{ + int val; + + val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); + if (val < 0) + return val; + + val |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART; + + return phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1, val); +} + +static int aquantia_config_advert(struct phy_device *phydev) +{ + int oldadv, adv; + int err, changed = 0; + + /* Setup standard advertisement */ + adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE); + if (adv < 0) + return adv; + + oldadv = adv; + adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | + ADVERTISE_PAUSE_ASYM); + adv |= ethtool_adv_to_mii_adv_t(phydev->advertising); + + if (adv != oldadv) { + err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE, + adv); + if (err < 0) + return err; + + changed = 1; + } + + /* Configure gigabit if it's supported */ + adv = phy_read_mmd(phydev, MDIO_MMD_AN, AQ_MDIO_AN_VENDOR_1); + if (adv < 0) + return adv; + + oldadv = adv; + if (phydev->advertising & SUPPORTED_1000baseT_Full) + adv |= AQ_MDIO_AN_VENDOR_1_ADV1G; + else + adv &= ~AQ_MDIO_AN_VENDOR_1_ADV1G; + + if (adv != oldadv) { + changed = 1; + err = phy_write_mmd(phydev, MDIO_MMD_AN, AQ_MDIO_AN_VENDOR_1, + adv); + if (err < 0) + return err; + } + + /* Configure 10Gigabit */ + adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL); + if (adv < 0) + return adv; + + oldadv = adv; + if (phydev->advertising & SUPPORTED_10000baseT_Full) + adv |= MDIO_AN_10GBT_CTRL_ADV10G; + else + adv &= ~MDIO_AN_10GBT_CTRL_ADV10G; + + if (adv != oldadv) { + changed = 1; + err = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, + adv); + if (err < 0) + return err; + } + + return changed; +} + static int aquantia_config_aneg(struct phy_device *phydev) { + int err; + phydev->supported = PHY_AQUANTIA_FEATURES; - phydev->advertising = phydev->supported; - return 0; + if (phydev->autoneg != AUTONEG_ENABLE) { + pr_err("%s - Autoneg-off is not supported\n", __func__); + + /* revert advertising mode to default */ + phydev->advertising = phydev->supported; + return -EINVAL; + } + + err = aquantia_config_advert(phydev); + if (err > 0) + err = aquantia_c45_restart_aneg(phydev); + + return err; } static int aquantia_aneg_done(struct phy_device *phydev) @@ -117,54 +212,66 @@ } static struct phy_driver aquantia_driver[] = { -{ - .phy_id = PHY_ID_AQ1202, - .phy_id_mask = 0xfffffff0, - .name = "Aquantia AQ1202", - .features = PHY_AQUANTIA_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .aneg_done = aquantia_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, -}, -{ - .phy_id = PHY_ID_AQ2104, - .phy_id_mask = 0xfffffff0, - .name = "Aquantia AQ2104", - .features = PHY_AQUANTIA_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .aneg_done = aquantia_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, -}, -{ - .phy_id = PHY_ID_AQR105, - .phy_id_mask = 0xfffffff0, - .name = "Aquantia AQR105", - .features = PHY_AQUANTIA_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .aneg_done = aquantia_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, -}, -{ - .phy_id = PHY_ID_AQR405, - .phy_id_mask = 0xfffffff0, - .name = "Aquantia AQR405", - .features = PHY_AQUANTIA_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .aneg_done = aquantia_aneg_done, - .config_aneg = aquantia_config_aneg, - .config_intr = aquantia_config_intr, - .ack_interrupt = aquantia_ack_interrupt, - .read_status = aquantia_read_status, -}, + { + .phy_id = PHY_ID_AQ1202, + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQ1202", + .features = PHY_AQUANTIA_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, + .config_intr = aquantia_config_intr, + .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + }, + { + .phy_id = PHY_ID_AQ2104, + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQ2104", + .features = PHY_AQUANTIA_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, + .config_intr = aquantia_config_intr, + .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + }, + { + .phy_id = PHY_ID_AQR105, + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQR105", + .features = PHY_AQUANTIA_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, + .config_intr = aquantia_config_intr, + .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + }, + { + .phy_id = PHY_ID_AQR107, + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQR107", + .features = PHY_AQUANTIA_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, + .config_intr = aquantia_config_intr, + .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + }, + { + .phy_id = PHY_ID_AQR405, + .phy_id_mask = 0xfffffff0, + .name = "Aquantia AQR405", + .features = PHY_AQUANTIA_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .aneg_done = aquantia_aneg_done, + .config_aneg = aquantia_config_aneg, + .config_intr = aquantia_config_intr, + .ack_interrupt = aquantia_ack_interrupt, + .read_status = aquantia_read_status, + }, }; module_phy_driver(aquantia_driver); @@ -173,8 +280,9 @@ { PHY_ID_AQ1202, 0xfffffff0 }, { PHY_ID_AQ2104, 0xfffffff0 }, { PHY_ID_AQR105, 0xfffffff0 }, + { PHY_ID_AQR107, 0xfffffff0 }, { PHY_ID_AQR405, 0xfffffff0 }, - { } + {} }; MODULE_DEVICE_TABLE(mdio, aquantia_tbl);