1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * PHY drivers for the sungem ethernet driver. 4 * 5 * This file could be shared with other drivers. 6 * 7 * (c) 2002-2007, Benjamin Herrenscmidt (benh@kernel.crashing.org) 8 * 9 * TODO: 10 * - Add support for PHYs that provide an IRQ line 11 * - Eventually moved the entire polling state machine in 12 * there (out of the eth driver), so that it can easily be 13 * skipped on PHYs that implement it in hardware. 14 * - On LXT971 & BCM5201, Apple uses some chip specific regs 15 * to read the link status. Figure out why and if it makes 16 * sense to do the same (magic aneg ?) 17 * - Apple has some additional power management code for some 18 * Broadcom PHYs that they "hide" from the OpenSource version 19 * of darwin, still need to reverse engineer that 20 */ 21 22 23 #include <linux/module.h> 24 25 #include <linux/kernel.h> 26 #include <linux/types.h> 27 #include <linux/netdevice.h> 28 #include <linux/etherdevice.h> 29 #include <linux/mii.h> 30 #include <linux/ethtool.h> 31 #include <linux/delay.h> 32 #include <linux/of.h> 33 #include <linux/sungem_phy.h> 34 35 /* Link modes of the BCM5400 PHY */ 36 static const int phy_BCM5400_link_table[8][3] = { 37 { 0, 0, 0 }, /* No link */ 38 { 0, 0, 0 }, /* 10BT Half Duplex */ 39 { 1, 0, 0 }, /* 10BT Full Duplex */ 40 { 0, 1, 0 }, /* 100BT Half Duplex */ 41 { 0, 1, 0 }, /* 100BT Half Duplex */ 42 { 1, 1, 0 }, /* 100BT Full Duplex*/ 43 { 1, 0, 1 }, /* 1000BT */ 44 { 1, 0, 1 }, /* 1000BT */ 45 }; 46 47 static inline int __sungem_phy_read(struct mii_phy* phy, int id, int reg) 48 { 49 return phy->mdio_read(phy->dev, id, reg); 50 } 51 52 static inline void __sungem_phy_write(struct mii_phy* phy, int id, int reg, int val) 53 { 54 phy->mdio_write(phy->dev, id, reg, val); 55 } 56 57 static inline int sungem_phy_read(struct mii_phy* phy, int reg) 58 { 59 return phy->mdio_read(phy->dev, phy->mii_id, reg); 60 } 61 62 static inline void sungem_phy_write(struct mii_phy* phy, int reg, int val) 63 { 64 phy->mdio_write(phy->dev, phy->mii_id, reg, val); 65 } 66 67 static int reset_one_mii_phy(struct mii_phy* phy, int phy_id) 68 { 69 u16 val; 70 int limit = 10000; 71 72 val = __sungem_phy_read(phy, phy_id, MII_BMCR); 73 val &= ~(BMCR_ISOLATE | BMCR_PDOWN); 74 val |= BMCR_RESET; 75 __sungem_phy_write(phy, phy_id, MII_BMCR, val); 76 77 udelay(100); 78 79 while (--limit) { 80 val = __sungem_phy_read(phy, phy_id, MII_BMCR); 81 if ((val & BMCR_RESET) == 0) 82 break; 83 udelay(10); 84 } 85 if ((val & BMCR_ISOLATE) && limit > 0) 86 __sungem_phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE); 87 88 return limit <= 0; 89 } 90 91 static int bcm5201_init(struct mii_phy* phy) 92 { 93 u16 data; 94 95 data = sungem_phy_read(phy, MII_BCM5201_MULTIPHY); 96 data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE; 97 sungem_phy_write(phy, MII_BCM5201_MULTIPHY, data); 98 99 sungem_phy_write(phy, MII_BCM5201_INTERRUPT, 0); 100 101 return 0; 102 } 103 104 static int bcm5201_suspend(struct mii_phy* phy) 105 { 106 sungem_phy_write(phy, MII_BCM5201_INTERRUPT, 0); 107 sungem_phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE); 108 109 return 0; 110 } 111 112 static int bcm5221_init(struct mii_phy* phy) 113 { 114 u16 data; 115 116 data = sungem_phy_read(phy, MII_BCM5221_TEST); 117 sungem_phy_write(phy, MII_BCM5221_TEST, 118 data | MII_BCM5221_TEST_ENABLE_SHADOWS); 119 120 data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2); 121 sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2, 122 data | MII_BCM5221_SHDOW_AUX_STAT2_APD); 123 124 data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4); 125 sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4, 126 data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR); 127 128 data = sungem_phy_read(phy, MII_BCM5221_TEST); 129 sungem_phy_write(phy, MII_BCM5221_TEST, 130 data & ~MII_BCM5221_TEST_ENABLE_SHADOWS); 131 132 return 0; 133 } 134 135 static int bcm5221_suspend(struct mii_phy* phy) 136 { 137 u16 data; 138 139 data = sungem_phy_read(phy, MII_BCM5221_TEST); 140 sungem_phy_write(phy, MII_BCM5221_TEST, 141 data | MII_BCM5221_TEST_ENABLE_SHADOWS); 142 143 data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4); 144 sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4, 145 data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE); 146 147 return 0; 148 } 149 150 static int bcm5241_init(struct mii_phy* phy) 151 { 152 u16 data; 153 154 data = sungem_phy_read(phy, MII_BCM5221_TEST); 155 sungem_phy_write(phy, MII_BCM5221_TEST, 156 data | MII_BCM5221_TEST_ENABLE_SHADOWS); 157 158 data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2); 159 sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2, 160 data | MII_BCM5221_SHDOW_AUX_STAT2_APD); 161 162 data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4); 163 sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4, 164 data & ~MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR); 165 166 data = sungem_phy_read(phy, MII_BCM5221_TEST); 167 sungem_phy_write(phy, MII_BCM5221_TEST, 168 data & ~MII_BCM5221_TEST_ENABLE_SHADOWS); 169 170 return 0; 171 } 172 173 static int bcm5241_suspend(struct mii_phy* phy) 174 { 175 u16 data; 176 177 data = sungem_phy_read(phy, MII_BCM5221_TEST); 178 sungem_phy_write(phy, MII_BCM5221_TEST, 179 data | MII_BCM5221_TEST_ENABLE_SHADOWS); 180 181 data = sungem_phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4); 182 sungem_phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4, 183 data | MII_BCM5241_SHDOW_AUX_MODE4_STANDBYPWR); 184 185 return 0; 186 } 187 188 static int bcm5400_init(struct mii_phy* phy) 189 { 190 u16 data; 191 192 /* Configure for gigabit full duplex */ 193 data = sungem_phy_read(phy, MII_BCM5400_AUXCONTROL); 194 data |= MII_BCM5400_AUXCONTROL_PWR10BASET; 195 sungem_phy_write(phy, MII_BCM5400_AUXCONTROL, data); 196 197 data = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL); 198 data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; 199 sungem_phy_write(phy, MII_BCM5400_GB_CONTROL, data); 200 201 udelay(100); 202 203 /* Reset and configure cascaded 10/100 PHY */ 204 (void)reset_one_mii_phy(phy, 0x1f); 205 206 data = __sungem_phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY); 207 data |= MII_BCM5201_MULTIPHY_SERIALMODE; 208 __sungem_phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data); 209 210 data = sungem_phy_read(phy, MII_BCM5400_AUXCONTROL); 211 data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET; 212 sungem_phy_write(phy, MII_BCM5400_AUXCONTROL, data); 213 214 return 0; 215 } 216 217 static int bcm5400_suspend(struct mii_phy* phy) 218 { 219 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */ 220 sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN); 221 #endif 222 return 0; 223 } 224 225 static int bcm5401_init(struct mii_phy* phy) 226 { 227 u16 data; 228 int rev; 229 230 rev = sungem_phy_read(phy, MII_PHYSID2) & 0x000f; 231 if (rev == 0 || rev == 3) { 232 /* Some revisions of 5401 appear to need this 233 * initialisation sequence to disable, according 234 * to OF, "tap power management" 235 * 236 * WARNING ! OF and Darwin don't agree on the 237 * register addresses. OF seem to interpret the 238 * register numbers below as decimal 239 * 240 * Note: This should (and does) match tg3_init_5401phy_dsp 241 * in the tg3.c driver. -DaveM 242 */ 243 sungem_phy_write(phy, 0x18, 0x0c20); 244 sungem_phy_write(phy, 0x17, 0x0012); 245 sungem_phy_write(phy, 0x15, 0x1804); 246 sungem_phy_write(phy, 0x17, 0x0013); 247 sungem_phy_write(phy, 0x15, 0x1204); 248 sungem_phy_write(phy, 0x17, 0x8006); 249 sungem_phy_write(phy, 0x15, 0x0132); 250 sungem_phy_write(phy, 0x17, 0x8006); 251 sungem_phy_write(phy, 0x15, 0x0232); 252 sungem_phy_write(phy, 0x17, 0x201f); 253 sungem_phy_write(phy, 0x15, 0x0a20); 254 } 255 256 /* Configure for gigabit full duplex */ 257 data = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL); 258 data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; 259 sungem_phy_write(phy, MII_BCM5400_GB_CONTROL, data); 260 261 udelay(10); 262 263 /* Reset and configure cascaded 10/100 PHY */ 264 (void)reset_one_mii_phy(phy, 0x1f); 265 266 data = __sungem_phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY); 267 data |= MII_BCM5201_MULTIPHY_SERIALMODE; 268 __sungem_phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data); 269 270 return 0; 271 } 272 273 static int bcm5401_suspend(struct mii_phy* phy) 274 { 275 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */ 276 sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN); 277 #endif 278 return 0; 279 } 280 281 static int bcm5411_init(struct mii_phy* phy) 282 { 283 u16 data; 284 285 /* Here's some more Apple black magic to setup 286 * some voltage stuffs. 287 */ 288 sungem_phy_write(phy, 0x1c, 0x8c23); 289 sungem_phy_write(phy, 0x1c, 0x8ca3); 290 sungem_phy_write(phy, 0x1c, 0x8c23); 291 292 /* Here, Apple seems to want to reset it, do 293 * it as well 294 */ 295 sungem_phy_write(phy, MII_BMCR, BMCR_RESET); 296 sungem_phy_write(phy, MII_BMCR, 0x1340); 297 298 data = sungem_phy_read(phy, MII_BCM5400_GB_CONTROL); 299 data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; 300 sungem_phy_write(phy, MII_BCM5400_GB_CONTROL, data); 301 302 udelay(10); 303 304 /* Reset and configure cascaded 10/100 PHY */ 305 (void)reset_one_mii_phy(phy, 0x1f); 306 307 return 0; 308 } 309 310 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) 311 { 312 u16 ctl, adv; 313 314 phy->autoneg = 1; 315 phy->speed = SPEED_10; 316 phy->duplex = DUPLEX_HALF; 317 phy->pause = 0; 318 phy->advertising = advertise; 319 320 /* Setup standard advertise */ 321 adv = sungem_phy_read(phy, MII_ADVERTISE); 322 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); 323 if (advertise & ADVERTISED_10baseT_Half) 324 adv |= ADVERTISE_10HALF; 325 if (advertise & ADVERTISED_10baseT_Full) 326 adv |= ADVERTISE_10FULL; 327 if (advertise & ADVERTISED_100baseT_Half) 328 adv |= ADVERTISE_100HALF; 329 if (advertise & ADVERTISED_100baseT_Full) 330 adv |= ADVERTISE_100FULL; 331 sungem_phy_write(phy, MII_ADVERTISE, adv); 332 333 /* Start/Restart aneg */ 334 ctl = sungem_phy_read(phy, MII_BMCR); 335 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); 336 sungem_phy_write(phy, MII_BMCR, ctl); 337 338 return 0; 339 } 340 341 static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd) 342 { 343 u16 ctl; 344 345 phy->autoneg = 0; 346 phy->speed = speed; 347 phy->duplex = fd; 348 phy->pause = 0; 349 350 ctl = sungem_phy_read(phy, MII_BMCR); 351 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE); 352 353 /* First reset the PHY */ 354 sungem_phy_write(phy, MII_BMCR, ctl | BMCR_RESET); 355 356 /* Select speed & duplex */ 357 switch(speed) { 358 case SPEED_10: 359 break; 360 case SPEED_100: 361 ctl |= BMCR_SPEED100; 362 break; 363 case SPEED_1000: 364 default: 365 return -EINVAL; 366 } 367 if (fd == DUPLEX_FULL) 368 ctl |= BMCR_FULLDPLX; 369 sungem_phy_write(phy, MII_BMCR, ctl); 370 371 return 0; 372 } 373 374 static int genmii_poll_link(struct mii_phy *phy) 375 { 376 u16 status; 377 378 (void)sungem_phy_read(phy, MII_BMSR); 379 status = sungem_phy_read(phy, MII_BMSR); 380 if ((status & BMSR_LSTATUS) == 0) 381 return 0; 382 if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE)) 383 return 0; 384 return 1; 385 } 386 387 static int genmii_read_link(struct mii_phy *phy) 388 { 389 u16 lpa; 390 391 if (phy->autoneg) { 392 lpa = sungem_phy_read(phy, MII_LPA); 393 394 if (lpa & (LPA_10FULL | LPA_100FULL)) 395 phy->duplex = DUPLEX_FULL; 396 else 397 phy->duplex = DUPLEX_HALF; 398 if (lpa & (LPA_100FULL | LPA_100HALF)) 399 phy->speed = SPEED_100; 400 else 401 phy->speed = SPEED_10; 402 phy->pause = 0; 403 } 404 /* On non-aneg, we assume what we put in BMCR is the speed, 405 * though magic-aneg shouldn't prevent this case from occurring 406 */ 407 408 return 0; 409 } 410 411 static int generic_suspend(struct mii_phy* phy) 412 { 413 sungem_phy_write(phy, MII_BMCR, BMCR_PDOWN); 414 415 return 0; 416 } 417 418 static int bcm5421_init(struct mii_phy* phy) 419 { 420 u16 data; 421 unsigned int id; 422 423 id = (sungem_phy_read(phy, MII_PHYSID1) << 16 | sungem_phy_read(phy, MII_PHYSID2)); 424 425 /* Revision 0 of 5421 needs some fixups */ 426 if (id == 0x002060e0) { 427 /* This is borrowed from MacOS 428 */ 429 sungem_phy_write(phy, 0x18, 0x1007); 430 data = sungem_phy_read(phy, 0x18); 431 sungem_phy_write(phy, 0x18, data | 0x0400); 432 sungem_phy_write(phy, 0x18, 0x0007); 433 data = sungem_phy_read(phy, 0x18); 434 sungem_phy_write(phy, 0x18, data | 0x0800); 435 sungem_phy_write(phy, 0x17, 0x000a); 436 data = sungem_phy_read(phy, 0x15); 437 sungem_phy_write(phy, 0x15, data | 0x0200); 438 } 439 440 /* Pick up some init code from OF for K2 version */ 441 if ((id & 0xfffffff0) == 0x002062e0) { 442 sungem_phy_write(phy, 4, 0x01e1); 443 sungem_phy_write(phy, 9, 0x0300); 444 } 445 446 /* Check if we can enable automatic low power */ 447 #ifdef CONFIG_PPC_PMAC 448 if (phy->platform_data) { 449 struct device_node *np = of_get_parent(phy->platform_data); 450 int can_low_power = 1; 451 if (np == NULL || of_get_property(np, "no-autolowpower", NULL)) 452 can_low_power = 0; 453 of_node_put(np); 454 if (can_low_power) { 455 /* Enable automatic low-power */ 456 sungem_phy_write(phy, 0x1c, 0x9002); 457 sungem_phy_write(phy, 0x1c, 0xa821); 458 sungem_phy_write(phy, 0x1c, 0x941d); 459 } 460 } 461 #endif /* CONFIG_PPC_PMAC */ 462 463 return 0; 464 } 465 466 static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise) 467 { 468 u16 ctl, adv; 469 470 phy->autoneg = 1; 471 phy->speed = SPEED_10; 472 phy->duplex = DUPLEX_HALF; 473 phy->pause = 0; 474 phy->advertising = advertise; 475 476 /* Setup standard advertise */ 477 adv = sungem_phy_read(phy, MII_ADVERTISE); 478 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); 479 if (advertise & ADVERTISED_10baseT_Half) 480 adv |= ADVERTISE_10HALF; 481 if (advertise & ADVERTISED_10baseT_Full) 482 adv |= ADVERTISE_10FULL; 483 if (advertise & ADVERTISED_100baseT_Half) 484 adv |= ADVERTISE_100HALF; 485 if (advertise & ADVERTISED_100baseT_Full) 486 adv |= ADVERTISE_100FULL; 487 if (advertise & ADVERTISED_Pause) 488 adv |= ADVERTISE_PAUSE_CAP; 489 if (advertise & ADVERTISED_Asym_Pause) 490 adv |= ADVERTISE_PAUSE_ASYM; 491 sungem_phy_write(phy, MII_ADVERTISE, adv); 492 493 /* Setup 1000BT advertise */ 494 adv = sungem_phy_read(phy, MII_1000BASETCONTROL); 495 adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP); 496 if (advertise & SUPPORTED_1000baseT_Half) 497 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP; 498 if (advertise & SUPPORTED_1000baseT_Full) 499 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP; 500 sungem_phy_write(phy, MII_1000BASETCONTROL, adv); 501 502 /* Start/Restart aneg */ 503 ctl = sungem_phy_read(phy, MII_BMCR); 504 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); 505 sungem_phy_write(phy, MII_BMCR, ctl); 506 507 return 0; 508 } 509 510 static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd) 511 { 512 u16 ctl; 513 514 phy->autoneg = 0; 515 phy->speed = speed; 516 phy->duplex = fd; 517 phy->pause = 0; 518 519 ctl = sungem_phy_read(phy, MII_BMCR); 520 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE); 521 522 /* First reset the PHY */ 523 sungem_phy_write(phy, MII_BMCR, ctl | BMCR_RESET); 524 525 /* Select speed & duplex */ 526 switch(speed) { 527 case SPEED_10: 528 break; 529 case SPEED_100: 530 ctl |= BMCR_SPEED100; 531 break; 532 case SPEED_1000: 533 ctl |= BMCR_SPD2; 534 } 535 if (fd == DUPLEX_FULL) 536 ctl |= BMCR_FULLDPLX; 537 538 // XXX Should we set the sungem to GII now on 1000BT ? 539 540 sungem_phy_write(phy, MII_BMCR, ctl); 541 542 return 0; 543 } 544 545 static int bcm54xx_read_link(struct mii_phy *phy) 546 { 547 int link_mode; 548 u16 val; 549 550 if (phy->autoneg) { 551 val = sungem_phy_read(phy, MII_BCM5400_AUXSTATUS); 552 link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >> 553 MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT); 554 phy->duplex = phy_BCM5400_link_table[link_mode][0] ? 555 DUPLEX_FULL : DUPLEX_HALF; 556 phy->speed = phy_BCM5400_link_table[link_mode][2] ? 557 SPEED_1000 : 558 (phy_BCM5400_link_table[link_mode][1] ? 559 SPEED_100 : SPEED_10); 560 val = sungem_phy_read(phy, MII_LPA); 561 phy->pause = (phy->duplex == DUPLEX_FULL) && 562 ((val & LPA_PAUSE) != 0); 563 } 564 /* On non-aneg, we assume what we put in BMCR is the speed, 565 * though magic-aneg shouldn't prevent this case from occurring 566 */ 567 568 return 0; 569 } 570 571 static int marvell88e1111_init(struct mii_phy* phy) 572 { 573 u16 rev; 574 575 /* magic init sequence for rev 0 */ 576 rev = sungem_phy_read(phy, MII_PHYSID2) & 0x000f; 577 if (rev == 0) { 578 sungem_phy_write(phy, 0x1d, 0x000a); 579 sungem_phy_write(phy, 0x1e, 0x0821); 580 581 sungem_phy_write(phy, 0x1d, 0x0006); 582 sungem_phy_write(phy, 0x1e, 0x8600); 583 584 sungem_phy_write(phy, 0x1d, 0x000b); 585 sungem_phy_write(phy, 0x1e, 0x0100); 586 587 sungem_phy_write(phy, 0x1d, 0x0004); 588 sungem_phy_write(phy, 0x1e, 0x4850); 589 } 590 return 0; 591 } 592 593 #define BCM5421_MODE_MASK (1 << 5) 594 595 static int bcm5421_poll_link(struct mii_phy* phy) 596 { 597 u32 phy_reg; 598 int mode; 599 600 /* find out in what mode we are */ 601 sungem_phy_write(phy, MII_NCONFIG, 0x1000); 602 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 603 604 mode = (phy_reg & BCM5421_MODE_MASK) >> 5; 605 606 if ( mode == BCM54XX_COPPER) 607 return genmii_poll_link(phy); 608 609 /* try to find out whether we have a link */ 610 sungem_phy_write(phy, MII_NCONFIG, 0x2000); 611 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 612 613 if (phy_reg & 0x0020) 614 return 0; 615 else 616 return 1; 617 } 618 619 static int bcm5421_read_link(struct mii_phy* phy) 620 { 621 u32 phy_reg; 622 int mode; 623 624 /* find out in what mode we are */ 625 sungem_phy_write(phy, MII_NCONFIG, 0x1000); 626 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 627 628 mode = (phy_reg & BCM5421_MODE_MASK ) >> 5; 629 630 if ( mode == BCM54XX_COPPER) 631 return bcm54xx_read_link(phy); 632 633 phy->speed = SPEED_1000; 634 635 /* find out whether we are running half- or full duplex */ 636 sungem_phy_write(phy, MII_NCONFIG, 0x2000); 637 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 638 639 if ( (phy_reg & 0x0080) >> 7) 640 phy->duplex |= DUPLEX_HALF; 641 else 642 phy->duplex |= DUPLEX_FULL; 643 644 return 0; 645 } 646 647 static int bcm5421_enable_fiber(struct mii_phy* phy, int autoneg) 648 { 649 /* enable fiber mode */ 650 sungem_phy_write(phy, MII_NCONFIG, 0x9020); 651 /* LEDs active in both modes, autosense prio = fiber */ 652 sungem_phy_write(phy, MII_NCONFIG, 0x945f); 653 654 if (!autoneg) { 655 /* switch off fibre autoneg */ 656 sungem_phy_write(phy, MII_NCONFIG, 0xfc01); 657 sungem_phy_write(phy, 0x0b, 0x0004); 658 } 659 660 phy->autoneg = autoneg; 661 662 return 0; 663 } 664 665 #define BCM5461_FIBER_LINK (1 << 2) 666 #define BCM5461_MODE_MASK (3 << 1) 667 668 static int bcm5461_poll_link(struct mii_phy* phy) 669 { 670 u32 phy_reg; 671 int mode; 672 673 /* find out in what mode we are */ 674 sungem_phy_write(phy, MII_NCONFIG, 0x7c00); 675 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 676 677 mode = (phy_reg & BCM5461_MODE_MASK ) >> 1; 678 679 if ( mode == BCM54XX_COPPER) 680 return genmii_poll_link(phy); 681 682 /* find out whether we have a link */ 683 sungem_phy_write(phy, MII_NCONFIG, 0x7000); 684 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 685 686 if (phy_reg & BCM5461_FIBER_LINK) 687 return 1; 688 else 689 return 0; 690 } 691 692 #define BCM5461_FIBER_DUPLEX (1 << 3) 693 694 static int bcm5461_read_link(struct mii_phy* phy) 695 { 696 u32 phy_reg; 697 int mode; 698 699 /* find out in what mode we are */ 700 sungem_phy_write(phy, MII_NCONFIG, 0x7c00); 701 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 702 703 mode = (phy_reg & BCM5461_MODE_MASK ) >> 1; 704 705 if ( mode == BCM54XX_COPPER) { 706 return bcm54xx_read_link(phy); 707 } 708 709 phy->speed = SPEED_1000; 710 711 /* find out whether we are running half- or full duplex */ 712 sungem_phy_write(phy, MII_NCONFIG, 0x7000); 713 phy_reg = sungem_phy_read(phy, MII_NCONFIG); 714 715 if (phy_reg & BCM5461_FIBER_DUPLEX) 716 phy->duplex |= DUPLEX_FULL; 717 else 718 phy->duplex |= DUPLEX_HALF; 719 720 return 0; 721 } 722 723 static int bcm5461_enable_fiber(struct mii_phy* phy, int autoneg) 724 { 725 /* select fiber mode, enable 1000 base-X registers */ 726 sungem_phy_write(phy, MII_NCONFIG, 0xfc0b); 727 728 if (autoneg) { 729 /* enable fiber with no autonegotiation */ 730 sungem_phy_write(phy, MII_ADVERTISE, 0x01e0); 731 sungem_phy_write(phy, MII_BMCR, 0x1140); 732 } else { 733 /* enable fiber with autonegotiation */ 734 sungem_phy_write(phy, MII_BMCR, 0x0140); 735 } 736 737 phy->autoneg = autoneg; 738 739 return 0; 740 } 741 742 static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise) 743 { 744 u16 ctl, adv; 745 746 phy->autoneg = 1; 747 phy->speed = SPEED_10; 748 phy->duplex = DUPLEX_HALF; 749 phy->pause = 0; 750 phy->advertising = advertise; 751 752 /* Setup standard advertise */ 753 adv = sungem_phy_read(phy, MII_ADVERTISE); 754 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); 755 if (advertise & ADVERTISED_10baseT_Half) 756 adv |= ADVERTISE_10HALF; 757 if (advertise & ADVERTISED_10baseT_Full) 758 adv |= ADVERTISE_10FULL; 759 if (advertise & ADVERTISED_100baseT_Half) 760 adv |= ADVERTISE_100HALF; 761 if (advertise & ADVERTISED_100baseT_Full) 762 adv |= ADVERTISE_100FULL; 763 if (advertise & ADVERTISED_Pause) 764 adv |= ADVERTISE_PAUSE_CAP; 765 if (advertise & ADVERTISED_Asym_Pause) 766 adv |= ADVERTISE_PAUSE_ASYM; 767 sungem_phy_write(phy, MII_ADVERTISE, adv); 768 769 /* Setup 1000BT advertise & enable crossover detect 770 * XXX How do we advertise 1000BT ? Darwin source is 771 * confusing here, they read from specific control and 772 * write to control... Someone has specs for those 773 * beasts ? 774 */ 775 adv = sungem_phy_read(phy, MII_M1011_PHY_SPEC_CONTROL); 776 adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX; 777 adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP | 778 MII_1000BASETCONTROL_HALFDUPLEXCAP); 779 if (advertise & SUPPORTED_1000baseT_Half) 780 adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP; 781 if (advertise & SUPPORTED_1000baseT_Full) 782 adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP; 783 sungem_phy_write(phy, MII_1000BASETCONTROL, adv); 784 785 /* Start/Restart aneg */ 786 ctl = sungem_phy_read(phy, MII_BMCR); 787 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); 788 sungem_phy_write(phy, MII_BMCR, ctl); 789 790 return 0; 791 } 792 793 static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd) 794 { 795 u16 ctl, ctl2; 796 797 phy->autoneg = 0; 798 phy->speed = speed; 799 phy->duplex = fd; 800 phy->pause = 0; 801 802 ctl = sungem_phy_read(phy, MII_BMCR); 803 ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE); 804 ctl |= BMCR_RESET; 805 806 /* Select speed & duplex */ 807 switch(speed) { 808 case SPEED_10: 809 break; 810 case SPEED_100: 811 ctl |= BMCR_SPEED100; 812 break; 813 /* I'm not sure about the one below, again, Darwin source is 814 * quite confusing and I lack chip specs 815 */ 816 case SPEED_1000: 817 ctl |= BMCR_SPD2; 818 } 819 if (fd == DUPLEX_FULL) 820 ctl |= BMCR_FULLDPLX; 821 822 /* Disable crossover. Again, the way Apple does it is strange, 823 * though I don't assume they are wrong ;) 824 */ 825 ctl2 = sungem_phy_read(phy, MII_M1011_PHY_SPEC_CONTROL); 826 ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX | 827 MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX | 828 MII_1000BASETCONTROL_FULLDUPLEXCAP | 829 MII_1000BASETCONTROL_HALFDUPLEXCAP); 830 if (speed == SPEED_1000) 831 ctl2 |= (fd == DUPLEX_FULL) ? 832 MII_1000BASETCONTROL_FULLDUPLEXCAP : 833 MII_1000BASETCONTROL_HALFDUPLEXCAP; 834 sungem_phy_write(phy, MII_1000BASETCONTROL, ctl2); 835 836 // XXX Should we set the sungem to GII now on 1000BT ? 837 838 sungem_phy_write(phy, MII_BMCR, ctl); 839 840 return 0; 841 } 842 843 static int marvell_read_link(struct mii_phy *phy) 844 { 845 u16 status, pmask; 846 847 if (phy->autoneg) { 848 status = sungem_phy_read(phy, MII_M1011_PHY_SPEC_STATUS); 849 if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0) 850 return -EAGAIN; 851 if (status & MII_M1011_PHY_SPEC_STATUS_1000) 852 phy->speed = SPEED_1000; 853 else if (status & MII_M1011_PHY_SPEC_STATUS_100) 854 phy->speed = SPEED_100; 855 else 856 phy->speed = SPEED_10; 857 if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX) 858 phy->duplex = DUPLEX_FULL; 859 else 860 phy->duplex = DUPLEX_HALF; 861 pmask = MII_M1011_PHY_SPEC_STATUS_TX_PAUSE | 862 MII_M1011_PHY_SPEC_STATUS_RX_PAUSE; 863 phy->pause = (status & pmask) == pmask; 864 } 865 /* On non-aneg, we assume what we put in BMCR is the speed, 866 * though magic-aneg shouldn't prevent this case from occurring 867 */ 868 869 return 0; 870 } 871 872 #define MII_BASIC_FEATURES \ 873 (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ 874 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ 875 SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | \ 876 SUPPORTED_Pause) 877 878 /* On gigabit capable PHYs, we advertise Pause support but not asym pause 879 * support for now as I'm not sure it's supported and Darwin doesn't do 880 * it neither. --BenH. 881 */ 882 #define MII_GBIT_FEATURES \ 883 (MII_BASIC_FEATURES | \ 884 SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full) 885 886 /* Broadcom BCM 5201 */ 887 static const struct mii_phy_ops bcm5201_phy_ops = { 888 .init = bcm5201_init, 889 .suspend = bcm5201_suspend, 890 .setup_aneg = genmii_setup_aneg, 891 .setup_forced = genmii_setup_forced, 892 .poll_link = genmii_poll_link, 893 .read_link = genmii_read_link, 894 }; 895 896 static const struct mii_phy_def bcm5201_phy_def = { 897 .phy_id = 0x00406210, 898 .phy_id_mask = 0xfffffff0, 899 .name = "BCM5201", 900 .features = MII_BASIC_FEATURES, 901 .magic_aneg = 1, 902 .ops = &bcm5201_phy_ops 903 }; 904 905 /* Broadcom BCM 5221 */ 906 static const struct mii_phy_ops bcm5221_phy_ops = { 907 .suspend = bcm5221_suspend, 908 .init = bcm5221_init, 909 .setup_aneg = genmii_setup_aneg, 910 .setup_forced = genmii_setup_forced, 911 .poll_link = genmii_poll_link, 912 .read_link = genmii_read_link, 913 }; 914 915 static const struct mii_phy_def bcm5221_phy_def = { 916 .phy_id = 0x004061e0, 917 .phy_id_mask = 0xfffffff0, 918 .name = "BCM5221", 919 .features = MII_BASIC_FEATURES, 920 .magic_aneg = 1, 921 .ops = &bcm5221_phy_ops 922 }; 923 924 /* Broadcom BCM 5241 */ 925 static const struct mii_phy_ops bcm5241_phy_ops = { 926 .suspend = bcm5241_suspend, 927 .init = bcm5241_init, 928 .setup_aneg = genmii_setup_aneg, 929 .setup_forced = genmii_setup_forced, 930 .poll_link = genmii_poll_link, 931 .read_link = genmii_read_link, 932 }; 933 934 static const struct mii_phy_def bcm5241_phy_def = { 935 .phy_id = 0x0143bc30, 936 .phy_id_mask = 0xfffffff0, 937 .name = "BCM5241", 938 .features = MII_BASIC_FEATURES, 939 .magic_aneg = 1, 940 .ops = &bcm5241_phy_ops 941 }; 942 943 /* Broadcom BCM 5400 */ 944 static const struct mii_phy_ops bcm5400_phy_ops = { 945 .init = bcm5400_init, 946 .suspend = bcm5400_suspend, 947 .setup_aneg = bcm54xx_setup_aneg, 948 .setup_forced = bcm54xx_setup_forced, 949 .poll_link = genmii_poll_link, 950 .read_link = bcm54xx_read_link, 951 }; 952 953 static const struct mii_phy_def bcm5400_phy_def = { 954 .phy_id = 0x00206040, 955 .phy_id_mask = 0xfffffff0, 956 .name = "BCM5400", 957 .features = MII_GBIT_FEATURES, 958 .magic_aneg = 1, 959 .ops = &bcm5400_phy_ops 960 }; 961 962 /* Broadcom BCM 5401 */ 963 static const struct mii_phy_ops bcm5401_phy_ops = { 964 .init = bcm5401_init, 965 .suspend = bcm5401_suspend, 966 .setup_aneg = bcm54xx_setup_aneg, 967 .setup_forced = bcm54xx_setup_forced, 968 .poll_link = genmii_poll_link, 969 .read_link = bcm54xx_read_link, 970 }; 971 972 static const struct mii_phy_def bcm5401_phy_def = { 973 .phy_id = 0x00206050, 974 .phy_id_mask = 0xfffffff0, 975 .name = "BCM5401", 976 .features = MII_GBIT_FEATURES, 977 .magic_aneg = 1, 978 .ops = &bcm5401_phy_ops 979 }; 980 981 /* Broadcom BCM 5411 */ 982 static const struct mii_phy_ops bcm5411_phy_ops = { 983 .init = bcm5411_init, 984 .suspend = generic_suspend, 985 .setup_aneg = bcm54xx_setup_aneg, 986 .setup_forced = bcm54xx_setup_forced, 987 .poll_link = genmii_poll_link, 988 .read_link = bcm54xx_read_link, 989 }; 990 991 static const struct mii_phy_def bcm5411_phy_def = { 992 .phy_id = 0x00206070, 993 .phy_id_mask = 0xfffffff0, 994 .name = "BCM5411", 995 .features = MII_GBIT_FEATURES, 996 .magic_aneg = 1, 997 .ops = &bcm5411_phy_ops 998 }; 999 1000 /* Broadcom BCM 5421 */ 1001 static const struct mii_phy_ops bcm5421_phy_ops = { 1002 .init = bcm5421_init, 1003 .suspend = generic_suspend, 1004 .setup_aneg = bcm54xx_setup_aneg, 1005 .setup_forced = bcm54xx_setup_forced, 1006 .poll_link = bcm5421_poll_link, 1007 .read_link = bcm5421_read_link, 1008 .enable_fiber = bcm5421_enable_fiber, 1009 }; 1010 1011 static const struct mii_phy_def bcm5421_phy_def = { 1012 .phy_id = 0x002060e0, 1013 .phy_id_mask = 0xfffffff0, 1014 .name = "BCM5421", 1015 .features = MII_GBIT_FEATURES, 1016 .magic_aneg = 1, 1017 .ops = &bcm5421_phy_ops 1018 }; 1019 1020 /* Broadcom BCM 5421 built-in K2 */ 1021 static const struct mii_phy_ops bcm5421k2_phy_ops = { 1022 .init = bcm5421_init, 1023 .suspend = generic_suspend, 1024 .setup_aneg = bcm54xx_setup_aneg, 1025 .setup_forced = bcm54xx_setup_forced, 1026 .poll_link = genmii_poll_link, 1027 .read_link = bcm54xx_read_link, 1028 }; 1029 1030 static const struct mii_phy_def bcm5421k2_phy_def = { 1031 .phy_id = 0x002062e0, 1032 .phy_id_mask = 0xfffffff0, 1033 .name = "BCM5421-K2", 1034 .features = MII_GBIT_FEATURES, 1035 .magic_aneg = 1, 1036 .ops = &bcm5421k2_phy_ops 1037 }; 1038 1039 static const struct mii_phy_ops bcm5461_phy_ops = { 1040 .init = bcm5421_init, 1041 .suspend = generic_suspend, 1042 .setup_aneg = bcm54xx_setup_aneg, 1043 .setup_forced = bcm54xx_setup_forced, 1044 .poll_link = bcm5461_poll_link, 1045 .read_link = bcm5461_read_link, 1046 .enable_fiber = bcm5461_enable_fiber, 1047 }; 1048 1049 static const struct mii_phy_def bcm5461_phy_def = { 1050 .phy_id = 0x002060c0, 1051 .phy_id_mask = 0xfffffff0, 1052 .name = "BCM5461", 1053 .features = MII_GBIT_FEATURES, 1054 .magic_aneg = 1, 1055 .ops = &bcm5461_phy_ops 1056 }; 1057 1058 /* Broadcom BCM 5462 built-in Vesta */ 1059 static const struct mii_phy_ops bcm5462V_phy_ops = { 1060 .init = bcm5421_init, 1061 .suspend = generic_suspend, 1062 .setup_aneg = bcm54xx_setup_aneg, 1063 .setup_forced = bcm54xx_setup_forced, 1064 .poll_link = genmii_poll_link, 1065 .read_link = bcm54xx_read_link, 1066 }; 1067 1068 static const struct mii_phy_def bcm5462V_phy_def = { 1069 .phy_id = 0x002060d0, 1070 .phy_id_mask = 0xfffffff0, 1071 .name = "BCM5462-Vesta", 1072 .features = MII_GBIT_FEATURES, 1073 .magic_aneg = 1, 1074 .ops = &bcm5462V_phy_ops 1075 }; 1076 1077 /* Marvell 88E1101 amd 88E1111 */ 1078 static const struct mii_phy_ops marvell88e1101_phy_ops = { 1079 .suspend = generic_suspend, 1080 .setup_aneg = marvell_setup_aneg, 1081 .setup_forced = marvell_setup_forced, 1082 .poll_link = genmii_poll_link, 1083 .read_link = marvell_read_link 1084 }; 1085 1086 static const struct mii_phy_ops marvell88e1111_phy_ops = { 1087 .init = marvell88e1111_init, 1088 .suspend = generic_suspend, 1089 .setup_aneg = marvell_setup_aneg, 1090 .setup_forced = marvell_setup_forced, 1091 .poll_link = genmii_poll_link, 1092 .read_link = marvell_read_link 1093 }; 1094 1095 /* two revs in darwin for the 88e1101 ... I could use a datasheet 1096 * to get the proper names... 1097 */ 1098 static const struct mii_phy_def marvell88e1101v1_phy_def = { 1099 .phy_id = 0x01410c20, 1100 .phy_id_mask = 0xfffffff0, 1101 .name = "Marvell 88E1101v1", 1102 .features = MII_GBIT_FEATURES, 1103 .magic_aneg = 1, 1104 .ops = &marvell88e1101_phy_ops 1105 }; 1106 1107 static const struct mii_phy_def marvell88e1101v2_phy_def = { 1108 .phy_id = 0x01410c60, 1109 .phy_id_mask = 0xfffffff0, 1110 .name = "Marvell 88E1101v2", 1111 .features = MII_GBIT_FEATURES, 1112 .magic_aneg = 1, 1113 .ops = &marvell88e1101_phy_ops 1114 }; 1115 1116 static const struct mii_phy_def marvell88e1111_phy_def = { 1117 .phy_id = 0x01410cc0, 1118 .phy_id_mask = 0xfffffff0, 1119 .name = "Marvell 88E1111", 1120 .features = MII_GBIT_FEATURES, 1121 .magic_aneg = 1, 1122 .ops = &marvell88e1111_phy_ops 1123 }; 1124 1125 /* Generic implementation for most 10/100 PHYs */ 1126 static const struct mii_phy_ops generic_phy_ops = { 1127 .setup_aneg = genmii_setup_aneg, 1128 .setup_forced = genmii_setup_forced, 1129 .poll_link = genmii_poll_link, 1130 .read_link = genmii_read_link 1131 }; 1132 1133 static const struct mii_phy_def genmii_phy_def = { 1134 .phy_id = 0x00000000, 1135 .phy_id_mask = 0x00000000, 1136 .name = "Generic MII", 1137 .features = MII_BASIC_FEATURES, 1138 .magic_aneg = 0, 1139 .ops = &generic_phy_ops 1140 }; 1141 1142 static const struct mii_phy_def *mii_phy_table[] = { 1143 &bcm5201_phy_def, 1144 &bcm5221_phy_def, 1145 &bcm5241_phy_def, 1146 &bcm5400_phy_def, 1147 &bcm5401_phy_def, 1148 &bcm5411_phy_def, 1149 &bcm5421_phy_def, 1150 &bcm5421k2_phy_def, 1151 &bcm5461_phy_def, 1152 &bcm5462V_phy_def, 1153 &marvell88e1101v1_phy_def, 1154 &marvell88e1101v2_phy_def, 1155 &marvell88e1111_phy_def, 1156 &genmii_phy_def, 1157 NULL 1158 }; 1159 1160 int sungem_phy_probe(struct mii_phy *phy, int mii_id) 1161 { 1162 const struct mii_phy_def *def; 1163 int rc; 1164 u32 id; 1165 int i; 1166 1167 /* We do not reset the mii_phy structure as the driver 1168 * may re-probe the PHY regulary 1169 */ 1170 phy->mii_id = mii_id; 1171 1172 /* Take PHY out of isloate mode and reset it. */ 1173 rc = reset_one_mii_phy(phy, mii_id); 1174 if (rc) 1175 goto fail; 1176 1177 /* Read ID and find matching entry */ 1178 id = (sungem_phy_read(phy, MII_PHYSID1) << 16 | sungem_phy_read(phy, MII_PHYSID2)); 1179 printk(KERN_DEBUG KBUILD_MODNAME ": " "PHY ID: %x, addr: %x\n", 1180 id, mii_id); 1181 for (i=0; (def = mii_phy_table[i]) != NULL; i++) 1182 if ((id & def->phy_id_mask) == def->phy_id) 1183 break; 1184 /* Should never be NULL (we have a generic entry), but... */ 1185 if (def == NULL) 1186 goto fail; 1187 1188 phy->def = def; 1189 1190 return 0; 1191 fail: 1192 phy->speed = 0; 1193 phy->duplex = 0; 1194 phy->pause = 0; 1195 phy->advertising = 0; 1196 return -ENODEV; 1197 } 1198 1199 EXPORT_SYMBOL(sungem_phy_probe); 1200 MODULE_DESCRIPTION("PHY drivers for the sungem Ethernet MAC driver"); 1201 MODULE_LICENSE("GPL"); 1202