]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/net/phy/broadcom.c
9e574ceacf43f55c315593200c7263a1471640a6
[net-next-2.6.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 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
241 static int bcm50610_a0_workaround(struct phy_device *phydev)
242 {
243         int err;
244
245         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
246                                 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ |
247                                 MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE);
248         if (err < 0)
249                 return err;
250
251         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
252                                 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
253                                 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
254         if (err < 0)
255                 return err;
256
257         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
258                                         MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
259         if (err < 0)
260                 return err;
261
262         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
263                                 MII_BCM54XX_EXP_EXP75_VDACCTRL);
264         if (err < 0)
265                 return err;
266
267         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
268                                 MII_BCM54XX_EXP_EXP96_MYST);
269         if (err < 0)
270                 return err;
271
272         err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
273                                 MII_BCM54XX_EXP_EXP97_MYST);
274
275         return err;
276 }
277
278 static int bcm54xx_phydsp_config(struct phy_device *phydev)
279 {
280         int err, err2;
281
282         /* Enable the SMDSP clock */
283         err = bcm54xx_auxctl_write(phydev,
284                                    MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
285                                    MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
286                                    MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
287         if (err < 0)
288                 return err;
289
290         if (phydev->drv->phy_id == PHY_ID_BCM50610)
291                 err = bcm50610_a0_workaround(phydev);
292
293         if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
294                 int val;
295
296                 val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
297                 if (val < 0)
298                         goto error;
299
300                 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
301                 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
302         }
303
304 error:
305         /* Disable the SMDSP clock */
306         err2 = bcm54xx_auxctl_write(phydev,
307                                     MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
308                                     MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
309
310         /* Return the first error reported. */
311         return err ? err : err2;
312 }
313
314 static int bcm54xx_config_init(struct phy_device *phydev)
315 {
316         int reg, err;
317
318         reg = phy_read(phydev, MII_BCM54XX_ECR);
319         if (reg < 0)
320                 return reg;
321
322         /* Mask interrupts globally.  */
323         reg |= MII_BCM54XX_ECR_IM;
324         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
325         if (err < 0)
326                 return err;
327
328         /* Unmask events we are interested in.  */
329         reg = ~(MII_BCM54XX_INT_DUPLEX |
330                 MII_BCM54XX_INT_SPEED |
331                 MII_BCM54XX_INT_LINK);
332         err = phy_write(phydev, MII_BCM54XX_IMR, reg);
333         if (err < 0)
334                 return err;
335
336         bcm54xx_phydsp_config(phydev);
337
338         return 0;
339 }
340
341 static int bcm5482_config_init(struct phy_device *phydev)
342 {
343         int err, reg;
344
345         err = bcm54xx_config_init(phydev);
346
347         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
348                 /*
349                  * Enable secondary SerDes and its use as an LED source
350                  */
351                 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
352                 bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
353                                      reg |
354                                      BCM5482_SHD_SSD_LEDM |
355                                      BCM5482_SHD_SSD_EN);
356
357                 /*
358                  * Enable SGMII slave mode and auto-detection
359                  */
360                 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
361                 err = bcm54xx_exp_read(phydev, reg);
362                 if (err < 0)
363                         return err;
364                 err = bcm54xx_exp_write(phydev, reg, err |
365                                         BCM5482_SSD_SGMII_SLAVE_EN |
366                                         BCM5482_SSD_SGMII_SLAVE_AD);
367                 if (err < 0)
368                         return err;
369
370                 /*
371                  * Disable secondary SerDes powerdown
372                  */
373                 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
374                 err = bcm54xx_exp_read(phydev, reg);
375                 if (err < 0)
376                         return err;
377                 err = bcm54xx_exp_write(phydev, reg,
378                                         err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
379                 if (err < 0)
380                         return err;
381
382                 /*
383                  * Select 1000BASE-X register set (primary SerDes)
384                  */
385                 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
386                 bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
387                                      reg | BCM5482_SHD_MODE_1000BX);
388
389                 /*
390                  * LED1=ACTIVITYLED, LED3=LINKSPD[2]
391                  * (Use LED1 as secondary SerDes ACTIVITY LED)
392                  */
393                 bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
394                         BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
395                         BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
396
397                 /*
398                  * Auto-negotiation doesn't seem to work quite right
399                  * in this mode, so we disable it and force it to the
400                  * right speed/duplex setting.  Only 'link status'
401                  * is important.
402                  */
403                 phydev->autoneg = AUTONEG_DISABLE;
404                 phydev->speed = SPEED_1000;
405                 phydev->duplex = DUPLEX_FULL;
406         }
407
408         return err;
409 }
410
411 static int bcm5482_read_status(struct phy_device *phydev)
412 {
413         int err;
414
415         err = genphy_read_status(phydev);
416
417         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
418                 /*
419                  * Only link status matters for 1000Base-X mode, so force
420                  * 1000 Mbit/s full-duplex status
421                  */
422                 if (phydev->link) {
423                         phydev->speed = SPEED_1000;
424                         phydev->duplex = DUPLEX_FULL;
425                 }
426         }
427
428         return err;
429 }
430
431 static int bcm54xx_ack_interrupt(struct phy_device *phydev)
432 {
433         int reg;
434
435         /* Clear pending interrupts.  */
436         reg = phy_read(phydev, MII_BCM54XX_ISR);
437         if (reg < 0)
438                 return reg;
439
440         return 0;
441 }
442
443 static int bcm54xx_config_intr(struct phy_device *phydev)
444 {
445         int reg, err;
446
447         reg = phy_read(phydev, MII_BCM54XX_ECR);
448         if (reg < 0)
449                 return reg;
450
451         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
452                 reg &= ~MII_BCM54XX_ECR_IM;
453         else
454                 reg |= MII_BCM54XX_ECR_IM;
455
456         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
457         return err;
458 }
459
460 static int bcm5481_config_aneg(struct phy_device *phydev)
461 {
462         int ret;
463
464         /* Aneg firsly. */
465         ret = genphy_config_aneg(phydev);
466
467         /* Then we can set up the delay. */
468         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
469                 u16 reg;
470
471                 /*
472                  * There is no BCM5481 specification available, so down
473                  * here is everything we know about "register 0x18". This
474                  * at least helps BCM5481 to successfuly receive packets
475                  * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
476                  * says: "This sets delay between the RXD and RXC signals
477                  * instead of using trace lengths to achieve timing".
478                  */
479
480                 /* Set RDX clk delay. */
481                 reg = 0x7 | (0x7 << 12);
482                 phy_write(phydev, 0x18, reg);
483
484                 reg = phy_read(phydev, 0x18);
485                 /* Set RDX-RXC skew. */
486                 reg |= (1 << 8);
487                 /* Write bits 14:0. */
488                 reg |= (1 << 15);
489                 phy_write(phydev, 0x18, reg);
490         }
491
492         return ret;
493 }
494
495 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
496 {
497         int val;
498
499         val = phy_read(phydev, reg);
500         if (val < 0)
501                 return val;
502
503         return phy_write(phydev, reg, val | set);
504 }
505
506 static int brcm_fet_config_init(struct phy_device *phydev)
507 {
508         int reg, err, err2, brcmtest;
509
510         /* Reset the PHY to bring it to a known state. */
511         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
512         if (err < 0)
513                 return err;
514
515         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
516         if (reg < 0)
517                 return reg;
518
519         /* Unmask events we are interested in and mask interrupts globally. */
520         reg = MII_BRCM_FET_IR_DUPLEX_EN |
521               MII_BRCM_FET_IR_SPEED_EN |
522               MII_BRCM_FET_IR_LINK_EN |
523               MII_BRCM_FET_IR_ENABLE |
524               MII_BRCM_FET_IR_MASK;
525
526         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
527         if (err < 0)
528                 return err;
529
530         /* Enable shadow register access */
531         brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
532         if (brcmtest < 0)
533                 return brcmtest;
534
535         reg = brcmtest | MII_BRCM_FET_BT_SRE;
536
537         err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
538         if (err < 0)
539                 return err;
540
541         /* Set the LED mode */
542         reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
543         if (reg < 0) {
544                 err = reg;
545                 goto done;
546         }
547
548         reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
549         reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
550
551         err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
552         if (err < 0)
553                 goto done;
554
555         /* Enable auto MDIX */
556         err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
557                                        MII_BRCM_FET_SHDW_MC_FAME);
558         if (err < 0)
559                 goto done;
560
561         /* Enable auto power down */
562         err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
563                                        MII_BRCM_FET_SHDW_AS2_APDE);
564
565 done:
566         /* Disable shadow register access */
567         err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
568         if (!err)
569                 err = err2;
570
571         return err;
572 }
573
574 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
575 {
576         int reg;
577
578         /* Clear pending interrupts.  */
579         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
580         if (reg < 0)
581                 return reg;
582
583         return 0;
584 }
585
586 static int brcm_fet_config_intr(struct phy_device *phydev)
587 {
588         int reg, err;
589
590         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
591         if (reg < 0)
592                 return reg;
593
594         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
595                 reg &= ~MII_BRCM_FET_IR_MASK;
596         else
597                 reg |= MII_BRCM_FET_IR_MASK;
598
599         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
600         return err;
601 }
602
603 static struct phy_driver bcm5411_driver = {
604         .phy_id         = 0x00206070,
605         .phy_id_mask    = 0xfffffff0,
606         .name           = "Broadcom BCM5411",
607         .features       = PHY_GBIT_FEATURES |
608                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
609         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
610         .config_init    = bcm54xx_config_init,
611         .config_aneg    = genphy_config_aneg,
612         .read_status    = genphy_read_status,
613         .ack_interrupt  = bcm54xx_ack_interrupt,
614         .config_intr    = bcm54xx_config_intr,
615         .driver         = { .owner = THIS_MODULE },
616 };
617
618 static struct phy_driver bcm5421_driver = {
619         .phy_id         = 0x002060e0,
620         .phy_id_mask    = 0xfffffff0,
621         .name           = "Broadcom BCM5421",
622         .features       = PHY_GBIT_FEATURES |
623                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
624         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
625         .config_init    = bcm54xx_config_init,
626         .config_aneg    = genphy_config_aneg,
627         .read_status    = genphy_read_status,
628         .ack_interrupt  = bcm54xx_ack_interrupt,
629         .config_intr    = bcm54xx_config_intr,
630         .driver         = { .owner = THIS_MODULE },
631 };
632
633 static struct phy_driver bcm5461_driver = {
634         .phy_id         = 0x002060c0,
635         .phy_id_mask    = 0xfffffff0,
636         .name           = "Broadcom BCM5461",
637         .features       = PHY_GBIT_FEATURES |
638                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
639         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
640         .config_init    = bcm54xx_config_init,
641         .config_aneg    = genphy_config_aneg,
642         .read_status    = genphy_read_status,
643         .ack_interrupt  = bcm54xx_ack_interrupt,
644         .config_intr    = bcm54xx_config_intr,
645         .driver         = { .owner = THIS_MODULE },
646 };
647
648 static struct phy_driver bcm5464_driver = {
649         .phy_id         = 0x002060b0,
650         .phy_id_mask    = 0xfffffff0,
651         .name           = "Broadcom BCM5464",
652         .features       = PHY_GBIT_FEATURES |
653                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
654         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
655         .config_init    = bcm54xx_config_init,
656         .config_aneg    = genphy_config_aneg,
657         .read_status    = genphy_read_status,
658         .ack_interrupt  = bcm54xx_ack_interrupt,
659         .config_intr    = bcm54xx_config_intr,
660         .driver         = { .owner = THIS_MODULE },
661 };
662
663 static struct phy_driver bcm5481_driver = {
664         .phy_id         = 0x0143bca0,
665         .phy_id_mask    = 0xfffffff0,
666         .name           = "Broadcom BCM5481",
667         .features       = PHY_GBIT_FEATURES |
668                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
669         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
670         .config_init    = bcm54xx_config_init,
671         .config_aneg    = bcm5481_config_aneg,
672         .read_status    = genphy_read_status,
673         .ack_interrupt  = bcm54xx_ack_interrupt,
674         .config_intr    = bcm54xx_config_intr,
675         .driver         = { .owner = THIS_MODULE },
676 };
677
678 static struct phy_driver bcm5482_driver = {
679         .phy_id         = 0x0143bcb0,
680         .phy_id_mask    = 0xfffffff0,
681         .name           = "Broadcom BCM5482",
682         .features       = PHY_GBIT_FEATURES |
683                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
684         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
685         .config_init    = bcm5482_config_init,
686         .config_aneg    = genphy_config_aneg,
687         .read_status    = bcm5482_read_status,
688         .ack_interrupt  = bcm54xx_ack_interrupt,
689         .config_intr    = bcm54xx_config_intr,
690         .driver         = { .owner = THIS_MODULE },
691 };
692
693 static struct phy_driver bcm50610_driver = {
694         .phy_id         = PHY_ID_BCM50610,
695         .phy_id_mask    = 0xfffffff0,
696         .name           = "Broadcom BCM50610",
697         .features       = PHY_GBIT_FEATURES |
698                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
699         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
700         .config_init    = bcm54xx_config_init,
701         .config_aneg    = genphy_config_aneg,
702         .read_status    = genphy_read_status,
703         .ack_interrupt  = bcm54xx_ack_interrupt,
704         .config_intr    = bcm54xx_config_intr,
705         .driver         = { .owner = THIS_MODULE },
706 };
707
708 static struct phy_driver bcm50610m_driver = {
709         .phy_id         = PHY_ID_BCM50610M,
710         .phy_id_mask    = 0xfffffff0,
711         .name           = "Broadcom BCM50610M",
712         .features       = PHY_GBIT_FEATURES |
713                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
714         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
715         .config_init    = bcm54xx_config_init,
716         .config_aneg    = genphy_config_aneg,
717         .read_status    = genphy_read_status,
718         .ack_interrupt  = bcm54xx_ack_interrupt,
719         .config_intr    = bcm54xx_config_intr,
720         .driver         = { .owner = THIS_MODULE },
721 };
722
723 static struct phy_driver bcm57780_driver = {
724         .phy_id         = PHY_ID_BCM57780,
725         .phy_id_mask    = 0xfffffff0,
726         .name           = "Broadcom BCM57780",
727         .features       = PHY_GBIT_FEATURES |
728                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
729         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
730         .config_init    = bcm54xx_config_init,
731         .config_aneg    = genphy_config_aneg,
732         .read_status    = genphy_read_status,
733         .ack_interrupt  = bcm54xx_ack_interrupt,
734         .config_intr    = bcm54xx_config_intr,
735         .driver         = { .owner = THIS_MODULE },
736 };
737
738 static struct phy_driver bcmac131_driver = {
739         .phy_id         = 0x0143bc70,
740         .phy_id_mask    = 0xfffffff0,
741         .name           = "Broadcom BCMAC131",
742         .features       = PHY_BASIC_FEATURES |
743                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
744         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
745         .config_init    = brcm_fet_config_init,
746         .config_aneg    = genphy_config_aneg,
747         .read_status    = genphy_read_status,
748         .ack_interrupt  = brcm_fet_ack_interrupt,
749         .config_intr    = brcm_fet_config_intr,
750         .driver         = { .owner = THIS_MODULE },
751 };
752
753 static int __init broadcom_init(void)
754 {
755         int ret;
756
757         ret = phy_driver_register(&bcm5411_driver);
758         if (ret)
759                 goto out_5411;
760         ret = phy_driver_register(&bcm5421_driver);
761         if (ret)
762                 goto out_5421;
763         ret = phy_driver_register(&bcm5461_driver);
764         if (ret)
765                 goto out_5461;
766         ret = phy_driver_register(&bcm5464_driver);
767         if (ret)
768                 goto out_5464;
769         ret = phy_driver_register(&bcm5481_driver);
770         if (ret)
771                 goto out_5481;
772         ret = phy_driver_register(&bcm5482_driver);
773         if (ret)
774                 goto out_5482;
775         ret = phy_driver_register(&bcm50610_driver);
776         if (ret)
777                 goto out_50610;
778         ret = phy_driver_register(&bcm50610m_driver);
779         if (ret)
780                 goto out_50610m;
781         ret = phy_driver_register(&bcm57780_driver);
782         if (ret)
783                 goto out_57780;
784         ret = phy_driver_register(&bcmac131_driver);
785         if (ret)
786                 goto out_ac131;
787         return ret;
788
789 out_ac131:
790         phy_driver_unregister(&bcm57780_driver);
791 out_57780:
792         phy_driver_unregister(&bcm50610m_driver);
793 out_50610m:
794         phy_driver_unregister(&bcm50610_driver);
795 out_50610:
796         phy_driver_unregister(&bcm5482_driver);
797 out_5482:
798         phy_driver_unregister(&bcm5481_driver);
799 out_5481:
800         phy_driver_unregister(&bcm5464_driver);
801 out_5464:
802         phy_driver_unregister(&bcm5461_driver);
803 out_5461:
804         phy_driver_unregister(&bcm5421_driver);
805 out_5421:
806         phy_driver_unregister(&bcm5411_driver);
807 out_5411:
808         return ret;
809 }
810
811 static void __exit broadcom_exit(void)
812 {
813         phy_driver_unregister(&bcmac131_driver);
814         phy_driver_unregister(&bcm57780_driver);
815         phy_driver_unregister(&bcm50610m_driver);
816         phy_driver_unregister(&bcm50610_driver);
817         phy_driver_unregister(&bcm5482_driver);
818         phy_driver_unregister(&bcm5481_driver);
819         phy_driver_unregister(&bcm5464_driver);
820         phy_driver_unregister(&bcm5461_driver);
821         phy_driver_unregister(&bcm5421_driver);
822         phy_driver_unregister(&bcm5411_driver);
823 }
824
825 module_init(broadcom_init);
826 module_exit(broadcom_exit);