Linux Audio

Check our new training course

Loading...
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);
v4.6
 
  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#include <linux/module.h>
 18
 19#define RTL821x_PHYSR		0x11
 20#define RTL821x_PHYSR_DUPLEX	0x2000
 21#define RTL821x_PHYSR_SPEED	0xc000
 22#define RTL821x_INER		0x12
 23#define RTL821x_INER_INIT	0x6400
 24#define RTL821x_INSR		0x13
 25#define RTL8211E_INER_LINK_STATUS 0x400
 26
 27#define RTL8211F_INER_LINK_STATUS 0x0010
 28#define RTL8211F_INSR		0x1d
 29#define RTL8211F_PAGE_SELECT	0x1f
 30#define RTL8211F_TX_DELAY	0x100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 31
 32MODULE_DESCRIPTION("Realtek PHY driver");
 33MODULE_AUTHOR("Johnson Leung");
 34MODULE_LICENSE("GPL");
 35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 36static int rtl821x_ack_interrupt(struct phy_device *phydev)
 37{
 38	int err;
 39
 40	err = phy_read(phydev, RTL821x_INSR);
 41
 42	return (err < 0) ? err : 0;
 43}
 44
 45static int rtl8211f_ack_interrupt(struct phy_device *phydev)
 46{
 47	int err;
 48
 49	phy_write(phydev, RTL8211F_PAGE_SELECT, 0xa43);
 50	err = phy_read(phydev, RTL8211F_INSR);
 51	/* restore to default page 0 */
 52	phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0);
 53
 54	return (err < 0) ? err : 0;
 55}
 56
 
 
 
 
 
 
 
 
 
 
 
 
 57static int rtl8211b_config_intr(struct phy_device *phydev)
 58{
 59	int err;
 60
 61	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 62		err = phy_write(phydev, RTL821x_INER,
 63				RTL821x_INER_INIT);
 64	else
 65		err = phy_write(phydev, RTL821x_INER, 0);
 66
 67	return err;
 68}
 69
 70static int rtl8211e_config_intr(struct phy_device *phydev)
 71{
 72	int err;
 73
 74	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 75		err = phy_write(phydev, RTL821x_INER,
 76				RTL8211E_INER_LINK_STATUS);
 77	else
 78		err = phy_write(phydev, RTL821x_INER, 0);
 79
 80	return err;
 81}
 82
 83static int rtl8211f_config_intr(struct phy_device *phydev)
 84{
 85	int err;
 86
 87	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
 88		err = phy_write(phydev, RTL821x_INER,
 89				RTL8211F_INER_LINK_STATUS);
 90	else
 91		err = phy_write(phydev, RTL821x_INER, 0);
 92
 93	return err;
 94}
 95
 96static int rtl8211f_config_init(struct phy_device *phydev)
 97{
 98	int ret;
 99	u16 reg;
100
101	ret = genphy_config_init(phydev);
102	if (ret < 0)
103		return ret;
104
105	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
106		/* enable TXDLY */
107		phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08);
108		reg = phy_read(phydev, 0x11);
109		reg |= RTL8211F_TX_DELAY;
110		phy_write(phydev, 0x11, reg);
111		/* restore to default page 0 */
112		phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0);
 
113	}
114
115	return 0;
116}
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118static struct phy_driver realtek_drvs[] = {
119	{
120		.phy_id         = 0x00008201,
121		.name           = "RTL8201CP Ethernet",
122		.phy_id_mask    = 0x0000ffff,
123		.features       = PHY_BASIC_FEATURES,
124		.flags          = PHY_HAS_INTERRUPT,
125		.config_aneg    = &genphy_config_aneg,
126		.read_status    = &genphy_read_status,
127	}, {
128		.phy_id		= 0x001cc912,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129		.name		= "RTL8211B Gigabit Ethernet",
130		.phy_id_mask	= 0x001fffff,
131		.features	= PHY_GBIT_FEATURES,
132		.flags		= PHY_HAS_INTERRUPT,
133		.config_aneg	= &genphy_config_aneg,
134		.read_status	= &genphy_read_status,
135		.ack_interrupt	= &rtl821x_ack_interrupt,
136		.config_intr	= &rtl8211b_config_intr,
 
 
 
 
 
 
137	}, {
138		.phy_id		= 0x001cc914,
 
 
 
 
 
 
 
 
139		.name		= "RTL8211DN Gigabit Ethernet",
140		.phy_id_mask	= 0x001fffff,
141		.features	= PHY_GBIT_FEATURES,
142		.flags		= PHY_HAS_INTERRUPT,
143		.config_aneg	= genphy_config_aneg,
144		.read_status	= genphy_read_status,
145		.ack_interrupt	= rtl821x_ack_interrupt,
146		.config_intr	= rtl8211e_config_intr,
147		.suspend	= genphy_suspend,
148		.resume		= genphy_resume,
 
 
149	}, {
150		.phy_id		= 0x001cc915,
151		.name		= "RTL8211E Gigabit Ethernet",
152		.phy_id_mask	= 0x001fffff,
153		.features	= PHY_GBIT_FEATURES,
154		.flags		= PHY_HAS_INTERRUPT,
155		.config_aneg	= &genphy_config_aneg,
156		.read_status	= &genphy_read_status,
157		.ack_interrupt	= &rtl821x_ack_interrupt,
158		.config_intr	= &rtl8211e_config_intr,
159		.suspend	= genphy_suspend,
160		.resume		= genphy_resume,
 
 
161	}, {
162		.phy_id		= 0x001cc916,
163		.name		= "RTL8211F Gigabit Ethernet",
164		.phy_id_mask	= 0x001fffff,
165		.features	= PHY_GBIT_FEATURES,
166		.flags		= PHY_HAS_INTERRUPT,
167		.config_aneg	= &genphy_config_aneg,
168		.config_init	= &rtl8211f_config_init,
169		.read_status	= &genphy_read_status,
170		.ack_interrupt	= &rtl8211f_ack_interrupt,
171		.config_intr	= &rtl8211f_config_intr,
172		.suspend	= genphy_suspend,
173		.resume		= genphy_resume,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174	},
175};
176
177module_phy_driver(realtek_drvs);
178
179static struct mdio_device_id __maybe_unused realtek_tbl[] = {
180	{ 0x001cc912, 0x001fffff },
181	{ 0x001cc914, 0x001fffff },
182	{ 0x001cc915, 0x001fffff },
183	{ 0x001cc916, 0x001fffff },
184	{ }
185};
186
187MODULE_DEVICE_TABLE(mdio, realtek_tbl);