From: Andrew Lunn <and...@lunn.ch>
Make use of the generic c45 code, plus code specific to the Aquantia
phy for 1000BaseT negotiation.

Signed-off-by: Andrew Lunn <and...@lunn.ch>
Signed-off-by: Heiner Kallweit <hkallwe...@gmail.com>
---
 drivers/net/phy/aquantia.c | 40 +++++++++++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c
index 9661ef4b4..a1846daa3 100644
--- a/drivers/net/phy/aquantia.c
+++ b/drivers/net/phy/aquantia.c
@@ -20,6 +20,10 @@
 #define PHY_ID_AQCS109 0x03a1b5c2
 #define PHY_ID_AQR405  0x03a1b4b0
 
+#define MDIO_AN_VEND_PROV                      0xc400
+#define MDIO_AN_VEND_PROV_1000BASET_FULL       BIT(15)
+#define MDIO_AN_VEND_PROV_1000BASET_HALF       BIT(14)
+
 #define MDIO_AN_TX_VEND_STATUS1                        0xc800
 #define MDIO_AN_TX_VEND_STATUS1_10BASET                (0x0 << 1)
 #define MDIO_AN_TX_VEND_STATUS1_100BASETX      (0x1 << 1)
@@ -64,10 +68,40 @@
 
 static int aqr_config_aneg(struct phy_device *phydev)
 {
-       linkmode_copy(phydev->supported, phy_10gbit_features);
-       linkmode_copy(phydev->advertising, phydev->supported);
+       bool changed = false;
+       u16 reg;
+       int ret;
 
-       return 0;
+       if (phydev->autoneg == AUTONEG_DISABLE)
+               return genphy_c45_pma_setup_forced(phydev);
+
+       ret = genphy_c45_an_config_aneg(phydev);
+       if (ret < 0)
+               return ret;
+       if (ret > 0)
+               changed = true;
+
+       /* Clause 45 has no standardized support for 1000BaseT, therefore
+        * use vendor registers for this mode.
+        */
+       reg = 0;
+       if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+                             phydev->advertising))
+               reg |= MDIO_AN_VEND_PROV_1000BASET_FULL;
+
+       if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
+                             phydev->advertising))
+               reg |= MDIO_AN_VEND_PROV_1000BASET_HALF;
+
+       ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV,
+                                    MDIO_AN_VEND_PROV_1000BASET_HALF |
+                                    MDIO_AN_VEND_PROV_1000BASET_FULL, reg);
+       if (ret < 0)
+               return ret;
+       if (ret > 0)
+               changed = true;
+
+       return genphy_c45_check_and_restart_aneg(phydev, changed);
 }
 
 static int aqr_config_intr(struct phy_device *phydev)
-- 
2.20.1


Reply via email to