uboot/drivers/qe/uec_phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2005,2010-2011 Freescale Semiconductor, Inc.
   4 *
   5 * Author: Shlomi Gridish
   6 *
   7 * Description: UCC GETH Driver -- PHY handling
   8 *              Driver for UEC on QE
   9 *              Based on 8260_io/fcc_enet.c
  10 */
  11
  12#include <common.h>
  13#include <net.h>
  14#include <malloc.h>
  15#include <linux/errno.h>
  16#include <linux/immap_qe.h>
  17#include <asm/io.h>
  18#include "uccf.h"
  19#include "uec.h"
  20#include "uec_phy.h"
  21#include "miiphy.h"
  22#include <fsl_qe.h>
  23#include <phy.h>
  24
  25#define ugphy_printk(format, arg...)  \
  26        printf(format "\n", ## arg)
  27
  28#define ugphy_dbg(format, arg...)            \
  29        ugphy_printk(format , ## arg)
  30#define ugphy_err(format, arg...)            \
  31        ugphy_printk(format , ## arg)
  32#define ugphy_info(format, arg...)           \
  33        ugphy_printk(format , ## arg)
  34#define ugphy_warn(format, arg...)           \
  35        ugphy_printk(format , ## arg)
  36
  37#ifdef UEC_VERBOSE_DEBUG
  38#define ugphy_vdbg ugphy_dbg
  39#else
  40#define ugphy_vdbg(ugeth, fmt, args...) do { } while (0)
  41#endif /* UEC_VERBOSE_DEBUG */
  42
  43/*--------------------------------------------------------------------+
  44 * Fixed PHY (PHY-less) support for Ethernet Ports.
  45 *
  46 * Copied from arch/powerpc/cpu/ppc4xx/4xx_enet.c
  47 *--------------------------------------------------------------------*/
  48
  49/*
  50 * Some boards do not have a PHY for each ethernet port. These ports are known
  51 * as Fixed PHY (or PHY-less) ports. For such ports, set the appropriate
  52 * CONFIG_SYS_UECx_PHY_ADDR equal to CONFIG_FIXED_PHY_ADDR (an unused address)
  53 * When the drver tries to identify the PHYs, CONFIG_FIXED_PHY will be returned
  54 * and the driver will search CONFIG_SYS_FIXED_PHY_PORTS to find what network
  55 * speed and duplex should be for the port.
  56 *
  57 * Example board header configuration file:
  58 *     #define CONFIG_FIXED_PHY   0xFFFFFFFF
  59 *     #define CONFIG_SYS_FIXED_PHY_ADDR 0x1E (pick an unused phy address)
  60 *
  61 *     #define CONFIG_SYS_UEC1_PHY_ADDR CONFIG_SYS_FIXED_PHY_ADDR
  62 *     #define CONFIG_SYS_UEC2_PHY_ADDR 0x02
  63 *     #define CONFIG_SYS_UEC3_PHY_ADDR CONFIG_SYS_FIXED_PHY_ADDR
  64 *     #define CONFIG_SYS_UEC4_PHY_ADDR 0x04
  65 *
  66 *     #define CONFIG_SYS_FIXED_PHY_PORT(name,speed,duplex) \
  67 *                 {name, speed, duplex},
  68 *
  69 *     #define CONFIG_SYS_FIXED_PHY_PORTS \
  70 *                 CONFIG_SYS_FIXED_PHY_PORT("UEC0",SPEED_100,DUPLEX_FULL) \
  71 *                 CONFIG_SYS_FIXED_PHY_PORT("UEC2",SPEED_100,DUPLEX_HALF)
  72 */
  73
  74#ifndef CONFIG_FIXED_PHY
  75#define CONFIG_FIXED_PHY        0xFFFFFFFF /* Fixed PHY (PHY-less) */
  76#endif
  77
  78#ifndef CONFIG_SYS_FIXED_PHY_PORTS
  79#define CONFIG_SYS_FIXED_PHY_PORTS      /* default is an empty array */
  80#endif
  81
  82struct fixed_phy_port {
  83        char name[16];  /* ethernet port name */
  84        unsigned int speed;     /* specified speed 10,100 or 1000 */
  85        unsigned int duplex;    /* specified duplex FULL or HALF */
  86};
  87
  88static const struct fixed_phy_port fixed_phy_port[] = {
  89        CONFIG_SYS_FIXED_PHY_PORTS /* defined in board configuration file */
  90};
  91
  92/*--------------------------------------------------------------------+
  93 * BitBang MII support for ethernet ports
  94 *
  95 * Based from MPC8560ADS implementation
  96 *--------------------------------------------------------------------*/
  97/*
  98 * Example board header file to define bitbang ethernet ports:
  99 *
 100 * #define CONFIG_SYS_BITBANG_PHY_PORT(name) name,
 101 * #define CONFIG_SYS_BITBANG_PHY_PORTS CONFIG_SYS_BITBANG_PHY_PORT("UEC0")
 102*/
 103#ifndef CONFIG_SYS_BITBANG_PHY_PORTS
 104#define CONFIG_SYS_BITBANG_PHY_PORTS    /* default is an empty array */
 105#endif
 106
 107#if defined(CONFIG_BITBANGMII)
 108static const char *bitbang_phy_port[] = {
 109        CONFIG_SYS_BITBANG_PHY_PORTS /* defined in board configuration file */
 110};
 111#endif /* CONFIG_BITBANGMII */
 112
 113static void config_genmii_advert (struct uec_mii_info *mii_info);
 114static void genmii_setup_forced (struct uec_mii_info *mii_info);
 115static void genmii_restart_aneg (struct uec_mii_info *mii_info);
 116static int gbit_config_aneg (struct uec_mii_info *mii_info);
 117static int genmii_config_aneg (struct uec_mii_info *mii_info);
 118static int genmii_update_link (struct uec_mii_info *mii_info);
 119static int genmii_read_status (struct uec_mii_info *mii_info);
 120u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum);
 121void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val);
 122
 123/* Write value to the PHY for this device to the register at regnum, */
 124/* waiting until the write is done before it returns.  All PHY */
 125/* configuration has to be done through the TSEC1 MIIM regs */
 126void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int value)
 127{
 128        uec_private_t *ugeth = (uec_private_t *) dev->priv;
 129        uec_mii_t *ug_regs;
 130        enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
 131        u32 tmp_reg;
 132
 133
 134#if defined(CONFIG_BITBANGMII)
 135        u32 i = 0;
 136
 137        for (i = 0; i < ARRAY_SIZE(bitbang_phy_port); i++) {
 138                if (strncmp(dev->name, bitbang_phy_port[i],
 139                        sizeof(dev->name)) == 0) {
 140                        (void)bb_miiphy_write(NULL, mii_id, regnum, value);
 141                        return;
 142                }
 143        }
 144#endif /* CONFIG_BITBANGMII */
 145
 146        ug_regs = ugeth->uec_mii_regs;
 147
 148        /* Stop the MII management read cycle */
 149        out_be32 (&ug_regs->miimcom, 0);
 150        /* Setting up the MII Mangement Address Register */
 151        tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
 152        out_be32 (&ug_regs->miimadd, tmp_reg);
 153
 154        /* Setting up the MII Mangement Control Register with the value */
 155        out_be32 (&ug_regs->miimcon, (u32) value);
 156        sync();
 157
 158        /* Wait till MII management write is complete */
 159        while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY);
 160}
 161
 162/* Reads from register regnum in the PHY for device dev, */
 163/* returning the value.  Clears miimcom first.  All PHY */
 164/* configuration has to be done through the TSEC1 MIIM regs */
 165int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum)
 166{
 167        uec_private_t *ugeth = (uec_private_t *) dev->priv;
 168        uec_mii_t *ug_regs;
 169        enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum;
 170        u32 tmp_reg;
 171        u16 value;
 172
 173
 174#if defined(CONFIG_BITBANGMII)
 175        u32 i = 0;
 176
 177        for (i = 0; i < ARRAY_SIZE(bitbang_phy_port); i++) {
 178                if (strncmp(dev->name, bitbang_phy_port[i],
 179                        sizeof(dev->name)) == 0) {
 180                        (void)bb_miiphy_read(NULL, mii_id, regnum, &value);
 181                        return (value);
 182                }
 183        }
 184#endif /* CONFIG_BITBANGMII */
 185
 186        ug_regs = ugeth->uec_mii_regs;
 187
 188        /* Setting up the MII Mangement Address Register */
 189        tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg;
 190        out_be32 (&ug_regs->miimadd, tmp_reg);
 191
 192        /* clear MII management command cycle */
 193        out_be32 (&ug_regs->miimcom, 0);
 194        sync();
 195
 196        /* Perform an MII management read cycle */
 197        out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE);
 198
 199        /* Wait till MII management write is complete */
 200        while ((in_be32 (&ug_regs->miimind)) &
 201               (MIIMIND_NOT_VALID | MIIMIND_BUSY));
 202
 203        /* Read MII management status  */
 204        value = (u16) in_be32 (&ug_regs->miimstat);
 205        if (value == 0xffff)
 206                ugphy_vdbg
 207                        ("read wrong value : mii_id %d,mii_reg %d, base %08x",
 208                         mii_id, mii_reg, (u32) & (ug_regs->miimcfg));
 209
 210        return (value);
 211}
 212
 213void mii_clear_phy_interrupt (struct uec_mii_info *mii_info)
 214{
 215        if (mii_info->phyinfo->ack_interrupt)
 216                mii_info->phyinfo->ack_interrupt (mii_info);
 217}
 218
 219void mii_configure_phy_interrupt (struct uec_mii_info *mii_info,
 220                                  u32 interrupts)
 221{
 222        mii_info->interrupts = interrupts;
 223        if (mii_info->phyinfo->config_intr)
 224                mii_info->phyinfo->config_intr (mii_info);
 225}
 226
 227/* Writes MII_ADVERTISE with the appropriate values, after
 228 * sanitizing advertise to make sure only supported features
 229 * are advertised
 230 */
 231static void config_genmii_advert (struct uec_mii_info *mii_info)
 232{
 233        u32 advertise;
 234        u16 adv;
 235
 236        /* Only allow advertising what this PHY supports */
 237        mii_info->advertising &= mii_info->phyinfo->features;
 238        advertise = mii_info->advertising;
 239
 240        /* Setup standard advertisement */
 241        adv = uec_phy_read(mii_info, MII_ADVERTISE);
 242        adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
 243        if (advertise & ADVERTISED_10baseT_Half)
 244                adv |= ADVERTISE_10HALF;
 245        if (advertise & ADVERTISED_10baseT_Full)
 246                adv |= ADVERTISE_10FULL;
 247        if (advertise & ADVERTISED_100baseT_Half)
 248                adv |= ADVERTISE_100HALF;
 249        if (advertise & ADVERTISED_100baseT_Full)
 250                adv |= ADVERTISE_100FULL;
 251        uec_phy_write(mii_info, MII_ADVERTISE, adv);
 252}
 253
 254static void genmii_setup_forced (struct uec_mii_info *mii_info)
 255{
 256        u16 ctrl;
 257        u32 features = mii_info->phyinfo->features;
 258
 259        ctrl = uec_phy_read(mii_info, MII_BMCR);
 260
 261        ctrl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 |
 262                  BMCR_SPEED1000 | BMCR_ANENABLE);
 263        ctrl |= BMCR_RESET;
 264
 265        switch (mii_info->speed) {
 266        case SPEED_1000:
 267                if (features & (SUPPORTED_1000baseT_Half
 268                                | SUPPORTED_1000baseT_Full)) {
 269                        ctrl |= BMCR_SPEED1000;
 270                        break;
 271                }
 272                mii_info->speed = SPEED_100;
 273        case SPEED_100:
 274                if (features & (SUPPORTED_100baseT_Half
 275                                | SUPPORTED_100baseT_Full)) {
 276                        ctrl |= BMCR_SPEED100;
 277                        break;
 278                }
 279                mii_info->speed = SPEED_10;
 280        case SPEED_10:
 281                if (features & (SUPPORTED_10baseT_Half
 282                                | SUPPORTED_10baseT_Full))
 283                        break;
 284        default:                /* Unsupported speed! */
 285                ugphy_err ("%s: Bad speed!", mii_info->dev->name);
 286                break;
 287        }
 288
 289        uec_phy_write(mii_info, MII_BMCR, ctrl);
 290}
 291
 292/* Enable and Restart Autonegotiation */
 293static void genmii_restart_aneg (struct uec_mii_info *mii_info)
 294{
 295        u16 ctl;
 296
 297        ctl = uec_phy_read(mii_info, MII_BMCR);
 298        ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
 299        uec_phy_write(mii_info, MII_BMCR, ctl);
 300}
 301
 302static int gbit_config_aneg (struct uec_mii_info *mii_info)
 303{
 304        u16 adv;
 305        u32 advertise;
 306
 307        if (mii_info->autoneg) {
 308                /* Configure the ADVERTISE register */
 309                config_genmii_advert (mii_info);
 310                advertise = mii_info->advertising;
 311
 312                adv = uec_phy_read(mii_info, MII_CTRL1000);
 313                adv &= ~(ADVERTISE_1000FULL |
 314                         ADVERTISE_1000HALF);
 315                if (advertise & SUPPORTED_1000baseT_Half)
 316                        adv |= ADVERTISE_1000HALF;
 317                if (advertise & SUPPORTED_1000baseT_Full)
 318                        adv |= ADVERTISE_1000FULL;
 319                uec_phy_write(mii_info, MII_CTRL1000, adv);
 320
 321                /* Start/Restart aneg */
 322                genmii_restart_aneg (mii_info);
 323        } else
 324                genmii_setup_forced (mii_info);
 325
 326        return 0;
 327}
 328
 329static int marvell_config_aneg (struct uec_mii_info *mii_info)
 330{
 331        /* The Marvell PHY has an errata which requires
 332         * that certain registers get written in order
 333         * to restart autonegotiation */
 334        uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
 335
 336        uec_phy_write(mii_info, 0x1d, 0x1f);
 337        uec_phy_write(mii_info, 0x1e, 0x200c);
 338        uec_phy_write(mii_info, 0x1d, 0x5);
 339        uec_phy_write(mii_info, 0x1e, 0);
 340        uec_phy_write(mii_info, 0x1e, 0x100);
 341
 342        gbit_config_aneg (mii_info);
 343
 344        return 0;
 345}
 346
 347static int genmii_config_aneg (struct uec_mii_info *mii_info)
 348{
 349        if (mii_info->autoneg) {
 350                /* Speed up the common case, if link is already up, speed and
 351                   duplex match, skip auto neg as it already matches */
 352                if (!genmii_read_status(mii_info) && mii_info->link)
 353                        if (mii_info->duplex == DUPLEX_FULL &&
 354                            mii_info->speed == SPEED_100)
 355                                if (mii_info->advertising &
 356                                    ADVERTISED_100baseT_Full)
 357                                        return 0;
 358
 359                config_genmii_advert (mii_info);
 360                genmii_restart_aneg (mii_info);
 361        } else
 362                genmii_setup_forced (mii_info);
 363
 364        return 0;
 365}
 366
 367static int genmii_update_link (struct uec_mii_info *mii_info)
 368{
 369        u16 status;
 370
 371        /* Status is read once to clear old link state */
 372        uec_phy_read(mii_info, MII_BMSR);
 373
 374        /*
 375         * Wait if the link is up, and autonegotiation is in progress
 376         * (ie - we're capable and it's not done)
 377         */
 378        status = uec_phy_read(mii_info, MII_BMSR);
 379        if ((status & BMSR_LSTATUS) && (status & BMSR_ANEGCAPABLE)
 380            && !(status & BMSR_ANEGCOMPLETE)) {
 381                int i = 0;
 382
 383                while (!(status & BMSR_ANEGCOMPLETE)) {
 384                        /*
 385                         * Timeout reached ?
 386                         */
 387                        if (i > UGETH_AN_TIMEOUT) {
 388                                mii_info->link = 0;
 389                                return 0;
 390                        }
 391
 392                        i++;
 393                        udelay(1000);   /* 1 ms */
 394                        status = uec_phy_read(mii_info, MII_BMSR);
 395                }
 396                mii_info->link = 1;
 397        } else {
 398                if (status & BMSR_LSTATUS)
 399                        mii_info->link = 1;
 400                else
 401                        mii_info->link = 0;
 402        }
 403
 404        return 0;
 405}
 406
 407static int genmii_read_status (struct uec_mii_info *mii_info)
 408{
 409        u16 status;
 410        int err;
 411
 412        /* Update the link, but return if there
 413         * was an error */
 414        err = genmii_update_link (mii_info);
 415        if (err)
 416                return err;
 417
 418        if (mii_info->autoneg) {
 419                status = uec_phy_read(mii_info, MII_STAT1000);
 420
 421                if (status & (LPA_1000FULL | LPA_1000HALF)) {
 422                        mii_info->speed = SPEED_1000;
 423                        if (status & LPA_1000FULL)
 424                                mii_info->duplex = DUPLEX_FULL;
 425                        else
 426                                mii_info->duplex = DUPLEX_HALF;
 427                } else {
 428                        status = uec_phy_read(mii_info, MII_LPA);
 429
 430                        if (status & (LPA_10FULL | LPA_100FULL))
 431                                mii_info->duplex = DUPLEX_FULL;
 432                        else
 433                                mii_info->duplex = DUPLEX_HALF;
 434                        if (status & (LPA_100FULL | LPA_100HALF))
 435                                mii_info->speed = SPEED_100;
 436                        else
 437                                mii_info->speed = SPEED_10;
 438                }
 439                mii_info->pause = 0;
 440        }
 441        /* On non-aneg, we assume what we put in BMCR is the speed,
 442         * though magic-aneg shouldn't prevent this case from occurring
 443         */
 444
 445        return 0;
 446}
 447
 448static int bcm_init(struct uec_mii_info *mii_info)
 449{
 450        struct eth_device *edev = mii_info->dev;
 451        uec_private_t *uec = edev->priv;
 452
 453        gbit_config_aneg(mii_info);
 454
 455        if ((uec->uec_info->enet_interface_type ==
 456                                PHY_INTERFACE_MODE_RGMII_RXID) &&
 457                        (uec->uec_info->speed == SPEED_1000)) {
 458                u16 val;
 459                int cnt = 50;
 460
 461                /* Wait for aneg to complete. */
 462                do
 463                        val = uec_phy_read(mii_info, MII_BMSR);
 464                while (--cnt && !(val & BMSR_ANEGCOMPLETE));
 465
 466                /* Set RDX clk delay. */
 467                uec_phy_write(mii_info, 0x18, 0x7 | (7 << 12));
 468
 469                val = uec_phy_read(mii_info, 0x18);
 470                /* Set RDX-RXC skew. */
 471                val |= (1 << 8);
 472                val |= (7 | (7 << 12));
 473                /* Write bits 14:0. */
 474                val |= (1 << 15);
 475                uec_phy_write(mii_info, 0x18, val);
 476        }
 477
 478         return 0;
 479}
 480
 481static int uec_marvell_init(struct uec_mii_info *mii_info)
 482{
 483        struct eth_device *edev = mii_info->dev;
 484        uec_private_t *uec = edev->priv;
 485        phy_interface_t iface = uec->uec_info->enet_interface_type;
 486        int     speed = uec->uec_info->speed;
 487
 488        if ((speed == SPEED_1000) &&
 489           (iface == PHY_INTERFACE_MODE_RGMII_ID ||
 490            iface == PHY_INTERFACE_MODE_RGMII_RXID ||
 491            iface == PHY_INTERFACE_MODE_RGMII_TXID)) {
 492                int temp;
 493
 494                temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_CR);
 495                if (iface == PHY_INTERFACE_MODE_RGMII_ID) {
 496                        temp |= MII_M1111_RX_DELAY | MII_M1111_TX_DELAY;
 497                } else if (iface == PHY_INTERFACE_MODE_RGMII_RXID) {
 498                        temp &= ~MII_M1111_TX_DELAY;
 499                        temp |= MII_M1111_RX_DELAY;
 500                } else if (iface == PHY_INTERFACE_MODE_RGMII_TXID) {
 501                        temp &= ~MII_M1111_RX_DELAY;
 502                        temp |= MII_M1111_TX_DELAY;
 503                }
 504                uec_phy_write(mii_info, MII_M1111_PHY_EXT_CR, temp);
 505
 506                temp = uec_phy_read(mii_info, MII_M1111_PHY_EXT_SR);
 507                temp &= ~MII_M1111_HWCFG_MODE_MASK;
 508                temp |= MII_M1111_HWCFG_MODE_RGMII;
 509                uec_phy_write(mii_info, MII_M1111_PHY_EXT_SR, temp);
 510
 511                uec_phy_write(mii_info, MII_BMCR, BMCR_RESET);
 512        }
 513
 514        return 0;
 515}
 516
 517static int marvell_read_status (struct uec_mii_info *mii_info)
 518{
 519        u16 status;
 520        int err;
 521
 522        /* Update the link, but return if there
 523         * was an error */
 524        err = genmii_update_link (mii_info);
 525        if (err)
 526                return err;
 527
 528        /* If the link is up, read the speed and duplex */
 529        /* If we aren't autonegotiating, assume speeds
 530         * are as set */
 531        if (mii_info->autoneg && mii_info->link) {
 532                int speed;
 533
 534                status = uec_phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS);
 535
 536                /* Get the duplexity */
 537                if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX)
 538                        mii_info->duplex = DUPLEX_FULL;
 539                else
 540                        mii_info->duplex = DUPLEX_HALF;
 541
 542                /* Get the speed */
 543                speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK;
 544                switch (speed) {
 545                case MII_M1011_PHY_SPEC_STATUS_1000:
 546                        mii_info->speed = SPEED_1000;
 547                        break;
 548                case MII_M1011_PHY_SPEC_STATUS_100:
 549                        mii_info->speed = SPEED_100;
 550                        break;
 551                default:
 552                        mii_info->speed = SPEED_10;
 553                        break;
 554                }
 555                mii_info->pause = 0;
 556        }
 557
 558        return 0;
 559}
 560
 561static int marvell_ack_interrupt (struct uec_mii_info *mii_info)
 562{
 563        /* Clear the interrupts by reading the reg */
 564        uec_phy_read(mii_info, MII_M1011_IEVENT);
 565
 566        return 0;
 567}
 568
 569static int marvell_config_intr (struct uec_mii_info *mii_info)
 570{
 571        if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
 572                uec_phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT);
 573        else
 574                uec_phy_write(mii_info, MII_M1011_IMASK,
 575                                MII_M1011_IMASK_CLEAR);
 576
 577        return 0;
 578}
 579
 580static int dm9161_init (struct uec_mii_info *mii_info)
 581{
 582        /* Reset the PHY */
 583        uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) |
 584                   BMCR_RESET);
 585        /* PHY and MAC connect */
 586        uec_phy_write(mii_info, MII_BMCR, uec_phy_read(mii_info, MII_BMCR) &
 587                   ~BMCR_ISOLATE);
 588
 589        uec_phy_write(mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT);
 590
 591        config_genmii_advert (mii_info);
 592        /* Start/restart aneg */
 593        genmii_config_aneg (mii_info);
 594
 595        return 0;
 596}
 597
 598static int dm9161_config_aneg (struct uec_mii_info *mii_info)
 599{
 600        return 0;
 601}
 602
 603static int dm9161_read_status (struct uec_mii_info *mii_info)
 604{
 605        u16 status;
 606        int err;
 607
 608        /* Update the link, but return if there was an error */
 609        err = genmii_update_link (mii_info);
 610        if (err)
 611                return err;
 612        /* If the link is up, read the speed and duplex
 613           If we aren't autonegotiating assume speeds are as set */
 614        if (mii_info->autoneg && mii_info->link) {
 615                status = uec_phy_read(mii_info, MII_DM9161_SCSR);
 616                if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H))
 617                        mii_info->speed = SPEED_100;
 618                else
 619                        mii_info->speed = SPEED_10;
 620
 621                if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F))
 622                        mii_info->duplex = DUPLEX_FULL;
 623                else
 624                        mii_info->duplex = DUPLEX_HALF;
 625        }
 626
 627        return 0;
 628}
 629
 630static int dm9161_ack_interrupt (struct uec_mii_info *mii_info)
 631{
 632        /* Clear the interrupt by reading the reg */
 633        uec_phy_read(mii_info, MII_DM9161_INTR);
 634
 635        return 0;
 636}
 637
 638static int dm9161_config_intr (struct uec_mii_info *mii_info)
 639{
 640        if (mii_info->interrupts == MII_INTERRUPT_ENABLED)
 641                uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT);
 642        else
 643                uec_phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP);
 644
 645        return 0;
 646}
 647
 648static void dm9161_close (struct uec_mii_info *mii_info)
 649{
 650}
 651
 652static int fixed_phy_aneg (struct uec_mii_info *mii_info)
 653{
 654        mii_info->autoneg = 0; /* Turn off auto negotiation for fixed phy */
 655        return 0;
 656}
 657
 658static int fixed_phy_read_status (struct uec_mii_info *mii_info)
 659{
 660        int i = 0;
 661
 662        for (i = 0; i < ARRAY_SIZE(fixed_phy_port); i++) {
 663                if (strncmp(mii_info->dev->name, fixed_phy_port[i].name,
 664                                strlen(mii_info->dev->name)) == 0) {
 665                        mii_info->speed = fixed_phy_port[i].speed;
 666                        mii_info->duplex = fixed_phy_port[i].duplex;
 667                        mii_info->link = 1; /* Link is always UP */
 668                        mii_info->pause = 0;
 669                        break;
 670                }
 671        }
 672        return 0;
 673}
 674
 675static int smsc_config_aneg (struct uec_mii_info *mii_info)
 676{
 677        return 0;
 678}
 679
 680static int smsc_read_status (struct uec_mii_info *mii_info)
 681{
 682        u16 status;
 683        int err;
 684
 685        /* Update the link, but return if there
 686         * was an error */
 687        err = genmii_update_link (mii_info);
 688        if (err)
 689                return err;
 690
 691        /* If the link is up, read the speed and duplex */
 692        /* If we aren't autonegotiating, assume speeds
 693         * are as set */
 694        if (mii_info->autoneg && mii_info->link) {
 695                int     val;
 696
 697                status = uec_phy_read(mii_info, 0x1f);
 698                val = (status & 0x1c) >> 2;
 699
 700                switch (val) {
 701                        case 1:
 702                                mii_info->duplex = DUPLEX_HALF;
 703                                mii_info->speed = SPEED_10;
 704                                break;
 705                        case 5:
 706                                mii_info->duplex = DUPLEX_FULL;
 707                                mii_info->speed = SPEED_10;
 708                                break;
 709                        case 2:
 710                                mii_info->duplex = DUPLEX_HALF;
 711                                mii_info->speed = SPEED_100;
 712                                break;
 713                        case 6:
 714                                mii_info->duplex = DUPLEX_FULL;
 715                                mii_info->speed = SPEED_100;
 716                                break;
 717                }
 718                mii_info->pause = 0;
 719        }
 720
 721        return 0;
 722}
 723
 724static struct phy_info phy_info_dm9161 = {
 725        .phy_id = 0x0181b880,
 726        .phy_id_mask = 0x0ffffff0,
 727        .name = "Davicom DM9161E",
 728        .init = dm9161_init,
 729        .config_aneg = dm9161_config_aneg,
 730        .read_status = dm9161_read_status,
 731        .close = dm9161_close,
 732};
 733
 734static struct phy_info phy_info_dm9161a = {
 735        .phy_id = 0x0181b8a0,
 736        .phy_id_mask = 0x0ffffff0,
 737        .name = "Davicom DM9161A",
 738        .features = MII_BASIC_FEATURES,
 739        .init = dm9161_init,
 740        .config_aneg = dm9161_config_aneg,
 741        .read_status = dm9161_read_status,
 742        .ack_interrupt = dm9161_ack_interrupt,
 743        .config_intr = dm9161_config_intr,
 744        .close = dm9161_close,
 745};
 746
 747static struct phy_info phy_info_marvell = {
 748        .phy_id = 0x01410c00,
 749        .phy_id_mask = 0xffffff00,
 750        .name = "Marvell 88E11x1",
 751        .features = MII_GBIT_FEATURES,
 752        .init = &uec_marvell_init,
 753        .config_aneg = &marvell_config_aneg,
 754        .read_status = &marvell_read_status,
 755        .ack_interrupt = &marvell_ack_interrupt,
 756        .config_intr = &marvell_config_intr,
 757};
 758
 759static struct phy_info phy_info_bcm5481 = {
 760        .phy_id = 0x0143bca0,
 761        .phy_id_mask = 0xffffff0,
 762        .name = "Broadcom 5481",
 763        .features = MII_GBIT_FEATURES,
 764        .read_status = genmii_read_status,
 765        .init = bcm_init,
 766};
 767
 768static struct phy_info phy_info_fixedphy = {
 769        .phy_id = CONFIG_FIXED_PHY,
 770        .phy_id_mask = CONFIG_FIXED_PHY,
 771        .name = "Fixed PHY",
 772        .config_aneg = fixed_phy_aneg,
 773        .read_status = fixed_phy_read_status,
 774};
 775
 776static struct phy_info phy_info_smsclan8700 = {
 777        .phy_id = 0x0007c0c0,
 778        .phy_id_mask = 0xfffffff0,
 779        .name = "SMSC LAN8700",
 780        .features = MII_BASIC_FEATURES,
 781        .config_aneg = smsc_config_aneg,
 782        .read_status = smsc_read_status,
 783};
 784
 785static struct phy_info phy_info_genmii = {
 786        .phy_id = 0x00000000,
 787        .phy_id_mask = 0x00000000,
 788        .name = "Generic MII",
 789        .features = MII_BASIC_FEATURES,
 790        .config_aneg = genmii_config_aneg,
 791        .read_status = genmii_read_status,
 792};
 793
 794static struct phy_info *phy_info[] = {
 795        &phy_info_dm9161,
 796        &phy_info_dm9161a,
 797        &phy_info_marvell,
 798        &phy_info_bcm5481,
 799        &phy_info_smsclan8700,
 800        &phy_info_fixedphy,
 801        &phy_info_genmii,
 802        NULL
 803};
 804
 805u16 uec_phy_read(struct uec_mii_info *mii_info, u16 regnum)
 806{
 807        return mii_info->mdio_read (mii_info->dev, mii_info->mii_id, regnum);
 808}
 809
 810void uec_phy_write(struct uec_mii_info *mii_info, u16 regnum, u16 val)
 811{
 812        mii_info->mdio_write (mii_info->dev, mii_info->mii_id, regnum, val);
 813}
 814
 815/* Use the PHY ID registers to determine what type of PHY is attached
 816 * to device dev.  return a struct phy_info structure describing that PHY
 817 */
 818struct phy_info *uec_get_phy_info (struct uec_mii_info *mii_info)
 819{
 820        u16 phy_reg;
 821        u32 phy_ID;
 822        int i;
 823        struct phy_info *theInfo = NULL;
 824
 825        /* Grab the bits from PHYIR1, and put them in the upper half */
 826        phy_reg = uec_phy_read(mii_info, MII_PHYSID1);
 827        phy_ID = (phy_reg & 0xffff) << 16;
 828
 829        /* Grab the bits from PHYIR2, and put them in the lower half */
 830        phy_reg = uec_phy_read(mii_info, MII_PHYSID2);
 831        phy_ID |= (phy_reg & 0xffff);
 832
 833        /* loop through all the known PHY types, and find one that */
 834        /* matches the ID we read from the PHY. */
 835        for (i = 0; phy_info[i]; i++)
 836                if (phy_info[i]->phy_id ==
 837                    (phy_ID & phy_info[i]->phy_id_mask)) {
 838                        theInfo = phy_info[i];
 839                        break;
 840                }
 841
 842        /* This shouldn't happen, as we have generic PHY support */
 843        if (theInfo == NULL) {
 844                ugphy_info ("UEC: PHY id %x is not supported!", phy_ID);
 845                return NULL;
 846        } else {
 847                ugphy_info ("UEC: PHY is %s (%x)", theInfo->name, phy_ID);
 848        }
 849
 850        return theInfo;
 851}
 852
 853void marvell_phy_interface_mode(struct eth_device *dev, phy_interface_t type,
 854                int speed)
 855{
 856        uec_private_t *uec = (uec_private_t *) dev->priv;
 857        struct uec_mii_info *mii_info;
 858        u16 status;
 859
 860        if (!uec->mii_info) {
 861                printf ("%s: the PHY not initialized\n", __FUNCTION__);
 862                return;
 863        }
 864        mii_info = uec->mii_info;
 865
 866        if (type == PHY_INTERFACE_MODE_RGMII) {
 867                if (speed == SPEED_100) {
 868                        uec_phy_write(mii_info, 0x00, 0x9140);
 869                        uec_phy_write(mii_info, 0x1d, 0x001f);
 870                        uec_phy_write(mii_info, 0x1e, 0x200c);
 871                        uec_phy_write(mii_info, 0x1d, 0x0005);
 872                        uec_phy_write(mii_info, 0x1e, 0x0000);
 873                        uec_phy_write(mii_info, 0x1e, 0x0100);
 874                        uec_phy_write(mii_info, 0x09, 0x0e00);
 875                        uec_phy_write(mii_info, 0x04, 0x01e1);
 876                        uec_phy_write(mii_info, 0x00, 0x9140);
 877                        uec_phy_write(mii_info, 0x00, 0x1000);
 878                        udelay (100000);
 879                        uec_phy_write(mii_info, 0x00, 0x2900);
 880                        uec_phy_write(mii_info, 0x14, 0x0cd2);
 881                        uec_phy_write(mii_info, 0x00, 0xa100);
 882                        uec_phy_write(mii_info, 0x09, 0x0000);
 883                        uec_phy_write(mii_info, 0x1b, 0x800b);
 884                        uec_phy_write(mii_info, 0x04, 0x05e1);
 885                        uec_phy_write(mii_info, 0x00, 0xa100);
 886                        uec_phy_write(mii_info, 0x00, 0x2100);
 887                        udelay (1000000);
 888                } else if (speed == SPEED_10) {
 889                        uec_phy_write(mii_info, 0x14, 0x8e40);
 890                        uec_phy_write(mii_info, 0x1b, 0x800b);
 891                        uec_phy_write(mii_info, 0x14, 0x0c82);
 892                        uec_phy_write(mii_info, 0x00, 0x8100);
 893                        udelay (1000000);
 894                }
 895        }
 896
 897        /* handle 88e1111 rev.B2 erratum 5.6 */
 898        if (mii_info->autoneg) {
 899                status = uec_phy_read(mii_info, MII_BMCR);
 900                uec_phy_write(mii_info, MII_BMCR, status | BMCR_ANENABLE);
 901        }
 902        /* now the B2 will correctly report autoneg completion status */
 903}
 904
 905void change_phy_interface_mode (struct eth_device *dev,
 906                                phy_interface_t type, int speed)
 907{
 908#ifdef CONFIG_PHY_MODE_NEED_CHANGE
 909        marvell_phy_interface_mode (dev, type, speed);
 910#endif
 911}
 912