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