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