nsphyter.c revision 231914
168349Sobrien/* $NetBSD: nsphyter.c,v 1.28 2008/01/20 07:58:19 msaitoh Exp $ */ 268349Sobrien 368349Sobrien/*- 468349Sobrien * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 568349Sobrien * All rights reserved. 668349Sobrien * 768349Sobrien * This code is derived from software contributed to The NetBSD Foundation 868349Sobrien * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9159764Sobrien * NASA Ames Research Center. 10159764Sobrien * 11159764Sobrien * Redistribution and use in source and binary forms, with or without 12159764Sobrien * modification, are permitted provided that the following conditions 13159764Sobrien * are met: 14159764Sobrien * 1. Redistributions of source code must retain the above copyright 15159764Sobrien * notice, this list of conditions and the following disclaimer. 16159764Sobrien * 2. Redistributions in binary form must reproduce the above copyright 17159764Sobrien * notice, this list of conditions and the following disclaimer in the 18159764Sobrien * documentation and/or other materials provided with the distribution. 19159764Sobrien * 20159764Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21159764Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22159764Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23159764Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24159764Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25159764Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26159764Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27159764Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28159764Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29159764Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30159764Sobrien * POSSIBILITY OF SUCH DAMAGE. 31159764Sobrien */ 32159764Sobrien 33159764Sobrien/*- 34159764Sobrien * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 35159764Sobrien * 36159764Sobrien * Redistribution and use in source and binary forms, with or without 37159764Sobrien * modification, are permitted provided that the following conditions 38159764Sobrien * are met: 39159764Sobrien * 1. Redistributions of source code must retain the above copyright 40159764Sobrien * notice, this list of conditions and the following disclaimer. 41159764Sobrien * 2. Redistributions in binary form must reproduce the above copyright 42159764Sobrien * notice, this list of conditions and the following disclaimer in the 43139368Sobrien * documentation and/or other materials provided with the distribution. 44139368Sobrien * 45159764Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46159764Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47159764Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48159764Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49159764Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50159764Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51139368Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52139368Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53139368Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54139368Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55139368Sobrien */ 56159764Sobrien 57159764Sobrien#include <sys/cdefs.h> 58159764Sobrien__FBSDID("$FreeBSD: head/sys/dev/mii/nsphyter.c 231914 2012-02-19 12:25:58Z marius $"); 59159764Sobrien 60159764Sobrien/* 61139368Sobrien * Driver for the National Semiconductor's DP83843, DP83847 and DP83849 62139368Sobrien * `PHYTER' Ethernet 10/100 PHYs 63139368Sobrien * Data Sheets are available from http://www.national.com 64139368Sobrien * 65139368Sobrien * We also support the DP83815 `MacPHYTER' internal PHY since, for our 66139368Sobrien * purposes, they are compatible. 67139368Sobrien */ 68159764Sobrien 69159764Sobrien#include <sys/param.h> 70159764Sobrien#include <sys/systm.h> 71159764Sobrien#include <sys/bus.h> 72139368Sobrien#include <sys/errno.h> 73139368Sobrien#include <sys/kernel.h> 74139368Sobrien#include <sys/module.h> 75139368Sobrien#include <sys/socket.h> 76139368Sobrien 77139368Sobrien#include <net/if.h> 78139368Sobrien#include <net/if_media.h> 79139368Sobrien 80139368Sobrien#include <dev/mii/mii.h> 81139368Sobrien#include <dev/mii/miivar.h> 82139368Sobrien#include "miidevs.h" 83139368Sobrien 84139368Sobrien#include <dev/mii/nsphyterreg.h> 85139368Sobrien 86139368Sobrien#include "miibus_if.h" 87139368Sobrien 88139368Sobrienstatic device_probe_t nsphyter_probe; 89139368Sobrienstatic device_attach_t nsphyter_attach; 90139368Sobrien 91139368Sobrienstatic device_method_t nsphyter_methods[] = { 92139368Sobrien /* device interface */ 93139368Sobrien DEVMETHOD(device_probe, nsphyter_probe), 94139368Sobrien DEVMETHOD(device_attach, nsphyter_attach), 95139368Sobrien DEVMETHOD(device_detach, mii_phy_detach), 96139368Sobrien DEVMETHOD(device_shutdown, bus_generic_shutdown), 97139368Sobrien DEVMETHOD_END 98139368Sobrien}; 99139368Sobrien 100139368Sobrienstatic devclass_t nsphyter_devclass; 101139368Sobrien 102139368Sobrienstatic driver_t nsphyter_driver = { 103139368Sobrien "nsphyter", 104139368Sobrien nsphyter_methods, 105139368Sobrien sizeof(struct mii_softc) 106139368Sobrien}; 107139368Sobrien 108139368SobrienDRIVER_MODULE(nsphyter, miibus, nsphyter_driver, nsphyter_devclass, 0, 0); 109139368Sobrien 110139368Sobrienstatic int nsphyter_service(struct mii_softc *, struct mii_data *, int); 111139368Sobrienstatic void nsphyter_status(struct mii_softc *); 112139368Sobrienstatic void nsphyter_reset(struct mii_softc *); 113139368Sobrien 114139368Sobrienstatic const struct mii_phydesc nsphyters[] = { 115139368Sobrien MII_PHY_DESC(xxNATSEMI, DP83815), 116139368Sobrien MII_PHY_DESC(xxNATSEMI, DP83843), 117139368Sobrien MII_PHY_DESC(xxNATSEMI, DP83847), 118139368Sobrien MII_PHY_DESC(xxNATSEMI, DP83849), 119139368Sobrien MII_PHY_END 120139368Sobrien}; 121139368Sobrien 122139368Sobrienstatic const struct mii_phy_funcs nsphyter_funcs = { 123139368Sobrien nsphyter_service, 124139368Sobrien nsphyter_status, 125139368Sobrien nsphyter_reset 126139368Sobrien}; 127139368Sobrien 128139368Sobrienstatic int 129139368Sobriennsphyter_probe(device_t dev) 130139368Sobrien{ 131139368Sobrien 132139368Sobrien return (mii_phy_dev_probe(dev, nsphyters, BUS_PROBE_DEFAULT)); 133139368Sobrien} 134139368Sobrien 135139368Sobrienstatic int 136159764Sobriennsphyter_attach(device_t dev) 137159764Sobrien{ 138159764Sobrien 139159764Sobrien mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsphyter_funcs, 1); 140139368Sobrien return (0); 141139368Sobrien} 142139368Sobrien 143139368Sobrienstatic int 144139368Sobriennsphyter_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 145139368Sobrien{ 146139368Sobrien 147139368Sobrien switch (cmd) { 148139368Sobrien case MII_POLLSTAT: 149139368Sobrien break; 150139368Sobrien 151139368Sobrien case MII_MEDIACHG: 152139368Sobrien /* 153139368Sobrien * If the interface is not up, don't do anything. 154139368Sobrien */ 155139368Sobrien if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 156139368Sobrien break; 157139368Sobrien 158139368Sobrien mii_phy_setmedia(sc); 159139368Sobrien break; 160139368Sobrien 161139368Sobrien case MII_TICK: 162139368Sobrien if (mii_phy_tick(sc) == EJUSTRETURN) 163139368Sobrien return (0); 164139368Sobrien break; 165139368Sobrien } 166139368Sobrien 167139368Sobrien /* Update the media status. */ 168139368Sobrien PHY_STATUS(sc); 169139368Sobrien 170139368Sobrien /* Callback if something changed. */ 171139368Sobrien mii_phy_update(sc, cmd); 172139368Sobrien return (0); 173139368Sobrien} 174139368Sobrien 175139368Sobrienstatic void 176139368Sobriennsphyter_status(struct mii_softc *sc) 177159764Sobrien{ 178159764Sobrien struct mii_data *mii = sc->mii_pdata; 179159764Sobrien struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 180159764Sobrien int bmsr, bmcr, physts; 181159764Sobrien 182159764Sobrien mii->mii_media_status = IFM_AVALID; 183159764Sobrien mii->mii_media_active = IFM_ETHER; 184159764Sobrien 185159764Sobrien bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 186159764Sobrien physts = PHY_READ(sc, MII_NSPHYTER_PHYSTS); 187159764Sobrien 188159764Sobrien if ((physts & PHYSTS_LINK) != 0) 189159764Sobrien mii->mii_media_status |= IFM_ACTIVE; 190159764Sobrien 191159764Sobrien bmcr = PHY_READ(sc, MII_BMCR); 192159764Sobrien if ((bmcr & BMCR_ISO) != 0) { 193159764Sobrien mii->mii_media_active |= IFM_NONE; 194139368Sobrien mii->mii_media_status = 0; 195139368Sobrien return; 196139368Sobrien } 197139368Sobrien 198139368Sobrien if ((bmcr & BMCR_LOOP) != 0) 199139368Sobrien mii->mii_media_active |= IFM_LOOP; 200139368Sobrien 201139368Sobrien if ((bmcr & BMCR_AUTOEN) != 0) { 202139368Sobrien /* 203139368Sobrien * The media status bits are only valid if autonegotiation 204139368Sobrien * has completed (or it's disabled). 205139368Sobrien */ 206139368Sobrien if ((bmsr & BMSR_ACOMP) == 0) { 207139368Sobrien /* Erg, still trying, I guess... */ 208139368Sobrien mii->mii_media_active |= IFM_NONE; 209139368Sobrien return; 210139368Sobrien } 211139368Sobrien 212139368Sobrien if ((physts & PHYSTS_SPEED10) != 0) 213139368Sobrien mii->mii_media_active |= IFM_10_T; 214139368Sobrien else 215139368Sobrien mii->mii_media_active |= IFM_100_TX; 216139368Sobrien if ((physts & PHYSTS_DUPLEX) != 0) 217139368Sobrien mii->mii_media_active |= 218139368Sobrien IFM_FDX | mii_phy_flowstatus(sc); 219139368Sobrien else 220139368Sobrien mii->mii_media_active |= IFM_HDX; 221139368Sobrien } else 222139368Sobrien mii->mii_media_active = ife->ifm_media; 223139368Sobrien} 224139368Sobrien 225139368Sobrienstatic void 226139368Sobriennsphyter_reset(struct mii_softc *sc) 227139368Sobrien{ 228139368Sobrien struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; 229139368Sobrien int reg, i; 230139368Sobrien 231139368Sobrien if ((sc->mii_flags & MIIF_NOISOLATE) != 0) 232139368Sobrien reg = BMCR_RESET; 233139368Sobrien else 234139368Sobrien reg = BMCR_RESET | BMCR_ISO; 235139368Sobrien PHY_WRITE(sc, MII_BMCR, reg); 236139368Sobrien 237139368Sobrien /* 238139368Sobrien * It is best to allow a little time for the reset to settle 239139368Sobrien * in before we start polling the BMCR again. Notably, the 240139368Sobrien * DP8384{3,7} manuals state that there should be a 500us delay 241139368Sobrien * between asserting software reset and attempting MII serial 242139368Sobrien * operations. Be conservative. Also, a DP83815 can get into 243139368Sobrien * a bad state on cable removal and reinsertion if we do not 244139368Sobrien * delay here. 245139368Sobrien */ 246139368Sobrien DELAY(1000); 247139368Sobrien 248139368Sobrien /* 24968349Sobrien * Wait another 2s for it to complete. 250139368Sobrien * This is only a little overkill as under normal circumstances 25168349Sobrien * the PHY can take up to 1s to complete reset. 252139368Sobrien * This is also a bit odd because after a reset, the BMCR will 25368349Sobrien * clear the reset bit and simply reports 0 even though the reset 254139368Sobrien * is not yet complete. 255139368Sobrien */ 256139368Sobrien for (i = 0; i < 1000; i++) { 257139368Sobrien reg = PHY_READ(sc, MII_BMCR); 258139368Sobrien if (reg != 0 && (reg & BMCR_RESET) == 0) 259139368Sobrien break; 260139368Sobrien DELAY(2000); 261139368Sobrien } 262139368Sobrien 263139368Sobrien if ((sc->mii_flags & MIIF_NOISOLATE) == 0) { 264139368Sobrien if ((ife == NULL && sc->mii_inst != 0) || 265139368Sobrien (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)) 266139368Sobrien PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 267139368Sobrien } 268139368Sobrien} 269139368Sobrien