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