|
|
@@ -1,166 +0,0 @@
|
|
|
---- a/drivers/net/phy/mxl-gpy.c
|
|
|
-+++ b/drivers/net/phy/mxl-gpy.c
|
|
|
-@@ -126,6 +126,12 @@ static int gpy_config_init(struct phy_de
|
|
|
- if (ret < 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
-+ /* Disable SGMII auto-negotiation */
|
|
|
-+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
|
|
|
-+ VSPEC1_SGMII_CTRL_ANEN, 0);
|
|
|
-+ if (ret < 0)
|
|
|
-+ return ret;
|
|
|
-+
|
|
|
- return gpy_led_write(phydev);
|
|
|
- }
|
|
|
-
|
|
|
-@@ -151,65 +157,6 @@ static int gpy_probe(struct phy_device *
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
--static bool gpy_sgmii_need_reaneg(struct phy_device *phydev)
|
|
|
--{
|
|
|
-- int fw_ver, fw_type, fw_minor;
|
|
|
-- size_t i;
|
|
|
--
|
|
|
-- fw_ver = phy_read(phydev, PHY_FWV);
|
|
|
-- if (fw_ver < 0)
|
|
|
-- return true;
|
|
|
--
|
|
|
-- fw_type = FIELD_GET(PHY_FWV_TYPE_MASK, fw_ver);
|
|
|
-- fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, fw_ver);
|
|
|
--
|
|
|
-- for (i = 0; i < ARRAY_SIZE(ver_need_sgmii_reaneg); i++) {
|
|
|
-- if (fw_type != ver_need_sgmii_reaneg[i].type)
|
|
|
-- continue;
|
|
|
-- if (fw_minor < ver_need_sgmii_reaneg[i].minor)
|
|
|
-- return true;
|
|
|
-- break;
|
|
|
-- }
|
|
|
--
|
|
|
-- return false;
|
|
|
--}
|
|
|
--
|
|
|
--static bool gpy_2500basex_chk(struct phy_device *phydev)
|
|
|
--{
|
|
|
-- int ret;
|
|
|
--
|
|
|
-- ret = phy_read(phydev, PHY_MIISTAT);
|
|
|
-- if (ret < 0) {
|
|
|
-- phydev_err(phydev, "Error: MDIO register access failed: %d\n",
|
|
|
-- ret);
|
|
|
-- return false;
|
|
|
-- }
|
|
|
--
|
|
|
-- if (!(ret & PHY_MIISTAT_LS) ||
|
|
|
-- FIELD_GET(PHY_MIISTAT_SPD_MASK, ret) != PHY_MIISTAT_SPD_2500)
|
|
|
-- return false;
|
|
|
--
|
|
|
-- phydev->speed = SPEED_2500;
|
|
|
-- phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
|
|
|
-- phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
|
|
|
-- VSPEC1_SGMII_CTRL_ANEN, 0);
|
|
|
-- return true;
|
|
|
--}
|
|
|
--
|
|
|
--static bool gpy_sgmii_aneg_en(struct phy_device *phydev)
|
|
|
--{
|
|
|
-- int ret;
|
|
|
--
|
|
|
-- ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL);
|
|
|
-- if (ret < 0) {
|
|
|
-- phydev_err(phydev, "Error: MMD register access failed: %d\n",
|
|
|
-- ret);
|
|
|
-- return true;
|
|
|
-- }
|
|
|
--
|
|
|
-- return (ret & VSPEC1_SGMII_CTRL_ANEN) ? true : false;
|
|
|
--}
|
|
|
--
|
|
|
- static int gpy_config_aneg(struct phy_device *phydev)
|
|
|
- {
|
|
|
- bool changed = false;
|
|
|
-@@ -248,53 +195,11 @@ static int gpy_config_aneg(struct phy_de
|
|
|
- phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
|
|
|
- return 0;
|
|
|
-
|
|
|
-- /* No need to trigger re-ANEG if link speed is 2.5G or SGMII ANEG is
|
|
|
-- * disabled.
|
|
|
-- */
|
|
|
-- if (!gpy_sgmii_need_reaneg(phydev) || gpy_2500basex_chk(phydev) ||
|
|
|
-- !gpy_sgmii_aneg_en(phydev))
|
|
|
-- return 0;
|
|
|
--
|
|
|
-- /* There is a design constraint in GPY2xx device where SGMII AN is
|
|
|
-- * only triggered when there is change of speed. If, PHY link
|
|
|
-- * partner`s speed is still same even after PHY TPI is down and up
|
|
|
-- * again, SGMII AN is not triggered and hence no new in-band message
|
|
|
-- * from GPY to MAC side SGMII.
|
|
|
-- * This could cause an issue during power up, when PHY is up prior to
|
|
|
-- * MAC. At this condition, once MAC side SGMII is up, MAC side SGMII
|
|
|
-- * wouldn`t receive new in-band message from GPY with correct link
|
|
|
-- * status, speed and duplex info.
|
|
|
-- *
|
|
|
-- * 1) If PHY is already up and TPI link status is still down (such as
|
|
|
-- * hard reboot), TPI link status is polled for 4 seconds before
|
|
|
-- * retriggerring SGMII AN.
|
|
|
-- * 2) If PHY is already up and TPI link status is also up (such as soft
|
|
|
-- * reboot), polling of TPI link status is not needed and SGMII AN is
|
|
|
-- * immediately retriggered.
|
|
|
-- * 3) Other conditions such as PHY is down, speed change etc, skip
|
|
|
-- * retriggering SGMII AN. Note: in case of speed change, GPY FW will
|
|
|
-- * initiate SGMII AN.
|
|
|
-- */
|
|
|
--
|
|
|
-- if (phydev->state != PHY_UP)
|
|
|
-- return 0;
|
|
|
--
|
|
|
-- ret = phy_read_poll_timeout(phydev, MII_BMSR, ret, ret & BMSR_LSTATUS,
|
|
|
-- 20000, 4000000, false);
|
|
|
-- if (ret == -ETIMEDOUT)
|
|
|
-- return 0;
|
|
|
-- else if (ret < 0)
|
|
|
-- return ret;
|
|
|
--
|
|
|
-- /* Trigger SGMII AN. */
|
|
|
-- return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
|
|
|
-- VSPEC1_SGMII_CTRL_ANRS, VSPEC1_SGMII_CTRL_ANRS);
|
|
|
-+ return 0;
|
|
|
- }
|
|
|
-
|
|
|
- static void gpy_update_interface(struct phy_device *phydev)
|
|
|
- {
|
|
|
-- int ret;
|
|
|
--
|
|
|
- /* Interface mode is fixed for USXGMII and integrated PHY */
|
|
|
- if (phydev->interface == PHY_INTERFACE_MODE_USXGMII ||
|
|
|
- phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
|
|
|
-@@ -306,29 +211,11 @@ static void gpy_update_interface(struct
|
|
|
- switch (phydev->speed) {
|
|
|
- case SPEED_2500:
|
|
|
- phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
|
|
|
-- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
|
|
|
-- VSPEC1_SGMII_CTRL_ANEN, 0);
|
|
|
-- if (ret < 0)
|
|
|
-- phydev_err(phydev,
|
|
|
-- "Error: Disable of SGMII ANEG failed: %d\n",
|
|
|
-- ret);
|
|
|
- break;
|
|
|
- case SPEED_1000:
|
|
|
- case SPEED_100:
|
|
|
- case SPEED_10:
|
|
|
- phydev->interface = PHY_INTERFACE_MODE_SGMII;
|
|
|
-- if (gpy_sgmii_aneg_en(phydev))
|
|
|
-- break;
|
|
|
-- /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed
|
|
|
-- * if ANEG is disabled (in 2500-BaseX mode).
|
|
|
-- */
|
|
|
-- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
|
|
|
-- VSPEC1_SGMII_ANEN_ANRS,
|
|
|
-- VSPEC1_SGMII_ANEN_ANRS);
|
|
|
-- if (ret < 0)
|
|
|
-- phydev_err(phydev,
|
|
|
-- "Error: Enable of SGMII ANEG failed: %d\n",
|
|
|
-- ret);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|