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 "bcm-phy-lib.h"
18 #include <linux/delay.h>
19 #include <linux/module.h>
20 #include <linux/phy.h>
21 #include <linux/brcmphy.h>
24 #define BRCM_PHY_MODEL(phydev) \
25 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
27 #define BRCM_PHY_REV(phydev) \
28 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
30 MODULE_DESCRIPTION("Broadcom PHY driver");
31 MODULE_AUTHOR("Maciej W. Rozycki");
32 MODULE_LICENSE("GPL");
34 static int bcm54210e_config_init(struct phy_device *phydev)
38 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
39 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
40 val |= MII_BCM54XX_AUXCTL_MISC_WREN;
41 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val);
43 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
44 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
45 bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
50 static int bcm54612e_config_init(struct phy_device *phydev)
52 /* Clear TX internal delay unless requested. */
53 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
54 (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
55 /* Disable TXD to GTXCLK clock delay (default set) */
56 /* Bit 9 is the only field in shadow register 00011 */
57 bcm_phy_write_shadow(phydev, 0x03, 0);
60 /* Clear RX internal delay unless requested. */
61 if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
62 (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
65 reg = bcm54xx_auxctl_read(phydev,
66 MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
67 /* Disable RXD to RXC delay (default set) */
68 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
69 /* Clear shadow selector field */
70 reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
71 bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
72 MII_BCM54XX_AUXCTL_MISC_WREN | reg);
78 static int bcm5481x_config(struct phy_device *phydev)
82 /* handling PHY's internal RX clock delay */
83 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
84 val |= MII_BCM54XX_AUXCTL_MISC_WREN;
85 if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||
86 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
87 /* Disable RGMII RXC-RXD skew */
88 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
90 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
91 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
92 /* Enable RGMII RXC-RXD skew */
93 val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
95 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
100 /* handling PHY's internal TX clock delay */
101 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
102 if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||
103 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
104 /* Disable internal TX clock delay */
105 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
107 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
108 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
109 /* Enable internal TX clock delay */
110 val |= BCM54810_SHD_CLK_CTL_GTXCLK_EN;
112 rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
119 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
120 static int bcm50610_a0_workaround(struct phy_device *phydev)
124 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,
125 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
126 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
130 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,
131 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
135 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,
136 MII_BCM54XX_EXP_EXP75_VDACCTRL);
140 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,
141 MII_BCM54XX_EXP_EXP96_MYST);
145 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,
146 MII_BCM54XX_EXP_EXP97_MYST);
151 static int bcm54xx_phydsp_config(struct phy_device *phydev)
155 /* Enable the SMDSP clock */
156 err = bcm54xx_auxctl_write(phydev,
157 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
158 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
159 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
163 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
164 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {
165 /* Clear bit 9 to fix a phy interop issue. */
166 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,
167 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);
171 if (phydev->drv->phy_id == PHY_ID_BCM50610) {
172 err = bcm50610_a0_workaround(phydev);
178 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {
181 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);
185 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;
186 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);
190 /* Disable the SMDSP clock */
191 err2 = bcm54xx_auxctl_write(phydev,
192 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
193 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
195 /* Return the first error reported. */
196 return err ? err : err2;
199 static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)
203 bool clk125en = true;
205 /* Abort if we are using an untested phy. */
206 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&
207 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&
208 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M)
211 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);
217 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
218 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
219 BRCM_PHY_REV(phydev) >= 0x3) {
221 * Here, bit 0 _disables_ CLK125 when set.
222 * This bit is set by default.
226 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {
227 /* Here, bit 0 _enables_ CLK125 when set */
228 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;
233 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
234 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;
236 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;
238 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY)
239 val |= BCM54XX_SHD_SCR3_TRDDAPD;
242 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);
244 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);
250 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
251 val |= BCM54XX_SHD_APD_EN;
253 val &= ~BCM54XX_SHD_APD_EN;
256 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);
259 static int bcm54xx_config_init(struct phy_device *phydev)
263 reg = phy_read(phydev, MII_BCM54XX_ECR);
267 /* Mask interrupts globally. */
268 reg |= MII_BCM54XX_ECR_IM;
269 err = phy_write(phydev, MII_BCM54XX_ECR, reg);
273 /* Unmask events we are interested in. */
274 reg = ~(MII_BCM54XX_INT_DUPLEX |
275 MII_BCM54XX_INT_SPEED |
276 MII_BCM54XX_INT_LINK);
277 err = phy_write(phydev, MII_BCM54XX_IMR, reg);
281 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||
282 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&
283 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))
284 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);
286 if ((phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) ||
287 (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) ||
288 (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
289 bcm54xx_adjust_rxrefclk(phydev);
291 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54210E) {
292 err = bcm54210e_config_init(phydev);
295 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
296 err = bcm54612e_config_init(phydev);
299 } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
300 /* For BCM54810, we need to disable BroadR-Reach function */
301 val = bcm_phy_read_exp(phydev,
302 BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
303 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
304 err = bcm_phy_write_exp(phydev,
305 BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
311 bcm54xx_phydsp_config(phydev);
316 static int bcm5482_config_init(struct phy_device *phydev)
320 err = bcm54xx_config_init(phydev);
322 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
324 * Enable secondary SerDes and its use as an LED source
326 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD);
327 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD,
329 BCM5482_SHD_SSD_LEDM |
333 * Enable SGMII slave mode and auto-detection
335 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
336 err = bcm_phy_read_exp(phydev, reg);
339 err = bcm_phy_write_exp(phydev, reg, err |
340 BCM5482_SSD_SGMII_SLAVE_EN |
341 BCM5482_SSD_SGMII_SLAVE_AD);
346 * Disable secondary SerDes powerdown
348 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
349 err = bcm_phy_read_exp(phydev, reg);
352 err = bcm_phy_write_exp(phydev, reg,
353 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
358 * Select 1000BASE-X register set (primary SerDes)
360 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_MODE);
361 bcm_phy_write_shadow(phydev, BCM5482_SHD_MODE,
362 reg | BCM5482_SHD_MODE_1000BX);
365 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
366 * (Use LED1 as secondary SerDes ACTIVITY LED)
368 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1,
369 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) |
370 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2));
373 * Auto-negotiation doesn't seem to work quite right
374 * in this mode, so we disable it and force it to the
375 * right speed/duplex setting. Only 'link status'
378 phydev->autoneg = AUTONEG_DISABLE;
379 phydev->speed = SPEED_1000;
380 phydev->duplex = DUPLEX_FULL;
386 static int bcm5482_read_status(struct phy_device *phydev)
390 err = genphy_read_status(phydev);
392 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) {
394 * Only link status matters for 1000Base-X mode, so force
395 * 1000 Mbit/s full-duplex status
398 phydev->speed = SPEED_1000;
399 phydev->duplex = DUPLEX_FULL;
406 static int bcm5481_config_aneg(struct phy_device *phydev)
408 struct device_node *np = phydev->mdio.dev.of_node;
412 ret = genphy_config_aneg(phydev);
414 /* Then we can set up the delay. */
415 bcm5481x_config(phydev);
417 if (of_property_read_bool(np, "enet-phy-lane-swap")) {
418 /* Lane Swap - Undocumented register...magic! */
419 ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
428 static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
432 val = phy_read(phydev, reg);
436 return phy_write(phydev, reg, val | set);
439 static int brcm_fet_config_init(struct phy_device *phydev)
441 int reg, err, err2, brcmtest;
443 /* Reset the PHY to bring it to a known state. */
444 err = phy_write(phydev, MII_BMCR, BMCR_RESET);
448 /* The datasheet indicates the PHY needs up to 1us to complete a reset,
449 * build some slack here.
451 usleep_range(1000, 2000);
453 /* The PHY requires 65 MDC clock cycles to complete a write operation
454 * and turnaround the line properly.
456 * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac)
457 * may flag the lack of turn-around as a read failure. This is
458 * particularly true with this combination since the MDIO controller
459 * only used 64 MDC cycles. This is not a critical failure in this
460 * specific case and it has no functional impact otherwise, so we let
461 * that one go through. If there is a genuine bus error, the next read
462 * of MII_BRCM_FET_INTREG will error out.
464 err = phy_read(phydev, MII_BMCR);
465 if (err < 0 && err != -EIO)
468 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
472 /* Unmask events we are interested in and mask interrupts globally. */
473 reg = MII_BRCM_FET_IR_DUPLEX_EN |
474 MII_BRCM_FET_IR_SPEED_EN |
475 MII_BRCM_FET_IR_LINK_EN |
476 MII_BRCM_FET_IR_ENABLE |
477 MII_BRCM_FET_IR_MASK;
479 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
483 /* Enable shadow register access */
484 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
488 reg = brcmtest | MII_BRCM_FET_BT_SRE;
490 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
494 /* Set the LED mode */
495 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);
501 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK;
502 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1;
504 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);
508 /* Enable auto MDIX */
509 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,
510 MII_BRCM_FET_SHDW_MC_FAME);
514 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {
515 /* Enable auto power down */
516 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,
517 MII_BRCM_FET_SHDW_AS2_APDE);
521 /* Disable shadow register access */
522 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
529 static int brcm_fet_ack_interrupt(struct phy_device *phydev)
533 /* Clear pending interrupts. */
534 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
541 static int brcm_fet_config_intr(struct phy_device *phydev)
545 reg = phy_read(phydev, MII_BRCM_FET_INTREG);
549 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
550 reg &= ~MII_BRCM_FET_IR_MASK;
552 reg |= MII_BRCM_FET_IR_MASK;
554 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);
558 static struct phy_driver broadcom_drivers[] = {
560 .phy_id = PHY_ID_BCM5411,
561 .phy_id_mask = 0xfffffff0,
562 .name = "Broadcom BCM5411",
563 .features = PHY_GBIT_FEATURES,
564 .flags = PHY_HAS_INTERRUPT,
565 .config_init = bcm54xx_config_init,
566 .config_aneg = genphy_config_aneg,
567 .read_status = genphy_read_status,
568 .ack_interrupt = bcm_phy_ack_intr,
569 .config_intr = bcm_phy_config_intr,
571 .phy_id = PHY_ID_BCM5421,
572 .phy_id_mask = 0xfffffff0,
573 .name = "Broadcom BCM5421",
574 .features = PHY_GBIT_FEATURES,
575 .flags = PHY_HAS_INTERRUPT,
576 .config_init = bcm54xx_config_init,
577 .config_aneg = genphy_config_aneg,
578 .read_status = genphy_read_status,
579 .ack_interrupt = bcm_phy_ack_intr,
580 .config_intr = bcm_phy_config_intr,
582 .phy_id = PHY_ID_BCM54210E,
583 .phy_id_mask = 0xfffffff0,
584 .name = "Broadcom BCM54210E",
585 .features = PHY_GBIT_FEATURES,
586 .flags = PHY_HAS_INTERRUPT,
587 .config_init = bcm54xx_config_init,
588 .config_aneg = genphy_config_aneg,
589 .read_status = genphy_read_status,
590 .ack_interrupt = bcm_phy_ack_intr,
591 .config_intr = bcm_phy_config_intr,
593 .phy_id = PHY_ID_BCM5461,
594 .phy_id_mask = 0xfffffff0,
595 .name = "Broadcom BCM5461",
596 .features = PHY_GBIT_FEATURES,
597 .flags = PHY_HAS_INTERRUPT,
598 .config_init = bcm54xx_config_init,
599 .config_aneg = genphy_config_aneg,
600 .read_status = genphy_read_status,
601 .ack_interrupt = bcm_phy_ack_intr,
602 .config_intr = bcm_phy_config_intr,
604 .phy_id = PHY_ID_BCM54612E,
605 .phy_id_mask = 0xfffffff0,
606 .name = "Broadcom BCM54612E",
607 .features = PHY_GBIT_FEATURES,
608 .flags = PHY_HAS_INTERRUPT,
609 .config_init = bcm54xx_config_init,
610 .config_aneg = genphy_config_aneg,
611 .read_status = genphy_read_status,
612 .ack_interrupt = bcm_phy_ack_intr,
613 .config_intr = bcm_phy_config_intr,
615 .phy_id = PHY_ID_BCM54616S,
616 .phy_id_mask = 0xfffffff0,
617 .name = "Broadcom BCM54616S",
618 .features = PHY_GBIT_FEATURES,
619 .flags = PHY_HAS_INTERRUPT,
620 .config_init = bcm54xx_config_init,
621 .config_aneg = genphy_config_aneg,
622 .read_status = genphy_read_status,
623 .ack_interrupt = bcm_phy_ack_intr,
624 .config_intr = bcm_phy_config_intr,
626 .phy_id = PHY_ID_BCM5464,
627 .phy_id_mask = 0xfffffff0,
628 .name = "Broadcom BCM5464",
629 .features = PHY_GBIT_FEATURES,
630 .flags = PHY_HAS_INTERRUPT,
631 .config_init = bcm54xx_config_init,
632 .config_aneg = genphy_config_aneg,
633 .read_status = genphy_read_status,
634 .ack_interrupt = bcm_phy_ack_intr,
635 .config_intr = bcm_phy_config_intr,
637 .phy_id = PHY_ID_BCM5481,
638 .phy_id_mask = 0xfffffff0,
639 .name = "Broadcom BCM5481",
640 .features = PHY_GBIT_FEATURES,
641 .flags = PHY_HAS_INTERRUPT,
642 .config_init = bcm54xx_config_init,
643 .config_aneg = bcm5481_config_aneg,
644 .read_status = genphy_read_status,
645 .ack_interrupt = bcm_phy_ack_intr,
646 .config_intr = bcm_phy_config_intr,
648 .phy_id = PHY_ID_BCM54810,
649 .phy_id_mask = 0xfffffff0,
650 .name = "Broadcom BCM54810",
651 .features = PHY_GBIT_FEATURES,
652 .flags = PHY_HAS_INTERRUPT,
653 .config_init = bcm54xx_config_init,
654 .config_aneg = bcm5481_config_aneg,
655 .read_status = genphy_read_status,
656 .ack_interrupt = bcm_phy_ack_intr,
657 .config_intr = bcm_phy_config_intr,
659 .phy_id = PHY_ID_BCM5482,
660 .phy_id_mask = 0xfffffff0,
661 .name = "Broadcom BCM5482",
662 .features = PHY_GBIT_FEATURES,
663 .flags = PHY_HAS_INTERRUPT,
664 .config_init = bcm5482_config_init,
665 .config_aneg = genphy_config_aneg,
666 .read_status = bcm5482_read_status,
667 .ack_interrupt = bcm_phy_ack_intr,
668 .config_intr = bcm_phy_config_intr,
670 .phy_id = PHY_ID_BCM50610,
671 .phy_id_mask = 0xfffffff0,
672 .name = "Broadcom BCM50610",
673 .features = PHY_GBIT_FEATURES,
674 .flags = PHY_HAS_INTERRUPT,
675 .config_init = bcm54xx_config_init,
676 .config_aneg = genphy_config_aneg,
677 .read_status = genphy_read_status,
678 .ack_interrupt = bcm_phy_ack_intr,
679 .config_intr = bcm_phy_config_intr,
681 .phy_id = PHY_ID_BCM50610M,
682 .phy_id_mask = 0xfffffff0,
683 .name = "Broadcom BCM50610M",
684 .features = PHY_GBIT_FEATURES,
685 .flags = PHY_HAS_INTERRUPT,
686 .config_init = bcm54xx_config_init,
687 .config_aneg = genphy_config_aneg,
688 .read_status = genphy_read_status,
689 .ack_interrupt = bcm_phy_ack_intr,
690 .config_intr = bcm_phy_config_intr,
692 .phy_id = PHY_ID_BCM57780,
693 .phy_id_mask = 0xfffffff0,
694 .name = "Broadcom BCM57780",
695 .features = PHY_GBIT_FEATURES,
696 .flags = PHY_HAS_INTERRUPT,
697 .config_init = bcm54xx_config_init,
698 .config_aneg = genphy_config_aneg,
699 .read_status = genphy_read_status,
700 .ack_interrupt = bcm_phy_ack_intr,
701 .config_intr = bcm_phy_config_intr,
703 .phy_id = PHY_ID_BCMAC131,
704 .phy_id_mask = 0xfffffff0,
705 .name = "Broadcom BCMAC131",
706 .features = PHY_BASIC_FEATURES,
707 .flags = PHY_HAS_INTERRUPT,
708 .config_init = brcm_fet_config_init,
709 .config_aneg = genphy_config_aneg,
710 .read_status = genphy_read_status,
711 .ack_interrupt = brcm_fet_ack_interrupt,
712 .config_intr = brcm_fet_config_intr,
714 .phy_id = PHY_ID_BCM5241,
715 .phy_id_mask = 0xfffffff0,
716 .name = "Broadcom BCM5241",
717 .features = PHY_BASIC_FEATURES,
718 .flags = PHY_HAS_INTERRUPT,
719 .config_init = brcm_fet_config_init,
720 .config_aneg = genphy_config_aneg,
721 .read_status = genphy_read_status,
722 .ack_interrupt = brcm_fet_ack_interrupt,
723 .config_intr = brcm_fet_config_intr,
726 module_phy_driver(broadcom_drivers);
728 static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
729 { PHY_ID_BCM5411, 0xfffffff0 },
730 { PHY_ID_BCM5421, 0xfffffff0 },
731 { PHY_ID_BCM54210E, 0xfffffff0 },
732 { PHY_ID_BCM5461, 0xfffffff0 },
733 { PHY_ID_BCM54612E, 0xfffffff0 },
734 { PHY_ID_BCM54616S, 0xfffffff0 },
735 { PHY_ID_BCM5464, 0xfffffff0 },
736 { PHY_ID_BCM5481, 0xfffffff0 },
737 { PHY_ID_BCM54810, 0xfffffff0 },
738 { PHY_ID_BCM5482, 0xfffffff0 },
739 { PHY_ID_BCM50610, 0xfffffff0 },
740 { PHY_ID_BCM50610M, 0xfffffff0 },
741 { PHY_ID_BCM57780, 0xfffffff0 },
742 { PHY_ID_BCMAC131, 0xfffffff0 },
743 { PHY_ID_BCM5241, 0xfffffff0 },
747 MODULE_DEVICE_TABLE(mdio, broadcom_tbl);