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