1 /* $FreeBSD: src/sys/dev/mii/e1000phy.c,v 1.18 2006/12/11 11:09:48 yongari Exp $ */ 2 /* $DragonFly: src/sys/dev/netif/mii_layer/e1000phy.c,v 1.12 2008/07/22 10:59:16 sephe Exp $ */ 3 /* $OpenBSD: eephy.c,v 1.26 2006/06/08 00:27:12 brad Exp $ */ 4 /* 5 * Principal Author: Parag Patel 6 * Copyright (c) 2001 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice unmodified, this list of conditions, and the following 14 * disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * Additonal Copyright (c) 2001 by Traakan Software under same licence. 32 * Secondary Author: Matthew Jacob 33 */ 34 35 /* 36 * driver for the Marvell 88E1000 series external 1000/100/10-BT PHY. 37 */ 38 39 /* 40 * Support added for the Marvell 88E1011 (Alaska) 1000/100/10baseT and 41 * 1000baseSX PHY. 42 * Nathan Binkert <nate@openbsd.org> 43 * Jung-uk Kim <jkim@niksun.com> 44 */ 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/socket.h> 50 #include <sys/bus.h> 51 52 #include <net/if.h> 53 #include <net/if_media.h> 54 55 #include "mii.h" 56 #include "miivar.h" 57 #include "miidevs.h" 58 59 #include "e1000phyreg.h" 60 61 #include "miibus_if.h" 62 63 static int e1000phy_probe(device_t); 64 static int e1000phy_attach(device_t); 65 static int e1000phy_service(struct mii_softc *, struct mii_data *, int); 66 static void e1000phy_status(struct mii_softc *); 67 static void e1000phy_mii_phy_auto(struct mii_softc *); 68 static void e1000phy_reset(struct mii_softc *); 69 70 static device_method_t e1000phy_methods[] = { 71 /* device interface */ 72 DEVMETHOD(device_probe, e1000phy_probe), 73 DEVMETHOD(device_attach, e1000phy_attach), 74 DEVMETHOD(device_detach, ukphy_detach), 75 DEVMETHOD(device_shutdown, bus_generic_shutdown), 76 { 0, 0 } 77 }; 78 79 static const struct mii_phydesc e1000phys[] = { 80 MII_PHYDESC(xxMARVELL, E1000_2), 81 MII_PHYDESC(xxMARVELL, E1000_3), 82 MII_PHYDESC(xxMARVELL, E1000_5), 83 MII_PHYDESC(xxMARVELL, E1111), 84 MII_PHYDESC(MARVELL, E1000), 85 MII_PHYDESC(MARVELL, E1011), 86 MII_PHYDESC(MARVELL, E1000_3), 87 MII_PHYDESC(MARVELL, E1000_4), 88 MII_PHYDESC(MARVELL, E1000_5), 89 MII_PHYDESC(MARVELL, E1000_6), 90 MII_PHYDESC(MARVELL, E3082), 91 MII_PHYDESC(MARVELL, E1112), 92 MII_PHYDESC(MARVELL, E1149), 93 MII_PHYDESC(MARVELL, E1111), 94 MII_PHYDESC(MARVELL, E1116), 95 MII_PHYDESC(MARVELL, E1118), 96 MII_PHYDESC_NULL 97 }; 98 99 static devclass_t e1000phy_devclass; 100 101 static driver_t e1000phy_driver = { 102 "e1000phy", 103 e1000phy_methods, 104 sizeof(struct mii_softc) 105 }; 106 DRIVER_MODULE(e1000phy, miibus, e1000phy_driver, e1000phy_devclass, 0, 0); 107 108 static int 109 e1000phy_probe(device_t dev) 110 { 111 struct mii_attach_args *ma = device_get_ivars(dev); 112 const struct mii_phydesc *mpd; 113 114 mpd = mii_phy_match(ma, e1000phys); 115 if (mpd != NULL) { 116 device_set_desc(dev, mpd->mpd_name); 117 return 0; 118 } 119 return (ENXIO); 120 } 121 122 static int 123 e1000phy_attach(device_t dev) 124 { 125 struct mii_softc *sc; 126 struct mii_attach_args *ma; 127 struct mii_data *mii; 128 const char *sep = ""; 129 int fast_ether = 0; 130 131 sc = device_get_softc(dev); 132 ma = device_get_ivars(dev); 133 mii_softc_init(sc, ma); 134 sc->mii_dev = device_get_parent(dev); 135 mii = device_get_softc(sc->mii_dev); 136 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 137 138 sc->mii_inst = mii->mii_instance; 139 sc->mii_service = e1000phy_service; 140 sc->mii_reset = e1000phy_reset; 141 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 142 sc->mii_pdata = mii; 143 144 sc->mii_flags |= MIIF_NOISOLATE; 145 146 switch (sc->mii_model) { 147 case MII_MODEL_MARVELL_E1011: 148 case MII_MODEL_MARVELL_E1112: 149 if (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK) 150 sc->mii_flags |= MIIF_HAVEFIBER; 151 break; 152 case MII_MODEL_MARVELL_E3082: 153 /* 88E3082 10/100 Fast Ethernet PHY. */ 154 sc->mii_anegticks = MII_ANEGTICKS; 155 fast_ether = 1; 156 break; 157 } 158 159 mii->mii_instance++; 160 161 e1000phy_reset(sc); 162 163 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 164 #define PRINT(s) kprintf("%s%s", sep, s); sep = ", " 165 166 device_printf(dev, "%s", ""); 167 168 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 169 E1000_CR_ISOLATE); 170 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 171 if (!fast_ether) { 172 /* 173 * 1000T-simplex not supported; driver must ignore 174 * this entry, but it must be present in order to 175 * manually set full-duplex. 176 */ 177 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, 178 sc->mii_inst), E1000_CR_SPEED_1000); 179 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, 180 sc->mii_inst), 181 E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX); 182 PRINT("1000baseT-FDX"); 183 } 184 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), 185 E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX); 186 PRINT("100baseTX-FDX"); 187 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), 188 E1000_CR_SPEED_100); 189 PRINT("100baseTX"); 190 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), 191 E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX); 192 PRINT("10baseTX-FDX"); 193 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 194 E1000_CR_SPEED_10); 195 PRINT("10baseTX"); 196 } else { 197 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst), 198 E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX); 199 PRINT("1000baseSX-FDX"); 200 } 201 202 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); 203 PRINT("auto\n"); 204 205 #undef ADD 206 #undef PRINT 207 208 MIIBUS_MEDIAINIT(sc->mii_dev); 209 return(0); 210 } 211 212 static void 213 e1000phy_reset(struct mii_softc *sc) 214 { 215 uint16_t reg; 216 217 reg = PHY_READ(sc, E1000_SCR); 218 if ((sc->mii_flags & MIIF_HAVEFIBER) != 0) { 219 reg &= ~E1000_SCR_AUTO_X_MODE; 220 PHY_WRITE(sc, E1000_SCR, reg); 221 if (sc->mii_model == MII_MODEL_MARVELL_E1112) { 222 /* Select 1000BASE-X only mode. */ 223 PHY_WRITE(sc, E1000_EADR, 2); 224 reg = PHY_READ(sc, E1000_SCR); 225 reg &= ~E1000_SCR_MODE_MASK; 226 reg |= E1000_SCR_MODE_1000BX; 227 PHY_WRITE(sc, E1000_SCR, reg); 228 PHY_WRITE(sc, E1000_EADR, 1); 229 } 230 } else { 231 switch (sc->mii_model) { 232 case MII_MODEL_MARVELL_E1111: 233 case MII_MODEL_MARVELL_E1112: 234 case MII_MODEL_MARVELL_E1116: 235 case MII_MODEL_MARVELL_E1118: 236 case MII_MODEL_MARVELL_E1149: 237 /* Disable energy detect mode. */ 238 reg &= ~E1000_SCR_EN_DETECT_MASK; 239 reg |= E1000_SCR_AUTO_X_MODE; 240 break; 241 case MII_MODEL_MARVELL_E3082: 242 reg |= (E1000_SCR_AUTO_X_MODE >> 1); 243 break; 244 default: 245 reg &= ~E1000_SCR_AUTO_X_MODE; 246 break; 247 } 248 /* Enable CRS on TX. */ 249 reg |= E1000_SCR_ASSERT_CRS_ON_TX; 250 /* Auto correction for reversed cable polarity. */ 251 reg &= ~E1000_SCR_POLARITY_REVERSAL; 252 PHY_WRITE(sc, E1000_SCR, reg); 253 } 254 255 switch (MII_MODEL(sc->mii_model)) { 256 case MII_MODEL_MARVELL_E3082: 257 case MII_MODEL_MARVELL_E1112: 258 case MII_MODEL_MARVELL_E1116: 259 case MII_MODEL_MARVELL_E1118: 260 case MII_MODEL_MARVELL_E1149: 261 break; 262 default: 263 /* Force TX_CLK to 25MHz clock. */ 264 reg = PHY_READ(sc, E1000_ESCR); 265 reg |= E1000_ESCR_TX_CLK_25; 266 PHY_WRITE(sc, E1000_ESCR, reg); 267 break; 268 } 269 270 /* Reset the PHY so all changes take effect. */ 271 reg = PHY_READ(sc, E1000_CR); 272 reg |= E1000_CR_RESET; 273 PHY_WRITE(sc, E1000_CR, reg); 274 } 275 276 static int 277 e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 278 { 279 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 280 uint16_t speed, gig; 281 int reg; 282 283 switch (cmd) { 284 case MII_POLLSTAT: 285 /* 286 * If we're not polling our PHY instance, just return. 287 */ 288 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 289 return (0); 290 break; 291 292 case MII_MEDIACHG: 293 /* 294 * If the media indicates a different PHY instance, 295 * isolate ourselves. 296 */ 297 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 298 reg = PHY_READ(sc, E1000_CR); 299 PHY_WRITE(sc, E1000_CR, reg | E1000_CR_ISOLATE); 300 return (0); 301 } 302 303 /* 304 * If the interface is not up, don't do anything. 305 */ 306 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 307 break; 308 309 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { 310 e1000phy_mii_phy_auto(sc); 311 break; 312 } 313 314 speed = 0; 315 switch (IFM_SUBTYPE(ife->ifm_media)) { 316 case IFM_1000_T: 317 if (sc->mii_model == MII_MODEL_MARVELL_E3082) 318 return (EINVAL); 319 speed = E1000_CR_SPEED_1000; 320 break; 321 case IFM_1000_SX: 322 if (sc->mii_model == MII_MODEL_MARVELL_E3082) 323 return (EINVAL); 324 speed = E1000_CR_SPEED_1000; 325 break; 326 case IFM_100_TX: 327 speed = E1000_CR_SPEED_100; 328 break; 329 case IFM_10_T: 330 speed = E1000_CR_SPEED_10; 331 break; 332 case IFM_NONE: 333 reg = PHY_READ(sc, E1000_CR); 334 PHY_WRITE(sc, E1000_CR, 335 reg | E1000_CR_ISOLATE | E1000_CR_POWER_DOWN); 336 goto done; 337 default: 338 return (EINVAL); 339 } 340 341 if (((ife->ifm_media & IFM_GMASK) & IFM_FDX) != 0) { 342 speed |= E1000_CR_FULL_DUPLEX; 343 gig = E1000_1GCR_1000T_FD; 344 } else { 345 gig = E1000_1GCR_1000T; 346 } 347 348 reg = PHY_READ(sc, E1000_CR); 349 reg &= ~E1000_CR_AUTO_NEG_ENABLE; 350 PHY_WRITE(sc, E1000_CR, reg | E1000_CR_RESET); 351 352 /* 353 * When setting the link manually, one side must 354 * be the master and the other the slave. However 355 * ifmedia doesn't give us a good way to specify 356 * this, so we fake it by using one of the LINK 357 * flags. If LINK0 is set, we program the PHY to 358 * be a master, otherwise it's a slave. 359 */ 360 if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T || 361 IFM_SUBTYPE(ife->ifm_media) == IFM_1000_SX) { 362 if (mii->mii_ifp->if_flags & IFF_LINK0) { 363 PHY_WRITE(sc, E1000_1GCR, gig | 364 E1000_1GCR_MS_ENABLE | E1000_1GCR_MS_VALUE); 365 } else { 366 PHY_WRITE(sc, E1000_1GCR, gig | 367 E1000_1GCR_MS_ENABLE); 368 } 369 } else { 370 if (sc->mii_model != MII_MODEL_MARVELL_E3082) 371 PHY_WRITE(sc, E1000_1GCR, 0); 372 } 373 PHY_WRITE(sc, E1000_AR, E1000_AR_SELECTOR_FIELD); 374 PHY_WRITE(sc, E1000_CR, speed | E1000_CR_RESET); 375 done: 376 break; 377 378 case MII_TICK: 379 /* 380 * If we're not currently selected, just return. 381 */ 382 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 383 return (0); 384 385 /* 386 * Is the interface even up? 387 */ 388 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 389 return (0); 390 391 /* 392 * Only used for autonegotiation. 393 */ 394 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 395 break; 396 397 /* 398 * Check to see if we have link. If we do, we don't 399 * need to restart the autonegotiation process. Read 400 * the BMSR twice in case it's latched. 401 */ 402 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 403 if (reg & BMSR_LINK) { 404 sc->mii_ticks = 0; 405 break; 406 } 407 408 /* 409 * Only retry autonegotiation every mii_anegticks seconds. 410 */ 411 if (++sc->mii_ticks <= sc->mii_anegticks) 412 return (0); 413 sc->mii_ticks = 0; 414 415 e1000phy_reset(sc); 416 e1000phy_mii_phy_auto(sc); 417 break; 418 } 419 420 /* Update the media status. */ 421 e1000phy_status(sc); 422 423 /* Callback if something changed. */ 424 mii_phy_update(sc, cmd); 425 return (0); 426 } 427 428 static void 429 e1000phy_status(struct mii_softc *sc) 430 { 431 struct mii_data *mii = sc->mii_pdata; 432 int bmsr, bmcr, esr, gsr, ssr, isr, ar, lpar; 433 434 mii->mii_media_status = IFM_AVALID; 435 mii->mii_media_active = IFM_ETHER; 436 437 bmsr = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR); 438 esr = PHY_READ(sc, E1000_ESR); 439 bmcr = PHY_READ(sc, E1000_CR); 440 ssr = PHY_READ(sc, E1000_SSR); 441 isr = PHY_READ(sc, E1000_ISR); 442 ar = PHY_READ(sc, E1000_AR); 443 lpar = PHY_READ(sc, E1000_LPAR); 444 445 if (bmsr & E1000_SR_LINK_STATUS) 446 mii->mii_media_status |= IFM_ACTIVE; 447 448 if (bmcr & E1000_CR_LOOPBACK) 449 mii->mii_media_active |= IFM_LOOP; 450 451 if (((bmcr & E1000_CR_AUTO_NEG_ENABLE) != 0 && 452 (bmsr & E1000_SR_AUTO_NEG_COMPLETE) == 0) || 453 (ssr & E1000_SSR_LINK) == 0 || 454 (ssr & E1000_SSR_SPD_DPLX_RESOLVED) == 0) { 455 /* Erg, still trying, I guess... */ 456 mii->mii_media_active |= IFM_NONE; 457 return; 458 } 459 460 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 461 if (ssr & E1000_SSR_1000MBS) 462 mii->mii_media_active |= IFM_1000_T; 463 else if (ssr & E1000_SSR_100MBS) 464 mii->mii_media_active |= IFM_100_TX; 465 else 466 mii->mii_media_active |= IFM_10_T; 467 } else { 468 if (ssr & E1000_SSR_1000MBS) 469 mii->mii_media_active |= IFM_1000_SX; 470 } 471 472 if (ssr & E1000_SSR_DUPLEX) 473 mii->mii_media_active |= IFM_FDX; 474 else 475 mii->mii_media_active |= IFM_HDX; 476 477 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 478 /* FLAG0==rx-flow-control FLAG1==tx-flow-control */ 479 if ((ar & E1000_AR_PAUSE) && (lpar & E1000_LPAR_PAUSE)) { 480 mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1; 481 } else if (!(ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) && 482 (lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) { 483 mii->mii_media_active |= IFM_FLAG1; 484 } else if ((ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) && 485 !(lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) { 486 mii->mii_media_active |= IFM_FLAG0; 487 } 488 } 489 490 /* FLAG2 : local PHY resolved to MASTER */ 491 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || 492 IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) { 493 PHY_READ(sc, E1000_1GSR); 494 gsr = PHY_READ(sc, E1000_1GSR); 495 if ((gsr & E1000_1GSR_MS_CONFIG_RES) != 0) 496 mii->mii_media_active |= IFM_FLAG2; 497 } 498 } 499 500 static void 501 e1000phy_mii_phy_auto(struct mii_softc *sc) 502 { 503 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 504 PHY_WRITE(sc, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD | 505 E1000_AR_100TX | E1000_AR_100TX_FD | 506 E1000_AR_PAUSE | E1000_AR_ASM_DIR); 507 } else { 508 PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD | E1000_FA_1000X | 509 E1000_FA_SYM_PAUSE | E1000_FA_ASYM_PAUSE); 510 } 511 if (sc->mii_model != MII_MODEL_MARVELL_E3082) { 512 PHY_WRITE(sc, E1000_1GCR, 513 E1000_1GCR_1000T_FD | E1000_1GCR_1000T); 514 } 515 PHY_WRITE(sc, E1000_CR, 516 E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG); 517 } 518