uboot/common/miiphyutil.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24/*
  25 * This provides a bit-banged interface to the ethernet MII management
  26 * channel.
  27 */
  28
  29#include <common.h>
  30#include <miiphy.h>
  31
  32#include <asm/types.h>
  33#include <linux/list.h>
  34#include <malloc.h>
  35#include <net.h>
  36
  37/* local debug macro */
  38#undef MII_DEBUG
  39
  40#undef debug
  41#ifdef MII_DEBUG
  42#define debug(fmt,args...)      printf (fmt ,##args)
  43#else
  44#define debug(fmt,args...)
  45#endif /* MII_DEBUG */
  46
  47struct mii_dev {
  48        struct list_head link;
  49        const char *name;
  50        int (*read) (const char *devname, unsigned char addr,
  51                     unsigned char reg, unsigned short *value);
  52        int (*write) (const char *devname, unsigned char addr,
  53                      unsigned char reg, unsigned short value);
  54};
  55
  56static struct list_head mii_devs;
  57static struct mii_dev *current_mii;
  58
  59/*
  60 * Lookup the mii_dev struct by the registered device name.
  61 */
  62static struct mii_dev *miiphy_get_dev_by_name(const char *devname, int quiet)
  63{
  64        struct list_head *entry;
  65        struct mii_dev *dev;
  66
  67        if (!devname) {
  68                printf("NULL device name!\n");
  69                return NULL;
  70        }
  71
  72        list_for_each(entry, &mii_devs) {
  73                dev = list_entry(entry, struct mii_dev, link);
  74                if (strcmp(dev->name, devname) == 0)
  75                        return dev;
  76        }
  77
  78        if (!quiet)
  79                printf("No such device: %s\n", devname);
  80        return NULL;
  81}
  82
  83/*****************************************************************************
  84 *
  85 * Initialize global data. Need to be called before any other miiphy routine.
  86 */
  87void miiphy_init(void)
  88{
  89        INIT_LIST_HEAD (&mii_devs);
  90        current_mii = NULL;
  91}
  92
  93/*****************************************************************************
  94 *
  95 * Register read and write MII access routines for the device <name>.
  96 */
  97void miiphy_register(const char *name,
  98                      int (*read) (const char *devname, unsigned char addr,
  99                                   unsigned char reg, unsigned short *value),
 100                      int (*write) (const char *devname, unsigned char addr,
 101                                    unsigned char reg, unsigned short value))
 102{
 103        struct mii_dev *new_dev;
 104        unsigned int name_len;
 105        char *new_name;
 106
 107        /* check if we have unique name */
 108        new_dev = miiphy_get_dev_by_name(name, 1);
 109        if (new_dev) {
 110                printf("miiphy_register: non unique device name '%s'\n", name);
 111                return;
 112        }
 113
 114        /* allocate memory */
 115        name_len = strlen (name);
 116        new_dev =
 117            (struct mii_dev *)malloc (sizeof (struct mii_dev) + name_len + 1);
 118
 119        if (new_dev == NULL) {
 120                printf ("miiphy_register: cannot allocate memory for '%s'\n",
 121                        name);
 122                return;
 123        }
 124        memset (new_dev, 0, sizeof (struct mii_dev) + name_len);
 125
 126        /* initalize mii_dev struct fields */
 127        INIT_LIST_HEAD (&new_dev->link);
 128        new_dev->read = read;
 129        new_dev->write = write;
 130        new_dev->name = new_name = (char *)(new_dev + 1);
 131        strncpy (new_name, name, name_len);
 132        new_name[name_len] = '\0';
 133
 134        debug ("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
 135               new_dev->name, new_dev->read, new_dev->write);
 136
 137        /* add it to the list */
 138        list_add_tail (&new_dev->link, &mii_devs);
 139
 140        if (!current_mii)
 141                current_mii = new_dev;
 142}
 143
 144int miiphy_set_current_dev(const char *devname)
 145{
 146        struct mii_dev *dev;
 147
 148        dev = miiphy_get_dev_by_name(devname, 0);
 149        if (dev) {
 150                current_mii = dev;
 151                return 0;
 152        }
 153
 154        return 1;
 155}
 156
 157const char *miiphy_get_current_dev(void)
 158{
 159        if (current_mii)
 160                return current_mii->name;
 161
 162        return NULL;
 163}
 164
 165static struct mii_dev *miiphy_get_active_dev(const char *devname)
 166{
 167        /* If the current mii is the one we want, return it */
 168        if (current_mii)
 169                if (strcmp(current_mii->name, devname) == 0)
 170                        return current_mii;
 171
 172        /* Otherwise, set the active one to the one we want */
 173        if (miiphy_set_current_dev(devname))
 174                return NULL;
 175        else
 176                return current_mii;
 177}
 178
 179/*****************************************************************************
 180 *
 181 * Read to variable <value> from the PHY attached to device <devname>,
 182 * use PHY address <addr> and register <reg>.
 183 *
 184 * Returns:
 185 *   0 on success
 186 */
 187int miiphy_read(const char *devname, unsigned char addr, unsigned char reg,
 188                 unsigned short *value)
 189{
 190        struct mii_dev *dev;
 191
 192        dev = miiphy_get_active_dev(devname);
 193        if (dev)
 194                return dev->read(devname, addr, reg, value);
 195
 196        return 1;
 197}
 198
 199/*****************************************************************************
 200 *
 201 * Write <value> to the PHY attached to device <devname>,
 202 * use PHY address <addr> and register <reg>.
 203 *
 204 * Returns:
 205 *   0 on success
 206 */
 207int miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
 208                  unsigned short value)
 209{
 210        struct mii_dev *dev;
 211
 212        dev = miiphy_get_active_dev(devname);
 213        if (dev)
 214                return dev->write(devname, addr, reg, value);
 215
 216        return 1;
 217}
 218
 219/*****************************************************************************
 220 *
 221 * Print out list of registered MII capable devices.
 222 */
 223void miiphy_listdev (void)
 224{
 225        struct list_head *entry;
 226        struct mii_dev *dev;
 227
 228        puts ("MII devices: ");
 229        list_for_each (entry, &mii_devs) {
 230                dev = list_entry (entry, struct mii_dev, link);
 231                printf ("'%s' ", dev->name);
 232        }
 233        puts ("\n");
 234
 235        if (current_mii)
 236                printf ("Current device: '%s'\n", current_mii->name);
 237}
 238
 239/*****************************************************************************
 240 *
 241 * Read the OUI, manufacture's model number, and revision number.
 242 *
 243 * OUI:     22 bits (unsigned int)
 244 * Model:    6 bits (unsigned char)
 245 * Revision: 4 bits (unsigned char)
 246 *
 247 * Returns:
 248 *   0 on success
 249 */
 250int miiphy_info(const char *devname, unsigned char addr, unsigned int *oui,
 251                 unsigned char *model, unsigned char *rev)
 252{
 253        unsigned int reg = 0;
 254        unsigned short tmp;
 255
 256        if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) {
 257                debug ("PHY ID register 2 read failed\n");
 258                return (-1);
 259        }
 260        reg = tmp;
 261
 262        debug ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg);
 263
 264        if (reg == 0xFFFF) {
 265                /* No physical device present at this address */
 266                return (-1);
 267        }
 268
 269        if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) {
 270                debug ("PHY ID register 1 read failed\n");
 271                return (-1);
 272        }
 273        reg |= tmp << 16;
 274        debug ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
 275
 276        *oui = (reg >> 10);
 277        *model = (unsigned char)((reg >> 4) & 0x0000003F);
 278        *rev = (unsigned char)(reg & 0x0000000F);
 279        return (0);
 280}
 281
 282/*****************************************************************************
 283 *
 284 * Reset the PHY.
 285 * Returns:
 286 *   0 on success
 287 */
 288int miiphy_reset(const char *devname, unsigned char addr)
 289{
 290        unsigned short reg;
 291        int timeout = 500;
 292
 293        if (miiphy_read (devname, addr, PHY_BMCR, &reg) != 0) {
 294                debug ("PHY status read failed\n");
 295                return (-1);
 296        }
 297        if (miiphy_write (devname, addr, PHY_BMCR, reg | PHY_BMCR_RESET) != 0) {
 298                debug ("PHY reset failed\n");
 299                return (-1);
 300        }
 301#ifdef CONFIG_PHY_RESET_DELAY
 302        udelay (CONFIG_PHY_RESET_DELAY);        /* Intel LXT971A needs this */
 303#endif
 304        /*
 305         * Poll the control register for the reset bit to go to 0 (it is
 306         * auto-clearing).  This should happen within 0.5 seconds per the
 307         * IEEE spec.
 308         */
 309        reg = 0x8000;
 310        while (((reg & 0x8000) != 0) && timeout--) {
 311                if (miiphy_read(devname, addr, PHY_BMCR, &reg) != 0) {
 312                        debug("PHY status read failed\n");
 313                        return -1;
 314                }
 315                udelay(1000);
 316        }
 317        if ((reg & 0x8000) == 0) {
 318                return (0);
 319        } else {
 320                puts ("PHY reset timed out\n");
 321                return (-1);
 322        }
 323        return (0);
 324}
 325
 326/*****************************************************************************
 327 *
 328 * Determine the ethernet speed (10/100/1000).  Return 10 on error.
 329 */
 330int miiphy_speed(const char *devname, unsigned char addr)
 331{
 332        u16 bmcr, anlpar;
 333
 334#if defined(CONFIG_PHY_GIGE)
 335        u16 btsr;
 336
 337        /*
 338         * Check for 1000BASE-X.  If it is supported, then assume that the speed
 339         * is 1000.
 340         */
 341        if (miiphy_is_1000base_x (devname, addr)) {
 342                return _1000BASET;
 343        }
 344        /*
 345         * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
 346         */
 347        /* Check for 1000BASE-T. */
 348        if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
 349                printf ("PHY 1000BT status");
 350                goto miiphy_read_failed;
 351        }
 352        if (btsr != 0xFFFF &&
 353            (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
 354                return _1000BASET;
 355        }
 356#endif /* CONFIG_PHY_GIGE */
 357
 358        /* Check Basic Management Control Register first. */
 359        if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
 360                printf ("PHY speed");
 361                goto miiphy_read_failed;
 362        }
 363        /* Check if auto-negotiation is on. */
 364        if (bmcr & PHY_BMCR_AUTON) {
 365                /* Get auto-negotiation results. */
 366                if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
 367                        printf ("PHY AN speed");
 368                        goto miiphy_read_failed;
 369                }
 370                return (anlpar & PHY_ANLPAR_100) ? _100BASET : _10BASET;
 371        }
 372        /* Get speed from basic control settings. */
 373        return (bmcr & PHY_BMCR_100MB) ? _100BASET : _10BASET;
 374
 375miiphy_read_failed:
 376        printf (" read failed, assuming 10BASE-T\n");
 377        return _10BASET;
 378}
 379
 380/*****************************************************************************
 381 *
 382 * Determine full/half duplex.  Return half on error.
 383 */
 384int miiphy_duplex(const char *devname, unsigned char addr)
 385{
 386        u16 bmcr, anlpar;
 387
 388#if defined(CONFIG_PHY_GIGE)
 389        u16 btsr;
 390
 391        /* Check for 1000BASE-X. */
 392        if (miiphy_is_1000base_x (devname, addr)) {
 393                /* 1000BASE-X */
 394                if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
 395                        printf ("1000BASE-X PHY AN duplex");
 396                        goto miiphy_read_failed;
 397                }
 398        }
 399        /*
 400         * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
 401         */
 402        /* Check for 1000BASE-T. */
 403        if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
 404                printf ("PHY 1000BT status");
 405                goto miiphy_read_failed;
 406        }
 407        if (btsr != 0xFFFF) {
 408                if (btsr & PHY_1000BTSR_1000FD) {
 409                        return FULL;
 410                } else if (btsr & PHY_1000BTSR_1000HD) {
 411                        return HALF;
 412                }
 413        }
 414#endif /* CONFIG_PHY_GIGE */
 415
 416        /* Check Basic Management Control Register first. */
 417        if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
 418                puts ("PHY duplex");
 419                goto miiphy_read_failed;
 420        }
 421        /* Check if auto-negotiation is on. */
 422        if (bmcr & PHY_BMCR_AUTON) {
 423                /* Get auto-negotiation results. */
 424                if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
 425                        puts ("PHY AN duplex");
 426                        goto miiphy_read_failed;
 427                }
 428                return (anlpar & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) ?
 429                    FULL : HALF;
 430        }
 431        /* Get speed from basic control settings. */
 432        return (bmcr & PHY_BMCR_DPLX) ? FULL : HALF;
 433
 434miiphy_read_failed:
 435        printf (" read failed, assuming half duplex\n");
 436        return HALF;
 437}
 438
 439/*****************************************************************************
 440 *
 441 * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
 442 * 1000BASE-T, or on error.
 443 */
 444int miiphy_is_1000base_x(const char *devname, unsigned char addr)
 445{
 446#if defined(CONFIG_PHY_GIGE)
 447        u16 exsr;
 448
 449        if (miiphy_read (devname, addr, PHY_EXSR, &exsr)) {
 450                printf ("PHY extended status read failed, assuming no "
 451                        "1000BASE-X\n");
 452                return 0;
 453        }
 454        return 0 != (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH));
 455#else
 456        return 0;
 457#endif
 458}
 459
 460#ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
 461/*****************************************************************************
 462 *
 463 * Determine link status
 464 */
 465int miiphy_link(const char *devname, unsigned char addr)
 466{
 467        unsigned short reg;
 468
 469        /* dummy read; needed to latch some phys */
 470        (void)miiphy_read (devname, addr, PHY_BMSR, &reg);
 471        if (miiphy_read (devname, addr, PHY_BMSR, &reg)) {
 472                puts ("PHY_BMSR read failed, assuming no link\n");
 473                return (0);
 474        }
 475
 476        /* Determine if a link is active */
 477        if ((reg & PHY_BMSR_LS) != 0) {
 478                return (1);
 479        } else {
 480                return (0);
 481        }
 482}
 483#endif
 484