1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver
4 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
7 #include <linux/module.h>
8 #include <linux/phy/phy.h>
10 #include "sparx5_main_regs.h"
11 #include "sparx5_main.h"
12 #include "sparx5_port.h"
14 #define SPX5_ETYPE_TAG_C 0x8100
15 #define SPX5_ETYPE_TAG_S 0x88a8
17 #define SPX5_WAIT_US 1000
18 #define SPX5_WAIT_MAX_US 2000
25 #define PAUSE_DISCARD 0xC
26 #define ETH_MAXLEN (ETH_DATA_LEN + ETH_HLEN + ETH_FCS_LEN)
28 static void decode_sgmii_word(u16 lp_abil, struct sparx5_port_status *status)
30 status->an_complete = true;
31 if (!(lp_abil & LPA_SGMII_LINK)) {
36 switch (lp_abil & LPA_SGMII_SPD_MASK) {
38 status->speed = SPEED_10;
41 status->speed = SPEED_100;
44 status->speed = SPEED_1000;
50 if (lp_abil & LPA_SGMII_FULL_DUPLEX)
51 status->duplex = DUPLEX_FULL;
53 status->duplex = DUPLEX_HALF;
56 static void decode_cl37_word(u16 lp_abil, uint16_t ld_abil, struct sparx5_port_status *status)
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
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) ?
70 status->pause |= (ld_abil & ADVERTISE_1000XPAUSE) ?
73 status->pause = MLO_PAUSE_NONE;
77 static int sparx5_get_dev2g5_status(struct sparx5 *sparx5,
78 struct sparx5_port *port,
79 struct sparx5_port_status *status)
81 u32 portno = port->portno;
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));
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);
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;
101 status->duplex = DUPLEX_FULL;
103 /* Get PCS ANEG status register */
104 value = spx5_rd(sparx5, DEV2G5_PCS1G_ANEG_STATUS(portno));
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);
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);
120 static int sparx5_get_sfi_status(struct sparx5 *sparx5,
121 struct sparx5_port *port,
122 struct sparx5_port_status *status)
124 bool high_speed_dev = sparx5_is_baser(port->conf.portmode);
125 u32 portno = port->portno;
126 u32 value, dev, tinst;
129 if (!high_speed_dev) {
130 netdev_err(port->ndev, "error: low speed and SFI mode\n");
134 dev = sparx5_to_high_dev(portno);
135 tinst = sparx5_port_dev_index(portno);
136 inst = spx5_inst_get(sparx5, dev, tinst);
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));
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;
152 status->speed = SPEED_25000;
157 /* Get link status of 1000Base-X/in-band and SFI ports.
159 int sparx5_get_port_status(struct sparx5 *sparx5,
160 struct sparx5_port *port,
161 struct sparx5_port_status *status)
163 memset(status, 0, sizeof(*status));
164 status->speed = port->conf.speed;
165 if (port->conf.power_down) {
166 status->link = false;
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:
182 netdev_err(port->ndev, "Status not supported");
188 static int sparx5_port_error(struct sparx5_port *port,
189 struct sparx5_port_config *conf,
190 enum port_error 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));
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));
204 netdev_err(port->ndev,
205 "Interface configuration error\n");
211 static int sparx5_port_verify_speed(struct sparx5 *sparx5,
212 struct sparx5_port *port,
213 struct sparx5_port_config *conf)
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);
223 switch (conf->portmode) {
224 case PHY_INTERFACE_MODE_NA:
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);
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);
238 case PHY_INTERFACE_MODE_QSGMII:
239 if (port->portno > 47)
240 return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
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);
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);
258 return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
263 static bool sparx5_dev_change(struct sparx5 *sparx5,
264 struct sparx5_port *port,
265 struct sparx5_port_config *conf)
267 return sparx5_is_baser(port->conf.portmode) ^
268 sparx5_is_baser(conf->portmode);
271 static int sparx5_port_flush_poll(struct sparx5 *sparx5, u32 portno)
273 u32 value, resource, prio, delay_cnt = 0;
274 bool poll_src = true;
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)
285 for (resource = 0; resource < (poll_src ? 2 : 1); resource++) {
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));
293 mem = resource == 0 ?
294 "DST-MEM" : "SRC-MEM";
303 if (delay_cnt++ == 2000) {
305 "Flush timeout port %u. %s queue not empty\n",
310 usleep_range(SPX5_WAIT_US, SPX5_WAIT_MAX_US);
315 static int sparx5_port_disable(struct sparx5 *sparx5, struct sparx5_port *port, bool high_spd_dev)
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;
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,
331 DEV10G_DEV_RST_CTRL(0));
333 /* 2: Disable MAC frame reception */
335 DEV10G_MAC_ENA_CFG_RX_ENA,
337 DEV10G_MAC_ENA_CFG(0));
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,
343 DEV2G5_DEV_RST_CTRL(0));
344 /* 2: Disable MAC frame reception */
346 DEV2G5_MAC_ENA_CFG_RX_ENA,
348 DEV2G5_MAC_ENA_CFG(0));
350 /* 3: Disable traffic being sent to or from switch port->portno */
352 QFWD_SWITCH_PORT_MODE_PORT_ENA,
354 QFWD_SWITCH_PORT_MODE(port->portno));
356 /* 4: Disable dequeuing from the egress queues */
357 spx5_rmw(HSCH_PORT_MODE_DEQUEUE_DIS,
358 HSCH_PORT_MODE_DEQUEUE_DIS,
360 HSCH_PORT_MODE(port->portno));
362 /* 5: Disable Flowcontrol */
363 spx5_rmw(QSYS_PAUSE_CFG_PAUSE_STOP_SET(0xFFF - 1),
364 QSYS_PAUSE_CFG_PAUSE_STOP,
366 QSYS_PAUSE_CFG(port->portno));
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);
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,
384 /* 8: Enable dequeuing from the egress queues */
386 HSCH_PORT_MODE_DEQUEUE_DIS,
388 HSCH_PORT_MODE(port->portno));
390 /* 9: Wait until flushing is complete */
391 err = sparx5_port_flush_poll(sparx5, port->portno);
395 /* 10: Reset the MAC clock domain */
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,
404 DEV10G_DEV_RST_CTRL(0));
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,
418 DEV2G5_DEV_RST_CTRL(0));
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,
429 u32 pcs = sparx5_to_pcs_dev(port->portno);
430 void __iomem *pcsinst = spx5_inst_get(sparx5, pcs, tinst);
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,
436 PCS10G_BR_PCS_CFG(0));
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,
443 DEV25G_PCS25G_CFG(tinst));
445 /* 12: Disable 1G PCS */
446 spx5_rmw(DEV2G5_PCS1G_CFG_PCS_ENA_SET(0),
447 DEV2G5_PCS1G_CFG_PCS_ENA,
449 DEV2G5_PCS1G_CFG(port->portno));
452 /* The port is now flushed and disabled */
456 static int sparx5_port_fifo_sz(struct sparx5 *sparx5,
457 u32 portno, u32 speed)
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,
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
470 u32 mac_per = 6400, tmp1, tmp2, tmp3;
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;
512 /* Configure port muxing:
513 * QSGMII: 4x2G5 devices
515 static int sparx5_port_mux_set(struct sparx5 *sparx5,
516 struct sparx5_port *port,
517 struct sparx5_port_config *conf)
519 u32 portno = port->portno;
522 if (port->conf.portmode == conf->portmode)
523 return 0; /* Nothing to do */
525 switch (conf->portmode) {
526 case PHY_INTERFACE_MODE_QSGMII: /* QSGMII: 4x2G5 devices. Mode Q' */
527 inst = (portno - portno % 4) / 4;
531 PORT_CONF_QSGMII_ENA);
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,
542 PORT_CONF_USGMII_CFG((portno / 8)));
551 static int sparx5_port_max_tags_set(struct sparx5 *sparx5,
552 struct sparx5_port *port)
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);
565 etype = (vlan_type == SPX5_VLAN_PORT_TYPE_S_CUSTOM ?
567 vlan_type == SPX5_VLAN_PORT_TYPE_C ?
568 SPX5_ETYPE_TAG_C : SPX5_ETYPE_TAG_S);
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),
575 DEV2G5_MAC_TAGS_CFG(port->portno));
577 if (sparx5_port_is_2g5(port->portno))
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,
585 DEV10G_MAC_TAGS_CFG(0, 0));
587 spx5_inst_rmw(DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS_SET(tag_ct),
588 DEV10G_MAC_NUM_TAGS_CFG_NUM_TAGS,
590 DEV10G_MAC_NUM_TAGS_CFG(0));
592 spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK_SET(dotag),
593 DEV10G_MAC_MAXLEN_CFG_MAX_LEN_TAG_CHK,
595 DEV10G_MAC_MAXLEN_CFG(0));
599 static int sparx5_port_fwd_urg(struct sparx5 *sparx5, u32 speed)
601 u32 clk_period_ps = 1600; /* 625Mhz for now */
623 return urg / clk_period_ps - 1;
626 static u16 sparx5_wm_enc(u16 value)
629 return 2048 + value / 16;
634 static int sparx5_port_fc_setup(struct sparx5 *sparx5,
635 struct sparx5_port *port,
636 struct sparx5_port_config *conf)
638 bool fc_obey = conf->pause & MLO_PAUSE_RX ? 1 : 0;
639 u32 pause_stop = 0xFFF - 1; /* FC gen disabled */
641 if (conf->pause & MLO_PAUSE_TX)
642 pause_stop = sparx5_wm_enc(4 * (ETH_MAXLEN /
643 SPX5_BUFFER_CELL_SZ));
645 /* Set HDX flowcontrol */
646 spx5_rmw(DSM_MAC_CFG_HDX_BACKPREASSURE_SET(conf->duplex == DUPLEX_HALF),
647 DSM_MAC_CFG_HDX_BACKPREASSURE,
649 DSM_MAC_CFG(port->portno));
651 /* Obey flowcontrol */
652 spx5_rmw(DSM_RX_PAUSE_CFG_RX_PAUSE_EN_SET(fc_obey),
653 DSM_RX_PAUSE_CFG_RX_PAUSE_EN,
655 DSM_RX_PAUSE_CFG(port->portno));
657 /* Disable forward pressure */
658 spx5_rmw(QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS_SET(fc_obey),
659 QSYS_FWD_PRESSURE_FWD_PRESSURE_DIS,
661 QSYS_FWD_PRESSURE(port->portno));
663 /* Generate pause frames */
664 spx5_rmw(QSYS_PAUSE_CFG_PAUSE_STOP_SET(pause_stop),
665 QSYS_PAUSE_CFG_PAUSE_STOP,
667 QSYS_PAUSE_CFG(port->portno));
672 static u16 sparx5_get_aneg_word(struct sparx5_port_config *conf)
674 if (conf->portmode == PHY_INTERFACE_MODE_1000BASEX) /* cl-37 aneg */
675 return (conf->pause_adv | ADVERTISE_LPACK | ADVERTISE_1000XFULL);
677 return 1; /* Enable SGMII Aneg */
680 int sparx5_serdes_set(struct sparx5 *sparx5,
681 struct sparx5_port *port,
682 struct sparx5_port_config *conf)
684 int portmode, err, speed = conf->speed;
686 if (conf->portmode == PHY_INTERFACE_MODE_QSGMII &&
687 ((port->portno % 4) != 0)) {
690 if (sparx5_is_baser(conf->portmode)) {
691 if (conf->portmode == PHY_INTERFACE_MODE_25GBASER)
693 else if (conf->portmode == PHY_INTERFACE_MODE_10GBASER)
699 err = phy_set_media(port->serdes, conf->media);
703 err = phy_set_speed(port->serdes, speed);
707 if (conf->serdes_reset) {
708 err = phy_reset(port->serdes);
713 /* Configure SerDes with port parameters
714 * For BaseR, the serdes driver supports 10GGBASE-R and speed 5G/10G/25G
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);
722 conf->serdes_reset = false;
726 static int sparx5_port_pcs_low_set(struct sparx5 *sparx5,
727 struct sparx5_port *port,
728 struct sparx5_port_config *conf)
730 bool sgmii = false, inband_aneg = false;
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 &&
739 inband_aneg = true; /* Clause-37 in-band-aneg */
741 err = sparx5_serdes_set(sparx5, port, conf);
745 sgmii = true; /* Phy is connnected to the MAC */
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,
752 DEV2G5_PCS1G_MODE_CFG(port->portno));
755 spx5_wr(DEV2G5_PCS1G_CFG_PCS_ENA_SET(1),
757 DEV2G5_PCS1G_CFG(port->portno));
760 u16 abil = sparx5_get_aneg_word(conf);
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),
768 DEV2G5_PCS1G_ANEG_CFG(port->portno));
770 spx5_wr(0, sparx5, DEV2G5_PCS1G_ANEG_CFG(port->portno));
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,
781 DEV2G5_DEV_RST_CTRL(port->portno));
786 static int sparx5_port_pcs_high_set(struct sparx5 *sparx5,
787 struct sparx5_port *port,
788 struct sparx5_port_config *conf)
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;
798 devinst = spx5_inst_get(sparx5, dev, pix);
799 pcsinst = spx5_inst_get(sparx5, pcs, pix);
801 /* SFI : No in-band-aneg. Speeds 5G/10G/25G */
802 err = sparx5_serdes_set(sparx5, port, conf);
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,
810 DEV25G_PCS25G_CFG(pix));
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,
816 PCS10G_BR_PCS_CFG(0));
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),
823 DEV10G_MAC_ENA_CFG(0));
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,
837 DEV10G_DEV_RST_CTRL(0));
842 /* Switch between 1G/2500 and 5G/10G/25G devices */
843 static void sparx5_dev_switch(struct sparx5 *sparx5, int port, bool hsd)
845 int bt_indx = BIT(sparx5_port_dev_index(port));
847 if (sparx5_port_is_5g(port)) {
848 spx5_rmw(hsd ? 0 : bt_indx,
851 PORT_CONF_DEV5G_MODES);
852 } else if (sparx5_port_is_10g(port)) {
853 spx5_rmw(hsd ? 0 : bt_indx,
856 PORT_CONF_DEV10G_MODES);
857 } else if (sparx5_port_is_25g(port)) {
858 spx5_rmw(hsd ? 0 : bt_indx,
861 PORT_CONF_DEV25G_MODES);
865 /* Configure speed/duplex dependent registers */
866 static int sparx5_port_config_low_set(struct sparx5 *sparx5,
867 struct sparx5_port *port,
868 struct sparx5_port_config *conf)
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;
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;
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,
886 DEV2G5_MAC_MODE_CFG(port->portno));
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),
893 DEV2G5_MAC_IFG_CFG(port->portno));
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,
899 HSCH_PORT_MODE(port->portno));
901 /* Enable MAC module */
902 spx5_wr(DEV2G5_MAC_ENA_CFG_RX_ENA |
903 DEV2G5_MAC_ENA_CFG_TX_ENA,
905 DEV2G5_MAC_ENA_CFG(port->portno));
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,
915 DEV2G5_DEV_RST_CTRL(port->portno));
920 int sparx5_port_pcs_set(struct sparx5 *sparx5,
921 struct sparx5_port *port,
922 struct sparx5_port_config *conf)
925 bool high_speed_dev = sparx5_is_baser(conf->portmode);
928 if (sparx5_dev_change(sparx5, port, conf)) {
930 sparx5_dev_switch(sparx5, port->portno, high_speed_dev);
932 /* Disable the not-in-use device */
933 err = sparx5_port_disable(sparx5, port, !high_speed_dev);
937 /* Disable the port before re-configuring */
938 err = sparx5_port_disable(sparx5, port, high_speed_dev);
943 err = sparx5_port_pcs_high_set(sparx5, port, conf);
945 err = sparx5_port_pcs_low_set(sparx5, port, conf);
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,
955 ASM_PORT_CFG(port->portno));
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,
961 DSM_BUF_CFG(port->portno));
969 int sparx5_port_config(struct sparx5 *sparx5,
970 struct sparx5_port *port,
971 struct sparx5_port_config *conf)
973 bool high_speed_dev = sparx5_is_baser(conf->portmode);
974 int err, urgency, stop_wm;
976 err = sparx5_port_verify_speed(sparx5, port, conf);
980 /* high speed device is already configured */
982 sparx5_port_config_low_set(sparx5, port, conf);
984 /* Configure flow control */
985 err = sparx5_port_fc_setup(sparx5, port, conf);
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,
994 DSM_DEV_TX_STOP_WM_CFG(port->portno));
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,
1003 QFWD_SWITCH_PORT_MODE(port->portno));
1005 /* Save the new values */
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)
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;
1029 devinst = spx5_inst_get(sparx5, devhigh, pix);
1030 pcsinst = spx5_inst_get(sparx5, pcs, pix);
1032 /* Set the mux port mode */
1033 err = sparx5_port_mux_set(sparx5, port, conf);
1037 /* Configure MAC vlan awareness */
1038 err = sparx5_port_max_tags_set(sparx5, port);
1042 /* Set Max Length */
1043 spx5_rmw(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
1044 DEV2G5_MAC_MAXLEN_CFG_MAX_LEN,
1046 DEV2G5_MAC_MAXLEN_CFG(port->portno));
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),
1053 DEV2G5_PCS1G_SD_CFG(port->portno));
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,
1063 QSYS_PAUSE_CFG(port->portno));
1065 /* Port ATOP. Frames are tail dropped when this WM is hit */
1066 spx5_wr(QSYS_ATOP_ATOP_SET(atop),
1068 QSYS_ATOP(port->portno));
1070 /* Discard pause frame 01-80-C2-00-00-01 */
1071 spx5_wr(PAUSE_DISCARD, sparx5, ANA_CL_CAPTURE_BPDU_CFG(port->portno));
1073 if (conf->portmode == PHY_INTERFACE_MODE_QSGMII ||
1074 conf->portmode == PHY_INTERFACE_MODE_SGMII) {
1075 err = sparx5_serdes_set(sparx5, port, conf);
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,
1084 DSM_DEV_TX_STOP_WM_CFG(port->portno));
1086 sparx5_dev_switch(sparx5, port->portno, false);
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,
1093 DEV2G5_DEV_RST_CTRL(port->portno));
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),
1100 DEV2G5_MAC_IFG_CFG(port->portno));
1102 if (sparx5_port_is_2g5(port->portno))
1103 return 0; /* Low speed device only - return */
1105 /* Now setup the high speed device */
1106 if (conf->portmode == PHY_INTERFACE_MODE_NA)
1107 conf->portmode = PHY_INTERFACE_MODE_10GBASER;
1109 if (sparx5_is_baser(conf->portmode))
1110 sparx5_dev_switch(sparx5, port->portno, true);
1112 /* Set Max Length */
1113 spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
1114 DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
1116 DEV10G_MAC_ENA_CFG(0));
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),
1123 PCS10G_BR_PCS_SD_CFG(0));
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),
1131 DEV25G_PCS25G_SD_CFG(pix));
1137 void sparx5_port_enable(struct sparx5_port *port, bool enable)
1139 struct sparx5 *sparx5 = port->sparx5;
1141 /* Enable port for frame transfer? */
1142 spx5_rmw(QFWD_SWITCH_PORT_MODE_PORT_ENA_SET(enable),
1143 QFWD_SWITCH_PORT_MODE_PORT_ENA,
1145 QFWD_SWITCH_PORT_MODE(port->portno));