1b6d90eb7SKip Macy /**************************************************************************
2*4d846d26SWarner Losh SPDX-License-Identifier: BSD-2-Clause
3b6d90eb7SKip Macy
4b6d90eb7SKip Macy Copyright (c) 2007, Chelsio Inc.
5b6d90eb7SKip Macy All rights reserved.
6b6d90eb7SKip Macy
7b6d90eb7SKip Macy Redistribution and use in source and binary forms, with or without
8b6d90eb7SKip Macy modification, are permitted provided that the following conditions are met:
9b6d90eb7SKip Macy
10b6d90eb7SKip Macy 1. Redistributions of source code must retain the above copyright notice,
11b6d90eb7SKip Macy this list of conditions and the following disclaimer.
12b6d90eb7SKip Macy
1310faa568SKip Macy 2. Neither the name of the Chelsio Corporation nor the names of its
14b6d90eb7SKip Macy contributors may be used to endorse or promote products derived from
15b6d90eb7SKip Macy this software without specific prior written permission.
16b6d90eb7SKip Macy
17b6d90eb7SKip Macy THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18b6d90eb7SKip Macy AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19b6d90eb7SKip Macy IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20b6d90eb7SKip Macy ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21b6d90eb7SKip Macy LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22b6d90eb7SKip Macy CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23b6d90eb7SKip Macy SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24b6d90eb7SKip Macy INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25b6d90eb7SKip Macy CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26b6d90eb7SKip Macy ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27b6d90eb7SKip Macy POSSIBILITY OF SUCH DAMAGE.
28b6d90eb7SKip Macy
29b6d90eb7SKip Macy ***************************************************************************/
30b6d90eb7SKip Macy
31b6d90eb7SKip Macy #include <sys/cdefs.h>
3210faa568SKip Macy #include <cxgb_include.h>
33b6d90eb7SKip Macy
348e10660fSKip Macy #undef msleep
358e10660fSKip Macy #define msleep t3_os_sleep
368e10660fSKip Macy
37b6d90eb7SKip Macy /* VSC8211 PHY specific registers. */
38b6d90eb7SKip Macy enum {
398e10660fSKip Macy VSC8211_SIGDET_CTRL = 19,
408e10660fSKip Macy VSC8211_EXT_CTRL = 23,
41c01f2b83SNavdeep Parhar VSC8211_PHY_CTRL = 24,
42b6d90eb7SKip Macy VSC8211_INTR_ENABLE = 25,
43b6d90eb7SKip Macy VSC8211_INTR_STATUS = 26,
444af83c8cSKip Macy VSC8211_LED_CTRL = 27,
45b6d90eb7SKip Macy VSC8211_AUX_CTRL_STAT = 28,
468e10660fSKip Macy VSC8211_EXT_PAGE_AXS = 31,
47b6d90eb7SKip Macy };
48b6d90eb7SKip Macy
49b6d90eb7SKip Macy enum {
50b6d90eb7SKip Macy VSC_INTR_RX_ERR = 1 << 0,
51b6d90eb7SKip Macy VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */
52b6d90eb7SKip Macy VSC_INTR_CABLE = 1 << 2, /* cable impairment */
53b6d90eb7SKip Macy VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */
54b6d90eb7SKip Macy VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */
55b6d90eb7SKip Macy VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */
56b6d90eb7SKip Macy VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */
57b6d90eb7SKip Macy VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */
58b6d90eb7SKip Macy VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */
59b6d90eb7SKip Macy VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */
60b6d90eb7SKip Macy VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */
618e10660fSKip Macy VSC_INTR_DPLX_CHG = 1 << 12, /* duplex change */
62b6d90eb7SKip Macy VSC_INTR_LINK_CHG = 1 << 13, /* link change */
638e10660fSKip Macy VSC_INTR_SPD_CHG = 1 << 14, /* speed change */
64b6d90eb7SKip Macy VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */
65b6d90eb7SKip Macy };
66b6d90eb7SKip Macy
678e10660fSKip Macy enum {
688e10660fSKip Macy VSC_CTRL_CLAUSE37_VIEW = 1 << 4, /* Switch to Clause 37 view */
698e10660fSKip Macy VSC_CTRL_MEDIA_MODE_HI = 0xf000 /* High part of media mode select */
708e10660fSKip Macy };
718e10660fSKip Macy
72b6d90eb7SKip Macy #define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \
738e10660fSKip Macy VSC_INTR_DPLX_CHG | VSC_INTR_SPD_CHG | \
74b6d90eb7SKip Macy VSC_INTR_NEG_DONE)
75b6d90eb7SKip Macy #define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \
76b6d90eb7SKip Macy VSC_INTR_ENABLE)
77b6d90eb7SKip Macy
78b6d90eb7SKip Macy /* PHY specific auxiliary control & status register fields */
79b6d90eb7SKip Macy #define S_ACSR_ACTIPHY_TMR 0
80b6d90eb7SKip Macy #define M_ACSR_ACTIPHY_TMR 0x3
81b6d90eb7SKip Macy #define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR)
82b6d90eb7SKip Macy
83b6d90eb7SKip Macy #define S_ACSR_SPEED 3
84b6d90eb7SKip Macy #define M_ACSR_SPEED 0x3
85b6d90eb7SKip Macy #define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED)
86b6d90eb7SKip Macy
87b6d90eb7SKip Macy #define S_ACSR_DUPLEX 5
88b6d90eb7SKip Macy #define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX)
89b6d90eb7SKip Macy
90b6d90eb7SKip Macy #define S_ACSR_ACTIPHY 6
91b6d90eb7SKip Macy #define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY)
92b6d90eb7SKip Macy
93b6d90eb7SKip Macy /*
94b6d90eb7SKip Macy * Reset the PHY. This PHY completes reset immediately so we never wait.
95b6d90eb7SKip Macy */
vsc8211_reset(struct cphy * cphy,int wait)96b6d90eb7SKip Macy static int vsc8211_reset(struct cphy *cphy, int wait)
97b6d90eb7SKip Macy {
98b6d90eb7SKip Macy return t3_phy_reset(cphy, 0, 0);
99b6d90eb7SKip Macy }
100b6d90eb7SKip Macy
vsc8211_intr_enable(struct cphy * cphy)101b6d90eb7SKip Macy static int vsc8211_intr_enable(struct cphy *cphy)
102b6d90eb7SKip Macy {
103b6d90eb7SKip Macy return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, INTR_MASK);
104b6d90eb7SKip Macy }
105b6d90eb7SKip Macy
vsc8211_intr_disable(struct cphy * cphy)106b6d90eb7SKip Macy static int vsc8211_intr_disable(struct cphy *cphy)
107b6d90eb7SKip Macy {
108b6d90eb7SKip Macy return mdio_write(cphy, 0, VSC8211_INTR_ENABLE, 0);
109b6d90eb7SKip Macy }
110b6d90eb7SKip Macy
vsc8211_intr_clear(struct cphy * cphy)111b6d90eb7SKip Macy static int vsc8211_intr_clear(struct cphy *cphy)
112b6d90eb7SKip Macy {
113b6d90eb7SKip Macy u32 val;
114b6d90eb7SKip Macy
115b6d90eb7SKip Macy /* Clear PHY interrupts by reading the register. */
116b6d90eb7SKip Macy return mdio_read(cphy, 0, VSC8211_INTR_STATUS, &val);
117b6d90eb7SKip Macy }
118b6d90eb7SKip Macy
vsc8211_autoneg_enable(struct cphy * cphy)119b6d90eb7SKip Macy static int vsc8211_autoneg_enable(struct cphy *cphy)
120b6d90eb7SKip Macy {
121b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE,
122b6d90eb7SKip Macy BMCR_ANENABLE | BMCR_ANRESTART);
123b6d90eb7SKip Macy }
124b6d90eb7SKip Macy
vsc8211_autoneg_restart(struct cphy * cphy)125b6d90eb7SKip Macy static int vsc8211_autoneg_restart(struct cphy *cphy)
126b6d90eb7SKip Macy {
127b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE,
128b6d90eb7SKip Macy BMCR_ANRESTART);
129b6d90eb7SKip Macy }
130b6d90eb7SKip Macy
vsc8211_get_link_status(struct cphy * cphy,int * link_state,int * speed,int * duplex,int * fc)131a5eb009bSNavdeep Parhar static int vsc8211_get_link_status(struct cphy *cphy, int *link_state,
132b6d90eb7SKip Macy int *speed, int *duplex, int *fc)
133b6d90eb7SKip Macy {
134b6d90eb7SKip Macy unsigned int bmcr, status, lpa, adv;
135b6d90eb7SKip Macy int err, sp = -1, dplx = -1, pause = 0;
136b6d90eb7SKip Macy
137b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_BMCR, &bmcr);
138b6d90eb7SKip Macy if (!err)
139b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status);
140b6d90eb7SKip Macy if (err)
141b6d90eb7SKip Macy return err;
142b6d90eb7SKip Macy
143a5eb009bSNavdeep Parhar if (link_state) {
144b6d90eb7SKip Macy /*
145b6d90eb7SKip Macy * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
146b6d90eb7SKip Macy * once more to get the current link state.
147b6d90eb7SKip Macy */
148b6d90eb7SKip Macy if (!(status & BMSR_LSTATUS))
149b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status);
150b6d90eb7SKip Macy if (err)
151b6d90eb7SKip Macy return err;
152a5eb009bSNavdeep Parhar *link_state = status & BMSR_LSTATUS ? PHY_LINK_UP :
153a5eb009bSNavdeep Parhar PHY_LINK_DOWN;
154b6d90eb7SKip Macy }
155b6d90eb7SKip Macy if (!(bmcr & BMCR_ANENABLE)) {
156b6d90eb7SKip Macy dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
157b6d90eb7SKip Macy if (bmcr & BMCR_SPEED1000)
158b6d90eb7SKip Macy sp = SPEED_1000;
159b6d90eb7SKip Macy else if (bmcr & BMCR_SPEED100)
160b6d90eb7SKip Macy sp = SPEED_100;
161b6d90eb7SKip Macy else
162b6d90eb7SKip Macy sp = SPEED_10;
163b6d90eb7SKip Macy } else if (status & BMSR_ANEGCOMPLETE) {
164b6d90eb7SKip Macy err = mdio_read(cphy, 0, VSC8211_AUX_CTRL_STAT, &status);
165b6d90eb7SKip Macy if (err)
166b6d90eb7SKip Macy return err;
167b6d90eb7SKip Macy
168b6d90eb7SKip Macy dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
169b6d90eb7SKip Macy sp = G_ACSR_SPEED(status);
170b6d90eb7SKip Macy if (sp == 0)
171b6d90eb7SKip Macy sp = SPEED_10;
172b6d90eb7SKip Macy else if (sp == 1)
173b6d90eb7SKip Macy sp = SPEED_100;
174b6d90eb7SKip Macy else
175b6d90eb7SKip Macy sp = SPEED_1000;
176b6d90eb7SKip Macy
177b6d90eb7SKip Macy if (fc && dplx == DUPLEX_FULL) {
178b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_LPA, &lpa);
179b6d90eb7SKip Macy if (!err)
180b6d90eb7SKip Macy err = mdio_read(cphy, 0, MII_ADVERTISE, &adv);
181b6d90eb7SKip Macy if (err)
182b6d90eb7SKip Macy return err;
183b6d90eb7SKip Macy
184b6d90eb7SKip Macy if (lpa & adv & ADVERTISE_PAUSE_CAP)
185b6d90eb7SKip Macy pause = PAUSE_RX | PAUSE_TX;
186b6d90eb7SKip Macy else if ((lpa & ADVERTISE_PAUSE_CAP) &&
187b6d90eb7SKip Macy (lpa & ADVERTISE_PAUSE_ASYM) &&
188b6d90eb7SKip Macy (adv & ADVERTISE_PAUSE_ASYM))
189b6d90eb7SKip Macy pause = PAUSE_TX;
190b6d90eb7SKip Macy else if ((lpa & ADVERTISE_PAUSE_ASYM) &&
191b6d90eb7SKip Macy (adv & ADVERTISE_PAUSE_CAP))
192b6d90eb7SKip Macy pause = PAUSE_RX;
193b6d90eb7SKip Macy }
194b6d90eb7SKip Macy }
195b6d90eb7SKip Macy if (speed)
196b6d90eb7SKip Macy *speed = sp;
197b6d90eb7SKip Macy if (duplex)
198b6d90eb7SKip Macy *duplex = dplx;
199b6d90eb7SKip Macy if (fc)
200b6d90eb7SKip Macy *fc = pause;
201b6d90eb7SKip Macy return 0;
202b6d90eb7SKip Macy }
203b6d90eb7SKip Macy
vsc8211_get_link_status_fiber(struct cphy * cphy,int * link_state,int * speed,int * duplex,int * fc)204a5eb009bSNavdeep Parhar static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_state,
2058e10660fSKip Macy int *speed, int *duplex, int *fc)
2068e10660fSKip Macy {
2078e10660fSKip Macy unsigned int bmcr, status, lpa, adv;
2088e10660fSKip Macy int err, sp = -1, dplx = -1, pause = 0;
2098e10660fSKip Macy
2108e10660fSKip Macy err = mdio_read(cphy, 0, MII_BMCR, &bmcr);
2118e10660fSKip Macy if (!err)
2128e10660fSKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status);
2138e10660fSKip Macy if (err)
2148e10660fSKip Macy return err;
2158e10660fSKip Macy
216a5eb009bSNavdeep Parhar if (link_state) {
2178e10660fSKip Macy /*
2188e10660fSKip Macy * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it
2198e10660fSKip Macy * once more to get the current link state.
2208e10660fSKip Macy */
2218e10660fSKip Macy if (!(status & BMSR_LSTATUS))
2228e10660fSKip Macy err = mdio_read(cphy, 0, MII_BMSR, &status);
2238e10660fSKip Macy if (err)
2248e10660fSKip Macy return err;
225a5eb009bSNavdeep Parhar *link_state = status & BMSR_LSTATUS ? PHY_LINK_UP :
226a5eb009bSNavdeep Parhar PHY_LINK_DOWN;
2278e10660fSKip Macy }
2288e10660fSKip Macy if (!(bmcr & BMCR_ANENABLE)) {
2298e10660fSKip Macy dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
2308e10660fSKip Macy if (bmcr & BMCR_SPEED1000)
2318e10660fSKip Macy sp = SPEED_1000;
2328e10660fSKip Macy else if (bmcr & BMCR_SPEED100)
2338e10660fSKip Macy sp = SPEED_100;
2348e10660fSKip Macy else
2358e10660fSKip Macy sp = SPEED_10;
2368e10660fSKip Macy } else if (status & BMSR_ANEGCOMPLETE) {
2378e10660fSKip Macy err = mdio_read(cphy, 0, MII_LPA, &lpa);
2388e10660fSKip Macy if (!err)
2398e10660fSKip Macy err = mdio_read(cphy, 0, MII_ADVERTISE, &adv);
2408e10660fSKip Macy if (err)
2418e10660fSKip Macy return err;
2428e10660fSKip Macy
2438e10660fSKip Macy if (adv & lpa & ADVERTISE_1000XFULL) {
2448e10660fSKip Macy dplx = DUPLEX_FULL;
2458e10660fSKip Macy sp = SPEED_1000;
2468e10660fSKip Macy } else if (adv & lpa & ADVERTISE_1000XHALF) {
2478e10660fSKip Macy dplx = DUPLEX_HALF;
2488e10660fSKip Macy sp = SPEED_1000;
2498e10660fSKip Macy }
2508e10660fSKip Macy
2518e10660fSKip Macy if (fc && dplx == DUPLEX_FULL) {
2528e10660fSKip Macy if (lpa & adv & ADVERTISE_1000XPAUSE)
2538e10660fSKip Macy pause = PAUSE_RX | PAUSE_TX;
2548e10660fSKip Macy else if ((lpa & ADVERTISE_1000XPAUSE) &&
2558e10660fSKip Macy (adv & lpa & ADVERTISE_1000XPSE_ASYM))
2568e10660fSKip Macy pause = PAUSE_TX;
2578e10660fSKip Macy else if ((lpa & ADVERTISE_1000XPSE_ASYM) &&
2588e10660fSKip Macy (adv & ADVERTISE_1000XPAUSE))
2598e10660fSKip Macy pause = PAUSE_RX;
2608e10660fSKip Macy }
2618e10660fSKip Macy }
2628e10660fSKip Macy if (speed)
2638e10660fSKip Macy *speed = sp;
2648e10660fSKip Macy if (duplex)
2658e10660fSKip Macy *duplex = dplx;
2668e10660fSKip Macy if (fc)
2678e10660fSKip Macy *fc = pause;
2688e10660fSKip Macy return 0;
2698e10660fSKip Macy }
2708e10660fSKip Macy
2718e10660fSKip Macy /*
2728e10660fSKip Macy * Enable/disable auto MDI/MDI-X in forced link speed mode.
2738e10660fSKip Macy */
vsc8211_set_automdi(struct cphy * phy,int enable)2748e10660fSKip Macy static int vsc8211_set_automdi(struct cphy *phy, int enable)
2758e10660fSKip Macy {
2768e10660fSKip Macy int err;
2778e10660fSKip Macy
2788e10660fSKip Macy if ((err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0x52b5)) != 0 ||
2798e10660fSKip Macy (err = mdio_write(phy, 0, 18, 0x12)) != 0 ||
2808e10660fSKip Macy (err = mdio_write(phy, 0, 17, enable ? 0x2803 : 0x3003)) != 0 ||
2818e10660fSKip Macy (err = mdio_write(phy, 0, 16, 0x87fa)) != 0 ||
2828e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0)) != 0)
2838e10660fSKip Macy return err;
2848e10660fSKip Macy return 0;
2858e10660fSKip Macy }
2868e10660fSKip Macy
vsc8211_set_speed_duplex(struct cphy * phy,int speed,int duplex)2878e10660fSKip Macy static int vsc8211_set_speed_duplex(struct cphy *phy, int speed, int duplex)
2888e10660fSKip Macy {
2898e10660fSKip Macy int err;
2908e10660fSKip Macy
2918e10660fSKip Macy err = t3_set_phy_speed_duplex(phy, speed, duplex);
2928e10660fSKip Macy if (!err)
2938e10660fSKip Macy err = vsc8211_set_automdi(phy, 1);
2948e10660fSKip Macy return err;
2958e10660fSKip Macy }
2968e10660fSKip Macy
vsc8211_power_down(struct cphy * cphy,int enable)297b6d90eb7SKip Macy static int vsc8211_power_down(struct cphy *cphy, int enable)
298b6d90eb7SKip Macy {
299b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN,
300b6d90eb7SKip Macy enable ? BMCR_PDOWN : 0);
301b6d90eb7SKip Macy }
302b6d90eb7SKip Macy
vsc8211_intr_handler(struct cphy * cphy)303b6d90eb7SKip Macy static int vsc8211_intr_handler(struct cphy *cphy)
304b6d90eb7SKip Macy {
305b6d90eb7SKip Macy unsigned int cause;
306b6d90eb7SKip Macy int err, cphy_cause = 0;
307b6d90eb7SKip Macy
308b6d90eb7SKip Macy err = mdio_read(cphy, 0, VSC8211_INTR_STATUS, &cause);
309b6d90eb7SKip Macy if (err)
310b6d90eb7SKip Macy return err;
311b6d90eb7SKip Macy
312b6d90eb7SKip Macy cause &= INTR_MASK;
313b6d90eb7SKip Macy if (cause & CFG_CHG_INTR_MASK)
314b6d90eb7SKip Macy cphy_cause |= cphy_cause_link_change;
315b6d90eb7SKip Macy if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO))
316b6d90eb7SKip Macy cphy_cause |= cphy_cause_fifo_error;
317b6d90eb7SKip Macy return cphy_cause;
318b6d90eb7SKip Macy }
319b6d90eb7SKip Macy
320b6d90eb7SKip Macy #ifdef C99_NOT_SUPPORTED
321b6d90eb7SKip Macy static struct cphy_ops vsc8211_ops = {
322b6d90eb7SKip Macy vsc8211_reset,
323b6d90eb7SKip Macy vsc8211_intr_enable,
324b6d90eb7SKip Macy vsc8211_intr_disable,
325b6d90eb7SKip Macy vsc8211_intr_clear,
326b6d90eb7SKip Macy vsc8211_intr_handler,
327b6d90eb7SKip Macy vsc8211_autoneg_enable,
328b6d90eb7SKip Macy vsc8211_autoneg_restart,
329b6d90eb7SKip Macy t3_phy_advertise,
330b6d90eb7SKip Macy NULL,
3318e10660fSKip Macy vsc8211_set_speed_duplex,
332b6d90eb7SKip Macy vsc8211_get_link_status,
333b6d90eb7SKip Macy vsc8211_power_down,
334b6d90eb7SKip Macy };
3358e10660fSKip Macy
3368e10660fSKip Macy static struct cphy_ops vsc8211_fiber_ops = {
3378e10660fSKip Macy vsc8211_reset,
3388e10660fSKip Macy vsc8211_intr_enable,
3398e10660fSKip Macy vsc8211_intr_disable,
3408e10660fSKip Macy vsc8211_intr_clear,
3418e10660fSKip Macy vsc8211_intr_handler,
3428e10660fSKip Macy vsc8211_autoneg_enable,
3438e10660fSKip Macy vsc8211_autoneg_restart,
3448e10660fSKip Macy t3_phy_advertise_fiber,
3458e10660fSKip Macy NULL,
3468e10660fSKip Macy t3_set_phy_speed_duplex,
3478e10660fSKip Macy vsc8211_get_link_status_fiber,
3488e10660fSKip Macy vsc8211_power_down,
3498e10660fSKip Macy };
350b6d90eb7SKip Macy #else
351b6d90eb7SKip Macy static struct cphy_ops vsc8211_ops = {
352b6d90eb7SKip Macy .reset = vsc8211_reset,
353b6d90eb7SKip Macy .intr_enable = vsc8211_intr_enable,
354b6d90eb7SKip Macy .intr_disable = vsc8211_intr_disable,
355b6d90eb7SKip Macy .intr_clear = vsc8211_intr_clear,
356b6d90eb7SKip Macy .intr_handler = vsc8211_intr_handler,
357b6d90eb7SKip Macy .autoneg_enable = vsc8211_autoneg_enable,
358b6d90eb7SKip Macy .autoneg_restart = vsc8211_autoneg_restart,
359b6d90eb7SKip Macy .advertise = t3_phy_advertise,
3608e10660fSKip Macy .set_speed_duplex = vsc8211_set_speed_duplex,
361b6d90eb7SKip Macy .get_link_status = vsc8211_get_link_status,
362b6d90eb7SKip Macy .power_down = vsc8211_power_down,
363b6d90eb7SKip Macy };
3648e10660fSKip Macy
3658e10660fSKip Macy static struct cphy_ops vsc8211_fiber_ops = {
3668e10660fSKip Macy .reset = vsc8211_reset,
3678e10660fSKip Macy .intr_enable = vsc8211_intr_enable,
3688e10660fSKip Macy .intr_disable = vsc8211_intr_disable,
3698e10660fSKip Macy .intr_clear = vsc8211_intr_clear,
3708e10660fSKip Macy .intr_handler = vsc8211_intr_handler,
3718e10660fSKip Macy .autoneg_enable = vsc8211_autoneg_enable,
3728e10660fSKip Macy .autoneg_restart = vsc8211_autoneg_restart,
3738e10660fSKip Macy .advertise = t3_phy_advertise_fiber,
3748e10660fSKip Macy .set_speed_duplex = t3_set_phy_speed_duplex,
3758e10660fSKip Macy .get_link_status = vsc8211_get_link_status_fiber,
3768e10660fSKip Macy .power_down = vsc8211_power_down,
3778e10660fSKip Macy };
378b6d90eb7SKip Macy #endif
379b6d90eb7SKip Macy
380c01f2b83SNavdeep Parhar #define VSC8211_PHY_CTRL 24
381c01f2b83SNavdeep Parhar
382c01f2b83SNavdeep Parhar #define S_VSC8211_TXFIFODEPTH 7
383c01f2b83SNavdeep Parhar #define M_VSC8211_TXFIFODEPTH 0x7
384c01f2b83SNavdeep Parhar #define V_VSC8211_TXFIFODEPTH(x) ((x) << S_VSC8211_TXFIFODEPTH)
385c01f2b83SNavdeep Parhar #define G_VSC8211_TXFIFODEPTH(x) (((x) >> S_VSC8211_TXFIFODEPTH) & M_VSC8211_TXFIFODEPTH)
386c01f2b83SNavdeep Parhar
387c01f2b83SNavdeep Parhar #define S_VSC8211_RXFIFODEPTH 4
388c01f2b83SNavdeep Parhar #define M_VSC8211_RXFIFODEPTH 0x7
389c01f2b83SNavdeep Parhar #define V_VSC8211_RXFIFODEPTH(x) ((x) << S_VSC8211_RXFIFODEPTH)
390c01f2b83SNavdeep Parhar #define G_VSC8211_RXFIFODEPTH(x) (((x) >> S_VSC8211_RXFIFODEPTH) & M_VSC8211_RXFIFODEPTH)
391c01f2b83SNavdeep Parhar
t3_vsc8211_fifo_depth(adapter_t * adap,unsigned int mtu,int port)392c01f2b83SNavdeep Parhar int t3_vsc8211_fifo_depth(adapter_t *adap, unsigned int mtu, int port)
393c01f2b83SNavdeep Parhar {
394c01f2b83SNavdeep Parhar /* TX FIFO Depth set bits 9:7 to 100 (IEEE mode) */
395c01f2b83SNavdeep Parhar unsigned int val = 4;
396c01f2b83SNavdeep Parhar unsigned int currentregval;
397c01f2b83SNavdeep Parhar unsigned int regval;
398c01f2b83SNavdeep Parhar int err;
399c01f2b83SNavdeep Parhar
400c01f2b83SNavdeep Parhar /* Retrieve the port info structure from adater_t */
401c01f2b83SNavdeep Parhar struct port_info *portinfo = adap2pinfo(adap, port);
402c01f2b83SNavdeep Parhar
403c01f2b83SNavdeep Parhar /* What phy is this */
404c01f2b83SNavdeep Parhar struct cphy *phy = &portinfo->phy;
405c01f2b83SNavdeep Parhar
406c01f2b83SNavdeep Parhar /* Read the current value of the PHY control Register */
407c01f2b83SNavdeep Parhar err = mdio_read(phy, 0, VSC8211_PHY_CTRL, ¤tregval);
408c01f2b83SNavdeep Parhar
409c01f2b83SNavdeep Parhar if (err)
410c01f2b83SNavdeep Parhar return err;
411c01f2b83SNavdeep Parhar
412c01f2b83SNavdeep Parhar /* IEEE mode supports up to 1518 bytes */
413c01f2b83SNavdeep Parhar /* mtu does not contain the header + FCS (18 bytes) */
414c01f2b83SNavdeep Parhar if (mtu > 1500)
415c01f2b83SNavdeep Parhar /*
416c01f2b83SNavdeep Parhar * If using a packet size > 1500 set TX FIFO Depth bits
417c01f2b83SNavdeep Parhar * 9:7 to 011 (Jumbo packet mode)
418c01f2b83SNavdeep Parhar */
419c01f2b83SNavdeep Parhar val = 3;
420c01f2b83SNavdeep Parhar
421c01f2b83SNavdeep Parhar regval = V_VSC8211_TXFIFODEPTH(val) | V_VSC8211_RXFIFODEPTH(val) |
422c01f2b83SNavdeep Parhar (currentregval & ~V_VSC8211_TXFIFODEPTH(M_VSC8211_TXFIFODEPTH) &
423c01f2b83SNavdeep Parhar ~V_VSC8211_RXFIFODEPTH(M_VSC8211_RXFIFODEPTH));
424c01f2b83SNavdeep Parhar
425c01f2b83SNavdeep Parhar return mdio_write(phy, 0, VSC8211_PHY_CTRL, regval);
426c01f2b83SNavdeep Parhar }
427c01f2b83SNavdeep Parhar
t3_vsc8211_phy_prep(pinfo_t * pinfo,int phy_addr,const struct mdio_ops * mdio_ops)428c01f2b83SNavdeep Parhar int t3_vsc8211_phy_prep(pinfo_t *pinfo, int phy_addr,
429b6d90eb7SKip Macy const struct mdio_ops *mdio_ops)
430b6d90eb7SKip Macy {
431c01f2b83SNavdeep Parhar struct cphy *phy = &pinfo->phy;
4328e10660fSKip Macy int err;
4338e10660fSKip Macy unsigned int val;
4348e10660fSKip Macy
435c01f2b83SNavdeep Parhar cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &vsc8211_ops, mdio_ops,
4368e10660fSKip Macy SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full |
4378e10660fSKip Macy SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII |
4388e10660fSKip Macy SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
4398e10660fSKip Macy msleep(20); /* PHY needs ~10ms to start responding to MDIO */
4408e10660fSKip Macy
4418e10660fSKip Macy err = mdio_read(phy, 0, VSC8211_EXT_CTRL, &val);
4428e10660fSKip Macy if (err)
4438e10660fSKip Macy return err;
4444af83c8cSKip Macy if (val & VSC_CTRL_MEDIA_MODE_HI) {
4454af83c8cSKip Macy /* copper interface, just need to configure the LEDs */
4464af83c8cSKip Macy return mdio_write(phy, 0, VSC8211_LED_CTRL, 0x100);
4474af83c8cSKip Macy }
4488e10660fSKip Macy
4498e10660fSKip Macy phy->caps = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
4508e10660fSKip Macy SUPPORTED_MII | SUPPORTED_FIBRE | SUPPORTED_IRQ;
4518e10660fSKip Macy phy->desc = "1000BASE-X";
4528e10660fSKip Macy phy->ops = &vsc8211_fiber_ops;
4538e10660fSKip Macy
4548e10660fSKip Macy if ((err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 1)) != 0 ||
4558e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_SIGDET_CTRL, 1)) != 0 ||
4568e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_EXT_PAGE_AXS, 0)) != 0 ||
4578e10660fSKip Macy (err = mdio_write(phy, 0, VSC8211_EXT_CTRL,
4588e10660fSKip Macy val | VSC_CTRL_CLAUSE37_VIEW)) != 0 ||
4598e10660fSKip Macy (err = vsc8211_reset(phy, 0)) != 0)
4608e10660fSKip Macy return err;
4618e10660fSKip Macy
4628e10660fSKip Macy udelay(5); /* delay after reset before next SMI */
4638e10660fSKip Macy return 0;
464b6d90eb7SKip Macy }
465