1 /* $NetBSD: brgphy.c,v 1.41 2008/11/17 03:04:27 dyoung 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 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by Manuel Bouyer. 47 * 4. The name of the author may not be used to endorse or promote products 48 * derived from this software without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 53 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 59 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 */ 61 62 /* 63 * driver for the Broadcom BCM5400 Gig-E PHY. 64 * 65 * Programming information for this PHY was gleaned from FreeBSD 66 * (they were apparently able to get a datasheet from Broadcom). 67 */ 68 69 #include <sys/cdefs.h> 70 __KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.41 2008/11/17 03:04:27 dyoung Exp $"); 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/kernel.h> 75 #include <sys/device.h> 76 #include <sys/socket.h> 77 #include <sys/errno.h> 78 79 #include <net/if.h> 80 #include <net/if_media.h> 81 82 #include <dev/mii/mii.h> 83 #include <dev/mii/miivar.h> 84 #include <dev/mii/miidevs.h> 85 86 #include <dev/mii/brgphyreg.h> 87 88 static int brgphymatch(device_t, cfdata_t, void *); 89 static void brgphyattach(device_t, device_t, void *); 90 91 CFATTACH_DECL_NEW(brgphy, sizeof(struct mii_softc), 92 brgphymatch, brgphyattach, mii_phy_detach, mii_phy_activate); 93 94 static int brgphy_service(struct mii_softc *, struct mii_data *, int); 95 static void brgphy_status(struct mii_softc *); 96 static int brgphy_mii_phy_auto(struct mii_softc *); 97 static void brgphy_loop(struct mii_softc *); 98 99 static void brgphy_5401_reset(struct mii_softc *); 100 static void brgphy_5411_reset(struct mii_softc *); 101 static void brgphy_5703_reset(struct mii_softc *); 102 static void brgphy_5704_reset(struct mii_softc *); 103 static void brgphy_5705_reset(struct mii_softc *); 104 static void brgphy_5750_reset(struct mii_softc *); 105 static void brgphy_5755_reset(struct mii_softc *); 106 107 static const struct mii_phy_funcs brgphy_funcs = { 108 brgphy_service, brgphy_status, mii_phy_reset, 109 }; 110 111 static const struct mii_phy_funcs brgphy_5401_funcs = { 112 brgphy_service, brgphy_status, brgphy_5401_reset, 113 }; 114 115 static const struct mii_phy_funcs brgphy_5411_funcs = { 116 brgphy_service, brgphy_status, brgphy_5411_reset, 117 }; 118 119 static const struct mii_phy_funcs brgphy_5703_funcs = { 120 brgphy_service, brgphy_status, brgphy_5703_reset, 121 }; 122 123 static const struct mii_phy_funcs brgphy_5704_funcs = { 124 brgphy_service, brgphy_status, brgphy_5704_reset, 125 }; 126 127 static const struct mii_phy_funcs brgphy_5705_funcs = { 128 brgphy_service, brgphy_status, brgphy_5705_reset, 129 }; 130 131 const struct mii_phy_funcs brgphy_5750_funcs = { 132 brgphy_service, brgphy_status, brgphy_5750_reset, 133 }; 134 135 const struct mii_phy_funcs brgphy_5755_funcs = { 136 brgphy_service, brgphy_status, brgphy_5755_reset, 137 }; 138 139 140 static const struct mii_phydesc brgphys[] = { 141 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5400, 142 MII_STR_BROADCOM_BCM5400 }, 143 144 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5401, 145 MII_STR_BROADCOM_BCM5401 }, 146 147 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5411, 148 MII_STR_BROADCOM_BCM5411 }, 149 150 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5421, 151 MII_STR_BROADCOM_BCM5421 }, 152 153 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5701, 154 MII_STR_BROADCOM_BCM5701 }, 155 156 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5703, 157 MII_STR_BROADCOM_BCM5703 }, 158 159 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5704, 160 MII_STR_BROADCOM_BCM5704 }, 161 162 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5705, 163 MII_STR_BROADCOM_BCM5705 }, 164 165 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5714, 166 MII_STR_BROADCOM_BCM5714 }, 167 168 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5750, 169 MII_STR_BROADCOM_BCM5750 }, 170 171 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5752, 172 MII_STR_BROADCOM_BCM5752 }, 173 174 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5780, 175 MII_STR_BROADCOM_BCM5780 }, 176 177 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5708C, 178 MII_STR_BROADCOM_BCM5708C }, 179 180 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5755, 181 MII_STR_BROADCOM2_BCM5755 }, 182 183 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5754, 184 MII_STR_BROADCOM2_BCM5754 }, 185 186 { MII_OUI_xxBROADCOM_ALT1, MII_MODEL_xxBROADCOM_ALT1_BCM5906, 187 MII_STR_xxBROADCOM_ALT1_BCM5906 }, 188 189 { 0, 0, 190 NULL }, 191 }; 192 193 static void bcm5401_load_dspcode(struct mii_softc *); 194 static void bcm5411_load_dspcode(struct mii_softc *); 195 static void bcm5703_load_dspcode(struct mii_softc *); 196 static void bcm5704_load_dspcode(struct mii_softc *); 197 static void bcm5750_load_dspcode(struct mii_softc *); 198 static void bcm5755_load_dspcode(struct mii_softc *); 199 200 static int 201 brgphymatch(struct device *parent, struct cfdata *match, 202 void *aux) 203 { 204 struct mii_attach_args *ma = aux; 205 206 if (mii_phy_match(ma, brgphys) != NULL) 207 return (10); 208 209 return (0); 210 } 211 212 static void 213 brgphyattach(struct device *parent, struct device *self, void *aux) 214 { 215 struct mii_softc *sc = device_private(self); 216 struct mii_attach_args *ma = aux; 217 struct mii_data *mii = ma->mii_data; 218 const struct mii_phydesc *mpd; 219 220 mpd = mii_phy_match(ma, brgphys); 221 aprint_naive(": Media interface\n"); 222 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 223 224 sc->mii_dev = self; 225 sc->mii_inst = mii->mii_instance; 226 sc->mii_phy = ma->mii_phyno; 227 sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 228 sc->mii_pdata = mii; 229 sc->mii_flags = ma->mii_flags; 230 sc->mii_anegticks = MII_ANEGTICKS; 231 232 if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM_ALT1) { 233 sc->mii_funcs = &brgphy_5750_funcs; 234 aprint_normal_dev(self, "using BCM5750 DSP patch\n"); 235 } else { 236 switch (MII_MODEL(ma->mii_id2)) { 237 case MII_MODEL_BROADCOM_BCM5400: 238 sc->mii_funcs = &brgphy_5401_funcs; 239 aprint_normal_dev(self, "using BCM5401 DSP patch\n"); 240 break; 241 242 case MII_MODEL_BROADCOM_BCM5401: 243 if (MII_REV(ma->mii_id2) == 1 || MII_REV(ma->mii_id2) == 3) { 244 sc->mii_funcs = &brgphy_5401_funcs; 245 aprint_normal_dev(self, "using BCM5401 DSP patch\n"); 246 } else 247 sc->mii_funcs = &brgphy_funcs; 248 break; 249 250 case MII_MODEL_BROADCOM_BCM5411: 251 sc->mii_funcs = &brgphy_5411_funcs; 252 aprint_normal_dev(self, "using BCM5411 DSP patch\n"); 253 break; 254 255 #ifdef notyet /* unverified, untested */ 256 case MII_MODEL_BROADCOM_BCM5703: 257 sc->mii_funcs = &brgphy_5703_funcs; 258 aprint_normal_dev(self, "using BCM5703 DSP patch\n"); 259 break; 260 #endif 261 262 case MII_MODEL_BROADCOM_BCM5704: 263 sc->mii_funcs = &brgphy_5704_funcs; 264 aprint_normal_dev(self, "using BCM5704 DSP patch\n"); 265 break; 266 267 case MII_MODEL_BROADCOM_BCM5705: 268 sc->mii_funcs = &brgphy_5705_funcs; 269 break; 270 271 case MII_MODEL_BROADCOM_BCM5714: 272 case MII_MODEL_BROADCOM_BCM5780: 273 case MII_MODEL_BROADCOM_BCM5708C: 274 case MII_MODEL_BROADCOM_BCM5750: 275 case MII_MODEL_BROADCOM_BCM5752: 276 sc->mii_funcs = &brgphy_5750_funcs; 277 break; 278 279 case MII_MODEL_BROADCOM2_BCM5754: 280 case MII_MODEL_BROADCOM2_BCM5755: 281 sc->mii_funcs = &brgphy_5755_funcs; 282 break; 283 284 default: 285 sc->mii_funcs = &brgphy_funcs; 286 break; 287 } 288 } 289 290 PHY_RESET(sc); 291 292 sc->mii_capabilities = 293 PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 294 if (sc->mii_capabilities & BMSR_EXTSTAT) 295 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 296 297 aprint_normal_dev(self, ""); 298 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 299 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) 300 aprint_error("no media present"); 301 else 302 mii_phy_add_media(sc); 303 aprint_normal("\n"); 304 } 305 306 static int 307 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 308 { 309 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 310 int reg, speed, gig; 311 312 switch (cmd) { 313 case MII_POLLSTAT: 314 /* 315 * If we're not polling our PHY instance, just return. 316 */ 317 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 318 return (0); 319 break; 320 321 case MII_MEDIACHG: 322 /* 323 * If the media indicates a different PHY instance, 324 * isolate ourselves. 325 */ 326 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 327 reg = PHY_READ(sc, MII_BMCR); 328 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 329 return (0); 330 } 331 332 /* 333 * If the interface is not up, don't do anything. 334 */ 335 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 336 break; 337 338 PHY_RESET(sc); /* XXX hardware bug work-around */ 339 340 switch (IFM_SUBTYPE(ife->ifm_media)) { 341 case IFM_AUTO: 342 (void) brgphy_mii_phy_auto(sc); 343 break; 344 case IFM_1000_T: 345 speed = BMCR_S1000; 346 goto setit; 347 case IFM_100_TX: 348 speed = BMCR_S100; 349 goto setit; 350 case IFM_10_T: 351 speed = BMCR_S10; 352 setit: 353 brgphy_loop(sc); 354 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 355 speed |= BMCR_FDX; 356 gig = GTCR_ADV_1000TFDX; 357 } else { 358 gig = GTCR_ADV_1000THDX; 359 } 360 361 PHY_WRITE(sc, MII_100T2CR, 0); 362 PHY_WRITE(sc, MII_BMCR, speed); 363 PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); 364 365 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 366 break; 367 368 PHY_WRITE(sc, MII_100T2CR, gig); 369 PHY_WRITE(sc, MII_BMCR, 370 speed|BMCR_AUTOEN|BMCR_STARTNEG); 371 372 if (sc->mii_mpd_model != MII_MODEL_BROADCOM_BCM5701) 373 break; 374 375 if (mii->mii_media.ifm_media & IFM_ETH_MASTER) 376 gig |= GTCR_MAN_MS | GTCR_ADV_MS; 377 PHY_WRITE(sc, MII_100T2CR, gig); 378 break; 379 default: 380 return (EINVAL); 381 } 382 break; 383 384 case MII_TICK: 385 /* 386 * If we're not currently selected, just return. 387 */ 388 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 389 return (0); 390 391 if (mii_phy_tick(sc) == EJUSTRETURN) 392 return (0); 393 break; 394 395 case MII_DOWN: 396 mii_phy_down(sc); 397 return (0); 398 } 399 400 /* Update the media status. */ 401 mii_phy_status(sc); 402 403 /* 404 * Callback if something changed. Note that we need to poke the DSP on 405 * the Broadcom PHYs if the media changes. 406 */ 407 if (sc->mii_media_active != mii->mii_media_active || 408 sc->mii_media_status != mii->mii_media_status || 409 cmd == MII_MEDIACHG) { 410 mii_phy_update(sc, cmd); 411 if (sc->mii_funcs == &brgphy_5401_funcs) 412 bcm5401_load_dspcode(sc); 413 else if (sc->mii_funcs == &brgphy_5411_funcs) 414 bcm5411_load_dspcode(sc); 415 } 416 return (0); 417 } 418 419 static void 420 brgphy_status(struct mii_softc *sc) 421 { 422 struct mii_data *mii = sc->mii_pdata; 423 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 424 int bmcr, auxsts, gtsr; 425 426 mii->mii_media_status = IFM_AVALID; 427 mii->mii_media_active = IFM_ETHER; 428 429 auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS); 430 431 if (auxsts & BRGPHY_AUXSTS_LINK) 432 mii->mii_media_status |= IFM_ACTIVE; 433 434 bmcr = PHY_READ(sc, MII_BMCR); 435 if (bmcr & BMCR_ISO) { 436 mii->mii_media_active |= IFM_NONE; 437 mii->mii_media_status = 0; 438 return; 439 } 440 441 if (bmcr & BMCR_LOOP) 442 mii->mii_media_active |= IFM_LOOP; 443 444 if (bmcr & BMCR_AUTOEN) { 445 /* 446 * The media status bits are only valid of autonegotiation 447 * has completed (or it's disabled). 448 */ 449 if ((auxsts & BRGPHY_AUXSTS_ACOMP) == 0) { 450 /* Erg, still trying, I guess... */ 451 mii->mii_media_active |= IFM_NONE; 452 return; 453 } 454 455 switch (auxsts & BRGPHY_AUXSTS_AN_RES) { 456 case BRGPHY_RES_1000FD: 457 mii->mii_media_active |= IFM_1000_T|IFM_FDX; 458 gtsr = PHY_READ(sc, MII_100T2SR); 459 if (gtsr & GTSR_MS_RES) 460 mii->mii_media_active |= IFM_ETH_MASTER; 461 break; 462 463 case BRGPHY_RES_1000HD: 464 mii->mii_media_active |= IFM_1000_T; 465 gtsr = PHY_READ(sc, MII_100T2SR); 466 if (gtsr & GTSR_MS_RES) 467 mii->mii_media_active |= IFM_ETH_MASTER; 468 break; 469 470 case BRGPHY_RES_100FD: 471 mii->mii_media_active |= IFM_100_TX|IFM_FDX; 472 break; 473 474 case BRGPHY_RES_100T4: 475 mii->mii_media_active |= IFM_100_T4; 476 break; 477 478 case BRGPHY_RES_100HD: 479 mii->mii_media_active |= IFM_100_TX; 480 break; 481 482 case BRGPHY_RES_10FD: 483 mii->mii_media_active |= IFM_10_T|IFM_FDX; 484 break; 485 486 case BRGPHY_RES_10HD: 487 mii->mii_media_active |= IFM_10_T; 488 break; 489 490 default: 491 mii->mii_media_active |= IFM_NONE; 492 mii->mii_media_status = 0; 493 } 494 if (mii->mii_media_active & IFM_FDX) 495 mii->mii_media_active |= mii_phy_flowstatus(sc); 496 } else 497 mii->mii_media_active = ife->ifm_media; 498 } 499 500 int 501 brgphy_mii_phy_auto(struct mii_softc *sc) 502 { 503 int anar, ktcr = 0; 504 505 brgphy_loop(sc); 506 PHY_RESET(sc); 507 ktcr = GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX; 508 if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701) 509 ktcr |= GTCR_MAN_MS|GTCR_ADV_MS; 510 PHY_WRITE(sc, MII_100T2CR, ktcr); 511 ktcr = PHY_READ(sc, MII_100T2CR); 512 DELAY(1000); 513 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; 514 if (sc->mii_flags & MIIF_DOPAUSE) 515 anar |= ANAR_FC| ANAR_X_PAUSE_ASYM; 516 517 PHY_WRITE(sc, MII_ANAR, anar); 518 DELAY(1000); 519 PHY_WRITE(sc, MII_BMCR, 520 BMCR_AUTOEN | BMCR_STARTNEG); 521 PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); 522 523 return (EJUSTRETURN); 524 } 525 526 void 527 brgphy_loop(struct mii_softc *sc) 528 { 529 u_int32_t bmsr; 530 int i; 531 532 PHY_WRITE(sc, MII_BMCR, BMCR_LOOP); 533 for (i = 0; i < 15000; i++) { 534 bmsr = PHY_READ(sc, MII_BMSR); 535 if (!(bmsr & BMSR_LINK)) 536 break; 537 DELAY(10); 538 } 539 } 540 541 static void 542 brgphy_5401_reset(struct mii_softc *sc) 543 { 544 545 mii_phy_reset(sc); 546 bcm5401_load_dspcode(sc); 547 } 548 549 static void 550 brgphy_5411_reset(struct mii_softc *sc) 551 { 552 553 mii_phy_reset(sc); 554 bcm5411_load_dspcode(sc); 555 } 556 557 558 static void 559 brgphy_5703_reset(struct mii_softc *sc) 560 { 561 562 mii_phy_reset(sc); 563 bcm5703_load_dspcode(sc); 564 } 565 566 static void 567 brgphy_5704_reset(struct mii_softc *sc) 568 { 569 570 mii_phy_reset(sc); 571 bcm5704_load_dspcode(sc); 572 } 573 574 /* 575 * Hardware bug workaround. Do nothing since after 576 * reset the 5705 PHY would get stuck in 10/100 MII mode. 577 */ 578 579 static void 580 brgphy_5705_reset(struct mii_softc *sc) 581 { 582 } 583 584 static void 585 brgphy_5750_reset(struct mii_softc *sc) 586 { 587 mii_phy_reset(sc); 588 bcm5750_load_dspcode(sc); 589 } 590 591 static void 592 brgphy_5755_reset(struct mii_softc *sc) 593 { 594 mii_phy_reset(sc); 595 bcm5755_load_dspcode(sc); 596 } 597 598 /* Turn off tap power management on 5401. */ 599 static void 600 bcm5401_load_dspcode(struct mii_softc *sc) 601 { 602 static const struct { 603 int reg; 604 uint16_t val; 605 } dspcode[] = { 606 { BRGPHY_MII_AUXCTL, 0x0c20 }, 607 { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 608 { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 609 { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 610 { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 611 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 612 { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 613 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 614 { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 615 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 616 { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 617 { 0, 0 }, 618 }; 619 int i; 620 621 for (i = 0; dspcode[i].reg != 0; i++) 622 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 623 delay(40); 624 } 625 626 static void 627 bcm5411_load_dspcode(struct mii_softc *sc) 628 { 629 static const struct { 630 int reg; 631 uint16_t val; 632 } dspcode[] = { 633 { 0x1c, 0x8c23 }, 634 { 0x1c, 0x8ca3 }, 635 { 0x1c, 0x8c23 }, 636 { 0, 0 }, 637 }; 638 int i; 639 640 for (i = 0; dspcode[i].reg != 0; i++) 641 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 642 } 643 644 static void 645 bcm5703_load_dspcode(struct mii_softc *sc) 646 { 647 static const struct { 648 int reg; 649 uint16_t val; 650 } dspcode[] = { 651 { BRGPHY_MII_AUXCTL, 0x0c00 }, 652 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 653 { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 654 { 0, 0 }, 655 }; 656 int i; 657 658 for (i = 0; dspcode[i].reg != 0; i++) 659 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 660 } 661 662 static void 663 bcm5704_load_dspcode(struct mii_softc *sc) 664 { 665 static const struct { 666 int reg; 667 uint16_t val; 668 } dspcode[] = { 669 { 0x1c, 0x8d68 }, 670 { 0x1c, 0x8d68 }, 671 { 0, 0 }, 672 }; 673 int i; 674 675 for (i = 0; dspcode[i].reg != 0; i++) 676 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 677 } 678 679 static void 680 bcm5750_load_dspcode(struct mii_softc *sc) 681 { 682 static const struct { 683 int reg; 684 uint16_t val; 685 } dspcode[] = { 686 { BRGPHY_MII_AUXCTL, 0x0c00 }, 687 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 688 { BRGPHY_MII_DSP_RW_PORT, 0x310b }, 689 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 690 { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, 691 { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, 692 { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, 693 { BRGPHY_MII_AUXCTL, 0x0400 }, 694 { 0, 0 }, 695 }; 696 int i; 697 698 for (i = 0; dspcode[i].reg != 0; i++) 699 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 700 } 701 702 static void 703 bcm5755_load_dspcode(struct mii_softc *sc) 704 { 705 static const struct { 706 int reg; 707 uint16_t val; 708 } dspcode[] = { 709 { BRGPHY_MII_AUXCTL, 0x0c00 }, 710 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 711 { BRGPHY_MII_DSP_RW_PORT, 0x010b }, 712 713 { BRGPHY_MII_AUXCTL, 0x0400 }, 714 { 0, 0 }, 715 }; 716 int i; 717 718 for (i = 0; dspcode[i].reg != 0; i++) 719 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 720 } 721