]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/net/phy/broadcom.c
tg3 / broadcom: Optionally disable TXC if no link
[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 val, orig;
330         bool clk125en = true;
331
332         /* Abort if we are using an untested phy. */
333         if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 ||
334             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 ||
335             BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
336                 return;
337
338         val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
339         if (val < 0)
340                 return;
341
342         orig = val;
343
344         if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
345              BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
346             BRCM_PHY_REV(phydev) >= 0x3) {
347                 /*
348                  * Here, bit 0 _disables_ CLK125 when set.
349                  * This bit is set by default.
350                  */
351                 clk125en = false;
352         } else {
353                 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
354                         /* Here, bit 0 _enables_ CLK125 when set */
355                         val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
356                         clk125en = false;
357                 }
358         }
359
360         if (clk125en == false ||
361             (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
362                 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
363         else
364                 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
365
366         if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
367                 val |= BCM54XX_SHD_SCR3_TRDDAPD;
368
369         if (orig != val)
370                 bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
371
372         val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
373         if (val < 0)
374                 return;
375
376         orig = val;
377
378         if (clk125en == false ||
379             (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
380                 val |= BCM54XX_SHD_APD_EN;
381         else
382                 val &= ~BCM54XX_SHD_APD_EN;
383
384         if (orig != val)
385                 bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
386 }
387
388 static int bcm54xx_config_init(struct phy_device *phydev)
389 {
390         int reg, err;
391
392         reg = phy_read(phydev, MII_BCM54XX_ECR);
393         if (reg < 0)
394                 return reg;
395
396         /* Mask interrupts globally.  */
397         reg |= MII_BCM54XX_ECR_IM;
398         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
399         if (err < 0)
400                 return err;
401
402         /* Unmask events we are interested in.  */
403         reg = ~(MII_BCM54XX_INT_DUPLEX |
404                 MII_BCM54XX_INT_SPEED |
405                 MII_BCM54XX_INT_LINK);
406         err = phy_write(phydev, MII_BCM54XX_IMR, reg);
407         if (err < 0)
408                 return err;
409
410         if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
411              BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
412             (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
413                 bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
414
415         if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
416             (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
417             (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
418                 bcm54xx_adjust_rxrefclk(phydev);
419
420         bcm54xx_phydsp_config(phydev);
421
422         return 0;
423 }
424
425 static int bcm5482_config_init(struct phy_device *phydev)
426 {
427         int err, reg;
428
429         err = bcm54xx_config_init(phydev);
430
431         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
432                 /*
433                  * Enable secondary SerDes and its use as an LED source
434                  */
435                 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
436                 bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
437                                      reg |
438                                      BCM5482_SHD_SSD_LEDM |
439                                      BCM5482_SHD_SSD_EN);
440
441                 /*
442                  * Enable SGMII slave mode and auto-detection
443                  */
444                 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
445                 err = bcm54xx_exp_read(phydev, reg);
446                 if (err < 0)
447                         return err;
448                 err = bcm54xx_exp_write(phydev, reg, err |
449                                         BCM5482_SSD_SGMII_SLAVE_EN |
450                                         BCM5482_SSD_SGMII_SLAVE_AD);
451                 if (err < 0)
452                         return err;
453
454                 /*
455                  * Disable secondary SerDes powerdown
456                  */
457                 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
458                 err = bcm54xx_exp_read(phydev, reg);
459                 if (err < 0)
460                         return err;
461                 err = bcm54xx_exp_write(phydev, reg,
462                                         err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
463                 if (err < 0)
464                         return err;
465
466                 /*
467                  * Select 1000BASE-X register set (primary SerDes)
468                  */
469                 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
470                 bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
471                                      reg | BCM5482_SHD_MODE_1000BX);
472
473                 /*
474                  * LED1=ACTIVITYLED, LED3=LINKSPD[2]
475                  * (Use LED1 as secondary SerDes ACTIVITY LED)
476                  */
477                 bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
478                         BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
479                         BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
480
481                 /*
482                  * Auto-negotiation doesn't seem to work quite right
483                  * in this mode, so we disable it and force it to the
484                  * right speed/duplex setting.  Only 'link status'
485                  * is important.
486                  */
487                 phydev->autoneg = AUTONEG_DISABLE;
488                 phydev->speed = SPEED_1000;
489                 phydev->duplex = DUPLEX_FULL;
490         }
491
492         return err;
493 }
494
495 static int bcm5482_read_status(struct phy_device *phydev)
496 {
497         int err;
498
499         err = genphy_read_status(phydev);
500
501         if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
502                 /*
503                  * Only link status matters for 1000Base-X mode, so force
504                  * 1000 Mbit/s full-duplex status
505                  */
506                 if (phydev->link) {
507                         phydev->speed = SPEED_1000;
508                         phydev->duplex = DUPLEX_FULL;
509                 }
510         }
511
512         return err;
513 }
514
515 static int bcm54xx_ack_interrupt(struct phy_device *phydev)
516 {
517         int reg;
518
519         /* Clear pending interrupts.  */
520         reg = phy_read(phydev, MII_BCM54XX_ISR);
521         if (reg < 0)
522                 return reg;
523
524         return 0;
525 }
526
527 static int bcm54xx_config_intr(struct phy_device *phydev)
528 {
529         int reg, err;
530
531         reg = phy_read(phydev, MII_BCM54XX_ECR);
532         if (reg < 0)
533                 return reg;
534
535         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
536                 reg &= ~MII_BCM54XX_ECR_IM;
537         else
538                 reg |= MII_BCM54XX_ECR_IM;
539
540         err = phy_write(phydev, MII_BCM54XX_ECR, reg);
541         return err;
542 }
543
544 static int bcm5481_config_aneg(struct phy_device *phydev)
545 {
546         int ret;
547
548         /* Aneg firsly. */
549         ret = genphy_config_aneg(phydev);
550
551         /* Then we can set up the delay. */
552         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
553                 u16 reg;
554
555                 /*
556                  * There is no BCM5481 specification available, so down
557                  * here is everything we know about "register 0x18". This
558                  * at least helps BCM5481 to successfuly receive packets
559                  * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
560                  * says: "This sets delay between the RXD and RXC signals
561                  * instead of using trace lengths to achieve timing".
562                  */
563
564                 /* Set RDX clk delay. */
565                 reg = 0x7 | (0x7 << 12);
566                 phy_write(phydev, 0x18, reg);
567
568                 reg = phy_read(phydev, 0x18);
569                 /* Set RDX-RXC skew. */
570                 reg |= (1 << 8);
571                 /* Write bits 14:0. */
572                 reg |= (1 << 15);
573                 phy_write(phydev, 0x18, reg);
574         }
575
576         return ret;
577 }
578
579 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
580 {
581         int val;
582
583         val = phy_read(phydev, reg);
584         if (val < 0)
585                 return val;
586
587         return phy_write(phydev, reg, val | set);
588 }
589
590 static int brcm_fet_config_init(struct phy_device *phydev)
591 {
592         int reg, err, err2, brcmtest;
593
594         /* Reset the PHY to bring it to a known state. */
595         err = phy_write(phydev, MII_BMCR, BMCR_RESET);
596         if (err < 0)
597                 return err;
598
599         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
600         if (reg < 0)
601                 return reg;
602
603         /* Unmask events we are interested in and mask interrupts globally. */
604         reg = MII_BRCM_FET_IR_DUPLEX_EN |
605               MII_BRCM_FET_IR_SPEED_EN |
606               MII_BRCM_FET_IR_LINK_EN |
607               MII_BRCM_FET_IR_ENABLE |
608               MII_BRCM_FET_IR_MASK;
609
610         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
611         if (err < 0)
612                 return err;
613
614         /* Enable shadow register access */
615         brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
616         if (brcmtest < 0)
617                 return brcmtest;
618
619         reg = brcmtest | MII_BRCM_FET_BT_SRE;
620
621         err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
622         if (err < 0)
623                 return err;
624
625         /* Set the LED mode */
626         reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
627         if (reg < 0) {
628                 err = reg;
629                 goto done;
630         }
631
632         reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
633         reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
634
635         err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
636         if (err < 0)
637                 goto done;
638
639         /* Enable auto MDIX */
640         err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
641                                        MII_BRCM_FET_SHDW_MC_FAME);
642         if (err < 0)
643                 goto done;
644
645         if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
646                 /* Enable auto power down */
647                 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
648                                                MII_BRCM_FET_SHDW_AS2_APDE);
649         }
650
651 done:
652         /* Disable shadow register access */
653         err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
654         if (!err)
655                 err = err2;
656
657         return err;
658 }
659
660 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
661 {
662         int reg;
663
664         /* Clear pending interrupts.  */
665         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
666         if (reg < 0)
667                 return reg;
668
669         return 0;
670 }
671
672 static int brcm_fet_config_intr(struct phy_device *phydev)
673 {
674         int reg, err;
675
676         reg = phy_read(phydev, MII_BRCM_FET_INTREG);
677         if (reg < 0)
678                 return reg;
679
680         if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
681                 reg &= ~MII_BRCM_FET_IR_MASK;
682         else
683                 reg |= MII_BRCM_FET_IR_MASK;
684
685         err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
686         return err;
687 }
688
689 static struct phy_driver bcm5411_driver = {
690         .phy_id         = 0x00206070,
691         .phy_id_mask    = 0xfffffff0,
692         .name           = "Broadcom BCM5411",
693         .features       = PHY_GBIT_FEATURES |
694                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
695         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
696         .config_init    = bcm54xx_config_init,
697         .config_aneg    = genphy_config_aneg,
698         .read_status    = genphy_read_status,
699         .ack_interrupt  = bcm54xx_ack_interrupt,
700         .config_intr    = bcm54xx_config_intr,
701         .driver         = { .owner = THIS_MODULE },
702 };
703
704 static struct phy_driver bcm5421_driver = {
705         .phy_id         = 0x002060e0,
706         .phy_id_mask    = 0xfffffff0,
707         .name           = "Broadcom BCM5421",
708         .features       = PHY_GBIT_FEATURES |
709                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
710         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
711         .config_init    = bcm54xx_config_init,
712         .config_aneg    = genphy_config_aneg,
713         .read_status    = genphy_read_status,
714         .ack_interrupt  = bcm54xx_ack_interrupt,
715         .config_intr    = bcm54xx_config_intr,
716         .driver         = { .owner = THIS_MODULE },
717 };
718
719 static struct phy_driver bcm5461_driver = {
720         .phy_id         = 0x002060c0,
721         .phy_id_mask    = 0xfffffff0,
722         .name           = "Broadcom BCM5461",
723         .features       = PHY_GBIT_FEATURES |
724                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
725         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
726         .config_init    = bcm54xx_config_init,
727         .config_aneg    = genphy_config_aneg,
728         .read_status    = genphy_read_status,
729         .ack_interrupt  = bcm54xx_ack_interrupt,
730         .config_intr    = bcm54xx_config_intr,
731         .driver         = { .owner = THIS_MODULE },
732 };
733
734 static struct phy_driver bcm5464_driver = {
735         .phy_id         = 0x002060b0,
736         .phy_id_mask    = 0xfffffff0,
737         .name           = "Broadcom BCM5464",
738         .features       = PHY_GBIT_FEATURES |
739                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
740         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
741         .config_init    = bcm54xx_config_init,
742         .config_aneg    = genphy_config_aneg,
743         .read_status    = genphy_read_status,
744         .ack_interrupt  = bcm54xx_ack_interrupt,
745         .config_intr    = bcm54xx_config_intr,
746         .driver         = { .owner = THIS_MODULE },
747 };
748
749 static struct phy_driver bcm5481_driver = {
750         .phy_id         = 0x0143bca0,
751         .phy_id_mask    = 0xfffffff0,
752         .name           = "Broadcom BCM5481",
753         .features       = PHY_GBIT_FEATURES |
754                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
755         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
756         .config_init    = bcm54xx_config_init,
757         .config_aneg    = bcm5481_config_aneg,
758         .read_status    = genphy_read_status,
759         .ack_interrupt  = bcm54xx_ack_interrupt,
760         .config_intr    = bcm54xx_config_intr,
761         .driver         = { .owner = THIS_MODULE },
762 };
763
764 static struct phy_driver bcm5482_driver = {
765         .phy_id         = 0x0143bcb0,
766         .phy_id_mask    = 0xfffffff0,
767         .name           = "Broadcom BCM5482",
768         .features       = PHY_GBIT_FEATURES |
769                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
770         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
771         .config_init    = bcm5482_config_init,
772         .config_aneg    = genphy_config_aneg,
773         .read_status    = bcm5482_read_status,
774         .ack_interrupt  = bcm54xx_ack_interrupt,
775         .config_intr    = bcm54xx_config_intr,
776         .driver         = { .owner = THIS_MODULE },
777 };
778
779 static struct phy_driver bcm50610_driver = {
780         .phy_id         = PHY_ID_BCM50610,
781         .phy_id_mask    = 0xfffffff0,
782         .name           = "Broadcom BCM50610",
783         .features       = PHY_GBIT_FEATURES |
784                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
785         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
786         .config_init    = bcm54xx_config_init,
787         .config_aneg    = genphy_config_aneg,
788         .read_status    = genphy_read_status,
789         .ack_interrupt  = bcm54xx_ack_interrupt,
790         .config_intr    = bcm54xx_config_intr,
791         .driver         = { .owner = THIS_MODULE },
792 };
793
794 static struct phy_driver bcm50610m_driver = {
795         .phy_id         = PHY_ID_BCM50610M,
796         .phy_id_mask    = 0xfffffff0,
797         .name           = "Broadcom BCM50610M",
798         .features       = PHY_GBIT_FEATURES |
799                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
800         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
801         .config_init    = bcm54xx_config_init,
802         .config_aneg    = genphy_config_aneg,
803         .read_status    = genphy_read_status,
804         .ack_interrupt  = bcm54xx_ack_interrupt,
805         .config_intr    = bcm54xx_config_intr,
806         .driver         = { .owner = THIS_MODULE },
807 };
808
809 static struct phy_driver bcm57780_driver = {
810         .phy_id         = PHY_ID_BCM57780,
811         .phy_id_mask    = 0xfffffff0,
812         .name           = "Broadcom BCM57780",
813         .features       = PHY_GBIT_FEATURES |
814                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
815         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
816         .config_init    = bcm54xx_config_init,
817         .config_aneg    = genphy_config_aneg,
818         .read_status    = genphy_read_status,
819         .ack_interrupt  = bcm54xx_ack_interrupt,
820         .config_intr    = bcm54xx_config_intr,
821         .driver         = { .owner = THIS_MODULE },
822 };
823
824 static struct phy_driver bcmac131_driver = {
825         .phy_id         = 0x0143bc70,
826         .phy_id_mask    = 0xfffffff0,
827         .name           = "Broadcom BCMAC131",
828         .features       = PHY_BASIC_FEATURES |
829                           SUPPORTED_Pause | SUPPORTED_Asym_Pause,
830         .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
831         .config_init    = brcm_fet_config_init,
832         .config_aneg    = genphy_config_aneg,
833         .read_status    = genphy_read_status,
834         .ack_interrupt  = brcm_fet_ack_interrupt,
835         .config_intr    = brcm_fet_config_intr,
836         .driver         = { .owner = THIS_MODULE },
837 };
838
839 static int __init broadcom_init(void)
840 {
841         int ret;
842
843         ret = phy_driver_register(&bcm5411_driver);
844         if (ret)
845                 goto out_5411;
846         ret = phy_driver_register(&bcm5421_driver);
847         if (ret)
848                 goto out_5421;
849         ret = phy_driver_register(&bcm5461_driver);
850         if (ret)
851                 goto out_5461;
852         ret = phy_driver_register(&bcm5464_driver);
853         if (ret)
854                 goto out_5464;
855         ret = phy_driver_register(&bcm5481_driver);
856         if (ret)
857                 goto out_5481;
858         ret = phy_driver_register(&bcm5482_driver);
859         if (ret)
860                 goto out_5482;
861         ret = phy_driver_register(&bcm50610_driver);
862         if (ret)
863                 goto out_50610;
864         ret = phy_driver_register(&bcm50610m_driver);
865         if (ret)
866                 goto out_50610m;
867         ret = phy_driver_register(&bcm57780_driver);
868         if (ret)
869                 goto out_57780;
870         ret = phy_driver_register(&bcmac131_driver);
871         if (ret)
872                 goto out_ac131;
873         return ret;
874
875 out_ac131:
876         phy_driver_unregister(&bcm57780_driver);
877 out_57780:
878         phy_driver_unregister(&bcm50610m_driver);
879 out_50610m:
880         phy_driver_unregister(&bcm50610_driver);
881 out_50610:
882         phy_driver_unregister(&bcm5482_driver);
883 out_5482:
884         phy_driver_unregister(&bcm5481_driver);
885 out_5481:
886         phy_driver_unregister(&bcm5464_driver);
887 out_5464:
888         phy_driver_unregister(&bcm5461_driver);
889 out_5461:
890         phy_driver_unregister(&bcm5421_driver);
891 out_5421:
892         phy_driver_unregister(&bcm5411_driver);
893 out_5411:
894         return ret;
895 }
896
897 static void __exit broadcom_exit(void)
898 {
899         phy_driver_unregister(&bcmac131_driver);
900         phy_driver_unregister(&bcm57780_driver);
901         phy_driver_unregister(&bcm50610m_driver);
902         phy_driver_unregister(&bcm50610_driver);
903         phy_driver_unregister(&bcm5482_driver);
904         phy_driver_unregister(&bcm5481_driver);
905         phy_driver_unregister(&bcm5464_driver);
906         phy_driver_unregister(&bcm5461_driver);
907         phy_driver_unregister(&bcm5421_driver);
908         phy_driver_unregister(&bcm5411_driver);
909 }
910
911 module_init(broadcom_init);
912 module_exit(broadcom_exit);