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