4440dc99cd49088734fb688167bc9dbd4fc84552
[openwrt/staging/jow.git] / target / linux / rtl838x / files-5.4 / drivers / net / dsa / rtl838x_phy.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Realtek RTL838X Ethernet MDIO interface driver
3 *
4 * Copyright (C) 2020 B. Koblitz
5 */
6
7 #include <linux/delay.h>
8 #include <linux/kernel.h>
9 #include <linux/module.h>
10 #include <linux/of_address.h>
11 #include <linux/of_mdio.h>
12 #include <linux/phy.h>
13 #include <linux/platform_device.h>
14 #include <linux/firmware.h>
15 #include <linux/crc32.h>
16
17 #include <asm/mach-rtl838x/mach-rtl838x.h>
18 #include "rtl838x.h"
19
20 /* External RTL8218B and RTL8214FC IDs are identical */
21 #define PHY_ID_RTL8214C 0x001cc942
22 #define PHY_ID_RTL8214FC 0x001cc981
23 #define PHY_ID_RTL8218B_E 0x001cc981
24 #define PHY_ID_RTL8218B_I 0x001cca40
25 #define PHY_ID_RTL8390_GENERIC 0x001ccab0
26
27 struct __attribute__ ((__packed__)) part {
28 uint16_t start;
29 uint8_t wordsize;
30 uint8_t words;
31 };
32
33 struct __attribute__ ((__packed__)) fw_header {
34 uint32_t magic;
35 uint32_t phy;
36 uint32_t checksum;
37 uint32_t version;
38 struct part parts[10];
39 };
40
41 #define FIRMWARE_838X_8380_1 "rtl838x_phy/rtl838x_8380.fw"
42 #define FIRMWARE_838X_8214FC_1 "rtl838x_phy/rtl838x_8214fc.fw"
43 #define FIRMWARE_838X_8218b_1 "rtl838x_phy/rtl838x_8218b.fw"
44
45 static const struct firmware rtl838x_8380_fw;
46 static const struct firmware rtl838x_8214fc_fw;
47 static const struct firmware rtl838x_8218b_fw;
48
49 struct rtl838x_phy_priv {
50 char *name;
51 };
52
53 static int read_phy(u32 port, u32 page, u32 reg, u32 *val)
54 {
55 if (soc_info.family == RTL8390_FAMILY_ID)
56 return rtl839x_read_phy(port, page, reg, val);
57 else
58 return rtl838x_read_phy(port, page, reg, val);
59 }
60
61 static int write_phy(u32 port, u32 page, u32 reg, u32 val)
62 {
63 if (soc_info.family == RTL8390_FAMILY_ID)
64 return rtl839x_write_phy(port, page, reg, val);
65 else
66 return rtl838x_write_phy(port, page, reg, val);
67 }
68
69 static void rtl8380_int_phy_on_off(int mac, bool on)
70 {
71 u32 val;
72
73 read_phy(mac, 0, 0, &val);
74 if (on)
75 write_phy(mac, 0, 0, val & ~(1 << 11));
76 else
77 write_phy(mac, 0, 0, val | (1 << 11));
78 }
79
80 static void rtl8380_rtl8214fc_on_off(int mac, bool on)
81 {
82 u32 val;
83
84 /* fiber ports */
85 write_phy(mac, 4095, 30, 3);
86 read_phy(mac, 0, 16, &val);
87 if (on)
88 write_phy(mac, 0, 16, val & ~(1 << 11));
89 else
90 write_phy(mac, 0, 16, val | (1 << 11));
91
92 /* copper ports */
93 write_phy(mac, 4095, 30, 1);
94 read_phy(mac, 0, 16, &val);
95 if (on)
96 write_phy(mac, 0xa40, 16, val & ~(1 << 11));
97 else
98 write_phy(mac, 0xa40, 16, val | (1 << 11));
99 }
100
101 static void rtl8380_phy_reset(int mac)
102 {
103 u32 val;
104
105 read_phy(mac, 0, 0, &val);
106 write_phy(mac, 0, 0, val | (0x1 << 15));
107 }
108
109 void rtl8380_sds_rst(int mac)
110 {
111 u32 offset = (mac == 24) ? 0 : 0x100;
112
113 sw_w32_mask(1 << 11, 0, RTL8380_SDS4_FIB_REG0 + offset);
114 sw_w32_mask(0x3, 0, RTL838X_SDS4_REG28 + offset);
115 sw_w32_mask(0x3, 0x3, RTL838X_SDS4_REG28 + offset);
116 sw_w32_mask(0, 0x1 << 6, RTL838X_SDS4_DUMMY0 + offset);
117 sw_w32_mask(0x1 << 6, 0, RTL838X_SDS4_DUMMY0 + offset);
118 pr_info("SERDES reset: %d\n", mac);
119 }
120
121 static struct fw_header *
122 rtl838x_request_fw(struct phy_device *phydev, const struct firmware *fw,
123 const char *name)
124 {
125 struct device *dev = &phydev->mdio.dev;
126 int err;
127 struct fw_header *h;
128 uint32_t checksum, my_checksum;
129
130 err = request_firmware(&fw, name, dev);
131 if (err < 0)
132 goto out;
133
134 if (fw->size < sizeof(struct fw_header)) {
135 pr_err("Firmware size too small.\n");
136 err = -EINVAL;
137 goto out;
138 }
139
140 h = (struct fw_header *) fw->data;
141 pr_info("Firmware loaded. Size %d, magic: %08x\n", fw->size, h->magic);
142
143 if (h->phy != 0x83800000) {
144 pr_err("Wrong firmware file: PHY mismatch.\n");
145 goto out;
146 }
147
148 checksum = h->checksum;
149 h->checksum = 0;
150 my_checksum = ~crc32(0xFFFFFFFFU, fw->data, fw->size);
151 if (checksum != my_checksum) {
152 pr_err("Firmware checksum mismatch.\n");
153 err = -EINVAL;
154 goto out;
155 }
156 h->checksum = checksum;
157
158 return h;
159 out:
160 dev_err(dev, "Unable to load firmware %s (%d)\n", name, err);
161 return NULL;
162 }
163
164 static int rtl8390_configure_generic(struct phy_device *phydev)
165 {
166 u32 val, phy_id;
167 int mac = phydev->mdio.addr;
168
169 read_phy(mac, 0, 2, &val);
170 phy_id = val << 16;
171 read_phy(mac, 0, 3, &val);
172 phy_id |= val;
173 pr_debug("Phy on MAC %d: %x\n", mac, phy_id);
174
175 /* Read internal PHY ID */
176 write_phy(mac, 31, 27, 0x0002);
177 read_phy(mac, 31, 28, &val);
178
179 /* Internal RTL8218B, version 2 */
180 phydev_info(phydev, "Detected unknown %x\n", val);
181 return 0;
182 }
183
184 static int rtl8380_configure_int_rtl8218b(struct phy_device *phydev)
185 {
186 u32 val, phy_id;
187 int i, p, ipd_flag;
188 int mac = phydev->mdio.addr;
189 struct fw_header *h;
190 u32 *rtl838x_6275B_intPhy_perport;
191 u32 *rtl8218b_6276B_hwEsd_perport;
192
193
194 read_phy(mac, 0, 2, &val);
195 phy_id = val << 16;
196 read_phy(mac, 0, 3, &val);
197 phy_id |= val;
198 pr_debug("Phy on MAC %d: %x\n", mac, phy_id);
199
200 /* Read internal PHY ID */
201 write_phy(mac, 31, 27, 0x0002);
202 read_phy(mac, 31, 28, &val);
203 if (val != 0x6275) {
204 phydev_err(phydev, "Expected internal RTL8218B, found PHY-ID %x\n", val);
205 return -1;
206 }
207
208 /* Internal RTL8218B, version 2 */
209 phydev_info(phydev, "Detected internal RTL8218B\n");
210
211 h = rtl838x_request_fw(phydev, &rtl838x_8380_fw, FIRMWARE_838X_8380_1);
212 if (!h)
213 return -1;
214
215 if (h->phy != 0x83800000) {
216 phydev_err(phydev, "Wrong firmware file: PHY mismatch.\n");
217 return -1;
218 }
219
220 rtl838x_6275B_intPhy_perport = (void *)h + sizeof(struct fw_header)
221 + h->parts[8].start;
222
223 rtl8218b_6276B_hwEsd_perport = (void *)h + sizeof(struct fw_header)
224 + h->parts[9].start;
225
226 if (sw_r32(RTL838X_DMY_REG31) == 0x1)
227 ipd_flag = 1;
228
229 read_phy(mac, 0, 0, &val);
230 if (val & (1 << 11))
231 rtl8380_int_phy_on_off(mac, true);
232 else
233 rtl8380_phy_reset(mac);
234 msleep(100);
235
236 /* Ready PHY for patch */
237 for (p = 0; p < 8; p++) {
238 write_phy(mac + p, 0xfff, 0x1f, 0x0b82);
239 write_phy(mac + p, 0xfff, 0x10, 0x0010);
240 }
241 msleep(500);
242 for (p = 0; p < 8; p++) {
243 for (i = 0; i < 100 ; i++) {
244 read_phy(mac + p, 0x0b80, 0x10, &val);
245 if (val & 0x40)
246 break;
247 }
248 if (i >= 100) {
249 phydev_err(phydev,
250 "ERROR: Port %d not ready for patch.\n",
251 mac + p);
252 return -1;
253 }
254 }
255 for (p = 0; p < 8; p++) {
256 i = 0;
257 while (rtl838x_6275B_intPhy_perport[i * 2]) {
258 write_phy(mac + p, 0xfff,
259 rtl838x_6275B_intPhy_perport[i * 2],
260 rtl838x_6275B_intPhy_perport[i * 2 + 1]);
261 i++;
262 }
263 i = 0;
264 while (rtl8218b_6276B_hwEsd_perport[i * 2]) {
265 write_phy(mac + p, 0xfff,
266 rtl8218b_6276B_hwEsd_perport[i * 2],
267 rtl8218b_6276B_hwEsd_perport[i * 2 + 1]);
268 i++;
269 }
270 }
271 return 0;
272 }
273
274 static int rtl8380_configure_ext_rtl8218b(struct phy_device *phydev)
275 {
276 u32 val, ipd, phy_id;
277 int i, l;
278 int mac = phydev->mdio.addr;
279 struct fw_header *h;
280 u32 *rtl8380_rtl8218b_perchip;
281 u32 *rtl8218B_6276B_rtl8380_perport;
282 u32 *rtl8380_rtl8218b_perport;
283
284 if (soc_info.family == RTL8380_FAMILY_ID && mac != 0 && mac != 16) {
285 phydev_err(phydev, "External RTL8218B must have PHY-IDs 0 or 16!\n");
286 return -1;
287 }
288 read_phy(mac, 0, 2, &val);
289 phy_id = val << 16;
290 read_phy(mac, 0, 3, &val);
291 phy_id |= val;
292 pr_info("Phy on MAC %d: %x\n", mac, phy_id);
293
294 /* Read internal PHY ID */
295 write_phy(mac, 31, 27, 0x0002);
296 read_phy(mac, 31, 28, &val);
297 if (val != 0x6276) {
298 phydev_err(phydev, "Expected external RTL8218B, found PHY-ID %x\n", val);
299 return -1;
300 }
301 phydev_info(phydev, "Detected external RTL8218B\n");
302
303 h = rtl838x_request_fw(phydev, &rtl838x_8218b_fw, FIRMWARE_838X_8218b_1);
304 if (!h)
305 return -1;
306
307 if (h->phy != 0x8218b00) {
308 phydev_err(phydev, "Wrong firmware file: PHY mismatch.\n");
309 return -1;
310 }
311
312 rtl8380_rtl8218b_perchip = (void *)h + sizeof(struct fw_header)
313 + h->parts[0].start;
314
315 rtl8218B_6276B_rtl8380_perport = (void *)h + sizeof(struct fw_header)
316 + h->parts[1].start;
317
318 rtl8380_rtl8218b_perport = (void *)h + sizeof(struct fw_header)
319 + h->parts[2].start;
320
321 read_phy(mac, 0, 0, &val);
322 if (val & (1 << 11))
323 rtl8380_int_phy_on_off(mac, true);
324 else
325 rtl8380_phy_reset(mac);
326 msleep(100);
327
328 /* Get Chip revision */
329 write_phy(mac, 0xfff, 0x1f, 0x0);
330 write_phy(mac, 0xfff, 0x1b, 0x4);
331 read_phy(mac, 0xfff, 0x1c, &val);
332
333 i = 0;
334 while (rtl8380_rtl8218b_perchip[i * 3]
335 && rtl8380_rtl8218b_perchip[i * 3 + 1]) {
336 write_phy(mac + rtl8380_rtl8218b_perchip[i * 3],
337 0xfff, rtl8380_rtl8218b_perchip[i * 3 + 1],
338 rtl8380_rtl8218b_perchip[i * 3 + 2]);
339 i++;
340 }
341
342 /* Enable PHY */
343 for (i = 0; i < 8; i++) {
344 write_phy(mac + i, 0xfff, 0x1f, 0x0000);
345 write_phy(mac + i, 0xfff, 0x00, 0x1140);
346 }
347 mdelay(100);
348
349 /* Request patch */
350 for (i = 0; i < 8; i++) {
351 write_phy(mac + i, 0xfff, 0x1f, 0x0b82);
352 write_phy(mac + i, 0xfff, 0x10, 0x0010);
353 }
354 mdelay(300);
355
356 /* Verify patch readiness */
357 for (i = 0; i < 8; i++) {
358 for (l = 0; l < 100; l++) {
359 read_phy(mac + i, 0xb80, 0x10, &val);
360 if (val & 0x40)
361 break;
362 }
363 if (l >= 100) {
364 phydev_err(phydev, "Could not patch PHY\n");
365 return -1;
366 }
367 }
368
369 /* Use Broadcast ID method for patching */
370 write_phy(mac, 0xfff, 0x1f, 0x0000);
371 write_phy(mac, 0xfff, 0x1d, 0x0008);
372 write_phy(mac, 0xfff, 0x1f, 0x0266);
373 write_phy(mac, 0xfff, 0x16, 0xff00 + mac);
374 write_phy(mac, 0xfff, 0x1f, 0x0000);
375 write_phy(mac, 0xfff, 0x1d, 0x0000);
376 mdelay(1);
377
378 write_phy(mac, 0xfff, 30, 8);
379 write_phy(mac, 0x26e, 17, 0xb);
380 write_phy(mac, 0x26e, 16, 0x2);
381 mdelay(1);
382 read_phy(mac, 0x26e, 19, &ipd);
383 write_phy(mac, 0, 30, 0);
384 ipd = (ipd >> 4) & 0xf;
385
386 i = 0;
387 while (rtl8218B_6276B_rtl8380_perport[i * 2]) {
388 write_phy(mac, 0xfff, rtl8218B_6276B_rtl8380_perport[i * 2],
389 rtl8218B_6276B_rtl8380_perport[i * 2 + 1]);
390 i++;
391 }
392
393 /*Disable broadcast ID*/
394 write_phy(mac, 0xfff, 0x1f, 0x0000);
395 write_phy(mac, 0xfff, 0x1d, 0x0008);
396 write_phy(mac, 0xfff, 0x1f, 0x0266);
397 write_phy(mac, 0xfff, 0x16, 0x00 + mac);
398 write_phy(mac, 0xfff, 0x1f, 0x0000);
399 write_phy(mac, 0xfff, 0x1d, 0x0000);
400 mdelay(1);
401
402 return 0;
403 }
404
405 static int rtl8218b_ext_match_phy_device(struct phy_device *phydev)
406 {
407 int addr = phydev->mdio.addr;
408
409 return phydev->phy_id == PHY_ID_RTL8218B_E && addr < 8;
410 }
411
412
413 static int rtl8380_rtl8218b_write_mmd(struct phy_device *phydev,
414 int devnum, u16 regnum, u16 val)
415 {
416 int addr = phydev->mdio.addr;
417
418 return rtl838x_write_mmd_phy(addr, devnum, regnum, val);
419 }
420
421 static int rtl8380_rtl8218b_read_mmd(struct phy_device *phydev,
422 int devnum, u16 regnum)
423 {
424 int ret;
425 u32 val;
426 int addr = phydev->mdio.addr;
427
428 ret = rtl838x_read_mmd_phy(addr, devnum, regnum, &val);
429 if (ret)
430 return ret;
431 return val;
432 }
433
434 static void rtl8380_rtl8214fc_media_set(int mac, bool set_fibre)
435 {
436 int base = mac - (mac % 4);
437 static int reg[] = {16, 19, 20, 21};
438 int val, media, power;
439
440 pr_info("%s: port %d, set_fibre: %d\n", __func__, mac, set_fibre);
441 write_phy(base, 0xfff, 29, 8);
442 read_phy(base, 0x266, reg[mac % 4], &val);
443
444 media = (val >> 10) & 0x3;
445 pr_info("Current media %x\n", media);
446 if (media & 0x2) {
447 pr_info("Powering off COPPER\n");
448 write_phy(base, 0xfff, 29, 1);
449 /* Ensure power is off */
450 read_phy(base, 0xa40, 16, &power);
451 if (!(power & (1 << 11)))
452 write_phy(base, 0xa40, 16, power | (1 << 11));
453 } else {
454 pr_info("Powering off FIBRE");
455 write_phy(base, 0xfff, 29, 3);
456 /* Ensure power is off */
457 read_phy(base, 0xa40, 16, &power);
458 if (!(power & (1 << 11)))
459 write_phy(base, 0xa40, 16, power | (1 << 11));
460 }
461
462 if (set_fibre) {
463 val |= 1 << 10;
464 val &= ~(1 << 11);
465 } else {
466 val |= 1 << 10;
467 val |= 1 << 11;
468 }
469 write_phy(base, 0xfff, 29, 8);
470 write_phy(base, 0x266, reg[mac % 4], val);
471 write_phy(base, 0xfff, 29, 0);
472
473 if (set_fibre) {
474 pr_info("Powering on FIBRE");
475 write_phy(base, 0xfff, 29, 3);
476 /* Ensure power is off */
477 read_phy(base, 0xa40, 16, &power);
478 if (power & (1 << 11))
479 write_phy(base, 0xa40, 16, power & ~(1 << 11));
480 } else {
481 pr_info("Powering on COPPER\n");
482 write_phy(base, 0xfff, 29, 1);
483 /* Ensure power is off */
484 read_phy(base, 0xa40, 16, &power);
485 if (power & (1 << 11))
486 write_phy(base, 0xa40, 16, power & ~(1 << 11));
487 }
488
489 write_phy(base, 0xfff, 29, 0);
490 }
491
492 static bool rtl8380_rtl8214fc_media_is_fibre(int mac)
493 {
494 int base = mac - (mac % 4);
495 static int reg[] = {16, 19, 20, 21};
496 u32 val;
497
498 write_phy(base, 0xfff, 29, 8);
499 read_phy(base, 0x266, reg[mac % 4], &val);
500 write_phy(base, 0xfff, 29, 0);
501 if (val & (1 << 11))
502 return false;
503 return true;
504 }
505
506 static int rtl8380_rtl8214fc_set_port(struct phy_device *phydev, int port)
507 {
508 bool is_fibre = (port == PORT_FIBRE ? true : false);
509 int addr = phydev->mdio.addr;
510
511 pr_debug("%s port %d to %d\n", __func__, addr, port);
512
513 rtl8380_rtl8214fc_media_set(addr, is_fibre);
514 return 0;
515 }
516
517 static int rtl8380_rtl8214fc_get_port(struct phy_device *phydev)
518 {
519 int addr = phydev->mdio.addr;
520
521 pr_debug("%s: port %d\n", __func__, addr);
522 if (rtl8380_rtl8214fc_media_is_fibre(addr))
523 return PORT_FIBRE;
524 return PORT_MII;
525 }
526
527 void rtl8380_rtl8214fc_ldps_set(int mac, struct ethtool_eee *e)
528 {
529
530 }
531
532 static void rtl8380_rtl8218b_eee_set_u_boot(int port, bool enable)
533 {
534 u32 val;
535 bool an_enabled;
536
537 /* Set GPHY page to copper */
538 write_phy(port, 0, 30, 0x0001);
539 read_phy(port, 0, 0, &val);
540 an_enabled = val & (1 << 12);
541
542 if (enable) {
543 /* 100/1000M EEE Capability */
544 write_phy(port, 0, 13, 0x0007);
545 write_phy(port, 0, 14, 0x003C);
546 write_phy(port, 0, 13, 0x4007);
547 write_phy(port, 0, 14, 0x0006);
548
549 read_phy(port, 0x0A43, 25, &val);
550 val |= 1 << 4;
551 write_phy(port, 0x0A43, 25, val);
552 } else {
553 /* 100/1000M EEE Capability */
554 write_phy(port, 0, 13, 0x0007);
555 write_phy(port, 0, 14, 0x003C);
556 write_phy(port, 0, 13, 0x0007);
557 write_phy(port, 0, 14, 0x0000);
558
559 read_phy(port, 0x0A43, 25, &val);
560 val &= ~(1 << 4);
561 write_phy(port, 0x0A43, 25, val);
562 }
563
564 /* Restart AN if enabled */
565 if (an_enabled) {
566 read_phy(port, 0, 0, &val);
567 val |= (1 << 12) | (1 << 9);
568 write_phy(port, 0, 0, val);
569 }
570
571 /* GPHY page back to auto*/
572 write_phy(port, 0xa42, 29, 0);
573 }
574
575 static int rtl8380_rtl8218b_get_eee_u_boot(struct phy_device *phydev, struct ethtool_eee *e)
576 {
577 u32 val;
578 int addr = phydev->mdio.addr;
579
580 pr_debug("In %s %d\n", __func__, addr);
581
582 /* Set GPHY page to copper */
583 write_phy(addr, 0xa42, 29, 0x0001);
584
585 read_phy(addr, 0xa43, 25, &val);
586 if (e->eee_enabled && (!!(val & (1 << 4))))
587 e->eee_enabled = !!(val & (1 << 4));
588 else
589 e->eee_enabled = 0;
590
591 /* GPHY page to auto */
592 write_phy(addr, 0xa42, 29, 0x0000);
593
594 return 0;
595 }
596
597 void rtl8380_rtl8218b_eee_set(int port, bool enable)
598 {
599 u32 val;
600 bool an_enabled;
601
602 pr_debug("In %s %d, enable %d\n", __func__, port, enable);
603 /* Set GPHY page to copper */
604 write_phy(port, 0xa42, 29, 0x0001);
605
606 read_phy(port, 0, 0, &val);
607 an_enabled = val & (1 << 12);
608
609 /* MAC based EEE */
610 read_phy(port, 0xa43, 25, &val);
611 val &= ~(1 << 5);
612 write_phy(port, 0xa43, 25, val);
613
614 /* 100M / 1000M EEE */
615 if (enable)
616 rtl838x_write_mmd_phy(port, 7, 60, 0x6);
617 else
618 rtl838x_write_mmd_phy(port, 7, 60, 0);
619
620 /* 500M EEE ability */
621 read_phy(port, 0xa42, 20, &val);
622 if (enable)
623 val |= 1 << 7;
624 else
625 val &= ~(1 << 7);
626 write_phy(port, 0xa42, 20, val);
627
628 /* Restart AN if enabled */
629 if (an_enabled) {
630 read_phy(port, 0, 0, &val);
631 val |= (1 << 12) | (1 << 9);
632 write_phy(port, 0, 0, val);
633 }
634
635 /* GPHY page back to auto*/
636 write_phy(port, 0xa42, 29, 0);
637 }
638
639 int rtl8380_rtl8218b_get_eee(struct phy_device *phydev,
640 struct ethtool_eee *e)
641 {
642 u32 val;
643 int addr = phydev->mdio.addr;
644
645 pr_debug("In %s, port %d\n", __func__, addr);
646
647 /* Set GPHY page to copper */
648 write_phy(addr, 0xa42, 29, 0x0001);
649
650 rtl838x_read_mmd_phy(addr, 7, 60, &val);
651 if (e->eee_enabled && (!!(val & (1 << 7))))
652 e->eee_enabled = !!(val & (1 << 7));
653 else
654 e->eee_enabled = 0;
655
656 /* GPHY page to auto */
657 write_phy(addr, 0xa42, 29, 0x0000);
658
659 return 0;
660 }
661
662 void rtl8380_rtl8218b_green_set(int mac, bool enable)
663 {
664 u32 val;
665
666 /* Set GPHY page to copper */
667 write_phy(mac, 0xa42, 29, 0x0001);
668
669 write_phy(mac, 0, 27, 0x8011);
670 read_phy(mac, 0, 28, &val);
671 if (enable) {
672 val |= 1 << 9;
673 write_phy(mac, 0, 27, 0x8011);
674 write_phy(mac, 0, 28, val);
675 } else {
676 val &= ~(1 << 9);
677 write_phy(mac, 0, 27, 0x8011);
678 write_phy(mac, 0, 28, val);
679 }
680
681 /* GPHY page to auto */
682 write_phy(mac, 0xa42, 29, 0x0000);
683 }
684
685 int rtl8380_rtl8214fc_get_green(struct phy_device *phydev, struct ethtool_eee *e)
686 {
687 u32 val;
688 int addr = phydev->mdio.addr;
689
690 pr_debug("In %s %d\n", __func__, addr);
691 /* Set GPHY page to copper */
692 write_phy(addr, 0xa42, 29, 0x0001);
693
694 write_phy(addr, 0, 27, 0x8011);
695 read_phy(addr, 0, 28, &val);
696 if (e->eee_enabled && (!!(val & (1 << 9))))
697 e->eee_enabled = !!(val & (1 << 9));
698 else
699 e->eee_enabled = 0;
700
701 /* GPHY page to auto */
702 write_phy(addr, 0xa42, 29, 0x0000);
703
704 return 0;
705 }
706
707 static int rtl8380_rtl8214fc_set_eee(struct phy_device *phydev,
708 struct ethtool_eee *e)
709 {
710 u32 pollMask;
711 int addr = phydev->mdio.addr;
712
713 pr_debug("In %s port %d, enabled %d\n", __func__, addr, e->eee_enabled);
714
715 if (rtl8380_rtl8214fc_media_is_fibre(addr)) {
716 netdev_err(phydev->attached_dev, "Port %d configured for FIBRE", addr);
717 return -ENOTSUPP;
718 }
719
720 pollMask = sw_r32(RTL838X_SMI_POLL_CTRL);
721 sw_w32(0, RTL838X_SMI_POLL_CTRL);
722 rtl8380_rtl8218b_eee_set_u_boot(addr, (bool) e->eee_enabled);
723 sw_w32(pollMask, RTL838X_SMI_POLL_CTRL);
724 return 0;
725 }
726
727 static int rtl8380_rtl8214fc_get_eee(struct phy_device *phydev,
728 struct ethtool_eee *e)
729 {
730 int addr = phydev->mdio.addr;
731
732 pr_debug("In %s port %d, enabled %d\n", __func__, addr, e->eee_enabled);
733 if (rtl8380_rtl8214fc_media_is_fibre(addr)) {
734 netdev_err(phydev->attached_dev, "Port %d configured for FIBRE", addr);
735 return -ENOTSUPP;
736 }
737
738 return rtl8380_rtl8218b_get_eee_u_boot(phydev, e);
739 }
740
741 static int rtl8380_rtl8218b_set_eee(struct phy_device *phydev,
742 struct ethtool_eee *e)
743 {
744 u32 pollMask;
745 int addr = phydev->mdio.addr;
746
747 pr_debug("In %s, port %d, enabled %d\n", __func__, addr, e->eee_enabled);
748
749 pollMask = sw_r32(RTL838X_SMI_POLL_CTRL);
750 sw_w32(0, RTL838X_SMI_POLL_CTRL);
751 rtl8380_rtl8218b_eee_set_u_boot(addr, (bool) e->eee_enabled);
752 sw_w32(pollMask, RTL838X_SMI_POLL_CTRL);
753
754 return 0;
755 }
756
757 static int rtl8214c_match_phy_device(struct phy_device *phydev)
758 {
759 return phydev->phy_id == PHY_ID_RTL8214C;
760 }
761
762 static int rtl8380_configure_rtl8214c(struct phy_device *phydev)
763 {
764 u32 phy_id, val;
765 int mac = phydev->mdio.addr;
766
767 read_phy(mac, 0, 2, &val);
768 phy_id = val << 16;
769 read_phy(mac, 0, 3, &val);
770 phy_id |= val;
771 pr_debug("Phy on MAC %d: %x\n", mac, phy_id);
772
773 phydev_info(phydev, "Detected external RTL8214C\n");
774
775 /* GPHY auto conf */
776 write_phy(mac, 0xa42, 29, 0);
777 return 0;
778 }
779
780 static int rtl8380_configure_rtl8214fc(struct phy_device *phydev)
781 {
782 u32 phy_id, val, page = 0;
783 int i, l;
784 int mac = phydev->mdio.addr;
785 struct fw_header *h;
786 u32 *rtl8380_rtl8214fc_perchip;
787 u32 *rtl8380_rtl8214fc_perport;
788
789 read_phy(mac, 0, 2, &val);
790 phy_id = val << 16;
791 read_phy(mac, 0, 3, &val);
792 phy_id |= val;
793 pr_debug("Phy on MAC %d: %x\n", mac, phy_id);
794
795 /* Read internal PHY id */
796 write_phy(mac, 0, 30, 0x0001);
797 write_phy(mac, 0, 31, 0x0a42);
798 write_phy(mac, 31, 27, 0x0002);
799 read_phy(mac, 31, 28, &val);
800 if (val != 0x6276) {
801 phydev_err(phydev, "Expected external RTL8214FC, found PHY-ID %x\n", val);
802 return -1;
803 }
804 phydev_info(phydev, "Detected external RTL8214FC\n");
805
806 h = rtl838x_request_fw(phydev, &rtl838x_8214fc_fw, FIRMWARE_838X_8214FC_1);
807 if (!h)
808 return -1;
809
810 if (h->phy != 0x8214fc00) {
811 phydev_err(phydev, "Wrong firmware file: PHY mismatch.\n");
812 return -1;
813 }
814
815 rtl8380_rtl8214fc_perchip = (void *)h + sizeof(struct fw_header)
816 + h->parts[0].start;
817
818 rtl8380_rtl8214fc_perport = (void *)h + sizeof(struct fw_header)
819 + h->parts[1].start;
820
821 /* detect phy version */
822 write_phy(mac, 0xfff, 27, 0x0004);
823 read_phy(mac, 0xfff, 28, &val);
824
825 read_phy(mac, 0, 16, &val);
826 if (val & (1 << 11))
827 rtl8380_rtl8214fc_on_off(mac, true);
828 else
829 rtl8380_phy_reset(mac);
830
831 msleep(100);
832 write_phy(mac, 0, 30, 0x0001);
833
834 i = 0;
835 while (rtl8380_rtl8214fc_perchip[i * 3]
836 && rtl8380_rtl8214fc_perchip[i * 3 + 1]) {
837 if (rtl8380_rtl8214fc_perchip[i * 3 + 1] == 0x1f)
838 page = rtl8380_rtl8214fc_perchip[i * 3 + 2];
839 if (rtl8380_rtl8214fc_perchip[i * 3 + 1] == 0x13 && page == 0x260) {
840 read_phy(mac + rtl8380_rtl8214fc_perchip[i * 3], 0x260, 13, &val);
841 val = (val & 0x1f00) | (rtl8380_rtl8214fc_perchip[i * 3 + 2]
842 & 0xe0ff);
843 write_phy(mac + rtl8380_rtl8214fc_perchip[i * 3],
844 0xfff, rtl8380_rtl8214fc_perchip[i * 3 + 1], val);
845 } else {
846 write_phy(mac + rtl8380_rtl8214fc_perchip[i * 3],
847 0xfff, rtl8380_rtl8214fc_perchip[i * 3 + 1],
848 rtl8380_rtl8214fc_perchip[i * 3 + 2]);
849 }
850 i++;
851 }
852
853 /* Force copper medium */
854 for (i = 0; i < 4; i++) {
855 write_phy(mac + i, 0xfff, 0x1f, 0x0000);
856 write_phy(mac + i, 0xfff, 0x1e, 0x0001);
857 }
858
859 /* Enable PHY */
860 for (i = 0; i < 4; i++) {
861 write_phy(mac + i, 0xfff, 0x1f, 0x0000);
862 write_phy(mac + i, 0xfff, 0x00, 0x1140);
863 }
864 mdelay(100);
865
866 /* Disable Autosensing */
867 for (i = 0; i < 4; i++) {
868 for (l = 0; l < 100; l++) {
869 read_phy(mac + i, 0x0a42, 0x10, &val);
870 if ((val & 0x7) >= 3)
871 break;
872 }
873 if (l >= 100) {
874 phydev_err(phydev, "Could not disable autosensing\n");
875 return -1;
876 }
877 }
878
879 /* Request patch */
880 for (i = 0; i < 4; i++) {
881 write_phy(mac + i, 0xfff, 0x1f, 0x0b82);
882 write_phy(mac + i, 0xfff, 0x10, 0x0010);
883 }
884 mdelay(300);
885
886 /* Verify patch readiness */
887 for (i = 0; i < 4; i++) {
888 for (l = 0; l < 100; l++) {
889 read_phy(mac + i, 0xb80, 0x10, &val);
890 if (val & 0x40)
891 break;
892 }
893 if (l >= 100) {
894 phydev_err(phydev, "Could not patch PHY\n");
895 return -1;
896 }
897 }
898
899 /* Use Broadcast ID method for patching */
900 write_phy(mac, 0xfff, 0x1f, 0x0000);
901 write_phy(mac, 0xfff, 0x1d, 0x0008);
902 write_phy(mac, 0xfff, 0x1f, 0x0266);
903 write_phy(mac, 0xfff, 0x16, 0xff00 + mac);
904 write_phy(mac, 0xfff, 0x1f, 0x0000);
905 write_phy(mac, 0xfff, 0x1d, 0x0000);
906 mdelay(1);
907
908 i = 0;
909 while (rtl8380_rtl8214fc_perport[i * 2]) {
910 write_phy(mac, 0xfff, rtl8380_rtl8214fc_perport[i * 2],
911 rtl8380_rtl8214fc_perport[i * 2 + 1]);
912 i++;
913 }
914
915 /*Disable broadcast ID*/
916 write_phy(mac, 0xfff, 0x1f, 0x0000);
917 write_phy(mac, 0xfff, 0x1d, 0x0008);
918 write_phy(mac, 0xfff, 0x1f, 0x0266);
919 write_phy(mac, 0xfff, 0x16, 0x00 + mac);
920 write_phy(mac, 0xfff, 0x1f, 0x0000);
921 write_phy(mac, 0xfff, 0x1d, 0x0000);
922 mdelay(1);
923
924 /* Auto medium selection */
925 for (i = 0; i < 4; i++) {
926 write_phy(mac + i, 0xfff, 0x1f, 0x0000);
927 write_phy(mac + i, 0xfff, 0x1e, 0x0000);
928 }
929
930 return 0;
931 }
932
933 static int rtl8214fc_match_phy_device(struct phy_device *phydev)
934 {
935 int addr = phydev->mdio.addr;
936
937 return phydev->phy_id == PHY_ID_RTL8214FC && addr >= 24;
938 }
939
940 static int rtl8380_configure_serdes(struct phy_device *phydev)
941 {
942 u32 v;
943 u32 sds_conf_value;
944 int i;
945 struct fw_header *h;
946 u32 *rtl8380_sds_take_reset;
947 u32 *rtl8380_sds_common;
948 u32 *rtl8380_sds01_qsgmii_6275b;
949 u32 *rtl8380_sds23_qsgmii_6275b;
950 u32 *rtl8380_sds4_fiber_6275b;
951 u32 *rtl8380_sds5_fiber_6275b;
952 u32 *rtl8380_sds_reset;
953 u32 *rtl8380_sds_release_reset;
954
955 phydev_info(phydev, "Detected internal RTL8380 SERDES\n");
956
957 h = rtl838x_request_fw(phydev, &rtl838x_8218b_fw, FIRMWARE_838X_8380_1);
958 if (!h)
959 return -1;
960
961 if (h->magic != 0x83808380) {
962 phydev_err(phydev, "Wrong firmware file: magic number mismatch.\n");
963 return -1;
964 }
965
966 rtl8380_sds_take_reset = (void *)h + sizeof(struct fw_header)
967 + h->parts[0].start;
968
969 rtl8380_sds_common = (void *)h + sizeof(struct fw_header)
970 + h->parts[1].start;
971
972 rtl8380_sds01_qsgmii_6275b = (void *)h + sizeof(struct fw_header)
973 + h->parts[2].start;
974
975 rtl8380_sds23_qsgmii_6275b = (void *)h + sizeof(struct fw_header)
976 + h->parts[3].start;
977
978 rtl8380_sds4_fiber_6275b = (void *)h + sizeof(struct fw_header)
979 + h->parts[4].start;
980
981 rtl8380_sds5_fiber_6275b = (void *)h + sizeof(struct fw_header)
982 + h->parts[5].start;
983
984 rtl8380_sds_reset = (void *)h + sizeof(struct fw_header)
985 + h->parts[6].start;
986
987 rtl8380_sds_release_reset = (void *)h + sizeof(struct fw_header)
988 + h->parts[7].start;
989
990 /* Back up serdes power off value */
991 sds_conf_value = sw_r32(RTL838X_SDS_CFG_REG);
992 pr_info("SDS power down value: %x\n", sds_conf_value);
993
994 /* take serdes into reset */
995 i = 0;
996 while (rtl8380_sds_take_reset[2 * i]) {
997 sw_w32(rtl8380_sds_take_reset[2 * i + 1], rtl8380_sds_take_reset[2 * i]);
998 i++;
999 udelay(1000);
1000 }
1001
1002 /* apply common serdes patch */
1003 i = 0;
1004 while (rtl8380_sds_common[2 * i]) {
1005 sw_w32(rtl8380_sds_common[2 * i + 1], rtl8380_sds_common[2 * i]);
1006 i++;
1007 udelay(1000);
1008 }
1009
1010 /* internal R/W enable */
1011 sw_w32(3, RTL838X_INT_RW_CTRL);
1012
1013 /* SerDes ports 4 and 5 are FIBRE ports */
1014 sw_w32_mask(0x7 | 0x38, 1 | (1 << 3), RTL838X_INT_MODE_CTRL);
1015
1016 /* SerDes module settings, SerDes 0-3 are QSGMII */
1017 v = 0x6 << 25 | 0x6 << 20 | 0x6 << 15 | 0x6 << 10;
1018 /* SerDes 4 and 5 are 1000BX FIBRE */
1019 v |= 0x4 << 5 | 0x4;
1020 sw_w32(v, RTL838X_SDS_MODE_SEL);
1021
1022 pr_info("PLL control register: %x\n", sw_r32(RTL838X_PLL_CML_CTRL));
1023 sw_w32_mask(0xfffffff0, 0xaaaaaaaf & 0xf, RTL838X_PLL_CML_CTRL);
1024 i = 0;
1025 while (rtl8380_sds01_qsgmii_6275b[2 * i]) {
1026 sw_w32(rtl8380_sds01_qsgmii_6275b[2 * i + 1],
1027 rtl8380_sds01_qsgmii_6275b[2 * i]);
1028 i++;
1029 }
1030
1031 i = 0;
1032 while (rtl8380_sds23_qsgmii_6275b[2 * i]) {
1033 sw_w32(rtl8380_sds23_qsgmii_6275b[2 * i + 1], rtl8380_sds23_qsgmii_6275b[2 * i]);
1034 i++;
1035 }
1036
1037 i = 0;
1038 while (rtl8380_sds4_fiber_6275b[2 * i]) {
1039 sw_w32(rtl8380_sds4_fiber_6275b[2 * i + 1], rtl8380_sds4_fiber_6275b[2 * i]);
1040 i++;
1041 }
1042
1043 i = 0;
1044 while (rtl8380_sds5_fiber_6275b[2 * i]) {
1045 sw_w32(rtl8380_sds5_fiber_6275b[2 * i + 1], rtl8380_sds5_fiber_6275b[2 * i]);
1046 i++;
1047 }
1048
1049 i = 0;
1050 while (rtl8380_sds_reset[2 * i]) {
1051 sw_w32(rtl8380_sds_reset[2 * i + 1], rtl8380_sds_reset[2 * i]);
1052 i++;
1053 }
1054
1055 i = 0;
1056 while (rtl8380_sds_release_reset[2 * i]) {
1057 sw_w32(rtl8380_sds_release_reset[2 * i + 1], rtl8380_sds_release_reset[2 * i]);
1058 i++;
1059 }
1060
1061 pr_info("SDS power down value now: %x\n", sw_r32(RTL838X_SDS_CFG_REG));
1062 sw_w32(sds_conf_value, RTL838X_SDS_CFG_REG);
1063
1064 pr_info("Configuration of SERDES done\n");
1065 return 0;
1066 }
1067
1068 static int rtl8214fc_phy_probe(struct phy_device *phydev)
1069 {
1070 struct device *dev = &phydev->mdio.dev;
1071 struct rtl838x_phy_priv *priv;
1072 int addr = phydev->mdio.addr;
1073
1074 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1075 if (!priv)
1076 return -ENOMEM;
1077
1078 priv->name = "RTL8214FC";
1079
1080 /* All base addresses of the PHYs start at multiples of 8 */
1081 if (!(addr % 8)) {
1082 /* Configuration must be done whil patching still possible */
1083 return rtl8380_configure_rtl8214fc(phydev);
1084 }
1085 return 0;
1086 }
1087
1088 static int rtl8214c_phy_probe(struct phy_device *phydev)
1089 {
1090 struct device *dev = &phydev->mdio.dev;
1091 struct rtl838x_phy_priv *priv;
1092 int addr = phydev->mdio.addr;
1093
1094 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1095 if (!priv)
1096 return -ENOMEM;
1097
1098 priv->name = "RTL8214C";
1099
1100 /* All base addresses of the PHYs start at multiples of 8 */
1101 if (!(addr % 8)) {
1102 /* Configuration must be done whil patching still possible */
1103 return rtl8380_configure_rtl8214c(phydev);
1104 }
1105 return 0;
1106 }
1107
1108 static int rtl8218b_ext_phy_probe(struct phy_device *phydev)
1109 {
1110 struct device *dev = &phydev->mdio.dev;
1111 struct rtl838x_phy_priv *priv;
1112 int addr = phydev->mdio.addr;
1113
1114 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1115 if (!priv)
1116 return -ENOMEM;
1117
1118 priv->name = "RTL8218B (external)";
1119
1120 /* All base addresses of the PHYs start at multiples of 8 */
1121 if (!(addr % 8)) {
1122 /* Configuration must be done while patching still possible */
1123 return rtl8380_configure_ext_rtl8218b(phydev);
1124 }
1125 return 0;
1126 }
1127
1128 static int rtl8218b_int_phy_probe(struct phy_device *phydev)
1129 {
1130 struct device *dev = &phydev->mdio.dev;
1131 struct rtl838x_phy_priv *priv;
1132 int addr = phydev->mdio.addr;
1133
1134 if (soc_info.family != RTL8380_FAMILY_ID)
1135 return -ENODEV;
1136 if (addr >= 24)
1137 return -ENODEV;
1138
1139 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1140 if (!priv)
1141 return -ENOMEM;
1142
1143 priv->name = "RTL8218B (internal)";
1144
1145 /* All base addresses of the PHYs start at multiples of 8 */
1146 if (!(addr % 8)) {
1147 /* Configuration must be done while patching still possible */
1148 return rtl8380_configure_int_rtl8218b(phydev);
1149 }
1150 return 0;
1151 }
1152
1153 static int rtl838x_serdes_probe(struct phy_device *phydev)
1154 {
1155 struct device *dev = &phydev->mdio.dev;
1156 struct rtl838x_phy_priv *priv;
1157 int addr = phydev->mdio.addr;
1158
1159 if (soc_info.family != RTL8380_FAMILY_ID)
1160 return -ENODEV;
1161 if (addr < 24)
1162 return -ENODEV;
1163
1164 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1165 if (!priv)
1166 return -ENOMEM;
1167
1168 priv->name = "RTL8380 Serdes";
1169
1170 /* On the RTL8380M, PHYs 24-27 connect to the internal SerDes */
1171 if (soc_info.id == 0x8380) {
1172 if (addr == 24)
1173 return rtl8380_configure_serdes(phydev);
1174 return 0;
1175 }
1176 return -ENODEV;
1177 }
1178
1179 static int rtl8390_serdes_probe(struct phy_device *phydev)
1180 {
1181 struct device *dev = &phydev->mdio.dev;
1182 struct rtl838x_phy_priv *priv;
1183 int addr = phydev->mdio.addr;
1184
1185 if (soc_info.family != RTL8390_FAMILY_ID)
1186 return -ENODEV;
1187
1188 if (addr < 24)
1189 return -ENODEV;
1190
1191 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
1192 if (!priv)
1193 return -ENOMEM;
1194
1195 priv->name = "RTL8390 Serdes";
1196 return rtl8390_configure_generic(phydev);
1197 }
1198
1199 static struct phy_driver rtl838x_phy_driver[] = {
1200 {
1201 PHY_ID_MATCH_MODEL(PHY_ID_RTL8214FC),
1202 .name = "REATLTEK RTL8214C",
1203 .features = PHY_GBIT_FEATURES,
1204 .match_phy_device = rtl8214c_match_phy_device,
1205 .probe = rtl8214c_phy_probe,
1206 .suspend = genphy_suspend,
1207 .resume = genphy_resume,
1208 .set_loopback = genphy_loopback,
1209 },
1210 {
1211 PHY_ID_MATCH_MODEL(PHY_ID_RTL8214FC),
1212 .name = "REATLTEK RTL8214FC",
1213 .features = PHY_GBIT_FIBRE_FEATURES,
1214 .match_phy_device = rtl8214fc_match_phy_device,
1215 .probe = rtl8214fc_phy_probe,
1216 .suspend = genphy_suspend,
1217 .resume = genphy_resume,
1218 .set_loopback = genphy_loopback,
1219 .read_mmd = rtl8380_rtl8218b_read_mmd,
1220 .write_mmd = rtl8380_rtl8218b_write_mmd,
1221 .set_port = rtl8380_rtl8214fc_set_port,
1222 .get_port = rtl8380_rtl8214fc_get_port,
1223 .set_eee = rtl8380_rtl8214fc_set_eee,
1224 .get_eee = rtl8380_rtl8214fc_get_eee,
1225 },
1226 {
1227 PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_E),
1228 .name = "REATLTEK RTL8218B (external)",
1229 .features = PHY_GBIT_FEATURES,
1230 .match_phy_device = rtl8218b_ext_match_phy_device,
1231 .probe = rtl8218b_ext_phy_probe,
1232 .suspend = genphy_suspend,
1233 .resume = genphy_resume,
1234 .set_loopback = genphy_loopback,
1235 .read_mmd = rtl8380_rtl8218b_read_mmd,
1236 .write_mmd = rtl8380_rtl8218b_write_mmd,
1237 .set_eee = rtl8380_rtl8218b_set_eee,
1238 .get_eee = rtl8380_rtl8218b_get_eee_u_boot,
1239 },
1240 {
1241 PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_I),
1242 .name = "REATLTEK RTL8218B (internal)",
1243 .features = PHY_GBIT_FEATURES,
1244 .probe = rtl8218b_int_phy_probe,
1245 .suspend = genphy_suspend,
1246 .resume = genphy_resume,
1247 .set_loopback = genphy_loopback,
1248 .read_mmd = rtl8380_rtl8218b_read_mmd,
1249 .write_mmd = rtl8380_rtl8218b_write_mmd,
1250 .set_eee = rtl8380_rtl8218b_set_eee,
1251 .get_eee = rtl8380_rtl8218b_get_eee_u_boot,
1252 },
1253 {
1254 PHY_ID_MATCH_MODEL(PHY_ID_RTL8218B_I),
1255 .name = "REATLTEK RTL8380 SERDES",
1256 .features = PHY_GBIT_FIBRE_FEATURES,
1257 .probe = rtl838x_serdes_probe,
1258 .suspend = genphy_suspend,
1259 .resume = genphy_resume,
1260 .set_loopback = genphy_loopback,
1261 .read_mmd = rtl8380_rtl8218b_read_mmd,
1262 .write_mmd = rtl8380_rtl8218b_write_mmd,
1263 },
1264 {
1265 PHY_ID_MATCH_MODEL(PHY_ID_RTL8390_GENERIC),
1266 .name = "REATLTEK RTL8390 Generic",
1267 .features = PHY_GBIT_FIBRE_FEATURES,
1268 .probe = rtl8390_serdes_probe,
1269 .suspend = genphy_suspend,
1270 .resume = genphy_resume,
1271 .set_loopback = genphy_loopback,
1272 }
1273 };
1274
1275 module_phy_driver(rtl838x_phy_driver);
1276
1277 static struct mdio_device_id __maybe_unused rtl838x_tbl[] = {
1278 { PHY_ID_MATCH_MODEL(PHY_ID_RTL8214FC) },
1279 { }
1280 };
1281
1282 MODULE_DEVICE_TABLE(mdio, rtl838x_tbl);
1283
1284 MODULE_AUTHOR("B. Koblitz");
1285 MODULE_DESCRIPTION("RTL838x PHY driver");
1286 MODULE_LICENSE("GPL");