Loading...
1/*
2 * drivers/net/phy/realtek.c
3 *
4 * Driver for Realtek PHYs
5 *
6 * Author: Johnson Leung <r58129@freescale.com>
7 *
8 * Copyright (c) 2004 Freescale Semiconductor, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16#include <linux/phy.h>
17
18#define RTL821x_PHYSR 0x11
19#define RTL821x_PHYSR_DUPLEX 0x2000
20#define RTL821x_PHYSR_SPEED 0xc000
21#define RTL821x_INER 0x12
22#define RTL821x_INER_INIT 0x6400
23#define RTL821x_INSR 0x13
24
25MODULE_DESCRIPTION("Realtek PHY driver");
26MODULE_AUTHOR("Johnson Leung");
27MODULE_LICENSE("GPL");
28
29static int rtl821x_ack_interrupt(struct phy_device *phydev)
30{
31 int err;
32
33 err = phy_read(phydev, RTL821x_INSR);
34
35 return (err < 0) ? err : 0;
36}
37
38static int rtl821x_config_intr(struct phy_device *phydev)
39{
40 int err;
41
42 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
43 err = phy_write(phydev, RTL821x_INER,
44 RTL821x_INER_INIT);
45 else
46 err = phy_write(phydev, RTL821x_INER, 0);
47
48 return err;
49}
50
51/* RTL8211B */
52static struct phy_driver rtl821x_driver = {
53 .phy_id = 0x001cc912,
54 .name = "RTL821x Gigabit Ethernet",
55 .phy_id_mask = 0x001fffff,
56 .features = PHY_GBIT_FEATURES,
57 .flags = PHY_HAS_INTERRUPT,
58 .config_aneg = &genphy_config_aneg,
59 .read_status = &genphy_read_status,
60 .ack_interrupt = &rtl821x_ack_interrupt,
61 .config_intr = &rtl821x_config_intr,
62 .driver = { .owner = THIS_MODULE,},
63};
64
65static int __init realtek_init(void)
66{
67 int ret;
68
69 ret = phy_driver_register(&rtl821x_driver);
70
71 return ret;
72}
73
74static void __exit realtek_exit(void)
75{
76 phy_driver_unregister(&rtl821x_driver);
77}
78
79module_init(realtek_init);
80module_exit(realtek_exit);
81
82static struct mdio_device_id __maybe_unused realtek_tbl[] = {
83 { 0x001cc912, 0x001fffff },
84 { }
85};
86
87MODULE_DEVICE_TABLE(mdio, realtek_tbl);
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
52MODULE_DESCRIPTION("Realtek PHY driver");
53MODULE_AUTHOR("Johnson Leung");
54MODULE_LICENSE("GPL");
55
56static int rtl821x_read_page(struct phy_device *phydev)
57{
58 return __phy_read(phydev, RTL821x_PAGE_SELECT);
59}
60
61static int rtl821x_write_page(struct phy_device *phydev, int page)
62{
63 return __phy_write(phydev, RTL821x_PAGE_SELECT, page);
64}
65
66static 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
75static 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
84static 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
93static 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
105static 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
118static 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
131static 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
143static 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
165static 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
172static 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
195static 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
237err_restore_page:
238 return phy_restore_page(phydev, oldpage, ret);
239}
240
241static 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
248static int rtl8211b_resume(struct phy_device *phydev)
249{
250 phy_write(phydev, MII_MMD_DATA, 0);
251
252 return genphy_resume(phydev);
253}
254
255static 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
269static 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
292static 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
308static 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
332static 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
349static 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
367static 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
387static 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
406static 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
417static 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
423static 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
429static 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_EXACT(0x001cc910),
444 .name = "RTL8211 Gigabit Ethernet",
445 .config_aneg = rtl8211_config_aneg,
446 .read_mmd = &genphy_read_mmd_unsupported,
447 .write_mmd = &genphy_write_mmd_unsupported,
448 .read_page = rtl821x_read_page,
449 .write_page = rtl821x_write_page,
450 }, {
451 PHY_ID_MATCH_EXACT(0x001cc912),
452 .name = "RTL8211B Gigabit Ethernet",
453 .ack_interrupt = &rtl821x_ack_interrupt,
454 .config_intr = &rtl8211b_config_intr,
455 .read_mmd = &genphy_read_mmd_unsupported,
456 .write_mmd = &genphy_write_mmd_unsupported,
457 .suspend = rtl8211b_suspend,
458 .resume = rtl8211b_resume,
459 .read_page = rtl821x_read_page,
460 .write_page = rtl821x_write_page,
461 }, {
462 PHY_ID_MATCH_EXACT(0x001cc913),
463 .name = "RTL8211C Gigabit Ethernet",
464 .config_init = rtl8211c_config_init,
465 .read_mmd = &genphy_read_mmd_unsupported,
466 .write_mmd = &genphy_write_mmd_unsupported,
467 .read_page = rtl821x_read_page,
468 .write_page = rtl821x_write_page,
469 }, {
470 PHY_ID_MATCH_EXACT(0x001cc914),
471 .name = "RTL8211DN Gigabit Ethernet",
472 .ack_interrupt = rtl821x_ack_interrupt,
473 .config_intr = rtl8211e_config_intr,
474 .suspend = genphy_suspend,
475 .resume = genphy_resume,
476 .read_page = rtl821x_read_page,
477 .write_page = rtl821x_write_page,
478 }, {
479 PHY_ID_MATCH_EXACT(0x001cc915),
480 .name = "RTL8211E Gigabit Ethernet",
481 .config_init = &rtl8211e_config_init,
482 .ack_interrupt = &rtl821x_ack_interrupt,
483 .config_intr = &rtl8211e_config_intr,
484 .suspend = genphy_suspend,
485 .resume = genphy_resume,
486 .read_page = rtl821x_read_page,
487 .write_page = rtl821x_write_page,
488 }, {
489 PHY_ID_MATCH_EXACT(0x001cc916),
490 .name = "RTL8211F Gigabit Ethernet",
491 .config_init = &rtl8211f_config_init,
492 .ack_interrupt = &rtl8211f_ack_interrupt,
493 .config_intr = &rtl8211f_config_intr,
494 .suspend = genphy_suspend,
495 .resume = genphy_resume,
496 .read_page = rtl821x_read_page,
497 .write_page = rtl821x_write_page,
498 }, {
499 .name = "Generic FE-GE Realtek PHY",
500 .match_phy_device = rtlgen_match_phy_device,
501 .suspend = genphy_suspend,
502 .resume = genphy_resume,
503 .read_page = rtl821x_read_page,
504 .write_page = rtl821x_write_page,
505 .read_mmd = rtlgen_read_mmd,
506 .write_mmd = rtlgen_write_mmd,
507 }, {
508 .name = "RTL8125 2.5Gbps internal",
509 .match_phy_device = rtl8125_match_phy_device,
510 .get_features = rtl8125_get_features,
511 .config_aneg = rtl8125_config_aneg,
512 .read_status = rtl8125_read_status,
513 .suspend = genphy_suspend,
514 .resume = genphy_resume,
515 .read_page = rtl821x_read_page,
516 .write_page = rtl821x_write_page,
517 .read_mmd = rtl8125_read_mmd,
518 .write_mmd = rtl8125_write_mmd,
519 }, {
520 PHY_ID_MATCH_EXACT(0x001cc961),
521 .name = "RTL8366RB Gigabit Ethernet",
522 .config_init = &rtl8366rb_config_init,
523 /* These interrupts are handled by the irq controller
524 * embedded inside the RTL8366RB, they get unmasked when the
525 * irq is requested and ACKed by reading the status register,
526 * which is done by the irqchip code.
527 */
528 .ack_interrupt = genphy_no_ack_interrupt,
529 .config_intr = genphy_no_config_intr,
530 .suspend = genphy_suspend,
531 .resume = genphy_resume,
532 },
533};
534
535module_phy_driver(realtek_drvs);
536
537static const struct mdio_device_id __maybe_unused realtek_tbl[] = {
538 { PHY_ID_MATCH_VENDOR(0x001cc800) },
539 { }
540};
541
542MODULE_DEVICE_TABLE(mdio, realtek_tbl);