1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * drivers/net/phy/broadcom.c 4 * 5 * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet 6 * transceivers. 7 * 8 * Copyright (c) 2006 Maciej W. Rozycki 9 * 10 * Inspired by code written by Amy Fong. 11 */ 12 13#include "bcm-phy-lib.h" 14#include <linux/delay.h> 15#include <linux/module.h> 16#include <linux/phy.h> 17#include <linux/brcmphy.h> 18#include <linux/of.h> 19 20#define BRCM_PHY_MODEL(phydev) \ 21 ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask) 22 23#define BRCM_PHY_REV(phydev) \ 24 ((phydev)->drv->phy_id & ~((phydev)->drv->phy_id_mask)) 25 26MODULE_DESCRIPTION("Broadcom PHY driver"); 27MODULE_AUTHOR("Maciej W. Rozycki"); 28MODULE_LICENSE("GPL"); 29 30static int bcm54xx_config_clock_delay(struct phy_device *phydev) 31{ 32 int rc, val; 33 34 /* handling PHY's internal RX clock delay */ 35 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 36 val |= MII_BCM54XX_AUXCTL_MISC_WREN; 37 if (phydev->interface == PHY_INTERFACE_MODE_RGMII || 38 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 39 /* Disable RGMII RXC-RXD skew */ 40 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN; 41 } 42 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 43 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 44 /* Enable RGMII RXC-RXD skew */ 45 val |= MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN; 46 } 47 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, 48 val); 49 if (rc < 0) 50 return rc; 51 52 /* handling PHY's internal TX clock delay */ 53 val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL); 54 if (phydev->interface == PHY_INTERFACE_MODE_RGMII || 55 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) { 56 /* Disable internal TX clock delay */ 57 val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN; 58 } 59 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || 60 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) { 61 /* Enable internal TX clock delay */ 62 val |= BCM54810_SHD_CLK_CTL_GTXCLK_EN; 63 } 64 rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val); 65 if (rc < 0) 66 return rc; 67 68 return 0; 69} 70 71static int bcm54210e_config_init(struct phy_device *phydev) 72{ 73 int val; 74 75 bcm54xx_config_clock_delay(phydev); 76 77 if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) { 78 val = phy_read(phydev, MII_CTRL1000); 79 val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER; 80 phy_write(phydev, MII_CTRL1000, val); 81 } 82 83 return 0; 84} 85 86static int bcm54612e_config_init(struct phy_device *phydev) 87{ 88 int reg; 89 90 bcm54xx_config_clock_delay(phydev); 91 92 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */ 93 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) { 94 int err; 95 96 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0); 97 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0, 98 BCM54612E_LED4_CLK125OUT_EN | reg); 99 100 if (err < 0) 101 return err; 102 } 103 104 return 0; 105} 106 107static int bcm54616s_config_init(struct phy_device *phydev) 108{ 109 int rc, val; 110 111 if (phydev->interface != PHY_INTERFACE_MODE_SGMII && 112 phydev->interface != PHY_INTERFACE_MODE_1000BASEX) 113 return 0; 114 115 /* Ensure proper interface mode is selected. */ 116 /* Disable RGMII mode */ 117 val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC); 118 if (val < 0) 119 return val; 120 val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_EN; 121 val |= MII_BCM54XX_AUXCTL_MISC_WREN; 122 rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, 123 val); 124 if (rc < 0) 125 return rc; 126 127 /* Select 1000BASE-X register set (primary SerDes) */ 128 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE); 129 if (val < 0) 130 return val; 131 val |= BCM54XX_SHD_MODE_1000BX; 132 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val); 133 if (rc < 0) 134 return rc; 135 136 /* Power down SerDes interface */ 137 rc = phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN); 138 if (rc < 0) 139 return rc; 140 141 /* Select proper interface mode */ 142 val &= ~BCM54XX_SHD_INTF_SEL_MASK; 143 val |= phydev->interface == PHY_INTERFACE_MODE_SGMII ? 144 BCM54XX_SHD_INTF_SEL_SGMII : 145 BCM54XX_SHD_INTF_SEL_GBIC; 146 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val); 147 if (rc < 0) 148 return rc; 149 150 /* Power up SerDes interface */ 151 rc = phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN); 152 if (rc < 0) 153 return rc; 154 155 /* Select copper register set */ 156 val &= ~BCM54XX_SHD_MODE_1000BX; 157 rc = bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, val); 158 if (rc < 0) 159 return rc; 160 161 /* Power up copper interface */ 162 return phy_clear_bits(phydev, MII_BMCR, BMCR_PDOWN); 163} 164 165/* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */ 166static int bcm50610_a0_workaround(struct phy_device *phydev) 167{ 168 int err; 169 170 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH0, 171 MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN | 172 MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF); 173 if (err < 0) 174 return err; 175 176 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_AADJ1CH3, 177 MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ); 178 if (err < 0) 179 return err; 180 181 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, 182 MII_BCM54XX_EXP_EXP75_VDACCTRL); 183 if (err < 0) 184 return err; 185 186 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP96, 187 MII_BCM54XX_EXP_EXP96_MYST); 188 if (err < 0) 189 return err; 190 191 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP97, 192 MII_BCM54XX_EXP_EXP97_MYST); 193 194 return err; 195} 196 197static int bcm54xx_phydsp_config(struct phy_device *phydev) 198{ 199 int err, err2; 200 201 /* Enable the SMDSP clock */ 202 err = bcm54xx_auxctl_write(phydev, 203 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 204 MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA | 205 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 206 if (err < 0) 207 return err; 208 209 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 210 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) { 211 /* Clear bit 9 to fix a phy interop issue. */ 212 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, 213 MII_BCM54XX_EXP_EXP08_RJCT_2MHZ); 214 if (err < 0) 215 goto error; 216 217 if (phydev->drv->phy_id == PHY_ID_BCM50610) { 218 err = bcm50610_a0_workaround(phydev); 219 if (err < 0) 220 goto error; 221 } 222 } 223 224 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM57780) { 225 int val; 226 227 val = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP75); 228 if (val < 0) 229 goto error; 230 231 val |= MII_BCM54XX_EXP_EXP75_CM_OSC; 232 err = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP75, val); 233 } 234 235error: 236 /* Disable the SMDSP clock */ 237 err2 = bcm54xx_auxctl_write(phydev, 238 MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL, 239 MII_BCM54XX_AUXCTL_ACTL_TX_6DB); 240 241 /* Return the first error reported. */ 242 return err ? err : err2; 243} 244 245static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) 246{ 247 u32 orig; 248 int val; 249 bool clk125en = true; 250 251 /* Abort if we are using an untested phy. */ 252 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM57780 && 253 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610 && 254 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM50610M && 255 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54810 && 256 BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811) 257 return; 258 259 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_SCR3); 260 if (val < 0) 261 return; 262 263 orig = val; 264 265 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 266 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 267 BRCM_PHY_REV(phydev) >= 0x3) { 268 /* 269 * Here, bit 0 _disables_ CLK125 when set. 270 * This bit is set by default. 271 */ 272 clk125en = false; 273 } else { 274 if (phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED) { 275 if (BRCM_PHY_MODEL(phydev) != PHY_ID_BCM54811) { 276 /* Here, bit 0 _enables_ CLK125 when set */ 277 val &= ~BCM54XX_SHD_SCR3_DEF_CLK125; 278 } 279 clk125en = false; 280 } 281 } 282 283 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 284 val &= ~BCM54XX_SHD_SCR3_DLLAPD_DIS; 285 else 286 val |= BCM54XX_SHD_SCR3_DLLAPD_DIS; 287 288 if (phydev->dev_flags & PHY_BRCM_DIS_TXCRXC_NOENRGY) { 289 if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810 || 290 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54811) 291 val |= BCM54810_SHD_SCR3_TRDDAPD; 292 else 293 val |= BCM54XX_SHD_SCR3_TRDDAPD; 294 } 295 296 if (orig != val) 297 bcm_phy_write_shadow(phydev, BCM54XX_SHD_SCR3, val); 298 299 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_APD); 300 if (val < 0) 301 return; 302 303 orig = val; 304 305 if (!clk125en || (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) 306 val |= BCM54XX_SHD_APD_EN; 307 else 308 val &= ~BCM54XX_SHD_APD_EN; 309 310 if (orig != val) 311 bcm_phy_write_shadow(phydev, BCM54XX_SHD_APD, val); 312} 313 314static int bcm54xx_config_init(struct phy_device *phydev) 315{ 316 int reg, err, val; 317 318 reg = phy_read(phydev, MII_BCM54XX_ECR); 319 if (reg < 0) 320 return reg; 321 322 /* Mask interrupts globally. */ 323 reg |= MII_BCM54XX_ECR_IM; 324 err = phy_write(phydev, MII_BCM54XX_ECR, reg); 325 if (err < 0) 326 return err; 327 328 /* Unmask events we are interested in. */ 329 reg = ~(MII_BCM54XX_INT_DUPLEX | 330 MII_BCM54XX_INT_SPEED | 331 MII_BCM54XX_INT_LINK); 332 err = phy_write(phydev, MII_BCM54XX_IMR, reg); 333 if (err < 0) 334 return err; 335 336 if ((BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610 || 337 BRCM_PHY_MODEL(phydev) == PHY_ID_BCM50610M) && 338 (phydev->dev_flags & PHY_BRCM_CLEAR_RGMII_MODE)) 339 bcm_phy_write_shadow(phydev, BCM54XX_SHD_RGMII_MODE, 0); 340 341 bcm54xx_adjust_rxrefclk(phydev); 342 343 switch (BRCM_PHY_MODEL(phydev)) { 344 case PHY_ID_BCM50610: 345 case PHY_ID_BCM50610M: 346 err = bcm54xx_config_clock_delay(phydev); 347 break; 348 case PHY_ID_BCM54210E: 349 err = bcm54210e_config_init(phydev); 350 break; 351 case PHY_ID_BCM54612E: 352 err = bcm54612e_config_init(phydev); 353 break; 354 case PHY_ID_BCM54616S: 355 err = bcm54616s_config_init(phydev); 356 break; 357 case PHY_ID_BCM54810: 358 /* For BCM54810, we need to disable BroadR-Reach function */ 359 val = bcm_phy_read_exp(phydev, 360 BCM54810_EXP_BROADREACH_LRE_MISC_CTL); 361 val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; 362 err = bcm_phy_write_exp(phydev, 363 BCM54810_EXP_BROADREACH_LRE_MISC_CTL, 364 val); 365 break; 366 } 367 if (err) 368 return err; 369 370 bcm54xx_phydsp_config(phydev); 371 372 /* Encode link speed into LED1 and LED3 pair (green/amber). 373 * Also flash these two LEDs on activity. This means configuring 374 * them for MULTICOLOR and encoding link/activity into them. 375 */ 376 val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | 377 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); 378 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val); 379 380 val = BCM_LED_MULTICOLOR_IN_PHASE | 381 BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | 382 BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); 383 bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); 384 385 return 0; 386} 387 388static int bcm54xx_resume(struct phy_device *phydev) 389{ 390 int ret; 391 392 /* Writes to register other than BMCR would be ignored 393 * unless we clear the PDOWN bit first 394 */ 395 ret = genphy_resume(phydev); 396 if (ret < 0) 397 return ret; 398 399 /* Upon exiting power down, the PHY remains in an internal reset state 400 * for 40us 401 */ 402 fsleep(40); 403 404 return bcm54xx_config_init(phydev); 405} 406 407static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum) 408{ 409 return -EOPNOTSUPP; 410} 411 412static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum, 413 u16 val) 414{ 415 return -EOPNOTSUPP; 416} 417 418static int bcm54811_config_init(struct phy_device *phydev) 419{ 420 int err, reg; 421 422 /* Disable BroadR-Reach function. */ 423 reg = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL); 424 reg &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN; 425 err = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL, 426 reg); 427 if (err < 0) 428 return err; 429 430 err = bcm54xx_config_init(phydev); 431 432 /* Enable CLK125 MUX on LED4 if ref clock is enabled. */ 433 if (!(phydev->dev_flags & PHY_BRCM_RX_REFCLK_UNUSED)) { 434 reg = bcm_phy_read_exp(phydev, BCM54612E_EXP_SPARE0); 435 err = bcm_phy_write_exp(phydev, BCM54612E_EXP_SPARE0, 436 BCM54612E_LED4_CLK125OUT_EN | reg); 437 if (err < 0) 438 return err; 439 } 440 441 return err; 442} 443 444static int bcm5482_config_init(struct phy_device *phydev) 445{ 446 int err, reg; 447 448 err = bcm54xx_config_init(phydev); 449 450 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 451 /* 452 * Enable secondary SerDes and its use as an LED source 453 */ 454 reg = bcm_phy_read_shadow(phydev, BCM5482_SHD_SSD); 455 bcm_phy_write_shadow(phydev, BCM5482_SHD_SSD, 456 reg | 457 BCM5482_SHD_SSD_LEDM | 458 BCM5482_SHD_SSD_EN); 459 460 /* 461 * Enable SGMII slave mode and auto-detection 462 */ 463 reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD; 464 err = bcm_phy_read_exp(phydev, reg); 465 if (err < 0) 466 return err; 467 err = bcm_phy_write_exp(phydev, reg, err | 468 BCM5482_SSD_SGMII_SLAVE_EN | 469 BCM5482_SSD_SGMII_SLAVE_AD); 470 if (err < 0) 471 return err; 472 473 /* 474 * Disable secondary SerDes powerdown 475 */ 476 reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD; 477 err = bcm_phy_read_exp(phydev, reg); 478 if (err < 0) 479 return err; 480 err = bcm_phy_write_exp(phydev, reg, 481 err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN); 482 if (err < 0) 483 return err; 484 485 /* 486 * Select 1000BASE-X register set (primary SerDes) 487 */ 488 reg = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE); 489 bcm_phy_write_shadow(phydev, BCM54XX_SHD_MODE, 490 reg | BCM54XX_SHD_MODE_1000BX); 491 492 /* 493 * LED1=ACTIVITYLED, LED3=LINKSPD[2] 494 * (Use LED1 as secondary SerDes ACTIVITY LED) 495 */ 496 bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, 497 BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_ACTIVITYLED) | 498 BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_LINKSPD2)); 499 500 /* 501 * Auto-negotiation doesn't seem to work quite right 502 * in this mode, so we disable it and force it to the 503 * right speed/duplex setting. Only 'link status' 504 * is important. 505 */ 506 phydev->autoneg = AUTONEG_DISABLE; 507 phydev->speed = SPEED_1000; 508 phydev->duplex = DUPLEX_FULL; 509 } 510 511 return err; 512} 513 514static int bcm5482_read_status(struct phy_device *phydev) 515{ 516 int err; 517 518 err = genphy_read_status(phydev); 519 520 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) { 521 /* 522 * Only link status matters for 1000Base-X mode, so force 523 * 1000 Mbit/s full-duplex status 524 */ 525 if (phydev->link) { 526 phydev->speed = SPEED_1000; 527 phydev->duplex = DUPLEX_FULL; 528 } 529 } 530 531 return err; 532} 533 534static int bcm5481_config_aneg(struct phy_device *phydev) 535{ 536 struct device_node *np = phydev->mdio.dev.of_node; 537 int ret; 538 539 /* Aneg firstly. */ 540 ret = genphy_config_aneg(phydev); 541 542 /* Then we can set up the delay. */ 543 bcm54xx_config_clock_delay(phydev); 544 545 if (of_property_read_bool(np, "enet-phy-lane-swap")) { 546 /* Lane Swap - Undocumented register...magic! */ 547 ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9, 548 0x11B); 549 if (ret < 0) 550 return ret; 551 } 552 553 return ret; 554} 555 556static int bcm54616s_probe(struct phy_device *phydev) 557{ 558 int val; 559 560 val = bcm_phy_read_shadow(phydev, BCM54XX_SHD_MODE); 561 if (val < 0) 562 return val; 563 564 /* The PHY is strapped in RGMII-fiber mode when INTERF_SEL[1:0] 565 * is 01b, and the link between PHY and its link partner can be 566 * either 1000Base-X or 100Base-FX. 567 * RGMII-1000Base-X is properly supported, but RGMII-100Base-FX 568 * support is still missing as of now. 569 */ 570 if ((val & BCM54XX_SHD_INTF_SEL_MASK) == BCM54XX_SHD_INTF_SEL_RGMII) { 571 val = bcm_phy_read_shadow(phydev, BCM54616S_SHD_100FX_CTRL); 572 if (val < 0) 573 return val; 574 575 /* Bit 0 of the SerDes 100-FX Control register, when set 576 * to 1, sets the MII/RGMII -> 100BASE-FX configuration. 577 * When this bit is set to 0, it sets the GMII/RGMII -> 578 * 1000BASE-X configuration. 579 */ 580 if (!(val & BCM54616S_100FX_MODE)) 581 phydev->dev_flags |= PHY_BCM_FLAGS_MODE_1000BX; 582 583 phydev->port = PORT_FIBRE; 584 } 585 586 return 0; 587} 588 589static int bcm54616s_config_aneg(struct phy_device *phydev) 590{ 591 int ret; 592 593 /* Aneg firstly. */ 594 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) 595 ret = genphy_c37_config_aneg(phydev); 596 else 597 ret = genphy_config_aneg(phydev); 598 599 /* Then we can set up the delay. */ 600 bcm54xx_config_clock_delay(phydev); 601 602 return ret; 603} 604 605static int bcm54616s_read_status(struct phy_device *phydev) 606{ 607 int err; 608 609 if (phydev->dev_flags & PHY_BCM_FLAGS_MODE_1000BX) 610 err = genphy_c37_read_status(phydev); 611 else 612 err = genphy_read_status(phydev); 613 614 return err; 615} 616 617static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set) 618{ 619 int val; 620 621 val = phy_read(phydev, reg); 622 if (val < 0) 623 return val; 624 625 return phy_write(phydev, reg, val | set); 626} 627 628static int brcm_fet_config_init(struct phy_device *phydev) 629{ 630 int reg, err, err2, brcmtest; 631 632 /* Reset the PHY to bring it to a known state. */ 633 err = phy_write(phydev, MII_BMCR, BMCR_RESET); 634 if (err < 0) 635 return err; 636 637 /* The datasheet indicates the PHY needs up to 1us to complete a reset, 638 * build some slack here. 639 */ 640 usleep_range(1000, 2000); 641 642 /* The PHY requires 65 MDC clock cycles to complete a write operation 643 * and turnaround the line properly. 644 * 645 * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac) 646 * may flag the lack of turn-around as a read failure. This is 647 * particularly true with this combination since the MDIO controller 648 * only used 64 MDC cycles. This is not a critical failure in this 649 * specific case and it has no functional impact otherwise, so we let 650 * that one go through. If there is a genuine bus error, the next read 651 * of MII_BRCM_FET_INTREG will error out. 652 */ 653 err = phy_read(phydev, MII_BMCR); 654 if (err < 0 && err != -EIO) 655 return err; 656 657 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 658 if (reg < 0) 659 return reg; 660 661 /* Unmask events we are interested in and mask interrupts globally. */ 662 reg = MII_BRCM_FET_IR_DUPLEX_EN | 663 MII_BRCM_FET_IR_SPEED_EN | 664 MII_BRCM_FET_IR_LINK_EN | 665 MII_BRCM_FET_IR_ENABLE | 666 MII_BRCM_FET_IR_MASK; 667 668 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 669 if (err < 0) 670 return err; 671 672 /* Enable shadow register access */ 673 brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST); 674 if (brcmtest < 0) 675 return brcmtest; 676 677 reg = brcmtest | MII_BRCM_FET_BT_SRE; 678 679 err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg); 680 if (err < 0) 681 return err; 682 683 /* Set the LED mode */ 684 reg = phy_read(phydev, MII_BRCM_FET_SHDW_AUXMODE4); 685 if (reg < 0) { 686 err = reg; 687 goto done; 688 } 689 690 reg &= ~MII_BRCM_FET_SHDW_AM4_LED_MASK; 691 reg |= MII_BRCM_FET_SHDW_AM4_LED_MODE1; 692 693 err = phy_write(phydev, MII_BRCM_FET_SHDW_AUXMODE4, reg); 694 if (err < 0) 695 goto done; 696 697 /* Enable auto MDIX */ 698 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_MISCCTRL, 699 MII_BRCM_FET_SHDW_MC_FAME); 700 if (err < 0) 701 goto done; 702 703 if (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE) { 704 /* Enable auto power down */ 705 err = brcm_phy_setbits(phydev, MII_BRCM_FET_SHDW_AUXSTAT2, 706 MII_BRCM_FET_SHDW_AS2_APDE); 707 } 708 709done: 710 /* Disable shadow register access */ 711 err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest); 712 if (!err) 713 err = err2; 714 715 return err; 716} 717 718static int brcm_fet_ack_interrupt(struct phy_device *phydev) 719{ 720 int reg; 721 722 /* Clear pending interrupts. */ 723 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 724 if (reg < 0) 725 return reg; 726 727 return 0; 728} 729 730static int brcm_fet_config_intr(struct phy_device *phydev) 731{ 732 int reg, err; 733 734 reg = phy_read(phydev, MII_BRCM_FET_INTREG); 735 if (reg < 0) 736 return reg; 737 738 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 739 reg &= ~MII_BRCM_FET_IR_MASK; 740 else 741 reg |= MII_BRCM_FET_IR_MASK; 742 743 err = phy_write(phydev, MII_BRCM_FET_INTREG, reg); 744 return err; 745} 746 747struct bcm53xx_phy_priv { 748 u64 *stats; 749}; 750 751static int bcm53xx_phy_probe(struct phy_device *phydev) 752{ 753 struct bcm53xx_phy_priv *priv; 754 755 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL); 756 if (!priv) 757 return -ENOMEM; 758 759 phydev->priv = priv; 760 761 priv->stats = devm_kcalloc(&phydev->mdio.dev, 762 bcm_phy_get_sset_count(phydev), sizeof(u64), 763 GFP_KERNEL); 764 if (!priv->stats) 765 return -ENOMEM; 766 767 return 0; 768} 769 770static void bcm53xx_phy_get_stats(struct phy_device *phydev, 771 struct ethtool_stats *stats, u64 *data) 772{ 773 struct bcm53xx_phy_priv *priv = phydev->priv; 774 775 bcm_phy_get_stats(phydev, priv->stats, stats, data); 776} 777 778static struct phy_driver broadcom_drivers[] = { 779{ 780 .phy_id = PHY_ID_BCM5411, 781 .phy_id_mask = 0xfffffff0, 782 .name = "Broadcom BCM5411", 783 /* PHY_GBIT_FEATURES */ 784 .config_init = bcm54xx_config_init, 785 .ack_interrupt = bcm_phy_ack_intr, 786 .config_intr = bcm_phy_config_intr, 787}, { 788 .phy_id = PHY_ID_BCM5421, 789 .phy_id_mask = 0xfffffff0, 790 .name = "Broadcom BCM5421", 791 /* PHY_GBIT_FEATURES */ 792 .config_init = bcm54xx_config_init, 793 .ack_interrupt = bcm_phy_ack_intr, 794 .config_intr = bcm_phy_config_intr, 795}, { 796 .phy_id = PHY_ID_BCM54210E, 797 .phy_id_mask = 0xfffffff0, 798 .name = "Broadcom BCM54210E", 799 /* PHY_GBIT_FEATURES */ 800 .config_init = bcm54xx_config_init, 801 .ack_interrupt = bcm_phy_ack_intr, 802 .config_intr = bcm_phy_config_intr, 803}, { 804 .phy_id = PHY_ID_BCM5461, 805 .phy_id_mask = 0xfffffff0, 806 .name = "Broadcom BCM5461", 807 /* PHY_GBIT_FEATURES */ 808 .config_init = bcm54xx_config_init, 809 .ack_interrupt = bcm_phy_ack_intr, 810 .config_intr = bcm_phy_config_intr, 811}, { 812 .phy_id = PHY_ID_BCM54612E, 813 .phy_id_mask = 0xfffffff0, 814 .name = "Broadcom BCM54612E", 815 /* PHY_GBIT_FEATURES */ 816 .config_init = bcm54xx_config_init, 817 .ack_interrupt = bcm_phy_ack_intr, 818 .config_intr = bcm_phy_config_intr, 819}, { 820 .phy_id = PHY_ID_BCM54616S, 821 .phy_id_mask = 0xfffffff0, 822 .name = "Broadcom BCM54616S", 823 /* PHY_GBIT_FEATURES */ 824 .soft_reset = genphy_soft_reset, 825 .config_init = bcm54xx_config_init, 826 .config_aneg = bcm54616s_config_aneg, 827 .ack_interrupt = bcm_phy_ack_intr, 828 .config_intr = bcm_phy_config_intr, 829 .read_status = bcm54616s_read_status, 830 .probe = bcm54616s_probe, 831}, { 832 .phy_id = PHY_ID_BCM5464, 833 .phy_id_mask = 0xfffffff0, 834 .name = "Broadcom BCM5464", 835 /* PHY_GBIT_FEATURES */ 836 .config_init = bcm54xx_config_init, 837 .ack_interrupt = bcm_phy_ack_intr, 838 .config_intr = bcm_phy_config_intr, 839 .suspend = genphy_suspend, 840 .resume = genphy_resume, 841}, { 842 .phy_id = PHY_ID_BCM5481, 843 .phy_id_mask = 0xfffffff0, 844 .name = "Broadcom BCM5481", 845 /* PHY_GBIT_FEATURES */ 846 .config_init = bcm54xx_config_init, 847 .config_aneg = bcm5481_config_aneg, 848 .ack_interrupt = bcm_phy_ack_intr, 849 .config_intr = bcm_phy_config_intr, 850}, { 851 .phy_id = PHY_ID_BCM54810, 852 .phy_id_mask = 0xfffffff0, 853 .name = "Broadcom BCM54810", 854 /* PHY_GBIT_FEATURES */ 855 .read_mmd = bcm54810_read_mmd, 856 .write_mmd = bcm54810_write_mmd, 857 .config_init = bcm54xx_config_init, 858 .config_aneg = bcm5481_config_aneg, 859 .ack_interrupt = bcm_phy_ack_intr, 860 .config_intr = bcm_phy_config_intr, 861 .suspend = genphy_suspend, 862 .resume = bcm54xx_resume, 863}, { 864 .phy_id = PHY_ID_BCM54811, 865 .phy_id_mask = 0xfffffff0, 866 .name = "Broadcom BCM54811", 867 /* PHY_GBIT_FEATURES */ 868 .config_init = bcm54811_config_init, 869 .config_aneg = bcm5481_config_aneg, 870 .ack_interrupt = bcm_phy_ack_intr, 871 .config_intr = bcm_phy_config_intr, 872 .suspend = genphy_suspend, 873 .resume = bcm54xx_resume, 874}, { 875 .phy_id = PHY_ID_BCM5482, 876 .phy_id_mask = 0xfffffff0, 877 .name = "Broadcom BCM5482", 878 /* PHY_GBIT_FEATURES */ 879 .config_init = bcm5482_config_init, 880 .read_status = bcm5482_read_status, 881 .ack_interrupt = bcm_phy_ack_intr, 882 .config_intr = bcm_phy_config_intr, 883}, { 884 .phy_id = PHY_ID_BCM50610, 885 .phy_id_mask = 0xfffffff0, 886 .name = "Broadcom BCM50610", 887 /* PHY_GBIT_FEATURES */ 888 .config_init = bcm54xx_config_init, 889 .ack_interrupt = bcm_phy_ack_intr, 890 .config_intr = bcm_phy_config_intr, 891}, { 892 .phy_id = PHY_ID_BCM50610M, 893 .phy_id_mask = 0xfffffff0, 894 .name = "Broadcom BCM50610M", 895 /* PHY_GBIT_FEATURES */ 896 .config_init = bcm54xx_config_init, 897 .ack_interrupt = bcm_phy_ack_intr, 898 .config_intr = bcm_phy_config_intr, 899}, { 900 .phy_id = PHY_ID_BCM57780, 901 .phy_id_mask = 0xfffffff0, 902 .name = "Broadcom BCM57780", 903 /* PHY_GBIT_FEATURES */ 904 .config_init = bcm54xx_config_init, 905 .ack_interrupt = bcm_phy_ack_intr, 906 .config_intr = bcm_phy_config_intr, 907}, { 908 .phy_id = PHY_ID_BCMAC131, 909 .phy_id_mask = 0xfffffff0, 910 .name = "Broadcom BCMAC131", 911 /* PHY_BASIC_FEATURES */ 912 .config_init = brcm_fet_config_init, 913 .ack_interrupt = brcm_fet_ack_interrupt, 914 .config_intr = brcm_fet_config_intr, 915}, { 916 .phy_id = PHY_ID_BCM5241, 917 .phy_id_mask = 0xfffffff0, 918 .name = "Broadcom BCM5241", 919 /* PHY_BASIC_FEATURES */ 920 .config_init = brcm_fet_config_init, 921 .ack_interrupt = brcm_fet_ack_interrupt, 922 .config_intr = brcm_fet_config_intr, 923}, { 924 .phy_id = PHY_ID_BCM5395, 925 .phy_id_mask = 0xfffffff0, 926 .name = "Broadcom BCM5395", 927 .flags = PHY_IS_INTERNAL, 928 /* PHY_GBIT_FEATURES */ 929 .get_sset_count = bcm_phy_get_sset_count, 930 .get_strings = bcm_phy_get_strings, 931 .get_stats = bcm53xx_phy_get_stats, 932 .probe = bcm53xx_phy_probe, 933}, { 934 .phy_id = PHY_ID_BCM53125, 935 .phy_id_mask = 0xfffffff0, 936 .name = "Broadcom BCM53125", 937 .flags = PHY_IS_INTERNAL, 938 /* PHY_GBIT_FEATURES */ 939 .get_sset_count = bcm_phy_get_sset_count, 940 .get_strings = bcm_phy_get_strings, 941 .get_stats = bcm53xx_phy_get_stats, 942 .probe = bcm53xx_phy_probe, 943 .config_init = bcm54xx_config_init, 944 .ack_interrupt = bcm_phy_ack_intr, 945 .config_intr = bcm_phy_config_intr, 946}, { 947 .phy_id = PHY_ID_BCM89610, 948 .phy_id_mask = 0xfffffff0, 949 .name = "Broadcom BCM89610", 950 /* PHY_GBIT_FEATURES */ 951 .config_init = bcm54xx_config_init, 952 .ack_interrupt = bcm_phy_ack_intr, 953 .config_intr = bcm_phy_config_intr, 954} }; 955 956module_phy_driver(broadcom_drivers); 957 958static struct mdio_device_id __maybe_unused broadcom_tbl[] = { 959 { PHY_ID_BCM5411, 0xfffffff0 }, 960 { PHY_ID_BCM5421, 0xfffffff0 }, 961 { PHY_ID_BCM54210E, 0xfffffff0 }, 962 { PHY_ID_BCM5461, 0xfffffff0 }, 963 { PHY_ID_BCM54612E, 0xfffffff0 }, 964 { PHY_ID_BCM54616S, 0xfffffff0 }, 965 { PHY_ID_BCM5464, 0xfffffff0 }, 966 { PHY_ID_BCM5481, 0xfffffff0 }, 967 { PHY_ID_BCM54810, 0xfffffff0 }, 968 { PHY_ID_BCM54811, 0xfffffff0 }, 969 { PHY_ID_BCM5482, 0xfffffff0 }, 970 { PHY_ID_BCM50610, 0xfffffff0 }, 971 { PHY_ID_BCM50610M, 0xfffffff0 }, 972 { PHY_ID_BCM57780, 0xfffffff0 }, 973 { PHY_ID_BCMAC131, 0xfffffff0 }, 974 { PHY_ID_BCM5241, 0xfffffff0 }, 975 { PHY_ID_BCM5395, 0xfffffff0 }, 976 { PHY_ID_BCM53125, 0xfffffff0 }, 977 { PHY_ID_BCM89610, 0xfffffff0 }, 978 { } 979}; 980 981MODULE_DEVICE_TABLE(mdio, broadcom_tbl); 982