1d1307e81SPyun YongHyeon /*- 2d1307e81SPyun YongHyeon * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org> 3d1307e81SPyun YongHyeon * All rights reserved. 4d1307e81SPyun YongHyeon * 5d1307e81SPyun YongHyeon * Redistribution and use in source and binary forms, with or without 6d1307e81SPyun YongHyeon * modification, are permitted provided that the following conditions 7d1307e81SPyun YongHyeon * are met: 8d1307e81SPyun YongHyeon * 1. Redistributions of source code must retain the above copyright 9d1307e81SPyun YongHyeon * notice unmodified, this list of conditions, and the following 10d1307e81SPyun YongHyeon * disclaimer. 11d1307e81SPyun YongHyeon * 2. Redistributions in binary form must reproduce the above copyright 12d1307e81SPyun YongHyeon * notice, this list of conditions and the following disclaimer in the 13d1307e81SPyun YongHyeon * documentation and/or other materials provided with the distribution. 14d1307e81SPyun YongHyeon * 15d1307e81SPyun YongHyeon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16d1307e81SPyun YongHyeon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17d1307e81SPyun YongHyeon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18d1307e81SPyun YongHyeon * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19d1307e81SPyun YongHyeon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20d1307e81SPyun YongHyeon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21d1307e81SPyun YongHyeon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22d1307e81SPyun YongHyeon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23d1307e81SPyun YongHyeon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24d1307e81SPyun YongHyeon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25d1307e81SPyun YongHyeon * SUCH DAMAGE. 26d1307e81SPyun YongHyeon */ 27d1307e81SPyun YongHyeon 28d1307e81SPyun YongHyeon #include <sys/cdefs.h> 29d1307e81SPyun YongHyeon __FBSDID("$FreeBSD$"); 30d1307e81SPyun YongHyeon 31d1307e81SPyun YongHyeon /* 32d1307e81SPyun YongHyeon * Driver for the Attansic/Atheros F1 10/100/1000 PHY. 33d1307e81SPyun YongHyeon */ 34d1307e81SPyun YongHyeon 35d1307e81SPyun YongHyeon #include <sys/param.h> 36d1307e81SPyun YongHyeon #include <sys/systm.h> 37d1307e81SPyun YongHyeon #include <sys/kernel.h> 38d1307e81SPyun YongHyeon #include <sys/module.h> 39d1307e81SPyun YongHyeon #include <sys/socket.h> 40d1307e81SPyun YongHyeon #include <sys/bus.h> 41d1307e81SPyun YongHyeon 42d1307e81SPyun YongHyeon #include <net/if.h> 43d1307e81SPyun YongHyeon #include <net/if_media.h> 44d1307e81SPyun YongHyeon 45d1307e81SPyun YongHyeon #include <dev/mii/mii.h> 46d1307e81SPyun YongHyeon #include <dev/mii/miivar.h> 47d1307e81SPyun YongHyeon #include "miidevs.h" 48d1307e81SPyun YongHyeon 49d1307e81SPyun YongHyeon #include <dev/mii/atphyreg.h> 50d1307e81SPyun YongHyeon 51d1307e81SPyun YongHyeon #include "miibus_if.h" 52d1307e81SPyun YongHyeon 53d1307e81SPyun YongHyeon static int atphy_probe(device_t); 54d1307e81SPyun YongHyeon static int atphy_attach(device_t); 55d1307e81SPyun YongHyeon 56d1307e81SPyun YongHyeon static device_method_t atphy_methods[] = { 57d1307e81SPyun YongHyeon /* Device interface. */ 58d1307e81SPyun YongHyeon DEVMETHOD(device_probe, atphy_probe), 59d1307e81SPyun YongHyeon DEVMETHOD(device_attach, atphy_attach), 60d1307e81SPyun YongHyeon DEVMETHOD(device_detach, mii_phy_detach), 61d1307e81SPyun YongHyeon DEVMETHOD(device_shutdown, bus_generic_shutdown), 62d1307e81SPyun YongHyeon { NULL, NULL } 63d1307e81SPyun YongHyeon }; 64d1307e81SPyun YongHyeon 65d1307e81SPyun YongHyeon static devclass_t atphy_devclass; 66d1307e81SPyun YongHyeon static driver_t atphy_driver = { 67d1307e81SPyun YongHyeon "atphy", 68d1307e81SPyun YongHyeon atphy_methods, 693fcb7a53SMarius Strobl sizeof(struct mii_softc) 70d1307e81SPyun YongHyeon }; 71d1307e81SPyun YongHyeon 72d1307e81SPyun YongHyeon DRIVER_MODULE(atphy, miibus, atphy_driver, atphy_devclass, 0, 0); 73d1307e81SPyun YongHyeon 74d1307e81SPyun YongHyeon static int atphy_service(struct mii_softc *, struct mii_data *, int); 75d1307e81SPyun YongHyeon static void atphy_status(struct mii_softc *); 76d1307e81SPyun YongHyeon static void atphy_reset(struct mii_softc *); 77d1307e81SPyun YongHyeon static uint16_t atphy_anar(struct ifmedia_entry *); 78991ab941SMarius Strobl static int atphy_setmedia(struct mii_softc *, int); 79d1307e81SPyun YongHyeon 80d1307e81SPyun YongHyeon static const struct mii_phydesc atphys[] = { 813fcb7a53SMarius Strobl MII_PHY_DESC(xxATHEROS, F1), 823fcb7a53SMarius Strobl MII_PHY_DESC(xxATHEROS, F1_7), 833fcb7a53SMarius Strobl MII_PHY_DESC(xxATHEROS, F2), 84d1307e81SPyun YongHyeon MII_PHY_END 85d1307e81SPyun YongHyeon }; 86d1307e81SPyun YongHyeon 873fcb7a53SMarius Strobl static const struct mii_phy_funcs atphy_funcs = { 883fcb7a53SMarius Strobl atphy_service, 893fcb7a53SMarius Strobl atphy_status, 903fcb7a53SMarius Strobl atphy_reset 913fcb7a53SMarius Strobl }; 923fcb7a53SMarius Strobl 93d1307e81SPyun YongHyeon static int 94d1307e81SPyun YongHyeon atphy_probe(device_t dev) 95d1307e81SPyun YongHyeon { 96d1307e81SPyun YongHyeon 97d1307e81SPyun YongHyeon return (mii_phy_dev_probe(dev, atphys, BUS_PROBE_DEFAULT)); 98d1307e81SPyun YongHyeon } 99d1307e81SPyun YongHyeon 100d1307e81SPyun YongHyeon static int 101d1307e81SPyun YongHyeon atphy_attach(device_t dev) 102d1307e81SPyun YongHyeon { 103d1307e81SPyun YongHyeon 1043fcb7a53SMarius Strobl mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &atphy_funcs, 1); 105d1307e81SPyun YongHyeon return (0); 106d1307e81SPyun YongHyeon } 107d1307e81SPyun YongHyeon 108d1307e81SPyun YongHyeon static int 109d1307e81SPyun YongHyeon atphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 110d1307e81SPyun YongHyeon { 111d1307e81SPyun YongHyeon struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 112d1307e81SPyun YongHyeon uint16_t anar, bmcr, bmsr; 113d1307e81SPyun YongHyeon 114d1307e81SPyun YongHyeon switch (cmd) { 115d1307e81SPyun YongHyeon case MII_POLLSTAT: 116d1307e81SPyun YongHyeon break; 117d1307e81SPyun YongHyeon 118d1307e81SPyun YongHyeon case MII_MEDIACHG: 119d1307e81SPyun YongHyeon /* 120d1307e81SPyun YongHyeon * If the interface is not up, don't do anything. 121d1307e81SPyun YongHyeon */ 122d1307e81SPyun YongHyeon if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 123d1307e81SPyun YongHyeon break; 124d1307e81SPyun YongHyeon 125d1307e81SPyun YongHyeon if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO || 126d1307e81SPyun YongHyeon IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { 127991ab941SMarius Strobl atphy_setmedia(sc, ife->ifm_media); 128d1307e81SPyun YongHyeon break; 129d1307e81SPyun YongHyeon } 130d1307e81SPyun YongHyeon 131d1307e81SPyun YongHyeon bmcr = 0; 132d1307e81SPyun YongHyeon switch (IFM_SUBTYPE(ife->ifm_media)) { 133d1307e81SPyun YongHyeon case IFM_100_TX: 134d1307e81SPyun YongHyeon bmcr = BMCR_S100; 135d1307e81SPyun YongHyeon break; 136d1307e81SPyun YongHyeon case IFM_10_T: 137d1307e81SPyun YongHyeon bmcr = BMCR_S10; 138d1307e81SPyun YongHyeon break; 139d1307e81SPyun YongHyeon case IFM_NONE: 140d1307e81SPyun YongHyeon bmcr = PHY_READ(sc, MII_BMCR); 141d1307e81SPyun YongHyeon /* 142d1307e81SPyun YongHyeon * XXX 143d1307e81SPyun YongHyeon * Due to an unknown reason powering down PHY resulted 144991ab941SMarius Strobl * in unexpected results such as inaccessibility of 145d1307e81SPyun YongHyeon * hardware of freshly rebooted system. Disable 146d1307e81SPyun YongHyeon * powering down PHY until I got more information for 147d1307e81SPyun YongHyeon * Attansic/Atheros PHY hardwares. 148d1307e81SPyun YongHyeon */ 149d1307e81SPyun YongHyeon PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO); 150d1307e81SPyun YongHyeon goto done; 151d1307e81SPyun YongHyeon default: 152d1307e81SPyun YongHyeon return (EINVAL); 153d1307e81SPyun YongHyeon } 154d1307e81SPyun YongHyeon 155d1307e81SPyun YongHyeon anar = atphy_anar(ife); 15634259ba3SMarius Strobl if ((ife->ifm_media & IFM_FDX) != 0) { 157d1307e81SPyun YongHyeon bmcr |= BMCR_FDX; 15834259ba3SMarius Strobl if ((ife->ifm_media & IFM_FLOW) != 0 || 159991ab941SMarius Strobl (sc->mii_flags & MIIF_FORCEPAUSE) != 0) 160991ab941SMarius Strobl anar |= ANAR_PAUSE_TOWARDS; 161d1307e81SPyun YongHyeon } 162d1307e81SPyun YongHyeon 163d1307e81SPyun YongHyeon if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | 164d1307e81SPyun YongHyeon EXTSR_1000THDX)) != 0) 165d1307e81SPyun YongHyeon PHY_WRITE(sc, MII_100T2CR, 0); 166d1307e81SPyun YongHyeon PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA); 167d1307e81SPyun YongHyeon 168d1307e81SPyun YongHyeon /* 169d1307e81SPyun YongHyeon * Reset the PHY so all changes take effect. 170d1307e81SPyun YongHyeon */ 171d2cd2263SPyun YongHyeon PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_RESET | BMCR_AUTOEN | 172d2cd2263SPyun YongHyeon BMCR_STARTNEG); 173d1307e81SPyun YongHyeon done: 174d1307e81SPyun YongHyeon break; 175d1307e81SPyun YongHyeon 176d1307e81SPyun YongHyeon case MII_TICK: 177d1307e81SPyun YongHyeon /* 178d1307e81SPyun YongHyeon * Is the interface even up? 179d1307e81SPyun YongHyeon */ 180d1307e81SPyun YongHyeon if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 181d1307e81SPyun YongHyeon return (0); 182d1307e81SPyun YongHyeon 183d1307e81SPyun YongHyeon /* 184d1307e81SPyun YongHyeon * Only used for autonegotiation. 185d1307e81SPyun YongHyeon */ 186d1307e81SPyun YongHyeon if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { 187d1307e81SPyun YongHyeon sc->mii_ticks = 0; 188d1307e81SPyun YongHyeon break; 189d1307e81SPyun YongHyeon } 190d1307e81SPyun YongHyeon 191d1307e81SPyun YongHyeon /* 192991ab941SMarius Strobl * Check for link. 193d1307e81SPyun YongHyeon * Read the status register twice; BMSR_LINK is latch-low. 194d1307e81SPyun YongHyeon */ 195d1307e81SPyun YongHyeon bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 196d1307e81SPyun YongHyeon if (bmsr & BMSR_LINK) { 197d1307e81SPyun YongHyeon sc->mii_ticks = 0; 198d1307e81SPyun YongHyeon break; 199d1307e81SPyun YongHyeon } 200d1307e81SPyun YongHyeon 201d1307e81SPyun YongHyeon /* Announce link loss right after it happens. */ 202d1307e81SPyun YongHyeon if (sc->mii_ticks++ == 0) 203d1307e81SPyun YongHyeon break; 204d1307e81SPyun YongHyeon if (sc->mii_ticks <= sc->mii_anegticks) 205d1307e81SPyun YongHyeon return (0); 206d1307e81SPyun YongHyeon 207d1307e81SPyun YongHyeon sc->mii_ticks = 0; 208991ab941SMarius Strobl atphy_setmedia(sc, ife->ifm_media); 209d1307e81SPyun YongHyeon break; 210d1307e81SPyun YongHyeon } 211d1307e81SPyun YongHyeon 212d1307e81SPyun YongHyeon /* Update the media status. */ 2133fcb7a53SMarius Strobl PHY_STATUS(sc); 214d1307e81SPyun YongHyeon 215d1307e81SPyun YongHyeon /* Callback if something changed. */ 216d1307e81SPyun YongHyeon mii_phy_update(sc, cmd); 217d1307e81SPyun YongHyeon return (0); 218d1307e81SPyun YongHyeon } 219d1307e81SPyun YongHyeon 220d1307e81SPyun YongHyeon static void 221d1307e81SPyun YongHyeon atphy_status(struct mii_softc *sc) 222d1307e81SPyun YongHyeon { 223d1307e81SPyun YongHyeon struct mii_data *mii = sc->mii_pdata; 224d1307e81SPyun YongHyeon uint32_t bmsr, bmcr, ssr; 225d1307e81SPyun YongHyeon 226d1307e81SPyun YongHyeon mii->mii_media_status = IFM_AVALID; 227d1307e81SPyun YongHyeon mii->mii_media_active = IFM_ETHER; 228d1307e81SPyun YongHyeon 229d1307e81SPyun YongHyeon bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 230d1307e81SPyun YongHyeon if ((bmsr & BMSR_LINK) != 0) 231d1307e81SPyun YongHyeon mii->mii_media_status |= IFM_ACTIVE; 232d1307e81SPyun YongHyeon 233d1307e81SPyun YongHyeon bmcr = PHY_READ(sc, MII_BMCR); 234d1307e81SPyun YongHyeon if ((bmcr & BMCR_ISO) != 0) { 235d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_NONE; 236d1307e81SPyun YongHyeon mii->mii_media_status = 0; 237d1307e81SPyun YongHyeon return; 238d1307e81SPyun YongHyeon } 239d1307e81SPyun YongHyeon 240d1307e81SPyun YongHyeon if ((bmcr & BMCR_LOOP) != 0) 241d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_LOOP; 242d1307e81SPyun YongHyeon 243d1307e81SPyun YongHyeon ssr = PHY_READ(sc, ATPHY_SSR); 244d1307e81SPyun YongHyeon if ((ssr & ATPHY_SSR_SPD_DPLX_RESOLVED) == 0) { 245d1307e81SPyun YongHyeon /* Erg, still trying, I guess... */ 246d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_NONE; 247d1307e81SPyun YongHyeon return; 248d1307e81SPyun YongHyeon } 249d1307e81SPyun YongHyeon 250d1307e81SPyun YongHyeon switch (ssr & ATPHY_SSR_SPEED_MASK) { 251d1307e81SPyun YongHyeon case ATPHY_SSR_1000MBS: 252d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_1000_T; 253d1307e81SPyun YongHyeon /* 254991ab941SMarius Strobl * atphy(4) has a valid link so reset mii_ticks. 255d1307e81SPyun YongHyeon * Resetting mii_ticks is needed in order to 256d1307e81SPyun YongHyeon * detect link loss after auto-negotiation. 257d1307e81SPyun YongHyeon */ 258d1307e81SPyun YongHyeon sc->mii_ticks = 0; 259d1307e81SPyun YongHyeon break; 260d1307e81SPyun YongHyeon case ATPHY_SSR_100MBS: 261d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_100_TX; 262d1307e81SPyun YongHyeon sc->mii_ticks = 0; 263d1307e81SPyun YongHyeon break; 264d1307e81SPyun YongHyeon case ATPHY_SSR_10MBS: 265d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_10_T; 266d1307e81SPyun YongHyeon sc->mii_ticks = 0; 267d1307e81SPyun YongHyeon break; 268d1307e81SPyun YongHyeon default: 269d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_NONE; 270d1307e81SPyun YongHyeon return; 271d1307e81SPyun YongHyeon } 272d1307e81SPyun YongHyeon 273d1307e81SPyun YongHyeon if ((ssr & ATPHY_SSR_DUPLEX) != 0) 274991ab941SMarius Strobl mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); 275d1307e81SPyun YongHyeon else 276d1307e81SPyun YongHyeon mii->mii_media_active |= IFM_HDX; 277d1307e81SPyun YongHyeon 278991ab941SMarius Strobl if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) && 279991ab941SMarius Strobl (PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0) 280991ab941SMarius Strobl mii->mii_media_active |= IFM_ETH_MASTER; 281d1307e81SPyun YongHyeon } 282d1307e81SPyun YongHyeon 283d1307e81SPyun YongHyeon static void 284d1307e81SPyun YongHyeon atphy_reset(struct mii_softc *sc) 285d1307e81SPyun YongHyeon { 286bab85d8dSMarius Strobl struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; 287d1307e81SPyun YongHyeon uint32_t reg; 288d1307e81SPyun YongHyeon int i; 289d1307e81SPyun YongHyeon 290d1307e81SPyun YongHyeon /* Take PHY out of power down mode. */ 291d1307e81SPyun YongHyeon PHY_WRITE(sc, 29, 0x29); 292d1307e81SPyun YongHyeon PHY_WRITE(sc, 30, 0); 293d1307e81SPyun YongHyeon 294d1307e81SPyun YongHyeon reg = PHY_READ(sc, ATPHY_SCR); 295d1307e81SPyun YongHyeon /* Enable automatic crossover. */ 296d1307e81SPyun YongHyeon reg |= ATPHY_SCR_AUTO_X_MODE; 297d1307e81SPyun YongHyeon /* Disable power down. */ 298d1307e81SPyun YongHyeon reg &= ~ATPHY_SCR_MAC_PDOWN; 299d1307e81SPyun YongHyeon /* Enable CRS on Tx. */ 300d1307e81SPyun YongHyeon reg |= ATPHY_SCR_ASSERT_CRS_ON_TX; 301d1307e81SPyun YongHyeon /* Auto correction for reversed cable polarity. */ 302d1307e81SPyun YongHyeon reg |= ATPHY_SCR_POLARITY_REVERSAL; 303d1307e81SPyun YongHyeon PHY_WRITE(sc, ATPHY_SCR, reg); 304d1307e81SPyun YongHyeon 305d1307e81SPyun YongHyeon /* Workaround F1 bug to reset phy. */ 306bab85d8dSMarius Strobl atphy_setmedia(sc, ife == NULL ? IFM_AUTO : ife->ifm_media); 307d1307e81SPyun YongHyeon 308d1307e81SPyun YongHyeon for (i = 0; i < 1000; i++) { 309d1307e81SPyun YongHyeon DELAY(1); 310d1307e81SPyun YongHyeon if ((PHY_READ(sc, MII_BMCR) & BMCR_RESET) == 0) 311d1307e81SPyun YongHyeon break; 312d1307e81SPyun YongHyeon } 313d1307e81SPyun YongHyeon } 314d1307e81SPyun YongHyeon 315d1307e81SPyun YongHyeon static uint16_t 316d1307e81SPyun YongHyeon atphy_anar(struct ifmedia_entry *ife) 317d1307e81SPyun YongHyeon { 318d1307e81SPyun YongHyeon uint16_t anar; 319d1307e81SPyun YongHyeon 320d1307e81SPyun YongHyeon anar = 0; 321d1307e81SPyun YongHyeon switch (IFM_SUBTYPE(ife->ifm_media)) { 322d1307e81SPyun YongHyeon case IFM_AUTO: 323d1307e81SPyun YongHyeon anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10; 324d1307e81SPyun YongHyeon return (anar); 325d1307e81SPyun YongHyeon case IFM_1000_T: 326d1307e81SPyun YongHyeon return (anar); 327d1307e81SPyun YongHyeon case IFM_100_TX: 328d1307e81SPyun YongHyeon anar |= ANAR_TX; 329d1307e81SPyun YongHyeon break; 330d1307e81SPyun YongHyeon case IFM_10_T: 331d1307e81SPyun YongHyeon anar |= ANAR_10; 332d1307e81SPyun YongHyeon break; 333d1307e81SPyun YongHyeon default: 334d1307e81SPyun YongHyeon return (0); 335d1307e81SPyun YongHyeon } 336d1307e81SPyun YongHyeon 33734259ba3SMarius Strobl if ((ife->ifm_media & IFM_FDX) != 0) { 338d1307e81SPyun YongHyeon if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_TX) 339d1307e81SPyun YongHyeon anar |= ANAR_TX_FD; 340d1307e81SPyun YongHyeon else 341d1307e81SPyun YongHyeon anar |= ANAR_10_FD; 342d1307e81SPyun YongHyeon } 343d1307e81SPyun YongHyeon 344d1307e81SPyun YongHyeon return (anar); 345d1307e81SPyun YongHyeon } 346d1307e81SPyun YongHyeon 347d1307e81SPyun YongHyeon static int 348991ab941SMarius Strobl atphy_setmedia(struct mii_softc *sc, int media) 349d1307e81SPyun YongHyeon { 350d1307e81SPyun YongHyeon uint16_t anar; 351d1307e81SPyun YongHyeon 352991ab941SMarius Strobl anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; 35334259ba3SMarius Strobl if ((IFM_SUBTYPE(media) == IFM_AUTO || (media & IFM_FDX) != 0) && 35434259ba3SMarius Strobl ((media & IFM_FLOW) != 0 || 35534259ba3SMarius Strobl (sc->mii_flags & MIIF_FORCEPAUSE) != 0)) 356991ab941SMarius Strobl anar |= ANAR_PAUSE_TOWARDS; 357991ab941SMarius Strobl PHY_WRITE(sc, MII_ANAR, anar); 35834259ba3SMarius Strobl if ((sc->mii_extcapabilities & 35934259ba3SMarius Strobl (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0) 360d1307e81SPyun YongHyeon PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX | 361d1307e81SPyun YongHyeon GTCR_ADV_1000THDX); 362*f6d9580dSPyun YongHyeon else if (sc->mii_mpd_model == MII_MODEL_xxATHEROS_F1) { 363*f6d9580dSPyun YongHyeon /* 364*f6d9580dSPyun YongHyeon * AR8132 has 10/100 PHY and the PHY uses the same 365*f6d9580dSPyun YongHyeon * model number of F1 gigabit PHY. The PHY has no 366*f6d9580dSPyun YongHyeon * ability to establish gigabit link so explicitly 367*f6d9580dSPyun YongHyeon * disable 1000baseT configuration for the PHY. 368*f6d9580dSPyun YongHyeon * Otherwise, there is a case that atphy(4) could 369*f6d9580dSPyun YongHyeon * not establish a link against gigabit link partner 370*f6d9580dSPyun YongHyeon * unless the link partner supports down-shifting. 371*f6d9580dSPyun YongHyeon */ 372*f6d9580dSPyun YongHyeon PHY_WRITE(sc, MII_100T2CR, 0); 373*f6d9580dSPyun YongHyeon } 374d1307e81SPyun YongHyeon PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG); 375d1307e81SPyun YongHyeon 376d1307e81SPyun YongHyeon return (EJUSTRETURN); 377d1307e81SPyun YongHyeon } 378