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