178679427SPyun YongHyeon /* $NetBSD: icsphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $ */ 278679427SPyun YongHyeon 378679427SPyun YongHyeon /*- 478679427SPyun YongHyeon * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. 578679427SPyun YongHyeon * All rights reserved. 678679427SPyun YongHyeon * 778679427SPyun YongHyeon * This code is derived from software contributed to The NetBSD Foundation 878679427SPyun YongHyeon * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 978679427SPyun YongHyeon * NASA Ames Research Center. 1078679427SPyun YongHyeon * 1178679427SPyun YongHyeon * Redistribution and use in source and binary forms, with or without 1278679427SPyun YongHyeon * modification, are permitted provided that the following conditions 1378679427SPyun YongHyeon * are met: 1478679427SPyun YongHyeon * 1. Redistributions of source code must retain the above copyright 1578679427SPyun YongHyeon * notice, this list of conditions and the following disclaimer. 1678679427SPyun YongHyeon * 2. Redistributions in binary form must reproduce the above copyright 1778679427SPyun YongHyeon * notice, this list of conditions and the following disclaimer in the 1878679427SPyun YongHyeon * documentation and/or other materials provided with the distribution. 1978679427SPyun YongHyeon * 2078679427SPyun YongHyeon * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2178679427SPyun YongHyeon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2278679427SPyun YongHyeon * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2378679427SPyun YongHyeon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2478679427SPyun YongHyeon * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2578679427SPyun YongHyeon * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2678679427SPyun YongHyeon * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2778679427SPyun YongHyeon * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2878679427SPyun YongHyeon * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2978679427SPyun YongHyeon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3078679427SPyun YongHyeon * POSSIBILITY OF SUCH DAMAGE. 3178679427SPyun YongHyeon */ 3278679427SPyun YongHyeon 3378679427SPyun YongHyeon /* 3478679427SPyun YongHyeon * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 3578679427SPyun YongHyeon * 3678679427SPyun YongHyeon * Redistribution and use in source and binary forms, with or without 3778679427SPyun YongHyeon * modification, are permitted provided that the following conditions 3878679427SPyun YongHyeon * are met: 3978679427SPyun YongHyeon * 1. Redistributions of source code must retain the above copyright 4078679427SPyun YongHyeon * notice, this list of conditions and the following disclaimer. 4178679427SPyun YongHyeon * 2. Redistributions in binary form must reproduce the above copyright 4278679427SPyun YongHyeon * notice, this list of conditions and the following disclaimer in the 4378679427SPyun YongHyeon * documentation and/or other materials provided with the distribution. 4478679427SPyun YongHyeon * 4578679427SPyun YongHyeon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4678679427SPyun YongHyeon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 4778679427SPyun YongHyeon * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 4878679427SPyun YongHyeon * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 4978679427SPyun YongHyeon * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 5078679427SPyun YongHyeon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5178679427SPyun YongHyeon * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5278679427SPyun YongHyeon * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5378679427SPyun YongHyeon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5478679427SPyun YongHyeon * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5578679427SPyun YongHyeon */ 5678679427SPyun YongHyeon 5778679427SPyun YongHyeon #include <sys/cdefs.h> 5878679427SPyun YongHyeon __FBSDID("$FreeBSD$"); 5978679427SPyun YongHyeon 6078679427SPyun YongHyeon /* 6178679427SPyun YongHyeon * driver for Integrated Circuit Systems' ICS1889-1893 ethernet 10/100 PHY 6278679427SPyun YongHyeon * datasheet from www.icst.com 6378679427SPyun YongHyeon */ 6478679427SPyun YongHyeon 6578679427SPyun YongHyeon #include <sys/param.h> 6678679427SPyun YongHyeon #include <sys/systm.h> 6778679427SPyun YongHyeon #include <sys/kernel.h> 6878679427SPyun YongHyeon #include <sys/module.h> 6978679427SPyun YongHyeon #include <sys/socket.h> 7078679427SPyun YongHyeon #include <sys/bus.h> 7178679427SPyun YongHyeon 7278679427SPyun YongHyeon #include <net/if.h> 7378679427SPyun YongHyeon #include <net/if_media.h> 7478679427SPyun YongHyeon 7578679427SPyun YongHyeon #include <dev/mii/mii.h> 7678679427SPyun YongHyeon #include <dev/mii/miivar.h> 7778679427SPyun YongHyeon #include "miidevs.h" 7878679427SPyun YongHyeon 7978679427SPyun YongHyeon #include <dev/mii/icsphyreg.h> 8078679427SPyun YongHyeon 8178679427SPyun YongHyeon #include "miibus_if.h" 8278679427SPyun YongHyeon 8378679427SPyun YongHyeon static int icsphy_probe(device_t dev); 8478679427SPyun YongHyeon static int icsphy_attach(device_t dev); 8578679427SPyun YongHyeon 8678679427SPyun YongHyeon static device_method_t icsphy_methods[] = { 8778679427SPyun YongHyeon /* device interface */ 8878679427SPyun YongHyeon DEVMETHOD(device_probe, icsphy_probe), 8978679427SPyun YongHyeon DEVMETHOD(device_attach, icsphy_attach), 9078679427SPyun YongHyeon DEVMETHOD(device_detach, mii_phy_detach), 9178679427SPyun YongHyeon DEVMETHOD(device_shutdown, bus_generic_shutdown), 9278679427SPyun YongHyeon { 0, 0 } 9378679427SPyun YongHyeon }; 9478679427SPyun YongHyeon 9578679427SPyun YongHyeon static devclass_t icsphy_devclass; 9678679427SPyun YongHyeon 9778679427SPyun YongHyeon static driver_t icsphy_driver = { 9878679427SPyun YongHyeon "icsphy", 9978679427SPyun YongHyeon icsphy_methods, 100*3fcb7a53SMarius Strobl sizeof(struct mii_softc) 10178679427SPyun YongHyeon }; 10278679427SPyun YongHyeon 10378679427SPyun YongHyeon DRIVER_MODULE(icsphy, miibus, icsphy_driver, icsphy_devclass, 0, 0); 10478679427SPyun YongHyeon 10578679427SPyun YongHyeon static int icsphy_service(struct mii_softc *, struct mii_data *, int); 10678679427SPyun YongHyeon static void icsphy_status(struct mii_softc *); 10778679427SPyun YongHyeon static void icsphy_reset(struct mii_softc *); 10878679427SPyun YongHyeon 10978679427SPyun YongHyeon static const struct mii_phydesc icsphys[] = { 110*3fcb7a53SMarius Strobl MII_PHY_DESC(ICS, 1889), 111*3fcb7a53SMarius Strobl MII_PHY_DESC(ICS, 1890), 112*3fcb7a53SMarius Strobl MII_PHY_DESC(ICS, 1892), 113*3fcb7a53SMarius Strobl MII_PHY_DESC(ICS, 1893), 11478679427SPyun YongHyeon MII_PHY_END 11578679427SPyun YongHyeon }; 11678679427SPyun YongHyeon 117*3fcb7a53SMarius Strobl static const struct mii_phy_funcs icsphy_funcs = { 118*3fcb7a53SMarius Strobl icsphy_service, 119*3fcb7a53SMarius Strobl icsphy_status, 120*3fcb7a53SMarius Strobl icsphy_reset 121*3fcb7a53SMarius Strobl }; 122*3fcb7a53SMarius Strobl 12378679427SPyun YongHyeon static int 12478679427SPyun YongHyeon icsphy_probe(device_t dev) 12578679427SPyun YongHyeon { 12678679427SPyun YongHyeon 12778679427SPyun YongHyeon return (mii_phy_dev_probe(dev, icsphys, BUS_PROBE_DEFAULT)); 12878679427SPyun YongHyeon } 12978679427SPyun YongHyeon 13078679427SPyun YongHyeon static int 13178679427SPyun YongHyeon icsphy_attach(device_t dev) 13278679427SPyun YongHyeon { 13378679427SPyun YongHyeon 134*3fcb7a53SMarius Strobl mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, 135*3fcb7a53SMarius Strobl &icsphy_funcs, 1); 13678679427SPyun YongHyeon return (0); 13778679427SPyun YongHyeon } 13878679427SPyun YongHyeon 13978679427SPyun YongHyeon static int 14078679427SPyun YongHyeon icsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 14178679427SPyun YongHyeon { 14278679427SPyun YongHyeon 14378679427SPyun YongHyeon switch (cmd) { 14478679427SPyun YongHyeon case MII_POLLSTAT: 14578679427SPyun YongHyeon break; 14678679427SPyun YongHyeon 14778679427SPyun YongHyeon case MII_MEDIACHG: 14878679427SPyun YongHyeon /* 14978679427SPyun YongHyeon * If the interface is not up, don't do anything. 15078679427SPyun YongHyeon */ 15178679427SPyun YongHyeon if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 15278679427SPyun YongHyeon break; 15378679427SPyun YongHyeon 15478679427SPyun YongHyeon mii_phy_setmedia(sc); 15578679427SPyun YongHyeon break; 15678679427SPyun YongHyeon 15778679427SPyun YongHyeon case MII_TICK: 15878679427SPyun YongHyeon if (mii_phy_tick(sc) == EJUSTRETURN) 15978679427SPyun YongHyeon return (0); 16078679427SPyun YongHyeon break; 16178679427SPyun YongHyeon } 16278679427SPyun YongHyeon 16378679427SPyun YongHyeon /* Update the media status. */ 164*3fcb7a53SMarius Strobl PHY_STATUS(sc); 16578679427SPyun YongHyeon 16678679427SPyun YongHyeon /* Callback if something changed. */ 16778679427SPyun YongHyeon mii_phy_update(sc, cmd); 16878679427SPyun YongHyeon return (0); 16978679427SPyun YongHyeon } 17078679427SPyun YongHyeon 17178679427SPyun YongHyeon static void 17278679427SPyun YongHyeon icsphy_status(struct mii_softc *sc) 17378679427SPyun YongHyeon { 17478679427SPyun YongHyeon struct mii_data *mii = sc->mii_pdata; 17578679427SPyun YongHyeon struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 17678679427SPyun YongHyeon int bmcr, qpr; 17778679427SPyun YongHyeon 17878679427SPyun YongHyeon mii->mii_media_status = IFM_AVALID; 17978679427SPyun YongHyeon mii->mii_media_active = IFM_ETHER; 18078679427SPyun YongHyeon 18178679427SPyun YongHyeon /* 18278679427SPyun YongHyeon * Don't get link from the BMSR. It's available in the QPR, 18378679427SPyun YongHyeon * and we have to read it twice to unlatch it anyhow. This 18478679427SPyun YongHyeon * gives us fewer register reads. 18578679427SPyun YongHyeon */ 18678679427SPyun YongHyeon qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* unlatch */ 18778679427SPyun YongHyeon qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* real value */ 18878679427SPyun YongHyeon 18978679427SPyun YongHyeon if (qpr & QPR_LINK) 19078679427SPyun YongHyeon mii->mii_media_status |= IFM_ACTIVE; 19178679427SPyun YongHyeon 19278679427SPyun YongHyeon bmcr = PHY_READ(sc, MII_BMCR); 19378679427SPyun YongHyeon if (bmcr & BMCR_ISO) { 19478679427SPyun YongHyeon mii->mii_media_active |= IFM_NONE; 19578679427SPyun YongHyeon mii->mii_media_status = 0; 19678679427SPyun YongHyeon return; 19778679427SPyun YongHyeon } 19878679427SPyun YongHyeon 19978679427SPyun YongHyeon if (bmcr & BMCR_LOOP) 20078679427SPyun YongHyeon mii->mii_media_active |= IFM_LOOP; 20178679427SPyun YongHyeon 20278679427SPyun YongHyeon if (bmcr & BMCR_AUTOEN) { 20378679427SPyun YongHyeon if ((qpr & QPR_ACOMP) == 0) { 20478679427SPyun YongHyeon /* Erg, still trying, I guess... */ 20578679427SPyun YongHyeon mii->mii_media_active |= IFM_NONE; 20678679427SPyun YongHyeon return; 20778679427SPyun YongHyeon } 20878679427SPyun YongHyeon if (qpr & QPR_SPEED) 20978679427SPyun YongHyeon mii->mii_media_active |= IFM_100_TX; 21078679427SPyun YongHyeon else 21178679427SPyun YongHyeon mii->mii_media_active |= IFM_10_T; 21278679427SPyun YongHyeon if (qpr & QPR_FDX) 213*3fcb7a53SMarius Strobl mii->mii_media_active |= 214*3fcb7a53SMarius Strobl IFM_FDX | mii_phy_flowstatus(sc); 21578679427SPyun YongHyeon else 21678679427SPyun YongHyeon mii->mii_media_active |= IFM_HDX; 21778679427SPyun YongHyeon } else 21878679427SPyun YongHyeon mii->mii_media_active = ife->ifm_media; 21978679427SPyun YongHyeon } 22078679427SPyun YongHyeon 22178679427SPyun YongHyeon static void 22278679427SPyun YongHyeon icsphy_reset(struct mii_softc *sc) 22378679427SPyun YongHyeon { 22478679427SPyun YongHyeon 22578679427SPyun YongHyeon mii_phy_reset(sc); 22678679427SPyun YongHyeon /* set powerdown feature */ 227*3fcb7a53SMarius Strobl switch (sc->mii_mpd_model) { 228*3fcb7a53SMarius Strobl case MII_MODEL_ICS_1890: 229*3fcb7a53SMarius Strobl case MII_MODEL_ICS_1893: 23078679427SPyun YongHyeon PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_100AUTOPWRDN); 23178679427SPyun YongHyeon break; 232*3fcb7a53SMarius Strobl case MII_MODEL_ICS_1892: 23378679427SPyun YongHyeon PHY_WRITE(sc, MII_ICSPHY_ECR2, 23478679427SPyun YongHyeon ECR2_10AUTOPWRDN|ECR2_100AUTOPWRDN); 23578679427SPyun YongHyeon break; 23678679427SPyun YongHyeon default: 23778679427SPyun YongHyeon /* 1889 have no ECR2 */ 23878679427SPyun YongHyeon break; 23978679427SPyun YongHyeon } 24078679427SPyun YongHyeon /* 24178679427SPyun YongHyeon * There is no description that the reset do auto-negotiation in the 24278679427SPyun YongHyeon * data sheet. 24378679427SPyun YongHyeon */ 24478679427SPyun YongHyeon PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_STARTNEG|BMCR_FDX); 24578679427SPyun YongHyeon } 246