1 // SPDX-License-Identifier: GPL-2.0 2 // Broadcom BCM84881 NBASE-T PHY driver, as found on a SFP+ module. 3 // Copyright (C) 2019 Russell King, Deep Blue Solutions Ltd. 4 // 5 // Like the Marvell 88x3310, the Broadcom 84881 changes its host-side 6 // interface according to the operating speed between 10GBASE-R, 7 // 2500BASE-X and SGMII (but unlike the 88x3310, without the control 8 // word). 9 // 10 // This driver only supports those aspects of the PHY that I'm able to 11 // observe and test with the SFP+ module, which is an incomplete subset 12 // of what this PHY is able to support. For example, I only assume it 13 // supports a single lane Serdes connection, but it may be that the PHY 14 // is able to support more than that. 15 #include <linux/delay.h> 16 #include <linux/module.h> 17 #include <linux/phy.h> 18 19 enum { 20 MDIO_AN_C22 = 0xffe0, 21 }; 22 23 static int bcm84881_wait_init(struct phy_device *phydev) 24 { 25 unsigned int tries = 20; 26 int ret, val; 27 28 do { 29 val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1); 30 if (val < 0) { 31 ret = val; 32 break; 33 } 34 if (!(val & MDIO_CTRL1_RESET)) { 35 ret = 0; 36 break; 37 } 38 if (!--tries) { 39 ret = -ETIMEDOUT; 40 break; 41 } 42 msleep(100); 43 } while (1); 44 45 if (ret) 46 phydev_err(phydev, "%s failed: %d\n", __func__, ret); 47 48 return ret; 49 } 50 51 static int bcm84881_config_init(struct phy_device *phydev) 52 { 53 switch (phydev->interface) { 54 case PHY_INTERFACE_MODE_SGMII: 55 case PHY_INTERFACE_MODE_2500BASEX: 56 case PHY_INTERFACE_MODE_10GBASER: 57 break; 58 default: 59 return -ENODEV; 60 } 61 return 0; 62 } 63 64 static int bcm84881_probe(struct phy_device *phydev) 65 { 66 /* This driver requires PMAPMD and AN blocks */ 67 const u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN; 68 69 if (!phydev->is_c45 || 70 (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask) 71 return -ENODEV; 72 73 return 0; 74 } 75 76 static int bcm84881_get_features(struct phy_device *phydev) 77 { 78 int ret; 79 80 ret = genphy_c45_pma_read_abilities(phydev); 81 if (ret) 82 return ret; 83 84 /* Although the PHY sets bit 1.11.8, it does not support 10M modes */ 85 linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, 86 phydev->supported); 87 linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, 88 phydev->supported); 89 90 return 0; 91 } 92 93 static int bcm84881_config_aneg(struct phy_device *phydev) 94 { 95 bool changed = false; 96 u32 adv; 97 int ret; 98 99 /* Wait for the PHY to finish initialising, otherwise our 100 * advertisement may be overwritten. 101 */ 102 ret = bcm84881_wait_init(phydev); 103 if (ret) 104 return ret; 105 106 /* We don't support manual MDI control */ 107 phydev->mdix_ctrl = ETH_TP_MDI_AUTO; 108 109 /* disabled autoneg doesn't seem to work with this PHY */ 110 if (phydev->autoneg == AUTONEG_DISABLE) 111 return -EINVAL; 112 113 ret = genphy_c45_an_config_aneg(phydev); 114 if (ret < 0) 115 return ret; 116 if (ret > 0) 117 changed = true; 118 119 adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); 120 ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, 121 MDIO_AN_C22 + MII_CTRL1000, 122 ADVERTISE_1000FULL | ADVERTISE_1000HALF, 123 adv); 124 if (ret < 0) 125 return ret; 126 if (ret > 0) 127 changed = true; 128 129 return genphy_c45_check_and_restart_aneg(phydev, changed); 130 } 131 132 static int bcm84881_aneg_done(struct phy_device *phydev) 133 { 134 int bmsr, val; 135 136 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); 137 if (val < 0) 138 return val; 139 140 bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR); 141 if (bmsr < 0) 142 return val; 143 144 return !!(val & MDIO_AN_STAT1_COMPLETE) && 145 !!(bmsr & BMSR_ANEGCOMPLETE); 146 } 147 148 static int bcm84881_read_status(struct phy_device *phydev) 149 { 150 unsigned int mode; 151 int bmsr, val; 152 153 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1); 154 if (val < 0) 155 return val; 156 157 if (val & MDIO_AN_CTRL1_RESTART) { 158 phydev->link = 0; 159 return 0; 160 } 161 162 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1); 163 if (val < 0) 164 return val; 165 166 bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR); 167 if (bmsr < 0) 168 return val; 169 170 phydev->autoneg_complete = !!(val & MDIO_AN_STAT1_COMPLETE) && 171 !!(bmsr & BMSR_ANEGCOMPLETE); 172 phydev->link = !!(val & MDIO_STAT1_LSTATUS) && 173 !!(bmsr & BMSR_LSTATUS); 174 if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete) 175 phydev->link = false; 176 177 if (!phydev->link) 178 return 0; 179 180 linkmode_zero(phydev->lp_advertising); 181 phydev->speed = SPEED_UNKNOWN; 182 phydev->duplex = DUPLEX_UNKNOWN; 183 phydev->pause = 0; 184 phydev->asym_pause = 0; 185 phydev->mdix = 0; 186 187 if (phydev->autoneg_complete) { 188 val = genphy_c45_read_lpa(phydev); 189 if (val < 0) 190 return val; 191 192 val = phy_read_mmd(phydev, MDIO_MMD_AN, 193 MDIO_AN_C22 + MII_STAT1000); 194 if (val < 0) 195 return val; 196 197 mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val); 198 199 if (phydev->autoneg == AUTONEG_ENABLE) 200 phy_resolve_aneg_linkmode(phydev); 201 } 202 203 if (phydev->autoneg == AUTONEG_DISABLE) { 204 /* disabled autoneg doesn't seem to work, so force the link 205 * down. 206 */ 207 phydev->link = 0; 208 return 0; 209 } 210 211 /* Set the host link mode - we set the phy interface mode and 212 * the speed according to this register so that downshift works. 213 * We leave the duplex setting as per the resolution from the 214 * above. 215 */ 216 val = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x4011); 217 mode = (val & 0x1e) >> 1; 218 if (mode == 1 || mode == 2) 219 phydev->interface = PHY_INTERFACE_MODE_SGMII; 220 else if (mode == 3) 221 phydev->interface = PHY_INTERFACE_MODE_10GBASER; 222 else if (mode == 4) 223 phydev->interface = PHY_INTERFACE_MODE_2500BASEX; 224 switch (mode & 7) { 225 case 1: 226 phydev->speed = SPEED_100; 227 break; 228 case 2: 229 phydev->speed = SPEED_1000; 230 break; 231 case 3: 232 phydev->speed = SPEED_10000; 233 break; 234 case 4: 235 phydev->speed = SPEED_2500; 236 break; 237 case 5: 238 phydev->speed = SPEED_5000; 239 break; 240 } 241 242 return genphy_c45_read_mdix(phydev); 243 } 244 245 static struct phy_driver bcm84881_drivers[] = { 246 { 247 .phy_id = 0xae025150, 248 .phy_id_mask = 0xfffffff0, 249 .name = "Broadcom BCM84881", 250 .config_init = bcm84881_config_init, 251 .probe = bcm84881_probe, 252 .get_features = bcm84881_get_features, 253 .config_aneg = bcm84881_config_aneg, 254 .aneg_done = bcm84881_aneg_done, 255 .read_status = bcm84881_read_status, 256 }, 257 }; 258 259 module_phy_driver(bcm84881_drivers); 260 261 /* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */ 262 static struct mdio_device_id __maybe_unused bcm84881_tbl[] = { 263 { 0xae025150, 0xfffffff0 }, 264 { }, 265 }; 266 MODULE_AUTHOR("Russell King"); 267 MODULE_DESCRIPTION("Broadcom BCM84881 PHY driver"); 268 MODULE_DEVICE_TABLE(mdio, bcm84881_tbl); 269 MODULE_LICENSE("GPL"); 270