Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /* Microchip Sparx5 Switch driver
0003  *
0004  * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
0005  */
0006 
0007 #include <linux/module.h>
0008 #include <linux/phy/phy.h>
0009 
0010 #include "sparx5_main_regs.h"
0011 #include "sparx5_main.h"
0012 #include "sparx5_port.h"
0013 
0014 #define SPX5_ETYPE_TAG_C     0x8100
0015 #define SPX5_ETYPE_TAG_S     0x88a8
0016 
0017 #define SPX5_WAIT_US         1000
0018 #define SPX5_WAIT_MAX_US     2000
0019 
0020 enum port_error {
0021     SPX5_PERR_SPEED,
0022     SPX5_PERR_IFTYPE,
0023 };
0024 
0025 #define PAUSE_DISCARD        0xC
0026 #define ETH_MAXLEN           (ETH_DATA_LEN + ETH_HLEN + ETH_FCS_LEN)
0027 
0028 static void decode_sgmii_word(u16 lp_abil, struct sparx5_port_status *status)
0029 {
0030     status->an_complete = true;
0031     if (!(lp_abil & LPA_SGMII_LINK)) {
0032         status->link = false;
0033         return;
0034     }
0035 
0036     switch (lp_abil & LPA_SGMII_SPD_MASK) {
0037     case LPA_SGMII_10:
0038         status->speed = SPEED_10;
0039         break;
0040     case LPA_SGMII_100:
0041         status->speed = SPEED_100;
0042         break;
0043     case LPA_SGMII_1000:
0044         status->speed = SPEED_1000;
0045         break;
0046     default:
0047         status->link = false;
0048         return;
0049     }
0050     if (lp_abil & LPA_SGMII_FULL_DUPLEX)
0051         status->duplex = DUPLEX_FULL;
0052     else
0053         status->duplex = DUPLEX_HALF;
0054 }
0055 
0056 static void decode_cl37_word(u16 lp_abil, uint16_t ld_abil, struct sparx5_port_status *status)
0057 {
0058     status->link = !(lp_abil & ADVERTISE_RFAULT) && status->link;
0059     status->an_complete = true;
0060     status->duplex = (ADVERTISE_1000XFULL & lp_abil) ?
0061         DUPLEX_FULL : DUPLEX_UNKNOWN; // 1G HDX not supported
0062 
0063     if ((ld_abil & ADVERTISE_1000XPAUSE) &&
0064         (lp_abil & ADVERTISE_1000XPAUSE)) {
0065         status->pause = MLO_PAUSE_RX | MLO_PAUSE_TX;
0066     } else if ((ld_abil & ADVERTISE_1000XPSE_ASYM) &&
0067            (lp_abil & ADVERTISE_1000XPSE_ASYM)) {
0068         status->pause |= (lp_abil & ADVERTISE_1000XPAUSE) ?
0069             MLO_PAUSE_TX : 0;
0070         status->pause |= (ld_abil & ADVERTISE_1000XPAUSE) ?
0071             MLO_PAUSE_RX : 0;
0072     } else {
0073         status->pause = MLO_PAUSE_NONE;
0074     }
0075 }
0076 
0077 static int sparx5_get_dev2g5_status(struct sparx5 *sparx5,
0078                     struct sparx5_port *port,
0079                     struct sparx5_port_status *status)
0080 {
0081     u32 portno = port->portno;
0082     u16 lp_adv, ld_adv;
0083     u32 value;
0084 
0085     /* Get PCS Link down sticky */
0086     value = spx5_rd(sparx5, DEV2G5_PCS1G_STICKY(portno));
0087     status->link_down = DEV2G5_PCS1G_STICKY_LINK_DOWN_STICKY_GET(value);
0088     if (status->link_down)  /* Clear the sticky */
0089         spx5_wr(value, sparx5, DEV2G5_PCS1G_STICKY(portno));
0090 
0091     /* Get both current Link and Sync status */
0092     value = spx5_rd(sparx5, DEV2G5_PCS1G_LINK_STATUS(portno));
0093     status->link = DEV2G5_PCS1G_LINK_STATUS_LINK_STATUS_GET(value) &&
0094                DEV2G5_PCS1G_LINK_STATUS_SYNC_STATUS_GET(value);
0095 
0096     if (port->conf.portmode == PHY_INTERFACE_MODE_1000BASEX)
0097         status->speed = SPEED_1000;
0098     else if (port->conf.portmode == PHY_INTERFACE_MODE_2500BASEX)
0099         status->speed = SPEED_2500;
0100 
0101     status->duplex = DUPLEX_FULL;
0102 
0103     /* Get PCS ANEG status register */
0104     value = spx5_rd(sparx5, DEV2G5_PCS1G_ANEG_STATUS(portno));
0105 
0106     /* Aneg complete provides more information  */
0107     if (DEV2G5_PCS1G_ANEG_STATUS_ANEG_COMPLETE_GET(value)) {
0108         lp_adv = DEV2G5_PCS1G_ANEG_STATUS_LP_ADV_ABILITY_GET(value);
0109         if (port->conf.portmode == PHY_INTERFACE_MODE_SGMII) {
0110             decode_sgmii_word(lp_adv, status);
0111         } else {
0112             value = spx5_rd(sparx5, DEV2G5_PCS1G_ANEG_CFG(portno));
0113             ld_adv = DEV2G5_PCS1G_ANEG_CFG_ADV_ABILITY_GET(value);
0114             decode_cl37_word(lp_adv, ld_adv, status);
0115         }
0116     }
0117     return 0;
0118 }
0119 
0120 static int sparx5_get_sfi_status(struct sparx5 *sparx5,
0121                  struct sparx5_port *port,
0122                  struct sparx5_port_status *status)
0123 {
0124     bool high_speed_dev = sparx5_is_baser(port->conf.portmode);
0125     u32 portno = port->portno;
0126     u32 value, dev, tinst;
0127     void __iomem *inst;
0128 
0129     if (!high_speed_dev) {
0130         netdev_err(port->ndev, "error: low speed and SFI mode\n");
0131         return -EINVAL;
0132     }
0133 
0134     dev = sparx5_to_high_dev(portno);
0135     tinst = sparx5_port_dev_index(portno);
0136     inst = spx5_inst_get(sparx5, dev, tinst);
0137 
0138     value = spx5_inst_rd(inst, DEV10G_MAC_TX_MONITOR_STICKY(0));
0139     if (value != DEV10G_MAC_TX_MONITOR_STICKY_IDLE_STATE_STICKY) {
0140         /* The link is or has been down. Clear the sticky bit */
0141         status->link_down = 1;
0142         spx5_inst_wr(0xffffffff, inst, DEV10G_MAC_TX_MONITOR_STICKY(0));
0143         value = spx5_inst_rd(inst, DEV10G_MAC_TX_MONITOR_STICKY(0));
0144     }
0145     status->link = (value == DEV10G_MAC_TX_MONITOR_STICKY_IDLE_STATE_STICKY);
0146     status->duplex = DUPLEX_FULL;
0147     if (port->conf.portmode == PHY_INTERFACE_MODE_5GBASER)
0148         status->speed = SPEED_5000;
0149     else if (port->conf.portmode == PHY_INTERFACE_MODE_10GBASER)
0150         status->speed = SPEED_10000;
0151     else
0152         status->speed = SPEED_25000;
0153 
0154     return 0;
0155 }
0156 
0157 /* Get link status of 1000Base-X/in-band and SFI ports.
0158  */
0159 int sparx5_get_port_status(struct sparx5 *sparx5,
0160                struct sparx5_port *port,
0161                struct sparx5_port_status *status)
0162 {
0163     memset(status, 0, sizeof(*status));
0164     status->speed = port->conf.speed;
0165     if (port->conf.power_down) {
0166         status->link = false;
0167         return 0;
0168     }
0169     switch (port->conf.portmode) {
0170     case PHY_INTERFACE_MODE_SGMII:
0171     case PHY_INTERFACE_MODE_QSGMII:
0172     case PHY_INTERFACE_MODE_1000BASEX:
0173     case PHY_INTERFACE_MODE_2500BASEX:
0174         return sparx5_get_dev2g5_status(sparx5, port, status);
0175     case PHY_INTERFACE_MODE_5GBASER:
0176     case PHY_INTERFACE_MODE_10GBASER:
0177     case PHY_INTERFACE_MODE_25GBASER:
0178         return sparx5_get_sfi_status(sparx5, port, status);
0179     case PHY_INTERFACE_MODE_NA:
0180         return 0;
0181     default:
0182         netdev_err(port->ndev, "Status not supported");
0183         return -ENODEV;
0184     }
0185     return 0;
0186 }
0187 
0188 static int sparx5_port_error(struct sparx5_port *port,
0189                  struct sparx5_port_config *conf,
0190                  enum port_error errtype)
0191 {
0192     switch (errtype) {
0193     case SPX5_PERR_SPEED:
0194         netdev_err(port->ndev,
0195                "Interface does not support speed: %u: for %s\n",
0196                conf->speed, phy_modes(conf->portmode));
0197         break;
0198     case SPX5_PERR_IFTYPE:
0199         netdev_err(port->ndev,
0200                "Switch port does not support interface type: %s\n",
0201                phy_modes(conf->portmode));
0202         break;
0203     default:
0204         netdev_err(port->ndev,
0205                "Interface configuration error\n");
0206     }
0207 
0208     return -EINVAL;
0209 }
0210 
0211 static int sparx5_port_verify_speed(struct sparx5 *sparx5,
0212                     struct sparx5_port *port,
0213                     struct sparx5_port_config *conf)
0214 {
0215     if ((sparx5_port_is_2g5(port->portno) &&
0216          conf->speed > SPEED_2500) ||
0217         (sparx5_port_is_5g(port->portno)  &&
0218          conf->speed > SPEED_5000) ||
0219         (sparx5_port_is_10g(port->portno) &&
0220          conf->speed > SPEED_10000))
0221         return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
0222 
0223     switch (conf->portmode) {
0224     case PHY_INTERFACE_MODE_NA:
0225         return -EINVAL;
0226     case PHY_INTERFACE_MODE_1000BASEX:
0227         if (conf->speed != SPEED_1000 ||
0228             sparx5_port_is_2g5(port->portno))
0229             return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
0230         if (sparx5_port_is_2g5(port->portno))
0231             return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
0232         break;
0233     case PHY_INTERFACE_MODE_2500BASEX:
0234         if (conf->speed != SPEED_2500 ||
0235             sparx5_port_is_2g5(port->portno))
0236             return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
0237         break;
0238     case PHY_INTERFACE_MODE_QSGMII:
0239         if (port->portno > 47)
0240             return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
0241         fallthrough;
0242     case PHY_INTERFACE_MODE_SGMII:
0243         if (conf->speed != SPEED_1000 &&
0244             conf->speed != SPEED_100 &&
0245             conf->speed != SPEED_10 &&
0246             conf->speed != SPEED_2500)
0247             return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
0248         break;
0249     case PHY_INTERFACE_MODE_5GBASER:
0250     case PHY_INTERFACE_MODE_10GBASER:
0251     case PHY_INTERFACE_MODE_25GBASER:
0252         if ((conf->speed != SPEED_5000 &&
0253              conf->speed != SPEED_10000 &&
0254              conf->speed != SPEED_25000))
0255             return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
0256         break;
0257     default:
0258         return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
0259     }
0260     return 0;
0261 }
0262 
0263 static bool sparx5_dev_change(struct sparx5 *sparx5,
0264                   struct sparx5_port *port,
0265                   struct sparx5_port_config *conf)
0266 {
0267     return sparx5_is_baser(port->conf.portmode) ^
0268         sparx5_is_baser(conf->portmode);
0269 }
0270 
0271 static int sparx5_port_flush_poll(struct sparx5 *sparx5, u32 portno)
0272 {
0273     u32  value, resource, prio, delay_cnt = 0;
0274     bool poll_src = true;
0275     char *mem = "";
0276 
0277     /* Resource == 0: Memory tracked per source (SRC-MEM)
0278      * Resource == 1: Frame references tracked per source (SRC-REF)
0279      * Resource == 2: Memory tracked per destination (DST-MEM)
0280      * Resource == 3: Frame references tracked per destination. (DST-REF)
0281      */
0282     while (1) {
0283         bool empty = true;
0284 
0285         for (resource = 0; resource < (poll_src ? 2 : 1); resource++) {
0286             u32 base;
0287 
0288             base = (resource == 0 ? 2048 : 0) + SPX5_PRIOS * portno;
0289             for (prio = 0; prio < SPX5_PRIOS; prio++) {
0290                 value = spx5_rd(sparx5,
0291                         QRES_RES_STAT(base + prio));
0292                 if (value) {
0293                     mem = resource == 0 ?
0294                         "DST-MEM" : "SRC-MEM";
0295                     empty = false;
0296                 }
0297             }
0298         }
0299 
0300         if (empty)
0301             break;
0302 
0303         if (delay_cnt++ == 2000) {
0304             dev_err(sparx5->dev,
0305                 "Flush timeout port %u. %s queue not empty\n",
0306                 portno, mem);
0307             return -EINVAL;
0308         }
0309 
0310         usleep_range(SPX5_WAIT_US, SPX5_WAIT_MAX_US);
0311     }
0312     return 0;
0313 }
0314 
0315 static int sparx5_port_disable(struct sparx5 *sparx5, struct sparx5_port *port, bool high_spd_dev)
0316 {
0317     u32 tinst = high_spd_dev ?
0318             sparx5_port_dev_index(port->portno) : port->portno;
0319     u32 dev = high_spd_dev ?
0320           sparx5_to_high_dev(port->portno) : TARGET_DEV2G5;
0321     void __iomem *devinst = spx5_inst_get(sparx5, dev, tinst);
0322     u32 spd = port->conf.speed;
0323     u32 spd_prm;
0324     int err;
0325 
0326     if (high_spd_dev) {
0327         /* 1: Reset the PCS Rx clock domain  */
0328         spx5_inst_rmw(DEV10G_DEV_RST_CTRL_PCS_RX_RST,
0329                   DEV10G_DEV_RST_CTRL_PCS_RX_RST,
0330                   devinst,
0331                   DEV10G_DEV_RST_CTRL(0));
0332 
0333         /* 2: Disable MAC frame reception */
0334         spx5_inst_rmw(0,
0335                   DEV10G_MAC_ENA_CFG_RX_ENA,
0336                   devinst,
0337                   DEV10G_MAC_ENA_CFG(0));
0338     } else {
0339         /* 1: Reset the PCS Rx clock domain  */
0340         spx5_inst_rmw(DEV2G5_DEV_RST_CTRL_PCS_RX_RST,
0341                   DEV2G5_DEV_RST_CTRL_PCS_RX_RST,
0342                   devinst,
0343                   DEV2G5_DEV_RST_CTRL(0));
0344         /* 2: Disable MAC frame reception */
0345         spx5_inst_rmw(0,
0346                   DEV2G5_MAC_ENA_CFG_RX_ENA,
0347                   devinst,
0348                   DEV2G5_MAC_ENA_CFG(0));
0349     }
0350     /* 3: Disable traffic being sent to or from switch port->portno */
0351     spx5_rmw(0,
0352          QFWD_SWITCH_PORT_MODE_PORT_ENA,
0353          sparx5,
0354          QFWD_SWITCH_PORT_MODE(port->portno));
0355 
0356     /* 4: Disable dequeuing from the egress queues  */
0357     spx5_rmw(HSCH_PORT_MODE_DEQUEUE_DIS,
0358          HSCH_PORT_MODE_DEQUEUE_DIS,
0359          sparx5,
0360          HSCH_PORT_MODE(port->portno));
0361 
0362     /* 5: Disable Flowcontrol */
0363     spx5_rmw(QSYS_PAUSE_CFG_PAUSE_STOP_SET(0xFFF - 1),
0364          QSYS_PAUSE_CFG_PAUSE_STOP,
0365          sparx5,
0366          QSYS_PAUSE_CFG(port->portno));
0367 
0368     spd_prm = spd == SPEED_10 ? 1000 : spd == SPEED_100 ? 100 : 10;
0369     /* 6: Wait while the last frame is exiting the queues */
0370     usleep_range(8 * spd_prm, 10 * spd_prm);
0371 
0372     /* 7: Flush the queues accociated with the port->portno */
0373     spx5_rmw(HSCH_FLUSH_CTRL_FLUSH_PORT_SET(port->portno) |
0374          HSCH_FLUSH_CTRL_FLUSH_DST_SET(1) |
0375          HSCH_FLUSH_CTRL_FLUSH_SRC_SET(1) |
0376          HSCH_FLUSH_CTRL_FLUSH_ENA_SET(1),
0377          HSCH_FLUSH_CTRL_FLUSH_PORT |
0378          HSCH_FLUSH_CTRL_FLUSH_DST |
0379          HSCH_FLUSH_CTRL_FLUSH_SRC |
0380          HSCH_FLUSH_CTRL_FLUSH_ENA,
0381          sparx5,
0382          HSCH_FLUSH_CTRL);
0383 
0384     /* 8: Enable dequeuing from the egress queues */
0385     spx5_rmw(0,
0386          HSCH_PORT_MODE_DEQUEUE_DIS,
0387          sparx5,
0388          HSCH_PORT_MODE(port->portno));
0389 
0390     /* 9: Wait until flushing is complete */
0391     err = sparx5_port_flush_poll(sparx5, port->portno);
0392     if (err)
0393         return err;
0394 
0395     /* 10: Reset the  MAC clock domain */
0396     if (high_spd_dev) {
0397         spx5_inst_rmw(DEV10G_DEV_RST_CTRL_PCS_TX_RST_SET(1) |
0398                   DEV10G_DEV_RST_CTRL_MAC_RX_RST_SET(1) |
0399                   DEV10G_DEV_RST_CTRL_MAC_TX_RST_SET(1),
0400                   DEV10G_DEV_RST_CTRL_PCS_TX_RST |
0401                   DEV10G_DEV_RST_CTRL_MAC_RX_RST |
0402                   DEV10G_DEV_RST_CTRL_MAC_TX_RST,
0403                   devinst,
0404                   DEV10G_DEV_RST_CTRL(0));
0405 
0406     } else {
0407         spx5_inst_rmw(DEV2G5_DEV_RST_CTRL_SPEED_SEL_SET(3) |
0408                   DEV2G5_DEV_RST_CTRL_PCS_TX_RST_SET(1) |
0409                   DEV2G5_DEV_RST_CTRL_PCS_RX_RST_SET(1) |
0410                   DEV2G5_DEV_RST_CTRL_MAC_TX_RST_SET(1) |
0411                   DEV2G5_DEV_RST_CTRL_MAC_RX_RST_SET(1),
0412                   DEV2G5_DEV_RST_CTRL_SPEED_SEL |
0413                   DEV2G5_DEV_RST_CTRL_PCS_TX_RST |
0414                   DEV2G5_DEV_RST_CTRL_PCS_RX_RST |
0415                   DEV2G5_DEV_RST_CTRL_MAC_TX_RST |
0416                   DEV2G5_DEV_RST_CTRL_MAC_RX_RST,
0417                   devinst,
0418                   DEV2G5_DEV_RST_CTRL(0));
0419     }
0420     /* 11: Clear flushing */
0421     spx5_rmw(HSCH_FLUSH_CTRL_FLUSH_PORT_SET(port->portno) |
0422          HSCH_FLUSH_CTRL_FLUSH_ENA_SET(0),
0423          HSCH_FLUSH_CTRL_FLUSH_PORT |
0424          HSCH_FLUSH_CTRL_FLUSH_ENA,
0425          sparx5,
0426          HSCH_FLUSH_CTRL);
0427 
0428     if (high_spd_dev) {
0429         u32 pcs = sparx5_to_pcs_dev(port->portno);
0430         void __iomem *pcsinst = spx5_inst_get(sparx5, pcs, tinst);
0431 
0432         /* 12: Disable 5G/10G/25 BaseR PCS */
0433         spx5_inst_rmw(PCS10G_BR_PCS_CFG_PCS_ENA_SET(0),
0434                   PCS10G_BR_PCS_CFG_PCS_ENA,
0435                   pcsinst,
0436                   PCS10G_BR_PCS_CFG(0));
0437 
0438         if (sparx5_port_is_25g(port->portno))
0439             /* Disable 25G PCS */
0440             spx5_rmw(DEV25G_PCS25G_CFG_PCS25G_ENA_SET(0),
0441                  DEV25G_PCS25G_CFG_PCS25G_ENA,
0442                  sparx5,
0443                  DEV25G_PCS25G_CFG(tinst));
0444     } else {
0445         /* 12: Disable 1G PCS */
0446         spx5_rmw(DEV2G5_PCS1G_CFG_PCS_ENA_SET(0),
0447              DEV2G5_PCS1G_CFG_PCS_ENA,
0448              sparx5,
0449              DEV2G5_PCS1G_CFG(port->portno));
0450     }
0451 
0452     /* The port is now flushed and disabled  */
0453     return 0;
0454 }
0455 
0456 static int sparx5_port_fifo_sz(struct sparx5 *sparx5,
0457                    u32 portno, u32 speed)
0458 {
0459     u32 sys_clk = sparx5_clk_period(sparx5->coreclock);
0460     const u32 taxi_dist[SPX5_PORTS_ALL] = {
0461         6, 8, 10, 6, 8, 10, 6, 8, 10, 6, 8, 10,
0462         4, 4, 4, 4,
0463         11, 12, 13, 14, 15, 16, 17, 18,
0464         11, 12, 13, 14, 15, 16, 17, 18,
0465         11, 12, 13, 14, 15, 16, 17, 18,
0466         11, 12, 13, 14, 15, 16, 17, 18,
0467         4, 6, 8, 4, 6, 8, 6, 8,
0468         2, 2, 2, 2, 2, 2, 2, 4, 2
0469     };
0470     u32 mac_per    = 6400, tmp1, tmp2, tmp3;
0471     u32 fifo_width = 16;
0472     u32 mac_width  = 8;
0473     u32 addition   = 0;
0474 
0475     switch (speed) {
0476     case SPEED_25000:
0477         return 0;
0478     case SPEED_10000:
0479         mac_per = 6400;
0480         mac_width = 8;
0481         addition = 1;
0482         break;
0483     case SPEED_5000:
0484         mac_per = 12800;
0485         mac_width = 8;
0486         addition = 0;
0487         break;
0488     case SPEED_2500:
0489         mac_per = 3200;
0490         mac_width = 1;
0491         addition = 0;
0492         break;
0493     case SPEED_1000:
0494         mac_per =  8000;
0495         mac_width = 1;
0496         addition = 0;
0497         break;
0498     case SPEED_100:
0499     case SPEED_10:
0500         return 1;
0501     default:
0502         break;
0503     }
0504 
0505     tmp1 = 1000 * mac_width / fifo_width;
0506     tmp2 = 3000 + ((12000 + 2 * taxi_dist[portno] * 1000)
0507                * sys_clk / mac_per);
0508     tmp3 = tmp1 * tmp2 / 1000;
0509     return  (tmp3 + 2000 + 999) / 1000 + addition;
0510 }
0511 
0512 /* Configure port muxing:
0513  * QSGMII:     4x2G5 devices
0514  */
0515 static int sparx5_port_mux_set(struct sparx5 *sparx5,
0516                    struct sparx5_port *port,
0517                    struct sparx5_port_config *conf)
0518 {
0519     u32 portno = port->portno;
0520     u32 inst;
0521 
0522     if (port->conf.portmode == conf->portmode)
0523         return 0; /* Nothing to do */
0524 
0525     switch (conf->portmode) {
0526     case PHY_INTERFACE_MODE_QSGMII: /* QSGMII: 4x2G5 devices. Mode Q'  */
0527         inst = (portno - portno % 4) / 4;
0528         spx5_rmw(BIT(inst),
0529              BIT(inst),
0530              sparx5,
0531              PORT_CONF_QSGMII_ENA);
0532 
0533         if ((portno / 4 % 2) == 0) {
0534             /* Affects d0-d3,d8-d11..d40-d43 */
0535             spx5_rmw(PORT_CONF_USGMII_CFG_BYPASS_SCRAM_SET(1) |
0536                  PORT_CONF_USGMII_CFG_BYPASS_DESCRAM_SET(1) |
0537                  PORT_CONF_USGMII_CFG_QUAD_MODE_SET(1),
0538                  PORT_CONF_USGMII_CFG_BYPASS_SCRAM |
0539                  PORT_CONF_USGMII_CFG_BYPASS_DESCRAM |
0540                  PORT_CONF_USGMII_CFG_QUAD_MODE,
0541                  sparx5,
0542                  PORT_CONF_USGMII_CFG((portno / 8)));
0543         }
0544         break;
0545     default:
0546         break;
0547     }
0548     return 0;
0549 }
0550 
0551 static int sparx5_port_max_tags_set(struct sparx5 *sparx5,
0552                     struct sparx5_port *port)
0553 {
0554     enum sparx5_port_max_tags max_tags    = port->max_vlan_tags;
0555     int tag_ct          = max_tags == SPX5_PORT_MAX_TAGS_ONE ? 1 :
0556                   max_tags == SPX5_PORT_MAX_TAGS_TWO ? 2 : 0;
0557     bool dtag           = max_tags == SPX5_PORT_MAX_TAGS_TWO;
0558     enum sparx5_vlan_port_type vlan_type  = port->vlan_type;
0559     bool dotag          = max_tags != SPX5_PORT_MAX_TAGS_NONE;
0560     u32 dev             = sparx5_to_high_dev(port->portno);
0561     u32 tinst           = sparx5_port_dev_index(port->portno);
0562     void __iomem *inst  = spx5_inst_get(sparx5, dev, tinst);
0563     u32 etype;
0564 
0565     etype = (vlan_type == SPX5_VLAN_PORT_TYPE_S_CUSTOM ?
0566          port->custom_etype :
0567          vlan_type == SPX5_VLAN_PORT_TYPE_C ?
0568          SPX5_ETYPE_TAG_C : SPX5_ETYPE_TAG_S);
0569 
0570     spx5_wr(DEV2G5_MAC_TAGS_CFG_TAG_ID_SET(etype) |
0571         DEV2G5_MAC_TAGS_CFG_PB_ENA_SET(dtag) |
0572         DEV2G5_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(dotag) |
0573         DEV2G5_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA_SET(dotag),
0574         sparx5,
0575         DEV2G5_MAC_TAGS_CFG(port->portno));
0576 
0577     if (sparx5_port_is_2g5(port->portno))
0578         return 0;
0579 
0580     spx5_inst_rmw(DEV10G_MAC_TAGS_CFG_TAG_ID_SET(etype) |
0581               DEV10G_MAC_TAGS_CFG_TAG_ENA_SET(dotag),
0582               DEV10G_MAC_TAGS_CFG_TAG_ID |
0583               DEV10G_MAC_TAGS_CFG_TAG_ENA,
0584               inst,
0585               DEV10G_MAC_TAGS_CFG(0, 0));
0586 
0587     spx5_inst_rmw(DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS_SET(tag_ct),
0588               DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS,
0589               inst,
0590               DEV10G_MAC_NUM_TAGS_CFG(0));
0591 
0592     spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK_SET(dotag),
0593               DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK,
0594               inst,
0595               DEV10G_MAC_MAXLEN_CFG(0));
0596     return 0;
0597 }
0598 
0599 int sparx5_port_fwd_urg(struct sparx5 *sparx5, u32 speed)
0600 {
0601     u32 clk_period_ps = 1600; /* 625Mhz for now */
0602     u32 urg = 672000;
0603 
0604     switch (speed) {
0605     case SPEED_10:
0606     case SPEED_100:
0607     case SPEED_1000:
0608         urg = 672000;
0609         break;
0610     case SPEED_2500:
0611         urg = 270000;
0612         break;
0613     case SPEED_5000:
0614         urg = 135000;
0615         break;
0616     case SPEED_10000:
0617         urg = 67200;
0618         break;
0619     case SPEED_25000:
0620         urg = 27000;
0621         break;
0622     }
0623     return urg / clk_period_ps - 1;
0624 }
0625 
0626 static u16 sparx5_wm_enc(u16 value)
0627 {
0628     if (value >= 2048)
0629         return 2048 + value / 16;
0630 
0631     return value;
0632 }
0633 
0634 static int sparx5_port_fc_setup(struct sparx5 *sparx5,
0635                 struct sparx5_port *port,
0636                 struct sparx5_port_config *conf)
0637 {
0638     bool fc_obey = conf->pause & MLO_PAUSE_RX ? 1 : 0;
0639     u32 pause_stop = 0xFFF - 1; /* FC gen disabled */
0640 
0641     if (conf->pause & MLO_PAUSE_TX)
0642         pause_stop = sparx5_wm_enc(4  * (ETH_MAXLEN /
0643                          SPX5_BUFFER_CELL_SZ));
0644 
0645     /* Set HDX flowcontrol */
0646     spx5_rmw(DSM_MAC_CFG_HDX_BACKPREASSURE_SET(conf->duplex == DUPLEX_HALF),
0647          DSM_MAC_CFG_HDX_BACKPREASSURE,
0648          sparx5,
0649          DSM_MAC_CFG(port->portno));
0650 
0651     /* Obey flowcontrol  */
0652     spx5_rmw(DSM_RX_PAUSE_CFG_RX_PAUSE_EN_SET(fc_obey),
0653          DSM_RX_PAUSE_CFG_RX_PAUSE_EN,
0654          sparx5,
0655          DSM_RX_PAUSE_CFG(port->portno));
0656 
0657     /* Disable forward pressure */
0658     spx5_rmw(QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS_SET(fc_obey),
0659          QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS,
0660          sparx5,
0661          QSYS_FWD_PRESSURE(port->portno));
0662 
0663     /* Generate pause frames */
0664     spx5_rmw(QSYS_PAUSE_CFG_PAUSE_STOP_SET(pause_stop),
0665          QSYS_PAUSE_CFG_PAUSE_STOP,
0666          sparx5,
0667          QSYS_PAUSE_CFG(port->portno));
0668 
0669     return 0;
0670 }
0671 
0672 static u16 sparx5_get_aneg_word(struct sparx5_port_config *conf)
0673 {
0674     if (conf->portmode == PHY_INTERFACE_MODE_1000BASEX) /* cl-37 aneg */
0675         return (conf->pause_adv | ADVERTISE_LPACK | ADVERTISE_1000XFULL);
0676     else
0677         return 1; /* Enable SGMII Aneg */
0678 }
0679 
0680 int sparx5_serdes_set(struct sparx5 *sparx5,
0681               struct sparx5_port *port,
0682               struct sparx5_port_config *conf)
0683 {
0684     int portmode, err, speed = conf->speed;
0685 
0686     if (conf->portmode == PHY_INTERFACE_MODE_QSGMII &&
0687         ((port->portno % 4) != 0)) {
0688         return 0;
0689     }
0690     if (sparx5_is_baser(conf->portmode)) {
0691         if (conf->portmode == PHY_INTERFACE_MODE_25GBASER)
0692             speed = SPEED_25000;
0693         else if (conf->portmode == PHY_INTERFACE_MODE_10GBASER)
0694             speed = SPEED_10000;
0695         else
0696             speed = SPEED_5000;
0697     }
0698 
0699     err = phy_set_media(port->serdes, conf->media);
0700     if (err)
0701         return err;
0702     if (speed > 0) {
0703         err = phy_set_speed(port->serdes, speed);
0704         if (err)
0705             return err;
0706     }
0707     if (conf->serdes_reset) {
0708         err = phy_reset(port->serdes);
0709         if (err)
0710             return err;
0711     }
0712 
0713     /* Configure SerDes with port parameters
0714      * For BaseR, the serdes driver supports 10GGBASE-R and speed 5G/10G/25G
0715      */
0716     portmode = conf->portmode;
0717     if (sparx5_is_baser(conf->portmode))
0718         portmode = PHY_INTERFACE_MODE_10GBASER;
0719     err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET, portmode);
0720     if (err)
0721         return err;
0722     conf->serdes_reset = false;
0723     return err;
0724 }
0725 
0726 static int sparx5_port_pcs_low_set(struct sparx5 *sparx5,
0727                    struct sparx5_port *port,
0728                    struct sparx5_port_config *conf)
0729 {
0730     bool sgmii = false, inband_aneg = false;
0731     int err;
0732 
0733     if (port->conf.inband) {
0734         if (conf->portmode == PHY_INTERFACE_MODE_SGMII ||
0735             conf->portmode == PHY_INTERFACE_MODE_QSGMII)
0736             inband_aneg = true; /* Cisco-SGMII in-band-aneg */
0737         else if (conf->portmode == PHY_INTERFACE_MODE_1000BASEX &&
0738              conf->autoneg)
0739             inband_aneg = true; /* Clause-37 in-band-aneg */
0740 
0741         err = sparx5_serdes_set(sparx5, port, conf);
0742         if (err)
0743             return -EINVAL;
0744     } else {
0745         sgmii = true; /* Phy is connected to the MAC */
0746     }
0747 
0748     /* Choose SGMII or 1000BaseX/2500BaseX PCS mode */
0749     spx5_rmw(DEV2G5_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(sgmii),
0750          DEV2G5_PCS1G_MODE_CFG_SGMII_MODE_ENA,
0751          sparx5,
0752          DEV2G5_PCS1G_MODE_CFG(port->portno));
0753 
0754     /* Enable PCS */
0755     spx5_wr(DEV2G5_PCS1G_CFG_PCS_ENA_SET(1),
0756         sparx5,
0757         DEV2G5_PCS1G_CFG(port->portno));
0758 
0759     if (inband_aneg) {
0760         u16 abil = sparx5_get_aneg_word(conf);
0761 
0762         /* Enable in-band aneg */
0763         spx5_wr(DEV2G5_PCS1G_ANEG_CFG_ADV_ABILITY_SET(abil) |
0764             DEV2G5_PCS1G_ANEG_CFG_SW_RESOLVE_ENA_SET(1) |
0765             DEV2G5_PCS1G_ANEG_CFG_ANEG_ENA_SET(1) |
0766             DEV2G5_PCS1G_ANEG_CFG_ANEG_RESTART_ONE_SHOT_SET(1),
0767             sparx5,
0768             DEV2G5_PCS1G_ANEG_CFG(port->portno));
0769     } else {
0770         spx5_wr(0, sparx5, DEV2G5_PCS1G_ANEG_CFG(port->portno));
0771     }
0772 
0773     /* Take PCS out of reset */
0774     spx5_rmw(DEV2G5_DEV_RST_CTRL_SPEED_SEL_SET(2) |
0775          DEV2G5_DEV_RST_CTRL_PCS_TX_RST_SET(0) |
0776          DEV2G5_DEV_RST_CTRL_PCS_RX_RST_SET(0),
0777          DEV2G5_DEV_RST_CTRL_SPEED_SEL |
0778          DEV2G5_DEV_RST_CTRL_PCS_TX_RST |
0779          DEV2G5_DEV_RST_CTRL_PCS_RX_RST,
0780          sparx5,
0781          DEV2G5_DEV_RST_CTRL(port->portno));
0782 
0783     return 0;
0784 }
0785 
0786 static int sparx5_port_pcs_high_set(struct sparx5 *sparx5,
0787                     struct sparx5_port *port,
0788                     struct sparx5_port_config *conf)
0789 {
0790     u32 clk_spd = conf->portmode == PHY_INTERFACE_MODE_5GBASER ? 1 : 0;
0791     u32 pix = sparx5_port_dev_index(port->portno);
0792     u32 dev = sparx5_to_high_dev(port->portno);
0793     u32 pcs = sparx5_to_pcs_dev(port->portno);
0794     void __iomem *devinst;
0795     void __iomem *pcsinst;
0796     int err;
0797 
0798     devinst = spx5_inst_get(sparx5, dev, pix);
0799     pcsinst = spx5_inst_get(sparx5, pcs, pix);
0800 
0801     /*  SFI : No in-band-aneg. Speeds 5G/10G/25G */
0802     err = sparx5_serdes_set(sparx5, port, conf);
0803     if (err)
0804         return -EINVAL;
0805     if (conf->portmode == PHY_INTERFACE_MODE_25GBASER) {
0806         /* Enable PCS for 25G device, speed 25G */
0807         spx5_rmw(DEV25G_PCS25G_CFG_PCS25G_ENA_SET(1),
0808              DEV25G_PCS25G_CFG_PCS25G_ENA,
0809              sparx5,
0810              DEV25G_PCS25G_CFG(pix));
0811     } else {
0812         /* Enable PCS for 5G/10G/25G devices, speed 5G/10G */
0813         spx5_inst_rmw(PCS10G_BR_PCS_CFG_PCS_ENA_SET(1),
0814                   PCS10G_BR_PCS_CFG_PCS_ENA,
0815                   pcsinst,
0816                   PCS10G_BR_PCS_CFG(0));
0817     }
0818 
0819     /* Enable 5G/10G/25G MAC module */
0820     spx5_inst_wr(DEV10G_MAC_ENA_CFG_RX_ENA_SET(1) |
0821              DEV10G_MAC_ENA_CFG_TX_ENA_SET(1),
0822              devinst,
0823              DEV10G_MAC_ENA_CFG(0));
0824 
0825     /* Take the device out of reset */
0826     spx5_inst_rmw(DEV10G_DEV_RST_CTRL_PCS_RX_RST_SET(0) |
0827               DEV10G_DEV_RST_CTRL_PCS_TX_RST_SET(0) |
0828               DEV10G_DEV_RST_CTRL_MAC_RX_RST_SET(0) |
0829               DEV10G_DEV_RST_CTRL_MAC_TX_RST_SET(0) |
0830               DEV10G_DEV_RST_CTRL_SPEED_SEL_SET(clk_spd),
0831               DEV10G_DEV_RST_CTRL_PCS_RX_RST |
0832               DEV10G_DEV_RST_CTRL_PCS_TX_RST |
0833               DEV10G_DEV_RST_CTRL_MAC_RX_RST |
0834               DEV10G_DEV_RST_CTRL_MAC_TX_RST |
0835               DEV10G_DEV_RST_CTRL_SPEED_SEL,
0836               devinst,
0837               DEV10G_DEV_RST_CTRL(0));
0838 
0839     return 0;
0840 }
0841 
0842 /* Switch between 1G/2500 and 5G/10G/25G devices */
0843 static void sparx5_dev_switch(struct sparx5 *sparx5, int port, bool hsd)
0844 {
0845     int bt_indx = BIT(sparx5_port_dev_index(port));
0846 
0847     if (sparx5_port_is_5g(port)) {
0848         spx5_rmw(hsd ? 0 : bt_indx,
0849              bt_indx,
0850              sparx5,
0851              PORT_CONF_DEV5G_MODES);
0852     } else if (sparx5_port_is_10g(port)) {
0853         spx5_rmw(hsd ? 0 : bt_indx,
0854              bt_indx,
0855              sparx5,
0856              PORT_CONF_DEV10G_MODES);
0857     } else if (sparx5_port_is_25g(port)) {
0858         spx5_rmw(hsd ? 0 : bt_indx,
0859              bt_indx,
0860              sparx5,
0861              PORT_CONF_DEV25G_MODES);
0862     }
0863 }
0864 
0865 /* Configure speed/duplex dependent registers */
0866 static int sparx5_port_config_low_set(struct sparx5 *sparx5,
0867                       struct sparx5_port *port,
0868                       struct sparx5_port_config *conf)
0869 {
0870     u32 clk_spd, gig_mode, tx_gap, hdx_gap_1, hdx_gap_2;
0871     bool fdx = conf->duplex == DUPLEX_FULL;
0872     int spd = conf->speed;
0873 
0874     clk_spd = spd == SPEED_10 ? 0 : spd == SPEED_100 ? 1 : 2;
0875     gig_mode = spd == SPEED_1000 || spd == SPEED_2500;
0876     tx_gap = spd == SPEED_1000 ? 4 : fdx ? 6 : 5;
0877     hdx_gap_1 = spd == SPEED_1000 ? 0 : spd == SPEED_100 ? 1 : 2;
0878     hdx_gap_2 = spd == SPEED_1000 ? 0 : spd == SPEED_100 ? 4 : 1;
0879 
0880     /* GIG/FDX mode */
0881     spx5_rmw(DEV2G5_MAC_MODE_CFG_GIGA_MODE_ENA_SET(gig_mode) |
0882          DEV2G5_MAC_MODE_CFG_FDX_ENA_SET(fdx),
0883          DEV2G5_MAC_MODE_CFG_GIGA_MODE_ENA |
0884          DEV2G5_MAC_MODE_CFG_FDX_ENA,
0885          sparx5,
0886          DEV2G5_MAC_MODE_CFG(port->portno));
0887 
0888     /* Set MAC IFG Gaps */
0889     spx5_wr(DEV2G5_MAC_IFG_CFG_TX_IFG_SET(tx_gap) |
0890         DEV2G5_MAC_IFG_CFG_RX_IFG1_SET(hdx_gap_1) |
0891         DEV2G5_MAC_IFG_CFG_RX_IFG2_SET(hdx_gap_2),
0892         sparx5,
0893         DEV2G5_MAC_IFG_CFG(port->portno));
0894 
0895     /* Disabling frame aging when in HDX (due to HDX issue) */
0896     spx5_rmw(HSCH_PORT_MODE_AGE_DIS_SET(fdx == 0),
0897          HSCH_PORT_MODE_AGE_DIS,
0898          sparx5,
0899          HSCH_PORT_MODE(port->portno));
0900 
0901     /* Enable MAC module */
0902     spx5_wr(DEV2G5_MAC_ENA_CFG_RX_ENA |
0903         DEV2G5_MAC_ENA_CFG_TX_ENA,
0904         sparx5,
0905         DEV2G5_MAC_ENA_CFG(port->portno));
0906 
0907     /* Select speed and take MAC out of reset */
0908     spx5_rmw(DEV2G5_DEV_RST_CTRL_SPEED_SEL_SET(clk_spd) |
0909          DEV2G5_DEV_RST_CTRL_MAC_TX_RST_SET(0) |
0910          DEV2G5_DEV_RST_CTRL_MAC_RX_RST_SET(0),
0911          DEV2G5_DEV_RST_CTRL_SPEED_SEL |
0912          DEV2G5_DEV_RST_CTRL_MAC_TX_RST |
0913          DEV2G5_DEV_RST_CTRL_MAC_RX_RST,
0914          sparx5,
0915          DEV2G5_DEV_RST_CTRL(port->portno));
0916 
0917     return 0;
0918 }
0919 
0920 int sparx5_port_pcs_set(struct sparx5 *sparx5,
0921             struct sparx5_port *port,
0922             struct sparx5_port_config *conf)
0923 
0924 {
0925     bool high_speed_dev = sparx5_is_baser(conf->portmode);
0926     int err;
0927 
0928     if (sparx5_dev_change(sparx5, port, conf)) {
0929         /* switch device */
0930         sparx5_dev_switch(sparx5, port->portno, high_speed_dev);
0931 
0932         /* Disable the not-in-use device */
0933         err = sparx5_port_disable(sparx5, port, !high_speed_dev);
0934         if (err)
0935             return err;
0936     }
0937     /* Disable the port before re-configuring */
0938     err = sparx5_port_disable(sparx5, port, high_speed_dev);
0939     if (err)
0940         return -EINVAL;
0941 
0942     if (high_speed_dev)
0943         err = sparx5_port_pcs_high_set(sparx5, port, conf);
0944     else
0945         err = sparx5_port_pcs_low_set(sparx5, port, conf);
0946 
0947     if (err)
0948         return -EINVAL;
0949 
0950     if (port->conf.inband) {
0951         /* Enable/disable 1G counters in ASM */
0952         spx5_rmw(ASM_PORT_CFG_CSC_STAT_DIS_SET(high_speed_dev),
0953              ASM_PORT_CFG_CSC_STAT_DIS,
0954              sparx5,
0955              ASM_PORT_CFG(port->portno));
0956 
0957         /* Enable/disable 1G counters in DSM */
0958         spx5_rmw(DSM_BUF_CFG_CSC_STAT_DIS_SET(high_speed_dev),
0959              DSM_BUF_CFG_CSC_STAT_DIS,
0960              sparx5,
0961              DSM_BUF_CFG(port->portno));
0962     }
0963 
0964     port->conf = *conf;
0965 
0966     return 0;
0967 }
0968 
0969 int sparx5_port_config(struct sparx5 *sparx5,
0970                struct sparx5_port *port,
0971                struct sparx5_port_config *conf)
0972 {
0973     bool high_speed_dev = sparx5_is_baser(conf->portmode);
0974     int err, urgency, stop_wm;
0975 
0976     err = sparx5_port_verify_speed(sparx5, port, conf);
0977     if (err)
0978         return err;
0979 
0980     /* high speed device is already configured */
0981     if (!high_speed_dev)
0982         sparx5_port_config_low_set(sparx5, port, conf);
0983 
0984     /* Configure flow control */
0985     err = sparx5_port_fc_setup(sparx5, port, conf);
0986     if (err)
0987         return err;
0988 
0989     /* Set the DSM stop watermark */
0990     stop_wm = sparx5_port_fifo_sz(sparx5, port->portno, conf->speed);
0991     spx5_rmw(DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM_SET(stop_wm),
0992          DSM_DEV_TX_STOP_WM_CFG_DEV_TX_STOP_WM,
0993          sparx5,
0994          DSM_DEV_TX_STOP_WM_CFG(port->portno));
0995 
0996     /* Enable port in queue system */
0997     urgency = sparx5_port_fwd_urg(sparx5, conf->speed);
0998     spx5_rmw(QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(1) |
0999          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 */
1012 int 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 
1137 void 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 }