172132Ssemenu/*- 272132Ssemenu * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. 372132Ssemenu * All rights reserved. 472132Ssemenu * 572132Ssemenu * This code is derived from software contributed to The NetBSD Foundation 672132Ssemenu * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 772132Ssemenu * NASA Ames Research Center. 872132Ssemenu * 972132Ssemenu * Redistribution and use in source and binary forms, with or without 1072132Ssemenu * modification, are permitted provided that the following conditions 1172132Ssemenu * are met: 1272132Ssemenu * 1. Redistributions of source code must retain the above copyright 1372132Ssemenu * notice, this list of conditions and the following disclaimer. 1472132Ssemenu * 2. Redistributions in binary form must reproduce the above copyright 1572132Ssemenu * notice, this list of conditions and the following disclaimer in the 1672132Ssemenu * documentation and/or other materials provided with the distribution. 1772132Ssemenu * 1872132Ssemenu * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 1972132Ssemenu * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2072132Ssemenu * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2172132Ssemenu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2272132Ssemenu * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2372132Ssemenu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2472132Ssemenu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2572132Ssemenu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2672132Ssemenu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2772132Ssemenu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2872132Ssemenu * POSSIBILITY OF SUCH DAMAGE. 2972132Ssemenu */ 30119418Sobrien 31139749Simp/*- 3272132Ssemenu * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 3372132Ssemenu * 3472132Ssemenu * Redistribution and use in source and binary forms, with or without 3572132Ssemenu * modification, are permitted provided that the following conditions 3672132Ssemenu * are met: 3772132Ssemenu * 1. Redistributions of source code must retain the above copyright 3872132Ssemenu * notice, this list of conditions and the following disclaimer. 3972132Ssemenu * 2. Redistributions in binary form must reproduce the above copyright 4072132Ssemenu * notice, this list of conditions and the following disclaimer in the 4172132Ssemenu * documentation and/or other materials provided with the distribution. 4272132Ssemenu * 4372132Ssemenu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4472132Ssemenu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 4572132Ssemenu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 4672132Ssemenu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 4772132Ssemenu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4872132Ssemenu * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 4972132Ssemenu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5072132Ssemenu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5172132Ssemenu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5272132Ssemenu * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5372132Ssemenu */ 5472132Ssemenu 55129844Smarius#include <sys/cdefs.h> 56129844Smarius__FBSDID("$FreeBSD: releng/11.0/sys/dev/mii/acphy.c 281821 2015-04-21 09:39:48Z glebius $"); 57129844Smarius 5872132Ssemenu/* 5972132Ssemenu * Driver for Altima AC101 10/100 PHY 6072132Ssemenu */ 6172132Ssemenu 6272132Ssemenu#include <sys/param.h> 6372132Ssemenu#include <sys/systm.h> 6472132Ssemenu#include <sys/kernel.h> 6572132Ssemenu#include <sys/socket.h> 6672132Ssemenu#include <sys/errno.h> 6772132Ssemenu#include <sys/module.h> 6872132Ssemenu#include <sys/bus.h> 6972132Ssemenu 7072132Ssemenu#include <net/if.h> 7172132Ssemenu#include <net/if_media.h> 7272132Ssemenu 7372132Ssemenu#include <dev/mii/mii.h> 7472132Ssemenu#include <dev/mii/miivar.h> 75109514Sobrien#include "miidevs.h" 7672132Ssemenu 7772132Ssemenu#include <dev/mii/acphyreg.h> 7872132Ssemenu 7972132Ssemenu#include "miibus_if.h" 8072132Ssemenu 81105135Salfredstatic int acphy_probe(device_t); 82105135Salfredstatic int acphy_attach(device_t); 8372132Ssemenu 8472132Ssemenustatic device_method_t acphy_methods[] = { 8572132Ssemenu /* device interface */ 8672132Ssemenu DEVMETHOD(device_probe, acphy_probe), 8772132Ssemenu DEVMETHOD(device_attach, acphy_attach), 8895722Sphk DEVMETHOD(device_detach, mii_phy_detach), 8972132Ssemenu DEVMETHOD(device_shutdown, bus_generic_shutdown), 90227908Smarius DEVMETHOD_END 9172132Ssemenu}; 9272132Ssemenu 9372132Ssemenustatic devclass_t acphy_devclass; 9472132Ssemenu 9572132Ssemenustatic driver_t acphy_driver = { 9672132Ssemenu "acphy", 9772132Ssemenu acphy_methods, 9872132Ssemenu sizeof(struct mii_softc) 9972132Ssemenu}; 10072132Ssemenu 10172132SsemenuDRIVER_MODULE(acphy, miibus, acphy_driver, acphy_devclass, 0, 0); 10272132Ssemenu 10392739Salfredstatic int acphy_service(struct mii_softc *, struct mii_data *, int); 10492739Salfredstatic void acphy_reset(struct mii_softc *); 10592739Salfredstatic void acphy_status(struct mii_softc *); 10672132Ssemenu 107164827Smariusstatic const struct mii_phydesc acphys[] = { 108221407Smarius MII_PHY_DESC(ALTIMA, AC101), 109221407Smarius MII_PHY_DESC(ALTIMA, AC101L), 110164834Smarius /* XXX This is reported to work, but it's not from any data sheet. */ 111221407Smarius MII_PHY_DESC(ALTIMA, ACXXX), 112164827Smarius MII_PHY_END 113164827Smarius}; 114164827Smarius 115221407Smariusstatic const struct mii_phy_funcs acphy_funcs = { 116221407Smarius acphy_service, 117221407Smarius acphy_status, 118221407Smarius acphy_reset 119221407Smarius}; 120221407Smarius 121105135Salfredstatic int 122150763Simpacphy_probe(device_t dev) 12372132Ssemenu{ 12472132Ssemenu 125164827Smarius return (mii_phy_dev_probe(dev, acphys, BUS_PROBE_DEFAULT)); 12672132Ssemenu} 12772132Ssemenu 128105135Salfredstatic int 129150763Simpacphy_attach(device_t dev) 13072132Ssemenu{ 13172132Ssemenu struct mii_softc *sc; 13272132Ssemenu 13372132Ssemenu sc = device_get_softc(dev); 13472132Ssemenu 135221407Smarius mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &acphy_funcs, 0); 13672132Ssemenu 137221407Smarius PHY_RESET(sc); 13872132Ssemenu 139221407Smarius sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; 14072132Ssemenu device_printf(dev, " "); 141165987Smarius 142281821Sglebius#define ADD(m) ifmedia_add(&sc->mii_pdata->mii_media, (m), 0, NULL) 143165987Smarius if ((PHY_READ(sc, MII_ACPHY_MCTL) & AC_MCTL_FX_SEL) != 0) { 144165987Smarius sc->mii_flags |= MIIF_HAVEFIBER; 145281821Sglebius ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst)); 146165987Smarius printf("100baseFX, "); 147281821Sglebius ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst)); 148165987Smarius printf("100baseFX-FDX, "); 149165987Smarius } 150165987Smarius#undef ADD 151165987Smarius 152164834Smarius mii_phy_add_media(sc); 15372132Ssemenu printf("\n"); 15472132Ssemenu 15572132Ssemenu MIIBUS_MEDIAINIT(sc->mii_dev); 15672132Ssemenu return (0); 15772132Ssemenu} 15872132Ssemenu 15984145Sjlemonstatic int 160150763Simpacphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 16172132Ssemenu{ 16272132Ssemenu int reg; 16372132Ssemenu 16472132Ssemenu switch (cmd) { 16572132Ssemenu case MII_POLLSTAT: 16672132Ssemenu break; 16772132Ssemenu 16872132Ssemenu case MII_MEDIACHG: 16995877Ssemenu /* Wake & deisolate up if necessary */ 17072132Ssemenu reg = PHY_READ(sc, MII_BMCR); 171164834Smarius if (reg & (BMCR_ISO | BMCR_PDOWN)) 17272132Ssemenu PHY_WRITE(sc, MII_BMCR, reg & ~(BMCR_ISO | BMCR_PDOWN)); 17372132Ssemenu 174164834Smarius mii_phy_setmedia(sc); 17572132Ssemenu break; 17672132Ssemenu 17772132Ssemenu case MII_TICK: 17872132Ssemenu /* 17995877Ssemenu * This PHY's autonegotiation doesn't need to be kicked. 18072132Ssemenu */ 18172132Ssemenu break; 18272132Ssemenu } 18372132Ssemenu 18472132Ssemenu /* Update the media status. */ 185221407Smarius PHY_STATUS(sc); 18672132Ssemenu 18772132Ssemenu /* Callback if something changed. */ 18884145Sjlemon mii_phy_update(sc, cmd); 18972132Ssemenu return (0); 19072132Ssemenu} 19172132Ssemenu 19284145Sjlemonstatic void 193150763Simpacphy_status(struct mii_softc *sc) 19472132Ssemenu{ 19572132Ssemenu struct mii_data *mii = sc->mii_pdata; 19672132Ssemenu struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 19772132Ssemenu int bmsr, bmcr, diag; 19872132Ssemenu 19972132Ssemenu mii->mii_media_status = IFM_AVALID; 20072132Ssemenu mii->mii_media_active = IFM_ETHER; 20172132Ssemenu 20272132Ssemenu bmsr = PHY_READ(sc, MII_BMSR) | 20372132Ssemenu PHY_READ(sc, MII_BMSR); 20472132Ssemenu if (bmsr & BMSR_LINK) 20572132Ssemenu mii->mii_media_status |= IFM_ACTIVE; 20672132Ssemenu 20772132Ssemenu bmcr = PHY_READ(sc, MII_BMCR); 20872132Ssemenu if (bmcr & BMCR_ISO) { 20972132Ssemenu mii->mii_media_active |= IFM_NONE; 21072132Ssemenu mii->mii_media_status = 0; 21172132Ssemenu return; 21272132Ssemenu } 21372132Ssemenu 21472132Ssemenu if (bmcr & BMCR_LOOP) 21572132Ssemenu mii->mii_media_active |= IFM_LOOP; 21672132Ssemenu 21772132Ssemenu if (bmcr & BMCR_AUTOEN) { 21872132Ssemenu if ((bmsr & BMSR_ACOMP) == 0) { 21972132Ssemenu /* Erg, still trying, I guess... */ 22072132Ssemenu mii->mii_media_active |= IFM_NONE; 22172132Ssemenu return; 22272132Ssemenu } 22395877Ssemenu diag = PHY_READ(sc, MII_ACPHY_DIAG); 22472132Ssemenu if (diag & AC_DIAG_SPEED) 22572132Ssemenu mii->mii_media_active |= IFM_100_TX; 22672132Ssemenu else 22772132Ssemenu mii->mii_media_active |= IFM_10_T; 22872132Ssemenu 22972132Ssemenu if (diag & AC_DIAG_DUPLEX) 230221407Smarius mii->mii_media_active |= 231221407Smarius IFM_FDX | mii_phy_flowstatus(sc); 232213384Smarius else 233213384Smarius mii->mii_media_active |= IFM_HDX; 23472132Ssemenu } else 23572132Ssemenu mii->mii_media_active = ife->ifm_media; 23672132Ssemenu} 23772132Ssemenu 23884145Sjlemonstatic void 239150763Simpacphy_reset(struct mii_softc *sc) 24072132Ssemenu{ 24172132Ssemenu 24272132Ssemenu mii_phy_reset(sc); 24372132Ssemenu PHY_WRITE(sc, MII_ACPHY_INT, 0); 24472132Ssemenu} 245