1/* 2 * drivers/net/ethernet/ibm/emac/phy.c 3 * 4 * Driver for PowerPC 4xx on-chip ethernet controller, PHY support. 5 * Borrowed from sungem_phy.c, though I only kept the generic MII 6 * driver for now. 7 * 8 * This file should be shared with other drivers or eventually 9 * merged as the "low level" part of miilib 10 * 11 * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. 12 * <benh@kernel.crashing.org> 13 * 14 * Based on the arch/ppc version of the driver: 15 * 16 * (c) 2003, Benjamin Herrenscmidt (benh@kernel.crashing.org) 17 * (c) 2004-2005, Eugene Surovegin <ebs@ebshome.net> 18 * 19 */ 20#include <linux/module.h> 21#include <linux/kernel.h> 22#include <linux/types.h> 23#include <linux/netdevice.h> 24#include <linux/mii.h> 25#include <linux/ethtool.h> 26#include <linux/delay.h> 27 28#include "emac.h" 29#include "phy.h" 30 31#define phy_read _phy_read 32#define phy_write _phy_write 33 34static inline int _phy_read(struct mii_phy *phy, int reg) 35{ 36 return phy->mdio_read(phy->dev, phy->address, reg); 37} 38 39static inline void _phy_write(struct mii_phy *phy, int reg, int val) 40{ 41 phy->mdio_write(phy->dev, phy->address, reg, val); 42} 43 44static inline int gpcs_phy_read(struct mii_phy *phy, int reg) 45{ 46 return phy->mdio_read(phy->dev, phy->gpcs_address, reg); 47} 48 49static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val) 50{ 51 phy->mdio_write(phy->dev, phy->gpcs_address, reg, val); 52} 53 54int emac_mii_reset_phy(struct mii_phy *phy) 55{ 56 int val; 57 int limit = 10000; 58 59 val = phy_read(phy, MII_BMCR); 60 val &= ~(BMCR_ISOLATE | BMCR_ANENABLE); 61 val |= BMCR_RESET; 62 phy_write(phy, MII_BMCR, val); 63 64 udelay(300); 65 66 while (--limit) { 67 val = phy_read(phy, MII_BMCR); 68 if (val >= 0 && (val & BMCR_RESET) == 0) 69 break; 70 udelay(10); 71 } 72 if ((val & BMCR_ISOLATE) && limit > 0) 73 phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE); 74 75 return limit <= 0; 76} 77 78int emac_mii_reset_gpcs(struct mii_phy *phy) 79{ 80 int val; 81 int limit = 10000; 82 83 val = gpcs_phy_read(phy, MII_BMCR); 84 val &= ~(BMCR_ISOLATE | BMCR_ANENABLE); 85 val |= BMCR_RESET; 86 gpcs_phy_write(phy, MII_BMCR, val); 87 88 udelay(300); 89 90 while (--limit) { 91 val = gpcs_phy_read(phy, MII_BMCR); 92 if (val >= 0 && (val & BMCR_RESET) == 0) 93 break; 94 udelay(10); 95 } 96 if ((val & BMCR_ISOLATE) && limit > 0) 97 gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE); 98 99 if (limit > 0 && phy->mode == PHY_MODE_SGMII) { 100 /* Configure GPCS interface to recommended setting for SGMII */ 101 gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */ 102 gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */ 103 gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX */ 104 } 105 106 return limit <= 0; 107} 108 109static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) 110{ 111 int ctl, adv; 112 113 phy->autoneg = AUTONEG_ENABLE; 114 phy->speed = SPEED_10; 115 phy->duplex = DUPLEX_HALF; 116 phy->pause = phy->asym_pause = 0; 117 phy->advertising = advertise; 118 119 ctl = phy_read(phy, MII_BMCR); 120 if (ctl < 0) 121 return ctl; 122 ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); 123 124 /* First clear the PHY */ 125 phy_write(phy, MII_BMCR, ctl); 126 127 /* Setup standard advertise */ 128 adv = phy_read(phy, MII_ADVERTISE); 129 if (adv < 0) 130 return adv; 131 adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | 132 ADVERTISE_PAUSE_ASYM); 133 if (advertise & ADVERTISED_10baseT_Half) 134 adv |= ADVERTISE_10HALF; 135 if (advertise & ADVERTISED_10baseT_Full) 136 adv |= ADVERTISE_10FULL; 137 if (advertise & ADVERTISED_100baseT_Half) 138 adv |= ADVERTISE_100HALF; 139 if (advertise & ADVERTISED_100baseT_Full) 140 adv |= ADVERTISE_100FULL; 141 if (advertise & ADVERTISED_Pause) 142 adv |= ADVERTISE_PAUSE_CAP; 143 if (advertise & ADVERTISED_Asym_Pause) 144 adv |= ADVERTISE_PAUSE_ASYM; 145 phy_write(phy, MII_ADVERTISE, adv); 146 147 if (phy->features & 148 (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) { 149 adv = phy_read(phy, MII_CTRL1000); 150 if (adv < 0) 151 return adv; 152 adv &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); 153 if (advertise & ADVERTISED_1000baseT_Full) 154 adv |= ADVERTISE_1000FULL; 155 if (advertise & ADVERTISED_1000baseT_Half) 156 adv |= ADVERTISE_1000HALF; 157 phy_write(phy, MII_CTRL1000, adv); 158 } 159 160 /* Start/Restart aneg */ 161 ctl = phy_read(phy, MII_BMCR); 162 ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); 163 phy_write(phy, MII_BMCR, ctl); 164 165 return 0; 166} 167 168static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd) 169{ 170 int ctl; 171 172 phy->autoneg = AUTONEG_DISABLE; 173 phy->speed = speed; 174 phy->duplex = fd; 175 phy->pause = phy->asym_pause = 0; 176 177 ctl = phy_read(phy, MII_BMCR); 178 if (ctl < 0) 179 return ctl; 180 ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); 181 182 /* First clear the PHY */ 183 phy_write(phy, MII_BMCR, ctl | BMCR_RESET); 184 185 /* Select speed & duplex */ 186 switch (speed) { 187 case SPEED_10: 188 break; 189 case SPEED_100: 190 ctl |= BMCR_SPEED100; 191 break; 192 case SPEED_1000: 193 ctl |= BMCR_SPEED1000; 194 break; 195 default: 196 return -EINVAL; 197 } 198 if (fd == DUPLEX_FULL) 199 ctl |= BMCR_FULLDPLX; 200 phy_write(phy, MII_BMCR, ctl); 201 202 return 0; 203} 204 205static int genmii_poll_link(struct mii_phy *phy) 206{ 207 int status; 208 209 /* Clear latched value with dummy read */ 210 phy_read(phy, MII_BMSR); 211 status = phy_read(phy, MII_BMSR); 212 if (status < 0 || (status & BMSR_LSTATUS) == 0) 213 return 0; 214 if (phy->autoneg == AUTONEG_ENABLE && !(status & BMSR_ANEGCOMPLETE)) 215 return 0; 216 return 1; 217} 218 219static int genmii_read_link(struct mii_phy *phy) 220{ 221 if (phy->autoneg == AUTONEG_ENABLE) { 222 int glpa = 0; 223 int lpa = phy_read(phy, MII_LPA) & phy_read(phy, MII_ADVERTISE); 224 if (lpa < 0) 225 return lpa; 226 227 if (phy->features & 228 (SUPPORTED_1000baseT_Full | SUPPORTED_1000baseT_Half)) { 229 int adv = phy_read(phy, MII_CTRL1000); 230 glpa = phy_read(phy, MII_STAT1000); 231 232 if (glpa < 0 || adv < 0) 233 return adv; 234 235 glpa &= adv << 2; 236 } 237 238 phy->speed = SPEED_10; 239 phy->duplex = DUPLEX_HALF; 240 phy->pause = phy->asym_pause = 0; 241 242 if (glpa & (LPA_1000FULL | LPA_1000HALF)) { 243 phy->speed = SPEED_1000; 244 if (glpa & LPA_1000FULL) 245 phy->duplex = DUPLEX_FULL; 246 } else if (lpa & (LPA_100FULL | LPA_100HALF)) { 247 phy->speed = SPEED_100; 248 if (lpa & LPA_100FULL) 249 phy->duplex = DUPLEX_FULL; 250 } else if (lpa & LPA_10FULL) 251 phy->duplex = DUPLEX_FULL; 252 253 if (phy->duplex == DUPLEX_FULL) { 254 phy->pause = lpa & LPA_PAUSE_CAP ? 1 : 0; 255 phy->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0; 256 } 257 } else { 258 int bmcr = phy_read(phy, MII_BMCR); 259 if (bmcr < 0) 260 return bmcr; 261 262 if (bmcr & BMCR_FULLDPLX) 263 phy->duplex = DUPLEX_FULL; 264 else 265 phy->duplex = DUPLEX_HALF; 266 if (bmcr & BMCR_SPEED1000) 267 phy->speed = SPEED_1000; 268 else if (bmcr & BMCR_SPEED100) 269 phy->speed = SPEED_100; 270 else 271 phy->speed = SPEED_10; 272 273 phy->pause = phy->asym_pause = 0; 274 } 275 return 0; 276} 277 278/* Generic implementation for most 10/100/1000 PHYs */ 279static struct mii_phy_ops generic_phy_ops = { 280 .setup_aneg = genmii_setup_aneg, 281 .setup_forced = genmii_setup_forced, 282 .poll_link = genmii_poll_link, 283 .read_link = genmii_read_link 284}; 285 286static struct mii_phy_def genmii_phy_def = { 287 .phy_id = 0x00000000, 288 .phy_id_mask = 0x00000000, 289 .name = "Generic MII", 290 .ops = &generic_phy_ops 291}; 292 293/* CIS8201 */ 294#define MII_CIS8201_10BTCSR 0x16 295#define TENBTCSR_ECHO_DISABLE 0x2000 296#define MII_CIS8201_EPCR 0x17 297#define EPCR_MODE_MASK 0x3000 298#define EPCR_GMII_MODE 0x0000 299#define EPCR_RGMII_MODE 0x1000 300#define EPCR_TBI_MODE 0x2000 301#define EPCR_RTBI_MODE 0x3000 302#define MII_CIS8201_ACSR 0x1c 303#define ACSR_PIN_PRIO_SELECT 0x0004 304 305static int cis8201_init(struct mii_phy *phy) 306{ 307 int epcr; 308 309 epcr = phy_read(phy, MII_CIS8201_EPCR); 310 if (epcr < 0) 311 return epcr; 312 313 epcr &= ~EPCR_MODE_MASK; 314 315 switch (phy->mode) { 316 case PHY_MODE_TBI: 317 epcr |= EPCR_TBI_MODE; 318 break; 319 case PHY_MODE_RTBI: 320 epcr |= EPCR_RTBI_MODE; 321 break; 322 case PHY_MODE_GMII: 323 epcr |= EPCR_GMII_MODE; 324 break; 325 case PHY_MODE_RGMII: 326 default: 327 epcr |= EPCR_RGMII_MODE; 328 } 329 330 phy_write(phy, MII_CIS8201_EPCR, epcr); 331 332 /* MII regs override strap pins */ 333 phy_write(phy, MII_CIS8201_ACSR, 334 phy_read(phy, MII_CIS8201_ACSR) | ACSR_PIN_PRIO_SELECT); 335 336 /* Disable TX_EN -> CRS echo mode, otherwise 10/HDX doesn't work */ 337 phy_write(phy, MII_CIS8201_10BTCSR, 338 phy_read(phy, MII_CIS8201_10BTCSR) | TENBTCSR_ECHO_DISABLE); 339 340 return 0; 341} 342 343static struct mii_phy_ops cis8201_phy_ops = { 344 .init = cis8201_init, 345 .setup_aneg = genmii_setup_aneg, 346 .setup_forced = genmii_setup_forced, 347 .poll_link = genmii_poll_link, 348 .read_link = genmii_read_link 349}; 350 351static struct mii_phy_def cis8201_phy_def = { 352 .phy_id = 0x000fc410, 353 .phy_id_mask = 0x000ffff0, 354 .name = "CIS8201 Gigabit Ethernet", 355 .ops = &cis8201_phy_ops 356}; 357 358static struct mii_phy_def bcm5248_phy_def = { 359 360 .phy_id = 0x0143bc00, 361 .phy_id_mask = 0x0ffffff0, 362 .name = "BCM5248 10/100 SMII Ethernet", 363 .ops = &generic_phy_ops 364}; 365 366static int m88e1111_init(struct mii_phy *phy) 367{ 368 pr_debug("%s: Marvell 88E1111 Ethernet\n", __func__); 369 phy_write(phy, 0x14, 0x0ce3); 370 phy_write(phy, 0x18, 0x4101); 371 phy_write(phy, 0x09, 0x0e00); 372 phy_write(phy, 0x04, 0x01e1); 373 phy_write(phy, 0x00, 0x9140); 374 phy_write(phy, 0x00, 0x1140); 375 376 return 0; 377} 378 379static int m88e1112_init(struct mii_phy *phy) 380{ 381 /* 382 * Marvell 88E1112 PHY needs to have the SGMII MAC 383 * interace (page 2) properly configured to 384 * communicate with the 460EX/GT GPCS interface. 385 */ 386 387 u16 reg_short; 388 389 pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__); 390 391 /* Set access to Page 2 */ 392 phy_write(phy, 0x16, 0x0002); 393 394 phy_write(phy, 0x00, 0x0040); /* 1Gbps */ 395 reg_short = (u16)(phy_read(phy, 0x1a)); 396 reg_short |= 0x8000; /* bypass Auto-Negotiation */ 397 phy_write(phy, 0x1a, reg_short); 398 emac_mii_reset_phy(phy); /* reset MAC interface */ 399 400 /* Reset access to Page 0 */ 401 phy_write(phy, 0x16, 0x0000); 402 403 return 0; 404} 405 406static int et1011c_init(struct mii_phy *phy) 407{ 408 u16 reg_short; 409 410 reg_short = (u16)(phy_read(phy, 0x16)); 411 reg_short &= ~(0x7); 412 reg_short |= 0x6; /* RGMII Trace Delay*/ 413 phy_write(phy, 0x16, reg_short); 414 415 reg_short = (u16)(phy_read(phy, 0x17)); 416 reg_short &= ~(0x40); 417 phy_write(phy, 0x17, reg_short); 418 419 phy_write(phy, 0x1c, 0x74f0); 420 return 0; 421} 422 423static struct mii_phy_ops et1011c_phy_ops = { 424 .init = et1011c_init, 425 .setup_aneg = genmii_setup_aneg, 426 .setup_forced = genmii_setup_forced, 427 .poll_link = genmii_poll_link, 428 .read_link = genmii_read_link 429}; 430 431static struct mii_phy_def et1011c_phy_def = { 432 .phy_id = 0x0282f000, 433 .phy_id_mask = 0x0fffff00, 434 .name = "ET1011C Gigabit Ethernet", 435 .ops = &et1011c_phy_ops 436}; 437 438 439 440 441 442static struct mii_phy_ops m88e1111_phy_ops = { 443 .init = m88e1111_init, 444 .setup_aneg = genmii_setup_aneg, 445 .setup_forced = genmii_setup_forced, 446 .poll_link = genmii_poll_link, 447 .read_link = genmii_read_link 448}; 449 450static struct mii_phy_def m88e1111_phy_def = { 451 452 .phy_id = 0x01410CC0, 453 .phy_id_mask = 0x0ffffff0, 454 .name = "Marvell 88E1111 Ethernet", 455 .ops = &m88e1111_phy_ops, 456}; 457 458static struct mii_phy_ops m88e1112_phy_ops = { 459 .init = m88e1112_init, 460 .setup_aneg = genmii_setup_aneg, 461 .setup_forced = genmii_setup_forced, 462 .poll_link = genmii_poll_link, 463 .read_link = genmii_read_link 464}; 465 466static struct mii_phy_def m88e1112_phy_def = { 467 .phy_id = 0x01410C90, 468 .phy_id_mask = 0x0ffffff0, 469 .name = "Marvell 88E1112 Ethernet", 470 .ops = &m88e1112_phy_ops, 471}; 472 473static struct mii_phy_def *mii_phy_table[] = { 474 &et1011c_phy_def, 475 &cis8201_phy_def, 476 &bcm5248_phy_def, 477 &m88e1111_phy_def, 478 &m88e1112_phy_def, 479 &genmii_phy_def, 480 NULL 481}; 482 483int emac_mii_phy_probe(struct mii_phy *phy, int address) 484{ 485 struct mii_phy_def *def; 486 int i; 487 u32 id; 488 489 phy->autoneg = AUTONEG_DISABLE; 490 phy->advertising = 0; 491 phy->address = address; 492 phy->speed = SPEED_10; 493 phy->duplex = DUPLEX_HALF; 494 phy->pause = phy->asym_pause = 0; 495 496 /* Take PHY out of isolate mode and reset it. */ 497 if (emac_mii_reset_phy(phy)) 498 return -ENODEV; 499 500 /* Read ID and find matching entry */ 501 id = (phy_read(phy, MII_PHYSID1) << 16) | phy_read(phy, MII_PHYSID2); 502 for (i = 0; (def = mii_phy_table[i]) != NULL; i++) 503 if ((id & def->phy_id_mask) == def->phy_id) 504 break; 505 /* Should never be NULL (we have a generic entry), but... */ 506 if (!def) 507 return -ENODEV; 508 509 phy->def = def; 510 511 /* Determine PHY features if needed */ 512 phy->features = def->features; 513 if (!phy->features) { 514 u16 bmsr = phy_read(phy, MII_BMSR); 515 if (bmsr & BMSR_ANEGCAPABLE) 516 phy->features |= SUPPORTED_Autoneg; 517 if (bmsr & BMSR_10HALF) 518 phy->features |= SUPPORTED_10baseT_Half; 519 if (bmsr & BMSR_10FULL) 520 phy->features |= SUPPORTED_10baseT_Full; 521 if (bmsr & BMSR_100HALF) 522 phy->features |= SUPPORTED_100baseT_Half; 523 if (bmsr & BMSR_100FULL) 524 phy->features |= SUPPORTED_100baseT_Full; 525 if (bmsr & BMSR_ESTATEN) { 526 u16 esr = phy_read(phy, MII_ESTATUS); 527 if (esr & ESTATUS_1000_TFULL) 528 phy->features |= SUPPORTED_1000baseT_Full; 529 if (esr & ESTATUS_1000_THALF) 530 phy->features |= SUPPORTED_1000baseT_Half; 531 } 532 phy->features |= SUPPORTED_MII; 533 } 534 535 /* Setup default advertising */ 536 phy->advertising = phy->features; 537 538 return 0; 539} 540 541MODULE_LICENSE("GPL"); 542