1098ca2bdSWarner Losh /*- 2ce4946daSBill Paul * Copyright (c) 2001 Wind River Systems 3ce4946daSBill Paul * Copyright (c) 2001 4ce4946daSBill Paul * Bill Paul <wpaul@bsdi.com>. All rights reserved. 578c8c3dbSPoul-Henning Kamp * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 678c8c3dbSPoul-Henning Kamp * All rights reserved. 778c8c3dbSPoul-Henning Kamp * 878c8c3dbSPoul-Henning Kamp * This code is derived from software contributed to The NetBSD Foundation 978c8c3dbSPoul-Henning Kamp * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 1078c8c3dbSPoul-Henning Kamp * NASA Ames Research Center. 11ce4946daSBill Paul * 12ce4946daSBill Paul * Redistribution and use in source and binary forms, with or without 13ce4946daSBill Paul * modification, are permitted provided that the following conditions 14ce4946daSBill Paul * are met: 15ce4946daSBill Paul * 1. Redistributions of source code must retain the above copyright 16ce4946daSBill Paul * notice, this list of conditions and the following disclaimer. 17ce4946daSBill Paul * 2. Redistributions in binary form must reproduce the above copyright 18ce4946daSBill Paul * notice, this list of conditions and the following disclaimer in the 19ce4946daSBill Paul * documentation and/or other materials provided with the distribution. 20ce4946daSBill Paul * 3. All advertising materials mentioning features or use of this software 21ce4946daSBill Paul * must display the following acknowledgement: 22ce4946daSBill Paul * This product includes software developed by Bill Paul. 23ce4946daSBill Paul * 4. Neither the name of the author nor the names of any co-contributors 24ce4946daSBill Paul * may be used to endorse or promote products derived from this software 25ce4946daSBill Paul * without specific prior written permission. 26ce4946daSBill Paul * 27ce4946daSBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 28ce4946daSBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29ce4946daSBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30ce4946daSBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 31ce4946daSBill Paul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32ce4946daSBill Paul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33ce4946daSBill Paul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34ce4946daSBill Paul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35ce4946daSBill Paul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36ce4946daSBill Paul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 37ce4946daSBill Paul * THE POSSIBILITY OF SUCH DAMAGE. 38ce4946daSBill Paul */ 39ce4946daSBill Paul 40aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 41aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 42aad970f1SDavid E. O'Brien 43ce4946daSBill Paul /* 4421211c45SMarius Strobl * Driver for the National Semiconductor DP83861, DP83865 and DP83891 45ce4946daSBill Paul * 10/100/1000 PHYs. 46ce4946daSBill Paul * Datasheet available at: http://www.national.com/ds/DP/DP83861.pdf 4721211c45SMarius Strobl * and at: http://www.national.com/ds/DP/DP83865.pdf 48ce4946daSBill Paul * 4921211c45SMarius Strobl * The DP83891 is the older NS GigE PHY which isn't being sold 50ce4946daSBill Paul * anymore. The DP83861 is its replacement, which is an 'enhanced' 51ce4946daSBill Paul * firmware driven component. The major difference between the 5221211c45SMarius Strobl * two is that the DP83891 can't generate interrupts, while the 5321211c45SMarius Strobl * 83861 can (probably it wasn't originally designed to do this, but 5421211c45SMarius Strobl * it can now thanks to firmware updates). The DP83861 also allows 5521211c45SMarius Strobl * access to its internal RAM via indirect register access. The 5621211c45SMarius Strobl * DP83865 is an ultra low power version of the DP83861 and DP83891. 57ce4946daSBill Paul */ 58ce4946daSBill Paul 59ce4946daSBill Paul #include <sys/param.h> 60ce4946daSBill Paul #include <sys/systm.h> 61ce4946daSBill Paul #include <sys/kernel.h> 6241ee9f1cSPoul-Henning Kamp #include <sys/module.h> 63ce4946daSBill Paul #include <sys/socket.h> 64ce4946daSBill Paul #include <sys/bus.h> 65ce4946daSBill Paul 66ce4946daSBill Paul #include <net/if.h> 67ce4946daSBill Paul #include <net/if_media.h> 68ce4946daSBill Paul 69ce4946daSBill Paul #include <dev/mii/mii.h> 70ce4946daSBill Paul #include <dev/mii/miivar.h> 712d3ce713SDavid E. O'Brien #include "miidevs.h" 72ce4946daSBill Paul 73ce4946daSBill Paul #include <dev/mii/nsgphyreg.h> 74ce4946daSBill Paul 75ce4946daSBill Paul #include "miibus_if.h" 76ce4946daSBill Paul 77e51a25f8SAlfred Perlstein static int nsgphy_probe(device_t); 78e51a25f8SAlfred Perlstein static int nsgphy_attach(device_t); 79ce4946daSBill Paul 80ce4946daSBill Paul static device_method_t nsgphy_methods[] = { 81ce4946daSBill Paul /* device interface */ 82ce4946daSBill Paul DEVMETHOD(device_probe, nsgphy_probe), 83ce4946daSBill Paul DEVMETHOD(device_attach, nsgphy_attach), 84279fe8d1SPoul-Henning Kamp DEVMETHOD(device_detach, mii_phy_detach), 85ce4946daSBill Paul DEVMETHOD(device_shutdown, bus_generic_shutdown), 86ce4946daSBill Paul { 0, 0 } 87ce4946daSBill Paul }; 88ce4946daSBill Paul 89ce4946daSBill Paul static devclass_t nsgphy_devclass; 90ce4946daSBill Paul 91ce4946daSBill Paul static driver_t nsgphy_driver = { 92ce4946daSBill Paul "nsgphy", 93ce4946daSBill Paul nsgphy_methods, 94ce4946daSBill Paul sizeof(struct mii_softc) 95ce4946daSBill Paul }; 96ce4946daSBill Paul 97ce4946daSBill Paul DRIVER_MODULE(nsgphy, miibus, nsgphy_driver, nsgphy_devclass, 0, 0); 98ce4946daSBill Paul 99e51a25f8SAlfred Perlstein static int nsgphy_service(struct mii_softc *, struct mii_data *,int); 100e51a25f8SAlfred Perlstein static void nsgphy_status(struct mii_softc *); 101ce4946daSBill Paul 102a35b9333SMarius Strobl static const struct mii_phydesc nsgphys[] = { 103a1039f82SWarner Losh MII_PHY_DESC(NATSEMI, DP83861), 10421211c45SMarius Strobl MII_PHY_DESC(NATSEMI, DP83865), 105a1039f82SWarner Losh MII_PHY_DESC(NATSEMI, DP83891), 106a1039f82SWarner Losh MII_PHY_END 107875525d5SPoul-Henning Kamp }; 108875525d5SPoul-Henning Kamp 1093aae18bdSPoul-Henning Kamp static int 1103aae18bdSPoul-Henning Kamp nsgphy_probe(device_t dev) 111ce4946daSBill Paul { 112ce4946daSBill Paul 113a35b9333SMarius Strobl return (mii_phy_dev_probe(dev, nsgphys, BUS_PROBE_DEFAULT)); 114ce4946daSBill Paul } 115ce4946daSBill Paul 1163aae18bdSPoul-Henning Kamp static int 1173aae18bdSPoul-Henning Kamp nsgphy_attach(device_t dev) 118ce4946daSBill Paul { 119ce4946daSBill Paul struct mii_softc *sc; 120ce4946daSBill Paul struct mii_attach_args *ma; 121ce4946daSBill Paul struct mii_data *mii; 122ce4946daSBill Paul 123ce4946daSBill Paul sc = device_get_softc(dev); 124ce4946daSBill Paul ma = device_get_ivars(dev); 125875525d5SPoul-Henning Kamp if (bootverbose) 126875525d5SPoul-Henning Kamp device_printf(dev, "<rev. %d>\n", MII_REV(ma->mii_id2)); 127875525d5SPoul-Henning Kamp device_printf(dev, " "); 128ce4946daSBill Paul sc->mii_dev = device_get_parent(dev); 1297b9a15f7SMarius Strobl mii = ma->mii_data; 130ce4946daSBill Paul LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); 131ce4946daSBill Paul 1328e5d93dbSMarius Strobl sc->mii_flags = miibus_get_flags(dev); 133de1add1eSMarius Strobl sc->mii_inst = mii->mii_instance++; 134ce4946daSBill Paul sc->mii_phy = ma->mii_phyno; 135ce4946daSBill Paul sc->mii_service = nsgphy_service; 136ce4946daSBill Paul sc->mii_pdata = mii; 137ce4946daSBill Paul 13821211c45SMarius Strobl mii_phy_reset(sc); 13921211c45SMarius Strobl 14021211c45SMarius Strobl /* 14121211c45SMarius Strobl * NB: the PHY has the 10baseT BMSR bits hard-wired to 0, 14221211c45SMarius Strobl * even though it supports 10baseT. 14321211c45SMarius Strobl */ 144b7dee1dbSPoul-Henning Kamp sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | 145ce4946daSBill Paul (BMSR_10TFDX | BMSR_10THDX)) & ma->mii_capmask; 146b7dee1dbSPoul-Henning Kamp if (sc->mii_capabilities & BMSR_EXTSTAT) 147b7dee1dbSPoul-Henning Kamp sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 14878c8c3dbSPoul-Henning Kamp 14978c8c3dbSPoul-Henning Kamp mii_phy_add_media(sc); 150ce4946daSBill Paul printf("\n"); 151ce4946daSBill Paul 152ce4946daSBill Paul MIIBUS_MEDIAINIT(sc->mii_dev); 153ce4946daSBill Paul return (0); 154ce4946daSBill Paul } 155ce4946daSBill Paul 1563aae18bdSPoul-Henning Kamp static int 1573aae18bdSPoul-Henning Kamp nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 158ce4946daSBill Paul { 159ce4946daSBill Paul 160ce4946daSBill Paul switch (cmd) { 161ce4946daSBill Paul case MII_POLLSTAT: 162ce4946daSBill Paul break; 163ce4946daSBill Paul 164ce4946daSBill Paul case MII_MEDIACHG: 165ce4946daSBill Paul /* 166ce4946daSBill Paul * If the interface is not up, don't do anything. 167ce4946daSBill Paul */ 168ce4946daSBill Paul if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 169ce4946daSBill Paul break; 170ce4946daSBill Paul 17178c8c3dbSPoul-Henning Kamp mii_phy_setmedia(sc); 172ce4946daSBill Paul break; 173ce4946daSBill Paul 174ce4946daSBill Paul case MII_TICK: 17578c8c3dbSPoul-Henning Kamp if (mii_phy_tick(sc) == EJUSTRETURN) 176ce4946daSBill Paul return (0); 177ce4946daSBill Paul break; 178ce4946daSBill Paul } 179ce4946daSBill Paul 180ce4946daSBill Paul /* Update the media status. */ 181ce4946daSBill Paul nsgphy_status(sc); 182ce4946daSBill Paul 183ce4946daSBill Paul /* Callback if something changed. */ 184d9730b8bSJonathan Lemon mii_phy_update(sc, cmd); 185ce4946daSBill Paul return (0); 186ce4946daSBill Paul } 187ce4946daSBill Paul 188d9730b8bSJonathan Lemon static void 1893aae18bdSPoul-Henning Kamp nsgphy_status(struct mii_softc *sc) 190ce4946daSBill Paul { 191ce4946daSBill Paul struct mii_data *mii = sc->mii_pdata; 19278c8c3dbSPoul-Henning Kamp struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 19378c8c3dbSPoul-Henning Kamp int bmsr, bmcr, physup, gtsr; 194ce4946daSBill Paul 195ce4946daSBill Paul mii->mii_media_status = IFM_AVALID; 196ce4946daSBill Paul mii->mii_media_active = IFM_ETHER; 197ce4946daSBill Paul 19878c8c3dbSPoul-Henning Kamp bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 1993aae18bdSPoul-Henning Kamp 200ce4946daSBill Paul physup = PHY_READ(sc, NSGPHY_MII_PHYSUP); 2013aae18bdSPoul-Henning Kamp 20278c8c3dbSPoul-Henning Kamp if (physup & PHY_SUP_LINK) 203ce4946daSBill Paul mii->mii_media_status |= IFM_ACTIVE; 204ce4946daSBill Paul 2053aae18bdSPoul-Henning Kamp bmcr = PHY_READ(sc, MII_BMCR); 20678c8c3dbSPoul-Henning Kamp if (bmcr & BMCR_ISO) { 20778c8c3dbSPoul-Henning Kamp mii->mii_media_active |= IFM_NONE; 20878c8c3dbSPoul-Henning Kamp mii->mii_media_status = 0; 20978c8c3dbSPoul-Henning Kamp return; 21078c8c3dbSPoul-Henning Kamp } 211ce4946daSBill Paul 2123aae18bdSPoul-Henning Kamp if (bmcr & BMCR_LOOP) 213ce4946daSBill Paul mii->mii_media_active |= IFM_LOOP; 214ce4946daSBill Paul 2153aae18bdSPoul-Henning Kamp if (bmcr & BMCR_AUTOEN) { 2163aae18bdSPoul-Henning Kamp /* 2173aae18bdSPoul-Henning Kamp * The media status bits are only valid if autonegotiation 2183aae18bdSPoul-Henning Kamp * has completed (or it's disabled). 2193aae18bdSPoul-Henning Kamp */ 2203aae18bdSPoul-Henning Kamp if ((bmsr & BMSR_ACOMP) == 0) { 221ce4946daSBill Paul /* Erg, still trying, I guess... */ 222ce4946daSBill Paul mii->mii_media_active |= IFM_NONE; 223ce4946daSBill Paul return; 224ce4946daSBill Paul } 225ce4946daSBill Paul 22678c8c3dbSPoul-Henning Kamp switch (physup & (PHY_SUP_SPEED1 | PHY_SUP_SPEED0)) { 22778c8c3dbSPoul-Henning Kamp case PHY_SUP_SPEED1: 228b418ad5cSPoul-Henning Kamp mii->mii_media_active |= IFM_1000_T; 22978c8c3dbSPoul-Henning Kamp gtsr = PHY_READ(sc, MII_100T2SR); 23078c8c3dbSPoul-Henning Kamp if (gtsr & GTSR_MS_RES) 23178c8c3dbSPoul-Henning Kamp mii->mii_media_active |= IFM_ETH_MASTER; 232ce4946daSBill Paul break; 23378c8c3dbSPoul-Henning Kamp 23478c8c3dbSPoul-Henning Kamp case PHY_SUP_SPEED0: 235ce4946daSBill Paul mii->mii_media_active |= IFM_100_TX; 236ce4946daSBill Paul break; 23778c8c3dbSPoul-Henning Kamp 23878c8c3dbSPoul-Henning Kamp case 0: 239ce4946daSBill Paul mii->mii_media_active |= IFM_10_T; 240ce4946daSBill Paul break; 24178c8c3dbSPoul-Henning Kamp 242ce4946daSBill Paul default: 24378c8c3dbSPoul-Henning Kamp mii->mii_media_active |= IFM_NONE; 24478c8c3dbSPoul-Henning Kamp mii->mii_media_status = 0; 24521211c45SMarius Strobl return; 246ce4946daSBill Paul } 24721211c45SMarius Strobl 24878c8c3dbSPoul-Henning Kamp if (physup & PHY_SUP_DUPLEX) 249*991ab941SMarius Strobl mii->mii_media_active |= 250*991ab941SMarius Strobl IFM_FDX | mii_phy_flowstatus(sc); 25121211c45SMarius Strobl else 25221211c45SMarius Strobl mii->mii_media_active |= IFM_HDX; 25378c8c3dbSPoul-Henning Kamp } else 25478c8c3dbSPoul-Henning Kamp mii->mii_media_active = ife->ifm_media; 255ce4946daSBill Paul } 256