1139749Simp/*- 276479Swpaul * Copyright (c) 2001 Wind River Systems 376479Swpaul * Copyright (c) 2001 476479Swpaul * Bill Paul <wpaul@bsdi.com>. All rights reserved. 595718Sphk * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 695718Sphk * All rights reserved. 776479Swpaul * 895718Sphk * This code is derived from software contributed to The NetBSD Foundation 995718Sphk * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 1095718Sphk * NASA Ames Research Center. 1195718Sphk * 1276479Swpaul * Redistribution and use in source and binary forms, with or without 1376479Swpaul * modification, are permitted provided that the following conditions 1476479Swpaul * are met: 1576479Swpaul * 1. Redistributions of source code must retain the above copyright 1676479Swpaul * notice, this list of conditions and the following disclaimer. 1776479Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1876479Swpaul * notice, this list of conditions and the following disclaimer in the 1976479Swpaul * documentation and/or other materials provided with the distribution. 2076479Swpaul * 3. All advertising materials mentioning features or use of this software 2176479Swpaul * must display the following acknowledgement: 2276479Swpaul * This product includes software developed by Bill Paul. 2376479Swpaul * 4. Neither the name of the author nor the names of any co-contributors 2476479Swpaul * may be used to endorse or promote products derived from this software 2576479Swpaul * without specific prior written permission. 2676479Swpaul * 2776479Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2876479Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2976479Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3076479Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 3176479Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3276479Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3376479Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3476479Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3576479Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3676479Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3776479Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 3876479Swpaul */ 3976479Swpaul 40119418Sobrien#include <sys/cdefs.h> 41119418Sobrien__FBSDID("$FreeBSD$"); 42119418Sobrien 4376479Swpaul/* 44194134Smarius * Driver for the National Semiconductor DP83861, DP83865 and DP83891 4576479Swpaul * 10/100/1000 PHYs. 4676479Swpaul * Datasheet available at: http://www.national.com/ds/DP/DP83861.pdf 47194134Smarius * and at: http://www.national.com/ds/DP/DP83865.pdf 4876479Swpaul * 49194134Smarius * The DP83891 is the older NS GigE PHY which isn't being sold 50194134Smarius * anymore. The DP83861 is its replacement, which is an 'enhanced' 51194134Smarius * firmware driven component. The major difference between the 52194134Smarius * two is that the DP83891 can't generate interrupts, while the 53194134Smarius * 83861 can (probably it wasn't originally designed to do this, but 54194134Smarius * it can now thanks to firmware updates). The DP83861 also allows 55194134Smarius * access to its internal RAM via indirect register access. The 56194134Smarius * DP83865 is an ultra low power version of the DP83861 and DP83891. 5776479Swpaul */ 5876479Swpaul 5976479Swpaul#include <sys/param.h> 6076479Swpaul#include <sys/systm.h> 6176479Swpaul#include <sys/kernel.h> 62129876Sphk#include <sys/module.h> 6376479Swpaul#include <sys/socket.h> 6476479Swpaul#include <sys/bus.h> 6576479Swpaul 6676479Swpaul#include <net/if.h> 6776479Swpaul#include <net/if_media.h> 6876479Swpaul 6976479Swpaul#include <dev/mii/mii.h> 7076479Swpaul#include <dev/mii/miivar.h> 71109514Sobrien#include "miidevs.h" 7276479Swpaul 7376479Swpaul#include <dev/mii/nsgphyreg.h> 7476479Swpaul 7576479Swpaul#include "miibus_if.h" 7676479Swpaul 77105135Salfredstatic int nsgphy_probe(device_t); 78105135Salfredstatic int nsgphy_attach(device_t); 7976479Swpaul 8076479Swpaulstatic device_method_t nsgphy_methods[] = { 8176479Swpaul /* device interface */ 8276479Swpaul DEVMETHOD(device_probe, nsgphy_probe), 8376479Swpaul DEVMETHOD(device_attach, nsgphy_attach), 8495722Sphk DEVMETHOD(device_detach, mii_phy_detach), 8576479Swpaul DEVMETHOD(device_shutdown, bus_generic_shutdown), 86227908Smarius DEVMETHOD_END 8776479Swpaul}; 8876479Swpaul 8976479Swpaulstatic devclass_t nsgphy_devclass; 9076479Swpaul 9176479Swpaulstatic driver_t nsgphy_driver = { 9276479Swpaul "nsgphy", 9376479Swpaul nsgphy_methods, 9476479Swpaul sizeof(struct mii_softc) 9576479Swpaul}; 9676479Swpaul 9776479SwpaulDRIVER_MODULE(nsgphy, miibus, nsgphy_driver, nsgphy_devclass, 0, 0); 9876479Swpaul 9992739Salfredstatic int nsgphy_service(struct mii_softc *, struct mii_data *,int); 10092739Salfredstatic void nsgphy_status(struct mii_softc *); 10176479Swpaul 102164827Smariusstatic const struct mii_phydesc nsgphys[] = { 103221407Smarius MII_PHY_DESC(xxNATSEMI, DP83861), 104221407Smarius MII_PHY_DESC(xxNATSEMI, DP83865), 105221407Smarius MII_PHY_DESC(xxNATSEMI, DP83891), 106150755Simp MII_PHY_END 10795724Sphk}; 10895724Sphk 109221407Smariusstatic const struct mii_phy_funcs nsgphy_funcs = { 110221407Smarius nsgphy_service, 111221407Smarius nsgphy_status, 112221407Smarius mii_phy_reset 113221407Smarius}; 114221407Smarius 11595664Sphkstatic int 11695664Sphknsgphy_probe(device_t dev) 11776479Swpaul{ 11876479Swpaul 119164827Smarius return (mii_phy_dev_probe(dev, nsgphys, BUS_PROBE_DEFAULT)); 12076479Swpaul} 12176479Swpaul 12295664Sphkstatic int 12395664Sphknsgphy_attach(device_t dev) 12476479Swpaul{ 12576479Swpaul struct mii_softc *sc; 12676479Swpaul 12776479Swpaul sc = device_get_softc(dev); 12876479Swpaul 129221407Smarius mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsgphy_funcs, 0); 13076479Swpaul 131221407Smarius PHY_RESET(sc); 132215714Smarius 133194134Smarius /* 134216623Smarius * NB: the PHY has the 10BASE-T BMSR bits hard-wired to 0, 135216623Smarius * even though it supports 10BASE-T. 136194134Smarius */ 13795707Sphk sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | 138221407Smarius BMSR_10TFDX | BMSR_10THDX) & sc->mii_capmask; 139216623Smarius /* 140216623Smarius * Note that as documented manual 1000BASE-T modes of DP83865 only 141216623Smarius * work together with other National Semiconductor PHYs. 142216623Smarius */ 14395707Sphk if (sc->mii_capabilities & BMSR_EXTSTAT) 14495707Sphk sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); 14595718Sphk 14695718Sphk mii_phy_add_media(sc); 14776479Swpaul printf("\n"); 14876479Swpaul 14976479Swpaul MIIBUS_MEDIAINIT(sc->mii_dev); 150164707Smarius return (0); 15176479Swpaul} 15276479Swpaul 15395664Sphkstatic int 15495664Sphknsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 15576479Swpaul{ 15676479Swpaul 15776479Swpaul switch (cmd) { 15876479Swpaul case MII_POLLSTAT: 15976479Swpaul break; 16076479Swpaul 16176479Swpaul case MII_MEDIACHG: 16276479Swpaul /* 16376479Swpaul * If the interface is not up, don't do anything. 16476479Swpaul */ 16576479Swpaul if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 16676479Swpaul break; 16776479Swpaul 16895718Sphk mii_phy_setmedia(sc); 16976479Swpaul break; 17076479Swpaul 17176479Swpaul case MII_TICK: 17295718Sphk if (mii_phy_tick(sc) == EJUSTRETURN) 17384145Sjlemon return (0); 17476479Swpaul break; 17576479Swpaul } 17676479Swpaul 17776479Swpaul /* Update the media status. */ 178221407Smarius PHY_STATUS(sc); 17976479Swpaul 18076479Swpaul /* Callback if something changed. */ 18184145Sjlemon mii_phy_update(sc, cmd); 18276479Swpaul return (0); 18376479Swpaul} 18476479Swpaul 18584145Sjlemonstatic void 18695664Sphknsgphy_status(struct mii_softc *sc) 18776479Swpaul{ 18876479Swpaul struct mii_data *mii = sc->mii_pdata; 18995718Sphk struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 19095718Sphk int bmsr, bmcr, physup, gtsr; 19176479Swpaul 19276479Swpaul mii->mii_media_status = IFM_AVALID; 19376479Swpaul mii->mii_media_active = IFM_ETHER; 19476479Swpaul 19595718Sphk bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 19695664Sphk 19776479Swpaul physup = PHY_READ(sc, NSGPHY_MII_PHYSUP); 19895664Sphk 19995718Sphk if (physup & PHY_SUP_LINK) 20076479Swpaul mii->mii_media_status |= IFM_ACTIVE; 20176479Swpaul 20295664Sphk bmcr = PHY_READ(sc, MII_BMCR); 20395718Sphk if (bmcr & BMCR_ISO) { 20495718Sphk mii->mii_media_active |= IFM_NONE; 20595718Sphk mii->mii_media_status = 0; 20695718Sphk return; 20795718Sphk } 20876479Swpaul 20995664Sphk if (bmcr & BMCR_LOOP) 21076479Swpaul mii->mii_media_active |= IFM_LOOP; 21176479Swpaul 21295664Sphk if (bmcr & BMCR_AUTOEN) { 21395664Sphk /* 21495664Sphk * The media status bits are only valid if autonegotiation 21595664Sphk * has completed (or it's disabled). 21695664Sphk */ 21795664Sphk if ((bmsr & BMSR_ACOMP) == 0) { 21876479Swpaul /* Erg, still trying, I guess... */ 21976479Swpaul mii->mii_media_active |= IFM_NONE; 22076479Swpaul return; 22176479Swpaul } 22276479Swpaul 223194134Smarius switch (physup & (PHY_SUP_SPEED1 | PHY_SUP_SPEED0)) { 22495718Sphk case PHY_SUP_SPEED1: 22595718Sphk mii->mii_media_active |= IFM_1000_T; 22695718Sphk gtsr = PHY_READ(sc, MII_100T2SR); 22795718Sphk if (gtsr & GTSR_MS_RES) 22895718Sphk mii->mii_media_active |= IFM_ETH_MASTER; 22995718Sphk break; 23076479Swpaul 23195718Sphk case PHY_SUP_SPEED0: 23295718Sphk mii->mii_media_active |= IFM_100_TX; 23395718Sphk break; 23476479Swpaul 23595718Sphk case 0: 23695718Sphk mii->mii_media_active |= IFM_10_T; 23795718Sphk break; 23876479Swpaul 23995718Sphk default: 24095718Sphk mii->mii_media_active |= IFM_NONE; 24195718Sphk mii->mii_media_status = 0; 242194134Smarius return; 24376479Swpaul } 244194134Smarius 24595718Sphk if (physup & PHY_SUP_DUPLEX) 246215298Smarius mii->mii_media_active |= 247215298Smarius IFM_FDX | mii_phy_flowstatus(sc); 248194134Smarius else 249194134Smarius mii->mii_media_active |= IFM_HDX; 25095718Sphk } else 25195718Sphk mii->mii_media_active = ife->ifm_media; 25276479Swpaul} 253