linux/drivers/net/dsa/mv88e6xxx/serdes.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Marvell 88E6xxx SERDES manipulation, via SMI bus
   4 *
   5 * Copyright (c) 2008 Marvell Semiconductor
   6 *
   7 * Copyright (c) 2017 Andrew Lunn <andrew@lunn.ch>
   8 */
   9
  10#include <linux/interrupt.h>
  11#include <linux/irqdomain.h>
  12#include <linux/mii.h>
  13
  14#include "chip.h"
  15#include "global2.h"
  16#include "phy.h"
  17#include "port.h"
  18#include "serdes.h"
  19
  20static int mv88e6352_serdes_read(struct mv88e6xxx_chip *chip, int reg,
  21                                 u16 *val)
  22{
  23        return mv88e6xxx_phy_page_read(chip, MV88E6352_ADDR_SERDES,
  24                                       MV88E6352_SERDES_PAGE_FIBER,
  25                                       reg, val);
  26}
  27
  28static int mv88e6352_serdes_write(struct mv88e6xxx_chip *chip, int reg,
  29                                  u16 val)
  30{
  31        return mv88e6xxx_phy_page_write(chip, MV88E6352_ADDR_SERDES,
  32                                        MV88E6352_SERDES_PAGE_FIBER,
  33                                        reg, val);
  34}
  35
  36static int mv88e6390_serdes_read(struct mv88e6xxx_chip *chip,
  37                                 int lane, int device, int reg, u16 *val)
  38{
  39        int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
  40
  41        return mv88e6xxx_phy_read(chip, lane, reg_c45, val);
  42}
  43
  44static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
  45                                  int lane, int device, int reg, u16 val)
  46{
  47        int reg_c45 = MII_ADDR_C45 | device << 16 | reg;
  48
  49        return mv88e6xxx_phy_write(chip, lane, reg_c45, val);
  50}
  51
  52static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,
  53                                          u16 status, u16 lpa,
  54                                          struct phylink_link_state *state)
  55{
  56        if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
  57                state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
  58                state->duplex = status &
  59                                MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
  60                                                 DUPLEX_FULL : DUPLEX_HALF;
  61
  62                if (status & MV88E6390_SGMII_PHY_STATUS_TX_PAUSE)
  63                        state->pause |= MLO_PAUSE_TX;
  64                if (status & MV88E6390_SGMII_PHY_STATUS_RX_PAUSE)
  65                        state->pause |= MLO_PAUSE_RX;
  66
  67                switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
  68                case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
  69                        if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
  70                                state->speed = SPEED_2500;
  71                        else
  72                                state->speed = SPEED_1000;
  73                        break;
  74                case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
  75                        state->speed = SPEED_100;
  76                        break;
  77                case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
  78                        state->speed = SPEED_10;
  79                        break;
  80                default:
  81                        dev_err(chip->dev, "invalid PHY speed\n");
  82                        return -EINVAL;
  83                }
  84        } else {
  85                state->link = false;
  86        }
  87
  88        if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
  89                mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
  90                                       ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
  91        else if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
  92                mii_lpa_mod_linkmode_x(state->lp_advertising, lpa,
  93                                       ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
  94
  95        return 0;
  96}
  97
  98int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
  99                           bool up)
 100{
 101        u16 val, new_val;
 102        int err;
 103
 104        err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 105        if (err)
 106                return err;
 107
 108        if (up)
 109                new_val = val & ~BMCR_PDOWN;
 110        else
 111                new_val = val | BMCR_PDOWN;
 112
 113        if (val != new_val)
 114                err = mv88e6352_serdes_write(chip, MII_BMCR, new_val);
 115
 116        return err;
 117}
 118
 119int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 120                                int lane, unsigned int mode,
 121                                phy_interface_t interface,
 122                                const unsigned long *advertise)
 123{
 124        u16 adv, bmcr, val;
 125        bool changed;
 126        int err;
 127
 128        switch (interface) {
 129        case PHY_INTERFACE_MODE_SGMII:
 130                adv = 0x0001;
 131                break;
 132
 133        case PHY_INTERFACE_MODE_1000BASEX:
 134                adv = linkmode_adv_to_mii_adv_x(advertise,
 135                                        ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 136                break;
 137
 138        default:
 139                return 0;
 140        }
 141
 142        err = mv88e6352_serdes_read(chip, MII_ADVERTISE, &val);
 143        if (err)
 144                return err;
 145
 146        changed = val != adv;
 147        if (changed) {
 148                err = mv88e6352_serdes_write(chip, MII_ADVERTISE, adv);
 149                if (err)
 150                        return err;
 151        }
 152
 153        err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 154        if (err)
 155                return err;
 156
 157        if (phylink_autoneg_inband(mode))
 158                bmcr = val | BMCR_ANENABLE;
 159        else
 160                bmcr = val & ~BMCR_ANENABLE;
 161
 162        if (bmcr == val)
 163                return changed;
 164
 165        return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
 166}
 167
 168int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 169                                   int lane, struct phylink_link_state *state)
 170{
 171        u16 lpa, status;
 172        int err;
 173
 174        err = mv88e6352_serdes_read(chip, 0x11, &status);
 175        if (err) {
 176                dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
 177                return err;
 178        }
 179
 180        err = mv88e6352_serdes_read(chip, MII_LPA, &lpa);
 181        if (err) {
 182                dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
 183                return err;
 184        }
 185
 186        return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
 187}
 188
 189int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
 190                                    int lane)
 191{
 192        u16 bmcr;
 193        int err;
 194
 195        err = mv88e6352_serdes_read(chip, MII_BMCR, &bmcr);
 196        if (err)
 197                return err;
 198
 199        return mv88e6352_serdes_write(chip, MII_BMCR, bmcr | BMCR_ANRESTART);
 200}
 201
 202int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
 203                                 int lane, int speed, int duplex)
 204{
 205        u16 val, bmcr;
 206        int err;
 207
 208        err = mv88e6352_serdes_read(chip, MII_BMCR, &val);
 209        if (err)
 210                return err;
 211
 212        bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
 213        switch (speed) {
 214        case SPEED_1000:
 215                bmcr |= BMCR_SPEED1000;
 216                break;
 217        case SPEED_100:
 218                bmcr |= BMCR_SPEED100;
 219                break;
 220        case SPEED_10:
 221                break;
 222        }
 223
 224        if (duplex == DUPLEX_FULL)
 225                bmcr |= BMCR_FULLDPLX;
 226
 227        if (bmcr == val)
 228                return 0;
 229
 230        return mv88e6352_serdes_write(chip, MII_BMCR, bmcr);
 231}
 232
 233int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 234{
 235        u8 cmode = chip->ports[port].cmode;
 236        int lane = -ENODEV;
 237
 238        if ((cmode == MV88E6XXX_PORT_STS_CMODE_100BASEX) ||
 239            (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX) ||
 240            (cmode == MV88E6XXX_PORT_STS_CMODE_SGMII))
 241                lane = 0xff; /* Unused */
 242
 243        return lane;
 244}
 245
 246static bool mv88e6352_port_has_serdes(struct mv88e6xxx_chip *chip, int port)
 247{
 248        if (mv88e6xxx_serdes_get_lane(chip, port) >= 0)
 249                return true;
 250
 251        return false;
 252}
 253
 254struct mv88e6352_serdes_hw_stat {
 255        char string[ETH_GSTRING_LEN];
 256        int sizeof_stat;
 257        int reg;
 258};
 259
 260static struct mv88e6352_serdes_hw_stat mv88e6352_serdes_hw_stats[] = {
 261        { "serdes_fibre_rx_error", 16, 21 },
 262        { "serdes_PRBS_error", 32, 24 },
 263};
 264
 265int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
 266{
 267        if (mv88e6352_port_has_serdes(chip, port))
 268                return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 269
 270        return 0;
 271}
 272
 273int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
 274                                 int port, uint8_t *data)
 275{
 276        struct mv88e6352_serdes_hw_stat *stat;
 277        int i;
 278
 279        if (!mv88e6352_port_has_serdes(chip, port))
 280                return 0;
 281
 282        for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
 283                stat = &mv88e6352_serdes_hw_stats[i];
 284                memcpy(data + i * ETH_GSTRING_LEN, stat->string,
 285                       ETH_GSTRING_LEN);
 286        }
 287        return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 288}
 289
 290static uint64_t mv88e6352_serdes_get_stat(struct mv88e6xxx_chip *chip,
 291                                          struct mv88e6352_serdes_hw_stat *stat)
 292{
 293        u64 val = 0;
 294        u16 reg;
 295        int err;
 296
 297        err = mv88e6352_serdes_read(chip, stat->reg, &reg);
 298        if (err) {
 299                dev_err(chip->dev, "failed to read statistic\n");
 300                return 0;
 301        }
 302
 303        val = reg;
 304
 305        if (stat->sizeof_stat == 32) {
 306                err = mv88e6352_serdes_read(chip, stat->reg + 1, &reg);
 307                if (err) {
 308                        dev_err(chip->dev, "failed to read statistic\n");
 309                        return 0;
 310                }
 311                val = val << 16 | reg;
 312        }
 313
 314        return val;
 315}
 316
 317int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 318                               uint64_t *data)
 319{
 320        struct mv88e6xxx_port *mv88e6xxx_port = &chip->ports[port];
 321        struct mv88e6352_serdes_hw_stat *stat;
 322        u64 value;
 323        int i;
 324
 325        if (!mv88e6352_port_has_serdes(chip, port))
 326                return 0;
 327
 328        BUILD_BUG_ON(ARRAY_SIZE(mv88e6352_serdes_hw_stats) >
 329                     ARRAY_SIZE(mv88e6xxx_port->serdes_stats));
 330
 331        for (i = 0; i < ARRAY_SIZE(mv88e6352_serdes_hw_stats); i++) {
 332                stat = &mv88e6352_serdes_hw_stats[i];
 333                value = mv88e6352_serdes_get_stat(chip, stat);
 334                mv88e6xxx_port->serdes_stats[i] += value;
 335                data[i] = mv88e6xxx_port->serdes_stats[i];
 336        }
 337
 338        return ARRAY_SIZE(mv88e6352_serdes_hw_stats);
 339}
 340
 341static void mv88e6352_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
 342{
 343        u16 bmsr;
 344        int err;
 345
 346        /* If the link has dropped, we want to know about it. */
 347        err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
 348        if (err) {
 349                dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
 350                return;
 351        }
 352
 353        dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
 354}
 355
 356irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 357                                        int lane)
 358{
 359        irqreturn_t ret = IRQ_NONE;
 360        u16 status;
 361        int err;
 362
 363        err = mv88e6352_serdes_read(chip, MV88E6352_SERDES_INT_STATUS, &status);
 364        if (err)
 365                return ret;
 366
 367        if (status & MV88E6352_SERDES_INT_LINK_CHANGE) {
 368                ret = IRQ_HANDLED;
 369                mv88e6352_serdes_irq_link(chip, port);
 370        }
 371
 372        return ret;
 373}
 374
 375int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
 376                                bool enable)
 377{
 378        u16 val = 0;
 379
 380        if (enable)
 381                val |= MV88E6352_SERDES_INT_LINK_CHANGE;
 382
 383        return mv88e6352_serdes_write(chip, MV88E6352_SERDES_INT_ENABLE, val);
 384}
 385
 386unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
 387{
 388        return irq_find_mapping(chip->g2_irq.domain, MV88E6352_SERDES_IRQ);
 389}
 390
 391int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
 392{
 393        if (!mv88e6352_port_has_serdes(chip, port))
 394                return 0;
 395
 396        return 32 * sizeof(u16);
 397}
 398
 399void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
 400{
 401        u16 *p = _p;
 402        u16 reg;
 403        int err;
 404        int i;
 405
 406        if (!mv88e6352_port_has_serdes(chip, port))
 407                return;
 408
 409        for (i = 0 ; i < 32; i++) {
 410                err = mv88e6352_serdes_read(chip, i, &reg);
 411                if (!err)
 412                        p[i] = reg;
 413        }
 414}
 415
 416int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 417{
 418        u8 cmode = chip->ports[port].cmode;
 419        int lane = -ENODEV;
 420
 421        switch (port) {
 422        case 5:
 423                if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 424                    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 425                    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 426                        lane = MV88E6341_PORT5_LANE;
 427                break;
 428        }
 429
 430        return lane;
 431}
 432
 433int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 434                           bool up)
 435{
 436        /* The serdes power can't be controlled on this switch chip but we need
 437         * to supply this function to avoid returning -EOPNOTSUPP in
 438         * mv88e6xxx_serdes_power_up/mv88e6xxx_serdes_power_down
 439         */
 440        return 0;
 441}
 442
 443int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 444{
 445        /* There are no configurable serdes lanes on this switch chip but we
 446         * need to return a non-negative lane number so that callers of
 447         * mv88e6xxx_serdes_get_lane() know this is a serdes port.
 448         */
 449        switch (chip->ports[port].cmode) {
 450        case MV88E6185_PORT_STS_CMODE_SERDES:
 451        case MV88E6185_PORT_STS_CMODE_1000BASE_X:
 452                return 0;
 453        default:
 454                return -ENODEV;
 455        }
 456}
 457
 458int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 459                                   int lane, struct phylink_link_state *state)
 460{
 461        int err;
 462        u16 status;
 463
 464        err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
 465        if (err)
 466                return err;
 467
 468        state->link = !!(status & MV88E6XXX_PORT_STS_LINK);
 469
 470        if (state->link) {
 471                state->duplex = status & MV88E6XXX_PORT_STS_DUPLEX ? DUPLEX_FULL : DUPLEX_HALF;
 472
 473                switch (status &  MV88E6XXX_PORT_STS_SPEED_MASK) {
 474                case MV88E6XXX_PORT_STS_SPEED_1000:
 475                        state->speed = SPEED_1000;
 476                        break;
 477                case MV88E6XXX_PORT_STS_SPEED_100:
 478                        state->speed = SPEED_100;
 479                        break;
 480                case MV88E6XXX_PORT_STS_SPEED_10:
 481                        state->speed = SPEED_10;
 482                        break;
 483                default:
 484                        dev_err(chip->dev, "invalid PHY speed\n");
 485                        return -EINVAL;
 486                }
 487        } else {
 488                state->duplex = DUPLEX_UNKNOWN;
 489                state->speed = SPEED_UNKNOWN;
 490        }
 491
 492        return 0;
 493}
 494
 495int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
 496                                bool enable)
 497{
 498        u8 cmode = chip->ports[port].cmode;
 499
 500        /* The serdes interrupts are enabled in the G2_INT_MASK register. We
 501         * need to return 0 to avoid returning -EOPNOTSUPP in
 502         * mv88e6xxx_serdes_irq_enable/mv88e6xxx_serdes_irq_disable
 503         */
 504        switch (cmode) {
 505        case MV88E6185_PORT_STS_CMODE_SERDES:
 506        case MV88E6185_PORT_STS_CMODE_1000BASE_X:
 507                return 0;
 508        }
 509
 510        return -EOPNOTSUPP;
 511}
 512
 513static void mv88e6097_serdes_irq_link(struct mv88e6xxx_chip *chip, int port)
 514{
 515        u16 status;
 516        int err;
 517
 518        err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, &status);
 519        if (err) {
 520                dev_err(chip->dev, "can't read port status: %d\n", err);
 521                return;
 522        }
 523
 524        dsa_port_phylink_mac_change(chip->ds, port, !!(status & MV88E6XXX_PORT_STS_LINK));
 525}
 526
 527irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
 528                                        int lane)
 529{
 530        u8 cmode = chip->ports[port].cmode;
 531
 532        switch (cmode) {
 533        case MV88E6185_PORT_STS_CMODE_SERDES:
 534        case MV88E6185_PORT_STS_CMODE_1000BASE_X:
 535                mv88e6097_serdes_irq_link(chip, port);
 536                return IRQ_HANDLED;
 537        }
 538
 539        return IRQ_NONE;
 540}
 541
 542int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 543{
 544        u8 cmode = chip->ports[port].cmode;
 545        int lane = -ENODEV;
 546
 547        switch (port) {
 548        case 9:
 549                if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 550                    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 551                    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 552                        lane = MV88E6390_PORT9_LANE0;
 553                break;
 554        case 10:
 555                if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 556                    cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 557                    cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 558                        lane = MV88E6390_PORT10_LANE0;
 559                break;
 560        }
 561
 562        return lane;
 563}
 564
 565int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 566{
 567        u8 cmode_port = chip->ports[port].cmode;
 568        u8 cmode_port10 = chip->ports[10].cmode;
 569        u8 cmode_port9 = chip->ports[9].cmode;
 570        int lane = -ENODEV;
 571
 572        switch (port) {
 573        case 2:
 574                if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 575                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 576                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 577                        if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 578                                lane = MV88E6390_PORT9_LANE1;
 579                break;
 580        case 3:
 581                if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 582                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 583                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 584                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 585                        if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 586                                lane = MV88E6390_PORT9_LANE2;
 587                break;
 588        case 4:
 589                if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 590                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 591                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 592                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 593                        if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 594                                lane = MV88E6390_PORT9_LANE3;
 595                break;
 596        case 5:
 597                if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 598                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 599                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX)
 600                        if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 601                                lane = MV88E6390_PORT10_LANE1;
 602                break;
 603        case 6:
 604                if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 605                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 606                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 607                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 608                        if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 609                                lane = MV88E6390_PORT10_LANE2;
 610                break;
 611        case 7:
 612                if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 613                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 614                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 615                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 616                        if (cmode_port == MV88E6XXX_PORT_STS_CMODE_1000BASEX)
 617                                lane = MV88E6390_PORT10_LANE3;
 618                break;
 619        case 9:
 620                if (cmode_port9 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 621                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 622                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 623                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
 624                    cmode_port9 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 625                        lane = MV88E6390_PORT9_LANE0;
 626                break;
 627        case 10:
 628                if (cmode_port10 == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 629                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 630                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 631                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_XAUI ||
 632                    cmode_port10 == MV88E6XXX_PORT_STS_CMODE_RXAUI)
 633                        lane = MV88E6390_PORT10_LANE0;
 634                break;
 635        }
 636
 637        return lane;
 638}
 639
 640/* Only Ports 0, 9 and 10 have SERDES lanes. Return the SERDES lane address
 641 * a port is using else Returns -ENODEV.
 642 */
 643int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port)
 644{
 645        u8 cmode = chip->ports[port].cmode;
 646        int lane = -ENODEV;
 647
 648        if (port != 0 && port != 9 && port != 10)
 649                return -EOPNOTSUPP;
 650
 651        if (cmode == MV88E6XXX_PORT_STS_CMODE_1000BASEX ||
 652            cmode == MV88E6XXX_PORT_STS_CMODE_SGMII ||
 653            cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX ||
 654            cmode == MV88E6393X_PORT_STS_CMODE_5GBASER ||
 655            cmode == MV88E6393X_PORT_STS_CMODE_10GBASER)
 656                lane = port;
 657
 658        return lane;
 659}
 660
 661/* Set power up/down for 10GBASE-R and 10GBASE-X4/X2 */
 662static int mv88e6390_serdes_power_10g(struct mv88e6xxx_chip *chip, int lane,
 663                                      bool up)
 664{
 665        u16 val, new_val;
 666        int err;
 667
 668        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 669                                    MV88E6390_10G_CTRL1, &val);
 670
 671        if (err)
 672                return err;
 673
 674        if (up)
 675                new_val = val & ~(MDIO_CTRL1_RESET |
 676                                  MDIO_PCS_CTRL1_LOOPBACK |
 677                                  MDIO_CTRL1_LPOWER);
 678        else
 679                new_val = val | MDIO_CTRL1_LPOWER;
 680
 681        if (val != new_val)
 682                err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 683                                             MV88E6390_10G_CTRL1, new_val);
 684
 685        return err;
 686}
 687
 688/* Set power up/down for SGMII and 1000Base-X */
 689static int mv88e6390_serdes_power_sgmii(struct mv88e6xxx_chip *chip, int lane,
 690                                        bool up)
 691{
 692        u16 val, new_val;
 693        int err;
 694
 695        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 696                                    MV88E6390_SGMII_BMCR, &val);
 697        if (err)
 698                return err;
 699
 700        if (up)
 701                new_val = val & ~(BMCR_RESET | BMCR_LOOPBACK | BMCR_PDOWN);
 702        else
 703                new_val = val | BMCR_PDOWN;
 704
 705        if (val != new_val)
 706                err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 707                                             MV88E6390_SGMII_BMCR, new_val);
 708
 709        return err;
 710}
 711
 712struct mv88e6390_serdes_hw_stat {
 713        char string[ETH_GSTRING_LEN];
 714        int reg;
 715};
 716
 717static struct mv88e6390_serdes_hw_stat mv88e6390_serdes_hw_stats[] = {
 718        { "serdes_rx_pkts", 0xf021 },
 719        { "serdes_rx_bytes", 0xf024 },
 720        { "serdes_rx_pkts_error", 0xf027 },
 721};
 722
 723int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port)
 724{
 725        if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
 726                return 0;
 727
 728        return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 729}
 730
 731int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
 732                                 int port, uint8_t *data)
 733{
 734        struct mv88e6390_serdes_hw_stat *stat;
 735        int i;
 736
 737        if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
 738                return 0;
 739
 740        for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
 741                stat = &mv88e6390_serdes_hw_stats[i];
 742                memcpy(data + i * ETH_GSTRING_LEN, stat->string,
 743                       ETH_GSTRING_LEN);
 744        }
 745        return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 746}
 747
 748static uint64_t mv88e6390_serdes_get_stat(struct mv88e6xxx_chip *chip, int lane,
 749                                          struct mv88e6390_serdes_hw_stat *stat)
 750{
 751        u16 reg[3];
 752        int err, i;
 753
 754        for (i = 0; i < 3; i++) {
 755                err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 756                                            stat->reg + i, &reg[i]);
 757                if (err) {
 758                        dev_err(chip->dev, "failed to read statistic\n");
 759                        return 0;
 760                }
 761        }
 762
 763        return reg[0] | ((u64)reg[1] << 16) | ((u64)reg[2] << 32);
 764}
 765
 766int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
 767                               uint64_t *data)
 768{
 769        struct mv88e6390_serdes_hw_stat *stat;
 770        int lane;
 771        int i;
 772
 773        lane = mv88e6xxx_serdes_get_lane(chip, port);
 774        if (lane < 0)
 775                return 0;
 776
 777        for (i = 0; i < ARRAY_SIZE(mv88e6390_serdes_hw_stats); i++) {
 778                stat = &mv88e6390_serdes_hw_stats[i];
 779                data[i] = mv88e6390_serdes_get_stat(chip, lane, stat);
 780        }
 781
 782        return ARRAY_SIZE(mv88e6390_serdes_hw_stats);
 783}
 784
 785static int mv88e6390_serdes_enable_checker(struct mv88e6xxx_chip *chip, int lane)
 786{
 787        u16 reg;
 788        int err;
 789
 790        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 791                                    MV88E6390_PG_CONTROL, &reg);
 792        if (err)
 793                return err;
 794
 795        reg |= MV88E6390_PG_CONTROL_ENABLE_PC;
 796        return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 797                                      MV88E6390_PG_CONTROL, reg);
 798}
 799
 800int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
 801                           bool up)
 802{
 803        u8 cmode = chip->ports[port].cmode;
 804        int err = 0;
 805
 806        switch (cmode) {
 807        case MV88E6XXX_PORT_STS_CMODE_SGMII:
 808        case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
 809        case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
 810                err = mv88e6390_serdes_power_sgmii(chip, lane, up);
 811                break;
 812        case MV88E6XXX_PORT_STS_CMODE_XAUI:
 813        case MV88E6XXX_PORT_STS_CMODE_RXAUI:
 814                err = mv88e6390_serdes_power_10g(chip, lane, up);
 815                break;
 816        }
 817
 818        if (!err && up)
 819                err = mv88e6390_serdes_enable_checker(chip, lane);
 820
 821        return err;
 822}
 823
 824int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
 825                                int lane, unsigned int mode,
 826                                phy_interface_t interface,
 827                                const unsigned long *advertise)
 828{
 829        u16 val, bmcr, adv;
 830        bool changed;
 831        int err;
 832
 833        switch (interface) {
 834        case PHY_INTERFACE_MODE_SGMII:
 835                adv = 0x0001;
 836                break;
 837
 838        case PHY_INTERFACE_MODE_1000BASEX:
 839                adv = linkmode_adv_to_mii_adv_x(advertise,
 840                                        ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 841                break;
 842
 843        case PHY_INTERFACE_MODE_2500BASEX:
 844                adv = linkmode_adv_to_mii_adv_x(advertise,
 845                                        ETHTOOL_LINK_MODE_2500baseX_Full_BIT);
 846                break;
 847
 848        default:
 849                return 0;
 850        }
 851
 852        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 853                                    MV88E6390_SGMII_ADVERTISE, &val);
 854        if (err)
 855                return err;
 856
 857        changed = val != adv;
 858        if (changed) {
 859                err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 860                                             MV88E6390_SGMII_ADVERTISE, adv);
 861                if (err)
 862                        return err;
 863        }
 864
 865        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 866                                    MV88E6390_SGMII_BMCR, &val);
 867        if (err)
 868                return err;
 869
 870        if (phylink_autoneg_inband(mode))
 871                bmcr = val | BMCR_ANENABLE;
 872        else
 873                bmcr = val & ~BMCR_ANENABLE;
 874
 875        /* setting ANENABLE triggers a restart of negotiation */
 876        if (bmcr == val)
 877                return changed;
 878
 879        return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
 880                                      MV88E6390_SGMII_BMCR, bmcr);
 881}
 882
 883static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
 884        int port, int lane, struct phylink_link_state *state)
 885{
 886        u16 lpa, status;
 887        int err;
 888
 889        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 890                                    MV88E6390_SGMII_PHY_STATUS, &status);
 891        if (err) {
 892                dev_err(chip->dev, "can't read Serdes PHY status: %d\n", err);
 893                return err;
 894        }
 895
 896        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 897                                    MV88E6390_SGMII_LPA, &lpa);
 898        if (err) {
 899                dev_err(chip->dev, "can't read Serdes PHY LPA: %d\n", err);
 900                return err;
 901        }
 902
 903        return mv88e6xxx_serdes_pcs_get_state(chip, status, lpa, state);
 904}
 905
 906static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
 907        int port, int lane, struct phylink_link_state *state)
 908{
 909        u16 status;
 910        int err;
 911
 912        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 913                                    MV88E6390_10G_STAT1, &status);
 914        if (err)
 915                return err;
 916
 917        state->link = !!(status & MDIO_STAT1_LSTATUS);
 918        if (state->link) {
 919                state->speed = SPEED_10000;
 920                state->duplex = DUPLEX_FULL;
 921        }
 922
 923        return 0;
 924}
 925
 926static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
 927                                               int port, int lane,
 928                                               struct phylink_link_state *state)
 929{
 930        u16 status;
 931        int err;
 932
 933        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 934                                    MV88E6390_10G_STAT1, &status);
 935        if (err)
 936                return err;
 937
 938        state->link = !!(status & MDIO_STAT1_LSTATUS);
 939        if (state->link) {
 940                if (state->interface == PHY_INTERFACE_MODE_5GBASER)
 941                        state->speed = SPEED_5000;
 942                else
 943                        state->speed = SPEED_10000;
 944                state->duplex = DUPLEX_FULL;
 945        }
 946
 947        return 0;
 948}
 949
 950int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 951                                   int lane, struct phylink_link_state *state)
 952{
 953        switch (state->interface) {
 954        case PHY_INTERFACE_MODE_SGMII:
 955        case PHY_INTERFACE_MODE_1000BASEX:
 956        case PHY_INTERFACE_MODE_2500BASEX:
 957                return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
 958                                                            state);
 959        case PHY_INTERFACE_MODE_XAUI:
 960        case PHY_INTERFACE_MODE_RXAUI:
 961                return mv88e6390_serdes_pcs_get_state_10g(chip, port, lane,
 962                                                          state);
 963
 964        default:
 965                return -EOPNOTSUPP;
 966        }
 967}
 968
 969int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
 970                                    int lane, struct phylink_link_state *state)
 971{
 972        switch (state->interface) {
 973        case PHY_INTERFACE_MODE_SGMII:
 974        case PHY_INTERFACE_MODE_1000BASEX:
 975        case PHY_INTERFACE_MODE_2500BASEX:
 976                return mv88e6390_serdes_pcs_get_state_sgmii(chip, port, lane,
 977                                                            state);
 978        case PHY_INTERFACE_MODE_5GBASER:
 979        case PHY_INTERFACE_MODE_10GBASER:
 980                return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane,
 981                                                           state);
 982
 983        default:
 984                return -EOPNOTSUPP;
 985        }
 986}
 987
 988int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
 989                                    int lane)
 990{
 991        u16 bmcr;
 992        int err;
 993
 994        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
 995                                    MV88E6390_SGMII_BMCR, &bmcr);
 996        if (err)
 997                return err;
 998
 999        return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1000                                      MV88E6390_SGMII_BMCR,
