gxmac.c (94216B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * XGS 1/2.5/10/12G Media Access Controller Driver (gxmac) 8 * 9 * This module is used for: 10 * 11 * - All ports on XGS3 HUMV/Bradley/Goldwing family 12 */ 13 14 #include <shared/bsl.h> 15 16 #include <sal/core/libc.h> 17 #include <shared/alloc.h> 18 #include <sal/core/spl.h> 19 #include <sal/core/boot.h> 20 #include <soc/drv.h> 21 #include <soc/error.h> 22 #include <soc/cmic.h> 23 #include <soc/portmode.h> 24 #include <soc/ll.h> 25 #include <soc/counter.h> 26 #include <soc/phy.h> 27 #include <soc/phyctrl.h> 28 29 #ifdef BCM_GXPORT_SUPPORT 30 31 32 #ifndef GXPORT_ISLOATE_IF_LOOPBACK 33 #define GXPORT_ISLOATE_IF_LOOPBACK 0 34 #endif 35 36 /* 37 * GXMAC Register field definitions. 38 */ 39 40 /* Transmit CRC Modes (Receive has bit field definitions in register) */ 41 #define GXMAC_CRC_APPEND 0x00 /* Append CRC (Default) */ 42 #define GXMAC_CRC_KEEP 0x01 /* CRC Assumed correct */ 43 #define GXMAC_CRC_REGEN 0x02 /* Replace CRC with a new one */ 44 #define GXMAC_CRC_RSVP 0x03 /* Reserved (does Replace) */ 45 46 47 #define JUMBO_MAXSZ 0x3fe8 /* Max legal value (per regsfile) */ 48 49 /* 50 * Forward Declarations 51 * 52 * gxmac_xxx Routines that work on XGS ports in 10Gig mode. 53 */ 54 STATIC int gxmac_ipg_update(int unit, soc_port_t port); 55 STATIC int gxmac_init(int unit, soc_port_t port); 56 STATIC int gxmac_enable_set(int unit, soc_port_t port, int enable); 57 STATIC int gxmac_enable_get(int unit, soc_port_t port, int *enable); 58 STATIC int gxmac_duplex_set(int unit, soc_port_t port, int duplex); 59 STATIC int gxmac_duplex_get(int unit, soc_port_t port, int *duplex); 60 STATIC int gxmac_pause_set(int unit, soc_port_t, int, int); 61 STATIC int gxmac_pause_get(int unit, soc_port_t, int*, int*); 62 STATIC int gxmac_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t); 63 STATIC int gxmac_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t); 64 STATIC int gxmac_interface_set(int unit, soc_port_t port, 65 soc_port_if_t pif); 66 STATIC int gxmac_interface_get(int unit, soc_port_t port, 67 soc_port_if_t *pif); 68 STATIC int gxmac_speed_set(int unit, soc_port_t port, int speed); 69 STATIC int gxmac_speed_get(int unit, soc_port_t port, int *speed); 70 STATIC int gxmac_loopback_get(int unit, soc_port_t port, int *loopback); 71 STATIC int gxmac_loopback_set(int unit, soc_port_t port, int loopback); 72 STATIC int gxmac_frame_max_set(int unit, soc_port_t port, int size); 73 STATIC int gxmac_frame_max_get(int unit, soc_port_t port, int *size); 74 STATIC int gxmac_control_set(int unit, soc_port_t port, 75 soc_mac_control_t type, int value); 76 STATIC int gxmac_control_get(int unit, soc_port_t port, 77 soc_mac_control_t type, int *value); 78 STATIC int gxmac_frame_spacing_stretch_set(int unit, 79 soc_port_t port, int value); 80 STATIC int soc_unicore_pll_lock_wait(int unit, soc_port_t port); 81 STATIC int soc_unicore_speed_set(int unit, soc_port_t port, int speed); 82 83 #ifdef BROADCOM_DEBUG 84 static char *gxmac_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER; 85 static char *gxmac_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 86 #endif /* BROADCOM_DEBUG */ 87 88 /* 89 * Returns the CMIC_XGXS_MDIO_CONFIG_N register corresponding to the port. 90 */ 91 STATIC int 92 _port2cmic_xgxs_mdio_config(int unit, soc_port_t port) 93 { 94 if (SOC_IS_HB_GW(unit)) { 95 switch(port) { 96 case 0: return CMIC_XGXS_MDIO_CONFIG_0r; 97 case 1: return CMIC_XGXS_MDIO_CONFIG_1r; 98 case 2: return CMIC_XGXS_MDIO_CONFIG_2r; 99 case 3: return CMIC_XGXS_MDIO_CONFIG_3r; 100 case 4: return CMIC_XGXS_MDIO_CONFIG_4r; 101 case 5: return CMIC_XGXS_MDIO_CONFIG_5r; 102 case 6: return CMIC_XGXS_MDIO_CONFIG_6r; 103 case 7: return CMIC_XGXS_MDIO_CONFIG_7r; 104 case 8: return CMIC_XGXS_MDIO_CONFIG_8r; 105 case 9: return CMIC_XGXS_MDIO_CONFIG_9r; 106 case 10: return CMIC_XGXS_MDIO_CONFIG_10r; 107 case 11: return CMIC_XGXS_MDIO_CONFIG_11r; 108 case 12: return CMIC_XGXS_MDIO_CONFIG_12r; 109 case 13: return CMIC_XGXS_MDIO_CONFIG_13r; 110 case 14: return CMIC_XGXS_MDIO_CONFIG_14r; 111 case 15: return CMIC_XGXS_MDIO_CONFIG_15r; 112 case 16: return CMIC_XGXS_MDIO_CONFIG_16r; 113 case 17: return CMIC_XGXS_MDIO_CONFIG_17r; 114 case 18: return CMIC_XGXS_MDIO_CONFIG_18r; 115 case 19: return CMIC_XGXS_MDIO_CONFIG_19r; 116 default: return INVALIDr; 117 } 118 } 119 120 return INVALIDr; 121 } 122 123 /* 124 * Function: 125 * soc_unicore_reset (10(X)-Gig/Xaui/Serdes (XGXS) reset) 126 * Purpose: 127 * Reset and initialize the BigMAC and Unicore. 128 * Parameters: 129 * unit - XGS unit #. 130 * port - Port number on unit. 131 * Returns: 132 * SOC_E_XXX 133 */ 134 int 135 soc_unicore_reset(int unit, soc_port_t port) 136 { 137 uint8 phy_addr; 138 uint64 xgxs_ctrl; 139 uint32 reg_val, lcpll; 140 uint16 mreg_val, hg_speeds; 141 soc_reg_t reg; 142 int preemph; 143 int idriver, pdriver; 144 int rxequal, offsctl; 145 int reset_sleep_usec; 146 #ifdef BCM_HB_GW_SUPPORT 147 uint32 gport_config; 148 #endif 149 150 LOG_VERBOSE(BSL_LS_SOC_10G, 151 (BSL_META_U(unit, 152 "gxmac: unit %d port %s: unicore reset\n"), 153 unit, SOC_PORT_NAME(unit, port))); 154 155 /* 156 * CX4 compliance related 157 */ 158 reg = _port2cmic_xgxs_mdio_config(unit, port); 159 if (reg == INVALIDr) { 160 return SOC_E_INTERNAL; 161 } 162 reg_val = soc_pci_read(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0)); 163 soc_reg_field_set(unit, reg, ®_val, MD_DEVADf, 0x0); 164 soc_reg_field_set(unit, reg, ®_val, IEEE_DEVICES_IN_PKGf, 165 (IS_HG_PORT(unit, port)) ? 0x03 : 0x15); 166 soc_pci_write(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0), reg_val); 167 168 /* 169 * Unicore reference clock selection between LCPLL and clock pads. 170 */ 171 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL, 172 (SAL_BOOT_QUICKTURN) ? 0 : 1); 173 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_CTRLr(unit, port, &xgxs_ctrl)); 174 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, 175 &xgxs_ctrl, LCREFENf, lcpll); 176 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 177 178 /* 179 * Allow properties to change important variables. 180 */ 181 rxequal = soc_property_port_get(unit, port, spn_XGXS_EQUALIZER, 182 /* coverity[identical_branches : FALSE] */ 183 IS_HG_PORT(unit,port) ? 0x5 : 0x5); 184 offsctl = soc_property_port_get(unit, port, spn_XGXS_OFFSET, 185 /* coverity[identical_branches : FALSE] */ 186 IS_HG_PORT(unit,port) ? 0x2 : 0x2); 187 /* NB: preemphasis, driver, pre-driver currents are bit-reversed in HW */ 188 preemph = soc_property_port_get(unit, port, spn_XGXS_PREEMPHASIS, 189 /* coverity[identical_branches : FALSE] */ 190 IS_HG_PORT(unit,port) ? 0x4 : 0x4); 191 preemph = _shr_bit_rev8(preemph) >> 4; 192 193 idriver = soc_property_port_get(unit, port, spn_XGXS_DRIVER_CURRENT, 194 IS_HG_PORT(unit,port) ? 0x9 : 0xf); 195 idriver = _shr_bit_rev8(idriver) >> 4; 196 197 pdriver = soc_property_port_get(unit, port, spn_XGXS_PRE_DRIVER_CURRENT, 198 IS_HG_PORT(unit,port) ? 0x9 : 0xf); 199 pdriver = _shr_bit_rev8(pdriver) >> 4; 200 201 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 202 reset_sleep_usec = 100; 203 if (SAL_BOOT_QUICKTURN) { 204 /* Kick the QT phy model */ 205 uint16 rv, kv; 206 207 rv = 0x0800; /* Reset */ 208 if (IS_HG_PORT(unit,port)) { 209 kv = 0x0000; /* Configure for HG mode */ 210 } else { 211 kv = 0x0002; /* Configure for XE mode */ 212 } 213 SOC_IF_ERROR_RETURN(soc_miim_write(unit, port + 0x41 , 0x00, rv)); 214 SOC_IF_ERROR_RETURN(soc_miim_write(unit, port + 0x41 , 0x00, kv)); 215 reset_sleep_usec = 500000; 216 } else { 217 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RELOADING(unit)) { 218 SOC_IF_ERROR_RETURN(soc_miim_write(unit, port + 1, 0x00, 0x0000)); 219 } 220 } 221 222 /* 223 * Force BigMAC and TriMAC into reset before initialization 224 */ 225 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_CTRLr(unit, port, &xgxs_ctrl)); 226 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, IDDQf, 1); 227 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, PWRDWNf, 1); 228 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, HW_RSTLf, 0); 229 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, RSTB_MDIOREGSf, 0); 230 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, RSTB_PLLf, 0); 231 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, BIGMACRSTLf, 0); 232 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, TXFIFO_RSTLf, 0); 233 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 234 235 #ifdef BCM_HB_GW_SUPPORT 236 if (soc_reg_field_valid(unit, GPORT_CONFIGr, TRIMAC_RESETf)) { 237 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &gport_config)); 238 soc_reg_field_set(unit, GPORT_CONFIGr, &gport_config, 239 TRIMAC_RESETf, 1); 240 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, gport_config)); 241 } 242 #endif 243 sal_usleep(reset_sleep_usec); 244 245 /* 246 * XGXS MAC initialization steps. 247 * 248 * A minimum delay is required between various initialization steps. 249 * There is no maximum delay. The values given are very conservative 250 * including the timeout for PLL lock. 251 */ 252 253 /* Powerup Unicore interface (digital and analog clocks) */ 254 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_CTRLr(unit, port, &xgxs_ctrl)); 255 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, IDDQf, 0); 256 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, PWRDWNf, 0); 257 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 258 sal_usleep(reset_sleep_usec); 259 260 /* Bring Unicore out of reset */ 261 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_CTRLr(unit, port, &xgxs_ctrl)); 262 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, HW_RSTLf, 1); 263 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 264 265 /* Bring MDIO registers out of reset */ 266 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, RSTB_MDIOREGSf, 1); 267 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 268 269 /* Activate all clocks */ 270 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, RSTB_PLLf, 1); 271 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 272 273 /* Bring TriMac out of reset */ 274 #ifdef BCM_HB_GW_SUPPORT 275 if (soc_reg_field_valid(unit, GPORT_CONFIGr, TRIMAC_RESETf)) { 276 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &gport_config)); 277 soc_reg_field_set(unit, GPORT_CONFIGr, &gport_config, 278 TRIMAC_RESETf, 0); 279 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, gport_config)); 280 } 281 #endif 282 283 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RELOADING(unit)) { 284 /* 285 * Isolate external power-down input pins 286 */ 287 if (soc_feature(unit, soc_feature_xgxs_power)) { 288 SOC_IF_ERROR_RETURN /* Select block 0x1 */ 289 (soc_miim_write(unit, phy_addr, 0x1f, 0x0010)); 290 SOC_IF_ERROR_RETURN 291 (soc_miim_read(unit, phy_addr, 0x1a, &mreg_val)); 292 mreg_val |= (1 << 10); 293 SOC_IF_ERROR_RETURN /* Power on Core */ 294 (soc_miim_write(unit, phy_addr, 0x1a, mreg_val)); 295 } 296 297 /* 298 * Basic XGXS configuration 299 */ 300 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 301 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 302 SOC_IF_ERROR_RETURN /* Disable PLL state machine */ 303 (soc_miim_write(unit, phy_addr, 0x11, 0x5006)); 304 SOC_IF_ERROR_RETURN /* PLL VCO step time */ 305 (soc_miim_write(unit, phy_addr, 0x12, 0x04ff)); 306 SOC_IF_ERROR_RETURN /* Turn off slowdn_xor */ 307 (soc_miim_write(unit, phy_addr, 0x15, 0x0000)); 308 SOC_IF_ERROR_RETURN /* Select block 0xf */ 309 (soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 310 SOC_IF_ERROR_RETURN /* CDR bandwidth */ 311 (soc_miim_write(unit, phy_addr, 0x16, 0x8300)); 312 313 SOC_IF_ERROR_RETURN /* Select block 0x0 */ 314 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 315 SOC_IF_ERROR_RETURN 316 (soc_miim_read(unit, phy_addr, 0x10, &mreg_val)); 317 mreg_val = (mreg_val & 0xf0ff) | (0xc << 8); 318 SOC_IF_ERROR_RETURN /* Select ComboCore mode */ 319 (soc_miim_write(unit, phy_addr, 0x10, mreg_val)); 320 if (IS_HG_PORT(unit,port)) { 321 SOC_IF_ERROR_RETURN /* Enable DTE mdio reg mapping */ 322 (soc_miim_write(unit, phy_addr, 0x1e, 0x0001)); 323 SOC_IF_ERROR_RETURN /* Select block 0x32 */ 324 (soc_miim_write(unit, phy_addr, 0x1f, 0x0320)); 325 /* For Draco and Hercules, use pre-CX4 signalling */ 326 hg_speeds = 0x0008; 327 if (soc_property_port_get(unit, port, spn_10G_IS_CX4, TRUE)) { 328 /* Also advertise 10G CX4 signalling by default */ 329 hg_speeds |= 0x0010; 330 } 331 if (SOC_INFO(unit).port_speed_max[port] >= 13000) { 332 /* Also advertise 12G and 13G */ 333 hg_speeds |= 0x00a0; 334 } 335 SOC_IF_ERROR_RETURN 336 (soc_miim_write(unit, phy_addr, 0x19, hg_speeds)); 337 } else { 338 SOC_IF_ERROR_RETURN /* Enable PMA/PMD mdio reg mapping */ 339 (soc_miim_write(unit, phy_addr, 0x1e, 0x0201)); 340 SOC_IF_ERROR_RETURN /* Select block 0x32 */ 341 (soc_miim_write(unit, phy_addr, 0x1f, 0x0320)); 342 if (IS_GE_PORT(unit,port)) { 343 SOC_IF_ERROR_RETURN /* Only advertise 2.5G CX4 */ 344 (soc_miim_write(unit, phy_addr, 0x19, 0x0001)); 345 } else { 346 /* Advertise only 10G CX4 for XE port */ 347 SOC_IF_ERROR_RETURN /* Advertise 10G CX4 only */ 348 (soc_miim_write(unit, phy_addr, 0x19, 0x0010)); 349 } 350 } 351 352 /* 353 * Configure 10G parallel detect 354 */ 355 SOC_IF_ERROR_RETURN /* Select block 0x34 */ 356 (soc_miim_write(unit, phy_addr, 0x1f, 0x0340)); 357 SOC_IF_ERROR_RETURN /* Adjust parallel detect link timer to 60ms */ 358 (soc_miim_write(unit, phy_addr, 0x13, 0x16E2)); 359 SOC_IF_ERROR_RETURN /* Read parDet10GControl register */ 360 (soc_miim_read(unit, phy_addr, 0x11, &mreg_val)); 361 mreg_val &= ~(1 << 0); 362 if (soc_property_port_get(unit, port, spn_XGXS_PDETECT_10G, 1)) { 363 mreg_val |= (1 << 0); /* Enable 10G parallel detect */ 364 } 365 SOC_IF_ERROR_RETURN /* Update parDet10GControl register */ 366 (soc_miim_write(unit, phy_addr, 0x11, mreg_val)); 367 if (!(IS_HG_PORT(unit, port) && 368 SOC_INFO(unit).port_speed_max[port] > 10000)) { 369 /* 370 * Disable 12 Gbps parallel detect on all ports with max 371 * speed 10Gbps and lower. 372 */ 373 SOC_IF_ERROR_RETURN /* Read parDet10GControl register */ 374 (soc_miim_read(unit, phy_addr, 0x11, &mreg_val)); 375 mreg_val |= (1 << 5); /* Disable parallel detect for 12 Gbps */ 376 mreg_val |= (1 << 6); /* Disable parallel detect 12 Gbps TXD */ 377 SOC_IF_ERROR_RETURN /* Update parDet10GControl register */ 378 (soc_miim_write(unit, phy_addr, 0x11, mreg_val)); 379 } 380 SOC_IF_ERROR_RETURN /* Update parDet10GLostLink register */ 381 (soc_miim_write(unit, phy_addr, 0x14, 0x4c4a)); 382 383 /* 384 * Configure TX pre-emphasis, driver and pre-driver currents 385 */ 386 SOC_IF_ERROR_RETURN /* Select block 0xa */ 387 (soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 388 SOC_IF_ERROR_RETURN /* TX pre-emphasis */ 389 (soc_miim_write(unit, phy_addr, 0x17, ((preemph & 0xf) << 12) | 390 ((idriver & 0xf) << 8) | 391 ((pdriver & 0xf) << 4))); 392 393 /* 394 * Configure PLL 395 */ 396 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 397 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 398 SOC_IF_ERROR_RETURN /* Enable PLL state machine */ 399 (soc_miim_write(unit, phy_addr, 0x11, 0xf01e)); 400 401 /* 402 * Transform CX4 pin out on the board to HG pinout 403 */ 404 if (soc_property_port_get(unit, port, spn_CX4_TO_HIGIG, FALSE)) { 405 SOC_IF_ERROR_RETURN /* Select block 0x10 */ 406 (soc_miim_write(unit, phy_addr, 0x1f, 0x0100)); 407 SOC_IF_ERROR_RETURN /* Enable TX Lane swap */ 408 (soc_miim_write(unit, phy_addr, 0x11, 0x80e4)); 409 410 SOC_IF_ERROR_RETURN /* Select block 0x0a */ 411 (soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 412 SOC_IF_ERROR_RETURN /* Flip TX Lane polarity */ 413 (soc_miim_write(unit, phy_addr, 0x11, 0x1020)); 414 } else { 415 /* If CX4 to HG conversion is enabled, do not allow individual lane 416 * swapping. 417 */ 418 uint16 lane_map, i; 419 uint16 lane, hw_map, chk_map; 420 421 /* Update RX lane map */ 422 lane_map = soc_property_port_get(unit, port, 423 spn_XGXS_RX_LANE_MAP, 0x0123) & 0xffff; 424 425 if (lane_map != 0x0123) { 426 hw_map = 0; 427 chk_map = 0; 428 for (i = 0; i < 4; i++) { 429 lane = (lane_map >> (i * 4)) & 0xf; 430 hw_map |= lane << (i * 2); 431 chk_map |= 1 << lane; 432 } 433 if (chk_map == 0xf) { 434 SOC_IF_ERROR_RETURN /* Select block 0x10 */ 435 (soc_miim_write(unit, phy_addr, 0x1f, 0x0100)); 436 SOC_IF_ERROR_RETURN /* Enable RX Lane swap */ 437 (soc_miim_modify(unit, phy_addr, 0x10, 438 0x8000 | hw_map, 0x80ff)); 439 } else { 440 LOG_ERROR(BSL_LS_SOC_COMMON, 441 (BSL_META_U(unit, 442 "unit %d port %s: Invalid RX lane map 0x%04x.\n"), 443 unit, SOC_PORT_NAME(unit, port), lane_map)); 444 } 445 } 446 447 /* Update TX lane map */ 448 lane_map = soc_property_port_get(unit, port, 449 spn_XGXS_TX_LANE_MAP, 0x0123) & 0xffff; 450 451 if (lane_map != 0x0123) { 452 hw_map = 0; 453 chk_map = 0; 454 for (i = 0; i < 4; i++) { 455 lane = (lane_map >> (i * 4)) & 0xf; 456 hw_map |= lane << (i * 2); 457 chk_map |= 1 << lane; 458 } 459 if (chk_map == 0xf) { 460 SOC_IF_ERROR_RETURN /* Select block 0x10 */ 461 (soc_miim_write(unit, phy_addr, 0x1f, 0x0100)); 462 SOC_IF_ERROR_RETURN /* Enable TX Lane swap */ 463 (soc_miim_modify(unit, phy_addr, 0x11, 464 0x8000 | hw_map, 0x80ff)); 465 } else { 466 LOG_ERROR(BSL_LS_SOC_COMMON, 467 (BSL_META_U(unit, 468 "unit %d port %s: Invalid TX lane map 0x%04x.\n"), 469 unit, SOC_PORT_NAME(unit, port), lane_map)); 470 } 471 } 472 } 473 474 /* 475 * Configure RX equalizer boost 476 */ 477 SOC_IF_ERROR_RETURN /* Select block 0xb */ 478 (soc_miim_write(unit, phy_addr, 0x1f, 0x00b0)); 479 SOC_IF_ERROR_RETURN /* RX equalizer and offset controls */ 480 (soc_miim_write(unit, phy_addr, 0x1c, ((offsctl & 0x7) << 3) | 481 (rxequal & 0x7))); 482 483 SOC_IF_ERROR_RETURN /* Select block 0x0 */ 484 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 485 486 if (SAL_BOOT_QUICKTURN) { 487 LOG_VERBOSE(BSL_LS_SOC_10G, 488 (BSL_META_U(unit, 489 "SIMULATION: xmac: unit %d port %s: " 490 "skipped waiting for pll lock\n"), 491 unit, SOC_PORT_NAME(unit, port))); 492 } else { 493 /* Wait for Tx PLL lock */ 494 SOC_IF_ERROR_RETURN 495 (soc_unicore_pll_lock_wait(unit, port)); 496 } 497 498 /* 499 * Configure signal auto-detection between SGMII and fiber. 500 */ 501 SOC_IF_ERROR_RETURN /* Select block DIGITAL (0x30) */ 502 (soc_miim_write(unit, phy_addr, 0x1f, 0x0300)); 503 SOC_IF_ERROR_RETURN 504 (soc_miim_read(unit, phy_addr, 0x10, &mreg_val)); 505 mreg_val &= ~((1 << 4) | (1 << 0)); 506 if (soc_property_port_get(unit, port, spn_SERDES_AUTOMEDIUM, TRUE)) { 507 mreg_val |= (1 << 4); 508 } 509 if (soc_property_port_get(unit, port, spn_SERDES_FIBER_PREF, TRUE)) { 510 mreg_val |= (1 << 0); 511 } 512 SOC_IF_ERROR_RETURN 513 (soc_miim_write(unit, phy_addr, 0x10, mreg_val)); 514 515 /* Set the block select to 0 after reset */ 516 SOC_IF_ERROR_RETURN 517 (soc_miim_write(unit, phy_addr, 0x1f, 0)); 518 } /* end if (!SOC_WARM_BOOT(unit) && !SOC_IS_RELOADING(unit)) */ 519 520 /* Bring BigMac out of reset */ 521 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_CTRLr(unit, port, &xgxs_ctrl)); 522 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, BIGMACRSTLf, 1); 523 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 524 525 /* Enable Tx FIFO */ 526 soc_reg64_field32_set(unit, MAC_XGXS_CTRLr, &xgxs_ctrl, TXFIFO_RSTLf, 1); 527 SOC_IF_ERROR_RETURN(WRITE_MAC_XGXS_CTRLr(unit, port, xgxs_ctrl)); 528 529 /* Set default speed */ 530 if (IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port)) { 531 SOC_IF_ERROR_RETURN(soc_unicore_speed_set(unit, port, 10000)); 532 } 533 534 return SOC_E_NONE; 535 } 536 537 /* 538 * Function: 539 * soc_unicore_pll_lock_wait 540 * Purpose: 541 * Wait for Unicore Tx PLL lock. 542 * Parameters: 543 * unit - XGS unit #. 544 * port - Port number on unit. 545 * Returns: 546 * SOC_E_XXX 547 */ 548 int 549 soc_unicore_pll_lock_wait(int unit, int port) 550 { 551 uint64 xgxs_stat; 552 int pll_lock_usec; 553 int locked; 554 soc_timeout_t to; 555 556 /* 557 * Wait up to 500 msec for TX PLL lock. 558 */ 559 pll_lock_usec = 500000; 560 soc_timeout_init(&to, pll_lock_usec, 0); 561 562 locked = 0; 563 while (!soc_timeout_check(&to)) { 564 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_STATr(unit, port, &xgxs_stat)); 565 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 566 TXPLL_LOCKf); 567 if (locked) { 568 break; 569 } 570 } 571 572 if (!locked) { 573 uint16 x_pll_stat; 574 uint16 block_select; 575 576 uint8 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 577 578 SOC_IF_ERROR_RETURN /* Save original block select to restore later */ 579 (soc_miim_read(unit, phy_addr, 0x1f, &block_select)); 580 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 581 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 582 SOC_IF_ERROR_RETURN /* Read PLL status */ 583 (soc_miim_read(unit, phy_addr, 0x10, &x_pll_stat)); 584 SOC_IF_ERROR_RETURN /* Restore original block select */ 585 (soc_miim_write(unit, phy_addr, 0x1f, block_select)); 586 587 LOG_ERROR(BSL_LS_SOC_COMMON, 588 (BSL_META_U(unit, 589 "unit %d port %s: Unicore PLL did not lock " 590 "PLL_STAT %04x\n"), 591 unit, SOC_PORT_NAME(unit, port), x_pll_stat)); 592 593 return SOC_E_TIMEOUT; 594 } 595 596 LOG_VERBOSE(BSL_LS_SOC_10G, 597 (BSL_META_U(unit, 598 "unit %d port %s: Unicore PLL locked in %d usec\n"), 599 unit, SOC_PORT_NAME(unit, port), 600 soc_timeout_elapsed(&to))); 601 602 return SOC_E_NONE; 603 } 604 605 #ifdef GXPORT_ISLOATE_IF_LOOPBACK 606 /* 607 * Function: 608 * soc_unicore_lane_power_set 609 * Purpose: 610 * Power XAUI lanes /up/down 611 * Parameters: 612 * unit - XGS unit #. 613 * port - Port number on unit. 614 * power_mask - mask of lanes to power up 615 * Returns: 616 * SOC_E_XXX 617 */ 618 int 619 soc_unicore_lane_power_set(int unit, soc_port_t port, uint32 power_mask) 620 { 621 uint8 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 622 uint16 lane_ctrl, o_lane_ctrl; 623 624 SOC_IF_ERROR_RETURN /* Select block 0x10 */ 625 (soc_miim_write(unit, phy_addr, 0x1f, 0x0010)); 626 627 SOC_IF_ERROR_RETURN 628 (soc_miim_read(unit, phy_addr, 0x18, &lane_ctrl)); 629 630 o_lane_ctrl = lane_ctrl; 631 lane_ctrl &= ~0x8ff; 632 /* Note that register bit value 1 means power down */ 633 power_mask = (power_mask & 0xf) ^ 0xf; 634 /* Set power for both Rx and Tx lanes */ 635 lane_ctrl |= (power_mask << 4) | power_mask; 636 if (power_mask) { 637 /* Force power down */ 638 lane_ctrl |= 0x800; 639 } 640 641 if (o_lane_ctrl != lane_ctrl) { 642 SOC_IF_ERROR_RETURN 643 (soc_miim_write(unit, phy_addr, 0x18, lane_ctrl)); 644 } 645 646 SOC_IF_ERROR_RETURN /* Select block 0 */ 647 (soc_miim_write(unit, phy_addr, 0x1f, 0)); 648 649 return SOC_E_NONE; 650 } 651 #endif 652 653 /* 654 * Function: 655 * soc_unicore_speed_set 656 * Purpose: 657 * Get current Unicore speed. 658 * Parameters: 659 * unit - XGS unit #. 660 * port - Port number on unit. 661 * speed - new XGXS speed. 662 * Returns: 663 * SOC_E_XXX 664 * Notes: 665 * The Start Sequencer bit in the xgxsControl register should 666 * be deasserted before calling this function to guarantee a 667 * glitch-free clock change. 668 */ 669 int 670 soc_unicore_speed_set(int unit, soc_port_t port, int speed) 671 { 672 int speed_val; 673 uint8 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 674 uint16 mii_ctrl, misc1, misc_ctrl; 675 uint16 block_select; 676 677 if (IS_HG_PORT(unit, port)) { 678 if ((speed != 0) && (speed < 10000)) { 679 return SOC_E_PARAM; 680 } 681 if (SOC_INFO(unit).port_speed_max[port] > 0 && 682 speed > SOC_INFO(unit).port_speed_max[port]) { 683 return SOC_E_PARAM; 684 } 685 } else if (IS_XE_PORT(unit, port)) { 686 if ((speed != 0) && ((speed < 1000) || (speed > 10000))) { 687 return SOC_E_PARAM; 688 } 689 } else { 690 if ((speed < 0) || (speed > 2500)) { 691 return SOC_E_PARAM; 692 } 693 } 694 695 switch (speed) { 696 case 13000: 697 speed_val = 7; 698 break; 699 case 12500: 700 speed_val = 6; 701 break; 702 case 12000: 703 speed_val = 5; 704 break; 705 case 10000: 706 speed_val = 4; /* 10G CX4 */ 707 if (IS_HG_PORT(unit, port) && 708 soc_property_port_get(unit, port, spn_10G_IS_CX4, TRUE) == FALSE) { 709 speed_val = 3; /* 10G HiG */ 710 } 711 break; 712 case 2500: 713 speed_val = 0; 714 break; 715 case 1000: 716 case 100: 717 case 10: 718 speed_val = -1; 719 break; 720 case 0: 721 return SOC_E_NONE; 722 case 16000: 723 case 15000: 724 case 6000: 725 case 5000: 726 default: 727 return SOC_E_PARAM; 728 } 729 730 if (!SOC_WARM_BOOT(unit) && !SOC_IS_RELOADING(unit)) { 731 /* Save original block select mapping */ 732 SOC_IF_ERROR_RETURN 733 (soc_miim_read(unit, phy_addr, 0x1f, &block_select)); 734 735 /* Select block DIGITAL (0x30) */ 736 SOC_IF_ERROR_RETURN 737 (soc_miim_write(unit, phy_addr, 0x1f, 0x0300)); 738 739 /* Set speed in Misc1 register */ 740 SOC_IF_ERROR_RETURN 741 (soc_miim_read(unit, phy_addr, 0x18, &misc1)); 742 misc1 &= ~0x001f; 743 if (speed_val >= 0) { 744 misc1 |= 0x0010 | speed_val; 745 } 746 SOC_IF_ERROR_RETURN 747 (soc_miim_write(unit, phy_addr, 0x18, misc1)); 748 749 /* Select block BLOCK0 */ 750 SOC_IF_ERROR_RETURN 751 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 752 753 /* Map XAUI or SerDes IEEE registers */ 754 SOC_IF_ERROR_RETURN 755 (soc_miim_read(unit, phy_addr, 0x1e, &misc_ctrl)); 756 /* Disable dynamic IEEE address space mapping and 757 * map Serdes IEEE address space. 758 */ 759 misc_ctrl &= ~0x0003; 760 if (speed > 2500) { 761 misc_ctrl |= 0x0001; /* Select XAUI registers */ 762 } 763 764 /* Write final IEEE register mapping */ 765 SOC_IF_ERROR_RETURN 766 (soc_miim_write(unit, phy_addr, 0x1e, misc_ctrl)); 767 768 /* 769 * Speeds of 2.5 Gbps and below must be set in IEEE registers. 770 */ 771 if (speed <= 2500) { 772 SOC_IF_ERROR_RETURN 773 (soc_miim_read(unit, phy_addr, MII_CTRL_REG, &mii_ctrl)); 774 mii_ctrl &= ~(MII_CTRL_SS_MASK | MII_CTRL_FS_2500); 775 if (speed == 2500) { 776 /* Force 2.5 Gbps */ 777 mii_ctrl |= MII_CTRL_FS_2500; 778 } else if (speed == 1000) { 779 mii_ctrl |= MII_CTRL_SS_1000; 780 } else if (speed == 100) { 781 mii_ctrl |= MII_CTRL_SS_100; 782 } else { 783 mii_ctrl |= MII_CTRL_SS_10; 784 } 785 SOC_IF_ERROR_RETURN 786 (soc_miim_write(unit, phy_addr, MII_CTRL_REG, mii_ctrl)); 787 } 788 789 /* Restore Original Block select mapping */ 790 SOC_IF_ERROR_RETURN 791 (soc_miim_write(unit, phy_addr, 0x1f, block_select)); 792 } 793 794 if (speed < 10000) { 795 SOC_IF_ERROR_RETURN 796 (gxmac_interface_set(unit, port, SOC_PORT_IF_GMII)); 797 } else { 798 SOC_IF_ERROR_RETURN 799 (gxmac_interface_set(unit, port, SOC_PORT_IF_XGMII)); 800 } 801 return SOC_E_NONE; 802 } 803 804 /* 805 * Function: 806 * soc_unicore_speed_get 807 * Purpose: 808 * Get current Unicore speed. 809 * Parameters: 810 * unit - XGS unit #. 811 * port - Port number on unit. 812 * speed - (OUT) current XGXS speed (forced or negotiated). 813 * an_done - (OUT) if true, auto-negotiation is complete. This value 814 * is undefined unless auto-negotiation is enabled. 815 * Returns: 816 * SOC_E_XXX 817 */ 818 int 819 soc_unicore_speed_get(int unit, soc_port_t port, int *speed, int *an_done) 820 { 821 uint64 xgxs_stat; 822 uint32 i; 823 824 static struct { 825 soc_field_t field; 826 int speed; 827 } _sp_sel[] = { 828 { SPEED_13000f, 13000 }, 829 { SPEED_12500f, 12500 }, 830 { SPEED_12000f, 12000 }, 831 { SPEED_10000_CX4f, 10000 }, 832 { SPEED_10000f, 10000 }, 833 { SPEED_6000f, 6000 }, 834 { SPEED_5000f, 5000 }, 835 { SPEED_2500f, 2500 }, 836 { SPEED_1000f, 1000 }, 837 { SPEED_100f, 100 }, 838 { SPEED_10f, 10 } 839 }; 840 841 /* Provide reasonable default value */ 842 *speed = IS_GE_PORT(unit, port) ? 1000 : 10000; 843 844 SOC_IF_ERROR_RETURN 845 (READ_MAC_XGXS_STATr(unit, port, &xgxs_stat)); 846 847 for (i = 0; i < COUNTOF(_sp_sel); i++) { 848 if (soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 849 _sp_sel[i].field)) { 850 *speed = _sp_sel[i].speed; 851 break; 852 } 853 } 854 855 if (IS_HG_PORT(unit, port) && *speed < 10000) { 856 *speed = 0; 857 } 858 859 /* Ignore if null pointer */ 860 if (an_done) { 861 *an_done = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 862 AUTONEG_COMPLETEf); 863 } 864 865 return SOC_E_NONE; 866 } 867 868 /* 869 * Function: 870 * soc_unicore_mac_mode_set 871 * Purpose: 872 * Set current Unicore MAC mode. 873 * Parameters: 874 * unit - XGS unit #. 875 * port - Port number on unit. 876 * mode - new XGXS MAC mode (TriMAC or BigMAC). 877 * enable - if zero, disable both MACs 878 * Returns: 879 * SOC_E_NONE 880 * Note: 881 * Don't need to restore old MAC states to new MAC when switching 882 * mode. All MACs are already in the same state. 883 */ 884 int 885 soc_unicore_mac_mode_set(int unit, soc_port_t port, 886 soc_mac_mode_t mode, int enable) 887 { 888 int gmac_en, bmac_en, femac_en, gport_en, xport_en; 889 uint32 xport, gport; 890 uint64 ctrl, octrl; 891 uint32 gmacc1, ogmacc1; 892 uint32 fe_mac1, ofe_mac1; 893 894 xport_en = (mode == SOC_MAC_MODE_10000) ? 1 : 0; 895 896 /* 897 * Note that for correct LED operation, either the XPORT or the 898 * GPORT must be enabled, even when both MACs are disabled. 899 */ 900 gport_en = !xport_en; 901 902 femac_en = gmac_en = bmac_en = 0; 903 if (enable) { 904 switch (mode) { 905 case SOC_MAC_MODE_10000: 906 bmac_en = 1; 907 break; 908 case SOC_MAC_MODE_1000_T: 909 gmac_en = 1; 910 break; 911 case SOC_MAC_MODE_10_100: /* fall through */ 912 case SOC_MAC_MODE_10: 913 femac_en = 1; 914 break; 915 default: 916 return SOC_E_INTERNAL; 917 } 918 } 919 920 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &gport)); 921 SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &xport)); 922 923 /* 924 * When switching between MAC modes, both GPORT and XPORT should be 925 * disabled before enabling the appropriate PORT. However, we should 926 * only disable the ports if necessary. In particular, when disabling 927 * a port the xPORT_EN should remain set to avoid incoming packets 928 * getting chopped in the middle. Only by disabling the MAC Rx we 929 * can ensure that packets are stopped at a packet boundary. 930 */ 931 if (xport_en) { 932 if (soc_reg_field_valid(unit, GPORT_CONFIGr, GPORT_ENf)) { 933 soc_reg_field_set(unit, GPORT_CONFIGr, &gport, GPORT_ENf, 0); 934 } 935 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, gport)); 936 } else { 937 soc_reg_field_set(unit, XPORT_CONFIGr, &xport, XPORT_ENf, 0); 938 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, xport)); 939 } 940 941 /* Enable/disable TriMAC */ 942 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 943 ogmacc1 = gmacc1; 944 soc_reg_field_set(unit, GMACC1r, &gmacc1, TXEN0f, 1); 945 soc_reg_field_set(unit, GMACC1r, &gmacc1, RXEN0f, gmac_en); 946 if (gmacc1 != ogmacc1) { 947 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1)); 948 } 949 950 SOC_IF_ERROR_RETURN(READ_FE_MAC1r(unit, port, &fe_mac1)); 951 ofe_mac1 = fe_mac1; 952 soc_reg_field_set(unit, FE_MAC1r, &fe_mac1, RX_ENf, femac_en); 953 if (fe_mac1 != ofe_mac1) { 954 SOC_IF_ERROR_RETURN(WRITE_FE_MAC1r(unit, port, fe_mac1)); 955 } 956 957 if (gport_en) { 958 if (soc_reg_field_valid(unit, GPORT_CONFIGr, GPORT_ENf)) { 959 soc_reg_field_set(unit, GPORT_CONFIGr, &gport, GPORT_ENf, 1); 960 } 961 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, gport)); 962 } 963 964 /* Enable/disable BigMAC */ 965 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 966 octrl = ctrl; 967 soc_reg64_field32_set(unit, MAC_CTRLr, &ctrl, TXENf, 1); 968 soc_reg64_field32_set(unit, MAC_CTRLr, &ctrl, RXENf, bmac_en); 969 if (COMPILER_64_NE(ctrl, octrl)) { 970 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, ctrl)); 971 } 972 if (xport_en) { 973 soc_reg_field_set(unit, XPORT_CONFIGr, &xport, XPORT_ENf, 1); 974 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, xport)); 975 } 976 977 return SOC_E_NONE; 978 } 979 980 /* 981 * Function: 982 * soc_unicore_mac_mode_get 983 * Purpose: 984 * Get current Unicore MAC mode. 985 * Parameters: 986 * unit - XGS unit #. 987 * port - Port number on unit. 988 * mode - (OUT) current XGXS MAC mode (TriMAC or BigMAC). 989 * Returns: 990 * SOC_E_NONE 991 */ 992 int 993 soc_unicore_mac_mode_get(int unit, soc_port_t port, soc_mac_mode_t *mode) 994 { 995 int cur_speed; 996 SOC_IF_ERROR_RETURN 997 (soc_unicore_speed_get(unit, port, &cur_speed, NULL)); 998 switch (cur_speed) { 999 case 16000: /* fall through */ 1000 case 15000: /* fall through */ 1001 case 13000: /* fall through */ 1002 case 12500: /* fall through */ 1003 case 12000: /* fall through */ 1004 case 10000: 1005 *mode = SOC_MAC_MODE_10000; 1006 break; 1007 case 2500: /* fall through */ 1008 case 1000: 1009 *mode = SOC_MAC_MODE_1000_T; 1010 break; 1011 case 100: 1012 *mode = SOC_MAC_MODE_10_100; 1013 break; 1014 case 10: 1015 *mode = SOC_MAC_MODE_10; 1016 break; 1017 default: 1018 return SOC_E_INTERNAL; 1019 } 1020 return SOC_E_NONE; 1021 } 1022 1023 /* 1024 * Function: 1025 * gxmac_ifg_to_ipg 1026 * Description: 1027 * Converts the inter-frame gap specified in bit-times into a value 1028 * suitable to be programmed into the IPG register 1029 * Parameters: 1030 * unit - Device number 1031 * port - Port number 1032 * speed - the speed for which the IFG is being set 1033 * duplex - the duplex for which the IFG is being set 1034 * ifg - Inter-frame gap in bit-times 1035 * ipg - (OUT) the value to be written into IPG 1036 * Return Value: 1037 * BCM_E_XXX 1038 * Notes: 1039 * The function makes sure the calculated IPG value will not cause 1040 * hardware to fail. If the requested ifg value cannot be supported in 1041 * hardware, the function will choose a value that approximates the 1042 * requested value as best as possible. 1043 * 1044 * Specifically: 1045 * -- Current chips only support ifg which is divisible by 8. If 1046 * the specified ifg is not divisible by 8, it will be rounded 1047 * to the next multiplier of 8 (65 will result in 72). 1048 * -- ifg < 64 are not supported 1049 */ 1050 STATIC int 1051 gxmac_ifg_to_ipg(int unit, soc_port_t port, int speed, int duplex, 1052 int ifg, int *ipg) 1053 { 1054 /* The inter-frame gap should be a multiple of 8 bit-times */ 1055 ifg = (ifg + 7) & ~7; 1056 1057 /* The smallest supported ifg is 64 bit-times */ 1058 ifg = (ifg < 64) ? 64 : ifg; 1059 1060 if (duplex) { 1061 if (speed == 10 || speed == 100) { 1062 *ipg = ifg / 4 - 3; 1063 } else { 1064 *ipg = ifg / 8; 1065 } 1066 } else { 1067 switch (speed) { 1068 case 10: 1069 *ipg = ifg / 4 - 12; 1070 break; 1071 case 100: 1072 *ipg = ifg / 4 - 13; 1073 break; 1074 default: 1075 return SOC_E_INTERNAL; 1076 } 1077 } 1078 1079 if (IS_HG_PORT(unit, port) && *ipg >= 4) { 1080 *ipg -= 4; 1081 } 1082 1083 return SOC_E_NONE; 1084 } 1085 1086 /* 1087 * Function: 1088 * gxmac_ipg_to_ifg 1089 * Description: 1090 * Converts the IPG register value into the inter-frame gap expressed in 1091 * bit-times 1092 * Parameters: 1093 * unit - Device number 1094 * port - Port number 1095 * speed - the speed for which the IFG is being set 1096 * duplex - the duplex for which the IFG is being set 1097 * ipg - the value in the IPG register 1098 * ifg - Inter-frame gap in bit-times 1099 * Return Value: 1100 * BCM_E_XXX 1101 */ 1102 STATIC int 1103 gxmac_ipg_to_ifg(int unit, soc_port_t port, int speed, int duplex, 1104 int ipg, int *ifg) 1105 { 1106 /* 1107 * Now we need to convert the value accoring to various chips' 1108 * peculiarities (there are none as of now) 1109 */ 1110 if (IS_HG_PORT(unit, port)) { 1111 ipg += 4; 1112 } 1113 1114 if (duplex) { 1115 if (speed == 10 || speed == 100) { 1116 *ifg = (ipg + 3) * 4; 1117 } else { 1118 *ifg = ipg * 8; 1119 } 1120 } else { 1121 switch (speed) { 1122 case 10: 1123 *ifg = (ipg + 12) * 4; 1124 break; 1125 case 100: 1126 *ifg = (ipg + 13) * 4; 1127 break; 1128 default: 1129 return SOC_E_INTERNAL; 1130 } 1131 } 1132 1133 return SOC_E_NONE; 1134 } 1135 1136 /* 1137 * Function: 1138 * gxmac_ipg_update 1139 * Purpose: 1140 * Set the IPG appropriate for current speed/duplex 1141 * Parameters: 1142 * unit - StrataSwitch unit #. 1143 * port - Port number on unit. 1144 * Notes: 1145 * The current speed/duplex are read from the hardware registers. 1146 */ 1147 STATIC int 1148 gxmac_ipg_update(int unit, int port) 1149 { 1150 int fd, speed, ifg, ipg; 1151 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1152 uint64 tx_ctrl, otx_ctrl; 1153 uint32 gmacc2, ogmacc2, fe_ipg; 1154 1155 SOC_IF_ERROR_RETURN(gxmac_duplex_get(unit, port, &fd)); 1156 SOC_IF_ERROR_RETURN(gxmac_speed_get(unit, port, &speed)); 1157 1158 /* Get the ifg value in bit-times */ 1159 if (fd) { 1160 switch (speed) { 1161 case 0: 1162 ifg = IS_GE_PORT(unit, port) ? si->fd_1000 : si->fd_10000; 1163 break; 1164 case 10: 1165 ifg = si->fd_10; 1166 break; 1167 case 100: 1168 ifg = si->fd_100; 1169 break; 1170 case 1000: 1171 ifg = si->fd_1000; 1172 break; 1173 case 2500: 1174 ifg = si->fd_2500; 1175 break; 1176 case 10000: /* fall through */ 1177 case 12000: /* fall through */ 1178 case 12500: /* fall through */ 1179 case 13000: /* fall through */ 1180 case 15000: /* fall through */ 1181 case 16000: /* fall through */ 1182 ifg = si->fd_10000; 1183 break; 1184 default: 1185 return SOC_E_INTERNAL; 1186 } 1187 } else { 1188 switch (speed) { 1189 case 10: 1190 ifg = si->hd_10; 1191 break; 1192 case 100: 1193 ifg = si->hd_100; 1194 break; 1195 default: 1196 return SOC_E_INTERNAL; 1197 } 1198 } 1199 1200 /* Convert the ifg value from bit-times into IPG register-specific value */ 1201 SOC_IF_ERROR_RETURN(gxmac_ifg_to_ipg(unit, port, speed, fd, ifg, &ipg)); 1202 1203 1204 /* Program the appropriate register */ 1205 switch (speed) { 1206 case 10: 1207 case 100: 1208 fe_ipg = 0; 1209 soc_reg_field_set(unit, FE_IPGTr, &fe_ipg, IPGTf, ipg); 1210 SOC_IF_ERROR_RETURN(WRITE_FE_IPGTr(unit, port, fe_ipg)); 1211 break; 1212 case 2500: 1213 case 1000: 1214 SOC_IF_ERROR_RETURN(READ_GMACC2r(unit, port, &gmacc2)); 1215 ogmacc2 = gmacc2; 1216 soc_reg_field_set(unit, GMACC2r, &gmacc2, IPGTf, ipg); 1217 if (gmacc2 != ogmacc2) { 1218 SOC_IF_ERROR_RETURN(WRITE_GMACC2r(unit, port, gmacc2)); 1219 } 1220 break; 1221 default: 1222 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tx_ctrl)); 1223 otx_ctrl = tx_ctrl; 1224 1225 1226 if (soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE)) { 1227 /* Back to back 64 bytes packet must have IPG = 19 to 1228 * prevent data rate higher than acceptable WAN mode line rate. 1229 */ 1230 if (ipg < 19) { 1231 ipg = 19; 1232 } 1233 1234 /* Insert an Idle after every 13 bytes of data to keep 1235 * the data rate lower than 9.294Gbps. 1236 */ 1237 soc_reg64_field32_set(unit, MAC_TXCTRLr, &otx_ctrl, THROTDENOMf, 1238 13); 1239 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 1240 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit)) { 1241 soc_reg64_field32_set(unit, MAC_TXCTRLr, &otx_ctrl, THROTNUMERf, 1); 1242 } 1243 else 1244 #endif 1245 { 1246 soc_reg64_field32_set(unit, MAC_TXCTRLr, &otx_ctrl, THROTNUMf, 1); 1247 } 1248 } 1249 1250 soc_reg64_field32_set(unit, MAC_TXCTRLr, &otx_ctrl, AVGIPGf, 1251 ipg & 0x1f); 1252 if (COMPILER_64_NE(tx_ctrl, otx_ctrl)) { 1253 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, otx_ctrl)); 1254 } 1255 break; 1256 } 1257 1258 return SOC_E_NONE; 1259 } 1260 1261 STATIC int 1262 _gxmac_trimac_init(int unit, soc_port_t port) 1263 { 1264 uint32 gmacc0, gmacc1, gmacc2, val32, pctrl; 1265 1266 /* 1267 * Perform length check on Ethernet frames and do not allow huge frames 1268 */ 1269 SOC_IF_ERROR_RETURN(READ_FE_MAC2r(unit, port, &val32)); 1270 soc_reg_field_set(unit, FE_MAC2r, &val32, FULL_DUPf, 1); 1271 soc_reg_field_set(unit, FE_MAC2r, &val32, EXC_DEFf, 1); 1272 soc_reg_field_set(unit, FE_MAC2r, &val32, LG_CHKf, 0); 1273 soc_reg_field_set(unit, FE_MAC2r, &val32, HUGE_FRf, 0); 1274 soc_reg_field_set(unit, FE_MAC2r, &val32, DEL_CRCf, 0); 1275 soc_reg_field_set(unit, FE_MAC2r, &val32, CRC_ENf, 0); 1276 soc_reg_field_set(unit, FE_MAC2r, &val32, PAD_ENf, 0); 1277 soc_reg_field_set(unit, FE_MAC2r, &val32, VLAN_PADf, 0); 1278 soc_reg_field_set(unit, FE_MAC2r, &val32, AUTO_PADf, 0); 1279 soc_reg_field_set(unit, FE_MAC2r, &val32, PURE_PADf, 0); 1280 soc_reg_field_set(unit, FE_MAC2r, &val32, LONG_PREf, 0); 1281 soc_reg_field_set(unit, FE_MAC2r, &val32, NO_BOFFf, 0); 1282 soc_reg_field_set(unit, FE_MAC2r, &val32, BP_NO_BOFFf, 0); 1283 SOC_IF_ERROR_RETURN(WRITE_FE_MAC2r(unit, port, val32)); 1284 1285 SOC_IF_ERROR_RETURN(READ_FE_CLRTr(unit, port, &val32)); 1286 soc_reg_field_set(unit, FE_CLRTr, &val32, COL_WINf, 0x37); 1287 soc_reg_field_set(unit, FE_CLRTr, &val32, RETRYf, 0xf); 1288 SOC_IF_ERROR_RETURN(WRITE_FE_CLRTr(unit, port, val32)); 1289 1290 /* Set receive IPG for FE MAC */ 1291 val32 = 0; 1292 soc_reg_field_set(unit, FE_IPGRr, &val32, IPGR1f, 0x6); 1293 soc_reg_field_set(unit, FE_IPGRr, &val32, IPGR2f, 0xf); 1294 SOC_IF_ERROR_RETURN(WRITE_FE_IPGRr(unit, port, val32)); 1295 1296 /* Update transmit IPG for FE MAC */ 1297 val32 = 0; 1298 soc_reg_field_set(unit, FE_IPGTr, &val32, IPGTf, 0xb); 1299 SOC_IF_ERROR_RETURN(WRITE_FE_IPGTr(unit, port, val32)); 1300 1301 SOC_IF_ERROR_RETURN(READ_FE_SUPPr(unit, port, &val32)); 1302 soc_reg_field_set(unit, FE_SUPPr, &val32, SPEEDf, 1); 1303 soc_reg_field_set(unit, FE_SUPPr, &val32, BIT_MODEf, 0); 1304 SOC_IF_ERROR_RETURN(WRITE_FE_SUPPr(unit, port, val32)); 1305 1306 SOC_IF_ERROR_RETURN(READ_FE_TESTr(unit, port, &val32)); 1307 soc_reg_field_set(unit, FE_TESTr, &val32, SHORT_QNTAf, 0); 1308 soc_reg_field_set(unit, FE_TESTr, &val32, TEST_PAUSEf, 0); 1309 soc_reg_field_set(unit, FE_TESTr, &val32, TEST_BACKf, 0); 1310 SOC_IF_ERROR_RETURN(WRITE_FE_TESTr(unit, port, val32)); 1311 1312 SOC_IF_ERROR_RETURN(READ_FE_MAC1r(unit, port, &val32)); 1313 soc_reg_field_set(unit, FE_MAC1r, &val32, LBACKf, 0); 1314 soc_reg_field_set(unit, FE_MAC1r, &val32, RX_ENf, 0); 1315 SOC_IF_ERROR_RETURN(WRITE_FE_MAC1r(unit, port, val32)); 1316 1317 /* Clear station address */ 1318 val32 = 0; 1319 SOC_IF_ERROR_RETURN(WRITE_ESA0r(unit, port, val32)); 1320 SOC_IF_ERROR_RETURN(WRITE_ESA1r(unit, port, val32)); 1321 SOC_IF_ERROR_RETURN(WRITE_ESA2r(unit, port, val32)); 1322 1323 /* NOTE : Allow dribble packets? */ 1324 1325 /* Initialize 1000 Mbps MAC */ 1326 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 1327 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 1328 SOC_IF_ERROR_RETURN(READ_GMACC2r(unit, port, &gmacc2)); 1329 1330 soc_reg_field_set(unit, GMACC0r, &gmacc0, SRSTf, 0); 1331 soc_reg_field_set(unit, GMACC0r, &gmacc0, L10Bf, 0); 1332 soc_reg_field_set(unit, GMACC0r, &gmacc0, L32Bf, 0); 1333 soc_reg_field_set(unit, GMACC0r, &gmacc0, TMDSf, 0); 1334 1335 soc_reg_field_set(unit, GMACC1r, &gmacc1, FULLDf, 1); /* arbitrary */ 1336 if (IS_ST_PORT(unit, port)) { 1337 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCTXf, 0); /* Flow ctl */ 1338 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCRXf, 0); /* Flow ctl */ 1339 } else { 1340 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCTXf, 1); /* Flow ctl */ 1341 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCRXf, 1); /* Flow ctl */ 1342 } 1343 soc_reg_field_set(unit, GMACC1r, &gmacc1, LONGPf, 1); 1344 soc_reg_field_set(unit, GMACC1r, &gmacc1, MIFGf, 2); 1345 soc_reg_field_set(unit, GMACC1r, &gmacc1, GLVRf, 1); 1346 soc_reg_field_set(unit, GMACC1r, &gmacc1, TXEN0f, 1); 1347 soc_reg_field_set(unit, GMACC1r, &gmacc1, RXEN0f, 0); 1348 soc_reg_field_set(unit, GMACC1r, &gmacc1, JUMBOf, 1); /* HUGEN=0 */ 1349 1350 soc_reg_field_set(unit, GMACC2r, &gmacc2, IPGTf, 0xc); 1351 1352 SOC_IF_ERROR_RETURN(WRITE_GMACC2r(unit, port, gmacc2)); 1353 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1)); 1354 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, gmacc0)); 1355 1356 pctrl = 0; 1357 soc_reg_field_set(unit, PAUSE_CONTROLr, &pctrl, ENABLEf, 1); 1358 /* Max out the pause duration; "resume" pause frame will end pause */ 1359 soc_reg_field_set(unit, PAUSE_CONTROLr, &pctrl, VALUEf, 1360 (1 << soc_reg_field_length(unit, 1361 PAUSE_CONTROLr, 1362 VALUEf)) - 1); 1363 SOC_IF_ERROR_RETURN(WRITE_PAUSE_CONTROLr(unit, port, pctrl)); 1364 1365 val32 = 0; 1366 SOC_IF_ERROR_RETURN(WRITE_TEST2r(unit, port, val32)); 1367 1368 1369 /* Clear station address */ 1370 val32 = 0; 1371 SOC_IF_ERROR_RETURN(WRITE_GSA0r(unit, port, val32)); 1372 SOC_IF_ERROR_RETURN(WRITE_GSA1r(unit, port, val32)); 1373 1374 /* Set egress enable */ 1375 SOC_IF_ERROR_RETURN(READ_EGR_ENABLEr(unit, port, &val32)); 1376 soc_reg_field_set(unit, EGR_ENABLEr, &val32, PRT_ENABLEf, 1); 1377 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, val32)); 1378 1379 /* Update IPG for GE MAC */ 1380 SOC_IF_ERROR_RETURN(gxmac_ipg_update(unit, port)); 1381 1382 return SOC_E_NONE; 1383 } 1384 1385 /* 1386 * Function: 1387 * gxmac_init 1388 * Purpose: 1389 * Initialize GMAC / Unicore MAC into a known good state. 1390 * Parameters: 1391 * unit - XGS unit #. 1392 * port - Port number on unit. 1393 * Returns: 1394 * SOC_E_XXX 1395 * Notes: 1396 */ 1397 STATIC int 1398 gxmac_init(int unit, soc_port_t port) 1399 { 1400 uint64 rx_ctrl, tx_ctrl, mac_ctrl; 1401 int encap; 1402 1403 LOG_VERBOSE(BSL_LS_SOC_10G, 1404 (BSL_META_U(unit, 1405 "gxmac_init: unit %d port %s\n"), 1406 unit, SOC_PORT_NAME(unit, port))); 1407 1408 SOC_IF_ERROR_RETURN(_gxmac_trimac_init(unit, port)); 1409 1410 /* 1411 * Initialize BigMAC 1412 */ 1413 1414 /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */ 1415 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &rx_ctrl)); 1416 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tx_ctrl)); 1417 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &mac_ctrl)); 1418 1419 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, RXENf, 0); 1420 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, TXENf, 0); 1421 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, RMTLOOPf, 0); 1422 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, LCLLOOPf, 0); 1423 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, PAUSEENf, 0); 1424 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, RXPAUSENf, 0); 1425 1426 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, mac_ctrl)); 1427 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, tx_ctrl)); 1428 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, rx_ctrl)); 1429 1430 /* Re-read MAC_TXCTRL, since it gets affected by ipg_update() */ 1431 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tx_ctrl)); 1432 1433 /* Set jumbo max size for 10G and Higig by default */ 1434 if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port)) { 1435 SOC_IF_ERROR_RETURN(gxmac_frame_max_set(unit, port, JUMBO_MAXSZ)); 1436 } 1437 1438 /* Program MAC settings */ 1439 1440 /* Setup header mode */ 1441 encap = (IS_HG_PORT(unit, port)) ? SOC_ENCAP_HIGIG : SOC_ENCAP_IEEE; 1442 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, HDRMODEf, encap); 1443 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, HDRMODEf, encap); 1444 1445 /* 1446 * Power-up defaults are CRC_APPEND for TX and STRIPCRC for RX. 1447 * Change to CRC_KEEP for Hercules, CRC_REGEN for other XGS, 1448 * and turn off STRIPCRC to be compatible with other BCM56xx. 1449 */ 1450 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, STRIPCRCf, 0); 1451 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, CRC_MODEf, 1452 GXMAC_CRC_REGEN); 1453 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, tx_ctrl)); 1454 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, rx_ctrl)); 1455 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1456 if (SOC_IS_XGS3_SWITCH(unit)) { 1457 int wan_mode = soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE); 1458 if (wan_mode) { 1459 /* Max speed for WAN mode is 9.294Gbps. 1460 * This setting gives 10Gbps * (13/14) or 9.286 Gbps */ 1461 SOC_IF_ERROR_RETURN 1462 (gxmac_control_set(unit, port, 1463 SOC_MAC_CONTROL_FRAME_SPACING_STRETCH, 13)); 1464 } 1465 } 1466 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1467 /* Update IPG separately */ 1468 SOC_IF_ERROR_RETURN(gxmac_ipg_update(unit, port)); 1469 1470 /* 1471 * Note that we leave Rx and Tx in the disabled state. 1472 * Rx and Tx are enabled for the appropriate MAC (BigMAC/TriMAc) 1473 * in gxmac_enable_set. 1474 */ 1475 1476 return SOC_E_NONE; 1477 } 1478 1479 /* 1480 * Function: 1481 * gxmac_enable_set 1482 * Purpose: 1483 * Enable or disable MAC 1484 * Parameters: 1485 * unit - XGS unit #. 1486 * port - Port number on unit. 1487 * enable - TRUE to enable, FALSE to disable 1488 * Returns: 1489 * SOC_E_XXX 1490 */ 1491 STATIC int 1492 gxmac_enable_set(int unit, soc_port_t port, int enable) 1493 { 1494 uint32 val, val2, drain_cells; 1495 pbmp_t mask; 1496 int cur_speed; 1497 soc_mac_mode_t mode; 1498 int drain_usec, loopback = -1; 1499 soc_timeout_t to; 1500 int rv = SOC_E_NONE; 1501 1502 /* Ensure we match the register field size */ 1503 if (enable) { 1504 enable = 1; 1505 } 1506 1507 /* Select appropriate MAC */ 1508 SOC_IF_ERROR_RETURN(soc_unicore_speed_get(unit, port, &cur_speed, NULL)); 1509 if (cur_speed > 2500 || IS_HG_PORT(unit, port)) { 1510 mode = SOC_MAC_MODE_10000; 1511 } else if (cur_speed >= 1000) { 1512 mode = SOC_MAC_MODE_1000_T; 1513 } else if (cur_speed >= 100) { 1514 mode = SOC_MAC_MODE_10_100; 1515 } else { 1516 mode = SOC_MAC_MODE_10; 1517 } 1518 1519 /* 1520 * Use EPC_LINK to control other ports sending to this port. This 1521 * blocking is independent and in addition to what Linkscan does. 1522 */ 1523 soc_link_mask2_get(unit, &mask); 1524 if (enable) { 1525 SOC_PBMP_PORT_ADD(mask, port); 1526 /* Postpone write until MAC is enabled */ 1527 } else { 1528 SOC_PBMP_PORT_REMOVE(mask, port); 1529 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 1530 } 1531 1532 if (!(SOC_IS_RELOADING(unit))) 1533 { 1534 /* 1535 * Drain all buffers and FIFOs if we are disabled 1536 */ 1537 if (!enable) { 1538 /* Start flushing BigMAc and TriMAC */ 1539 SOC_IF_ERROR_RETURN(WRITE_XP_EGR_PKT_DROP_CTLr(unit, port, 1)); 1540 SOC_IF_ERROR_RETURN(WRITE_GE_EGR_PKT_DROP_CTLr(unit, port, 1)); 1541 1542 /* Do not drain forever in case of problems */ 1543 drain_usec = soc_property_get(unit, spn_LCCDRAIN_TIMEOUT_USEC, 250000); 1544 soc_timeout_init(&to, drain_usec, 0); 1545 1546 /* Drain MMU and GXPORT in one go */ 1547 drain_cells = 0xffffffff; 1548 do { 1549 if (SOC_REG_IS_VALID(unit, OP_PORT_TOTAL_COUNTr)) { 1550 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNTr(unit, port, &val)); 1551 } else { 1552 SOC_IF_ERROR_RETURN(READ_OP_PORT_TOTAL_COUNT_CELLr(unit, port, &val)); 1553 } 1554 SOC_IF_ERROR_RETURN(READ_XP_XBODE_CELL_CNTr(unit, port, &val2)); 1555 val += val2; 1556 SOC_IF_ERROR_RETURN(READ_GE_GBODE_CELL_CNTr(unit, port, &val2)); 1557 val += val2; 1558 /* Gig MAC in pause state needs loopback mode to clear xoff */ 1559 if (drain_cells == val && loopback < 0 && 1560 mode == SOC_MAC_MODE_1000_T) { 1561 if (gxmac_loopback_get(unit, port, &loopback) < 0) { 1562 loopback = -1; 1563 } else { 1564 gxmac_loopback_set(unit, port, 1); 1565 } 1566 } 1567 /* Check for progress */ 1568 if (val < drain_cells) { 1569 soc_timeout_init(&to, drain_usec, 0); 1570 } 1571 drain_cells = val; 1572 } 1573 while (drain_cells && !soc_timeout_check(&to)); 1574 1575 /* Stop flushing */ 1576 SOC_IF_ERROR_RETURN(WRITE_XP_EGR_PKT_DROP_CTLr(unit, port, 0)); 1577 SOC_IF_ERROR_RETURN(WRITE_GE_EGR_PKT_DROP_CTLr(unit, port, 0)); 1578 1579 /* Restore loopback setting if changed */ 1580 if (loopback >= 0) { 1581 SOC_IF_ERROR_RETURN 1582 (gxmac_loopback_set(unit, port, loopback)); 1583 } 1584 1585 /* Check for drain error */ 1586 if (drain_cells) { 1587 LOG_ERROR(BSL_LS_SOC_COMMON, 1588 (BSL_META_U(unit, 1589 "ERROR: port %d:%s: " 1590 "timeout draining packets (%d cells remain)\n"), 1591 unit, SOC_PORT_NAME(unit, port), drain_cells)); 1592 /* Indicate error, but continue to MAC disable below */ 1593 rv = SOC_E_INTERNAL; 1594 } 1595 } 1596 } 1597 1598 /* Set new MAC mode (or disable MACs) */ 1599 SOC_IF_ERROR_RETURN(soc_unicore_mac_mode_set(unit, port, mode, enable)); 1600 1601 if (enable) { 1602 /* Set EPC_LINK */ 1603 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 1604 } 1605 1606 return rv; 1607 } 1608 1609 /* 1610 * Function: 1611 * gxmac_enable_get 1612 * Purpose: 1613 * Get MAC enable state 1614 * Parameters: 1615 * unit - XGS unit #. 1616 * port - Port number on unit. 1617 * enable - (OUT) TRUE if enabled, FALSE if disabled 1618 * Returns: 1619 * SOC_E_XXX 1620 */ 1621 STATIC int 1622 gxmac_enable_get(int unit, soc_port_t port, int *enable) 1623 { 1624 uint32 fe_mac1, gmacc1; 1625 uint64 ctrl; 1626 1627 /* Instead of checking the current mode we read from all MACs */ 1628 1629 /* TriMAC */ 1630 SOC_IF_ERROR_RETURN(READ_FE_MAC1r(unit, port, &fe_mac1)); 1631 *enable = soc_reg_field_get(unit, FE_MAC1r, fe_mac1, RX_ENf); 1632 1633 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 1634 *enable |= soc_reg_field_get(unit, GMACC1r, gmacc1, RXEN0f); 1635 1636 /* BigMAC */ 1637 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 1638 *enable |= soc_reg64_field32_get(unit, MAC_CTRLr, ctrl, RXENf); 1639 1640 LOG_VERBOSE(BSL_LS_SOC_10G, 1641 (BSL_META_U(unit, 1642 "gxmac_enable_get:u=%d port=%d enable=%c\n"), 1643 unit, port, *enable ? 'T' : 'F')); 1644 1645 return SOC_E_NONE; 1646 } 1647 1648 /* 1649 * Function: 1650 * gxmac_duplex_set 1651 * Purpose: 1652 * Set GXMAC in the specified duplex mode. 1653 * Parameters: 1654 * unit - XGS unit #. 1655 * port - XGS port # on unit. 1656 * duplex - Boolean: true --> full duplex, false --> half duplex. 1657 * Returns: 1658 * SOC_E_XXX 1659 * Notes: 1660 */ 1661 STATIC int 1662 gxmac_duplex_set(int unit, soc_port_t port, int duplex) 1663 { 1664 /* Always full duplex */ 1665 COMPILER_REFERENCE(unit); 1666 COMPILER_REFERENCE(port); 1667 COMPILER_REFERENCE(duplex); 1668 1669 LOG_VERBOSE(BSL_LS_SOC_10G, 1670 (BSL_META_U(unit, 1671 "gxmac_duplex_set: unit %d port %s %s duplex\n"), 1672 unit, SOC_PORT_NAME(unit, port), 1673 duplex ? "FULL" : "HALF")); 1674 1675 if (IS_GE_PORT(unit, port)) { 1676 int cur_speed; 1677 1678 SOC_IF_ERROR_RETURN 1679 (soc_unicore_speed_get(unit, port, &cur_speed, NULL)); 1680 1681 /* Do not support half duplex for 1Gbps speed */ 1682 if (cur_speed <= 100) { 1683 uint32 fe_mac2, ofe_mac2; 1684 duplex = duplex ? 1 : 0; 1685 1686 SOC_IF_ERROR_RETURN(READ_FE_MAC2r(unit, port, &fe_mac2)); 1687 ofe_mac2 = fe_mac2; 1688 soc_reg_field_set(unit, FE_MAC2r, &fe_mac2, FULL_DUPf, duplex); 1689 if (fe_mac2 != ofe_mac2) { 1690 /* Set duplex for FE MAC */ 1691 SOC_IF_ERROR_RETURN(WRITE_FE_MAC2r(unit, port, fe_mac2)); 1692 1693 /* Set IPG to match new duplex */ 1694 SOC_IF_ERROR_RETURN(gxmac_ipg_update(unit, port)); 1695 1696 } 1697 } 1698 } 1699 return SOC_E_NONE; 1700 } 1701 1702 /* 1703 * Function: 1704 * gxmac_duplex_get 1705 * Purpose: 1706 * Get GXMAC duplex mode. 1707 * Parameters: 1708 * unit - XGS unit #. 1709 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 1710 * Returns: 1711 * SOC_E_XXX 1712 */ 1713 STATIC int 1714 gxmac_duplex_get(int unit, soc_port_t port, int *duplex) 1715 { 1716 COMPILER_REFERENCE(unit); 1717 COMPILER_REFERENCE(port); 1718 1719 *duplex = TRUE; /* HG and XE ports are always full duplex */ 1720 1721 if (IS_GE_PORT(unit, port)){ 1722 int cur_speed; 1723 1724 SOC_IF_ERROR_RETURN 1725 (soc_unicore_speed_get(unit, port, &cur_speed, NULL)); 1726 if (cur_speed <= 100) { 1727 uint32 fe_mac2; 1728 1729 SOC_IF_ERROR_RETURN(READ_FE_MAC2r(unit, port, &fe_mac2)); 1730 *duplex = soc_reg_field_get(unit, FE_MAC2r, fe_mac2, FULL_DUPf); 1731 } 1732 } 1733 LOG_VERBOSE(BSL_LS_SOC_10G, 1734 (BSL_META_U(unit, 1735 "gxmac_duplex_get: unit %d port %s %s duplex\n"), 1736 unit, SOC_PORT_NAME(unit, port), 1737 *duplex ? "FULL" : "HALF")); 1738 1739 return SOC_E_NONE; 1740 } 1741 1742 /* 1743 * Function: 1744 * gxmac_pause_set 1745 * Purpose: 1746 * Configure GXMAC to transmit/receive pause frames. 1747 * Parameters: 1748 * unit - XGS unit #. 1749 * port - XGS port # on unit. 1750 * pause_tx - Boolean: transmit pause or -1 (don't change) 1751 * pause_rx - Boolean: receive pause or -1 (don't change) 1752 * Returns: 1753 * SOC_E_XXX 1754 */ 1755 STATIC int 1756 gxmac_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 1757 { 1758 uint64 ctrl, octrl; 1759 uint32 gmacc1, ogmacc1; 1760 uint32 fe_mac1, ofe_mac1; 1761 1762 pause_tx = pause_tx ? 1 : 0; 1763 pause_rx = pause_rx ? 1 : 0; 1764 1765 /* TriMAC */ 1766 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 1767 ogmacc1 = gmacc1; 1768 SOC_IF_ERROR_RETURN(READ_FE_MAC1r(unit, port, &fe_mac1)); 1769 ofe_mac1 = fe_mac1; 1770 1771 if (pause_tx >= 0) { 1772 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCTXf, pause_tx); 1773 soc_reg_field_set(unit, FE_MAC1r, &fe_mac1, 1774 TX_PAUf, pause_tx); 1775 } 1776 if (pause_rx >= 0) { 1777 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCRXf, pause_rx); 1778 soc_reg_field_set(unit, FE_MAC1r, &fe_mac1, 1779 RX_PAUf, pause_rx); 1780 } 1781 1782 if (gmacc1 != ogmacc1) { 1783 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1)); 1784 } 1785 if (fe_mac1 != ofe_mac1) { 1786 SOC_IF_ERROR_RETURN(WRITE_FE_MAC1r(unit, port, fe_mac1)); 1787 } 1788 1789 /* BigMAC */ 1790 if (pause_tx >= 0) { 1791 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &ctrl)); 1792 octrl = ctrl; 1793 soc_reg64_field32_set(unit, MAC_TXCTRLr, &ctrl, PAUSEENf, 1794 pause_tx ? 1 : 0); 1795 if (COMPILER_64_NE(ctrl, octrl)) { 1796 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, ctrl)); 1797 } 1798 } 1799 if (pause_rx >= 0) { 1800 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &ctrl)); 1801 octrl = ctrl; 1802 soc_reg64_field32_set(unit, MAC_RXCTRLr, &ctrl, RXPAUSENf, 1803 pause_rx ? 1 : 0); 1804 if (COMPILER_64_NE(ctrl, octrl)) { 1805 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, ctrl)); 1806 } 1807 } 1808 1809 LOG_VERBOSE(BSL_LS_SOC_10G, 1810 (BSL_META_U(unit, 1811 "gxmac_pause_set: unit %d port %s RX=%s TX=%s\n"), 1812 unit, SOC_PORT_NAME(unit, port), 1813 pause_rx ? "on" : "off", 1814 pause_tx ? "on" : "off")); 1815 1816 return SOC_E_NONE; 1817 } 1818 1819 /* 1820 * Function: 1821 * gxmac_pause_get 1822 * Purpose: 1823 * Return the pause ability of GXMAC 1824 * Parameters: 1825 * unit - XGS unit #. 1826 * port - XGS port # on unit. 1827 * pause_tx - Boolean: transmit pause 1828 * pause_rx - Boolean: receive pause 1829 * pause_mac - MAC address used for pause transmission. 1830 * Returns: 1831 * SOC_E_XXX 1832 */ 1833 STATIC int 1834 gxmac_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 1835 { 1836 uint32 gmacc1; 1837 1838 /* Read TriMAC status only */ 1839 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 1840 *pause_tx = soc_reg_field_get(unit, GMACC1r, gmacc1, FCTXf); 1841 *pause_rx = soc_reg_field_get(unit, GMACC1r, gmacc1, FCRXf); 1842 1843 LOG_VERBOSE(BSL_LS_SOC_10G, 1844 (BSL_META_U(unit, 1845 "gxmac_pause_get: unit %d port %s RX=%s TX=%s\n"), 1846 unit, SOC_PORT_NAME(unit, port), 1847 *pause_rx ? "on" : "off", 1848 *pause_tx ? "on" : "off")); 1849 1850 return SOC_E_NONE; 1851 } 1852 1853 /* 1854 * Function: 1855 * gxmac_speed_set 1856 * Purpose: 1857 * Set BigMAC in the specified speed. 1858 * Parameters: 1859 * unit - XGS unit #. 1860 * port - XGS port # on unit. 1861 * speed - 1000, 2500, ... 13000. 1862 * Returns: 1863 * SOC_E_NONE 1864 */ 1865 STATIC int 1866 gxmac_speed_set(int unit, soc_port_t port, int speed) 1867 { 1868 soc_mac_mode_t mode; 1869 int enable; 1870 uint32 speed_sel, fe_supp; 1871 1872 /* Also set the Unicore speed here for MAC loopback support */ 1873 SOC_IF_ERROR_RETURN(soc_unicore_speed_set(unit, port, speed)); 1874 1875 /* Disable MACs before doing anything else */ 1876 SOC_IF_ERROR_RETURN(gxmac_enable_get(unit, port, &enable)); 1877 SOC_IF_ERROR_RETURN(gxmac_enable_set(unit, port, 0)); 1878 1879 speed_sel = 0; 1880 fe_supp = 0; 1881 if (speed > 2500) { 1882 mode = SOC_MAC_MODE_10000; 1883 } else if (speed >=1000) { 1884 speed_sel = 0; 1885 mode = SOC_MAC_MODE_1000_T; 1886 } else if (speed >=100) { 1887 fe_supp = 1; 1888 speed_sel = 1; 1889 mode = SOC_MAC_MODE_10_100; 1890 } else { 1891 fe_supp = 0; 1892 speed_sel = 2; 1893 mode = SOC_MAC_MODE_10; 1894 } 1895 1896 if (speed <= 1000) { 1897 SOC_IF_ERROR_RETURN 1898 (soc_reg_field32_modify(unit, GE_PORT_CONFIGr, port, 1899 SPEED_SELECTf, speed_sel)); 1900 1901 if (speed <= 100) { 1902 SOC_IF_ERROR_RETURN 1903 (soc_reg_field32_modify(unit, FE_SUPPr, port, SPEEDf, fe_supp)); 1904 } 1905 } 1906 1907 /* Select appropriate MAC */ 1908 SOC_IF_ERROR_RETURN(soc_unicore_mac_mode_set(unit, port, mode, enable)); 1909 1910 /* Update IPG for new speed */ 1911 SOC_IF_ERROR_RETURN(gxmac_ipg_update(unit, port)); 1912 1913 /* Re-enable MAC */ 1914 SOC_IF_ERROR_RETURN(gxmac_enable_set(unit, port, enable)); 1915 1916 LOG_VERBOSE(BSL_LS_SOC_10G, 1917 (BSL_META_U(unit, 1918 "gxmac_speed_set: unit %d port %s speed %dMb\n"), 1919 unit, SOC_PORT_NAME(unit, port), speed)); 1920 1921 return SOC_E_NONE; 1922 } 1923 1924 /* 1925 * Function: 1926 * gxmac_speed_get 1927 * Purpose: 1928 * Get GXMAC speed 1929 * Parameters: 1930 * unit - XGS unit #. 1931 * port - XGS port # on unit. 1932 * speed - (OUT) speed in Mbps 1933 * Returns: 1934 * SOC_E_XXX 1935 */ 1936 STATIC int 1937 gxmac_speed_get(int unit, soc_port_t port, int *speed) 1938 { 1939 int rv; 1940 1941 rv = soc_unicore_speed_get(unit, port, speed, NULL); 1942 1943 LOG_VERBOSE(BSL_LS_SOC_10G, 1944 (BSL_META_U(unit, 1945 "gxmac_speed_get: unit %d port %s speed %dMb\n"), 1946 unit, SOC_PORT_NAME(unit, port), *speed)); 1947 return rv; 1948 } 1949 1950 /* 1951 * Function: 1952 * gxmac_loopback_set 1953 * Purpose: 1954 * Set a GXMAC into/out-of loopback mode 1955 * Parameters: 1956 * unit - XGS unit #. 1957 * port - XGS unit # on unit. 1958 * loopback - Boolean: true -> loopback mode, false -> normal operation 1959 * Note: 1960 * On bigmac, when setting loopback, we enable the TX/RX function also. 1961 * Note that to test the PHY, we use the remote loopback facility. 1962 * Returns: 1963 * SOC_E_XXX 1964 */ 1965 STATIC int 1966 gxmac_loopback_set(int unit, soc_port_t port, int lb) 1967 { 1968 uint64 ctrl, octrl; 1969 uint32 gmacc0, ogmacc0; 1970 uint32 fe_mac1, ofe_mac1; 1971 1972 LOG_VERBOSE(BSL_LS_SOC_10G, 1973 (BSL_META_U(unit, 1974 "gxmac_loopback_set: unit %d port %s %s loopback\n"), 1975 unit, SOC_PORT_NAME(unit, port), 1976 lb ? "local" : "no")); 1977 1978 lb = lb ? 1 : 0; 1979 1980 /* TriMAC */ 1981 SOC_IF_ERROR_RETURN(READ_FE_MAC1r(unit, port, &fe_mac1)); 1982 ofe_mac1 = fe_mac1; 1983 soc_reg_field_set(unit, FE_MAC1r, &fe_mac1, LBACKf, lb); 1984 if (fe_mac1 != ofe_mac1) { 1985 SOC_IF_ERROR_RETURN(WRITE_FE_MAC1r(unit, port, fe_mac1)); 1986 } 1987 1988 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 1989 ogmacc0 = gmacc0; 1990 soc_reg_field_set(unit, GMACC0r, &gmacc0, L32Bf, lb); 1991 if (gmacc0 != ogmacc0) { 1992 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, gmacc0)); 1993 } 1994 1995 /* BigMAC */ 1996 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 1997 octrl = ctrl; 1998 soc_reg64_field32_set(unit, MAC_CTRLr, &ctrl, LCLLOOPf, lb); 1999 if (COMPILER_64_NE(ctrl, octrl)) { 2000 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, ctrl)); 2001 } 2002 2003 #ifdef GXPORT_ISLOATE_IF_LOOPBACK 2004 /* Power lanes up/down */ 2005 soc_unicore_lane_power_set(unit, port, lb ? 0 : 0xf); 2006 #endif 2007 2008 return SOC_E_NONE; 2009 } 2010 2011 /* 2012 * Function: 2013 * gxmac_loopback_get 2014 * Purpose: 2015 * Get current GXMAC loopback mode setting. 2016 * Parameters: 2017 * unit - XGS unit #. 2018 * port - XGS port # on unit. 2019 * loopback - (OUT) Boolean: true = loopback, false = normal 2020 * Returns: 2021 * SOC_E_XXX 2022 */ 2023 STATIC int 2024 gxmac_loopback_get(int unit, soc_port_t port, int *lb) 2025 { 2026 uint64 ctrl; 2027 int local, remote; 2028 2029 /* Read BigMAC status only */ 2030 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 2031 remote = soc_reg64_field32_get(unit, MAC_CTRLr, ctrl, RMTLOOPf); 2032 local = soc_reg64_field32_get(unit, MAC_CTRLr, ctrl, LCLLOOPf); 2033 *lb = local | remote; 2034 2035 LOG_VERBOSE(BSL_LS_SOC_10G, 2036 (BSL_META_U(unit, 2037 "gxmac_loopback_get: unit %d port %s %s loopback\n"), 2038 unit, SOC_PORT_NAME(unit, port), 2039 *lb ? (remote ? "remote" : "local") : "no")); 2040 2041 return SOC_E_NONE; 2042 } 2043 2044 /* 2045 * Function: 2046 * gxmac_pause_addr_set 2047 * Purpose: 2048 * Configure PAUSE frame source address. 2049 * Parameters: 2050 * unit - XGS unit #. 2051 * port - XGS port # on unit. 2052 * pause_mac - (OUT) MAC address used for pause transmission. 2053 * Returns: 2054 * SOC_E_XXX 2055 */ 2056 STATIC int 2057 gxmac_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t mac) 2058 { 2059 uint32 w0, w1, w2; 2060 uint32 gsa0, gsa1; 2061 uint32 esa0, esa1, esa2; 2062 uint64 macsa; 2063 2064 w0 = mac[0] << 8 | mac[1]; 2065 w1 = mac[2] << 8 | mac[3]; 2066 w2 = mac[4] << 8 | mac[5]; 2067 2068 /* TriMAC */ 2069 esa0 = 0; 2070 esa1 = 0; 2071 esa2 = 0; 2072 2073 soc_reg_field_set(unit, ESA0r, &esa0, STAD0f, (mac[4] << 8) | mac[5]); 2074 soc_reg_field_set(unit, ESA1r, &esa1, STAD0f, (mac[2] << 8) | mac[3]); 2075 soc_reg_field_set(unit, ESA2r, &esa2, STAD0f, (mac[0] << 8) | mac[1]); 2076 2077 SOC_IF_ERROR_RETURN(FE_WRITE(ESA0r, GTH_ESA0r, unit, port, esa0)); 2078 SOC_IF_ERROR_RETURN(FE_WRITE(ESA1r, GTH_ESA1r, unit, port, esa1)); 2079 SOC_IF_ERROR_RETURN(FE_WRITE(ESA2r, GTH_ESA2r, unit, port, esa2)); 2080 2081 gsa0 = 0; 2082 gsa1 = 0; 2083 soc_reg_field_set(unit, GSA0r, &gsa0, STAD1f, (w0 << 16) | w1); 2084 soc_reg_field_set(unit, GSA1r, &gsa1, STAD2f, w2); 2085 2086 SOC_IF_ERROR_RETURN(WRITE_GSA0r(unit, port, gsa0)); 2087 SOC_IF_ERROR_RETURN(WRITE_GSA1r(unit, port, gsa1)); 2088 2089 /* BigMAC */ 2090 COMPILER_64_SET(macsa, w0, (w1 << 16) | w2); 2091 2092 SOC_IF_ERROR_RETURN(WRITE_MAC_TXMACSAr(unit, port, macsa)); 2093 SOC_IF_ERROR_RETURN(WRITE_MAC_RXMACSAr(unit, port, macsa)); 2094 2095 LOG_VERBOSE(BSL_LS_SOC_10G, 2096 (BSL_META_U(unit, 2097 "gxmac_pause_addr_set: unit %d port %s MAC=<" 2098 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 2099 unit, SOC_PORT_NAME(unit, port), 2100 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); 2101 return SOC_E_NONE; 2102 } 2103 2104 /* 2105 * Function: 2106 * gxmac_pause_addr_get 2107 * Purpose: 2108 * Retrieve PAUSE frame source address. 2109 * Parameters: 2110 * unit - XGS unit #. 2111 * port - XGS port # on unit. 2112 * pause_mac - (OUT) MAC address used for pause transmission. 2113 * Returns: 2114 * SOC_E_XXX 2115 * Notes; 2116 * We always write the same thing to TX & RX SA 2117 * so, we just return the contects on RXMACSA. 2118 */ 2119 STATIC int 2120 gxmac_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t mac) 2121 { 2122 uint64 macsa; 2123 uint32 msw, lsw; 2124 2125 /* Read BigMAC only */ 2126 SOC_IF_ERROR_RETURN(READ_MAC_RXMACSAr(unit, port, &macsa)); 2127 2128 COMPILER_64_TO_32_HI(msw, macsa); 2129 COMPILER_64_TO_32_LO(lsw, macsa); 2130 2131 mac[0] = (uint8)(msw >> 8); 2132 mac[1] = (uint8)(msw >> 0); 2133 mac[2] = (uint8)(lsw >> 24); 2134 mac[3] = (uint8)(lsw >> 16); 2135 mac[4] = (uint8)(lsw >> 8); 2136 mac[5] = (uint8)(lsw >> 0); 2137 2138 LOG_VERBOSE(BSL_LS_SOC_10G, 2139 (BSL_META_U(unit, 2140 "gxmac_pause_addr_get: unit %d port %s MAC=<" 2141 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 2142 unit, SOC_PORT_NAME(unit, port), 2143 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); 2144 2145 return SOC_E_NONE; 2146 } 2147 2148 /* 2149 * Function: 2150 * gxmac_interface_set 2151 * Purpose: 2152 * Set a GXMAC interface type 2153 * Parameters: 2154 * unit - XGS unit #. 2155 * port - XGS port # on unit. 2156 * pif - one of SOC_PORT_IF_* 2157 * Returns: 2158 * SOC_E_NONE 2159 * SOC_E_UNAVAIL - requested mode not supported. 2160 * Notes: 2161 */ 2162 STATIC int 2163 gxmac_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 2164 { 2165 uint32 gmacc0, gpcsc; 2166 uint32 ogmacc0, ogpcsc; 2167 2168 #ifdef BROADCOM_DEBUG 2169 LOG_VERBOSE(BSL_LS_SOC_10G, 2170 (BSL_META_U(unit, 2171 "gxmac_interface_set: unit %d port %s %s interface\n"), 2172 unit, SOC_PORT_NAME(unit, port), gxmac_port_if_names[pif])); 2173 #endif 2174 2175 if (pif == SOC_PORT_IF_XGMII) { 2176 return SOC_E_NONE; 2177 } 2178 2179 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 2180 SOC_IF_ERROR_RETURN(READ_GPCSCr(unit, port, &gpcsc)); 2181 ogmacc0 = gmacc0; 2182 ogpcsc = gpcsc; 2183 2184 switch (pif) { 2185 case SOC_PORT_IF_MII: 2186 case SOC_PORT_IF_GMII: 2187 case SOC_PORT_IF_SGMII: 2188 soc_reg_field_set(unit, GMACC0r, &gmacc0, TMDSf, 1); /* GMII */ 2189 soc_reg_field_set(unit, GPCSCr, &gpcsc, RCSELf, 1); /* 125 MHz */ 2190 break; 2191 case SOC_PORT_IF_TBI: 2192 soc_reg_field_set(unit, GMACC0r, &gmacc0, TMDSf, 0); /* TBI */ 2193 soc_reg_field_set(unit, GPCSCr, &gpcsc, RCSELf, 0); /* 62.5 MHz */ 2194 break; 2195 default: 2196 return SOC_E_UNAVAIL; 2197 } 2198 2199 if (gpcsc != ogpcsc) { 2200 SOC_IF_ERROR_RETURN(WRITE_GPCSCr(unit, port, gpcsc)); 2201 } 2202 if (gmacc0 != ogmacc0) { 2203 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, gmacc0)); 2204 } 2205 2206 return SOC_E_NONE; 2207 } 2208 2209 2210 /* 2211 * Function: 2212 * gxmac_interface_get 2213 * Purpose: 2214 * Retrieve GXMAC interface type 2215 * Parameters: 2216 * unit - XGS unit #. 2217 * port - XGS port # on unit. 2218 * pif - (OUT) one of SOC_PORT_IF_* 2219 * Returns: 2220 * SOC_E_NONE 2221 */ 2222 STATIC int 2223 gxmac_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 2224 { 2225 uint32 gmacc0; 2226 soc_mac_mode_t mode; 2227 2228 SOC_IF_ERROR_RETURN(soc_unicore_mac_mode_get(unit, port, &mode)); 2229 2230 if (mode == SOC_MAC_MODE_1000_T) { 2231 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 2232 2233 *pif = (soc_reg_field_get(unit, GMACC0r, gmacc0, TMDSf) ? 2234 SOC_PORT_IF_GMII : 2235 SOC_PORT_IF_TBI); 2236 } else { 2237 *pif = SOC_PORT_IF_MII; 2238 } 2239 2240 2241 #ifdef BROADCOM_DEBUG 2242 LOG_VERBOSE(BSL_LS_SOC_10G, 2243 (BSL_META_U(unit, 2244 "gxmac_interface_get: unit %d port %s %s interface\n"), 2245 unit, SOC_PORT_NAME(unit, port), gxmac_port_if_names[*pif])); 2246 #endif 2247 2248 return SOC_E_NONE; 2249 } 2250 2251 2252 /* 2253 * Function: 2254 * gxmac_frame_max_set 2255 * Description: 2256 * Set the maximum receive frame size for the port 2257 * Parameters: 2258 * unit - Device number 2259 * port - Port number 2260 * size - Maximum frame size in bytes 2261 * Return Value: 2262 * BCM_E_XXX 2263 */ 2264 STATIC int 2265 gxmac_frame_max_set(int unit, soc_port_t port, int size) 2266 { 2267 uint64 val64; 2268 uint32 val32; 2269 2270 if (!IS_ST_PORT(unit, port)) { 2271 /* Account for vlan tagged packets */ 2272 COMPILER_64_SET(val64, 0, size + 4); 2273 } else { 2274 COMPILER_64_SET(val64, 0, size); 2275 } 2276 2277 /* BigMAC */ 2278 SOC_IF_ERROR_RETURN(WRITE_MAC_TXMAXSZr(unit, port, val64)); 2279 SOC_IF_ERROR_RETURN(WRITE_MAC_RXMAXSZr(unit, port, val64)); 2280 2281 /* To be neutral to the above change */ 2282 val32 = size; 2283 2284 /* TriMAC */ 2285 SOC_IF_ERROR_RETURN(WRITE_MAXFRr(unit, port, val32)); 2286 2287 size += 1; /* XGS3 FE MAC_FR is one greater than MAX len */ 2288 val32 = size; 2289 return (WRITE_FE_MAXFr(unit, port, val32)); 2290 } 2291 2292 /* 2293 * Function: 2294 * gxmac_frame_max_get 2295 * Description: 2296 * Set the maximum receive frame size for the port 2297 * Parameters: 2298 * unit - Device number 2299 * port - Port number 2300 * size - Maximum frame size in bytes 2301 * Return Value: 2302 * BCM_E_XXX 2303 */ 2304 STATIC int 2305 gxmac_frame_max_get(int unit, soc_port_t port, int *size) 2306 { 2307 int rv; 2308 uint64 val64; 2309 2310 /* Note: MAC_RXMAXSZ returns 0 if the port is in GPORT mode. */ 2311 rv = READ_MAC_TXMAXSZr(unit, port, &val64); 2312 2313 if (rv == SOC_E_NONE) { 2314 COMPILER_64_TO_32_LO(*size, val64); 2315 if (!IS_ST_PORT(unit, port)) { 2316 /* For VLAN tagged packets */ 2317 *size -= 4; 2318 } 2319 } 2320 2321 return rv; 2322 } 2323 2324 /* 2325 * Function: 2326 * gxmac_ifg_set 2327 * Description: 2328 * Sets the new ifg (Inter-frame gap) value 2329 * Parameters: 2330 * unit - Device number 2331 * port - Port number 2332 * speed - the speed for which the IFG is being set 2333 * duplex - the duplex for which the IFG is being set 2334 * size - Maximum frame size in bytes 2335 * Return Value: 2336 * BCM_E_XXX 2337 * Notes: 2338 * The function makes sure the IFG value makes sense and updates the 2339 * IPG register in case the speed/duplex match the current settings 2340 */ 2341 STATIC int 2342 gxmac_ifg_set(int unit, soc_port_t port, int speed, soc_port_duplex_t duplex, 2343 int ifg) 2344 { 2345 int cur_duplex; 2346 int cur_speed; 2347 int ipg; 2348 int real_ifg; 2349 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 2350 int rv; 2351 2352 SOC_IF_ERROR_RETURN(gxmac_ifg_to_ipg(unit, port, speed, duplex, 2353 ifg, &ipg)); 2354 SOC_IF_ERROR_RETURN(gxmac_ipg_to_ifg(unit, port, speed, duplex, 2355 ipg, &real_ifg)); 2356 2357 if (duplex) { 2358 switch (speed) { 2359 case 10: 2360 si->fd_10 = real_ifg; 2361 break; 2362 case 100: 2363 si->fd_100 = real_ifg; 2364 break; 2365 case 1000: 2366 si->fd_1000 = real_ifg; 2367 break; 2368 case 2500: 2369 si->fd_2500 = real_ifg; 2370 break; 2371 case 10000: 2372 case 12000: 2373 case 12500: 2374 case 13000: 2375 si->fd_10000 = real_ifg; 2376 break; 2377 case 5000: 2378 case 6000: 2379 case 15000: 2380 case 16000: 2381 default: 2382 return SOC_E_PARAM; 2383 } 2384 } else { 2385 switch (speed) { 2386 case 10: 2387 si->hd_10 = real_ifg; 2388 break; 2389 case 100: 2390 si->hd_100 = real_ifg; 2391 break; 2392 default: 2393 return SOC_E_PARAM; 2394 } 2395 } 2396 2397 SOC_IF_ERROR_RETURN(gxmac_duplex_get(unit, port, &cur_duplex)); 2398 SOC_IF_ERROR_RETURN(gxmac_speed_get(unit, port, &cur_speed)); 2399 2400 if (cur_speed == speed && ((soc_port_duplex_t)cur_duplex == duplex)) { 2401 rv = gxmac_ipg_update(unit, port); 2402 } else { 2403 rv = SOC_E_NONE; 2404 } 2405 2406 return (rv); 2407 } 2408 2409 /* 2410 * Function: 2411 * gxmac_ifg_get 2412 * Description: 2413 * Sets the new ifg (Inter-frame gap) value 2414 * Parameters: 2415 * unit - Device number 2416 * port - Port number 2417 * speed - the speed for which the IFG is being set 2418 * duplex - the duplex for which the IFG is being set 2419 * size - Maximum frame size in bytes 2420 * Return Value: 2421 * BCM_E_XXX 2422 * Notes: 2423 * The function makes sure the IFG value makes sense and updates the 2424 * IPG register in case the speed/duplex match the current settings 2425 */ 2426 STATIC int 2427 gxmac_ifg_get(int unit, soc_port_t port, int speed, soc_port_duplex_t duplex, 2428 int *ifg) 2429 { 2430 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 2431 2432 if (duplex) { 2433 switch (speed) { 2434 case 10: 2435 *ifg = si->fd_10; 2436 break; 2437 case 100: 2438 *ifg = si->fd_100; 2439 break; 2440 case 1000: 2441 *ifg = si->fd_1000; 2442 break; 2443 case 2500: 2444 *ifg = si->fd_2500; 2445 break; 2446 case 10000: 2447 case 12000: 2448 case 12500: 2449 case 13000: 2450 *ifg = si->fd_10000; 2451 break; 2452 case 5000: 2453 case 6000: 2454 case 15000: 2455 case 16000: 2456 default: 2457 return SOC_E_PARAM; 2458 } 2459 } else { 2460 switch (speed) { 2461 case 10: 2462 *ifg = si->hd_10; 2463 break; 2464 case 100: 2465 *ifg = si->hd_100; 2466 break; 2467 default: 2468 return SOC_E_PARAM; 2469 } 2470 } 2471 2472 return SOC_E_NONE; 2473 } 2474 2475 /* 2476 * Function: 2477 * soc_gxmac_port_mode_update 2478 * Purpose: 2479 * Set the GXMAC port encapsulation mode. 2480 * Parameters: 2481 * unit - XGS unit #. 2482 * port - XGS port # on unit. 2483 * to_hg_port - (TRUE/FALSE) 2484 * Returns: 2485 * SOC_E_XXX 2486 */ 2487 STATIC int 2488 soc_gxmac_port_mode_update(int unit, soc_port_t port, int to_hg_port) 2489 { 2490 uint32 rval; 2491 uint64 val64; 2492 soc_pbmp_t ctr_pbmp; 2493 int rv = SOC_E_NONE; 2494 2495 /* Pause linkscan */ 2496 soc_linkscan_pause(unit); 2497 2498 /* Pause counter collection */ 2499 COUNTER_LOCK(unit); 2500 2501 soc_xport_type_update(unit, port, to_hg_port); 2502 2503 /* Now that we've patched, reinit the port */ 2504 rv = soc_unicore_reset(unit, port); 2505 2506 if (rv >= 0) { 2507 rv = gxmac_init(unit, port); 2508 } 2509 2510 if (rv >= 0) { 2511 rv = gxmac_enable_set( unit, port, 0); 2512 } 2513 2514 if (rv >= 0) { 2515 SOC_PBMP_CLEAR(ctr_pbmp); 2516 SOC_PBMP_PORT_SET(ctr_pbmp, port); 2517 COMPILER_64_SET(val64, 0, 0); 2518 rv = soc_counter_set_by_port(unit, ctr_pbmp, val64); 2519 } 2520 2521 COUNTER_UNLOCK(unit); 2522 soc_linkscan_continue(unit); 2523 2524 SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &rval)); 2525 if (to_hg_port) { 2526 soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 1); 2527 } else { 2528 soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 0); 2529 } 2530 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval)); 2531 2532 return rv; 2533 } 2534 2535 /* 2536 * Function: 2537 * gxmac_encap_set 2538 * Purpose: 2539 * Set the GXMAC port encapsulation mode. 2540 * Parameters: 2541 * unit - XGS unit #. 2542 * port - XGS port # on unit. 2543 * mode - (IN) encap bits (defined above) 2544 * Returns: 2545 * SOC_E_XXX 2546 */ 2547 STATIC int 2548 gxmac_encap_set(int unit, soc_port_t port, int mode) 2549 { 2550 uint64 rx_ctrl, tx_ctrl, orx, otx; 2551 int encap = 0; /* IEEE */ 2552 int higig2 = 0; 2553 int enable; 2554 2555 switch (mode) { 2556 case SOC_ENCAP_IEEE: 2557 break; 2558 case SOC_ENCAP_HIGIG2: 2559 higig2 = 1; 2560 /* Fall through */ 2561 case SOC_ENCAP_HIGIG: 2562 encap = 1; 2563 break; 2564 default: 2565 return SOC_E_PARAM; 2566 } 2567 2568 #ifdef BROADCOM_DEBUG 2569 LOG_VERBOSE(BSL_LS_SOC_10G, 2570 (BSL_META_U(unit, 2571 "gxmac_encap_set: unit %d port %s %s encapsulation\n"), 2572 unit, SOC_PORT_NAME(unit, port), gxmac_encap_mode[mode])); 2573 #endif 2574 2575 SOC_IF_ERROR_RETURN(gxmac_enable_get(unit, port, &enable)); 2576 2577 if (enable) { 2578 /* Turn off TX/RX enable */ 2579 SOC_IF_ERROR_RETURN(gxmac_enable_set(unit, port, 0)); 2580 } 2581 2582 if ((mode != SOC_ENCAP_IEEE) && IS_E_PORT(unit, port)) { 2583 /* XE -> HG */ 2584 SOC_IF_ERROR_RETURN(soc_gxmac_port_mode_update(unit, port, TRUE)); 2585 } else if ((mode == SOC_ENCAP_IEEE) && IS_ST_PORT(unit, port)) { 2586 /* HG -> XE */ 2587 SOC_IF_ERROR_RETURN(soc_gxmac_port_mode_update(unit, port, FALSE)); 2588 } 2589 2590 /* Read modify write the encapsulation mode */ 2591 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &rx_ctrl)); 2592 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tx_ctrl)); 2593 orx = rx_ctrl; 2594 otx = tx_ctrl; 2595 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, HDRMODEf, encap); 2596 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, HIGIG2MODEf, higig2); 2597 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, HDRMODEf, encap); 2598 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, HIGIG2MODEf, higig2); 2599 if (COMPILER_64_NE(tx_ctrl, otx)) { 2600 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, tx_ctrl)); 2601 } 2602 if (COMPILER_64_NE(rx_ctrl, orx)) { 2603 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, rx_ctrl)); 2604 } 2605 2606 if (enable) { 2607 /* Re-enable transmitter and receiver */ 2608 SOC_IF_ERROR_RETURN(gxmac_enable_set(unit, port, 1)); 2609 } 2610 2611 return SOC_E_NONE; 2612 } 2613 2614 /* 2615 * Function: 2616 * gxmac_encap_get 2617 * Purpose: 2618 * Get the GXMAC port encapsulation mode. 2619 * Parameters: 2620 * unit - XGS unit #. 2621 * port - XGS port # on unit. 2622 * mode - (INT) encap bits (defined above) 2623 * Returns: 2624 * SOC_E_XXX 2625 */ 2626 STATIC int 2627 gxmac_encap_get(int unit, soc_port_t port, int *mode) 2628 { 2629 uint64 rx_ctrl; 2630 2631 /* 2632 * TX/RX mode should always be programmed to the same 2633 * value (or all sorts of weird things will happen). 2634 * So, for purpose of S/W state, we only need to read 2635 * one or the other and return the state. 2636 * 2637 * WARNING: The following assumes BCM_PORT_ENCAP_xxx values equal 2638 * the hardware register field values. 2639 */ 2640 2641 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &rx_ctrl)); 2642 *mode = soc_reg64_field32_get(unit, MAC_RXCTRLr, rx_ctrl, HDRMODEf); 2643 2644 if (*mode == SOC_ENCAP_HIGIG && 2645 soc_reg64_field32_get(unit, MAC_RXCTRLr, rx_ctrl, HIGIG2MODEf)) { 2646 *mode = SOC_ENCAP_HIGIG2; 2647 } 2648 2649 #ifdef BROADCOM_DEBUG 2650 LOG_VERBOSE(BSL_LS_SOC_10G, 2651 (BSL_META_U(unit, 2652 "gxmac_encap_get: unit %d port %s %s encapsulation\n"), 2653 unit, SOC_PORT_NAME(unit, port), gxmac_encap_mode[*mode])); 2654 #endif 2655 2656 return SOC_E_NONE; 2657 } 2658 2659 /* 2660 * Function: 2661 * gxmac_ability_local_get 2662 * Purpose: 2663 * Return the abilities of GXMAC 2664 * Parameters: 2665 * unit - XGS unit #. 2666 * port - XGS port # on unit. 2667 * mode - (OUT) Supported operating modes as a mask of abilities. 2668 * Returns: 2669 * SOC_E_XXX 2670 */ 2671 STATIC int 2672 gxmac_ability_local_get(int unit, soc_port_t port, 2673 soc_port_ability_t *ability) 2674 { 2675 if (NULL == ability) { 2676 return (SOC_E_PARAM); 2677 } 2678 2679 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 2680 ability->speed_full_duplex = SOC_PA_ABILITY_NONE; 2681 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 2682 ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_GMII | 2683 SOC_PA_INTF_XGMII; 2684 ability->medium = SOC_PA_ABILITY_NONE; 2685 ability->loopback = SOC_PA_LB_MAC; 2686 ability->flags = SOC_PA_ABILITY_NONE; 2687 ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG | 2688 SOC_PA_ENCAP_HIGIG2; 2689 2690 if (IS_HG_PORT(unit, port)) { 2691 switch (SOC_INFO(unit).port_speed_max[port]) { 2692 case 13000: 2693 ability->speed_full_duplex |= SOC_PA_SPEED_13GB; 2694 /* fall through */ 2695 case 12000: 2696 ability->speed_full_duplex |= SOC_PA_SPEED_12GB; 2697 /* fall through */ 2698 default: 2699 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 2700 break; 2701 } 2702 2703 } else if (IS_XE_PORT(unit, port)) { 2704 ability->speed_full_duplex = SOC_PA_SPEED_1000MB | SOC_PA_SPEED_2500MB | 2705 SOC_PA_SPEED_10GB; 2706 } else { 2707 ability->speed_half_duplex = SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 2708 ability->speed_full_duplex = SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | 2709 SOC_PA_SPEED_1000MB | SOC_PA_SPEED_2500MB; 2710 } 2711 2712 return (SOC_E_NONE); 2713 } 2714 2715 /* 2716 * Function: 2717 * gxmac_frame_spacing_stretch_set 2718 * Purpose: 2719 * Set frame spacing stretch parameters. 2720 * Parameters: 2721 * unit - XGS unit #. 2722 * port - XGS port # on unit. 2723 * Returns: 2724 * SOC_E_XXX 2725 */ 2726 2727 STATIC int 2728 gxmac_frame_spacing_stretch_set(int unit, soc_port_t port, int value) 2729 { 2730 #if defined(BCM_XGS3_SWITCH_SUPPORT) 2731 if (SOC_IS_XGS3_SWITCH(unit)) { 2732 int field_width, max_value; 2733 uint64 reg_val; 2734 field_width = soc_reg_field_length(unit, MAC_TXCTRLr, THROTDENOMf); 2735 max_value = (1 << field_width) - 1; 2736 if ((value > max_value) || (value < 0)) { 2737 return SOC_E_PARAM; 2738 } 2739 2740 SOC_IF_ERROR_RETURN 2741 (READ_MAC_TXCTRLr(unit, port, ®_val)); 2742 soc_reg64_field32_set(unit, MAC_TXCTRLr, ®_val, 2743 THROTDENOMf, value); 2744 2745 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) 2746 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit)) { 2747 soc_reg64_field32_set(unit, MAC_TXCTRLr, ®_val, 2748 THROTNUMERf, value ? 1 : 0); 2749 } else 2750 #endif 2751 { 2752 soc_reg64_field32_set(unit, MAC_TXCTRLr, ®_val, 2753 THROTNUMf, value ? 1 : 0); 2754 } 2755 SOC_IF_ERROR_RETURN 2756 (WRITE_MAC_TXCTRLr(unit, port, reg_val)); 2757 2758 return SOC_E_NONE; 2759 } 2760 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 2761 2762 return SOC_E_UNAVAIL; 2763 } 2764 2765 /* 2766 * Function: 2767 * gxmac_control_set 2768 * Purpose: 2769 * To configure MAC control properties. 2770 * Parameters: 2771 * unit - XGS unit #. 2772 * port - XGS port # on unit. 2773 * type - MAC control property to set. 2774 * int - New setting for MAC control. 2775 * Returns: 2776 * SOC_E_XXX 2777 */ 2778 2779 STATIC int 2780 gxmac_control_set(int unit, soc_port_t port, 2781 soc_mac_control_t type, int value) 2782 { 2783 int rv; 2784 uint32 reg32, copy32; 2785 uint64 reg64, copy64; 2786 2787 LOG_VERBOSE(BSL_LS_SOC_10G, 2788 (BSL_META_U(unit, 2789 "gxmac_control_set: unit %d port %s: %d = %d\n"), 2790 unit, SOC_PORT_NAME(unit, port), 2791 type, value)); 2792 2793 if ((type < 0) || (type >= SOC_MAC_CONTROL_COUNT)) { 2794 return SOC_E_PARAM; 2795 } 2796 2797 rv = SOC_E_UNAVAIL; 2798 switch(type) { 2799 case SOC_MAC_CONTROL_RX_SET: 2800 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, ®32)); 2801 copy32 = reg32; 2802 soc_reg_field_set(unit, GMACC1r, ®32, RXEN0f, value ? 1 : 0); 2803 if (reg32 != copy32) { 2804 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, reg32)); 2805 } 2806 SOC_IF_ERROR_RETURN(READ_FE_MAC1r(unit, port, ®32)); 2807 copy32 = reg32; 2808 soc_reg_field_set(unit, FE_MAC1r, ®32, RX_ENf, value ? 1 : 0); 2809 if (reg32 != copy32) { 2810 SOC_IF_ERROR_RETURN(WRITE_FE_MAC1r(unit, port, reg32)); 2811 } 2812 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, ®64)); 2813 copy64 = reg64; 2814 soc_reg64_field32_set(unit, MAC_CTRLr, ®64, RXENf, value ? 1 : 0); 2815 if (COMPILER_64_NE(reg64, copy64)) { 2816 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, reg64)); 2817 } 2818 break; 2819 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 2820 rv = gxmac_frame_spacing_stretch_set(unit, port, value); 2821 break; 2822 default: 2823 rv = SOC_E_UNAVAIL; 2824 break; 2825 } 2826 2827 return rv; 2828 } 2829 2830 /* 2831 * Function: 2832 * gxmac_control_get 2833 * Purpose: 2834 * To get current MAC control setting. 2835 * Parameters: 2836 * unit - XGS unit #. 2837 * port - XGS port # on unit. 2838 * type - MAC control property to set. 2839 * int - New setting for MAC control. 2840 * Returns: 2841 * SOC_E_XXX 2842 */ 2843 2844 STATIC int 2845 gxmac_control_get(int unit, soc_port_t port, 2846 soc_mac_control_t type, int *value) 2847 { 2848 uint32 val; 2849 int rv; 2850 uint32 reg32; 2851 uint64 reg64; 2852 2853 if (NULL == value) { 2854 return SOC_E_PARAM; 2855 } 2856 2857 if ((type < 0) || (type >= SOC_MAC_CONTROL_COUNT)) { 2858 return SOC_E_PARAM; 2859 } 2860 2861 rv = SOC_E_UNAVAIL; 2862 switch(type) { 2863 case SOC_MAC_CONTROL_RX_SET: 2864 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, ®32)); 2865 val = soc_reg_field_get(unit, GMACC1r, reg32, RXEN0f); 2866 SOC_IF_ERROR_RETURN(READ_FE_MAC1r(unit, port, ®32)); 2867 val |= soc_reg_field_get(unit, FE_MAC1r, reg32, RX_ENf); 2868 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, ®64)); 2869 val |= soc_reg64_field32_get(unit, MAC_CTRLr, reg64, RXENf); 2870 *value = val ? 1 : 0; 2871 break; 2872 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 2873 if (SOC_REG_IS_VALID(unit, MAC_TXCTRLr)) { 2874 SOC_IF_ERROR_RETURN 2875 (READ_MAC_TXCTRLr(unit, port, ®64)); 2876 *value = soc_reg64_field32_get(unit, MAC_TXCTRLr, reg64, 2877 THROTDENOMf); 2878 rv = SOC_E_NONE; 2879 } 2880 break; 2881 default: 2882 rv = SOC_E_UNAVAIL; 2883 break; 2884 } 2885 2886 LOG_VERBOSE(BSL_LS_SOC_10G, 2887 (BSL_META_U(unit, 2888 "gxmac_control_get: unit %d port %s: %d = %d: rv = %d\n"), 2889 unit, SOC_PORT_NAME(unit, port), 2890 type, *value, rv)); 2891 2892 return rv; 2893 } 2894 /* Exported XGS MAC driver structure */ 2895 2896 mac_driver_t soc_mac_gx = { 2897 "12G/10G/2.5G/1G MAC Driver", /* drv_name */ 2898 gxmac_init, /* md_init */ 2899 gxmac_enable_set, /* md_enable_set */ 2900 gxmac_enable_get, /* md_enable_get */ 2901 gxmac_duplex_set, /* md_duplex_set */ 2902 gxmac_duplex_get, /* md_duplex_get */ 2903 gxmac_speed_set, /* md_speed_set */ 2904 gxmac_speed_get, /* md_speed_get */ 2905 gxmac_pause_set, /* md_pause_set */ 2906 gxmac_pause_get, /* md_pause_get */ 2907 gxmac_pause_addr_set, /* md_pause_addr_set */ 2908 gxmac_pause_addr_get, /* md_pause_addr_get */ 2909 gxmac_loopback_set, /* md_lb_set */ 2910 gxmac_loopback_get, /* md_lb_get */ 2911 gxmac_interface_set, /* md_interface_set */ 2912 gxmac_interface_get, /* md_interface_get */ 2913 NULL, /* md_ability_get - Deprecated */ 2914 gxmac_frame_max_set, /* md_frame_max_set */ 2915 gxmac_frame_max_get, /* md_frame_max_get */ 2916 gxmac_ifg_set, /* md_ifg_set */ 2917 gxmac_ifg_get, /* md_ifg_get */ 2918 gxmac_encap_set, /* md_encap_set */ 2919 gxmac_encap_get, /* md_encap_get */ 2920 gxmac_control_set, /* md_control_set */ 2921 gxmac_control_get, /* md_control_get */ 2922 gxmac_ability_local_get, /* md_ability_local_get */ 2923 NULL /* md_timesync_tx_info_get */ 2924 }; 2925 #endif /* BCM_GXPORT_SUPPORT */