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