]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/phy/broadcom.c
net: hix5hd2_gmac: fix compatible strings name
[karo-tx-linux.git] / drivers / net / phy / broadcom.c
1 /*
2  *      drivers/net/phy/broadcom.c
3  *
4  *      Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
5  *      transceivers.
6  *
7  *      Copyright (c) 2006  Maciej W. Rozycki
8  *
9  *      Inspired by code written by Amy Fong.
10  *
11  *      This program is free software; you can redistribute it and/or
12  *      modify it under the terms of the GNU General Public License
13  *      as published by the Free Software Foundation; either version
14  *      2 of the License, or (at your option) any later version.
15  */
16
17 #include "bcm-phy-lib.h"
18 #include <linux/module.h>
19 #include <linux/phy.h>
20 #include <linux/brcmphy.h>
21 #include <linux/of.h>
22
23 #define BRCM_PHY_MODEL(phydev) \
24         ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
25
26 #define BRCM_PHY_REV(phydev) \
27         ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
28
29 MODULE_DESCRIPTION("Broadcom PHY driver");
30 MODULE_AUTHOR("Maciej W. Rozycki");
31 MODULE_LICENSE("GPL");
32
33 static int bcm54810_config(struct phy_device *phydev)
34 {
35         int rc, val;
36
37         val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
38         val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
39         rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
40                                val);
41         if (rc < 0)
42                 return rc;
43
44         val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
45         val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
46         val |= MII_BCM54XX_AUXCTL_MISC_WREN;
47         rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
48                                   val);
49         if (rc < 0)
50                 return rc;
51
52         val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
53         val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
54         rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
55         if (rc < 0)
56                 return rc;
57
58         return 0;
59 }
60
61 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
62 static int bcm50610_a0_workaround(struct phy_device *phydev)
63 {
64         int err;
65
66         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
67                                 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
68                                 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
69         if (err < 0)
70                 return err;
71
72         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
73                                 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
74         if (err < 0)
75                 return err;
76
77         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
78                                 MII_BCM54XX_EXP_EXP75_VDACCTRL);
79         if (err < 0)
80                 return err;
81
82         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
83                                 MII_BCM54XX_EXP_EXP96_MYST);
84         if (err < 0)
85                 return err;
86
87         err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
88                                 MII_BCM54XX_EXP_EXP97_MYST);
89
90         return err;
91 }
92
93 static int bcm54xx_phydsp_config(struct phy_device *phydev)
94 {
95         int err, err2;
96
97         /* Enable the SMDSP clock */
98         err = bcm54xx_auxctl_write(phydev,
99                                    MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
100                                    MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
101                                    MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
102         if (err < 0)
103                 return err;
104
105         if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
106             BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
107                 /* Clear bit 9 to fix a phy interop issue. */
108                 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
109                                         MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
110                 if (err < 0)
111                         goto error;
112
113                 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
114                         err = bcm50610_a0_workaround(phydev);
115                         if (err < 0)
116                                 goto error;
117                 }
118         }
119
120         if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
121                 int val;
122
123                 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
124                 if (val < 0)
125                         goto error;
126
127                 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
128                 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
129         }
130
131 error:
132         /* Disable the SMDSP clock */
133         err2 = bcm54xx_auxctl_write(phydev,
134                                     MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
135                                     MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
136
137         /* Return the first error reported. */
138         return err ? err : err2;
139 }
140
141 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
142 {
143         u32 orig;
144         int val;
145         bool clk125en = true;
146
147         /* Abort if we are using an untested phy. */
148         if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
149             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
150             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
151                 return;
152
153         val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
154         if (val < 0)
155                 return;
156
157         orig = val;
158
159         if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
160              BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
161             BRCM_PHY_REV(phydev) >= 0x3) {
162                 /*
163                  * Here, bit 0 _disables_ CLK125 when set.
164                  * This bit is set by default.
165                  */
166                 clk125en = false;
167         } else {
168                 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
169                         /* Here, bit 0 _enables_ CLK125 when set */
170                         val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
171                         clk125en = false;
172                 }
173         }
174
175         if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
176                 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
177         else
178                 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
179
180         if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
181                 val |= BCM54XX_SHD_SCR3_TRDDAPD;
182
183         if (orig != val)
184                 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
185
186         val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
187         if (val < 0)
188                 return;
189
190         orig = val;
191
192         if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
193                 val |= BCM54XX_SHD_APD_EN;
194         else
195                 val &= ~BCM54XX_SHD_APD_EN;
196
197         if (orig != val)
198                 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
199 }
200
201 static int bcm54xx_config_init(struct phy_device *phydev)
202 {
203         int reg, err;
204
205         reg = phy_read(phydev, MII_BCM54XX_ECR);
206         if (reg < 0)
207                 return reg;
208
209         /* Mask interrupts globally.  */
210         reg |= MII_BCM54XX_ECR_IM;
211         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
212         if (err < 0)
213                 return err;
214
215         /* Unmask events we are interested in.  */
216         reg = ~(MII_BCM54XX_INT_DUPLEX |
217                 MII_BCM54XX_INT_SPEED |
218                 MII_BCM54XX_INT_LINK);
219         err = phy_write(phydev, MII_BCM54XX_IMR, reg);
220         if (err < 0)
221                 return err;
222
223         if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
224              BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
225             (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
226                 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
227
228         if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
229             (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
230             (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
231                 bcm54xx_adjust_rxrefclk(phydev);
232
233         if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
234                 err = bcm54810_config(phydev);
235                 if (err)
236                         return err;
237         }
238
239         bcm54xx_phydsp_config(phydev);
240
241         return 0;
242 }
243
244 static int bcm5482_config_init(struct phy_device *phydev)
245 {
246         int err, reg;
247
248         err = bcm54xx_config_init(phydev);
249
250         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
251                 /*
252                  * Enable secondary SerDes and its use as an LED source
253                  */
254                 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD);
255                 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD,
256                                      reg |
257                                      BCM5482_SHD_SSD_LEDM |
258                                      BCM5482_SHD_SSD_EN);
259
260                 /*
261                  * Enable SGMII slave mode and auto-detection
262                  */
263                 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
264                 err = bcm_phy_read_exp(phydev, reg);
265                 if (err < 0)
266                         return err;
267                 err = bcm_phy_write_exp(phydev, reg, err |
268                                         BCM5482_SSD_SGMII_SLAVE_EN |
269                                         BCM5482_SSD_SGMII_SLAVE_AD);
270                 if (err < 0)
271                         return err;
272
273                 /*
274                  * Disable secondary SerDes powerdown
275                  */
276                 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
277                 err = bcm_phy_read_exp(phydev, reg);
278                 if (err < 0)
279                         return err;
280                 err = bcm_phy_write_exp(phydev, reg,
281                                         err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
282                 if (err < 0)
283                         return err;
284
285                 /*
286                  * Select 1000BASE-X register set (primary SerDes)
287                  */
288                 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
289                 bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
290                                      reg | BCM5482_SHD_MODE_1000BX);
291
292                 /*
293                  * LED1=ACTIVITYLED, LED3=LINKSPD[2]
294                  * (Use LED1 as secondary SerDes ACTIVITY LED)
295                  */
296                 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1,
297                         BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
298                         BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
299
300                 /*
301                  * Auto-negotiation doesn't seem to work quite right
302                  * in this mode, so we disable it and force it to the
303                  * right speed/duplex setting.  Only 'link status'
304                  * is important.
305                  */
306                 phydev->autoneg = AUTONEG_DISABLE;
307                 phydev->speed = SPEED_1000;
308                 phydev->duplex = DUPLEX_FULL;
309         }
310
311         return err;
312 }
313
314 static int bcm5482_read_status(struct phy_device *phydev)
315 {
316         int err;
317
318         err = genphy_read_status(phydev);
319
320         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
321                 /*
322                  * Only link status matters for 1000Base-X mode, so force
323                  * 1000 Mbit/s full-duplex status
324                  */
325                 if (phydev->link) {
326                         phydev->speed = SPEED_1000;
327                         phydev->duplex = DUPLEX_FULL;
328                 }
329         }
330
331         return err;
332 }
333
334 static int bcm5481_config_aneg(struct phy_device *phydev)
335 {
336         struct device_node *np = phydev->mdio.dev.of_node;
337         int ret;
338
339         /* Aneg firsly. */
340         ret = genphy_config_aneg(phydev);
341
342         /* Then we can set up the delay. */
343         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
344                 u16 reg;
345
346                 /*
347                  * There is no BCM5481 specification available, so down
348                  * here is everything we know about "register 0x18". This
349                  * at least helps BCM5481 to successfully receive packets
350                  * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
351                  * says: "This sets delay between the RXD and RXC signals
352                  * instead of using trace lengths to achieve timing".
353                  */
354
355                 /* Set RDX clk delay. */
356                 reg = 0x7 | (0x7 << 12);
357                 phy_write(phydev, 0x18, reg);
358
359                 reg = phy_read(phydev, 0x18);
360                 /* Set RDX-RXC skew. */
361                 reg |= (1 << 8);
362                 /* Write bits 14:0. */
363                 reg |= (1 << 15);
364                 phy_write(phydev, 0x18, reg);
365         }
366
367         if (of_property_read_bool(np, "enet-phy-lane-swap")) {
368                 /* Lane Swap - Undocumented register...magic! */
369                 ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
370                                         0x11B);
371                 if (ret < 0)
372                         return ret;
373         }
374
375         return ret;
376 }
377
378 static int bcm54612e_config_aneg(struct phy_device *phydev)
379 {
380         int ret;
381
382         /* First, auto-negotiate. */
383         ret = genphy_config_aneg(phydev);
384
385         /* Clear TX internal delay unless requested. */
386         if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
387             (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
388                 /* Disable TXD to GTXCLK clock delay (default set) */
389                 /* Bit 9 is the only field in shadow register 00011 */
390                 bcm_phy_write_shadow(phydev, 0x03, 0);
391         }
392
393         /* Clear RX internal delay unless requested. */
394         if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
395             (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
396                 u16 reg;
397
398                 /* Errata: reads require filling in the write selector field */
399                 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
400                                      MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
401                 reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
402                 /* Disable RXD to RXC delay (default set) */
403                 reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
404                 /* Clear shadow selector field */
405                 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
406                 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
407                                      MII_BCM54XX_AUXCTL_MISC_WREN | reg);
408         }
409
410         return ret;
411 }
412
413 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
414 {
415         int val;
416
417         val = phy_read(phydev, reg);
418         if (val < 0)
419                 return val;
420
421         return phy_write(phydev, reg, val | set);
422 }
423
424 static int brcm_fet_config_init(struct phy_device *phydev)
425 {
426         int reg, err, err2, brcmtest;
427
428         /* Reset the PHY to bring it to a known state. */
429         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
430         if (err < 0)
431                 return err;
432
433         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
434         if (reg < 0)
435                 return reg;
436
437         /* Unmask events we are interested in and mask interrupts globally. */
438         reg = MII_BRCM_FET_IR_DUPLEX_EN |
439               MII_BRCM_FET_IR_SPEED_EN |
440               MII_BRCM_FET_IR_LINK_EN |
441               MII_BRCM_FET_IR_ENABLE |
442               MII_BRCM_FET_IR_MASK;
443
444         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
445         if (err < 0)
446                 return err;
447
448         /* Enable shadow register access */
449         brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
450         if (brcmtest < 0)
451                 return brcmtest;
452
453         reg = brcmtest | MII_BRCM_FET_BT_SRE;
454
455         err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
456         if (err < 0)
457                 return err;
458
459         /* Set the LED mode */
460         reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
461         if (reg < 0) {
462                 err = reg;
463                 goto done;
464         }
465
466         reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
467         reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
468
469         err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
470         if (err < 0)
471                 goto done;
472
473         /* Enable auto MDIX */
474         err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
475                                        MII_BRCM_FET_SHDW_MC_FAME);
476         if (err < 0)
477                 goto done;
478
479         if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
480                 /* Enable auto power down */
481                 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
482                                                MII_BRCM_FET_SHDW_AS2_APDE);
483         }
484
485 done:
486         /* Disable shadow register access */
487         err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
488         if (!err)
489                 err = err2;
490
491         return err;
492 }
493
494 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
495 {
496         int reg;
497
498         /* Clear pending interrupts.  */
499         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
500         if (reg < 0)
501                 return reg;
502
503         return 0;
504 }
505
506 static int brcm_fet_config_intr(struct phy_device *phydev)
507 {
508         int reg, err;
509
510         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
511         if (reg < 0)
512                 return reg;
513
514         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
515                 reg &= ~MII_BRCM_FET_IR_MASK;
516         else
517                 reg |= MII_BRCM_FET_IR_MASK;
518
519         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
520         return err;
521 }
522
523 static struct phy_driver broadcom_drivers[] = {
524 {
525         .phy_id         = PHY_ID_BCM5411,
526         .phy_id_mask    = 0xfffffff0,
527         .name           = "Broadcom BCM5411",
528         .features       = PHY_GBIT_FEATURES,
529         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
530         .config_init    = bcm54xx_config_init,
531         .config_aneg    = genphy_config_aneg,
532         .read_status    = genphy_read_status,
533         .ack_interrupt  = bcm_phy_ack_intr,
534         .config_intr    = bcm_phy_config_intr,
535 }, {
536         .phy_id         = PHY_ID_BCM5421,
537         .phy_id_mask    = 0xfffffff0,
538         .name           = "Broadcom BCM5421",
539         .features       = PHY_GBIT_FEATURES,
540         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
541         .config_init    = bcm54xx_config_init,
542         .config_aneg    = genphy_config_aneg,
543         .read_status    = genphy_read_status,
544         .ack_interrupt  = bcm_phy_ack_intr,
545         .config_intr    = bcm_phy_config_intr,
546 }, {
547         .phy_id         = PHY_ID_BCM5461,
548         .phy_id_mask    = 0xfffffff0,
549         .name           = "Broadcom BCM5461",
550         .features       = PHY_GBIT_FEATURES,
551         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
552         .config_init    = bcm54xx_config_init,
553         .config_aneg    = genphy_config_aneg,
554         .read_status    = genphy_read_status,
555         .ack_interrupt  = bcm_phy_ack_intr,
556         .config_intr    = bcm_phy_config_intr,
557 }, {
558         .phy_id         = PHY_ID_BCM54612E,
559         .phy_id_mask    = 0xfffffff0,
560         .name           = "Broadcom BCM54612E",
561         .features       = PHY_GBIT_FEATURES,
562         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
563         .config_init    = bcm54xx_config_init,
564         .config_aneg    = bcm54612e_config_aneg,
565         .read_status    = genphy_read_status,
566         .ack_interrupt  = bcm_phy_ack_intr,
567         .config_intr    = bcm_phy_config_intr,
568 }, {
569         .phy_id         = PHY_ID_BCM54616S,
570         .phy_id_mask    = 0xfffffff0,
571         .name           = "Broadcom BCM54616S",
572         .features       = PHY_GBIT_FEATURES,
573         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
574         .config_init    = bcm54xx_config_init,
575         .config_aneg    = genphy_config_aneg,
576         .read_status    = genphy_read_status,
577         .ack_interrupt  = bcm_phy_ack_intr,
578         .config_intr    = bcm_phy_config_intr,
579 }, {
580         .phy_id         = PHY_ID_BCM5464,
581         .phy_id_mask    = 0xfffffff0,
582         .name           = "Broadcom BCM5464",
583         .features       = PHY_GBIT_FEATURES,
584         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
585         .config_init    = bcm54xx_config_init,
586         .config_aneg    = genphy_config_aneg,
587         .read_status    = genphy_read_status,
588         .ack_interrupt  = bcm_phy_ack_intr,
589         .config_intr    = bcm_phy_config_intr,
590 }, {
591         .phy_id         = PHY_ID_BCM5481,
592         .phy_id_mask    = 0xfffffff0,
593         .name           = "Broadcom BCM5481",
594         .features       = PHY_GBIT_FEATURES,
595         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
596         .config_init    = bcm54xx_config_init,
597         .config_aneg    = bcm5481_config_aneg,
598         .read_status    = genphy_read_status,
599         .ack_interrupt  = bcm_phy_ack_intr,
600         .config_intr    = bcm_phy_config_intr,
601 }, {
602         .phy_id         = PHY_ID_BCM54810,
603         .phy_id_mask    = 0xfffffff0,
604         .name           = "Broadcom BCM54810",
605         .features       = PHY_GBIT_FEATURES,
606         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
607         .config_init    = bcm54xx_config_init,
608         .config_aneg    = bcm5481_config_aneg,
609         .read_status    = genphy_read_status,
610         .ack_interrupt  = bcm_phy_ack_intr,
611         .config_intr    = bcm_phy_config_intr,
612 }, {
613         .phy_id         = PHY_ID_BCM5482,
614         .phy_id_mask    = 0xfffffff0,
615         .name           = "Broadcom BCM5482",
616         .features       = PHY_GBIT_FEATURES,
617         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
618         .config_init    = bcm5482_config_init,
619         .config_aneg    = genphy_config_aneg,
620         .read_status    = bcm5482_read_status,
621         .ack_interrupt  = bcm_phy_ack_intr,
622         .config_intr    = bcm_phy_config_intr,
623 }, {
624         .phy_id         = PHY_ID_BCM50610,
625         .phy_id_mask    = 0xfffffff0,
626         .name           = "Broadcom BCM50610",
627         .features       = PHY_GBIT_FEATURES,
628         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
629         .config_init    = bcm54xx_config_init,
630         .config_aneg    = genphy_config_aneg,
631         .read_status    = genphy_read_status,
632         .ack_interrupt  = bcm_phy_ack_intr,
633         .config_intr    = bcm_phy_config_intr,
634 }, {
635         .phy_id         = PHY_ID_BCM50610M,
636         .phy_id_mask    = 0xfffffff0,
637         .name           = "Broadcom BCM50610M",
638         .features       = PHY_GBIT_FEATURES,
639         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
640         .config_init    = bcm54xx_config_init,
641         .config_aneg    = genphy_config_aneg,
642         .read_status    = genphy_read_status,
643         .ack_interrupt  = bcm_phy_ack_intr,
644         .config_intr    = bcm_phy_config_intr,
645 }, {
646         .phy_id         = PHY_ID_BCM57780,
647         .phy_id_mask    = 0xfffffff0,
648         .name           = "Broadcom BCM57780",
649         .features       = PHY_GBIT_FEATURES,
650         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
651         .config_init    = bcm54xx_config_init,
652         .config_aneg    = genphy_config_aneg,
653         .read_status    = genphy_read_status,
654         .ack_interrupt  = bcm_phy_ack_intr,
655         .config_intr    = bcm_phy_config_intr,
656 }, {
657         .phy_id         = PHY_ID_BCMAC131,
658         .phy_id_mask    = 0xfffffff0,
659         .name           = "Broadcom BCMAC131",
660         .features       = PHY_BASIC_FEATURES,
661         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
662         .config_init    = brcm_fet_config_init,
663         .config_aneg    = genphy_config_aneg,
664         .read_status    = genphy_read_status,
665         .ack_interrupt  = brcm_fet_ack_interrupt,
666         .config_intr    = brcm_fet_config_intr,
667 }, {
668         .phy_id         = PHY_ID_BCM5241,
669         .phy_id_mask    = 0xfffffff0,
670         .name           = "Broadcom BCM5241",
671         .features       = PHY_BASIC_FEATURES,
672         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
673         .config_init    = brcm_fet_config_init,
674         .config_aneg    = genphy_config_aneg,
675         .read_status    = genphy_read_status,
676         .ack_interrupt  = brcm_fet_ack_interrupt,
677         .config_intr    = brcm_fet_config_intr,
678 } };
679
680 module_phy_driver(broadcom_drivers);
681
682 static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
683         { PHY_ID_BCM5411, 0xfffffff0 },
684         { PHY_ID_BCM5421, 0xfffffff0 },
685         { PHY_ID_BCM5461, 0xfffffff0 },
686         { PHY_ID_BCM54612E, 0xfffffff0 },
687         { PHY_ID_BCM54616S, 0xfffffff0 },
688         { PHY_ID_BCM5464, 0xfffffff0 },
689         { PHY_ID_BCM5481, 0xfffffff0 },
690         { PHY_ID_BCM54810, 0xfffffff0 },
691         { PHY_ID_BCM5482, 0xfffffff0 },
692         { PHY_ID_BCM50610, 0xfffffff0 },
693         { PHY_ID_BCM50610M, 0xfffffff0 },
694         { PHY_ID_BCM57780, 0xfffffff0 },
695         { PHY_ID_BCMAC131, 0xfffffff0 },
696         { PHY_ID_BCM5241, 0xfffffff0 },
697         { }
698 };
699
700 MODULE_DEVICE_TABLE(mdio, broadcom_tbl);