1/* 2 * @TAG(OTHER_GPL) 3 */ 4// SPDX-License-Identifier: GPL-2.0+ 5/* 6 * (C) Copyright 2001 7 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. 8 */ 9 10/* 11 * This provides a bit-banged interface to the ethernet MII management 12 * channel. 13 */ 14 15#include "miiphy.h" 16#include "phy.h" 17 18#include "list.h" 19#include <malloc.h> 20#include "net.h" 21 22#include "../unimplemented.h" 23 24/* local debug macro */ 25#undef MII_DEBUG 26 27#undef debug 28#ifdef MII_DEBUG 29#define debug(fmt, args...) printf(fmt, ##args) 30#else 31#define debug(fmt, args...) 32#endif /* MII_DEBUG */ 33 34static struct list_head mii_devs; 35static struct mii_dev *current_mii; 36 37/* 38 * Lookup the mii_dev struct by the registered device name. 39 */ 40struct mii_dev *miiphy_get_dev_by_name(const char *devname) 41{ 42 struct list_head *entry; 43 struct mii_dev *dev; 44 45 if (!devname) { 46 printf("NULL device name!\n"); 47 return NULL; 48 } 49 50 list_for_each(entry, &mii_devs) { 51 dev = list_entry(entry, struct mii_dev, link); 52 if (strcmp(dev->name, devname) == 0) { 53 return dev; 54 } 55 } 56 57 return NULL; 58} 59 60/***************************************************************************** 61 * 62 * Initialize global data. Need to be called before any other miiphy routine. 63 */ 64void miiphy_init(void) 65{ 66 INIT_LIST_HEAD(&mii_devs); 67 current_mii = NULL; 68} 69 70struct mii_dev *mdio_alloc(void) 71{ 72 struct mii_dev *bus; 73 74 bus = malloc(sizeof(*bus)); 75 if (!bus) { 76 return bus; 77 } 78 79 memset(bus, 0, sizeof(*bus)); 80 81 /* initalize mii_dev struct fields */ 82 INIT_LIST_HEAD(&bus->link); 83 84 return bus; 85} 86 87void mdio_free(struct mii_dev *bus) 88{ 89 free(bus); 90} 91 92int mdio_register(struct mii_dev *bus) 93{ 94 if (!bus || !bus->read || !bus->write) { 95 return -1; 96 } 97 98 /* check if we have unique name */ 99 if (miiphy_get_dev_by_name(bus->name)) { 100 printf("mdio_register: non unique device name '%s'\n", 101 bus->name); 102 return -1; 103 } 104 105 /* add it to the list */ 106 list_add_tail(&bus->link, &mii_devs); 107 108 if (!current_mii) { 109 current_mii = bus; 110 } 111 112 return 0; 113} 114 115int mdio_register_seq(struct mii_dev *bus, int seq) 116{ 117 int ret; 118 119 /* Setup a unique name for each mdio bus */ 120 ret = snprintf(bus->name, MDIO_NAME_LEN, "eth%d", seq); 121 if (ret < 0) { 122 return ret; 123 } 124 125 return mdio_register(bus); 126} 127 128int mdio_unregister(struct mii_dev *bus) 129{ 130 if (!bus) { 131 return 0; 132 } 133 134 /* delete it from the list */ 135 list_del(&bus->link); 136 137 if (current_mii == bus) { 138 current_mii = NULL; 139 } 140 141 return 0; 142} 143 144void mdio_list_devices(void) 145{ 146 struct list_head *entry; 147 148 list_for_each(entry, &mii_devs) { 149 int i; 150 struct mii_dev *bus = list_entry(entry, struct mii_dev, link); 151 152 printf("%s:\n", bus->name); 153 154 for (i = 0; i < PHY_MAX_ADDR; i++) { 155 struct phy_device *phydev = bus->phymap[i]; 156 157 if (phydev) { 158 printf("%x - %s", i, phydev->drv->name); 159 160 if (phydev->dev) { 161 printf(" <--> %s\n", phydev->dev->name); 162 } else { 163 printf("\n"); 164 } 165 } 166 } 167 } 168} 169 170int miiphy_set_current_dev(const char *devname) 171{ 172 struct mii_dev *dev; 173 174 dev = miiphy_get_dev_by_name(devname); 175 if (dev) { 176 current_mii = dev; 177 return 0; 178 } 179 180 printf("No such device: %s\n", devname); 181 182 return 1; 183} 184 185struct mii_dev *mdio_get_current_dev(void) 186{ 187 return current_mii; 188} 189 190struct list_head *mdio_get_list_head(void) 191{ 192 return &mii_devs; 193} 194 195struct phy_device *mdio_phydev_for_ethname(const char *ethname) 196{ 197 struct list_head *entry; 198 struct mii_dev *bus; 199 200 list_for_each(entry, &mii_devs) { 201 int i; 202 bus = list_entry(entry, struct mii_dev, link); 203 204 for (i = 0; i < PHY_MAX_ADDR; i++) { 205 if (!bus->phymap[i] || !bus->phymap[i]->dev) { 206 continue; 207 } 208 209 if (strcmp(bus->phymap[i]->dev->name, ethname) == 0) { 210 return bus->phymap[i]; 211 } 212 } 213 } 214 215 printf("%s is not a known ethernet\n", ethname); 216 return NULL; 217} 218 219const char *miiphy_get_current_dev(void) 220{ 221 if (current_mii) { 222 return current_mii->name; 223 } 224 225 return NULL; 226} 227 228static struct mii_dev *miiphy_get_active_dev(const char *devname) 229{ 230 /* If the current mii is the one we want, return it */ 231 if (current_mii) 232 if (strcmp(current_mii->name, devname) == 0) { 233 return current_mii; 234 } 235 236 /* Otherwise, set the active one to the one we want */ 237 if (miiphy_set_current_dev(devname)) { 238 return NULL; 239 } else { 240 return current_mii; 241 } 242} 243 244/***************************************************************************** 245 * 246 * Read to variable <value> from the PHY attached to device <devname>, 247 * use PHY address <addr> and register <reg>. 248 * 249 * This API is deprecated. Use phy_read on a phy_device found via phy_connect 250 * 251 * Returns: 252 * 0 on success 253 */ 254int miiphy_read(const char *devname, unsigned char addr, unsigned char reg, 255 unsigned short *value) 256{ 257 struct mii_dev *bus; 258 int ret; 259 260 bus = miiphy_get_active_dev(devname); 261 if (!bus) { 262 return 1; 263 } 264 265 ret = bus->read(bus, addr, MDIO_DEVAD_NONE, reg); 266 if (ret < 0) { 267 return 1; 268 } 269 270 *value = (unsigned short)ret; 271 return 0; 272} 273 274/***************************************************************************** 275 * 276 * Write <value> to the PHY attached to device <devname>, 277 * use PHY address <addr> and register <reg>. 278 * 279 * This API is deprecated. Use phy_write on a phy_device found by phy_connect 280 * 281 * Returns: 282 * 0 on success 283 */ 284int miiphy_write(const char *devname, unsigned char addr, unsigned char reg, 285 unsigned short value) 286{ 287 struct mii_dev *bus; 288 289 bus = miiphy_get_active_dev(devname); 290 if (bus) { 291 return bus->write(bus, addr, MDIO_DEVAD_NONE, reg, value); 292 } 293 294 return 1; 295} 296 297/***************************************************************************** 298 * 299 * Print out list of registered MII capable devices. 300 */ 301void miiphy_listdev(void) 302{ 303 struct list_head *entry; 304 struct mii_dev *dev; 305 306 puts("MII devices: "); 307 list_for_each(entry, &mii_devs) { 308 dev = list_entry(entry, struct mii_dev, link); 309 printf("'%s' ", dev->name); 310 } 311 puts("\n"); 312 313 if (current_mii) { 314 printf("Current device: '%s'\n", current_mii->name); 315 } 316} 317 318/***************************************************************************** 319 * 320 * Read the OUI, manufacture's model number, and revision number. 321 * 322 * OUI: 22 bits (unsigned int) 323 * Model: 6 bits (unsigned char) 324 * Revision: 4 bits (unsigned char) 325 * 326 * This API is deprecated. 327 * 328 * Returns: 329 * 0 on success 330 */ 331int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui, 332 unsigned char *model, unsigned char *rev) 333{ 334 unsigned int reg = 0; 335 unsigned short tmp; 336 337 if (miiphy_read(devname, addr, MII_PHYSID2, &tmp) != 0) { 338 debug("PHY ID register 2 read failed\n"); 339 return -1; 340 } 341 reg = tmp; 342 343 debug("MII_PHYSID2 @ 0x%x = 0x%04x\n", addr, reg); 344 345 if (reg == 0xFFFF) { 346 /* No physical device present at this address */ 347 return -1; 348 } 349 350 if (miiphy_read(devname, addr, MII_PHYSID1, &tmp) != 0) { 351 debug("PHY ID register 1 read failed\n"); 352 return -1; 353 } 354 reg |= tmp << 16; 355 debug("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg); 356 357 *oui = (reg >> 10); 358 *model = (unsigned char)((reg >> 4) & 0x0000003F); 359 *rev = (unsigned char)(reg & 0x0000000F); 360 return 0; 361} 362 363// #ifndef CONFIG_PHYLIB 364/***************************************************************************** 365 * 366 * Reset the PHY. 367 * 368 * This API is deprecated. Use PHYLIB. 369 * 370 * Returns: 371 * 0 on success 372 */ 373// int miiphy_reset(const char *devname, unsigned char addr) 374// { 375// unsigned short reg; 376// int timeout = 500; 377 378// if (miiphy_read(devname, addr, MII_BMCR, ®) != 0) { 379// debug("PHY status read failed\n"); 380// return -1; 381// } 382// if (miiphy_write(devname, addr, MII_BMCR, reg | BMCR_RESET) != 0) { 383// debug("PHY reset failed\n"); 384// return -1; 385// } 386 387// // * Poll the control register for the reset bit to go to 0 (it is 388// // * auto-clearing). This should happen within 0.5 seconds per the 389// // * IEEE spec. 390 391// reg = 0x8000; 392// while (((reg & 0x8000) != 0) && timeout--) { 393// if (miiphy_read(devname, addr, MII_BMCR, ®) != 0) { 394// debug("PHY status read failed\n"); 395// return -1; 396// } 397// udelay(1000); 398// } 399// if ((reg & 0x8000) == 0) { 400// return 0; 401// } else { 402// puts("PHY reset timed out\n"); 403// return -1; 404// } 405// return 0; 406// } 407// #endif /* !PHYLIB */ 408 409/***************************************************************************** 410 * 411 * Determine the ethernet speed (10/100/1000). Return 10 on error. 412 */ 413int miiphy_speed(const char *devname, unsigned char addr) 414{ 415 u16 bmcr, anlpar, adv; 416 417#if defined(CONFIG_PHY_GIGE) 418 u16 btsr; 419 420 /* 421 * Check for 1000BASE-X. If it is supported, then assume that the speed 422 * is 1000. 423 */ 424 if (miiphy_is_1000base_x(devname, addr)) { 425 return _1000BASET; 426 } 427 428 /* 429 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set. 430 */ 431 /* Check for 1000BASE-T. */ 432 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) { 433 printf("PHY 1000BT status"); 434 goto miiphy_read_failed; 435 } 436 if (btsr != 0xFFFF && 437 (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) { 438 return _1000BASET; 439 } 440#endif /* CONFIG_PHY_GIGE */ 441 442 /* Check Basic Management Control Register first. */ 443 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) { 444 printf("PHY speed"); 445 goto miiphy_read_failed; 446 } 447 /* Check if auto-negotiation is on. */ 448 if (bmcr & BMCR_ANENABLE) { 449 /* Get auto-negotiation results. */ 450 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) { 451 printf("PHY AN speed"); 452 goto miiphy_read_failed; 453 } 454 455 if (miiphy_read(devname, addr, MII_ADVERTISE, &adv)) { 456 puts("PHY AN adv speed"); 457 goto miiphy_read_failed; 458 } 459 return ((anlpar & adv) & LPA_100) ? _100BASET : _10BASET; 460 } 461 /* Get speed from basic control settings. */ 462 return (bmcr & BMCR_SPEED100) ? _100BASET : _10BASET; 463 464miiphy_read_failed: 465 printf(" read failed, assuming 10BASE-T\n"); 466 return _10BASET; 467} 468 469/***************************************************************************** 470 * 471 * Determine full/half duplex. Return half on error. 472 */ 473int miiphy_duplex(const char *devname, unsigned char addr) 474{ 475 u16 bmcr, anlpar, adv; 476 477#if defined(CONFIG_PHY_GIGE) 478 u16 btsr; 479 480 /* Check for 1000BASE-X. */ 481 if (miiphy_is_1000base_x(devname, addr)) { 482 /* 1000BASE-X */ 483 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) { 484 printf("1000BASE-X PHY AN duplex"); 485 goto miiphy_read_failed; 486 } 487 } 488 /* 489 * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set. 490 */ 491 /* Check for 1000BASE-T. */ 492 if (miiphy_read(devname, addr, MII_STAT1000, &btsr)) { 493 printf("PHY 1000BT status"); 494 goto miiphy_read_failed; 495 } 496 if (btsr != 0xFFFF) { 497 if (btsr & PHY_1000BTSR_1000FD) { 498 return FULL; 499 } else if (btsr & PHY_1000BTSR_1000HD) { 500 return HALF; 501 } 502 } 503#endif /* CONFIG_PHY_GIGE */ 504 505 /* Check Basic Management Control Register first. */ 506 if (miiphy_read(devname, addr, MII_BMCR, &bmcr)) { 507 puts("PHY duplex"); 508 goto miiphy_read_failed; 509 } 510 /* Check if auto-negotiation is on. */ 511 if (bmcr & BMCR_ANENABLE) { 512 /* Get auto-negotiation results. */ 513 if (miiphy_read(devname, addr, MII_LPA, &anlpar)) { 514 puts("PHY AN duplex"); 515 goto miiphy_read_failed; 516 } 517 518 if (miiphy_read(devname, addr, MII_ADVERTISE, &adv)) { 519 puts("PHY AN adv duplex"); 520 goto miiphy_read_failed; 521 } 522 return ((anlpar & adv) & (LPA_10FULL | LPA_100FULL)) ? 523 FULL : HALF; 524 } 525 /* Get speed from basic control settings. */ 526 return (bmcr & BMCR_FULLDPLX) ? FULL : HALF; 527 528miiphy_read_failed: 529 printf(" read failed, assuming half duplex\n"); 530 return HALF; 531} 532 533/***************************************************************************** 534 * 535 * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/ 536 * 1000BASE-T, or on error. 537 */ 538int miiphy_is_1000base_x(const char *devname, unsigned char addr) 539{ 540#if defined(CONFIG_PHY_GIGE) 541 u16 exsr; 542 543 if (miiphy_read(devname, addr, MII_ESTATUS, &exsr)) { 544 printf("PHY extended status read failed, assuming no " 545 "1000BASE-X\n"); 546 return 0; 547 } 548 return 0 != (exsr & (ESTATUS_1000XF | ESTATUS_1000XH)); 549#else 550 return 0; 551#endif 552} 553 554#ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN 555/***************************************************************************** 556 * 557 * Determine link status 558 */ 559int miiphy_link(const char *devname, unsigned char addr) 560{ 561 unsigned short reg; 562 563 /* dummy read; needed to latch some phys */ 564 (void)miiphy_read(devname, addr, MII_BMSR, ®); 565 if (miiphy_read(devname, addr, MII_BMSR, ®)) { 566 puts("MII_BMSR read failed, assuming no link\n"); 567 return 0; 568 } 569 570 /* Determine if a link is active */ 571 if ((reg & BMSR_LSTATUS) != 0) { 572 return 1; 573 } else { 574 return 0; 575 } 576} 577#endif 578