broadcom: Add BCM50610M support
[deliverable/linux.git] / drivers / net / phy / broadcom.c
CommitLineData
c4b41c9f
MR
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
772638b6 20#define PHY_ID_BCM50610 0x0143bd60
4f4598fd 21#define PHY_ID_BCM50610M 0x0143bd70
772638b6 22
c4b41c9f
MR
23#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */
24#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */
25#define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */
26
27#define MII_BCM54XX_ESR 0x11 /* BCM54xx extended status register */
28#define MII_BCM54XX_ESR_IS 0x1000 /* Interrupt status */
29
cd9af3da
NC
30#define MII_BCM54XX_EXP_DATA 0x15 /* Expansion register data */
31#define MII_BCM54XX_EXP_SEL 0x17 /* Expansion register select */
32#define MII_BCM54XX_EXP_SEL_SSD 0x0e00 /* Secondary SerDes select */
33#define MII_BCM54XX_EXP_SEL_ER 0x0f00 /* Expansion register select */
34
35#define MII_BCM54XX_AUX_CTL 0x18 /* Auxiliary control register */
c4b41c9f
MR
36#define MII_BCM54XX_ISR 0x1a /* BCM54xx interrupt status register */
37#define MII_BCM54XX_IMR 0x1b /* BCM54xx interrupt mask register */
38#define MII_BCM54XX_INT_CRCERR 0x0001 /* CRC error */
39#define MII_BCM54XX_INT_LINK 0x0002 /* Link status changed */
40#define MII_BCM54XX_INT_SPEED 0x0004 /* Link speed change */
41#define MII_BCM54XX_INT_DUPLEX 0x0008 /* Duplex mode changed */
42#define MII_BCM54XX_INT_LRS 0x0010 /* Local receiver status changed */
43#define MII_BCM54XX_INT_RRS 0x0020 /* Remote receiver status changed */
44#define MII_BCM54XX_INT_SSERR 0x0040 /* Scrambler synchronization error */
45#define MII_BCM54XX_INT_UHCD 0x0080 /* Unsupported HCD negotiated */
46#define MII_BCM54XX_INT_NHCD 0x0100 /* No HCD */
47#define MII_BCM54XX_INT_NHCDL 0x0200 /* No HCD link */
48#define MII_BCM54XX_INT_ANPR 0x0400 /* Auto-negotiation page received */
49#define MII_BCM54XX_INT_LC 0x0800 /* All counters below 128 */
50#define MII_BCM54XX_INT_HC 0x1000 /* Counter above 32768 */
51#define MII_BCM54XX_INT_MDIX 0x2000 /* MDIX status change */
52#define MII_BCM54XX_INT_PSERR 0x4000 /* Pair swap error */
53
cd9af3da
NC
54#define MII_BCM54XX_SHD 0x1c /* 0x1c shadow registers */
55#define MII_BCM54XX_SHD_WRITE 0x8000
56#define MII_BCM54XX_SHD_VAL(x) ((x & 0x1f) << 10)
57#define MII_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0)
58
772638b6
MC
59/*
60 * AUXILIARY CONTROL SHADOW ACCESS REGISTERS. (PHY REG 0x18)
61 */
62#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
63#define MII_BCM54XX_AUXCTL_ACTL_TX_6DB 0x0400
64#define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA 0x0800
65
66#define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000
67#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200
68#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
69#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
70
71#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
72
73
cd9af3da
NC
74/*
75 * Broadcom LED source encodings. These are used in BCM5461, BCM5481,
76 * BCM5482, and possibly some others.
77 */
78#define BCM_LED_SRC_LINKSPD1 0x0
79#define BCM_LED_SRC_LINKSPD2 0x1
80#define BCM_LED_SRC_XMITLED 0x2
81#define BCM_LED_SRC_ACTIVITYLED 0x3
82#define BCM_LED_SRC_FDXLED 0x4
83#define BCM_LED_SRC_SLAVE 0x5
84#define BCM_LED_SRC_INTR 0x6
85#define BCM_LED_SRC_QUALITY 0x7
86#define BCM_LED_SRC_RCVLED 0x8
87#define BCM_LED_SRC_MULTICOLOR1 0xa
88#define BCM_LED_SRC_OPENSHORT 0xb
89#define BCM_LED_SRC_OFF 0xe /* Tied high */
90#define BCM_LED_SRC_ON 0xf /* Tied low */
91
92/*
93 * BCM5482: Shadow registers
94 * Shadow values go into bits [14:10] of register 0x1c to select a shadow
95 * register to access.
96 */
97#define BCM5482_SHD_LEDS1 0x0d /* 01101: LED Selector 1 */
98 /* LED3 / ~LINKSPD[2] selector */
99#define BCM5482_SHD_LEDS1_LED3(src) ((src & 0xf) << 4)
100 /* LED1 / ~LINKSPD[1] selector */
101#define BCM5482_SHD_LEDS1_LED1(src) ((src & 0xf) << 0)
102#define BCM5482_SHD_SSD 0x14 /* 10100: Secondary SerDes control */
103#define BCM5482_SHD_SSD_LEDM 0x0008 /* SSD LED Mode enable */
104#define BCM5482_SHD_SSD_EN 0x0001 /* SSD enable */
105#define BCM5482_SHD_MODE 0x1f /* 11111: Mode Control Register */
106#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */
107
772638b6
MC
108/*
109 * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17)
110 */
111#define MII_BCM54XX_EXP_AADJ1CH0 0x001f
112#define MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN 0x0200
113#define MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF 0x0100
114#define MII_BCM54XX_EXP_AADJ1CH3 0x601f
115#define MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ 0x0002
116#define MII_BCM54XX_EXP_EXP08 0x0F08
117#define MII_BCM54XX_EXP_EXP08_RJCT_2MHZ 0x0001
118#define MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE 0x0200
119#define MII_BCM54XX_EXP_EXP75 0x0f75
120#define MII_BCM54XX_EXP_EXP75_VDACCTRL 0x003c
121#define MII_BCM54XX_EXP_EXP96 0x0f96
122#define MII_BCM54XX_EXP_EXP96_MYST 0x0010
123#define MII_BCM54XX_EXP_EXP97 0x0f97
124#define MII_BCM54XX_EXP_EXP97_MYST 0x0c0c
125
cd9af3da
NC
126/*
127 * BCM5482: Secondary SerDes registers
128 */
129#define BCM5482_SSD_1000BX_CTL 0x00 /* 1000BASE-X Control */
130#define BCM5482_SSD_1000BX_CTL_PWRDOWN 0x0800 /* Power-down SSD */
131#define BCM5482_SSD_SGMII_SLAVE 0x15 /* SGMII Slave Register */
132#define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
133#define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
134
135/*
136 * Device flags for PHYs that can be configured for different operating
137 * modes.
138 */
139#define PHY_BCM_FLAGS_VALID 0x80000000
140#define PHY_BCM_FLAGS_INTF_XAUI 0x00000020
141#define PHY_BCM_FLAGS_INTF_SGMII 0x00000010
142#define PHY_BCM_FLAGS_MODE_1000BX 0x00000002
143#define PHY_BCM_FLAGS_MODE_COPPER 0x00000001
144
c4b41c9f
MR
145MODULE_DESCRIPTION("Broadcom PHY driver");
146MODULE_AUTHOR("Maciej W. Rozycki");
147MODULE_LICENSE("GPL");
148
cd9af3da
NC
149/*
150 * Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T
151 * 0x1c shadow registers.
152 */
153static int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow)
154{
155 phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
156 return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
157}
158
159static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val)
160{
161 return phy_write(phydev, MII_BCM54XX_SHD,
162 MII_BCM54XX_SHD_WRITE |
163 MII_BCM54XX_SHD_VAL(shadow) |
164 MII_BCM54XX_SHD_DATA(val));
165}
166
042a75b9
MC
167/* Indirect register access functions for the Expansion Registers */
168static int bcm54xx_exp_read(struct phy_device *phydev, u8 regnum)
cd9af3da
NC
169{
170 int val;
171
042a75b9
MC
172 val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
173 if (val < 0)
174 return val;
175
cd9af3da 176 val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
042a75b9
MC
177
178 /* Restore default value. It's O.K. if this write fails. */
179 phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
cd9af3da
NC
180
181 return val;
182}
183
772638b6 184static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
cd9af3da
NC
185{
186 int ret;
187
042a75b9
MC
188 ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
189 if (ret < 0)
190 return ret;
191
cd9af3da 192 ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
042a75b9
MC
193
194 /* Restore default value. It's O.K. if this write fails. */
195 phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
cd9af3da
NC
196
197 return ret;
198}
199
772638b6
MC
200static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
201{
202 return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
203}
204
205static int bcm50610_a0_workaround(struct phy_device *phydev)
206{
207 int err;
208
209 err = bcm54xx_auxctl_write(phydev,
210 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
211 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
212 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
213 if (err < 0)
214 return err;
215
216 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
217 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ |
218 MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE);
219 if (err < 0)
220 goto error;
221
222 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
223 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
224 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
225 if (err < 0)
226 goto error;
227
228 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
229 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
230 if (err < 0)
231 goto error;
232
233 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
234 MII_BCM54XX_EXP_EXP75_VDACCTRL);
235 if (err < 0)
236 goto error;
237
238 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
239 MII_BCM54XX_EXP_EXP96_MYST);
240 if (err < 0)
241 goto error;
242
243 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
244 MII_BCM54XX_EXP_EXP97_MYST);
245
246error:
247 bcm54xx_auxctl_write(phydev,
248 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
249 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
250
251 return err;
252}
253
c4b41c9f
MR
254static int bcm54xx_config_init(struct phy_device *phydev)
255{
256 int reg, err;
257
258 reg = phy_read(phydev, MII_BCM54XX_ECR);
259 if (reg < 0)
260 return reg;
261
262 /* Mask interrupts globally. */
263 reg |= MII_BCM54XX_ECR_IM;
264 err = phy_write(phydev, MII_BCM54XX_ECR, reg);
265 if (err < 0)
266 return err;
267
268 /* Unmask events we are interested in. */
269 reg = ~(MII_BCM54XX_INT_DUPLEX |
270 MII_BCM54XX_INT_SPEED |
271 MII_BCM54XX_INT_LINK);
272 err = phy_write(phydev, MII_BCM54XX_IMR, reg);
273 if (err < 0)
274 return err;
772638b6
MC
275
276 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
277 err = bcm50610_a0_workaround(phydev);
278 if (err < 0)
279 return err;
280 }
281
c4b41c9f
MR
282 return 0;
283}
284
cd9af3da
NC
285static int bcm5482_config_init(struct phy_device *phydev)
286{
287 int err, reg;
288
289 err = bcm54xx_config_init(phydev);
290
291 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
292 /*
293 * Enable secondary SerDes and its use as an LED source
294 */
295 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
296 bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
297 reg |
298 BCM5482_SHD_SSD_LEDM |
299 BCM5482_SHD_SSD_EN);
300
301 /*
302 * Enable SGMII slave mode and auto-detection
303 */
042a75b9
MC
304 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
305 err = bcm54xx_exp_read(phydev, reg);
306 if (err < 0)
307 return err;
308 err = bcm54xx_exp_write(phydev, reg, err |
309 BCM5482_SSD_SGMII_SLAVE_EN |
310 BCM5482_SSD_SGMII_SLAVE_AD);
311 if (err < 0)
312 return err;
cd9af3da
NC
313
314 /*
315 * Disable secondary SerDes powerdown
316 */
042a75b9
MC
317 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
318 err = bcm54xx_exp_read(phydev, reg);
319 if (err < 0)
320 return err;
321 err = bcm54xx_exp_write(phydev, reg,
322 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
323 if (err < 0)
324 return err;
cd9af3da
NC
325
326 /*
327 * Select 1000BASE-X register set (primary SerDes)
328 */
329 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
330 bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
331 reg | BCM5482_SHD_MODE_1000BX);
332
333 /*
334 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
335 * (Use LED1 as secondary SerDes ACTIVITY LED)
336 */
337 bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
338 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
339 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
340
341 /*
342 * Auto-negotiation doesn't seem to work quite right
343 * in this mode, so we disable it and force it to the
344 * right speed/duplex setting. Only 'link status'
345 * is important.
346 */
347 phydev->autoneg = AUTONEG_DISABLE;
348 phydev->speed = SPEED_1000;
349 phydev->duplex = DUPLEX_FULL;
350 }
351
352 return err;
353}
354
355static int bcm5482_read_status(struct phy_device *phydev)
356{
357 int err;
358
359 err = genphy_read_status(phydev);
360
361 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
362 /*
363 * Only link status matters for 1000Base-X mode, so force
364 * 1000 Mbit/s full-duplex status
365 */
366 if (phydev->link) {
367 phydev->speed = SPEED_1000;
368 phydev->duplex = DUPLEX_FULL;
369 }
370 }
371
372 return err;
373}
374
c4b41c9f
MR
375static int bcm54xx_ack_interrupt(struct phy_device *phydev)
376{
377 int reg;
378
379 /* Clear pending interrupts. */
380 reg = phy_read(phydev, MII_BCM54XX_ISR);
381 if (reg < 0)
382 return reg;
383
384 return 0;
385}
386
387static int bcm54xx_config_intr(struct phy_device *phydev)
388{
389 int reg, err;
390
391 reg = phy_read(phydev, MII_BCM54XX_ECR);
392 if (reg < 0)
393 return reg;
394
395 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
396 reg &= ~MII_BCM54XX_ECR_IM;
397 else
398 reg |= MII_BCM54XX_ECR_IM;
399
400 err = phy_write(phydev, MII_BCM54XX_ECR, reg);
401 return err;
402}
403
57bb7e22
AV
404static int bcm5481_config_aneg(struct phy_device *phydev)
405{
406 int ret;
407
408 /* Aneg firsly. */
409 ret = genphy_config_aneg(phydev);
410
411 /* Then we can set up the delay. */
412 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
413 u16 reg;
414
415 /*
416 * There is no BCM5481 specification available, so down
417 * here is everything we know about "register 0x18". This
418 * at least helps BCM5481 to successfuly receive packets
419 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
420 * says: "This sets delay between the RXD and RXC signals
421 * instead of using trace lengths to achieve timing".
422 */
423
424 /* Set RDX clk delay. */
425 reg = 0x7 | (0x7 << 12);
426 phy_write(phydev, 0x18, reg);
427
428 reg = phy_read(phydev, 0x18);
429 /* Set RDX-RXC skew. */
430 reg |= (1 << 8);
431 /* Write bits 14:0. */
432 reg |= (1 << 15);
433 phy_write(phydev, 0x18, reg);
434 }
435
436 return ret;
437}
438
c4b41c9f
MR
439static struct phy_driver bcm5411_driver = {
440 .phy_id = 0x00206070,
441 .phy_id_mask = 0xfffffff0,
442 .name = "Broadcom BCM5411",
5e0c676c
MC
443 .features = PHY_GBIT_FEATURES |
444 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
c4b41c9f
MR
445 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
446 .config_init = bcm54xx_config_init,
447 .config_aneg = genphy_config_aneg,
448 .read_status = genphy_read_status,
449 .ack_interrupt = bcm54xx_ack_interrupt,
450 .config_intr = bcm54xx_config_intr,
4f4598fd 451 .driver = { .owner = THIS_MODULE },
c4b41c9f
MR
452};
453
454static struct phy_driver bcm5421_driver = {
455 .phy_id = 0x002060e0,
456 .phy_id_mask = 0xfffffff0,
457 .name = "Broadcom BCM5421",
5e0c676c
MC
458 .features = PHY_GBIT_FEATURES |
459 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
c4b41c9f
MR
460 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
461 .config_init = bcm54xx_config_init,
462 .config_aneg = genphy_config_aneg,
463 .read_status = genphy_read_status,
464 .ack_interrupt = bcm54xx_ack_interrupt,
465 .config_intr = bcm54xx_config_intr,
4f4598fd 466 .driver = { .owner = THIS_MODULE },
c4b41c9f
MR
467};
468
469static struct phy_driver bcm5461_driver = {
470 .phy_id = 0x002060c0,
471 .phy_id_mask = 0xfffffff0,
472 .name = "Broadcom BCM5461",
5e0c676c
MC
473 .features = PHY_GBIT_FEATURES |
474 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
c4b41c9f
MR
475 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
476 .config_init = bcm54xx_config_init,
477 .config_aneg = genphy_config_aneg,
478 .read_status = genphy_read_status,
479 .ack_interrupt = bcm54xx_ack_interrupt,
480 .config_intr = bcm54xx_config_intr,
4f4598fd 481 .driver = { .owner = THIS_MODULE },
c4b41c9f
MR
482};
483
b1394f96
PG
484static struct phy_driver bcm5464_driver = {
485 .phy_id = 0x002060b0,
486 .phy_id_mask = 0xfffffff0,
487 .name = "Broadcom BCM5464",
5e0c676c
MC
488 .features = PHY_GBIT_FEATURES |
489 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
b1394f96
PG
490 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
491 .config_init = bcm54xx_config_init,
492 .config_aneg = genphy_config_aneg,
493 .read_status = genphy_read_status,
494 .ack_interrupt = bcm54xx_ack_interrupt,
495 .config_intr = bcm54xx_config_intr,
4f4598fd 496 .driver = { .owner = THIS_MODULE },
b1394f96
PG
497};
498
57bb7e22
AV
499static struct phy_driver bcm5481_driver = {
500 .phy_id = 0x0143bca0,
501 .phy_id_mask = 0xfffffff0,
502 .name = "Broadcom BCM5481",
5e0c676c
MC
503 .features = PHY_GBIT_FEATURES |
504 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
57bb7e22
AV
505 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
506 .config_init = bcm54xx_config_init,
507 .config_aneg = bcm5481_config_aneg,
508 .read_status = genphy_read_status,
509 .ack_interrupt = bcm54xx_ack_interrupt,
510 .config_intr = bcm54xx_config_intr,
4f4598fd 511 .driver = { .owner = THIS_MODULE },
57bb7e22
AV
512};
513
03157ac3 514static struct phy_driver bcm5482_driver = {
57bb7e22 515 .phy_id = 0x0143bcb0,
03157ac3
NC
516 .phy_id_mask = 0xfffffff0,
517 .name = "Broadcom BCM5482",
5e0c676c
MC
518 .features = PHY_GBIT_FEATURES |
519 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
03157ac3 520 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
cd9af3da 521 .config_init = bcm5482_config_init,
03157ac3 522 .config_aneg = genphy_config_aneg,
cd9af3da 523 .read_status = bcm5482_read_status,
03157ac3
NC
524 .ack_interrupt = bcm54xx_ack_interrupt,
525 .config_intr = bcm54xx_config_intr,
4f4598fd 526 .driver = { .owner = THIS_MODULE },
03157ac3
NC
527};
528
772638b6
MC
529static struct phy_driver bcm50610_driver = {
530 .phy_id = PHY_ID_BCM50610,
531 .phy_id_mask = 0xfffffff0,
532 .name = "Broadcom BCM50610",
533 .features = PHY_GBIT_FEATURES |
534 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
535 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
536 .config_init = bcm54xx_config_init,
537 .config_aneg = genphy_config_aneg,
538 .read_status = genphy_read_status,
539 .ack_interrupt = bcm54xx_ack_interrupt,
540 .config_intr = bcm54xx_config_intr,
4f4598fd
MC
541 .driver = { .owner = THIS_MODULE },
542};
543
544static struct phy_driver bcm50610m_driver = {
545 .phy_id = PHY_ID_BCM50610M,
546 .phy_id_mask = 0xfffffff0,
547 .name = "Broadcom BCM50610M",
548 .features = PHY_GBIT_FEATURES |
549 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
550 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
551 .config_init = bcm54xx_config_init,
552 .config_aneg = genphy_config_aneg,
553 .read_status = genphy_read_status,
554 .ack_interrupt = bcm54xx_ack_interrupt,
555 .config_intr = bcm54xx_config_intr,
556 .driver = { .owner = THIS_MODULE },
772638b6
MC
557};
558
2fbb69aa
MC
559static struct phy_driver bcm57780_driver = {
560 .phy_id = 0x03625d90,
561 .phy_id_mask = 0xfffffff0,
562 .name = "Broadcom BCM57780",
563 .features = PHY_GBIT_FEATURES |
564 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
565 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
566 .config_init = bcm54xx_config_init,
567 .config_aneg = genphy_config_aneg,
568 .read_status = genphy_read_status,
569 .ack_interrupt = bcm54xx_ack_interrupt,
570 .config_intr = bcm54xx_config_intr,
4f4598fd 571 .driver = { .owner = THIS_MODULE },
2fbb69aa
MC
572};
573
c4b41c9f
MR
574static int __init broadcom_init(void)
575{
576 int ret;
577
578 ret = phy_driver_register(&bcm5411_driver);
579 if (ret)
580 goto out_5411;
581 ret = phy_driver_register(&bcm5421_driver);
582 if (ret)
583 goto out_5421;
584 ret = phy_driver_register(&bcm5461_driver);
585 if (ret)
586 goto out_5461;
b1394f96
PG
587 ret = phy_driver_register(&bcm5464_driver);
588 if (ret)
589 goto out_5464;
57bb7e22
AV
590 ret = phy_driver_register(&bcm5481_driver);
591 if (ret)
592 goto out_5481;
03157ac3
NC
593 ret = phy_driver_register(&bcm5482_driver);
594 if (ret)
595 goto out_5482;
772638b6
MC
596 ret = phy_driver_register(&bcm50610_driver);
597 if (ret)
598 goto out_50610;
4f4598fd
MC
599 ret = phy_driver_register(&bcm50610m_driver);
600 if (ret)
601 goto out_50610m;
2fbb69aa
MC
602 ret = phy_driver_register(&bcm57780_driver);
603 if (ret)
604 goto out_57780;
c4b41c9f
MR
605 return ret;
606
2fbb69aa 607out_57780:
4f4598fd
MC
608 phy_driver_unregister(&bcm50610m_driver);
609out_50610m:
2fbb69aa 610 phy_driver_unregister(&bcm50610_driver);
772638b6
MC
611out_50610:
612 phy_driver_unregister(&bcm5482_driver);
03157ac3 613out_5482:
57bb7e22
AV
614 phy_driver_unregister(&bcm5481_driver);
615out_5481:
b1394f96
PG
616 phy_driver_unregister(&bcm5464_driver);
617out_5464:
03157ac3 618 phy_driver_unregister(&bcm5461_driver);
c4b41c9f
MR
619out_5461:
620 phy_driver_unregister(&bcm5421_driver);
621out_5421:
622 phy_driver_unregister(&bcm5411_driver);
623out_5411:
624 return ret;
625}
626
627static void __exit broadcom_exit(void)
628{
2fbb69aa 629 phy_driver_unregister(&bcm57780_driver);
4f4598fd 630 phy_driver_unregister(&bcm50610m_driver);
772638b6 631 phy_driver_unregister(&bcm50610_driver);
03157ac3 632 phy_driver_unregister(&bcm5482_driver);
57bb7e22 633 phy_driver_unregister(&bcm5481_driver);
b1394f96 634 phy_driver_unregister(&bcm5464_driver);
c4b41c9f
MR
635 phy_driver_unregister(&bcm5461_driver);
636 phy_driver_unregister(&bcm5421_driver);
637 phy_driver_unregister(&bcm5411_driver);
638}
639
640module_init(broadcom_init);
641module_exit(broadcom_exit);
This page took 0.403097 seconds and 5 git commands to generate.