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