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