blob: 339bb78bbc8902f0a197206ffa54f3f874cf980c [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001// 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#include <linux/delay.h>
hj.shaof72d6ff2025-06-10 04:34:26 -070015#include <linux/miscdevice.h>
16#include <linux/uaccess.h>
17#include <linux/gpio/consumer.h>
18#include <linux/of_gpio.h>
19//#LYNQ_MODFIY modify for task-1618 2025/6/10 start
20
21#define DEVICE_NAME "mdio_misc"
22
23struct rtl9000bf_mdio_dev {
24 struct phy_device *phydev;
25 struct mutex lock;
26 int rst_gpio;
hj.shaofb3ba9b2025-06-19 02:53:56 -070027 //#LYNQ_MODFIY modify for task-1618 2025/6/19 start
28 int power_gpio;
29 //#LYNQ_MODFIY modify for task-1618 2025/6/19 end
hj.shaof72d6ff2025-06-10 04:34:26 -070030};
31struct mdio_reg_op {
32 uint32_t reg;
33 uint32_t val;
34};
35static struct rtl9000bf_mdio_dev *s_rtl9000bf_mdio_dev;
36static u16 param_check[27] = {0, 0x8017, 0xFB03, 0, 0x8092, 0x6000, 0, 0x80AF, 0x6000, \
37 0, 0x807D, 0x4443, 0, 0x809A, 0x4443, \
38 0, 0x81A3, 0x0F00, 0x0A81, 0x12, 0x0004, 0, \
39 0x83C8, 0x0005, 0x0A5C, 0x12, 0x0003};
40
41static u16 param_check2[5] = {0x401C, 0xA610, 0x8520, 0xA510, 0x21F4};
42static u16 param_check3[3] = {0, 0xA000, 0x11EF};
43
44#define RTL9000BF_INIT_TIMES_OUT 10
45#define RTL9000BF_ACCESS_TIMES_OUT 10
46//#LYNQ_MODFIY modify for task-1618 2025/6/10 end
b.liue9582032025-04-17 19:18:16 +080047
48#define RTL821x_PHYSR 0x11
49#define RTL821x_PHYSR_DUPLEX BIT(13)
50#define RTL821x_PHYSR_SPEED GENMASK(15, 14)
51
52#define RTL821x_INER 0x12
53#define RTL8211B_INER_INIT 0x6400
54#define RTL8211E_INER_LINK_STATUS BIT(10)
55#define RTL8211F_INER_LINK_STATUS BIT(4)
56
57#define RTL821x_INSR 0x13
58
59#define RTL821x_EXT_PAGE_SELECT 0x1e
60#define RTL821x_PAGE_SELECT 0x1f
61
62#define RTL8211F_INSR 0x1d
63
64#define RTL8211F_TX_DELAY BIT(8)
65#define RTL8211E_TX_DELAY BIT(1)
66#define RTL8211E_RX_DELAY BIT(2)
67#define RTL8211E_MODE_MII_GMII BIT(3)
68
69#define RTL8201F_ISR 0x1e
70#define RTL8201F_IER 0x13
71
72#define RTL8366RB_POWER_SAVE 0x15
73#define RTL8366RB_POWER_SAVE_ON BIT(12)
74
75#define RTL_SUPPORTS_5000FULL BIT(14)
76#define RTL_SUPPORTS_2500FULL BIT(13)
77#define RTL_SUPPORTS_10000FULL BIT(0)
78#define RTL_ADV_2500FULL BIT(7)
79#define RTL_LPADV_10000FULL BIT(11)
80#define RTL_LPADV_5000FULL BIT(6)
81#define RTL_LPADV_2500FULL BIT(5)
82
83#define RTLGEN_SPEED_MASK 0x0630
84
85#define RTL_GENERIC_PHYID 0x001cc800
86
87MODULE_DESCRIPTION("Realtek PHY driver");
88MODULE_AUTHOR("Johnson Leung");
89MODULE_LICENSE("GPL");
90
91static int rtl821x_read_page(struct phy_device *phydev)
92{
93 return __phy_read(phydev, RTL821x_PAGE_SELECT);
94}
95
96static int rtl821x_write_page(struct phy_device *phydev, int page)
97{
98 return __phy_write(phydev, RTL821x_PAGE_SELECT, page);
99}
100
101static int rtl8201_ack_interrupt(struct phy_device *phydev)
102{
103 int err;
104
105 err = phy_read(phydev, RTL8201F_ISR);
106
107 return (err < 0) ? err : 0;
108}
109
110static int rtl821x_ack_interrupt(struct phy_device *phydev)
111{
112 int err;
113
114 err = phy_read(phydev, RTL821x_INSR);
115
116 return (err < 0) ? err : 0;
117}
118
119static int rtl8211f_ack_interrupt(struct phy_device *phydev)
120{
121 int err;
122
123 err = phy_read_paged(phydev, 0xa43, RTL8211F_INSR);
124
125 return (err < 0) ? err : 0;
126}
127
128static int rtl8201_config_intr(struct phy_device *phydev)
129{
130 u16 val;
131
132 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
133 val = BIT(13) | BIT(12) | BIT(11);
134 else
135 val = 0;
136
137 return phy_write_paged(phydev, 0x7, RTL8201F_IER, val);
138}
139
140static int rtl8211b_config_intr(struct phy_device *phydev)
141{
142 int err;
143
144 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
145 err = phy_write(phydev, RTL821x_INER,
146 RTL8211B_INER_INIT);
147 else
148 err = phy_write(phydev, RTL821x_INER, 0);
149
150 return err;
151}
152
153static int rtl8211e_config_intr(struct phy_device *phydev)
154{
155 int err;
156
157 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
158 err = phy_write(phydev, RTL821x_INER,
159 RTL8211E_INER_LINK_STATUS);
160 else
161 err = phy_write(phydev, RTL821x_INER, 0);
162
163 return err;
164}
165
166static int rtl8211f_config_intr(struct phy_device *phydev)
167{
168 u16 val;
169
170 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
171 val = RTL8211F_INER_LINK_STATUS;
172 else
173 val = 0;
174
175 return phy_write_paged(phydev, 0xa42, RTL821x_INER, val);
176}
177
178static int rtl8211_config_aneg(struct phy_device *phydev)
179{
180 int ret;
181
182 ret = genphy_config_aneg(phydev);
183 if (ret < 0)
184 return ret;
185
186 /* Quirk was copied from vendor driver. Unfortunately it includes no
187 * description of the magic numbers.
188 */
189 if (phydev->speed == SPEED_100 && phydev->autoneg == AUTONEG_DISABLE) {
190 phy_write(phydev, 0x17, 0x2138);
191 phy_write(phydev, 0x0e, 0x0260);
192 } else {
193 phy_write(phydev, 0x17, 0x2108);
194 phy_write(phydev, 0x0e, 0x0000);
195 }
196
197 return 0;
198}
199
200static int rtl8211c_config_init(struct phy_device *phydev)
201{
202 /* RTL8211C has an issue when operating in Gigabit slave mode */
203 return phy_set_bits(phydev, MII_CTRL1000,
204 CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER);
205}
206
207static int rtl8211f_config_init(struct phy_device *phydev)
208{
209 struct device *dev = &phydev->mdio.dev;
210 u16 val;
211 int ret;
212
213 /* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and
214 * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin.
215 */
216 switch (phydev->interface) {
217 case PHY_INTERFACE_MODE_RGMII:
218 case PHY_INTERFACE_MODE_RGMII_RXID:
219 val = 0;
220 break;
221 case PHY_INTERFACE_MODE_RGMII_ID:
222 case PHY_INTERFACE_MODE_RGMII_TXID:
223 val = RTL8211F_TX_DELAY;
224 break;
225 default: /* the rest of the modes imply leaving delay as is. */
226 return 0;
227 }
228
229 ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY,
230 val);
231 if (ret < 0) {
232 dev_err(dev, "Failed to update the TX delay register\n");
233 return ret;
234 } else if (ret) {
235 dev_dbg(dev,
236 "%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n",
237 val ? "Enabling" : "Disabling");
238 } else {
239 dev_dbg(dev,
240 "2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n",
241 val ? "enabled" : "disabled");
242 }
243
244 return 0;
245}
246
247static int rtl8211e_config_init(struct phy_device *phydev)
248{
249 int ret = 0, oldpage;
250 u16 val;
251
252 /* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
253 switch (phydev->interface) {
254 case PHY_INTERFACE_MODE_RGMII:
255 val = 0;
256 break;
257 case PHY_INTERFACE_MODE_RGMII_ID:
258 val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
259 break;
260 case PHY_INTERFACE_MODE_RGMII_RXID:
261 val = RTL8211E_RX_DELAY;
262 break;
263 case PHY_INTERFACE_MODE_RGMII_TXID:
264 val = RTL8211E_TX_DELAY;
265 break;
266 default: /* the rest of the modes imply leaving delays as is. */
267 return 0;
268 }
269
270 /* According to a sample driver there is a 0x1c config register on the
271 * 0xa4 extension page (0x7) layout. It can be used to disable/enable
272 * the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can
273 * also be used to customize the whole configuration register:
274 * 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select,
275 * 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
276 * for details).
277 */
278 oldpage = phy_select_page(phydev, 0x7);
279 if (oldpage < 0)
280 goto err_restore_page;
281
282 ret = __phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
283 if (ret)
284 goto err_restore_page;
285
286 ret = __phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
287 val);
288
289err_restore_page:
290 return phy_restore_page(phydev, oldpage, ret);
291}
292
293static int rtl8211b_suspend(struct phy_device *phydev)
294{
295 phy_write(phydev, MII_MMD_DATA, BIT(9));
296
297 return genphy_suspend(phydev);
298}
299
300static int rtl8211b_resume(struct phy_device *phydev)
301{
302 phy_write(phydev, MII_MMD_DATA, 0);
303
304 return genphy_resume(phydev);
305}
306
307static int rtl8366rb_config_init(struct phy_device *phydev)
308{
309 int ret;
310
311 ret = phy_set_bits(phydev, RTL8366RB_POWER_SAVE,
312 RTL8366RB_POWER_SAVE_ON);
313 if (ret) {
314 dev_err(&phydev->mdio.dev,
315 "error enabling power management\n");
316 }
317
318 return ret;
319}
320
321/* get actual speed to cover the downshift case */
322static int rtlgen_get_speed(struct phy_device *phydev)
323{
324 int val;
325
326 if (!phydev->link)
327 return 0;
328
329 val = phy_read_paged(phydev, 0xa43, 0x12);
330 if (val < 0)
331 return val;
332
333 switch (val & RTLGEN_SPEED_MASK) {
334 case 0x0000:
335 phydev->speed = SPEED_10;
336 break;
337 case 0x0010:
338 phydev->speed = SPEED_100;
339 break;
340 case 0x0020:
341 phydev->speed = SPEED_1000;
342 break;
343 case 0x0200:
344 phydev->speed = SPEED_10000;
345 break;
346 case 0x0210:
347 phydev->speed = SPEED_2500;
348 break;
349 case 0x0220:
350 phydev->speed = SPEED_5000;
351 break;
352 default:
353 break;
354 }
355
356 return 0;
357}
358
359static int rtlgen_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
360{
361 int ret;
362
363 if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE) {
364 rtl821x_write_page(phydev, 0xa5c);
365 ret = __phy_read(phydev, 0x12);
366 rtl821x_write_page(phydev, 0);
367 } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {
368 rtl821x_write_page(phydev, 0xa5d);
369 ret = __phy_read(phydev, 0x10);
370 rtl821x_write_page(phydev, 0);
371 } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE) {
372 rtl821x_write_page(phydev, 0xa5d);
373 ret = __phy_read(phydev, 0x11);
374 rtl821x_write_page(phydev, 0);
375 } else {
376 ret = -EOPNOTSUPP;
377 }
378
379 return ret;
380}
381
382static int rtlgen_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
383 u16 val)
384{
385 int ret;
386
387 if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV) {
388 rtl821x_write_page(phydev, 0xa5d);
389 ret = __phy_write(phydev, 0x10, val);
390 rtl821x_write_page(phydev, 0);
391 } else {
392 ret = -EOPNOTSUPP;
393 }
394
395 return ret;
396}
397
398static int rtl8125_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
399{
400 int ret = rtlgen_read_mmd(phydev, devnum, regnum);
401
402 if (ret != -EOPNOTSUPP)
403 return ret;
404
405 if (devnum == MDIO_MMD_PCS && regnum == MDIO_PCS_EEE_ABLE2) {
406 rtl821x_write_page(phydev, 0xa6e);
407 ret = __phy_read(phydev, 0x16);
408 rtl821x_write_page(phydev, 0);
409 } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) {
410 rtl821x_write_page(phydev, 0xa6d);
411 ret = __phy_read(phydev, 0x12);
412 rtl821x_write_page(phydev, 0);
413 } else if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_LPABLE2) {
414 rtl821x_write_page(phydev, 0xa6d);
415 ret = __phy_read(phydev, 0x10);
416 rtl821x_write_page(phydev, 0);
417 }
418
419 return ret;
420}
421
422static int rtl8125_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
423 u16 val)
424{
425 int ret = rtlgen_write_mmd(phydev, devnum, regnum, val);
426
427 if (ret != -EOPNOTSUPP)
428 return ret;
429
430 if (devnum == MDIO_MMD_AN && regnum == MDIO_AN_EEE_ADV2) {
431 rtl821x_write_page(phydev, 0xa6d);
432 ret = __phy_write(phydev, 0x12, val);
433 rtl821x_write_page(phydev, 0);
434 }
435
436 return ret;
437}
438
439static int rtl8125_get_features(struct phy_device *phydev)
440{
441 int val;
442
443 val = phy_read_paged(phydev, 0xa61, 0x13);
444 if (val < 0)
445 return val;
446
447 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
448 phydev->supported, val & RTL_SUPPORTS_2500FULL);
449 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
450 phydev->supported, val & RTL_SUPPORTS_5000FULL);
451 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
452 phydev->supported, val & RTL_SUPPORTS_10000FULL);
453
454 return genphy_read_abilities(phydev);
455}
456
457static int rtl8125_config_aneg(struct phy_device *phydev)
458{
459 int ret = 0;
460
461 if (phydev->autoneg == AUTONEG_ENABLE) {
462 u16 adv2500 = 0;
463
464 if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
465 phydev->advertising))
466 adv2500 = RTL_ADV_2500FULL;
467
468 ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12,
469 RTL_ADV_2500FULL, adv2500);
470 if (ret < 0)
471 return ret;
472 }
473
474 return __genphy_config_aneg(phydev, ret);
475}
476
477static int rtl8125_read_status(struct phy_device *phydev)
478{
479 if (phydev->autoneg == AUTONEG_ENABLE) {
480 int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
481
482 if (lpadv < 0)
483 return lpadv;
484
485 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
486 phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL);
487 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
488 phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL);
489 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
490 phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL);
491 }
492
493 return genphy_read_status(phydev);
494}
495
496static int rtl822x_config_init(struct phy_device *phydev)
497{
498 struct device *dev = &phydev->mdio.dev;
499 int ret;
500 int reg;
501
502 switch (phydev->interface) {
503 case PHY_INTERFACE_MODE_SGMII:
504 case PHY_INTERFACE_MODE_2500BASEX:
505 break;
506 default:
507 return 0;
508 }
509
510 /* set serdes mode */
511 reg = phy_read_mmd(phydev, 30, 0x697a);
512 dev_info(dev, "MMD30:0x697a = 0x%x\n", reg);
513
514 /* change to 2500Base-X + SGMII mode*/
515 phy_modify_mmd_changed(phydev, 30, 0x75F3, 0x1, 0);
516 ret = phy_modify_mmd_changed(phydev, 30, 0x697a, 0x1f, 0x0);
517 if (ret < 0) {
518 dev_err(dev, "Failed to update serdes option mode\n");
519 return ret;
520 } else if (ret) {
521 dev_info(dev, "serdes option mode set\n");
522
523 /* make changes take effect */
524 phy_modify_mmd_changed(phydev, 31, 0xA400, 0x1 << 14, 0x1 << 14);
525 do {
526 reg = phy_read_mmd(phydev, 31, 0xA434);
527 if (reg & (0x1 << 2))
528 break;
529 } while(1);
530 phy_modify_mmd_changed(phydev, 31, 0xA400, 0x1 << 14, 0);
531
532 } else {
533 dev_info(dev, "serdes option mode already set\n");
534 }
535
536 /* disabled hisgmii auto-negotiation */
537 phy_write_mmd(phydev, 30, 0x7588, 0x2);
538 phy_write_mmd(phydev, 30, 0x7589, 0x71d0);
539 phy_write_mmd(phydev, 30, 0x7587, 0x3);
540
541 dev_info(dev, "start to wait disable hisgmii AN finish\n");
542 do {
543 reg = phy_read_mmd(phydev, 30, 0x7587);
544 if ((reg & 0x1) == 0)
545 break;
546 } while(1);
547
548 return 0;
549}
550
551static int rtl822x_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
552{
553 int ret;
554
555 if (devnum == MDIO_MMD_VEND2) {
556 int page, regad;
557
558 page = regnum >> 4;
559 regad = 16 + (regnum % 16) / 2;
560
561 rtl821x_write_page(phydev, page);
562 ret = __phy_read(phydev, regad);
563 rtl821x_write_page(phydev, 0);
564 } else {
565 /* Write the desired MMD Devad */
566 __phy_write(phydev, MII_MMD_CTRL, devnum);
567 /* Write the desired MMD register address */
568 __phy_write(phydev, MII_MMD_DATA, regnum);
569 /* Select the Function : DATA with no post increment */
570 __phy_write(phydev, MII_MMD_CTRL, devnum | MII_MMD_CTRL_NOINCR);
571 /* Read the content of the MMD's selected register */
572 ret = __phy_read(phydev, MII_MMD_DATA);
573 }
574
575 return ret;
576}
577
578static int rtl822x_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
579 u16 val)
580{
581 int ret;
582
583 if (devnum == MDIO_MMD_VEND2) {
584 int page, regad;
585
586 page = regnum >> 4;
587 regad = 16 + (regnum % 16) / 2;
588
589 rtl821x_write_page(phydev, page);
590 ret = __phy_write(phydev, regad, val);
591 rtl821x_write_page(phydev, 0);
592 } else {
593 /* Write the desired MMD Devad */
594 __phy_write(phydev, MII_MMD_CTRL, devnum);
595 /* Write the desired MMD register address */
596 __phy_write(phydev, MII_MMD_DATA, regnum);
597 /* Select the Function : DATA with no post increment */
598 __phy_write(phydev, MII_MMD_CTRL, devnum | MII_MMD_CTRL_NOINCR);
599 /* Write the data into MMD's selected register */
600 ret = __phy_write(phydev, MII_MMD_DATA, val);
601 }
602
603 return ret;
604}
605
606static int rtl822x_get_features(struct phy_device *phydev)
607{
608 int val;
609
610 val = phy_read_paged(phydev, 0xa61, 0x13);
611 if (val < 0)
612 return val;
613
614 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
615 phydev->supported, val & RTL_SUPPORTS_2500FULL);
616 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
617 phydev->supported, val & RTL_SUPPORTS_5000FULL);
618 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
619 phydev->supported, val & RTL_SUPPORTS_10000FULL);
620
621 return genphy_read_abilities(phydev);
622}
623
624static int rtl822x_config_aneg(struct phy_device *phydev)
625{
626 int ret = 0;
627
628 if (phydev->autoneg == AUTONEG_ENABLE) {
629 u16 adv2500 = 0;
630
631 if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
632 phydev->advertising))
633 adv2500 = RTL_ADV_2500FULL;
634
635 ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12,
636 RTL_ADV_2500FULL, adv2500);
637 if (ret < 0)
638 return ret;
639 }
640
641 return __genphy_config_aneg(phydev, ret);
642}
643
644static int rtlgen_get_serdes_mode(struct phy_device *phydev)
645{
646 struct device *dev = &phydev->mdio.dev;
647 int ret;
648
649 ret = phy_read_mmd(phydev, 30, 0x7580);
650 if (ret < 0)
651 return ret;
652
653 switch (ret & 0x1f) {
654 case 0x2:
655 phydev->interface = PHY_INTERFACE_MODE_SGMII;
656 dev_dbg(dev, "==> Serdes mode: SGMII\n");
657 break;
658 case 0x12:
659 phydev->interface = PHY_INTERFACE_MODE_NA;
660 dev_dbg(dev, "==> Serdes mode: HiSGMII\n");
661 break;
662 case 0x16:
663 phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
664 dev_dbg(dev, "==> Serdes mode: 2500BASE-X\n");
665 break;
666 case 0x1f:
667 dev_dbg(dev, "==> Serdes mode: off\n");
668 break;
669 default:
670 break;
671 }
672
673 return 0;
674}
675
676static int rtl822x_read_status(struct phy_device *phydev)
677{
678 int ret;
679
680 if (phydev->autoneg == AUTONEG_ENABLE) {
681 int lpadv = phy_read_paged(phydev, 0xa5d, 0x13);
682
683 if (lpadv < 0)
684 return lpadv;
685
686 linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
687 phydev->lp_advertising, lpadv & RTL_LPADV_10000FULL);
688 linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
689 phydev->lp_advertising, lpadv & RTL_LPADV_5000FULL);
690 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
691 phydev->lp_advertising, lpadv & RTL_LPADV_2500FULL);
692 }
693
694 ret = genphy_read_status(phydev);
695 if (ret < 0)
696 return ret;
697
698 ret = rtlgen_get_serdes_mode(phydev);
699 if (ret < 0)
700 return ret;
701
702 return rtlgen_get_speed(phydev);
703}
704
705static bool rtlgen_supports_2_5gbps(struct phy_device *phydev)
706{
707 int val;
708
709 phy_write(phydev, RTL821x_PAGE_SELECT, 0xa61);
710 val = phy_read(phydev, 0x13);
711 phy_write(phydev, RTL821x_PAGE_SELECT, 0);
712
713 return val >= 0 && val & RTL_SUPPORTS_2500FULL;
714}
715
716static int rtlgen_match_phy_device(struct phy_device *phydev)
717{
718 return phydev->phy_id == RTL_GENERIC_PHYID &&
719 !rtlgen_supports_2_5gbps(phydev);
720}
721
722static int rtl8125_match_phy_device(struct phy_device *phydev)
723{
724 return phydev->phy_id == RTL_GENERIC_PHYID &&
725 rtlgen_supports_2_5gbps(phydev);
726}
727
728static int rtlgen_resume(struct phy_device *phydev)
729{
730 int ret = genphy_resume(phydev);
731
732 /* Internal PHY's from RTL8168h up may not be instantly ready */
733 msleep(20);
734
735 return ret;
736}
hj.shaof72d6ff2025-06-10 04:34:26 -0700737//#LYNQ_MODFIY modify for task-1618 2025/6/10 start
738
739static int mdio_misc_open(struct inode *inode, struct file *file)
740{
741 return 0;
742}
743
744static ssize_t mdio_misc_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
745{
746 struct rtl9000bf_mdio_dev *dev = s_rtl9000bf_mdio_dev;
747 struct mdio_reg_op reg_op;
748
749 if (count < sizeof(struct mdio_reg_op))
750 return -EINVAL;
751
752 if (copy_from_user(&reg_op, buf, sizeof(struct mdio_reg_op)))
753 return -EFAULT;
754
755
756 mutex_lock(&dev->lock);
hj.shao5586c8f2025-06-26 00:41:40 -0700757 reg_op.val = phy_read(dev->phydev, reg_op.reg);
hj.shaof72d6ff2025-06-10 04:34:26 -0700758 mutex_unlock(&dev->lock);
759
760 if (copy_to_user(buf, &reg_op, sizeof(struct mdio_reg_op)))
761 return -EFAULT;
762
763 return sizeof(reg_op);
764}
765
766static ssize_t mdio_misc_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
767{
768 struct rtl9000bf_mdio_dev *dev = s_rtl9000bf_mdio_dev;
769 struct mdio_reg_op reg_op;
770 int ret;
771
772 if (count < sizeof(struct mdio_reg_op))
773 return -EINVAL;
774
775 if (copy_from_user(&reg_op, buf, sizeof(struct mdio_reg_op)))
776 return -EFAULT;
777
778
779 mutex_lock(&dev->lock);
hj.shao5586c8f2025-06-26 00:41:40 -0700780 ret = phy_write(dev->phydev, reg_op.reg, reg_op.val);
hj.shaof72d6ff2025-06-10 04:34:26 -0700781 mutex_unlock(&dev->lock);
782
783 *f_pos += count;
784 return ret ? ret : count;
785
786}
787
788static const struct file_operations mdio_misc_fops = {
789 .owner = THIS_MODULE,
790 .open = mdio_misc_open,
791 .read = mdio_misc_read,
792 .write = mdio_misc_write,
793};
794
795static struct miscdevice mdio_misc_device = {
796 .minor = MISC_DYNAMIC_MINOR,
797 .name = DEVICE_NAME,
798 .fops = &mdio_misc_fops,
799};
800
801static int mdio_misc_init(struct phy_device *phydev)
802{
803 s_rtl9000bf_mdio_dev->phydev = phydev;
804 mutex_init(&s_rtl9000bf_mdio_dev->lock);
805 return misc_register(&mdio_misc_device);
806}
807
808static s16 RTL9000Bx_Initial_Configuration(struct phy_device *phydev)
809{
810 u16 reg_data = 0;
811 u32 timer = 2000; // set a 2ms timer
812
813 //power down
hj.shao5586c8f2025-06-26 00:41:40 -0700814 phy_write(phydev, 0, 0x800);
hj.shaof72d6ff2025-06-10 04:34:26 -0700815 mdelay(10);
816
hj.shao5586c8f2025-06-26 00:41:40 -0700817 phy_write(phydev, 27, 0x8017);
818 phy_write(phydev, 28, 0xFB03);
819 phy_write(phydev, 27, 0x8092);
820 phy_write(phydev, 28, 0x6000);
821 phy_write(phydev, 27, 0x80AF);
822 phy_write(phydev, 28, 0x6000);
823 phy_write(phydev, 27, 0x807D);
824 phy_write(phydev, 28, 0x4443);
825 phy_write(phydev, 27, 0x809A);
826 phy_write(phydev, 28, 0x4443);
827 phy_write(phydev, 27, 0x81A3);
828 phy_write(phydev, 28, 0x0F00);
829 phy_write(phydev, 31, 0x0a81);
830 phy_write(phydev, 18, 0x0004);
831 phy_write(phydev, 27, 0x83c8);
832 phy_write(phydev, 28, 0x0005);
833 phy_write(phydev, 31, 0x0a5c);
834 phy_write(phydev, 18, 0x0003);
835 phy_write(phydev, 27, 0xB820);
836 phy_write(phydev, 28, 0x0010);
837 phy_write(phydev, 27, 0xB830);
838 phy_write(phydev, 28, 0x8000);
hj.shaof72d6ff2025-06-10 04:34:26 -0700839
hj.shao5586c8f2025-06-26 00:41:40 -0700840 phy_write(phydev, 27, 0xB800);
hj.shaof72d6ff2025-06-10 04:34:26 -0700841 do {
hj.shao5586c8f2025-06-26 00:41:40 -0700842 reg_data = ((u16)phy_read(phydev, 28) & 0x0040);
hj.shaof72d6ff2025-06-10 04:34:26 -0700843 timer--;
844 if (timer == 0)
845 {
846 return -1;
847 }
848 } while (reg_data != 0x0040);
849
hj.shao5586c8f2025-06-26 00:41:40 -0700850 phy_write(phydev, 27, 0x8020);
851 phy_write(phydev, 28, 0x3300);
852 phy_write(phydev, 27, 0xb82e);
853 phy_write(phydev, 28, 0x0001);
854 phy_write(phydev, 27, 0xb820);
855 phy_write(phydev, 28, 0x0290);
856 phy_write(phydev, 27, 0xa012);
857 phy_write(phydev, 28, 0x0000);
858 phy_write(phydev, 27, 0xa014);
859 phy_write(phydev, 28, 0x401c);
860 phy_write(phydev, 28, 0xa610);
861 phy_write(phydev, 28, 0x8520);
862 phy_write(phydev, 28, 0xa510);
863 phy_write(phydev, 28, 0x21f4);
864 phy_write(phydev, 27, 0xa01a);
865 phy_write(phydev, 28, 0x0000);
866 phy_write(phydev, 27, 0xa000);
867 phy_write(phydev, 28, 0x11ef);
868 phy_write(phydev, 27, 0xb820);
869 phy_write(phydev, 28, 0x0210);
870 phy_write(phydev, 27, 0xb82e);
871 phy_write(phydev, 28, 0x0000);
872 phy_write(phydev, 27, 0x8020);
873 phy_write(phydev, 28, 0x0000);
874 phy_write(phydev, 27, 0xb820);
875 phy_write(phydev, 28, 0x0000);
hj.shaof72d6ff2025-06-10 04:34:26 -0700876
hj.shao5586c8f2025-06-26 00:41:40 -0700877 phy_write(phydev, 27, 0xb800);
hj.shaof72d6ff2025-06-10 04:34:26 -0700878 timer = 2000; // set a 2ms timer
879 do {
hj.shao5586c8f2025-06-26 00:41:40 -0700880 reg_data = ((u16)phy_read(phydev, 28) & 0x0040);
hj.shaof72d6ff2025-06-10 04:34:26 -0700881 timer--;
882 if (timer == 0) {
883 return -1;
884 }
885 } while (reg_data != 0x0000);
886
hj.shao5586c8f2025-06-26 00:41:40 -0700887 phy_write(phydev, 0, 0x2100); //power on
888 phy_write(phydev, 9, 0x0); //set slave mode
hj.shaof72d6ff2025-06-10 04:34:26 -0700889 return 0;
890}
891
892static s16 RTL9000Bx_Initial_Configuration_Check(struct phy_device *phydev)
893{
894 u16 reg_data = 0, reg_data_temp;
895 u16 reg_data_chk = 0;
896 u32 timer = 2000; // set a 2ms timer
897
898 u16 page;
899 u16 reg, i, param_address;
900
901 for (i = 0; i < 27; i = i + 3) {
902 page = param_check[i];
903 reg = param_check[i + 1];
904 reg_data_chk = param_check[i + 2];
905
906 if (page == 0) {
hj.shao5586c8f2025-06-26 00:41:40 -0700907 phy_write(phydev, 27, reg);
908 reg_data = phy_read(phydev, 28);
hj.shaof72d6ff2025-06-10 04:34:26 -0700909 }
910 else {
hj.shao5586c8f2025-06-26 00:41:40 -0700911 phy_write(phydev, 31, page);
912 reg_data = phy_read(phydev, reg);
hj.shaof72d6ff2025-06-10 04:34:26 -0700913 }
914 if (reg_data_chk != reg_data) {
915 printk(KERN_ERR "%dth param error page=0x%04X reg=0x%04X data=0x%04X\r\n", i / 3, page, reg, reg_data);
916 return -1;
917 }
918 }
919
hj.shao5586c8f2025-06-26 00:41:40 -0700920 phy_write(phydev, 27, 0xB820);
921 phy_write(phydev, 28, 0x0010);
922 phy_write(phydev, 27, 0xB830);
923 phy_write(phydev, 28, 0x8000);
hj.shaof72d6ff2025-06-10 04:34:26 -0700924
hj.shao5586c8f2025-06-26 00:41:40 -0700925 phy_write(phydev, 27, 0xB800);
hj.shaof72d6ff2025-06-10 04:34:26 -0700926 do {
hj.shao5586c8f2025-06-26 00:41:40 -0700927 reg_data = ((u16)phy_read(phydev, 28) & 0x0040);
hj.shaof72d6ff2025-06-10 04:34:26 -0700928 timer--;
929 if (timer == 0){
930 return -1;
931 }
932 } while (reg_data != 0x0040);
933
hj.shao5586c8f2025-06-26 00:41:40 -0700934 phy_write(phydev, 27, 0x8020);
935 phy_write(phydev, 28, 0x3300);
936 phy_write(phydev, 27, 0xB82E);
937 phy_write(phydev, 28, 0x0001);
hj.shaof72d6ff2025-06-10 04:34:26 -0700938
939 param_address = 0;
940 for (i = 0; i < 5; i++) {
hj.shao5586c8f2025-06-26 00:41:40 -0700941 phy_write(phydev, 31, 0xA01);
942 reg_data_temp = phy_read(phydev, 17);
hj.shaof72d6ff2025-06-10 04:34:26 -0700943 reg_data_temp &= ~(0x1ff);
944 param_address &= 0x1FF;
hj.shao5586c8f2025-06-26 00:41:40 -0700945 phy_write(phydev, 17, (reg_data_temp | param_address));
946 phy_write(phydev, 31, 0xA01);
947 reg_data = phy_read(phydev, 18);
hj.shaof72d6ff2025-06-10 04:34:26 -0700948 reg_data_chk = param_check2[i];
949 if (reg_data_chk != reg_data){
950 printk(KERN_ERR "%dth param error data=0x%04X expected_data=0x%04X\r\n", i, reg_data, reg_data_chk);
951 return -1;
952 }
953 param_address++;
954 }
955 for (i = 0; i < 3; i = i + 3) {
956 page = param_check3[i];
957 reg = param_check3[i + 1];
958 reg_data_chk = param_check3[i + 2];
959
960 if (page == 0) {
hj.shao5586c8f2025-06-26 00:41:40 -0700961 phy_write(phydev, 27, reg);
962 reg_data = phy_read(phydev, 28);
hj.shaof72d6ff2025-06-10 04:34:26 -0700963 }
964 else {
hj.shao5586c8f2025-06-26 00:41:40 -0700965 phy_write(phydev, 31, page);
966 reg_data = phy_read(phydev, reg);
hj.shaof72d6ff2025-06-10 04:34:26 -0700967 }
968 if (reg_data_chk != reg_data) {
969 printk(KERN_ERR "%dth param error page=0x%04X reg=0x%04X data=0x%04X\r\n", i / 3, page, reg, reg_data);
970 return -1;
971 }
972 }
hj.shao5586c8f2025-06-26 00:41:40 -0700973 phy_write(phydev, 27, 0xB82E);
974 phy_write(phydev, 28, 0x0000);
975 phy_write(phydev, 27, 0x8020);
976 phy_write(phydev, 28, 0x0000);
977 phy_write(phydev, 27, 0xB820);
978 phy_write(phydev, 28, 0x0000);
hj.shaof72d6ff2025-06-10 04:34:26 -0700979
hj.shao5586c8f2025-06-26 00:41:40 -0700980 phy_write(phydev, 27, 0xB800);
hj.shaof72d6ff2025-06-10 04:34:26 -0700981 timer = 2000; // set a 2ms timer
982 do {
hj.shao5586c8f2025-06-26 00:41:40 -0700983 reg_data = ((u16)phy_read(phydev, 28) & 0x0040);
hj.shaof72d6ff2025-06-10 04:34:26 -0700984 timer--;
985 if (timer == 0){
986 return -1;
987 }
988 } while (reg_data != 0x0000);
989
990 return 0;
991}
hj.shao49e0d262025-07-07 03:21:43 -0700992//#LYNQ_MODFIY modify for task-1618 2025/7/7 start
993static void RTL9000Bx_xMII_driving_strength(struct phy_device *phydev)
994{
b.liue9582032025-04-17 19:18:16 +0800995
hj.shao49e0d262025-07-07 03:21:43 -0700996 // Typical_xMII_1V8
997 phy_write(phydev, 0x1B, 0xD414);
998 phy_write(phydev, 0x1C, 0x0201);
999
1000 phy_write(phydev, 0x1B, 0xD416);
1001 phy_write(phydev, 0x1C, 0x0101);
1002
1003 phy_write(phydev, 0x1B, 0xD418);
1004 phy_write(phydev, 0x1C, 0x0200);
1005
1006 phy_write(phydev, 0x1B, 0xD41A);
1007 phy_write(phydev, 0x1C, 0x0100);
1008
1009 phy_write(phydev, 0x1B, 0xD42E);
1010 phy_write(phydev, 0x1C, 0xC8C8);
1011
1012}
1013
1014static s16 RTL9000Bx_Soft_Reset(struct phy_device *phydev)
1015{
1016 u16 reg_data = 0;
1017 u32 timer = 2000; // set a 2ms timer
1018
1019 phy_write(phydev, 0, 0x8000); // PHY soft-reset
1020
1021 do
1022 { // Check soft-reset complete
1023
1024 reg_data = phy_read(phydev, 0);
1025 if (reg_data == 0xFFFF)
1026 return -1;
1027 timer--;
1028 if (timer == 0)
1029 {
1030 return -1;
1031 }
1032 } while (reg_data != 0x2100);
1033
1034 return 0;
1035}
1036//#LYNQ_MODFIY modify for task-1618 2025/7/7 end
hj.shaofb3ba9b2025-06-19 02:53:56 -07001037//#LYNQ_MODFIY modify for task-1618 2025/6/19 satrt
1038static int rtl9000Bf_power_set(int gpio, int power_en)
1039{
1040 int ret;
1041 ret = gpio_direction_output(gpio, power_en);
hj.shao5586c8f2025-06-26 00:41:40 -07001042 mdelay(10);
hj.shaofb3ba9b2025-06-19 02:53:56 -07001043 return ret;
1044}
1045
1046static void rtl9000Bf_reset(int gpio)
1047{
hj.shao213a35e2025-06-24 04:25:54 -07001048 //#LYNQ_MODFIY modify for task-1618 2025/6/24 start
hj.shaofb3ba9b2025-06-19 02:53:56 -07001049 gpio_direction_output(gpio, 0);
hj.shao213a35e2025-06-24 04:25:54 -07001050 mdelay(10);
hj.shaofb3ba9b2025-06-19 02:53:56 -07001051 gpio_set_value(gpio, 1);
hj.shao213a35e2025-06-24 04:25:54 -07001052 mdelay(10);
1053 //#LYNQ_MODFIY modify for task-1618 2025/6/24 end
hj.shaofb3ba9b2025-06-19 02:53:56 -07001054}
1055
hj.shaofe1632a2025-06-05 00:19:33 -07001056static int rtl9000Bf_config_init(struct phy_device *phydev)
1057{
hj.shaofe1632a2025-06-05 00:19:33 -07001058 u32 mdio_data = 0;
hj.shaof72d6ff2025-06-10 04:34:26 -07001059 u32 ret;
1060 int times= 1;
1061 struct device_node *np;
1062
1063 np = phydev->mdio.dev.of_node;
1064 if (!np) {
1065 dev_err(&phydev->mdio.dev, "No device tree node found\n");
1066 return -ENODEV;
1067 }
1068
1069 if (!s_rtl9000bf_mdio_dev) {
1070 s_rtl9000bf_mdio_dev = kzalloc(sizeof(*s_rtl9000bf_mdio_dev), GFP_KERNEL);
1071 if (!s_rtl9000bf_mdio_dev)
1072 return -ENOMEM;
hj.shaofe1632a2025-06-05 00:19:33 -07001073
hj.shaof72d6ff2025-06-10 04:34:26 -07001074 s_rtl9000bf_mdio_dev->rst_gpio = of_get_named_gpio(np, "rst-gpio", 0);
1075 if (s_rtl9000bf_mdio_dev->rst_gpio < 0) {
1076 dev_err(&phydev->mdio.dev, "Failed to get reset gpio: %d\n", s_rtl9000bf_mdio_dev->rst_gpio);
1077 kfree(s_rtl9000bf_mdio_dev);
1078 s_rtl9000bf_mdio_dev = NULL;
1079 return s_rtl9000bf_mdio_dev->rst_gpio;
hj.shaofe1632a2025-06-05 00:19:33 -07001080 }
hj.shaofb3ba9b2025-06-19 02:53:56 -07001081 gpio_request(s_rtl9000bf_mdio_dev->rst_gpio, "phy-reset");
1082
1083 s_rtl9000bf_mdio_dev->power_gpio = of_get_named_gpio(np, "power-en-gpio", 0);
1084 if (s_rtl9000bf_mdio_dev->power_gpio < 0) {
1085 dev_err(&phydev->mdio.dev, "Failed to get power gpio: %d\n", s_rtl9000bf_mdio_dev->power_gpio);
1086 kfree(s_rtl9000bf_mdio_dev);
1087 s_rtl9000bf_mdio_dev = NULL;
1088 return s_rtl9000bf_mdio_dev->power_gpio;
1089 }
hj.shaof72d6ff2025-06-10 04:34:26 -07001090 ret = mdio_misc_init(phydev);
1091 if(ret){
1092 goto err;
hj.shaofe1632a2025-06-05 00:19:33 -07001093 }
hj.shaofb3ba9b2025-06-19 02:53:56 -07001094 gpio_request(s_rtl9000bf_mdio_dev->power_gpio, "phy-power");
hj.shaof72d6ff2025-06-10 04:34:26 -07001095 }
1096
hj.shaofb3ba9b2025-06-19 02:53:56 -07001097 rtl9000Bf_power_set(s_rtl9000bf_mdio_dev->power_gpio, 1);
1098 rtl9000Bf_reset(s_rtl9000bf_mdio_dev->rst_gpio);
hj.shaofe1632a2025-06-05 00:19:33 -07001099
hj.shaof72d6ff2025-06-10 04:34:26 -07001100 //check PHY accessible
1101 while(times <= RTL9000BF_ACCESS_TIMES_OUT) {
1102 mdio_data = phy_read(phydev, 0x10);
1103 mdio_data = mdio_data & 0x0007;
1104 if(mdio_data == 0x0003) {
1105 printk(KERN_INFO "phy_info: phy is accessible \n");
1106 break;
1107 } else {
1108 printk(KERN_INFO "phy_info: phy is not accessible times:%d \n", times);
hj.shaofb3ba9b2025-06-19 02:53:56 -07001109 rtl9000Bf_reset(s_rtl9000bf_mdio_dev->rst_gpio);
hj.shaof72d6ff2025-06-10 04:34:26 -07001110 }
1111 times++;
1112 mdelay(1000);
1113 }
1114
1115 if(times >= RTL9000BF_ACCESS_TIMES_OUT) {
1116 printk(KERN_ERR "phy_info: phy init error times:%d \n", times);
1117 ret = -1;
1118 goto err;
1119 }
1120
1121 times = 1;
1122
1123 //init phy init and check phy init
1124 while(times <= RTL9000BF_INIT_TIMES_OUT) {
1125 ret = RTL9000Bx_Initial_Configuration(phydev);
1126 if(0 == ret) {
1127 printk(KERN_INFO "phy_info: phy init success times:%d \n", times);
1128 ret = RTL9000Bx_Initial_Configuration_Check(phydev);
1129 if(0 == ret) {
1130 printk(KERN_INFO "phy_info: phy init_check success times:%d \n", times);
1131 break;
1132 } else {
1133 printk(KERN_INFO "phy_info: phy init_check error times:%d \n", times);
1134 }
1135 } else {
1136 printk(KERN_INFO "phy_info: phy init error times:%d \n", times);
1137 //phy hard reset
hj.shaofb3ba9b2025-06-19 02:53:56 -07001138 rtl9000Bf_reset(s_rtl9000bf_mdio_dev->rst_gpio);
1139
hj.shaof72d6ff2025-06-10 04:34:26 -07001140 }
1141 times++;
1142 }
1143
1144 if(times >= RTL9000BF_INIT_TIMES_OUT) {
1145 printk(KERN_ERR "phy_info: phy init error times:%d \n", times);
1146 ret = -1;
1147 goto err;
1148 }
hj.shao49e0d262025-07-07 03:21:43 -07001149 //#LYNQ_MODFIY modify for task-1618 2025/7/7 start
1150 RTL9000Bx_xMII_driving_strength(phydev);
hj.shaof72d6ff2025-06-10 04:34:26 -07001151
hj.shaofe1632a2025-06-05 00:19:33 -07001152 /* I/O Power Sllection */
hj.shaof72d6ff2025-06-10 04:34:26 -07001153 //change page to default value
hj.shao5586c8f2025-06-26 00:41:40 -07001154 phy_write(phydev, 0x1F, 0x0A4C);
1155 mdio_data = phy_read(phydev, 0x12);
hj.shaofe1632a2025-06-05 00:19:33 -07001156 mdio_data &= 0xC7FF;
1157 mdio_data |= 4 << 11;
hj.shao5586c8f2025-06-26 00:41:40 -07001158 phy_write(phydev, 0x12, mdio_data);
hj.shaof72d6ff2025-06-10 04:34:26 -07001159 printk(KERN_INFO "phy_info: set rgmii driving strengths is 1.8v \n");
hj.shaofe1632a2025-06-05 00:19:33 -07001160
hj.shao49e0d262025-07-07 03:21:43 -07001161 ret = RTL9000Bx_Soft_Reset(phydev);
1162 if(0 != ret) {
1163 goto err;
1164 }
1165 printk(KERN_INFO "phy_info: phy soft-reset over \n");
1166 //#LYNQ_MODFIY modify for task-1618 2025/7/7 end
hj.shaofe1632a2025-06-05 00:19:33 -07001167 phydev->autoneg = AUTONEG_DISABLE;
1168 phydev->duplex = DUPLEX_FULL;
1169
hj.shaofe1632a2025-06-05 00:19:33 -07001170 return 0;
hj.shaof72d6ff2025-06-10 04:34:26 -07001171
1172err:
1173 gpio_free(s_rtl9000bf_mdio_dev->rst_gpio);
hj.shaofb3ba9b2025-06-19 02:53:56 -07001174 gpio_free(s_rtl9000bf_mdio_dev->power_gpio);
1175 kfree(s_rtl9000bf_mdio_dev);
hj.shaof72d6ff2025-06-10 04:34:26 -07001176 s_rtl9000bf_mdio_dev = NULL;
1177 return ret;
1178}
hj.shaofb3ba9b2025-06-19 02:53:56 -07001179//#LYNQ_MODFIY modify for task-1618 2025/6/19 end
hj.shaof72d6ff2025-06-10 04:34:26 -07001180
1181static void rtl9000Bf_remove(struct phy_device *phydev)
1182{
1183 if (s_rtl9000bf_mdio_dev && s_rtl9000bf_mdio_dev->phydev == phydev) {
1184 misc_deregister(&mdio_misc_device);
1185 gpio_free(s_rtl9000bf_mdio_dev->rst_gpio);
hj.shaofb3ba9b2025-06-19 02:53:56 -07001186 //#LYNQ_MODFIY modify for task-1618 2025/6/19 start
1187 gpio_free(s_rtl9000bf_mdio_dev->power_gpio);
1188 //#LYNQ_MODFIY modify for task-1618 2025/6/19 end
hj.shaof72d6ff2025-06-10 04:34:26 -07001189 kfree(s_rtl9000bf_mdio_dev);
1190 s_rtl9000bf_mdio_dev = NULL;
1191 }
1192
hj.shaofe1632a2025-06-05 00:19:33 -07001193}
1194
1195static int rtl9000Bf_read_status(struct phy_device *phydev)
1196{
hj.shaofe1632a2025-06-05 00:19:33 -07001197 phydev->duplex = DUPLEX_FULL;
1198 phydev->speed = SPEED_100;
1199 phydev->pause = 0;
1200 phydev->asym_pause = 0;
1201 phydev->link = 1;
1202
1203 return 0;
1204}
hj.shaof72d6ff2025-06-10 04:34:26 -07001205static int rtl9000Bf_soft_reset(struct phy_device *phydev)
1206{
1207 return 0;
1208}
1209
1210//#LYNQ_MODFIY modify for task-1618 2025/6/10 end
hj.shaofe1632a2025-06-05 00:19:33 -07001211
hj.shao213a35e2025-06-24 04:25:54 -07001212//#LYNQ_MODFIY modify for task-1618 2025/6/24 start
hj.shaofb3ba9b2025-06-19 02:53:56 -07001213static int rtl9000Bf_suspend(struct phy_device *phydev)
1214{
hj.shao213a35e2025-06-24 04:25:54 -07001215 int ret;
1216 ret = gpio_direction_output(s_rtl9000bf_mdio_dev->rst_gpio, 0);
1217 if(ret != 0){
1218 printk(KERN_ERR "phy_error:reset phy error\n");
1219 return ret;
1220 }
1221 mdelay(10);
hj.shaofb3ba9b2025-06-19 02:53:56 -07001222 return gpio_direction_output(s_rtl9000bf_mdio_dev->power_gpio, 0);
hj.shao213a35e2025-06-24 04:25:54 -07001223
hj.shaofb3ba9b2025-06-19 02:53:56 -07001224}
hj.shao213a35e2025-06-24 04:25:54 -07001225//#LYNQ_MODFIY modify for task-1618 2025/6/24 end
hj.shaofb3ba9b2025-06-19 02:53:56 -07001226
1227
b.liue9582032025-04-17 19:18:16 +08001228static struct phy_driver realtek_drvs[] = {
1229 {
1230 PHY_ID_MATCH_EXACT(0x00008201),
1231 .name = "RTL8201CP Ethernet",
1232 }, {
1233 PHY_ID_MATCH_EXACT(0x001cc816),
1234 .name = "RTL8201F Fast Ethernet",
1235 .ack_interrupt = &rtl8201_ack_interrupt,
1236 .config_intr = &rtl8201_config_intr,
1237 .suspend = genphy_suspend,
1238 .resume = genphy_resume,
1239 .read_page = rtl821x_read_page,
1240 .write_page = rtl821x_write_page,
1241 }, {
1242 PHY_ID_MATCH_MODEL(0x001cc880),
1243 .name = "RTL8208 Fast Ethernet",
1244 .read_mmd = genphy_read_mmd_unsupported,
1245 .write_mmd = genphy_write_mmd_unsupported,
1246 .suspend = genphy_suspend,
1247 .resume = genphy_resume,
1248 .read_page = rtl821x_read_page,
1249 .write_page = rtl821x_write_page,
1250 }, {
1251 PHY_ID_MATCH_EXACT(0x001cc910),
1252 .name = "RTL8211 Gigabit Ethernet",
1253 .config_aneg = rtl8211_config_aneg,
1254 .read_mmd = &genphy_read_mmd_unsupported,
1255 .write_mmd = &genphy_write_mmd_unsupported,
1256 .read_page = rtl821x_read_page,
1257 .write_page = rtl821x_write_page,
1258 }, {
1259 PHY_ID_MATCH_EXACT(0x001cc912),
1260 .name = "RTL8211B Gigabit Ethernet",
1261 .ack_interrupt = &rtl821x_ack_interrupt,
1262 .config_intr = &rtl8211b_config_intr,
1263 .read_mmd = &genphy_read_mmd_unsupported,
1264 .write_mmd = &genphy_write_mmd_unsupported,
1265 .suspend = rtl8211b_suspend,
1266 .resume = rtl8211b_resume,
1267 .read_page = rtl821x_read_page,
1268 .write_page = rtl821x_write_page,
1269 }, {
1270 PHY_ID_MATCH_EXACT(0x001cc913),
1271 .name = "RTL8211C Gigabit Ethernet",
1272 .config_init = rtl8211c_config_init,
1273 .read_mmd = &genphy_read_mmd_unsupported,
1274 .write_mmd = &genphy_write_mmd_unsupported,
1275 .read_page = rtl821x_read_page,
1276 .write_page = rtl821x_write_page,
1277 }, {
1278 PHY_ID_MATCH_EXACT(0x001cc914),
1279 .name = "RTL8211DN Gigabit Ethernet",
1280 .ack_interrupt = rtl821x_ack_interrupt,
1281 .config_intr = rtl8211e_config_intr,
1282 .suspend = genphy_suspend,
1283 .resume = genphy_resume,
1284 .read_page = rtl821x_read_page,
1285 .write_page = rtl821x_write_page,
1286 }, {
1287 PHY_ID_MATCH_EXACT(0x001cc915),
1288 .name = "RTL8211E Gigabit Ethernet",
1289 .config_init = &rtl8211e_config_init,
1290 .ack_interrupt = &rtl821x_ack_interrupt,
1291 .config_intr = &rtl8211e_config_intr,
1292 .suspend = genphy_suspend,
1293 .resume = genphy_resume,
1294 .read_page = rtl821x_read_page,
1295 .write_page = rtl821x_write_page,
1296 }, {
1297 PHY_ID_MATCH_EXACT(0x001cc916),
1298 .name = "RTL8211F Gigabit Ethernet",
1299 .config_init = &rtl8211f_config_init,
1300 .ack_interrupt = &rtl8211f_ack_interrupt,
1301 .config_intr = &rtl8211f_config_intr,
1302 .suspend = genphy_suspend,
1303 .resume = genphy_resume,
1304 .read_page = rtl821x_read_page,
1305 .write_page = rtl821x_write_page,
1306 }, {
1307 .name = "Generic FE-GE Realtek PHY",
1308 .match_phy_device = rtlgen_match_phy_device,
1309 .suspend = genphy_suspend,
1310 .resume = genphy_resume,
1311 .read_page = rtl821x_read_page,
1312 .write_page = rtl821x_write_page,
1313 .read_mmd = rtlgen_read_mmd,
1314 .write_mmd = rtlgen_write_mmd,
1315 }, {
1316 .name = "RTL8125 2.5Gbps internal",
1317 .match_phy_device = rtl8125_match_phy_device,
1318 .get_features = rtl8125_get_features,
1319 .config_aneg = rtl8125_config_aneg,
1320 .read_status = rtl8125_read_status,
1321 .suspend = genphy_suspend,
1322 .resume = genphy_resume,
1323 .read_page = rtl821x_read_page,
1324 .write_page = rtl821x_write_page,
1325 .read_mmd = rtl8125_read_mmd,
1326 .write_mmd = rtl8125_write_mmd,
1327 }, {
1328 PHY_ID_MATCH_EXACT(0x001cc961),
1329 .name = "RTL8366RB Gigabit Ethernet",
1330 .config_init = &rtl8366rb_config_init,
1331 /* These interrupts are handled by the irq controller
1332 * embedded inside the RTL8366RB, they get unmasked when the
1333 * irq is requested and ACKed by reading the status register,
1334 * which is done by the irqchip code.
1335 */
1336 .ack_interrupt = genphy_no_ack_interrupt,
1337 .config_intr = genphy_no_config_intr,
1338 .suspend = genphy_suspend,
1339 .resume = genphy_resume,
1340 }, {
1341 PHY_ID_MATCH_EXACT(0x001cc849),
1342 .name = "RTL8221B-VB-CG 2.5Gbps PHY",
1343 .config_init = &rtl822x_config_init,
1344 .get_features = rtl822x_get_features,
1345 .config_aneg = rtl822x_config_aneg,
1346 .read_status = rtl822x_read_status,
1347 .suspend = genphy_suspend,
1348 .resume = rtlgen_resume,
1349 .read_page = rtl821x_read_page,
1350 .write_page = rtl821x_write_page,
1351 .read_mmd = rtl822x_read_mmd,
1352 .write_mmd = rtl822x_write_mmd,
1353 }, {
1354 PHY_ID_MATCH_EXACT(0x001cc84a),
1355 .name = "RTL8221B-VM-CG 2.5Gbps PHY",
1356 .config_init = &rtl822x_config_init,
1357 .get_features = rtl822x_get_features,
1358 .config_aneg = rtl822x_config_aneg,
1359 .read_status = rtl822x_read_status,
1360 .suspend = genphy_suspend,
1361 .resume = rtlgen_resume,
1362 .read_page = rtl821x_read_page,
1363 .write_page = rtl821x_write_page,
1364 .read_mmd = rtl822x_read_mmd,
1365 .write_mmd = rtl822x_write_mmd,
hj.shaof72d6ff2025-06-10 04:34:26 -07001366 },
1367//#LYNQ_MODFIY modify for task-1618 2025/6/10 start
1368 {
hj.shaofe1632a2025-06-05 00:19:33 -07001369 PHY_ID_MATCH_EXACT(0x001ccb00),
1370 .name = "RTL90000Bf PHY",
1371 .config_init = &rtl9000Bf_config_init,
hj.shaof72d6ff2025-06-10 04:34:26 -07001372 .remove = &rtl9000Bf_remove,
hj.shaofe1632a2025-06-05 00:19:33 -07001373 .read_status = rtl9000Bf_read_status,
hj.shaofb3ba9b2025-06-19 02:53:56 -07001374 //#LYNQ_MODFIY modify for task-1618 2025/6/19 start
1375 .suspend = rtl9000Bf_suspend,
hj.shaofb3ba9b2025-06-19 02:53:56 -07001376 //#LYNQ_MODFIY modify for task-1618 2025/6/19 end
hj.shaof72d6ff2025-06-10 04:34:26 -07001377 .soft_reset = rtl9000Bf_soft_reset,
hj.shaofe1632a2025-06-05 00:19:33 -07001378 },
hj.shaof72d6ff2025-06-10 04:34:26 -07001379//#LYNQ_MODFIY modify for task-1618 2025/6/10 end
hj.shaofe1632a2025-06-05 00:19:33 -07001380
b.liue9582032025-04-17 19:18:16 +08001381};
1382
hj.shaofe1632a2025-06-05 00:19:33 -07001383
1384
b.liue9582032025-04-17 19:18:16 +08001385module_phy_driver(realtek_drvs);
1386
1387static const struct mdio_device_id __maybe_unused realtek_tbl[] = {
1388 { PHY_ID_MATCH_VENDOR(0x001cc800) },
hj.shaof72d6ff2025-06-10 04:34:26 -07001389//#LYNQ_MODFIY modify for task-1618 2025/6/10 start
1390
hj.shaofe1632a2025-06-05 00:19:33 -07001391 { 0x001ccb00, 0x001fffff },
hj.shaof72d6ff2025-06-10 04:34:26 -07001392
1393//#LYNQ_MODFIY modify for task-1618 2025/6/10 end
b.liue9582032025-04-17 19:18:16 +08001394 { }
1395};
1396
1397MODULE_DEVICE_TABLE(mdio, realtek_tbl);
hj.shaof72d6ff2025-06-10 04:34:26 -07001398