1 /* $NetBSD: makphy.c,v 1.45 2018/06/18 09:12:17 msaitoh Exp $ */ 2 /* $OpenBSD: eephy.c,v 1.56 2015/03/14 03:38:48 jsg Exp $ */ 3 4 /*- 5 * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10 * NASA Ames Research Center. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58 /* 59 * Principal Author: Parag Patel 60 * Copyright (c) 2001 61 * All rights reserved. 62 * 63 * Redistribution and use in source and binary forms, with or without 64 * modification, are permitted provided that the following conditions 65 * are met: 66 * 1. Redistributions of source code must retain the above copyright 67 * notice unmodified, this list of conditions, and the following 68 * disclaimer. 69 * 2. Redistributions in binary form must reproduce the above copyright 70 * notice, this list of conditions and the following disclaimer in the 71 * documentation and/or other materials provided with the distribution. 72 * 73 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 74 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 76 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 77 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 78 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 79 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 80 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 81 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 82 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 83 * SUCH DAMAGE. 84 * 85 * Additonal Copyright (c) 2001 by Traakan Software under same licence. 86 * Secondary Author: Matthew Jacob 87 */ 88 /* 89 * Driver for the Marvell 88E1000 ``Alaska'' 10/100/1000 PHY. 90 */ 91 92 /* 93 * Support added for the Marvell 88E1011 (Alaska) 1000/100/10baseTX and 94 * 1000baseSX PHY. 95 * Nathan Binkert <nate@openbsd.org> 96 */ 97 98 #include <sys/cdefs.h> 99 __KERNEL_RCSID(0, "$NetBSD: makphy.c,v 1.45 2018/06/18 09:12:17 msaitoh Exp $"); 100 101 #include <sys/param.h> 102 #include <sys/systm.h> 103 #include <sys/kernel.h> 104 #include <sys/device.h> 105 #include <sys/socket.h> 106 #include <sys/errno.h> 107 108 #include <net/if.h> 109 #include <net/if_media.h> 110 111 #include <dev/mii/mii.h> 112 #include <dev/mii/miivar.h> 113 #include <dev/mii/miidevs.h> 114 115 #include <dev/mii/e1000phyreg.h> 116 117 static int makphymatch(device_t, cfdata_t, void *); 118 static void makphyattach(device_t, device_t, void *); 119 120 CFATTACH_DECL_NEW(makphy, sizeof(struct mii_softc), 121 makphymatch, makphyattach, mii_phy_detach, mii_phy_activate); 122 123 static int makphy_service(struct mii_softc *, struct mii_data *, int); 124 static void makphy_status(struct mii_softc *); 125 static void makphy_reset(struct mii_softc *); 126 127 static const struct mii_phy_funcs eephy_funcs = { 128 makphy_service, makphy_status, makphy_reset, 129 }; 130 131 static const struct mii_phydesc eephys[] = { 132 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_0, 133 MII_STR_MARVELL_E1000_0 }, 134 135 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_3, 136 MII_STR_MARVELL_E1000_3 }, 137 138 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_5, 139 MII_STR_MARVELL_E1000_5 }, 140 141 { MII_OUI_MARVELL, MII_MODEL_MARVELL_E1000_6, 142 MII_STR_MARVELL_E1000_6 }, 143 144 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000_3, 145 MII_STR_xxMARVELL_E1000_3 }, 146 147 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000_5, 148 MII_STR_xxMARVELL_E1000_5 }, 149 150 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1000S, 151 MII_STR_xxMARVELL_E1000S }, 152 153 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1011, 154 MII_STR_xxMARVELL_E1011 }, 155 156 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1111, 157 MII_STR_xxMARVELL_E1111 }, 158 159 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1112, 160 MII_STR_xxMARVELL_E1112 }, 161 162 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1116, 163 MII_STR_xxMARVELL_E1116 }, 164 165 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1116R, 166 MII_STR_xxMARVELL_E1116R }, 167 168 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1116R_29, 169 MII_STR_xxMARVELL_E1116R_29 }, 170 171 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1118, 172 MII_STR_xxMARVELL_E1118 }, 173 174 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1145, 175 MII_STR_xxMARVELL_E1145 }, 176 177 /* XXX: reported not to work on eg. HP XW9400 */ 178 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1149, 179 MII_STR_xxMARVELL_E1149 }, 180 181 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1149R, 182 MII_STR_xxMARVELL_E1149R }, 183 184 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E1543, 185 MII_STR_xxMARVELL_E1543 }, 186 187 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E3016, 188 MII_STR_xxMARVELL_E3016 }, 189 190 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_E3082, 191 MII_STR_xxMARVELL_E3082 }, 192 193 { MII_OUI_xxMARVELL, MII_MODEL_xxMARVELL_PHYG65G, 194 MII_STR_xxMARVELL_PHYG65G }, 195 { 0, 0, 196 NULL }, 197 }; 198 199 static int 200 makphymatch(device_t parent, cfdata_t match, void *aux) 201 { 202 struct mii_attach_args *ma = aux; 203 204 if (mii_phy_match(ma, eephys) != NULL) 205 return (10); 206 207 return (0); 208 } 209 210 static void 211 makphyattach(device_t parent, device_t self, void *aux) 212 { 213 struct mii_softc *sc = device_private(self); 214 struct mii_attach_args *ma = aux; 215 struct mii_data *mii = ma->mii_data; 216 const struct mii_phydesc *mpd; 217 218 mpd = mii_phy_match(ma, eephys); 219 aprint_naive(": Media interface\n"); 220 aprint_normal(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2)); 221 222 sc->mii_dev = self; 223 sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); 224 sc->mii_mpd_model = MII_MODEL(ma->mii_id2); 225 sc->mii_mpd_rev = MII_REV(ma->mii_id2); 226 sc->mii_inst = mii->mii_instance; 227 sc->mii_phy = ma->mii_phyno; 228 sc->mii_funcs = &eephy_funcs; 229 sc->mii_pdata = mii; 230 sc->mii_flags = ma->mii_flags; 231 sc->mii_anegticks = MII_ANEGTICKS; 232 233 /* XXX No loopback support yet, although the hardware can do it. */ 234 sc->mii_flags |= MIIF_NOLOOP; 235 236 /* Make sure page 0 is selected. */ 237 PHY_WRITE(sc, E1000_EADR, 0); 238 239 /* Switch to copper-only mode if necessary. */ 240 if (sc->mii_mpd_model == MII_MODEL_MARVELL_E1111 && 241 (sc->mii_flags & MIIF_HAVEFIBER) == 0) { 242 /* 243 * The onboard 88E1111 PHYs on the Sun X4100 M2 come 244 * up with fiber/copper auto-selection enabled, even 245 * though the machine only has copper ports. This 246 * makes the chip autoselect to 1000baseX, and makes 247 * it impossible to select any other media. So 248 * disable fiber/copper autoselection. 249 */ 250 int reg = PHY_READ(sc, E1000_ESSR); 251 if ((reg & E1000_ESSR_HWCFG_MODE) == E1000_ESSR_RGMII_COPPER) { 252 reg |= E1000_ESSR_DIS_FC; 253 PHY_WRITE(sc, E1000_ESSR, reg); 254 } 255 } 256 257 /* Switch to fiber-only mode if necessary. */ 258 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1112 && 259 sc->mii_flags & MIIF_HAVEFIBER) { 260 int page = PHY_READ(sc, E1000_EADR); 261 PHY_WRITE(sc, E1000_EADR, 2); 262 int reg = PHY_READ(sc, E1000_SCR); 263 reg &= ~E1000_SCR_MODE_MASK; 264 reg |= E1000_SCR_MODE_1000BX; 265 PHY_WRITE(sc, E1000_SCR, reg); 266 PHY_WRITE(sc, E1000_EADR, page); 267 } 268 269 PHY_RESET(sc); 270 271 sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; 272 if (sc->mii_capabilities & BMSR_EXTSTAT) 273 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 274 275 aprint_normal_dev(self, ""); 276 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 277 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) 278 aprint_error("no media present"); 279 else 280 mii_phy_add_media(sc); 281 aprint_normal("\n"); 282 } 283 284 static void 285 makphy_reset(struct mii_softc *sc) 286 { 287 int reg, i; 288 289 reg = PHY_READ(sc, MII_BMCR); 290 reg |= BMCR_RESET; 291 PHY_WRITE(sc, MII_BMCR, reg); 292 293 for (i = 0; i < 500; i++) { 294 DELAY(1); 295 reg = PHY_READ(sc, MII_BMCR); 296 if (!(reg & BMCR_RESET)) 297 break; 298 } 299 300 /* 301 * Initialize PHY Specific Control Register. 302 */ 303 reg = PHY_READ(sc, E1000_SCR); 304 305 /* Assert CRS on transmit. */ 306 reg |= E1000_SCR_ASSERT_CRS_ON_TX; 307 308 /* Enable auto crossover. */ 309 switch (sc->mii_mpd_model) { 310 case MII_MODEL_xxMARVELL_E3016: 311 case MII_MODEL_xxMARVELL_E3082: 312 /* Bits are in a different position. */ 313 reg |= (E1000_SCR_AUTO_X_MODE >> 1); 314 break; 315 default: 316 /* Automatic crossover causes problems for 1000baseX. */ 317 if (sc->mii_flags & MIIF_IS_1000X) 318 reg &= ~E1000_SCR_AUTO_X_MODE; 319 else 320 reg |= E1000_SCR_AUTO_X_MODE; 321 } 322 323 /* Disable energy detect; only available on some models. */ 324 switch(sc->mii_mpd_model) { 325 case MII_MODEL_xxMARVELL_E3016: 326 reg &= ~E3000_SCR_EN_DETECT_MASK; 327 break; 328 case MII_MODEL_MARVELL_E1011: 329 case MII_MODEL_MARVELL_E1111: 330 case MII_MODEL_xxMARVELL_E1112: 331 case MII_MODEL_xxMARVELL_PHYG65G: 332 reg &= ~E1000_SCR_EN_DETECT_MASK; 333 break; 334 } 335 336 /* Enable scrambler if necessary. */ 337 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016) 338 reg &= ~E3000_SCR_SCRAMBLER_DISABLE; 339 340 /* 341 * Store next page in the Link Partner Next Page register for 342 * compatibility with 802.3ab. 343 */ 344 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016) 345 reg |= E3000_SCR_REG8_NEXT_PAGE; 346 347 PHY_WRITE(sc, E1000_SCR, reg); 348 349 /* 25 MHz TX_CLK should always work. */ 350 reg = PHY_READ(sc, E1000_ESCR); 351 reg |= E1000_ESCR_TX_CLK_25; 352 PHY_WRITE(sc, E1000_ESCR, reg); 353 354 /* Configure LEDs if they were left unconfigured. */ 355 if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E3016 && 356 PHY_READ(sc, 0x16) == 0) { 357 reg = (0x0b << 8) | (0x05 << 4) | 0x04; /* XXX */ 358 PHY_WRITE(sc, 0x16, reg); 359 } 360 361 /* 362 * Do a software reset for these settings to take effect. 363 * Disable autonegotiation, such that all capabilities get 364 * advertised when it is switched back on. 365 */ 366 reg = PHY_READ(sc, MII_BMCR); 367 reg &= ~BMCR_AUTOEN; 368 PHY_WRITE(sc, MII_BMCR, reg | BMCR_RESET); 369 } 370 371 static int 372 makphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 373 { 374 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 375 int bmcr; 376 377 if (!device_is_active(sc->mii_dev)) 378 return (ENXIO); 379 380 switch (cmd) { 381 case MII_POLLSTAT: 382 /* 383 * If we're not polling our PHY instance, just return. 384 */ 385 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 386 return (0); 387 break; 388 389 case MII_MEDIACHG: 390 /* 391 * If the media indicates a different PHY instance, 392 * isolate ourselves. 393 */ 394 if (IFM_INST(ife->ifm_media) != sc->mii_inst) { 395 bmcr = PHY_READ(sc, MII_BMCR); 396 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO); 397 return (0); 398 } 399 400 /* 401 * If the interface is not up, don't do anything. 402 */ 403 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 404 break; 405 406 mii_phy_setmedia(sc); 407 408 /* 409 * If autonegitation is not enabled, we need a 410 * software reset for the settings to take effect. 411 */ 412 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { 413 bmcr = PHY_READ(sc, MII_BMCR); 414 PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_RESET); 415 } 416 break; 417 418 case MII_TICK: 419 /* 420 * If we're not currently selected, just return. 421 */ 422 if (IFM_INST(ife->ifm_media) != sc->mii_inst) 423 return (0); 424 425 if (mii_phy_tick(sc) == EJUSTRETURN) 426 return (0); 427 break; 428 429 case MII_DOWN: 430 mii_phy_down(sc); 431 return (0); 432 } 433 434 /* Update the media status. */ 435 mii_phy_status(sc); 436 437 /* Callback if something changed. */ 438 mii_phy_update(sc, cmd); 439 return (0); 440 } 441 442 static void 443 makphy_status(struct mii_softc *sc) 444 { 445 struct mii_data *mii = sc->mii_pdata; 446 int bmcr, gsr, ssr; 447 448 mii->mii_media_status = IFM_AVALID; 449 mii->mii_media_active = IFM_ETHER; 450 451 bmcr = PHY_READ(sc, MII_BMCR); 452 ssr = PHY_READ(sc, E1000_SSR); 453 454 if (ssr & E1000_SSR_LINK) 455 mii->mii_media_status |= IFM_ACTIVE; 456 457 if (bmcr & BMCR_ISO) { 458 mii->mii_media_active |= IFM_NONE; 459 mii->mii_media_status = 0; 460 return; 461 } 462 463 if (bmcr & BMCR_LOOP) 464 mii->mii_media_active |= IFM_LOOP; 465 466 if (!(ssr & E1000_SSR_SPD_DPLX_RESOLVED)) { 467 /* Erg, still trying, I guess... */ 468 mii->mii_media_active |= IFM_NONE; 469 return; 470 } 471 472 if (sc->mii_flags & MIIF_IS_1000X) { 473 mii->mii_media_active |= IFM_1000_SX; 474 } else { 475 if (ssr & E1000_SSR_1000MBS) 476 mii->mii_media_active |= IFM_1000_T; 477 else if (ssr & E1000_SSR_100MBS) 478 mii->mii_media_active |= IFM_100_TX; 479 else 480 mii->mii_media_active |= IFM_10_T; 481 } 482 483 if (ssr & E1000_SSR_DUPLEX) 484 mii->mii_media_active |= mii_phy_flowstatus(sc) | IFM_FDX; 485 else 486 mii->mii_media_active |= IFM_HDX; 487 488 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) { 489 gsr = PHY_READ(sc, MII_100T2SR) | PHY_READ(sc, MII_100T2SR); 490 if (gsr & GTSR_MS_RES) 491 mii->mii_media_active |= IFM_ETH_MASTER; 492 } 493 } 494