12061Sjkh/* $NetBSD: icsphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $ */ 250479Speter 32061Sjkh/*- 438666Sjb * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. 532427Sjb * All rights reserved. 638666Sjb * 738666Sjb * This code is derived from software contributed to The NetBSD Foundation 838666Sjb * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 938666Sjb * NASA Ames Research Center. 1064049Salex * 1164049Salex * Redistribution and use in source and binary forms, with or without 1266071Smarkm * modification, are permitted provided that the following conditions 1373504Sobrien * are met: 1438666Sjb * 1. Redistributions of source code must retain the above copyright 1544918Sjkh * notice, this list of conditions and the following disclaimer. 1638666Sjb * 2. Redistributions in binary form must reproduce the above copyright 1738666Sjb * notice, this list of conditions and the following disclaimer in the 1838666Sjb * documentation and/or other materials provided with the distribution. 1938666Sjb * 2038666Sjb * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2138666Sjb * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2238666Sjb * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2338978Sjb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 2438978Sjb * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2532427Sjb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2638666Sjb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2738666Sjb * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2838666Sjb * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2938666Sjb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3038666Sjb * POSSIBILITY OF SUCH DAMAGE. 3138666Sjb */ 3217308Speter 3391606Skeramida/* 3419175Sbde * Copyright (c) 1997 Manuel Bouyer. All rights reserved. 3596205Sjwd * 3696205Sjwd * Redistribution and use in source and binary forms, with or without 3738042Sbde * modification, are permitted provided that the following conditions 3896205Sjwd * are met: 3996205Sjwd * 1. Redistributions of source code must retain the above copyright 4038042Sbde * notice, this list of conditions and the following disclaimer. 4196205Sjwd * 2. Redistributions in binary form must reproduce the above copyright 4296205Sjwd * notice, this list of conditions and the following disclaimer in the 4317308Speter * documentation and/or other materials provided with the distribution. 4496205Sjwd * 4596205Sjwd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4617308Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 4796205Sjwd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 4896205Sjwd * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 4996205Sjwd * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 5096205Sjwd * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 5196205Sjwd * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 5296205Sjwd * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 5396205Sjwd * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 5496205Sjwd * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5596205Sjwd */ 5696205Sjwd 5796205Sjwd#include <sys/cdefs.h> 5896205Sjwd__FBSDID("$FreeBSD$"); 5945108Sobrien 6042128Speter/* 6142128Speter * driver for Integrated Circuit Systems' ICS1889-1893 ethernet 10/100 PHY 6238666Sjb * datasheet from www.icst.com 6351361Sjb */ 6438666Sjb 6517308Speter#include <sys/param.h> 6698775Sdillon#include <sys/systm.h> 6798723Sdillon#include <sys/kernel.h> 6898723Sdillon#include <sys/module.h> 6998723Sdillon#include <sys/socket.h> 7098723Sdillon#include <sys/bus.h> 7138666Sjb 7217308Speter#include <net/if.h> 7338666Sjb#include <net/if_media.h> 7417308Speter 7527910Sasami#include <dev/mii/mii.h> 7643226Sjkh#include <dev/mii/miivar.h> 7743226Sjkh#include "miidevs.h" 7843226Sjkh 7938666Sjb#include <dev/mii/icsphyreg.h> 8027910Sasami 8138666Sjb#include "miibus_if.h" 8238666Sjb 8338666Sjbstatic int icsphy_probe(device_t dev); 8427910Sasamistatic int icsphy_attach(device_t dev); 8538666Sjb 8638666Sjbstatic device_method_t icsphy_methods[] = { 8743226Sjkh /* device interface */ 8843226Sjkh DEVMETHOD(device_probe, icsphy_probe), 8927910Sasami DEVMETHOD(device_attach, icsphy_attach), 9038666Sjb DEVMETHOD(device_detach, mii_phy_detach), 9138666Sjb DEVMETHOD(device_shutdown, bus_generic_shutdown), 9227910Sasami DEVMETHOD_END 9338666Sjb}; 9427910Sasami 9517308Speterstatic devclass_t icsphy_devclass; 9638666Sjb 9738666Sjbstatic driver_t icsphy_driver = { 9817308Speter "icsphy", 9995509Sru icsphy_methods, 10095793Sru sizeof(struct mii_softc) 10197252Sru}; 10296164Sru 10395146SgshapiroDRIVER_MODULE(icsphy, miibus, icsphy_driver, icsphy_devclass, 0, 0); 1042061Sjkh 10597769Srustatic int icsphy_service(struct mii_softc *, struct mii_data *, int); 10697252Srustatic void icsphy_status(struct mii_softc *); 10797252Srustatic void icsphy_reset(struct mii_softc *); 10895730Sru 10995793Srustatic const struct mii_phydesc icsphys[] = { 11095730Sru MII_PHY_DESC(ICS, 1889), 11195730Sru MII_PHY_DESC(ICS, 1890), 11295730Sru MII_PHY_DESC(ICS, 1892), 11355026Smarcel MII_PHY_DESC(ICS, 1893), 11455026Smarcel MII_PHY_END 11554324Smarcel}; 11617308Speter 11738666Sjbstatic const struct mii_phy_funcs icsphy_funcs = { 11817308Speter icsphy_service, 11997252Sru icsphy_status, 12038666Sjb icsphy_reset 12154324Smarcel}; 1222302Spaul 12339206Sjkhstatic int 12439206Sjkhicsphy_probe(device_t dev) 12539206Sjkh{ 12673349Sru 12717308Speter return (mii_phy_dev_probe(dev, icsphys, BUS_PROBE_DEFAULT)); 12854324Smarcel} 12954324Smarcel 13054324Smarcelstatic int 13154324Smarcelicsphy_attach(device_t dev) 13254324Smarcel{ 13354324Smarcel 13454324Smarcel mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, 13569659Sobrien &icsphy_funcs, 1); 13654324Smarcel return (0); 13754324Smarcel} 13854324Smarcel 13954324Smarcelstatic int 14054324Smarcelicsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 14154324Smarcel{ 14254324Smarcel 14354324Smarcel switch (cmd) { 14454324Smarcel case MII_POLLSTAT: 14554324Smarcel break; 14654324Smarcel 14754324Smarcel case MII_MEDIACHG: 14854324Smarcel /* 14954324Smarcel * If the interface is not up, don't do anything. 15054324Smarcel */ 15154324Smarcel if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 15254324Smarcel break; 15354324Smarcel 15454324Smarcel mii_phy_setmedia(sc); 15597536Sobrien break; 15654324Smarcel 15754324Smarcel case MII_TICK: 15854324Smarcel if (mii_phy_tick(sc) == EJUSTRETURN) 15995730Sru return (0); 16095730Sru break; 16195730Sru } 16295730Sru 16395730Sru /* Update the media status. */ 16495730Sru PHY_STATUS(sc); 16595730Sru 16638666Sjb /* Callback if something changed. */ 16738666Sjb mii_phy_update(sc, cmd); 16817308Speter return (0); 16938666Sjb} 17038666Sjb 17138666Sjbstatic void 17217308Spetericsphy_status(struct mii_softc *sc) 17355678Smarcel{ 17455678Smarcel struct mii_data *mii = sc->mii_pdata; 175100402Sru struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 176100402Sru int bmcr, qpr; 177100402Sru 17890395Sru mii->mii_media_status = IFM_AVALID; 179100402Sru mii->mii_media_active = IFM_ETHER; 180100402Sru 181100402Sru /* 182100402Sru * Don't get link from the BMSR. It's available in the QPR, 1832061Sjkh * and we have to read it twice to unlatch it anyhow. This 18417308Speter * gives us fewer register reads. 18538666Sjb */ 186100401Sru qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* unlatch */ 187100401Sru qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* real value */ 18817308Speter 18955678Smarcel if (qpr & QPR_LINK) 190100401Sru mii->mii_media_status |= IFM_ACTIVE; 191100401Sru 192100401Sru bmcr = PHY_READ(sc, MII_BMCR); 193100401Sru if (bmcr & BMCR_ISO) { 194100401Sru mii->mii_media_active |= IFM_NONE; 1953626Swollman mii->mii_media_status = 0; 19617308Speter return; 19755678Smarcel } 19855678Smarcel 19955678Smarcel if (bmcr & BMCR_LOOP) 20055678Smarcel mii->mii_media_active |= IFM_LOOP; 20155678Smarcel 20255678Smarcel if (bmcr & BMCR_AUTOEN) { 20355678Smarcel if ((qpr & QPR_ACOMP) == 0) { 20455678Smarcel /* Erg, still trying, I guess... */ 20555678Smarcel mii->mii_media_active |= IFM_NONE; 20655678Smarcel return; 20755678Smarcel } 20855678Smarcel if (qpr & QPR_SPEED) 20955678Smarcel mii->mii_media_active |= IFM_100_TX; 21038666Sjb else 21138666Sjb mii->mii_media_active |= IFM_10_T; 21217308Speter if (qpr & QPR_FDX) 21355678Smarcel mii->mii_media_active |= 21438978Sjb IFM_FDX | mii_phy_flowstatus(sc); 2153626Swollman else 21617308Speter mii->mii_media_active |= IFM_HDX; 21738666Sjb } else 21817308Speter mii->mii_media_active = ife->ifm_media; 21943226Sjkh} 22043226Sjkh 22143226Sjkhstatic void 22238666Sjbicsphy_reset(struct mii_softc *sc) 22338666Sjb{ 22444103Smsmith 225 mii_phy_reset(sc); 226 /* set powerdown feature */ 227 switch (sc->mii_mpd_model) { 228 case MII_MODEL_ICS_1890: 229 case MII_MODEL_ICS_1893: 230 PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_100AUTOPWRDN); 231 break; 232 case MII_MODEL_ICS_1892: 233 PHY_WRITE(sc, MII_ICSPHY_ECR2, 234 ECR2_10AUTOPWRDN|ECR2_100AUTOPWRDN); 235 break; 236 default: 237 /* 1889 have no ECR2 */ 238 break; 239 } 240 /* 241 * There is no description that the reset do auto-negotiation in the 242 * data sheet. 243 */ 244 PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_STARTNEG|BMCR_FDX); 245} 246