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