1b6d90eb7SKip Macy /************************************************************************** 2b6d90eb7SKip Macy 3b6d90eb7SKip Macy Copyright (c) 2007, Chelsio Inc. 4b6d90eb7SKip Macy All rights reserved. 5b6d90eb7SKip Macy 6b6d90eb7SKip Macy Redistribution and use in source and binary forms, with or without 7b6d90eb7SKip Macy modification, are permitted provided that the following conditions are met: 8b6d90eb7SKip Macy 9b6d90eb7SKip Macy 1. Redistributions of source code must retain the above copyright notice, 10b6d90eb7SKip Macy this list of conditions and the following disclaimer. 11b6d90eb7SKip Macy 1210faa568SKip Macy 2. Neither the name of the Chelsio Corporation nor the names of its 13b6d90eb7SKip Macy contributors may be used to endorse or promote products derived from 14b6d90eb7SKip Macy this software without specific prior written permission. 15b6d90eb7SKip Macy 16b6d90eb7SKip Macy THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17b6d90eb7SKip Macy AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18b6d90eb7SKip Macy IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19b6d90eb7SKip Macy ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20b6d90eb7SKip Macy LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21b6d90eb7SKip Macy CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22b6d90eb7SKip Macy SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23b6d90eb7SKip Macy INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24b6d90eb7SKip Macy CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25b6d90eb7SKip Macy ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26b6d90eb7SKip Macy POSSIBILITY OF SUCH DAMAGE. 27b6d90eb7SKip Macy 28b6d90eb7SKip Macy ***************************************************************************/ 29b6d90eb7SKip Macy 30b6d90eb7SKip Macy #include <sys/cdefs.h> 31b6d90eb7SKip Macy __FBSDID("$FreeBSD$"); 32b6d90eb7SKip Macy 3310faa568SKip Macy #ifdef CONFIG_DEFINED 3410faa568SKip Macy #include <cxgb_include.h> 3510faa568SKip Macy #else 3610faa568SKip Macy #include <dev/cxgb/cxgb_include.h> 3710faa568SKip Macy #endif 38b6d90eb7SKip Macy 398e10660fSKip Macy #undef msleep 408e10660fSKip Macy #define msleep t3_os_sleep 418e10660fSKip Macy 42b6d90eb7SKip Macy /* VSC8211 PHY specific registers. */ 43b6d90eb7SKip Macy enum { 448e10660fSKip Macy VSC8211_SIGDET_CTRL = 19, 458e10660fSKip Macy VSC8211_EXT_CTRL = 23, 46b6d90eb7SKip Macy VSC8211_INTR_ENABLE = 25, 47b6d90eb7SKip Macy VSC8211_INTR_STATUS = 26, 484af83c8cSKip Macy VSC8211_LED_CTRL = 27, 49b6d90eb7SKip Macy VSC8211_AUX_CTRL_STAT = 28, 508e10660fSKip Macy VSC8211_EXT_PAGE_AXS = 31, 51b6d90eb7SKip Macy }; 52b6d90eb7SKip Macy 53b6d90eb7SKip Macy enum { 54b6d90eb7SKip Macy VSC_INTR_RX_ERR = 1 << 0, 55b6d90eb7SKip Macy VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */ 56b6d90eb7SKip Macy VSC_INTR_CABLE = 1 << 2, /* cable impairment */ 57b6d90eb7SKip Macy VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */ 58b6d90eb7SKip Macy VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */ 59b6d90eb7SKip Macy VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */ 60b6d90eb7SKip Macy VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */ 61b6d90eb7SKip Macy VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */ 62b6d90eb7SKip Macy VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */ 63b6d90eb7SKip Macy VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */ 64b6d90eb7SKip Macy VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */ 658e10660fSKip Macy VSC_INTR_DPLX_CHG = 1 << 12, /* duplex change */ 66b6d90eb7SKip Macy VSC_INTR_LINK_CHG = 1 << 13, /* link change */ 678e10660fSKip Macy VSC_INTR_SPD_CHG = 1 << 14, /* speed change */ 68b6d90eb7SKip Macy VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */ 69b6d90eb7SKip Macy }; 70b6d90eb7SKip Macy 718e10660fSKip Macy enum { 728e10660fSKip Macy VSC_CTRL_CLAUSE37_VIEW = 1 << 4, /* Switch to Clause 37 view */ 738e10660fSKip Macy VSC_CTRL_MEDIA_MODE_HI = 0xf000 /* High part of media mode select */ 748e10660fSKip Macy }; 758e10660fSKip Macy 76b6d90eb7SKip Macy #define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \ 778e10660fSKip Macy VSC_INTR_DPLX_CHG | VSC_INTR_SPD_CHG | \ 78b6d90eb7SKip Macy VSC_INTR_NEG_DONE) 79b6d90eb7SKip Macy #define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \ 80b6d90eb7SKip Macy VSC_INTR_ENABLE) 81b6d90eb7SKip Macy 82b6d90eb7SKip Macy /* PHY specific auxiliary control & status register fields */ 83b6d90eb7SKip Macy #define S_ACSR_ACTIPHY_TMR 0 84b6d90eb7SKip Macy #define M_ACSR_ACTIPHY_TMR 0x3 85b6d90eb7SKip Macy #define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR) 86b6d90eb7SKip Macy 87b6d90eb7SKip Macy #define S_ACSR_SPEED 3 88b6d90eb7SKip Macy #define M_ACSR_SPEED 0x3 89b6d90eb7SKip Macy #define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED) 90b6d90eb7SKip Macy 91b6d90eb7SKip Macy #define S_ACSR_DUPLEX 5 92b6d90eb7SKip Macy #define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX) 93b6d90eb7SKip Macy 94b6d90eb7SKip Macy #define S_ACSR_ACTIPHY 6 95b6d90eb7SKip Macy #define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY) 96b6d90eb7SKip Macy 97b6d90eb7SKip Macy /* 98b6d90eb7SKip Macy * Reset the PHY. This PHY completes reset immediately so we never wait. 99b6d90eb7SKip Macy */ 100b6d90eb7SKip Macy static int vsc8211_reset(struct cphy *cphy, int wait) 101b6d90eb7SKip Macy { 102b6d90eb7SKip Macy return t3_phy_reset(cphy, 0, 0); 103b6d90eb7SKip Macy } 104b6d90eb7SKip Macy 105b6d90eb7SKip Macy static int vsc8211_intr_enable(struct cphy *cphy) 106b6d90eb7SKip Macy { 107b6d90eb7SKip Macy return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, INTR_MASK); 108b6d90eb7SKip Macy } 109b6d90eb7SKip Macy 110b6d90eb7SKip Macy static int vsc8211_intr_disable(struct cphy *cphy) 111b6d90eb7SKip Macy { 112b6d90eb7SKip Macy return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, 0); 113b6d90eb7SKip Macy } 114b6d90eb7SKip Macy 115b6d90eb7SKip Macy static int vsc8211_intr_clear(struct cphy *cphy) 116b6d90eb7SKip Macy { 117b6d90eb7SKip Macy u32 val; 118b6d90eb7SKip Macy 119b6d90eb7SKip Macy /* Clear PHY interrupts by reading the register. */ 120b6d90eb7SKip Macy return mdio_read(cphy, 0, VSC8211_INTR_STATUS, &val); 121b6d90eb7SKip Macy } 122b6d90eb7SKip Macy 123b6d90eb7SKip Macy static int vsc8211_autoneg_enable(struct cphy *cphy) 124b6d90eb7SKip Macy { 125b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 126b6d90eb7SKip Macy BMCR_ANENABLE | BMCR_ANRESTART); 127b6d90eb7SKip Macy } 128b6d90eb7SKip Macy 129b6d90eb7SKip Macy static int vsc8211_autoneg_restart(struct cphy *cphy) 130b6d90eb7SKip Macy { 131b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 132b6d90eb7SKip Macy BMCR_ANRESTART); 133b6d90eb7SKip Macy } 134b6d90eb7SKip Macy 135b6d90eb7SKip Macy static int vsc8211_get_link_status(struct cphy *cphy, int *link_ok, 136b6d90eb7SKip Macy int *speed, int *duplex, int *fc) 137b6d90eb7SKip Macy { 138b6d90eb7SKip Macy unsigned int bmcr, status, lpa, adv; 139b6d90eb7SKip Macy int err, sp = -1, dplx = -1, pause = 0; 140b6d90eb7SKip Macy 141b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_BMCR, &bmcr); 142b6d90eb7SKip Macy if (!err) 143b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status); 144b6d90eb7SKip Macy if (err) 145b6d90eb7SKip Macy return err; 146b6d90eb7SKip Macy 147b6d90eb7SKip Macy if (link_ok) { 148b6d90eb7SKip Macy /* 149b6d90eb7SKip Macy * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it 150b6d90eb7SKip Macy * once more to get the current link state. 151b6d90eb7SKip Macy */ 152b6d90eb7SKip Macy if (!(status & BMSR_LSTATUS)) 153b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status); 154b6d90eb7SKip Macy if (err) 155b6d90eb7SKip Macy return err; 156b6d90eb7SKip Macy *link_ok = (status & BMSR_LSTATUS) != 0; 157b6d90eb7SKip Macy } 158b6d90eb7SKip Macy if (!(bmcr & BMCR_ANENABLE)) { 159b6d90eb7SKip Macy dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; 160b6d90eb7SKip Macy if (bmcr & BMCR_SPEED1000) 161b6d90eb7SKip Macy sp = SPEED_1000; 162b6d90eb7SKip Macy else if (bmcr & BMCR_SPEED100) 163b6d90eb7SKip Macy sp = SPEED_100; 164b6d90eb7SKip Macy else 165b6d90eb7SKip Macy sp = SPEED_10; 166b6d90eb7SKip Macy } else if (status & BMSR_ANEGCOMPLETE) { 167b6d90eb7SKip Macy err = mdio_read(cphy, 0, VSC8211_AUX_CTRL_STAT, &status); 168b6d90eb7SKip Macy if (err) 169b6d90eb7SKip Macy return err; 170b6d90eb7SKip Macy 171b6d90eb7SKip Macy dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; 172b6d90eb7SKip Macy sp = G_ACSR_SPEED(status); 173b6d90eb7SKip Macy if (sp == 0) 174b6d90eb7SKip Macy sp = SPEED_10; 175b6d90eb7SKip Macy else if (sp == 1) 176b6d90eb7SKip Macy sp = SPEED_100; 177b6d90eb7SKip Macy else 178b6d90eb7SKip Macy sp = SPEED_1000; 179b6d90eb7SKip Macy 180b6d90eb7SKip Macy if (fc && dplx == DUPLEX_FULL) { 181b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_LPA, &lpa); 182b6d90eb7SKip Macy if (!err) 183b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); 184b6d90eb7SKip Macy if (err) 185b6d90eb7SKip Macy return err; 186b6d90eb7SKip Macy 187b6d90eb7SKip Macy if (lpa & adv & ADVERTISE_PAUSE_CAP) 188b6d90eb7SKip Macy pause = PAUSE_RX | PAUSE_TX; 189b6d90eb7SKip Macy else if ((lpa & ADVERTISE_PAUSE_CAP) && 190b6d90eb7SKip Macy (lpa & ADVERTISE_PAUSE_ASYM) && 191b6d90eb7SKip Macy (adv & ADVERTISE_PAUSE_ASYM)) 192b6d90eb7SKip Macy pause = PAUSE_TX; 193b6d90eb7SKip Macy else if ((lpa & ADVERTISE_PAUSE_ASYM) && 194b6d90eb7SKip Macy (adv & ADVERTISE_PAUSE_CAP)) 195b6d90eb7SKip Macy pause = PAUSE_RX; 196b6d90eb7SKip Macy } 197b6d90eb7SKip Macy } 198b6d90eb7SKip Macy if (speed) 199b6d90eb7SKip Macy *speed = sp; 200b6d90eb7SKip Macy if (duplex) 201b6d90eb7SKip Macy *duplex = dplx; 202b6d90eb7SKip Macy if (fc) 203b6d90eb7SKip Macy *fc = pause; 204b6d90eb7SKip Macy return 0; 205b6d90eb7SKip Macy } 206b6d90eb7SKip Macy 2078e10660fSKip Macy static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok, 2088e10660fSKip Macy int *speed, int *duplex, int *fc) 2098e10660fSKip Macy { 2108e10660fSKip Macy unsigned int bmcr, status, lpa, adv; 2118e10660fSKip Macy int err, sp = -1, dplx = -1, pause = 0; 2128e10660fSKip Macy 2138e10660fSKip Macy err = mdio_read(cphy, 0, MII_BMCR, &bmcr); 2148e10660fSKip Macy if (!err) 2158e10660fSKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status); 2168e10660fSKip Macy if (err) 2178e10660fSKip Macy return err; 2188e10660fSKip Macy 2198e10660fSKip Macy if (link_ok) { 2208e10660fSKip Macy /* 2218e10660fSKip Macy * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it 2228e10660fSKip Macy * once more to get the current link state. 2238e10660fSKip Macy */ 2248e10660fSKip Macy if (!(status & BMSR_LSTATUS)) 2258e10660fSKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status); 2268e10660fSKip Macy if (err) 2278e10660fSKip Macy return err; 2288e10660fSKip Macy *link_ok = (status & BMSR_LSTATUS) != 0; 2298e10660fSKip Macy } 2308e10660fSKip Macy if (!(bmcr & BMCR_ANENABLE)) { 2318e10660fSKip Macy dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; 2328e10660fSKip Macy if (bmcr & BMCR_SPEED1000) 2338e10660fSKip Macy sp = SPEED_1000; 2348e10660fSKip Macy else if (bmcr & BMCR_SPEED100) 2358e10660fSKip Macy sp = SPEED_100; 2368e10660fSKip Macy else 2378e10660fSKip Macy sp = SPEED_10; 2388e10660fSKip Macy } else if (status & BMSR_ANEGCOMPLETE) { 2398e10660fSKip Macy err = mdio_read(cphy, 0, MII_LPA, &lpa); 2408e10660fSKip Macy if (!err) 2418e10660fSKip Macy err = mdio_read(cphy, 0, MII_ADVERTISE, &adv); 2428e10660fSKip Macy if (err) 2438e10660fSKip Macy return err; 2448e10660fSKip Macy 2458e10660fSKip Macy if (adv & lpa & ADVERTISE_1000XFULL) { 2468e10660fSKip Macy dplx = DUPLEX_FULL; 2478e10660fSKip Macy sp = SPEED_1000; 2488e10660fSKip Macy } else if (adv & lpa & ADVERTISE_1000XHALF) { 2498e10660fSKip Macy dplx = DUPLEX_HALF; 2508e10660fSKip Macy sp = SPEED_1000; 2518e10660fSKip Macy } 2528e10660fSKip Macy 2538e10660fSKip Macy if (fc && dplx == DUPLEX_FULL) { 2548e10660fSKip Macy if (lpa & adv & ADVERTISE_1000XPAUSE) 2558e10660fSKip Macy pause = PAUSE_RX | PAUSE_TX; 2568e10660fSKip Macy else if ((lpa & ADVERTISE_1000XPAUSE) && 2578e10660fSKip Macy (adv & lpa & ADVERTISE_1000XPSE_ASYM)) 2588e10660fSKip Macy pause = PAUSE_TX; 2598e10660fSKip Macy else if ((lpa & ADVERTISE_1000XPSE_ASYM) && 2608e10660fSKip Macy (adv & ADVERTISE_1000XPAUSE)) 2618e10660fSKip Macy pause = PAUSE_RX; 2628e10660fSKip Macy } 2638e10660fSKip Macy } 2648e10660fSKip Macy if (speed) 2658e10660fSKip Macy *speed = sp; 2668e10660fSKip Macy if (duplex) 2678e10660fSKip Macy *duplex = dplx; 2688e10660fSKip Macy if (fc) 2698e10660fSKip Macy *fc = pause; 2708e10660fSKip Macy return 0; 2718e10660fSKip Macy } 2728e10660fSKip Macy 2738e10660fSKip Macy /* 2748e10660fSKip Macy * Enable/disable auto MDI/MDI-X in forced link speed mode. 2758e10660fSKip Macy */ 2768e10660fSKip Macy static int vsc8211_set_automdi(struct cphy *phy, int enable) 2778e10660fSKip Macy { 2788e10660fSKip Macy int err; 2798e10660fSKip Macy 2808e10660fSKip Macy if ((err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5)) != 0 || 2818e10660fSKip Macy (err = mdio_write(phy, 0, 18, 0x12)) != 0 || 2828e10660fSKip Macy (err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003)) != 0 || 2838e10660fSKip Macy (err = mdio_write(phy, 0, 16, 0x87fa)) != 0 || 2848e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0)) != 0) 2858e10660fSKip Macy return err; 2868e10660fSKip Macy return 0; 2878e10660fSKip Macy } 2888e10660fSKip Macy 2898e10660fSKip Macy static int vsc8211_set_speed_duplex(struct cphy *phy, int speed, int duplex) 2908e10660fSKip Macy { 2918e10660fSKip Macy int err; 2928e10660fSKip Macy 2938e10660fSKip Macy err = t3_set_phy_speed_duplex(phy, speed, duplex); 2948e10660fSKip Macy if (!err) 2958e10660fSKip Macy err = vsc8211_set_automdi(phy, 1); 2968e10660fSKip Macy return err; 2978e10660fSKip Macy } 2988e10660fSKip Macy 299b6d90eb7SKip Macy static int vsc8211_power_down(struct cphy *cphy, int enable) 300b6d90eb7SKip Macy { 301b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN, 302b6d90eb7SKip Macy enable ? BMCR_PDOWN : 0); 303b6d90eb7SKip Macy } 304b6d90eb7SKip Macy 305b6d90eb7SKip Macy static int vsc8211_intr_handler(struct cphy *cphy) 306b6d90eb7SKip Macy { 307b6d90eb7SKip Macy unsigned int cause; 308b6d90eb7SKip Macy int err, cphy_cause = 0; 309b6d90eb7SKip Macy 310b6d90eb7SKip Macy err = mdio_read(cphy, 0, VSC8211_INTR_STATUS, &cause); 311b6d90eb7SKip Macy if (err) 312b6d90eb7SKip Macy return err; 313b6d90eb7SKip Macy 314b6d90eb7SKip Macy cause &= INTR_MASK; 315b6d90eb7SKip Macy if (cause & CFG_CHG_INTR_MASK) 316b6d90eb7SKip Macy cphy_cause |= cphy_cause_link_change; 317b6d90eb7SKip Macy if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO)) 318b6d90eb7SKip Macy cphy_cause |= cphy_cause_fifo_error; 319b6d90eb7SKip Macy return cphy_cause; 320b6d90eb7SKip Macy } 321b6d90eb7SKip Macy 322b6d90eb7SKip Macy #ifdef C99_NOT_SUPPORTED 323b6d90eb7SKip Macy static struct cphy_ops vsc8211_ops = { 324b6d90eb7SKip Macy vsc8211_reset, 325b6d90eb7SKip Macy vsc8211_intr_enable, 326b6d90eb7SKip Macy vsc8211_intr_disable, 327b6d90eb7SKip Macy vsc8211_intr_clear, 328b6d90eb7SKip Macy vsc8211_intr_handler, 329b6d90eb7SKip Macy vsc8211_autoneg_enable, 330b6d90eb7SKip Macy vsc8211_autoneg_restart, 331b6d90eb7SKip Macy t3_phy_advertise, 332b6d90eb7SKip Macy NULL, 3338e10660fSKip Macy vsc8211_set_speed_duplex, 334b6d90eb7SKip Macy vsc8211_get_link_status, 335b6d90eb7SKip Macy vsc8211_power_down, 336b6d90eb7SKip Macy }; 3378e10660fSKip Macy 3388e10660fSKip Macy static struct cphy_ops vsc8211_fiber_ops = { 3398e10660fSKip Macy vsc8211_reset, 3408e10660fSKip Macy vsc8211_intr_enable, 3418e10660fSKip Macy vsc8211_intr_disable, 3428e10660fSKip Macy vsc8211_intr_clear, 3438e10660fSKip Macy vsc8211_intr_handler, 3448e10660fSKip Macy vsc8211_autoneg_enable, 3458e10660fSKip Macy vsc8211_autoneg_restart, 3468e10660fSKip Macy t3_phy_advertise_fiber, 3478e10660fSKip Macy NULL, 3488e10660fSKip Macy t3_set_phy_speed_duplex, 3498e10660fSKip Macy vsc8211_get_link_status_fiber, 3508e10660fSKip Macy vsc8211_power_down, 3518e10660fSKip Macy }; 352b6d90eb7SKip Macy #else 353b6d90eb7SKip Macy static struct cphy_ops vsc8211_ops = { 354b6d90eb7SKip Macy .reset = vsc8211_reset, 355b6d90eb7SKip Macy .intr_enable = vsc8211_intr_enable, 356b6d90eb7SKip Macy .intr_disable = vsc8211_intr_disable, 357b6d90eb7SKip Macy .intr_clear = vsc8211_intr_clear, 358b6d90eb7SKip Macy .intr_handler = vsc8211_intr_handler, 359b6d90eb7SKip Macy .autoneg_enable = vsc8211_autoneg_enable, 360b6d90eb7SKip Macy .autoneg_restart = vsc8211_autoneg_restart, 361b6d90eb7SKip Macy .advertise = t3_phy_advertise, 3628e10660fSKip Macy .set_speed_duplex = vsc8211_set_speed_duplex, 363b6d90eb7SKip Macy .get_link_status = vsc8211_get_link_status, 364b6d90eb7SKip Macy .power_down = vsc8211_power_down, 365b6d90eb7SKip Macy }; 3668e10660fSKip Macy 3678e10660fSKip Macy static struct cphy_ops vsc8211_fiber_ops = { 3688e10660fSKip Macy .reset = vsc8211_reset, 3698e10660fSKip Macy .intr_enable = vsc8211_intr_enable, 3708e10660fSKip Macy .intr_disable = vsc8211_intr_disable, 3718e10660fSKip Macy .intr_clear = vsc8211_intr_clear, 3728e10660fSKip Macy .intr_handler = vsc8211_intr_handler, 3738e10660fSKip Macy .autoneg_enable = vsc8211_autoneg_enable, 3748e10660fSKip Macy .autoneg_restart = vsc8211_autoneg_restart, 3758e10660fSKip Macy .advertise = t3_phy_advertise_fiber, 3768e10660fSKip Macy .set_speed_duplex = t3_set_phy_speed_duplex, 3778e10660fSKip Macy .get_link_status = vsc8211_get_link_status_fiber, 3788e10660fSKip Macy .power_down = vsc8211_power_down, 3798e10660fSKip Macy }; 380b6d90eb7SKip Macy #endif 381b6d90eb7SKip Macy 3828e10660fSKip Macy int t3_vsc8211_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 383b6d90eb7SKip Macy const struct mdio_ops *mdio_ops) 384b6d90eb7SKip Macy { 3858e10660fSKip Macy int err; 3868e10660fSKip Macy unsigned int val; 3878e10660fSKip Macy 3888e10660fSKip Macy cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops, 3898e10660fSKip Macy SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full | 3908e10660fSKip Macy SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII | 3918e10660fSKip Macy SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T"); 3928e10660fSKip Macy msleep(20); /* PHY needs ~10ms to start responding to MDIO */ 3938e10660fSKip Macy 3948e10660fSKip Macy err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val); 3958e10660fSKip Macy if (err) 3968e10660fSKip Macy return err; 3974af83c8cSKip Macy if (val & VSC_CTRL_MEDIA_MODE_HI) { 3984af83c8cSKip Macy /* copper interface, just need to configure the LEDs */ 3994af83c8cSKip Macy return mdio_write(phy, 0, VSC8211_LED_CTRL, 0x100); 4004af83c8cSKip Macy } 4018e10660fSKip Macy 4028e10660fSKip Macy phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | 4038e10660fSKip Macy SUPPORTED_MII | SUPPORTED_FIBRE | SUPPORTED_IRQ; 4048e10660fSKip Macy phy->desc = "1000BASE-X"; 4058e10660fSKip Macy phy->ops = &vsc8211_fiber_ops; 4068e10660fSKip Macy 4078e10660fSKip Macy if ((err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1)) != 0 || 4088e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1)) != 0 || 4098e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0)) != 0 || 4108e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_EXT_CTRL, 4118e10660fSKip Macy val | VSC_CTRL_CLAUSE37_VIEW)) != 0 || 4128e10660fSKip Macy (err = vsc8211_reset(phy, 0)) != 0) 4138e10660fSKip Macy return err; 4148e10660fSKip Macy 4158e10660fSKip Macy udelay(5); /* delay after reset before next SMI */ 4168e10660fSKip Macy return 0; 417b6d90eb7SKip Macy } 418