nsgphy.c revision 331722
1138568Ssam/*- 2178354Ssam * Copyright (c) 2001 Wind River Systems 3138568Ssam * Copyright (c) 2001 4138568Ssam * Bill Paul <wpaul@bsdi.com>. All rights reserved. 5138568Ssam * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 6138568Ssam * All rights reserved. 7138568Ssam * 8138568Ssam * This code is derived from software contributed to The NetBSD Foundation 9138568Ssam * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 10138568Ssam * NASA Ames Research Center. 11138568Ssam * 12138568Ssam * Redistribution and use in source and binary forms, with or without 13138568Ssam * modification, are permitted provided that the following conditions 14138568Ssam * are met: 15138568Ssam * 1. Redistributions of source code must retain the above copyright 16138568Ssam * notice, this list of conditions and the following disclaimer. 17138568Ssam * 2. Redistributions in binary form must reproduce the above copyright 18138568Ssam * notice, this list of conditions and the following disclaimer in the 19138568Ssam * documentation and/or other materials provided with the distribution. 20138568Ssam * 3. All advertising materials mentioning features or use of this software 21138568Ssam * must display the following acknowledgement: 22138568Ssam * This product includes software developed by Bill Paul. 23138568Ssam * 4. Neither the name of the author nor the names of any co-contributors 24138568Ssam * may be used to endorse or promote products derived from this software 25138568Ssam * without specific prior written permission. 26138568Ssam * 27138568Ssam * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 28138568Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29138568Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30165911Ssam * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 31298899Savos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32283614Sglebius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33283614Sglebius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34178354Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35178354Ssam * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36178354Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 37192473Ssam * THE POSSIBILITY OF SUCH DAMAGE. 38191746Sthompsa */ 39178354Ssam 40138568Ssam#include <sys/cdefs.h> 41170530Ssam__FBSDID("$FreeBSD: stable/11/sys/dev/mii/nsgphy.c 331722 2018-03-29 02:50:57Z eadler $"); 42170530Ssam 43179388Ssam/* 44179388Ssam * Driver for the National Semiconductor DP83861, DP83865 and DP83891 45179388Ssam * 10/100/1000 PHYs. 46179388Ssam * Datasheet available at: http://www.national.com/ds/DP/DP83861.pdf 47179388Ssam * and at: http://www.national.com/ds/DP/DP83865.pdf 48179388Ssam * 49179388Ssam * The DP83891 is the older NS GigE PHY which isn't being sold 50179388Ssam * anymore. The DP83861 is its replacement, which is an 'enhanced' 51179388Ssam * firmware driven component. The major difference between the 52179388Ssam * two is that the DP83891 can't generate interrupts, while the 53179388Ssam * 83861 can (probably it wasn't originally designed to do this, but 54179388Ssam * it can now thanks to firmware updates). The DP83861 also allows 55179388Ssam * access to its internal RAM via indirect register access. The 56170530Ssam * DP83865 is an ultra low power version of the DP83861 and DP83891. 57179388Ssam */ 58243532Sadrian 59243532Sadrian#include <sys/param.h> 60170530Ssam#include <sys/systm.h> 61170530Ssam#include <sys/kernel.h> 62248069Sadrian#include <sys/module.h> 63248069Sadrian#include <sys/socket.h> 64248069Sadrian#include <sys/bus.h> 65248069Sadrian 66248069Sadrian#include <net/if.h> 67248069Sadrian#include <net/if_media.h> 68296171Savos 69248069Sadrian#include <dev/mii/mii.h> 70248069Sadrian#include <dev/mii/miivar.h> 71248069Sadrian#include "miidevs.h" 72248069Sadrian 73248069Sadrian#include <dev/mii/nsgphyreg.h> 74248069Sadrian 75248069Sadrian#include "miibus_if.h" 76248069Sadrian 77248069Sadrianstatic int nsgphy_probe(device_t); 78248069Sadrianstatic int nsgphy_attach(device_t); 79248069Sadrian 80248069Sadrianstatic device_method_t nsgphy_methods[] = { 81248069Sadrian /* device interface */ 82248069Sadrian DEVMETHOD(device_probe, nsgphy_probe), 83248069Sadrian DEVMETHOD(device_attach, nsgphy_attach), 84248069Sadrian DEVMETHOD(device_detach, mii_phy_detach), 85248069Sadrian DEVMETHOD(device_shutdown, bus_generic_shutdown), 86138568Ssam DEVMETHOD_END 87138568Ssam}; 88178354Ssam 89178354Ssamstatic devclass_t nsgphy_devclass; 90178354Ssam 91178354Ssamstatic driver_t nsgphy_driver = { 92178354Ssam "nsgphy", 93178354Ssam nsgphy_methods, 94178354Ssam sizeof(struct mii_softc) 95179388Ssam}; 96178354Ssam 97179388SsamDRIVER_MODULE(nsgphy, miibus, nsgphy_driver, nsgphy_devclass, 0, 0); 98178354Ssam 99179388Ssamstatic int nsgphy_service(struct mii_softc *, struct mii_data *,int); 100178354Ssamstatic void nsgphy_status(struct mii_softc *); 101179388Ssam 102178354Ssamstatic const struct mii_phydesc nsgphys[] = { 103179388Ssam MII_PHY_DESC(xxNATSEMI, DP83861), 104178354Ssam MII_PHY_DESC(xxNATSEMI, DP83865), 105179388Ssam MII_PHY_DESC(xxNATSEMI, DP83891), 106178354Ssam MII_PHY_END 107179388Ssam}; 108138568Ssam 109138568Ssamstatic const struct mii_phy_funcs nsgphy_funcs = { 110178354Ssam nsgphy_service, 111178354Ssam nsgphy_status, 112178354Ssam mii_phy_reset 113138568Ssam}; 114178354Ssam 115178354Ssamstatic int 116178354Ssamnsgphy_probe(device_t dev) 117178354Ssam{ 118178354Ssam 119178354Ssam return (mii_phy_dev_probe(dev, nsgphys, BUS_PROBE_DEFAULT)); 120178354Ssam} 121179388Ssam 122178354Ssamstatic int 123179388Ssamnsgphy_attach(device_t dev) 124178354Ssam{ 125179388Ssam struct mii_softc *sc; 126178354Ssam 127179388Ssam sc = device_get_softc(dev); 128178354Ssam 129179388Ssam mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsgphy_funcs, 0); 130138568Ssam 131138568Ssam PHY_RESET(sc); 132184288Ssam 133138568Ssam /* 134184288Ssam * NB: the PHY has the 10BASE-T BMSR bits hard-wired to 0, 135184288Ssam * even though it supports 10BASE-T. 136195379Ssam */ 137184288Ssam sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | 138184288Ssam BMSR_10TFDX | BMSR_10THDX) & sc->mii_capmask; 139184288Ssam /* 140138568Ssam * Note that as documented manual 1000BASE-T modes of DP83865 only 141167284Ssam * work together with other National Semiconductor PHYs. 142167284Ssam */ 143167284Ssam if (sc->mii_capabilities & BMSR_EXTSTAT) 144167284Ssam sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 145167284Ssam 146167284Ssam mii_phy_add_media(sc); 147167284Ssam printf("\n"); 148167284Ssam 149167284Ssam MIIBUS_MEDIAINIT(sc->mii_dev); 150167284Ssam return (0); 151167284Ssam} 152167284Ssam 153167284Ssamstatic int 154167284Ssamnsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 155195379Ssam{ 156195379Ssam 157195379Ssam switch (cmd) { 158195379Ssam case MII_POLLSTAT: 159195379Ssam break; 160195379Ssam 161195379Ssam case MII_MEDIACHG: 162195379Ssam mii_phy_setmedia(sc); 163195379Ssam break; 164195379Ssam 165167284Ssam case MII_TICK: 166138568Ssam if (mii_phy_tick(sc) == EJUSTRETURN) 167138568Ssam return (0); 168138568Ssam break; 169138568Ssam } 170138568Ssam 171138568Ssam /* Update the media status. */ 172138568Ssam PHY_STATUS(sc); 173138568Ssam 174138568Ssam /* Callback if something changed. */ 175138568Ssam mii_phy_update(sc, cmd); 176138568Ssam return (0); 177138568Ssam} 178138568Ssam 179206617Srpaulostatic void 180206617Srpaulonsgphy_status(struct mii_softc *sc) 181206617Srpaulo{ 182206617Srpaulo struct mii_data *mii = sc->mii_pdata; 183206617Srpaulo struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 184206617Srpaulo int bmsr, bmcr, physup, gtsr; 185206617Srpaulo 186206617Srpaulo mii->mii_media_status = IFM_AVALID; 187206617Srpaulo mii->mii_media_active = IFM_ETHER; 188283556Sadrian 189283556Sadrian bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 190283556Sadrian 191283556Sadrian physup = PHY_READ(sc, NSGPHY_MII_PHYSUP); 192283556Sadrian 193283556Sadrian if (physup & PHY_SUP_LINK) 194283556Sadrian mii->mii_media_status |= IFM_ACTIVE; 195206617Srpaulo 196283555Sadrian bmcr = PHY_READ(sc, MII_BMCR); 197283555Sadrian if (bmcr & BMCR_ISO) { 198283555Sadrian mii->mii_media_active |= IFM_NONE; 199283555Sadrian mii->mii_media_status = 0; 200283555Sadrian return; 201283555Sadrian } 202283555Sadrian 203283555Sadrian if (bmcr & BMCR_LOOP) 204283555Sadrian mii->mii_media_active |= IFM_LOOP; 205283555Sadrian 206283555Sadrian if (bmcr & BMCR_AUTOEN) { 207283555Sadrian /* 208283555Sadrian * The media status bits are only valid if autonegotiation 209283555Sadrian * has completed (or it's disabled). 210283555Sadrian */ 211283555Sadrian if ((bmsr & BMSR_ACOMP) == 0) { 212283555Sadrian /* Erg, still trying, I guess... */ 213283555Sadrian mii->mii_media_active |= IFM_NONE; 214283555Sadrian return; 215283555Sadrian } 216283555Sadrian 217138568Ssam switch (physup & (PHY_SUP_SPEED1 | PHY_SUP_SPEED0)) { 218138568Ssam case PHY_SUP_SPEED1: 219138568Ssam mii->mii_media_active |= IFM_1000_T; 220138568Ssam gtsr = PHY_READ(sc, MII_100T2SR); 221138568Ssam if (gtsr & GTSR_MS_RES) 222138568Ssam mii->mii_media_active |= IFM_ETH_MASTER; 223138568Ssam break; 224138568Ssam 225138568Ssam case PHY_SUP_SPEED0: 226138568Ssam mii->mii_media_active |= IFM_100_TX; 227138568Ssam break; 228138568Ssam 229138568Ssam case 0: 230138568Ssam mii->mii_media_active |= IFM_10_T; 231138568Ssam break; 232138568Ssam 233138568Ssam default: 234138568Ssam mii->mii_media_active |= IFM_NONE; 235144618Ssam mii->mii_media_status = 0; 236138568Ssam return; 237138568Ssam } 238165904Ssam 239178354Ssam if (physup & PHY_SUP_DUPLEX) 240165894Ssam mii->mii_media_active |= 241178354Ssam IFM_FDX | mii_phy_flowstatus(sc); 242165894Ssam else 243178354Ssam mii->mii_media_active |= IFM_HDX; 244178354Ssam } else 245178354Ssam mii->mii_media_active = ife->ifm_media; 246178354Ssam} 247178354Ssam