1 /* $NetBSD: makphy.c,v 1.73 2024/02/09 22:08:35 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 */ 56 57 /* 58 * Driver for the Marvell 88E1000 ``Alaska'' 10/100/1000 PHY. 59 */ 60 61 #include <sys/cdefs.h> 62 __KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.73 2024/02/09 22:08:35 andvar Exp $"); 63 64 #include <sys/param.h> 65 #include <sys/systm.h> 66 #include <sys/kernel.h> 67 #include <sys/device.h> 68 #include <sys/socket.h> 69 #include <sys/errno.h> 70 71 #include <net/if.h> 72 #include <net/if_media.h> 73 74 #include <dev/mii/mii.h> 75 #include <dev/mii/miivar.h> 76 #include <dev/mii/miidevs.h> 77 78 #include <dev/mii/makphyreg.h> 79 #include <dev/mii/makphyvar.h> 80 81 static int makphymatch(device_t, cfdata_t, void *); 82 static void makphyattach(device_t, device_t, void *); 83 84 CFATTACH_DECL_NEW(makphy, sizeof(struct makphy_softc), 85 makphymatch, makphyattach, mii_phy_detach, mii_phy_activate); 86 87 static int makphy_service(struct mii_softc *, struct mii_data *, int); 88 static void makphy_status(struct mii_softc *); 89 static void makphy_reset(struct mii_softc *); 90 91 static const struct mii_phy_funcs makphy_funcs = { 92 makphy_service, makphy_status, makphy_reset, 93 }; 94 95 static const struct mii_phydesc makphys[] = { 96 MII_PHY_DESC(MARVELL, E1000_0), 97 MII_PHY_DESC(MARVELL, E1000_3), 98 MII_PHY_DESC(MARVELL, E1000_5), 99 MII_PHY_DESC(MARVELL, E1000_6), 100 MII_PHY_DESC(xxMARVELL, E1000_3), 101 MII_PHY_DESC(xxMARVELL, E1000_5), 102 MII_PHY_DESC(xxMARVELL, E1000S), 103 MII_PHY_DESC(xxMARVELL, E1011), 104 MII_PHY_DESC(xxMARVELL, E1101), 105 MII_PHY_DESC(xxMARVELL, E1111), 106 MII_PHY_DESC(xxMARVELL, E1112), 107 MII_PHY_DESC(xxMARVELL, E1116), 108 MII_PHY_DESC(xxMARVELL, E1116R), 109 MII_PHY_DESC(xxMARVELL, E1118), 110 MII_PHY_DESC(xxMARVELL, E1145), 111 MII_PHY_DESC(xxMARVELL, E1149), 112 MII_PHY_DESC(xxMARVELL, E1149R), 113 MII_PHY_DESC(xxMARVELL, E1240), 114 MII_PHY_DESC(xxMARVELL, E1318S), 115 MII_PHY_DESC(xxMARVELL, E1512), 116 MII_PHY_DESC(xxMARVELL, E1543), 117 MII_PHY_DESC(xxMARVELL, E3016), 118 MII_PHY_DESC(xxMARVELL, E3082), 119 MII_PHY_DESC(xxMARVELL, PHYG65G), 120 MII_PHY_DESC(xxMARVELL, I347), 121 MII_PHY_END, 122 }; 123 124 #define MAKARG_PDOWN true /* Power DOWN */ 125 #define MAKARG_PUP false /* Power UP */ 126 127 static bool 128 makphy_isi210(device_t parent, struct mii_attach_args *ma) 129 { 130 131 /* I21[01]'s model number is 0 */ 132 if ((MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxMARVELL) 133 && (MII_MODEL(ma->mii_id2) == MII_MODEL_xxMARVELL_I210) 134 && (device_is_a(parent, "wm"))) 135 return true; 136 return false; 137 } 138 139 static int 140 makphymatch(device_t parent, cfdata_t match, void *aux) 141 { 142 struct mii_attach_args *ma = aux; 143 144 if (mii_phy_match(ma, makphys) != NULL) 145 return 10; 146 147 if (makphy_isi210(parent, ma)) 148 return 10; 149 150 return 0; 151 } 152 153 static void 154 makphyattach(device_t parent, device_t self, void *aux) 155 { 156 struct mii_softc *sc = device_private(self); 157 struct mii_attach_args *ma = aux; 158 struct mii_data *mii = ma->mii_data; 159 const struct mii_phydesc *mpd; 160 struct makphy_softc *maksc = (struct makphy_softc *)sc; 161 const char *name; 162 uint16_t reg, model; 163 int rv; 164 165 mpd = mii_phy_match(ma, makphys); 166 aprint_naive(": Media interface\n"); 167 if (mpd) 168 name = mpd->mpd_name; 169 else if (makphy_isi210(parent, ma)) { 170 name = MII_STR_xxMARVELL_I210; 171 maksc->sc_flags |= MAKPHY_F_I210; 172 } else 173 panic("Unknown PHY"); 174 aprint_normal(": %s, rev. %d\n", name, MII_REV(ma->mii_id2)); 175 176 sc->mii_dev = self; 177 sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); 178 sc->mii_mpd_model = model = MII_MODEL(ma->mii_id2); 179 sc->mii_mpd_rev = MII_REV(ma->mii_id2); 180 sc->mii_inst = mii->mii_instance; 181 sc->mii_phy = ma->mii_phyno; 182 sc->mii_funcs = &makphy_funcs; 183 sc->mii_pdata = mii; 184 sc->mii_flags = ma->mii_flags; 185 186 mii_lock(mii); 187 188 switch (model) { 189 case MII_MODEL_xxMARVELL_E1000: 190 if ((maksc->sc_flags & MAKPHY_F_I210) != 0) 191 goto page0; 192 /* FALLTHROUGH */ 193 case MII_MODEL_xxMARVELL_E1000_3: 194 case MII_MODEL_xxMARVELL_E1000S: 195 case MII_MODEL_xxMARVELL_E1000_5: 196 /* 88E1000 series has no EADR */ 197 break; 198 default: 199 page0: 200 /* Make sure page 0 is selected. */ 201 if (PHY_WRITE(sc, MAKPHY_EADR, 0) != 0) 202 aprint_verbose_dev(self, 203 "Failed to access EADR. Are you an emulator?\n"); 204 break; 205 } 206 207 PHY_RESET(sc); 208 209 PHY_READ(sc, MII_BMSR, &sc->mii_capabilities); 210 sc->mii_capabilities &= ma->mii_capmask; 211 if (sc->mii_capabilities & BMSR_EXTSTAT) { 212 rv = PHY_READ(sc, MII_EXTSR, &sc->mii_extcapabilities); 213 if (rv != 0) { 214 aprint_verbose_dev(self, "Failed to read EXTSR. " 215 "Are you an emulator?. " 216 "Regard as 1000BASE-T.\n"); 217 sc->mii_extcapabilities 218 |= EXTSR_1000TFDX | EXTSR_1000THDX; 219 220 /* 221 * Also assume it doesn't support PSSR_LINK bit. 222 * It's for QEMU. 223 */ 224 maksc->sc_flags |= MAKPHY_QUIRK_PSSR_LINK; 225 } 226 } 227 228 if (((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) 229 != 0) 230 && ((sc->mii_extcapabilities & (EXTSR_1000XFDX | EXTSR_1000XHDX)) 231 != 0)) { 232 bool fiberonly = false, copperonly = false; 233 234 /* Both copper and fiber are set. check MODE[] */ 235 switch (sc->mii_mpd_model) { 236 case MII_MODEL_xxMARVELL_E1011: 237 case MII_MODEL_xxMARVELL_E1111: 238 /* These devices have ESSR register */ 239 rv = PHY_READ(sc, MAKPHY_ESSR, ®); 240 if (rv != 0) { 241 /* 242 * XXX Emulator (e.g qemu) may not implement 243 * the ESSR register. If so, regard as copper 244 * media. 245 */ 246 copperonly = true; 247 aprint_verbose_dev(self, "Failed to access " 248 "ESSR. Are you an emulator? Regard as " 249 "copper only media.\n"); 250 } else if ((reg & ESSR_AUTOSEL_DISABLE) != 0) { 251 switch (reg & ESSR_HWCFG_MODE) { 252 case ESSR_RTBI_FIBER: 253 case ESSR_RGMII_FIBER: 254 case ESSR_RGMII_SGMII: /* right? */ 255 case ESSR_TBI_FIBER: 256 case ESSR_GMII_FIBER: 257 fiberonly = true; 258 break; 259 case ESSR_SGMII_WC_COPPER: 260 case ESSR_SGMII_WOC_COPPER: 261 case ESSR_RTBI_COPPER: 262 case ESSR_RGMII_COPPER: 263 case ESSR_GMII_COPPER: 264 copperonly = true; 265 default: 266 break; 267 } 268 } else 269 maksc->sc_flags |= MAKPHY_F_FICO_AUTOSEL; 270 break; 271 default: 272 break; 273 } 274 if (fiberonly || copperonly) 275 aprint_debug_dev(self, "both copper and fiber are set " 276 "but MODE[] is %s only.\n", 277 fiberonly ? "fiber" : "copper"); 278 if (fiberonly) 279 sc->mii_extcapabilities 280 &= ~(EXTSR_1000TFDX | EXTSR_1000THDX); 281 else if (copperonly) { 282 sc->mii_extcapabilities 283 &= ~(EXTSR_1000XFDX | EXTSR_1000XHDX); 284 sc->mii_flags &= ~MIIF_IS_1000X; 285 } 286 } 287 mii_unlock(mii); 288 mii_phy_add_media(sc); 289 } 290 291 static void 292 makphy_reset(struct mii_softc *sc) 293 { 294 struct makphy_softc *maksc = (struct makphy_softc *)sc; 295 uint16_t reg; 296 297 KASSERT(mii_locked(sc->mii_pdata)); 298 299 mii_phy_reset(sc); 300 301 /* Initialize PHY Specific Control Register. */ 302 PHY_READ(sc, MAKPHY_PSCR, ®); 303 304 /* Assert CRS on transmit. */ 305 switch (sc->mii_mpd_model) { 306 case MII_MODEL_MARVELL_E1000_0: 307 if ((maksc->sc_flags & MAKPHY_F_I210) != 0) 308 break; 309 /* FALLTHROUGH */ 310 case MII_MODEL_MARVELL_E1000_3: 311 case MII_MODEL_MARVELL_E1000_5: 312 case MII_MODEL_MARVELL_E1000_6: 313 case MII_MODEL_xxMARVELL_E1000S: 314 case MII_MODEL_xxMARVELL_E1011: 315 case MII_MODEL_xxMARVELL_E1111: 316 reg |= PSCR_CRS_ON_TX; 317 break; 318 default: /* No PSCR_CRS_ON_TX bit */ 319 break; 320 } 321 322 /* Enable scrambler if necessary. */ 323 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016) 324 reg &= ~E3016_PSCR_SCRAMBLE_DIS; 325 326 /* 327 * Store next page in the Link Partner Next Page register for 328 * compatibility with 802.3ab. 329 */ 330 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016) 331 reg |= E3016_PSCR_REG8NXTPG; 332 333 PHY_WRITE(sc, MAKPHY_PSCR, reg); 334 335 /* Configure LEDs if they were left unconfigured. */ 336 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016) { 337 PHY_READ(sc, 0x16, ®); 338 if (reg == 0) { 339 reg = (0x0b << 8) | (0x05 << 4) | 0x04; /* XXX */ 340 PHY_WRITE(sc, 0x16, reg); 341 } 342 } 343 344 mii_phy_reset(sc); 345 } 346 347 static void 348 makphy_pdown(struct mii_softc *sc, bool pdown) 349 { 350 uint16_t bmcr, new; 351 bool need_reset = false; 352 353 /* 354 * XXX 355 * PSCR (register 16) should be modified on some chips. 356 */ 357 358 PHY_READ(sc, MII_BMCR, &bmcr); 359 if (pdown) 360 new = bmcr | BMCR_PDOWN; 361 else 362 new = bmcr & ~BMCR_PDOWN; 363 if (bmcr != new) 364 need_reset = true; 365 366 if (need_reset) 367 new |= BMCR_RESET; 368 PHY_WRITE(sc, MII_BMCR, new); 369 } 370 371 static int 372 makphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 373 { 374 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 375 uint16_t bmcr; 376 377 if (!device_is_active(sc->mii_dev)) 378 return ENXIO; 379 380 KASSERT(mii_locked(mii)); 381 382 switch (cmd) { 383 case MII_POLLSTAT: 384 /* If we're not polling our PHY instance, just return. */ 385 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 386 return 0; 387 break; 388 389 case MII_MEDIACHG: 390 /* 391 * If the media indicates a different PHY instance, 392 * isolate ourselves. 393 */ 394 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 395 PHY_READ(sc, MII_BMCR, &bmcr); 396 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO); 397 return 0; 398 } 399 400 /* If the interface is not up, don't do anything. */ 401 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 402 break; 403 404 /* Try to power up the PHY in case it's down */ 405 if (IFM_SUBTYPE(ife->ifm_media) != IFM_NONE) 406 makphy_pdown(sc, MAKARG_PUP); 407 408 mii_phy_setmedia(sc); 409 410 /* 411 * If autonegotiation is not enabled, we need a 412 * software reset for the settings to take effect. 413 */ 414 if (IFM_SUBTYPE(ife->ifm_media) == IFM_NONE) 415 makphy_pdown(sc, MAKARG_PDOWN); 416 else if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { 417 PHY_READ(sc, MII_BMCR, &bmcr); 418 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_RESET); 419 } 420 break; 421 422 case MII_TICK: 423 /* If we're not currently selected, just return. */ 424 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 425 return 0; 426 427 if (mii_phy_tick(sc) == EJUSTRETURN) 428 return 0; 429 break; 430 431 case MII_DOWN: 432 mii_phy_down(sc); 433 return 0; 434 } 435 436 /* Update the media status. */ 437 mii_phy_status(sc); 438 439 /* Callback if something changed. */ 440 mii_phy_update(sc, cmd); 441 return 0; 442 } 443 444 static void 445 makphy_status(struct mii_softc *sc) 446 { 447 struct makphy_softc *maksc = (struct makphy_softc *)sc; 448 struct mii_data *mii = sc->mii_pdata; 449 uint16_t bmcr, gsr, pssr, essr; 450 451 KASSERT(mii_locked(mii)); 452 453 mii->mii_media_status = IFM_AVALID; 454 mii->mii_media_active = IFM_ETHER; 455 456 PHY_READ(sc, MII_BMCR, &bmcr); 457 /* XXX FIXME: Use different page for Fiber on newer chips */ 458 PHY_READ(sc, MAKPHY_PSSR, &pssr); 459 460 if ((maksc->sc_flags & MAKPHY_QUIRK_PSSR_LINK) != 0) { 461 uint16_t bmsr; 462 463 /* 464 * QEMU e1000 driver has the PSSR register but it doesn't 465 * support the PSSR_LINK bit well. It always returns 1. 466 * To avoid this problem, use the BMSR_LINK bit. It's not 467 * required to read it twice as real device because it's not 468 * latched. 469 */ 470 PHY_READ(sc, MII_BMSR, &bmsr); 471 if (bmsr & BMSR_LINK) 472 pssr |= MAKPHY_PSSR_LINK; 473 else 474 pssr &= ~MAKPHY_PSSR_LINK; 475 } 476 477 if (pssr & MAKPHY_PSSR_LINK) 478 mii->mii_media_status |= IFM_ACTIVE; 479 480 if (bmcr & BMCR_LOOP) 481 mii->mii_media_active |= IFM_LOOP; 482 483 if (bmcr & (BMCR_ISO | BMCR_PDOWN)) { 484 mii->mii_media_active |= IFM_NONE; 485 return; 486 } 487 488 if ((bmcr & BMCR_AUTOEN) != 0) { 489 /* 490 * Check Speed and Duplex Resolved bit. 491 * Note that this bit is always 1 when autonego is not enabled. 492 */ 493 if (!(pssr & MAKPHY_PSSR_RESOLVED)) { 494 /* Erg, still trying, I guess... */ 495 mii->mii_media_active |= IFM_NONE; 496 return; 497 } 498 } else { 499 if ((pssr & MAKPHY_PSSR_LINK) == 0) { 500 mii->mii_media_active |= IFM_NONE; 501 return; 502 } 503 } 504 505 /* 506 * XXX The following code support Fiber/Copper auto select mode 507 * only for 88E1011, 88E1111 and 88E1112. For other chips, the document 508 * is required. 509 */ 510 if (sc->mii_flags & MIIF_IS_1000X) { 511 /* Not in Fiber/Copper auto select mode */ 512 mii->mii_media_active |= IFM_1000_SX; 513 } else if ((sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1011) || 514 (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1111)) { 515 if ((maksc->sc_flags & MAKPHY_F_FICO_AUTOSEL) != 0) { 516 /* Fiber/Copper auto select mode */ 517 PHY_READ(sc, MAKPHY_ESSR, &essr); 518 if ((essr & ESSR_FIBER_LINK) == 0) 519 goto copper; 520 else { 521 /* Regard as 1000BASE-SX */ 522 mii->mii_media_active |= IFM_1000_SX; 523 } 524 } else 525 goto copper; 526 } else if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1112) { 527 /* Fiber/Copper auto select mode */ 528 529 PHY_READ(sc, MAKPHY_PSSR, &pssr); 530 if ((pssr & MAKPHY_PSSR_RESOLUTION_FIBER) == 0) 531 goto copper; 532 533 switch (MAKPHY_PSSR_SPEED_get(pssr)) { 534 case SPEED_1000: 535 mii->mii_media_active |= IFM_1000_SX; 536 break; 537 case SPEED_100: 538 mii->mii_media_active |= IFM_100_FX; 539 break; 540 default: /* Undefined (reserved) value */ 541 mii->mii_media_active |= IFM_NONE; 542 mii->mii_media_status = 0; 543 return; 544 } 545 } else { 546 copper: 547 switch (MAKPHY_PSSR_SPEED_get(pssr)) { 548 case SPEED_1000: 549 mii->mii_media_active |= IFM_1000_T; 550 break; 551 case SPEED_100: 552 mii->mii_media_active |= IFM_100_TX; 553 break; 554 case SPEED_10: 555 mii->mii_media_active |= IFM_10_T; 556 break; 557 default: /* Undefined (reserved) value */ 558 mii->mii_media_active |= IFM_NONE; 559 mii->mii_media_status = 0; 560 return; 561 } 562 } 563 564 if (pssr & MAKPHY_PSSR_DUPLEX) 565 mii->mii_media_active |= mii_phy_flowstatus(sc) | IFM_FDX; 566 else 567 mii->mii_media_active |= IFM_HDX; 568 569 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) { 570 PHY_READ(sc, MII_100T2SR, &gsr); 571 if (gsr & GTSR_MS_RES) 572 mii->mii_media_active |= IFM_ETH_MASTER; 573 } 574 } 575