15fb1afd7SWarner Losh /*- 2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3718cf2ccSPedro F. Giffuni * 4f86e6000SWarner Losh * Copyright (c) 2009 M. Warner Losh <imp@FreeBSD.org> 55fb1afd7SWarner Losh * 65fb1afd7SWarner Losh * Redistribution and use in source and binary forms, with or without 75fb1afd7SWarner Losh * modification, are permitted provided that the following conditions 85fb1afd7SWarner Losh * are met: 95fb1afd7SWarner Losh * 1. Redistributions of source code must retain the above copyright 105fb1afd7SWarner Losh * notice unmodified, this list of conditions, and the following 115fb1afd7SWarner Losh * disclaimer. 125fb1afd7SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 135fb1afd7SWarner Losh * notice, this list of conditions and the following disclaimer in the 145fb1afd7SWarner Losh * documentation and/or other materials provided with the distribution. 155fb1afd7SWarner Losh * 165fb1afd7SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 175fb1afd7SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 185fb1afd7SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 195fb1afd7SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 205fb1afd7SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 215fb1afd7SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 225fb1afd7SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 235fb1afd7SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 245fb1afd7SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 255fb1afd7SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 265fb1afd7SWarner Losh * SUCH DAMAGE. 275fb1afd7SWarner Losh */ 285fb1afd7SWarner Losh #include <sys/cdefs.h> 295fb1afd7SWarner Losh __FBSDID("$FreeBSD$"); 305fb1afd7SWarner Losh 315fb1afd7SWarner Losh /* 325fb1afd7SWarner Losh * driver for internal phy in the AX88x9x chips. 335fb1afd7SWarner Losh */ 345fb1afd7SWarner Losh 355fb1afd7SWarner Losh #include <sys/param.h> 365fb1afd7SWarner Losh #include <sys/systm.h> 375fb1afd7SWarner Losh #include <sys/kernel.h> 385fb1afd7SWarner Losh #include <sys/module.h> 395fb1afd7SWarner Losh #include <sys/socket.h> 405fb1afd7SWarner Losh #include <sys/bus.h> 415fb1afd7SWarner Losh 425fb1afd7SWarner Losh #include <net/if.h> 435fb1afd7SWarner Losh #include <net/if_media.h> 445fb1afd7SWarner Losh 455fb1afd7SWarner Losh #include <dev/mii/mii.h> 465fb1afd7SWarner Losh #include <dev/mii/miivar.h> 475fb1afd7SWarner Losh #include "miidevs.h" 485fb1afd7SWarner Losh 495fb1afd7SWarner Losh #include "miibus_if.h" 505fb1afd7SWarner Losh 515fb1afd7SWarner Losh static int axphy_probe(device_t dev); 525fb1afd7SWarner Losh static int axphy_attach(device_t dev); 535fb1afd7SWarner Losh 545fb1afd7SWarner Losh static device_method_t axphy_methods[] = { 555fb1afd7SWarner Losh /* device interface */ 565fb1afd7SWarner Losh DEVMETHOD(device_probe, axphy_probe), 575fb1afd7SWarner Losh DEVMETHOD(device_attach, axphy_attach), 585fb1afd7SWarner Losh DEVMETHOD(device_detach, mii_phy_detach), 595fb1afd7SWarner Losh DEVMETHOD(device_shutdown, bus_generic_shutdown), 60604f5f1fSMarius Strobl DEVMETHOD_END 615fb1afd7SWarner Losh }; 625fb1afd7SWarner Losh 635fb1afd7SWarner Losh static driver_t axphy_driver = { 645fb1afd7SWarner Losh "axphy", 655fb1afd7SWarner Losh axphy_methods, 665fb1afd7SWarner Losh sizeof(struct mii_softc) 675fb1afd7SWarner Losh }; 685fb1afd7SWarner Losh 69*f438c2ffSJohn Baldwin DRIVER_MODULE(axphy, miibus, axphy_driver, 0, 0); 705fb1afd7SWarner Losh 715fb1afd7SWarner Losh static int axphy_service(struct mii_softc *, struct mii_data *, int); 725fb1afd7SWarner Losh static void axphy_status(struct mii_softc *); 735fb1afd7SWarner Losh 745fb1afd7SWarner Losh static const struct mii_phydesc axphys[] = { 753fcb7a53SMarius Strobl MII_PHY_DESC(xxASIX, AX88X9X), 765fb1afd7SWarner Losh MII_PHY_END 775fb1afd7SWarner Losh }; 785fb1afd7SWarner Losh 793fcb7a53SMarius Strobl static const struct mii_phy_funcs axphy_funcs = { 803fcb7a53SMarius Strobl axphy_service, 813fcb7a53SMarius Strobl axphy_status, 823fcb7a53SMarius Strobl mii_phy_reset 833fcb7a53SMarius Strobl }; 843fcb7a53SMarius Strobl 855fb1afd7SWarner Losh static int 865fb1afd7SWarner Losh axphy_probe(device_t dev) 875fb1afd7SWarner Losh { 885fb1afd7SWarner Losh 895fb1afd7SWarner Losh return (mii_phy_dev_probe(dev, axphys, BUS_PROBE_DEFAULT)); 905fb1afd7SWarner Losh } 915fb1afd7SWarner Losh 925fb1afd7SWarner Losh static int 935fb1afd7SWarner Losh axphy_attach(device_t dev) 945fb1afd7SWarner Losh { 955fb1afd7SWarner Losh struct mii_softc *sc; 965fb1afd7SWarner Losh 975fb1afd7SWarner Losh sc = device_get_softc(dev); 985fb1afd7SWarner Losh 993fcb7a53SMarius Strobl mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, 1003fcb7a53SMarius Strobl &axphy_funcs, 1); 1015fb1afd7SWarner Losh mii_phy_setmedia(sc); 1025fb1afd7SWarner Losh 1035fb1afd7SWarner Losh return (0); 1045fb1afd7SWarner Losh } 1055fb1afd7SWarner Losh 1065fb1afd7SWarner Losh static int 1075fb1afd7SWarner Losh axphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 1085fb1afd7SWarner Losh { 1095fb1afd7SWarner Losh 1105fb1afd7SWarner Losh switch (cmd) { 1115fb1afd7SWarner Losh case MII_POLLSTAT: 1125fb1afd7SWarner Losh break; 1135fb1afd7SWarner Losh 1145fb1afd7SWarner Losh case MII_MEDIACHG: 1155fb1afd7SWarner Losh mii_phy_setmedia(sc); 1165fb1afd7SWarner Losh break; 1175fb1afd7SWarner Losh 1185fb1afd7SWarner Losh case MII_TICK: 1195fb1afd7SWarner Losh if (mii_phy_tick(sc) == EJUSTRETURN) 1205fb1afd7SWarner Losh return (0); 1215fb1afd7SWarner Losh break; 1225fb1afd7SWarner Losh } 1235fb1afd7SWarner Losh 1245fb1afd7SWarner Losh /* Update the media status. */ 1253fcb7a53SMarius Strobl PHY_STATUS(sc); 1265fb1afd7SWarner Losh 1275fb1afd7SWarner Losh /* Callback if something changed. */ 1285fb1afd7SWarner Losh mii_phy_update(sc, cmd); 1295fb1afd7SWarner Losh return (0); 1305fb1afd7SWarner Losh } 1315fb1afd7SWarner Losh 1325fb1afd7SWarner Losh static void 1335fb1afd7SWarner Losh axphy_status(struct mii_softc *sc) 1345fb1afd7SWarner Losh { 1355fb1afd7SWarner Losh struct mii_data *mii = sc->mii_pdata; 1365fb1afd7SWarner Losh struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 1375fb1afd7SWarner Losh int bmsr, bmcr; 1385fb1afd7SWarner Losh 1395fb1afd7SWarner Losh mii->mii_media_status = IFM_AVALID; 1405fb1afd7SWarner Losh mii->mii_media_active = IFM_ETHER; 1415fb1afd7SWarner Losh 1425fb1afd7SWarner Losh bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 1435fb1afd7SWarner Losh if (bmsr & BMSR_LINK) 1445fb1afd7SWarner Losh mii->mii_media_status |= IFM_ACTIVE; 1455fb1afd7SWarner Losh 1465fb1afd7SWarner Losh bmcr = PHY_READ(sc, MII_BMCR); 1475fb1afd7SWarner Losh if (bmcr & BMCR_ISO) { 1485fb1afd7SWarner Losh mii->mii_media_active |= IFM_NONE; 1495fb1afd7SWarner Losh mii->mii_media_status = 0; 1505fb1afd7SWarner Losh return; 1515fb1afd7SWarner Losh } 1525fb1afd7SWarner Losh 1535fb1afd7SWarner Losh if (bmcr & BMCR_LOOP) 1545fb1afd7SWarner Losh mii->mii_media_active |= IFM_LOOP; 1555fb1afd7SWarner Losh 1565fb1afd7SWarner Losh if (bmcr & BMCR_AUTOEN) { 1575fb1afd7SWarner Losh if ((bmsr & BMSR_ACOMP) == 0) { 1585fb1afd7SWarner Losh mii->mii_media_active |= IFM_NONE; 1595fb1afd7SWarner Losh return; 1605fb1afd7SWarner Losh } 1615fb1afd7SWarner Losh 1625fb1afd7SWarner Losh #if 0 1635fb1afd7SWarner Losh scr = PHY_READ(sc, MII_AXPHY_SCR); 1645fb1afd7SWarner Losh if (scr & SCR_S100) 1655fb1afd7SWarner Losh mii->mii_media_active |= IFM_100_TX; 1665fb1afd7SWarner Losh else 1675fb1afd7SWarner Losh mii->mii_media_active |= IFM_10_T; 1685fb1afd7SWarner Losh if (scr & SCR_FDX) 1693fcb7a53SMarius Strobl mii->mii_media_active |= 1703fcb7a53SMarius Strobl IFM_FDX | mii_phy_flowstatus(sc); 171d7a9ad56SMarius Strobl else 172d7a9ad56SMarius Strobl mii->mii_media_active |= IFM_HDX; 1735fb1afd7SWarner Losh #endif 1745fb1afd7SWarner Losh } else 1755fb1afd7SWarner Losh mii->mii_media_active = ife->ifm_media; 1765fb1afd7SWarner Losh } 177