1 /* $NetBSD: brgphy.c,v 1.42 2009/04/07 18:05:54 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.42 2009/04/07 18:05:54 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_DECL3_NEW(brgphy, sizeof(struct mii_softc), 92 brgphymatch, brgphyattach, mii_phy_detach, mii_phy_activate, NULL, NULL, 93 DVF_DETACH_SHUTDOWN); 94 95 static int brgphy_service(struct mii_softc *, struct mii_data *, int); 96 static void brgphy_status(struct mii_softc *); 97 static int brgphy_mii_phy_auto(struct mii_softc *); 98 static void brgphy_loop(struct mii_softc *); 99 100 static void brgphy_5401_reset(struct mii_softc *); 101 static void brgphy_5411_reset(struct mii_softc *); 102 static void brgphy_5703_reset(struct mii_softc *); 103 static void brgphy_5704_reset(struct mii_softc *); 104 static void brgphy_5705_reset(struct mii_softc *); 105 static void brgphy_5750_reset(struct mii_softc *); 106 static void brgphy_5755_reset(struct mii_softc *); 107 108 static const struct mii_phy_funcs brgphy_funcs = { 109 brgphy_service, brgphy_status, mii_phy_reset, 110 }; 111 112 static const struct mii_phy_funcs brgphy_5401_funcs = { 113 brgphy_service, brgphy_status, brgphy_5401_reset, 114 }; 115 116 static const struct mii_phy_funcs brgphy_5411_funcs = { 117 brgphy_service, brgphy_status, brgphy_5411_reset, 118 }; 119 120 static const struct mii_phy_funcs brgphy_5703_funcs = { 121 brgphy_service, brgphy_status, brgphy_5703_reset, 122 }; 123 124 static const struct mii_phy_funcs brgphy_5704_funcs = { 125 brgphy_service, brgphy_status, brgphy_5704_reset, 126 }; 127 128 static const struct mii_phy_funcs brgphy_5705_funcs = { 129 brgphy_service, brgphy_status, brgphy_5705_reset, 130 }; 131 132 const struct mii_phy_funcs brgphy_5750_funcs = { 133 brgphy_service, brgphy_status, brgphy_5750_reset, 134 }; 135 136 const struct mii_phy_funcs brgphy_5755_funcs = { 137 brgphy_service, brgphy_status, brgphy_5755_reset, 138 }; 139 140 141 static const struct mii_phydesc brgphys[] = { 142 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5400, 143 MII_STR_BROADCOM_BCM5400 }, 144 145 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5401, 146 MII_STR_BROADCOM_BCM5401 }, 147 148 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5411, 149 MII_STR_BROADCOM_BCM5411 }, 150 151 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5421, 152 MII_STR_BROADCOM_BCM5421 }, 153 154 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5701, 155 MII_STR_BROADCOM_BCM5701 }, 156 157 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5703, 158 MII_STR_BROADCOM_BCM5703 }, 159 160 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5704, 161 MII_STR_BROADCOM_BCM5704 }, 162 163 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5705, 164 MII_STR_BROADCOM_BCM5705 }, 165 166 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5714, 167 MII_STR_BROADCOM_BCM5714 }, 168 169 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5750, 170 MII_STR_BROADCOM_BCM5750 }, 171 172 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5752, 173 MII_STR_BROADCOM_BCM5752 }, 174 175 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5780, 176 MII_STR_BROADCOM_BCM5780 }, 177 178 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5708C, 179 MII_STR_BROADCOM_BCM5708C }, 180 181 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5755, 182 MII_STR_BROADCOM2_BCM5755 }, 183 184 { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5754, 185 MII_STR_BROADCOM2_BCM5754 }, 186 187 { MII_OUI_xxBROADCOM_ALT1, MII_MODEL_xxBROADCOM_ALT1_BCM5906, 188 MII_STR_xxBROADCOM_ALT1_BCM5906 }, 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_dev = self; 226 sc->mii_inst = mii->mii_instance; 227 sc->mii_phy = ma->mii_phyno; 228 sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 229 sc->mii_pdata = mii; 230 sc->mii_flags = ma->mii_flags; 231 sc->mii_anegticks = MII_ANEGTICKS; 232 233 if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM_ALT1) { 234 sc->mii_funcs = &brgphy_5750_funcs; 235 aprint_normal_dev(self, "using BCM5750 DSP patch\n"); 236 } else { 237 switch (MII_MODEL(ma->mii_id2)) { 238 case MII_MODEL_BROADCOM_BCM5400: 239 sc->mii_funcs = &brgphy_5401_funcs; 240 aprint_normal_dev(self, "using BCM5401 DSP patch\n"); 241 break; 242 243 case MII_MODEL_BROADCOM_BCM5401: 244 if (MII_REV(ma->mii_id2) == 1 || MII_REV(ma->mii_id2) == 3) { 245 sc->mii_funcs = &brgphy_5401_funcs; 246 aprint_normal_dev(self, "using BCM5401 DSP patch\n"); 247 } else 248 sc->mii_funcs = &brgphy_funcs; 249 break; 250 251 case MII_MODEL_BROADCOM_BCM5411: 252 sc->mii_funcs = &brgphy_5411_funcs; 253 aprint_normal_dev(self, "using BCM5411 DSP patch\n"); 254 break; 255 256 #ifdef notyet /* unverified, untested */ 257 case MII_MODEL_BROADCOM_BCM5703: 258 sc->mii_funcs = &brgphy_5703_funcs; 259 aprint_normal_dev(self, "using BCM5703 DSP patch\n"); 260 break; 261 #endif 262 263 case MII_MODEL_BROADCOM_BCM5704: 264 sc->mii_funcs = &brgphy_5704_funcs; 265 aprint_normal_dev(self, "using BCM5704 DSP patch\n"); 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_BCM5708C: 275 case MII_MODEL_BROADCOM_BCM5750: 276 case MII_MODEL_BROADCOM_BCM5752: 277 sc->mii_funcs = &brgphy_5750_funcs; 278 break; 279 280 case MII_MODEL_BROADCOM2_BCM5754: 281 case MII_MODEL_BROADCOM2_BCM5755: 282 sc->mii_funcs = &brgphy_5755_funcs; 283 break; 284 285 default: 286 sc->mii_funcs = &brgphy_funcs; 287 break; 288 } 289 } 290 291 PHY_RESET(sc); 292 293 sc->mii_capabilities = 294 PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 295 if (sc->mii_capabilities & BMSR_EXTSTAT) 296 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 297 298 aprint_normal_dev(self, ""); 299 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 300 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) 301 aprint_error("no media present"); 302 else 303 mii_phy_add_media(sc); 304 aprint_normal("\n"); 305 } 306 307 static int 308 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 309 { 310 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 311 int reg, speed, gig; 312 313 switch (cmd) { 314 case MII_POLLSTAT: 315 /* 316 * If we're not polling our PHY instance, just return. 317 */ 318 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 319 return (0); 320 break; 321 322 case MII_MEDIACHG: 323 /* 324 * If the media indicates a different PHY instance, 325 * isolate ourselves. 326 */ 327 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 328 reg = PHY_READ(sc, MII_BMCR); 329 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 330 return (0); 331 } 332 333 /* 334 * If the interface is not up, don't do anything. 335 */ 336 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 337 break; 338 339 PHY_RESET(sc); /* XXX hardware bug work-around */ 340 341 switch (IFM_SUBTYPE(ife->ifm_media)) { 342 case IFM_AUTO: 343 (void) brgphy_mii_phy_auto(sc); 344 break; 345 case IFM_1000_T: 346 speed = BMCR_S1000; 347 goto setit; 348 case IFM_100_TX: 349 speed = BMCR_S100; 350 goto setit; 351 case IFM_10_T: 352 speed = BMCR_S10; 353 setit: 354 brgphy_loop(sc); 355 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 356 speed |= BMCR_FDX; 357 gig = GTCR_ADV_1000TFDX; 358 } else { 359 gig = GTCR_ADV_1000THDX; 360 } 361 362 PHY_WRITE(sc, MII_100T2CR, 0); 363 PHY_WRITE(sc, MII_BMCR, speed); 364 PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); 365 366 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 367 break; 368 369 PHY_WRITE(sc, MII_100T2CR, gig); 370 PHY_WRITE(sc, MII_BMCR, 371 speed|BMCR_AUTOEN|BMCR_STARTNEG); 372 373 if (sc->mii_mpd_model != MII_MODEL_BROADCOM_BCM5701) 374 break; 375 376 if (mii->mii_media.ifm_media & IFM_ETH_MASTER) 377 gig |= GTCR_MAN_MS | GTCR_ADV_MS; 378 PHY_WRITE(sc, MII_100T2CR, gig); 379 break; 380 default: 381 return (EINVAL); 382 } 383 break; 384 385 case MII_TICK: 386 /* 387 * If we're not currently selected, just return. 388 */ 389 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 390 return (0); 391 392 if (mii_phy_tick(sc) == EJUSTRETURN) 393 return (0); 394 break; 395 396 case MII_DOWN: 397 mii_phy_down(sc); 398 return (0); 399 } 400 401 /* Update the media status. */ 402 mii_phy_status(sc); 403 404 /* 405 * Callback if something changed. Note that we need to poke the DSP on 406 * the Broadcom PHYs if the media changes. 407 */ 408 if (sc->mii_media_active != mii->mii_media_active || 409 sc->mii_media_status != mii->mii_media_status || 410 cmd == MII_MEDIACHG) { 411 mii_phy_update(sc, cmd); 412 if (sc->mii_funcs == &brgphy_5401_funcs) 413 bcm5401_load_dspcode(sc); 414 else if (sc->mii_funcs == &brgphy_5411_funcs) 415 bcm5411_load_dspcode(sc); 416 } 417 return (0); 418 } 419 420 static void 421 brgphy_status(struct mii_softc *sc) 422 { 423 struct mii_data *mii = sc->mii_pdata; 424 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 425 int bmcr, auxsts, gtsr; 426 427 mii->mii_media_status = IFM_AVALID; 428 mii->mii_media_active = IFM_ETHER; 429 430 auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS); 431 432 if (auxsts & BRGPHY_AUXSTS_LINK) 433 mii->mii_media_status |= IFM_ACTIVE; 434 435 bmcr = PHY_READ(sc, MII_BMCR); 436 if (bmcr & BMCR_ISO) { 437 mii->mii_media_active |= IFM_NONE; 438 mii->mii_media_status = 0; 439 return; 440 } 441 442 if (bmcr & BMCR_LOOP) 443 mii->mii_media_active |= IFM_LOOP; 444 445 if (bmcr & BMCR_AUTOEN) { 446 /* 447 * The media status bits are only valid of autonegotiation 448 * has completed (or it's disabled). 449 */ 450 if ((auxsts & BRGPHY_AUXSTS_ACOMP) == 0) { 451 /* Erg, still trying, I guess... */ 452 mii->mii_media_active |= IFM_NONE; 453 return; 454 } 455 456 switch (auxsts & BRGPHY_AUXSTS_AN_RES) { 457 case BRGPHY_RES_1000FD: 458 mii->mii_media_active |= IFM_1000_T|IFM_FDX; 459 gtsr = PHY_READ(sc, MII_100T2SR); 460 if (gtsr & GTSR_MS_RES) 461 mii->mii_media_active |= IFM_ETH_MASTER; 462 break; 463 464 case BRGPHY_RES_1000HD: 465 mii->mii_media_active |= IFM_1000_T; 466 gtsr = PHY_READ(sc, MII_100T2SR); 467 if (gtsr & GTSR_MS_RES) 468 mii->mii_media_active |= IFM_ETH_MASTER; 469 break; 470 471 case BRGPHY_RES_100FD: 472 mii->mii_media_active |= IFM_100_TX|IFM_FDX; 473 break; 474 475 case BRGPHY_RES_100T4: 476 mii->mii_media_active |= IFM_100_T4; 477 break; 478 479 case BRGPHY_RES_100HD: 480 mii->mii_media_active |= IFM_100_TX; 481 break; 482 483 case BRGPHY_RES_10FD: 484 mii->mii_media_active |= IFM_10_T|IFM_FDX; 485 break; 486 487 case BRGPHY_RES_10HD: 488 mii->mii_media_active |= IFM_10_T; 489 break; 490 491 default: 492 mii->mii_media_active |= IFM_NONE; 493 mii->mii_media_status = 0; 494 } 495 if (mii->mii_media_active & IFM_FDX) 496 mii->mii_media_active |= mii_phy_flowstatus(sc); 497 } else 498 mii->mii_media_active = ife->ifm_media; 499 } 500 501 int 502 brgphy_mii_phy_auto(struct mii_softc *sc) 503 { 504 int anar, ktcr = 0; 505 506 brgphy_loop(sc); 507 PHY_RESET(sc); 508 ktcr = GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX; 509 if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701) 510 ktcr |= GTCR_MAN_MS|GTCR_ADV_MS; 511 PHY_WRITE(sc, MII_100T2CR, ktcr); 512 ktcr = PHY_READ(sc, MII_100T2CR); 513 DELAY(1000); 514 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; 515 if (sc->mii_flags & MIIF_DOPAUSE) 516 anar |= ANAR_FC| ANAR_X_PAUSE_ASYM; 517 518 PHY_WRITE(sc, MII_ANAR, anar); 519 DELAY(1000); 520 PHY_WRITE(sc, MII_BMCR, 521 BMCR_AUTOEN | BMCR_STARTNEG); 522 PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); 523 524 return (EJUSTRETURN); 525 } 526 527 void 528 brgphy_loop(struct mii_softc *sc) 529 { 530 u_int32_t bmsr; 531 int i; 532 533 PHY_WRITE(sc, MII_BMCR, BMCR_LOOP); 534 for (i = 0; i < 15000; i++) { 535 bmsr = PHY_READ(sc, MII_BMSR); 536 if (!(bmsr & BMSR_LINK)) 537 break; 538 DELAY(10); 539 } 540 } 541 542 static void 543 brgphy_5401_reset(struct mii_softc *sc) 544 { 545 546 mii_phy_reset(sc); 547 bcm5401_load_dspcode(sc); 548 } 549 550 static void 551 brgphy_5411_reset(struct mii_softc *sc) 552 { 553 554 mii_phy_reset(sc); 555 bcm5411_load_dspcode(sc); 556 } 557 558 559 static void 560 brgphy_5703_reset(struct mii_softc *sc) 561 { 562 563 mii_phy_reset(sc); 564 bcm5703_load_dspcode(sc); 565 } 566 567 static void 568 brgphy_5704_reset(struct mii_softc *sc) 569 { 570 571 mii_phy_reset(sc); 572 bcm5704_load_dspcode(sc); 573 } 574 575 /* 576 * Hardware bug workaround. Do nothing since after 577 * reset the 5705 PHY would get stuck in 10/100 MII mode. 578 */ 579 580 static void 581 brgphy_5705_reset(struct mii_softc *sc) 582 { 583 } 584 585 static void 586 brgphy_5750_reset(struct mii_softc *sc) 587 { 588 mii_phy_reset(sc); 589 bcm5750_load_dspcode(sc); 590 } 591 592 static void 593 brgphy_5755_reset(struct mii_softc *sc) 594 { 595 mii_phy_reset(sc); 596 bcm5755_load_dspcode(sc); 597 } 598 599 /* Turn off tap power management on 5401. */ 600 static void 601 bcm5401_load_dspcode(struct mii_softc *sc) 602 { 603 static const struct { 604 int reg; 605 uint16_t val; 606 } dspcode[] = { 607 { BRGPHY_MII_AUXCTL, 0x0c20 }, 608 { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 609 { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 610 { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 611 { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 612 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 613 { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 614 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 615 { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 616 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 617 { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 618 { 0, 0 }, 619 }; 620 int i; 621 622 for (i = 0; dspcode[i].reg != 0; i++) 623 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 624 delay(40); 625 } 626 627 static void 628 bcm5411_load_dspcode(struct mii_softc *sc) 629 { 630 static const struct { 631 int reg; 632 uint16_t val; 633 } dspcode[] = { 634 { 0x1c, 0x8c23 }, 635 { 0x1c, 0x8ca3 }, 636 { 0x1c, 0x8c23 }, 637 { 0, 0 }, 638 }; 639 int i; 640 641 for (i = 0; dspcode[i].reg != 0; i++) 642 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 643 } 644 645 static void 646 bcm5703_load_dspcode(struct mii_softc *sc) 647 { 648 static const struct { 649 int reg; 650 uint16_t val; 651 } dspcode[] = { 652 { BRGPHY_MII_AUXCTL, 0x0c00 }, 653 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 654 { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 655 { 0, 0 }, 656 }; 657 int i; 658 659 for (i = 0; dspcode[i].reg != 0; i++) 660 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 661 } 662 663 static void 664 bcm5704_load_dspcode(struct mii_softc *sc) 665 { 666 static const struct { 667 int reg; 668 uint16_t val; 669 } dspcode[] = { 670 { 0x1c, 0x8d68 }, 671 { 0x1c, 0x8d68 }, 672 { 0, 0 }, 673 }; 674 int i; 675 676 for (i = 0; dspcode[i].reg != 0; i++) 677 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 678 } 679 680 static void 681 bcm5750_load_dspcode(struct mii_softc *sc) 682 { 683 static const struct { 684 int reg; 685 uint16_t val; 686 } dspcode[] = { 687 { BRGPHY_MII_AUXCTL, 0x0c00 }, 688 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 689 { BRGPHY_MII_DSP_RW_PORT, 0x310b }, 690 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 691 { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, 692 { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, 693 { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, 694 { BRGPHY_MII_AUXCTL, 0x0400 }, 695 { 0, 0 }, 696 }; 697 int i; 698 699 for (i = 0; dspcode[i].reg != 0; i++) 700 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 701 } 702 703 static void 704 bcm5755_load_dspcode(struct mii_softc *sc) 705 { 706 static const struct { 707 int reg; 708 uint16_t val; 709 } dspcode[] = { 710 { BRGPHY_MII_AUXCTL, 0x0c00 }, 711 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 712 { BRGPHY_MII_DSP_RW_PORT, 0x010b }, 713 714 { BRGPHY_MII_AUXCTL, 0x0400 }, 715 { 0, 0 }, 716 }; 717 int i; 718 719 for (i = 0; dspcode[i].reg != 0; i++) 720 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 721 } 722