1 /*- 2 * Principal Author: Parag Patel 3 * Copyright (c) 2001 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice unmodified, this list of conditions, and the following 11 * disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * Additonal Copyright (c) 2001 by Traakan Software under same licence. 29 * Secondary Author: Matthew Jacob 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 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/10baseTX 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/module.h> 50 #include <sys/socket.h> 51 #include <sys/bus.h> 52 53 54 #include <net/if.h> 55 #include <net/if_media.h> 56 57 #include <dev/mii/mii.h> 58 #include <dev/mii/miivar.h> 59 #include "miidevs.h" 60 61 #include <dev/mii/e1000phyreg.h> 62 63 #include "miibus_if.h" 64 65 static int e1000phy_probe(device_t); 66 static int e1000phy_attach(device_t); 67 68 static device_method_t e1000phy_methods[] = { 69 /* device interface */ 70 DEVMETHOD(device_probe, e1000phy_probe), 71 DEVMETHOD(device_attach, e1000phy_attach), 72 DEVMETHOD(device_detach, mii_phy_detach), 73 DEVMETHOD(device_shutdown, bus_generic_shutdown), 74 { 0, 0 } 75 }; 76 77 static devclass_t e1000phy_devclass; 78 static driver_t e1000phy_driver = { 79 "e1000phy", e1000phy_methods, sizeof (struct mii_softc) 80 }; 81 DRIVER_MODULE(e1000phy, miibus, e1000phy_driver, e1000phy_devclass, 0, 0); 82 83 static int e1000phy_service(struct mii_softc *, struct mii_data *, int); 84 static void e1000phy_status(struct mii_softc *); 85 static void e1000phy_reset(struct mii_softc *); 86 static int e1000phy_mii_phy_auto(struct mii_softc *); 87 88 static int e1000phy_debug = 0; 89 90 static int 91 e1000phy_probe(device_t dev) 92 { 93 struct mii_attach_args *ma; 94 u_int32_t id; 95 96 ma = device_get_ivars(dev); 97 id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK; 98 if (id != E1000_ID_88E1000 99 && id != E1000_ID_88E1000S 100 && id != E1000_ID_88E1011) { 101 return ENXIO; 102 } 103 104 device_set_desc(dev, MII_STR_MARVELL_E1000); 105 return BUS_PROBE_DEFAULT; 106 } 107 108 static int 109 e1000phy_attach(device_t dev) 110 { 111 struct mii_softc *sc; 112 struct mii_attach_args *ma; 113 struct mii_data *mii; 114 u_int32_t id; 115 116 getenv_int("e1000phy_debug", &e1000phy_debug); 117 118 sc = device_get_softc(dev); 119 ma = device_get_ivars(dev); 120 sc->mii_dev = device_get_parent(dev); 121 mii = device_get_softc(sc->mii_dev); 122 LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 123 124 sc->mii_inst = mii->mii_instance; 125 sc->mii_phy = ma->mii_phyno; 126 sc->mii_service = e1000phy_service; 127 sc->mii_pdata = mii; 128 sc->mii_flags |= MIIF_NOISOLATE; 129 130 id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK; 131 if (id == E1000_ID_88E1011 132 && (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK)) 133 sc->mii_flags |= MIIF_HAVEFIBER; 134 mii->mii_instance++; 135 e1000phy_reset(sc); 136 137 device_printf(dev, " "); 138 139 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 140 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 141 #if 0 142 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 143 E1000_CR_ISOLATE); 144 #endif 145 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 146 E1000_CR_SPEED_10); 147 printf("10baseT, "); 148 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), 149 E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX); 150 printf("10baseT-FDX, "); 151 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), 152 E1000_CR_SPEED_100); 153 printf("100baseTX, "); 154 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), 155 E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX); 156 printf("100baseTX-FDX, "); 157 /* 158 * 1000BT-simplex not supported; driver must ignore this entry, 159 * but it must be present in order to manually set full-duplex. 160 */ 161 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), 162 E1000_CR_SPEED_1000); 163 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 164 E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX); 165 printf("1000baseTX-FDX, "); 166 } else { 167 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst), 168 E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX); 169 printf("1000baseSX-FDX, "); 170 } 171 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); 172 printf("auto\n"); 173 #undef ADD 174 175 MIIBUS_MEDIAINIT(sc->mii_dev); 176 return(0); 177 } 178 179 static void 180 e1000phy_reset(struct mii_softc *sc) 181 { 182 u_int32_t reg; 183 int i; 184 185 /* initialize custom E1000 registers to magic values */ 186 reg = PHY_READ(sc, E1000_SCR); 187 reg &= ~E1000_SCR_AUTO_X_MODE; 188 PHY_WRITE(sc, E1000_SCR, reg); 189 190 /* normal PHY reset */ 191 /*mii_phy_reset(sc);*/ 192 reg = PHY_READ(sc, E1000_CR); 193 reg |= E1000_CR_RESET; 194 PHY_WRITE(sc, E1000_CR, reg); 195 196 for (i = 0; i < 500; i++) { 197 DELAY(1); 198 reg = PHY_READ(sc, E1000_CR); 199 if (!(reg & E1000_CR_RESET)) 200 break; 201 } 202 203 /* set more custom E1000 registers to magic values */ 204 reg = PHY_READ(sc, E1000_SCR); 205 reg |= E1000_SCR_ASSERT_CRS_ON_TX; 206 PHY_WRITE(sc, E1000_SCR, reg); 207 208 reg = PHY_READ(sc, E1000_ESCR); 209 reg |= E1000_ESCR_TX_CLK_25; 210 PHY_WRITE(sc, E1000_ESCR, reg); 211 212 /* even more magic to reset DSP? */ 213 PHY_WRITE(sc, 29, 0x1d); 214 PHY_WRITE(sc, 30, 0xc1); 215 PHY_WRITE(sc, 30, 0x00); 216 } 217 218 static int 219 e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 220 { 221 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 222 int reg; 223 224 switch (cmd) { 225 case MII_POLLSTAT: 226 /* 227 * If we're not polling our PHY instance, just return. 228 */ 229 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 230 return (0); 231 break; 232 233 case MII_MEDIACHG: 234 /* 235 * If the media indicates a different PHY instance, 236 * isolate ourselves. 237 */ 238 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 239 reg = PHY_READ(sc, E1000_CR); 240 PHY_WRITE(sc, E1000_CR, reg | E1000_CR_ISOLATE); 241 return (0); 242 } 243 244 /* 245 * If the interface is not up, don't do anything. 246 */ 247 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) { 248 break; 249 } 250 251 switch (IFM_SUBTYPE(ife->ifm_media)) { 252 case IFM_AUTO: 253 e1000phy_reset(sc); 254 (void)e1000phy_mii_phy_auto(sc); 255 break; 256 257 case IFM_1000_T: 258 e1000phy_reset(sc); 259 260 /* TODO - any other way to force 1000BT? */ 261 (void)e1000phy_mii_phy_auto(sc); 262 break; 263 264 case IFM_1000_SX: 265 e1000phy_reset(sc); 266 267 PHY_WRITE(sc, E1000_CR, 268 E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_1000); 269 PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD); 270 break; 271 272 case IFM_100_TX: 273 e1000phy_reset(sc); 274 275 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 276 PHY_WRITE(sc, E1000_CR, 277 E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_100); 278 PHY_WRITE(sc, E1000_AR, E1000_AR_100TX_FD); 279 } else { 280 PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_100); 281 PHY_WRITE(sc, E1000_AR, E1000_AR_100TX); 282 } 283 break; 284 285 case IFM_10_T: 286 e1000phy_reset(sc); 287 288 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { 289 PHY_WRITE(sc, E1000_CR, 290 E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_10); 291 PHY_WRITE(sc, E1000_AR, E1000_AR_10T_FD); 292 } else { 293 PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_10); 294 PHY_WRITE(sc, E1000_AR, E1000_AR_10T); 295 } 296 297 break; 298 299 default: 300 return (EINVAL); 301 } 302 303 break; 304 305 case MII_TICK: 306 /* 307 * If we're not currently selected, just return. 308 */ 309 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 310 return (0); 311 } 312 313 /* 314 * Is the interface even up? 315 */ 316 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 317 return (0); 318 319 /* 320 * Only used for autonegotiation. 321 */ 322 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 323 break; 324 325 /* 326 * check for link. 327 * Read the status register twice; BMSR_LINK is latch-low. 328 */ 329 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 330 if (reg & BMSR_LINK) 331 break; 332 333 /* 334 * Only retry autonegotiation every 5 seconds. 335 */ 336 if (++sc->mii_ticks <= 5) 337 break; 338 339 sc->mii_ticks = 0; 340 e1000phy_reset(sc); 341 e1000phy_mii_phy_auto(sc); 342 return (0); 343 } 344 345 /* Update the media status. */ 346 e1000phy_status(sc); 347 348 /* Callback if something changed. */ 349 mii_phy_update(sc, cmd); 350 return (0); 351 } 352 353 static void 354 e1000phy_status(struct mii_softc *sc) 355 { 356 struct mii_data *mii = sc->mii_pdata; 357 int bmsr, bmcr, esr, ssr, isr, ar, lpar; 358 359 mii->mii_media_status = IFM_AVALID; 360 mii->mii_media_active = IFM_ETHER; 361 362 bmsr = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR); 363 esr = PHY_READ(sc, E1000_ESR); 364 bmcr = PHY_READ(sc, E1000_CR); 365 ssr = PHY_READ(sc, E1000_SSR); 366 isr = PHY_READ(sc, E1000_ISR); 367 ar = PHY_READ(sc, E1000_AR); 368 lpar = PHY_READ(sc, E1000_LPAR); 369 370 if (bmsr & E1000_SR_LINK_STATUS) 371 mii->mii_media_status |= IFM_ACTIVE; 372 373 if (bmcr & E1000_CR_LOOPBACK) 374 mii->mii_media_active |= IFM_LOOP; 375 376 if ((!(bmsr & E1000_SR_AUTO_NEG_COMPLETE) || !(ssr & E1000_SSR_LINK) || 377 !(ssr & E1000_SSR_SPD_DPLX_RESOLVED))) { 378 /* Erg, still trying, I guess... */ 379 mii->mii_media_active |= IFM_NONE; 380 return; 381 } 382 383 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 384 if (ssr & E1000_SSR_1000MBS) 385 mii->mii_media_active |= IFM_1000_T; 386 else if (ssr & E1000_SSR_100MBS) 387 mii->mii_media_active |= IFM_100_TX; 388 else 389 mii->mii_media_active |= IFM_10_T; 390 } else { 391 if (ssr & E1000_SSR_1000MBS) 392 mii->mii_media_active |= IFM_1000_SX; 393 } 394 395 if (ssr & E1000_SSR_DUPLEX) 396 mii->mii_media_active |= IFM_FDX; 397 else 398 mii->mii_media_active |= IFM_HDX; 399 400 if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { 401 /* FLAG0==rx-flow-control FLAG1==tx-flow-control */ 402 if ((ar & E1000_AR_PAUSE) && (lpar & E1000_LPAR_PAUSE)) { 403 mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1; 404 } else if (!(ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) && 405 (lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) { 406 mii->mii_media_active |= IFM_FLAG1; 407 } else if ((ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) && 408 !(lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) { 409 mii->mii_media_active |= IFM_FLAG0; 410 } 411 } 412 } 413 414 static int 415 e1000phy_mii_phy_auto(struct mii_softc *mii) 416 { 417 418 if ((mii->mii_flags & MIIF_HAVEFIBER) == 0) { 419 PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD | 420 E1000_AR_100TX | E1000_AR_100TX_FD | 421 E1000_AR_PAUSE | E1000_AR_ASM_DIR); 422 PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD); 423 PHY_WRITE(mii, E1000_CR, 424 E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG); 425 } 426 427 return (EJUSTRETURN); 428 } 429