Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
[firefly-linux-kernel-4.4.55.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 <linux/module.h>
18 #include <linux/phy.h>
19
20 #define PHY_ID_BCM50610         0x0143bd60
21 #define PHY_ID_BCM50610M        0x0143bd70
22 #define PHY_ID_BCM57780         0x03625d90
23
24 #define BRCM_PHY_MODEL(phydev) \
25         ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
26
27
28 #define MII_BCM54XX_ECR         0x10    /* BCM54xx extended control register */
29 #define MII_BCM54XX_ECR_IM      0x1000  /* Interrupt mask */
30 #define MII_BCM54XX_ECR_IF      0x0800  /* Interrupt force */
31
32 #define MII_BCM54XX_ESR         0x11    /* BCM54xx extended status register */
33 #define MII_BCM54XX_ESR_IS      0x1000  /* Interrupt status */
34
35 #define MII_BCM54XX_EXP_DATA    0x15    /* Expansion register data */
36 #define MII_BCM54XX_EXP_SEL     0x17    /* Expansion register select */
37 #define MII_BCM54XX_EXP_SEL_SSD 0x0e00  /* Secondary SerDes select */
38 #define MII_BCM54XX_EXP_SEL_ER  0x0f00  /* Expansion register select */
39
40 #define MII_BCM54XX_AUX_CTL     0x18    /* Auxiliary control register */
41 #define MII_BCM54XX_ISR         0x1a    /* BCM54xx interrupt status register */
42 #define MII_BCM54XX_IMR         0x1b    /* BCM54xx interrupt mask register */
43 #define MII_BCM54XX_INT_CRCERR  0x0001  /* CRC error */
44 #define MII_BCM54XX_INT_LINK    0x0002  /* Link status changed */
45 #define MII_BCM54XX_INT_SPEED   0x0004  /* Link speed change */
46 #define MII_BCM54XX_INT_DUPLEX  0x0008  /* Duplex mode changed */
47 #define MII_BCM54XX_INT_LRS     0x0010  /* Local receiver status changed */
48 #define MII_BCM54XX_INT_RRS     0x0020  /* Remote receiver status changed */
49 #define MII_BCM54XX_INT_SSERR   0x0040  /* Scrambler synchronization error */
50 #define MII_BCM54XX_INT_UHCD    0x0080  /* Unsupported HCD negotiated */
51 #define MII_BCM54XX_INT_NHCD    0x0100  /* No HCD */
52 #define MII_BCM54XX_INT_NHCDL   0x0200  /* No HCD link */
53 #define MII_BCM54XX_INT_ANPR    0x0400  /* Auto-negotiation page received */
54 #define MII_BCM54XX_INT_LC      0x0800  /* All counters below 128 */
55 #define MII_BCM54XX_INT_HC      0x1000  /* Counter above 32768 */
56 #define MII_BCM54XX_INT_MDIX    0x2000  /* MDIX status change */
57 #define MII_BCM54XX_INT_PSERR   0x4000  /* Pair swap error */
58
59 #define MII_BCM54XX_SHD         0x1c    /* 0x1c shadow registers */
60 #define MII_BCM54XX_SHD_WRITE   0x8000
61 #define MII_BCM54XX_SHD_VAL(x)  ((x & 0x1f) << 10)
62 #define MII_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0)
63
64 /*
65  * AUXILIARY CONTROL SHADOW ACCESS REGISTERS.  (PHY REG 0x18)
66  */
67 #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL       0x0000
68 #define MII_BCM54XX_AUXCTL_ACTL_TX_6DB          0x0400
69 #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA       0x0800
70
71 #define MII_BCM54XX_AUXCTL_MISC_WREN    0x8000
72 #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX     0x0200
73 #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC      0x7000
74 #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
75
76 #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL       0x0000
77
78
79 /*
80  * Broadcom LED source encodings.  These are used in BCM5461, BCM5481,
81  * BCM5482, and possibly some others.
82  */
83 #define BCM_LED_SRC_LINKSPD1    0x0
84 #define BCM_LED_SRC_LINKSPD2    0x1
85 #define BCM_LED_SRC_XMITLED     0x2
86 #define BCM_LED_SRC_ACTIVITYLED 0x3
87 #define BCM_LED_SRC_FDXLED      0x4
88 #define BCM_LED_SRC_SLAVE       0x5
89 #define BCM_LED_SRC_INTR        0x6
90 #define BCM_LED_SRC_QUALITY     0x7
91 #define BCM_LED_SRC_RCVLED      0x8
92 #define BCM_LED_SRC_MULTICOLOR1 0xa
93 #define BCM_LED_SRC_OPENSHORT   0xb
94 #define BCM_LED_SRC_OFF         0xe     /* Tied high */
95 #define BCM_LED_SRC_ON          0xf     /* Tied low */
96
97 /*
98  * BCM5482: Shadow registers
99  * Shadow values go into bits [14:10] of register 0x1c to select a shadow
100  * register to access.
101  */
102 #define BCM5482_SHD_LEDS1       0x0d    /* 01101: LED Selector 1 */
103                                         /* LED3 / ~LINKSPD[2] selector */
104 #define BCM5482_SHD_LEDS1_LED3(src)     ((src & 0xf) << 4)
105                                         /* LED1 / ~LINKSPD[1] selector */
106 #define BCM5482_SHD_LEDS1_LED1(src)     ((src & 0xf) << 0)
107 #define BCM5482_SHD_SSD         0x14    /* 10100: Secondary SerDes control */
108 #define BCM5482_SHD_SSD_LEDM    0x0008  /* SSD LED Mode enable */
109 #define BCM5482_SHD_SSD_EN      0x0001  /* SSD enable */
110 #define BCM5482_SHD_MODE        0x1f    /* 11111: Mode Control Register */
111 #define BCM5482_SHD_MODE_1000BX 0x0001  /* Enable 1000BASE-X registers */
112
113 /*
114  * EXPANSION SHADOW ACCESS REGISTERS.  (PHY REG 0x15, 0x16, and 0x17)
115  */
116 #define MII_BCM54XX_EXP_AADJ1CH0                0x001f
117 #define  MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN  0x0200
118 #define  MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF    0x0100
119 #define MII_BCM54XX_EXP_AADJ1CH3                0x601f
120 #define  MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ      0x0002
121 #define MII_BCM54XX_EXP_EXP08                   0x0F08
122 #define  MII_BCM54XX_EXP_EXP08_RJCT_2MHZ        0x0001
123 #define  MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE   0x0200
124 #define MII_BCM54XX_EXP_EXP75                   0x0f75
125 #define  MII_BCM54XX_EXP_EXP75_VDACCTRL         0x003c
126 #define  MII_BCM54XX_EXP_EXP75_CM_OSC           0x0001
127 #define MII_BCM54XX_EXP_EXP96                   0x0f96
128 #define  MII_BCM54XX_EXP_EXP96_MYST             0x0010
129 #define MII_BCM54XX_EXP_EXP97                   0x0f97
130 #define  MII_BCM54XX_EXP_EXP97_MYST             0x0c0c
131
132 /*
133  * BCM5482: Secondary SerDes registers
134  */
135 #define BCM5482_SSD_1000BX_CTL          0x00    /* 1000BASE-X Control */
136 #define BCM5482_SSD_1000BX_CTL_PWRDOWN  0x0800  /* Power-down SSD */
137 #define BCM5482_SSD_SGMII_SLAVE         0x15    /* SGMII Slave Register */
138 #define BCM5482_SSD_SGMII_SLAVE_EN      0x0002  /* Slave mode enable */
139 #define BCM5482_SSD_SGMII_SLAVE_AD      0x0001  /* Slave auto-detection */
140
141 /*
142  * Device flags for PHYs that can be configured for different operating
143  * modes.
144  */
145 #define PHY_BCM_FLAGS_VALID             0x80000000
146 #define PHY_BCM_FLAGS_INTF_XAUI         0x00000020
147 #define PHY_BCM_FLAGS_INTF_SGMII        0x00000010
148 #define PHY_BCM_FLAGS_MODE_1000BX       0x00000002
149 #define PHY_BCM_FLAGS_MODE_COPPER       0x00000001
150
151
152 /*****************************************************************************/
153 /* Fast Ethernet Transceiver definitions. */
154 /*****************************************************************************/
155
156 #define MII_BRCM_FET_INTREG             0x1a    /* Interrupt register */
157 #define MII_BRCM_FET_IR_MASK            0x0100  /* Mask all interrupts */
158 #define MII_BRCM_FET_IR_LINK_EN         0x0200  /* Link status change enable */
159 #define MII_BRCM_FET_IR_SPEED_EN        0x0400  /* Link speed change enable */
160 #define MII_BRCM_FET_IR_DUPLEX_EN       0x0800  /* Duplex mode change enable */
161 #define MII_BRCM_FET_IR_ENABLE          0x4000  /* Interrupt enable */
162
163 #define MII_BRCM_FET_BRCMTEST           0x1f    /* Brcm test register */
164 #define MII_BRCM_FET_BT_SRE             0x0080  /* Shadow register enable */
165
166
167 /*** Shadow register definitions ***/
168
169 #define MII_BRCM_FET_SHDW_MISCCTRL      0x10    /* Shadow misc ctrl */
170 #define MII_BRCM_FET_SHDW_MC_FAME       0x4000  /* Force Auto MDIX enable */
171
172 #define MII_BRCM_FET_SHDW_AUXMODE4      0x1a    /* Auxiliary mode 4 */
173 #define MII_BRCM_FET_SHDW_AM4_LED_MASK  0x0003
174 #define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001
175
176 #define MII_BRCM_FET_SHDW_AUXSTAT2      0x1b    /* Auxiliary status 2 */
177 #define MII_BRCM_FET_SHDW_AS2_APDE      0x0020  /* Auto power down enable */
178
179
180 MODULE_DESCRIPTION("Broadcom PHY driver");
181 MODULE_AUTHOR("Maciej W. Rozycki");
182 MODULE_LICENSE("GPL");
183
184 /*
185  * Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T
186  * 0x1c shadow registers.
187  */
188 static int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow)
189 {
190         phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
191         return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
192 }
193
194 static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val)
195 {
196         return phy_write(phydev, MII_BCM54XX_SHD,
197                          MII_BCM54XX_SHD_WRITE |
198                          MII_BCM54XX_SHD_VAL(shadow) |
199                          MII_BCM54XX_SHD_DATA(val));
200 }
201
202 /* Indirect register access functions for the Expansion Registers */
203 static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
204 {
205         int val;
206
207         val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
208         if (val < 0)
209                 return val;
210
211         val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
212
213         /* Restore default value.  It's O.K. if this write fails. */
214         phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
215
216         return val;
217 }
218
219 static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
220 {
221         int ret;
222
223         ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
224         if (ret < 0)
225                 return ret;
226
227         ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
228
229         /* Restore default value.  It's O.K. if this write fails. */
230         phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
231
232         return ret;
233 }
234
235 static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
236 {
237         return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
238 }
239
240 static int bcm50610_a0_workaround(struct phy_device *phydev)
241 {
242         int err;
243
244         err = bcm54xx_auxctl_write(phydev,
245                                    MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
246                                    MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
247                                    MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
248         if (err < 0)
249                 return err;
250
251         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
252                                 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ |
253                                 MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE);
254         if (err < 0)
255                 goto error;
256
257         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
258                                 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
259                                 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
260         if (err < 0)
261                 goto error;
262
263         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
264                                         MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
265         if (err < 0)
266                 goto error;
267
268         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
269                                 MII_BCM54XX_EXP_EXP75_VDACCTRL);
270         if (err < 0)
271                 goto error;
272
273         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
274                                 MII_BCM54XX_EXP_EXP96_MYST);
275         if (err < 0)
276                 goto error;
277
278         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
279                                 MII_BCM54XX_EXP_EXP97_MYST);
280
281 error:
282         bcm54xx_auxctl_write(phydev,
283                              MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
284                              MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
285
286         return err;
287 }
288
289 static int bcm54xx_config_init(struct phy_device *phydev)
290 {
291         int reg, err;
292
293         reg = phy_read(phydev, MII_BCM54XX_ECR);
294         if (reg < 0)
295                 return reg;
296
297         /* Mask interrupts globally.  */
298         reg |= MII_BCM54XX_ECR_IM;
299         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
300         if (err < 0)
301                 return err;
302
303         /* Unmask events we are interested in.  */
304         reg = ~(MII_BCM54XX_INT_DUPLEX |
305                 MII_BCM54XX_INT_SPEED |
306                 MII_BCM54XX_INT_LINK);
307         err = phy_write(phydev, MII_BCM54XX_IMR, reg);
308         if (err < 0)
309                 return err;
310
311         if (phydev->drv->phy_id == PHY_ID_BCM50610) {
312                 err = bcm50610_a0_workaround(phydev);
313                 if (err < 0)
314                         return err;
315         }
316
317         if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
318                 int err2;
319
320                 err = bcm54xx_auxctl_write(phydev,
321                                            MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
322                                            MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
323                                            MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
324                 if (err < 0)
325                         return err;
326
327                 reg = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
328                 if (reg < 0)
329                         goto error;
330
331                 reg |= MII_BCM54XX_EXP_EXP75_CM_OSC;
332                 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, reg);
333
334 error:
335                 err2 = bcm54xx_auxctl_write(phydev,
336                                             MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
337                                             MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
338                 if (err)
339                         return err;
340                 if (err2)
341                         return err2;
342         }
343
344         return 0;
345 }
346
347 static int bcm5482_config_init(struct phy_device *phydev)
348 {
349         int err, reg;
350
351         err = bcm54xx_config_init(phydev);
352
353         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
354                 /*
355                  * Enable secondary SerDes and its use as an LED source
356                  */
357                 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
358                 bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
359                                      reg |
360                                      BCM5482_SHD_SSD_LEDM |
361                                      BCM5482_SHD_SSD_EN);
362
363                 /*
364                  * Enable SGMII slave mode and auto-detection
365                  */
366                 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
367                 err = bcm54xx_exp_read(phydev, reg);
368                 if (err < 0)
369                         return err;
370                 err = bcm54xx_exp_write(phydev, reg, err |
371                                         BCM5482_SSD_SGMII_SLAVE_EN |
372                                         BCM5482_SSD_SGMII_SLAVE_AD);
373                 if (err < 0)
374                         return err;
375
376                 /*
377                  * Disable secondary SerDes powerdown
378                  */
379                 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
380                 err = bcm54xx_exp_read(phydev, reg);
381                 if (err < 0)
382                         return err;
383                 err = bcm54xx_exp_write(phydev, reg,
384                                         err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
385                 if (err < 0)
386                         return err;
387
388                 /*
389                  * Select 1000BASE-X register set (primary SerDes)
390                  */
391                 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
392                 bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
393                                      reg | BCM5482_SHD_MODE_1000BX);
394
395                 /*
396                  * LED1=ACTIVITYLED, LED3=LINKSPD[2]
397                  * (Use LED1 as secondary SerDes ACTIVITY LED)
398                  */
399                 bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
400                         BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
401                         BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
402
403                 /*
404                  * Auto-negotiation doesn't seem to work quite right
405                  * in this mode, so we disable it and force it to the
406                  * right speed/duplex setting.  Only 'link status'
407                  * is important.
408                  */
409                 phydev->autoneg = AUTONEG_DISABLE;
410                 phydev->speed = SPEED_1000;
411                 phydev->duplex = DUPLEX_FULL;
412         }
413
414         return err;
415 }
416
417 static int bcm5482_read_status(struct phy_device *phydev)
418 {
419         int err;
420
421         err = genphy_read_status(phydev);
422
423         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
424                 /*
425                  * Only link status matters for 1000Base-X mode, so force
426                  * 1000 Mbit/s full-duplex status
427                  */
428                 if (phydev->link) {
429                         phydev->speed = SPEED_1000;
430                         phydev->duplex = DUPLEX_FULL;
431                 }
432         }
433
434         return err;
435 }
436
437 static int bcm54xx_ack_interrupt(struct phy_device *phydev)
438 {
439         int reg;
440
441         /* Clear pending interrupts.  */
442         reg = phy_read(phydev, MII_BCM54XX_ISR);
443         if (reg < 0)
444                 return reg;
445
446         return 0;
447 }
448
449 static int bcm54xx_config_intr(struct phy_device *phydev)
450 {
451         int reg, err;
452
453         reg = phy_read(phydev, MII_BCM54XX_ECR);
454         if (reg < 0)
455                 return reg;
456
457         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
458                 reg &= ~MII_BCM54XX_ECR_IM;
459         else
460                 reg |= MII_BCM54XX_ECR_IM;
461
462         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
463         return err;
464 }
465
466 static int bcm5481_config_aneg(struct phy_device *phydev)
467 {
468         int ret;
469
470         /* Aneg firsly. */
471         ret = genphy_config_aneg(phydev);
472
473         /* Then we can set up the delay. */
474         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
475                 u16 reg;
476
477                 /*
478                  * There is no BCM5481 specification available, so down
479                  * here is everything we know about "register 0x18". This
480                  * at least helps BCM5481 to successfuly receive packets
481                  * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
482                  * says: "This sets delay between the RXD and RXC signals
483                  * instead of using trace lengths to achieve timing".
484                  */
485
486                 /* Set RDX clk delay. */
487                 reg = 0x7 | (0x7 << 12);
488                 phy_write(phydev, 0x18, reg);
489
490                 reg = phy_read(phydev, 0x18);
491                 /* Set RDX-RXC skew. */
492                 reg |= (1 << 8);
493                 /* Write bits 14:0. */
494                 reg |= (1 << 15);
495                 phy_write(phydev, 0x18, reg);
496         }
497
498         return ret;
499 }
500
501 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
502 {
503         int val;
504
505         val = phy_read(phydev, reg);
506         if (val < 0)
507                 return val;
508
509         return phy_write(phydev, reg, val | set);
510 }
511
512 static int brcm_fet_config_init(struct phy_device *phydev)
513 {
514         int reg, err, err2, brcmtest;
515
516         /* Reset the PHY to bring it to a known state. */
517         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
518         if (err < 0)
519                 return err;
520
521         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
522         if (reg < 0)
523                 return reg;
524
525         /* Unmask events we are interested in and mask interrupts globally. */
526         reg = MII_BRCM_FET_IR_DUPLEX_EN |
527               MII_BRCM_FET_IR_SPEED_EN |
528               MII_BRCM_FET_IR_LINK_EN |
529               MII_BRCM_FET_IR_ENABLE |
530               MII_BRCM_FET_IR_MASK;
531
532         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
533         if (err < 0)
534                 return err;
535
536         /* Enable shadow register access */
537         brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
538         if (brcmtest < 0)
539                 return brcmtest;
540
541         reg = brcmtest | MII_BRCM_FET_BT_SRE;
542
543         err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
544         if (err < 0)
545                 return err;
546
547         /* Set the LED mode */
548         reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
549         if (reg < 0) {
550                 err = reg;
551                 goto done;
552         }
553
554         reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
555         reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
556
557         err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
558         if (err < 0)
559                 goto done;
560
561         /* Enable auto MDIX */
562         err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
563                                        MII_BRCM_FET_SHDW_MC_FAME);
564         if (err < 0)
565                 goto done;
566
567         /* Enable auto power down */
568         err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
569                                        MII_BRCM_FET_SHDW_AS2_APDE);
570
571 done:
572         /* Disable shadow register access */
573         err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
574         if (!err)
575                 err = err2;
576
577         return err;
578 }
579
580 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
581 {
582         int reg;
583
584         /* Clear pending interrupts.  */
585         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
586         if (reg < 0)
587                 return reg;
588
589         return 0;
590 }
591
592 static int brcm_fet_config_intr(struct phy_device *phydev)
593 {
594         int reg, err;
595
596         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
597         if (reg < 0)
598                 return reg;
599
600         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
601                 reg &= ~MII_BRCM_FET_IR_MASK;
602         else
603                 reg |= MII_BRCM_FET_IR_MASK;
604
605         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
606         return err;
607 }
608
609 static struct phy_driver bcm5411_driver = {
610         .phy_id         = 0x00206070,
611         .phy_id_mask    = 0xfffffff0,
612         .name           = "Broadcom BCM5411",
613         .features       = PHY_GBIT_FEATURES |
614                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
615         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
616         .config_init    = bcm54xx_config_init,
617         .config_aneg    = genphy_config_aneg,
618         .read_status    = genphy_read_status,
619         .ack_interrupt  = bcm54xx_ack_interrupt,
620         .config_intr    = bcm54xx_config_intr,
621         .driver         = { .owner = THIS_MODULE },
622 };
623
624 static struct phy_driver bcm5421_driver = {
625         .phy_id         = 0x002060e0,
626         .phy_id_mask    = 0xfffffff0,
627         .name           = "Broadcom BCM5421",
628         .features       = PHY_GBIT_FEATURES |
629                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
630         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
631         .config_init    = bcm54xx_config_init,
632         .config_aneg    = genphy_config_aneg,
633         .read_status    = genphy_read_status,
634         .ack_interrupt  = bcm54xx_ack_interrupt,
635         .config_intr    = bcm54xx_config_intr,
636         .driver         = { .owner = THIS_MODULE },
637 };
638
639 static struct phy_driver bcm5461_driver = {
640         .phy_id         = 0x002060c0,
641         .phy_id_mask    = 0xfffffff0,
642         .name           = "Broadcom BCM5461",
643         .features       = PHY_GBIT_FEATURES |
644                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
645         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
646         .config_init    = bcm54xx_config_init,
647         .config_aneg    = genphy_config_aneg,
648         .read_status    = genphy_read_status,
649         .ack_interrupt  = bcm54xx_ack_interrupt,
650         .config_intr    = bcm54xx_config_intr,
651         .driver         = { .owner = THIS_MODULE },
652 };
653
654 static struct phy_driver bcm5464_driver = {
655         .phy_id         = 0x002060b0,
656         .phy_id_mask    = 0xfffffff0,
657         .name           = "Broadcom BCM5464",
658         .features       = PHY_GBIT_FEATURES |
659                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
660         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
661         .config_init    = bcm54xx_config_init,
662         .config_aneg    = genphy_config_aneg,
663         .read_status    = genphy_read_status,
664         .ack_interrupt  = bcm54xx_ack_interrupt,
665         .config_intr    = bcm54xx_config_intr,
666         .driver         = { .owner = THIS_MODULE },
667 };
668
669 static struct phy_driver bcm5481_driver = {
670         .phy_id         = 0x0143bca0,
671         .phy_id_mask    = 0xfffffff0,
672         .name           = "Broadcom BCM5481",
673         .features       = PHY_GBIT_FEATURES |
674                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
675         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
676         .config_init    = bcm54xx_config_init,
677         .config_aneg    = bcm5481_config_aneg,
678         .read_status    = genphy_read_status,
679         .ack_interrupt  = bcm54xx_ack_interrupt,
680         .config_intr    = bcm54xx_config_intr,
681         .driver         = { .owner = THIS_MODULE },
682 };
683
684 static struct phy_driver bcm5482_driver = {
685         .phy_id         = 0x0143bcb0,
686         .phy_id_mask    = 0xfffffff0,
687         .name           = "Broadcom BCM5482",
688         .features       = PHY_GBIT_FEATURES |
689                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
690         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
691         .config_init    = bcm5482_config_init,
692         .config_aneg    = genphy_config_aneg,
693         .read_status    = bcm5482_read_status,
694         .ack_interrupt  = bcm54xx_ack_interrupt,
695         .config_intr    = bcm54xx_config_intr,
696         .driver         = { .owner = THIS_MODULE },
697 };
698
699 static struct phy_driver bcm50610_driver = {
700         .phy_id         = PHY_ID_BCM50610,
701         .phy_id_mask    = 0xfffffff0,
702         .name           = "Broadcom BCM50610",
703         .features       = PHY_GBIT_FEATURES |
704                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
705         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
706         .config_init    = bcm54xx_config_init,
707         .config_aneg    = genphy_config_aneg,
708         .read_status    = genphy_read_status,
709         .ack_interrupt  = bcm54xx_ack_interrupt,
710         .config_intr    = bcm54xx_config_intr,
711         .driver         = { .owner = THIS_MODULE },
712 };
713
714 static struct phy_driver bcm50610m_driver = {
715         .phy_id         = PHY_ID_BCM50610M,
716         .phy_id_mask    = 0xfffffff0,
717         .name           = "Broadcom BCM50610M",
718         .features       = PHY_GBIT_FEATURES |
719                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
720         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
721         .config_init    = bcm54xx_config_init,
722         .config_aneg    = genphy_config_aneg,
723         .read_status    = genphy_read_status,
724         .ack_interrupt  = bcm54xx_ack_interrupt,
725         .config_intr    = bcm54xx_config_intr,
726         .driver         = { .owner = THIS_MODULE },
727 };
728
729 static struct phy_driver bcm57780_driver = {
730         .phy_id         = PHY_ID_BCM57780,
731         .phy_id_mask    = 0xfffffff0,
732         .name           = "Broadcom BCM57780",
733         .features       = PHY_GBIT_FEATURES |
734                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
735         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
736         .config_init    = bcm54xx_config_init,
737         .config_aneg    = genphy_config_aneg,
738         .read_status    = genphy_read_status,
739         .ack_interrupt  = bcm54xx_ack_interrupt,
740         .config_intr    = bcm54xx_config_intr,
741         .driver         = { .owner = THIS_MODULE },
742 };
743
744 static struct phy_driver bcmac131_driver = {
745         .phy_id         = 0x0143bc70,
746         .phy_id_mask    = 0xfffffff0,
747         .name           = "Broadcom BCMAC131",
748         .features       = PHY_BASIC_FEATURES |
749                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
750         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
751         .config_init    = brcm_fet_config_init,
752         .config_aneg    = genphy_config_aneg,
753         .read_status    = genphy_read_status,
754         .ack_interrupt  = brcm_fet_ack_interrupt,
755         .config_intr    = brcm_fet_config_intr,
756         .driver         = { .owner = THIS_MODULE },
757 };
758
759 static int __init broadcom_init(void)
760 {
761         int ret;
762
763         ret = phy_driver_register(&bcm5411_driver);
764         if (ret)
765                 goto out_5411;
766         ret = phy_driver_register(&bcm5421_driver);
767         if (ret)
768                 goto out_5421;
769         ret = phy_driver_register(&bcm5461_driver);
770         if (ret)
771                 goto out_5461;
772         ret = phy_driver_register(&bcm5464_driver);
773         if (ret)
774                 goto out_5464;
775         ret = phy_driver_register(&bcm5481_driver);
776         if (ret)
777                 goto out_5481;
778         ret = phy_driver_register(&bcm5482_driver);
779         if (ret)
780                 goto out_5482;
781         ret = phy_driver_register(&bcm50610_driver);
782         if (ret)
783                 goto out_50610;
784         ret = phy_driver_register(&bcm50610m_driver);
785         if (ret)
786                 goto out_50610m;
787         ret = phy_driver_register(&bcm57780_driver);
788         if (ret)
789                 goto out_57780;
790         ret = phy_driver_register(&bcmac131_driver);
791         if (ret)
792                 goto out_ac131;
793         return ret;
794
795 out_ac131:
796         phy_driver_unregister(&bcm57780_driver);
797 out_57780:
798         phy_driver_unregister(&bcm50610m_driver);
799 out_50610m:
800         phy_driver_unregister(&bcm50610_driver);
801 out_50610:
802         phy_driver_unregister(&bcm5482_driver);
803 out_5482:
804         phy_driver_unregister(&bcm5481_driver);
805 out_5481:
806         phy_driver_unregister(&bcm5464_driver);
807 out_5464:
808         phy_driver_unregister(&bcm5461_driver);
809 out_5461:
810         phy_driver_unregister(&bcm5421_driver);
811 out_5421:
812         phy_driver_unregister(&bcm5411_driver);
813 out_5411:
814         return ret;
815 }
816
817 static void __exit broadcom_exit(void)
818 {
819         phy_driver_unregister(&bcmac131_driver);
820         phy_driver_unregister(&bcm57780_driver);
821         phy_driver_unregister(&bcm50610m_driver);
822         phy_driver_unregister(&bcm50610_driver);
823         phy_driver_unregister(&bcm5482_driver);
824         phy_driver_unregister(&bcm5481_driver);
825         phy_driver_unregister(&bcm5464_driver);
826         phy_driver_unregister(&bcm5461_driver);
827         phy_driver_unregister(&bcm5421_driver);
828         phy_driver_unregister(&bcm5411_driver);
829 }
830
831 module_init(broadcom_init);
832 module_exit(broadcom_exit);