1746 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * drivers/net/phy/broadcom.c4 *5 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet6 * transceivers.7 *8 * Broadcom BCM54810, BCM54811 BroadR-Reach transceivers.9 *10 * Copyright (c) 2006 Maciej W. Rozycki11 *12 * Inspired by code written by Amy Fong.13 */14 15#include "bcm-phy-lib.h"16#include <linux/delay.h>17#include <linux/module.h>18#include <linux/phy.h>19#include <linux/pm_wakeup.h>20#include <linux/brcmphy.h>21#include <linux/of.h>22#include <linux/interrupt.h>23#include <linux/irq.h>24#include <linux/gpio/consumer.h>25 26#define BRCM_PHY_MODEL(phydev) \27 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)28 29#define BRCM_PHY_REV(phydev) \30 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask))31 32MODULE_DESCRIPTION("Broadcom PHY driver");33MODULE_AUTHOR("Maciej W. Rozycki");34MODULE_LICENSE("GPL");35 36struct bcm54xx_phy_priv {37 u64 *stats;38 struct bcm_ptp_private *ptp;39 int wake_irq;40 bool wake_irq_enabled;41 bool brr_mode;42};43 44/* Link modes for BCM58411 PHY */45static const int bcm54811_linkmodes[] = {46 ETHTOOL_LINK_MODE_100baseT1_Full_BIT,47 ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,48 ETHTOOL_LINK_MODE_1000baseT_Full_BIT,49 ETHTOOL_LINK_MODE_1000baseX_Full_BIT,50 ETHTOOL_LINK_MODE_1000baseT_Half_BIT,51 ETHTOOL_LINK_MODE_100baseT_Full_BIT,52 ETHTOOL_LINK_MODE_100baseT_Half_BIT,53 ETHTOOL_LINK_MODE_10baseT_Full_BIT,54 ETHTOOL_LINK_MODE_10baseT_Half_BIT55};56 57/* Long-Distance Signaling (BroadR-Reach mode aneg) relevant linkmode bits */58static const int lds_br_bits[] = {59 ETHTOOL_LINK_MODE_Autoneg_BIT,60 ETHTOOL_LINK_MODE_Pause_BIT,61 ETHTOOL_LINK_MODE_Asym_Pause_BIT,62 ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,63 ETHTOOL_LINK_MODE_100baseT1_Full_BIT64};65 66static bool bcm54xx_phy_can_wakeup(struct phy_device *phydev)67{68 struct bcm54xx_phy_priv *priv = phydev->priv;69 70 return phy_interrupt_is_valid(phydev) || priv->wake_irq >= 0;71}72 73static int bcm54xx_config_clock_delay(struct phy_device *phydev)74{75 int rc, val;76 77 /* handling PHY's internal RX clock delay */78 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);79 val |= MII_BCM54XX_AUXCTL_MISC_WREN;80 if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||81 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {82 /* Disable RGMII RXC-RXD skew */83 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;84 }85 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||86 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {87 /* Enable RGMII RXC-RXD skew */88 val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;89 }90 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,91 val);92 if (rc < 0)93 return rc;94 95 /* handling PHY's internal TX clock delay */96 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);97 if (phydev->interface == PHY_INTERFACE_MODE_RGMII ||98 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {99 /* Disable internal TX clock delay */100 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;101 }102 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||103 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {104 /* Enable internal TX clock delay */105 val |= BCM54810_SHD_CLK_CTL_GTXCLK_EN;106 }107 rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);108 if (rc < 0)109 return rc;110 111 return 0;112}113 114static int bcm54210e_config_init(struct phy_device *phydev)115{116 int val;117 118 bcm54xx_config_clock_delay(phydev);119 120 if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) {121 val = phy_read(phydev, MII_CTRL1000);122 val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;123 phy_write(phydev, MII_CTRL1000, val);124 }125 126 return 0;127}128 129static int bcm54612e_config_init(struct phy_device *phydev)130{131 int reg;132 133 bcm54xx_config_clock_delay(phydev);134 135 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */136 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) {137 int err;138 139 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0);140 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0,141 BCM54612E_LED4_CLK125OUT_EN | reg);142 143 if (err < 0)144 return err;145 }146 147 return 0;148}149 150static int bcm54616s_config_init(struct phy_device *phydev)151{152 int rc, val;153 154 if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&155 phydev->interface != PHY_INTERFACE_MODE_1000BASEX)156 return 0;157 158 /* Ensure proper interface mode is selected. */159 /* Disable RGMII mode */160 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);161 if (val < 0)162 return val;163 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN;164 val |= MII_BCM54XX_AUXCTL_MISC_WREN;165 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,166 val);167 if (rc < 0)168 return rc;169 170 /* Select 1000BASE-X register set (primary SerDes) */171 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);172 if (val < 0)173 return val;174 val |= BCM54XX_SHD_MODE_1000BX;175 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);176 if (rc < 0)177 return rc;178 179 /* Power down SerDes interface */180 rc = phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);181 if (rc < 0)182 return rc;183 184 /* Select proper interface mode */185 val &= ~BCM54XX_SHD_INTF_SEL_MASK;186 val |= phydev->interface == PHY_INTERFACE_MODE_SGMII ?187 BCM54XX_SHD_INTF_SEL_SGMII :188 BCM54XX_SHD_INTF_SEL_GBIC;189 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);190 if (rc < 0)191 return rc;192 193 /* Power up SerDes interface */194 rc = phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);195 if (rc < 0)196 return rc;197 198 /* Select copper register set */199 val &= ~BCM54XX_SHD_MODE_1000BX;200 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val);201 if (rc < 0)202 return rc;203 204 /* Power up copper interface */205 return phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN);206}207 208/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */209static int bcm50610_a0_workaround(struct phy_device *phydev)210{211 int err;212 213 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0,214 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |215 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);216 if (err < 0)217 return err;218 219 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3,220 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);221 if (err < 0)222 return err;223 224 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75,225 MII_BCM54XX_EXP_EXP75_VDACCTRL);226 if (err < 0)227 return err;228 229 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96,230 MII_BCM54XX_EXP_EXP96_MYST);231 if (err < 0)232 return err;233 234 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97,235 MII_BCM54XX_EXP_EXP97_MYST);236 237 return err;238}239 240static int bcm54xx_phydsp_config(struct phy_device *phydev)241{242 int err, err2;243 244 /* Enable the SMDSP clock */245 err = bcm54xx_auxctl_write(phydev,246 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,247 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |248 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);249 if (err < 0)250 return err;251 252 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||253 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) {254 /* Clear bit 9 to fix a phy interop issue. */255 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08,256 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ);257 if (err < 0)258 goto error;259 260 if (phydev->drv->phy_id == PHY_ID_BCM50610) {261 err = bcm50610_a0_workaround(phydev);262 if (err < 0)263 goto error;264 }265 }266 267 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) {268 int val;269 270 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75);271 if (val < 0)272 goto error;273 274 val |= MII_BCM54XX_EXP_EXP75_CM_OSC;275 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val);276 }277 278error:279 /* Disable the SMDSP clock */280 err2 = bcm54xx_auxctl_write(phydev,281 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,282 MII_BCM54XX_AUXCTL_ACTL_TX_6DB);283 284 /* Return the first error reported. */285 return err ? err : err2;286}287 288static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev)289{290 u32 orig;291 int val;292 bool clk125en = true;293 294 /* Abort if we are using an untested phy. */295 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 &&296 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 &&297 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M &&298 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54210E &&299 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54810 &&300 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811)301 return;302 303 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3);304 if (val < 0)305 return;306 307 orig = val;308 309 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||310 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&311 BRCM_PHY_REV(phydev) >= 0x3) {312 /*313 * Here, bit 0 _disables_ CLK125 when set.314 * This bit is set by default.315 */316 clk125en = false;317 } else {318 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) {319 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811) {320 /* Here, bit 0 _enables_ CLK125 when set */321 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125;322 }323 clk125en = false;324 }325 }326 327 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))328 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS;329 else330 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS;331 332 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) {333 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54210E ||334 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810 ||335 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54811)336 val |= BCM54XX_SHD_SCR3_RXCTXC_DIS;337 else338 val |= BCM54XX_SHD_SCR3_TRDDAPD;339 }340 341 if (orig != val)342 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val);343 344 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD);345 if (val < 0)346 return;347 348 orig = val;349 350 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))351 val |= BCM54XX_SHD_APD_EN;352 else353 val &= ~BCM54XX_SHD_APD_EN;354 355 if (orig != val)356 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val);357}358 359static void bcm54xx_ptp_stop(struct phy_device *phydev)360{361 struct bcm54xx_phy_priv *priv = phydev->priv;362 363 if (priv->ptp)364 bcm_ptp_stop(priv->ptp);365}366 367static void bcm54xx_ptp_config_init(struct phy_device *phydev)368{369 struct bcm54xx_phy_priv *priv = phydev->priv;370 371 if (priv->ptp)372 bcm_ptp_config_init(phydev);373}374 375static int bcm5481x_set_brrmode(struct phy_device *phydev, bool on)376{377 int reg;378 int err;379 u16 val;380 381 reg = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);382 383 if (reg < 0)384 return reg;385 386 if (on)387 reg |= BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;388 else389 reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;390 391 err = bcm_phy_write_exp(phydev,392 BCM54810_EXP_BROADREACH_LRE_MISC_CTL, reg);393 if (err)394 return err;395 396 /* Ensure LRE or IEEE register set is accessed according to the brr397 * on/off, thus set the override398 */399 val = BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_EN;400 if (!on)401 val |= BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL_OVERRIDE_VAL;402 403 return bcm_phy_write_exp(phydev,404 BCM54811_EXP_BROADREACH_LRE_OVERLAY_CTL, val);405}406 407static int bcm54811_config_init(struct phy_device *phydev)408{409 struct bcm54xx_phy_priv *priv = phydev->priv;410 int err, reg;411 412 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */413 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) {414 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0);415 if (reg < 0)416 return reg;417 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0,418 BCM54612E_LED4_CLK125OUT_EN | reg);419 if (err < 0)420 return err;421 }422 423 /* With BCM54811, BroadR-Reach implies no autoneg */424 if (priv->brr_mode)425 phydev->autoneg = 0;426 427 return bcm5481x_set_brrmode(phydev, priv->brr_mode);428}429 430static int bcm54xx_config_init(struct phy_device *phydev)431{432 int reg, err, val;433 434 reg = phy_read(phydev, MII_BCM54XX_ECR);435 if (reg < 0)436 return reg;437 438 /* Mask interrupts globally. */439 reg |= MII_BCM54XX_ECR_IM;440 err = phy_write(phydev, MII_BCM54XX_ECR, reg);441 if (err < 0)442 return err;443 444 /* Unmask events we are interested in. */445 reg = ~(MII_BCM54XX_INT_DUPLEX |446 MII_BCM54XX_INT_SPEED |447 MII_BCM54XX_INT_LINK);448 err = phy_write(phydev, MII_BCM54XX_IMR, reg);449 if (err < 0)450 return err;451 452 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 ||453 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) &&454 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE))455 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0);456 457 bcm54xx_adjust_rxrefclk(phydev);458 459 switch (BRCM_PHY_MODEL(phydev)) {460 case PHY_ID_BCM50610:461 case PHY_ID_BCM50610M:462 err = bcm54xx_config_clock_delay(phydev);463 break;464 case PHY_ID_BCM54210E:465 err = bcm54210e_config_init(phydev);466 break;467 case PHY_ID_BCM54612E:468 err = bcm54612e_config_init(phydev);469 break;470 case PHY_ID_BCM54616S:471 err = bcm54616s_config_init(phydev);472 break;473 case PHY_ID_BCM54810:474 /* For BCM54810, we need to disable BroadR-Reach function */475 val = bcm_phy_read_exp(phydev,476 BCM54810_EXP_BROADREACH_LRE_MISC_CTL);477 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;478 err = bcm_phy_write_exp(phydev,479 BCM54810_EXP_BROADREACH_LRE_MISC_CTL,480 val);481 break;482 case PHY_ID_BCM54811:483 err = bcm54811_config_init(phydev);484 break;485 }486 if (err)487 return err;488 489 bcm54xx_phydsp_config(phydev);490 491 /* For non-SFP setups, encode link speed into LED1 and LED3 pair492 * (green/amber).493 * Also flash these two LEDs on activity. This means configuring494 * them for MULTICOLOR and encoding link/activity into them.495 * Don't do this for devices on an SFP module, since some of these496 * use the LED outputs to control the SFP LOS signal, and changing497 * these settings will cause LOS to malfunction.498 */499 if (!phy_on_sfp(phydev)) {500 val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) |501 BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1);502 bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val);503 504 val = BCM_LED_MULTICOLOR_IN_PHASE |505 BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) |506 BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT);507 bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val);508 }509 510 bcm54xx_ptp_config_init(phydev);511 512 /* Acknowledge any left over interrupt and charge the device for513 * wake-up.514 */515 err = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);516 if (err < 0)517 return err;518 519 if (err)520 pm_wakeup_event(&phydev->mdio.dev, 0);521 522 return 0;523}524 525static int bcm54xx_iddq_set(struct phy_device *phydev, bool enable)526{527 int ret = 0;528 529 if (!(phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND))530 return ret;531 532 ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_IDDQ_CTRL);533 if (ret < 0)534 goto out;535 536 if (enable)537 ret |= BCM54XX_TOP_MISC_IDDQ_SR | BCM54XX_TOP_MISC_IDDQ_LP;538 else539 ret &= ~(BCM54XX_TOP_MISC_IDDQ_SR | BCM54XX_TOP_MISC_IDDQ_LP);540 541 ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_IDDQ_CTRL, ret);542out:543 return ret;544}545 546static int bcm54xx_set_wakeup_irq(struct phy_device *phydev, bool state)547{548 struct bcm54xx_phy_priv *priv = phydev->priv;549 int ret = 0;550 551 if (!bcm54xx_phy_can_wakeup(phydev))552 return ret;553 554 if (priv->wake_irq_enabled != state) {555 if (state)556 ret = enable_irq_wake(priv->wake_irq);557 else558 ret = disable_irq_wake(priv->wake_irq);559 priv->wake_irq_enabled = state;560 }561 562 return ret;563}564 565static int bcm54xx_suspend(struct phy_device *phydev)566{567 int ret = 0;568 569 bcm54xx_ptp_stop(phydev);570 571 /* Acknowledge any Wake-on-LAN interrupt prior to suspend */572 ret = bcm_phy_read_exp(phydev, BCM54XX_WOL_INT_STATUS);573 if (ret < 0)574 return ret;575 576 if (phydev->wol_enabled)577 return bcm54xx_set_wakeup_irq(phydev, true);578 579 /* We cannot use a read/modify/write here otherwise the PHY gets into580 * a bad state where its LEDs keep flashing, thus defeating the purpose581 * of low power mode.582 */583 ret = phy_write(phydev, MII_BMCR, BMCR_PDOWN);584 if (ret < 0)585 return ret;586 587 return bcm54xx_iddq_set(phydev, true);588}589 590static int bcm54xx_resume(struct phy_device *phydev)591{592 int ret = 0;593 594 if (phydev->wol_enabled) {595 ret = bcm54xx_set_wakeup_irq(phydev, false);596 if (ret)597 return ret;598 }599 600 ret = bcm54xx_iddq_set(phydev, false);601 if (ret < 0)602 return ret;603 604 /* Writes to register other than BMCR would be ignored605 * unless we clear the PDOWN bit first606 */607 ret = genphy_resume(phydev);608 if (ret < 0)609 return ret;610 611 /* Upon exiting power down, the PHY remains in an internal reset state612 * for 40us613 */614 fsleep(40);615 616 /* Issue a soft reset after clearing the power down bit617 * and before doing any other configuration.618 */619 if (phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND) {620 ret = genphy_soft_reset(phydev);621 if (ret < 0)622 return ret;623 }624 625 return bcm54xx_config_init(phydev);626}627 628static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)629{630 return -EOPNOTSUPP;631}632 633static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,634 u16 val)635{636 return -EOPNOTSUPP;637}638 639 640/**641 * bcm5481x_read_abilities - read PHY abilities from LRESR or Clause 22642 * (BMSR) registers, based on whether the PHY is in BroadR-Reach or IEEE mode643 * @phydev: target phy_device struct644 *645 * Description: Reads the PHY's abilities and populates phydev->supported646 * accordingly. The register to read the abilities from is determined by647 * the brr mode setting of the PHY as read from the device tree.648 * Note that the LRE and IEEE sets of abilities are disjunct, in other words,649 * not only the link modes differ, but also the auto-negotiation and650 * master-slave setup is controlled differently.651 *652 * Returns: 0 on success, < 0 on failure653 */654static int bcm5481x_read_abilities(struct phy_device *phydev)655{656 struct device_node *np = phydev->mdio.dev.of_node;657 struct bcm54xx_phy_priv *priv = phydev->priv;658 int i, val, err;659 660 for (i = 0; i < ARRAY_SIZE(bcm54811_linkmodes); i++)661 linkmode_clear_bit(bcm54811_linkmodes[i], phydev->supported);662 663 priv->brr_mode = of_property_read_bool(np, "brr-mode");664 665 /* Set BroadR-Reach mode as configured in the DT. */666 err = bcm5481x_set_brrmode(phydev, priv->brr_mode);667 if (err)668 return err;669 670 if (priv->brr_mode) {671 linkmode_set_bit_array(phy_basic_ports_array,672 ARRAY_SIZE(phy_basic_ports_array),673 phydev->supported);674 675 val = phy_read(phydev, MII_BCM54XX_LRESR);676 if (val < 0)677 return val;678 679 linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,680 phydev->supported,681 val & LRESR_LDSABILITY);682 linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT,683 phydev->supported,684 val & LRESR_100_1PAIR);685 linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,686 phydev->supported,687 val & LRESR_10_1PAIR);688 return 0;689 }690 691 return genphy_read_abilities(phydev);692}693 694static int bcm5481x_config_delay_swap(struct phy_device *phydev)695{696 struct device_node *np = phydev->mdio.dev.of_node;697 698 /* Set up the delay. */699 bcm54xx_config_clock_delay(phydev);700 701 if (of_property_read_bool(np, "enet-phy-lane-swap")) {702 /* Lane Swap - Undocumented register...magic! */703 int ret = bcm_phy_write_exp(phydev,704 MII_BCM54XX_EXP_SEL_ER + 0x9,705 0x11B);706 if (ret < 0)707 return ret;708 }709 710 return 0;711}712 713static int bcm5481_config_aneg(struct phy_device *phydev)714{715 struct bcm54xx_phy_priv *priv = phydev->priv;716 int ret;717 718 /* Aneg firstly. */719 if (priv->brr_mode)720 ret = bcm_config_lre_aneg(phydev, false);721 else722 ret = genphy_config_aneg(phydev);723 724 if (ret)725 return ret;726 727 /* Then we can set up the delay and swap. */728 return bcm5481x_config_delay_swap(phydev);729}730 731static int bcm54811_config_aneg(struct phy_device *phydev)732{733 struct bcm54xx_phy_priv *priv = phydev->priv;734 int ret;735 736 /* Aneg firstly. */737 if (priv->brr_mode) {738 /* BCM54811 is only capable of autonegotiation in IEEE mode */739 phydev->autoneg = 0;740 ret = bcm_config_lre_aneg(phydev, false);741 } else {742 ret = genphy_config_aneg(phydev);743 }744 745 if (ret)746 return ret;747 748 /* Then we can set up the delay and swap. */749 return bcm5481x_config_delay_swap(phydev);750}751 752struct bcm54616s_phy_priv {753 bool mode_1000bx_en;754};755 756static int bcm54616s_probe(struct phy_device *phydev)757{758 struct bcm54616s_phy_priv *priv;759 int val;760 761 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);762 if (!priv)763 return -ENOMEM;764 765 phydev->priv = priv;766 767 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE);768 if (val < 0)769 return val;770 771 /* The PHY is strapped in RGMII-fiber mode when INTERF_SEL[1:0]772 * is 01b, and the link between PHY and its link partner can be773 * either 1000Base-X or 100Base-FX.774 * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX775 * support is still missing as of now.776 */777 if ((val & BCM54XX_SHD_INTF_SEL_MASK) == BCM54XX_SHD_INTF_SEL_RGMII) {778 val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL);779 if (val < 0)780 return val;781 782 /* Bit 0 of the SerDes 100-FX Control register, when set783 * to 1, sets the MII/RGMII -> 100BASE-FX configuration.784 * When this bit is set to 0, it sets the GMII/RGMII ->785 * 1000BASE-X configuration.786 */787 if (!(val & BCM54616S_100FX_MODE))788 priv->mode_1000bx_en = true;789 790 phydev->port = PORT_FIBRE;791 }792 793 return 0;794}795 796static int bcm54616s_config_aneg(struct phy_device *phydev)797{798 struct bcm54616s_phy_priv *priv = phydev->priv;799 int ret;800 801 /* Aneg firstly. */802 if (priv->mode_1000bx_en)803 ret = genphy_c37_config_aneg(phydev);804 else805 ret = genphy_config_aneg(phydev);806 807 /* Then we can set up the delay. */808 bcm54xx_config_clock_delay(phydev);809 810 return ret;811}812 813static int bcm54616s_read_status(struct phy_device *phydev)814{815 struct bcm54616s_phy_priv *priv = phydev->priv;816 bool changed;817 int err;818 819 if (priv->mode_1000bx_en)820 err = genphy_c37_read_status(phydev, &changed);821 else822 err = genphy_read_status(phydev);823 824 return err;825}826 827static int brcm_fet_config_init(struct phy_device *phydev)828{829 int reg, err, err2, brcmtest;830 831 /* Reset the PHY to bring it to a known state. */832 err = phy_write(phydev, MII_BMCR, BMCR_RESET);833 if (err < 0)834 return err;835 836 /* The datasheet indicates the PHY needs up to 1us to complete a reset,837 * build some slack here.838 */839 usleep_range(1000, 2000);840 841 /* The PHY requires 65 MDC clock cycles to complete a write operation842 * and turnaround the line properly.843 *844 * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac)845 * may flag the lack of turn-around as a read failure. This is846 * particularly true with this combination since the MDIO controller847 * only used 64 MDC cycles. This is not a critical failure in this848 * specific case and it has no functional impact otherwise, so we let849 * that one go through. If there is a genuine bus error, the next read850 * of MII_BRCM_FET_INTREG will error out.851 */852 err = phy_read(phydev, MII_BMCR);853 if (err < 0 && err != -EIO)854 return err;855 856 /* Read to clear status bits */857 reg = phy_read(phydev, MII_BRCM_FET_INTREG);858 if (reg < 0)859 return reg;860 861 /* Unmask events we are interested in and mask interrupts globally. */862 if (phydev->phy_id == PHY_ID_BCM5221)863 reg = MII_BRCM_FET_IR_ENABLE |864 MII_BRCM_FET_IR_MASK;865 else866 reg = MII_BRCM_FET_IR_DUPLEX_EN |867 MII_BRCM_FET_IR_SPEED_EN |868 MII_BRCM_FET_IR_LINK_EN |869 MII_BRCM_FET_IR_ENABLE |870 MII_BRCM_FET_IR_MASK;871 872 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);873 if (err < 0)874 return err;875 876 /* Enable shadow register access */877 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);878 if (brcmtest < 0)879 return brcmtest;880 881 reg = brcmtest | MII_BRCM_FET_BT_SRE;882 883 phy_lock_mdio_bus(phydev);884 885 err = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);886 if (err < 0) {887 phy_unlock_mdio_bus(phydev);888 return err;889 }890 891 if (phydev->phy_id != PHY_ID_BCM5221) {892 /* Set the LED mode */893 reg = __phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4);894 if (reg < 0) {895 err = reg;896 goto done;897 }898 899 err = __phy_modify(phydev, MII_BRCM_FET_SHDW_AUXMODE4,900 MII_BRCM_FET_SHDW_AM4_LED_MASK,901 MII_BRCM_FET_SHDW_AM4_LED_MODE1);902 if (err < 0)903 goto done;904 905 /* Enable auto MDIX */906 err = __phy_set_bits(phydev, MII_BRCM_FET_SHDW_MISCCTRL,907 MII_BRCM_FET_SHDW_MC_FAME);908 if (err < 0)909 goto done;910 }911 912 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) {913 /* Enable auto power down */914 err = __phy_set_bits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2,915 MII_BRCM_FET_SHDW_AS2_APDE);916 }917 918done:919 /* Disable shadow register access */920 err2 = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);921 if (!err)922 err = err2;923 924 phy_unlock_mdio_bus(phydev);925 926 return err;927}928 929static int brcm_fet_ack_interrupt(struct phy_device *phydev)930{931 int reg;932 933 /* Clear pending interrupts. */934 reg = phy_read(phydev, MII_BRCM_FET_INTREG);935 if (reg < 0)936 return reg;937 938 return 0;939}940 941static int brcm_fet_config_intr(struct phy_device *phydev)942{943 int reg, err;944 945 reg = phy_read(phydev, MII_BRCM_FET_INTREG);946 if (reg < 0)947 return reg;948 949 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {950 err = brcm_fet_ack_interrupt(phydev);951 if (err)952 return err;953 954 reg &= ~MII_BRCM_FET_IR_MASK;955 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);956 } else {957 reg |= MII_BRCM_FET_IR_MASK;958 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg);959 if (err)960 return err;961 962 err = brcm_fet_ack_interrupt(phydev);963 }964 965 return err;966}967 968static irqreturn_t brcm_fet_handle_interrupt(struct phy_device *phydev)969{970 int irq_status;971 972 irq_status = phy_read(phydev, MII_BRCM_FET_INTREG);973 if (irq_status < 0) {974 phy_error(phydev);975 return IRQ_NONE;976 }977 978 if (irq_status == 0)979 return IRQ_NONE;980 981 phy_trigger_machine(phydev);982 983 return IRQ_HANDLED;984}985 986static int brcm_fet_suspend(struct phy_device *phydev)987{988 int reg, err, err2, brcmtest;989 990 /* We cannot use a read/modify/write here otherwise the PHY continues991 * to drive LEDs which defeats the purpose of low power mode.992 */993 err = phy_write(phydev, MII_BMCR, BMCR_PDOWN);994 if (err < 0)995 return err;996 997 /* Enable shadow register access */998 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);999 if (brcmtest < 0)1000 return brcmtest;1001 1002 reg = brcmtest | MII_BRCM_FET_BT_SRE;1003 1004 phy_lock_mdio_bus(phydev);1005 1006 err = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);1007 if (err < 0) {1008 phy_unlock_mdio_bus(phydev);1009 return err;1010 }1011 1012 if (phydev->phy_id == PHY_ID_BCM5221)1013 /* Force Low Power Mode with clock enabled */1014 reg = BCM5221_SHDW_AM4_EN_CLK_LPM | BCM5221_SHDW_AM4_FORCE_LPM;1015 else1016 /* Set standby mode */1017 reg = MII_BRCM_FET_SHDW_AM4_STANDBY;1018 1019 err = __phy_set_bits(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg);1020 1021 /* Disable shadow register access */1022 err2 = __phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);1023 if (!err)1024 err = err2;1025 1026 phy_unlock_mdio_bus(phydev);1027 1028 return err;1029}1030 1031static int bcm5221_config_aneg(struct phy_device *phydev)1032{1033 int ret, val;1034 1035 ret = genphy_config_aneg(phydev);1036 if (ret)1037 return ret;1038 1039 switch (phydev->mdix_ctrl) {1040 case ETH_TP_MDI:1041 val = BCM5221_AEGSR_MDIX_DIS;1042 break;1043 case ETH_TP_MDI_X:1044 val = BCM5221_AEGSR_MDIX_DIS | BCM5221_AEGSR_MDIX_MAN_SWAP;1045 break;1046 case ETH_TP_MDI_AUTO:1047 val = 0;1048 break;1049 default:1050 return 0;1051 }1052 1053 return phy_modify(phydev, BCM5221_AEGSR, BCM5221_AEGSR_MDIX_MAN_SWAP |1054 BCM5221_AEGSR_MDIX_DIS,1055 val);1056}1057 1058static int bcm5221_read_status(struct phy_device *phydev)1059{1060 int ret;1061 1062 /* Read MDIX status */1063 ret = phy_read(phydev, BCM5221_AEGSR);1064 if (ret < 0)1065 return ret;1066 1067 if (ret & BCM5221_AEGSR_MDIX_DIS) {1068 if (ret & BCM5221_AEGSR_MDIX_MAN_SWAP)1069 phydev->mdix_ctrl = ETH_TP_MDI_X;1070 else1071 phydev->mdix_ctrl = ETH_TP_MDI;1072 } else {1073 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;1074 }1075 1076 if (ret & BCM5221_AEGSR_MDIX_STATUS)1077 phydev->mdix = ETH_TP_MDI_X;1078 else1079 phydev->mdix = ETH_TP_MDI;1080 1081 return genphy_read_status(phydev);1082}1083 1084static void bcm54xx_phy_get_wol(struct phy_device *phydev,1085 struct ethtool_wolinfo *wol)1086{1087 /* We cannot wake-up if we do not have a dedicated PHY interrupt line1088 * or an out of band GPIO descriptor for wake-up. Zeroing1089 * wol->supported allows the caller (MAC driver) to play through and1090 * offer its own Wake-on-LAN scheme if available.1091 */1092 if (!bcm54xx_phy_can_wakeup(phydev)) {1093 wol->supported = 0;1094 return;1095 }1096 1097 bcm_phy_get_wol(phydev, wol);1098}1099 1100static int bcm54xx_phy_set_wol(struct phy_device *phydev,1101 struct ethtool_wolinfo *wol)1102{1103 int ret;1104 1105 /* We cannot wake-up if we do not have a dedicated PHY interrupt line1106 * or an out of band GPIO descriptor for wake-up. Returning -EOPNOTSUPP1107 * allows the caller (MAC driver) to play through and offer its own1108 * Wake-on-LAN scheme if available.1109 */1110 if (!bcm54xx_phy_can_wakeup(phydev))1111 return -EOPNOTSUPP;1112 1113 ret = bcm_phy_set_wol(phydev, wol);1114 if (ret < 0)1115 return ret;1116 1117 return 0;1118}1119 1120static int bcm54xx_phy_probe(struct phy_device *phydev)1121{1122 struct bcm54xx_phy_priv *priv;1123 struct gpio_desc *wakeup_gpio;1124 int ret = 0;1125 1126 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);1127 if (!priv)1128 return -ENOMEM;1129 1130 priv->wake_irq = -ENXIO;1131 1132 phydev->priv = priv;1133 1134 priv->stats = devm_kcalloc(&phydev->mdio.dev,1135 bcm_phy_get_sset_count(phydev), sizeof(u64),1136 GFP_KERNEL);1137 if (!priv->stats)1138 return -ENOMEM;1139 1140 priv->ptp = bcm_ptp_probe(phydev);1141 if (IS_ERR(priv->ptp))1142 return PTR_ERR(priv->ptp);1143 1144 /* We cannot utilize the _optional variant here since we want to know1145 * whether the GPIO descriptor exists or not to advertise Wake-on-LAN1146 * support or not.1147 */1148 wakeup_gpio = devm_gpiod_get(&phydev->mdio.dev, "wakeup", GPIOD_IN);1149 if (PTR_ERR(wakeup_gpio) == -EPROBE_DEFER)1150 return PTR_ERR(wakeup_gpio);1151 1152 if (!IS_ERR(wakeup_gpio)) {1153 priv->wake_irq = gpiod_to_irq(wakeup_gpio);1154 1155 /* Dummy interrupt handler which is not enabled but is provided1156 * in order for the interrupt descriptor to be fully set-up.1157 */1158 ret = devm_request_irq(&phydev->mdio.dev, priv->wake_irq,1159 bcm_phy_wol_isr,1160 IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN,1161 dev_name(&phydev->mdio.dev), phydev);1162 if (ret)1163 return ret;1164 }1165 1166 /* If we do not have a main interrupt or a side-band wake-up interrupt,1167 * then the device cannot be marked as wake-up capable.1168 */1169 if (!bcm54xx_phy_can_wakeup(phydev))1170 return 0;1171 1172 return device_init_wakeup(&phydev->mdio.dev, true);1173}1174 1175static void bcm54xx_get_stats(struct phy_device *phydev,1176 struct ethtool_stats *stats, u64 *data)1177{1178 struct bcm54xx_phy_priv *priv = phydev->priv;1179 1180 bcm_phy_get_stats(phydev, priv->stats, stats, data);1181}1182 1183static void bcm54xx_link_change_notify(struct phy_device *phydev)1184{1185 u16 mask = MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE |1186 MII_BCM54XX_EXP_EXP08_FORCE_DAC_WAKE;1187 int ret;1188 1189 if (phydev->state != PHY_RUNNING)1190 return;1191 1192 /* Don't change the DAC wake settings if auto power down1193 * is not requested.1194 */1195 if (!(phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))1196 return;1197 1198 ret = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP08);1199 if (ret < 0)1200 return;1201 1202 /* Enable/disable 10BaseT auto and forced early DAC wake depending1203 * on the negotiated speed, those settings should only be done1204 * for 10Mbits/sec.1205 */1206 if (phydev->speed == SPEED_10)1207 ret |= mask;1208 else1209 ret &= ~mask;1210 bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, ret);1211}1212 1213static int lre_read_master_slave(struct phy_device *phydev)1214{1215 int cfg = MASTER_SLAVE_CFG_UNKNOWN, state;1216 int val;1217 1218 /* In BroadR-Reach mode we are always capable of master-slave1219 * and there is no preferred master or slave configuration1220 */1221 phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN;1222 phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;1223 1224 val = phy_read(phydev, MII_BCM54XX_LRECR);1225 if (val < 0)1226 return val;1227 1228 if ((val & LRECR_LDSEN) == 0) {1229 if (val & LRECR_MASTER)1230 cfg = MASTER_SLAVE_CFG_MASTER_FORCE;1231 else1232 cfg = MASTER_SLAVE_CFG_SLAVE_FORCE;1233 }1234 1235 val = phy_read(phydev, MII_BCM54XX_LRELDSE);1236 if (val < 0)1237 return val;1238 1239 if (val & LDSE_MASTER)1240 state = MASTER_SLAVE_STATE_MASTER;1241 else1242 state = MASTER_SLAVE_STATE_SLAVE;1243 1244 phydev->master_slave_get = cfg;1245 phydev->master_slave_state = state;1246 1247 return 0;1248}1249 1250/* Read LDS Link Partner Ability in BroadR-Reach mode */1251static int lre_read_lpa(struct phy_device *phydev)1252{1253 int i, lrelpa;1254 1255 if (phydev->autoneg != AUTONEG_ENABLE) {1256 if (!phydev->autoneg_complete) {1257 /* aneg not yet done, reset all relevant bits */1258 for (i = 0; i < ARRAY_SIZE(lds_br_bits); i++)1259 linkmode_clear_bit(lds_br_bits[i],1260 phydev->lp_advertising);1261 1262 return 0;1263 }1264 1265 /* Long-Distance Signaling Link Partner Ability */1266 lrelpa = phy_read(phydev, MII_BCM54XX_LRELPA);1267 if (lrelpa < 0)1268 return lrelpa;1269 1270 linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,1271 phydev->lp_advertising,1272 lrelpa & LRELPA_PAUSE_ASYM);1273 linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT,1274 phydev->lp_advertising,1275 lrelpa & LRELPA_PAUSE);1276 linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT,1277 phydev->lp_advertising,1278 lrelpa & LRELPA_100_1PAIR);1279 linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1BRR_Full_BIT,1280 phydev->lp_advertising,1281 lrelpa & LRELPA_10_1PAIR);1282 } else {1283 linkmode_zero(phydev->lp_advertising);1284 }1285 1286 return 0;1287}1288 1289static int lre_read_status_fixed(struct phy_device *phydev)1290{1291 int lrecr = phy_read(phydev, MII_BCM54XX_LRECR);1292 1293 if (lrecr < 0)1294 return lrecr;1295 1296 phydev->duplex = DUPLEX_FULL;1297 1298 if (lrecr & LRECR_SPEED100)1299 phydev->speed = SPEED_100;1300 else1301 phydev->speed = SPEED_10;1302 1303 return 0;1304}1305 1306/**1307 * lre_update_link - update link status in @phydev1308 * @phydev: target phy_device struct1309 * Return: 0 on success, < 0 on error1310 *1311 * Description: Update the value in phydev->link to reflect the1312 * current link value. In order to do this, we need to read1313 * the status register twice, keeping the second value.1314 * This is a genphy_update_link modified to work on LRE registers1315 * of BroadR-Reach PHY1316 */1317static int lre_update_link(struct phy_device *phydev)1318{1319 int status = 0, lrecr;1320 1321 lrecr = phy_read(phydev, MII_BCM54XX_LRECR);1322 if (lrecr < 0)1323 return lrecr;1324 1325 /* Autoneg is being started, therefore disregard BMSR value and1326 * report link as down.1327 */1328 if (lrecr & BMCR_ANRESTART)1329 goto done;1330 1331 /* The link state is latched low so that momentary link1332 * drops can be detected. Do not double-read the status1333 * in polling mode to detect such short link drops except1334 * the link was already down.1335 */1336 if (!phy_polling_mode(phydev) || !phydev->link) {1337 status = phy_read(phydev, MII_BCM54XX_LRESR);1338 if (status < 0)1339 return status;1340 else if (status & LRESR_LSTATUS)1341 goto done;1342 }1343 1344 /* Read link and autonegotiation status */1345 status = phy_read(phydev, MII_BCM54XX_LRESR);1346 if (status < 0)1347 return status;1348done:1349 phydev->link = status & LRESR_LSTATUS ? 1 : 0;1350 phydev->autoneg_complete = status & LRESR_LDSCOMPLETE ? 1 : 0;1351 1352 /* Consider the case that autoneg was started and "aneg complete"1353 * bit has been reset, but "link up" bit not yet.1354 */1355 if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)1356 phydev->link = 0;1357 1358 return 0;1359}1360 1361/* Get the status in BroadRReach mode just like genphy_read_status does1362* in normal mode1363*/1364static int bcm54811_lre_read_status(struct phy_device *phydev)1365{1366 int err, old_link = phydev->link;1367 1368 /* Update the link, but return if there was an error */1369 err = lre_update_link(phydev);1370 if (err)1371 return err;1372 1373 /* why bother the PHY if nothing can have changed */1374 if (phydev->autoneg ==1375 AUTONEG_ENABLE && old_link && phydev->link)1376 return 0;1377 1378 phydev->speed = SPEED_UNKNOWN;1379 phydev->duplex = DUPLEX_UNKNOWN;1380 phydev->pause = 0;1381 phydev->asym_pause = 0;1382 1383 err = lre_read_master_slave(phydev);1384 if (err < 0)1385 return err;1386 1387 /* Read LDS Link Partner Ability */1388 err = lre_read_lpa(phydev);1389 if (err < 0)1390 return err;1391 1392 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)1393 phy_resolve_aneg_linkmode(phydev);1394 else if (phydev->autoneg == AUTONEG_DISABLE)1395 err = lre_read_status_fixed(phydev);1396 1397 return err;1398}1399 1400static int bcm54811_read_status(struct phy_device *phydev)1401{1402 struct bcm54xx_phy_priv *priv = phydev->priv;1403 1404 if (priv->brr_mode)1405 return bcm54811_lre_read_status(phydev);1406 1407 return genphy_read_status(phydev);1408}1409 1410static struct phy_driver broadcom_drivers[] = {1411{1412 .phy_id = PHY_ID_BCM5411,1413 .phy_id_mask = 0xfffffff0,1414 .name = "Broadcom BCM5411",1415 /* PHY_GBIT_FEATURES */1416 .get_sset_count = bcm_phy_get_sset_count,1417 .get_strings = bcm_phy_get_strings,1418 .get_stats = bcm54xx_get_stats,1419 .probe = bcm54xx_phy_probe,1420 .config_init = bcm54xx_config_init,1421 .config_intr = bcm_phy_config_intr,1422 .handle_interrupt = bcm_phy_handle_interrupt,1423 .link_change_notify = bcm54xx_link_change_notify,1424}, {1425 .phy_id = PHY_ID_BCM5421,1426 .phy_id_mask = 0xfffffff0,1427 .name = "Broadcom BCM5421",1428 /* PHY_GBIT_FEATURES */1429 .get_sset_count = bcm_phy_get_sset_count,1430 .get_strings = bcm_phy_get_strings,1431 .get_stats = bcm54xx_get_stats,1432 .probe = bcm54xx_phy_probe,1433 .config_init = bcm54xx_config_init,1434 .config_intr = bcm_phy_config_intr,1435 .handle_interrupt = bcm_phy_handle_interrupt,1436 .link_change_notify = bcm54xx_link_change_notify,1437}, {1438 .phy_id = PHY_ID_BCM54210E,1439 .phy_id_mask = 0xfffffff0,1440 .name = "Broadcom BCM54210E",1441 /* PHY_GBIT_FEATURES */1442 .flags = PHY_ALWAYS_CALL_SUSPEND,1443 .get_sset_count = bcm_phy_get_sset_count,1444 .get_strings = bcm_phy_get_strings,1445 .get_stats = bcm54xx_get_stats,1446 .probe = bcm54xx_phy_probe,1447 .config_init = bcm54xx_config_init,1448 .config_intr = bcm_phy_config_intr,1449 .handle_interrupt = bcm_phy_handle_interrupt,1450 .link_change_notify = bcm54xx_link_change_notify,1451 .suspend = bcm54xx_suspend,1452 .resume = bcm54xx_resume,1453 .get_wol = bcm54xx_phy_get_wol,1454 .set_wol = bcm54xx_phy_set_wol,1455 .led_brightness_set = bcm_phy_led_brightness_set,1456}, {1457 .phy_id = PHY_ID_BCM5461,1458 .phy_id_mask = 0xfffffff0,1459 .name = "Broadcom BCM5461",1460 /* PHY_GBIT_FEATURES */1461 .get_sset_count = bcm_phy_get_sset_count,1462 .get_strings = bcm_phy_get_strings,1463 .get_stats = bcm54xx_get_stats,1464 .probe = bcm54xx_phy_probe,1465 .config_init = bcm54xx_config_init,1466 .config_intr = bcm_phy_config_intr,1467 .handle_interrupt = bcm_phy_handle_interrupt,1468 .link_change_notify = bcm54xx_link_change_notify,1469 .led_brightness_set = bcm_phy_led_brightness_set,1470}, {1471 .phy_id = PHY_ID_BCM54612E,1472 .phy_id_mask = 0xfffffff0,1473 .name = "Broadcom BCM54612E",1474 /* PHY_GBIT_FEATURES */1475 .get_sset_count = bcm_phy_get_sset_count,1476 .get_strings = bcm_phy_get_strings,1477 .get_stats = bcm54xx_get_stats,1478 .probe = bcm54xx_phy_probe,1479 .config_init = bcm54xx_config_init,1480 .config_intr = bcm_phy_config_intr,1481 .handle_interrupt = bcm_phy_handle_interrupt,1482 .link_change_notify = bcm54xx_link_change_notify,1483 .led_brightness_set = bcm_phy_led_brightness_set,1484 .suspend = bcm54xx_suspend,1485 .resume = bcm54xx_resume,1486}, {1487 .phy_id = PHY_ID_BCM54616S,1488 .phy_id_mask = 0xfffffff0,1489 .name = "Broadcom BCM54616S",1490 /* PHY_GBIT_FEATURES */1491 .soft_reset = genphy_soft_reset,1492 .config_init = bcm54xx_config_init,1493 .config_aneg = bcm54616s_config_aneg,1494 .config_intr = bcm_phy_config_intr,1495 .handle_interrupt = bcm_phy_handle_interrupt,1496 .read_status = bcm54616s_read_status,1497 .probe = bcm54616s_probe,1498 .link_change_notify = bcm54xx_link_change_notify,1499 .led_brightness_set = bcm_phy_led_brightness_set,1500}, {1501 .phy_id = PHY_ID_BCM5464,1502 .phy_id_mask = 0xfffffff0,1503 .name = "Broadcom BCM5464",1504 /* PHY_GBIT_FEATURES */1505 .get_sset_count = bcm_phy_get_sset_count,1506 .get_strings = bcm_phy_get_strings,1507 .get_stats = bcm54xx_get_stats,1508 .probe = bcm54xx_phy_probe,1509 .config_init = bcm54xx_config_init,1510 .config_intr = bcm_phy_config_intr,1511 .handle_interrupt = bcm_phy_handle_interrupt,1512 .suspend = genphy_suspend,1513 .resume = genphy_resume,1514 .link_change_notify = bcm54xx_link_change_notify,1515 .led_brightness_set = bcm_phy_led_brightness_set,1516}, {1517 .phy_id = PHY_ID_BCM5481,1518 .phy_id_mask = 0xfffffff0,1519 .name = "Broadcom BCM5481",1520 /* PHY_GBIT_FEATURES */1521 .get_sset_count = bcm_phy_get_sset_count,1522 .get_strings = bcm_phy_get_strings,1523 .get_stats = bcm54xx_get_stats,1524 .probe = bcm54xx_phy_probe,1525 .config_init = bcm54xx_config_init,1526 .config_aneg = bcm5481_config_aneg,1527 .config_intr = bcm_phy_config_intr,1528 .handle_interrupt = bcm_phy_handle_interrupt,1529 .link_change_notify = bcm54xx_link_change_notify,1530 .led_brightness_set = bcm_phy_led_brightness_set,1531}, {1532 .phy_id = PHY_ID_BCM54810,1533 .phy_id_mask = 0xfffffff0,1534 .name = "Broadcom BCM54810",1535 /* PHY_GBIT_FEATURES */1536 .get_sset_count = bcm_phy_get_sset_count,1537 .get_strings = bcm_phy_get_strings,1538 .get_stats = bcm54xx_get_stats,1539 .probe = bcm54xx_phy_probe,1540 .read_mmd = bcm54810_read_mmd,1541 .write_mmd = bcm54810_write_mmd,1542 .config_init = bcm54xx_config_init,1543 .config_aneg = bcm5481_config_aneg,1544 .config_intr = bcm_phy_config_intr,1545 .handle_interrupt = bcm_phy_handle_interrupt,1546 .suspend = bcm54xx_suspend,1547 .resume = bcm54xx_resume,1548 .link_change_notify = bcm54xx_link_change_notify,1549 .led_brightness_set = bcm_phy_led_brightness_set,1550}, {1551 .phy_id = PHY_ID_BCM54811,1552 .phy_id_mask = 0xfffffff0,1553 .name = "Broadcom BCM54811",1554 /* PHY_GBIT_FEATURES */1555 .get_sset_count = bcm_phy_get_sset_count,1556 .get_strings = bcm_phy_get_strings,1557 .get_stats = bcm54xx_get_stats,1558 .probe = bcm54xx_phy_probe,1559 .config_init = bcm54xx_config_init,1560 .config_aneg = bcm54811_config_aneg,1561 .config_intr = bcm_phy_config_intr,1562 .handle_interrupt = bcm_phy_handle_interrupt,1563 .read_status = bcm54811_read_status,1564 .get_features = bcm5481x_read_abilities,1565 .suspend = bcm54xx_suspend,1566 .resume = bcm54xx_resume,1567 .link_change_notify = bcm54xx_link_change_notify,1568 .led_brightness_set = bcm_phy_led_brightness_set,1569}, {1570 .phy_id = PHY_ID_BCM5482,1571 .phy_id_mask = 0xfffffff0,1572 .name = "Broadcom BCM5482",1573 /* PHY_GBIT_FEATURES */1574 .get_sset_count = bcm_phy_get_sset_count,1575 .get_strings = bcm_phy_get_strings,1576 .get_stats = bcm54xx_get_stats,1577 .probe = bcm54xx_phy_probe,1578 .config_init = bcm54xx_config_init,1579 .config_intr = bcm_phy_config_intr,1580 .handle_interrupt = bcm_phy_handle_interrupt,1581 .link_change_notify = bcm54xx_link_change_notify,1582 .led_brightness_set = bcm_phy_led_brightness_set,1583}, {1584 .phy_id = PHY_ID_BCM50610,1585 .phy_id_mask = 0xfffffff0,1586 .name = "Broadcom BCM50610",1587 /* PHY_GBIT_FEATURES */1588 .get_sset_count = bcm_phy_get_sset_count,1589 .get_strings = bcm_phy_get_strings,1590 .get_stats = bcm54xx_get_stats,1591 .probe = bcm54xx_phy_probe,1592 .config_init = bcm54xx_config_init,1593 .config_intr = bcm_phy_config_intr,1594 .handle_interrupt = bcm_phy_handle_interrupt,1595 .link_change_notify = bcm54xx_link_change_notify,1596 .suspend = bcm54xx_suspend,1597 .resume = bcm54xx_resume,1598 .led_brightness_set = bcm_phy_led_brightness_set,1599}, {1600 .phy_id = PHY_ID_BCM50610M,1601 .phy_id_mask = 0xfffffff0,1602 .name = "Broadcom BCM50610M",1603 /* PHY_GBIT_FEATURES */1604 .get_sset_count = bcm_phy_get_sset_count,1605 .get_strings = bcm_phy_get_strings,1606 .get_stats = bcm54xx_get_stats,1607 .probe = bcm54xx_phy_probe,1608 .config_init = bcm54xx_config_init,1609 .config_intr = bcm_phy_config_intr,1610 .handle_interrupt = bcm_phy_handle_interrupt,1611 .link_change_notify = bcm54xx_link_change_notify,1612 .suspend = bcm54xx_suspend,1613 .resume = bcm54xx_resume,1614 .led_brightness_set = bcm_phy_led_brightness_set,1615}, {1616 .phy_id = PHY_ID_BCM57780,1617 .phy_id_mask = 0xfffffff0,1618 .name = "Broadcom BCM57780",1619 /* PHY_GBIT_FEATURES */1620 .get_sset_count = bcm_phy_get_sset_count,1621 .get_strings = bcm_phy_get_strings,1622 .get_stats = bcm54xx_get_stats,1623 .probe = bcm54xx_phy_probe,1624 .config_init = bcm54xx_config_init,1625 .config_intr = bcm_phy_config_intr,1626 .handle_interrupt = bcm_phy_handle_interrupt,1627 .link_change_notify = bcm54xx_link_change_notify,1628 .led_brightness_set = bcm_phy_led_brightness_set,1629}, {1630 .phy_id = PHY_ID_BCMAC131,1631 .phy_id_mask = 0xfffffff0,1632 .name = "Broadcom BCMAC131",1633 /* PHY_BASIC_FEATURES */1634 .config_init = brcm_fet_config_init,1635 .config_intr = brcm_fet_config_intr,1636 .handle_interrupt = brcm_fet_handle_interrupt,1637 .suspend = brcm_fet_suspend,1638 .resume = brcm_fet_config_init,1639}, {1640 .phy_id = PHY_ID_BCM5241,1641 .phy_id_mask = 0xfffffff0,1642 .name = "Broadcom BCM5241",1643 /* PHY_BASIC_FEATURES */1644 .config_init = brcm_fet_config_init,1645 .config_intr = brcm_fet_config_intr,1646 .handle_interrupt = brcm_fet_handle_interrupt,1647 .suspend = brcm_fet_suspend,1648 .resume = brcm_fet_config_init,1649}, {1650 .phy_id = PHY_ID_BCM5221,1651 .phy_id_mask = 0xfffffff0,1652 .name = "Broadcom BCM5221",1653 /* PHY_BASIC_FEATURES */1654 .config_init = brcm_fet_config_init,1655 .config_intr = brcm_fet_config_intr,1656 .handle_interrupt = brcm_fet_handle_interrupt,1657 .suspend = brcm_fet_suspend,1658 .resume = brcm_fet_config_init,1659 .config_aneg = bcm5221_config_aneg,1660 .read_status = bcm5221_read_status,1661}, {1662 .phy_id = PHY_ID_BCM5395,1663 .phy_id_mask = 0xfffffff0,1664 .name = "Broadcom BCM5395",1665 .flags = PHY_IS_INTERNAL,1666 /* PHY_GBIT_FEATURES */1667 .get_sset_count = bcm_phy_get_sset_count,1668 .get_strings = bcm_phy_get_strings,1669 .get_stats = bcm54xx_get_stats,1670 .probe = bcm54xx_phy_probe,1671 .link_change_notify = bcm54xx_link_change_notify,1672 .led_brightness_set = bcm_phy_led_brightness_set,1673}, {1674 .phy_id = PHY_ID_BCM53125,1675 .phy_id_mask = 0xfffffff0,1676 .name = "Broadcom BCM53125",1677 .flags = PHY_IS_INTERNAL,1678 /* PHY_GBIT_FEATURES */1679 .get_sset_count = bcm_phy_get_sset_count,1680 .get_strings = bcm_phy_get_strings,1681 .get_stats = bcm54xx_get_stats,1682 .probe = bcm54xx_phy_probe,1683 .config_init = bcm54xx_config_init,1684 .config_intr = bcm_phy_config_intr,1685 .handle_interrupt = bcm_phy_handle_interrupt,1686 .link_change_notify = bcm54xx_link_change_notify,1687 .led_brightness_set = bcm_phy_led_brightness_set,1688}, {1689 .phy_id = PHY_ID_BCM53128,1690 .phy_id_mask = 0xfffffff0,1691 .name = "Broadcom BCM53128",1692 .flags = PHY_IS_INTERNAL,1693 /* PHY_GBIT_FEATURES */1694 .get_sset_count = bcm_phy_get_sset_count,1695 .get_strings = bcm_phy_get_strings,1696 .get_stats = bcm54xx_get_stats,1697 .probe = bcm54xx_phy_probe,1698 .config_init = bcm54xx_config_init,1699 .config_intr = bcm_phy_config_intr,1700 .handle_interrupt = bcm_phy_handle_interrupt,1701 .link_change_notify = bcm54xx_link_change_notify,1702 .led_brightness_set = bcm_phy_led_brightness_set,1703}, {1704 .phy_id = PHY_ID_BCM89610,1705 .phy_id_mask = 0xfffffff0,1706 .name = "Broadcom BCM89610",1707 /* PHY_GBIT_FEATURES */1708 .get_sset_count = bcm_phy_get_sset_count,1709 .get_strings = bcm_phy_get_strings,1710 .get_stats = bcm54xx_get_stats,1711 .probe = bcm54xx_phy_probe,1712 .config_init = bcm54xx_config_init,1713 .config_intr = bcm_phy_config_intr,1714 .handle_interrupt = bcm_phy_handle_interrupt,1715 .link_change_notify = bcm54xx_link_change_notify,1716} };1717 1718module_phy_driver(broadcom_drivers);1719 1720static struct mdio_device_id __maybe_unused broadcom_tbl[] = {1721 { PHY_ID_BCM5411, 0xfffffff0 },1722 { PHY_ID_BCM5421, 0xfffffff0 },1723 { PHY_ID_BCM54210E, 0xfffffff0 },1724 { PHY_ID_BCM5461, 0xfffffff0 },1725 { PHY_ID_BCM54612E, 0xfffffff0 },1726 { PHY_ID_BCM54616S, 0xfffffff0 },1727 { PHY_ID_BCM5464, 0xfffffff0 },1728 { PHY_ID_BCM5481, 0xfffffff0 },1729 { PHY_ID_BCM54810, 0xfffffff0 },1730 { PHY_ID_BCM54811, 0xfffffff0 },1731 { PHY_ID_BCM5482, 0xfffffff0 },1732 { PHY_ID_BCM50610, 0xfffffff0 },1733 { PHY_ID_BCM50610M, 0xfffffff0 },1734 { PHY_ID_BCM57780, 0xfffffff0 },1735 { PHY_ID_BCMAC131, 0xfffffff0 },1736 { PHY_ID_BCM5221, 0xfffffff0 },1737 { PHY_ID_BCM5241, 0xfffffff0 },1738 { PHY_ID_BCM5395, 0xfffffff0 },1739 { PHY_ID_BCM53125, 0xfffffff0 },1740 { PHY_ID_BCM53128, 0xfffffff0 },1741 { PHY_ID_BCM89610, 0xfffffff0 },1742 { }1743};1744 1745MODULE_DEVICE_TABLE(mdio, broadcom_tbl);1746