xref: /OK3568_Linux_fs/kernel/drivers/net/phy/phy-c45.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Clause 45 PHY support
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun #include <linux/ethtool.h>
6*4882a593Smuzhiyun #include <linux/export.h>
7*4882a593Smuzhiyun #include <linux/mdio.h>
8*4882a593Smuzhiyun #include <linux/mii.h>
9*4882a593Smuzhiyun #include <linux/phy.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun /**
12*4882a593Smuzhiyun  * genphy_c45_setup_forced - configures a forced speed
13*4882a593Smuzhiyun  * @phydev: target phy_device struct
14*4882a593Smuzhiyun  */
genphy_c45_pma_setup_forced(struct phy_device * phydev)15*4882a593Smuzhiyun int genphy_c45_pma_setup_forced(struct phy_device *phydev)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun 	int ctrl1, ctrl2, ret;
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun 	/* Half duplex is not supported */
20*4882a593Smuzhiyun 	if (phydev->duplex != DUPLEX_FULL)
21*4882a593Smuzhiyun 		return -EINVAL;
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun 	ctrl1 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
24*4882a593Smuzhiyun 	if (ctrl1 < 0)
25*4882a593Smuzhiyun 		return ctrl1;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 	ctrl2 = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2);
28*4882a593Smuzhiyun 	if (ctrl2 < 0)
29*4882a593Smuzhiyun 		return ctrl2;
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	ctrl1 &= ~MDIO_CTRL1_SPEEDSEL;
32*4882a593Smuzhiyun 	/*
33*4882a593Smuzhiyun 	 * PMA/PMD type selection is 1.7.5:0 not 1.7.3:0.  See 45.2.1.6.1
34*4882a593Smuzhiyun 	 * in 802.3-2012 and 802.3-2015.
35*4882a593Smuzhiyun 	 */
36*4882a593Smuzhiyun 	ctrl2 &= ~(MDIO_PMA_CTRL2_TYPE | 0x30);
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	switch (phydev->speed) {
39*4882a593Smuzhiyun 	case SPEED_10:
40*4882a593Smuzhiyun 		ctrl2 |= MDIO_PMA_CTRL2_10BT;
41*4882a593Smuzhiyun 		break;
42*4882a593Smuzhiyun 	case SPEED_100:
43*4882a593Smuzhiyun 		ctrl1 |= MDIO_PMA_CTRL1_SPEED100;
44*4882a593Smuzhiyun 		ctrl2 |= MDIO_PMA_CTRL2_100BTX;
45*4882a593Smuzhiyun 		break;
46*4882a593Smuzhiyun 	case SPEED_1000:
47*4882a593Smuzhiyun 		ctrl1 |= MDIO_PMA_CTRL1_SPEED1000;
48*4882a593Smuzhiyun 		/* Assume 1000base-T */
49*4882a593Smuzhiyun 		ctrl2 |= MDIO_PMA_CTRL2_1000BT;
50*4882a593Smuzhiyun 		break;
51*4882a593Smuzhiyun 	case SPEED_2500:
52*4882a593Smuzhiyun 		ctrl1 |= MDIO_CTRL1_SPEED2_5G;
53*4882a593Smuzhiyun 		/* Assume 2.5Gbase-T */
54*4882a593Smuzhiyun 		ctrl2 |= MDIO_PMA_CTRL2_2_5GBT;
55*4882a593Smuzhiyun 		break;
56*4882a593Smuzhiyun 	case SPEED_5000:
57*4882a593Smuzhiyun 		ctrl1 |= MDIO_CTRL1_SPEED5G;
58*4882a593Smuzhiyun 		/* Assume 5Gbase-T */
59*4882a593Smuzhiyun 		ctrl2 |= MDIO_PMA_CTRL2_5GBT;
60*4882a593Smuzhiyun 		break;
61*4882a593Smuzhiyun 	case SPEED_10000:
62*4882a593Smuzhiyun 		ctrl1 |= MDIO_CTRL1_SPEED10G;
63*4882a593Smuzhiyun 		/* Assume 10Gbase-T */
64*4882a593Smuzhiyun 		ctrl2 |= MDIO_PMA_CTRL2_10GBT;
65*4882a593Smuzhiyun 		break;
66*4882a593Smuzhiyun 	default:
67*4882a593Smuzhiyun 		return -EINVAL;
68*4882a593Smuzhiyun 	}
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1, ctrl1);
71*4882a593Smuzhiyun 	if (ret < 0)
72*4882a593Smuzhiyun 		return ret;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL2, ctrl2);
75*4882a593Smuzhiyun 	if (ret < 0)
76*4882a593Smuzhiyun 		return ret;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	return genphy_c45_an_disable_aneg(phydev);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_pma_setup_forced);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun /**
83*4882a593Smuzhiyun  * genphy_c45_an_config_aneg - configure advertisement registers
84*4882a593Smuzhiyun  * @phydev: target phy_device struct
85*4882a593Smuzhiyun  *
86*4882a593Smuzhiyun  * Configure advertisement registers based on modes set in phydev->advertising
87*4882a593Smuzhiyun  *
88*4882a593Smuzhiyun  * Returns negative errno code on failure, 0 if advertisement didn't change,
89*4882a593Smuzhiyun  * or 1 if advertised modes changed.
90*4882a593Smuzhiyun  */
genphy_c45_an_config_aneg(struct phy_device * phydev)91*4882a593Smuzhiyun int genphy_c45_an_config_aneg(struct phy_device *phydev)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	int changed, ret;
94*4882a593Smuzhiyun 	u32 adv;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	linkmode_and(phydev->advertising, phydev->advertising,
97*4882a593Smuzhiyun 		     phydev->supported);
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	changed = genphy_config_eee_advert(phydev);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	adv = linkmode_adv_to_mii_adv_t(phydev->advertising);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
104*4882a593Smuzhiyun 				     ADVERTISE_ALL | ADVERTISE_100BASE4 |
105*4882a593Smuzhiyun 				     ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
106*4882a593Smuzhiyun 				     adv);
107*4882a593Smuzhiyun 	if (ret < 0)
108*4882a593Smuzhiyun 		return ret;
109*4882a593Smuzhiyun 	if (ret > 0)
110*4882a593Smuzhiyun 		changed = 1;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	adv = linkmode_adv_to_mii_10gbt_adv_t(phydev->advertising);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
115*4882a593Smuzhiyun 				     MDIO_AN_10GBT_CTRL_ADV10G |
116*4882a593Smuzhiyun 				     MDIO_AN_10GBT_CTRL_ADV5G |
117*4882a593Smuzhiyun 				     MDIO_AN_10GBT_CTRL_ADV2_5G, adv);
118*4882a593Smuzhiyun 	if (ret < 0)
119*4882a593Smuzhiyun 		return ret;
120*4882a593Smuzhiyun 	if (ret > 0)
121*4882a593Smuzhiyun 		changed = 1;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	return changed;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_an_config_aneg);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun /**
128*4882a593Smuzhiyun  * genphy_c45_an_disable_aneg - disable auto-negotiation
129*4882a593Smuzhiyun  * @phydev: target phy_device struct
130*4882a593Smuzhiyun  *
131*4882a593Smuzhiyun  * Disable auto-negotiation in the Clause 45 PHY. The link parameters
132*4882a593Smuzhiyun  * parameters are controlled through the PMA/PMD MMD registers.
133*4882a593Smuzhiyun  *
134*4882a593Smuzhiyun  * Returns zero on success, negative errno code on failure.
135*4882a593Smuzhiyun  */
genphy_c45_an_disable_aneg(struct phy_device * phydev)136*4882a593Smuzhiyun int genphy_c45_an_disable_aneg(struct phy_device *phydev)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
140*4882a593Smuzhiyun 				  MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_an_disable_aneg);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun /**
145*4882a593Smuzhiyun  * genphy_c45_restart_aneg - Enable and restart auto-negotiation
146*4882a593Smuzhiyun  * @phydev: target phy_device struct
147*4882a593Smuzhiyun  *
148*4882a593Smuzhiyun  * This assumes that the auto-negotiation MMD is present.
149*4882a593Smuzhiyun  *
150*4882a593Smuzhiyun  * Enable and restart auto-negotiation.
151*4882a593Smuzhiyun  */
genphy_c45_restart_aneg(struct phy_device * phydev)152*4882a593Smuzhiyun int genphy_c45_restart_aneg(struct phy_device *phydev)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	return phy_set_bits_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1,
155*4882a593Smuzhiyun 				MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_restart_aneg);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun /**
160*4882a593Smuzhiyun  * genphy_c45_check_and_restart_aneg - Enable and restart auto-negotiation
161*4882a593Smuzhiyun  * @phydev: target phy_device struct
162*4882a593Smuzhiyun  * @restart: whether aneg restart is requested
163*4882a593Smuzhiyun  *
164*4882a593Smuzhiyun  * This assumes that the auto-negotiation MMD is present.
165*4882a593Smuzhiyun  *
166*4882a593Smuzhiyun  * Check, and restart auto-negotiation if needed.
167*4882a593Smuzhiyun  */
genphy_c45_check_and_restart_aneg(struct phy_device * phydev,bool restart)168*4882a593Smuzhiyun int genphy_c45_check_and_restart_aneg(struct phy_device *phydev, bool restart)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	int ret;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	if (!restart) {
173*4882a593Smuzhiyun 		/* Configure and restart aneg if it wasn't set before */
174*4882a593Smuzhiyun 		ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
175*4882a593Smuzhiyun 		if (ret < 0)
176*4882a593Smuzhiyun 			return ret;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 		if (!(ret & MDIO_AN_CTRL1_ENABLE))
179*4882a593Smuzhiyun 			restart = true;
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (restart)
183*4882a593Smuzhiyun 		return genphy_c45_restart_aneg(phydev);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	return 0;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_check_and_restart_aneg);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun /**
190*4882a593Smuzhiyun  * genphy_c45_aneg_done - return auto-negotiation complete status
191*4882a593Smuzhiyun  * @phydev: target phy_device struct
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  * This assumes that the auto-negotiation MMD is present.
194*4882a593Smuzhiyun  *
195*4882a593Smuzhiyun  * Reads the status register from the auto-negotiation MMD, returning:
196*4882a593Smuzhiyun  * - positive if auto-negotiation is complete
197*4882a593Smuzhiyun  * - negative errno code on error
198*4882a593Smuzhiyun  * - zero otherwise
199*4882a593Smuzhiyun  */
genphy_c45_aneg_done(struct phy_device * phydev)200*4882a593Smuzhiyun int genphy_c45_aneg_done(struct phy_device *phydev)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	int val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	return val < 0 ? val : val & MDIO_AN_STAT1_COMPLETE ? 1 : 0;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_aneg_done);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun /**
209*4882a593Smuzhiyun  * genphy_c45_read_link - read the overall link status from the MMDs
210*4882a593Smuzhiyun  * @phydev: target phy_device struct
211*4882a593Smuzhiyun  *
212*4882a593Smuzhiyun  * Read the link status from the specified MMDs, and if they all indicate
213*4882a593Smuzhiyun  * that the link is up, set phydev->link to 1.  If an error is encountered,
214*4882a593Smuzhiyun  * a negative errno will be returned, otherwise zero.
215*4882a593Smuzhiyun  */
genphy_c45_read_link(struct phy_device * phydev)216*4882a593Smuzhiyun int genphy_c45_read_link(struct phy_device *phydev)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	u32 mmd_mask = MDIO_DEVS_PMAPMD;
219*4882a593Smuzhiyun 	int val, devad;
220*4882a593Smuzhiyun 	bool link = true;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	if (phydev->c45_ids.mmds_present & MDIO_DEVS_AN) {
223*4882a593Smuzhiyun 		val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
224*4882a593Smuzhiyun 		if (val < 0)
225*4882a593Smuzhiyun 			return val;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 		/* Autoneg is being started, therefore disregard current
228*4882a593Smuzhiyun 		 * link status and report link as down.
229*4882a593Smuzhiyun 		 */
230*4882a593Smuzhiyun 		if (val & MDIO_AN_CTRL1_RESTART) {
231*4882a593Smuzhiyun 			phydev->link = 0;
232*4882a593Smuzhiyun 			return 0;
233*4882a593Smuzhiyun 		}
234*4882a593Smuzhiyun 	}
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	while (mmd_mask && link) {
237*4882a593Smuzhiyun 		devad = __ffs(mmd_mask);
238*4882a593Smuzhiyun 		mmd_mask &= ~BIT(devad);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 		/* The link state is latched low so that momentary link
241*4882a593Smuzhiyun 		 * drops can be detected. Do not double-read the status
242*4882a593Smuzhiyun 		 * in polling mode to detect such short link drops except
243*4882a593Smuzhiyun 		 * the link was already down.
244*4882a593Smuzhiyun 		 */
245*4882a593Smuzhiyun 		if (!phy_polling_mode(phydev) || !phydev->link) {
246*4882a593Smuzhiyun 			val = phy_read_mmd(phydev, devad, MDIO_STAT1);
247*4882a593Smuzhiyun 			if (val < 0)
248*4882a593Smuzhiyun 				return val;
249*4882a593Smuzhiyun 			else if (val & MDIO_STAT1_LSTATUS)
250*4882a593Smuzhiyun 				continue;
251*4882a593Smuzhiyun 		}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 		val = phy_read_mmd(phydev, devad, MDIO_STAT1);
254*4882a593Smuzhiyun 		if (val < 0)
255*4882a593Smuzhiyun 			return val;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 		if (!(val & MDIO_STAT1_LSTATUS))
258*4882a593Smuzhiyun 			link = false;
259*4882a593Smuzhiyun 	}
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	phydev->link = link;
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	return 0;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_read_link);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun /**
268*4882a593Smuzhiyun  * genphy_c45_read_lpa - read the link partner advertisement and pause
269*4882a593Smuzhiyun  * @phydev: target phy_device struct
270*4882a593Smuzhiyun  *
271*4882a593Smuzhiyun  * Read the Clause 45 defined base (7.19) and 10G (7.33) status registers,
272*4882a593Smuzhiyun  * filling in the link partner advertisement, pause and asym_pause members
273*4882a593Smuzhiyun  * in @phydev.  This assumes that the auto-negotiation MMD is present, and
274*4882a593Smuzhiyun  * the backplane bit (7.48.0) is clear.  Clause 45 PHY drivers are expected
275*4882a593Smuzhiyun  * to fill in the remainder of the link partner advert from vendor registers.
276*4882a593Smuzhiyun  */
genphy_c45_read_lpa(struct phy_device * phydev)277*4882a593Smuzhiyun int genphy_c45_read_lpa(struct phy_device *phydev)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	int val;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
282*4882a593Smuzhiyun 	if (val < 0)
283*4882a593Smuzhiyun 		return val;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	if (!(val & MDIO_AN_STAT1_COMPLETE)) {
286*4882a593Smuzhiyun 		linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
287*4882a593Smuzhiyun 				   phydev->lp_advertising);
288*4882a593Smuzhiyun 		mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0);
289*4882a593Smuzhiyun 		mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, 0);
290*4882a593Smuzhiyun 		phydev->pause = 0;
291*4882a593Smuzhiyun 		phydev->asym_pause = 0;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 		return 0;
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->lp_advertising,
297*4882a593Smuzhiyun 			 val & MDIO_AN_STAT1_LPABLE);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	/* Read the link partner's base page advertisement */
300*4882a593Smuzhiyun 	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_LPA);
301*4882a593Smuzhiyun 	if (val < 0)
302*4882a593Smuzhiyun 		return val;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	mii_adv_mod_linkmode_adv_t(phydev->lp_advertising, val);
305*4882a593Smuzhiyun 	phydev->pause = val & LPA_PAUSE_CAP ? 1 : 0;
306*4882a593Smuzhiyun 	phydev->asym_pause = val & LPA_PAUSE_ASYM ? 1 : 0;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	/* Read the link partner's 10G advertisement */
309*4882a593Smuzhiyun 	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
310*4882a593Smuzhiyun 	if (val < 0)
311*4882a593Smuzhiyun 		return val;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, val);
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	return 0;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_read_lpa);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun /**
320*4882a593Smuzhiyun  * genphy_c45_read_pma - read link speed etc from PMA
321*4882a593Smuzhiyun  * @phydev: target phy_device struct
322*4882a593Smuzhiyun  */
genphy_c45_read_pma(struct phy_device * phydev)323*4882a593Smuzhiyun int genphy_c45_read_pma(struct phy_device *phydev)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun 	int val;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	linkmode_zero(phydev->lp_advertising);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1);
330*4882a593Smuzhiyun 	if (val < 0)
331*4882a593Smuzhiyun 		return val;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	switch (val & MDIO_CTRL1_SPEEDSEL) {
334*4882a593Smuzhiyun 	case 0:
335*4882a593Smuzhiyun 		phydev->speed = SPEED_10;
336*4882a593Smuzhiyun 		break;
337*4882a593Smuzhiyun 	case MDIO_PMA_CTRL1_SPEED100:
338*4882a593Smuzhiyun 		phydev->speed = SPEED_100;
339*4882a593Smuzhiyun 		break;
340*4882a593Smuzhiyun 	case MDIO_PMA_CTRL1_SPEED1000:
341*4882a593Smuzhiyun 		phydev->speed = SPEED_1000;
342*4882a593Smuzhiyun 		break;
343*4882a593Smuzhiyun 	case MDIO_CTRL1_SPEED2_5G:
344*4882a593Smuzhiyun 		phydev->speed = SPEED_2500;
345*4882a593Smuzhiyun 		break;
346*4882a593Smuzhiyun 	case MDIO_CTRL1_SPEED5G:
347*4882a593Smuzhiyun 		phydev->speed = SPEED_5000;
348*4882a593Smuzhiyun 		break;
349*4882a593Smuzhiyun 	case MDIO_CTRL1_SPEED10G:
350*4882a593Smuzhiyun 		phydev->speed = SPEED_10000;
351*4882a593Smuzhiyun 		break;
352*4882a593Smuzhiyun 	default:
353*4882a593Smuzhiyun 		phydev->speed = SPEED_UNKNOWN;
354*4882a593Smuzhiyun 		break;
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	phydev->duplex = DUPLEX_FULL;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	return 0;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun /**
364*4882a593Smuzhiyun  * genphy_c45_read_mdix - read mdix status from PMA
365*4882a593Smuzhiyun  * @phydev: target phy_device struct
366*4882a593Smuzhiyun  */
genphy_c45_read_mdix(struct phy_device * phydev)367*4882a593Smuzhiyun int genphy_c45_read_mdix(struct phy_device *phydev)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun 	int val;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	if (phydev->speed == SPEED_10000) {
372*4882a593Smuzhiyun 		val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
373*4882a593Smuzhiyun 				   MDIO_PMA_10GBT_SWAPPOL);
374*4882a593Smuzhiyun 		if (val < 0)
375*4882a593Smuzhiyun 			return val;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 		switch (val) {
378*4882a593Smuzhiyun 		case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
379*4882a593Smuzhiyun 			phydev->mdix = ETH_TP_MDI;
380*4882a593Smuzhiyun 			break;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 		case 0:
383*4882a593Smuzhiyun 			phydev->mdix = ETH_TP_MDI_X;
384*4882a593Smuzhiyun 			break;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 		default:
387*4882a593Smuzhiyun 			phydev->mdix = ETH_TP_MDI_INVALID;
388*4882a593Smuzhiyun 			break;
389*4882a593Smuzhiyun 		}
390*4882a593Smuzhiyun 	}
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return 0;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun /**
397*4882a593Smuzhiyun  * genphy_c45_pma_read_abilities - read supported link modes from PMA
398*4882a593Smuzhiyun  * @phydev: target phy_device struct
399*4882a593Smuzhiyun  *
400*4882a593Smuzhiyun  * Read the supported link modes from the PMA Status 2 (1.8) register. If bit
401*4882a593Smuzhiyun  * 1.8.9 is set, the list of supported modes is build using the values in the
402*4882a593Smuzhiyun  * PMA Extended Abilities (1.11) register, indicating 1000BASET an 10G related
403*4882a593Smuzhiyun  * modes. If bit 1.11.14 is set, then the list is also extended with the modes
404*4882a593Smuzhiyun  * in the 2.5G/5G PMA Extended register (1.21), indicating if 2.5GBASET and
405*4882a593Smuzhiyun  * 5GBASET are supported.
406*4882a593Smuzhiyun  */
genphy_c45_pma_read_abilities(struct phy_device * phydev)407*4882a593Smuzhiyun int genphy_c45_pma_read_abilities(struct phy_device *phydev)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	int val;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
412*4882a593Smuzhiyun 	if (phydev->c45_ids.mmds_present & MDIO_DEVS_AN) {
413*4882a593Smuzhiyun 		val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
414*4882a593Smuzhiyun 		if (val < 0)
415*4882a593Smuzhiyun 			return val;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 		if (val & MDIO_AN_STAT1_ABLE)
418*4882a593Smuzhiyun 			linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
419*4882a593Smuzhiyun 					 phydev->supported);
420*4882a593Smuzhiyun 	}
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
423*4882a593Smuzhiyun 	if (val < 0)
424*4882a593Smuzhiyun 		return val;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
427*4882a593Smuzhiyun 			 phydev->supported,
428*4882a593Smuzhiyun 			 val & MDIO_PMA_STAT2_10GBSR);
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
431*4882a593Smuzhiyun 			 phydev->supported,
432*4882a593Smuzhiyun 			 val & MDIO_PMA_STAT2_10GBLR);
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
435*4882a593Smuzhiyun 			 phydev->supported,
436*4882a593Smuzhiyun 			 val & MDIO_PMA_STAT2_10GBER);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (val & MDIO_PMA_STAT2_EXTABLE) {
439*4882a593Smuzhiyun 		val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
440*4882a593Smuzhiyun 		if (val < 0)
441*4882a593Smuzhiyun 			return val;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
444*4882a593Smuzhiyun 				 phydev->supported,
445*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_10GBLRM);
446*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
447*4882a593Smuzhiyun 				 phydev->supported,
448*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_10GBT);
449*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
450*4882a593Smuzhiyun 				 phydev->supported,
451*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_10GBKX4);
452*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
453*4882a593Smuzhiyun 				 phydev->supported,
454*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_10GBKR);
455*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
456*4882a593Smuzhiyun 				 phydev->supported,
457*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_1000BT);
458*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
459*4882a593Smuzhiyun 				 phydev->supported,
460*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_1000BKX);
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
463*4882a593Smuzhiyun 				 phydev->supported,
464*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_100BTX);
465*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
466*4882a593Smuzhiyun 				 phydev->supported,
467*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_100BTX);
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
470*4882a593Smuzhiyun 				 phydev->supported,
471*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_10BT);
472*4882a593Smuzhiyun 		linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
473*4882a593Smuzhiyun 				 phydev->supported,
474*4882a593Smuzhiyun 				 val & MDIO_PMA_EXTABLE_10BT);
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 		if (val & MDIO_PMA_EXTABLE_NBT) {
477*4882a593Smuzhiyun 			val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
478*4882a593Smuzhiyun 					   MDIO_PMA_NG_EXTABLE);
479*4882a593Smuzhiyun 			if (val < 0)
480*4882a593Smuzhiyun 				return val;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 			linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
483*4882a593Smuzhiyun 					 phydev->supported,
484*4882a593Smuzhiyun 					 val & MDIO_PMA_NG_EXTABLE_2_5GBT);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 			linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
487*4882a593Smuzhiyun 					 phydev->supported,
488*4882a593Smuzhiyun 					 val & MDIO_PMA_NG_EXTABLE_5GBT);
489*4882a593Smuzhiyun 		}
490*4882a593Smuzhiyun 	}
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	return 0;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun /**
497*4882a593Smuzhiyun  * genphy_c45_read_status - read PHY status
498*4882a593Smuzhiyun  * @phydev: target phy_device struct
499*4882a593Smuzhiyun  *
500*4882a593Smuzhiyun  * Reads status from PHY and sets phy_device members accordingly.
501*4882a593Smuzhiyun  */
genphy_c45_read_status(struct phy_device * phydev)502*4882a593Smuzhiyun int genphy_c45_read_status(struct phy_device *phydev)
503*4882a593Smuzhiyun {
504*4882a593Smuzhiyun 	int ret;
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun 	ret = genphy_c45_read_link(phydev);
507*4882a593Smuzhiyun 	if (ret)
508*4882a593Smuzhiyun 		return ret;
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun 	phydev->speed = SPEED_UNKNOWN;
511*4882a593Smuzhiyun 	phydev->duplex = DUPLEX_UNKNOWN;
512*4882a593Smuzhiyun 	phydev->pause = 0;
513*4882a593Smuzhiyun 	phydev->asym_pause = 0;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	if (phydev->autoneg == AUTONEG_ENABLE) {
516*4882a593Smuzhiyun 		ret = genphy_c45_read_lpa(phydev);
517*4882a593Smuzhiyun 		if (ret)
518*4882a593Smuzhiyun 			return ret;
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 		phy_resolve_aneg_linkmode(phydev);
521*4882a593Smuzhiyun 	} else {
522*4882a593Smuzhiyun 		ret = genphy_c45_read_pma(phydev);
523*4882a593Smuzhiyun 	}
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	return ret;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_read_status);
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun /**
530*4882a593Smuzhiyun  * genphy_c45_config_aneg - restart auto-negotiation or forced setup
531*4882a593Smuzhiyun  * @phydev: target phy_device struct
532*4882a593Smuzhiyun  *
533*4882a593Smuzhiyun  * Description: If auto-negotiation is enabled, we configure the
534*4882a593Smuzhiyun  *   advertising, and then restart auto-negotiation.  If it is not
535*4882a593Smuzhiyun  *   enabled, then we force a configuration.
536*4882a593Smuzhiyun  */
genphy_c45_config_aneg(struct phy_device * phydev)537*4882a593Smuzhiyun int genphy_c45_config_aneg(struct phy_device *phydev)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun 	bool changed = false;
540*4882a593Smuzhiyun 	int ret;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	if (phydev->autoneg == AUTONEG_DISABLE)
543*4882a593Smuzhiyun 		return genphy_c45_pma_setup_forced(phydev);
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	ret = genphy_c45_an_config_aneg(phydev);
546*4882a593Smuzhiyun 	if (ret < 0)
547*4882a593Smuzhiyun 		return ret;
548*4882a593Smuzhiyun 	if (ret > 0)
549*4882a593Smuzhiyun 		changed = true;
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	return genphy_c45_check_and_restart_aneg(phydev, changed);
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(genphy_c45_config_aneg);
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun /* The gen10g_* functions are the old Clause 45 stub */
556*4882a593Smuzhiyun 
gen10g_config_aneg(struct phy_device * phydev)557*4882a593Smuzhiyun int gen10g_config_aneg(struct phy_device *phydev)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun 	return 0;
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(gen10g_config_aneg);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun struct phy_driver genphy_c45_driver = {
564*4882a593Smuzhiyun 	.phy_id         = 0xffffffff,
565*4882a593Smuzhiyun 	.phy_id_mask    = 0xffffffff,
566*4882a593Smuzhiyun 	.name           = "Generic Clause 45 PHY",
567*4882a593Smuzhiyun 	.read_status    = genphy_c45_read_status,
568*4882a593Smuzhiyun };
569