1 /* $NetBSD: brgphy.c,v 1.68 2013/10/31 04:26:40 msaitoh 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 Broadcom BCM5400 and BCM5700 Gig-E PHYs. 59 * 60 * Programming information for this PHY was gleaned from FreeBSD 61 * (they were apparently able to get a datasheet from Broadcom). 62 */ 63 64 #include <sys/cdefs.h> 65 __KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.68 2013/10/31 04:26:40 msaitoh Exp $"); 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/kernel.h> 70 #include <sys/device.h> 71 #include <sys/socket.h> 72 #include <sys/errno.h> 73 #include <prop/proplib.h> 74 75 #include <net/if.h> 76 #include <net/if_media.h> 77 78 #include <dev/mii/mii.h> 79 #include <dev/mii/miivar.h> 80 #include <dev/mii/miidevs.h> 81 #include <dev/mii/brgphyreg.h> 82 83 #include <dev/pci/if_bgereg.h> 84 #include <dev/pci/if_bnxreg.h> 85 86 static int brgphymatch(device_t, cfdata_t, void *); 87 static void brgphyattach(device_t, device_t, void *); 88 89 struct brgphy_softc { 90 struct mii_softc sc_mii; 91 bool sc_isbge; 92 bool sc_isbnx; 93 uint32_t sc_chipid; /* parent's chipid */ 94 uint32_t sc_phyflags; /* parent's phyflags */ 95 }; 96 97 CFATTACH_DECL3_NEW(brgphy, sizeof(struct brgphy_softc), 98 brgphymatch, brgphyattach, mii_phy_detach, mii_phy_activate, NULL, NULL, 99 DVF_DETACH_SHUTDOWN); 100 101 static int brgphy_service(struct mii_softc *, struct mii_data *, int); 102 static void brgphy_status(struct mii_softc *); 103 static int brgphy_mii_phy_auto(struct mii_softc *); 104 static void brgphy_loop(struct mii_softc *); 105 static void brgphy_reset(struct mii_softc *); 106 static void brgphy_bcm5401_dspcode(struct mii_softc *); 107 static void brgphy_bcm5411_dspcode(struct mii_softc *); 108 static void brgphy_bcm5421_dspcode(struct mii_softc *); 109 static void brgphy_bcm54k2_dspcode(struct mii_softc *); 110 static void brgphy_adc_bug(struct mii_softc *); 111 static void brgphy_5704_a0_bug(struct mii_softc *); 112 static void brgphy_ber_bug(struct mii_softc *); 113 static void brgphy_crc_bug(struct mii_softc *); 114 static void brgphy_disable_early_dac(struct mii_softc *); 115 static void brgphy_jumbo_settings(struct mii_softc *); 116 static void brgphy_eth_wirespeed(struct mii_softc *); 117 118 119 static const struct mii_phy_funcs brgphy_funcs = { 120 brgphy_service, brgphy_status, brgphy_reset, 121 }; 122 123 static const struct mii_phydesc brgphys[] = { 124 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5400, 125 MII_STR_BROADCOM_BCM5400 }, 126 127 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5401, 128 MII_STR_BROADCOM_BCM5401 }, 129 130 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5411, 131 MII_STR_BROADCOM_BCM5411 }, 132 133 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5421, 134 MII_STR_BROADCOM_BCM5421 }, 135 136 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5462, 137 MII_STR_BROADCOM_BCM5462 }, 138 139 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5461, 140 MII_STR_BROADCOM_BCM5461 }, 141 142 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM54K2, 143 MII_STR_BROADCOM_BCM54K2 }, 144 145 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5464, 146 MII_STR_BROADCOM_BCM5464 }, 147 148 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5701, 149 MII_STR_BROADCOM_BCM5701 }, 150 151 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5703, 152 MII_STR_BROADCOM_BCM5703 }, 153 154 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5704, 155 MII_STR_BROADCOM_BCM5704 }, 156 157 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5705, 158 MII_STR_BROADCOM_BCM5705 }, 159 160 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5714, 161 MII_STR_BROADCOM_BCM5714 }, 162 163 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5750, 164 MII_STR_BROADCOM_BCM5750 }, 165 166 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5752, 167 MII_STR_BROADCOM_BCM5752 }, 168 169 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5780, 170 MII_STR_BROADCOM_BCM5780 }, 171 172 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5708C, 173 MII_STR_BROADCOM_BCM5708C }, 174 175 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5481, 176 MII_STR_BROADCOM2_BCM5481 }, 177 178 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5482, 179 MII_STR_BROADCOM2_BCM5482 }, 180 181 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709C, 182 MII_STR_BROADCOM2_BCM5709C }, 183 184 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709S, 185 MII_STR_BROADCOM2_BCM5709S }, 186 187 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709CAX, 188 MII_STR_BROADCOM2_BCM5709CAX }, 189 190 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5722, 191 MII_STR_BROADCOM2_BCM5722 }, 192 193 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5754, 194 MII_STR_BROADCOM2_BCM5754 }, 195 196 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5755, 197 MII_STR_BROADCOM2_BCM5755 }, 198 199 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5756, 200 MII_STR_BROADCOM2_BCM5756 }, 201 202 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5761, 203 MII_STR_BROADCOM2_BCM5761 }, 204 205 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5784, 206 MII_STR_BROADCOM2_BCM5784 }, 207 208 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5785, 209 MII_STR_BROADCOM2_BCM5785 }, 210 211 { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM5717C, 212 MII_STR_BROADCOM3_BCM5717C }, 213 214 { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM5719C, 215 MII_STR_BROADCOM3_BCM5719C }, 216 217 { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM5720C, 218 MII_STR_BROADCOM3_BCM5720C }, 219 220 { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM57765, 221 MII_STR_BROADCOM3_BCM57765 }, 222 223 { MII_OUI_BROADCOM3, MII_MODEL_BROADCOM3_BCM57780, 224 MII_STR_BROADCOM3_BCM57780 }, 225 226 { MII_OUI_xxBROADCOM_ALT1, MII_MODEL_xxBROADCOM_ALT1_BCM5906, 227 MII_STR_xxBROADCOM_ALT1_BCM5906 }, 228 229 { 0, 0, 230 NULL }, 231 }; 232 233 static int 234 brgphymatch(device_t parent, cfdata_t match, void *aux) 235 { 236 struct mii_attach_args *ma = aux; 237 238 if (mii_phy_match(ma, brgphys) != NULL) 239 return (10); 240 241 return (0); 242 } 243 244 static void 245 brgphyattach(device_t parent, device_t self, void *aux) 246 { 247 struct brgphy_softc *bsc = device_private(self); 248 struct mii_softc *sc = &bsc->sc_mii; 249 struct mii_attach_args *ma = aux; 250 struct mii_data *mii = ma->mii_data; 251 const struct mii_phydesc *mpd; 252 prop_dictionary_t dict; 253 254 mpd = mii_phy_match(ma, brgphys); 255 aprint_naive(": Media interface\n"); 256 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 257 258 sc->mii_dev = self; 259 sc->mii_inst = mii->mii_instance; 260 sc->mii_phy = ma->mii_phyno; 261 sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); 262 sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 263 sc->mii_mpd_rev = MII_REV(ma->mii_id2); 264 sc->mii_pdata = mii; 265 sc->mii_flags = ma->mii_flags; 266 sc->mii_anegticks = MII_ANEGTICKS; 267 sc->mii_funcs = &brgphy_funcs; 268 269 if (device_is_a(parent, "bge")) 270 bsc->sc_isbge = true; 271 else if (device_is_a(parent, "bnx")) 272 bsc->sc_isbnx = true; 273 274 if (bsc->sc_isbge || bsc->sc_isbnx) { 275 dict = device_properties(parent); 276 if (!prop_dictionary_get_uint32(dict, "phyflags", 277 &bsc->sc_phyflags)) 278 aprint_error_dev(self, "failed to get phyflags\n"); 279 if (!prop_dictionary_get_uint32(dict, "chipid", 280 &bsc->sc_chipid)) 281 aprint_error_dev(self, "failed to get chipid\n"); 282 } 283 284 PHY_RESET(sc); 285 286 sc->mii_capabilities = 287 PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 288 if (sc->mii_capabilities & BMSR_EXTSTAT) 289 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 290 291 aprint_normal_dev(self, ""); 292 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 293 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) 294 aprint_error("no media present"); 295 else { 296 if (sc->mii_flags & MIIF_HAVEFIBER) { 297 sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP; 298 299 /* 300 * Set the proper bits for capabilities so that the 301 * correct media get selected by mii_phy_add_media() 302 */ 303 sc->mii_capabilities |= BMSR_ANEG; 304 sc->mii_capabilities &= ~BMSR_100T4; 305 sc->mii_extcapabilities |= EXTSR_1000XFDX; 306 307 if (bsc->sc_isbnx) { 308 /* 309 * 2.5Gb support is a software enabled feature 310 * on the BCM5708S and BCM5709S controllers. 311 */ 312 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 313 if (bsc->sc_phyflags 314 & BNX_PHY_2_5G_CAPABLE_FLAG) { 315 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, 316 IFM_FDX, sc->mii_inst), 0); 317 aprint_normal("2500baseSX-FDX, "); 318 #undef ADD 319 } 320 } 321 } 322 mii_phy_add_media(sc); 323 } 324 aprint_normal("\n"); 325 326 } 327 328 static int 329 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 330 { 331 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 332 int reg, speed, gig; 333 334 switch (cmd) { 335 case MII_POLLSTAT: 336 /* 337 * If we're not polling our PHY instance, just return. 338 */ 339 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 340 return (0); 341 break; 342 343 case MII_MEDIACHG: 344 /* 345 * If the media indicates a different PHY instance, 346 * isolate ourselves. 347 */ 348 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 349 reg = PHY_READ(sc, MII_BMCR); 350 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 351 return (0); 352 } 353 354 /* 355 * If the interface is not up, don't do anything. 356 */ 357 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 358 break; 359 360 PHY_RESET(sc); /* XXX hardware bug work-around */ 361 362 switch (IFM_SUBTYPE(ife->ifm_media)) { 363 case IFM_AUTO: 364 (void) brgphy_mii_phy_auto(sc); 365 break; 366 case IFM_1000_T: 367 speed = BMCR_S1000; 368 goto setit; 369 case IFM_100_TX: 370 speed = BMCR_S100; 371 goto setit; 372 case IFM_10_T: 373 speed = BMCR_S10; 374 setit: 375 brgphy_loop(sc); 376 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 377 speed |= BMCR_FDX; 378 gig = GTCR_ADV_1000TFDX; 379 } else { 380 gig = GTCR_ADV_1000THDX; 381 } 382 383 PHY_WRITE(sc, MII_100T2CR, 0); 384 PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); 385 PHY_WRITE(sc, MII_BMCR, speed); 386 387 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 388 break; 389 390 PHY_WRITE(sc, MII_100T2CR, gig); 391 PHY_WRITE(sc, MII_BMCR, 392 speed | BMCR_AUTOEN | BMCR_STARTNEG); 393 394 if ((sc->mii_mpd_oui != MII_OUI_BROADCOM) 395 || (sc->mii_mpd_model != MII_MODEL_BROADCOM_BCM5701)) 396 break; 397 398 if (mii->mii_media.ifm_media & IFM_ETH_MASTER) 399 gig |= GTCR_MAN_MS | GTCR_ADV_MS; 400 PHY_WRITE(sc, MII_100T2CR, gig); 401 break; 402 default: 403 return (EINVAL); 404 } 405 break; 406 407 case MII_TICK: 408 /* 409 * If we're not currently selected, just return. 410 */ 411 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 412 return (0); 413 414 /* 415 * Is the interface even up? 416 */ 417 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 418 return 0; 419 420 /* 421 * Only used for autonegotiation. 422 */ 423 if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && 424 (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { 425 sc->mii_ticks = 0; 426 break; 427 } 428 429 /* 430 * Check for link. 431 * Read the status register twice; BMSR_LINK is latch-low. 432 */ 433 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 434 if (reg & BMSR_LINK) { 435 sc->mii_ticks = 0; 436 break; 437 } 438 439 /* 440 * mii_ticks == 0 means it's the first tick after changing the 441 * media or the link became down since the last tick 442 * (see above), so break to update the status. 443 */ 444 if (sc->mii_ticks++ == 0) 445 break; 446 447 /* 448 * Only retry autonegotiation every mii_anegticks seconds. 449 */ 450 KASSERT(sc->mii_anegticks != 0); 451 if (sc->mii_ticks <= sc->mii_anegticks) 452 break; 453 454 brgphy_mii_phy_auto(sc); 455 break; 456 457 case MII_DOWN: 458 mii_phy_down(sc); 459 return (0); 460 } 461 462 /* Update the media status. */ 463 mii_phy_status(sc); 464 465 /* 466 * Callback if something changed. Note that we need to poke the DSP on 467 * the Broadcom PHYs if the media changes. 468 */ 469 if (sc->mii_media_active != mii->mii_media_active || 470 sc->mii_media_status != mii->mii_media_status || 471 cmd == MII_MEDIACHG) { 472 switch (sc->mii_mpd_oui) { 473 case MII_OUI_BROADCOM: 474 switch (sc->mii_mpd_model) { 475 case MII_MODEL_BROADCOM_BCM5400: 476 brgphy_bcm5401_dspcode(sc); 477 break; 478 case MII_MODEL_BROADCOM_BCM5401: 479 if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) 480 brgphy_bcm5401_dspcode(sc); 481 break; 482 case MII_MODEL_BROADCOM_BCM5411: 483 brgphy_bcm5411_dspcode(sc); 484 break; 485 } 486 break; 487 } 488 } 489 490 /* Callback if something changed. */ 491 mii_phy_update(sc, cmd); 492 return (0); 493 } 494 495 static void 496 brgphy_status(struct mii_softc *sc) 497 { 498 struct mii_data *mii = sc->mii_pdata; 499 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 500 int bmcr, bmsr, auxsts, gtsr; 501 502 mii->mii_media_status = IFM_AVALID; 503 mii->mii_media_active = IFM_ETHER; 504 505 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 506 if (bmsr & BMSR_LINK) 507 mii->mii_media_status |= IFM_ACTIVE; 508 509 bmcr = PHY_READ(sc, MII_BMCR); 510 if (bmcr & BMCR_ISO) { 511 mii->mii_media_active |= IFM_NONE; 512 mii->mii_media_status = 0; 513 return; 514 } 515 516 if (bmcr & BMCR_LOOP) 517 mii->mii_media_active |= IFM_LOOP; 518 519 if (bmcr & BMCR_AUTOEN) { 520 /* 521 * The media status bits are only valid of autonegotiation 522 * has completed (or it's disabled). 523 */ 524 if ((bmsr & BMSR_ACOMP) == 0) { 525 /* Erg, still trying, I guess... */ 526 mii->mii_media_active |= IFM_NONE; 527 return; 528 } 529 530 if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 531 && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5709S)) { 532 /* 533 * 5709S has its own general purpose status registers 534 */ 535 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 536 BRGPHY_BLOCK_ADDR_GP_STATUS); 537 538 auxsts = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS); 539 540 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 541 BRGPHY_BLOCK_ADDR_COMBO_IEEE0); 542 543 switch (auxsts & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) { 544 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10: 545 mii->mii_media_active |= IFM_10_FL; 546 break; 547 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100: 548 mii->mii_media_active |= IFM_100_FX; 549 break; 550 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G: 551 mii->mii_media_active |= IFM_1000_SX; 552 break; 553 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G: 554 mii->mii_media_active |= IFM_2500_SX; 555 break; 556 default: 557 mii->mii_media_active |= IFM_NONE; 558 mii->mii_media_status = 0; 559 break; 560 } 561 562 if (auxsts & BRGPHY_GP_STATUS_TOP_ANEG_FDX) 563 mii->mii_media_active |= IFM_FDX; 564 else 565 mii->mii_media_active |= IFM_HDX; 566 567 } else { 568 auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS); 569 570 switch (auxsts & BRGPHY_AUXSTS_AN_RES) { 571 case BRGPHY_RES_1000FD: 572 mii->mii_media_active |= IFM_1000_T | IFM_FDX; 573 gtsr = PHY_READ(sc, MII_100T2SR); 574 if (gtsr & GTSR_MS_RES) 575 mii->mii_media_active |= IFM_ETH_MASTER; 576 break; 577 578 case BRGPHY_RES_1000HD: 579 mii->mii_media_active |= IFM_1000_T; 580 gtsr = PHY_READ(sc, MII_100T2SR); 581 if (gtsr & GTSR_MS_RES) 582 mii->mii_media_active |= IFM_ETH_MASTER; 583 break; 584 585 case BRGPHY_RES_100FD: 586 mii->mii_media_active |= IFM_100_TX | IFM_FDX; 587 break; 588 589 case BRGPHY_RES_100T4: 590 mii->mii_media_active |= IFM_100_T4; 591 break; 592 593 case BRGPHY_RES_100HD: 594 mii->mii_media_active |= IFM_100_TX; 595 break; 596 597 case BRGPHY_RES_10FD: 598 mii->mii_media_active |= IFM_10_T | IFM_FDX; 599 break; 600 601 case BRGPHY_RES_10HD: 602 mii->mii_media_active |= IFM_10_T; 603 break; 604 605 default: 606 mii->mii_media_active |= IFM_NONE; 607 mii->mii_media_status = 0; 608 } 609 } 610 611 if (mii->mii_media_active & IFM_FDX) 612 mii->mii_media_active |= mii_phy_flowstatus(sc); 613 614 } else 615 mii->mii_media_active = ife->ifm_media; 616 } 617 618 int 619 brgphy_mii_phy_auto(struct mii_softc *sc) 620 { 621 int anar, ktcr = 0; 622 623 sc->mii_ticks = 0; 624 brgphy_loop(sc); 625 PHY_RESET(sc); 626 627 ktcr = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; 628 if ((sc->mii_mpd_oui == MII_OUI_BROADCOM) 629 && (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701)) 630 ktcr |= GTCR_MAN_MS | GTCR_ADV_MS; 631 PHY_WRITE(sc, MII_100T2CR, ktcr); 632 ktcr = PHY_READ(sc, MII_100T2CR); 633 DELAY(1000); 634 635 if (sc->mii_flags & MIIF_HAVEFIBER) { 636 anar = ANAR_X_FD | ANAR_X_HD; 637 if (sc->mii_flags & MIIF_DOPAUSE) 638 anar |= BRGPHY_SERDES_ANAR_BOTH_PAUSE; 639 } else { 640 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; 641 if (sc->mii_flags & MIIF_DOPAUSE) 642 anar |= ANAR_FC | ANAR_PAUSE_ASYM; 643 } 644 PHY_WRITE(sc, MII_ANAR, anar); 645 DELAY(1000); 646 647 /* Start autonegotiation */ 648 PHY_WRITE(sc, MII_BMCR, 649 BMCR_AUTOEN | BMCR_STARTNEG); 650 PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); 651 652 return (EJUSTRETURN); 653 } 654 655 void 656 brgphy_loop(struct mii_softc *sc) 657 { 658 u_int32_t bmsr; 659 int i; 660 661 PHY_WRITE(sc, MII_BMCR, BMCR_LOOP); 662 for (i = 0; i < 15000; i++) { 663 bmsr = PHY_READ(sc, MII_BMSR); 664 if (!(bmsr & BMSR_LINK)) 665 break; 666 DELAY(10); 667 } 668 } 669 670 static void 671 brgphy_reset(struct mii_softc *sc) 672 { 673 struct brgphy_softc *bsc = device_private(sc->mii_dev); 674 675 mii_phy_reset(sc); 676 switch (sc->mii_mpd_oui) { 677 case MII_OUI_BROADCOM: 678 switch (sc->mii_mpd_model) { 679 case MII_MODEL_BROADCOM_BCM5400: 680 brgphy_bcm5401_dspcode(sc); 681 break; 682 case MII_MODEL_BROADCOM_BCM5401: 683 if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) 684 brgphy_bcm5401_dspcode(sc); 685 break; 686 case MII_MODEL_BROADCOM_BCM5411: 687 brgphy_bcm5411_dspcode(sc); 688 break; 689 case MII_MODEL_BROADCOM_BCM5421: 690 brgphy_bcm5421_dspcode(sc); 691 break; 692 case MII_MODEL_BROADCOM_BCM54K2: 693 brgphy_bcm54k2_dspcode(sc); 694 break; 695 } 696 break; 697 case MII_OUI_BROADCOM3: 698 switch (sc->mii_mpd_model) { 699 case MII_MODEL_BROADCOM3_BCM5717C: 700 case MII_MODEL_BROADCOM3_BCM5719C: 701 case MII_MODEL_BROADCOM3_BCM5720C: 702 case MII_MODEL_BROADCOM3_BCM57765: 703 return; 704 } 705 break; 706 default: 707 break; 708 } 709 710 /* Handle any bge (NetXtreme/NetLink) workarounds. */ 711 if (bsc->sc_isbge) { 712 if (!(sc->mii_flags & MIIF_HAVEFIBER)) { 713 714 if (bsc->sc_phyflags & BGEPHYF_ADC_BUG) 715 brgphy_adc_bug(sc); 716 if (bsc->sc_phyflags & BGEPHYF_5704_A0_BUG) 717 brgphy_5704_a0_bug(sc); 718 if (bsc->sc_phyflags & BGEPHYF_BER_BUG) 719 brgphy_ber_bug(sc); 720 else if (bsc->sc_phyflags & BGEPHYF_JITTER_BUG) { 721 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0c00); 722 PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 723 0x000a); 724 725 if (bsc->sc_phyflags 726 & BGEPHYF_ADJUST_TRIM) { 727 PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 728 0x110b); 729 PHY_WRITE(sc, BRGPHY_TEST1, 730 BRGPHY_TEST1_TRIM_EN | 0x4); 731 } else { 732 PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, 733 0x010b); 734 } 735 736 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0400); 737 } 738 if (bsc->sc_phyflags & BGEPHYF_CRC_BUG) 739 brgphy_crc_bug(sc); 740 741 /* Set Jumbo frame settings in the PHY. */ 742 if (bsc->sc_phyflags & BGEPHYF_JUMBO_CAPABLE) 743 brgphy_jumbo_settings(sc); 744 745 /* Adjust output voltage */ 746 if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 747 && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5906)) 748 PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12); 749 750 /* Enable Ethernet@Wirespeed */ 751 if (!(bsc->sc_phyflags & BGEPHYF_NO_WIRESPEED)) 752 brgphy_eth_wirespeed(sc); 753 754 #if 0 755 /* Enable Link LED on Dell boxes */ 756 if (bsc->sc_phyflags & BGEPHYF_NO_3LED) { 757 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 758 PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) 759 & ~BRGPHY_PHY_EXTCTL_3_LED); 760 } 761 #endif 762 } 763 /* Handle any bnx (NetXtreme II) workarounds. */ 764 } else if (bsc->sc_isbnx) { 765 #if 0 /* not yet */ 766 if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 767 && sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5708S) { 768 /* Store autoneg capabilities/results in digital block (Page 0) */ 769 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG3_PG2); 770 PHY_WRITE(sc, BRGPHY_5708S_PG2_DIGCTL_3_0, 771 BRGPHY_5708S_PG2_DIGCTL_3_0_USE_IEEE); 772 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); 773 774 /* Enable fiber mode and autodetection */ 775 PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL1, 776 PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL1) | 777 BRGPHY_5708S_PG0_1000X_CTL1_AUTODET_EN | 778 BRGPHY_5708S_PG0_1000X_CTL1_FIBER_MODE); 779 780 /* Enable parallel detection */ 781 PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL2, 782 PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL2) | 783 BRGPHY_5708S_PG0_1000X_CTL2_PAR_DET_EN); 784 785 /* Advertise 2.5G support through next page during autoneg */ 786 if (bnx_sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG) 787 PHY_WRITE(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1, 788 PHY_READ(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1) | 789 BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); 790 791 /* Increase TX signal amplitude */ 792 if ((BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_A0) || 793 (BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_B0) || 794 (BNX_CHIP_ID(bnx_sc) == BNX_CHIP_ID_5708_B1)) { 795 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 796 BRGPHY_5708S_TX_MISC_PG5); 797 PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL1, 798 PHY_READ(sc, BRGPHY_5708S_PG5_TXACTL1) & 799 ~BRGPHY_5708S_PG5_TXACTL1_VCM); 800 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 801 BRGPHY_5708S_DIG_PG0); 802 } 803 804 /* Backplanes use special driver/pre-driver/pre-emphasis values. */ 805 if ((bnx_sc->bnx_shared_hw_cfg & BNX_SHARED_HW_CFG_PHY_BACKPLANE) && 806 (bnx_sc->bnx_port_hw_cfg & BNX_PORT_HW_CFG_CFG_TXCTL3_MASK)) { 807 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 808 BRGPHY_5708S_TX_MISC_PG5); 809 PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL3, 810 bnx_sc->bnx_port_hw_cfg & 811 BNX_PORT_HW_CFG_CFG_TXCTL3_MASK); 812 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 813 BRGPHY_5708S_DIG_PG0); 814 } 815 } else 816 #endif 817 if ((sc->mii_mpd_oui == MII_OUI_BROADCOM2) 818 && (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5709S)) { 819 /* Select the SerDes Digital block of the AN MMD. */ 820 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 821 BRGPHY_BLOCK_ADDR_SERDES_DIG); 822 823 PHY_WRITE(sc, BRGPHY_SERDES_DIG_1000X_CTL1, 824 (PHY_READ(sc, BRGPHY_SERDES_DIG_1000X_CTL1) & 825 ~BRGPHY_SD_DIG_1000X_CTL1_AUTODET) | 826 BRGPHY_SD_DIG_1000X_CTL1_FIBER); 827 828 if (bsc->sc_phyflags & BNX_PHY_2_5G_CAPABLE_FLAG) { 829 /* Select the Over 1G block of the AN MMD. */ 830 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 831 BRGPHY_BLOCK_ADDR_OVER_1G); 832 833 /* 834 * Enable autoneg "Next Page" to advertise 835 * 2.5G support. 836 */ 837 PHY_WRITE(sc, BRGPHY_OVER_1G_UNFORMAT_PG1, 838 PHY_READ(sc, BRGPHY_OVER_1G_UNFORMAT_PG1) | 839 BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); 840 } 841 842 /* 843 * Select the Multi-Rate Backplane Ethernet block of 844 * the AN MMD. 845 */ 846 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 847 BRGPHY_BLOCK_ADDR_MRBE); 848 849 /* Enable MRBE speed autoneg. */ 850 PHY_WRITE(sc, BRGPHY_MRBE_MSG_PG5_NP, 851 PHY_READ(sc, BRGPHY_MRBE_MSG_PG5_NP) | 852 BRGPHY_MRBE_MSG_PG5_NP_MBRE | 853 BRGPHY_MRBE_MSG_PG5_NP_T2); 854 855 /* Select the Clause 73 User B0 block of the AN MMD. */ 856 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 857 BRGPHY_BLOCK_ADDR_CL73_USER_B0); 858 859 /* Enable MRBE speed autoneg. */ 860 PHY_WRITE(sc, BRGPHY_CL73_USER_B0_MBRE_CTL1, 861 BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP | 862 BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR | 863 BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG); 864 865 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, 866 BRGPHY_BLOCK_ADDR_COMBO_IEEE0); 867 868 } else if (_BNX_CHIP_NUM(bsc->sc_chipid) == BNX_CHIP_NUM_5709) { 869 if (_BNX_CHIP_REV(bsc->sc_chipid) == BNX_CHIP_REV_Ax || 870 _BNX_CHIP_REV(bsc->sc_chipid) == BNX_CHIP_REV_Bx) 871 brgphy_disable_early_dac(sc); 872 873 /* Set Jumbo frame settings in the PHY. */ 874 brgphy_jumbo_settings(sc); 875 876 /* Enable Ethernet@Wirespeed */ 877 brgphy_eth_wirespeed(sc); 878 } else { 879 if (!(sc->mii_flags & MIIF_HAVEFIBER)) { 880 brgphy_ber_bug(sc); 881 882 /* Set Jumbo frame settings in the PHY. */ 883 brgphy_jumbo_settings(sc); 884 885 /* Enable Ethernet@Wirespeed */ 886 brgphy_eth_wirespeed(sc); 887 } 888 } 889 } 890 } 891 892 /* Turn off tap power management on 5401. */ 893 static void 894 brgphy_bcm5401_dspcode(struct mii_softc *sc) 895 { 896 static const struct { 897 int reg; 898 uint16_t val; 899 } dspcode[] = { 900 { BRGPHY_MII_AUXCTL, 0x0c20 }, 901 { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 902 { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 903 { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 904 { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 905 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 906 { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 907 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 908 { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 909 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 910 { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 911 { 0, 0 }, 912 }; 913 int i; 914 915 for (i = 0; dspcode[i].reg != 0; i++) 916 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 917 delay(40); 918 } 919 920 static void 921 brgphy_bcm5411_dspcode(struct mii_softc *sc) 922 { 923 static const struct { 924 int reg; 925 uint16_t val; 926 } dspcode[] = { 927 { 0x1c, 0x8c23 }, 928 { 0x1c, 0x8ca3 }, 929 { 0x1c, 0x8c23 }, 930 { 0, 0 }, 931 }; 932 int i; 933 934 for (i = 0; dspcode[i].reg != 0; i++) 935 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 936 } 937 938 void 939 brgphy_bcm5421_dspcode(struct mii_softc *sc) 940 { 941 uint16_t data; 942 943 /* Set Class A mode */ 944 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x1007); 945 data = PHY_READ(sc, BRGPHY_MII_AUXCTL); 946 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0400); 947 948 /* Set FFE gamma override to -0.125 */ 949 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0007); 950 data = PHY_READ(sc, BRGPHY_MII_AUXCTL); 951 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0800); 952 PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a); 953 data = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT); 954 PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, data | 0x0200); 955 } 956 957 void 958 brgphy_bcm54k2_dspcode(struct mii_softc *sc) 959 { 960 static const struct { 961 int reg; 962 uint16_t val; 963 } dspcode[] = { 964 { 4, 0x01e1 }, 965 { 9, 0x0300 }, 966 { 0, 0 }, 967 }; 968 int i; 969 970 for (i = 0; dspcode[i].reg != 0; i++) 971 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 972 } 973 974 static void 975 brgphy_adc_bug(struct mii_softc *sc) 976 { 977 static const struct { 978 int reg; 979 uint16_t val; 980 } dspcode[] = { 981 { BRGPHY_MII_AUXCTL, 0x0c00 }, 982 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 983 { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 984 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 985 { BRGPHY_MII_DSP_RW_PORT, 0x0323 }, 986 { BRGPHY_MII_AUXCTL, 0x0400 }, 987 { 0, 0 }, 988 }; 989 int i; 990 991 for (i = 0; dspcode[i].reg != 0; i++) 992 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 993 } 994 995 static void 996 brgphy_5704_a0_bug(struct mii_softc *sc) 997 { 998 static const struct { 999 int reg; 1000 uint16_t val; 1001 } dspcode[] = { 1002 { 0x1c, 0x8d68 }, 1003 { 0x1c, 0x8d68 }, 1004 { 0, 0 }, 1005 }; 1006 int i; 1007 1008 for (i = 0; dspcode[i].reg != 0; i++) 1009 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1010 } 1011 1012 static void 1013 brgphy_ber_bug(struct mii_softc *sc) 1014 { 1015 static const struct { 1016 int reg; 1017 uint16_t val; 1018 } dspcode[] = { 1019 { BRGPHY_MII_AUXCTL, 0x0c00 }, 1020 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 1021 { BRGPHY_MII_DSP_RW_PORT, 0x310b }, 1022 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 1023 { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, 1024 { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, 1025 { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, 1026 { BRGPHY_MII_AUXCTL, 0x0400 }, 1027 { 0, 0 }, 1028 }; 1029 int i; 1030 1031 for (i = 0; dspcode[i].reg != 0; i++) 1032 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1033 } 1034 1035 /* BCM5701 A0/B0 CRC bug workaround */ 1036 void 1037 brgphy_crc_bug(struct mii_softc *sc) 1038 { 1039 static const struct { 1040 int reg; 1041 uint16_t val; 1042 } dspcode[] = { 1043 { BRGPHY_MII_DSP_ADDR_REG, 0x0a75 }, 1044 { 0x1c, 0x8c68 }, 1045 { 0x1c, 0x8d68 }, 1046 { 0x1c, 0x8c68 }, 1047 { 0, 0 }, 1048 }; 1049 int i; 1050 1051 for (i = 0; dspcode[i].reg != 0; i++) 1052 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 1053 } 1054 1055 static void 1056 brgphy_disable_early_dac(struct mii_softc *sc) 1057 { 1058 uint32_t val; 1059 1060 PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08); 1061 val = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT); 1062 val &= ~(1 << 8); 1063 PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val); 1064 1065 } 1066 1067 static void 1068 brgphy_jumbo_settings(struct mii_softc *sc) 1069 { 1070 u_int32_t val; 1071 1072 /* Set Jumbo frame settings in the PHY. */ 1073 if ((sc->mii_mpd_oui == MII_OUI_BROADCOM) 1074 && (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5401)) { 1075 /* Cannot do read-modify-write on the BCM5401 */ 1076 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20); 1077 } else { 1078 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); 1079 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 1080 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 1081 val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7)); 1082 } 1083 1084 val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); 1085 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 1086 val & ~BRGPHY_PHY_EXTCTL_HIGH_LA); 1087 } 1088 1089 static void 1090 brgphy_eth_wirespeed(struct mii_softc *sc) 1091 { 1092 u_int32_t val; 1093 1094 /* Enable Ethernet@Wirespeed */ 1095 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); 1096 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 1097 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 1098 (val | (1 << 15) | (1 << 4))); 1099 } 1100