1001                                      bmcr | BMCR_ANRESTART);
1002}
1003
1004int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
1005                                 int lane, int speed, int duplex)
1006{
1007        u16 val, bmcr;
1008        int err;
1009
1010        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1011                                    MV88E6390_SGMII_BMCR, &val);
1012        if (err)
1013                return err;
1014
1015        bmcr = val & ~(BMCR_SPEED100 | BMCR_FULLDPLX | BMCR_SPEED1000);
1016        switch (speed) {
1017        case SPEED_2500:
1018        case SPEED_1000:
1019                bmcr |= BMCR_SPEED1000;
1020                break;
1021        case SPEED_100:
1022                bmcr |= BMCR_SPEED100;
1023                break;
1024        case SPEED_10:
1025                break;
1026        }
1027
1028        if (duplex == DUPLEX_FULL)
1029                bmcr |= BMCR_FULLDPLX;
1030
1031        if (bmcr == val)
1032                return 0;
1033
1034        return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1035                                      MV88E6390_SGMII_BMCR, bmcr);
1036}
1037
1038static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
1039                                            int port, int lane)
1040{
1041        u16 bmsr;
1042        int err;
1043
1044        /* If the link has dropped, we want to know about it. */
1045        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1046                                    MV88E6390_SGMII_BMSR, &bmsr);
1047        if (err) {
1048                dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
1049                return;
1050        }
1051
1052        dsa_port_phylink_mac_change(chip->ds, port, !!(bmsr & BMSR_LSTATUS));
1053}
1054
1055static void mv88e6393x_serdes_irq_link_10g(struct mv88e6xxx_chip *chip,
1056                                           int port, u8 lane)
1057{
1058        u16 status;
1059        int err;
1060
1061        /* If the link has dropped, we want to know about it. */
1062        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1063                                    MV88E6390_10G_STAT1, &status);
1064        if (err) {
1065                dev_err(chip->dev, "can't read Serdes STAT1: %d\n", err);
1066                return;
1067        }
1068
1069        dsa_port_phylink_mac_change(chip->ds, port, !!(status & MDIO_STAT1_LSTATUS));
1070}
1071
1072static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
1073                                             int lane, bool enable)
1074{
1075        u16 val = 0;
1076
1077        if (enable)
1078                val |= MV88E6390_SGMII_INT_LINK_DOWN |
1079                        MV88E6390_SGMII_INT_LINK_UP;
1080
1081        return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1082                                      MV88E6390_SGMII_INT_ENABLE, val);
1083}
1084
1085int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
1086                                bool enable)
1087{
1088        u8 cmode = chip->ports[port].cmode;
1089
1090        switch (cmode) {
1091        case MV88E6XXX_PORT_STS_CMODE_SGMII:
1092        case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1093        case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1094                return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1095        }
1096
1097        return 0;
1098}
1099
1100static int mv88e6390_serdes_irq_status_sgmii(struct mv88e6xxx_chip *chip,
1101                                             int lane, u16 *status)
1102{
1103        int err;
1104
1105        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1106                                    MV88E6390_SGMII_INT_STATUS, status);
1107
1108        return err;
1109}
1110
1111static int mv88e6393x_serdes_irq_enable_10g(struct mv88e6xxx_chip *chip,
1112                                            u8 lane, bool enable)
1113{
1114        u16 val = 0;
1115
1116        if (enable)
1117                val |= MV88E6393X_10G_INT_LINK_CHANGE;
1118
1119        return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1120                                      MV88E6393X_10G_INT_ENABLE, val);
1121}
1122
1123int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
1124                                 int lane, bool enable)
1125{
1126        u8 cmode = chip->ports[port].cmode;
1127
1128        switch (cmode) {
1129        case MV88E6XXX_PORT_STS_CMODE_SGMII:
1130        case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1131        case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1132                return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable);
1133        case MV88E6393X_PORT_STS_CMODE_5GBASER:
1134        case MV88E6393X_PORT_STS_CMODE_10GBASER:
1135                return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable);
1136        }
1137
1138        return 0;
1139}
1140
1141static int mv88e6393x_serdes_irq_status_10g(struct mv88e6xxx_chip *chip,
1142                                            u8 lane, u16 *status)
1143{
1144        int err;
1145
1146        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1147                                    MV88E6393X_10G_INT_STATUS, status);
1148
1149        return err;
1150}
1151
1152irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1153                                         int lane)
1154{
1155        u8 cmode = chip->ports[port].cmode;
1156        irqreturn_t ret = IRQ_NONE;
1157        u16 status;
1158        int err;
1159
1160        switch (cmode) {
1161        case MV88E6XXX_PORT_STS_CMODE_SGMII:
1162        case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1163        case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1164                err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1165                if (err)
1166                        return ret;
1167                if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1168                              MV88E6390_SGMII_INT_LINK_UP)) {
1169                        ret = IRQ_HANDLED;
1170                        mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1171                }
1172                break;
1173        case MV88E6393X_PORT_STS_CMODE_5GBASER:
1174        case MV88E6393X_PORT_STS_CMODE_10GBASER:
1175                err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status);
1176                if (err)
1177                        return err;
1178                if (status & MV88E6393X_10G_INT_LINK_CHANGE) {
1179                        ret = IRQ_HANDLED;
1180                        mv88e6393x_serdes_irq_link_10g(chip, port, lane);
1181                }
1182                break;
1183        }
1184
1185        return ret;
1186}
1187
1188irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
1189                                        int lane)
1190{
1191        u8 cmode = chip->ports[port].cmode;
1192        irqreturn_t ret = IRQ_NONE;
1193        u16 status;
1194        int err;
1195
1196        switch (cmode) {
1197        case MV88E6XXX_PORT_STS_CMODE_SGMII:
1198        case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1199        case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1200                err = mv88e6390_serdes_irq_status_sgmii(chip, lane, &status);
1201                if (err)
1202                        return ret;
1203                if (status & (MV88E6390_SGMII_INT_LINK_DOWN |
1204                              MV88E6390_SGMII_INT_LINK_UP)) {
1205                        ret = IRQ_HANDLED;
1206                        mv88e6390_serdes_irq_link_sgmii(chip, port, lane);
1207                }
1208        }
1209
1210        return ret;
1211}
1212
1213unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
1214{
1215        return irq_find_mapping(chip->g2_irq.domain, port);
1216}
1217
1218static const u16 mv88e6390_serdes_regs[] = {
1219        /* SERDES common registers */
1220        0xf00a, 0xf00b, 0xf00c,
1221        0xf010, 0xf011, 0xf012, 0xf013,
1222        0xf016, 0xf017, 0xf018,
1223        0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
1224        0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
1225        0xf028, 0xf029,
1226        0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
1227        0xf038, 0xf039,
1228        /* SGMII */
1229        0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007,
1230        0x2008,
1231        0x200f,
1232        0xa000, 0xa001, 0xa002, 0xa003,
1233        /* 10Gbase-X */
1234        0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, 0x1007,
1235        0x1008,
1236        0x100e, 0x100f,
1237        0x1018, 0x1019,
1238        0x9000, 0x9001, 0x9002, 0x9003, 0x9004,
1239        0x9006,
1240        0x9010, 0x9011, 0x9012, 0x9013, 0x9014, 0x9015, 0x9016,
1241        /* 10Gbase-R */
1242        0x1020, 0x1021, 0x1022, 0x1023, 0x1024, 0x1025, 0x1026, 0x1027,
1243        0x1028, 0x1029, 0x102a, 0x102b,
1244};
1245
1246int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port)
1247{
1248        if (mv88e6xxx_serdes_get_lane(chip, port) < 0)
1249                return 0;
1250
1251        return ARRAY_SIZE(mv88e6390_serdes_regs) * sizeof(u16);
1252}
1253
1254void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
1255{
1256        u16 *p = _p;
1257        int lane;
1258        u16 reg;
1259        int err;
1260        int i;
1261
1262        lane = mv88e6xxx_serdes_get_lane(chip, port);
1263        if (lane < 0)
1264                return;
1265
1266        for (i = 0 ; i < ARRAY_SIZE(mv88e6390_serdes_regs); i++) {
1267                err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1268                                            mv88e6390_serdes_regs[i], &reg);
1269                if (!err)
1270                        p[i] = reg;
1271        }
1272}
1273
1274static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane)
1275{
1276        u16 reg, pcs;
1277        int err;
1278
1279        /* mv88e6393x family errata 4.6:
1280         * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD
1281         * mode or P0_mode is configured for [x]MII.
1282         * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
1283         *
1284         * It seems that after this workaround the SERDES is automatically
1285         * powered up (the bit is cleared), so power it down.
1286         */
1287        if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE ||
1288            lane == MV88E6393X_PORT10_LANE) {
1289                err = mv88e6390_serdes_read(chip, lane,
1290                                            MDIO_MMD_PHYXS,
1291                                            MV88E6393X_SERDES_POC, &reg);
1292                if (err)
1293                        return err;
1294
1295                reg &= ~MV88E6393X_SERDES_POC_PDOWN;
1296                reg |= MV88E6393X_SERDES_POC_RESET;
1297
1298                err = mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1299                                             MV88E6393X_SERDES_POC, reg);
1300                if (err)
1301                        return err;
1302
1303                err = mv88e6390_serdes_power_sgmii(chip, lane, false);
1304                if (err)
1305                        return err;
1306        }
1307
1308        /* mv88e6393x family errata 4.8:
1309         * When a SERDES port is operating in 1000BASE-X or SGMII mode link may
1310         * not come up after hardware reset or software reset of SERDES core.
1311         * Workaround is to write SERDES register 4.F074.14=1 for only those
1312         * modes and 0 in all other modes.
1313         */
1314        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1315                                    MV88E6393X_SERDES_POC, &pcs);
1316        if (err)
1317                return err;
1318
1319        pcs &= MV88E6393X_SERDES_POC_PCS_MASK;
1320
1321        err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
1322                                    MV88E6393X_ERRATA_4_8_REG, &reg);
1323        if (err)
1324                return err;
1325
1326        if (pcs == MV88E6393X_SERDES_POC_PCS_1000BASEX ||
1327            pcs == MV88E6393X_SERDES_POC_PCS_SGMII_PHY ||
1328            pcs == MV88E6393X_SERDES_POC_PCS_SGMII_MAC)
1329                reg |= MV88E6393X_ERRATA_4_8_BIT;
1330        else
1331                reg &= ~MV88E6393X_ERRATA_4_8_BIT;
1332
1333        return mv88e6390_serdes_write(chip, lane, MDIO_MMD_PHYXS,
1334                                      MV88E6393X_ERRATA_4_8_REG, reg);
1335}
1336
1337int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip)
1338{
1339        int err;
1340
1341        err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT0_LANE);
1342        if (err)
1343                return err;
1344
1345        err = mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT9_LANE);
1346        if (err)
1347                return err;
1348
1349        return mv88e6393x_serdes_port_errata(chip, MV88E6393X_PORT10_LANE);
1350}
1351
1352int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
1353                            bool on)
1354{
1355        u8 cmode = chip->ports[port].cmode;
1356
1357        if (port != 0 && port != 9 && port != 10)
1358                return -EOPNOTSUPP;
1359
1360        switch (cmode) {
1361        case MV88E6XXX_PORT_STS_CMODE_SGMII:
1362        case MV88E6XXX_PORT_STS_CMODE_1000BASEX:
1363        case MV88E6XXX_PORT_STS_CMODE_2500BASEX:
1364                return mv88e6390_serdes_power_sgmii(chip, lane, on);
1365        case MV88E6393X_PORT_STS_CMODE_5GBASER:
1366        case MV88E6393X_PORT_STS_CMODE_10GBASER:
1367                return mv88e6390_serdes_power_10g(chip, lane, on);
1368        }
1369
1370        return 0;
1371}
1372