1175702Smarius/* $NetBSD: nsphyter.c,v 1.28 2008/01/20 07:58:19 msaitoh Exp $ */ 2175702Smarius 3175702Smarius/*- 4175702Smarius * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 5175702Smarius * All rights reserved. 6175702Smarius * 7175702Smarius * This code is derived from software contributed to The NetBSD Foundation 8175702Smarius * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9175702Smarius * NASA Ames Research Center. 10175702Smarius * 11175702Smarius * Redistribution and use in source and binary forms, with or without 12175702Smarius * modification, are permitted provided that the following conditions 13175702Smarius * are met: 14175702Smarius * 1. Redistributions of source code must retain the above copyright 15175702Smarius * notice, this list of conditions and the following disclaimer. 16175702Smarius * 2. Redistributions in binary form must reproduce the above copyright 17175702Smarius * notice, this list of conditions and the following disclaimer in the 18175702Smarius * documentation and/or other materials provided with the distribution. 19175702Smarius * 20175702Smarius * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21175702Smarius * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22175702Smarius * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23175702Smarius * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24175702Smarius * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25175702Smarius * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26175702Smarius * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27175702Smarius * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28175702Smarius * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29175702Smarius * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30175702Smarius * POSSIBILITY OF SUCH DAMAGE. 31175702Smarius */ 32175702Smarius 33175702Smarius/*- 34175702Smarius * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 35175702Smarius * 36175702Smarius * Redistribution and use in source and binary forms, with or without 37175702Smarius * modification, are permitted provided that the following conditions 38175702Smarius * are met: 39175702Smarius * 1. Redistributions of source code must retain the above copyright 40175702Smarius * notice, this list of conditions and the following disclaimer. 41175702Smarius * 2. Redistributions in binary form must reproduce the above copyright 42175702Smarius * notice, this list of conditions and the following disclaimer in the 43175702Smarius * documentation and/or other materials provided with the distribution. 44175702Smarius * 45175702Smarius * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46175702Smarius * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47175702Smarius * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48175702Smarius * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49175702Smarius * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50175702Smarius * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51175702Smarius * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52175702Smarius * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53175702Smarius * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54175702Smarius * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55175702Smarius */ 56175702Smarius 57175702Smarius#include <sys/cdefs.h> 58175702Smarius__FBSDID("$FreeBSD$"); 59175702Smarius 60175702Smarius/* 61231914Smarius * Driver for the National Semiconductor's DP83843, DP83847 and DP83849 62231914Smarius * `PHYTER' Ethernet 10/100 PHYs 63231914Smarius * Data Sheets are available from http://www.national.com 64175702Smarius * 65175702Smarius * We also support the DP83815 `MacPHYTER' internal PHY since, for our 66175702Smarius * purposes, they are compatible. 67175702Smarius */ 68175702Smarius 69175702Smarius#include <sys/param.h> 70175702Smarius#include <sys/systm.h> 71175702Smarius#include <sys/bus.h> 72175702Smarius#include <sys/errno.h> 73175702Smarius#include <sys/kernel.h> 74175702Smarius#include <sys/module.h> 75175702Smarius#include <sys/socket.h> 76175702Smarius 77175702Smarius#include <net/if.h> 78175702Smarius#include <net/if_media.h> 79175702Smarius 80175702Smarius#include <dev/mii/mii.h> 81175702Smarius#include <dev/mii/miivar.h> 82175702Smarius#include "miidevs.h" 83175702Smarius 84175702Smarius#include <dev/mii/nsphyterreg.h> 85175702Smarius 86175702Smarius#include "miibus_if.h" 87175702Smarius 88175702Smariusstatic device_probe_t nsphyter_probe; 89175702Smariusstatic device_attach_t nsphyter_attach; 90175702Smarius 91175702Smariusstatic device_method_t nsphyter_methods[] = { 92175702Smarius /* device interface */ 93175702Smarius DEVMETHOD(device_probe, nsphyter_probe), 94175702Smarius DEVMETHOD(device_attach, nsphyter_attach), 95175702Smarius DEVMETHOD(device_detach, mii_phy_detach), 96175702Smarius DEVMETHOD(device_shutdown, bus_generic_shutdown), 97227908Smarius DEVMETHOD_END 98175702Smarius}; 99175702Smarius 100175702Smariusstatic devclass_t nsphyter_devclass; 101175702Smarius 102175702Smariusstatic driver_t nsphyter_driver = { 103175702Smarius "nsphyter", 104175702Smarius nsphyter_methods, 105175702Smarius sizeof(struct mii_softc) 106175702Smarius}; 107175702Smarius 108175702SmariusDRIVER_MODULE(nsphyter, miibus, nsphyter_driver, nsphyter_devclass, 0, 0); 109175702Smarius 110175702Smariusstatic int nsphyter_service(struct mii_softc *, struct mii_data *, int); 111175702Smariusstatic void nsphyter_status(struct mii_softc *); 112175702Smariusstatic void nsphyter_reset(struct mii_softc *); 113175702Smarius 114221407Smariusstatic const struct mii_phydesc nsphyters[] = { 115221407Smarius MII_PHY_DESC(xxNATSEMI, DP83815), 116221407Smarius MII_PHY_DESC(xxNATSEMI, DP83843), 117221407Smarius MII_PHY_DESC(xxNATSEMI, DP83847), 118231914Smarius MII_PHY_DESC(xxNATSEMI, DP83849), 119175702Smarius MII_PHY_END 120175702Smarius}; 121175702Smarius 122221407Smariusstatic const struct mii_phy_funcs nsphyter_funcs = { 123221407Smarius nsphyter_service, 124221407Smarius nsphyter_status, 125221407Smarius nsphyter_reset 126221407Smarius}; 127221407Smarius 128175702Smariusstatic int 129175702Smariusnsphyter_probe(device_t dev) 130175702Smarius{ 131175702Smarius 132221407Smarius return (mii_phy_dev_probe(dev, nsphyters, BUS_PROBE_DEFAULT)); 133175702Smarius} 134175702Smarius 135175702Smariusstatic int 136175702Smariusnsphyter_attach(device_t dev) 137175702Smarius{ 138175702Smarius 139221407Smarius mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsphyter_funcs, 1); 140175702Smarius return (0); 141175702Smarius} 142175702Smarius 143175702Smariusstatic int 144175702Smariusnsphyter_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 145175702Smarius{ 146175702Smarius 147175702Smarius switch (cmd) { 148175702Smarius case MII_POLLSTAT: 149175702Smarius break; 150175702Smarius 151175702Smarius case MII_MEDIACHG: 152175702Smarius /* 153175702Smarius * If the interface is not up, don't do anything. 154175702Smarius */ 155175702Smarius if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 156175702Smarius break; 157175702Smarius 158175702Smarius mii_phy_setmedia(sc); 159175702Smarius break; 160175702Smarius 161175702Smarius case MII_TICK: 162175702Smarius if (mii_phy_tick(sc) == EJUSTRETURN) 163175702Smarius return (0); 164175702Smarius break; 165175702Smarius } 166175702Smarius 167175702Smarius /* Update the media status. */ 168221407Smarius PHY_STATUS(sc); 169175702Smarius 170175702Smarius /* Callback if something changed. */ 171175702Smarius mii_phy_update(sc, cmd); 172175702Smarius return (0); 173175702Smarius} 174175702Smarius 175175702Smariusstatic void 176175702Smariusnsphyter_status(struct mii_softc *sc) 177175702Smarius{ 178175702Smarius struct mii_data *mii = sc->mii_pdata; 179175702Smarius struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 180175702Smarius int bmsr, bmcr, physts; 181175702Smarius 182175702Smarius mii->mii_media_status = IFM_AVALID; 183175702Smarius mii->mii_media_active = IFM_ETHER; 184175702Smarius 185175702Smarius bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 186175702Smarius physts = PHY_READ(sc, MII_NSPHYTER_PHYSTS); 187175702Smarius 188175702Smarius if ((physts & PHYSTS_LINK) != 0) 189175702Smarius mii->mii_media_status |= IFM_ACTIVE; 190175702Smarius 191175702Smarius bmcr = PHY_READ(sc, MII_BMCR); 192175702Smarius if ((bmcr & BMCR_ISO) != 0) { 193175702Smarius mii->mii_media_active |= IFM_NONE; 194175702Smarius mii->mii_media_status = 0; 195175702Smarius return; 196175702Smarius } 197175702Smarius 198175702Smarius if ((bmcr & BMCR_LOOP) != 0) 199175702Smarius mii->mii_media_active |= IFM_LOOP; 200175702Smarius 201175702Smarius if ((bmcr & BMCR_AUTOEN) != 0) { 202175702Smarius /* 203175702Smarius * The media status bits are only valid if autonegotiation 204175702Smarius * has completed (or it's disabled). 205175702Smarius */ 206175702Smarius if ((bmsr & BMSR_ACOMP) == 0) { 207175702Smarius /* Erg, still trying, I guess... */ 208175702Smarius mii->mii_media_active |= IFM_NONE; 209175702Smarius return; 210175702Smarius } 211175702Smarius 212175702Smarius if ((physts & PHYSTS_SPEED10) != 0) 213175702Smarius mii->mii_media_active |= IFM_10_T; 214175702Smarius else 215175702Smarius mii->mii_media_active |= IFM_100_TX; 216175702Smarius if ((physts & PHYSTS_DUPLEX) != 0) 217175702Smarius mii->mii_media_active |= 218175702Smarius IFM_FDX | mii_phy_flowstatus(sc); 219175702Smarius else 220175702Smarius mii->mii_media_active |= IFM_HDX; 221175702Smarius } else 222175702Smarius mii->mii_media_active = ife->ifm_media; 223175702Smarius} 224175702Smarius 225175702Smariusstatic void 226175702Smariusnsphyter_reset(struct mii_softc *sc) 227175702Smarius{ 228175702Smarius struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; 229175702Smarius int reg, i; 230175702Smarius 231175702Smarius if ((sc->mii_flags & MIIF_NOISOLATE) != 0) 232175702Smarius reg = BMCR_RESET; 233175702Smarius else 234175702Smarius reg = BMCR_RESET | BMCR_ISO; 235175702Smarius PHY_WRITE(sc, MII_BMCR, reg); 236175702Smarius 237175702Smarius /* 238175702Smarius * It is best to allow a little time for the reset to settle 239175702Smarius * in before we start polling the BMCR again. Notably, the 240175702Smarius * DP8384{3,7} manuals state that there should be a 500us delay 241175702Smarius * between asserting software reset and attempting MII serial 242175702Smarius * operations. Be conservative. Also, a DP83815 can get into 243175702Smarius * a bad state on cable removal and reinsertion if we do not 244175702Smarius * delay here. 245175702Smarius */ 246175702Smarius DELAY(1000); 247175702Smarius 248175702Smarius /* 249175702Smarius * Wait another 2s for it to complete. 250175702Smarius * This is only a little overkill as under normal circumstances 251175702Smarius * the PHY can take up to 1s to complete reset. 252175702Smarius * This is also a bit odd because after a reset, the BMCR will 253175702Smarius * clear the reset bit and simply reports 0 even though the reset 254175702Smarius * is not yet complete. 255175702Smarius */ 256175702Smarius for (i = 0; i < 1000; i++) { 257175702Smarius reg = PHY_READ(sc, MII_BMCR); 258175702Smarius if (reg != 0 && (reg & BMCR_RESET) == 0) 259175702Smarius break; 260175702Smarius DELAY(2000); 261175702Smarius } 262175702Smarius 263175702Smarius if ((sc->mii_flags & MIIF_NOISOLATE) == 0) { 264175702Smarius if ((ife == NULL && sc->mii_inst != 0) || 265175702Smarius (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)) 266175702Smarius PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 267175702Smarius } 268175702Smarius} 269