1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2015-2017 Broadcom
6 #include "bcm-phy-lib.h"
7 #include <linux/bitfield.h>
8 #include <linux/brcmphy.h>
9 #include <linux/etherdevice.h>
10 #include <linux/export.h>
11 #include <linux/mdio.h>
12 #include <linux/module.h>
13 #include <linux/phy.h>
14 #include <linux/ethtool.h>
15 #include <linux/ethtool_netlink.h>
16 #include <linux/netdevice.h>
18 #define MII_BCM_CHANNEL_WIDTH 0x2000
19 #define BCM_CL45VEN_EEE_ADV 0x3c
21 int __bcm_phy_write_exp(struct phy_device
*phydev
, u16 reg
, u16 val
)
25 rc
= __phy_write(phydev
, MII_BCM54XX_EXP_SEL
, reg
);
29 return __phy_write(phydev
, MII_BCM54XX_EXP_DATA
, val
);
31 EXPORT_SYMBOL_GPL(__bcm_phy_write_exp
);
33 int bcm_phy_write_exp(struct phy_device
*phydev
, u16 reg
, u16 val
)
37 phy_lock_mdio_bus(phydev
);
38 rc
= __bcm_phy_write_exp(phydev
, reg
, val
);
39 phy_unlock_mdio_bus(phydev
);
43 EXPORT_SYMBOL_GPL(bcm_phy_write_exp
);
45 int __bcm_phy_read_exp(struct phy_device
*phydev
, u16 reg
)
49 val
= __phy_write(phydev
, MII_BCM54XX_EXP_SEL
, reg
);
53 val
= __phy_read(phydev
, MII_BCM54XX_EXP_DATA
);
55 /* Restore default value. It's O.K. if this write fails. */
56 __phy_write(phydev
, MII_BCM54XX_EXP_SEL
, 0);
60 EXPORT_SYMBOL_GPL(__bcm_phy_read_exp
);
62 int bcm_phy_read_exp(struct phy_device
*phydev
, u16 reg
)
66 phy_lock_mdio_bus(phydev
);
67 rc
= __bcm_phy_read_exp(phydev
, reg
);
68 phy_unlock_mdio_bus(phydev
);
72 EXPORT_SYMBOL_GPL(bcm_phy_read_exp
);
74 int __bcm_phy_modify_exp(struct phy_device
*phydev
, u16 reg
, u16 mask
, u16 set
)
78 ret
= __phy_write(phydev
, MII_BCM54XX_EXP_SEL
, reg
);
82 ret
= __phy_read(phydev
, MII_BCM54XX_EXP_DATA
);
86 new = (ret
& ~mask
) | set
;
90 return __phy_write(phydev
, MII_BCM54XX_EXP_DATA
, new);
92 EXPORT_SYMBOL_GPL(__bcm_phy_modify_exp
);
94 int bcm_phy_modify_exp(struct phy_device
*phydev
, u16 reg
, u16 mask
, u16 set
)
98 phy_lock_mdio_bus(phydev
);
99 ret
= __bcm_phy_modify_exp(phydev
, reg
, mask
, set
);
100 phy_unlock_mdio_bus(phydev
);
104 EXPORT_SYMBOL_GPL(bcm_phy_modify_exp
);
106 int bcm54xx_auxctl_read(struct phy_device
*phydev
, u16 regnum
)
108 /* The register must be written to both the Shadow Register Select and
109 * the Shadow Read Register Selector
111 phy_write(phydev
, MII_BCM54XX_AUX_CTL
, MII_BCM54XX_AUXCTL_SHDWSEL_MASK
|
112 regnum
<< MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT
);
113 return phy_read(phydev
, MII_BCM54XX_AUX_CTL
);
115 EXPORT_SYMBOL_GPL(bcm54xx_auxctl_read
);
117 int bcm54xx_auxctl_write(struct phy_device
*phydev
, u16 regnum
, u16 val
)
119 return phy_write(phydev
, MII_BCM54XX_AUX_CTL
, regnum
| val
);
121 EXPORT_SYMBOL(bcm54xx_auxctl_write
);
123 int bcm_phy_write_misc(struct phy_device
*phydev
,
124 u16 reg
, u16 chl
, u16 val
)
129 rc
= phy_write(phydev
, MII_BCM54XX_AUX_CTL
,
130 MII_BCM54XX_AUXCTL_SHDWSEL_MISC
);
134 tmp
= phy_read(phydev
, MII_BCM54XX_AUX_CTL
);
135 tmp
|= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA
;
136 rc
= phy_write(phydev
, MII_BCM54XX_AUX_CTL
, tmp
);
140 tmp
= (chl
* MII_BCM_CHANNEL_WIDTH
) | reg
;
141 rc
= bcm_phy_write_exp(phydev
, tmp
, val
);
145 EXPORT_SYMBOL_GPL(bcm_phy_write_misc
);
147 int bcm_phy_read_misc(struct phy_device
*phydev
,
153 rc
= phy_write(phydev
, MII_BCM54XX_AUX_CTL
,
154 MII_BCM54XX_AUXCTL_SHDWSEL_MISC
);
158 tmp
= phy_read(phydev
, MII_BCM54XX_AUX_CTL
);
159 tmp
|= MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA
;
160 rc
= phy_write(phydev
, MII_BCM54XX_AUX_CTL
, tmp
);
164 tmp
= (chl
* MII_BCM_CHANNEL_WIDTH
) | reg
;
165 rc
= bcm_phy_read_exp(phydev
, tmp
);
169 EXPORT_SYMBOL_GPL(bcm_phy_read_misc
);
171 int bcm_phy_ack_intr(struct phy_device
*phydev
)
175 /* Clear pending interrupts. */
176 reg
= phy_read(phydev
, MII_BCM54XX_ISR
);
182 EXPORT_SYMBOL_GPL(bcm_phy_ack_intr
);
184 int bcm_phy_config_intr(struct phy_device
*phydev
)
188 reg
= phy_read(phydev
, MII_BCM54XX_ECR
);
192 if (phydev
->interrupts
== PHY_INTERRUPT_ENABLED
) {
193 err
= bcm_phy_ack_intr(phydev
);
197 reg
&= ~MII_BCM54XX_ECR_IM
;
198 err
= phy_write(phydev
, MII_BCM54XX_ECR
, reg
);
200 reg
|= MII_BCM54XX_ECR_IM
;
201 err
= phy_write(phydev
, MII_BCM54XX_ECR
, reg
);
205 err
= bcm_phy_ack_intr(phydev
);
209 EXPORT_SYMBOL_GPL(bcm_phy_config_intr
);
211 irqreturn_t
bcm_phy_handle_interrupt(struct phy_device
*phydev
)
213 int irq_status
, irq_mask
;
215 irq_status
= phy_read(phydev
, MII_BCM54XX_ISR
);
216 if (irq_status
< 0) {
221 /* If a bit from the Interrupt Mask register is set, the corresponding
222 * bit from the Interrupt Status register is masked. So read the IMR
223 * and then flip the bits to get the list of possible interrupt
226 irq_mask
= phy_read(phydev
, MII_BCM54XX_IMR
);
231 irq_mask
= ~irq_mask
;
233 if (!(irq_status
& irq_mask
))
236 phy_trigger_machine(phydev
);
240 EXPORT_SYMBOL_GPL(bcm_phy_handle_interrupt
);
242 int bcm_phy_read_shadow(struct phy_device
*phydev
, u16 shadow
)
244 phy_write(phydev
, MII_BCM54XX_SHD
, MII_BCM54XX_SHD_VAL(shadow
));
245 return MII_BCM54XX_SHD_DATA(phy_read(phydev
, MII_BCM54XX_SHD
));
247 EXPORT_SYMBOL_GPL(bcm_phy_read_shadow
);
249 int bcm_phy_write_shadow(struct phy_device
*phydev
, u16 shadow
,
252 return phy_write(phydev
, MII_BCM54XX_SHD
,
253 MII_BCM54XX_SHD_WRITE
|
254 MII_BCM54XX_SHD_VAL(shadow
) |
255 MII_BCM54XX_SHD_DATA(val
));
257 EXPORT_SYMBOL_GPL(bcm_phy_write_shadow
);
259 int __bcm_phy_read_rdb(struct phy_device
*phydev
, u16 rdb
)
263 val
= __phy_write(phydev
, MII_BCM54XX_RDB_ADDR
, rdb
);
267 return __phy_read(phydev
, MII_BCM54XX_RDB_DATA
);
269 EXPORT_SYMBOL_GPL(__bcm_phy_read_rdb
);
271 int bcm_phy_read_rdb(struct phy_device
*phydev
, u16 rdb
)
275 phy_lock_mdio_bus(phydev
);
276 ret
= __bcm_phy_read_rdb(phydev
, rdb
);
277 phy_unlock_mdio_bus(phydev
);
281 EXPORT_SYMBOL_GPL(bcm_phy_read_rdb
);
283 int __bcm_phy_write_rdb(struct phy_device
*phydev
, u16 rdb
, u16 val
)
287 ret
= __phy_write(phydev
, MII_BCM54XX_RDB_ADDR
, rdb
);
291 return __phy_write(phydev
, MII_BCM54XX_RDB_DATA
, val
);
293 EXPORT_SYMBOL_GPL(__bcm_phy_write_rdb
);
295 int bcm_phy_write_rdb(struct phy_device
*phydev
, u16 rdb
, u16 val
)
299 phy_lock_mdio_bus(phydev
);
300 ret
= __bcm_phy_write_rdb(phydev
, rdb
, val
);
301 phy_unlock_mdio_bus(phydev
);
305 EXPORT_SYMBOL_GPL(bcm_phy_write_rdb
);
307 int __bcm_phy_modify_rdb(struct phy_device
*phydev
, u16 rdb
, u16 mask
, u16 set
)
311 ret
= __phy_write(phydev
, MII_BCM54XX_RDB_ADDR
, rdb
);
315 ret
= __phy_read(phydev
, MII_BCM54XX_RDB_DATA
);
319 new = (ret
& ~mask
) | set
;
323 return __phy_write(phydev
, MII_BCM54XX_RDB_DATA
, new);
325 EXPORT_SYMBOL_GPL(__bcm_phy_modify_rdb
);
327 int bcm_phy_modify_rdb(struct phy_device
*phydev
, u16 rdb
, u16 mask
, u16 set
)
331 phy_lock_mdio_bus(phydev
);
332 ret
= __bcm_phy_modify_rdb(phydev
, rdb
, mask
, set
);
333 phy_unlock_mdio_bus(phydev
);
337 EXPORT_SYMBOL_GPL(bcm_phy_modify_rdb
);
339 int bcm_phy_enable_apd(struct phy_device
*phydev
, bool dll_pwr_down
)
344 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_SCR3
);
348 val
|= BCM54XX_SHD_SCR3_DLLAPD_DIS
;
349 bcm_phy_write_shadow(phydev
, BCM54XX_SHD_SCR3
, val
);
352 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_APD
);
357 val
&= BCM_APD_CLR_MASK
;
359 if (phydev
->autoneg
== AUTONEG_ENABLE
)
360 val
|= BCM54XX_SHD_APD_EN
;
362 val
|= BCM_NO_ANEG_APD_EN
;
364 /* Enable energy detect single link pulse for easy wakeup */
365 val
|= BCM_APD_SINGLELP_EN
;
367 /* Enable Auto Power-Down (APD) for the PHY */
368 return bcm_phy_write_shadow(phydev
, BCM54XX_SHD_APD
, val
);
370 EXPORT_SYMBOL_GPL(bcm_phy_enable_apd
);
372 int bcm_phy_set_eee(struct phy_device
*phydev
, bool enable
)
376 /* Enable EEE at PHY level */
377 val
= phy_read_mmd(phydev
, MDIO_MMD_AN
, BRCM_CL45VEN_EEE_CONTROL
);
382 val
|= LPI_FEATURE_EN
| LPI_FEATURE_EN_DIG1000X
;
384 val
&= ~(LPI_FEATURE_EN
| LPI_FEATURE_EN_DIG1000X
);
386 phy_write_mmd(phydev
, MDIO_MMD_AN
, BRCM_CL45VEN_EEE_CONTROL
, (u32
)val
);
389 val
= phy_read_mmd(phydev
, MDIO_MMD_AN
, BCM_CL45VEN_EEE_ADV
);
393 if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT
,
395 mask
|= MDIO_EEE_1000T
;
396 if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT
,
398 mask
|= MDIO_EEE_100TX
;
405 phy_write_mmd(phydev
, MDIO_MMD_AN
, BCM_CL45VEN_EEE_ADV
, (u32
)val
);
409 EXPORT_SYMBOL_GPL(bcm_phy_set_eee
);
411 int bcm_phy_downshift_get(struct phy_device
*phydev
, u8
*count
)
415 val
= bcm54xx_auxctl_read(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_MISC
);
419 /* Check if wirespeed is enabled or not */
420 if (!(val
& MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN
)) {
421 *count
= DOWNSHIFT_DEV_DISABLE
;
425 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_SCR2
);
429 /* Downgrade after one link attempt */
430 if (val
& BCM54XX_SHD_SCR2_WSPD_RTRY_DIS
) {
433 /* Downgrade after configured retry count */
434 val
>>= BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT
;
435 val
&= BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK
;
436 *count
= val
+ BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET
;
441 EXPORT_SYMBOL_GPL(bcm_phy_downshift_get
);
443 int bcm_phy_downshift_set(struct phy_device
*phydev
, u8 count
)
445 int val
= 0, ret
= 0;
447 /* Range check the number given */
448 if (count
- BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET
>
449 BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK
&&
450 count
!= DOWNSHIFT_DEV_DEFAULT_COUNT
) {
454 val
= bcm54xx_auxctl_read(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_MISC
);
458 /* Se the write enable bit */
459 val
|= MII_BCM54XX_AUXCTL_MISC_WREN
;
461 if (count
== DOWNSHIFT_DEV_DISABLE
) {
462 val
&= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN
;
463 return bcm54xx_auxctl_write(phydev
,
464 MII_BCM54XX_AUXCTL_SHDWSEL_MISC
,
467 val
|= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_WIRESPEED_EN
;
468 ret
= bcm54xx_auxctl_write(phydev
,
469 MII_BCM54XX_AUXCTL_SHDWSEL_MISC
,
475 val
= bcm_phy_read_shadow(phydev
, BCM54XX_SHD_SCR2
);
476 val
&= ~(BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_MASK
<<
477 BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT
|
478 BCM54XX_SHD_SCR2_WSPD_RTRY_DIS
);
482 val
|= BCM54XX_SHD_SCR2_WSPD_RTRY_DIS
;
484 case DOWNSHIFT_DEV_DEFAULT_COUNT
:
485 val
|= 1 << BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT
;
488 val
|= (count
- BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_OFFSET
) <<
489 BCM54XX_SHD_SCR2_WSPD_RTRY_LMT_SHIFT
;
493 return bcm_phy_write_shadow(phydev
, BCM54XX_SHD_SCR2
, val
);
495 EXPORT_SYMBOL_GPL(bcm_phy_downshift_set
);
497 struct bcm_phy_hw_stat
{
505 /* Counters freeze at either 0xffff or 0xff, better than nothing */
506 static const struct bcm_phy_hw_stat bcm_phy_hw_stats
[] = {
507 { "phy_receive_errors", -1, MII_BRCM_CORE_BASE12
, 0, 16 },
508 { "phy_serdes_ber_errors", -1, MII_BRCM_CORE_BASE13
, 8, 8 },
509 { "phy_false_carrier_sense_errors", -1, MII_BRCM_CORE_BASE13
, 0, 8 },
510 { "phy_local_rcvr_nok", -1, MII_BRCM_CORE_BASE14
, 8, 8 },
511 { "phy_remote_rcv_nok", -1, MII_BRCM_CORE_BASE14
, 0, 8 },
512 { "phy_lpi_count", MDIO_MMD_AN
, BRCM_CL45VEN_EEE_LPI_CNT
, 0, 16 },
515 int bcm_phy_get_sset_count(struct phy_device
*phydev
)
517 return ARRAY_SIZE(bcm_phy_hw_stats
);
519 EXPORT_SYMBOL_GPL(bcm_phy_get_sset_count
);
521 void bcm_phy_get_strings(struct phy_device
*phydev
, u8
*data
)
525 for (i
= 0; i
< ARRAY_SIZE(bcm_phy_hw_stats
); i
++)
526 ethtool_puts(&data
, bcm_phy_hw_stats
[i
].string
);
528 EXPORT_SYMBOL_GPL(bcm_phy_get_strings
);
530 /* Caller is supposed to provide appropriate storage for the library code to
531 * access the shadow copy
533 static u64
bcm_phy_get_stat(struct phy_device
*phydev
, u64
*shadow
,
536 struct bcm_phy_hw_stat stat
= bcm_phy_hw_stats
[i
];
541 val
= phy_read(phydev
, stat
.reg
);
543 val
= phy_read_mmd(phydev
, stat
.devad
, stat
.reg
);
548 val
= val
& ((1 << stat
.bits
) - 1);
556 void bcm_phy_get_stats(struct phy_device
*phydev
, u64
*shadow
,
557 struct ethtool_stats
*stats
, u64
*data
)
561 for (i
= 0; i
< ARRAY_SIZE(bcm_phy_hw_stats
); i
++)
562 data
[i
] = bcm_phy_get_stat(phydev
, shadow
, i
);
564 EXPORT_SYMBOL_GPL(bcm_phy_get_stats
);
566 void bcm_phy_r_rc_cal_reset(struct phy_device
*phydev
)
568 /* Reset R_CAL/RC_CAL Engine */
569 bcm_phy_write_exp_sel(phydev
, 0x00b0, 0x0010);
571 /* Disable Reset R_AL/RC_CAL Engine */
572 bcm_phy_write_exp_sel(phydev
, 0x00b0, 0x0000);
574 EXPORT_SYMBOL_GPL(bcm_phy_r_rc_cal_reset
);
576 int bcm_phy_28nm_a0b0_afe_config_init(struct phy_device
*phydev
)
578 /* Increase VCO range to prevent unlocking problem of PLL at low
581 bcm_phy_write_misc(phydev
, PLL_PLLCTRL_1
, 0x0048);
583 /* Change Ki to 011 */
584 bcm_phy_write_misc(phydev
, PLL_PLLCTRL_2
, 0x021b);
586 /* Disable loading of TVCO buffer to bandgap, set bandgap trim
589 bcm_phy_write_misc(phydev
, PLL_PLLCTRL_4
, 0x0e20);
591 /* Adjust bias current trim by -3 */
592 bcm_phy_write_misc(phydev
, DSP_TAP10
, 0x690b);
594 /* Switch to CORE_BASE1E */
595 phy_write(phydev
, MII_BRCM_CORE_BASE1E
, 0xd);
597 bcm_phy_r_rc_cal_reset(phydev
);
599 /* write AFE_RXCONFIG_0 */
600 bcm_phy_write_misc(phydev
, AFE_RXCONFIG_0
, 0xeb19);
602 /* write AFE_RXCONFIG_1 */
603 bcm_phy_write_misc(phydev
, AFE_RXCONFIG_1
, 0x9a3f);
605 /* write AFE_RX_LP_COUNTER */
606 bcm_phy_write_misc(phydev
, AFE_RX_LP_COUNTER
, 0x7fc0);
608 /* write AFE_HPF_TRIM_OTHERS */
609 bcm_phy_write_misc(phydev
, AFE_HPF_TRIM_OTHERS
, 0x000b);
611 /* write AFTE_TX_CONFIG */
612 bcm_phy_write_misc(phydev
, AFE_TX_CONFIG
, 0x0800);
616 EXPORT_SYMBOL_GPL(bcm_phy_28nm_a0b0_afe_config_init
);
618 int bcm_phy_enable_jumbo(struct phy_device
*phydev
)
622 ret
= bcm54xx_auxctl_read(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL
);
626 /* Enable extended length packet reception */
627 ret
= bcm54xx_auxctl_write(phydev
, MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL
,
628 ret
| MII_BCM54XX_AUXCTL_ACTL_EXT_PKT_LEN
);
632 /* Enable the elastic FIFO for raising the transmission limit from
633 * 4.5KB to 10KB, at the expense of an additional 16 ns in propagation
636 return phy_set_bits(phydev
, MII_BCM54XX_ECR
, MII_BCM54XX_ECR_FIFOE
);
638 EXPORT_SYMBOL_GPL(bcm_phy_enable_jumbo
);
640 static int __bcm_phy_enable_rdb_access(struct phy_device
*phydev
)
642 return __bcm_phy_write_exp(phydev
, BCM54XX_EXP_REG7E
, 0);
645 static int __bcm_phy_enable_legacy_access(struct phy_device
*phydev
)
647 return __bcm_phy_write_rdb(phydev
, BCM54XX_RDB_REG0087
,
648 BCM54XX_ACCESS_MODE_LEGACY_EN
);
651 static int _bcm_phy_cable_test_start(struct phy_device
*phydev
, bool is_rdb
)
656 /* Auto-negotiation must be enabled for cable diagnostics to work, but
657 * don't advertise any capabilities.
659 phy_write(phydev
, MII_BMCR
, BMCR_ANENABLE
);
660 phy_write(phydev
, MII_ADVERTISE
, ADVERTISE_CSMA
);
661 phy_write(phydev
, MII_CTRL1000
, 0);
663 phy_lock_mdio_bus(phydev
);
665 ret
= __bcm_phy_enable_legacy_access(phydev
);
670 mask
= BCM54XX_ECD_CTRL_CROSS_SHORT_DIS
| BCM54XX_ECD_CTRL_UNIT_MASK
;
671 set
= BCM54XX_ECD_CTRL_RUN
| BCM54XX_ECD_CTRL_BREAK_LINK
|
672 FIELD_PREP(BCM54XX_ECD_CTRL_UNIT_MASK
,
673 BCM54XX_ECD_CTRL_UNIT_CM
);
675 ret
= __bcm_phy_modify_exp(phydev
, BCM54XX_EXP_ECD_CTRL
, mask
, set
);
678 /* re-enable the RDB access even if there was an error */
680 ret
= __bcm_phy_enable_rdb_access(phydev
) ? : ret
;
682 phy_unlock_mdio_bus(phydev
);
687 static int bcm_phy_cable_test_report_trans(int result
)
690 case BCM54XX_ECD_FAULT_TYPE_OK
:
691 return ETHTOOL_A_CABLE_RESULT_CODE_OK
;
692 case BCM54XX_ECD_FAULT_TYPE_OPEN
:
693 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN
;
694 case BCM54XX_ECD_FAULT_TYPE_SAME_SHORT
:
695 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT
;
696 case BCM54XX_ECD_FAULT_TYPE_CROSS_SHORT
:
697 return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT
;
698 case BCM54XX_ECD_FAULT_TYPE_INVALID
:
699 case BCM54XX_ECD_FAULT_TYPE_BUSY
:
701 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC
;
705 static bool bcm_phy_distance_valid(int result
)
708 case BCM54XX_ECD_FAULT_TYPE_OPEN
:
709 case BCM54XX_ECD_FAULT_TYPE_SAME_SHORT
:
710 case BCM54XX_ECD_FAULT_TYPE_CROSS_SHORT
:
716 static int bcm_phy_report_length(struct phy_device
*phydev
, int pair
)
720 val
= __bcm_phy_read_exp(phydev
,
721 BCM54XX_EXP_ECD_PAIR_A_LENGTH_RESULTS
+ pair
);
725 if (val
== BCM54XX_ECD_LENGTH_RESULTS_INVALID
)
728 ethnl_cable_test_fault_length(phydev
, pair
, val
);
733 static int _bcm_phy_cable_test_get_status(struct phy_device
*phydev
,
734 bool *finished
, bool is_rdb
)
736 int pair_a
, pair_b
, pair_c
, pair_d
, ret
;
740 phy_lock_mdio_bus(phydev
);
743 ret
= __bcm_phy_enable_legacy_access(phydev
);
748 ret
= __bcm_phy_read_exp(phydev
, BCM54XX_EXP_ECD_CTRL
);
752 if (ret
& BCM54XX_ECD_CTRL_IN_PROGRESS
) {
757 ret
= __bcm_phy_read_exp(phydev
, BCM54XX_EXP_ECD_FAULT_TYPE
);
761 pair_a
= FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_A_MASK
, ret
);
762 pair_b
= FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_B_MASK
, ret
);
763 pair_c
= FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_C_MASK
, ret
);
764 pair_d
= FIELD_GET(BCM54XX_ECD_FAULT_TYPE_PAIR_D_MASK
, ret
);
766 ethnl_cable_test_result(phydev
, ETHTOOL_A_CABLE_PAIR_A
,
767 bcm_phy_cable_test_report_trans(pair_a
));
768 ethnl_cable_test_result(phydev
, ETHTOOL_A_CABLE_PAIR_B
,
769 bcm_phy_cable_test_report_trans(pair_b
));
770 ethnl_cable_test_result(phydev
, ETHTOOL_A_CABLE_PAIR_C
,
771 bcm_phy_cable_test_report_trans(pair_c
));
772 ethnl_cable_test_result(phydev
, ETHTOOL_A_CABLE_PAIR_D
,
773 bcm_phy_cable_test_report_trans(pair_d
));
775 if (bcm_phy_distance_valid(pair_a
))
776 bcm_phy_report_length(phydev
, 0);
777 if (bcm_phy_distance_valid(pair_b
))
778 bcm_phy_report_length(phydev
, 1);
779 if (bcm_phy_distance_valid(pair_c
))
780 bcm_phy_report_length(phydev
, 2);
781 if (bcm_phy_distance_valid(pair_d
))
782 bcm_phy_report_length(phydev
, 3);
787 /* re-enable the RDB access even if there was an error */
789 ret
= __bcm_phy_enable_rdb_access(phydev
) ? : ret
;
791 phy_unlock_mdio_bus(phydev
);
796 static int bcm_setup_lre_forced(struct phy_device
*phydev
)
801 phydev
->asym_pause
= 0;
803 if (phydev
->speed
== SPEED_100
)
804 ctl
|= LRECR_SPEED100
;
806 if (phydev
->duplex
!= DUPLEX_FULL
)
809 return phy_modify(phydev
, MII_BCM54XX_LRECR
, LRECR_SPEED100
, ctl
);
813 * bcm_linkmode_adv_to_lre_adv_t - translate linkmode advertisement to LDS
814 * @advertising: the linkmode advertisement settings
815 * Return: LDS Auto-Negotiation Advertised Ability register value
817 * A small helper function that translates linkmode advertisement
818 * settings to phy LDS autonegotiation advertisements for the
819 * MII_BCM54XX_LREANAA register of Broadcom PHYs capable of LDS
821 static u32
bcm_linkmode_adv_to_lre_adv_t(unsigned long *advertising
)
825 if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT
,
827 result
|= LREANAA_10_1PAIR
;
828 if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT
,
830 result
|= LREANAA_100_1PAIR
;
831 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT
, advertising
))
832 result
|= LRELPA_PAUSE
;
833 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT
, advertising
))
834 result
|= LRELPA_PAUSE_ASYM
;
839 int bcm_phy_cable_test_start(struct phy_device
*phydev
)
841 return _bcm_phy_cable_test_start(phydev
, false);
843 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_start
);
845 int bcm_phy_cable_test_get_status(struct phy_device
*phydev
, bool *finished
)
847 return _bcm_phy_cable_test_get_status(phydev
, finished
, false);
849 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status
);
851 /* We assume that all PHYs which support RDB access can be switched to legacy
852 * mode. If, in the future, this is not true anymore, we have to re-implement
853 * this with RDB access.
855 int bcm_phy_cable_test_start_rdb(struct phy_device
*phydev
)
857 return _bcm_phy_cable_test_start(phydev
, true);
859 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_start_rdb
);
861 int bcm_phy_cable_test_get_status_rdb(struct phy_device
*phydev
,
864 return _bcm_phy_cable_test_get_status(phydev
, finished
, true);
866 EXPORT_SYMBOL_GPL(bcm_phy_cable_test_get_status_rdb
);
868 #define BCM54XX_WOL_SUPPORTED_MASK (WAKE_UCAST | \
874 int bcm_phy_set_wol(struct phy_device
*phydev
, struct ethtool_wolinfo
*wol
)
876 struct net_device
*ndev
= phydev
->attached_dev
;
877 u8 da
[ETH_ALEN
], mask
[ETH_ALEN
];
882 /* Allow a MAC driver to play through its own Wake-on-LAN
885 if (wol
->wolopts
& ~BCM54XX_WOL_SUPPORTED_MASK
)
888 /* The PHY supports passwords of 4, 6 and 8 bytes in size, but Linux's
889 * ethtool only supports 6, for now.
891 BUILD_BUG_ON(sizeof(wol
->sopass
) != ETH_ALEN
);
893 /* Clear previous interrupts */
894 ret
= bcm_phy_read_exp(phydev
, BCM54XX_WOL_INT_STATUS
);
898 ret
= bcm_phy_read_exp(phydev
, BCM54XX_WOL_MAIN_CTL
);
905 if (phy_interrupt_is_valid(phydev
))
906 disable_irq_wake(phydev
->irq
);
908 /* Leave all interrupts disabled */
909 ret
= bcm_phy_write_exp(phydev
, BCM54XX_WOL_INT_MASK
,
910 BCM54XX_WOL_ALL_INTRS
);
914 /* Disable the global Wake-on-LAN enable bit */
915 ctl
&= ~BCM54XX_WOL_EN
;
917 return bcm_phy_write_exp(phydev
, BCM54XX_WOL_MAIN_CTL
, ctl
);
920 /* Clear the previously configured mode and mask mode for Wake-on-LAN */
921 ctl
&= ~(BCM54XX_WOL_MODE_MASK
<< BCM54XX_WOL_MODE_SHIFT
);
922 ctl
&= ~(BCM54XX_WOL_MASK_MODE_MASK
<< BCM54XX_WOL_MASK_MODE_SHIFT
);
923 ctl
&= ~BCM54XX_WOL_DIR_PKT_EN
;
924 ctl
&= ~(BCM54XX_WOL_SECKEY_OPT_MASK
<< BCM54XX_WOL_SECKEY_OPT_SHIFT
);
926 /* When using WAKE_MAGIC, we program the magic pattern filter to match
927 * the device's MAC address and we accept any MAC DA in the Ethernet
930 * When using WAKE_UCAST, WAKE_BCAST or WAKE_MCAST, we program the
932 * - WAKE_UCAST -> MAC DA is the device's MAC with a perfect match
933 * - WAKE_MCAST -> MAC DA is X1:XX:XX:XX:XX:XX where XX is don't care
934 * - WAKE_BCAST -> MAC DA is FF:FF:FF:FF:FF:FF with a perfect match
936 * Note that the Broadcast MAC DA is inherently going to match the
937 * multicast pattern being matched.
939 memset(mask
, 0, sizeof(mask
));
941 if (wol
->wolopts
& WAKE_MCAST
) {
942 memset(da
, 0, sizeof(da
));
943 memset(mask
, 0xff, sizeof(mask
));
947 if (wol
->wolopts
& WAKE_UCAST
) {
948 ether_addr_copy(da
, ndev
->dev_addr
);
949 } else if (wol
->wolopts
& WAKE_BCAST
) {
950 eth_broadcast_addr(da
);
951 } else if (wol
->wolopts
& WAKE_MAGICSECURE
) {
952 ether_addr_copy(da
, wol
->sopass
);
953 } else if (wol
->wolopts
& WAKE_MAGIC
) {
954 memset(da
, 0, sizeof(da
));
955 memset(mask
, 0xff, sizeof(mask
));
959 for (i
= 0; i
< ETH_ALEN
/ 2; i
++) {
960 if (wol
->wolopts
& (WAKE_MAGIC
| WAKE_MAGICSECURE
)) {
961 ret
= bcm_phy_write_exp(phydev
,
962 BCM54XX_WOL_MPD_DATA1(2 - i
),
963 ndev
->dev_addr
[i
* 2] << 8 |
964 ndev
->dev_addr
[i
* 2 + 1]);
969 ret
= bcm_phy_write_exp(phydev
, BCM54XX_WOL_MPD_DATA2(2 - i
),
970 da
[i
* 2] << 8 | da
[i
* 2 + 1]);
974 ret
= bcm_phy_write_exp(phydev
, BCM54XX_WOL_MASK(2 - i
),
975 mask
[i
* 2] << 8 | mask
[i
* 2 + 1]);
980 if (wol
->wolopts
& WAKE_MAGICSECURE
) {
981 ctl
|= BCM54XX_WOL_SECKEY_OPT_6B
<<
982 BCM54XX_WOL_SECKEY_OPT_SHIFT
;
983 ctl
|= BCM54XX_WOL_MODE_SINGLE_MPDSEC
<< BCM54XX_WOL_MODE_SHIFT
;
984 ctl
|= BCM54XX_WOL_MASK_MODE_DA_FF
<<
985 BCM54XX_WOL_MASK_MODE_SHIFT
;
987 if (wol
->wolopts
& WAKE_MAGIC
)
988 ctl
|= BCM54XX_WOL_MODE_SINGLE_MPD
;
990 ctl
|= BCM54XX_WOL_DIR_PKT_EN
;
991 ctl
|= BCM54XX_WOL_MASK_MODE_DA_ONLY
<<
992 BCM54XX_WOL_MASK_MODE_SHIFT
;
995 /* Globally enable Wake-on-LAN */
996 ctl
|= BCM54XX_WOL_EN
| BCM54XX_WOL_CRC_CHK
;
998 ret
= bcm_phy_write_exp(phydev
, BCM54XX_WOL_MAIN_CTL
, ctl
);
1002 /* Enable WOL interrupt on LED4 */
1003 ret
= bcm_phy_read_exp(phydev
, BCM54XX_TOP_MISC_LED_CTL
);
1007 ret
|= BCM54XX_LED4_SEL_INTR
;
1008 ret
= bcm_phy_write_exp(phydev
, BCM54XX_TOP_MISC_LED_CTL
, ret
);
1012 /* Enable all Wake-on-LAN interrupt sources */
1013 ret
= bcm_phy_write_exp(phydev
, BCM54XX_WOL_INT_MASK
, 0);
1017 if (phy_interrupt_is_valid(phydev
))
1018 enable_irq_wake(phydev
->irq
);
1022 EXPORT_SYMBOL_GPL(bcm_phy_set_wol
);
1024 void bcm_phy_get_wol(struct phy_device
*phydev
, struct ethtool_wolinfo
*wol
)
1026 struct net_device
*ndev
= phydev
->attached_dev
;
1032 wol
->supported
= BCM54XX_WOL_SUPPORTED_MASK
;
1035 ret
= bcm_phy_read_exp(phydev
, BCM54XX_WOL_MAIN_CTL
);
1041 if (!(ctl
& BCM54XX_WOL_EN
))
1044 for (i
= 0; i
< sizeof(da
) / 2; i
++) {
1045 ret
= bcm_phy_read_exp(phydev
,
1046 BCM54XX_WOL_MPD_DATA2(2 - i
));
1050 da
[i
* 2] = ret
>> 8;
1051 da
[i
* 2 + 1] = ret
& 0xff;
1054 if (ctl
& BCM54XX_WOL_DIR_PKT_EN
) {
1055 if (is_broadcast_ether_addr(da
))
1056 wol
->wolopts
|= WAKE_BCAST
;
1057 else if (is_multicast_ether_addr(da
))
1058 wol
->wolopts
|= WAKE_MCAST
;
1059 else if (ether_addr_equal(da
, ndev
->dev_addr
))
1060 wol
->wolopts
|= WAKE_UCAST
;
1062 ctl
= (ctl
>> BCM54XX_WOL_MODE_SHIFT
) & BCM54XX_WOL_MODE_MASK
;
1064 case BCM54XX_WOL_MODE_SINGLE_MPD
:
1065 wol
->wolopts
|= WAKE_MAGIC
;
1067 case BCM54XX_WOL_MODE_SINGLE_MPDSEC
:
1068 wol
->wolopts
|= WAKE_MAGICSECURE
;
1069 memcpy(wol
->sopass
, da
, sizeof(da
));
1076 EXPORT_SYMBOL_GPL(bcm_phy_get_wol
);
1078 irqreturn_t
bcm_phy_wol_isr(int irq
, void *dev_id
)
1082 EXPORT_SYMBOL_GPL(bcm_phy_wol_isr
);
1084 int bcm_phy_led_brightness_set(struct phy_device
*phydev
,
1085 u8 index
, enum led_brightness value
)
1094 /* Two LEDS per register */
1095 led_num
= index
% 2;
1096 reg
= index
>= 2 ? BCM54XX_SHD_LEDS2
: BCM54XX_SHD_LEDS1
;
1098 ret
= bcm_phy_read_shadow(phydev
, reg
);
1102 ret
&= ~(BCM_LED_SRC_MASK
<< BCM54XX_SHD_LEDS_SHIFT(led_num
));
1103 if (value
== LED_OFF
)
1104 ret
|= BCM_LED_SRC_OFF
<< BCM54XX_SHD_LEDS_SHIFT(led_num
);
1106 ret
|= BCM_LED_SRC_ON
<< BCM54XX_SHD_LEDS_SHIFT(led_num
);
1107 return bcm_phy_write_shadow(phydev
, reg
, ret
);
1109 EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set
);
1111 int bcm_setup_lre_master_slave(struct phy_device
*phydev
)
1115 switch (phydev
->master_slave_set
) {
1116 case MASTER_SLAVE_CFG_MASTER_PREFERRED
:
1117 case MASTER_SLAVE_CFG_MASTER_FORCE
:
1120 case MASTER_SLAVE_CFG_SLAVE_PREFERRED
:
1121 case MASTER_SLAVE_CFG_SLAVE_FORCE
:
1123 case MASTER_SLAVE_CFG_UNKNOWN
:
1124 case MASTER_SLAVE_CFG_UNSUPPORTED
:
1127 phydev_warn(phydev
, "Unsupported Master/Slave mode\n");
1131 return phy_modify_changed(phydev
, MII_BCM54XX_LRECR
, LRECR_MASTER
, ctl
);
1133 EXPORT_SYMBOL_GPL(bcm_setup_lre_master_slave
);
1135 int bcm_config_lre_aneg(struct phy_device
*phydev
, bool changed
)
1139 if (genphy_c45_an_config_eee_aneg(phydev
) > 0)
1142 err
= bcm_setup_lre_master_slave(phydev
);
1148 if (phydev
->autoneg
!= AUTONEG_ENABLE
)
1149 return bcm_setup_lre_forced(phydev
);
1151 err
= bcm_config_lre_advert(phydev
);
1157 return genphy_check_and_restart_aneg(phydev
, changed
);
1159 EXPORT_SYMBOL_GPL(bcm_config_lre_aneg
);
1162 * bcm_config_lre_advert - sanitize and advertise Long-Distance Signaling
1163 * auto-negotiation parameters
1164 * @phydev: target phy_device struct
1165 * Return: 0 if the PHY's advertisement hasn't changed, < 0 on error,
1166 * > 0 if it has changed
1168 * Writes MII_BCM54XX_LREANAA with the appropriate values. The values are to be
1169 * sanitized before, to make sure we only advertise what is supported.
1170 * The sanitization is done already in phy_ethtool_ksettings_set()
1172 int bcm_config_lre_advert(struct phy_device
*phydev
)
1174 u32 adv
= bcm_linkmode_adv_to_lre_adv_t(phydev
->advertising
);
1176 /* Setup BroadR-Reach mode advertisement */
1177 return phy_modify_changed(phydev
, MII_BCM54XX_LREANAA
,
1178 LRE_ADVERTISE_ALL
| LREANAA_PAUSE
|
1179 LREANAA_PAUSE_ASYM
, adv
);
1181 EXPORT_SYMBOL_GPL(bcm_config_lre_advert
);
1183 MODULE_DESCRIPTION("Broadcom PHY Library");
1184 MODULE_LICENSE("GPL v2");
1185 MODULE_AUTHOR("Broadcom Corporation");