Linux Audio

Check our new training course

Loading...
v3.1
 
 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);
v5.4
  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);