1 /* $NetBSD: brgphy.c,v 1.35 2007/12/09 20:28:02 jmcneill 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.35 2007/12/09 20:28:02 jmcneill 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 if (!pmf_device_register(self, NULL, mii_phy_resume)) 305 aprint_error_dev(self, "couldn't establish power handler\n"); 306 } 307 308 static int 309 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 310 { 311 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 312 int reg, speed, gig; 313 314 switch (cmd) { 315 case MII_POLLSTAT: 316 /* 317 * If we're not polling our PHY instance, just return. 318 */ 319 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 320 return (0); 321 break; 322 323 case MII_MEDIACHG: 324 /* 325 * If the media indicates a different PHY instance, 326 * isolate ourselves. 327 */ 328 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 329 reg = PHY_READ(sc, MII_BMCR); 330 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 331 return (0); 332 } 333 334 /* 335 * If the interface is not up, don't do anything. 336 */ 337 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 338 break; 339 340 PHY_RESET(sc); /* XXX hardware bug work-around */ 341 342 switch (IFM_SUBTYPE(ife->ifm_media)) { 343 case IFM_AUTO: 344 (void) brgphy_mii_phy_auto(sc); 345 break; 346 case IFM_1000_T: 347 speed = BMCR_S1000; 348 goto setit; 349 case IFM_100_TX: 350 speed = BMCR_S100; 351 goto setit; 352 case IFM_10_T: 353 speed = BMCR_S10; 354 setit: 355 brgphy_loop(sc); 356 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 357 speed |= BMCR_FDX; 358 gig = GTCR_ADV_1000TFDX; 359 } else { 360 gig = GTCR_ADV_1000THDX; 361 } 362 363 PHY_WRITE(sc, MII_100T2CR, 0); 364 PHY_WRITE(sc, MII_BMCR, speed); 365 PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); 366 367 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 368 break; 369 370 PHY_WRITE(sc, MII_100T2CR, gig); 371 PHY_WRITE(sc, MII_BMCR, 372 speed|BMCR_AUTOEN|BMCR_STARTNEG); 373 374 if (sc->mii_mpd_model != MII_MODEL_BROADCOM_BCM5701) 375 break; 376 377 if (mii->mii_media.ifm_media & IFM_ETH_MASTER) 378 gig |= GTCR_MAN_MS | GTCR_ADV_MS; 379 PHY_WRITE(sc, MII_100T2CR, gig); 380 break; 381 default: 382 return (EINVAL); 383 } 384 break; 385 386 case MII_TICK: 387 /* 388 * If we're not currently selected, just return. 389 */ 390 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 391 return (0); 392 393 if (mii_phy_tick(sc) == EJUSTRETURN) 394 return (0); 395 break; 396 397 case MII_DOWN: 398 mii_phy_down(sc); 399 return (0); 400 } 401 402 /* Update the media status. */ 403 mii_phy_status(sc); 404 405 /* 406 * Callback if something changed. Note that we need to poke the DSP on 407 * the Broadcom PHYs if the media changes. 408 */ 409 if (sc->mii_media_active != mii->mii_media_active || 410 sc->mii_media_status != mii->mii_media_status || 411 cmd == MII_MEDIACHG) { 412 mii_phy_update(sc, cmd); 413 if (sc->mii_funcs == &brgphy_5401_funcs) 414 bcm5401_load_dspcode(sc); 415 else if (sc->mii_funcs == &brgphy_5411_funcs) 416 bcm5411_load_dspcode(sc); 417 } 418 return (0); 419 } 420 421 static void 422 brgphy_status(struct mii_softc *sc) 423 { 424 struct mii_data *mii = sc->mii_pdata; 425 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 426 int bmcr, auxsts, gtsr; 427 428 mii->mii_media_status = IFM_AVALID; 429 mii->mii_media_active = IFM_ETHER; 430 431 auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS); 432 433 if (auxsts & BRGPHY_AUXSTS_LINK) 434 mii->mii_media_status |= IFM_ACTIVE; 435 436 bmcr = PHY_READ(sc, MII_BMCR); 437 if (bmcr & BMCR_ISO) { 438 mii->mii_media_active |= IFM_NONE; 439 mii->mii_media_status = 0; 440 return; 441 } 442 443 if (bmcr & BMCR_LOOP) 444 mii->mii_media_active |= IFM_LOOP; 445 446 if (bmcr & BMCR_AUTOEN) { 447 /* 448 * The media status bits are only valid of autonegotiation 449 * has completed (or it's disabled). 450 */ 451 if ((auxsts & BRGPHY_AUXSTS_ACOMP) == 0) { 452 /* Erg, still trying, I guess... */ 453 mii->mii_media_active |= IFM_NONE; 454 return; 455 } 456 457 switch (auxsts & BRGPHY_AUXSTS_AN_RES) { 458 case BRGPHY_RES_1000FD: 459 mii->mii_media_active |= IFM_1000_T|IFM_FDX; 460 gtsr = PHY_READ(sc, MII_100T2SR); 461 if (gtsr & GTSR_MS_RES) 462 mii->mii_media_active |= IFM_ETH_MASTER; 463 break; 464 465 case BRGPHY_RES_1000HD: 466 mii->mii_media_active |= IFM_1000_T; 467 gtsr = PHY_READ(sc, MII_100T2SR); 468 if (gtsr & GTSR_MS_RES) 469 mii->mii_media_active |= IFM_ETH_MASTER; 470 break; 471 472 case BRGPHY_RES_100FD: 473 mii->mii_media_active |= IFM_100_TX|IFM_FDX; 474 break; 475 476 case BRGPHY_RES_100T4: 477 mii->mii_media_active |= IFM_100_T4; 478 break; 479 480 case BRGPHY_RES_100HD: 481 mii->mii_media_active |= IFM_100_TX; 482 break; 483 484 case BRGPHY_RES_10FD: 485 mii->mii_media_active |= IFM_10_T|IFM_FDX; 486 break; 487 488 case BRGPHY_RES_10HD: 489 mii->mii_media_active |= IFM_10_T; 490 break; 491 492 default: 493 mii->mii_media_active |= IFM_NONE; 494 mii->mii_media_status = 0; 495 } 496 if (mii->mii_media_active & IFM_FDX) 497 mii->mii_media_active |= mii_phy_flowstatus(sc); 498 } else 499 mii->mii_media_active = ife->ifm_media; 500 } 501 502 int 503 brgphy_mii_phy_auto(struct mii_softc *sc) 504 { 505 int anar, ktcr = 0; 506 507 brgphy_loop(sc); 508 PHY_RESET(sc); 509 ktcr = GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX; 510 if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701) 511 ktcr |= GTCR_MAN_MS|GTCR_ADV_MS; 512 PHY_WRITE(sc, MII_100T2CR, ktcr); 513 ktcr = PHY_READ(sc, MII_100T2CR); 514 DELAY(1000); 515 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; 516 if (sc->mii_flags & MIIF_DOPAUSE) 517 anar |= ANAR_FC| ANAR_X_PAUSE_ASYM; 518 519 PHY_WRITE(sc, MII_ANAR, anar); 520 DELAY(1000); 521 PHY_WRITE(sc, MII_BMCR, 522 BMCR_AUTOEN | BMCR_STARTNEG); 523 PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); 524 525 return (EJUSTRETURN); 526 } 527 528 void 529 brgphy_loop(struct mii_softc *sc) 530 { 531 u_int32_t bmsr; 532 int i; 533 534 PHY_WRITE(sc, MII_BMCR, BMCR_LOOP); 535 for (i = 0; i < 15000; i++) { 536 bmsr = PHY_READ(sc, MII_BMSR); 537 if (!(bmsr & BMSR_LINK)) 538 break; 539 DELAY(10); 540 } 541 } 542 543 static void 544 brgphy_5401_reset(struct mii_softc *sc) 545 { 546 547 mii_phy_reset(sc); 548 bcm5401_load_dspcode(sc); 549 } 550 551 static void 552 brgphy_5411_reset(struct mii_softc *sc) 553 { 554 555 mii_phy_reset(sc); 556 bcm5411_load_dspcode(sc); 557 } 558 559 560 static void 561 brgphy_5703_reset(struct mii_softc *sc) 562 { 563 564 mii_phy_reset(sc); 565 bcm5703_load_dspcode(sc); 566 } 567 568 static void 569 brgphy_5704_reset(struct mii_softc *sc) 570 { 571 572 mii_phy_reset(sc); 573 bcm5704_load_dspcode(sc); 574 } 575 576 /* 577 * Hardware bug workaround. Do nothing since after 578 * reset the 5705 PHY would get stuck in 10/100 MII mode. 579 */ 580 581 static void 582 brgphy_5705_reset(struct mii_softc *sc) 583 { 584 } 585 586 static void 587 brgphy_5750_reset(struct mii_softc *sc) 588 { 589 mii_phy_reset(sc); 590 bcm5750_load_dspcode(sc); 591 } 592 593 static void 594 brgphy_5755_reset(struct mii_softc *sc) 595 { 596 mii_phy_reset(sc); 597 bcm5755_load_dspcode(sc); 598 } 599 600 /* Turn off tap power management on 5401. */ 601 static void 602 bcm5401_load_dspcode(struct mii_softc *sc) 603 { 604 static const struct { 605 int reg; 606 uint16_t val; 607 } dspcode[] = { 608 { BRGPHY_MII_AUXCTL, 0x0c20 }, 609 { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 610 { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 611 { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 612 { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 613 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 614 { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 615 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 616 { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 617 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 618 { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 619 { 0, 0 }, 620 }; 621 int i; 622 623 for (i = 0; dspcode[i].reg != 0; i++) 624 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 625 delay(40); 626 } 627 628 static void 629 bcm5411_load_dspcode(struct mii_softc *sc) 630 { 631 static const struct { 632 int reg; 633 uint16_t val; 634 } dspcode[] = { 635 { 0x1c, 0x8c23 }, 636 { 0x1c, 0x8ca3 }, 637 { 0x1c, 0x8c23 }, 638 { 0, 0 }, 639 }; 640 int i; 641 642 for (i = 0; dspcode[i].reg != 0; i++) 643 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 644 } 645 646 static void 647 bcm5703_load_dspcode(struct mii_softc *sc) 648 { 649 static const struct { 650 int reg; 651 uint16_t val; 652 } dspcode[] = { 653 { BRGPHY_MII_AUXCTL, 0x0c00 }, 654 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 655 { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 656 { 0, 0 }, 657 }; 658 int i; 659 660 for (i = 0; dspcode[i].reg != 0; i++) 661 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 662 } 663 664 static void 665 bcm5704_load_dspcode(struct mii_softc *sc) 666 { 667 static const struct { 668 int reg; 669 uint16_t val; 670 } dspcode[] = { 671 { 0x1c, 0x8d68 }, 672 { 0x1c, 0x8d68 }, 673 { 0, 0 }, 674 }; 675 int i; 676 677 for (i = 0; dspcode[i].reg != 0; i++) 678 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 679 } 680 681 static void 682 bcm5750_load_dspcode(struct mii_softc *sc) 683 { 684 static const struct { 685 int reg; 686 uint16_t val; 687 } dspcode[] = { 688 { BRGPHY_MII_AUXCTL, 0x0c00 }, 689 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 690 { BRGPHY_MII_DSP_RW_PORT, 0x310b }, 691 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 692 { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, 693 { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, 694 { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, 695 { BRGPHY_MII_AUXCTL, 0x0400 }, 696 { 0, 0 }, 697 }; 698 int i; 699 700 for (i = 0; dspcode[i].reg != 0; i++) 701 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 702 } 703 704 static void 705 bcm5755_load_dspcode(struct mii_softc *sc) 706 { 707 static const struct { 708 int reg; 709 uint16_t val; 710 } dspcode[] = { 711 { BRGPHY_MII_AUXCTL, 0x0c00 }, 712 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 713 { BRGPHY_MII_DSP_RW_PORT, 0x010b }, 714 715 { BRGPHY_MII_AUXCTL, 0x0400 }, 716 { 0, 0 }, 717 }; 718 int i; 719 720 for (i = 0; dspcode[i].reg != 0; i++) 721 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 722 } 723