1 // SPDX-License-Identifier: GPL-2.0+
3 * drivers/net/phy/broadcom.c
5 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet
8 * Copyright (c) 2006 Maciej W. Rozycki
10 * Inspired by code written by Amy Fong.
13 #include "bcm-phy-lib.h"
14 #include <linux/module.h>
15 #include <linux/phy.h>
16 #include <linux/brcmphy.h>
19 #define BRCM_PHY_MODEL(phydev) \
20 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
22 #define BRCM_PHY_REV(phydev) \
23 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
25 MODULE_DESCRIPTION("Broadcom PHY driver");
26 MODULE_AUTHOR("Maciej W. Rozycki");
27 MODULE_LICENSE("GPL");
29 static int bcm54xx_config_clock_delay(struct phy_device
*phydev
)
33 /* handling PHY's internal RX clock delay */
34 val
= bcm54xx_auxctl_read(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_MISC
);
35 val
|= MII_BCM54XX_AUXCTL_MISC_WREN
;
36 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII
||
37 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_TXID
) {
38 /* Disable RGMII RXC-RXD skew */
39 val
&= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN
;
41 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII_ID
||
42 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_RXID
) {
43 /* Enable RGMII RXC-RXD skew */
44 val
|= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN
;
46 rc
= bcm54xx_auxctl_write(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_MISC
,
51 /* handling PHY's internal TX clock delay */
52 val
= bcm_phy_read_shadow(phydev
, BCM54810_SHD_CLK_CTL
);
53 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII
||
54 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_RXID
) {
55 /* Disable internal TX clock delay */
56 val
&= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN
;
58 if (phydev
->interface
== PHY_INTERFACE_MODE_RGMII_ID
||
59 phydev
->interface
== PHY_INTERFACE_MODE_RGMII_TXID
) {
60 /* Enable internal TX clock delay */
61 val
|= BCM54810_SHD_CLK_CTL_GTXCLK_EN
;
63 rc
= bcm_phy_write_shadow(phydev
, BCM54810_SHD_CLK_CTL
, val
);
70 static int bcm54210e_config_init(struct phy_device
*phydev
)
74 bcm54xx_config_clock_delay(phydev
);
76 if (phydev
->dev_flags
& PHY_BRCM_EN_MASTER_MODE
) {
77 val
= phy_read(phydev
, MII_CTRL1000
);
78 val
|= CTL1000_AS_MASTER
| CTL1000_ENABLE_MASTER
;
79 phy_write(phydev
, MII_CTRL1000
, val
);
85 static int bcm54612e_config_init(struct phy_device
*phydev
)
89 bcm54xx_config_clock_delay(phydev
);
91 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */
92 if (!(phydev
->dev_flags
& PHY_BRCM_RX_REFCLK_UNUSED
)) {
95 reg
= bcm_phy_read_exp(phydev
, BCM54612E_EXP_SPARE0
);
96 err
= bcm_phy_write_exp(phydev
, BCM54612E_EXP_SPARE0
,
97 BCM54612E_LED4_CLK125OUT_EN
| reg
);
106 static int bcm54616s_config_init(struct phy_device
*phydev
)
110 if (phydev
->interface
!= PHY_INTERFACE_MODE_SGMII
&&
111 phydev
->interface
!= PHY_INTERFACE_MODE_1000BASEX
)
114 /* Ensure proper interface mode is selected. */
115 /* Disable RGMII mode */
116 val
= bcm54xx_auxctl_read(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_MISC
);
119 val
&= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN
;
120 val
|= MII_BCM54XX_AUXCTL_MISC_WREN
;
121 rc
= bcm54xx_auxctl_write(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_MISC
,
126 /* Select 1000BASE-X register set (primary SerDes) */
127 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_MODE
);
130 val
|= BCM54XX_SHD_MODE_1000BX
;
131 rc
= bcm_phy_write_shadow(phydev
, BCM54XX_SHD_MODE
, val
);
135 /* Power down SerDes interface */
136 rc
= phy_set_bits(phydev
, MII_BMCR
, BMCR_PDOWN
);
140 /* Select proper interface mode */
141 val
&= ~BCM54XX_SHD_INTF_SEL_MASK
;
142 val
|= phydev
->interface
== PHY_INTERFACE_MODE_SGMII
?
143 BCM54XX_SHD_INTF_SEL_SGMII
:
144 BCM54XX_SHD_INTF_SEL_GBIC
;
145 rc
= bcm_phy_write_shadow(phydev
, BCM54XX_SHD_MODE
, val
);
149 /* Power up SerDes interface */
150 rc
= phy_clear_bits(phydev
, MII_BMCR
, BMCR_PDOWN
);
154 /* Select copper register set */
155 val
&= ~BCM54XX_SHD_MODE_1000BX
;
156 rc
= bcm_phy_write_shadow(phydev
, BCM54XX_SHD_MODE
, val
);
160 /* Power up copper interface */
161 return phy_clear_bits(phydev
, MII_BMCR
, BMCR_PDOWN
);
164 /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
165 static int bcm50610_a0_workaround(struct phy_device
*phydev
)
169 err
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_AADJ1CH0
,
170 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN
|
171 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF
);
175 err
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_AADJ1CH3
,
176 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ
);
180 err
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_EXP75
,
181 MII_BCM54XX_EXP_EXP75_VDACCTRL
);
185 err
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_EXP96
,
186 MII_BCM54XX_EXP_EXP96_MYST
);
190 err
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_EXP97
,
191 MII_BCM54XX_EXP_EXP97_MYST
);
196 static int bcm54xx_phydsp_config(struct phy_device
*phydev
)
200 /* Enable the SMDSP clock */
201 err
= bcm54xx_auxctl_write(phydev
,
202 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL
,
203 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA
|
204 MII_BCM54XX_AUXCTL_ACTL_TX_6DB
);
208 if (BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610
||
209 BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610M
) {
210 /* Clear bit 9 to fix a phy interop issue. */
211 err
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_EXP08
,
212 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ
);
216 if (phydev
->drv
->phy_id
== PHY_ID_BCM50610
) {
217 err
= bcm50610_a0_workaround(phydev
);
223 if (BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM57780
) {
226 val
= bcm_phy_read_exp(phydev
, MII_BCM54XX_EXP_EXP75
);
230 val
|= MII_BCM54XX_EXP_EXP75_CM_OSC
;
231 err
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_EXP75
, val
);
235 /* Disable the SMDSP clock */
236 err2
= bcm54xx_auxctl_write(phydev
,
237 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL
,
238 MII_BCM54XX_AUXCTL_ACTL_TX_6DB
);
240 /* Return the first error reported. */
241 return err
? err
: err2
;
244 static void bcm54xx_adjust_rxrefclk(struct phy_device
*phydev
)
248 bool clk125en
= true;
250 /* Abort if we are using an untested phy. */
251 if (BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM57780
&&
252 BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM50610
&&
253 BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM50610M
&&
254 BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM54810
&&
255 BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM54811
)
258 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_SCR3
);
264 if ((BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610
||
265 BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610M
) &&
266 BRCM_PHY_REV(phydev
) >= 0x3) {
268 * Here, bit 0 _disables_ CLK125 when set.
269 * This bit is set by default.
273 if (phydev
->dev_flags
& PHY_BRCM_RX_REFCLK_UNUSED
) {
274 if (BRCM_PHY_MODEL(phydev
) != PHY_ID_BCM54811
) {
275 /* Here, bit 0 _enables_ CLK125 when set */
276 val
&= ~BCM54XX_SHD_SCR3_DEF_CLK125
;
282 if (!clk125en
|| (phydev
->dev_flags
& PHY_BRCM_AUTO_PWRDWN_ENABLE
))
283 val
&= ~BCM54XX_SHD_SCR3_DLLAPD_DIS
;
285 val
|= BCM54XX_SHD_SCR3_DLLAPD_DIS
;
287 if (phydev
->dev_flags
& PHY_BRCM_DIS_TXCRXC_NOENRGY
) {
288 if (BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM54810
||
289 BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM54811
)
290 val
|= BCM54810_SHD_SCR3_TRDDAPD
;
292 val
|= BCM54XX_SHD_SCR3_TRDDAPD
;
296 bcm_phy_write_shadow(phydev
, BCM54XX_SHD_SCR3
, val
);
298 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_APD
);
304 if (!clk125en
|| (phydev
->dev_flags
& PHY_BRCM_AUTO_PWRDWN_ENABLE
))
305 val
|= BCM54XX_SHD_APD_EN
;
307 val
&= ~BCM54XX_SHD_APD_EN
;
310 bcm_phy_write_shadow(phydev
, BCM54XX_SHD_APD
, val
);
313 static int bcm54xx_config_init(struct phy_device
*phydev
)
317 reg
= phy_read(phydev
, MII_BCM54XX_ECR
);
321 /* Mask interrupts globally. */
322 reg
|= MII_BCM54XX_ECR_IM
;
323 err
= phy_write(phydev
, MII_BCM54XX_ECR
, reg
);
327 /* Unmask events we are interested in. */
328 reg
= ~(MII_BCM54XX_INT_DUPLEX
|
329 MII_BCM54XX_INT_SPEED
|
330 MII_BCM54XX_INT_LINK
);
331 err
= phy_write(phydev
, MII_BCM54XX_IMR
, reg
);
335 if ((BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610
||
336 BRCM_PHY_MODEL(phydev
) == PHY_ID_BCM50610M
) &&
337 (phydev
->dev_flags
& PHY_BRCM_CLEAR_RGMII_MODE
))
338 bcm_phy_write_shadow(phydev
, BCM54XX_SHD_RGMII_MODE
, 0);
340 bcm54xx_adjust_rxrefclk(phydev
);
342 switch (BRCM_PHY_MODEL(phydev
)) {
343 case PHY_ID_BCM50610
:
344 case PHY_ID_BCM50610M
:
345 err
= bcm54xx_config_clock_delay(phydev
);
347 case PHY_ID_BCM54210E
:
348 err
= bcm54210e_config_init(phydev
);
350 case PHY_ID_BCM54612E
:
351 err
= bcm54612e_config_init(phydev
);
353 case PHY_ID_BCM54616S
:
354 err
= bcm54616s_config_init(phydev
);
356 case PHY_ID_BCM54810
:
357 /* For BCM54810, we need to disable BroadR-Reach function */
358 val
= bcm_phy_read_exp(phydev
,
359 BCM54810_EXP_BROADREACH_LRE_MISC_CTL
);
360 val
&= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN
;
361 err
= bcm_phy_write_exp(phydev
,
362 BCM54810_EXP_BROADREACH_LRE_MISC_CTL
,
369 bcm54xx_phydsp_config(phydev
);
371 /* Encode link speed into LED1 and LED3 pair (green/amber).
372 * Also flash these two LEDs on activity. This means configuring
373 * them for MULTICOLOR and encoding link/activity into them.
375 val
= BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1
) |
376 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1
);
377 bcm_phy_write_shadow(phydev
, BCM5482_SHD_LEDS1
, val
);
379 val
= BCM_LED_MULTICOLOR_IN_PHASE
|
380 BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT
) |
381 BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT
);
382 bcm_phy_write_exp(phydev
, BCM_EXP_MULTICOLOR
, val
);
387 static int bcm54xx_resume(struct phy_device
*phydev
)
391 /* Writes to register other than BMCR would be ignored
392 * unless we clear the PDOWN bit first
394 ret
= genphy_resume(phydev
);
398 /* Upon exiting power down, the PHY remains in an internal reset state
403 return bcm54xx_config_init(phydev
);
406 static int bcm54811_config_init(struct phy_device
*phydev
)
410 /* Disable BroadR-Reach function. */
411 reg
= bcm_phy_read_exp(phydev
, BCM54810_EXP_BROADREACH_LRE_MISC_CTL
);
412 reg
&= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN
;
413 err
= bcm_phy_write_exp(phydev
, BCM54810_EXP_BROADREACH_LRE_MISC_CTL
,
418 err
= bcm54xx_config_init(phydev
);
420 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */
421 if (!(phydev
->dev_flags
& PHY_BRCM_RX_REFCLK_UNUSED
)) {
422 reg
= bcm_phy_read_exp(phydev
, BCM54612E_EXP_SPARE0
);
423 err
= bcm_phy_write_exp(phydev
, BCM54612E_EXP_SPARE0
,
424 BCM54612E_LED4_CLK125OUT_EN
| reg
);
432 static int bcm5482_config_init(struct phy_device
*phydev
)
436 err
= bcm54xx_config_init(phydev
);
438 if (phydev
->dev_flags
& PHY_BCM_FLAGS_MODE_1000BX
) {
440 * Enable secondary SerDes and its use as an LED source
442 reg
= bcm_phy_read_shadow(phydev
, BCM5482_SHD_SSD
);
443 bcm_phy_write_shadow(phydev
, BCM5482_SHD_SSD
,
445 BCM5482_SHD_SSD_LEDM
|
449 * Enable SGMII slave mode and auto-detection
451 reg
= BCM5482_SSD_SGMII_SLAVE
| MII_BCM54XX_EXP_SEL_SSD
;
452 err
= bcm_phy_read_exp(phydev
, reg
);
455 err
= bcm_phy_write_exp(phydev
, reg
, err
|
456 BCM5482_SSD_SGMII_SLAVE_EN
|
457 BCM5482_SSD_SGMII_SLAVE_AD
);
462 * Disable secondary SerDes powerdown
464 reg
= BCM5482_SSD_1000BX_CTL
| MII_BCM54XX_EXP_SEL_SSD
;
465 err
= bcm_phy_read_exp(phydev
, reg
);
468 err
= bcm_phy_write_exp(phydev
, reg
,
469 err
& ~BCM5482_SSD_1000BX_CTL_PWRDOWN
);
474 * Select 1000BASE-X register set (primary SerDes)
476 reg
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_MODE
);
477 bcm_phy_write_shadow(phydev
, BCM54XX_SHD_MODE
,
478 reg
| BCM54XX_SHD_MODE_1000BX
);
481 * LED1=ACTIVITYLED, LED3=LINKSPD[2]
482 * (Use LED1 as secondary SerDes ACTIVITY LED)
484 bcm_phy_write_shadow(phydev
, BCM5482_SHD_LEDS1
,
485 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED
) |
486 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2
));
489 * Auto-negotiation doesn't seem to work quite right
490 * in this mode, so we disable it and force it to the
491 * right speed/duplex setting. Only 'link status'
494 phydev
->autoneg
= AUTONEG_DISABLE
;
495 phydev
->speed
= SPEED_1000
;
496 phydev
->duplex
= DUPLEX_FULL
;
502 static int bcm5482_read_status(struct phy_device
*phydev
)
506 err
= genphy_read_status(phydev
);
508 if (phydev
->dev_flags
& PHY_BCM_FLAGS_MODE_1000BX
) {
510 * Only link status matters for 1000Base-X mode, so force
511 * 1000 Mbit/s full-duplex status
514 phydev
->speed
= SPEED_1000
;
515 phydev
->duplex
= DUPLEX_FULL
;
522 static int bcm5481_config_aneg(struct phy_device
*phydev
)
524 struct device_node
*np
= phydev
->mdio
.dev
.of_node
;
528 ret
= genphy_config_aneg(phydev
);
530 /* Then we can set up the delay. */
531 bcm54xx_config_clock_delay(phydev
);
533 if (of_property_read_bool(np
, "enet-phy-lane-swap")) {
534 /* Lane Swap - Undocumented register...magic! */
535 ret
= bcm_phy_write_exp(phydev
, MII_BCM54XX_EXP_SEL_ER
+ 0x9,
544 static int bcm54616s_probe(struct phy_device
*phydev
)
548 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_MODE
);
552 /* The PHY is strapped in RGMII-fiber mode when INTERF_SEL[1:0]
553 * is 01b, and the link between PHY and its link partner can be
554 * either 1000Base-X or 100Base-FX.
555 * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX
556 * support is still missing as of now.
558 if ((val
& BCM54XX_SHD_INTF_SEL_MASK
) == BCM54XX_SHD_INTF_SEL_RGMII
) {
559 val
= bcm_phy_read_shadow(phydev
, BCM54616S_SHD_100FX_CTRL
);
563 /* Bit 0 of the SerDes 100-FX Control register, when set
564 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.
565 * When this bit is set to 0, it sets the GMII/RGMII ->
566 * 1000BASE-X configuration.
568 if (!(val
& BCM54616S_100FX_MODE
))
569 phydev
->dev_flags
|= PHY_BCM_FLAGS_MODE_1000BX
;
571 phydev
->port
= PORT_FIBRE
;
577 static int bcm54616s_config_aneg(struct phy_device
*phydev
)
582 if (phydev
->dev_flags
& PHY_BCM_FLAGS_MODE_1000BX
)
583 ret
= genphy_c37_config_aneg(phydev
);
585 ret
= genphy_config_aneg(phydev
);
587 /* Then we can set up the delay. */
588 bcm54xx_config_clock_delay(phydev
);
593 static int bcm54616s_read_status(struct phy_device
*phydev
)
597 if (phydev
->dev_flags
& PHY_BCM_FLAGS_MODE_1000BX
)
598 err
= genphy_c37_read_status(phydev
);
600 err
= genphy_read_status(phydev
);
605 static int brcm_phy_setbits(struct phy_device
*phydev
, int reg
, int set
)
609 val
= phy_read(phydev
, reg
);
613 return phy_write(phydev
, reg
, val
| set
);
616 static int brcm_fet_config_init(struct phy_device
*phydev
)
618 int reg
, err
, err2
, brcmtest
;
620 /* Reset the PHY to bring it to a known state. */
621 err
= phy_write(phydev
, MII_BMCR
, BMCR_RESET
);
625 reg
= phy_read(phydev
, MII_BRCM_FET_INTREG
);
629 /* Unmask events we are interested in and mask interrupts globally. */
630 reg
= MII_BRCM_FET_IR_DUPLEX_EN
|
631 MII_BRCM_FET_IR_SPEED_EN
|
632 MII_BRCM_FET_IR_LINK_EN
|
633 MII_BRCM_FET_IR_ENABLE
|
634 MII_BRCM_FET_IR_MASK
;
636 err
= phy_write(phydev
, MII_BRCM_FET_INTREG
, reg
);
640 /* Enable shadow register access */
641 brcmtest
= phy_read(phydev
, MII_BRCM_FET_BRCMTEST
);
645 reg
= brcmtest
| MII_BRCM_FET_BT_SRE
;
647 err
= phy_write(phydev
, MII_BRCM_FET_BRCMTEST
, reg
);
651 /* Set the LED mode */
652 reg
= phy_read(phydev
, MII_BRCM_FET_SHDW_AUXMODE4
);
658 reg
&= ~MII_BRCM_FET_SHDW_AM4_LED_MASK
;
659 reg
|= MII_BRCM_FET_SHDW_AM4_LED_MODE1
;
661 err
= phy_write(phydev
, MII_BRCM_FET_SHDW_AUXMODE4
, reg
);
665 /* Enable auto MDIX */
666 err
= brcm_phy_setbits(phydev
, MII_BRCM_FET_SHDW_MISCCTRL
,
667 MII_BRCM_FET_SHDW_MC_FAME
);
671 if (phydev
->dev_flags
& PHY_BRCM_AUTO_PWRDWN_ENABLE
) {
672 /* Enable auto power down */
673 err
= brcm_phy_setbits(phydev
, MII_BRCM_FET_SHDW_AUXSTAT2
,
674 MII_BRCM_FET_SHDW_AS2_APDE
);
678 /* Disable shadow register access */
679 err2
= phy_write(phydev
, MII_BRCM_FET_BRCMTEST
, brcmtest
);
686 static int brcm_fet_ack_interrupt(struct phy_device
*phydev
)
690 /* Clear pending interrupts. */
691 reg
= phy_read(phydev
, MII_BRCM_FET_INTREG
);
698 static int brcm_fet_config_intr(struct phy_device
*phydev
)
702 reg
= phy_read(phydev
, MII_BRCM_FET_INTREG
);
706 if (phydev
->interrupts
== PHY_INTERRUPT_ENABLED
) {
707 err
= brcm_fet_ack_interrupt(phydev
);
711 reg
&= ~MII_BRCM_FET_IR_MASK
;
712 err
= phy_write(phydev
, MII_BRCM_FET_INTREG
, reg
);
714 reg
|= MII_BRCM_FET_IR_MASK
;
715 err
= phy_write(phydev
, MII_BRCM_FET_INTREG
, reg
);
719 err
= brcm_fet_ack_interrupt(phydev
);
725 static irqreturn_t
brcm_fet_handle_interrupt(struct phy_device
*phydev
)
729 irq_status
= phy_read(phydev
, MII_BRCM_FET_INTREG
);
730 if (irq_status
< 0) {
738 phy_trigger_machine(phydev
);
743 struct bcm53xx_phy_priv
{
747 static int bcm53xx_phy_probe(struct phy_device
*phydev
)
749 struct bcm53xx_phy_priv
*priv
;
751 priv
= devm_kzalloc(&phydev
->mdio
.dev
, sizeof(*priv
), GFP_KERNEL
);
757 priv
->stats
= devm_kcalloc(&phydev
->mdio
.dev
,
758 bcm_phy_get_sset_count(phydev
), sizeof(u64
),
766 static void bcm53xx_phy_get_stats(struct phy_device
*phydev
,
767 struct ethtool_stats
*stats
, u64
*data
)
769 struct bcm53xx_phy_priv
*priv
= phydev
->priv
;
771 bcm_phy_get_stats(phydev
, priv
->stats
, stats
, data
);
774 static struct phy_driver broadcom_drivers
[] = {
776 .phy_id
= PHY_ID_BCM5411
,
777 .phy_id_mask
= 0xfffffff0,
778 .name
= "Broadcom BCM5411",
779 /* PHY_GBIT_FEATURES */
780 .config_init
= bcm54xx_config_init
,
781 .config_intr
= bcm_phy_config_intr
,
782 .handle_interrupt
= bcm_phy_handle_interrupt
,
784 .phy_id
= PHY_ID_BCM5421
,
785 .phy_id_mask
= 0xfffffff0,
786 .name
= "Broadcom BCM5421",
787 /* PHY_GBIT_FEATURES */
788 .config_init
= bcm54xx_config_init
,
789 .config_intr
= bcm_phy_config_intr
,
790 .handle_interrupt
= bcm_phy_handle_interrupt
,
792 .phy_id
= PHY_ID_BCM54210E
,
793 .phy_id_mask
= 0xfffffff0,
794 .name
= "Broadcom BCM54210E",
795 /* PHY_GBIT_FEATURES */
796 .config_init
= bcm54xx_config_init
,
797 .config_intr
= bcm_phy_config_intr
,
798 .handle_interrupt
= bcm_phy_handle_interrupt
,
800 .phy_id
= PHY_ID_BCM5461
,
801 .phy_id_mask
= 0xfffffff0,
802 .name
= "Broadcom BCM5461",
803 /* PHY_GBIT_FEATURES */
804 .config_init
= bcm54xx_config_init
,
805 .config_intr
= bcm_phy_config_intr
,
806 .handle_interrupt
= bcm_phy_handle_interrupt
,
808 .phy_id
= PHY_ID_BCM54612E
,
809 .phy_id_mask
= 0xfffffff0,
810 .name
= "Broadcom BCM54612E",
811 /* PHY_GBIT_FEATURES */
812 .config_init
= bcm54xx_config_init
,
813 .config_intr
= bcm_phy_config_intr
,
814 .handle_interrupt
= bcm_phy_handle_interrupt
,
816 .phy_id
= PHY_ID_BCM54616S
,
817 .phy_id_mask
= 0xfffffff0,
818 .name
= "Broadcom BCM54616S",
819 /* PHY_GBIT_FEATURES */
820 .config_init
= bcm54xx_config_init
,
821 .config_aneg
= bcm54616s_config_aneg
,
822 .config_intr
= bcm_phy_config_intr
,
823 .handle_interrupt
= bcm_phy_handle_interrupt
,
824 .read_status
= bcm54616s_read_status
,
825 .probe
= bcm54616s_probe
,
827 .phy_id
= PHY_ID_BCM5464
,
828 .phy_id_mask
= 0xfffffff0,
829 .name
= "Broadcom BCM5464",
830 /* PHY_GBIT_FEATURES */
831 .config_init
= bcm54xx_config_init
,
832 .config_intr
= bcm_phy_config_intr
,
833 .handle_interrupt
= bcm_phy_handle_interrupt
,
834 .suspend
= genphy_suspend
,
835 .resume
= genphy_resume
,
837 .phy_id
= PHY_ID_BCM5481
,
838 .phy_id_mask
= 0xfffffff0,
839 .name
= "Broadcom BCM5481",
840 /* PHY_GBIT_FEATURES */
841 .config_init
= bcm54xx_config_init
,
842 .config_aneg
= bcm5481_config_aneg
,
843 .config_intr
= bcm_phy_config_intr
,
844 .handle_interrupt
= bcm_phy_handle_interrupt
,
846 .phy_id
= PHY_ID_BCM54810
,
847 .phy_id_mask
= 0xfffffff0,
848 .name
= "Broadcom BCM54810",
849 /* PHY_GBIT_FEATURES */
850 .config_init
= bcm54xx_config_init
,
851 .config_aneg
= bcm5481_config_aneg
,
852 .config_intr
= bcm_phy_config_intr
,
853 .handle_interrupt
= bcm_phy_handle_interrupt
,
854 .suspend
= genphy_suspend
,
855 .resume
= bcm54xx_resume
,
857 .phy_id
= PHY_ID_BCM54811
,
858 .phy_id_mask
= 0xfffffff0,
859 .name
= "Broadcom BCM54811",
860 /* PHY_GBIT_FEATURES */
861 .config_init
= bcm54811_config_init
,
862 .config_aneg
= bcm5481_config_aneg
,
863 .config_intr
= bcm_phy_config_intr
,
864 .handle_interrupt
= bcm_phy_handle_interrupt
,
865 .suspend
= genphy_suspend
,
866 .resume
= bcm54xx_resume
,
868 .phy_id
= PHY_ID_BCM5482
,
869 .phy_id_mask
= 0xfffffff0,
870 .name
= "Broadcom BCM5482",
871 /* PHY_GBIT_FEATURES */
872 .config_init
= bcm5482_config_init
,
873 .read_status
= bcm5482_read_status
,
874 .config_intr
= bcm_phy_config_intr
,
875 .handle_interrupt
= bcm_phy_handle_interrupt
,
877 .phy_id
= PHY_ID_BCM50610
,
878 .phy_id_mask
= 0xfffffff0,
879 .name
= "Broadcom BCM50610",
880 /* PHY_GBIT_FEATURES */
881 .config_init
= bcm54xx_config_init
,
882 .config_intr
= bcm_phy_config_intr
,
883 .handle_interrupt
= bcm_phy_handle_interrupt
,
885 .phy_id
= PHY_ID_BCM50610M
,
886 .phy_id_mask
= 0xfffffff0,
887 .name
= "Broadcom BCM50610M",
888 /* PHY_GBIT_FEATURES */
889 .config_init
= bcm54xx_config_init
,
890 .config_intr
= bcm_phy_config_intr
,
891 .handle_interrupt
= bcm_phy_handle_interrupt
,
893 .phy_id
= PHY_ID_BCM57780
,
894 .phy_id_mask
= 0xfffffff0,
895 .name
= "Broadcom BCM57780",
896 /* PHY_GBIT_FEATURES */
897 .config_init
= bcm54xx_config_init
,
898 .config_intr
= bcm_phy_config_intr
,
899 .handle_interrupt
= bcm_phy_handle_interrupt
,
901 .phy_id
= PHY_ID_BCMAC131
,
902 .phy_id_mask
= 0xfffffff0,
903 .name
= "Broadcom BCMAC131",
904 /* PHY_BASIC_FEATURES */
905 .config_init
= brcm_fet_config_init
,
906 .config_intr
= brcm_fet_config_intr
,
907 .handle_interrupt
= brcm_fet_handle_interrupt
,
909 .phy_id
= PHY_ID_BCM5241
,
910 .phy_id_mask
= 0xfffffff0,
911 .name
= "Broadcom BCM5241",
912 /* PHY_BASIC_FEATURES */
913 .config_init
= brcm_fet_config_init
,
914 .config_intr
= brcm_fet_config_intr
,
915 .handle_interrupt
= brcm_fet_handle_interrupt
,
917 .phy_id
= PHY_ID_BCM5395
,
918 .phy_id_mask
= 0xfffffff0,
919 .name
= "Broadcom BCM5395",
920 .flags
= PHY_IS_INTERNAL
,
921 /* PHY_GBIT_FEATURES */
922 .get_sset_count
= bcm_phy_get_sset_count
,
923 .get_strings
= bcm_phy_get_strings
,
924 .get_stats
= bcm53xx_phy_get_stats
,
925 .probe
= bcm53xx_phy_probe
,
927 .phy_id
= PHY_ID_BCM53125
,
928 .phy_id_mask
= 0xfffffff0,
929 .name
= "Broadcom BCM53125",
930 .flags
= PHY_IS_INTERNAL
,
931 /* PHY_GBIT_FEATURES */
932 .get_sset_count
= bcm_phy_get_sset_count
,
933 .get_strings
= bcm_phy_get_strings
,
934 .get_stats
= bcm53xx_phy_get_stats
,
935 .probe
= bcm53xx_phy_probe
,
936 .config_init
= bcm54xx_config_init
,
937 .config_intr
= bcm_phy_config_intr
,
938 .handle_interrupt
= bcm_phy_handle_interrupt
,
940 .phy_id
= PHY_ID_BCM89610
,
941 .phy_id_mask
= 0xfffffff0,
942 .name
= "Broadcom BCM89610",
943 /* PHY_GBIT_FEATURES */
944 .config_init
= bcm54xx_config_init
,
945 .config_intr
= bcm_phy_config_intr
,
946 .handle_interrupt
= bcm_phy_handle_interrupt
,
949 module_phy_driver(broadcom_drivers
);
951 static struct mdio_device_id __maybe_unused broadcom_tbl
[] = {
952 { PHY_ID_BCM5411
, 0xfffffff0 },
953 { PHY_ID_BCM5421
, 0xfffffff0 },
954 { PHY_ID_BCM54210E
, 0xfffffff0 },
955 { PHY_ID_BCM5461
, 0xfffffff0 },
956 { PHY_ID_BCM54612E
, 0xfffffff0 },
957 { PHY_ID_BCM54616S
, 0xfffffff0 },
958 { PHY_ID_BCM5464
, 0xfffffff0 },
959 { PHY_ID_BCM5481
, 0xfffffff0 },
960 { PHY_ID_BCM54810
, 0xfffffff0 },
961 { PHY_ID_BCM54811
, 0xfffffff0 },
962 { PHY_ID_BCM5482
, 0xfffffff0 },
963 { PHY_ID_BCM50610
, 0xfffffff0 },
964 { PHY_ID_BCM50610M
, 0xfffffff0 },
965 { PHY_ID_BCM57780
, 0xfffffff0 },
966 { PHY_ID_BCMAC131
, 0xfffffff0 },
967 { PHY_ID_BCM5241
, 0xfffffff0 },
968 { PHY_ID_BCM5395
, 0xfffffff0 },
969 { PHY_ID_BCM53125
, 0xfffffff0 },
970 { PHY_ID_BCM89610
, 0xfffffff0 },
974 MODULE_DEVICE_TABLE(mdio
, broadcom_tbl
);