1 /*- 2 * Copyright (c) 2000 3 * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 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 30 * THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __FBSDID("$FreeBSD$"); 35 36 /* 37 * Driver for the Broadcom BCM54xx/57xx 1000baseTX PHY. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/kernel.h> 43 #include <sys/module.h> 44 #include <sys/socket.h> 45 #include <sys/bus.h> 46 47 #include <net/if.h> 48 #include <net/ethernet.h> 49 #include <net/if_media.h> 50 51 #include <dev/mii/mii.h> 52 #include <dev/mii/miivar.h> 53 #include "miidevs.h" 54 55 #include <dev/mii/brgphyreg.h> 56 #include <net/if_arp.h> 57 #include <machine/bus.h> 58 #include <dev/bge/if_bgereg.h> 59 #include <dev/bce/if_bcereg.h> 60 61 #include <dev/pci/pcireg.h> 62 #include <dev/pci/pcivar.h> 63 64 #include "miibus_if.h" 65 66 static int brgphy_probe(device_t); 67 static int brgphy_attach(device_t); 68 69 struct brgphy_softc { 70 struct mii_softc mii_sc; 71 int mii_oui; 72 int mii_model; 73 int mii_rev; 74 int serdes_flags; /* Keeps track of the serdes type used */ 75 #define BRGPHY_5706S 0x0001 76 #define BRGPHY_5708S 0x0002 77 #define BRGPHY_NOANWAIT 0x0004 78 #define BRGPHY_5709S 0x0008 79 int bce_phy_flags; /* PHY flags transferred from the MAC driver */ 80 }; 81 82 static device_method_t brgphy_methods[] = { 83 /* device interface */ 84 DEVMETHOD(device_probe, brgphy_probe), 85 DEVMETHOD(device_attach, brgphy_attach), 86 DEVMETHOD(device_detach, mii_phy_detach), 87 DEVMETHOD(device_shutdown, bus_generic_shutdown), 88 { 0, 0 } 89 }; 90 91 static devclass_t brgphy_devclass; 92 93 static driver_t brgphy_driver = { 94 "brgphy", 95 brgphy_methods, 96 sizeof(struct brgphy_softc) 97 }; 98 99 DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, 0, 0); 100 101 static int brgphy_service(struct mii_softc *, struct mii_data *, int); 102 static void brgphy_setmedia(struct mii_softc *, int, int); 103 static void brgphy_status(struct mii_softc *); 104 static void brgphy_mii_phy_auto(struct mii_softc *); 105 static void brgphy_reset(struct mii_softc *); 106 static void brgphy_enable_loopback(struct mii_softc *); 107 static void bcm5401_load_dspcode(struct mii_softc *); 108 static void bcm5411_load_dspcode(struct mii_softc *); 109 static void bcm54k2_load_dspcode(struct mii_softc *); 110 static void brgphy_fixup_5704_a0_bug(struct mii_softc *); 111 static void brgphy_fixup_adc_bug(struct mii_softc *); 112 static void brgphy_fixup_adjust_trim(struct mii_softc *); 113 static void brgphy_fixup_ber_bug(struct mii_softc *); 114 static void brgphy_fixup_crc_bug(struct mii_softc *); 115 static void brgphy_fixup_jitter_bug(struct mii_softc *); 116 static void brgphy_ethernet_wirespeed(struct mii_softc *); 117 static void brgphy_jumbo_settings(struct mii_softc *, u_long); 118 119 static const struct mii_phydesc brgphys[] = { 120 MII_PHY_DESC(xxBROADCOM, BCM5400), 121 MII_PHY_DESC(xxBROADCOM, BCM5401), 122 MII_PHY_DESC(xxBROADCOM, BCM5411), 123 MII_PHY_DESC(xxBROADCOM, BCM54K2), 124 MII_PHY_DESC(xxBROADCOM, BCM5701), 125 MII_PHY_DESC(xxBROADCOM, BCM5703), 126 MII_PHY_DESC(xxBROADCOM, BCM5704), 127 MII_PHY_DESC(xxBROADCOM, BCM5705), 128 MII_PHY_DESC(xxBROADCOM, BCM5706), 129 MII_PHY_DESC(xxBROADCOM, BCM5714), 130 MII_PHY_DESC(xxBROADCOM, BCM5750), 131 MII_PHY_DESC(xxBROADCOM, BCM5752), 132 MII_PHY_DESC(xxBROADCOM, BCM5754), 133 MII_PHY_DESC(xxBROADCOM, BCM5780), 134 MII_PHY_DESC(xxBROADCOM, BCM5708C), 135 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5755), 136 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5787), 137 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5708S), 138 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709CAX), 139 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5722), 140 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5784), 141 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709C), 142 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5761), 143 MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709S), 144 MII_PHY_DESC(BROADCOM2, BCM5906), 145 MII_PHY_END 146 }; 147 148 #define HS21_PRODUCT_ID "IBM eServer BladeCenter HS21" 149 #define HS21_BCM_CHIPID 0x57081021 150 151 static int 152 detect_hs21(struct bce_softc *bce_sc) 153 { 154 char *sysenv; 155 156 if (bce_sc->bce_chipid != HS21_BCM_CHIPID) 157 return (0); 158 sysenv = getenv("smbios.system.product"); 159 if (sysenv == NULL) 160 return (0); 161 if (strncmp(sysenv, HS21_PRODUCT_ID, strlen(HS21_PRODUCT_ID)) != 0) 162 return (0); 163 return (1); 164 } 165 166 /* Search for our PHY in the list of known PHYs */ 167 static int 168 brgphy_probe(device_t dev) 169 { 170 return (mii_phy_dev_probe(dev, brgphys, BUS_PROBE_DEFAULT)); 171 } 172 173 /* Attach the PHY to the MII bus */ 174 static int 175 brgphy_attach(device_t dev) 176 { 177 struct brgphy_softc *bsc; 178 struct bge_softc *bge_sc = NULL; 179 struct bce_softc *bce_sc = NULL; 180 struct mii_softc *sc; 181 struct mii_attach_args *ma; 182 struct mii_data *mii; 183 struct ifnet *ifp; 184 int fast_ether; 185 186 bsc = device_get_softc(dev); 187 sc = &bsc->mii_sc; 188 ma = device_get_ivars(dev); 189 sc->mii_dev = device_get_parent(dev); 190 mii = ma->mii_data; 191 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 192 193 /* Initialize mii_softc structure */ 194 sc->mii_flags = miibus_get_flags(dev); 195 sc->mii_inst = mii->mii_instance++; 196 sc->mii_phy = ma->mii_phyno; 197 sc->mii_service = brgphy_service; 198 sc->mii_pdata = mii; 199 200 /* 201 * At least some variants wedge when isolating, at least some also 202 * don't support loopback. 203 */ 204 sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP; 205 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 206 207 /* Initialize brgphy_softc structure */ 208 bsc->mii_oui = MII_OUI(ma->mii_id1, ma->mii_id2); 209 bsc->mii_model = MII_MODEL(ma->mii_id2); 210 bsc->mii_rev = MII_REV(ma->mii_id2); 211 bsc->serdes_flags = 0; 212 213 fast_ether = 0; 214 215 if (bootverbose) 216 device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n", 217 bsc->mii_oui, bsc->mii_model, bsc->mii_rev); 218 219 /* Handle any special cases based on the PHY ID */ 220 switch (bsc->mii_oui) { 221 case MII_OUI_BROADCOM: 222 case MII_OUI_BROADCOM2: 223 break; 224 case MII_OUI_xxBROADCOM: 225 switch (bsc->mii_model) { 226 case MII_MODEL_xxBROADCOM_BCM5706: 227 case MII_MODEL_xxBROADCOM_BCM5714: 228 /* 229 * The 5464 PHY used in the 5706 supports both copper 230 * and fiber interfaces over GMII. Need to check the 231 * shadow registers to see which mode is actually 232 * in effect, and therefore whether we have 5706C or 233 * 5706S. 234 */ 235 PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, 236 BRGPHY_SHADOW_1C_MODE_CTRL); 237 if (PHY_READ(sc, BRGPHY_MII_SHADOW_1C) & 238 BRGPHY_SHADOW_1C_ENA_1000X) { 239 bsc->serdes_flags |= BRGPHY_5706S; 240 sc->mii_flags |= MIIF_HAVEFIBER; 241 } 242 break; 243 } break; 244 case MII_OUI_xxBROADCOM_ALT1: 245 switch (bsc->mii_model) { 246 case MII_MODEL_xxBROADCOM_ALT1_BCM5708S: 247 bsc->serdes_flags |= BRGPHY_5708S; 248 sc->mii_flags |= MIIF_HAVEFIBER; 249 break; 250 case MII_MODEL_xxBROADCOM_ALT1_BCM5709S: 251 bsc->serdes_flags |= BRGPHY_5709S; 252 sc->mii_flags |= MIIF_HAVEFIBER; 253 break; 254 } 255 break; 256 default: 257 device_printf(dev, "Unrecognized OUI for PHY!\n"); 258 } 259 260 ifp = sc->mii_pdata->mii_ifp; 261 262 /* Find the MAC driver associated with this PHY. */ 263 if (strcmp(ifp->if_dname, "bge") == 0) { 264 bge_sc = ifp->if_softc; 265 } else if (strcmp(ifp->if_dname, "bce") == 0) { 266 bce_sc = ifp->if_softc; 267 } 268 269 /* Todo: Need to add additional controllers such as 5906 & 5787F */ 270 /* The 590x chips are 10/100 only. */ 271 if (bge_sc && 272 pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID && 273 (pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901 || 274 pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5901A2 || 275 pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906 || 276 pci_get_device(bge_sc->bge_dev) == BCOM_DEVICEID_BCM5906M)) { 277 fast_ether = 1; 278 sc->mii_anegticks = MII_ANEGTICKS; 279 } 280 281 brgphy_reset(sc); 282 283 /* Read the PHY's capabilities. */ 284 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 285 if (sc->mii_capabilities & BMSR_EXTSTAT) 286 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 287 device_printf(dev, " "); 288 289 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 290 291 /* Add the supported media types */ 292 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 293 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 294 BRGPHY_S10); 295 printf("10baseT, "); 296 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), 297 BRGPHY_S10 | BRGPHY_BMCR_FDX); 298 printf("10baseT-FDX, "); 299 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), 300 BRGPHY_S100); 301 printf("100baseTX, "); 302 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), 303 BRGPHY_S100 | BRGPHY_BMCR_FDX); 304 printf("100baseTX-FDX, "); 305 if (fast_ether == 0) { 306 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), 307 BRGPHY_S1000); 308 printf("1000baseT, "); 309 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 310 BRGPHY_S1000 | BRGPHY_BMCR_FDX); 311 printf("1000baseT-FDX, "); 312 } 313 } else { 314 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst), 315 BRGPHY_S1000 | BRGPHY_BMCR_FDX); 316 printf("1000baseSX-FDX, "); 317 /* 2.5G support is a software enabled feature on the 5708S and 5709S. */ 318 if (bce_sc && (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) { 319 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX, sc->mii_inst), 0); 320 printf("2500baseSX-FDX, "); 321 } else if ((bsc->serdes_flags & BRGPHY_5708S) && bce_sc && 322 (detect_hs21(bce_sc) != 0)) { 323 /* 324 * There appears to be certain silicon revision 325 * in IBM HS21 blades that is having issues with 326 * this driver wating for the auto-negotiation to 327 * complete. This happens with a specific chip id 328 * only and when the 1000baseSX-FDX is the only 329 * mode. Workaround this issue since it's unlikely 330 * to be ever addressed. 331 */ 332 printf("auto-neg workaround, "); 333 bsc->serdes_flags |= BRGPHY_NOANWAIT; 334 } 335 } 336 337 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); 338 printf("auto\n"); 339 340 #undef ADD 341 MIIBUS_MEDIAINIT(sc->mii_dev); 342 return (0); 343 } 344 345 static int 346 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 347 { 348 struct brgphy_softc *bsc = (struct brgphy_softc *)sc; 349 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 350 int val; 351 352 switch (cmd) { 353 case MII_POLLSTAT: 354 break; 355 case MII_MEDIACHG: 356 /* If the interface is not up, don't do anything. */ 357 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 358 break; 359 360 /* Todo: Why is this here? Is it really needed? */ 361 brgphy_reset(sc); /* XXX hardware bug work-around */ 362 363 switch (IFM_SUBTYPE(ife->ifm_media)) { 364 case IFM_AUTO: 365 brgphy_mii_phy_auto(sc); 366 break; 367 case IFM_2500_SX: 368 case IFM_1000_SX: 369 case IFM_1000_T: 370 case IFM_100_TX: 371 case IFM_10_T: 372 brgphy_setmedia(sc, ife->ifm_media, 373 mii->mii_ifp->if_flags & IFF_LINK0); 374 break; 375 default: 376 return (EINVAL); 377 } 378 break; 379 case MII_TICK: 380 /* Bail if the interface isn't up. */ 381 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 382 return (0); 383 384 385 /* Bail if autoneg isn't in process. */ 386 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { 387 sc->mii_ticks = 0; 388 break; 389 } 390 391 /* 392 * Check to see if we have link. If we do, we don't 393 * need to restart the autonegotiation process. 394 */ 395 val = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 396 if (val & BMSR_LINK) { 397 sc->mii_ticks = 0; /* Reset autoneg timer. */ 398 break; 399 } 400 401 /* Announce link loss right after it happens. */ 402 if (sc->mii_ticks++ == 0) 403 break; 404 405 /* Only retry autonegotiation every mii_anegticks seconds. */ 406 if (sc->mii_ticks <= sc->mii_anegticks) 407 break; 408 409 410 /* Retry autonegotiation */ 411 sc->mii_ticks = 0; 412 brgphy_mii_phy_auto(sc); 413 break; 414 } 415 416 /* Update the media status. */ 417 brgphy_status(sc); 418 419 /* 420 * Callback if something changed. Note that we need to poke 421 * the DSP on the Broadcom PHYs if the media changes. 422 */ 423 if (sc->mii_media_active != mii->mii_media_active || 424 sc->mii_media_status != mii->mii_media_status || 425 cmd == MII_MEDIACHG) { 426 switch (bsc->mii_oui) { 427 case MII_OUI_BROADCOM: 428 break; 429 case MII_OUI_xxBROADCOM: 430 switch (bsc->mii_model) { 431 case MII_MODEL_xxBROADCOM_BCM5400: 432 bcm5401_load_dspcode(sc); 433 break; 434 case MII_MODEL_xxBROADCOM_BCM5401: 435 if (bsc->mii_rev == 1 || bsc->mii_rev == 3) 436 bcm5401_load_dspcode(sc); 437 break; 438 case MII_MODEL_xxBROADCOM_BCM5411: 439 bcm5411_load_dspcode(sc); 440 break; 441 case MII_MODEL_xxBROADCOM_BCM54K2: 442 bcm54k2_load_dspcode(sc); 443 break; 444 } 445 break; 446 case MII_OUI_xxBROADCOM_ALT1: 447 break; 448 } 449 } 450 mii_phy_update(sc, cmd); 451 return (0); 452 } 453 454 455 /****************************************************************************/ 456 /* Sets the PHY link speed. */ 457 /* */ 458 /* Returns: */ 459 /* None */ 460 /****************************************************************************/ 461 static void 462 brgphy_setmedia(struct mii_softc *sc, int media, int master) 463 { 464 struct brgphy_softc *bsc = (struct brgphy_softc *)sc; 465 int bmcr = 0, gig; 466 467 /* Calculate the value for the BMCR register. */ 468 switch (IFM_SUBTYPE(media)) { 469 case IFM_2500_SX: 470 break; 471 case IFM_1000_SX: 472 case IFM_1000_T: 473 bmcr = BRGPHY_S1000; 474 break; 475 case IFM_100_TX: 476 bmcr = BRGPHY_S100; 477 break; 478 case IFM_10_T: 479 default: 480 bmcr = BRGPHY_S10; 481 break; 482 } 483 484 /* Calculate duplex settings for 1000BasetT/1000BaseX. */ 485 if ((media & IFM_GMASK) == IFM_FDX) { 486 bmcr |= BRGPHY_BMCR_FDX; 487 gig = BRGPHY_1000CTL_AFD; 488 } else { 489 gig = BRGPHY_1000CTL_AHD; 490 } 491 492 /* Force loopback to disconnect PHY for Ethernet medium. */ 493 brgphy_enable_loopback(sc); 494 495 /* Disable 1000BaseT advertisements. */ 496 PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0); 497 /* Disable 10/100 advertisements. */ 498 PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE); 499 /* Write forced link speed. */ 500 PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr); 501 502 /* If 10/100 only then configuration is complete. */ 503 if ((IFM_SUBTYPE(media) != IFM_1000_T) && (IFM_SUBTYPE(media) != IFM_1000_SX)) 504 goto brgphy_setmedia_exit; 505 506 /* Set duplex speed advertisement for 1000BaseT/1000BaseX. */ 507 PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig); 508 /* Restart auto-negotiation for 1000BaseT/1000BaseX. */ 509 PHY_WRITE(sc, BRGPHY_MII_BMCR, 510 bmcr | BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); 511 512 /* If not 5701 PHY then configuration is complete. */ 513 if (bsc->mii_model != MII_MODEL_xxBROADCOM_BCM5701) 514 goto brgphy_setmedia_exit; 515 516 /* 517 * When setting the link manually, one side must be the master and 518 * the other the slave. However ifmedia doesn't give us a good way 519 * to specify this, so we fake it by using one of the LINK flags. 520 * If LINK0 is set, we program the PHY to be a master, otherwise 521 * it's a slave. 522 */ 523 if (master) { 524 PHY_WRITE(sc, BRGPHY_MII_1000CTL, 525 gig | BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC); 526 } else { 527 PHY_WRITE(sc, BRGPHY_MII_1000CTL, 528 gig | BRGPHY_1000CTL_MSE); 529 } 530 531 brgphy_setmedia_exit: 532 return; 533 } 534 535 /****************************************************************************/ 536 /* Set the media status based on the PHY settings. */ 537 /* IFM_FLAG0 = 0 (RX flow control disabled) | 1 (enabled) */ 538 /* IFM_FLAG1 = 0 (TX flow control disabled) | 1 (enabled) */ 539 /* */ 540 /* Returns: */ 541 /* None */ 542 /****************************************************************************/ 543 static void 544 brgphy_status(struct mii_softc *sc) 545 { 546 struct brgphy_softc *bsc = (struct brgphy_softc *)sc; 547 struct mii_data *mii = sc->mii_pdata; 548 int aux, bmcr, bmsr, anar, anlpar, xstat, val; 549 550 551 mii->mii_media_status = IFM_AVALID; 552 mii->mii_media_active = IFM_ETHER; 553 554 bmsr = PHY_READ(sc, BRGPHY_MII_BMSR) | PHY_READ(sc, BRGPHY_MII_BMSR); 555 bmcr = PHY_READ(sc, BRGPHY_MII_BMCR); 556 anar = PHY_READ(sc, BRGPHY_MII_ANAR); 557 anlpar = PHY_READ(sc, BRGPHY_MII_ANLPAR); 558 559 /* Loopback is enabled. */ 560 if (bmcr & BRGPHY_BMCR_LOOP) { 561 562 mii->mii_media_active |= IFM_LOOP; 563 } 564 565 /* Autoneg is still in progress. */ 566 if ((bmcr & BRGPHY_BMCR_AUTOEN) && 567 (bmsr & BRGPHY_BMSR_ACOMP) == 0 && 568 (bsc->serdes_flags & BRGPHY_NOANWAIT) == 0) { 569 /* Erg, still trying, I guess... */ 570 mii->mii_media_active |= IFM_NONE; 571 goto brgphy_status_exit; 572 } 573 574 /* Autoneg is enabled and complete, link should be up. */ 575 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 576 aux = PHY_READ(sc, BRGPHY_MII_AUXSTS); 577 578 /* If copper link is up, get the negotiated speed/duplex. */ 579 if (aux & BRGPHY_AUXSTS_LINK) { 580 mii->mii_media_status |= IFM_ACTIVE; 581 switch (aux & BRGPHY_AUXSTS_AN_RES) { 582 case BRGPHY_RES_1000FD: 583 mii->mii_media_active |= IFM_1000_T | IFM_FDX; break; 584 case BRGPHY_RES_1000HD: 585 mii->mii_media_active |= IFM_1000_T | IFM_HDX; break; 586 case BRGPHY_RES_100FD: 587 mii->mii_media_active |= IFM_100_TX | IFM_FDX; break; 588 case BRGPHY_RES_100T4: 589 mii->mii_media_active |= IFM_100_T4; break; 590 case BRGPHY_RES_100HD: 591 mii->mii_media_active |= IFM_100_TX | IFM_HDX; break; 592 case BRGPHY_RES_10FD: 593 mii->mii_media_active |= IFM_10_T | IFM_FDX; break; 594 case BRGPHY_RES_10HD: 595 mii->mii_media_active |= IFM_10_T | IFM_HDX; break; 596 default: 597 mii->mii_media_active |= IFM_NONE; break; 598 } 599 } 600 } else { 601 /* If serdes link is up, get the negotiated speed/duplex. */ 602 if (bmsr & BRGPHY_BMSR_LINK) { 603 mii->mii_media_status |= IFM_ACTIVE; 604 } 605 606 /* Check the link speed/duplex based on the PHY type. */ 607 if (bsc->serdes_flags & BRGPHY_5706S) { 608 mii->mii_media_active |= IFM_1000_SX; 609 610 /* If autoneg enabled, read negotiated duplex settings */ 611 if (bmcr & BRGPHY_BMCR_AUTOEN) { 612 val = PHY_READ(sc, BRGPHY_SERDES_ANAR) & PHY_READ(sc, BRGPHY_SERDES_ANLPAR); 613 if (val & BRGPHY_SERDES_ANAR_FDX) 614 mii->mii_media_active |= IFM_FDX; 615 else 616 mii->mii_media_active |= IFM_HDX; 617 } 618 619 } else if (bsc->serdes_flags & BRGPHY_5708S) { 620 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); 621 xstat = PHY_READ(sc, BRGPHY_5708S_PG0_1000X_STAT1); 622 623 /* Check for MRBE auto-negotiated speed results. */ 624 switch (xstat & BRGPHY_5708S_PG0_1000X_STAT1_SPEED_MASK) { 625 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_10: 626 mii->mii_media_active |= IFM_10_FL; break; 627 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_100: 628 mii->mii_media_active |= IFM_100_FX; break; 629 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_1G: 630 mii->mii_media_active |= IFM_1000_SX; break; 631 case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_25G: 632 mii->mii_media_active |= IFM_2500_SX; break; 633 } 634 635 /* Check for MRBE auto-negotiated duplex results. */ 636 if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_FDX) 637 mii->mii_media_active |= IFM_FDX; 638 else 639 mii->mii_media_active |= IFM_HDX; 640 641 } else if (bsc->serdes_flags & BRGPHY_5709S) { 642 643 /* Select GP Status Block of the AN MMD, get autoneg results. */ 644 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_GP_STATUS); 645 xstat = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS); 646 647 /* Restore IEEE0 block (assumed in all brgphy(4) code). */ 648 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_COMBO_IEEE0); 649 650 /* Check for MRBE auto-negotiated speed results. */ 651 switch (xstat & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) { 652 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10: 653 mii->mii_media_active |= IFM_10_FL; break; 654 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100: 655 mii->mii_media_active |= IFM_100_FX; break; 656 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G: 657 mii->mii_media_active |= IFM_1000_SX; break; 658 case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G: 659 mii->mii_media_active |= IFM_2500_SX; break; 660 } 661 662 /* Check for MRBE auto-negotiated duplex results. */ 663 if (xstat & BRGPHY_GP_STATUS_TOP_ANEG_FDX) 664 mii->mii_media_active |= IFM_FDX; 665 else 666 mii->mii_media_active |= IFM_HDX; 667 } 668 669 } 670 671 /* Todo: Change bge to use these settings. */ 672 673 /* Fetch flow control settings from the copper PHY. */ 674 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 675 /* Set FLAG0 if RX is enabled and FLAG1 if TX is enabled */ 676 if ((anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANLPAR_PC)) { 677 mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1; 678 } else if (!(anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANAR_ASP) && 679 (anlpar & BRGPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) { 680 mii->mii_media_active |= IFM_FLAG1; 681 } else if ((anar & BRGPHY_ANAR_PC) && (anar & BRGPHY_ANAR_ASP) && 682 !(anlpar & BRGPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) { 683 mii->mii_media_active |= IFM_FLAG0; 684 } 685 } 686 687 /* Todo: Add support for fiber settings too. */ 688 689 690 brgphy_status_exit: 691 return; 692 } 693 694 static void 695 brgphy_mii_phy_auto(struct mii_softc *sc) 696 { 697 struct brgphy_softc *bsc = (struct brgphy_softc *)sc; 698 int ktcr = 0; 699 700 brgphy_reset(sc); 701 702 /* Enable flow control in the advertisement register. */ 703 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 704 /* Pause capability advertisement (pause capable & asymmetric) */ 705 PHY_WRITE(sc, BRGPHY_MII_ANAR, 706 BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA | 707 BRGPHY_ANAR_ASP | BRGPHY_ANAR_PC); 708 } else { 709 PHY_WRITE(sc, BRGPHY_SERDES_ANAR, BRGPHY_SERDES_ANAR_FDX | 710 BRGPHY_SERDES_ANAR_HDX | BRGPHY_SERDES_ANAR_BOTH_PAUSE); 711 } 712 713 /* Enable speed in the 1000baseT control register */ 714 ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD; 715 if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701) 716 ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC; 717 PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr); 718 ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL); 719 720 /* Start autonegotiation */ 721 PHY_WRITE(sc, BRGPHY_MII_BMCR,BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); 722 PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); 723 724 } 725 726 727 /* Enable loopback to force the link down. */ 728 static void 729 brgphy_enable_loopback(struct mii_softc *sc) 730 { 731 int i; 732 733 PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP); 734 for (i = 0; i < 15000; i++) { 735 if (!(PHY_READ(sc, BRGPHY_MII_BMSR) & BRGPHY_BMSR_LINK)) 736 break; 737 DELAY(10); 738 } 739 } 740 741 /* Turn off tap power management on 5401. */ 742 static void 743 bcm5401_load_dspcode(struct mii_softc *sc) 744 { 745 static const struct { 746 int reg; 747 uint16_t val; 748 } dspcode[] = { 749 { BRGPHY_MII_AUXCTL, 0x0c20 }, 750 { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 751 { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 752 { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 753 { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 754 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 755 { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 756 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 757 { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 758 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 759 { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 760 { 0, 0 }, 761 }; 762 int i; 763 764 for (i = 0; dspcode[i].reg != 0; i++) 765 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 766 DELAY(40); 767 } 768 769 static void 770 bcm5411_load_dspcode(struct mii_softc *sc) 771 { 772 static const struct { 773 int reg; 774 uint16_t val; 775 } dspcode[] = { 776 { 0x1c, 0x8c23 }, 777 { 0x1c, 0x8ca3 }, 778 { 0x1c, 0x8c23 }, 779 { 0, 0 }, 780 }; 781 int i; 782 783 for (i = 0; dspcode[i].reg != 0; i++) 784 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 785 } 786 787 void 788 bcm54k2_load_dspcode(struct mii_softc *sc) 789 { 790 static const struct { 791 int reg; 792 uint16_t val; 793 } dspcode[] = { 794 { 4, 0x01e1 }, 795 { 9, 0x0300 }, 796 { 0, 0 }, 797 }; 798 int i; 799 800 for (i = 0; dspcode[i].reg != 0; i++) 801 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 802 803 } 804 805 static void 806 brgphy_fixup_5704_a0_bug(struct mii_softc *sc) 807 { 808 static const struct { 809 int reg; 810 uint16_t val; 811 } dspcode[] = { 812 { 0x1c, 0x8d68 }, 813 { 0x1c, 0x8d68 }, 814 { 0, 0 }, 815 }; 816 int i; 817 818 for (i = 0; dspcode[i].reg != 0; i++) 819 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 820 } 821 822 static void 823 brgphy_fixup_adc_bug(struct mii_softc *sc) 824 { 825 static const struct { 826 int reg; 827 uint16_t val; 828 } dspcode[] = { 829 { BRGPHY_MII_AUXCTL, 0x0c00 }, 830 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 831 { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 832 { 0, 0 }, 833 }; 834 int i; 835 836 for (i = 0; dspcode[i].reg != 0; i++) 837 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 838 } 839 840 static void 841 brgphy_fixup_adjust_trim(struct mii_softc *sc) 842 { 843 static const struct { 844 int reg; 845 uint16_t val; 846 } dspcode[] = { 847 { BRGPHY_MII_AUXCTL, 0x0c00 }, 848 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 849 { BRGPHY_MII_DSP_RW_PORT, 0x110b }, 850 { BRGPHY_MII_TEST1, 0x0014 }, 851 { BRGPHY_MII_AUXCTL, 0x0400 }, 852 { 0, 0 }, 853 }; 854 int i; 855 856 for (i = 0; dspcode[i].reg != 0; i++) 857 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 858 } 859 860 static void 861 brgphy_fixup_ber_bug(struct mii_softc *sc) 862 { 863 static const struct { 864 int reg; 865 uint16_t val; 866 } dspcode[] = { 867 { BRGPHY_MII_AUXCTL, 0x0c00 }, 868 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 869 { BRGPHY_MII_DSP_RW_PORT, 0x310b }, 870 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 871 { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, 872 { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, 873 { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, 874 { BRGPHY_MII_AUXCTL, 0x0400 }, 875 { 0, 0 }, 876 }; 877 int i; 878 879 for (i = 0; dspcode[i].reg != 0; i++) 880 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 881 } 882 883 static void 884 brgphy_fixup_crc_bug(struct mii_softc *sc) 885 { 886 static const struct { 887 int reg; 888 uint16_t val; 889 } dspcode[] = { 890 { BRGPHY_MII_DSP_RW_PORT, 0x0a75 }, 891 { 0x1c, 0x8c68 }, 892 { 0x1c, 0x8d68 }, 893 { 0x1c, 0x8c68 }, 894 { 0, 0 }, 895 }; 896 int i; 897 898 for (i = 0; dspcode[i].reg != 0; i++) 899 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 900 } 901 902 static void 903 brgphy_fixup_jitter_bug(struct mii_softc *sc) 904 { 905 static const struct { 906 int reg; 907 uint16_t val; 908 } dspcode[] = { 909 { BRGPHY_MII_AUXCTL, 0x0c00 }, 910 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 911 { BRGPHY_MII_DSP_RW_PORT, 0x010b }, 912 { BRGPHY_MII_AUXCTL, 0x0400 }, 913 { 0, 0 }, 914 }; 915 int i; 916 917 for (i = 0; dspcode[i].reg != 0; i++) 918 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 919 } 920 921 922 static void 923 brgphy_fixup_disable_early_dac(struct mii_softc *sc) 924 { 925 uint32_t val; 926 927 PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08); 928 val = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT); 929 val &= ~(1 << 8); 930 PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val); 931 932 } 933 934 935 static void 936 brgphy_ethernet_wirespeed(struct mii_softc *sc) 937 { 938 uint32_t val; 939 940 /* Enable Ethernet@WireSpeed. */ 941 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); 942 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 943 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); 944 } 945 946 947 static void 948 brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu) 949 { 950 struct brgphy_softc *bsc = (struct brgphy_softc *)sc; 951 uint32_t val; 952 953 /* Set or clear jumbo frame settings in the PHY. */ 954 if (mtu > ETHER_MAX_LEN) { 955 if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5401) { 956 /* BCM5401 PHY cannot read-modify-write. */ 957 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20); 958 } else { 959 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); 960 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 961 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 962 val | BRGPHY_AUXCTL_LONG_PKT); 963 } 964 965 val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); 966 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 967 val | BRGPHY_PHY_EXTCTL_HIGH_LA); 968 } else { 969 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); 970 val = PHY_READ(sc, BRGPHY_MII_AUXCTL); 971 PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 972 val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7)); 973 974 val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); 975 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 976 val & ~BRGPHY_PHY_EXTCTL_HIGH_LA); 977 } 978 } 979 980 static void 981 brgphy_reset(struct mii_softc *sc) 982 { 983 struct brgphy_softc *bsc = (struct brgphy_softc *)sc; 984 struct bge_softc *bge_sc = NULL; 985 struct bce_softc *bce_sc = NULL; 986 struct ifnet *ifp; 987 int val; 988 989 /* Perform a standard PHY reset. */ 990 mii_phy_reset(sc); 991 992 /* Handle any PHY specific procedures following the reset. */ 993 switch (bsc->mii_oui) { 994 case MII_OUI_BROADCOM: 995 break; 996 case MII_OUI_xxBROADCOM: 997 switch (bsc->mii_model) { 998 case MII_MODEL_xxBROADCOM_BCM5400: 999 bcm5401_load_dspcode(sc); 1000 break; 1001 case MII_MODEL_xxBROADCOM_BCM5401: 1002 if (bsc->mii_rev == 1 || bsc->mii_rev == 3) 1003 bcm5401_load_dspcode(sc); 1004 break; 1005 case MII_MODEL_xxBROADCOM_BCM5411: 1006 bcm5411_load_dspcode(sc); 1007 break; 1008 case MII_MODEL_xxBROADCOM_BCM54K2: 1009 bcm54k2_load_dspcode(sc); 1010 break; 1011 } 1012 break; 1013 case MII_OUI_xxBROADCOM_ALT1: 1014 break; 1015 } 1016 1017 ifp = sc->mii_pdata->mii_ifp; 1018 1019 /* Find the driver associated with this PHY. */ 1020 if (strcmp(ifp->if_dname, "bge") == 0) { 1021 bge_sc = ifp->if_softc; 1022 } else if (strcmp(ifp->if_dname, "bce") == 0) { 1023 bce_sc = ifp->if_softc; 1024 } 1025 1026 /* Handle any bge (NetXtreme/NetLink) workarounds. */ 1027 if (bge_sc) { 1028 /* Fix up various bugs */ 1029 if (bge_sc->bge_phy_flags & BGE_PHY_5704_A0_BUG) 1030 brgphy_fixup_5704_a0_bug(sc); 1031 if (bge_sc->bge_phy_flags & BGE_PHY_ADC_BUG) 1032 brgphy_fixup_adc_bug(sc); 1033 if (bge_sc->bge_phy_flags & BGE_PHY_ADJUST_TRIM) 1034 brgphy_fixup_adjust_trim(sc); 1035 if (bge_sc->bge_phy_flags & BGE_PHY_BER_BUG) 1036 brgphy_fixup_ber_bug(sc); 1037 if (bge_sc->bge_phy_flags & BGE_PHY_CRC_BUG) 1038 brgphy_fixup_crc_bug(sc); 1039 if (bge_sc->bge_phy_flags & BGE_PHY_JITTER_BUG) 1040 brgphy_fixup_jitter_bug(sc); 1041 1042 brgphy_jumbo_settings(sc, ifp->if_mtu); 1043 1044 if (bge_sc->bge_phy_flags & BGE_PHY_WIRESPEED) 1045 brgphy_ethernet_wirespeed(sc); 1046 1047 /* Enable Link LED on Dell boxes */ 1048 if (bge_sc->bge_phy_flags & BGE_PHY_NO_3LED) { 1049 PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, 1050 PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) & 1051 ~BRGPHY_PHY_EXTCTL_3_LED); 1052 } 1053 1054 /* Adjust output voltage (From Linux driver) */ 1055 if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5906) 1056 PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12); 1057 1058 /* Handle any bce (NetXtreme II) workarounds. */ 1059 } else if (bce_sc) { 1060 1061 if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5708 && 1062 (bce_sc->bce_phy_flags & BCE_PHY_SERDES_FLAG)) { 1063 1064 /* Store autoneg capabilities/results in digital block (Page 0) */ 1065 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG3_PG2); 1066 PHY_WRITE(sc, BRGPHY_5708S_PG2_DIGCTL_3_0, 1067 BRGPHY_5708S_PG2_DIGCTL_3_0_USE_IEEE); 1068 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); 1069 1070 /* Enable fiber mode and autodetection */ 1071 PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL1, 1072 PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL1) | 1073 BRGPHY_5708S_PG0_1000X_CTL1_AUTODET_EN | 1074 BRGPHY_5708S_PG0_1000X_CTL1_FIBER_MODE); 1075 1076 /* Enable parallel detection */ 1077 PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL2, 1078 PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL2) | 1079 BRGPHY_5708S_PG0_1000X_CTL2_PAR_DET_EN); 1080 1081 /* Advertise 2.5G support through next page during autoneg */ 1082 if (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) 1083 PHY_WRITE(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1, 1084 PHY_READ(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1) | 1085 BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); 1086 1087 /* Increase TX signal amplitude */ 1088 if ((BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_A0) || 1089 (BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_B0) || 1090 (BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_B1)) { 1091 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 1092 BRGPHY_5708S_TX_MISC_PG5); 1093 PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL1, 1094 PHY_READ(sc, BRGPHY_5708S_PG5_TXACTL1) & ~0x30); 1095 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 1096 BRGPHY_5708S_DIG_PG0); 1097 } 1098 1099 /* Backplanes use special driver/pre-driver/pre-emphasis values. */ 1100 if ((bce_sc->bce_shared_hw_cfg & BCE_SHARED_HW_CFG_PHY_BACKPLANE) && 1101 (bce_sc->bce_port_hw_cfg & BCE_PORT_HW_CFG_CFG_TXCTL3_MASK)) { 1102 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 1103 BRGPHY_5708S_TX_MISC_PG5); 1104 PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL3, 1105 bce_sc->bce_port_hw_cfg & 1106 BCE_PORT_HW_CFG_CFG_TXCTL3_MASK); 1107 PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, 1108 BRGPHY_5708S_DIG_PG0); 1109 } 1110 } else if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5709 && 1111 (bce_sc->bce_phy_flags & BCE_PHY_SERDES_FLAG)) { 1112 1113 /* Select the SerDes Digital block of the AN MMD. */ 1114 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_SERDES_DIG); 1115 val = PHY_READ(sc, BRGPHY_SERDES_DIG_1000X_CTL1); 1116 val &= ~BRGPHY_SD_DIG_1000X_CTL1_AUTODET; 1117 val |= BRGPHY_SD_DIG_1000X_CTL1_FIBER; 1118 PHY_WRITE(sc, BRGPHY_SERDES_DIG_1000X_CTL1, val); 1119 1120 /* Select the Over 1G block of the AN MMD. */ 1121 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_OVER_1G); 1122 1123 /* Enable autoneg "Next Page" to advertise 2.5G support. */ 1124 val = PHY_READ(sc, BRGPHY_OVER_1G_UNFORMAT_PG1); 1125 if (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) 1126 val |= BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G; 1127 else 1128 val &= ~BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G; 1129 PHY_WRITE(sc, BRGPHY_OVER_1G_UNFORMAT_PG1, val); 1130 1131 /* Select the Multi-Rate Backplane Ethernet block of the AN MMD. */ 1132 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_MRBE); 1133 1134 /* Enable MRBE speed autoneg. */ 1135 val = PHY_READ(sc, BRGPHY_MRBE_MSG_PG5_NP); 1136 val |= BRGPHY_MRBE_MSG_PG5_NP_MBRE | 1137 BRGPHY_MRBE_MSG_PG5_NP_T2; 1138 PHY_WRITE(sc, BRGPHY_MRBE_MSG_PG5_NP, val); 1139 1140 /* Select the Clause 73 User B0 block of the AN MMD. */ 1141 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_CL73_USER_B0); 1142 1143 /* Enable MRBE speed autoneg. */ 1144 PHY_WRITE(sc, BRGPHY_CL73_USER_B0_MBRE_CTL1, 1145 BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP | 1146 BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR | 1147 BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG); 1148 1149 /* Restore IEEE0 block (assumed in all brgphy(4) code). */ 1150 PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_COMBO_IEEE0); 1151 1152 } else if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5709) { 1153 if ((BCE_CHIP_REV(bce_sc) == BCE_CHIP_REV_Ax) || 1154 (BCE_CHIP_REV(bce_sc) == BCE_CHIP_REV_Bx)) 1155 brgphy_fixup_disable_early_dac(sc); 1156 1157 brgphy_jumbo_settings(sc, ifp->if_mtu); 1158 brgphy_ethernet_wirespeed(sc); 1159 } else { 1160 brgphy_fixup_ber_bug(sc); 1161 brgphy_jumbo_settings(sc, ifp->if_mtu); 1162 brgphy_ethernet_wirespeed(sc); 1163 } 1164 1165 } 1166 } 1167