uboot/drivers/net/phy/marvell.c
<<
>>
Prefs
   1/*
   2 * Marvell PHY drivers
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 *
   6 * Copyright 2010-2011 Freescale Semiconductor, Inc.
   7 * author Andy Fleming
   8 */
   9#include <config.h>
  10#include <common.h>
  11#include <errno.h>
  12#include <phy.h>
  13
  14#define PHY_AUTONEGOTIATE_TIMEOUT 5000
  15
  16#define MII_MARVELL_PHY_PAGE            22
  17
  18/* 88E1011 PHY Status Register */
  19#define MIIM_88E1xxx_PHY_STATUS         0x11
  20#define MIIM_88E1xxx_PHYSTAT_SPEED      0xc000
  21#define MIIM_88E1xxx_PHYSTAT_GBIT       0x8000
  22#define MIIM_88E1xxx_PHYSTAT_100        0x4000
  23#define MIIM_88E1xxx_PHYSTAT_DUPLEX     0x2000
  24#define MIIM_88E1xxx_PHYSTAT_SPDDONE    0x0800
  25#define MIIM_88E1xxx_PHYSTAT_LINK       0x0400
  26
  27#define MIIM_88E1xxx_PHY_SCR            0x10
  28#define MIIM_88E1xxx_PHY_MDI_X_AUTO     0x0060
  29
  30/* 88E1111 PHY LED Control Register */
  31#define MIIM_88E1111_PHY_LED_CONTROL    24
  32#define MIIM_88E1111_PHY_LED_DIRECT     0x4100
  33#define MIIM_88E1111_PHY_LED_COMBINE    0x411C
  34
  35/* 88E1111 Extended PHY Specific Control Register */
  36#define MIIM_88E1111_PHY_EXT_CR         0x14
  37#define MIIM_88E1111_RX_DELAY           0x80
  38#define MIIM_88E1111_TX_DELAY           0x2
  39
  40/* 88E1111 Extended PHY Specific Status Register */
  41#define MIIM_88E1111_PHY_EXT_SR         0x1b
  42#define MIIM_88E1111_HWCFG_MODE_MASK            0xf
  43#define MIIM_88E1111_HWCFG_MODE_COPPER_RGMII    0xb
  44#define MIIM_88E1111_HWCFG_MODE_FIBER_RGMII     0x3
  45#define MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK    0x4
  46#define MIIM_88E1111_HWCFG_MODE_COPPER_RTBI     0x9
  47#define MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO    0x8000
  48#define MIIM_88E1111_HWCFG_FIBER_COPPER_RES     0x2000
  49
  50#define MIIM_88E1111_COPPER             0
  51#define MIIM_88E1111_FIBER              1
  52
  53/* 88E1118 PHY defines */
  54#define MIIM_88E1118_PHY_PAGE           22
  55#define MIIM_88E1118_PHY_LED_PAGE       3
  56
  57/* 88E1121 PHY LED Control Register */
  58#define MIIM_88E1121_PHY_LED_CTRL       16
  59#define MIIM_88E1121_PHY_LED_PAGE       3
  60#define MIIM_88E1121_PHY_LED_DEF        0x0030
  61
  62/* 88E1121 PHY IRQ Enable/Status Register */
  63#define MIIM_88E1121_PHY_IRQ_EN         18
  64#define MIIM_88E1121_PHY_IRQ_STATUS     19
  65
  66#define MIIM_88E1121_PHY_PAGE           22
  67
  68/* 88E1145 Extended PHY Specific Control Register */
  69#define MIIM_88E1145_PHY_EXT_CR 20
  70#define MIIM_M88E1145_RGMII_RX_DELAY    0x0080
  71#define MIIM_M88E1145_RGMII_TX_DELAY    0x0002
  72
  73#define MIIM_88E1145_PHY_LED_CONTROL    24
  74#define MIIM_88E1145_PHY_LED_DIRECT     0x4100
  75
  76#define MIIM_88E1145_PHY_PAGE   29
  77#define MIIM_88E1145_PHY_CAL_OV 30
  78
  79#define MIIM_88E1149_PHY_PAGE   29
  80
  81/* 88E1310 PHY defines */
  82#define MIIM_88E1310_PHY_LED_CTRL       16
  83#define MIIM_88E1310_PHY_IRQ_EN         18
  84#define MIIM_88E1310_PHY_RGMII_CTRL     21
  85#define MIIM_88E1310_PHY_PAGE           22
  86
  87/* 88E151x PHY defines */
  88/* Page 2 registers */
  89#define MIIM_88E151x_PHY_MSCR           21
  90#define MIIM_88E151x_RGMII_RX_DELAY     BIT(5)
  91#define MIIM_88E151x_RGMII_TX_DELAY     BIT(4)
  92#define MIIM_88E151x_RGMII_RXTX_DELAY   (BIT(5) | BIT(4))
  93/* Page 3 registers */
  94#define MIIM_88E151x_LED_FUNC_CTRL      16
  95#define MIIM_88E151x_LED_FLD_SZ         4
  96#define MIIM_88E151x_LED0_OFFS          (0 * MIIM_88E151x_LED_FLD_SZ)
  97#define MIIM_88E151x_LED1_OFFS          (1 * MIIM_88E151x_LED_FLD_SZ)
  98#define MIIM_88E151x_LED0_ACT           3
  99#define MIIM_88E151x_LED1_100_1000_LINK 6
 100#define MIIM_88E151x_LED_TIMER_CTRL     18
 101#define MIIM_88E151x_INT_EN_OFFS        7
 102/* Page 18 registers */
 103#define MIIM_88E151x_GENERAL_CTRL       20
 104#define MIIM_88E151x_MODE_SGMII         1
 105#define MIIM_88E151x_RESET_OFFS         15
 106
 107/* Marvell 88E1011S */
 108static int m88e1011s_config(struct phy_device *phydev)
 109{
 110        /* Reset and configure the PHY */
 111        phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
 112
 113        phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
 114        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c);
 115        phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x5);
 116        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0);
 117        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
 118
 119        phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET);
 120
 121        genphy_config_aneg(phydev);
 122
 123        return 0;
 124}
 125
 126/* Parse the 88E1011's status register for speed and duplex
 127 * information
 128 */
 129static int m88e1xxx_parse_status(struct phy_device *phydev)
 130{
 131        unsigned int speed;
 132        unsigned int mii_reg;
 133
 134        mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_STATUS);
 135
 136        if ((mii_reg & MIIM_88E1xxx_PHYSTAT_LINK) &&
 137                !(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
 138                int i = 0;
 139
 140                puts("Waiting for PHY realtime link");
 141                while (!(mii_reg & MIIM_88E1xxx_PHYSTAT_SPDDONE)) {
 142                        /* Timeout reached ? */
 143                        if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
 144                                puts(" TIMEOUT !\n");
 145                                phydev->link = 0;
 146                                return -ETIMEDOUT;
 147                        }
 148
 149                        if ((i++ % 1000) == 0)
 150                                putc('.');
 151                        udelay(1000);
 152                        mii_reg = phy_read(phydev, MDIO_DEVAD_NONE,
 153                                        MIIM_88E1xxx_PHY_STATUS);
 154                }
 155                puts(" done\n");
 156                udelay(500000); /* another 500 ms (results in faster booting) */
 157        } else {
 158                if (mii_reg & MIIM_88E1xxx_PHYSTAT_LINK)
 159                        phydev->link = 1;
 160                else
 161                        phydev->link = 0;
 162        }
 163
 164        if (mii_reg & MIIM_88E1xxx_PHYSTAT_DUPLEX)
 165                phydev->duplex = DUPLEX_FULL;
 166        else
 167                phydev->duplex = DUPLEX_HALF;
 168
 169        speed = mii_reg & MIIM_88E1xxx_PHYSTAT_SPEED;
 170
 171        switch (speed) {
 172        case MIIM_88E1xxx_PHYSTAT_GBIT:
 173                phydev->speed = SPEED_1000;
 174                break;
 175        case MIIM_88E1xxx_PHYSTAT_100:
 176                phydev->speed = SPEED_100;
 177                break;
 178        default:
 179                phydev->speed = SPEED_10;
 180                break;
 181        }
 182
 183        return 0;
 184}
 185
 186static int m88e1011s_startup(struct phy_device *phydev)
 187{
 188        int ret;
 189
 190        ret = genphy_update_link(phydev);
 191        if (ret)
 192                return ret;
 193
 194        return m88e1xxx_parse_status(phydev);
 195}
 196
 197/* Marvell 88E1111S */
 198static int m88e1111s_config(struct phy_device *phydev)
 199{
 200        int reg;
 201
 202        if (phy_interface_is_rgmii(phydev)) {
 203                reg = phy_read(phydev,
 204                        MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR);
 205                if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
 206                        (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)) {
 207                        reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY);
 208                } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
 209                        reg &= ~MIIM_88E1111_TX_DELAY;
 210                        reg |= MIIM_88E1111_RX_DELAY;
 211                } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
 212                        reg &= ~MIIM_88E1111_RX_DELAY;
 213                        reg |= MIIM_88E1111_TX_DELAY;
 214                }
 215
 216                phy_write(phydev,
 217                        MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg);
 218
 219                reg = phy_read(phydev,
 220                        MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR);
 221
 222                reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK);
 223
 224                if (reg & MIIM_88E1111_HWCFG_FIBER_COPPER_RES)
 225                        reg |= MIIM_88E1111_HWCFG_MODE_FIBER_RGMII;
 226                else
 227                        reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RGMII;
 228
 229                phy_write(phydev,
 230                        MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR, reg);
 231        }
 232
 233        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
 234                reg = phy_read(phydev,
 235                        MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_SR);
 236
 237                reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK);
 238                reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK;
 239                reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO;
 240
 241                phy_write(phydev, MDIO_DEVAD_NONE,
 242                        MIIM_88E1111_PHY_EXT_SR, reg);
 243        }
 244
 245        if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
 246                reg = phy_read(phydev,
 247                        MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR);
 248                reg |= (MIIM_88E1111_RX_DELAY | MIIM_88E1111_TX_DELAY);
 249                phy_write(phydev,
 250                        MDIO_DEVAD_NONE, MIIM_88E1111_PHY_EXT_CR, reg);
 251
 252                reg = phy_read(phydev, MDIO_DEVAD_NONE,
 253                        MIIM_88E1111_PHY_EXT_SR);
 254                reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK |
 255                        MIIM_88E1111_HWCFG_FIBER_COPPER_RES);
 256                reg |= 0x7 | MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO;
 257                phy_write(phydev, MDIO_DEVAD_NONE,
 258                        MIIM_88E1111_PHY_EXT_SR, reg);
 259
 260                /* soft reset */
 261                phy_reset(phydev);
 262
 263                reg = phy_read(phydev, MDIO_DEVAD_NONE,
 264                        MIIM_88E1111_PHY_EXT_SR);
 265                reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK |
 266                        MIIM_88E1111_HWCFG_FIBER_COPPER_RES);
 267                reg |= MIIM_88E1111_HWCFG_MODE_COPPER_RTBI |
 268                        MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO;
 269                phy_write(phydev, MDIO_DEVAD_NONE,
 270                        MIIM_88E1111_PHY_EXT_SR, reg);
 271        }
 272
 273        /* soft reset */
 274        phy_reset(phydev);
 275
 276        genphy_config_aneg(phydev);
 277        genphy_restart_aneg(phydev);
 278
 279        return 0;
 280}
 281
 282/**
 283 * m88e1518_phy_writebits - write bits to a register
 284 */
 285void m88e1518_phy_writebits(struct phy_device *phydev,
 286                   u8 reg_num, u16 offset, u16 len, u16 data)
 287{
 288        u16 reg, mask;
 289
 290        if ((len + offset) >= 16)
 291                mask = 0 - (1 << offset);
 292        else
 293                mask = (1 << (len + offset)) - (1 << offset);
 294
 295        reg = phy_read(phydev, MDIO_DEVAD_NONE, reg_num);
 296
 297        reg &= ~mask;
 298        reg |= data << offset;
 299
 300        phy_write(phydev, MDIO_DEVAD_NONE, reg_num, reg);
 301}
 302
 303static int m88e1518_config(struct phy_device *phydev)
 304{
 305        u16 reg;
 306
 307        /*
 308         * As per Marvell Release Notes - Alaska 88E1510/88E1518/88E1512
 309         * /88E1514 Rev A0, Errata Section 3.1
 310         */
 311
 312        /* EEE initialization */
 313        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff);
 314        phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x214B);
 315        phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2144);
 316        phy_write(phydev, MDIO_DEVAD_NONE, 17, 0x0C28);
 317        phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2146);
 318        phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xB233);
 319        phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x214D);
 320        phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xCC0C);
 321        phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x2159);
 322        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 323
 324        /* SGMII-to-Copper mode initialization */
 325        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
 326                /* Select page 18 */
 327                phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 18);
 328
 329                /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */
 330                m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL,
 331                                       0, 3, MIIM_88E151x_MODE_SGMII);
 332
 333                /* PHY reset is necessary after changing MODE[2:0] */
 334                m88e1518_phy_writebits(phydev, MIIM_88E151x_GENERAL_CTRL,
 335                                       MIIM_88E151x_RESET_OFFS, 1, 1);
 336
 337                /* Reset page selection */
 338                phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0);
 339
 340                udelay(100);
 341        }
 342
 343        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
 344                reg = phy_read(phydev, MDIO_DEVAD_NONE,
 345                               MIIM_88E1111_PHY_EXT_SR);
 346
 347                reg &= ~(MIIM_88E1111_HWCFG_MODE_MASK);
 348                reg |= MIIM_88E1111_HWCFG_MODE_SGMII_NO_CLK;
 349                reg |= MIIM_88E1111_HWCFG_FIBER_COPPER_AUTO;
 350
 351                phy_write(phydev, MDIO_DEVAD_NONE,
 352                          MIIM_88E1111_PHY_EXT_SR, reg);
 353        }
 354
 355        if (phy_interface_is_rgmii(phydev)) {
 356                phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 2);
 357
 358                reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR);
 359                reg &= ~MIIM_88E151x_RGMII_RXTX_DELAY;
 360                if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
 361                        reg |= MIIM_88E151x_RGMII_RXTX_DELAY;
 362                else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
 363                        reg |= MIIM_88E151x_RGMII_RX_DELAY;
 364                else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
 365                        reg |= MIIM_88E151x_RGMII_TX_DELAY;
 366                phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E151x_PHY_MSCR, reg);
 367
 368                phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, 0);
 369        }
 370
 371        /* soft reset */
 372        phy_reset(phydev);
 373
 374        genphy_config_aneg(phydev);
 375        genphy_restart_aneg(phydev);
 376
 377        return 0;
 378}
 379
 380/* Marvell 88E1510 */
 381static int m88e1510_config(struct phy_device *phydev)
 382{
 383        /* Select page 3 */
 384        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE,
 385                  MIIM_88E1118_PHY_LED_PAGE);
 386
 387        /* Enable INTn output on LED[2] */
 388        m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_TIMER_CTRL,
 389                               MIIM_88E151x_INT_EN_OFFS, 1, 1);
 390
 391        /* Configure LEDs */
 392        /* LED[0]:0011 (ACT) */
 393        m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL,
 394                               MIIM_88E151x_LED0_OFFS, MIIM_88E151x_LED_FLD_SZ,
 395                               MIIM_88E151x_LED0_ACT);
 396        /* LED[1]:0110 (LINK 100/1000 Mbps) */
 397        m88e1518_phy_writebits(phydev, MIIM_88E151x_LED_FUNC_CTRL,
 398                               MIIM_88E151x_LED1_OFFS, MIIM_88E151x_LED_FLD_SZ,
 399                               MIIM_88E151x_LED1_100_1000_LINK);
 400
 401        /* Reset page selection */
 402        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0);
 403
 404        return m88e1518_config(phydev);
 405}
 406
 407/* Marvell 88E1118 */
 408static int m88e1118_config(struct phy_device *phydev)
 409{
 410        /* Change Page Number */
 411        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0002);
 412        /* Delay RGMII TX and RX */
 413        phy_write(phydev, MDIO_DEVAD_NONE, 0x15, 0x1070);
 414        /* Change Page Number */
 415        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0003);
 416        /* Adjust LED control */
 417        phy_write(phydev, MDIO_DEVAD_NONE, 0x10, 0x021e);
 418        /* Change Page Number */
 419        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 420
 421        return genphy_config_aneg(phydev);
 422}
 423
 424static int m88e1118_startup(struct phy_device *phydev)
 425{
 426        int ret;
 427
 428        /* Change Page Number */
 429        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 430
 431        ret = genphy_update_link(phydev);
 432        if (ret)
 433                return ret;
 434
 435        return m88e1xxx_parse_status(phydev);
 436}
 437
 438/* Marvell 88E1121R */
 439static int m88e1121_config(struct phy_device *phydev)
 440{
 441        int pg;
 442
 443        /* Configure the PHY */
 444        genphy_config_aneg(phydev);
 445
 446        /* Switch the page to access the led register */
 447        pg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE);
 448        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE,
 449                        MIIM_88E1121_PHY_LED_PAGE);
 450        /* Configure leds */
 451        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_LED_CTRL,
 452                        MIIM_88E1121_PHY_LED_DEF);
 453        /* Restore the page pointer */
 454        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_PAGE, pg);
 455
 456        /* Disable IRQs and de-assert interrupt */
 457        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_EN, 0);
 458        phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1121_PHY_IRQ_STATUS);
 459
 460        return 0;
 461}
 462
 463/* Marvell 88E1145 */
 464static int m88e1145_config(struct phy_device *phydev)
 465{
 466        int reg;
 467
 468        /* Errata E0, E1 */
 469        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x001b);
 470        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0x418f);
 471        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_PAGE, 0x0016);
 472        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_CAL_OV, 0xa2da);
 473
 474        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1xxx_PHY_SCR,
 475                        MIIM_88E1xxx_PHY_MDI_X_AUTO);
 476
 477        reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR);
 478        if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
 479                reg |= MIIM_M88E1145_RGMII_RX_DELAY |
 480                        MIIM_M88E1145_RGMII_TX_DELAY;
 481        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg);
 482
 483        genphy_config_aneg(phydev);
 484
 485        /* soft reset */
 486        reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
 487        reg |= BMCR_RESET;
 488        phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg);
 489
 490        return 0;
 491}
 492
 493static int m88e1145_startup(struct phy_device *phydev)
 494{
 495        int ret;
 496
 497        ret = genphy_update_link(phydev);
 498        if (ret)
 499                return ret;
 500
 501        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_LED_CONTROL,
 502                        MIIM_88E1145_PHY_LED_DIRECT);
 503        return m88e1xxx_parse_status(phydev);
 504}
 505
 506/* Marvell 88E1149S */
 507static int m88e1149_config(struct phy_device *phydev)
 508{
 509        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x1f);
 510        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x200c);
 511        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1149_PHY_PAGE, 0x5);
 512        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0);
 513        phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
 514
 515        genphy_config_aneg(phydev);
 516
 517        phy_reset(phydev);
 518
 519        return 0;
 520}
 521
 522/* Marvell 88E1310 */
 523static int m88e1310_config(struct phy_device *phydev)
 524{
 525        u16 reg;
 526
 527        /* LED link and activity */
 528        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003);
 529        reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL);
 530        reg = (reg & ~0xf) | 0x1;
 531        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_LED_CTRL, reg);
 532
 533        /* Set LED2/INT to INT mode, low active */
 534        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0003);
 535        reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN);
 536        reg = (reg & 0x77ff) | 0x0880;
 537        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_IRQ_EN, reg);
 538
 539        /* Set RGMII delay */
 540        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0002);
 541        reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL);
 542        reg |= 0x0030;
 543        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_RGMII_CTRL, reg);
 544
 545        /* Ensure to return to page 0 */
 546        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000);
 547
 548        return genphy_config_aneg(phydev);
 549}
 550
 551static int m88e1680_config(struct phy_device *phydev)
 552{
 553        /*
 554         * As per Marvell Release Notes - Alaska V 88E1680 Rev A2
 555         * Errata Section 4.1
 556         */
 557        u16 reg;
 558        int res;
 559
 560        /* Matrix LED mode (not neede if single LED mode is used */
 561        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0004);
 562        reg = phy_read(phydev, MDIO_DEVAD_NONE, 27);
 563        reg |= (1 << 5);
 564        phy_write(phydev, MDIO_DEVAD_NONE, 27, reg);
 565
 566        /* QSGMII TX amplitude change */
 567        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00fd);
 568        phy_write(phydev, MDIO_DEVAD_NONE,  8, 0x0b53);
 569        phy_write(phydev, MDIO_DEVAD_NONE,  7, 0x200d);
 570        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 571
 572        /* EEE initialization */
 573        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x00ff);
 574        phy_write(phydev, MDIO_DEVAD_NONE, 17, 0xb030);
 575        phy_write(phydev, MDIO_DEVAD_NONE, 16, 0x215c);
 576        phy_write(phydev, MDIO_DEVAD_NONE, 22, 0x00fc);
 577        phy_write(phydev, MDIO_DEVAD_NONE, 24, 0x888c);
 578        phy_write(phydev, MDIO_DEVAD_NONE, 25, 0x888c);
 579        phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000);
 580        phy_write(phydev, MDIO_DEVAD_NONE,  0, 0x9140);
 581
 582        res = genphy_config_aneg(phydev);
 583        if (res < 0)
 584                return res;
 585
 586        /* soft reset */
 587        reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMCR);
 588        reg |= BMCR_RESET;
 589        phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, reg);
 590
 591        return 0;
 592}
 593
 594static struct phy_driver M88E1011S_driver = {
 595        .name = "Marvell 88E1011S",
 596        .uid = 0x1410c60,
 597        .mask = 0xffffff0,
 598        .features = PHY_GBIT_FEATURES,
 599        .config = &m88e1011s_config,
 600        .startup = &m88e1011s_startup,
 601        .shutdown = &genphy_shutdown,
 602};
 603
 604static struct phy_driver M88E1111S_driver = {
 605        .name = "Marvell 88E1111S",
 606        .uid = 0x1410cc0,
 607        .mask = 0xffffff0,
 608        .features = PHY_GBIT_FEATURES,
 609        .config = &m88e1111s_config,
 610        .startup = &m88e1011s_startup,
 611        .shutdown = &genphy_shutdown,
 612};
 613
 614static struct phy_driver M88E1118_driver = {
 615        .name = "Marvell 88E1118",
 616        .uid = 0x1410e10,
 617        .mask = 0xffffff0,
 618        .features = PHY_GBIT_FEATURES,
 619        .config = &m88e1118_config,
 620        .startup = &m88e1118_startup,
 621        .shutdown = &genphy_shutdown,
 622};
 623
 624static struct phy_driver M88E1118R_driver = {
 625        .name = "Marvell 88E1118R",
 626        .uid = 0x1410e40,
 627        .mask = 0xffffff0,
 628        .features = PHY_GBIT_FEATURES,
 629        .config = &m88e1118_config,
 630        .startup = &m88e1118_startup,
 631        .shutdown = &genphy_shutdown,
 632};
 633
 634static struct phy_driver M88E1121R_driver = {
 635        .name = "Marvell 88E1121R",
 636        .uid = 0x1410cb0,
 637        .mask = 0xffffff0,
 638        .features = PHY_GBIT_FEATURES,
 639        .config = &m88e1121_config,
 640        .startup = &genphy_startup,
 641        .shutdown = &genphy_shutdown,
 642};
 643
 644static struct phy_driver M88E1145_driver = {
 645        .name = "Marvell 88E1145",
 646        .uid = 0x1410cd0,
 647        .mask = 0xffffff0,
 648        .features = PHY_GBIT_FEATURES,
 649        .config = &m88e1145_config,
 650        .startup = &m88e1145_startup,
 651        .shutdown = &genphy_shutdown,
 652};
 653
 654static struct phy_driver M88E1149S_driver = {
 655        .name = "Marvell 88E1149S",
 656        .uid = 0x1410ca0,
 657        .mask = 0xffffff0,
 658        .features = PHY_GBIT_FEATURES,
 659        .config = &m88e1149_config,
 660        .startup = &m88e1011s_startup,
 661        .shutdown = &genphy_shutdown,
 662};
 663
 664static struct phy_driver M88E1510_driver = {
 665        .name = "Marvell 88E1510",
 666        .uid = 0x1410dd0,
 667        .mask = 0xfffffff,
 668        .features = PHY_GBIT_FEATURES,
 669        .config = &m88e1510_config,
 670        .startup = &m88e1011s_startup,
 671        .shutdown = &genphy_shutdown,
 672};
 673
 674/*
 675 * This supports:
 676 *  88E1518, uid 0x1410dd1
 677 *  88E1512, uid 0x1410dd4
 678 */
 679static struct phy_driver M88E1518_driver = {
 680        .name = "Marvell 88E1518",
 681        .uid = 0x1410dd0,
 682        .mask = 0xffffffa,
 683        .features = PHY_GBIT_FEATURES,
 684        .config = &m88e1518_config,
 685        .startup = &m88e1011s_startup,
 686        .shutdown = &genphy_shutdown,
 687};
 688
 689static struct phy_driver M88E1310_driver = {
 690        .name = "Marvell 88E1310",
 691        .uid = 0x01410e90,
 692        .mask = 0xffffff0,
 693        .features = PHY_GBIT_FEATURES,
 694        .config = &m88e1310_config,
 695        .startup = &m88e1011s_startup,
 696        .shutdown = &genphy_shutdown,
 697};
 698
 699static struct phy_driver M88E1680_driver = {
 700        .name = "Marvell 88E1680",
 701        .uid = 0x1410ed0,
 702        .mask = 0xffffff0,
 703        .features = PHY_GBIT_FEATURES,
 704        .config = &m88e1680_config,
 705        .startup = &genphy_startup,
 706        .shutdown = &genphy_shutdown,
 707};
 708
 709int phy_marvell_init(void)
 710{
 711        phy_register(&M88E1310_driver);
 712        phy_register(&M88E1149S_driver);
 713        phy_register(&M88E1145_driver);
 714        phy_register(&M88E1121R_driver);
 715        phy_register(&M88E1118_driver);
 716        phy_register(&M88E1118R_driver);
 717        phy_register(&M88E1111S_driver);
 718        phy_register(&M88E1011S_driver);
 719        phy_register(&M88E1510_driver);
 720        phy_register(&M88E1518_driver);
 721        phy_register(&M88E1680_driver);
 722
 723        return 0;
 724}
 725