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