1 /* $NetBSD: nsphy.c,v 1.18 1999/07/14 23:57:36 thorpej Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 11 * NASA Ames Research Center. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 /*- 36 * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 48 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 49 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 50 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 51 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 52 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 53 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 54 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 55 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 56 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 */ 58 59 #include <sys/cdefs.h> 60 /* 61 * driver for National Semiconductor's DP83840A ethernet 10/100 PHY 62 * Data Sheet available from www.national.com 63 */ 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/kernel.h> 68 #include <sys/socket.h> 69 #include <sys/errno.h> 70 #include <sys/module.h> 71 #include <sys/bus.h> 72 73 #include <net/if.h> 74 #include <net/if_var.h> 75 #include <net/if_media.h> 76 77 #include <dev/mii/mii.h> 78 #include <dev/mii/miivar.h> 79 #include "miidevs.h" 80 81 #include <dev/mii/nsphyreg.h> 82 83 #include "miibus_if.h" 84 85 static int nsphy_probe(device_t); 86 static int nsphy_attach(device_t); 87 88 static device_method_t nsphy_methods[] = { 89 /* device interface */ 90 DEVMETHOD(device_probe, nsphy_probe), 91 DEVMETHOD(device_attach, nsphy_attach), 92 DEVMETHOD(device_detach, mii_phy_detach), 93 DEVMETHOD(device_shutdown, bus_generic_shutdown), 94 DEVMETHOD_END 95 }; 96 97 static driver_t nsphy_driver = { 98 "nsphy", 99 nsphy_methods, 100 sizeof(struct mii_softc) 101 }; 102 103 DRIVER_MODULE(nsphy, miibus, nsphy_driver, 0, 0); 104 105 static int nsphy_service(struct mii_softc *, struct mii_data *, int); 106 static void nsphy_status(struct mii_softc *); 107 static void nsphy_reset(struct mii_softc *); 108 109 static const struct mii_phydesc nsphys[] = { 110 MII_PHY_DESC(xxNATSEMI, DP83840), 111 MII_PHY_END 112 }; 113 114 static const struct mii_phy_funcs nsphy_funcs = { 115 nsphy_service, 116 nsphy_status, 117 nsphy_reset 118 }; 119 120 static int 121 nsphy_probe(device_t dev) 122 { 123 124 return (mii_phy_dev_probe(dev, nsphys, BUS_PROBE_DEFAULT)); 125 } 126 127 static int 128 nsphy_attach(device_t dev) 129 { 130 131 mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsphy_funcs, 1); 132 return (0); 133 } 134 135 static int 136 nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 137 { 138 int reg; 139 140 switch (cmd) { 141 case MII_POLLSTAT: 142 break; 143 144 case MII_MEDIACHG: 145 reg = PHY_READ(sc, MII_NSPHY_PCR); 146 147 /* 148 * Set up the PCR to use LED4 to indicate full-duplex 149 * in both 10baseT and 100baseTX modes. 150 */ 151 reg |= PCR_LED4MODE; 152 153 /* 154 * Make sure Carrier Integrity Monitor function is 155 * disabled (normal for Node operation, but sometimes 156 * it's not set?!) 157 */ 158 reg |= PCR_CIMDIS; 159 160 /* 161 * Make sure "force link good" is set to normal mode. 162 * It's only intended for debugging. 163 */ 164 reg |= PCR_FLINK100; 165 166 /* 167 * Mystery bits which are supposedly `reserved', 168 * but we seem to need to set them when the PHY 169 * is connected to some interfaces: 170 * 171 * 0x0400 is needed for fxp 172 * (Intel EtherExpress Pro 10+/100B, 82557 chip) 173 * (nsphy with a DP83840 chip) 174 * 0x0100 may be needed for some other card 175 */ 176 reg |= 0x0100 | 0x0400; 177 178 if (mii_phy_mac_match(sc, "fxp")) 179 PHY_WRITE(sc, MII_NSPHY_PCR, reg); 180 181 mii_phy_setmedia(sc); 182 break; 183 184 case MII_TICK: 185 if (mii_phy_tick(sc) == EJUSTRETURN) 186 return (0); 187 break; 188 } 189 190 /* Update the media status. */ 191 PHY_STATUS(sc); 192 193 /* Callback if something changed. */ 194 mii_phy_update(sc, cmd); 195 return (0); 196 } 197 198 static void 199 nsphy_status(struct mii_softc *sc) 200 { 201 struct mii_data *mii = sc->mii_pdata; 202 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 203 int bmsr, bmcr, par, anlpar; 204 205 mii->mii_media_status = IFM_AVALID; 206 mii->mii_media_active = IFM_ETHER; 207 208 bmsr = PHY_READ(sc, MII_BMSR) | 209 PHY_READ(sc, MII_BMSR); 210 if (bmsr & BMSR_LINK) 211 mii->mii_media_status |= IFM_ACTIVE; 212 213 bmcr = PHY_READ(sc, MII_BMCR); 214 if (bmcr & BMCR_ISO) { 215 mii->mii_media_active |= IFM_NONE; 216 mii->mii_media_status = 0; 217 return; 218 } 219 220 if (bmcr & BMCR_LOOP) 221 mii->mii_media_active |= IFM_LOOP; 222 223 if (bmcr & BMCR_AUTOEN) { 224 /* 225 * The PAR status bits are only valid if autonegotiation 226 * has completed (or it's disabled). 227 */ 228 if ((bmsr & BMSR_ACOMP) == 0) { 229 /* Erg, still trying, I guess... */ 230 mii->mii_media_active |= IFM_NONE; 231 return; 232 } 233 234 /* 235 * Argh. The PAR doesn't seem to indicate duplex mode 236 * properly! Determine media based on link partner's 237 * advertised capabilities. 238 */ 239 if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { 240 anlpar = PHY_READ(sc, MII_ANAR) & 241 PHY_READ(sc, MII_ANLPAR); 242 if (anlpar & ANLPAR_TX_FD) 243 mii->mii_media_active |= IFM_100_TX|IFM_FDX; 244 else if (anlpar & ANLPAR_T4) 245 mii->mii_media_active |= IFM_100_T4|IFM_HDX; 246 else if (anlpar & ANLPAR_TX) 247 mii->mii_media_active |= IFM_100_TX|IFM_HDX; 248 else if (anlpar & ANLPAR_10_FD) 249 mii->mii_media_active |= IFM_10_T|IFM_FDX; 250 else if (anlpar & ANLPAR_10) 251 mii->mii_media_active |= IFM_10_T|IFM_HDX; 252 else 253 mii->mii_media_active |= IFM_NONE; 254 if ((mii->mii_media_active & IFM_FDX) != 0) 255 mii->mii_media_active |= 256 mii_phy_flowstatus(sc); 257 return; 258 } 259 260 /* 261 * Link partner is not capable of autonegotiation. 262 * We will never be in full-duplex mode if this is 263 * the case, so reading the PAR is OK. 264 */ 265 par = PHY_READ(sc, MII_NSPHY_PAR); 266 if (par & PAR_10) 267 mii->mii_media_active |= IFM_10_T; 268 else 269 mii->mii_media_active |= IFM_100_TX; 270 mii->mii_media_active |= IFM_HDX; 271 } else 272 mii->mii_media_active = ife->ifm_media; 273 } 274 275 static void 276 nsphy_reset(struct mii_softc *sc) 277 { 278 struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; 279 int reg, i; 280 281 if (sc->mii_flags & MIIF_NOISOLATE) 282 reg = BMCR_RESET; 283 else 284 reg = BMCR_RESET | BMCR_ISO; 285 PHY_WRITE(sc, MII_BMCR, reg); 286 287 /* 288 * It is best to allow a little time for the reset to settle 289 * in before we start polling the BMCR again. Notably, the 290 * DP83840A manuals state that there should be a 500us delay 291 * between asserting software reset and attempting MII serial 292 * operations. Be conservative. 293 */ 294 DELAY(1000); 295 296 /* 297 * Wait another 2s for it to complete. 298 * This is only a little overkill as under normal circumstances 299 * the PHY can take up to 1s to complete reset. 300 * This is also a bit odd because after a reset, the BMCR will 301 * clear the reset bit and simply reports 0 even though the reset 302 * is not yet complete. 303 */ 304 for (i = 0; i < 1000; i++) { 305 reg = PHY_READ(sc, MII_BMCR); 306 if (reg != 0 && (reg & BMCR_RESET) == 0) 307 break; 308 DELAY(2000); 309 } 310 311 if ((sc->mii_flags & MIIF_NOISOLATE) == 0) { 312 if ((ife == NULL && sc->mii_inst != 0) || 313 (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)) 314 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 315 } 316 } 317