1*112a855dSMarius Strobl /*- 2*112a855dSMarius Strobl * Copyright (c) 2001 Jonathan Lemon 3*112a855dSMarius Strobl * All rights reserved. 4*112a855dSMarius Strobl * 5*112a855dSMarius Strobl * Redistribution and use in source and binary forms, with or without 6*112a855dSMarius Strobl * modification, are permitted provided that the following conditions 7*112a855dSMarius Strobl * are met: 8*112a855dSMarius Strobl * 1. Redistributions of source code must retain the above copyright 9*112a855dSMarius Strobl * notice, this list of conditions and the following disclaimer. 10*112a855dSMarius Strobl * 2. Redistributions in binary form must reproduce the above copyright 11*112a855dSMarius Strobl * notice, this list of conditions and the following disclaimer in the 12*112a855dSMarius Strobl * documentation and/or other materials provided with the distribution. 13*112a855dSMarius Strobl * 3. Neither the name of the author nor the names of any co-contributors 14*112a855dSMarius Strobl * may be used to endorse or promote products derived from this software 15*112a855dSMarius Strobl * without specific prior written permission. 16*112a855dSMarius Strobl * 17*112a855dSMarius Strobl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18*112a855dSMarius Strobl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*112a855dSMarius Strobl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*112a855dSMarius Strobl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21*112a855dSMarius Strobl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*112a855dSMarius Strobl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*112a855dSMarius Strobl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*112a855dSMarius Strobl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*112a855dSMarius Strobl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*112a855dSMarius Strobl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*112a855dSMarius Strobl * SUCH DAMAGE. 28*112a855dSMarius Strobl * 29*112a855dSMarius Strobl */ 30*112a855dSMarius Strobl 31*112a855dSMarius Strobl #include <sys/cdefs.h> 32*112a855dSMarius Strobl __FBSDID("$FreeBSD$"); 33*112a855dSMarius Strobl 34*112a855dSMarius Strobl /* 35*112a855dSMarius Strobl * driver for Intel 82553 and 82555 PHYs 36*112a855dSMarius Strobl */ 37*112a855dSMarius Strobl 38*112a855dSMarius Strobl #include <sys/param.h> 39*112a855dSMarius Strobl #include <sys/systm.h> 40*112a855dSMarius Strobl #include <sys/kernel.h> 41*112a855dSMarius Strobl #include <sys/module.h> 42*112a855dSMarius Strobl #include <sys/socket.h> 43*112a855dSMarius Strobl #include <sys/bus.h> 44*112a855dSMarius Strobl 45*112a855dSMarius Strobl #include <net/if.h> 46*112a855dSMarius Strobl #include <net/if_media.h> 47*112a855dSMarius Strobl 48*112a855dSMarius Strobl #include <dev/mii/mii.h> 49*112a855dSMarius Strobl #include <dev/mii/miivar.h> 50*112a855dSMarius Strobl #include "miidevs.h" 51*112a855dSMarius Strobl 52*112a855dSMarius Strobl #include <dev/fxp/inphyreg.h> 53*112a855dSMarius Strobl 54*112a855dSMarius Strobl #include "miibus_if.h" 55*112a855dSMarius Strobl 56*112a855dSMarius Strobl static int inphy_probe(device_t dev); 57*112a855dSMarius Strobl static int inphy_attach(device_t dev); 58*112a855dSMarius Strobl 59*112a855dSMarius Strobl static device_method_t inphy_methods[] = { 60*112a855dSMarius Strobl /* device interface */ 61*112a855dSMarius Strobl DEVMETHOD(device_probe, inphy_probe), 62*112a855dSMarius Strobl DEVMETHOD(device_attach, inphy_attach), 63*112a855dSMarius Strobl DEVMETHOD(device_detach, mii_phy_detach), 64*112a855dSMarius Strobl DEVMETHOD(device_shutdown, bus_generic_shutdown), 65*112a855dSMarius Strobl { 0, 0 } 66*112a855dSMarius Strobl }; 67*112a855dSMarius Strobl 68*112a855dSMarius Strobl static devclass_t inphy_devclass; 69*112a855dSMarius Strobl 70*112a855dSMarius Strobl static driver_t inphy_driver = { 71*112a855dSMarius Strobl "inphy", 72*112a855dSMarius Strobl inphy_methods, 73*112a855dSMarius Strobl sizeof(struct mii_softc) 74*112a855dSMarius Strobl }; 75*112a855dSMarius Strobl 76*112a855dSMarius Strobl DRIVER_MODULE(inphy, miibus, inphy_driver, inphy_devclass, 0, 0); 77*112a855dSMarius Strobl 78*112a855dSMarius Strobl static int inphy_service(struct mii_softc *, struct mii_data *, int); 79*112a855dSMarius Strobl static void inphy_status(struct mii_softc *); 80*112a855dSMarius Strobl static void inphy_reset(struct mii_softc *); 81*112a855dSMarius Strobl 82*112a855dSMarius Strobl static const struct mii_phydesc inphys[] = { 83*112a855dSMarius Strobl MII_PHY_DESC(xxINTEL, I82553), 84*112a855dSMarius Strobl MII_PHY_DESC(yyINTEL, I82553), 85*112a855dSMarius Strobl MII_PHY_DESC(yyINTEL, I82555), 86*112a855dSMarius Strobl MII_PHY_DESC(yyINTEL, I82562EM), 87*112a855dSMarius Strobl MII_PHY_DESC(yyINTEL, I82562ET), 88*112a855dSMarius Strobl MII_PHY_END 89*112a855dSMarius Strobl }; 90*112a855dSMarius Strobl 91*112a855dSMarius Strobl static const struct mii_phy_funcs inphy_funcs = { 92*112a855dSMarius Strobl inphy_service, 93*112a855dSMarius Strobl inphy_status, 94*112a855dSMarius Strobl inphy_reset 95*112a855dSMarius Strobl }; 96*112a855dSMarius Strobl 97*112a855dSMarius Strobl static int 98*112a855dSMarius Strobl inphy_probe(device_t dev) 99*112a855dSMarius Strobl { 100*112a855dSMarius Strobl 101*112a855dSMarius Strobl return (mii_phy_dev_probe(dev, inphys, BUS_PROBE_DEFAULT)); 102*112a855dSMarius Strobl } 103*112a855dSMarius Strobl 104*112a855dSMarius Strobl static int 105*112a855dSMarius Strobl inphy_attach(device_t dev) 106*112a855dSMarius Strobl { 107*112a855dSMarius Strobl 108*112a855dSMarius Strobl mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &inphy_funcs, 1); 109*112a855dSMarius Strobl return (0); 110*112a855dSMarius Strobl } 111*112a855dSMarius Strobl 112*112a855dSMarius Strobl static int 113*112a855dSMarius Strobl inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 114*112a855dSMarius Strobl { 115*112a855dSMarius Strobl 116*112a855dSMarius Strobl switch (cmd) { 117*112a855dSMarius Strobl case MII_POLLSTAT: 118*112a855dSMarius Strobl break; 119*112a855dSMarius Strobl 120*112a855dSMarius Strobl case MII_MEDIACHG: 121*112a855dSMarius Strobl /* 122*112a855dSMarius Strobl * If the interface is not up, don't do anything. 123*112a855dSMarius Strobl */ 124*112a855dSMarius Strobl if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 125*112a855dSMarius Strobl break; 126*112a855dSMarius Strobl 127*112a855dSMarius Strobl mii_phy_setmedia(sc); 128*112a855dSMarius Strobl break; 129*112a855dSMarius Strobl 130*112a855dSMarius Strobl case MII_TICK: 131*112a855dSMarius Strobl if (mii_phy_tick(sc) == EJUSTRETURN) 132*112a855dSMarius Strobl return (0); 133*112a855dSMarius Strobl break; 134*112a855dSMarius Strobl } 135*112a855dSMarius Strobl 136*112a855dSMarius Strobl /* Update the media status. */ 137*112a855dSMarius Strobl PHY_STATUS(sc); 138*112a855dSMarius Strobl 139*112a855dSMarius Strobl /* Callback if something changed. */ 140*112a855dSMarius Strobl mii_phy_update(sc, cmd); 141*112a855dSMarius Strobl return (0); 142*112a855dSMarius Strobl } 143*112a855dSMarius Strobl 144*112a855dSMarius Strobl static void 145*112a855dSMarius Strobl inphy_status(struct mii_softc *sc) 146*112a855dSMarius Strobl { 147*112a855dSMarius Strobl struct mii_data *mii = sc->mii_pdata; 148*112a855dSMarius Strobl struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 149*112a855dSMarius Strobl int bmsr, bmcr, scr; 150*112a855dSMarius Strobl 151*112a855dSMarius Strobl mii->mii_media_status = IFM_AVALID; 152*112a855dSMarius Strobl mii->mii_media_active = IFM_ETHER; 153*112a855dSMarius Strobl 154*112a855dSMarius Strobl bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 155*112a855dSMarius Strobl if (bmsr & BMSR_LINK) 156*112a855dSMarius Strobl mii->mii_media_status |= IFM_ACTIVE; 157*112a855dSMarius Strobl 158*112a855dSMarius Strobl bmcr = PHY_READ(sc, MII_BMCR); 159*112a855dSMarius Strobl if (bmcr & BMCR_ISO) { 160*112a855dSMarius Strobl mii->mii_media_active |= IFM_NONE; 161*112a855dSMarius Strobl mii->mii_media_status = 0; 162*112a855dSMarius Strobl return; 163*112a855dSMarius Strobl } 164*112a855dSMarius Strobl 165*112a855dSMarius Strobl if (bmcr & BMCR_LOOP) 166*112a855dSMarius Strobl mii->mii_media_active |= IFM_LOOP; 167*112a855dSMarius Strobl 168*112a855dSMarius Strobl if (bmcr & BMCR_AUTOEN) { 169*112a855dSMarius Strobl if ((bmsr & BMSR_ACOMP) == 0) { 170*112a855dSMarius Strobl mii->mii_media_active |= IFM_NONE; 171*112a855dSMarius Strobl return; 172*112a855dSMarius Strobl } 173*112a855dSMarius Strobl 174*112a855dSMarius Strobl scr = PHY_READ(sc, MII_INPHY_SCR); 175*112a855dSMarius Strobl if (scr & SCR_S100) 176*112a855dSMarius Strobl mii->mii_media_active |= IFM_100_TX; 177*112a855dSMarius Strobl else 178*112a855dSMarius Strobl mii->mii_media_active |= IFM_10_T; 179*112a855dSMarius Strobl if (scr & SCR_FDX) 180*112a855dSMarius Strobl mii->mii_media_active |= 181*112a855dSMarius Strobl IFM_FDX | mii_phy_flowstatus(sc); 182*112a855dSMarius Strobl else 183*112a855dSMarius Strobl mii->mii_media_active |= IFM_HDX; 184*112a855dSMarius Strobl } else 185*112a855dSMarius Strobl mii->mii_media_active = ife->ifm_media; 186*112a855dSMarius Strobl } 187*112a855dSMarius Strobl 188*112a855dSMarius Strobl static void 189*112a855dSMarius Strobl inphy_reset(struct mii_softc *sc) 190*112a855dSMarius Strobl { 191*112a855dSMarius Strobl 192*112a855dSMarius Strobl mii_phy_reset(sc); 193*112a855dSMarius Strobl 194*112a855dSMarius Strobl /* Ensure Bay flow control is disabled. */ 195*112a855dSMarius Strobl PHY_WRITE(sc, MII_INPHY_SCR, 196*112a855dSMarius Strobl PHY_READ(sc, MII_INPHY_SCR) & ~SCR_FLOWCTL); 197*112a855dSMarius Strobl } 198