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