1190558Simp/*- 2190558Simp * Copyright (c) 2009, M. Warner Losh 3190558Simp * All rights reserved. 4190558Simp * 5190558Simp * Redistribution and use in source and binary forms, with or without 6190558Simp * modification, are permitted provided that the following conditions 7190558Simp * are met: 8190558Simp * 1. Redistributions of source code must retain the above copyright 9190558Simp * notice unmodified, this list of conditions, and the following 10190558Simp * disclaimer. 11190558Simp * 2. Redistributions in binary form must reproduce the above copyright 12190558Simp * notice, this list of conditions and the following disclaimer in the 13190558Simp * documentation and/or other materials provided with the distribution. 14190558Simp * 15190558Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16190558Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17190558Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18190558Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19190558Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20190558Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21190558Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22190558Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23190558Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24190558Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25190558Simp * SUCH DAMAGE. 26190558Simp */ 27190558Simp#include <sys/cdefs.h> 28190558Simp__FBSDID("$FreeBSD$"); 29190558Simp 30190558Simp/* 31190558Simp * driver for internal phy in the AX88x9x chips. 32190558Simp */ 33190558Simp 34190558Simp#include <sys/param.h> 35190558Simp#include <sys/systm.h> 36190558Simp#include <sys/kernel.h> 37190558Simp#include <sys/module.h> 38190558Simp#include <sys/socket.h> 39190558Simp#include <sys/bus.h> 40190558Simp 41190558Simp#include <net/if.h> 42190558Simp#include <net/if_media.h> 43190558Simp 44190558Simp#include <dev/mii/mii.h> 45190558Simp#include <dev/mii/miivar.h> 46190558Simp#include "miidevs.h" 47190558Simp 48190558Simp#include "miibus_if.h" 49190558Simp 50190558Simpstatic int axphy_probe(device_t dev); 51190558Simpstatic int axphy_attach(device_t dev); 52190558Simp 53190558Simpstatic device_method_t axphy_methods[] = { 54190558Simp /* device interface */ 55190558Simp DEVMETHOD(device_probe, axphy_probe), 56190558Simp DEVMETHOD(device_attach, axphy_attach), 57190558Simp DEVMETHOD(device_detach, mii_phy_detach), 58190558Simp DEVMETHOD(device_shutdown, bus_generic_shutdown), 59227908Smarius DEVMETHOD_END 60190558Simp}; 61190558Simp 62190558Simpstatic devclass_t axphy_devclass; 63190558Simp 64190558Simpstatic driver_t axphy_driver = { 65190558Simp "axphy", 66190558Simp axphy_methods, 67190558Simp sizeof(struct mii_softc) 68190558Simp}; 69190558Simp 70190558SimpDRIVER_MODULE(axphy, miibus, axphy_driver, axphy_devclass, 0, 0); 71190558Simp 72190558Simpstatic int axphy_service(struct mii_softc *, struct mii_data *, int); 73190558Simpstatic void axphy_status(struct mii_softc *); 74190558Simp 75190558Simpstatic const struct mii_phydesc axphys[] = { 76221407Smarius MII_PHY_DESC(xxASIX, AX88X9X), 77190558Simp MII_PHY_END 78190558Simp}; 79190558Simp 80221407Smariusstatic const struct mii_phy_funcs axphy_funcs = { 81221407Smarius axphy_service, 82221407Smarius axphy_status, 83221407Smarius mii_phy_reset 84221407Smarius}; 85221407Smarius 86190558Simpstatic int 87190558Simpaxphy_probe(device_t dev) 88190558Simp{ 89190558Simp 90190558Simp return (mii_phy_dev_probe(dev, axphys, BUS_PROBE_DEFAULT)); 91190558Simp} 92190558Simp 93190558Simpstatic int 94190558Simpaxphy_attach(device_t dev) 95190558Simp{ 96190558Simp struct mii_softc *sc; 97190558Simp 98190558Simp sc = device_get_softc(dev); 99190558Simp 100221407Smarius mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, 101221407Smarius &axphy_funcs, 1); 102190558Simp mii_phy_setmedia(sc); 103190558Simp 104190558Simp return (0); 105190558Simp} 106190558Simp 107190558Simpstatic int 108190558Simpaxphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 109190558Simp{ 110190558Simp 111190558Simp switch (cmd) { 112190558Simp case MII_POLLSTAT: 113190558Simp break; 114190558Simp 115190558Simp case MII_MEDIACHG: 116190558Simp mii_phy_setmedia(sc); 117190558Simp break; 118190558Simp 119190558Simp case MII_TICK: 120190558Simp if (mii_phy_tick(sc) == EJUSTRETURN) 121190558Simp return (0); 122190558Simp break; 123190558Simp } 124190558Simp 125190558Simp /* Update the media status. */ 126221407Smarius PHY_STATUS(sc); 127190558Simp 128190558Simp /* Callback if something changed. */ 129190558Simp mii_phy_update(sc, cmd); 130190558Simp return (0); 131190558Simp} 132190558Simp 133190558Simpstatic void 134190558Simpaxphy_status(struct mii_softc *sc) 135190558Simp{ 136190558Simp struct mii_data *mii = sc->mii_pdata; 137190558Simp struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 138190558Simp int bmsr, bmcr; 139190558Simp 140190558Simp mii->mii_media_status = IFM_AVALID; 141190558Simp mii->mii_media_active = IFM_ETHER; 142190558Simp 143190558Simp bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 144190558Simp if (bmsr & BMSR_LINK) 145190558Simp mii->mii_media_status |= IFM_ACTIVE; 146190558Simp 147190558Simp bmcr = PHY_READ(sc, MII_BMCR); 148190558Simp if (bmcr & BMCR_ISO) { 149190558Simp mii->mii_media_active |= IFM_NONE; 150190558Simp mii->mii_media_status = 0; 151190558Simp return; 152190558Simp } 153190558Simp 154190558Simp if (bmcr & BMCR_LOOP) 155190558Simp mii->mii_media_active |= IFM_LOOP; 156190558Simp 157190558Simp if (bmcr & BMCR_AUTOEN) { 158190558Simp if ((bmsr & BMSR_ACOMP) == 0) { 159190558Simp mii->mii_media_active |= IFM_NONE; 160190558Simp return; 161190558Simp } 162190558Simp 163190558Simp#if 0 164190558Simp scr = PHY_READ(sc, MII_AXPHY_SCR); 165190558Simp if (scr & SCR_S100) 166190558Simp mii->mii_media_active |= IFM_100_TX; 167190558Simp else 168190558Simp mii->mii_media_active |= IFM_10_T; 169190558Simp if (scr & SCR_FDX) 170221407Smarius mii->mii_media_active |= 171221407Smarius IFM_FDX | mii_phy_flowstatus(sc); 172213384Smarius else 173213384Smarius mii->mii_media_active |= IFM_HDX; 174190558Simp#endif 175190558Simp } else 176190558Simp mii->mii_media_active = ife->ifm_media; 177190558Simp} 178