linux/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/* Microchip Sparx5 Switch driver
   3 *
   4 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/phy/phy.h>
   9
  10#include "sparx5_main_regs.h"
  11#include "sparx5_main.h"
  12#include "sparx5_port.h"
  13
  14#define SPX5_ETYPE_TAG_C     0x8100
  15#define SPX5_ETYPE_TAG_S     0x88a8
  16
  17#define SPX5_WAIT_US         1000
  18#define SPX5_WAIT_MAX_US     2000
  19
  20enum port_error {
  21        SPX5_PERR_SPEED,
  22        SPX5_PERR_IFTYPE,
  23};
  24
  25#define PAUSE_DISCARD        0xC
  26#define ETH_MAXLEN           (ETH_DATA_LEN + ETH_HLEN + ETH_FCS_LEN)
  27
  28static void decode_sgmii_word(u16 lp_abil, struct sparx5_port_status *status)
  29{
  30        status->an_complete = true;
  31        if (!(lp_abil & LPA_SGMII_LINK)) {
  32                status->link = false;
  33                return;
  34        }
  35
  36        switch (lp_abil & LPA_SGMII_SPD_MASK) {
  37        case LPA_SGMII_10:
  38                status->speed = SPEED_10;
  39                break;
  40        case LPA_SGMII_100:
  41                status->speed = SPEED_100;
  42                break;
  43        case LPA_SGMII_1000:
  44                status->speed = SPEED_1000;
  45                break;
  46        default:
  47                status->link = false;
  48                return;
  49        }
  50        if (lp_abil & LPA_SGMII_FULL_DUPLEX)
  51                status->duplex = DUPLEX_FULL;
  52        else
  53                status->duplex = DUPLEX_HALF;
  54}
  55
  56static void decode_cl37_word(u16 lp_abil, uint16_t ld_abil, struct sparx5_port_status *status)
  57{
  58        status->link = !(lp_abil & ADVERTISE_RFAULT) && status->link;
  59        status->an_complete = true;
  60        status->duplex = (ADVERTISE_1000XFULL & lp_abil) ?
  61                DUPLEX_FULL : DUPLEX_UNKNOWN; // 1G HDX not supported
  62
  63        if ((ld_abil & ADVERTISE_1000XPAUSE) &&
  64            (lp_abil & ADVERTISE_1000XPAUSE)) {
  65                status->pause = MLO_PAUSE_RX | MLO_PAUSE_TX;
  66        } else if ((ld_abil & ADVERTISE_1000XPSE_ASYM) &&
  67                   (lp_abil & ADVERTISE_1000XPSE_ASYM)) {
  68                status->pause |= (lp_abil & ADVERTISE_1000XPAUSE) ?
  69                        MLO_PAUSE_TX : 0;
  70                status->pause |= (ld_abil & ADVERTISE_1000XPAUSE) ?
  71                        MLO_PAUSE_RX : 0;
  72        } else {
  73                status->pause = MLO_PAUSE_NONE;
  74        }
  75}
  76
  77static int sparx5_get_dev2g5_status(struct sparx5 *sparx5,
  78                                    struct sparx5_port *port,
  79                                    struct sparx5_port_status *status)
  80{
  81        u32 portno = port->portno;
  82        u16 lp_adv, ld_adv;
  83        u32 value;
  84
  85        /* Get PCS Link down sticky */
  86        value = spx5_rd(sparx5, DEV2G5_PCS1G_STICKY(portno));
  87        status->link_down = DEV2G5_PCS1G_STICKY_LINK_DOWN_STICKY_GET(value);
  88        if (status->link_down)  /* Clear the sticky */
  89                spx5_wr(value, sparx5, DEV2G5_PCS1G_STICKY(portno));
  90
  91        /* Get both current Link and Sync status */
  92        value = spx5_rd(sparx5, DEV2G5_PCS1G_LINK_STATUS(portno));
  93        status->link = DEV2G5_PCS1G_LINK_STATUS_LINK_STATUS_GET(value) &&
  94                       DEV2G5_PCS1G_LINK_STATUS_SYNC_STATUS_GET(value);
  95
  96        if (port->conf.portmode == PHY_INTERFACE_MODE_1000BASEX)
  97                status->speed = SPEED_1000;
  98        else if (port->conf.portmode == PHY_INTERFACE_MODE_2500BASEX)
  99                status->speed = SPEED_2500;
 100
 101        status->duplex = DUPLEX_FULL;
 102
 103        /* Get PCS ANEG status register */
 104        value = spx5_rd(sparx5, DEV2G5_PCS1G_ANEG_STATUS(portno));
 105
 106        /* Aneg complete provides more information  */
 107        if (DEV2G5_PCS1G_ANEG_STATUS_ANEG_COMPLETE_GET(value)) {
 108                lp_adv = DEV2G5_PCS1G_ANEG_STATUS_LP_ADV_ABILITY_GET(value);
 109                if (port->conf.portmode == PHY_INTERFACE_MODE_SGMII) {
 110                        decode_sgmii_word(lp_adv, status);
 111                } else {
 112                        value = spx5_rd(sparx5, DEV2G5_PCS1G_ANEG_CFG(portno));
 113                        ld_adv = DEV2G5_PCS1G_ANEG_CFG_ADV_ABILITY_GET(value);
 114                        decode_cl37_word(lp_adv, ld_adv, status);
 115                }
 116        }
 117        return 0;
 118}
 119
 120static int sparx5_get_sfi_status(struct sparx5 *sparx5,
 121                                 struct sparx5_port *port,
 122                                 struct sparx5_port_status *status)
 123{
 124        bool high_speed_dev = sparx5_is_baser(port->conf.portmode);
 125        u32 portno = port->portno;
 126        u32 value, dev, tinst;
 127        void __iomem *inst;
 128
 129        if (!high_speed_dev) {
 130                netdev_err(port->ndev, "error: low speed and SFI mode\n");
 131                return -EINVAL;
 132        }
 133
 134        dev = sparx5_to_high_dev(portno);
 135        tinst = sparx5_port_dev_index(portno);
 136        inst = spx5_inst_get(sparx5, dev, tinst);
 137
 138        value = spx5_inst_rd(inst, DEV10G_MAC_TX_MONITOR_STICKY(0));
 139        if (value != DEV10G_MAC_TX_MONITOR_STICKY_IDLE_STATE_STICKY) {
 140                /* The link is or has been down. Clear the sticky bit */
 141                status->link_down = 1;
 142                spx5_inst_wr(0xffffffff, inst, DEV10G_MAC_TX_MONITOR_STICKY(0));
 143                value = spx5_inst_rd(inst, DEV10G_MAC_TX_MONITOR_STICKY(0));
 144        }
 145        status->link = (value == DEV10G_MAC_TX_MONITOR_STICKY_IDLE_STATE_STICKY);
 146        status->duplex = DUPLEX_FULL;
 147        if (port->conf.portmode == PHY_INTERFACE_MODE_5GBASER)
 148                status->speed = SPEED_5000;
 149        else if (port->conf.portmode == PHY_INTERFACE_MODE_10GBASER)
 150                status->speed = SPEED_10000;
 151        else
 152                status->speed = SPEED_25000;
 153
 154        return 0;
 155}
 156
 157/* Get link status of 1000Base-X/in-band and SFI ports.
 158 */
 159int sparx5_get_port_status(struct sparx5 *sparx5,
 160                           struct sparx5_port *port,
 161                           struct sparx5_port_status *status)
 162{
 163        memset(status, 0, sizeof(*status));
 164        status->speed = port->conf.speed;
 165        if (port->conf.power_down) {
 166                status->link = false;
 167                return 0;
 168        }
 169        switch (port->conf.portmode) {
 170        case PHY_INTERFACE_MODE_SGMII:
 171        case PHY_INTERFACE_MODE_QSGMII:
 172        case PHY_INTERFACE_MODE_1000BASEX:
 173        case PHY_INTERFACE_MODE_2500BASEX:
 174                return sparx5_get_dev2g5_status(sparx5, port, status);
 175        case PHY_INTERFACE_MODE_5GBASER:
 176        case PHY_INTERFACE_MODE_10GBASER:
 177        case PHY_INTERFACE_MODE_25GBASER:
 178                return sparx5_get_sfi_status(sparx5, port, status);
 179        case PHY_INTERFACE_MODE_NA:
 180                return 0;
 181        default:
 182                netdev_err(port->ndev, "Status not supported");
 183                return -ENODEV;
 184        }
 185        return 0;
 186}
 187
 188static int sparx5_port_error(struct sparx5_port *port,
 189                             struct sparx5_port_config *conf,
 190                             enum port_error errtype)
 191{
 192        switch (errtype) {
 193        case SPX5_PERR_SPEED:
 194                netdev_err(port->ndev,
 195                           "Interface does not support speed: %u: for %s\n",
 196                           conf->speed, phy_modes(conf->portmode));
 197                break;
 198        case SPX5_PERR_IFTYPE:
 199                netdev_err(port->ndev,
 200                           "Switch port does not support interface type: %s\n",
 201                           phy_modes(conf->portmode));
 202                break;
 203        default:
 204                netdev_err(port->ndev,
 205                           "Interface configuration error\n");
 206        }
 207
 208        return -EINVAL;
 209}
 210
 211static int sparx5_port_verify_speed(struct sparx5 *sparx5,
 212                                    struct sparx5_port *port,
 213                                    struct sparx5_port_config *conf)
 214{
 215        if ((sparx5_port_is_2g5(port->portno) &&
 216             conf->speed > SPEED_2500) ||
 217            (sparx5_port_is_5g(port->portno)  &&
 218             conf->speed > SPEED_5000) ||
 219            (sparx5_port_is_10g(port->portno) &&
 220             conf->speed > SPEED_10000))
 221                return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
 222
 223        switch (conf->portmode) {
 224        case PHY_INTERFACE_MODE_NA:
 225                return -EINVAL;
 226        case PHY_INTERFACE_MODE_1000BASEX:
 227                if (conf->speed != SPEED_1000 ||
 228                    sparx5_port_is_2g5(port->portno))
 229                        return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
 230                if (sparx5_port_is_2g5(port->portno))
 231                        return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
 232                break;
 233        case PHY_INTERFACE_MODE_2500BASEX:
 234                if (conf->speed != SPEED_2500 ||
 235                    sparx5_port_is_2g5(port->portno))
 236                        return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
 237                break;
 238        case PHY_INTERFACE_MODE_QSGMII:
 239                if (port->portno > 47)
 240                        return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
 241                fallthrough;
 242        case PHY_INTERFACE_MODE_SGMII:
 243                if (conf->speed != SPEED_1000 &&
 244                    conf->speed != SPEED_100 &&
 245                    conf->speed != SPEED_10 &&
 246                    conf->speed != SPEED_2500)
 247                        return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
 248                break;
 249        case PHY_INTERFACE_MODE_5GBASER:
 250        case PHY_INTERFACE_MODE_10GBASER:
 251        case PHY_INTERFACE_MODE_25GBASER:
 252                if ((conf->speed != SPEED_5000 &&
 253                     conf->speed != SPEED_10000 &&
 254                     conf->speed != SPEED_25000))
 255                        return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
 256                break;
 257        default:
 258                return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
 259        }
 260        return 0;
 261}
 262
 263static bool sparx5_dev_change(struct sparx5 *sparx5,
 264                              struct sparx5_port *port,
 265                              struct sparx5_port_config *conf)
 266{
 267        return sparx5_is_baser(port->conf.portmode) ^
 268                sparx5_is_baser(conf->portmode);
 269}
 270
 271static int sparx5_port_flush_poll(struct sparx5 *sparx5, u32 portno)
 272{
 273        u32  value, resource, prio, delay_cnt = 0;
 274        bool poll_src = true;
 275        char *mem = "";
 276
 277        /* Resource == 0: Memory tracked per source (SRC-MEM)
 278         * Resource == 1: Frame references tracked per source (SRC-REF)
 279         * Resource == 2: Memory tracked per destination (DST-MEM)
 280         * Resource == 3: Frame references tracked per destination. (DST-REF)
 281         */
 282        while (1) {
 283                bool empty = true;
 284
 285                for (resource = 0; resource < (poll_src ? 2 : 1); resource++) {
 286                        u32 base;
 287
 288                        base = (resource == 0 ? 2048 : 0) + SPX5_PRIOS * portno;
 289                        for (prio = 0; prio < SPX5_PRIOS; prio++) {
 290                                value = spx5_rd(sparx5,
 291                                                QRES_RES_STAT(base + prio));
 292                                if (value) {
 293                                        mem = resource == 0 ?
 294                                                "DST-MEM" : "SRC-MEM";
 295                                        empty = false;
 296                                }
 297                        }
 298                }
 299
 300                if (empty)
 301                        break;
 302
 303                if (delay_cnt++ == 2000) {
 304                        dev_err(sparx5->dev,
 305                                "Flush timeout port %u. %s queue not empty\n",
 306                                portno, mem);
 307                        return -EINVAL;
 308                }
 309
 310                usleep_range(SPX5_WAIT_US, SPX5_WAIT_MAX_US);
 311        }
 312        return 0;
 313}
 314
 315static int sparx5_port_disable(struct sparx5 *sparx5, struct sparx5_port *port, bool high_spd_dev)
 316{
 317        u32 tinst = high_spd_dev ?
 318                    sparx5_port_dev_index(port->portno) : port->portno;
 319        u32 dev = high_spd_dev ?
 320                  sparx5_to_high_dev(port->portno) : TARGET_DEV2G5;
 321        void __iomem *devinst = spx5_inst_get(sparx5, dev, tinst);
 322        u32 spd = port->conf.speed;
 323        u32 spd_prm;
 324        int err;
 325
 326        if (high_spd_dev) {
 327                /* 1: Reset the PCS Rx clock domain  */
 328                spx5_inst_rmw(DEV10G_DEV_RST_CTRL_PCS_RX_RST,
 329                              DEV10G_DEV_RST_CTRL_PCS_RX_RST,
 330                              devinst,
 331                              DEV10G_DEV_RST_CTRL(0));
 332
 333                /* 2: Disable MAC frame reception */
 334                spx5_inst_rmw(0,
 335                              DEV10G_MAC_ENA_CFG_RX_ENA,
 336                              devinst,
 337                              DEV10G_MAC_ENA_CFG(0));
 338        } else {
 339                /* 1: Reset the PCS Rx clock domain  */
 340                spx5_inst_rmw(DEV2G5_DEV_RST_CTRL_PCS_RX_RST,
 341                              DEV2G5_DEV_RST_CTRL_PCS_RX_RST,
 342                              devinst,
 343                              DEV2G5_DEV_RST_CTRL(0));
 344                /* 2: Disable MAC frame reception */
 345                spx5_inst_rmw(0,
 346                              DEV2G5_MAC_ENA_CFG_RX_ENA,
 347                              devinst,
 348                              DEV2G5_MAC_ENA_CFG(0));
 349        }
 350        /* 3: Disable traffic being sent to or from switch port->portno */
 351        spx5_rmw(0,
 352                 QFWD_SWITCH_PORT_MODE_PORT_ENA,
 353                 sparx5,
 354                 QFWD_SWITCH_PORT_MODE(port->portno));
 355
 356        /* 4: Disable dequeuing from the egress queues  */
 357        spx5_rmw(HSCH_PORT_MODE_DEQUEUE_DIS,
 358                 HSCH_PORT_MODE_DEQUEUE_DIS,
 359                 sparx5,
 360                 HSCH_PORT_MODE(port->portno));
 361
 362        /* 5: Disable Flowcontrol */
 363        spx5_rmw(QSYS_PAUSE_CFG_PAUSE_STOP_SET(0xFFF - 1),
 364                 QSYS_PAUSE_CFG_PAUSE_STOP,
 365                 sparx5,
 366                 QSYS_PAUSE_CFG(port->portno));
 367
 368        spd_prm = spd == SPEED_10 ? 1000 : spd == SPEED_100 ? 100 : 10;
 369        /* 6: Wait while the last frame is exiting the queues */
 370        usleep_range(8 * spd_prm, 10 * spd_prm);
 371
 372        /* 7: Flush the queues accociated with the port->portno */
 373        spx5_rmw(HSCH_FLUSH_CTRL_FLUSH_PORT_SET(port->portno) |
 374                 HSCH_FLUSH_CTRL_FLUSH_DST_SET(1) |
 375                 HSCH_FLUSH_CTRL_FLUSH_SRC_SET(1) |
 376                 HSCH_FLUSH_CTRL_FLUSH_ENA_SET(1),
 377                 HSCH_FLUSH_CTRL_FLUSH_PORT |
 378                 HSCH_FLUSH_CTRL_FLUSH_DST |
 379                 HSCH_FLUSH_CTRL_FLUSH_SRC |
 380                 HSCH_FLUSH_CTRL_FLUSH_ENA,
 381                 sparx5,
 382                 HSCH_FLUSH_CTRL);
 383
 384        /* 8: Enable dequeuing from the egress queues */
 385        spx5_rmw(0,
 386                 HSCH_PORT_MODE_DEQUEUE_DIS,
 387                 sparx5,
 388                 HSCH_PORT_MODE(port->portno));
 389
 390        /* 9: Wait until flushing is complete */
 391        err = sparx5_port_flush_poll(sparx5, port->portno);
 392        if (err)
 393                return err;
 394
 395        /* 10: Reset the  MAC clock domain */
 396        if (high_spd_dev) {
 397                spx5_inst_rmw(DEV10G_DEV_RST_CTRL_PCS_TX_RST_SET(1) |
 398                              DEV10G_DEV_RST_CTRL_MAC_RX_RST_SET(1) |
 399                              DEV10G_DEV_RST_CTRL_MAC_TX_RST_SET(1),
 400                              DEV10G_DEV_RST_CTRL_PCS_TX_RST |
 401                              DEV10G_DEV_RST_CTRL_MAC_RX_RST |
 402                              DEV10G_DEV_RST_CTRL_MAC_TX_RST,
 403                              devinst,
 404                              DEV10G_DEV_RST_CTRL(0));
 405
 406        } else {
 407                spx5_inst_rmw(DEV2G5_DEV_RST_CTRL_SPEED_SEL_SET(3) |
 408                              DEV2G5_DEV_RST_CTRL_PCS_TX_RST_SET(1) |
 409                              DEV2G5_DEV_RST_CTRL_PCS_RX_RST_SET(1) |
 410                              DEV2G5_DEV_RST_CTRL_MAC_TX_RST_SET(1) |
 411                              DEV2G5_DEV_RST_CTRL_MAC_RX_RST_SET(1),
 412                              DEV2G5_DEV_RST_CTRL_SPEED_SEL |
 413                              DEV2G5_DEV_RST_CTRL_PCS_TX_RST |
 414                              DEV2G5_DEV_RST_CTRL_PCS_RX_RST |
 415                              DEV2G5_DEV_RST_CTRL_MAC_TX_RST |
 416                              DEV2G5_DEV_RST_CTRL_MAC_RX_RST,
 417                              devinst,
 418                              DEV2G5_DEV_RST_CTRL(0));
 419        }
 420        /* 11: Clear flushing */
 421        spx5_rmw(HSCH_FLUSH_CTRL_FLUSH_PORT_SET(port->portno) |
 422                 HSCH_FLUSH_CTRL_FLUSH_ENA_SET(0),
 423                 HSCH_FLUSH_CTRL_FLUSH_PORT |
 424                 HSCH_FLUSH_CTRL_FLUSH_ENA,
 425                 sparx5,
 426                 HSCH_FLUSH_CTRL);
 427
 428        if (high_spd_dev) {
 429                u32 pcs = sparx5_to_pcs_dev(port->portno);
 430                void __iomem *pcsinst = spx5_inst_get(sparx5, pcs, tinst);
 431
 432                /* 12: Disable 5G/10G/25 BaseR PCS */
 433                spx5_inst_rmw(PCS10G_BR_PCS_CFG_PCS_ENA_SET(0),
 434                              PCS10G_BR_PCS_CFG_PCS_ENA,
 435                              pcsinst,
 436                              PCS10G_BR_PCS_CFG(0));
 437
 438                if (sparx5_port_is_25g(port->portno))
 439                        /* Disable 25G PCS */
 440                        spx5_rmw(DEV25G_PCS25G_CFG_PCS25G_ENA_SET(0),
 441                                 DEV25G_PCS25G_CFG_PCS25G_ENA,
 442                                 sparx5,
 443                                 DEV25G_PCS25G_CFG(tinst));
 444        } else {
 445                /* 12: Disable 1G PCS */
 446                spx5_rmw(DEV2G5_PCS1G_CFG_PCS_ENA_SET(0),
 447                         DEV2G5_PCS1G_CFG_PCS_ENA,
 448                         sparx5,
 449                         DEV2G5_PCS1G_CFG(port->portno));
 450        }
 451
 452        /* The port is now flushed and disabled  */
 453        return 0;
 454}
 455
 456static int sparx5_port_fifo_sz(struct sparx5 *sparx5,
 457                               u32 portno, u32 speed)
 458{
 459        u32 sys_clk = sparx5_clk_period(sparx5->coreclock);
 460        const u32 taxi_dist[SPX5_PORTS_ALL] = {
 461                6, 8, 10, 6, 8, 10, 6, 8, 10, 6, 8, 10,
 462                4, 4, 4, 4,
 463                11, 12, 13, 14, 15, 16, 17, 18,
 464                11, 12, 13, 14, 15, 16, 17, 18,
 465                11, 12, 13, 14, 15, 16, 17, 18,
 466                11, 12, 13, 14, 15, 16, 17, 18,
 467                4, 6, 8, 4, 6, 8, 6, 8,
 468                2, 2, 2, 2, 2, 2, 2, 4, 2
 469        };
 470        u32 mac_per    = 6400, tmp1, tmp2, tmp3;
 471        u32 fifo_width = 16;
 472        u32 mac_width  = 8;
 473        u32 addition   = 0;
 474
 475        switch (speed) {
 476        case SPEED_25000:
 477                return 0;
 478        case SPEED_10000:
 479                mac_per = 6400;
 480                mac_width = 8;
 481                addition = 1;
 482                break;
 483        case SPEED_5000:
 484                mac_per = 12800;
 485                mac_width = 8;
 486                addition = 0;
 487                break;
 488        case SPEED_2500:
 489                mac_per = 3200;
 490                mac_width = 1;
 491                addition = 0;
 492                break;
 493        case SPEED_1000:
 494                mac_per =  8000;
 495                mac_width = 1;
 496                addition = 0;
 497                break;
 498        case SPEED_100:
 499        case SPEED_10:
 500                return 1;
 501        default:
 502                break;
 503        }
 504
 505        tmp1 = 1000 * mac_width / fifo_width;
 506        tmp2 = 3000 + ((12000 + 2 * taxi_dist[portno] * 1000)
 507                       * sys_clk / mac_per);
 508        tmp3 = tmp1 * tmp2 / 1000;
 509        return  (tmp3 + 2000 + 999) / 1000 + addition;
 510}
 511
 512/* Configure port muxing:
 513 * QSGMII:     4x2G5 devices
 514 */
 515static int sparx5_port_mux_set(struct sparx5 *sparx5,
 516                               struct sparx5_port *port,
 517                               struct sparx5_port_config *conf)
 518{
 519        u32 portno = port->portno;
 520        u32 inst;
 521
 522        if (port->conf.portmode == conf->portmode)
 523                return 0; /* Nothing to do */
 524
 525        switch (conf->portmode) {
 526        case PHY_INTERFACE_MODE_QSGMII: /* QSGMII: 4x2G5 devices. Mode Q'  */
 527                inst = (portno - portno % 4) / 4;
 528                spx5_rmw(BIT(inst),
 529                         BIT(inst),
 530                         sparx5,
 531                         PORT_CONF_QSGMII_ENA);
 532
 533                if ((portno / 4 % 2) == 0) {
 534                        /* Affects d0-d3,d8-d11..d40-d43 */
 535                        spx5_rmw(PORT_CONF_USGMII_CFG_BYPASS_SCRAM_SET(1) |
 536                                 PORT_CONF_USGMII_CFG_BYPASS_DESCRAM_SET(1) |
 537                                 PORT_CONF_USGMII_CFG_QUAD_MODE_SET(1),
 538                                 PORT_CONF_USGMII_CFG_BYPASS_SCRAM |
 539                                 PORT_CONF_USGMII_CFG_BYPASS_DESCRAM |
 540                                 PORT_CONF_USGMII_CFG_QUAD_MODE,
 541                                 sparx5,
 542                                 PORT_CONF_USGMII_CFG((portno / 8)));
 543                }
 544                break;
 545        default:
 546                break;
 547        }
 548        return 0;
 549}
 550
 551static int sparx5_port_max_tags_set(struct sparx5 *sparx5,
 552                                    struct sparx5_port *port)
 553{
 554        enum sparx5_port_max_tags max_tags    = port->max_vlan_tags;
 555        int tag_ct          = max_tags == SPX5_PORT_MAX_TAGS_ONE ? 1 :
 556                              max_tags == SPX5_PORT_MAX_TAGS_TWO ? 2 : 0;
 557        bool dtag           = max_tags == SPX5_PORT_MAX_TAGS_TWO;
 558        enum sparx5_vlan_port_type vlan_type  = port->vlan_type;
 559        bool dotag          = max_tags != SPX5_PORT_MAX_TAGS_NONE;
 560        u32 dev             = sparx5_to_high_dev(port->portno);
 561        u32 tinst           = sparx5_port_dev_index(port->portno);
 562        void __iomem *inst  = spx5_inst_get(sparx5, dev, tinst);
 563        u32 etype;
 564
 565        etype = (vlan_type == SPX5_VLAN_PORT_TYPE_S_CUSTOM ?
 566                 port->custom_etype :
 567                 vlan_type == SPX5_VLAN_PORT_TYPE_C ?
 568                 SPX5_ETYPE_TAG_C : SPX5_ETYPE_TAG_S);
 569
 570        spx5_wr(DEV2G5_MAC_TAGS_CFG_TAG_ID_SET(etype) |
 571                DEV2G5_MAC_TAGS_CFG_PB_ENA_SET(dtag) |
 572                DEV2G5_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(dotag) |
 573                DEV2G5_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA_SET(dotag),
 574                sparx5,
 575                DEV2G5_MAC_TAGS_CFG(port->portno));
 576
 577        if (sparx5_port_is_2g5(port->portno))
 578                return 0;
 579
 580        spx5_inst_rmw(DEV10G_MAC_TAGS_CFG_TAG_ID_SET(etype) |
 581                      DEV10G_MAC_TAGS_CFG_TAG_ENA_SET(dotag),
 582                      DEV10G_MAC_TAGS_CFG_TAG_ID |
 583                      DEV10G_MAC_TAGS_CFG_TAG_ENA,
 584                      inst,
 585                      DEV10G_MAC_TAGS_CFG(0, 0));
 586
 587        spx5_inst_rmw(DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS_SET(tag_ct),
 588                      DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS,
 589                      inst,
 590                      DEV10G_MAC_NUM_TAGS_CFG(0));
 591
 592        spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK_SET(dotag),
 593                      DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK,
 594                      inst,
 595                      DEV10G_MAC_MAXLEN_CFG(0));
 596        return 0;
 597}
 598
 599int sparx5_port_fwd_urg(struct sparx5 *sparx5, u32 speed)
 600{
 601        u32 clk_period_ps = 1600; /* 625Mhz for now */
 602        u32 urg = 672000;
 603
 604        switch (speed) {
 605        case SPEED_10:
 606        case SPEED_100:
 607        case SPEED_1000:
 608                urg = 672000;
 609                break;
 610        case SPEED_2500:
 611                urg = 270000;
 612                break;
 613        case SPEED_5000:
 614                urg = 135000;
 615                break;
 616        case SPEED_10000:
 617                urg = 67200;
 618                break;
 619        case SPEED_25000:
 620                urg = 27000;
 621                break;
 622        }
 623        return urg / clk_period_ps - 1;
 624}
 625
 626static u16 sparx5_wm_enc(u16 value)
 627{
 628        if (value >= 2048)
 629                return 2048 + value / 16;
 630
 631        return value;
 632}
 633
 634static int sparx5_port_fc_setup(struct sparx5 *sparx5,
 635                                struct sparx5_port *port,
 636                                struct sparx5_port_config *conf)
 637{
 638        bool fc_obey = conf->pause & MLO_PAUSE_RX ? 1 : 0;
 639        u32 pause_stop = 0xFFF - 1; /* FC gen disabled */
 640
 641        if (conf->pause & MLO_PAUSE_TX)
 642                pause_stop = sparx5_wm_enc(4  * (ETH_MAXLEN /
 643                                                 SPX5_BUFFER_CELL_SZ));
 644
 645        /* Set HDX flowcontrol */
 646        spx5_rmw(DSM_MAC_CFG_HDX_BACKPREASSURE_SET(conf->duplex == DUPLEX_HALF),
 647                 DSM_MAC_CFG_HDX_BACKPREASSURE,
 648                 sparx5,
 649                 DSM_MAC_CFG(port->portno));
 650
 651        /* Obey flowcontrol  */
 652        spx5_rmw(DSM_RX_PAUSE_CFG_RX_PAUSE_EN_SET(fc_obey),
 653                 DSM_RX_PAUSE_CFG_RX_PAUSE_EN,
 654                 sparx5,
 655                 DSM_RX_PAUSE_CFG(port->portno));
 656
 657        /* Disable forward pressure */
 658        spx5_rmw(QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS_SET(fc_obey),
 659                 QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS,
 660                 sparx5,
 661                 QSYS_FWD_PRESSURE(port->portno));
 662
 663        /* Generate pause frames */
 664        spx5_rmw(QSYS_PAUSE_CFG_PAUSE_STOP_SET(pause_stop),
 665                 QSYS_PAUSE_CFG_PAUSE_STOP,
 666                 sparx5,
 667                 QSYS_PAUSE_CFG(port->portno));
 668
 669        return 0;
 670}
 671
 672static u16 sparx5_get_aneg_word(struct sparx5_port_config *conf)
 673{
 674        if (conf->portmode == PHY_INTERFACE_MODE_1000BASEX) /* cl-37 aneg */
 675                return (conf->pause_adv | ADVERTISE_LPACK | ADVERTISE_1000XFULL);
 676        else
 677                return 1; /* Enable SGMII Aneg */
 678}
 679
 680int sparx5_serdes_set(struct sparx5 *sparx5,
 681                      struct sparx5_port *port,
 682                      struct sparx5_port_config *conf)
 683{
 684        int portmode, err, speed = conf->speed;
 685
 686        if (conf->portmode == PHY_INTERFACE_MODE_QSGMII &&
 687            ((port->portno % 4) != 0)) {
 688                return 0;
 689        }
 690        if (sparx5_is_baser(conf->portmode)) {
 691                if (conf->portmode == PHY_INTERFACE_MODE_25GBASER)
 692                        speed = SPEED_25000;
 693                else if (conf->portmode == PHY_INTERFACE_MODE_10GBASER)
 694                        speed = SPEED_10000;
 695                else
 696                        speed = SPEED_5000;
 697        }
 698
 699        err = phy_set_media(port->serdes, conf->media);
 700        if (err)
 701                return err;
 702        if (speed > 0) {
 703                err = phy_set_speed(port->serdes, speed);
 704                if (err)
 705                        return err;
 706        }
 707        if (conf->serdes_reset) {
 708                err = phy_reset(port->serdes);
 709                if (err)
 710                        return err;
 711        }
 712
 713        /* Configure SerDes with port parameters
 714         * For BaseR, the serdes driver supports 10GGBASE-R and speed 5G/10G/25G
 715         */
 716        portmode = conf->portmode;
 717        if (sparx5_is_baser(conf->portmode))
 718                portmode = PHY_INTERFACE_MODE_10GBASER;
 719        err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET, portmode);
 720        if (err)
 721                return err;
 722        conf->serdes_reset = false;
 723        return err;
 724}
 725
 726static int sparx5_port_pcs_low_set(struct sparx5 *sparx5,
 727                                   struct sparx5_port *port,
 728                                   struct sparx5_port_config *conf)
 729{
 730        bool sgmii = false, inband_aneg = false;
 731        int err;
 732
 733        if (port->conf.inband) {
 734                if (conf->portmode == PHY_INTERFACE_MODE_SGMII ||
 735                    conf->portmode == PHY_INTERFACE_MODE_QSGMII)
 736                        inband_aneg = true; /* Cisco-SGMII in-band-aneg */
 737                else if (conf->portmode == PHY_INTERFACE_MODE_1000BASEX &&
 738                         conf->autoneg)
 739                        inband_aneg = true; /* Clause-37 in-band-aneg */
 740
 741                err = sparx5_serdes_set(sparx5, port, conf);
 742                if (err)
 743                        return -EINVAL;
 744        } else {
 745                sgmii = true; /* Phy is connnected to the MAC */
 746        }
 747
 748        /* Choose SGMII or 1000BaseX/2500BaseX PCS mode */
 749        spx5_rmw(DEV2G5_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(sgmii),
 750                 DEV2G5_PCS1G_MODE_CFG_SGMII_MODE_ENA,
 751                 sparx5,
 752                 DEV2G5_PCS1G_MODE_CFG(port->portno));
 753
 754        /* Enable PCS */
 755        spx5_wr(DEV2G5_PCS1G_CFG_PCS_ENA_SET(1),
 756                sparx5,
 757                DEV2G5_PCS1G_CFG(port->portno));
 758
 759        if (inband_aneg) {
 760                u16 abil = sparx5_get_aneg_word(conf);
 761
 762                /* Enable in-band aneg */
 763                spx5_wr(DEV2G5_PCS1G_ANEG_CFG_ADV_ABILITY_SET(abil) |
 764                        DEV2G5_PCS1G_ANEG_CFG_SW_RESOLVE_ENA_SET(1) |
 765                        DEV2G5_PCS1G_ANEG_CFG_ANEG_ENA_SET(1) |
 766                        DEV2G5_PCS1G_ANEG_CFG_ANEG_RESTART_ONE_SHOT_SET(1),
 767                        sparx5,
 768                        DEV2G5_PCS1G_ANEG_CFG(port->portno));
 769        } else {
 770                spx5_wr(0, sparx5, DEV2G5_PCS1G_ANEG_CFG(port->portno));
 771        }
 772
 773        /* Take PCS out of reset */
 774        spx5_rmw(DEV2G5_DEV_RST_CTRL_SPEED_SEL_SET(2) |
 775                 DEV2G5_DEV_RST_CTRL_PCS_TX_RST_SET(0) |
 776                 DEV2G5_DEV_RST_CTRL_PCS_RX_RST_SET(0),
 777                 DEV2G5_DEV_RST_CTRL_SPEED_SEL |
 778                 DEV2G5_DEV_RST_CTRL_PCS_TX_RST |
 779                 DEV2G5_DEV_RST_CTRL_PCS_RX_RST,
 780                 sparx5,
 781                 DEV2G5_DEV_RST_CTRL(port->portno));
 782
 783        return 0;
 784}
 785
 786static int sparx5_port_pcs_high_set(struct sparx5 *sparx5,
 787                                    struct sparx5_port *port,
 788                                    struct sparx5_port_config *conf)
 789{
 790        u32 clk_spd = conf->portmode == PHY_INTERFACE_MODE_5GBASER ? 1 : 0;
 791        u32 pix = sparx5_port_dev_index(port->portno);
 792        u32 dev = sparx5_to_high_dev(port->portno);
 793        u32 pcs = sparx5_to_pcs_dev(port->portno);
 794        void __iomem *devinst;
 795        void __iomem *pcsinst;
 796        int err;
 797
 798        devinst = spx5_inst_get(sparx5, dev, pix);
 799        pcsinst = spx5_inst_get(sparx5, pcs, pix);
 800
 801        /*  SFI : No in-band-aneg. Speeds 5G/10G/25G */
 802        err = sparx5_serdes_set(sparx5, port, conf);
 803        if (err)
 804                return -EINVAL;
 805        if (conf->portmode == PHY_INTERFACE_MODE_25GBASER) {
 806                /* Enable PCS for 25G device, speed 25G */
 807                spx5_rmw(DEV25G_PCS25G_CFG_PCS25G_ENA_SET(1),
 808                         DEV25G_PCS25G_CFG_PCS25G_ENA,
 809                         sparx5,
 810                         DEV25G_PCS25G_CFG(pix));
 811        } else {
 812                /* Enable PCS for 5G/10G/25G devices, speed 5G/10G */
 813                spx5_inst_rmw(PCS10G_BR_PCS_CFG_PCS_ENA_SET(1),
 814                              PCS10G_BR_PCS_CFG_PCS_ENA,
 815                              pcsinst,
 816                              PCS10G_BR_PCS_CFG(0));
 817        }
 818
 819        /* Enable 5G/10G/25G MAC module */
 820        spx5_inst_wr(DEV10G_MAC_ENA_CFG_RX_ENA_SET(1) |
 821                     DEV10G_MAC_ENA_CFG_TX_ENA_SET(1),
 822                     devinst,
 823                     DEV10G_MAC_ENA_CFG(0));
 824
 825        /* Take the device out of reset */
 826        spx5_inst_rmw(DEV10G_DEV_RST_CTRL_PCS_RX_RST_SET(0) |
 827                      DEV10G_DEV_RST_CTRL_PCS_TX_RST_SET(0) |
 828                      DEV10G_DEV_RST_CTRL_MAC_RX_RST_SET(0) |
 829                      DEV10G_DEV_RST_CTRL_MAC_TX_RST_SET(0) |
 830                      DEV10G_DEV_RST_CTRL_SPEED_SEL_SET(clk_spd),
 831                      DEV10G_DEV_RST_CTRL_PCS_RX_RST |
 832                      DEV10G_DEV_RST_CTRL_PCS_TX_RST |
 833                      DEV10G_DEV_RST_CTRL_MAC_RX_RST |
 834                      DEV10G_DEV_RST_CTRL_MAC_TX_RST |
 835                      DEV10G_DEV_RST_CTRL_SPEED_SEL,
 836                      devinst,
 837                      DEV10G_DEV_RST_CTRL(0));
 838
 839        return 0;
 840}
 841
 842/* Switch between 1G/2500 and 5G/10G/25G devices */
 843static void sparx5_dev_switch(struct sparx5 *sparx5, int port, bool hsd)
 844{
 845        int bt_indx = BIT(sparx5_port_dev_index(port));
 846
 847        if (sparx5_port_is_5g(port)) {
 848                spx5_rmw(hsd ? 0 : bt_indx,
 849                         bt_indx,
 850                         sparx5,
 851                         PORT_CONF_DEV5G_MODES);
 852        } else if (sparx5_port_is_10g(port)) {
 853                spx5_rmw(hsd ? 0 : bt_indx,
 854                         bt_indx,
 855                         sparx5,
 856                         PORT_CONF_DEV10G_MODES);
 857        } else if (sparx5_port_is_25g(port)) {
 858                spx5_rmw(hsd ? 0 : bt_indx,
 859                         bt_indx,
 860                         sparx5,
 861                         PORT_CONF_DEV25G_MODES);
 862        }
 863}
 864
 865/* Configure speed/duplex dependent registers */
 866static int sparx5_port_config_low_set(struct sparx5 *sparx5,
 867                                      struct sparx5_port *port,
 868                                      struct sparx5_port_config *conf)
 869{
 870        u32 clk_spd, gig_mode, tx_gap, hdx_gap_1, hdx_gap_2;
 871        bool fdx = conf->duplex == DUPLEX_FULL;
 872        int spd = conf->speed;
 873
 874        clk_spd = spd == SPEED_10 ? 0 : spd == SPEED_100 ? 1 : 2;
 875        gig_mode = spd == SPEED_1000 || spd == SPEED_2500;
 876        tx_gap = spd == SPEED_1000 ? 4 : fdx ? 6 : 5;
 877        hdx_gap_1 = spd == SPEED_1000 ? 0 : spd == SPEED_100 ? 1 : 2;
 878        hdx_gap_2 = spd == SPEED_1000 ? 0 : spd == SPEED_100 ? 4 : 1;
 879
 880        /* GIG/FDX mode */
 881        spx5_rmw(DEV2G5_MAC_MODE_CFG_GIGA_MODE_ENA_SET(gig_mode) |
 882                 DEV2G5_MAC_MODE_CFG_FDX_ENA_SET(fdx),
 883                 DEV2G5_MAC_MODE_CFG_GIGA_MODE_ENA |
 884                 DEV2G5_MAC_MODE_CFG_FDX_ENA,
 885                 sparx5,
 886                 DEV2G5_MAC_MODE_CFG(port->portno));
 887
 888        /* Set MAC IFG Gaps */
 889        spx5_wr(DEV2G5_MAC_IFG_CFG_TX_IFG_SET(tx_gap) |
 890                DEV2G5_MAC_IFG_CFG_RX_IFG1_SET(hdx_gap_1) |
 891                DEV2G5_MAC_IFG_CFG_RX_IFG2_SET(hdx_gap_2),
 892                sparx5,
 893                DEV2G5_MAC_IFG_CFG(port->portno));
 894
 895        /* Disabling frame aging when in HDX (due to HDX issue) */
 896        spx5_rmw(HSCH_PORT_MODE_AGE_DIS_SET(fdx == 0),
 897                 HSCH_PORT_MODE_AGE_DIS,
 898                 sparx5,
 899                 HSCH_PORT_MODE(port->portno));
 900
 901        /* Enable MAC module */
 902        spx5_wr(DEV2G5_MAC_ENA_CFG_RX_ENA |
 903                DEV2G5_MAC_ENA_CFG_TX_ENA,
 904                sparx5,
 905                DEV2G5_MAC_ENA_CFG(port->portno));
 906
 907        /* Select speed and take MAC out of reset */
 908        spx5_rmw(DEV2G5_DEV_RST_CTRL_SPEED_SEL_SET(clk_spd) |
 909                 DEV2G5_DEV_RST_CTRL_MAC_TX_RST_SET(0) |
 910                 DEV2G5_DEV_RST_CTRL_MAC_RX_RST_SET(0),
 911                 DEV2G5_DEV_RST_CTRL_SPEED_SEL |
 912                 DEV2G5_DEV_RST_CTRL_MAC_TX_RST |
 913                 DEV2G5_DEV_RST_CTRL_MAC_RX_RST,
 914                 sparx5,
 915                 DEV2G5_DEV_RST_CTRL(port->portno));
 916
 917        return 0;
 918}
 919
 920int sparx5_port_pcs_set(struct sparx5 *sparx5,
 921                        struct sparx5_port *port,
 922                        struct sparx5_port_config *conf)
 923
 924{
 925        bool high_speed_dev = sparx5_is_baser(conf->portmode);
 926        int err;
 927
 928        if (sparx5_dev_change(sparx5, port, conf)) {
 929                /* switch device */
 930                sparx5_dev_switch(sparx5, port->portno, high_speed_dev);
 931
 932                /* Disable the not-in-use device */
 933                err = sparx5_port_disable(sparx5, port, !high_speed_dev);
 934                if (err)
 935                        return err;
 936        }
 937        /* Disable the port before re-configuring */
 938        err = sparx5_port_disable(sparx5, port, high_speed_dev);
 939        if (err)
 940                return -EINVAL;
 941
 942        if (high_speed_dev)
 943                err = sparx5_port_pcs_high_set(sparx5, port, conf);
 944        else
 945                err = sparx5_port_pcs_low_set(sparx5, port, conf);
 946
 947        if (err)
 948                return -EINVAL;
 949
 950        if (port->conf.inband) {
 951                /* Enable/disable 1G counters in ASM */
 952                spx5_rmw(ASM_PORT_CFG_CSC_STAT_DIS_SET(high_speed_dev),
 953                         ASM_PORT_CFG_CSC_STAT_DIS,
 954                         sparx5,
 955                         ASM_PORT_CFG(port->portno));
 956
 957                /* Enable/disable 1G counters in DSM */
 958                spx5_rmw(DSM_BUF_CFG_CSC_STAT_DIS_SET(high_speed_dev),
 959                         DSM_BUF_CFG_CSC_STAT_DIS,
 960                         sparx5,
 961                         DSM_BUF_CFG(port->portno));
 962        }
 963
 964        port->conf = *conf;
 965
 966        return 0;
 967}
 968
 969int sparx5_port_config(struct sparx5 *sparx5,
 970                       struct sparx5_port *port,
 971                       struct sparx5_port_config *conf)
 972{
 973        bool high_speed_dev = sparx5_is_baser(conf->portmode);
 974        int err, urgency, stop_wm;
 975
 976        err = sparx5_port_verify_speed(sparx5, port, conf);
 977        if (err)
 978                return err;
 979
 980        /* high speed device is already configured */
 981        if (!high_speed_dev)
 982                sparx5_port_config_low_set(sparx5, port, conf);
 983
 984        /* Configure flow control */
 985        err = sparx5_port_fc_setup(sparx5, port, conf);
 986        if (err)
 987                return err;
 988
 989        /* Set the DSM stop watermark */
 990        stop_wm = sparx5_port_fifo_sz(sparx5, port->portno, conf->speed);
 991        spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM_SET(stop_wm),
 992                 DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM,
 993                 sparx5,
 994                 DSM_DEV_TX_STOP_WM_CFG(port->portno));
 995
 996        /* Enable port in queue system */
 997        urgency = sparx5_port_fwd_urg(sparx5, conf->speed);
 998        spx5_rmw(QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(1) |
 999                 QFWD_SWITCH_PORT_MODE_FWD_URGENCY_SET(urgency),
1000                 QFWD_SWITCH_PORT_MODE_PORT_ENA |
1001                 QFWD_SWITCH_PORT_MODE_FWD_URGENCY,
1002                 sparx5,
1003                 QFWD_SWITCH_PORT_MODE(port->portno));
1004
1005        /* Save the new values */
1006        port->conf = *conf;
1007
1008        return 0;
1009}
1010
1011/* Initialize port config to default */
1012int sparx5_port_init(struct sparx5 *sparx5,
1013                     struct sparx5_port *port,
1014                     struct sparx5_port_config *conf)
1015{
1016        u32 pause_start = sparx5_wm_enc(6  * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
1017        u32 atop = sparx5_wm_enc(20 * (ETH_MAXLEN / SPX5_BUFFER_CELL_SZ));
1018        u32 devhigh = sparx5_to_high_dev(port->portno);
1019        u32 pix = sparx5_port_dev_index(port->portno);
1020        u32 pcs = sparx5_to_pcs_dev(port->portno);
1021        bool sd_pol = port->signd_active_high;
1022        bool sd_sel = !port->signd_internal;
1023        bool sd_ena = port->signd_enable;
1024        u32 pause_stop = 0xFFF - 1; /* FC generate disabled */
1025        void __iomem *devinst;
1026        void __iomem *pcsinst;
1027        int err;
1028
1029        devinst = spx5_inst_get(sparx5, devhigh, pix);
1030        pcsinst = spx5_inst_get(sparx5, pcs, pix);
1031
1032        /* Set the mux port mode  */
1033        err = sparx5_port_mux_set(sparx5, port, conf);
1034        if (err)
1035                return err;
1036
1037        /* Configure MAC vlan awareness */
1038        err = sparx5_port_max_tags_set(sparx5, port);
1039        if (err)
1040                return err;
1041
1042        /* Set Max Length */
1043        spx5_rmw(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
1044                 DEV2G5_MAC_MAXLEN_CFG_MAX_LEN,
1045                 sparx5,
1046                 DEV2G5_MAC_MAXLEN_CFG(port->portno));
1047
1048        /* 1G/2G5: Signal Detect configuration */
1049        spx5_wr(DEV2G5_PCS1G_SD_CFG_SD_POL_SET(sd_pol) |
1050                DEV2G5_PCS1G_SD_CFG_SD_SEL_SET(sd_sel) |
1051                DEV2G5_PCS1G_SD_CFG_SD_ENA_SET(sd_ena),
1052                sparx5,
1053                DEV2G5_PCS1G_SD_CFG(port->portno));
1054
1055        /* Set Pause WM hysteresis */
1056        spx5_rmw(QSYS_PAUSE_CFG_PAUSE_START_SET(pause_start) |
1057                 QSYS_PAUSE_CFG_PAUSE_STOP_SET(pause_stop) |
1058                 QSYS_PAUSE_CFG_PAUSE_ENA_SET(1),
1059                 QSYS_PAUSE_CFG_PAUSE_START |
1060                 QSYS_PAUSE_CFG_PAUSE_STOP |
1061                 QSYS_PAUSE_CFG_PAUSE_ENA,
1062                 sparx5,
1063                 QSYS_PAUSE_CFG(port->portno));
1064
1065        /* Port ATOP. Frames are tail dropped when this WM is hit */
1066        spx5_wr(QSYS_ATOP_ATOP_SET(atop),
1067                sparx5,
1068                QSYS_ATOP(port->portno));
1069
1070        /* Discard pause frame 01-80-C2-00-00-01 */
1071        spx5_wr(PAUSE_DISCARD, sparx5, ANA_CL_CAPTURE_BPDU_CFG(port->portno));
1072
1073        if (conf->portmode == PHY_INTERFACE_MODE_QSGMII ||
1074            conf->portmode == PHY_INTERFACE_MODE_SGMII) {
1075                err = sparx5_serdes_set(sparx5, port, conf);
1076                if (err)
1077                        return err;
1078
1079                if (!sparx5_port_is_2g5(port->portno))
1080                        /* Enable shadow device */
1081                        spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA_SET(1),
1082                                 DSM_DEV_TX_STOP_WM_CFG_DEV10G_SHADOW_ENA,
1083                                 sparx5,
1084                                 DSM_DEV_TX_STOP_WM_CFG(port->portno));
1085
1086                sparx5_dev_switch(sparx5, port->portno, false);
1087        }
1088        if (conf->portmode == PHY_INTERFACE_MODE_QSGMII) {
1089                // All ports must be PCS enabled in QSGMII mode
1090                spx5_rmw(DEV2G5_DEV_RST_CTRL_PCS_TX_RST_SET(0),
1091                         DEV2G5_DEV_RST_CTRL_PCS_TX_RST,
1092                         sparx5,
1093                         DEV2G5_DEV_RST_CTRL(port->portno));
1094        }
1095        /* Default IFGs for 1G */
1096        spx5_wr(DEV2G5_MAC_IFG_CFG_TX_IFG_SET(6) |
1097                DEV2G5_MAC_IFG_CFG_RX_IFG1_SET(0) |
1098                DEV2G5_MAC_IFG_CFG_RX_IFG2_SET(0),
1099                sparx5,
1100                DEV2G5_MAC_IFG_CFG(port->portno));
1101
1102        if (sparx5_port_is_2g5(port->portno))
1103                return 0; /* Low speed device only - return */
1104
1105        /* Now setup the high speed device */
1106        if (conf->portmode == PHY_INTERFACE_MODE_NA)
1107                conf->portmode = PHY_INTERFACE_MODE_10GBASER;
1108
1109        if (sparx5_is_baser(conf->portmode))
1110                sparx5_dev_switch(sparx5, port->portno, true);
1111
1112        /* Set Max Length */
1113        spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
1114                      DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
1115                      devinst,
1116                      DEV10G_MAC_ENA_CFG(0));
1117
1118        /* Handle Signal Detect in 10G PCS */
1119        spx5_inst_wr(PCS10G_BR_PCS_SD_CFG_SD_POL_SET(sd_pol) |
1120                     PCS10G_BR_PCS_SD_CFG_SD_SEL_SET(sd_sel) |
1121                     PCS10G_BR_PCS_SD_CFG_SD_ENA_SET(sd_ena),
1122                     pcsinst,
1123                     PCS10G_BR_PCS_SD_CFG(0));
1124
1125        if (sparx5_port_is_25g(port->portno)) {
1126                /* Handle Signal Detect in 25G PCS */
1127                spx5_wr(DEV25G_PCS25G_SD_CFG_SD_POL_SET(sd_pol) |
1128                        DEV25G_PCS25G_SD_CFG_SD_SEL_SET(sd_sel) |
1129                        DEV25G_PCS25G_SD_CFG_SD_ENA_SET(sd_ena),
1130                        sparx5,
1131                        DEV25G_PCS25G_SD_CFG(pix));
1132        }
1133
1134        return 0;
1135}
1136
1137void sparx5_port_enable(struct sparx5_port *port, bool enable)
1138{
1139        struct sparx5 *sparx5 = port->sparx5;
1140
1141        /* Enable port for frame transfer? */
1142        spx5_rmw(QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(enable),
1143                 QFWD_SWITCH_PORT_MODE_PORT_ENA,
1144                 sparx5,
1145                 QFWD_SWITCH_PORT_MODE(port->portno));
1146}
1147