diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2008-11-03 19:56:51 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-03 19:56:51 -0500 |
commit | 772638b6c87da7043c50914dbb033c08155508dd (patch) | |
tree | 186389bdcc22be1eb0a89944d553d8c246dedf51 /drivers/net | |
parent | 042a75b99fbda6bf7c7bf4496e205e3e7acc953a (diff) |
broadcom: Add support for BCM50610
This patch adds the BCM50610 to the list of phys supported by the
broadcom driver.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/phy/broadcom.c | 119 |
1 files changed, 118 insertions, 1 deletions
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 7e935924793d..fd4fc66b6d6e 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/phy.h> | 18 | #include <linux/phy.h> |
19 | 19 | ||
20 | #define PHY_ID_BCM50610 0x0143bd60 | ||
21 | |||
20 | #define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ | 22 | #define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ |
21 | #define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ | 23 | #define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ |
22 | #define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */ | 24 | #define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */ |
@@ -54,6 +56,21 @@ | |||
54 | #define MII_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0) | 56 | #define MII_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0) |
55 | 57 | ||
56 | /* | 58 | /* |
59 | * AUXILIARY CONTROL SHADOW ACCESS REGISTERS. (PHY REG 0x18) | ||
60 | */ | ||
61 | #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000 | ||
62 | #define MII_BCM54XX_AUXCTL_ACTL_TX_6DB 0x0400 | ||
63 | #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA 0x0800 | ||
64 | |||
65 | #define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000 | ||
66 | #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200 | ||
67 | #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000 | ||
68 | #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007 | ||
69 | |||
70 | #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000 | ||
71 | |||
72 | |||
73 | /* | ||
57 | * Broadcom LED source encodings. These are used in BCM5461, BCM5481, | 74 | * Broadcom LED source encodings. These are used in BCM5461, BCM5481, |
58 | * BCM5482, and possibly some others. | 75 | * BCM5482, and possibly some others. |
59 | */ | 76 | */ |
@@ -88,6 +105,24 @@ | |||
88 | #define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */ | 105 | #define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */ |
89 | 106 | ||
90 | /* | 107 | /* |
108 | * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17) | ||
109 | */ | ||
110 | #define MII_BCM54XX_EXP_AADJ1CH0 0x001f | ||
111 | #define MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN 0x0200 | ||
112 | #define MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF 0x0100 | ||
113 | #define MII_BCM54XX_EXP_AADJ1CH3 0x601f | ||
114 | #define MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ 0x0002 | ||
115 | #define MII_BCM54XX_EXP_EXP08 0x0F08 | ||
116 | #define MII_BCM54XX_EXP_EXP08_RJCT_2MHZ 0x0001 | ||
117 | #define MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE 0x0200 | ||
118 | #define MII_BCM54XX_EXP_EXP75 0x0f75 | ||
119 | #define MII_BCM54XX_EXP_EXP75_VDACCTRL 0x003c | ||
120 | #define MII_BCM54XX_EXP_EXP96 0x0f96 | ||
121 | #define MII_BCM54XX_EXP_EXP96_MYST 0x0010 | ||
122 | #define MII_BCM54XX_EXP_EXP97 0x0f97 | ||
123 | #define MII_BCM54XX_EXP_EXP97_MYST 0x0c0c | ||
124 | |||
125 | /* | ||
91 | * BCM5482: Secondary SerDes registers | 126 | * BCM5482: Secondary SerDes registers |
92 | */ | 127 | */ |
93 | #define BCM5482_SSD_1000BX_CTL 0x00 /* 1000BASE-X Control */ | 128 | #define BCM5482_SSD_1000BX_CTL 0x00 /* 1000BASE-X Control */ |
@@ -145,7 +180,7 @@ static int bcm54xx_exp_read(struct phy_device *phydev, u8 regnum) | |||
145 | return val; | 180 | return val; |
146 | } | 181 | } |
147 | 182 | ||
148 | static int bcm54xx_exp_write(struct phy_device *phydev, u8 regnum, u16 val) | 183 | static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val) |
149 | { | 184 | { |
150 | int ret; | 185 | int ret; |
151 | 186 | ||
@@ -161,6 +196,60 @@ static int bcm54xx_exp_write(struct phy_device *phydev, u8 regnum, u16 val) | |||
161 | return ret; | 196 | return ret; |
162 | } | 197 | } |
163 | 198 | ||
199 | static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val) | ||
200 | { | ||
201 | return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val); | ||
202 | } | ||
203 | |||
204 | static int bcm50610_a0_workaround(struct phy_device *phydev) | ||
205 | { | ||
206 | int err; | ||
207 | |||
208 | err = bcm54xx_auxctl_write(phydev, | ||
209 | MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, | ||
210 | MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | | ||
211 | MII_BCM54XX_AUXCTL_ACTL_TX_6DB); | ||
212 | if (err < 0) | ||
213 | return err; | ||
214 | |||
215 | err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08, | ||
216 | MII_BCM54XX_EXP_EXP08_RJCT_2MHZ | | ||
217 | MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE); | ||
218 | if (err < 0) | ||
219 | goto error; | ||
220 | |||
221 | err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0, | ||
222 | MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | | ||
223 | MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); | ||
224 | if (err < 0) | ||
225 | goto error; | ||
226 | |||
227 | err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3, | ||
228 | MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); | ||
229 | if (err < 0) | ||
230 | goto error; | ||
231 | |||
232 | err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, | ||
233 | MII_BCM54XX_EXP_EXP75_VDACCTRL); | ||
234 | if (err < 0) | ||
235 | goto error; | ||
236 | |||
237 | err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96, | ||
238 | MII_BCM54XX_EXP_EXP96_MYST); | ||
239 | if (err < 0) | ||
240 | goto error; | ||
241 | |||
242 | err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97, | ||
243 | MII_BCM54XX_EXP_EXP97_MYST); | ||
244 | |||
245 | error: | ||
246 | bcm54xx_auxctl_write(phydev, | ||
247 | MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, | ||
248 | MII_BCM54XX_AUXCTL_ACTL_TX_6DB); | ||
249 | |||
250 | return err; | ||
251 | } | ||
252 | |||
164 | static int bcm54xx_config_init(struct phy_device *phydev) | 253 | static int bcm54xx_config_init(struct phy_device *phydev) |
165 | { | 254 | { |
166 | int reg, err; | 255 | int reg, err; |
@@ -182,6 +271,13 @@ static int bcm54xx_config_init(struct phy_device *phydev) | |||
182 | err = phy_write(phydev, MII_BCM54XX_IMR, reg); | 271 | err = phy_write(phydev, MII_BCM54XX_IMR, reg); |
183 | if (err < 0) | 272 | if (err < 0) |
184 | return err; | 273 | return err; |
274 | |||
275 | if (phydev->drv->phy_id == PHY_ID_BCM50610) { | ||
276 | err = bcm50610_a0_workaround(phydev); | ||
277 | if (err < 0) | ||
278 | return err; | ||
279 | } | ||
280 | |||
185 | return 0; | 281 | return 0; |
186 | } | 282 | } |
187 | 283 | ||
@@ -429,6 +525,21 @@ static struct phy_driver bcm5482_driver = { | |||
429 | .driver = { .owner = THIS_MODULE }, | 525 | .driver = { .owner = THIS_MODULE }, |
430 | }; | 526 | }; |
431 | 527 | ||
528 | static struct phy_driver bcm50610_driver = { | ||
529 | .phy_id = PHY_ID_BCM50610, | ||
530 | .phy_id_mask = 0xfffffff0, | ||
531 | .name = "Broadcom BCM50610", | ||
532 | .features = PHY_GBIT_FEATURES | | ||
533 | SUPPORTED_Pause | SUPPORTED_Asym_Pause, | ||
534 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, | ||
535 | .config_init = bcm54xx_config_init, | ||
536 | .config_aneg = genphy_config_aneg, | ||
537 | .read_status = genphy_read_status, | ||
538 | .ack_interrupt = bcm54xx_ack_interrupt, | ||
539 | .config_intr = bcm54xx_config_intr, | ||
540 | .driver = { .owner = THIS_MODULE }, | ||
541 | }; | ||
542 | |||
432 | static int __init broadcom_init(void) | 543 | static int __init broadcom_init(void) |
433 | { | 544 | { |
434 | int ret; | 545 | int ret; |
@@ -451,8 +562,13 @@ static int __init broadcom_init(void) | |||
451 | ret = phy_driver_register(&bcm5482_driver); | 562 | ret = phy_driver_register(&bcm5482_driver); |
452 | if (ret) | 563 | if (ret) |
453 | goto out_5482; | 564 | goto out_5482; |
565 | ret = phy_driver_register(&bcm50610_driver); | ||
566 | if (ret) | ||
567 | goto out_50610; | ||
454 | return ret; | 568 | return ret; |
455 | 569 | ||
570 | out_50610: | ||
571 | phy_driver_unregister(&bcm5482_driver); | ||
456 | out_5482: | 572 | out_5482: |
457 | phy_driver_unregister(&bcm5481_driver); | 573 | phy_driver_unregister(&bcm5481_driver); |
458 | out_5481: | 574 | out_5481: |
@@ -469,6 +585,7 @@ out_5411: | |||
469 | 585 | ||
470 | static void __exit broadcom_exit(void) | 586 | static void __exit broadcom_exit(void) |
471 | { | 587 | { |
588 | phy_driver_unregister(&bcm50610_driver); | ||
472 | phy_driver_unregister(&bcm5482_driver); | 589 | phy_driver_unregister(&bcm5482_driver); |
473 | phy_driver_unregister(&bcm5481_driver); | 590 | phy_driver_unregister(&bcm5481_driver); |
474 | phy_driver_unregister(&bcm5464_driver); | 591 | phy_driver_unregister(&bcm5464_driver); |