cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

lan966x_port.c (11825B)


      1// SPDX-License-Identifier: GPL-2.0+
      2
      3#include <linux/netdevice.h>
      4#include <linux/phy/phy.h>
      5
      6#include "lan966x_main.h"
      7
      8/* Watermark encode */
      9#define MULTIPLIER_BIT BIT(8)
     10static u32 lan966x_wm_enc(u32 value)
     11{
     12	value /= LAN966X_BUFFER_CELL_SZ;
     13
     14	if (value >= MULTIPLIER_BIT) {
     15		value /= 16;
     16		if (value >= MULTIPLIER_BIT)
     17			value = (MULTIPLIER_BIT - 1);
     18
     19		value |= MULTIPLIER_BIT;
     20	}
     21
     22	return value;
     23}
     24
     25static void lan966x_port_link_down(struct lan966x_port *port)
     26{
     27	struct lan966x *lan966x = port->lan966x;
     28	u32 val, delay = 0;
     29
     30	/* 0.5: Disable any AFI */
     31	lan_rmw(AFI_PORT_CFG_FC_SKIP_TTI_INJ_SET(1) |
     32		AFI_PORT_CFG_FRM_OUT_MAX_SET(0),
     33		AFI_PORT_CFG_FC_SKIP_TTI_INJ |
     34		AFI_PORT_CFG_FRM_OUT_MAX,
     35		lan966x, AFI_PORT_CFG(port->chip_port));
     36
     37	/* wait for reg afi_port_frm_out to become 0 for the port */
     38	while (true) {
     39		val = lan_rd(lan966x, AFI_PORT_FRM_OUT(port->chip_port));
     40		if (!AFI_PORT_FRM_OUT_FRM_OUT_CNT_GET(val))
     41			break;
     42
     43		usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
     44		delay++;
     45		if (delay == 2000) {
     46			pr_err("AFI timeout chip port %u", port->chip_port);
     47			break;
     48		}
     49	}
     50
     51	delay = 0;
     52
     53	/* 1: Reset the PCS Rx clock domain  */
     54	lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(1),
     55		DEV_CLOCK_CFG_PCS_RX_RST,
     56		lan966x, DEV_CLOCK_CFG(port->chip_port));
     57
     58	/* 2: Disable MAC frame reception */
     59	lan_rmw(DEV_MAC_ENA_CFG_RX_ENA_SET(0),
     60		DEV_MAC_ENA_CFG_RX_ENA,
     61		lan966x, DEV_MAC_ENA_CFG(port->chip_port));
     62
     63	/* 3: Disable traffic being sent to or from switch port */
     64	lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(0),
     65		QSYS_SW_PORT_MODE_PORT_ENA,
     66		lan966x, QSYS_SW_PORT_MODE(port->chip_port));
     67
     68	/* 4: Disable dequeuing from the egress queues  */
     69	lan_rmw(QSYS_PORT_MODE_DEQUEUE_DIS_SET(1),
     70		QSYS_PORT_MODE_DEQUEUE_DIS,
     71		lan966x, QSYS_PORT_MODE(port->chip_port));
     72
     73	/* 5: Disable Flowcontrol */
     74	lan_rmw(SYS_PAUSE_CFG_PAUSE_ENA_SET(0),
     75		SYS_PAUSE_CFG_PAUSE_ENA,
     76		lan966x, SYS_PAUSE_CFG(port->chip_port));
     77
     78	/* 5.1: Disable PFC */
     79	lan_rmw(QSYS_SW_PORT_MODE_TX_PFC_ENA_SET(0),
     80		QSYS_SW_PORT_MODE_TX_PFC_ENA,
     81		lan966x, QSYS_SW_PORT_MODE(port->chip_port));
     82
     83	/* 6: Wait a worst case time 8ms (jumbo/10Mbit) */
     84	usleep_range(8 * USEC_PER_MSEC, 9 * USEC_PER_MSEC);
     85
     86	/* 7: Disable HDX backpressure */
     87	lan_rmw(SYS_FRONT_PORT_MODE_HDX_MODE_SET(0),
     88		SYS_FRONT_PORT_MODE_HDX_MODE,
     89		lan966x, SYS_FRONT_PORT_MODE(port->chip_port));
     90
     91	/* 8: Flush the queues accociated with the port */
     92	lan_rmw(QSYS_SW_PORT_MODE_AGING_MODE_SET(3),
     93		QSYS_SW_PORT_MODE_AGING_MODE,
     94		lan966x, QSYS_SW_PORT_MODE(port->chip_port));
     95
     96	/* 9: Enable dequeuing from the egress queues */
     97	lan_rmw(QSYS_PORT_MODE_DEQUEUE_DIS_SET(0),
     98		QSYS_PORT_MODE_DEQUEUE_DIS,
     99		lan966x, QSYS_PORT_MODE(port->chip_port));
    100
    101	/* 10: Wait until flushing is complete */
    102	while (true) {
    103		val = lan_rd(lan966x, QSYS_SW_STATUS(port->chip_port));
    104		if (!QSYS_SW_STATUS_EQ_AVAIL_GET(val))
    105			break;
    106
    107		usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
    108		delay++;
    109		if (delay == 2000) {
    110			pr_err("Flush timeout chip port %u", port->chip_port);
    111			break;
    112		}
    113	}
    114
    115	/* 11: Reset the Port and MAC clock domains */
    116	lan_rmw(DEV_MAC_ENA_CFG_TX_ENA_SET(0),
    117		DEV_MAC_ENA_CFG_TX_ENA,
    118		lan966x, DEV_MAC_ENA_CFG(port->chip_port));
    119
    120	lan_rmw(DEV_CLOCK_CFG_PORT_RST_SET(1),
    121		DEV_CLOCK_CFG_PORT_RST,
    122		lan966x, DEV_CLOCK_CFG(port->chip_port));
    123
    124	usleep_range(USEC_PER_MSEC, 2 * USEC_PER_MSEC);
    125
    126	lan_rmw(DEV_CLOCK_CFG_MAC_TX_RST_SET(1) |
    127		DEV_CLOCK_CFG_MAC_RX_RST_SET(1) |
    128		DEV_CLOCK_CFG_PORT_RST_SET(1),
    129		DEV_CLOCK_CFG_MAC_TX_RST |
    130		DEV_CLOCK_CFG_MAC_RX_RST |
    131		DEV_CLOCK_CFG_PORT_RST,
    132		lan966x, DEV_CLOCK_CFG(port->chip_port));
    133
    134	/* 12: Clear flushing */
    135	lan_rmw(QSYS_SW_PORT_MODE_AGING_MODE_SET(2),
    136		QSYS_SW_PORT_MODE_AGING_MODE,
    137		lan966x, QSYS_SW_PORT_MODE(port->chip_port));
    138
    139	/* The port is disabled and flushed, now set up the port in the
    140	 * new operating mode
    141	 */
    142}
    143
    144static void lan966x_port_link_up(struct lan966x_port *port)
    145{
    146	struct lan966x_port_config *config = &port->config;
    147	struct lan966x *lan966x = port->lan966x;
    148	int speed = 0, mode = 0;
    149	int atop_wm = 0;
    150
    151	switch (config->speed) {
    152	case SPEED_10:
    153		speed = LAN966X_SPEED_10;
    154		break;
    155	case SPEED_100:
    156		speed = LAN966X_SPEED_100;
    157		break;
    158	case SPEED_1000:
    159		speed = LAN966X_SPEED_1000;
    160		mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);
    161		break;
    162	case SPEED_2500:
    163		speed = LAN966X_SPEED_2500;
    164		mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);
    165		break;
    166	}
    167
    168	/* Also the GIGA_MODE_ENA(1) needs to be set regardless of the
    169	 * port speed for QSGMII ports.
    170	 */
    171	if (config->portmode == PHY_INTERFACE_MODE_QSGMII)
    172		mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);
    173
    174	lan_wr(config->duplex | mode,
    175	       lan966x, DEV_MAC_MODE_CFG(port->chip_port));
    176
    177	lan_rmw(DEV_MAC_IFG_CFG_TX_IFG_SET(config->duplex ? 6 : 5) |
    178		DEV_MAC_IFG_CFG_RX_IFG1_SET(config->speed == SPEED_10 ? 2 : 1) |
    179		DEV_MAC_IFG_CFG_RX_IFG2_SET(2),
    180		DEV_MAC_IFG_CFG_TX_IFG |
    181		DEV_MAC_IFG_CFG_RX_IFG1 |
    182		DEV_MAC_IFG_CFG_RX_IFG2,
    183		lan966x, DEV_MAC_IFG_CFG(port->chip_port));
    184
    185	lan_rmw(DEV_MAC_HDX_CFG_SEED_SET(4) |
    186		DEV_MAC_HDX_CFG_SEED_LOAD_SET(1),
    187		DEV_MAC_HDX_CFG_SEED |
    188		DEV_MAC_HDX_CFG_SEED_LOAD,
    189		lan966x, DEV_MAC_HDX_CFG(port->chip_port));
    190
    191	if (config->portmode == PHY_INTERFACE_MODE_GMII) {
    192		if (config->speed == SPEED_1000)
    193			lan_rmw(CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA_SET(1),
    194				CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA,
    195				lan966x,
    196				CHIP_TOP_CUPHY_PORT_CFG(port->chip_port));
    197		else
    198			lan_rmw(CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA_SET(0),
    199				CHIP_TOP_CUPHY_PORT_CFG_GTX_CLK_ENA,
    200				lan966x,
    201				CHIP_TOP_CUPHY_PORT_CFG(port->chip_port));
    202	}
    203
    204	/* No PFC */
    205	lan_wr(ANA_PFC_CFG_FC_LINK_SPEED_SET(speed),
    206	       lan966x, ANA_PFC_CFG(port->chip_port));
    207
    208	lan_rmw(DEV_PCS1G_CFG_PCS_ENA_SET(1),
    209		DEV_PCS1G_CFG_PCS_ENA,
    210		lan966x, DEV_PCS1G_CFG(port->chip_port));
    211
    212	lan_rmw(DEV_PCS1G_SD_CFG_SD_ENA_SET(0),
    213		DEV_PCS1G_SD_CFG_SD_ENA,
    214		lan966x, DEV_PCS1G_SD_CFG(port->chip_port));
    215
    216	/* Set Pause WM hysteresis, start/stop are in 1518 byte units */
    217	lan_wr(SYS_PAUSE_CFG_PAUSE_ENA_SET(1) |
    218	       SYS_PAUSE_CFG_PAUSE_STOP_SET(lan966x_wm_enc(4 * 1518)) |
    219	       SYS_PAUSE_CFG_PAUSE_START_SET(lan966x_wm_enc(6 * 1518)),
    220	       lan966x, SYS_PAUSE_CFG(port->chip_port));
    221
    222	/* Set SMAC of Pause frame (00:00:00:00:00:00) */
    223	lan_wr(0, lan966x, DEV_FC_MAC_LOW_CFG(port->chip_port));
    224	lan_wr(0, lan966x, DEV_FC_MAC_HIGH_CFG(port->chip_port));
    225
    226	/* Flow control */
    227	lan_rmw(SYS_MAC_FC_CFG_FC_LINK_SPEED_SET(speed) |
    228		SYS_MAC_FC_CFG_FC_LATENCY_CFG_SET(7) |
    229		SYS_MAC_FC_CFG_ZERO_PAUSE_ENA_SET(1) |
    230		SYS_MAC_FC_CFG_PAUSE_VAL_CFG_SET(0xffff) |
    231		SYS_MAC_FC_CFG_RX_FC_ENA_SET(config->pause & MLO_PAUSE_RX ? 1 : 0) |
    232		SYS_MAC_FC_CFG_TX_FC_ENA_SET(config->pause & MLO_PAUSE_TX ? 1 : 0),
    233		SYS_MAC_FC_CFG_FC_LINK_SPEED |
    234		SYS_MAC_FC_CFG_FC_LATENCY_CFG |
    235		SYS_MAC_FC_CFG_ZERO_PAUSE_ENA |
    236		SYS_MAC_FC_CFG_PAUSE_VAL_CFG |
    237		SYS_MAC_FC_CFG_RX_FC_ENA |
    238		SYS_MAC_FC_CFG_TX_FC_ENA,
    239		lan966x, SYS_MAC_FC_CFG(port->chip_port));
    240
    241	/* Tail dropping watermark */
    242	atop_wm = lan966x->shared_queue_sz;
    243
    244	/* The total memory size is diveded by number of front ports plus CPU
    245	 * port
    246	 */
    247	lan_wr(lan966x_wm_enc(atop_wm / lan966x->num_phys_ports + 1), lan966x,
    248	       SYS_ATOP(port->chip_port));
    249	lan_wr(lan966x_wm_enc(atop_wm), lan966x, SYS_ATOP_TOT_CFG);
    250
    251	/* This needs to be at the end */
    252	/* Enable MAC module */
    253	lan_wr(DEV_MAC_ENA_CFG_RX_ENA_SET(1) |
    254	       DEV_MAC_ENA_CFG_TX_ENA_SET(1),
    255	       lan966x, DEV_MAC_ENA_CFG(port->chip_port));
    256
    257	/* Take out the clock from reset */
    258	lan_wr(DEV_CLOCK_CFG_LINK_SPEED_SET(speed),
    259	       lan966x, DEV_CLOCK_CFG(port->chip_port));
    260
    261	/* Core: Enable port for frame transfer */
    262	lan_wr(QSYS_SW_PORT_MODE_PORT_ENA_SET(1) |
    263	       QSYS_SW_PORT_MODE_SCH_NEXT_CFG_SET(1) |
    264	       QSYS_SW_PORT_MODE_INGRESS_DROP_MODE_SET(1),
    265	       lan966x, QSYS_SW_PORT_MODE(port->chip_port));
    266
    267	lan_rmw(AFI_PORT_CFG_FC_SKIP_TTI_INJ_SET(0) |
    268		AFI_PORT_CFG_FRM_OUT_MAX_SET(16),
    269		AFI_PORT_CFG_FC_SKIP_TTI_INJ |
    270		AFI_PORT_CFG_FRM_OUT_MAX,
    271		lan966x, AFI_PORT_CFG(port->chip_port));
    272}
    273
    274void lan966x_port_config_down(struct lan966x_port *port)
    275{
    276	lan966x_port_link_down(port);
    277}
    278
    279void lan966x_port_config_up(struct lan966x_port *port)
    280{
    281	lan966x_port_link_up(port);
    282}
    283
    284void lan966x_port_status_get(struct lan966x_port *port,
    285			     struct phylink_link_state *state)
    286{
    287	struct lan966x *lan966x = port->lan966x;
    288	bool link_down;
    289	u16 bmsr = 0;
    290	u16 lp_adv;
    291	u32 val;
    292
    293	val = lan_rd(lan966x, DEV_PCS1G_STICKY(port->chip_port));
    294	link_down = DEV_PCS1G_STICKY_LINK_DOWN_STICKY_GET(val);
    295	if (link_down)
    296		lan_wr(val, lan966x, DEV_PCS1G_STICKY(port->chip_port));
    297
    298	/* Get both current Link and Sync status */
    299	val = lan_rd(lan966x, DEV_PCS1G_LINK_STATUS(port->chip_port));
    300	state->link = DEV_PCS1G_LINK_STATUS_LINK_STATUS_GET(val) &&
    301		      DEV_PCS1G_LINK_STATUS_SYNC_STATUS_GET(val);
    302	state->link &= !link_down;
    303
    304	/* Get PCS ANEG status register */
    305	val = lan_rd(lan966x, DEV_PCS1G_ANEG_STATUS(port->chip_port));
    306	/* Aneg complete provides more information  */
    307	if (DEV_PCS1G_ANEG_STATUS_ANEG_COMPLETE_GET(val)) {
    308		state->an_complete = true;
    309
    310		bmsr |= state->link ? BMSR_LSTATUS : 0;
    311		bmsr |= BMSR_ANEGCOMPLETE;
    312
    313		lp_adv = DEV_PCS1G_ANEG_STATUS_LP_ADV_GET(val);
    314		phylink_mii_c22_pcs_decode_state(state, bmsr, lp_adv);
    315	} else {
    316		if (!state->link)
    317			return;
    318
    319		if (state->interface == PHY_INTERFACE_MODE_1000BASEX)
    320			state->speed = SPEED_1000;
    321		else if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
    322			state->speed = SPEED_2500;
    323
    324		state->duplex = DUPLEX_FULL;
    325	}
    326}
    327
    328int lan966x_port_pcs_set(struct lan966x_port *port,
    329			 struct lan966x_port_config *config)
    330{
    331	struct lan966x *lan966x = port->lan966x;
    332	bool inband_aneg = false;
    333	bool outband;
    334
    335	if (config->inband) {
    336		if (config->portmode == PHY_INTERFACE_MODE_SGMII ||
    337		    config->portmode == PHY_INTERFACE_MODE_QSGMII)
    338			inband_aneg = true; /* Cisco-SGMII in-band-aneg */
    339		else if (config->portmode == PHY_INTERFACE_MODE_1000BASEX &&
    340			 config->autoneg)
    341			inband_aneg = true; /* Clause-37 in-band-aneg */
    342
    343		outband = false;
    344	} else {
    345		outband = true;
    346	}
    347
    348	/* Disable or enable inband */
    349	lan_rmw(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(outband),
    350		DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA,
    351		lan966x, DEV_PCS1G_MODE_CFG(port->chip_port));
    352
    353	/* Enable PCS */
    354	lan_wr(DEV_PCS1G_CFG_PCS_ENA_SET(1),
    355	       lan966x, DEV_PCS1G_CFG(port->chip_port));
    356
    357	if (inband_aneg) {
    358		int adv = phylink_mii_c22_pcs_encode_advertisement(config->portmode,
    359								   config->advertising);
    360		if (adv >= 0)
    361			/* Enable in-band aneg */
    362			lan_wr(DEV_PCS1G_ANEG_CFG_ADV_ABILITY_SET(adv) |
    363			       DEV_PCS1G_ANEG_CFG_SW_RESOLVE_ENA_SET(1) |
    364			       DEV_PCS1G_ANEG_CFG_ENA_SET(1) |
    365			       DEV_PCS1G_ANEG_CFG_RESTART_ONE_SHOT_SET(1),
    366			       lan966x, DEV_PCS1G_ANEG_CFG(port->chip_port));
    367	} else {
    368		lan_wr(0, lan966x, DEV_PCS1G_ANEG_CFG(port->chip_port));
    369	}
    370
    371	/* Take PCS out of reset */
    372	lan_rmw(DEV_CLOCK_CFG_LINK_SPEED_SET(2) |
    373		DEV_CLOCK_CFG_PCS_RX_RST_SET(0) |
    374		DEV_CLOCK_CFG_PCS_TX_RST_SET(0),
    375		DEV_CLOCK_CFG_LINK_SPEED |
    376		DEV_CLOCK_CFG_PCS_RX_RST |
    377		DEV_CLOCK_CFG_PCS_TX_RST,
    378		lan966x, DEV_CLOCK_CFG(port->chip_port));
    379
    380	port->config = *config;
    381
    382	return 0;
    383}
    384
    385void lan966x_port_init(struct lan966x_port *port)
    386{
    387	struct lan966x_port_config *config = &port->config;
    388	struct lan966x *lan966x = port->lan966x;
    389
    390	lan_rmw(ANA_PORT_CFG_LEARN_ENA_SET(0),
    391		ANA_PORT_CFG_LEARN_ENA,
    392		lan966x, ANA_PORT_CFG(port->chip_port));
    393
    394	lan966x_port_config_down(port);
    395
    396	if (lan966x->fdma)
    397		lan966x_fdma_netdev_init(lan966x, port->dev);
    398
    399	if (config->portmode != PHY_INTERFACE_MODE_QSGMII)
    400		return;
    401
    402	lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(0) |
    403		DEV_CLOCK_CFG_PCS_TX_RST_SET(0) |
    404		DEV_CLOCK_CFG_LINK_SPEED_SET(LAN966X_SPEED_1000),
    405		DEV_CLOCK_CFG_PCS_RX_RST |
    406		DEV_CLOCK_CFG_PCS_TX_RST |
    407		DEV_CLOCK_CFG_LINK_SPEED,
    408		lan966x, DEV_CLOCK_CFG(port->chip_port));
    409}