net: phy: broadcom: extract all registers to brcmphy.h
[linux-2.6/btrfs-unstable.git] / drivers / net / phy / broadcom.c
blob6001d76d8676e74b9c9583ae16770f370771cafd
1 /*
2 * drivers/net/phy/broadcom.c
4 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
5 * transceivers.
7 * Copyright (c) 2006 Maciej W. Rozycki
9 * Inspired by code written by Amy Fong.
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.
17 #include <linux/module.h>
18 #include <linux/phy.h>
19 #include <linux/brcmphy.h>
22 #define BRCM_PHY_MODEL(phydev) \
23 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
25 #define BRCM_PHY_REV(phydev) \
26 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
28 MODULE_DESCRIPTION("Broadcom PHY driver");
29 MODULE_AUTHOR("Maciej W. Rozycki");
30 MODULE_LICENSE("GPL");
33 * Indirect register access functions for the 1000BASE-T/100BASE-TX/10BASE-T
34 * 0x1c shadow registers.
36 static int bcm54xx_shadow_read(struct phy_device *phydev, u16 shadow)
38 phy_write(phydev, MII_BCM54XX_SHD, MII_BCM54XX_SHD_VAL(shadow));
39 return MII_BCM54XX_SHD_DATA(phy_read(phydev, MII_BCM54XX_SHD));
42 static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val)
44 return phy_write(phydev, MII_BCM54XX_SHD,
45 MII_BCM54XX_SHD_WRITE |
46 MII_BCM54XX_SHD_VAL(shadow) |
47 MII_BCM54XX_SHD_DATA(val));
50 /* Indirect register access functions for the Expansion Registers */
51 static int bcm54xx_exp_read(struct phy_device *phydev, u16 regnum)
53 int val;
55 val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
56 if (val < 0)
57 return val;
59 val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
61 /* Restore default value. It's O.K. if this write fails. */
62 phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
64 return val;
67 static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
69 int ret;
71 ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
72 if (ret < 0)
73 return ret;
75 ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
77 /* Restore default value. It's O.K. if this write fails. */
78 phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
80 return ret;
83 static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
85 return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
88 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
89 static int bcm50610_a0_workaround(struct phy_device *phydev)
91 int err;
93 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
94 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
95 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
96 if (err < 0)
97 return err;
99 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
100 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
101 if (err < 0)
102 return err;
104 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
105 MII_BCM54XX_EXP_EXP75_VDACCTRL);
106 if (err < 0)
107 return err;
109 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
110 MII_BCM54XX_EXP_EXP96_MYST);
111 if (err < 0)
112 return err;
114 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
115 MII_BCM54XX_EXP_EXP97_MYST);
117 return err;
120 static int bcm54xx_phydsp_config(struct phy_device *phydev)
122 int err, err2;
124 /* Enable the SMDSP clock */
125 err = bcm54xx_auxctl_write(phydev,
126 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
127 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
128 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
129 if (err < 0)
130 return err;
132 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
133 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
134 /* Clear bit 9 to fix a phy interop issue. */
135 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
136 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
137 if (err < 0)
138 goto error;
140 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
141 err = bcm50610_a0_workaround(phydev);
142 if (err < 0)
143 goto error;
147 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
148 int val;
150 val = bcm54xx_exp_read(phydev, MII_BCM54XX_EXP_EXP75);
151 if (val < 0)
152 goto error;
154 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
155 err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75, val);
158 error:
159 /* Disable the SMDSP clock */
160 err2 = bcm54xx_auxctl_write(phydev,
161 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
162 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
164 /* Return the first error reported. */
165 return err ? err : err2;
168 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
170 u32 orig;
171 int val;
172 bool clk125en = true;
174 /* Abort if we are using an untested phy. */
175 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
176 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
177 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
178 return;
180 val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_SCR3);
181 if (val < 0)
182 return;
184 orig = val;
186 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
187 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
188 BRCM_PHY_REV(phydev) >= 0x3) {
190 * Here, bit 0 _disables_ CLK125 when set.
191 * This bit is set by default.
193 clk125en = false;
194 } else {
195 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
196 /* Here, bit 0 _enables_ CLK125 when set */
197 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
198 clk125en = false;
202 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
203 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
204 else
205 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
207 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
208 val |= BCM54XX_SHD_SCR3_TRDDAPD;
210 if (orig != val)
211 bcm54xx_shadow_write(phydev, BCM54XX_SHD_SCR3, val);
213 val = bcm54xx_shadow_read(phydev, BCM54XX_SHD_APD);
214 if (val < 0)
215 return;
217 orig = val;
219 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
220 val |= BCM54XX_SHD_APD_EN;
221 else
222 val &= ~BCM54XX_SHD_APD_EN;
224 if (orig != val)
225 bcm54xx_shadow_write(phydev, BCM54XX_SHD_APD, val);
228 static int bcm54xx_config_init(struct phy_device *phydev)
230 int reg, err;
232 reg = phy_read(phydev, MII_BCM54XX_ECR);
233 if (reg < 0)
234 return reg;
236 /* Mask interrupts globally. */
237 reg |= MII_BCM54XX_ECR_IM;
238 err = phy_write(phydev, MII_BCM54XX_ECR, reg);
239 if (err < 0)
240 return err;
242 /* Unmask events we are interested in. */
243 reg = ~(MII_BCM54XX_INT_DUPLEX |
244 MII_BCM54XX_INT_SPEED |
245 MII_BCM54XX_INT_LINK);
246 err = phy_write(phydev, MII_BCM54XX_IMR, reg);
247 if (err < 0)
248 return err;
250 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
251 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
252 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
253 bcm54xx_shadow_write(phydev, BCM54XX_SHD_RGMII_MODE, 0);
255 if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
256 (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
257 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
258 bcm54xx_adjust_rxrefclk(phydev);
260 bcm54xx_phydsp_config(phydev);
262 return 0;
265 static int bcm5482_config_init(struct phy_device *phydev)
267 int err, reg;
269 err = bcm54xx_config_init(phydev);
271 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
273 * Enable secondary SerDes and its use as an LED source
275 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_SSD);
276 bcm54xx_shadow_write(phydev, BCM5482_SHD_SSD,
277 reg |
278 BCM5482_SHD_SSD_LEDM |
279 BCM5482_SHD_SSD_EN);
282 * Enable SGMII slave mode and auto-detection
284 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
285 err = bcm54xx_exp_read(phydev, reg);
286 if (err < 0)
287 return err;
288 err = bcm54xx_exp_write(phydev, reg, err |
289 BCM5482_SSD_SGMII_SLAVE_EN |
290 BCM5482_SSD_SGMII_SLAVE_AD);
291 if (err < 0)
292 return err;
295 * Disable secondary SerDes powerdown
297 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
298 err = bcm54xx_exp_read(phydev, reg);
299 if (err < 0)
300 return err;
301 err = bcm54xx_exp_write(phydev, reg,
302 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
303 if (err < 0)
304 return err;
307 * Select 1000BASE-X register set (primary SerDes)
309 reg = bcm54xx_shadow_read(phydev, BCM5482_SHD_MODE);
310 bcm54xx_shadow_write(phydev, BCM5482_SHD_MODE,
311 reg | BCM5482_SHD_MODE_1000BX);
314 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
315 * (Use LED1 as secondary SerDes ACTIVITY LED)
317 bcm54xx_shadow_write(phydev, BCM5482_SHD_LEDS1,
318 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
319 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
322 * Auto-negotiation doesn't seem to work quite right
323 * in this mode, so we disable it and force it to the
324 * right speed/duplex setting. Only 'link status'
325 * is important.
327 phydev->autoneg = AUTONEG_DISABLE;
328 phydev->speed = SPEED_1000;
329 phydev->duplex = DUPLEX_FULL;
332 return err;
335 static int bcm5482_read_status(struct phy_device *phydev)
337 int err;
339 err = genphy_read_status(phydev);
341 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
343 * Only link status matters for 1000Base-X mode, so force
344 * 1000 Mbit/s full-duplex status
346 if (phydev->link) {
347 phydev->speed = SPEED_1000;
348 phydev->duplex = DUPLEX_FULL;
352 return err;
355 static int bcm54xx_ack_interrupt(struct phy_device *phydev)
357 int reg;
359 /* Clear pending interrupts. */
360 reg = phy_read(phydev, MII_BCM54XX_ISR);
361 if (reg < 0)
362 return reg;
364 return 0;
367 static int bcm54xx_config_intr(struct phy_device *phydev)
369 int reg, err;
371 reg = phy_read(phydev, MII_BCM54XX_ECR);
372 if (reg < 0)
373 return reg;
375 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
376 reg &= ~MII_BCM54XX_ECR_IM;
377 else
378 reg |= MII_BCM54XX_ECR_IM;
380 err = phy_write(phydev, MII_BCM54XX_ECR, reg);
381 return err;
384 static int bcm5481_config_aneg(struct phy_device *phydev)
386 int ret;
388 /* Aneg firsly. */
389 ret = genphy_config_aneg(phydev);
391 /* Then we can set up the delay. */
392 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
393 u16 reg;
396 * There is no BCM5481 specification available, so down
397 * here is everything we know about "register 0x18". This
398 * at least helps BCM5481 to successfully receive packets
399 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
400 * says: "This sets delay between the RXD and RXC signals
401 * instead of using trace lengths to achieve timing".
404 /* Set RDX clk delay. */
405 reg = 0x7 | (0x7 << 12);
406 phy_write(phydev, 0x18, reg);
408 reg = phy_read(phydev, 0x18);
409 /* Set RDX-RXC skew. */
410 reg |= (1 << 8);
411 /* Write bits 14:0. */
412 reg |= (1 << 15);
413 phy_write(phydev, 0x18, reg);
416 return ret;
419 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
421 int val;
423 val = phy_read(phydev, reg);
424 if (val < 0)
425 return val;
427 return phy_write(phydev, reg, val | set);
430 static int brcm_fet_config_init(struct phy_device *phydev)
432 int reg, err, err2, brcmtest;
434 /* Reset the PHY to bring it to a known state. */
435 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
436 if (err < 0)
437 return err;
439 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
440 if (reg < 0)
441 return reg;
443 /* Unmask events we are interested in and mask interrupts globally. */
444 reg = MII_BRCM_FET_IR_DUPLEX_EN |
445 MII_BRCM_FET_IR_SPEED_EN |
446 MII_BRCM_FET_IR_LINK_EN |
447 MII_BRCM_FET_IR_ENABLE |
448 MII_BRCM_FET_IR_MASK;
450 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
451 if (err < 0)
452 return err;
454 /* Enable shadow register access */
455 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
456 if (brcmtest < 0)
457 return brcmtest;
459 reg = brcmtest | MII_BRCM_FET_BT_SRE;
461 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
462 if (err < 0)
463 return err;
465 /* Set the LED mode */
466 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
467 if (reg < 0) {
468 err = reg;
469 goto done;
472 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
473 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
475 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
476 if (err < 0)
477 goto done;
479 /* Enable auto MDIX */
480 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
481 MII_BRCM_FET_SHDW_MC_FAME);
482 if (err < 0)
483 goto done;
485 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
486 /* Enable auto power down */
487 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
488 MII_BRCM_FET_SHDW_AS2_APDE);
491 done:
492 /* Disable shadow register access */
493 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
494 if (!err)
495 err = err2;
497 return err;
500 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
502 int reg;
504 /* Clear pending interrupts. */
505 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
506 if (reg < 0)
507 return reg;
509 return 0;
512 static int brcm_fet_config_intr(struct phy_device *phydev)
514 int reg, err;
516 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
517 if (reg < 0)
518 return reg;
520 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
521 reg &= ~MII_BRCM_FET_IR_MASK;
522 else
523 reg |= MII_BRCM_FET_IR_MASK;
525 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
526 return err;
529 static struct phy_driver broadcom_drivers[] = {
531 .phy_id = PHY_ID_BCM5411,
532 .phy_id_mask = 0xfffffff0,
533 .name = "Broadcom BCM5411",
534 .features = PHY_GBIT_FEATURES |
535 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
536 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
537 .config_init = bcm54xx_config_init,
538 .config_aneg = genphy_config_aneg,
539 .read_status = genphy_read_status,
540 .ack_interrupt = bcm54xx_ack_interrupt,
541 .config_intr = bcm54xx_config_intr,
542 .driver = { .owner = THIS_MODULE },
543 }, {
544 .phy_id = PHY_ID_BCM5421,
545 .phy_id_mask = 0xfffffff0,
546 .name = "Broadcom BCM5421",
547 .features = PHY_GBIT_FEATURES |
548 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
549 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
550 .config_init = bcm54xx_config_init,
551 .config_aneg = genphy_config_aneg,
552 .read_status = genphy_read_status,
553 .ack_interrupt = bcm54xx_ack_interrupt,
554 .config_intr = bcm54xx_config_intr,
555 .driver = { .owner = THIS_MODULE },
556 }, {
557 .phy_id = PHY_ID_BCM5461,
558 .phy_id_mask = 0xfffffff0,
559 .name = "Broadcom BCM5461",
560 .features = PHY_GBIT_FEATURES |
561 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
562 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
563 .config_init = bcm54xx_config_init,
564 .config_aneg = genphy_config_aneg,
565 .read_status = genphy_read_status,
566 .ack_interrupt = bcm54xx_ack_interrupt,
567 .config_intr = bcm54xx_config_intr,
568 .driver = { .owner = THIS_MODULE },
569 }, {
570 .phy_id = PHY_ID_BCM5464,
571 .phy_id_mask = 0xfffffff0,
572 .name = "Broadcom BCM5464",
573 .features = PHY_GBIT_FEATURES |
574 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
575 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
576 .config_init = bcm54xx_config_init,
577 .config_aneg = genphy_config_aneg,
578 .read_status = genphy_read_status,
579 .ack_interrupt = bcm54xx_ack_interrupt,
580 .config_intr = bcm54xx_config_intr,
581 .driver = { .owner = THIS_MODULE },
582 }, {
583 .phy_id = PHY_ID_BCM5481,
584 .phy_id_mask = 0xfffffff0,
585 .name = "Broadcom BCM5481",
586 .features = PHY_GBIT_FEATURES |
587 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
588 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
589 .config_init = bcm54xx_config_init,
590 .config_aneg = bcm5481_config_aneg,
591 .read_status = genphy_read_status,
592 .ack_interrupt = bcm54xx_ack_interrupt,
593 .config_intr = bcm54xx_config_intr,
594 .driver = { .owner = THIS_MODULE },
595 }, {
596 .phy_id = PHY_ID_BCM5482,
597 .phy_id_mask = 0xfffffff0,
598 .name = "Broadcom BCM5482",
599 .features = PHY_GBIT_FEATURES |
600 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
601 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
602 .config_init = bcm5482_config_init,
603 .config_aneg = genphy_config_aneg,
604 .read_status = bcm5482_read_status,
605 .ack_interrupt = bcm54xx_ack_interrupt,
606 .config_intr = bcm54xx_config_intr,
607 .driver = { .owner = THIS_MODULE },
608 }, {
609 .phy_id = PHY_ID_BCM50610,
610 .phy_id_mask = 0xfffffff0,
611 .name = "Broadcom BCM50610",
612 .features = PHY_GBIT_FEATURES |
613 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
614 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
615 .config_init = bcm54xx_config_init,
616 .config_aneg = genphy_config_aneg,
617 .read_status = genphy_read_status,
618 .ack_interrupt = bcm54xx_ack_interrupt,
619 .config_intr = bcm54xx_config_intr,
620 .driver = { .owner = THIS_MODULE },
621 }, {
622 .phy_id = PHY_ID_BCM50610M,
623 .phy_id_mask = 0xfffffff0,
624 .name = "Broadcom BCM50610M",
625 .features = PHY_GBIT_FEATURES |
626 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
627 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
628 .config_init = bcm54xx_config_init,
629 .config_aneg = genphy_config_aneg,
630 .read_status = genphy_read_status,
631 .ack_interrupt = bcm54xx_ack_interrupt,
632 .config_intr = bcm54xx_config_intr,
633 .driver = { .owner = THIS_MODULE },
634 }, {
635 .phy_id = PHY_ID_BCM57780,
636 .phy_id_mask = 0xfffffff0,
637 .name = "Broadcom BCM57780",
638 .features = PHY_GBIT_FEATURES |
639 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
640 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
641 .config_init = bcm54xx_config_init,
642 .config_aneg = genphy_config_aneg,
643 .read_status = genphy_read_status,
644 .ack_interrupt = bcm54xx_ack_interrupt,
645 .config_intr = bcm54xx_config_intr,
646 .driver = { .owner = THIS_MODULE },
647 }, {
648 .phy_id = PHY_ID_BCMAC131,
649 .phy_id_mask = 0xfffffff0,
650 .name = "Broadcom BCMAC131",
651 .features = PHY_BASIC_FEATURES |
652 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
653 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
654 .config_init = brcm_fet_config_init,
655 .config_aneg = genphy_config_aneg,
656 .read_status = genphy_read_status,
657 .ack_interrupt = brcm_fet_ack_interrupt,
658 .config_intr = brcm_fet_config_intr,
659 .driver = { .owner = THIS_MODULE },
660 }, {
661 .phy_id = PHY_ID_BCM5241,
662 .phy_id_mask = 0xfffffff0,
663 .name = "Broadcom BCM5241",
664 .features = PHY_BASIC_FEATURES |
665 SUPPORTED_Pause | SUPPORTED_Asym_Pause,
666 .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
667 .config_init = brcm_fet_config_init,
668 .config_aneg = genphy_config_aneg,
669 .read_status = genphy_read_status,
670 .ack_interrupt = brcm_fet_ack_interrupt,
671 .config_intr = brcm_fet_config_intr,
672 .driver = { .owner = THIS_MODULE },
673 } };
675 static int __init broadcom_init(void)
677 return phy_drivers_register(broadcom_drivers,
678 ARRAY_SIZE(broadcom_drivers));
681 static void __exit broadcom_exit(void)
683 phy_drivers_unregister(broadcom_drivers,
684 ARRAY_SIZE(broadcom_drivers));
687 module_init(broadcom_init);
688 module_exit(broadcom_exit);
690 static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
691 { PHY_ID_BCM5411, 0xfffffff0 },
692 { PHY_ID_BCM5421, 0xfffffff0 },
693 { PHY_ID_BCM5461, 0xfffffff0 },
694 { PHY_ID_BCM5464, 0xfffffff0 },
695 { PHY_ID_BCM5482, 0xfffffff0 },
696 { PHY_ID_BCM5482, 0xfffffff0 },
697 { PHY_ID_BCM50610, 0xfffffff0 },
698 { PHY_ID_BCM50610M, 0xfffffff0 },
699 { PHY_ID_BCM57780, 0xfffffff0 },
700 { PHY_ID_BCMAC131, 0xfffffff0 },
701 { PHY_ID_BCM5241, 0xfffffff0 },
705 MODULE_DEVICE_TABLE(mdio, broadcom_tbl);