1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * mdio.c: Generic support for MDIO-compatible transceivers 4 * Copyright 2006-2009 Solarflare Communications Inc. 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/capability.h> 9 #include <linux/errno.h> 10 #include <linux/ethtool.h> 11 #include <linux/mdio.h> 12 #include <linux/module.h> 13 14 MODULE_DESCRIPTION("Generic support for MDIO-compatible transceivers"); 15 MODULE_AUTHOR("Copyright 2006-2009 Solarflare Communications Inc."); 16 MODULE_LICENSE("GPL"); 17 18 /** 19 * mdio45_probe - probe for an MDIO (clause 45) device 20 * @mdio: MDIO interface 21 * @prtad: Expected PHY address 22 * 23 * This sets @prtad and @mmds in the MDIO interface if successful. 24 * Returns 0 on success, negative on error. 25 */ 26 int mdio45_probe(struct mdio_if_info *mdio, int prtad) 27 { 28 int mmd, stat2, devs1, devs2; 29 30 /* Assume PHY must have at least one of PMA/PMD, WIS, PCS, PHY 31 * XS or DTE XS; give up if none is present. */ 32 for (mmd = 1; mmd <= 5; mmd++) { 33 /* Is this MMD present? */ 34 stat2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_STAT2); 35 if (stat2 < 0 || 36 (stat2 & MDIO_STAT2_DEVPRST) != MDIO_STAT2_DEVPRST_VAL) 37 continue; 38 39 /* It should tell us about all the other MMDs */ 40 devs1 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS1); 41 devs2 = mdio->mdio_read(mdio->dev, prtad, mmd, MDIO_DEVS2); 42 if (devs1 < 0 || devs2 < 0) 43 continue; 44 45 mdio->prtad = prtad; 46 mdio->mmds = devs1 | (devs2 << 16); 47 return 0; 48 } 49 50 return -ENODEV; 51 } 52 EXPORT_SYMBOL(mdio45_probe); 53 54 /** 55 * mdio_set_flag - set or clear flag in an MDIO register 56 * @mdio: MDIO interface 57 * @prtad: PHY address 58 * @devad: MMD address 59 * @addr: Register address 60 * @mask: Mask for flag (single bit set) 61 * @sense: New value of flag 62 * 63 * This debounces changes: it does not write the register if the flag 64 * already has the proper value. Returns 0 on success, negative on error. 65 */ 66 int mdio_set_flag(const struct mdio_if_info *mdio, 67 int prtad, int devad, u16 addr, int mask, 68 bool sense) 69 { 70 int old_val = mdio->mdio_read(mdio->dev, prtad, devad, addr); 71 int new_val; 72 73 if (old_val < 0) 74 return old_val; 75 if (sense) 76 new_val = old_val | mask; 77 else 78 new_val = old_val & ~mask; 79 if (old_val == new_val) 80 return 0; 81 return mdio->mdio_write(mdio->dev, prtad, devad, addr, new_val); 82 } 83 EXPORT_SYMBOL(mdio_set_flag); 84 85 /** 86 * mdio45_links_ok - is link status up/OK 87 * @mdio: MDIO interface 88 * @mmd_mask: Mask for MMDs to check 89 * 90 * Returns 1 if the PHY reports link status up/OK, 0 otherwise. 91 * @mmd_mask is normally @mdio->mmds, but if loopback is enabled 92 * the MMDs being bypassed should be excluded from the mask. 93 */ 94 int mdio45_links_ok(const struct mdio_if_info *mdio, u32 mmd_mask) 95 { 96 int devad, reg; 97 98 if (!mmd_mask) { 99 /* Use absence of XGMII faults in lieu of link state */ 100 reg = mdio->mdio_read(mdio->dev, mdio->prtad, 101 MDIO_MMD_PHYXS, MDIO_STAT2); 102 return reg >= 0 && !(reg & MDIO_STAT2_RXFAULT); 103 } 104 105 for (devad = 0; mmd_mask; devad++) { 106 if (mmd_mask & (1 << devad)) { 107 mmd_mask &= ~(1 << devad); 108 109 /* Reset the latched status and fault flags */ 110 mdio->mdio_read(mdio->dev, mdio->prtad, 111 devad, MDIO_STAT1); 112 if (devad == MDIO_MMD_PMAPMD || devad == MDIO_MMD_PCS || 113 devad == MDIO_MMD_PHYXS || devad == MDIO_MMD_DTEXS) 114 mdio->mdio_read(mdio->dev, mdio->prtad, 115 devad, MDIO_STAT2); 116 117 /* Check the current status and fault flags */ 118 reg = mdio->mdio_read(mdio->dev, mdio->prtad, 119 devad, MDIO_STAT1); 120 if (reg < 0 || 121 (reg & (MDIO_STAT1_FAULT | MDIO_STAT1_LSTATUS)) != 122 MDIO_STAT1_LSTATUS) 123 return false; 124 } 125 } 126 127 return true; 128 } 129 EXPORT_SYMBOL(mdio45_links_ok); 130 131 /** 132 * mdio45_nway_restart - restart auto-negotiation for this interface 133 * @mdio: MDIO interface 134 * 135 * Returns 0 on success, negative on error. 136 */ 137 int mdio45_nway_restart(const struct mdio_if_info *mdio) 138 { 139 if (!(mdio->mmds & MDIO_DEVS_AN)) 140 return -EOPNOTSUPP; 141 142 mdio_set_flag(mdio, mdio->prtad, MDIO_MMD_AN, MDIO_CTRL1, 143 MDIO_AN_CTRL1_RESTART, true); 144 return 0; 145 } 146 EXPORT_SYMBOL(mdio45_nway_restart); 147 148 static u32 mdio45_get_an(const struct mdio_if_info *mdio, u16 addr) 149 { 150 u32 result = 0; 151 int reg; 152 153 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, addr); 154 if (reg & ADVERTISE_10HALF) 155 result |= ADVERTISED_10baseT_Half; 156 if (reg & ADVERTISE_10FULL) 157 result |= ADVERTISED_10baseT_Full; 158 if (reg & ADVERTISE_100HALF) 159 result |= ADVERTISED_100baseT_Half; 160 if (reg & ADVERTISE_100FULL) 161 result |= ADVERTISED_100baseT_Full; 162 if (reg & ADVERTISE_PAUSE_CAP) 163 result |= ADVERTISED_Pause; 164 if (reg & ADVERTISE_PAUSE_ASYM) 165 result |= ADVERTISED_Asym_Pause; 166 return result; 167 } 168 169 /** 170 * mdio45_ethtool_ksettings_get_npage - get settings for ETHTOOL_GLINKSETTINGS 171 * @mdio: MDIO interface 172 * @cmd: Ethtool request structure 173 * @npage_adv: Modes currently advertised on next pages 174 * @npage_lpa: Modes advertised by link partner on next pages 175 * 176 * The @cmd parameter is expected to have been cleared before calling 177 * mdio45_ethtool_ksettings_get_npage(). 178 * 179 * Since the CSRs for auto-negotiation using next pages are not fully 180 * standardised, this function does not attempt to decode them. The 181 * caller must pass them in. 182 */ 183 void mdio45_ethtool_ksettings_get_npage(const struct mdio_if_info *mdio, 184 struct ethtool_link_ksettings *cmd, 185 u32 npage_adv, u32 npage_lpa) 186 { 187 int reg; 188 u32 speed, supported = 0, advertising = 0, lp_advertising = 0; 189 190 BUILD_BUG_ON(MDIO_SUPPORTS_C22 != ETH_MDIO_SUPPORTS_C22); 191 BUILD_BUG_ON(MDIO_SUPPORTS_C45 != ETH_MDIO_SUPPORTS_C45); 192 193 cmd->base.phy_address = mdio->prtad; 194 cmd->base.mdio_support = 195 mdio->mode_support & (MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22); 196 197 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 198 MDIO_CTRL2); 199 switch (reg & MDIO_PMA_CTRL2_TYPE) { 200 case MDIO_PMA_CTRL2_10GBT: 201 case MDIO_PMA_CTRL2_1000BT: 202 case MDIO_PMA_CTRL2_100BTX: 203 case MDIO_PMA_CTRL2_10BT: 204 cmd->base.port = PORT_TP; 205 supported = SUPPORTED_TP; 206 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 207 MDIO_SPEED); 208 if (reg & MDIO_SPEED_10G) 209 supported |= SUPPORTED_10000baseT_Full; 210 if (reg & MDIO_PMA_SPEED_1000) 211 supported |= (SUPPORTED_1000baseT_Full | 212 SUPPORTED_1000baseT_Half); 213 if (reg & MDIO_PMA_SPEED_100) 214 supported |= (SUPPORTED_100baseT_Full | 215 SUPPORTED_100baseT_Half); 216 if (reg & MDIO_PMA_SPEED_10) 217 supported |= (SUPPORTED_10baseT_Full | 218 SUPPORTED_10baseT_Half); 219 advertising = ADVERTISED_TP; 220 break; 221 222 case MDIO_PMA_CTRL2_10GBCX4: 223 cmd->base.port = PORT_OTHER; 224 supported = 0; 225 advertising = 0; 226 break; 227 228 case MDIO_PMA_CTRL2_10GBKX4: 229 case MDIO_PMA_CTRL2_10GBKR: 230 case MDIO_PMA_CTRL2_1000BKX: 231 cmd->base.port = PORT_OTHER; 232 supported = SUPPORTED_Backplane; 233 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 234 MDIO_PMA_EXTABLE); 235 if (reg & MDIO_PMA_EXTABLE_10GBKX4) 236 supported |= SUPPORTED_10000baseKX4_Full; 237 if (reg & MDIO_PMA_EXTABLE_10GBKR) 238 supported |= SUPPORTED_10000baseKR_Full; 239 if (reg & MDIO_PMA_EXTABLE_1000BKX) 240 supported |= SUPPORTED_1000baseKX_Full; 241 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 242 MDIO_PMA_10GBR_FECABLE); 243 if (reg & MDIO_PMA_10GBR_FECABLE_ABLE) 244 supported |= SUPPORTED_10000baseR_FEC; 245 advertising = ADVERTISED_Backplane; 246 break; 247 248 /* All the other defined modes are flavours of optical */ 249 default: 250 cmd->base.port = PORT_FIBRE; 251 supported = SUPPORTED_FIBRE; 252 advertising = ADVERTISED_FIBRE; 253 break; 254 } 255 256 if (mdio->mmds & MDIO_DEVS_AN) { 257 supported |= SUPPORTED_Autoneg; 258 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_AN, 259 MDIO_CTRL1); 260 if (reg & MDIO_AN_CTRL1_ENABLE) { 261 cmd->base.autoneg = AUTONEG_ENABLE; 262 advertising |= 263 ADVERTISED_Autoneg | 264 mdio45_get_an(mdio, MDIO_AN_ADVERTISE) | 265 npage_adv; 266 } else { 267 cmd->base.autoneg = AUTONEG_DISABLE; 268 } 269 } else { 270 cmd->base.autoneg = AUTONEG_DISABLE; 271 } 272 273 if (cmd->base.autoneg) { 274 u32 modes = 0; 275 int an_stat = mdio->mdio_read(mdio->dev, mdio->prtad, 276 MDIO_MMD_AN, MDIO_STAT1); 277 278 /* If AN is complete and successful, report best common 279 * mode, otherwise report best advertised mode. 280 */ 281 if (an_stat & MDIO_AN_STAT1_COMPLETE) { 282 lp_advertising = 283 mdio45_get_an(mdio, MDIO_AN_LPA) | npage_lpa; 284 if (an_stat & MDIO_AN_STAT1_LPABLE) 285 lp_advertising |= ADVERTISED_Autoneg; 286 modes = advertising & lp_advertising; 287 } 288 if ((modes & ~ADVERTISED_Autoneg) == 0) 289 modes = advertising; 290 291 if (modes & (ADVERTISED_10000baseT_Full | 292 ADVERTISED_10000baseKX4_Full | 293 ADVERTISED_10000baseKR_Full)) { 294 speed = SPEED_10000; 295 cmd->base.duplex = DUPLEX_FULL; 296 } else if (modes & (ADVERTISED_1000baseT_Full | 297 ADVERTISED_1000baseT_Half | 298 ADVERTISED_1000baseKX_Full)) { 299 speed = SPEED_1000; 300 cmd->base.duplex = !(modes & ADVERTISED_1000baseT_Half); 301 } else if (modes & (ADVERTISED_100baseT_Full | 302 ADVERTISED_100baseT_Half)) { 303 speed = SPEED_100; 304 cmd->base.duplex = !!(modes & ADVERTISED_100baseT_Full); 305 } else { 306 speed = SPEED_10; 307 cmd->base.duplex = !!(modes & ADVERTISED_10baseT_Full); 308 } 309 } else { 310 /* Report forced settings */ 311 reg = mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 312 MDIO_CTRL1); 313 speed = (((reg & MDIO_PMA_CTRL1_SPEED1000) ? 100 : 1) 314 * ((reg & MDIO_PMA_CTRL1_SPEED100) ? 100 : 10)); 315 cmd->base.duplex = (reg & MDIO_CTRL1_FULLDPLX || 316 speed == SPEED_10000); 317 } 318 319 cmd->base.speed = speed; 320 321 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 322 supported); 323 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 324 advertising); 325 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, 326 lp_advertising); 327 328 /* 10GBASE-T MDI/MDI-X */ 329 if (cmd->base.port == PORT_TP && (cmd->base.speed == SPEED_10000)) { 330 switch (mdio->mdio_read(mdio->dev, mdio->prtad, MDIO_MMD_PMAPMD, 331 MDIO_PMA_10GBT_SWAPPOL)) { 332 case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX: 333 cmd->base.eth_tp_mdix = ETH_TP_MDI; 334 break; 335 case 0: 336 cmd->base.eth_tp_mdix = ETH_TP_MDI_X; 337 break; 338 default: 339 /* It's complicated... */ 340 cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; 341 break; 342 } 343 } 344 } 345 EXPORT_SYMBOL(mdio45_ethtool_ksettings_get_npage); 346 347 /** 348 * mdio_mii_ioctl - MII ioctl interface for MDIO (clause 22 or 45) PHYs 349 * @mdio: MDIO interface 350 * @mii_data: MII ioctl data structure 351 * @cmd: MII ioctl command 352 * 353 * Returns 0 on success, negative on error. 354 */ 355 int mdio_mii_ioctl(const struct mdio_if_info *mdio, 356 struct mii_ioctl_data *mii_data, int cmd) 357 { 358 int prtad, devad; 359 u16 addr = mii_data->reg_num; 360 361 /* Validate/convert cmd to one of SIOC{G,S}MIIREG */ 362 switch (cmd) { 363 case SIOCGMIIPHY: 364 if (mdio->prtad == MDIO_PRTAD_NONE) 365 return -EOPNOTSUPP; 366 mii_data->phy_id = mdio->prtad; 367 cmd = SIOCGMIIREG; 368 break; 369 case SIOCGMIIREG: 370 case SIOCSMIIREG: 371 break; 372 default: 373 return -EOPNOTSUPP; 374 } 375 376 /* Validate/convert phy_id */ 377 if ((mdio->mode_support & MDIO_SUPPORTS_C45) && 378 mdio_phy_id_is_c45(mii_data->phy_id)) { 379 prtad = mdio_phy_id_prtad(mii_data->phy_id); 380 devad = mdio_phy_id_devad(mii_data->phy_id); 381 } else if ((mdio->mode_support & MDIO_SUPPORTS_C22) && 382 mii_data->phy_id < 0x20) { 383 prtad = mii_data->phy_id; 384 devad = MDIO_DEVAD_NONE; 385 addr &= 0x1f; 386 } else if ((mdio->mode_support & MDIO_EMULATE_C22) && 387 mdio->prtad != MDIO_PRTAD_NONE && 388 mii_data->phy_id == mdio->prtad) { 389 /* Remap commonly-used MII registers. */ 390 prtad = mdio->prtad; 391 switch (addr) { 392 case MII_BMCR: 393 case MII_BMSR: 394 case MII_PHYSID1: 395 case MII_PHYSID2: 396 devad = __ffs(mdio->mmds); 397 break; 398 case MII_ADVERTISE: 399 case MII_LPA: 400 if (!(mdio->mmds & MDIO_DEVS_AN)) 401 return -EINVAL; 402 devad = MDIO_MMD_AN; 403 if (addr == MII_ADVERTISE) 404 addr = MDIO_AN_ADVERTISE; 405 else 406 addr = MDIO_AN_LPA; 407 break; 408 default: 409 return -EINVAL; 410 } 411 } else { 412 return -EINVAL; 413 } 414 415 if (cmd == SIOCGMIIREG) { 416 int rc = mdio->mdio_read(mdio->dev, prtad, devad, addr); 417 if (rc < 0) 418 return rc; 419 mii_data->val_out = rc; 420 return 0; 421 } else { 422 return mdio->mdio_write(mdio->dev, prtad, devad, addr, 423 mii_data->val_in); 424 } 425 } 426 EXPORT_SYMBOL(mdio_mii_ioctl); 427