Lines Matching +full:need +full:- +full:phy +full:- +full:for +full:- +full:wake
1 // SPDX-License-Identifier: GPL-2.0+
3 * drivers/net/phy/broadcom.c
8 * Broadcom BCM54810, BCM54811 BroadR-Reach transceivers.
15 #include "bcm-phy-lib.h"
18 #include <linux/phy.h>
27 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))
29 MODULE_DESCRIPTION("Broadcom PHY driver");
41 /* Link modes for BCM58411 PHY */
54 /* Long-Distance Signaling (BroadR-Reach mode aneg) relevant linkmode bits */
65 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54xx_phy_can_wakeup()
67 return phy_interrupt_is_valid(phydev) || priv->wake_irq >= 0; in bcm54xx_phy_can_wakeup()
74 /* handling PHY's internal RX clock delay */ in bcm54xx_config_clock_delay()
77 if (phydev->interface == PHY_INTERFACE_MODE_RGMII || in bcm54xx_config_clock_delay()
78 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { in bcm54xx_config_clock_delay()
79 /* Disable RGMII RXC-RXD skew */ in bcm54xx_config_clock_delay()
82 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || in bcm54xx_config_clock_delay()
83 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { in bcm54xx_config_clock_delay()
84 /* Enable RGMII RXC-RXD skew */ in bcm54xx_config_clock_delay()
92 /* handling PHY's internal TX clock delay */ in bcm54xx_config_clock_delay()
94 if (phydev->interface == PHY_INTERFACE_MODE_RGMII || in bcm54xx_config_clock_delay()
95 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { in bcm54xx_config_clock_delay()
99 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || in bcm54xx_config_clock_delay()
100 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { in bcm54xx_config_clock_delay()
117 if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) { in bcm54210e_config_init()
133 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) { in bcm54612e_config_init()
151 if (phydev->interface != PHY_INTERFACE_MODE_SGMII && in bcm54616s_config_init()
152 phydev->interface != PHY_INTERFACE_MODE_1000BASEX) in bcm54616s_config_init()
167 /* Select 1000BASE-X register set (primary SerDes) */ in bcm54616s_config_init()
183 val |= phydev->interface == PHY_INTERFACE_MODE_SGMII ? in bcm54616s_config_init()
249 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) || in bcm54xx_phydsp_config()
250 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M)) { in bcm54xx_phydsp_config()
251 /* Clear bit 9 to fix a phy interop issue. */ in bcm54xx_phydsp_config()
257 if (phydev->drv->phy_id == PHY_ID_BCM50610) { in bcm54xx_phydsp_config()
264 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM57780)) { in bcm54xx_phydsp_config()
291 /* Abort if we are using an untested phy. */ in bcm54xx_adjust_rxrefclk()
292 if (!(phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM57780) || in bcm54xx_adjust_rxrefclk()
293 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) || in bcm54xx_adjust_rxrefclk()
294 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M) || in bcm54xx_adjust_rxrefclk()
295 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54210E) || in bcm54xx_adjust_rxrefclk()
296 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54810) || in bcm54xx_adjust_rxrefclk()
297 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811))) in bcm54xx_adjust_rxrefclk()
306 if ((phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) || in bcm54xx_adjust_rxrefclk()
307 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M)) && in bcm54xx_adjust_rxrefclk()
315 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { in bcm54xx_adjust_rxrefclk()
316 if (!phy_id_compare_model(phydev->drv->phy_id, in bcm54xx_adjust_rxrefclk()
325 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) in bcm54xx_adjust_rxrefclk()
330 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) { in bcm54xx_adjust_rxrefclk()
331 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54210E) || in bcm54xx_adjust_rxrefclk()
332 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54810) || in bcm54xx_adjust_rxrefclk()
333 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811)) in bcm54xx_adjust_rxrefclk()
348 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) in bcm54xx_adjust_rxrefclk()
359 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54xx_ptp_stop()
361 if (priv->ptp) in bcm54xx_ptp_stop()
362 bcm_ptp_stop(priv->ptp); in bcm54xx_ptp_stop()
367 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54xx_ptp_config_init()
369 if (priv->ptp) in bcm54xx_ptp_config_init()
407 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54811_config_init()
411 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) { in bcm54811_config_init()
421 /* With BCM54811, BroadR-Reach implies no autoneg */ in bcm54811_config_init()
422 if (priv->brr_mode) in bcm54811_config_init()
423 phydev->autoneg = 0; in bcm54811_config_init()
426 if (phydev->interface == PHY_INTERFACE_MODE_MIILITE) in bcm54811_config_init()
455 return bcm5481x_set_brrmode(phydev, priv->brr_mode); in bcm54811_config_init()
480 if ((phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610) || in bcm54xx_config_init()
481 phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM50610M)) && in bcm54xx_config_init()
482 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) in bcm54xx_config_init()
487 switch (phydev->drv->phy_id & PHY_ID_MATCH_MODEL_MASK) { in bcm54xx_config_init()
502 /* For BCM54810, we need to disable BroadR-Reach function */ in bcm54xx_config_init()
519 /* For non-SFP setups, encode link speed into LED1 and LED3 pair in bcm54xx_config_init()
522 * them for MULTICOLOR and encoding link/activity into them. in bcm54xx_config_init()
523 * Don't do this for devices on an SFP module, since some of these in bcm54xx_config_init()
540 /* Acknowledge any left over interrupt and charge the device for in bcm54xx_config_init()
541 * wake-up. in bcm54xx_config_init()
548 pm_wakeup_event(&phydev->mdio.dev, 0); in bcm54xx_config_init()
557 if (!(phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND)) in bcm54xx_iddq_set()
576 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54xx_set_wakeup_irq()
582 if (priv->wake_irq_enabled != state) { in bcm54xx_set_wakeup_irq()
584 ret = enable_irq_wake(priv->wake_irq); in bcm54xx_set_wakeup_irq()
586 ret = disable_irq_wake(priv->wake_irq); in bcm54xx_set_wakeup_irq()
587 priv->wake_irq_enabled = state; in bcm54xx_set_wakeup_irq()
599 /* Acknowledge any Wake-on-LAN interrupt prior to suspend */ in bcm54xx_suspend()
604 if (phydev->wol_enabled) in bcm54xx_suspend()
607 /* We cannot use a read/modify/write here otherwise the PHY gets into in bcm54xx_suspend()
622 if (phydev->wol_enabled) { in bcm54xx_resume()
639 /* Upon exiting power down, the PHY remains in an internal reset state in bcm54xx_resume()
640 * for 40us in bcm54xx_resume()
647 if (phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND) { in bcm54xx_resume()
658 return -EOPNOTSUPP; in bcm54810_read_mmd()
664 return -EOPNOTSUPP; in bcm54810_write_mmd()
669 * bcm5481x_read_abilities - read PHY abilities from LRESR or Clause 22
670 * (BMSR) registers, based on whether the PHY is in BroadR-Reach or IEEE mode
673 * Description: Reads the PHY's abilities and populates phydev->supported
675 * the brr mode setting of the PHY as read from the device tree.
677 * not only the link modes differ, but also the auto-negotiation and
678 * master-slave setup is controlled differently.
684 struct device_node *np = phydev->mdio.dev.of_node; in bcm5481x_read_abilities()
685 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm5481x_read_abilities()
688 for (i = 0; i < ARRAY_SIZE(bcm54811_linkmodes); i++) in bcm5481x_read_abilities()
689 linkmode_clear_bit(bcm54811_linkmodes[i], phydev->supported); in bcm5481x_read_abilities()
691 priv->brr_mode = of_property_read_bool(np, "brr-mode"); in bcm5481x_read_abilities()
693 /* Set BroadR-Reach mode as configured in the DT. */ in bcm5481x_read_abilities()
694 err = bcm5481x_set_brrmode(phydev, priv->brr_mode); in bcm5481x_read_abilities()
698 if (priv->brr_mode) { in bcm5481x_read_abilities()
701 phydev->supported); in bcm5481x_read_abilities()
709 * So we must read the bcm54811 as unable to auto-negotiate in bcm5481x_read_abilities()
710 * in BroadR-Reach mode. in bcm5481x_read_abilities()
712 if (phy_id_compare_model(phydev->drv->phy_id, PHY_ID_BCM54811)) in bcm5481x_read_abilities()
718 phydev->supported, in bcm5481x_read_abilities()
721 phydev->supported, in bcm5481x_read_abilities()
724 phydev->supported, in bcm5481x_read_abilities()
734 struct device_node *np = phydev->mdio.dev.of_node; in bcm5481x_config_delay_swap()
739 if (of_property_read_bool(np, "enet-phy-lane-swap")) { in bcm5481x_config_delay_swap()
740 /* Lane Swap - Undocumented register...magic! */ in bcm5481x_config_delay_swap()
753 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm5481_config_aneg()
757 if (priv->brr_mode) in bcm5481_config_aneg()
771 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54811_config_aneg()
775 if (priv->brr_mode) { in bcm54811_config_aneg()
777 * In BroadR-Reach mode, disable the Long Distance Signaling, in bcm54811_config_aneg()
806 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); in bcm54616s_probe()
808 return -ENOMEM; in bcm54616s_probe()
810 phydev->priv = priv; in bcm54616s_probe()
816 /* The PHY is strapped in RGMII-fiber mode when INTERF_SEL[1:0] in bcm54616s_probe()
817 * is 01b, and the link between PHY and its link partner can be in bcm54616s_probe()
818 * either 1000Base-X or 100Base-FX. in bcm54616s_probe()
819 * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX in bcm54616s_probe()
827 /* Bit 0 of the SerDes 100-FX Control register, when set in bcm54616s_probe()
828 * to 1, sets the MII/RGMII -> 100BASE-FX configuration. in bcm54616s_probe()
829 * When this bit is set to 0, it sets the GMII/RGMII -> in bcm54616s_probe()
830 * 1000BASE-X configuration. in bcm54616s_probe()
833 priv->mode_1000bx_en = true; in bcm54616s_probe()
835 phydev->port = PORT_FIBRE; in bcm54616s_probe()
843 struct bcm54616s_phy_priv *priv = phydev->priv; in bcm54616s_config_aneg()
847 if (priv->mode_1000bx_en) in bcm54616s_config_aneg()
860 struct bcm54616s_phy_priv *priv = phydev->priv; in bcm54616s_read_status()
864 if (priv->mode_1000bx_en) in bcm54616s_read_status()
876 /* Reset the PHY to bring it to a known state. */ in brcm_fet_config_init()
881 /* The datasheet indicates the PHY needs up to 1us to complete a reset, in brcm_fet_config_init()
886 /* The PHY requires 65 MDC clock cycles to complete a write operation in brcm_fet_config_init()
889 * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac) in brcm_fet_config_init()
890 * may flag the lack of turn-around as a read failure. This is in brcm_fet_config_init()
898 if (err < 0 && err != -EIO) in brcm_fet_config_init()
907 if (phydev->drv->phy_id == PHY_ID_BCM5221) in brcm_fet_config_init()
936 if (phydev->drv->phy_id != PHY_ID_BCM5221) { in brcm_fet_config_init()
957 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { in brcm_fet_config_init()
994 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { in brcm_fet_config_intr()
1035 /* We cannot use a read/modify/write here otherwise the PHY continues in brcm_fet_suspend()
1057 if (phydev->drv->phy_id == PHY_ID_BCM5221) in brcm_fet_suspend()
1084 switch (phydev->mdix_ctrl) { in bcm5221_config_aneg()
1114 phydev->mdix_ctrl = ETH_TP_MDI_X; in bcm5221_read_status()
1116 phydev->mdix_ctrl = ETH_TP_MDI; in bcm5221_read_status()
1118 phydev->mdix_ctrl = ETH_TP_MDI_AUTO; in bcm5221_read_status()
1122 phydev->mdix = ETH_TP_MDI_X; in bcm5221_read_status()
1124 phydev->mdix = ETH_TP_MDI; in bcm5221_read_status()
1132 /* We cannot wake-up if we do not have a dedicated PHY interrupt line in bcm54xx_phy_get_wol()
1133 * or an out of band GPIO descriptor for wake-up. Zeroing in bcm54xx_phy_get_wol()
1134 * wol->supported allows the caller (MAC driver) to play through and in bcm54xx_phy_get_wol()
1135 * offer its own Wake-on-LAN scheme if available. in bcm54xx_phy_get_wol()
1138 wol->supported = 0; in bcm54xx_phy_get_wol()
1150 /* We cannot wake-up if we do not have a dedicated PHY interrupt line in bcm54xx_phy_set_wol()
1151 * or an out of band GPIO descriptor for wake-up. Returning -EOPNOTSUPP in bcm54xx_phy_set_wol()
1153 * Wake-on-LAN scheme if available. in bcm54xx_phy_set_wol()
1156 return -EOPNOTSUPP; in bcm54xx_phy_set_wol()
1171 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); in bcm54xx_phy_probe()
1173 return -ENOMEM; in bcm54xx_phy_probe()
1175 priv->wake_irq = -ENXIO; in bcm54xx_phy_probe()
1177 phydev->priv = priv; in bcm54xx_phy_probe()
1179 priv->stats = devm_kcalloc(&phydev->mdio.dev, in bcm54xx_phy_probe()
1182 if (!priv->stats) in bcm54xx_phy_probe()
1183 return -ENOMEM; in bcm54xx_phy_probe()
1185 priv->ptp = bcm_ptp_probe(phydev); in bcm54xx_phy_probe()
1186 if (IS_ERR(priv->ptp)) in bcm54xx_phy_probe()
1187 return PTR_ERR(priv->ptp); in bcm54xx_phy_probe()
1190 * whether the GPIO descriptor exists or not to advertise Wake-on-LAN in bcm54xx_phy_probe()
1193 wakeup_gpio = devm_gpiod_get(&phydev->mdio.dev, "wakeup", GPIOD_IN); in bcm54xx_phy_probe()
1194 if (PTR_ERR(wakeup_gpio) == -EPROBE_DEFER) in bcm54xx_phy_probe()
1198 priv->wake_irq = gpiod_to_irq(wakeup_gpio); in bcm54xx_phy_probe()
1201 * in order for the interrupt descriptor to be fully set-up. in bcm54xx_phy_probe()
1203 ret = devm_request_irq(&phydev->mdio.dev, priv->wake_irq, in bcm54xx_phy_probe()
1206 dev_name(&phydev->mdio.dev), phydev); in bcm54xx_phy_probe()
1211 /* If we do not have a main interrupt or a side-band wake-up interrupt, in bcm54xx_phy_probe()
1212 * then the device cannot be marked as wake-up capable. in bcm54xx_phy_probe()
1217 return device_init_wakeup(&phydev->mdio.dev, true); in bcm54xx_phy_probe()
1223 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54xx_get_stats()
1225 bcm_phy_get_stats(phydev, priv->stats, stats, data); in bcm54xx_get_stats()
1234 if (phydev->state != PHY_RUNNING) in bcm54xx_link_change_notify()
1237 /* Don't change the DAC wake settings if auto power down in bcm54xx_link_change_notify()
1240 if (!(phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) in bcm54xx_link_change_notify()
1247 /* Enable/disable 10BaseT auto and forced early DAC wake depending in bcm54xx_link_change_notify()
1249 * for 10Mbits/sec. in bcm54xx_link_change_notify()
1251 if (phydev->speed == SPEED_10) in bcm54xx_link_change_notify()
1263 /* In BroadR-Reach mode we are always capable of master-slave in lre_read_master_slave()
1266 phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; in lre_read_master_slave()
1267 phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; in lre_read_master_slave()
1289 phydev->master_slave_get = cfg; in lre_read_master_slave()
1290 phydev->master_slave_state = state; in lre_read_master_slave()
1295 /* Read LDS Link Partner Ability in BroadR-Reach mode */
1300 if (phydev->autoneg != AUTONEG_ENABLE) { in lre_read_lpa()
1301 if (!phydev->autoneg_complete) { in lre_read_lpa()
1303 for (i = 0; i < ARRAY_SIZE(lds_br_bits); i++) in lre_read_lpa()
1305 phydev->lp_advertising); in lre_read_lpa()
1310 /* Long-Distance Signaling Link Partner Ability */ in lre_read_lpa()
1316 phydev->lp_advertising, in lre_read_lpa()
1319 phydev->lp_advertising, in lre_read_lpa()
1322 phydev->lp_advertising, in lre_read_lpa()
1325 phydev->lp_advertising, in lre_read_lpa()
1328 linkmode_zero(phydev->lp_advertising); in lre_read_lpa()
1341 phydev->duplex = DUPLEX_FULL; in lre_read_status_fixed()
1344 phydev->speed = SPEED_100; in lre_read_status_fixed()
1346 phydev->speed = SPEED_10; in lre_read_status_fixed()
1352 * lre_update_link - update link status in @phydev
1356 * Description: Update the value in phydev->link to reflect the
1357 * current link value. In order to do this, we need to read
1360 * of BroadR-Reach PHY
1377 * drops can be detected. Do not double-read the status in lre_update_link()
1381 if (!phy_polling_mode(phydev) || !phydev->link) { in lre_update_link()
1394 phydev->link = status & LRESR_LSTATUS ? 1 : 0; in lre_update_link()
1395 phydev->autoneg_complete = status & LRESR_LDSCOMPLETE ? 1 : 0; in lre_update_link()
1400 if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete) in lre_update_link()
1401 phydev->link = 0; in lre_update_link()
1411 int err, old_link = phydev->link; in bcm54811_lre_read_status()
1418 /* why bother the PHY if nothing can have changed */ in bcm54811_lre_read_status()
1419 if (phydev->autoneg == in bcm54811_lre_read_status()
1420 AUTONEG_ENABLE && old_link && phydev->link) in bcm54811_lre_read_status()
1423 phydev->speed = SPEED_UNKNOWN; in bcm54811_lre_read_status()
1424 phydev->duplex = DUPLEX_UNKNOWN; in bcm54811_lre_read_status()
1425 phydev->pause = 0; in bcm54811_lre_read_status()
1426 phydev->asym_pause = 0; in bcm54811_lre_read_status()
1437 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) in bcm54811_lre_read_status()
1439 else if (phydev->autoneg == AUTONEG_DISABLE) in bcm54811_lre_read_status()
1447 struct bcm54xx_phy_priv *priv = phydev->priv; in bcm54811_read_status()
1449 if (priv->brr_mode) in bcm54811_read_status()