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