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