2 * drivers/net/phy/broadcom.c
4 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
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");
32 /* Indirect register access functions for the Expansion Registers */
33 static int bcm54xx_exp_read(struct phy_device
*phydev
, u16 regnum
)
37 val
= phy_write(phydev
, MII_BCM54XX_EXP_SEL
, regnum
);
41 val
= phy_read(phydev
, MII_BCM54XX_EXP_DATA
);
43 /* Restore default value. It's O.K. if this write fails. */
44 phy_write(phydev
, MII_BCM54XX_EXP_SEL
, 0);
49 static int bcm54xx_exp_write(struct phy_device
*phydev
, u16 regnum
, u16 val
)
53 ret
= phy_write(phydev
, MII_BCM54XX_EXP_SEL
, regnum
);
57 ret
= phy_write(phydev
, MII_BCM54XX_EXP_DATA
, val
);
59 /* Restore default value. It's O.K. if this write fails. */
60 phy_write(phydev
, MII_BCM54XX_EXP_SEL
, 0);
65 static int bcm54xx_auxctl_write(struct phy_device
*phydev
, u16 regnum
, u16 val
)
67 return phy_write(phydev
, MII_BCM54XX_AUX_CTL
, regnum
| val
);
70 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
71 static int bcm50610_a0_workaround(struct phy_device
*phydev
)
75 err
= bcm54xx_exp_write(phydev
, MII_BCM54XX_EXP_AADJ1CH0
,
76 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN
|
77 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF
);
81 err
= bcm54xx_exp_write(phydev
, MII_BCM54XX_EXP_AADJ1CH3
,
82 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ
);
86 err
= bcm54xx_exp_write(phydev
, MII_BCM54XX_EXP_EXP75
,
87 MII_BCM54XX_EXP_EXP75_VDACCTRL
);
91 err
= bcm54xx_exp_write(phydev
, MII_BCM54XX_EXP_EXP96
,
92 MII_BCM54XX_EXP_EXP96_MYST
);
96 err
= bcm54xx_exp_write(phydev
, MII_BCM54XX_EXP_EXP97
,
97 MII_BCM54XX_EXP_EXP97_MYST
);
102 static int bcm54xx_phydsp_config(struct phy_device
*phydev
)
106 /* Enable the SMDSP clock */
107 err
= bcm54xx_auxctl_write(phydev
,
108 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL
,
109 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA
|
110 MII_BCM54XX_AUXCTL_ACTL_TX_6DB
);
114 if (BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610
||
115 BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610M
) {
116 /* Clear bit 9 to fix a phy interop issue. */
117 err
= bcm54xx_exp_write(phydev
, MII_BCM54XX_EXP_EXP08
,
118 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ
);
122 if (phydev
->drv
->phy_id
== PHY_ID_BCM50610
) {
123 err
= bcm50610_a0_workaround(phydev
);
129 if (BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM57780
) {
132 val
= bcm54xx_exp_read(phydev
, MII_BCM54XX_EXP_EXP75
);
136 val
|= MII_BCM54XX_EXP_EXP75_CM_OSC
;
137 err
= bcm54xx_exp_write(phydev
, MII_BCM54XX_EXP_EXP75
, val
);
141 /* Disable the SMDSP clock */
142 err2
= bcm54xx_auxctl_write(phydev
,
143 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL
,
144 MII_BCM54XX_AUXCTL_ACTL_TX_6DB
);
146 /* Return the first error reported. */
147 return err
? err
: err2
;
150 static void bcm54xx_adjust_rxrefclk(struct phy_device
*phydev
)
154 bool clk125en
= true;
156 /* Abort if we are using an untested phy. */
157 if (BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM57780
&&
158 BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM50610
&&
159 BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM50610M
)
162 val
= bcm54xx_shadow_read(phydev
, BCM54XX_SHD_SCR3
);
168 if ((BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610
||
169 BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610M
) &&
170 BRCM_PHY_REV(phydev
) >= 0x3) {
172 * Here, bit 0 _disables_ CLK125 when set.
173 * This bit is set by default.
177 if (phydev
->dev_flags
& PHY_BRCM_RX_REFCLK_UNUSED
) {
178 /* Here, bit 0 _enables_ CLK125 when set */
179 val
&= ~BCM54XX_SHD_SCR3_DEF_CLK125
;
184 if (!clk125en
|| (phydev
->dev_flags
& PHY_BRCM_AUTO_PWRDWN_ENABLE
))
185 val
&= ~BCM54XX_SHD_SCR3_DLLAPD_DIS
;
187 val
|= BCM54XX_SHD_SCR3_DLLAPD_DIS
;
189 if (phydev
->dev_flags
& PHY_BRCM_DIS_TXCRXC_NOENRGY
)
190 val
|= BCM54XX_SHD_SCR3_TRDDAPD
;
193 bcm54xx_shadow_write(phydev
, BCM54XX_SHD_SCR3
, val
);
195 val
= bcm54xx_shadow_read(phydev
, BCM54XX_SHD_APD
);
201 if (!clk125en
|| (phydev
->dev_flags
& PHY_BRCM_AUTO_PWRDWN_ENABLE
))
202 val
|= BCM54XX_SHD_APD_EN
;
204 val
&= ~BCM54XX_SHD_APD_EN
;
207 bcm54xx_shadow_write(phydev
, BCM54XX_SHD_APD
, val
);
210 static int bcm54xx_config_init(struct phy_device
*phydev
)
214 reg
= phy_read(phydev
, MII_BCM54XX_ECR
);
218 /* Mask interrupts globally. */
219 reg
|= MII_BCM54XX_ECR_IM
;
220 err
= phy_write(phydev
, MII_BCM54XX_ECR
, reg
);
224 /* Unmask events we are interested in. */
225 reg
= ~(MII_BCM54XX_INT_DUPLEX
|
226 MII_BCM54XX_INT_SPEED
|
227 MII_BCM54XX_INT_LINK
);
228 err
= phy_write(phydev
, MII_BCM54XX_IMR
, reg
);
232 if ((BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610
||
233 BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610M
) &&
234 (phydev
->dev_flags
& PHY_BRCM_CLEAR_RGMII_MODE
))
235 bcm54xx_shadow_write(phydev
, BCM54XX_SHD_RGMII_MODE
, 0);
237 if ((phydev
->dev_flags
& PHY_BRCM_RX_REFCLK_UNUSED
) ||
238 (phydev
->dev_flags
& PHY_BRCM_DIS_TXCRXC_NOENRGY
) ||
239 (phydev
->dev_flags
& PHY_BRCM_AUTO_PWRDWN_ENABLE
))
240 bcm54xx_adjust_rxrefclk(phydev
);
242 bcm54xx_phydsp_config(phydev
);
247 static int bcm5482_config_init(struct phy_device
*phydev
)
251 err
= bcm54xx_config_init(phydev
);
253 if (phydev
->dev_flags
& PHY_BCM_FLAGS_MODE_1000BX
) {
255 * Enable secondary SerDes and its use as an LED source
257 reg
= bcm54xx_shadow_read(phydev
, BCM5482_SHD_SSD
);
258 bcm54xx_shadow_write(phydev
, BCM5482_SHD_SSD
,
260 BCM5482_SHD_SSD_LEDM
|
264 * Enable SGMII slave mode and auto-detection
266 reg
= BCM5482_SSD_SGMII_SLAVE
| MII_BCM54XX_EXP_SEL_SSD
;
267 err
= bcm54xx_exp_read(phydev
, reg
);
270 err
= bcm54xx_exp_write(phydev
, reg
, err
|
271 BCM5482_SSD_SGMII_SLAVE_EN
|
272 BCM5482_SSD_SGMII_SLAVE_AD
);
277 * Disable secondary SerDes powerdown
279 reg
= BCM5482_SSD_1000BX_CTL
| MII_BCM54XX_EXP_SEL_SSD
;
280 err
= bcm54xx_exp_read(phydev
, reg
);
283 err
= bcm54xx_exp_write(phydev
, reg
,
284 err
& ~BCM5482_SSD_1000BX_CTL_PWRDOWN
);
289 * Select 1000BASE-X register set (primary SerDes)
291 reg
= bcm54xx_shadow_read(phydev
, BCM5482_SHD_MODE
);
292 bcm54xx_shadow_write(phydev
, BCM5482_SHD_MODE
,
293 reg
| BCM5482_SHD_MODE_1000BX
);
296 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
297 * (Use LED1 as secondary SerDes ACTIVITY LED)
299 bcm54xx_shadow_write(phydev
, BCM5482_SHD_LEDS1
,
300 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED
) |
301 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2
));
304 * Auto-negotiation doesn't seem to work quite right
305 * in this mode, so we disable it and force it to the
306 * right speed/duplex setting. Only 'link status'
309 phydev
->autoneg
= AUTONEG_DISABLE
;
310 phydev
->speed
= SPEED_1000
;
311 phydev
->duplex
= DUPLEX_FULL
;
317 static int bcm5482_read_status(struct phy_device
*phydev
)
321 err
= genphy_read_status(phydev
);
323 if (phydev
->dev_flags
& PHY_BCM_FLAGS_MODE_1000BX
) {
325 * Only link status matters for 1000Base-X mode, so force
326 * 1000 Mbit/s full-duplex status
329 phydev
->speed
= SPEED_1000
;
330 phydev
->duplex
= DUPLEX_FULL
;
337 static int bcm54xx_ack_interrupt(struct phy_device
*phydev
)
341 /* Clear pending interrupts. */
342 reg
= phy_read(phydev
, MII_BCM54XX_ISR
);
349 static int bcm54xx_config_intr(struct phy_device
*phydev
)
353 reg
= phy_read(phydev
, MII_BCM54XX_ECR
);
357 if (phydev
->interrupts
== PHY_INTERRUPT_ENABLED
)
358 reg
&= ~MII_BCM54XX_ECR_IM
;
360 reg
|= MII_BCM54XX_ECR_IM
;
362 err
= phy_write(phydev
, MII_BCM54XX_ECR
, reg
);
366 static int bcm5481_config_aneg(struct phy_device
*phydev
)
371 ret
= genphy_config_aneg(phydev
);
373 /* Then we can set up the delay. */
374 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII_RXID
) {
378 * There is no BCM5481 specification available, so down
379 * here is everything we know about "register 0x18". This
380 * at least helps BCM5481 to successfully receive packets
381 * on MPC8360E-RDK board. Peter Barada <peterb@logicpd.com>
382 * says: "This sets delay between the RXD and RXC signals
383 * instead of using trace lengths to achieve timing".
386 /* Set RDX clk delay. */
387 reg
= 0x7 | (0x7 << 12);
388 phy_write(phydev
, 0x18, reg
);
390 reg
= phy_read(phydev
, 0x18);
391 /* Set RDX-RXC skew. */
393 /* Write bits 14:0. */
395 phy_write(phydev
, 0x18, reg
);
401 static int brcm_phy_setbits(struct phy_device
*phydev
, int reg
, int set
)
405 val
= phy_read(phydev
, reg
);
409 return phy_write(phydev
, reg
, val
| set
);
412 static int brcm_fet_config_init(struct phy_device
*phydev
)
414 int reg
, err
, err2
, brcmtest
;
416 /* Reset the PHY to bring it to a known state. */
417 err
= phy_write(phydev
, MII_BMCR
, BMCR_RESET
);
421 reg
= phy_read(phydev
, MII_BRCM_FET_INTREG
);
425 /* Unmask events we are interested in and mask interrupts globally. */
426 reg
= MII_BRCM_FET_IR_DUPLEX_EN
|
427 MII_BRCM_FET_IR_SPEED_EN
|
428 MII_BRCM_FET_IR_LINK_EN
|
429 MII_BRCM_FET_IR_ENABLE
|
430 MII_BRCM_FET_IR_MASK
;
432 err
= phy_write(phydev
, MII_BRCM_FET_INTREG
, reg
);
436 /* Enable shadow register access */
437 brcmtest
= phy_read(phydev
, MII_BRCM_FET_BRCMTEST
);
441 reg
= brcmtest
| MII_BRCM_FET_BT_SRE
;
443 err
= phy_write(phydev
, MII_BRCM_FET_BRCMTEST
, reg
);
447 /* Set the LED mode */
448 reg
= phy_read(phydev
, MII_BRCM_FET_SHDW_AUXMODE4
);
454 reg
&= ~MII_BRCM_FET_SHDW_AM4_LED_MASK
;
455 reg
|= MII_BRCM_FET_SHDW_AM4_LED_MODE1
;
457 err
= phy_write(phydev
, MII_BRCM_FET_SHDW_AUXMODE4
, reg
);
461 /* Enable auto MDIX */
462 err
= brcm_phy_setbits(phydev
, MII_BRCM_FET_SHDW_MISCCTRL
,
463 MII_BRCM_FET_SHDW_MC_FAME
);
467 if (phydev
->dev_flags
& PHY_BRCM_AUTO_PWRDWN_ENABLE
) {
468 /* Enable auto power down */
469 err
= brcm_phy_setbits(phydev
, MII_BRCM_FET_SHDW_AUXSTAT2
,
470 MII_BRCM_FET_SHDW_AS2_APDE
);
474 /* Disable shadow register access */
475 err2
= phy_write(phydev
, MII_BRCM_FET_BRCMTEST
, brcmtest
);
482 static int brcm_fet_ack_interrupt(struct phy_device
*phydev
)
486 /* Clear pending interrupts. */
487 reg
= phy_read(phydev
, MII_BRCM_FET_INTREG
);
494 static int brcm_fet_config_intr(struct phy_device
*phydev
)
498 reg
= phy_read(phydev
, MII_BRCM_FET_INTREG
);
502 if (phydev
->interrupts
== PHY_INTERRUPT_ENABLED
)
503 reg
&= ~MII_BRCM_FET_IR_MASK
;
505 reg
|= MII_BRCM_FET_IR_MASK
;
507 err
= phy_write(phydev
, MII_BRCM_FET_INTREG
, reg
);
511 static struct phy_driver broadcom_drivers
[] = {
513 .phy_id
= PHY_ID_BCM5411
,
514 .phy_id_mask
= 0xfffffff0,
515 .name
= "Broadcom BCM5411",
516 .features
= PHY_GBIT_FEATURES
|
517 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
518 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
519 .config_init
= bcm54xx_config_init
,
520 .config_aneg
= genphy_config_aneg
,
521 .read_status
= genphy_read_status
,
522 .ack_interrupt
= bcm54xx_ack_interrupt
,
523 .config_intr
= bcm54xx_config_intr
,
524 .driver
= { .owner
= THIS_MODULE
},
526 .phy_id
= PHY_ID_BCM5421
,
527 .phy_id_mask
= 0xfffffff0,
528 .name
= "Broadcom BCM5421",
529 .features
= PHY_GBIT_FEATURES
|
530 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
531 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
532 .config_init
= bcm54xx_config_init
,
533 .config_aneg
= genphy_config_aneg
,
534 .read_status
= genphy_read_status
,
535 .ack_interrupt
= bcm54xx_ack_interrupt
,
536 .config_intr
= bcm54xx_config_intr
,
537 .driver
= { .owner
= THIS_MODULE
},
539 .phy_id
= PHY_ID_BCM5461
,
540 .phy_id_mask
= 0xfffffff0,
541 .name
= "Broadcom BCM5461",
542 .features
= PHY_GBIT_FEATURES
|
543 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
544 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
545 .config_init
= bcm54xx_config_init
,
546 .config_aneg
= genphy_config_aneg
,
547 .read_status
= genphy_read_status
,
548 .ack_interrupt
= bcm54xx_ack_interrupt
,
549 .config_intr
= bcm54xx_config_intr
,
550 .driver
= { .owner
= THIS_MODULE
},
552 .phy_id
= PHY_ID_BCM54616S
,
553 .phy_id_mask
= 0xfffffff0,
554 .name
= "Broadcom BCM54616S",
555 .features
= PHY_GBIT_FEATURES
|
556 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
557 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
558 .config_init
= bcm54xx_config_init
,
559 .config_aneg
= genphy_config_aneg
,
560 .read_status
= genphy_read_status
,
561 .ack_interrupt
= bcm54xx_ack_interrupt
,
562 .config_intr
= bcm54xx_config_intr
,
563 .driver
= { .owner
= THIS_MODULE
},
565 .phy_id
= PHY_ID_BCM5464
,
566 .phy_id_mask
= 0xfffffff0,
567 .name
= "Broadcom BCM5464",
568 .features
= PHY_GBIT_FEATURES
|
569 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
570 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
571 .config_init
= bcm54xx_config_init
,
572 .config_aneg
= genphy_config_aneg
,
573 .read_status
= genphy_read_status
,
574 .ack_interrupt
= bcm54xx_ack_interrupt
,
575 .config_intr
= bcm54xx_config_intr
,
576 .driver
= { .owner
= THIS_MODULE
},
578 .phy_id
= PHY_ID_BCM5481
,
579 .phy_id_mask
= 0xfffffff0,
580 .name
= "Broadcom BCM5481",
581 .features
= PHY_GBIT_FEATURES
|
582 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
583 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
584 .config_init
= bcm54xx_config_init
,
585 .config_aneg
= bcm5481_config_aneg
,
586 .read_status
= genphy_read_status
,
587 .ack_interrupt
= bcm54xx_ack_interrupt
,
588 .config_intr
= bcm54xx_config_intr
,
589 .driver
= { .owner
= THIS_MODULE
},
591 .phy_id
= PHY_ID_BCM5482
,
592 .phy_id_mask
= 0xfffffff0,
593 .name
= "Broadcom BCM5482",
594 .features
= PHY_GBIT_FEATURES
|
595 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
596 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
597 .config_init
= bcm5482_config_init
,
598 .config_aneg
= genphy_config_aneg
,
599 .read_status
= bcm5482_read_status
,
600 .ack_interrupt
= bcm54xx_ack_interrupt
,
601 .config_intr
= bcm54xx_config_intr
,
602 .driver
= { .owner
= THIS_MODULE
},
604 .phy_id
= PHY_ID_BCM50610
,
605 .phy_id_mask
= 0xfffffff0,
606 .name
= "Broadcom BCM50610",
607 .features
= PHY_GBIT_FEATURES
|
608 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
609 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
610 .config_init
= bcm54xx_config_init
,
611 .config_aneg
= genphy_config_aneg
,
612 .read_status
= genphy_read_status
,
613 .ack_interrupt
= bcm54xx_ack_interrupt
,
614 .config_intr
= bcm54xx_config_intr
,
615 .driver
= { .owner
= THIS_MODULE
},
617 .phy_id
= PHY_ID_BCM50610M
,
618 .phy_id_mask
= 0xfffffff0,
619 .name
= "Broadcom BCM50610M",
620 .features
= PHY_GBIT_FEATURES
|
621 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
622 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
623 .config_init
= bcm54xx_config_init
,
624 .config_aneg
= genphy_config_aneg
,
625 .read_status
= genphy_read_status
,
626 .ack_interrupt
= bcm54xx_ack_interrupt
,
627 .config_intr
= bcm54xx_config_intr
,
628 .driver
= { .owner
= THIS_MODULE
},
630 .phy_id
= PHY_ID_BCM57780
,
631 .phy_id_mask
= 0xfffffff0,
632 .name
= "Broadcom BCM57780",
633 .features
= PHY_GBIT_FEATURES
|
634 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
635 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
636 .config_init
= bcm54xx_config_init
,
637 .config_aneg
= genphy_config_aneg
,
638 .read_status
= genphy_read_status
,
639 .ack_interrupt
= bcm54xx_ack_interrupt
,
640 .config_intr
= bcm54xx_config_intr
,
641 .driver
= { .owner
= THIS_MODULE
},
643 .phy_id
= PHY_ID_BCMAC131
,
644 .phy_id_mask
= 0xfffffff0,
645 .name
= "Broadcom BCMAC131",
646 .features
= PHY_BASIC_FEATURES
|
647 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
648 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
649 .config_init
= brcm_fet_config_init
,
650 .config_aneg
= genphy_config_aneg
,
651 .read_status
= genphy_read_status
,
652 .ack_interrupt
= brcm_fet_ack_interrupt
,
653 .config_intr
= brcm_fet_config_intr
,
654 .driver
= { .owner
= THIS_MODULE
},
656 .phy_id
= PHY_ID_BCM5241
,
657 .phy_id_mask
= 0xfffffff0,
658 .name
= "Broadcom BCM5241",
659 .features
= PHY_BASIC_FEATURES
|
660 SUPPORTED_Pause
| SUPPORTED_Asym_Pause
,
661 .flags
= PHY_HAS_MAGICANEG
| PHY_HAS_INTERRUPT
,
662 .config_init
= brcm_fet_config_init
,
663 .config_aneg
= genphy_config_aneg
,
664 .read_status
= genphy_read_status
,
665 .ack_interrupt
= brcm_fet_ack_interrupt
,
666 .config_intr
= brcm_fet_config_intr
,
667 .driver
= { .owner
= THIS_MODULE
},
670 module_phy_driver(broadcom_drivers
);
672 static struct mdio_device_id __maybe_unused broadcom_tbl
[] = {
673 { PHY_ID_BCM5411
, 0xfffffff0 },
674 { PHY_ID_BCM5421
, 0xfffffff0 },
675 { PHY_ID_BCM5461
, 0xfffffff0 },
676 { PHY_ID_BCM54616S
, 0xfffffff0 },
677 { PHY_ID_BCM5464
, 0xfffffff0 },
678 { PHY_ID_BCM5482
, 0xfffffff0 },
679 { PHY_ID_BCM5482
, 0xfffffff0 },
680 { PHY_ID_BCM50610
, 0xfffffff0 },
681 { PHY_ID_BCM50610M
, 0xfffffff0 },
682 { PHY_ID_BCM57780
, 0xfffffff0 },
683 { PHY_ID_BCMAC131
, 0xfffffff0 },
684 { PHY_ID_BCM5241
, 0xfffffff0 },
688 MODULE_DEVICE_TABLE(mdio
, broadcom_tbl
);