xref: /openbmc/linux/drivers/net/phy/realtek.c (revision aeb64ff3)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * drivers/net/phy/realtek.c
4  *
5  * Driver for Realtek PHYs
6  *
7  * Author: Johnson Leung <r58129@freescale.com>
8  *
9  * Copyright (c) 2004 Freescale Semiconductor, Inc.
10  */
11 #include <linux/bitops.h>
12 #include <linux/phy.h>
13 #include <linux/module.h>
14 
15 #define RTL821x_PHYSR				0x11
16 #define RTL821x_PHYSR_DUPLEX			BIT(13)
17 #define RTL821x_PHYSR_SPEED			GENMASK(15, 14)
18 
19 #define RTL821x_INER				0x12
20 #define RTL8211B_INER_INIT			0x6400
21 #define RTL8211E_INER_LINK_STATUS		BIT(10)
22 #define RTL8211F_INER_LINK_STATUS		BIT(4)
23 
24 #define RTL821x_INSR				0x13
25 
26 #define RTL821x_EXT_PAGE_SELECT			0x1e
27 #define RTL821x_PAGE_SELECT			0x1f
28 
29 #define RTL8211F_INSR				0x1d
30 
31 #define RTL8211F_TX_DELAY			BIT(8)
32 #define RTL8211E_TX_DELAY			BIT(1)
33 #define RTL8211E_RX_DELAY			BIT(2)
34 #define RTL8211E_MODE_MII_GMII			BIT(3)
35 
36 #define RTL8201F_ISR				0x1e
37 #define RTL8201F_IER				0x13
38 
39 #define RTL8366RB_POWER_SAVE			0x15
40 #define RTL8366RB_POWER_SAVE_ON			BIT(12)
41 
42 #define RTL_SUPPORTS_5000FULL			BIT(14)
43 #define RTL_SUPPORTS_2500FULL			BIT(13)
44 #define RTL_SUPPORTS_10000FULL			BIT(0)
45 #define RTL_ADV_2500FULL			BIT(7)
46 #define RTL_LPADV_10000FULL			BIT(11)
47 #define RTL_LPADV_5000FULL			BIT(6)
48 #define RTL_LPADV_2500FULL			BIT(5)
49 
50 #define RTL_GENERIC_PHYID			0x001cc800
51 
52 MODULE_DESCRIPTION("Realtek PHY driver");
53 MODULE_AUTHOR("Johnson Leung");
54 MODULE_LICENSE("GPL");
55 
56 static int rtl821x_read_page(struct phy_device *phydev)
57 {
58 	return __phy_read(phydev, RTL821x_PAGE_SELECT);
59 }
60 
61 static int rtl821x_write_page(struct phy_device *phydev, int page)
62 {
63 	return __phy_write(phydev, RTL821x_PAGE_SELECT, page);
64 }
65 
66 static int rtl8201_ack_interrupt(struct phy_device *phydev)
67 {
68 	int err;
69 
70 	err = phy_read(phydev, RTL8201F_ISR);
71 
72 	return (err < 0) ? err : 0;
73 }
74 
75 static int rtl821x_ack_interrupt(struct phy_device *phydev)
76 {
77 	int err;
78 
79 	err = phy_read(phydev, RTL821x_INSR);
80 
81 	return (err < 0) ? err : 0;
82 }
83 
84 static int rtl8211f_ack_interrupt(struct phy_device *phydev)
85 {
86 	int err;
87 
88 	err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR);
89 
90 	return (err < 0) ? err : 0;
91 }
92 
93 static int rtl8201_config_intr(struct phy_device *phydev)
94 {
95 	u16 val;
96 
97 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
98 		val = BIT(13) | BIT(12) | BIT(11);
99 	else
100 		val = 0;
101 
102 	return phy_write_paged(phydev, 0x7, RTL8201F_IER, val);
103 }
104 
105 static int rtl8211b_config_intr(struct phy_device *phydev)
106 {
107 	int err;
108 
109 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
110 		err = phy_write(phydev, RTL821x_INER,
111 				RTL8211B_INER_INIT);
112 	else
113 		err = phy_write(phydev, RTL821x_INER, 0);
114 
115 	return err;
116 }
117 
118 static int rtl8211e_config_intr(struct phy_device *phydev)
119 {
120 	int err;
121 
122 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
123 		err = phy_write(phydev, RTL821x_INER,
124 				RTL8211E_INER_LINK_STATUS);
125 	else
126 		err = phy_write(phydev, RTL821x_INER, 0);
127 
128 	return err;
129 }
130 
131 static int rtl8211f_config_intr(struct phy_device *phydev)
132 {
133 	u16 val;
134 
135 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
136 		val = RTL8211F_INER_LINK_STATUS;
137 	else
138 		val = 0;
139 
140 	return phy_write_paged(phydev, 0xa42, RTL821x_INER, val);
141 }
142 
143 static int rtl8211_config_aneg(struct phy_device *phydev)
144 {
145 	int ret;
146 
147 	ret = genphy_config_aneg(phydev);
148 	if (ret < 0)
149 		return ret;
150 
151 	/* Quirk was copied from vendor driver. Unfortunately it includes no
152 	 * description of the magic numbers.
153 	 */
154 	if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) {
155 		phy_write(phydev, 0x17, 0x2138);
156 		phy_write(phydev, 0x0e, 0x0260);
157 	} else {
158 		phy_write(phydev, 0x17, 0x2108);
159 		phy_write(phydev, 0x0e, 0x0000);
160 	}
161 
162 	return 0;
163 }
164 
165 static int rtl8211c_config_init(struct phy_device *phydev)
166 {
167 	/* RTL8211C has an issue when operating in Gigabit slave mode */
168 	return phy_set_bits(phydev, MII_CTRL1000,
169 			    CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER);
170 }
171 
172 static int rtl8211f_config_init(struct phy_device *phydev)
173 {
174 	u16 val;
175 
176 	/* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and
177 	 * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin.
178 	 */
179 	switch (phydev->interface) {
180 	case PHY_INTERFACE_MODE_RGMII:
181 	case PHY_INTERFACE_MODE_RGMII_RXID:
182 		val = 0;
183 		break;
184 	case PHY_INTERFACE_MODE_RGMII_ID:
185 	case PHY_INTERFACE_MODE_RGMII_TXID:
186 		val = RTL8211F_TX_DELAY;
187 		break;
188 	default: /* the rest of the modes imply leaving delay as is. */
189 		return 0;
190 	}
191 
192 	return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val);
193 }
194 
195 static int rtl8211e_config_init(struct phy_device *phydev)
196 {
197 	int ret = 0, oldpage;
198 	u16 val;
199 
200 	/* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
201 	switch (phydev->interface) {
202 	case PHY_INTERFACE_MODE_RGMII:
203 		val = 0;
204 		break;
205 	case PHY_INTERFACE_MODE_RGMII_ID:
206 		val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
207 		break;
208 	case PHY_INTERFACE_MODE_RGMII_RXID:
209 		val = RTL8211E_RX_DELAY;
210 		break;
211 	case PHY_INTERFACE_MODE_RGMII_TXID:
212 		val = RTL8211E_TX_DELAY;
213 		break;
214 	default: /* the rest of the modes imply leaving delays as is. */
215 		return 0;
216 	}
217 
218 	/* According to a sample driver there is a 0x1c config register on the
219 	 * 0xa4 extension page (0x7) layout. It can be used to disable/enable
220 	 * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can
221 	 * also be used to customize the whole configuration register:
222 	 * 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select,
223 	 * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
224 	 * for details).
225 	 */
226 	oldpage = phy_select_page(phydev, 0x7);
227 	if (oldpage < 0)
228 		goto err_restore_page;
229 
230 	ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
231 	if (ret)
232 		goto err_restore_page;
233 
234 	ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
235 			   val);
236 
237 err_restore_page:
238 	return phy_restore_page(phydev, oldpage, ret);
239 }
240 
241 static int rtl8211b_suspend(struct phy_device *phydev)
242 {
243 	phy_write(phydev, MII_MMD_DATA, BIT(9));
244 
245 	return genphy_suspend(phydev);
246 }
247 
248 static int rtl8211b_resume(struct phy_device *phydev)
249 {
250 	phy_write(phydev, MII_MMD_DATA, 0);
251 
252 	return genphy_resume(phydev);
253 }
254 
255 static int rtl8366rb_config_init(struct phy_device *phydev)
256 {
257 	int ret;
258 
259 	ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE,
260 			   RTL8366RB_POWER_SAVE_ON);
261 	if (ret) {
262 		dev_err(&phydev->mdio.dev,
263 			"error enabling power management\n");
264 	}
265 
266 	return ret;
267 }
268 
269 static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
270 {
271 	int ret;
272 
273 	if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) {
274 		rtl821x_write_page(phydev, 0xa5c);
275 		ret = __phy_read(phydev, 0x12);
276 		rtl821x_write_page(phydev, 0);
277 	} else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {
278 		rtl821x_write_page(phydev, 0xa5d);
279 		ret = __phy_read(phydev, 0x10);
280 		rtl821x_write_page(phydev, 0);
281 	} else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) {
282 		rtl821x_write_page(phydev, 0xa5d);
283 		ret = __phy_read(phydev, 0x11);
284 		rtl821x_write_page(phydev, 0);
285 	} else {
286 		ret = -EOPNOTSUPP;
287 	}
288 
289 	return ret;
290 }
291 
292 static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
293 			    u16 val)
294 {
295 	int ret;
296 
297 	if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {
298 		rtl821x_write_page(phydev, 0xa5d);
299 		ret = __phy_write(phydev, 0x10, val);
300 		rtl821x_write_page(phydev, 0);
301 	} else {
302 		ret = -EOPNOTSUPP;
303 	}
304 
305 	return ret;
306 }
307 
308 static int rtl8125_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
309 {
310 	int ret = rtlgen_read_mmd(phydev, devnum, regnum);
311 
312 	if (ret != -EOPNOTSUPP)
313 		return ret;
314 
315 	if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) {
316 		rtl821x_write_page(phydev, 0xa6e);
317 		ret = __phy_read(phydev, 0x16);
318 		rtl821x_write_page(phydev, 0);
319 	} else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) {
320 		rtl821x_write_page(phydev, 0xa6d);
321 		ret = __phy_read(phydev, 0x12);
322 		rtl821x_write_page(phydev, 0);
323 	} else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) {
324 		rtl821x_write_page(phydev, 0xa6d);
325 		ret = __phy_read(phydev, 0x10);
326 		rtl821x_write_page(phydev, 0);
327 	}
328 
329 	return ret;
330 }
331 
332 static int rtl8125_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
333 			     u16 val)
334 {
335 	int ret = rtlgen_write_mmd(phydev, devnum, regnum, val);
336 
337 	if (ret != -EOPNOTSUPP)
338 		return ret;
339 
340 	if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) {
341 		rtl821x_write_page(phydev, 0xa6d);
342 		ret = __phy_write(phydev, 0x12, val);
343 		rtl821x_write_page(phydev, 0);
344 	}
345 
346 	return ret;
347 }
348 
349 static int rtl8125_get_features(struct phy_device *phydev)
350 {
351 	int val;
352 
353 	val = phy_read_paged(phydev, 0xa61, 0x13);
354 	if (val < 0)
355 		return val;
356 
357 	linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
358 			 phydev->supported, val & RTL_SUPPORTS_2500FULL);
359 	linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
360 			 phydev->supported, val & RTL_SUPPORTS_5000FULL);
361 	linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
362 			 phydev->supported, val & RTL_SUPPORTS_10000FULL);
363 
364 	return genphy_read_abilities(phydev);
365 }
366 
367 static int rtl8125_config_aneg(struct phy_device *phydev)
368 {
369 	int ret = 0;
370 
371 	if (phydev->autoneg == AUTONEG_ENABLE) {
372 		u16 adv2500 = 0;
373 
374 		if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
375 				      phydev->advertising))
376 			adv2500 = RTL_ADV_2500FULL;
377 
378 		ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12,
379 					       RTL_ADV_2500FULL, adv2500);
380 		if (ret < 0)
381 			return ret;
382 	}
383 
384 	return __genphy_config_aneg(phydev, ret);
385 }
386 
387 static int rtl8125_read_status(struct phy_device *phydev)
388 {
389 	if (phydev->autoneg == AUTONEG_ENABLE) {
390 		int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
391 
392 		if (lpadv < 0)
393 			return lpadv;
394 
395 		linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
396 			phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL);
397 		linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
398 			phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL);
399 		linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
400 			phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL);
401 	}
402 
403 	return genphy_read_status(phydev);
404 }
405 
406 static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
407 {
408 	int val;
409 
410 	phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61);
411 	val = phy_read(phydev, 0x13);
412 	phy_write(phydev, RTL821x_PAGE_SELECT, 0);
413 
414 	return val >= 0 && val & RTL_SUPPORTS_2500FULL;
415 }
416 
417 static int rtlgen_match_phy_device(struct phy_device *phydev)
418 {
419 	return phydev->phy_id == RTL_GENERIC_PHYID &&
420 	       !rtlgen_supports_2_5gbps(phydev);
421 }
422 
423 static int rtl8125_match_phy_device(struct phy_device *phydev)
424 {
425 	return phydev->phy_id == RTL_GENERIC_PHYID &&
426 	       rtlgen_supports_2_5gbps(phydev);
427 }
428 
429 static struct phy_driver realtek_drvs[] = {
430 	{
431 		PHY_ID_MATCH_EXACT(0x00008201),
432 		.name           = "RTL8201CP Ethernet",
433 	}, {
434 		PHY_ID_MATCH_EXACT(0x001cc816),
435 		.name		= "RTL8201F Fast Ethernet",
436 		.ack_interrupt	= &rtl8201_ack_interrupt,
437 		.config_intr	= &rtl8201_config_intr,
438 		.suspend	= genphy_suspend,
439 		.resume		= genphy_resume,
440 		.read_page	= rtl821x_read_page,
441 		.write_page	= rtl821x_write_page,
442 	}, {
443 		PHY_ID_MATCH_MODEL(0x001cc880),
444 		.name		= "RTL8208 Fast Ethernet",
445 		.read_mmd	= genphy_read_mmd_unsupported,
446 		.write_mmd	= genphy_write_mmd_unsupported,
447 		.suspend	= genphy_suspend,
448 		.resume		= genphy_resume,
449 		.read_page	= rtl821x_read_page,
450 		.write_page	= rtl821x_write_page,
451 	}, {
452 		PHY_ID_MATCH_EXACT(0x001cc910),
453 		.name		= "RTL8211 Gigabit Ethernet",
454 		.config_aneg	= rtl8211_config_aneg,
455 		.read_mmd	= &genphy_read_mmd_unsupported,
456 		.write_mmd	= &genphy_write_mmd_unsupported,
457 		.read_page	= rtl821x_read_page,
458 		.write_page	= rtl821x_write_page,
459 	}, {
460 		PHY_ID_MATCH_EXACT(0x001cc912),
461 		.name		= "RTL8211B Gigabit Ethernet",
462 		.ack_interrupt	= &rtl821x_ack_interrupt,
463 		.config_intr	= &rtl8211b_config_intr,
464 		.read_mmd	= &genphy_read_mmd_unsupported,
465 		.write_mmd	= &genphy_write_mmd_unsupported,
466 		.suspend	= rtl8211b_suspend,
467 		.resume		= rtl8211b_resume,
468 		.read_page	= rtl821x_read_page,
469 		.write_page	= rtl821x_write_page,
470 	}, {
471 		PHY_ID_MATCH_EXACT(0x001cc913),
472 		.name		= "RTL8211C Gigabit Ethernet",
473 		.config_init	= rtl8211c_config_init,
474 		.read_mmd	= &genphy_read_mmd_unsupported,
475 		.write_mmd	= &genphy_write_mmd_unsupported,
476 		.read_page	= rtl821x_read_page,
477 		.write_page	= rtl821x_write_page,
478 	}, {
479 		PHY_ID_MATCH_EXACT(0x001cc914),
480 		.name		= "RTL8211DN Gigabit Ethernet",
481 		.ack_interrupt	= rtl821x_ack_interrupt,
482 		.config_intr	= rtl8211e_config_intr,
483 		.suspend	= genphy_suspend,
484 		.resume		= genphy_resume,
485 		.read_page	= rtl821x_read_page,
486 		.write_page	= rtl821x_write_page,
487 	}, {
488 		PHY_ID_MATCH_EXACT(0x001cc915),
489 		.name		= "RTL8211E Gigabit Ethernet",
490 		.config_init	= &rtl8211e_config_init,
491 		.ack_interrupt	= &rtl821x_ack_interrupt,
492 		.config_intr	= &rtl8211e_config_intr,
493 		.suspend	= genphy_suspend,
494 		.resume		= genphy_resume,
495 		.read_page	= rtl821x_read_page,
496 		.write_page	= rtl821x_write_page,
497 	}, {
498 		PHY_ID_MATCH_EXACT(0x001cc916),
499 		.name		= "RTL8211F Gigabit Ethernet",
500 		.config_init	= &rtl8211f_config_init,
501 		.ack_interrupt	= &rtl8211f_ack_interrupt,
502 		.config_intr	= &rtl8211f_config_intr,
503 		.suspend	= genphy_suspend,
504 		.resume		= genphy_resume,
505 		.read_page	= rtl821x_read_page,
506 		.write_page	= rtl821x_write_page,
507 	}, {
508 		.name		= "Generic FE-GE Realtek PHY",
509 		.match_phy_device = rtlgen_match_phy_device,
510 		.suspend	= genphy_suspend,
511 		.resume		= genphy_resume,
512 		.read_page	= rtl821x_read_page,
513 		.write_page	= rtl821x_write_page,
514 		.read_mmd	= rtlgen_read_mmd,
515 		.write_mmd	= rtlgen_write_mmd,
516 	}, {
517 		.name		= "RTL8125 2.5Gbps internal",
518 		.match_phy_device = rtl8125_match_phy_device,
519 		.get_features	= rtl8125_get_features,
520 		.config_aneg	= rtl8125_config_aneg,
521 		.read_status	= rtl8125_read_status,
522 		.suspend	= genphy_suspend,
523 		.resume		= genphy_resume,
524 		.read_page	= rtl821x_read_page,
525 		.write_page	= rtl821x_write_page,
526 		.read_mmd	= rtl8125_read_mmd,
527 		.write_mmd	= rtl8125_write_mmd,
528 	}, {
529 		PHY_ID_MATCH_EXACT(0x001cc961),
530 		.name		= "RTL8366RB Gigabit Ethernet",
531 		.config_init	= &rtl8366rb_config_init,
532 		/* These interrupts are handled by the irq controller
533 		 * embedded inside the RTL8366RB, they get unmasked when the
534 		 * irq is requested and ACKed by reading the status register,
535 		 * which is done by the irqchip code.
536 		 */
537 		.ack_interrupt	= genphy_no_ack_interrupt,
538 		.config_intr	= genphy_no_config_intr,
539 		.suspend	= genphy_suspend,
540 		.resume		= genphy_resume,
541 	},
542 };
543 
544 module_phy_driver(realtek_drvs);
545 
546 static const struct mdio_device_id __maybe_unused realtek_tbl[] = {
547 	{ PHY_ID_MATCH_VENDOR(0x001cc800) },
548 	{ }
549 };
550 
551 MODULE_DEVICE_TABLE(mdio, realtek_tbl);
552