1 /* $NetBSD: brgphy.c,v 1.39 2008/05/04 17:06:09 xtraeme 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.39 2008/05/04 17:06:09 xtraeme 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 { 0, 0, 187 NULL }, 188 }; 189 190 static void bcm5401_load_dspcode(struct mii_softc *); 191 static void bcm5411_load_dspcode(struct mii_softc *); 192 static void bcm5703_load_dspcode(struct mii_softc *); 193 static void bcm5704_load_dspcode(struct mii_softc *); 194 static void bcm5750_load_dspcode(struct mii_softc *); 195 static void bcm5755_load_dspcode(struct mii_softc *); 196 197 static int 198 brgphymatch(struct device *parent, struct cfdata *match, 199 void *aux) 200 { 201 struct mii_attach_args *ma = aux; 202 203 if (mii_phy_match(ma, brgphys) != NULL) 204 return (10); 205 206 return (0); 207 } 208 209 static void 210 brgphyattach(struct device *parent, struct device *self, void *aux) 211 { 212 struct mii_softc *sc = device_private(self); 213 struct mii_attach_args *ma = aux; 214 struct mii_data *mii = ma->mii_data; 215 const struct mii_phydesc *mpd; 216 217 mpd = mii_phy_match(ma, brgphys); 218 aprint_naive(": Media interface\n"); 219 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 220 221 sc->mii_dev = self; 222 sc->mii_inst = mii->mii_instance; 223 sc->mii_phy = ma->mii_phyno; 224 sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 225 sc->mii_pdata = mii; 226 sc->mii_flags = ma->mii_flags; 227 sc->mii_anegticks = MII_ANEGTICKS; 228 229 switch (MII_MODEL(ma->mii_id2)) { 230 case MII_MODEL_BROADCOM_BCM5400: 231 sc->mii_funcs = &brgphy_5401_funcs; 232 aprint_normal_dev(self, "using BCM5401 DSP patch\n"); 233 break; 234 235 case MII_MODEL_BROADCOM_BCM5401: 236 if (MII_REV(ma->mii_id2) == 1 || MII_REV(ma->mii_id2) == 3) { 237 sc->mii_funcs = &brgphy_5401_funcs; 238 aprint_normal_dev(self, "using BCM5401 DSP patch\n"); 239 } else 240 sc->mii_funcs = &brgphy_funcs; 241 break; 242 243 case MII_MODEL_BROADCOM_BCM5411: 244 sc->mii_funcs = &brgphy_5411_funcs; 245 aprint_normal_dev(self, "using BCM5411 DSP patch\n"); 246 break; 247 248 #ifdef notyet /* unverified, untested */ 249 case MII_MODEL_BROADCOM_BCM5703: 250 sc->mii_funcs = &brgphy_5703_funcs; 251 aprint_normal_dev(self, "using BCM5703 DSP patch\n"); 252 break; 253 #endif 254 255 case MII_MODEL_BROADCOM_BCM5704: 256 sc->mii_funcs = &brgphy_5704_funcs; 257 aprint_normal_dev(self, "using BCM5704 DSP patch\n"); 258 break; 259 260 case MII_MODEL_BROADCOM_BCM5705: 261 sc->mii_funcs = &brgphy_5705_funcs; 262 break; 263 264 case MII_MODEL_BROADCOM_BCM5714: 265 case MII_MODEL_BROADCOM_BCM5780: 266 case MII_MODEL_BROADCOM_BCM5708C: 267 case MII_MODEL_BROADCOM_BCM5750: 268 case MII_MODEL_BROADCOM_BCM5752: 269 sc->mii_funcs = &brgphy_5750_funcs; 270 break; 271 272 case MII_MODEL_BROADCOM2_BCM5754: 273 case MII_MODEL_BROADCOM2_BCM5755: 274 sc->mii_funcs = &brgphy_5755_funcs; 275 break; 276 277 default: 278 sc->mii_funcs = &brgphy_funcs; 279 break; 280 } 281 282 PHY_RESET(sc); 283 284 sc->mii_capabilities = 285 PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 286 if (sc->mii_capabilities & BMSR_EXTSTAT) 287 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 288 289 aprint_normal_dev(self, ""); 290 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 291 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) 292 aprint_error("no media present"); 293 else 294 mii_phy_add_media(sc); 295 aprint_normal("\n"); 296 297 if (!pmf_device_register(self, NULL, mii_phy_resume)) 298 aprint_error_dev(self, "couldn't establish power handler\n"); 299 } 300 301 static int 302 brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 303 { 304 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 305 int reg, speed, gig; 306 307 switch (cmd) { 308 case MII_POLLSTAT: 309 /* 310 * If we're not polling our PHY instance, just return. 311 */ 312 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 313 return (0); 314 break; 315 316 case MII_MEDIACHG: 317 /* 318 * If the media indicates a different PHY instance, 319 * isolate ourselves. 320 */ 321 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 322 reg = PHY_READ(sc, MII_BMCR); 323 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 324 return (0); 325 } 326 327 /* 328 * If the interface is not up, don't do anything. 329 */ 330 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 331 break; 332 333 PHY_RESET(sc); /* XXX hardware bug work-around */ 334 335 switch (IFM_SUBTYPE(ife->ifm_media)) { 336 case IFM_AUTO: 337 (void) brgphy_mii_phy_auto(sc); 338 break; 339 case IFM_1000_T: 340 speed = BMCR_S1000; 341 goto setit; 342 case IFM_100_TX: 343 speed = BMCR_S100; 344 goto setit; 345 case IFM_10_T: 346 speed = BMCR_S10; 347 setit: 348 brgphy_loop(sc); 349 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 350 speed |= BMCR_FDX; 351 gig = GTCR_ADV_1000TFDX; 352 } else { 353 gig = GTCR_ADV_1000THDX; 354 } 355 356 PHY_WRITE(sc, MII_100T2CR, 0); 357 PHY_WRITE(sc, MII_BMCR, speed); 358 PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); 359 360 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) 361 break; 362 363 PHY_WRITE(sc, MII_100T2CR, gig); 364 PHY_WRITE(sc, MII_BMCR, 365 speed|BMCR_AUTOEN|BMCR_STARTNEG); 366 367 if (sc->mii_mpd_model != MII_MODEL_BROADCOM_BCM5701) 368 break; 369 370 if (mii->mii_media.ifm_media & IFM_ETH_MASTER) 371 gig |= GTCR_MAN_MS | GTCR_ADV_MS; 372 PHY_WRITE(sc, MII_100T2CR, gig); 373 break; 374 default: 375 return (EINVAL); 376 } 377 break; 378 379 case MII_TICK: 380 /* 381 * If we're not currently selected, just return. 382 */ 383 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 384 return (0); 385 386 if (mii_phy_tick(sc) == EJUSTRETURN) 387 return (0); 388 break; 389 390 case MII_DOWN: 391 mii_phy_down(sc); 392 return (0); 393 } 394 395 /* Update the media status. */ 396 mii_phy_status(sc); 397 398 /* 399 * Callback if something changed. Note that we need to poke the DSP on 400 * the Broadcom PHYs if the media changes. 401 */ 402 if (sc->mii_media_active != mii->mii_media_active || 403 sc->mii_media_status != mii->mii_media_status || 404 cmd == MII_MEDIACHG) { 405 mii_phy_update(sc, cmd); 406 if (sc->mii_funcs == &brgphy_5401_funcs) 407 bcm5401_load_dspcode(sc); 408 else if (sc->mii_funcs == &brgphy_5411_funcs) 409 bcm5411_load_dspcode(sc); 410 } 411 return (0); 412 } 413 414 static void 415 brgphy_status(struct mii_softc *sc) 416 { 417 struct mii_data *mii = sc->mii_pdata; 418 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 419 int bmcr, auxsts, gtsr; 420 421 mii->mii_media_status = IFM_AVALID; 422 mii->mii_media_active = IFM_ETHER; 423 424 auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS); 425 426 if (auxsts & BRGPHY_AUXSTS_LINK) 427 mii->mii_media_status |= IFM_ACTIVE; 428 429 bmcr = PHY_READ(sc, MII_BMCR); 430 if (bmcr & BMCR_ISO) { 431 mii->mii_media_active |= IFM_NONE; 432 mii->mii_media_status = 0; 433 return; 434 } 435 436 if (bmcr & BMCR_LOOP) 437 mii->mii_media_active |= IFM_LOOP; 438 439 if (bmcr & BMCR_AUTOEN) { 440 /* 441 * The media status bits are only valid of autonegotiation 442 * has completed (or it's disabled). 443 */ 444 if ((auxsts & BRGPHY_AUXSTS_ACOMP) == 0) { 445 /* Erg, still trying, I guess... */ 446 mii->mii_media_active |= IFM_NONE; 447 return; 448 } 449 450 switch (auxsts & BRGPHY_AUXSTS_AN_RES) { 451 case BRGPHY_RES_1000FD: 452 mii->mii_media_active |= IFM_1000_T|IFM_FDX; 453 gtsr = PHY_READ(sc, MII_100T2SR); 454 if (gtsr & GTSR_MS_RES) 455 mii->mii_media_active |= IFM_ETH_MASTER; 456 break; 457 458 case BRGPHY_RES_1000HD: 459 mii->mii_media_active |= IFM_1000_T; 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_100FD: 466 mii->mii_media_active |= IFM_100_TX|IFM_FDX; 467 break; 468 469 case BRGPHY_RES_100T4: 470 mii->mii_media_active |= IFM_100_T4; 471 break; 472 473 case BRGPHY_RES_100HD: 474 mii->mii_media_active |= IFM_100_TX; 475 break; 476 477 case BRGPHY_RES_10FD: 478 mii->mii_media_active |= IFM_10_T|IFM_FDX; 479 break; 480 481 case BRGPHY_RES_10HD: 482 mii->mii_media_active |= IFM_10_T; 483 break; 484 485 default: 486 mii->mii_media_active |= IFM_NONE; 487 mii->mii_media_status = 0; 488 } 489 if (mii->mii_media_active & IFM_FDX) 490 mii->mii_media_active |= mii_phy_flowstatus(sc); 491 } else 492 mii->mii_media_active = ife->ifm_media; 493 } 494 495 int 496 brgphy_mii_phy_auto(struct mii_softc *sc) 497 { 498 int anar, ktcr = 0; 499 500 brgphy_loop(sc); 501 PHY_RESET(sc); 502 ktcr = GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX; 503 if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701) 504 ktcr |= GTCR_MAN_MS|GTCR_ADV_MS; 505 PHY_WRITE(sc, MII_100T2CR, ktcr); 506 ktcr = PHY_READ(sc, MII_100T2CR); 507 DELAY(1000); 508 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; 509 if (sc->mii_flags & MIIF_DOPAUSE) 510 anar |= ANAR_FC| ANAR_X_PAUSE_ASYM; 511 512 PHY_WRITE(sc, MII_ANAR, anar); 513 DELAY(1000); 514 PHY_WRITE(sc, MII_BMCR, 515 BMCR_AUTOEN | BMCR_STARTNEG); 516 PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); 517 518 return (EJUSTRETURN); 519 } 520 521 void 522 brgphy_loop(struct mii_softc *sc) 523 { 524 u_int32_t bmsr; 525 int i; 526 527 PHY_WRITE(sc, MII_BMCR, BMCR_LOOP); 528 for (i = 0; i < 15000; i++) { 529 bmsr = PHY_READ(sc, MII_BMSR); 530 if (!(bmsr & BMSR_LINK)) 531 break; 532 DELAY(10); 533 } 534 } 535 536 static void 537 brgphy_5401_reset(struct mii_softc *sc) 538 { 539 540 mii_phy_reset(sc); 541 bcm5401_load_dspcode(sc); 542 } 543 544 static void 545 brgphy_5411_reset(struct mii_softc *sc) 546 { 547 548 mii_phy_reset(sc); 549 bcm5411_load_dspcode(sc); 550 } 551 552 553 static void 554 brgphy_5703_reset(struct mii_softc *sc) 555 { 556 557 mii_phy_reset(sc); 558 bcm5703_load_dspcode(sc); 559 } 560 561 static void 562 brgphy_5704_reset(struct mii_softc *sc) 563 { 564 565 mii_phy_reset(sc); 566 bcm5704_load_dspcode(sc); 567 } 568 569 /* 570 * Hardware bug workaround. Do nothing since after 571 * reset the 5705 PHY would get stuck in 10/100 MII mode. 572 */ 573 574 static void 575 brgphy_5705_reset(struct mii_softc *sc) 576 { 577 } 578 579 static void 580 brgphy_5750_reset(struct mii_softc *sc) 581 { 582 mii_phy_reset(sc); 583 bcm5750_load_dspcode(sc); 584 } 585 586 static void 587 brgphy_5755_reset(struct mii_softc *sc) 588 { 589 mii_phy_reset(sc); 590 bcm5755_load_dspcode(sc); 591 } 592 593 /* Turn off tap power management on 5401. */ 594 static void 595 bcm5401_load_dspcode(struct mii_softc *sc) 596 { 597 static const struct { 598 int reg; 599 uint16_t val; 600 } dspcode[] = { 601 { BRGPHY_MII_AUXCTL, 0x0c20 }, 602 { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, 603 { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, 604 { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, 605 { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, 606 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 607 { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, 608 { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, 609 { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, 610 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 611 { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, 612 { 0, 0 }, 613 }; 614 int i; 615 616 for (i = 0; dspcode[i].reg != 0; i++) 617 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 618 delay(40); 619 } 620 621 static void 622 bcm5411_load_dspcode(struct mii_softc *sc) 623 { 624 static const struct { 625 int reg; 626 uint16_t val; 627 } dspcode[] = { 628 { 0x1c, 0x8c23 }, 629 { 0x1c, 0x8ca3 }, 630 { 0x1c, 0x8c23 }, 631 { 0, 0 }, 632 }; 633 int i; 634 635 for (i = 0; dspcode[i].reg != 0; i++) 636 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 637 } 638 639 static void 640 bcm5703_load_dspcode(struct mii_softc *sc) 641 { 642 static const struct { 643 int reg; 644 uint16_t val; 645 } dspcode[] = { 646 { BRGPHY_MII_AUXCTL, 0x0c00 }, 647 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 648 { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, 649 { 0, 0 }, 650 }; 651 int i; 652 653 for (i = 0; dspcode[i].reg != 0; i++) 654 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 655 } 656 657 static void 658 bcm5704_load_dspcode(struct mii_softc *sc) 659 { 660 static const struct { 661 int reg; 662 uint16_t val; 663 } dspcode[] = { 664 { 0x1c, 0x8d68 }, 665 { 0x1c, 0x8d68 }, 666 { 0, 0 }, 667 }; 668 int i; 669 670 for (i = 0; dspcode[i].reg != 0; i++) 671 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 672 } 673 674 static void 675 bcm5750_load_dspcode(struct mii_softc *sc) 676 { 677 static const struct { 678 int reg; 679 uint16_t val; 680 } dspcode[] = { 681 { BRGPHY_MII_AUXCTL, 0x0c00 }, 682 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 683 { BRGPHY_MII_DSP_RW_PORT, 0x310b }, 684 { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, 685 { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, 686 { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, 687 { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, 688 { BRGPHY_MII_AUXCTL, 0x0400 }, 689 { 0, 0 }, 690 }; 691 int i; 692 693 for (i = 0; dspcode[i].reg != 0; i++) 694 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 695 } 696 697 static void 698 bcm5755_load_dspcode(struct mii_softc *sc) 699 { 700 static const struct { 701 int reg; 702 uint16_t val; 703 } dspcode[] = { 704 { BRGPHY_MII_AUXCTL, 0x0c00 }, 705 { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, 706 { BRGPHY_MII_DSP_RW_PORT, 0x010b }, 707 708 { BRGPHY_MII_AUXCTL, 0x0400 }, 709 { 0, 0 }, 710 }; 711 int i; 712 713 for (i = 0; dspcode[i].reg != 0; i++) 714 PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); 715 } 716