xref: /linux/drivers/net/phy/marvell10g.c (revision 20b2af32ff3f0ac74f2bfd0bc2c175b56002d1f1)
1*20b2af32SRussell King /*
2*20b2af32SRussell King  * Marvell 10G 88x3310 PHY driver
3*20b2af32SRussell King  *
4*20b2af32SRussell King  * Based upon the ID registers, this PHY appears to be a mixture of IPs
5*20b2af32SRussell King  * from two different companies.
6*20b2af32SRussell King  *
7*20b2af32SRussell King  * There appears to be several different data paths through the PHY which
8*20b2af32SRussell King  * are automatically managed by the PHY.  The following has been determined
9*20b2af32SRussell King  * via observation and experimentation:
10*20b2af32SRussell King  *
11*20b2af32SRussell King  *       SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
12*20b2af32SRussell King  *  10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
13*20b2af32SRussell King  *  10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
14*20b2af32SRussell King  *
15*20b2af32SRussell King  * If both the fiber and copper ports are connected, the first to gain
16*20b2af32SRussell King  * link takes priority and the other port is completely locked out.
17*20b2af32SRussell King  */
18*20b2af32SRussell King #include <linux/phy.h>
19*20b2af32SRussell King 
20*20b2af32SRussell King enum {
21*20b2af32SRussell King 	MV_PCS_BASE_T		= 0x0000,
22*20b2af32SRussell King 	MV_PCS_BASE_R		= 0x1000,
23*20b2af32SRussell King 	MV_PCS_1000BASEX	= 0x2000,
24*20b2af32SRussell King 
25*20b2af32SRussell King 	/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
26*20b2af32SRussell King 	 * registers appear to set themselves to the 0x800X when AN is
27*20b2af32SRussell King 	 * restarted, but status registers appear readable from either.
28*20b2af32SRussell King 	 */
29*20b2af32SRussell King 	MV_AN_CTRL1000		= 0x8000, /* 1000base-T control register */
30*20b2af32SRussell King 	MV_AN_STAT1000		= 0x8001, /* 1000base-T status register */
31*20b2af32SRussell King 
32*20b2af32SRussell King 	/* This register appears to reflect the copper status */
33*20b2af32SRussell King 	MV_AN_RESULT		= 0xa016,
34*20b2af32SRussell King 	MV_AN_RESULT_SPD_10	= BIT(12),
35*20b2af32SRussell King 	MV_AN_RESULT_SPD_100	= BIT(13),
36*20b2af32SRussell King 	MV_AN_RESULT_SPD_1000	= BIT(14),
37*20b2af32SRussell King 	MV_AN_RESULT_SPD_10000	= BIT(15),
38*20b2af32SRussell King };
39*20b2af32SRussell King 
40*20b2af32SRussell King static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
41*20b2af32SRussell King 			 u16 mask, u16 bits)
42*20b2af32SRussell King {
43*20b2af32SRussell King 	int old, val, ret;
44*20b2af32SRussell King 
45*20b2af32SRussell King 	old = phy_read_mmd(phydev, devad, reg);
46*20b2af32SRussell King 	if (old < 0)
47*20b2af32SRussell King 		return old;
48*20b2af32SRussell King 
49*20b2af32SRussell King 	val = (old & ~mask) | (bits & mask);
50*20b2af32SRussell King 	if (val == old)
51*20b2af32SRussell King 		return 0;
52*20b2af32SRussell King 
53*20b2af32SRussell King 	ret = phy_write_mmd(phydev, devad, reg, val);
54*20b2af32SRussell King 
55*20b2af32SRussell King 	return ret < 0 ? ret : 1;
56*20b2af32SRussell King }
57*20b2af32SRussell King 
58*20b2af32SRussell King static int mv3310_probe(struct phy_device *phydev)
59*20b2af32SRussell King {
60*20b2af32SRussell King 	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
61*20b2af32SRussell King 
62*20b2af32SRussell King 	if (!phydev->is_c45 ||
63*20b2af32SRussell King 	    (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
64*20b2af32SRussell King 		return -ENODEV;
65*20b2af32SRussell King 
66*20b2af32SRussell King 	return 0;
67*20b2af32SRussell King }
68*20b2af32SRussell King 
69*20b2af32SRussell King /*
70*20b2af32SRussell King  * Resetting the MV88X3310 causes it to become non-responsive.  Avoid
71*20b2af32SRussell King  * setting the reset bit(s).
72*20b2af32SRussell King  */
73*20b2af32SRussell King static int mv3310_soft_reset(struct phy_device *phydev)
74*20b2af32SRussell King {
75*20b2af32SRussell King 	return 0;
76*20b2af32SRussell King }
77*20b2af32SRussell King 
78*20b2af32SRussell King static int mv3310_config_init(struct phy_device *phydev)
79*20b2af32SRussell King {
80*20b2af32SRussell King 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
81*20b2af32SRussell King 	u32 mask;
82*20b2af32SRussell King 	int val;
83*20b2af32SRussell King 
84*20b2af32SRussell King 	/* Check that the PHY interface type is compatible */
85*20b2af32SRussell King 	if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
86*20b2af32SRussell King 	    phydev->interface != PHY_INTERFACE_MODE_XGMII &&
87*20b2af32SRussell King 	    phydev->interface != PHY_INTERFACE_MODE_XAUI &&
88*20b2af32SRussell King 	    phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
89*20b2af32SRussell King 	    phydev->interface != PHY_INTERFACE_MODE_10GKR)
90*20b2af32SRussell King 		return -ENODEV;
91*20b2af32SRussell King 
92*20b2af32SRussell King 	__set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
93*20b2af32SRussell King 	__set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
94*20b2af32SRussell King 
95*20b2af32SRussell King 	if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
96*20b2af32SRussell King 		val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
97*20b2af32SRussell King 		if (val < 0)
98*20b2af32SRussell King 			return val;
99*20b2af32SRussell King 
100*20b2af32SRussell King 		if (val & MDIO_AN_STAT1_ABLE)
101*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
102*20b2af32SRussell King 	}
103*20b2af32SRussell King 
104*20b2af32SRussell King 	val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
105*20b2af32SRussell King 	if (val < 0)
106*20b2af32SRussell King 		return val;
107*20b2af32SRussell King 
108*20b2af32SRussell King 	/* Ethtool does not support the WAN mode bits */
109*20b2af32SRussell King 	if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
110*20b2af32SRussell King 		   MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
111*20b2af32SRussell King 		   MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
112*20b2af32SRussell King 		   MDIO_PMA_STAT2_10GBEW))
113*20b2af32SRussell King 		__set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
114*20b2af32SRussell King 	if (val & MDIO_PMA_STAT2_10GBSR)
115*20b2af32SRussell King 		__set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
116*20b2af32SRussell King 	if (val & MDIO_PMA_STAT2_10GBLR)
117*20b2af32SRussell King 		__set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
118*20b2af32SRussell King 	if (val & MDIO_PMA_STAT2_10GBER)
119*20b2af32SRussell King 		__set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
120*20b2af32SRussell King 
121*20b2af32SRussell King 	if (val & MDIO_PMA_STAT2_EXTABLE) {
122*20b2af32SRussell King 		val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
123*20b2af32SRussell King 		if (val < 0)
124*20b2af32SRussell King 			return val;
125*20b2af32SRussell King 
126*20b2af32SRussell King 		if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
127*20b2af32SRussell King 			   MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
128*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
129*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_10GBLRM)
130*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
131*20b2af32SRussell King 		if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
132*20b2af32SRussell King 			   MDIO_PMA_EXTABLE_1000BKX))
133*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
134*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_10GBLRM)
135*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
136*20b2af32SRussell King 				  supported);
137*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_10GBT)
138*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
139*20b2af32SRussell King 				  supported);
140*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_10GBKX4)
141*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
142*20b2af32SRussell King 				  supported);
143*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_10GBKR)
144*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
145*20b2af32SRussell King 				  supported);
146*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_1000BT)
147*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
148*20b2af32SRussell King 				  supported);
149*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_1000BKX)
150*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
151*20b2af32SRussell King 				  supported);
152*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_100BTX)
153*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
154*20b2af32SRussell King 				  supported);
155*20b2af32SRussell King 		if (val & MDIO_PMA_EXTABLE_10BT)
156*20b2af32SRussell King 			__set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
157*20b2af32SRussell King 				  supported);
158*20b2af32SRussell King 	}
159*20b2af32SRussell King 
160*20b2af32SRussell King 	if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
161*20b2af32SRussell King 		dev_warn(&phydev->mdio.dev,
162*20b2af32SRussell King 			 "PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
163*20b2af32SRussell King 			 __ETHTOOL_LINK_MODE_MASK_NBITS, supported);
164*20b2af32SRussell King 
165*20b2af32SRussell King 	phydev->supported &= mask;
166*20b2af32SRussell King 	phydev->advertising &= phydev->supported;
167*20b2af32SRussell King 
168*20b2af32SRussell King 	return 0;
169*20b2af32SRussell King }
170*20b2af32SRussell King 
171*20b2af32SRussell King static int mv3310_config_aneg(struct phy_device *phydev)
172*20b2af32SRussell King {
173*20b2af32SRussell King 	bool changed = false;
174*20b2af32SRussell King 	u32 advertising;
175*20b2af32SRussell King 	int ret;
176*20b2af32SRussell King 
177*20b2af32SRussell King 	if (phydev->autoneg == AUTONEG_DISABLE) {
178*20b2af32SRussell King 		ret = genphy_c45_pma_setup_forced(phydev);
179*20b2af32SRussell King 		if (ret < 0)
180*20b2af32SRussell King 			return ret;
181*20b2af32SRussell King 
182*20b2af32SRussell King 		return genphy_c45_an_disable_aneg(phydev);
183*20b2af32SRussell King 	}
184*20b2af32SRussell King 
185*20b2af32SRussell King 	phydev->advertising &= phydev->supported;
186*20b2af32SRussell King 	advertising = phydev->advertising;
187*20b2af32SRussell King 
188*20b2af32SRussell King 	ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
189*20b2af32SRussell King 			    ADVERTISE_ALL | ADVERTISE_100BASE4 |
190*20b2af32SRussell King 			    ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
191*20b2af32SRussell King 			    ethtool_adv_to_mii_adv_t(advertising));
192*20b2af32SRussell King 	if (ret < 0)
193*20b2af32SRussell King 		return ret;
194*20b2af32SRussell King 	if (ret > 0)
195*20b2af32SRussell King 		changed = true;
196*20b2af32SRussell King 
197*20b2af32SRussell King 	ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
198*20b2af32SRussell King 			    ADVERTISE_1000FULL | ADVERTISE_1000HALF,
199*20b2af32SRussell King 			    ethtool_adv_to_mii_ctrl1000_t(advertising));
200*20b2af32SRussell King 	if (ret < 0)
201*20b2af32SRussell King 		return ret;
202*20b2af32SRussell King 	if (ret > 0)
203*20b2af32SRussell King 		changed = true;
204*20b2af32SRussell King 
205*20b2af32SRussell King 	/* 10G control register */
206*20b2af32SRussell King 	ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
207*20b2af32SRussell King 			    MDIO_AN_10GBT_CTRL_ADV10G,
208*20b2af32SRussell King 			    advertising & ADVERTISED_10000baseT_Full ?
209*20b2af32SRussell King 				MDIO_AN_10GBT_CTRL_ADV10G : 0);
210*20b2af32SRussell King 	if (ret < 0)
211*20b2af32SRussell King 		return ret;
212*20b2af32SRussell King 	if (ret > 0)
213*20b2af32SRussell King 		changed = true;
214*20b2af32SRussell King 
215*20b2af32SRussell King 	if (changed)
216*20b2af32SRussell King 		ret = genphy_c45_restart_aneg(phydev);
217*20b2af32SRussell King 
218*20b2af32SRussell King 	return ret;
219*20b2af32SRussell King }
220*20b2af32SRussell King 
221*20b2af32SRussell King static int mv3310_aneg_done(struct phy_device *phydev)
222*20b2af32SRussell King {
223*20b2af32SRussell King 	int val;
224*20b2af32SRussell King 
225*20b2af32SRussell King 	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
226*20b2af32SRussell King 	if (val < 0)
227*20b2af32SRussell King 		return val;
228*20b2af32SRussell King 
229*20b2af32SRussell King 	if (val & MDIO_STAT1_LSTATUS)
230*20b2af32SRussell King 		return 1;
231*20b2af32SRussell King 
232*20b2af32SRussell King 	return genphy_c45_aneg_done(phydev);
233*20b2af32SRussell King }
234*20b2af32SRussell King 
235*20b2af32SRussell King /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
236*20b2af32SRussell King static int mv3310_read_10gbr_status(struct phy_device *phydev)
237*20b2af32SRussell King {
238*20b2af32SRussell King 	phydev->link = 1;
239*20b2af32SRussell King 	phydev->speed = SPEED_10000;
240*20b2af32SRussell King 	phydev->duplex = DUPLEX_FULL;
241*20b2af32SRussell King 
242*20b2af32SRussell King 	if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
243*20b2af32SRussell King 		phydev->interface = PHY_INTERFACE_MODE_10GKR;
244*20b2af32SRussell King 
245*20b2af32SRussell King 	return 0;
246*20b2af32SRussell King }
247*20b2af32SRussell King 
248*20b2af32SRussell King static int mv3310_read_status(struct phy_device *phydev)
249*20b2af32SRussell King {
250*20b2af32SRussell King 	u32 mmd_mask = phydev->c45_ids.devices_in_package;
251*20b2af32SRussell King 	int val;
252*20b2af32SRussell King 
253*20b2af32SRussell King 	/* The vendor devads do not report link status.  Avoid the PHYXS
254*20b2af32SRussell King 	 * instance as there are three, and its status depends on the MAC
255*20b2af32SRussell King 	 * being appropriately configured for the negotiated speed.
256*20b2af32SRussell King 	 */
257*20b2af32SRussell King 	mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) |
258*20b2af32SRussell King 		      BIT(MDIO_MMD_PHYXS));
259*20b2af32SRussell King 
260*20b2af32SRussell King 	phydev->speed = SPEED_UNKNOWN;
261*20b2af32SRussell King 	phydev->duplex = DUPLEX_UNKNOWN;
262*20b2af32SRussell King 	phydev->lp_advertising = 0;
263*20b2af32SRussell King 	phydev->link = 0;
264*20b2af32SRussell King 	phydev->pause = 0;
265*20b2af32SRussell King 	phydev->asym_pause = 0;
266*20b2af32SRussell King 
267*20b2af32SRussell King 	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
268*20b2af32SRussell King 	if (val < 0)
269*20b2af32SRussell King 		return val;
270*20b2af32SRussell King 
271*20b2af32SRussell King 	if (val & MDIO_STAT1_LSTATUS)
272*20b2af32SRussell King 		return mv3310_read_10gbr_status(phydev);
273*20b2af32SRussell King 
274*20b2af32SRussell King 	val = genphy_c45_read_link(phydev, mmd_mask);
275*20b2af32SRussell King 	if (val < 0)
276*20b2af32SRussell King 		return val;
277*20b2af32SRussell King 
278*20b2af32SRussell King 	phydev->link = val > 0 ? 1 : 0;
279*20b2af32SRussell King 
280*20b2af32SRussell King 	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
281*20b2af32SRussell King 	if (val < 0)
282*20b2af32SRussell King 		return val;
283*20b2af32SRussell King 
284*20b2af32SRussell King 	if (val & MDIO_AN_STAT1_COMPLETE) {
285*20b2af32SRussell King 		val = genphy_c45_read_lpa(phydev);
286*20b2af32SRussell King 		if (val < 0)
287*20b2af32SRussell King 			return val;
288*20b2af32SRussell King 
289*20b2af32SRussell King 		/* Read the link partner's 1G advertisment */
290*20b2af32SRussell King 		val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
291*20b2af32SRussell King 		if (val < 0)
292*20b2af32SRussell King 			return val;
293*20b2af32SRussell King 
294*20b2af32SRussell King 		phydev->lp_advertising |= mii_stat1000_to_ethtool_lpa_t(val);
295*20b2af32SRussell King 
296*20b2af32SRussell King 		if (phydev->autoneg == AUTONEG_ENABLE) {
297*20b2af32SRussell King 			val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_RESULT);
298*20b2af32SRussell King 			if (val < 0)
299*20b2af32SRussell King 				return val;
300*20b2af32SRussell King 
301*20b2af32SRussell King 			if (val & MV_AN_RESULT_SPD_10000)
302*20b2af32SRussell King 				phydev->speed = SPEED_10000;
303*20b2af32SRussell King 			else if (val & MV_AN_RESULT_SPD_1000)
304*20b2af32SRussell King 				phydev->speed = SPEED_1000;
305*20b2af32SRussell King 			else if (val & MV_AN_RESULT_SPD_100)
306*20b2af32SRussell King 				phydev->speed = SPEED_100;
307*20b2af32SRussell King 			else if (val & MV_AN_RESULT_SPD_10)
308*20b2af32SRussell King 				phydev->speed = SPEED_10;
309*20b2af32SRussell King 
310*20b2af32SRussell King 			phydev->duplex = DUPLEX_FULL;
311*20b2af32SRussell King 		}
312*20b2af32SRussell King 	}
313*20b2af32SRussell King 
314*20b2af32SRussell King 	if (phydev->autoneg != AUTONEG_ENABLE) {
315*20b2af32SRussell King 		val = genphy_c45_read_pma(phydev);
316*20b2af32SRussell King 		if (val < 0)
317*20b2af32SRussell King 			return val;
318*20b2af32SRussell King 	}
319*20b2af32SRussell King 
320*20b2af32SRussell King 	if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
321*20b2af32SRussell King 	     phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
322*20b2af32SRussell King 		/* The PHY automatically switches its serdes interface (and
323*20b2af32SRussell King 		 * active PHYXS instance) between Cisco SGMII and 10GBase-KR
324*20b2af32SRussell King 		 * modes according to the speed.  Florian suggests setting
325*20b2af32SRussell King 		 * phydev->interface to communicate this to the MAC. Only do
326*20b2af32SRussell King 		 * this if we are already in either SGMII or 10GBase-KR mode.
327*20b2af32SRussell King 		 */
328*20b2af32SRussell King 		if (phydev->speed == SPEED_10000)
329*20b2af32SRussell King 			phydev->interface = PHY_INTERFACE_MODE_10GKR;
330*20b2af32SRussell King 		else if (phydev->speed >= SPEED_10 &&
331*20b2af32SRussell King 			 phydev->speed < SPEED_10000)
332*20b2af32SRussell King 			phydev->interface = PHY_INTERFACE_MODE_SGMII;
333*20b2af32SRussell King 	}
334*20b2af32SRussell King 
335*20b2af32SRussell King 	return 0;
336*20b2af32SRussell King }
337*20b2af32SRussell King 
338*20b2af32SRussell King static struct phy_driver mv3310_drivers[] = {
339*20b2af32SRussell King 	{
340*20b2af32SRussell King 		.phy_id		= 0x002b09aa,
341*20b2af32SRussell King 		.phy_id_mask	= 0xffffffff,
342*20b2af32SRussell King 		.name		= "mv88x3310",
343*20b2af32SRussell King 		.features	= SUPPORTED_10baseT_Full |
344*20b2af32SRussell King 				  SUPPORTED_100baseT_Full |
345*20b2af32SRussell King 				  SUPPORTED_1000baseT_Full |
346*20b2af32SRussell King 				  SUPPORTED_Autoneg |
347*20b2af32SRussell King 				  SUPPORTED_TP |
348*20b2af32SRussell King 				  SUPPORTED_FIBRE |
349*20b2af32SRussell King 				  SUPPORTED_10000baseT_Full |
350*20b2af32SRussell King 				  SUPPORTED_Backplane,
351*20b2af32SRussell King 		.probe		= mv3310_probe,
352*20b2af32SRussell King 		.soft_reset	= mv3310_soft_reset,
353*20b2af32SRussell King 		.config_init	= mv3310_config_init,
354*20b2af32SRussell King 		.config_aneg	= mv3310_config_aneg,
355*20b2af32SRussell King 		.aneg_done	= mv3310_aneg_done,
356*20b2af32SRussell King 		.read_status	= mv3310_read_status,
357*20b2af32SRussell King 	},
358*20b2af32SRussell King };
359*20b2af32SRussell King 
360*20b2af32SRussell King module_phy_driver(mv3310_drivers);
361*20b2af32SRussell King 
362*20b2af32SRussell King static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
363*20b2af32SRussell King 	{ 0x002b09aa, 0xffffffff },
364*20b2af32SRussell King 	{ },
365*20b2af32SRussell King };
366*20b2af32SRussell King MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
367*20b2af32SRussell King MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
368*20b2af32SRussell King MODULE_LICENSE("GPL");
369