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
34b6d90eb7SKip Macy /* Marvell PHY interrupt status bits. */
35b6d90eb7SKip Macy #define MV_INTR_JABBER 0x0001
36b6d90eb7SKip Macy #define MV_INTR_POLARITY_CHNG 0x0002
37b6d90eb7SKip Macy #define MV_INTR_ENG_DETECT_CHNG 0x0010
38b6d90eb7SKip Macy #define MV_INTR_DOWNSHIFT 0x0020
39b6d90eb7SKip Macy #define MV_INTR_MDI_XOVER_CHNG 0x0040
40b6d90eb7SKip Macy #define MV_INTR_FIFO_OVER_UNDER 0x0080
41b6d90eb7SKip Macy #define MV_INTR_FALSE_CARRIER 0x0100
42b6d90eb7SKip Macy #define MV_INTR_SYMBOL_ERROR 0x0200
43b6d90eb7SKip Macy #define MV_INTR_LINK_CHNG 0x0400
44b6d90eb7SKip Macy #define MV_INTR_AUTONEG_DONE 0x0800
45b6d90eb7SKip Macy #define MV_INTR_PAGE_RECV 0x1000
46b6d90eb7SKip Macy #define MV_INTR_DUPLEX_CHNG 0x2000
47b6d90eb7SKip Macy #define MV_INTR_SPEED_CHNG 0x4000
48b6d90eb7SKip Macy #define MV_INTR_AUTONEG_ERR 0x8000
49b6d90eb7SKip Macy
50b6d90eb7SKip Macy /* Marvell PHY specific registers. */
51b6d90eb7SKip Macy #define MV88E1XXX_SPECIFIC_CNTRL 16
52b6d90eb7SKip Macy #define MV88E1XXX_SPECIFIC_STATUS 17
53b6d90eb7SKip Macy #define MV88E1XXX_INTR_ENABLE 18
54b6d90eb7SKip Macy #define MV88E1XXX_INTR_STATUS 19
55b6d90eb7SKip Macy #define MV88E1XXX_EXT_SPECIFIC_CNTRL 20
56b6d90eb7SKip Macy #define MV88E1XXX_RECV_ERR 21
57b6d90eb7SKip Macy #define MV88E1XXX_EXT_ADDR 22
58b6d90eb7SKip Macy #define MV88E1XXX_GLOBAL_STATUS 23
59b6d90eb7SKip Macy #define MV88E1XXX_LED_CNTRL 24
60b6d90eb7SKip Macy #define MV88E1XXX_LED_OVERRIDE 25
61b6d90eb7SKip Macy #define MV88E1XXX_EXT_SPECIFIC_CNTRL2 26
62b6d90eb7SKip Macy #define MV88E1XXX_EXT_SPECIFIC_STATUS 27
63b6d90eb7SKip Macy #define MV88E1XXX_VIRTUAL_CABLE_TESTER 28
64b6d90eb7SKip Macy #define MV88E1XXX_EXTENDED_ADDR 29
65b6d90eb7SKip Macy #define MV88E1XXX_EXTENDED_DATA 30
66b6d90eb7SKip Macy
67b6d90eb7SKip Macy /* PHY specific control register fields */
68b6d90eb7SKip Macy #define S_PSCR_MDI_XOVER_MODE 5
69b6d90eb7SKip Macy #define M_PSCR_MDI_XOVER_MODE 0x3
70b6d90eb7SKip Macy #define V_PSCR_MDI_XOVER_MODE(x) ((x) << S_PSCR_MDI_XOVER_MODE)
71b6d90eb7SKip Macy
72b6d90eb7SKip Macy /* Extended PHY specific control register fields */
73b6d90eb7SKip Macy #define S_DOWNSHIFT_ENABLE 8
74b6d90eb7SKip Macy #define V_DOWNSHIFT_ENABLE (1 << S_DOWNSHIFT_ENABLE)
75b6d90eb7SKip Macy
76b6d90eb7SKip Macy #define S_DOWNSHIFT_CNT 9
77b6d90eb7SKip Macy #define M_DOWNSHIFT_CNT 0x7
78b6d90eb7SKip Macy #define V_DOWNSHIFT_CNT(x) ((x) << S_DOWNSHIFT_CNT)
79b6d90eb7SKip Macy
80b6d90eb7SKip Macy /* PHY specific status register fields */
81b6d90eb7SKip Macy #define S_PSSR_JABBER 0
82b6d90eb7SKip Macy #define V_PSSR_JABBER (1 << S_PSSR_JABBER)
83b6d90eb7SKip Macy
84b6d90eb7SKip Macy #define S_PSSR_POLARITY 1
85b6d90eb7SKip Macy #define V_PSSR_POLARITY (1 << S_PSSR_POLARITY)
86b6d90eb7SKip Macy
87b6d90eb7SKip Macy #define S_PSSR_RX_PAUSE 2
88b6d90eb7SKip Macy #define V_PSSR_RX_PAUSE (1 << S_PSSR_RX_PAUSE)
89b6d90eb7SKip Macy
90b6d90eb7SKip Macy #define S_PSSR_TX_PAUSE 3
91b6d90eb7SKip Macy #define V_PSSR_TX_PAUSE (1 << S_PSSR_TX_PAUSE)
92b6d90eb7SKip Macy
93b6d90eb7SKip Macy #define S_PSSR_ENERGY_DETECT 4
94b6d90eb7SKip Macy #define V_PSSR_ENERGY_DETECT (1 << S_PSSR_ENERGY_DETECT)
95b6d90eb7SKip Macy
96b6d90eb7SKip Macy #define S_PSSR_DOWNSHIFT_STATUS 5
97b6d90eb7SKip Macy #define V_PSSR_DOWNSHIFT_STATUS (1 << S_PSSR_DOWNSHIFT_STATUS)
98b6d90eb7SKip Macy
99b6d90eb7SKip Macy #define S_PSSR_MDI 6
100b6d90eb7SKip Macy #define V_PSSR_MDI (1 << S_PSSR_MDI)
101b6d90eb7SKip Macy
102b6d90eb7SKip Macy #define S_PSSR_CABLE_LEN 7
103b6d90eb7SKip Macy #define M_PSSR_CABLE_LEN 0x7
104b6d90eb7SKip Macy #define V_PSSR_CABLE_LEN(x) ((x) << S_PSSR_CABLE_LEN)
105b6d90eb7SKip Macy #define G_PSSR_CABLE_LEN(x) (((x) >> S_PSSR_CABLE_LEN) & M_PSSR_CABLE_LEN)
106b6d90eb7SKip Macy
107b6d90eb7SKip Macy #define S_PSSR_LINK 10
108b6d90eb7SKip Macy #define V_PSSR_LINK (1 << S_PSSR_LINK)
109b6d90eb7SKip Macy
110b6d90eb7SKip Macy #define S_PSSR_STATUS_RESOLVED 11
111b6d90eb7SKip Macy #define V_PSSR_STATUS_RESOLVED (1 << S_PSSR_STATUS_RESOLVED)
112b6d90eb7SKip Macy
113b6d90eb7SKip Macy #define S_PSSR_PAGE_RECEIVED 12
114b6d90eb7SKip Macy #define V_PSSR_PAGE_RECEIVED (1 << S_PSSR_PAGE_RECEIVED)
115b6d90eb7SKip Macy
116b6d90eb7SKip Macy #define S_PSSR_DUPLEX 13
117b6d90eb7SKip Macy #define V_PSSR_DUPLEX (1 << S_PSSR_DUPLEX)
118b6d90eb7SKip Macy
119b6d90eb7SKip Macy #define S_PSSR_SPEED 14
120b6d90eb7SKip Macy #define M_PSSR_SPEED 0x3
121b6d90eb7SKip Macy #define V_PSSR_SPEED(x) ((x) << S_PSSR_SPEED)
122b6d90eb7SKip Macy #define G_PSSR_SPEED(x) (((x) >> S_PSSR_SPEED) & M_PSSR_SPEED)
123b6d90eb7SKip Macy
124b6d90eb7SKip Macy /* MV88E1XXX MDI crossover register values */
125b6d90eb7SKip Macy #define CROSSOVER_MDI 0
126b6d90eb7SKip Macy #define CROSSOVER_MDIX 1
127b6d90eb7SKip Macy #define CROSSOVER_AUTO 3
128b6d90eb7SKip Macy
129b6d90eb7SKip Macy #define INTR_ENABLE_MASK (MV_INTR_SPEED_CHNG | MV_INTR_DUPLEX_CHNG | \
130b6d90eb7SKip Macy MV_INTR_AUTONEG_DONE | MV_INTR_LINK_CHNG | MV_INTR_FIFO_OVER_UNDER | \
131b6d90eb7SKip Macy MV_INTR_ENG_DETECT_CHNG)
132b6d90eb7SKip Macy
133b6d90eb7SKip Macy /*
134b6d90eb7SKip Macy * Reset the PHY. If 'wait' is set wait until the reset completes.
135b6d90eb7SKip Macy */
mv88e1xxx_reset(struct cphy * cphy,int wait)136b6d90eb7SKip Macy static int mv88e1xxx_reset(struct cphy *cphy, int wait)
137b6d90eb7SKip Macy {
138b6d90eb7SKip Macy return t3_phy_reset(cphy, 0, wait);
139b6d90eb7SKip Macy }
140b6d90eb7SKip Macy
mv88e1xxx_intr_enable(struct cphy * cphy)141b6d90eb7SKip Macy static int mv88e1xxx_intr_enable(struct cphy *cphy)
142b6d90eb7SKip Macy {
143b6d90eb7SKip Macy return mdio_write(cphy, 0, MV88E1XXX_INTR_ENABLE, INTR_ENABLE_MASK);
144b6d90eb7SKip Macy }
145b6d90eb7SKip Macy
mv88e1xxx_intr_disable(struct cphy * cphy)146b6d90eb7SKip Macy static int mv88e1xxx_intr_disable(struct cphy *cphy)
147b6d90eb7SKip Macy {
148b6d90eb7SKip Macy return mdio_write(cphy, 0, MV88E1XXX_INTR_ENABLE, 0);
149b6d90eb7SKip Macy }
150b6d90eb7SKip Macy
mv88e1xxx_intr_clear(struct cphy * cphy)151b6d90eb7SKip Macy static int mv88e1xxx_intr_clear(struct cphy *cphy)
152b6d90eb7SKip Macy {
153b6d90eb7SKip Macy u32 val;
154b6d90eb7SKip Macy
155b6d90eb7SKip Macy /* Clear PHY interrupts by reading the register. */
156b6d90eb7SKip Macy return mdio_read(cphy, 0, MV88E1XXX_INTR_STATUS, &val);
157b6d90eb7SKip Macy }
158b6d90eb7SKip Macy
mv88e1xxx_crossover_set(struct cphy * cphy,int crossover)159b6d90eb7SKip Macy static int mv88e1xxx_crossover_set(struct cphy *cphy, int crossover)
160b6d90eb7SKip Macy {
161b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MV88E1XXX_SPECIFIC_CNTRL,
162b6d90eb7SKip Macy V_PSCR_MDI_XOVER_MODE(M_PSCR_MDI_XOVER_MODE),
163b6d90eb7SKip Macy V_PSCR_MDI_XOVER_MODE(crossover));
164b6d90eb7SKip Macy }
165b6d90eb7SKip Macy
mv88e1xxx_autoneg_enable(struct cphy * cphy)166b6d90eb7SKip Macy static int mv88e1xxx_autoneg_enable(struct cphy *cphy)
167b6d90eb7SKip Macy {
168b6d90eb7SKip Macy mv88e1xxx_crossover_set(cphy, CROSSOVER_AUTO);
169b6d90eb7SKip Macy
170b6d90eb7SKip Macy /* restart autoneg for change to take effect */
171b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE,
172b6d90eb7SKip Macy BMCR_ANENABLE | BMCR_ANRESTART);
173b6d90eb7SKip Macy }
174b6d90eb7SKip Macy
mv88e1xxx_autoneg_restart(struct cphy * cphy)175b6d90eb7SKip Macy static int mv88e1xxx_autoneg_restart(struct cphy *cphy)
176b6d90eb7SKip Macy {
177b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE,
178b6d90eb7SKip Macy BMCR_ANRESTART);
179b6d90eb7SKip Macy }
180b6d90eb7SKip Macy
mv88e1xxx_set_loopback(struct cphy * cphy,int mmd,int dir,int on)181b6d90eb7SKip Macy static int mv88e1xxx_set_loopback(struct cphy *cphy, int mmd, int dir, int on)
182b6d90eb7SKip Macy {
183b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_LOOPBACK,
184b6d90eb7SKip Macy on ? BMCR_LOOPBACK : 0);
185b6d90eb7SKip Macy }
186b6d90eb7SKip Macy
mv88e1xxx_get_link_status(struct cphy * cphy,int * link_state,int * speed,int * duplex,int * fc)187a5eb009bSNavdeep Parhar static int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_state,
188b6d90eb7SKip Macy int *speed, int *duplex, int *fc)
189b6d90eb7SKip Macy {
190b6d90eb7SKip Macy u32 status;
191b6d90eb7SKip Macy int sp = -1, dplx = -1, pause = 0;
192b6d90eb7SKip Macy
193b6d90eb7SKip Macy mdio_read(cphy, 0, MV88E1XXX_SPECIFIC_STATUS, &status);
194b6d90eb7SKip Macy if ((status & V_PSSR_STATUS_RESOLVED) != 0) {
195b6d90eb7SKip Macy if (status & V_PSSR_RX_PAUSE)
196b6d90eb7SKip Macy pause |= PAUSE_RX;
197b6d90eb7SKip Macy if (status & V_PSSR_TX_PAUSE)
198b6d90eb7SKip Macy pause |= PAUSE_TX;
199b6d90eb7SKip Macy dplx = (status & V_PSSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF;
200b6d90eb7SKip Macy sp = G_PSSR_SPEED(status);
201b6d90eb7SKip Macy if (sp == 0)
202b6d90eb7SKip Macy sp = SPEED_10;
203b6d90eb7SKip Macy else if (sp == 1)
204b6d90eb7SKip Macy sp = SPEED_100;
205b6d90eb7SKip Macy else
206b6d90eb7SKip Macy sp = SPEED_1000;
207b6d90eb7SKip Macy }
208a5eb009bSNavdeep Parhar if (link_state)
209a5eb009bSNavdeep Parhar *link_state = status & V_PSSR_LINK ? PHY_LINK_UP :
210a5eb009bSNavdeep Parhar PHY_LINK_DOWN;
211b6d90eb7SKip Macy if (speed)
212b6d90eb7SKip Macy *speed = sp;
213b6d90eb7SKip Macy if (duplex)
214b6d90eb7SKip Macy *duplex = dplx;
215b6d90eb7SKip Macy if (fc)
216b6d90eb7SKip Macy *fc = pause;
217b6d90eb7SKip Macy return 0;
218b6d90eb7SKip Macy }
219b6d90eb7SKip Macy
mv88e1xxx_set_speed_duplex(struct cphy * phy,int speed,int duplex)2208e10660fSKip Macy static int mv88e1xxx_set_speed_duplex(struct cphy *phy, int speed, int duplex)
2218e10660fSKip Macy {
2228e10660fSKip Macy int err = t3_set_phy_speed_duplex(phy, speed, duplex);
2238e10660fSKip Macy
2248e10660fSKip Macy /* PHY needs reset for new settings to take effect */
2258e10660fSKip Macy if (!err)
2268e10660fSKip Macy err = mv88e1xxx_reset(phy, 0);
2278e10660fSKip Macy return err;
2288e10660fSKip Macy }
2298e10660fSKip Macy
mv88e1xxx_downshift_set(struct cphy * cphy,int downshift_enable)230b6d90eb7SKip Macy static int mv88e1xxx_downshift_set(struct cphy *cphy, int downshift_enable)
231b6d90eb7SKip Macy {
232b6d90eb7SKip Macy /*
233b6d90eb7SKip Macy * Set the downshift counter to 2 so we try to establish Gb link
234b6d90eb7SKip Macy * twice before downshifting.
235b6d90eb7SKip Macy */
236b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MV88E1XXX_EXT_SPECIFIC_CNTRL,
237b6d90eb7SKip Macy V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(M_DOWNSHIFT_CNT),
238b6d90eb7SKip Macy downshift_enable ? V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(2) : 0);
239b6d90eb7SKip Macy }
240b6d90eb7SKip Macy
mv88e1xxx_power_down(struct cphy * cphy,int enable)241b6d90eb7SKip Macy static int mv88e1xxx_power_down(struct cphy *cphy, int enable)
242b6d90eb7SKip Macy {
243b6d90eb7SKip Macy return t3_mdio_change_bits(cphy, 0, MII_BMCR, BMCR_PDOWN,
244b6d90eb7SKip Macy enable ? BMCR_PDOWN : 0);
245b6d90eb7SKip Macy }
246b6d90eb7SKip Macy
mv88e1xxx_intr_handler(struct cphy * cphy)247b6d90eb7SKip Macy static int mv88e1xxx_intr_handler(struct cphy *cphy)
248b6d90eb7SKip Macy {
249b6d90eb7SKip Macy const u32 link_change_intrs = MV_INTR_LINK_CHNG |
250b6d90eb7SKip Macy MV_INTR_AUTONEG_DONE | MV_INTR_DUPLEX_CHNG |
251b6d90eb7SKip Macy MV_INTR_SPEED_CHNG | MV_INTR_DOWNSHIFT;
252b6d90eb7SKip Macy
253b6d90eb7SKip Macy u32 cause;
254b6d90eb7SKip Macy int cphy_cause = 0;
255b6d90eb7SKip Macy
256b6d90eb7SKip Macy mdio_read(cphy, 0, MV88E1XXX_INTR_STATUS, &cause);
257b6d90eb7SKip Macy cause &= INTR_ENABLE_MASK;
258b6d90eb7SKip Macy if (cause & link_change_intrs)
259b6d90eb7SKip Macy cphy_cause |= cphy_cause_link_change;
260b6d90eb7SKip Macy if (cause & MV_INTR_FIFO_OVER_UNDER)
261b6d90eb7SKip Macy cphy_cause |= cphy_cause_fifo_error;
262b6d90eb7SKip Macy return cphy_cause;
263b6d90eb7SKip Macy }
264b6d90eb7SKip Macy
265b6d90eb7SKip Macy #ifdef C99_NOT_SUPPORTED
266b6d90eb7SKip Macy static struct cphy_ops mv88e1xxx_ops = {
267b6d90eb7SKip Macy mv88e1xxx_reset,
268b6d90eb7SKip Macy mv88e1xxx_intr_enable,
269b6d90eb7SKip Macy mv88e1xxx_intr_disable,
270b6d90eb7SKip Macy mv88e1xxx_intr_clear,
271b6d90eb7SKip Macy mv88e1xxx_intr_handler,
272b6d90eb7SKip Macy mv88e1xxx_autoneg_enable,
273b6d90eb7SKip Macy mv88e1xxx_autoneg_restart,
274b6d90eb7SKip Macy t3_phy_advertise,
275b6d90eb7SKip Macy mv88e1xxx_set_loopback,
2768e10660fSKip Macy mv88e1xxx_set_speed_duplex,
277b6d90eb7SKip Macy mv88e1xxx_get_link_status,
278b6d90eb7SKip Macy mv88e1xxx_power_down,
279b6d90eb7SKip Macy };
280b6d90eb7SKip Macy #else
281b6d90eb7SKip Macy static struct cphy_ops mv88e1xxx_ops = {
282b6d90eb7SKip Macy .reset = mv88e1xxx_reset,
283b6d90eb7SKip Macy .intr_enable = mv88e1xxx_intr_enable,
284b6d90eb7SKip Macy .intr_disable = mv88e1xxx_intr_disable,
285b6d90eb7SKip Macy .intr_clear = mv88e1xxx_intr_clear,
286b6d90eb7SKip Macy .intr_handler = mv88e1xxx_intr_handler,
287b6d90eb7SKip Macy .autoneg_enable = mv88e1xxx_autoneg_enable,
288b6d90eb7SKip Macy .autoneg_restart = mv88e1xxx_autoneg_restart,
289b6d90eb7SKip Macy .advertise = t3_phy_advertise,
290b6d90eb7SKip Macy .set_loopback = mv88e1xxx_set_loopback,
2918e10660fSKip Macy .set_speed_duplex = mv88e1xxx_set_speed_duplex,
292b6d90eb7SKip Macy .get_link_status = mv88e1xxx_get_link_status,
293b6d90eb7SKip Macy .power_down = mv88e1xxx_power_down,
294b6d90eb7SKip Macy };
295b6d90eb7SKip Macy #endif
296b6d90eb7SKip Macy
t3_mv88e1xxx_phy_prep(pinfo_t * pinfo,int phy_addr,const struct mdio_ops * mdio_ops)297c01f2b83SNavdeep Parhar int t3_mv88e1xxx_phy_prep(pinfo_t *pinfo, int phy_addr,
298b6d90eb7SKip Macy const struct mdio_ops *mdio_ops)
299b6d90eb7SKip Macy {
300c01f2b83SNavdeep Parhar struct cphy *phy = &pinfo->phy;
3018e10660fSKip Macy int err;
3028e10660fSKip Macy
303c01f2b83SNavdeep Parhar cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &mv88e1xxx_ops, mdio_ops,
3048e10660fSKip Macy SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full |
3058e10660fSKip Macy SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII |
3068e10660fSKip Macy SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
307b6d90eb7SKip Macy
308b6d90eb7SKip Macy /* Configure copper PHY transmitter as class A to reduce EMI. */
3098e10660fSKip Macy err = mdio_write(phy, 0, MV88E1XXX_EXTENDED_ADDR, 0xb);
3108e10660fSKip Macy if (!err)
3118e10660fSKip Macy err = mdio_write(phy, 0, MV88E1XXX_EXTENDED_DATA, 0x8004);
3124af83c8cSKip Macy
3138e10660fSKip Macy if (!err)
3148e10660fSKip Macy err = mv88e1xxx_downshift_set(phy, 1); /* Enable downshift */
3158e10660fSKip Macy return err;
316b6d90eb7SKip Macy }
317