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