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