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