^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Clause 45 PHY support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/ethtool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/mdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/mii.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/phy.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * genphy_c45_setup_forced - configures a forced speed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) int genphy_c45_pma_setup_forced(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int ctrl1, ctrl2, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* Half duplex is not supported */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) if (phydev->duplex != DUPLEX_FULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (ctrl1 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return ctrl1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (ctrl2 < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return ctrl2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * PMA/PMD type selection is 1.7.5:0 not 1.7.3:0. See 45.2.1.6.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * in 802.3-2012 and 802.3-2015.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) switch (phydev->speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) case SPEED_10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) ctrl2 |= MDIO_PMA_CTRL2_10BT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case SPEED_100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) ctrl2 |= MDIO_PMA_CTRL2_100BTX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) case SPEED_1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* Assume 1000base-T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) ctrl2 |= MDIO_PMA_CTRL2_1000BT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case SPEED_2500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ctrl1 |= MDIO_CTRL1_SPEED2_5G;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* Assume 2.5Gbase-T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) ctrl2 |= MDIO_PMA_CTRL2_2_5GBT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case SPEED_5000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ctrl1 |= MDIO_CTRL1_SPEED5G;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Assume 5Gbase-T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) ctrl2 |= MDIO_PMA_CTRL2_5GBT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case SPEED_10000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ctrl1 |= MDIO_CTRL1_SPEED10G;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* Assume 10Gbase-T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) ctrl2 |= MDIO_PMA_CTRL2_10GBT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return genphy_c45_an_disable_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * genphy_c45_an_config_aneg - configure advertisement registers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * Configure advertisement registers based on modes set in phydev->advertising
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Returns negative errno code on failure, 0 if advertisement didn't change,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * or 1 if advertised modes changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int genphy_c45_an_config_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int changed, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 adv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) linkmode_and(phydev->advertising, phydev->advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) changed = genphy_config_eee_advert(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) adv = linkmode_adv_to_mii_adv_t(phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ADVERTISE_ALL | ADVERTISE_100BASE4 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) MDIO_AN_10GBT_CTRL_ADV10G |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) MDIO_AN_10GBT_CTRL_ADV5G |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) MDIO_AN_10GBT_CTRL_ADV2_5G, adv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) changed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) EXPORT_SYMBOL_GPL(genphy_c45_an_config_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * genphy_c45_an_disable_aneg - disable auto-negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Disable auto-negotiation in the Clause 45 PHY. The link parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * parameters are controlled through the PMA/PMD MMD registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * Returns zero on success, negative errno code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int genphy_c45_an_disable_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * genphy_c45_restart_aneg - Enable and restart auto-negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * This assumes that the auto-negotiation MMD is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Enable and restart auto-negotiation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int genphy_c45_restart_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * genphy_c45_check_and_restart_aneg - Enable and restart auto-negotiation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * @restart: whether aneg restart is requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * This assumes that the auto-negotiation MMD is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * Check, and restart auto-negotiation if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (!restart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Configure and restart aneg if it wasn't set before */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (!(ret & MDIO_AN_CTRL1_ENABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) restart = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (restart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return genphy_c45_restart_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * genphy_c45_aneg_done - return auto-negotiation complete status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * This assumes that the auto-negotiation MMD is present.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * Reads the status register from the auto-negotiation MMD, returning:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * - positive if auto-negotiation is complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * - negative errno code on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * - zero otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int genphy_c45_aneg_done(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * genphy_c45_read_link - read the overall link status from the MMDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * Read the link status from the specified MMDs, and if they all indicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * that the link is up, set phydev->link to 1. If an error is encountered,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * a negative errno will be returned, otherwise zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int genphy_c45_read_link(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) u32 mmd_mask = MDIO_DEVS_PMAPMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int val, devad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) bool link = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (phydev->c45_ids.mmds_present & MDIO_DEVS_AN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* Autoneg is being started, therefore disregard current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * link status and report link as down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) if (val & MDIO_AN_CTRL1_RESTART) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) phydev->link = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) while (mmd_mask && link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) devad = __ffs(mmd_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mmd_mask &= ~BIT(devad);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* The link state is latched low so that momentary link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * drops can be detected. Do not double-read the status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * in polling mode to detect such short link drops except
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * the link was already down.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!phy_polling_mode(phydev) || !phydev->link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) val = phy_read_mmd(phydev, devad, MDIO_STAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) else if (val & MDIO_STAT1_LSTATUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) val = phy_read_mmd(phydev, devad, MDIO_STAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!(val & MDIO_STAT1_LSTATUS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) link = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) phydev->link = link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) EXPORT_SYMBOL_GPL(genphy_c45_read_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * genphy_c45_read_lpa - read the link partner advertisement and pause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * filling in the link partner advertisement, pause and asym_pause members
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * in @phydev. This assumes that the auto-negotiation MMD is present, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * the backplane bit (7.48.0) is clear. Clause 45 PHY drivers are expected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * to fill in the remainder of the link partner advert from vendor registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int genphy_c45_read_lpa(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!(val & MDIO_AN_STAT1_COMPLETE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) phydev->lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) phydev->pause = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) phydev->asym_pause = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->lp_advertising,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) val & MDIO_AN_STAT1_LPABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /* Read the link partner's base page advertisement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Read the link partner's 10G advertisement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * genphy_c45_read_pma - read link speed etc from PMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int genphy_c45_read_pma(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) linkmode_zero(phydev->lp_advertising);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) switch (val & MDIO_CTRL1_SPEEDSEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) phydev->speed = SPEED_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) case MDIO_PMA_CTRL1_SPEED100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) phydev->speed = SPEED_100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case MDIO_PMA_CTRL1_SPEED1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) phydev->speed = SPEED_1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case MDIO_CTRL1_SPEED2_5G:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) phydev->speed = SPEED_2500;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case MDIO_CTRL1_SPEED5G:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) phydev->speed = SPEED_5000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case MDIO_CTRL1_SPEED10G:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) phydev->speed = SPEED_10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) phydev->speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) phydev->duplex = DUPLEX_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * genphy_c45_read_mdix - read mdix status from PMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) int genphy_c45_read_mdix(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (phydev->speed == SPEED_10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) MDIO_PMA_10GBT_SWAPPOL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) phydev->mdix = ETH_TP_MDI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) phydev->mdix = ETH_TP_MDI_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) phydev->mdix = ETH_TP_MDI_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * genphy_c45_pma_read_abilities - read supported link modes from PMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Read the supported link modes from the PMA Status 2 (1.8) register. If bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * 1.8.9 is set, the list of supported modes is build using the values in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * modes. If bit 1.11.14 is set, then the list is also extended with the modes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * 5GBASET are supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int genphy_c45_pma_read_abilities(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (phydev->c45_ids.mmds_present & MDIO_DEVS_AN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (val & MDIO_AN_STAT1_ABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) phydev->supported);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) val & MDIO_PMA_STAT2_10GBSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) val & MDIO_PMA_STAT2_10GBLR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) val & MDIO_PMA_STAT2_10GBER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (val & MDIO_PMA_STAT2_EXTABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) val & MDIO_PMA_EXTABLE_10GBLRM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) val & MDIO_PMA_EXTABLE_10GBT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) val & MDIO_PMA_EXTABLE_10GBKX4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) val & MDIO_PMA_EXTABLE_10GBKR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) val & MDIO_PMA_EXTABLE_1000BT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) val & MDIO_PMA_EXTABLE_1000BKX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) val & MDIO_PMA_EXTABLE_100BTX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) val & MDIO_PMA_EXTABLE_100BTX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) val & MDIO_PMA_EXTABLE_10BT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) val & MDIO_PMA_EXTABLE_10BT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (val & MDIO_PMA_EXTABLE_NBT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) MDIO_PMA_NG_EXTABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (val < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) val & MDIO_PMA_NG_EXTABLE_2_5GBT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) phydev->supported,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) val & MDIO_PMA_NG_EXTABLE_5GBT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * genphy_c45_read_status - read PHY status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * Reads status from PHY and sets phy_device members accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) int genphy_c45_read_status(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) ret = genphy_c45_read_link(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) phydev->speed = SPEED_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) phydev->duplex = DUPLEX_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) phydev->pause = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) phydev->asym_pause = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (phydev->autoneg == AUTONEG_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ret = genphy_c45_read_lpa(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) phy_resolve_aneg_linkmode(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) ret = genphy_c45_read_pma(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) EXPORT_SYMBOL_GPL(genphy_c45_read_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) * genphy_c45_config_aneg - restart auto-negotiation or forced setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * @phydev: target phy_device struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * Description: If auto-negotiation is enabled, we configure the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * advertising, and then restart auto-negotiation. If it is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * enabled, then we force a configuration.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) int genphy_c45_config_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) bool changed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (phydev->autoneg == AUTONEG_DISABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return genphy_c45_pma_setup_forced(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ret = genphy_c45_an_config_aneg(phydev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (ret > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return genphy_c45_check_and_restart_aneg(phydev, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) EXPORT_SYMBOL_GPL(genphy_c45_config_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) /* The gen10g_* functions are the old Clause 45 stub */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) int gen10g_config_aneg(struct phy_device *phydev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) EXPORT_SYMBOL_GPL(gen10g_config_aneg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) struct phy_driver genphy_c45_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) .phy_id = 0xffffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) .phy_id_mask = 0xffffffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) .name = "Generic Clause 45 PHY",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) .read_status = genphy_c45_read_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) };