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        char *name;
  50        int (*read) (char *devname, unsigned char addr,
  51                     unsigned char reg, unsigned short *value);
  52        int (*write) (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 *
  61 * Initialize global data. Need to be called before any other miiphy routine.
  62 */
  63void miiphy_init ()
  64{
  65        INIT_LIST_HEAD (&mii_devs);
  66        current_mii = NULL;
  67}
  68
  69/*****************************************************************************
  70 *
  71 * Register read and write MII access routines for the device <name>.
  72 */
  73void miiphy_register (char *name,
  74                      int (*read) (char *devname, unsigned char addr,
  75                                   unsigned char reg, unsigned short *value),
  76                      int (*write) (char *devname, unsigned char addr,
  77                                    unsigned char reg, unsigned short value))
  78{
  79        struct list_head *entry;
  80        struct mii_dev *new_dev;
  81        struct mii_dev *miidev;
  82        unsigned int name_len;
  83
  84        /* check if we have unique name */
  85        list_for_each (entry, &mii_devs) {
  86                miidev = list_entry (entry, struct mii_dev, link);
  87                if (strcmp (miidev->name, name) == 0) {
  88                        printf ("miiphy_register: non unique device name "
  89                                "'%s'\n", name);
  90                        return;
  91                }
  92        }
  93
  94        /* allocate memory */
  95        name_len = strlen (name);
  96        new_dev =
  97            (struct mii_dev *)malloc (sizeof (struct mii_dev) + name_len + 1);
  98
  99        if (new_dev == NULL) {
 100                printf ("miiphy_register: cannot allocate memory for '%s'\n",
 101                        name);
 102                return;
 103        }
 104        memset (new_dev, 0, sizeof (struct mii_dev) + name_len);
 105
 106        /* initalize mii_dev struct fields */
 107        INIT_LIST_HEAD (&new_dev->link);
 108        new_dev->read = read;
 109        new_dev->write = write;
 110        new_dev->name = (char *)(new_dev + 1);
 111        strncpy (new_dev->name, name, name_len);
 112        new_dev->name[name_len] = '\0';
 113
 114        debug ("miiphy_register: added '%s', read=0x%08lx, write=0x%08lx\n",
 115               new_dev->name, new_dev->read, new_dev->write);
 116
 117        /* add it to the list */
 118        list_add_tail (&new_dev->link, &mii_devs);
 119
 120        if (!current_mii)
 121                current_mii = new_dev;
 122}
 123
 124int miiphy_set_current_dev (char *devname)
 125{
 126        struct list_head *entry;
 127        struct mii_dev *dev;
 128
 129        list_for_each (entry, &mii_devs) {
 130                dev = list_entry (entry, struct mii_dev, link);
 131
 132                if (strcmp (devname, dev->name) == 0) {
 133                        current_mii = dev;
 134                        return 0;
 135                }
 136        }
 137
 138        printf ("No such device: %s\n", devname);
 139        return 1;
 140}
 141
 142char *miiphy_get_current_dev ()
 143{
 144        if (current_mii)
 145                return current_mii->name;
 146
 147        return NULL;
 148}
 149
 150/*****************************************************************************
 151 *
 152 * Read to variable <value> from the PHY attached to device <devname>,
 153 * use PHY address <addr> and register <reg>.
 154 *
 155 * Returns:
 156 *   0 on success
 157 */
 158int miiphy_read (char *devname, unsigned char addr, unsigned char reg,
 159                 unsigned short *value)
 160{
 161        struct list_head *entry;
 162        struct mii_dev *dev;
 163        int found_dev = 0;
 164        int read_ret = 0;
 165
 166        if (!devname) {
 167                printf ("NULL device name!\n");
 168                return 1;
 169        }
 170
 171        list_for_each (entry, &mii_devs) {
 172                dev = list_entry (entry, struct mii_dev, link);
 173
 174                if (strcmp (devname, dev->name) == 0) {
 175                        found_dev = 1;
 176                        read_ret = dev->read (devname, addr, reg, value);
 177                        break;
 178                }
 179        }
 180
 181        if (found_dev == 0)
 182                printf ("No such device: %s\n", devname);
 183
 184        return ((found_dev) ? read_ret : 1);
 185}
 186
 187/*****************************************************************************
 188 *
 189 * Write <value> to the PHY attached to device <devname>,
 190 * use PHY address <addr> and register <reg>.
 191 *
 192 * Returns:
 193 *   0 on success
 194 */
 195int miiphy_write (char *devname, unsigned char addr, unsigned char reg,
 196                  unsigned short value)
 197{
 198        struct list_head *entry;
 199        struct mii_dev *dev;
 200        int found_dev = 0;
 201        int write_ret = 0;
 202
 203        if (!devname) {
 204                printf ("NULL device name!\n");
 205                return 1;
 206        }
 207
 208        list_for_each (entry, &mii_devs) {
 209                dev = list_entry (entry, struct mii_dev, link);
 210
 211                if (strcmp (devname, dev->name) == 0) {
 212                        found_dev = 1;
 213                        write_ret = dev->write (devname, addr, reg, value);
 214                        break;
 215                }
 216        }
 217
 218        if (found_dev == 0)
 219                printf ("No such device: %s\n", devname);
 220
 221        return ((found_dev) ? write_ret : 1);
 222}
 223
 224/*****************************************************************************
 225 *
 226 * Print out list of registered MII capable devices.
 227 */
 228void miiphy_listdev (void)
 229{
 230        struct list_head *entry;
 231        struct mii_dev *dev;
 232
 233        puts ("MII devices: ");
 234        list_for_each (entry, &mii_devs) {
 235                dev = list_entry (entry, struct mii_dev, link);
 236                printf ("'%s' ", dev->name);
 237        }
 238        puts ("\n");
 239
 240        if (current_mii)
 241                printf ("Current device: '%s'\n", current_mii->name);
 242}
 243
 244/*****************************************************************************
 245 *
 246 * Read the OUI, manufacture's model number, and revision number.
 247 *
 248 * OUI:     22 bits (unsigned int)
 249 * Model:    6 bits (unsigned char)
 250 * Revision: 4 bits (unsigned char)
 251 *
 252 * Returns:
 253 *   0 on success
 254 */
 255int miiphy_info (char *devname, unsigned char addr, unsigned int *oui,
 256                 unsigned char *model, unsigned char *rev)
 257{
 258        unsigned int reg = 0;
 259        unsigned short tmp;
 260
 261        if (miiphy_read (devname, addr, PHY_PHYIDR2, &tmp) != 0) {
 262                debug ("PHY ID register 2 read failed\n");
 263                return (-1);
 264        }
 265        reg = tmp;
 266
 267        debug ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg);
 268
 269        if (reg == 0xFFFF) {
 270                /* No physical device present at this address */
 271                return (-1);
 272        }
 273
 274        if (miiphy_read (devname, addr, PHY_PHYIDR1, &tmp) != 0) {
 275                debug ("PHY ID register 1 read failed\n");
 276                return (-1);
 277        }
 278        reg |= tmp << 16;
 279        debug ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg);
 280
 281        *oui = (reg >> 10);
 282        *model = (unsigned char)((reg >> 4) & 0x0000003F);
 283        *rev = (unsigned char)(reg & 0x0000000F);
 284        return (0);
 285}
 286
 287/*****************************************************************************
 288 *
 289 * Reset the PHY.
 290 * Returns:
 291 *   0 on success
 292 */
 293int miiphy_reset (char *devname, unsigned char addr)
 294{
 295        unsigned short reg;
 296        int loop_cnt;
 297
 298        if (miiphy_read (devname, addr, PHY_BMCR, &reg) != 0) {
 299                debug ("PHY status read failed\n");
 300                return (-1);
 301        }
 302        if (miiphy_write (devname, addr, PHY_BMCR, reg | 0x8000) != 0) {
 303                debug ("PHY reset failed\n");
 304                return (-1);
 305        }
 306#ifdef CONFIG_PHY_RESET_DELAY
 307        udelay (CONFIG_PHY_RESET_DELAY);        /* Intel LXT971A needs this */
 308#endif
 309        /*
 310         * Poll the control register for the reset bit to go to 0 (it is
 311         * auto-clearing).  This should happen within 0.5 seconds per the
 312         * IEEE spec.
 313         */
 314        loop_cnt = 0;
 315        reg = 0x8000;
 316        while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) {
 317                if (miiphy_read (devname, addr, PHY_BMCR, &reg) != 0) {
 318                        debug ("PHY status read failed\n");
 319                        return (-1);
 320                }
 321        }
 322        if ((reg & 0x8000) == 0) {
 323                return (0);
 324        } else {
 325                puts ("PHY reset timed out\n");
 326                return (-1);
 327        }
 328        return (0);
 329}
 330
 331/*****************************************************************************
 332 *
 333 * Determine the ethernet speed (10/100/1000).  Return 10 on error.
 334 */
 335int miiphy_speed (char *devname, unsigned char addr)
 336{
 337        u16 bmcr, anlpar;
 338
 339#if defined(CONFIG_PHY_GIGE)
 340        u16 btsr;
 341
 342        /*
 343         * Check for 1000BASE-X.  If it is supported, then assume that the speed
 344         * is 1000.
 345         */
 346        if (miiphy_is_1000base_x (devname, addr)) {
 347                return _1000BASET;
 348        }
 349        /*
 350         * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
 351         */
 352        /* Check for 1000BASE-T. */
 353        if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
 354                printf ("PHY 1000BT status");
 355                goto miiphy_read_failed;
 356        }
 357        if (btsr != 0xFFFF &&
 358            (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
 359                return _1000BASET;
 360        }
 361#endif /* CONFIG_PHY_GIGE */
 362
 363        /* Check Basic Management Control Register first. */
 364        if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
 365                printf ("PHY speed");
 366                goto miiphy_read_failed;
 367        }
 368        /* Check if auto-negotiation is on. */
 369        if (bmcr & PHY_BMCR_AUTON) {
 370                /* Get auto-negotiation results. */
 371                if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
 372                        printf ("PHY AN speed");
 373                        goto miiphy_read_failed;
 374                }
 375                return (anlpar & PHY_ANLPAR_100) ? _100BASET : _10BASET;
 376        }
 377        /* Get speed from basic control settings. */
 378        return (bmcr & PHY_BMCR_100MB) ? _100BASET : _10BASET;
 379
 380      miiphy_read_failed:
 381        printf (" read failed, assuming 10BASE-T\n");
 382        return _10BASET;
 383}
 384
 385/*****************************************************************************
 386 *
 387 * Determine full/half duplex.  Return half on error.
 388 */
 389int miiphy_duplex (char *devname, unsigned char addr)
 390{
 391        u16 bmcr, anlpar;
 392
 393#if defined(CONFIG_PHY_GIGE)
 394        u16 btsr;
 395
 396        /* Check for 1000BASE-X. */
 397        if (miiphy_is_1000base_x (devname, addr)) {
 398                /* 1000BASE-X */
 399                if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
 400                        printf ("1000BASE-X PHY AN duplex");
 401                        goto miiphy_read_failed;
 402                }
 403        }
 404        /*
 405         * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
 406         */
 407        /* Check for 1000BASE-T. */
 408        if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
 409                printf ("PHY 1000BT status");
 410                goto miiphy_read_failed;
 411        }
 412        if (btsr != 0xFFFF) {
 413                if (btsr & PHY_1000BTSR_1000FD) {
 414                        return FULL;
 415                } else if (btsr & PHY_1000BTSR_1000HD) {
 416                        return HALF;
 417                }
 418        }
 419#endif /* CONFIG_PHY_GIGE */
 420
 421        /* Check Basic Management Control Register first. */
 422        if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
 423                puts ("PHY duplex");
 424                goto miiphy_read_failed;
 425        }
 426        /* Check if auto-negotiation is on. */
 427        if (bmcr & PHY_BMCR_AUTON) {
 428                /* Get auto-negotiation results. */
 429                if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
 430                        puts ("PHY AN duplex");
 431                        goto miiphy_read_failed;
 432                }
 433                return (anlpar & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) ?
 434                    FULL : HALF;
 435        }
 436        /* Get speed from basic control settings. */
 437        return (bmcr & PHY_BMCR_DPLX) ? FULL : HALF;
 438
 439      miiphy_read_failed:
 440        printf (" read failed, assuming half duplex\n");
 441        return HALF;
 442}
 443
 444/*****************************************************************************
 445 *
 446 * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
 447 * 1000BASE-T, or on error.
 448 */
 449int miiphy_is_1000base_x (char *devname, unsigned char addr)
 450{
 451#if defined(CONFIG_PHY_GIGE)
 452        u16 exsr;
 453
 454        if (miiphy_read (devname, addr, PHY_EXSR, &exsr)) {
 455                printf ("PHY extended status read failed, assuming no "
 456                        "1000BASE-X\n");
 457                return 0;
 458        }
 459        return 0 != (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH));
 460#else
 461        return 0;
 462#endif
 463}
 464
 465#ifdef CONFIG_SYS_FAULT_ECHO_LINK_DOWN
 466/*****************************************************************************
 467 *
 468 * Determine link status
 469 */
 470int miiphy_link (char *devname, unsigned char addr)
 471{
 472        unsigned short reg;
 473
 474        /* dummy read; needed to latch some phys */
 475        (void)miiphy_read (devname, addr, PHY_BMSR, &reg);
 476        if (miiphy_read (devname, addr, PHY_BMSR, &reg)) {
 477                puts ("PHY_BMSR read failed, assuming no link\n");
 478                return (0);
 479        }
 480
 481        /* Determine if a link is active */
 482        if ((reg & PHY_BMSR_LS) != 0) {
 483                return (1);
 484        } else {
 485                return (0);
 486        }
 487}
 488#endif
 489