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