1 /* $NetBSD: nsphyter.c,v 1.28 2008/01/20 07:58:19 msaitoh Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-2-Clause 5 * 6 * Copyright (c) 1998, 1999, 2000, 2001 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 __FBSDID("$FreeBSD$"); 61 62 /* 63 * Driver for the National Semiconductor's DP83843, DP83847 and DP83849 64 * `PHYTER' Ethernet 10/100 PHYs 65 * Data Sheets are available from http://www.national.com 66 * 67 * We also support the DP83815 `MacPHYTER' internal PHY since, for our 68 * purposes, they are compatible. 69 */ 70 71 #include <sys/param.h> 72 #include <sys/systm.h> 73 #include <sys/bus.h> 74 #include <sys/errno.h> 75 #include <sys/kernel.h> 76 #include <sys/module.h> 77 #include <sys/socket.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 "miidevs.h" 85 86 #include <dev/mii/nsphyterreg.h> 87 88 #include "miibus_if.h" 89 90 static device_probe_t nsphyter_probe; 91 static device_attach_t nsphyter_attach; 92 93 static device_method_t nsphyter_methods[] = { 94 /* device interface */ 95 DEVMETHOD(device_probe, nsphyter_probe), 96 DEVMETHOD(device_attach, nsphyter_attach), 97 DEVMETHOD(device_detach, mii_phy_detach), 98 DEVMETHOD(device_shutdown, bus_generic_shutdown), 99 DEVMETHOD_END 100 }; 101 102 static devclass_t nsphyter_devclass; 103 104 static driver_t nsphyter_driver = { 105 "nsphyter", 106 nsphyter_methods, 107 sizeof(struct mii_softc) 108 }; 109 110 DRIVER_MODULE(nsphyter, miibus, nsphyter_driver, nsphyter_devclass, 0, 0); 111 112 static int nsphyter_service(struct mii_softc *, struct mii_data *, int); 113 static void nsphyter_status(struct mii_softc *); 114 static void nsphyter_reset(struct mii_softc *); 115 116 static const struct mii_phydesc nsphyters[] = { 117 MII_PHY_DESC(xxNATSEMI, DP83815), 118 MII_PHY_DESC(xxNATSEMI, DP83843), 119 MII_PHY_DESC(xxNATSEMI, DP83847), 120 MII_PHY_DESC(xxNATSEMI, DP83849), 121 MII_PHY_END 122 }; 123 124 static const struct mii_phy_funcs nsphyter_funcs = { 125 nsphyter_service, 126 nsphyter_status, 127 nsphyter_reset 128 }; 129 130 static int 131 nsphyter_probe(device_t dev) 132 { 133 134 return (mii_phy_dev_probe(dev, nsphyters, BUS_PROBE_DEFAULT)); 135 } 136 137 static int 138 nsphyter_attach(device_t dev) 139 { 140 141 mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsphyter_funcs, 1); 142 return (0); 143 } 144 145 static int 146 nsphyter_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 147 { 148 149 switch (cmd) { 150 case MII_POLLSTAT: 151 break; 152 153 case MII_MEDIACHG: 154 mii_phy_setmedia(sc); 155 break; 156 157 case MII_TICK: 158 if (mii_phy_tick(sc) == EJUSTRETURN) 159 return (0); 160 break; 161 } 162 163 /* Update the media status. */ 164 PHY_STATUS(sc); 165 166 /* Callback if something changed. */ 167 mii_phy_update(sc, cmd); 168 return (0); 169 } 170 171 static void 172 nsphyter_status(struct mii_softc *sc) 173 { 174 struct mii_data *mii = sc->mii_pdata; 175 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 176 int bmsr, bmcr, physts; 177 178 mii->mii_media_status = IFM_AVALID; 179 mii->mii_media_active = IFM_ETHER; 180 181 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 182 physts = PHY_READ(sc, MII_NSPHYTER_PHYSTS); 183 184 if ((physts & PHYSTS_LINK) != 0) 185 mii->mii_media_status |= IFM_ACTIVE; 186 187 bmcr = PHY_READ(sc, MII_BMCR); 188 if ((bmcr & BMCR_ISO) != 0) { 189 mii->mii_media_active |= IFM_NONE; 190 mii->mii_media_status = 0; 191 return; 192 } 193 194 if ((bmcr & BMCR_LOOP) != 0) 195 mii->mii_media_active |= IFM_LOOP; 196 197 if ((bmcr & BMCR_AUTOEN) != 0) { 198 /* 199 * The media status bits are only valid if autonegotiation 200 * has completed (or it's disabled). 201 */ 202 if ((bmsr & BMSR_ACOMP) == 0) { 203 /* Erg, still trying, I guess... */ 204 mii->mii_media_active |= IFM_NONE; 205 return; 206 } 207 208 if ((physts & PHYSTS_SPEED10) != 0) 209 mii->mii_media_active |= IFM_10_T; 210 else 211 mii->mii_media_active |= IFM_100_TX; 212 if ((physts & PHYSTS_DUPLEX) != 0) 213 mii->mii_media_active |= 214 IFM_FDX | mii_phy_flowstatus(sc); 215 else 216 mii->mii_media_active |= IFM_HDX; 217 } else 218 mii->mii_media_active = ife->ifm_media; 219 } 220 221 static void 222 nsphyter_reset(struct mii_softc *sc) 223 { 224 struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; 225 int reg, i; 226 227 if ((sc->mii_flags & MIIF_NOISOLATE) != 0) 228 reg = BMCR_RESET; 229 else 230 reg = BMCR_RESET | BMCR_ISO; 231 PHY_WRITE(sc, MII_BMCR, reg); 232 233 /* 234 * It is best to allow a little time for the reset to settle 235 * in before we start polling the BMCR again. Notably, the 236 * DP8384{3,7} manuals state that there should be a 500us delay 237 * between asserting software reset and attempting MII serial 238 * operations. Be conservative. Also, a DP83815 can get into 239 * a bad state on cable removal and reinsertion if we do not 240 * delay here. 241 */ 242 DELAY(1000); 243 244 /* 245 * Wait another 2s for it to complete. 246 * This is only a little overkill as under normal circumstances 247 * the PHY can take up to 1s to complete reset. 248 * This is also a bit odd because after a reset, the BMCR will 249 * clear the reset bit and simply reports 0 even though the reset 250 * is not yet complete. 251 */ 252 for (i = 0; i < 1000; i++) { 253 reg = PHY_READ(sc, MII_BMCR); 254 if (reg != 0 && (reg & BMCR_RESET) == 0) 255 break; 256 DELAY(2000); 257 } 258 259 if ((sc->mii_flags & MIIF_NOISOLATE) == 0) { 260 if ((ife == NULL && sc->mii_inst != 0) || 261 (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)) 262 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 263 } 264 } 265