xgxs16g1l.c (114554B)
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 * File: xgxs16g.c 8 * Purpose: Broadcom 1000 Mbps SerDes 9 * (XGXS-16G1L) 10 * 11 * supported speed modes in independent channel mode for these three devices. 12 * 13 * XGXS_16G XGXS_13G Quad SGMII 14 * CL37 lane0 only lane0 only lane0 only 15 * CL37 BAM no no no 16 * CL73 lane0 only all four lanes all four lanes 17 * CL73 BAM no no no 18 * Forced 2.5G yes yes yes 19 * Forced 1G yes yes yes 20 * 100FX no yes yes 21 * SGMII yes yes yes 22 * 23 * Each channel has to run the same rate. 24 * Invalid combination: 25 * lane0 1G and lane1 2.5G, lane2 SGMII and lane1 2.5G 26 * Valid combination: 27 * lane0 1G and lane1 SGMII, lane0 autoneg 1G and lane2 forced 1G. 28 */ 29 30 #include <sal/types.h> 31 32 #include <sal/types.h> 33 #include <sal/core/spl.h> 34 #include <shared/bsl.h> 35 #include <soc/drv.h> 36 #include <soc/debug.h> 37 #include <soc/error.h> 38 #include <soc/phyreg.h> 39 #include <soc/port_ability.h> 40 41 #include <soc/phy.h> 42 #include <soc/phy/phyctrl.h> 43 #include <soc/phy/drv.h> 44 45 #include "phydefs.h" /* Must include before other phy related includes */ 46 47 48 #if defined(INCLUDE_XGXS_16G) 49 #include "phyconfig.h" /* Must include before other phy related includes */ 50 #include "phyident.h" 51 #include "phyreg.h" 52 #include "phynull.h" 53 #include "xgxs.h" 54 #include "serdesid.h" 55 #include "xgxs16g.h" 56 57 #define PHY_XGXS16G_LANEPRBS_LANE_SHIFT 4 58 59 60 #define XGXS16G_PLL_WAIT 250000 61 62 STATIC int phy_xgxs16g1l_interface_get(int unit, soc_port_t port, 63 soc_port_if_t *pif); 64 STATIC int phy_xgxs16g1l_master_get(int unit, soc_port_t port, int *master); 65 STATIC int phy_xgxs16g1l_an_set(int unit, soc_port_t port, int an); 66 STATIC int phy_xgxs16g1l_an_get(int unit, soc_port_t port, 67 int *an, int *an_done); 68 STATIC int phy_xgxs16g1l_speed_get(int unit, soc_port_t port, int *speed); 69 STATIC int phy_xgxs16g1l_ability_advert_set(int unit, soc_port_t port, 70 soc_port_ability_t *ability); 71 STATIC int phy_xgxs16g1l_ability_advert_get(int unit, soc_port_t port, 72 soc_port_ability_t *ability); 73 STATIC int phy_xgxs16g1l_ability_local_get(int unit, soc_port_t port, 74 soc_port_ability_t *ability); 75 STATIC int phy_xgxs16g1l_medium_config_set(int unit, soc_port_t port, 76 soc_port_medium_t medium, soc_phy_config_t *cfg); 77 STATIC int phy_xgxs16g1l_medium_get(int unit, soc_port_t port, soc_port_medium_t *medium); 78 79 /* Notify event forward declaration */ 80 STATIC int 81 _phy_xgxs16g1l_notify_duplex(int unit, soc_port_t port, uint32 duplex); 82 STATIC int 83 _phy_xgxs16g1l_notify_speed(int unit, soc_port_t port, uint32 speed); 84 STATIC int 85 _phy_xgxs16g1l_notify_stop(int unit, soc_port_t port, uint32 flags); 86 STATIC int 87 _phy_xgxs16g1l_notify_resume(int unit, soc_port_t port, uint32 flags); 88 STATIC int 89 _phy_xgxs16g1l_notify_interface(int unit, soc_port_t port, uint32 intf); 90 STATIC int 91 _phy_xgxs16g1l_control_vco_disturbed_set(int unit, soc_port_t port); 92 STATIC int 93 _phy_xgxs16g1l_control_vco_disturbed_get(int unit, soc_port_t port, uint32 *value); 94 95 STATIC int 96 _phy_xgxs16g1l_pll_lock_wait(int unit, soc_port_t port) 97 { 98 uint16 data16; 99 phy_ctrl_t *pc; 100 soc_timeout_t to; 101 int rv; 102 103 pc = INT_PHY_SW_STATE(unit, port); 104 _phy_xgxs16g1l_control_vco_disturbed_set(unit, port); 105 soc_timeout_init(&to, XGXS16G_PLL_WAIT, 0); 106 while (!soc_timeout_check(&to)) { 107 rv = READ_XGXS16G_XGXSBLK0_XGXSSTATUSr(unit, pc, &data16); 108 if ((data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK) || 109 SOC_FAILURE(rv)) { 110 break; 111 } 112 } 113 if ((data16 & XGXSBLK0_XGXSSTATUS_TXPLL_LOCK_MASK) == 0) { 114 LOG_WARN(BSL_LS_SOC_PHY, 115 (BSL_META_U(unit, 116 "XGXS_16G : TXPLL did not lock: u=%d p=%d\n"), 117 unit, port)); 118 return (SOC_E_TIMEOUT); 119 } 120 return (SOC_E_NONE); 121 } 122 123 STATIC int 124 _phy_xgxs16g1l_lane_swap(int unit, soc_port_t port) 125 { 126 phy_ctrl_t *pc; 127 int i; 128 uint16 lane_map; 129 uint16 lane, hw_map, chk_map; 130 131 pc = INT_PHY_SW_STATE(unit, port); 132 133 /* Update RX lane map */ 134 135 if (soc_property_port_get_str(unit, port, spn_XGXS_RX_LANE_MAP)) { 136 lane_map = soc_property_port_get(unit, port, 137 spn_XGXS_RX_LANE_MAP, 0x0123) & 0xffff; 138 hw_map = 0; 139 chk_map = 0; 140 141 /* contruct lane swap map in register format */ 142 for (hw_map=0, i = 3; i >= 0; i--) { 143 lane = (lane_map >> (i * 4)) & 0xf; 144 hw_map |= lane << ((3 - i) * 2); 145 chk_map |= 1 << lane; 146 } 147 148 /* check if valid configuration */ 149 if (chk_map == 0xf) { 150 SOC_IF_ERROR_RETURN /* Enable RX Lane swap */ 151 (MODIFY_XGXS16G_XGXSBLK8_RXLNSWAP1r(unit, pc, 152 hw_map, 153 XGXSBLK2_RXLNSWAP_RX_LNSWAP_EN_MASK | 154 XGXSBLK8_RXLNSWAP1_RX0_LNSWAP_SEL_MASK | 155 XGXSBLK8_RXLNSWAP1_RX1_LNSWAP_SEL_MASK | 156 XGXSBLK8_RXLNSWAP1_RX2_LNSWAP_SEL_MASK | 157 XGXSBLK8_RXLNSWAP1_RX3_LNSWAP_SEL_MASK)); 158 } else { 159 LOG_WARN(BSL_LS_SOC_PHY, 160 (BSL_META_U(unit, 161 "unit %d port %s: Invalid RX lane map 0x%04x.\n"), 162 unit, SOC_PORT_NAME(unit, port), lane_map)); 163 } 164 } 165 166 /* Update TX lane map */ 167 if (soc_property_port_get_str(unit, port, spn_XGXS_TX_LANE_MAP)) { 168 lane_map = soc_property_port_get(unit, port, 169 spn_XGXS_TX_LANE_MAP, 0x0123) & 0xffff; 170 hw_map = 0; 171 chk_map = 0; 172 173 /* contruct lane swap map in register format */ 174 for (hw_map=0, i = 3; i >= 0; i--) { 175 lane = (lane_map >> (i * 4)) & 0xf; 176 hw_map |= lane << ((3 - i) * 2); 177 chk_map |= 1 << lane; 178 } 179 if (chk_map == 0xf) { 180 SOC_IF_ERROR_RETURN /* Enable TX Lane swap */ 181 (MODIFY_XGXS16G_XGXSBLK8_TXLNSWAP1r(unit, pc, 182 hw_map, 183 XGXSBLK8_TXLNSWAP1_TX3_LNSWAP_SEL_MASK | 184 XGXSBLK8_TXLNSWAP1_TX2_LNSWAP_SEL_MASK | 185 XGXSBLK8_TXLNSWAP1_TX1_LNSWAP_SEL_MASK | 186 XGXSBLK8_TXLNSWAP1_TX0_LNSWAP_SEL_MASK)); 187 } else { 188 LOG_WARN(BSL_LS_SOC_PHY, 189 (BSL_META_U(unit, 190 "unit %d port %s: Invalid TX lane map 0x%04x.\n"), 191 unit, SOC_PORT_NAME(unit, port), lane_map)); 192 } 193 } 194 return SOC_E_NONE; 195 } 196 197 STATIC int 198 _phy_xgxs16g1l_polarity_flip(int unit, soc_port_t port) 199 { 200 uint16 data16; 201 uint16 mask16; 202 phy_ctrl_t *pc; 203 uint32 phy_xaui_polarity_flip; 204 205 pc = INT_PHY_SW_STATE(unit, port); 206 207 if (soc_property_port_get_str(unit, port, spn_PHY_XAUI_TX_POLARITY_FLIP)) { 208 phy_xaui_polarity_flip = soc_property_port_get(unit, port, 209 spn_PHY_XAUI_TX_POLARITY_FLIP, 0); 210 /* Flip TX polarity */ 211 mask16 = TX0_TX_ACONTROL0_TXPOL_FLIP_MASK; 212 data16 = phy_xaui_polarity_flip? mask16:0; 213 LOG_INFO(BSL_LS_SOC_PHY, 214 (BSL_META_U(unit, 215 "unit %d port %s: TX Polarity swap 0x%04x.\n"), 216 unit, SOC_PORT_NAME(unit, port), data16)); 217 if (pc->lane_num == 0) { 218 SOC_IF_ERROR_RETURN 219 (MODIFY_XGXS16G_TX0_TX_ACONTROL0r(unit, pc, data16, mask16)); 220 } else if (pc->lane_num == 1) { 221 SOC_IF_ERROR_RETURN 222 (MODIFY_XGXS16G_TX1_TX_ACONTROL0r(unit, pc, data16, mask16)); 223 } else if (pc->lane_num == 2) { 224 SOC_IF_ERROR_RETURN 225 (MODIFY_XGXS16G_TX2_TX_ACONTROL0r(unit, pc, data16, mask16)); 226 } else { 227 SOC_IF_ERROR_RETURN 228 (MODIFY_XGXS16G_TX3_TX_ACONTROL0r(unit, pc, data16, mask16)); 229 } 230 } 231 232 if (soc_property_port_get_str(unit, port, spn_PHY_XAUI_RX_POLARITY_FLIP)) { 233 phy_xaui_polarity_flip = soc_property_port_get(unit, port, 234 spn_PHY_XAUI_RX_POLARITY_FLIP, 0); 235 /* Flip RX polarity. */ 236 /*XXX hardcoded for now */ 237 mask16 = 0xc; 238 data16 = phy_xaui_polarity_flip? mask16 :0; 239 LOG_INFO(BSL_LS_SOC_PHY, 240 (BSL_META_U(unit, 241 "unit %d port %s: RX Polarity swap 0x%04x.\n"), 242 unit, SOC_PORT_NAME(unit, port), data16)); 243 244 SOC_IF_ERROR_RETURN 245 (XGXS16G_REG_MODIFY(unit,pc,0x0, 0x80ba + (0x10 * pc->lane_num), 246 data16, mask16)); 247 } 248 return SOC_E_NONE; 249 } 250 251 /* 252 * Function: 253 * phy_xgxs16g1l_init 254 * Purpose: 255 * Initialize xgxs6 phys 256 * Parameters: 257 * unit - StrataSwitch unit #. 258 * port - StrataSwitch port #. 259 * Returns: 260 * SOC_E_NONE 261 */ 262 263 STATIC int 264 phy_xgxs16g1l_init(int unit, soc_port_t port) 265 { 266 uint16 data16; 267 uint16 mask16; 268 uint16 mode_1000x; 269 int preemph, idriver, pdriver; 270 phy_ctrl_t *pc; 271 soc_port_ability_t ability; 272 XGXS16G_DEV_DESC *pDesc; 273 soc_phy_info_t *pi; 274 int len; 275 int serdes_id0; 276 int asymmetric_speed_mode = 0; 277 uint16 rx_los = 0; 278 uint16 rx_los_invert = 0; 279 280 281 pc = INT_PHY_SW_STATE(unit, port); 282 pDesc = (XGXS16G_DEV_DESC *)(pc + 1); 283 284 asymmetric_speed_mode = soc_property_port_get(unit, port, spn_SERDES_ASYMMETRIC_SPEED_MODE, 0); 285 286 SOC_IF_ERROR_RETURN 287 (READ_XGXS16G_SERDESID_SERDESID0r(unit, pc, &pDesc->serdes_id0)); 288 serdes_id0 = pDesc->serdes_id0; 289 SOC_IF_ERROR_RETURN 290 (READ_XGXS16G_SERDESID_SERDESID2r(unit, pc, &pDesc->serdes_id2)); 291 292 /* compose device name/instance/lane information for display 293 * XGXS_16G device uses existing method 294 */ 295 if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)) { 296 if (XGXS16G_13G_ID(pc)) { 297 /* 298 * COVERITY 299 * 300 * Buffer will not happen as destination string is of length 30. 301 */ 302 /* coverity[secure_coding] */ 303 304 sal_strcpy(pDesc->name,"XGXS13G-"); 305 } else { 306 sal_strcpy(pDesc->name,"QS-"); 307 } 308 len = sal_strlen(pDesc->name); 309 /* add rev letter */ 310 pDesc->name[len++] = 'A' + ((serdes_id0 >> 311 SERDESID_SERDESID0_REV_LETTER_SHIFT) & 0x3); 312 /* add rev number */ 313 pDesc->name[len++] = '0' + ((serdes_id0 >> 314 SERDESID_SERDESID0_REV_NUMBER_SHIFT) & 0x7); 315 pDesc->name[len++] = '/'; 316 pDesc->name[len++] = (pc->chip_num/10)%10 + '0'; 317 pDesc->name[len++] = pc->chip_num%10 + '0'; 318 pDesc->name[len++] = '/'; 319 pDesc->name[len++] = pc->lane_num + '0'; 320 pDesc->name[len] = 0; /* string terminator */ 321 322 if (len > XGXS16G_LANE_NAME_LEN) { 323 LOG_ERROR(BSL_LS_SOC_PHY, 324 (BSL_META_U(unit, 325 "XGXS13G info string length %d exceeds max length 0x%x: u=%d p=%d\n"), 326 len,XGXS16G_LANE_NAME_LEN,unit, port)); 327 return SOC_E_MEMORY; 328 } 329 330 pi = &SOC_PHY_INFO(unit, port); 331 if (!PHY_EXTERNAL_MODE(unit, port)) { 332 pi->phy_name = pDesc->name; 333 } 334 335 } 336 337 /* Initialize software state */ 338 pc->fiber.autoneg_enable = TRUE; 339 340 if ((!PHY_FLAGS_TST(unit, port, PHY_FLAGS_INIT_DONE)) && 341 (pc->lane_num == 0)) { 342 343 /* Reset the core */ 344 345 /* Stop PLL Sequencer and configure the core into correct mode */ 346 data16 = (XGXSBLK0_XGXSCONTROL_MODE_10G_IndLane << 347 XGXSBLK0_XGXSCONTROL_MODE_10G_SHIFT) | 348 XGXSBLK0_XGXSCONTROL_HSTL_MASK | 349 XGXSBLK0_XGXSCONTROL_CDET_EN_MASK | 350 XGXSBLK0_XGXSCONTROL_EDEN_MASK | 351 XGXSBLK0_XGXSCONTROL_AFRST_EN_MASK | 352 XGXSBLK0_XGXSCONTROL_TXCKO_DIV_MASK; 353 SOC_IF_ERROR_RETURN 354 (WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, data16)); 355 356 /* Disable IEEE block select auto-detect. 357 * The driver will select desired block as necessary. 358 * By default, the driver keeps the XAUI block in 359 * IEEE address space. 360 */ 361 if (XGXS16G_2p5G_ID(pc)) { 362 data16 = 0; 363 } else { 364 data16 = XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK; 365 } 366 SOC_IF_ERROR_RETURN 367 (MODIFY_XGXS16G_XGXSBLK0_MISCCONTROL1r(unit, pc, 368 data16, 369 XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_AUTODET_MASK | 370 XGXSBLK0_MISCCONTROL1_IEEE_BLKSEL_VAL_MASK)); 371 372 if (XGXS16G_13G_ID(pc)) { 373 data16 = XGXSBLK0_MMDSELECT_MULTIPRTS_EN_MASK | 374 XGXSBLK0_MMDSELECT_MULTIMMDS_EN_MASK; 375 mask16 = data16; 376 #ifdef BCM_KATANA_SUPPORT 377 if (SOC_IS_KATANA(unit)) { 378 if ((25 == port) || (26 == port)) { 379 data16 &= ~XGXSBLK0_MMDSELECT_MULTIPRTS_EN_MASK; 380 } 381 } 382 #endif 383 SOC_IF_ERROR_RETURN 384 (MODIFY_XGXS16G_XGXSBLK0_MMDSELECTr(unit, pc, 385 data16, mask16)); 386 } 387 388 /* disable in-band MDIO. PHY-443 */ 389 SOC_IF_ERROR_RETURN 390 (XGXS16G_REG_MODIFY(unit, pc, 0x00, 0x8111, 1 << 3, 1 << 3)); 391 392 393 if (XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) { 394 395 /* FORCE ASYMMETRIC SPEED MODES. Refer sect 4.3.2 product brief. */ 396 397 /* 398 1. Force VCO at 3.125GHz by configuring 399 Misc1 register (0x8308) so that 400 Misc1[12] = 1'b1; 401 Misc[11:8] = 4'h1. 402 */ 403 SOC_IF_ERROR_RETURN 404 (MODIFY_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, 405 SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SEL_MASK 406 | (0x1 << SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SHIFT), 407 SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SEL_MASK 408 | SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_MASK)); 409 /* 410 2. Enable the asymmetric_enable 411 bit[BIT8] within the xgxsBlk8txLnSwap1 register (0x8169) 412 */ 413 414 SOC_IF_ERROR_RETURN 415 (MODIFY_XGXS16G_XGXSBLK8_TXLNSWAP1r(unit, pc, 416 XGXSBLK8_TXLNSWAP1_ASYMM_EN_MASK, 417 XGXSBLK8_TXLNSWAP1_ASYMM_EN_MASK)); 418 419 } 420 421 } 422 423 if (XGXS16G_13G_ID(pc)) { 424 SOC_IF_ERROR_RETURN 425 (MODIFY_XGXS16G_REMOTEPHY_MISC3r(unit, pc, 426 0, (1 << 6))); 427 } 428 429 /* check if need to do lane swap */ 430 if (FEATURE_NEW_LANESWAP(pc)) { 431 SOC_IF_ERROR_RETURN 432 (_phy_xgxs16g1l_lane_swap(unit,port)); 433 } 434 435 /* check if need to polarity flip */ 436 SOC_IF_ERROR_RETURN 437 (_phy_xgxs16g1l_polarity_flip(unit,port)); 438 439 if (soc_property_port_get(unit, port, 440 spn_PHY_AN_C73, FALSE)) { 441 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C73); 442 } 443 444 /* disable CL73 BAM */ 445 SOC_IF_ERROR_RETURN 446 (MODIFY_XGXS16G_AN_CL73_REG(unit,pc,0x8372, 447 0, 448 CL73_USERB0_CL73_BAMCTRL1_CL73_BAMEN_MASK)); 449 450 if (!PHY_CLAUSE73_MODE(unit, port)) { 451 /* disable CL73 AN device*/ 452 SOC_IF_ERROR_RETURN 453 (WRITE_XGXS16G_AN_CL73_REG(unit,pc,MII_CTRL_REG,0)); 454 } 455 456 /* Set Local Advertising Configuration */ 457 SOC_IF_ERROR_RETURN 458 (phy_xgxs16g1l_ability_local_get(unit, port, &ability)); 459 /* Do not advertise 2.5G. 1Gbps vs 2.5 Gbps AN is not supported */ 460 ability.speed_full_duplex &= SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | 461 SOC_PA_SPEED_1000MB; 462 pc->fiber.advert_ability = ability; 463 SOC_IF_ERROR_RETURN 464 (phy_xgxs16g1l_ability_advert_set(unit, port, &ability)); 465 466 /* Disable BAM in Independent Lane mode. Over1G AN not supported */ 467 SOC_IF_ERROR_RETURN 468 (WRITE_XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr(unit, pc, 0)); 469 SOC_IF_ERROR_RETURN 470 (WRITE_XGXS16G_BAM_NEXTPAGE_UD_FIELDr(unit, pc, 0)); 471 472 data16 = SERDESDIGITAL_CONTROL1000X1_CRC_CHECKER_DISABLE_MASK | 473 SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK; 474 SOC_IF_ERROR_RETURN 475 (WRITE_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16)); 476 477 mask16 = SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK | 478 SERDESDIGITAL_CONTROL1000X1_DISABLE_PLL_PWRDWN_MASK | 479 SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; 480 /* 481 * Configure signal auto-detection between SGMII and fiber. 482 * This detection only works if auto-negotiation is enabled. 483 */ 484 if (soc_property_port_get(unit, port, 485 spn_SERDES_AUTOMEDIUM, FALSE)) { 486 data16 |= SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK; 487 } 488 489 /* 490 * Put the Serdes in Fiber or SGMII mode 491 */ 492 mode_1000x = 0; 493 if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) || 494 PHY_PASSTHRU_MODE(unit, port)) { 495 mode_1000x = SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; 496 } 497 /* Allow property to override */ 498 if (soc_property_port_get(unit, port, 499 spn_SERDES_FIBER_PREF, mode_1000x)) { 500 data16 |= SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; 501 } else { 502 data16 &= ~SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; 503 } 504 505 SOC_IF_ERROR_RETURN 506 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16, mask16)); 507 if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) || 508 PHY_PASSTHRU_MODE(unit, port) || 509 PHY_SGMII_AUTONEG_MODE(unit, port)) { 510 /* Enable 1000X parallel detect */ 511 data16 = SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK; 512 mask16 = SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK; 513 } else { 514 data16 = 0; 515 mask16 = SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK | 516 SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_MASK; 517 } 518 SOC_IF_ERROR_RETURN 519 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, data16, mask16)); 520 521 /* Initialialize autoneg and fullduplex */ 522 data16 = MII_CTRL_FD | MII_CTRL_SS_1000; 523 if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) || 524 PHY_PASSTHRU_MODE(unit, port) || 525 PHY_SGMII_AUTONEG_MODE(unit, port)) { 526 data16 |= MII_CTRL_AE | MII_CTRL_RAN; 527 } 528 SOC_IF_ERROR_RETURN 529 (WRITE_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, data16)); 530 531 if (PHY_CLAUSE73_MODE(unit, port)) { 532 SOC_IF_ERROR_RETURN 533 (MODIFY_XGXS16G_AN_CL73_REG(unit, pc,MII_CTRL_REG, 534 data16, 535 MII_CTRL_AE | MII_CTRL_RAN)); 536 } 537 538 /* Disable 10G parallel detect */ 539 SOC_IF_ERROR_RETURN 540 (WRITE_XGXS16G_AN73_PDET_PARDET10GCONTROLr(unit, pc, 0)); 541 542 /* Disable BAM mode and Teton mode */ 543 SOC_IF_ERROR_RETURN 544 (WRITE_XGXS16G_BAM_NEXTPAGE_MP5_NEXTPAGECTRLr(unit, pc, 0)); 545 546 /* Initialize XAUI to reasonable default settings */ 547 if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)){ 548 preemph = 0; 549 idriver = 4; 550 preemph = soc_property_port_get(unit, port, spn_XGXS_PREEMPHASIS, preemph); 551 idriver = soc_property_port_get(unit, port, spn_XGXS_DRIVER_CURRENT, idriver); 552 data16 = ((preemph & 0xf) << TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_SHIFT) | 553 ((idriver & 0x7) << TX_ALL_040_TX_DRIVER_IDRIVER_SHIFT); 554 mask16 = TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_MASK | 555 TX_ALL_040_TX_DRIVER_IDRIVER_MASK; 556 switch(pc->lane_num){ 557 case 0: 558 SOC_IF_ERROR_RETURN 559 (MODIFY_XGXS13G_040_TX0_ACONTROL1r(unit, pc, data16, mask16)); 560 break; 561 case 1: 562 SOC_IF_ERROR_RETURN 563 (MODIFY_XGXS13G_040_TX1_ACONTROL1r(unit, pc, data16, mask16)); 564 break; 565 case 2: 566 SOC_IF_ERROR_RETURN 567 (MODIFY_XGXS13G_040_TX2_ACONTROL1r(unit, pc, data16, mask16)); 568 break; 569 case 3: 570 SOC_IF_ERROR_RETURN 571 (MODIFY_XGXS13G_040_TX3_ACONTROL1r(unit, pc, data16, mask16)); 572 break; 573 default: 574 SOC_IF_ERROR_RETURN 575 (MODIFY_XGXS13G_040_TX_ALL_ACONTROL1r(unit, pc, data16, mask16)); 576 break; 577 } 578 } else { 579 preemph = 0; 580 idriver = 9; 581 pdriver = 9; 582 preemph = soc_property_port_get(unit, port, spn_XGXS_PREEMPHASIS, preemph); 583 idriver = soc_property_port_get(unit, port, spn_XGXS_DRIVER_CURRENT, idriver); 584 pdriver = soc_property_port_get(unit, port, spn_XGXS_PRE_DRIVER_CURRENT, pdriver); 585 data16 = ((preemph & 0xf) << TX_ALL_TX_DRIVER_PREEMPHASIS_SHIFT) | 586 ((idriver & 0xf) << TX_ALL_TX_DRIVER_IDRIVER_SHIFT) | 587 ((pdriver & 0xf) << TX_ALL_TX_DRIVER_IPREDRIVER_SHIFT); 588 mask16 = TX_ALL_TX_DRIVER_PREEMPHASIS_MASK | 589 TX_ALL_TX_DRIVER_IDRIVER_MASK | 590 TX_ALL_TX_DRIVER_IPREDRIVER_MASK; 591 switch(pc->lane_num){ 592 case 0: 593 SOC_IF_ERROR_RETURN 594 (MODIFY_XGXS16G_TX0_TX_DRIVERr(unit, pc, data16, mask16)); 595 break; 596 case 1: 597 SOC_IF_ERROR_RETURN 598 (MODIFY_XGXS16G_TX1_TX_DRIVERr(unit, pc, data16, mask16)); 599 break; 600 case 2: 601 SOC_IF_ERROR_RETURN 602 (MODIFY_XGXS16G_TX2_TX_DRIVERr(unit, pc, data16, mask16)); 603 break; 604 case 3: 605 SOC_IF_ERROR_RETURN 606 (MODIFY_XGXS16G_TX3_TX_DRIVERr(unit, pc, data16, mask16)); 607 break; 608 default: 609 SOC_IF_ERROR_RETURN 610 (MODIFY_XGXS16G_TX_ALL_TX_DRIVERr(unit, pc, data16, mask16)); 611 break; 612 } 613 } 614 615 /* Enable lanes */ 616 mask16 = XGXSBLK1_LANECTRL0_CL36_PCS_EN_RX_MASK | 617 XGXSBLK1_LANECTRL0_CL36_PCS_EN_TX_MASK; 618 data16 = mask16; 619 SOC_IF_ERROR_RETURN 620 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL0r(unit, pc, data16, mask16)); 621 622 /* set elasticity fifo size to 13.5k to support 12k jumbo pkt size*/ 623 SOC_IF_ERROR_RETURN 624 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X3r(unit,pc, 625 (1 << 2), 626 SERDESDIGITAL_CONTROL1000X3_FIFO_ELASICITY_TX_RX_MASK)); 627 628 /* Enabble LPI passthru' for native mode EEE */ 629 if (pc->dev_name && !(sal_strcmp(pc->dev_name, "XGXS13G1l") && sal_strcmp(pc->dev_name, "QS40"))) { 630 /* Enabble LPI passthru' for native mode EEE */ 631 SOC_IF_ERROR_RETURN 632 (MODIFY_XGXS16G_REMOTEPHY_MISC5r(unit, pc, 0xc000, 0xc000)); 633 SOC_IF_ERROR_RETURN 634 (MODIFY_XGXS16G_XGXSBLK7_EEECONTROLr(unit, pc, 0x0007, 0x0007)); 635 } 636 637 if ((!PHY_FLAGS_TST(unit, port, PHY_FLAGS_INIT_DONE)) && 638 (pc->lane_num == 0)) { 639 /* Start PLL Sequencer and wait for PLL to lock */ 640 SOC_IF_ERROR_RETURN 641 (MODIFY_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 642 XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK, 643 XGXSBLK0_XGXSCONTROL_START_SEQUENCER_MASK)); 644 (void) _phy_xgxs16g1l_pll_lock_wait(unit, port); 645 } 646 647 /* PRBS Polynomial for all lanes: 0x8019=0x0000 */ 648 649 SOC_IF_ERROR_RETURN 650 (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, 0)); 651 652 /* ************************************************************************/ 653 /* Speical case handling for KT2:OLP port(MXQ10:lane2).Lane0,1,3 not used */ 654 /* ************************************************************************/ 655 656 #ifdef BCM_KATANA2_SUPPORT 657 if ((SOC_IS_KATANA2(unit)) && 658 (SOC_INFO(unit).olp_port[0]) && 659 (port == 40) && /* OLP PORT surely */ 660 (!(soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE))) { 661 /* Set Broadcast mode */ 662 SOC_IF_ERROR_RETURN(WRITE_XGXS16G_AERBLK_AERr(unit, pc, 0x1F)); 663 /* Disable PLL */ 664 SOC_IF_ERROR_RETURN( 665 WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x062f)); 666 /* Put serdes in 4 * 2.5G symmetric mode then */ 667 SOC_IF_ERROR_RETURN( 668 WRITE_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, 0x6010)); 669 /* Enable PLL */ 670 SOC_IF_ERROR_RETURN( 671 WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x262f)); 672 } 673 #endif 674 /* Check if HW rx los is configured */ 675 data16 = 0; 676 mask16 = SERDESDIGITAL_CONTROL1000X1_SIGNAL_DETECT_EN_MASK | 677 SERDESDIGITAL_CONTROL1000X1_INVERT_SIGNAL_DETECT_MASK; 678 if (soc_property_port_get(unit, port, 679 spn_SERDES_RX_LOS, rx_los)) { 680 data16 = SERDESDIGITAL_CONTROL1000X1_SIGNAL_DETECT_EN_MASK; 681 } 682 if (soc_property_port_get(unit, port, 683 spn_SERDES_RX_LOS_INVERT, rx_los_invert)) { 684 data16 |= SERDESDIGITAL_CONTROL1000X1_INVERT_SIGNAL_DETECT_MASK; 685 } 686 SOC_IF_ERROR_RETURN( 687 MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16, mask16)); 688 689 return (SOC_E_NONE); 690 } 691 692 /* 693 * Function: 694 * phy_xgxs16g1l_link_get 695 * Purpose: 696 * Get layer2 connection status. 697 * Parameters: 698 * unit - StrataSwitch unit #. 699 * port - StrataSwitch port #. 700 * link - address of memory to store link up/down state. 701 * Returns: 702 * SOC_E_NONE 703 */ 704 705 STATIC int 706 phy_xgxs16g1l_link_get(int unit, soc_port_t port, int *link) 707 { 708 phy_ctrl_t *pc; 709 uint16 mii_serdes_stat; 710 711 if (PHY_DISABLED_MODE(unit, port)) { 712 *link = FALSE; 713 return (SOC_E_NONE); 714 } 715 716 pc = INT_PHY_SW_STATE(unit, port); 717 718 SOC_IF_ERROR_RETURN 719 (READ_XGXS16G_COMBO_IEEE0_MIISTATr(unit, pc, &mii_serdes_stat)); 720 721 *link = ((mii_serdes_stat & MII_STAT_LA) != 0); 722 723 return (SOC_E_NONE); 724 } 725 726 /* 727 * Function: 728 * phy_xgxs16g1l_enable_set 729 * Purpose: 730 * Enable/Disable phy 731 * Parameters: 732 * unit - StrataSwitch unit #. 733 * port - StrataSwitch port #. 734 * enable - on/off state to set 735 * Returns: 736 * SOC_E_NONE 737 */ 738 739 STATIC int 740 phy_xgxs16g1l_enable_set(int unit, soc_port_t port, int enable) 741 { 742 int rv; 743 744 if (enable) { 745 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 746 rv = _phy_xgxs16g1l_notify_resume(unit, port, PHY_STOP_PHY_DIS); 747 } else { 748 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 749 rv = _phy_xgxs16g1l_notify_stop(unit, port, PHY_STOP_PHY_DIS); 750 } 751 752 return (rv); 753 } 754 755 /* 756 * Function: 757 * phy_xgxs16g1l_speed_set 758 * Purpose: 759 * Set PHY speed 760 * Parameters: 761 * unit - StrataSwitch unit #. 762 * port - StrataSwitch port #. 763 * speed - link speed in Mbps 764 * Returns: 765 * SOC_E_NONE 766 */ 767 768 STATIC int 769 phy_xgxs16g1l_speed_set(int unit, soc_port_t port, int speed) 770 { 771 phy_ctrl_t *pc; 772 phy_ctrl_t *local_pc; 773 uint16 speed_val, mask; 774 uint16 sgmii_status = 0, data16, temp16; 775 uint16 speed_mii; 776 int asymmetric_speed_mode = 0; 777 int blk_num = 0; 778 soc_pbmp_t blk_pbmp; 779 soc_port_t local_port = 0; 780 781 pc = INT_PHY_SW_STATE(unit, port); 782 783 if (speed > 2500) { 784 return (SOC_E_CONFIG); 785 } 786 787 speed_val = 0; 788 speed_mii = 0; 789 mask = SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK | 790 SERDESDIGITAL_MISC1_FORCE_SPEED_MASK; 791 792 asymmetric_speed_mode = soc_property_port_get(unit, port, spn_SERDES_ASYMMETRIC_SPEED_MODE, 0); 793 794 switch (speed) { 795 case 0: 796 /* Do not change speed */ 797 return SOC_E_NONE; 798 case 10: 799 speed_mii = MII_CTRL_SS_10; 800 break; 801 case 100: 802 speed_mii = MII_CTRL_SS_100; 803 break; 804 case 1000: 805 speed_mii = MII_CTRL_SS_1000; 806 break; 807 case 2500: 808 speed_val = 0; 809 break; 810 default: 811 return SOC_E_PARAM; 812 } 813 814 /* 2.5G only valid in fiber mode */ 815 if (speed == 2500) { 816 speed_val |= SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK; 817 } 818 819 /* Hold rxSeqStart */ 820 SOC_IF_ERROR_RETURN 821 (MODIFY_XGXS16G_RX0_RX_CONTROLr(unit, pc, 822 DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK, 823 DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK)); 824 825 /* hold TX FIFO in reset */ 826 SOC_IF_ERROR_RETURN 827 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X3r(unit, pc, 828 SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK, 829 SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK)); 830 831 if(XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) { 832 833 /* FORCE ASYMMETRIC SPEED MODES. Refer sect 4.3.2 product brief. 834 Initial setup is done under init() 835 836 (RESET TX and RX lane) 837 838 1. Set anaTxAControl1 7th bit 839 (Lane0 - 0x8065[6]; 840 Lane1 - 0x8075[6]; 841 Lane2 - 0x8085[6]; 842 Lane3 - 0x8095[6]; 843 All lanes - 0x80A5[6];) 844 if rates are 1G or less than 1G. 845 Keep this bit at the default value 1'b0, if the rate is 2.5G. 846 847 2. Set anaRxAControl1 7th bit 848 (Lane0 - 0x80BC[6]; 849 Lane1 - 0x80CC[6]; 850 Lane2 - 0x80DC[6]; 851 Lane3 - 0x80EC[6]; 852 All lanes - 0x80FC[6];) 853 if rates are 1G or less than 1G. 854 Keep this bit at the default value 1'b0, if the rate is 2.5G. 855 856 3. Set laneCtrl1 (0x8016), so that each lane is in OS1 mode. 857 For OS1, set mode value = 2'b11 = 0x3 858 859 */ 860 temp16 = 0x0; 861 if( speed <= 1000) { 862 temp16 = 0x1 << 6; 863 } 864 865 /* Reset lane - tx & rx */ 866 SOC_IF_ERROR_RETURN 867 (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc, 868 ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT) 869 | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT), 870 ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT) 871 | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT))); 872 873 switch(pc->lane_num) { 874 case 0: 875 SOC_IF_ERROR_RETURN 876 (MODIFY_XGXS16G_TX0_TX_BGVCMr(unit, pc, 877 temp16, 878 TX0_TX_BGVCM_TICKSEL_MASK)); 879 SOC_IF_ERROR_RETURN 880 (MODIFY_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc, 881 temp16, 882 RX0_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 883 SOC_IF_ERROR_RETURN 884 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 885 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_SHIFT 886 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_SHIFT, 887 XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_MASK 888 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_MASK)); 889 break; 890 case 1: 891 SOC_IF_ERROR_RETURN 892 (MODIFY_XGXS16G_TX1_TX_BGVCMr(unit, pc, 893 temp16, 894 TX1_TX_BGVCM_TICKSEL_MASK)); 895 SOC_IF_ERROR_RETURN 896 (MODIFY_XGXS16G_RX1_RX_ANALOGBIAS0r(unit, pc, 897 temp16, 898 RX1_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 899 SOC_IF_ERROR_RETURN 900 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 901 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_SHIFT 902 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_SHIFT, 903 XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_MASK 904 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_MASK)); 905 break; 906 case 2: 907 SOC_IF_ERROR_RETURN 908 (MODIFY_XGXS16G_TX2_TX_BGVCMr(unit, pc, 909 temp16, 910 TX2_TX_BGVCM_TICKSEL_MASK)); 911 SOC_IF_ERROR_RETURN 912 (MODIFY_XGXS16G_RX2_RX_ANALOGBIAS0r(unit, pc, 913 temp16, 914 RX2_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 915 SOC_IF_ERROR_RETURN 916 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 917 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_SHIFT 918 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_SHIFT, 919 XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_MASK 920 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_MASK)); 921 break; 922 case 3: 923 SOC_IF_ERROR_RETURN 924 (MODIFY_XGXS16G_TX3_TX_BGVCMr(unit, pc, 925 temp16, 926 TX3_TX_BGVCM_TICKSEL_MASK)); 927 SOC_IF_ERROR_RETURN 928 (MODIFY_XGXS16G_RX3_RX_ANALOGBIAS0r(unit, pc, 929 temp16, 930 RX3_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 931 SOC_IF_ERROR_RETURN 932 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 933 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_SHIFT 934 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_SHIFT, 935 XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_MASK 936 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_MASK)); 937 break; 938 default: 939 return SOC_E_FAIL; 940 } 941 942 if (speed <= 1000) { 943 speed_val |= SERDESDIGITAL_MISC1_FORCE_LN_MODE_MASK; 944 mask |= SERDESDIGITAL_MISC1_FORCE_LN_MODE_MASK; 945 } 946 } 947 948 if (FEATURE_SPEED_100FX(pc) 949 && IF_XGXS16G_13G_B0_IS_SYMMETRIC_MODE(pc, asymmetric_speed_mode)) { 950 /* disable 100FX and 100FX auto-detect */ 951 SOC_IF_ERROR_RETURN 952 (MODIFY_XGXS16G_FX100_CONTROL1r(unit,pc, 953 0, 954 FX100_CONTROL1_AUTODET_EN_MASK | 955 FX100_CONTROL1_ENABLE_MASK)); 956 957 /* disable 100FX idle detect */ 958 SOC_IF_ERROR_RETURN 959 (MODIFY_XGXS16G_FX100_CONTROL3r(unit,pc, 960 FX100_CONTROL3_CORRELATOR_DISABLE_MASK, 961 FX100_CONTROL3_CORRELATOR_DISABLE_MASK)); 962 SOC_IF_ERROR_RETURN 963 (READ_XGXS16G_SERDESDIGITAL_STATUS1000X1r(unit, pc, &sgmii_status)); 964 965 sgmii_status &= SERDESDIGITAL_STATUS1000X1_SGMII_MODE_MASK; 966 } 967 968 SOC_IF_ERROR_RETURN 969 (MODIFY_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, speed_val, mask)); 970 971 if ( FEATURE_SPEED_100FX(pc) 972 && (!sgmii_status && (speed == 100)) 973 && IF_XGXS16G_13G_B0_IS_SYMMETRIC_MODE(pc, asymmetric_speed_mode)) { 974 /* fiber mode 100fx, enable */ 975 SOC_IF_ERROR_RETURN 976 (MODIFY_XGXS16G_FX100_CONTROL1r(unit,pc, 977 FX100_CONTROL1_FAR_END_FAULT_EN_MASK | 978 FX100_CONTROL1_ENABLE_MASK, 979 FX100_CONTROL1_FAR_END_FAULT_EN_MASK | 980 FX100_CONTROL1_ENABLE_MASK)); 981 982 /* enable 100fx extended packet size */ 983 SOC_IF_ERROR_RETURN 984 (MODIFY_XGXS16G_FX100_CONTROL2r(unit,pc, 985 FX100_CONTROL2_EXTEND_PKT_SIZE_MASK, 986 FX100_CONTROL2_EXTEND_PKT_SIZE_MASK)); 987 988 } else { 989 SOC_IF_ERROR_RETURN 990 (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &data16)); 991 data16 &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); 992 data16 |= speed_mii; 993 SOC_IF_ERROR_RETURN 994 (WRITE_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, data16)); 995 } 996 997 998 if(XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) { 999 /* Release Rx and Tx lane reset */ 1000 SOC_IF_ERROR_RETURN 1001 (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc, 0, 1002 ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT) 1003 | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT))); 1004 1005 } 1006 1007 1008 /* release rxSeqStart */ 1009 SOC_IF_ERROR_RETURN 1010 (MODIFY_XGXS16G_RX0_RX_CONTROLr(unit, pc, 1011 0, 1012 DSC_2_0_DSC_CTRL0_RXSEQSTART_MASK)); 1013 1014 /* release TX FIFO reset */ 1015 SOC_IF_ERROR_RETURN 1016 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X3r(unit, pc, 1017 0, 1018 SERDESDIGITAL_CONTROL1000X3_TX_FIFO_RST_MASK)); 1019 1020 if (SOC_IS_KATANA(unit)) { 1021 blk_num = SOC_PORT_BLOCK(unit, port); 1022 SOC_PBMP_ASSIGN(blk_pbmp,SOC_BLOCK_BITMAP(unit,blk_num)); 1023 SOC_PBMP_ITER(blk_pbmp,local_port) { 1024 local_pc = INT_PHY_SW_STATE(unit, local_port); 1025 if (local_pc == NULL) { 1026 continue; 1027 } 1028 if ((local_pc->lane_num == 0) && !SOC_PORT_VALID(unit, local_port)) { 1029 SOC_IF_ERROR_RETURN(WRITE_XGXS16G_AERBLK_AERr(unit, pc, 0x1f)); 1030 break; 1031 } 1032 } 1033 } 1034 1035 return (SOC_E_NONE); 1036 } 1037 1038 /* 1039 * Function: 1040 * phy_xgxs16g1l_speed_get 1041 * Purpose: 1042 * Get PHY speed 1043 * Parameters: 1044 * unit - StrataSwitch unit #. 1045 * port - StrataSwitch port #. 1046 * speed - current link speed in Mbps 1047 * Returns: 1048 * SOC_E_NONE 1049 */ 1050 STATIC int 1051 phy_xgxs16g1l_speed_get(int unit, soc_port_t port, int *speed) 1052 { 1053 uint16 data16; 1054 phy_ctrl_t *pc; 1055 1056 pc = INT_PHY_SW_STATE(unit, port); 1057 1058 if (NULL == speed) { 1059 return (SOC_E_PARAM); 1060 } 1061 1062 SOC_IF_ERROR_RETURN 1063 (READ_XGXS16G_SERDESDIGITAL_STATUS1000X1r(unit, pc, &data16)); 1064 1065 data16 &= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_MASK; 1066 data16 >>= SERDESDIGITAL_STATUS1000X1_SPEED_STATUS_SHIFT; 1067 1068 if (data16 == 3) { 1069 *speed= 2500; 1070 } else if (data16 == 2) { 1071 *speed= 1000; 1072 } else if (data16 == 1) { 1073 *speed= 100; 1074 } else { 1075 *speed= 10; 1076 } 1077 1078 return (SOC_E_NONE); 1079 } 1080 1081 STATIC int 1082 _force_asym_speedmod_set(int unit, soc_port_t port, int is_speed_2500) 1083 { 1084 int asymmetric_speed_mode ; 1085 phy_ctrl_t *pc; 1086 uint16 temp16; 1087 1088 1089 pc = INT_PHY_SW_STATE(unit, port); 1090 asymmetric_speed_mode = soc_property_port_get(unit, port, spn_SERDES_ASYMMETRIC_SPEED_MODE, 0); 1091 if(XGXS16G_13G_REV_B0(pc) && asymmetric_speed_mode) { 1092 1093 /* FORCE ASYMMETRIC SPEED MODES. Refer sect 4.3.2 product brief. 1094 Initial setup is done under init() 1095 1096 (RESET TX and RX lane) 1097 1098 1. Set anaTxAControl1 7th bit 1099 (Lane0 - 0x8065[6]; 1100 Lane1 - 0x8075[6]; 1101 Lane2 - 0x8085[6]; 1102 Lane3 - 0x8095[6]; 1103 All lanes - 0x80A5[6];) 1104 if rates are 1G or less than 1G. 1105 Keep this bit at the default value 1'b0, if the rate is 2.5G. 1106 1107 2. Set anaRxAControl1 7th bit 1108 (Lane0 - 0x80BC[6]; 1109 Lane1 - 0x80CC[6]; 1110 Lane2 - 0x80DC[6]; 1111 Lane3 - 0x80EC[6]; 1112 All lanes - 0x80FC[6];) 1113 if rates are 1G or less than 1G. 1114 Keep this bit at the default value 1'b0, if the rate is 2.5G. 1115 1116 3. Set laneCtrl1 (0x8016), so that each lane is in OS1 mode. 1117 For OS1, set mode value = 2'b11 = 0x3 1118 1119 */ 1120 temp16 = 0x0; 1121 if(!is_speed_2500) { 1122 temp16 = 0x1 << 6; 1123 } 1124 1125 /* Reset lane - tx & rx */ 1126 SOC_IF_ERROR_RETURN 1127 (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc, 1128 ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT) 1129 | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT), 1130 ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT) 1131 | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT))); 1132 1133 switch(pc->lane_num) { 1134 case 0: 1135 SOC_IF_ERROR_RETURN 1136 (MODIFY_XGXS16G_TX0_TX_BGVCMr(unit, pc, 1137 temp16, 1138 TX0_TX_BGVCM_TICKSEL_MASK)); 1139 SOC_IF_ERROR_RETURN 1140 (MODIFY_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc, 1141 temp16, 1142 RX0_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 1143 SOC_IF_ERROR_RETURN 1144 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 1145 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_SHIFT 1146 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_SHIFT, 1147 XGXSBLK1_LANECTRL1_RX1G_MODE_LN0_MASK 1148 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN0_MASK)); 1149 break; 1150 case 1: 1151 SOC_IF_ERROR_RETURN 1152 (MODIFY_XGXS16G_TX1_TX_BGVCMr(unit, pc, 1153 temp16, 1154 TX1_TX_BGVCM_TICKSEL_MASK)); 1155 SOC_IF_ERROR_RETURN 1156 (MODIFY_XGXS16G_RX1_RX_ANALOGBIAS0r(unit, pc, 1157 temp16, 1158 RX1_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 1159 SOC_IF_ERROR_RETURN 1160 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 1161 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_SHIFT 1162 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_SHIFT, 1163 XGXSBLK1_LANECTRL1_RX1G_MODE_LN1_MASK 1164 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN1_MASK)); 1165 break; 1166 case 2: 1167 SOC_IF_ERROR_RETURN 1168 (MODIFY_XGXS16G_TX2_TX_BGVCMr(unit, pc, 1169 temp16, 1170 TX2_TX_BGVCM_TICKSEL_MASK)); 1171 SOC_IF_ERROR_RETURN 1172 (MODIFY_XGXS16G_RX2_RX_ANALOGBIAS0r(unit, pc, 1173 temp16, 1174 RX2_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 1175 SOC_IF_ERROR_RETURN 1176 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 1177 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_SHIFT 1178 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_SHIFT, 1179 XGXSBLK1_LANECTRL1_RX1G_MODE_LN2_MASK 1180 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN2_MASK)); 1181 break; 1182 case 3: 1183 SOC_IF_ERROR_RETURN 1184 (MODIFY_XGXS16G_TX3_TX_BGVCMr(unit, pc, 1185 temp16, 1186 TX3_TX_BGVCM_TICKSEL_MASK)); 1187 SOC_IF_ERROR_RETURN 1188 (MODIFY_XGXS16G_RX3_RX_ANALOGBIAS0r(unit, pc, 1189 temp16, 1190 RX3_RX_ANALOGBIAS0_SIG_PWRDN_MASK)); 1191 SOC_IF_ERROR_RETURN 1192 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 1193 0x3 << XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_SHIFT 1194 | 0x3 << XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_SHIFT, 1195 XGXSBLK1_LANECTRL1_RX1G_MODE_LN3_MASK 1196 | XGXSBLK1_LANECTRL1_TX1G_MODE_LN3_MASK)); 1197 break; 1198 default: 1199 return SOC_E_FAIL; 1200 } 1201 /* Release Rx and Tx lane reset */ 1202 SOC_IF_ERROR_RETURN 1203 (MODIFY_XGXS16G_XGXSBLK2_LANERESETr(unit, pc, 0, 1204 ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETTX_SHIFT) 1205 | ((1 << pc->lane_num) <<XGXSBLK2_LANERESET_RESETRX_SHIFT))); 1206 1207 } 1208 1209 return SOC_E_NONE ; 1210 1211 } 1212 /* 1213 * Function: 1214 * phy_xgxs16g1l_an_set 1215 * Purpose: 1216 * Enable or disabled auto-negotiation on the specified port. 1217 * Parameters: 1218 * unit - StrataSwitch unit #. 1219 * port - StrataSwitch port #. 1220 * an - Boolean, if true, auto-negotiation is enabled 1221 * (and/or restarted). If false, autonegotiation is disabled. 1222 * Returns: 1223 * SOC_E_XXX 1224 */ 1225 STATIC int 1226 phy_xgxs16g1l_an_set(int unit, soc_port_t port, int an) 1227 { 1228 phy_ctrl_t *pc; 1229 phy_ctrl_t *local_pc; 1230 uint16 an_enable; 1231 uint16 auto_det; 1232 int blk_num = 0; 1233 soc_pbmp_t blk_pbmp; 1234 soc_port_t local_port = 0; 1235 int speed = 0; 1236 int is_speed_2500 = 0; 1237 1238 pc = INT_PHY_SW_STATE(unit, port); 1239 1240 LOG_INFO(BSL_LS_SOC_PHY, 1241 (BSL_META_U(unit, 1242 "phy_xgxs16g1l_an_set: u=%d p=%d an=%d\n"), 1243 unit, port, an)); 1244 1245 an_enable = 0; 1246 auto_det = 0; 1247 1248 if (an) { 1249 /* disable 100FX and 100FX auto-detect */ 1250 SOC_IF_ERROR_RETURN 1251 (MODIFY_XGXS16G_FX100_CONTROL1r(unit, pc, 0, 1252 FX100_CONTROL1_AUTODET_EN_MASK | 1253 FX100_CONTROL1_ENABLE_MASK)); 1254 1255 an_enable = MII_CTRL_AE | MII_CTRL_RAN; 1256 1257 /* 1258 * Should read one during init and cache it in Phy flags 1259 */ 1260 if (soc_property_port_get(unit, port, 1261 spn_SERDES_AUTOMEDIUM, 1262 FALSE)) { 1263 auto_det = SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK; 1264 } 1265 1266 /* If auto-neg is enabled, make sure not forcing any speed */ 1267 SOC_IF_ERROR_RETURN 1268 (MODIFY_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, 0, 1269 SERDESDIGITAL_MISC1_FORCE_SPEED_SEL_MASK)); 1270 /* Enable/Disable auto detect */ 1271 SOC_IF_ERROR_RETURN 1272 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, auto_det, 1273 SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK)); 1274 1275 } else { 1276 /* Disable auto detect */ 1277 SOC_IF_ERROR_RETURN 1278 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, auto_det, 1279 SERDESDIGITAL_CONTROL1000X1_AUTODET_EN_MASK)); 1280 1281 } 1282 1283 /* restart the autoneg if enabled, or disable the autoneg */ 1284 SOC_IF_ERROR_RETURN 1285 (MODIFY_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, an_enable, 1286 MII_CTRL_AE | MII_CTRL_RAN)); 1287 1288 if (PHY_CLAUSE73_MODE(unit, port)) { 1289 SOC_IF_ERROR_RETURN 1290 (MODIFY_XGXS16G_AN_CL73_REG(unit, pc,MII_CTRL_REG, 1291 an_enable, 1292 MII_CTRL_AE | MII_CTRL_RAN)); 1293 } 1294 1295 if(an) { 1296 is_speed_2500 = 0; 1297 }else{ 1298 SOC_IF_ERROR_RETURN 1299 (phy_xgxs16g1l_speed_get(unit, port, &speed)); 1300 if(speed == 2500) { 1301 is_speed_2500 = 1; 1302 } else { 1303 is_speed_2500 = 0; 1304 } 1305 } 1306 1307 SOC_IF_ERROR_RETURN 1308 (_force_asym_speedmod_set(unit,port,is_speed_2500)); 1309 1310 pc->fiber.autoneg_enable = an; 1311 1312 if (SOC_IS_KATANA(unit)) { 1313 blk_num = SOC_PORT_BLOCK(unit, port); 1314 SOC_PBMP_ASSIGN(blk_pbmp,SOC_BLOCK_BITMAP(unit,blk_num)); 1315 SOC_PBMP_ITER(blk_pbmp,local_port) { 1316 local_pc = INT_PHY_SW_STATE(unit, local_port); 1317 if (local_pc == NULL) { 1318 continue; 1319 } 1320 if ((local_pc->lane_num == 0) && !SOC_PORT_VALID(unit, local_port)) { 1321 SOC_IF_ERROR_RETURN(WRITE_XGXS16G_AERBLK_AERr(unit, pc, 0x1f)); 1322 break; 1323 } 1324 } 1325 } 1326 1327 return SOC_E_NONE; 1328 } 1329 1330 1331 /* 1332 * Function: 1333 * phy_xgxs16g1l_an_get 1334 * Purpose: 1335 * Get the current auto-negotiation status (enabled/busy) 1336 * Parameters: 1337 * unit - StrataSwitch unit #. 1338 * port - StrataSwitch port #. 1339 * an - (OUT) if true, auto-negotiation is enabled. 1340 * an_done - (OUT) if true, auto-negotiation is complete. This 1341 * value is undefined if an == false. 1342 * Returns: 1343 * SOC_E_XXX 1344 */ 1345 1346 STATIC int 1347 phy_xgxs16g1l_an_get(int unit, soc_port_t port, int *an, int *an_done) 1348 { 1349 uint16 mii_ctrl; 1350 uint16 mii_stat; 1351 phy_ctrl_t *pc; 1352 1353 if ((NULL == an) || (NULL == an_done)) { 1354 return (SOC_E_PARAM); 1355 } 1356 1357 pc = INT_PHY_SW_STATE(unit, port); 1358 1359 SOC_IF_ERROR_RETURN 1360 (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl)); 1361 SOC_IF_ERROR_RETURN 1362 (READ_XGXS16G_COMBO_IEEE0_MIISTATr(unit, pc, &mii_stat)); 1363 1364 *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE; 1365 *an_done = (mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE; 1366 if (!((*an == TRUE) && (*an_done == TRUE))) { 1367 if (PHY_CLAUSE73_MODE(unit, port)) { 1368 /* check clause 73 */ 1369 SOC_IF_ERROR_RETURN 1370 (READ_XGXS16G_AN_CL73_REG(unit, pc, MII_CTRL_REG,&mii_ctrl)); 1371 SOC_IF_ERROR_RETURN 1372 (READ_XGXS16G_AN_CL73_REG(unit, pc, MII_STAT_REG, &mii_stat)); 1373 1374 *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE; 1375 *an_done = (mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE; 1376 } 1377 } 1378 1379 return SOC_E_NONE; 1380 } 1381 1382 STATIC int 1383 _phy_xgxs16g1l_c73_adv_local_set(int unit, soc_port_t port, 1384 soc_port_ability_t *ability) 1385 { 1386 uint16 an_adv; 1387 uint16 pause; 1388 phy_ctrl_t *pc; 1389 1390 pc = INT_PHY_SW_STATE(unit, port); 1391 1392 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 1393 CL73_AN_ADV_TECH_1G_KX : 0; 1394 an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ? 1395 CL73_AN_ADV_TECH_10G_KX4 : 0; 1396 1397 SOC_IF_ERROR_RETURN 1398 (MODIFY_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT1_REG, an_adv, 1399 CL73_AN_ADV_TECH_SPEEDS_MASK)); 1400 1401 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 1402 case SOC_PA_PAUSE_TX: 1403 pause = CL73_AN_ADV_ASYM_PAUSE; 1404 break; 1405 case SOC_PA_PAUSE_RX: 1406 pause = CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE; 1407 break; 1408 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 1409 pause = CL73_AN_ADV_PAUSE; 1410 break; 1411 default: 1412 pause = 0; 1413 break; 1414 } 1415 1416 SOC_IF_ERROR_RETURN 1417 (MODIFY_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT0_REG, pause, 1418 (CL73_AN_ADV_PAUSE | 1419 CL73_AN_ADV_ASYM_PAUSE))); 1420 1421 LOG_INFO(BSL_LS_SOC_PHY, 1422 (BSL_META_U(unit, 1423 "_phy_xgxs16g1l_c73_adv_local_set: u=%d p=%d pause=%08x speeds=%04x,adv=0x%x\n"), 1424 unit, port, pause, an_adv,ability->speed_full_duplex)); 1425 return SOC_E_NONE; 1426 } 1427 1428 STATIC int 1429 _phy_xgxs16g1l_c73_adv_local_get(int unit, soc_port_t port, 1430 soc_port_ability_t *ability) 1431 { 1432 uint16 an_adv; 1433 soc_port_mode_t speeds,pause; 1434 phy_ctrl_t *pc; 1435 1436 pc = INT_PHY_SW_STATE(unit, port); 1437 1438 SOC_IF_ERROR_RETURN 1439 (READ_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT1_REG, &an_adv)); 1440 1441 speeds = (an_adv & CL73_AN_ADV_TECH_1G_KX) ? SOC_PA_SPEED_1000MB : 0; 1442 speeds |= (an_adv & CL73_AN_ADV_TECH_10G_KX4) ? SOC_PA_SPEED_10GB : 0; 1443 ability->speed_full_duplex |= speeds; 1444 1445 SOC_IF_ERROR_RETURN 1446 (READ_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_ADVERT0_REG, &an_adv)); 1447 1448 switch (an_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) { 1449 case CL73_AN_ADV_PAUSE: 1450 pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1451 break; 1452 case CL73_AN_ADV_ASYM_PAUSE: 1453 pause = SOC_PA_PAUSE_TX; 1454 break; 1455 case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE: 1456 pause = SOC_PA_PAUSE_RX; 1457 break; 1458 default: 1459 pause = 0; 1460 break; 1461 } 1462 ability->pause = pause; 1463 1464 LOG_INFO(BSL_LS_SOC_PHY, 1465 (BSL_META_U(unit, 1466 "_phy_xgxs16g1l_c73_adv_local_get: u=%d p=%d pause=%08x speeds=%04x\n"), 1467 unit, port, pause, speeds)); 1468 return SOC_E_NONE; 1469 } 1470 1471 STATIC int 1472 _phy_xgxs16g1l_c73_adv_remote_get(int unit, soc_port_t port, 1473 soc_port_ability_t *ability) 1474 { 1475 uint16 an_adv; 1476 soc_port_mode_t mode; 1477 phy_ctrl_t *pc; 1478 pc = INT_PHY_SW_STATE(unit, port); 1479 SOC_IF_ERROR_RETURN 1480 (READ_XGXS16G_AN_CL73_REG(unit, pc,CL73_AN_LP_ABILITY1_REG, &an_adv)); 1481 1482 mode = (an_adv & CL73_AN_ADV_TECH_1G_KX) ? SOC_PA_SPEED_1000MB : 0; 1483 mode |= (an_adv & CL73_AN_ADV_TECH_10G_KX4) ? SOC_PA_SPEED_10GB : 0; 1484 ability->speed_full_duplex |= mode; 1485 1486 SOC_IF_ERROR_RETURN 1487 (READ_XGXS16G_AN_CL73_REG(unit, pc, CL73_AN_LP_ABILITY0_REG,&an_adv)); 1488 1489 mode = 0; 1490 switch (an_adv & (CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE)) { 1491 case CL73_AN_ADV_PAUSE: 1492 mode = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1493 break; 1494 case CL73_AN_ADV_ASYM_PAUSE: 1495 mode = SOC_PA_PAUSE_TX; 1496 break; 1497 case CL73_AN_ADV_PAUSE | CL73_AN_ADV_ASYM_PAUSE: 1498 mode = SOC_PA_PAUSE_RX; 1499 break; 1500 } 1501 ability->pause = mode; 1502 1503 return SOC_E_NONE; 1504 } 1505 1506 /* 1507 * Function: 1508 * phy_xgxs16g1l_ability_advert_set 1509 * Purpose: 1510 * Set the current advertisement for auto-negotiation. 1511 * Parameters: 1512 * unit - StrataSwitch unit #. 1513 * port - StrataSwitch port #. 1514 * mode - Port mode mask indicating supported options/speeds. 1515 * Returns: 1516 * SOC_E_XXX 1517 * Notes: 1518 * The advertisement is set only for the ACTIVE medium. 1519 * No synchronization performed at this level. 1520 */ 1521 1522 STATIC int 1523 phy_xgxs16g1l_ability_advert_set(int unit, soc_port_t port, 1524 soc_port_ability_t *ability) 1525 { 1526 uint16 an_adv; 1527 phy_ctrl_t *pc; 1528 1529 if (NULL == ability) { 1530 return (SOC_E_PARAM); 1531 } 1532 1533 pc = INT_PHY_SW_STATE(unit, port); 1534 1535 /* Set advertised duplex (only FD supported). */ 1536 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 1537 MII_ANA_C37_FD : 0; 1538 1539 /* Set advertised pause bits in link code word. */ 1540 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 1541 case SOC_PA_PAUSE_TX: 1542 an_adv |= MII_ANA_C37_ASYM_PAUSE; 1543 break; 1544 case SOC_PA_PAUSE_RX: 1545 an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; 1546 break; 1547 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 1548 an_adv |= MII_ANA_C37_PAUSE; 1549 break; 1550 } 1551 /* Update less than 1G capability */ 1552 SOC_IF_ERROR_RETURN 1553 (WRITE_XGXS16G_COMBO_IEEE0_AUTONEGADVr(unit, pc, an_adv)); 1554 1555 if (PHY_CLAUSE73_MODE(unit, port)) { 1556 SOC_IF_ERROR_RETURN 1557 (_phy_xgxs16g1l_c73_adv_local_set(unit, port, ability)); 1558 } 1559 1560 LOG_INFO(BSL_LS_SOC_PHY, 1561 (BSL_META_U(unit, 1562 "phy_xgxs16g1l_ability_advert_set: u=%d p=%d pause=%08x OVER1G_UP1 %04x\n"), 1563 unit, port, ability->pause, an_adv)); 1564 1565 return (SOC_E_NONE); 1566 } 1567 1568 /* 1569 * Function: 1570 * phy_xgxs16g1l_ability_advert_get 1571 * Purpose: 1572 * Get the current advertisement for auto-negotiation. 1573 * Parameters: 1574 * unit - StrataSwitch unit #. 1575 * port - StrataSwitch port #. 1576 * mode - (OUT) Port mode mask indicating supported options/speeds. 1577 * Returns: 1578 * SOC_E_XXX 1579 * Notes: 1580 * The advertisement is retrieved for the ACTIVE medium. 1581 * No synchronization performed at this level. 1582 */ 1583 1584 STATIC int 1585 phy_xgxs16g1l_ability_advert_get(int unit, soc_port_t port, 1586 soc_port_ability_t *ability) 1587 { 1588 phy_ctrl_t *pc; 1589 uint16 an_adv; 1590 1591 if (NULL == ability) { 1592 return (SOC_E_PARAM); 1593 } 1594 1595 pc = INT_PHY_SW_STATE(unit, port); 1596 1597 sal_memset(ability, 0, sizeof(*ability)); 1598 SOC_IF_ERROR_RETURN 1599 (READ_XGXS16G_COMBO_IEEE0_AUTONEGADVr(unit, pc, &an_adv)); 1600 1601 ability->speed_full_duplex = 1602 (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0; 1603 1604 switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) { 1605 case MII_ANA_C37_PAUSE: 1606 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1607 break; 1608 case MII_ANA_C37_ASYM_PAUSE: 1609 ability->pause = SOC_PA_PAUSE_TX; 1610 break; 1611 case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE: 1612 ability->pause = SOC_PA_PAUSE_RX; 1613 break; 1614 } 1615 1616 /* check for clause73 */ 1617 if (PHY_CLAUSE73_MODE(unit, port)) { 1618 SOC_IF_ERROR_RETURN 1619 (_phy_xgxs16g1l_c73_adv_local_get(unit, port, ability)); 1620 } 1621 1622 LOG_INFO(BSL_LS_SOC_PHY, 1623 (BSL_META_U(unit, 1624 "phy_xgxs16g1l_ability_advert_get:unit=%d p=%d pause=%08x sp=%08x\n"), 1625 unit, port, ability->pause, ability->speed_full_duplex)); 1626 1627 return (SOC_E_NONE); 1628 } 1629 1630 /* 1631 * Function: 1632 * phy_xgxs16g1l_ability_remote_get 1633 * Purpose: 1634 * Get the current advertisement for auto-negotiation. 1635 * Parameters: 1636 * unit - StrataSwitch unit #. 1637 * port - StrataSwitch port #. 1638 * mode - (OUT) Port mode mask indicating supported options/speeds. 1639 * Returns: 1640 * SOC_E_XXX 1641 * Notes: 1642 * The advertisement is retrieved for the ACTIVE medium. 1643 * No synchronization performed at this level. 1644 */ 1645 1646 STATIC int 1647 phy_xgxs16g1l_ability_remote_get(int unit, soc_port_t port, 1648 soc_port_ability_t *ability) 1649 { 1650 phy_ctrl_t *pc; 1651 uint16 an_adv; 1652 soc_port_mode_t mode; 1653 1654 if (NULL == ability) { 1655 return (SOC_E_PARAM); 1656 } 1657 1658 pc = INT_PHY_SW_STATE(unit, port); 1659 1660 sal_memset(ability, 0, sizeof(*ability)); 1661 1662 SOC_IF_ERROR_RETURN 1663 (READ_XGXS16G_COMBO_IEEE0_AUTONEGLPABILr(unit, pc, &an_adv)); 1664 1665 mode = (an_adv & MII_ANP_C37_FD) ? SOC_PA_SPEED_1000MB : 0; 1666 ability->speed_full_duplex = mode; 1667 1668 mode = 0; 1669 switch (an_adv & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) { 1670 case MII_ANP_C37_PAUSE: 1671 mode |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1672 break; 1673 case MII_ANP_C37_ASYM_PAUSE: 1674 mode |= SOC_PA_PAUSE_TX; 1675 break; 1676 case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE: 1677 mode |= SOC_PA_PAUSE_RX; 1678 break; 1679 } 1680 ability->pause = mode; 1681 1682 if (PHY_CLAUSE73_MODE(unit, port)) { 1683 SOC_IF_ERROR_RETURN 1684 (_phy_xgxs16g1l_c73_adv_remote_get(unit, port, ability)); 1685 } 1686 1687 LOG_INFO(BSL_LS_SOC_PHY, 1688 (BSL_META_U(unit, 1689 "phy_xgxs16g1l_ability_remote_get:unit=%d p=%d pause=%08x sp=%08x\n"), 1690 unit, port, ability->pause, ability->speed_full_duplex)); 1691 1692 return (SOC_E_NONE); 1693 } 1694 1695 1696 /* 1697 * Function: 1698 * phy_xgxs16g1l_lb_set 1699 * Purpose: 1700 * Put XGXS6/FusionCore in PHY loopback 1701 * Parameters: 1702 * unit - StrataSwitch unit #. 1703 * port - StrataSwitch port #. 1704 * enable - binary value for on/off (1/0) 1705 * Returns: 1706 * SOC_E_NONE 1707 */ 1708 1709 STATIC int 1710 phy_xgxs16g1l_lb_set(int unit, soc_port_t port, int enable) 1711 { 1712 uint16 misc_ctrl; 1713 uint16 lb_bit; 1714 uint16 lb_mask; 1715 phy_ctrl_t *pc; 1716 1717 pc = INT_PHY_SW_STATE(unit, port); 1718 1719 /* Configure Loopback in XAUI */ 1720 SOC_IF_ERROR_RETURN 1721 (READ_XGXS16G_XGXSBLK0_MISCCONTROL1r(unit, pc, &misc_ctrl)); 1722 if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PCS_DEV_EN_OVERRIDE_MASK) { 1723 /* PCS */ 1724 lb_bit = (enable) ? IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK : 0; 1725 lb_mask = IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK; 1726 } else if (misc_ctrl & XGXSBLK0_MISCCONTROL1_PMD_DEV_EN_OVERRIDE_MASK) { 1727 /* PMA/PMD */ 1728 lb_bit = (enable) ? 1 : 0; 1729 lb_mask = 1; 1730 } else { 1731 /* PHY XS, DTE XS */ 1732 lb_bit = (enable) ? IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK : 0; 1733 lb_mask = IEEE0BLK_IEEECONTROL0_GLOOPBACK_MASK; 1734 } 1735 SOC_IF_ERROR_RETURN 1736 (MODIFY_XGXS16G_IEEE0BLK_IEEECONTROL0r(unit, pc, lb_bit, lb_mask)); 1737 1738 /* Configure Loopback in SerDes */ 1739 SOC_IF_ERROR_RETURN 1740 (MODIFY_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, 1741 (enable) ? MII_CTRL_LE : 0, 1742 MII_CTRL_LE)); 1743 1744 return (SOC_E_NONE); 1745 } 1746 1747 /* 1748 * Function: 1749 * phy_xgxs16g1l_lb_get 1750 * Purpose: 1751 * Get XGXS6/FusionCore PHY loopback state 1752 * Parameters: 1753 * unit - StrataSwitch unit #. 1754 * port - StrataSwitch port #. 1755 * enable - address of location to store binary value for on/off (1/0) 1756 * Returns: 1757 * SOC_E_NONE 1758 */ 1759 1760 STATIC int 1761 phy_xgxs16g1l_lb_get(int unit, soc_port_t port, int *enable) 1762 { 1763 uint16 mii_ctrl; 1764 phy_ctrl_t *pc; 1765 1766 pc = INT_PHY_SW_STATE(unit, port); 1767 1768 SOC_IF_ERROR_RETURN 1769 (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl)); 1770 *enable = ((mii_ctrl & MII_CTRL_LE) == MII_CTRL_LE); 1771 1772 return (SOC_E_NONE); 1773 } 1774 1775 1776 STATIC int 1777 phy_xgxs16g1l_ability_local_get(int unit, soc_port_t port, 1778 soc_port_ability_t *ability) 1779 { 1780 phy_ctrl_t *pc; 1781 1782 if (NULL == ability) { 1783 return (SOC_E_PARAM); 1784 } 1785 1786 pc = INT_PHY_SW_STATE(unit, port); 1787 1788 sal_memset(ability, 0, sizeof(*ability)); 1789 1790 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 1791 ability->speed_full_duplex = SOC_PA_SPEED_1000MB; 1792 if (PHY_FIBER_MODE(unit, port)) { 1793 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 1794 if (FEATURE_SPEED_100FX(pc)) { 1795 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 1796 } 1797 } else { 1798 ability->speed_half_duplex = SOC_PA_SPEED_10MB | 1799 SOC_PA_SPEED_100MB; 1800 ability->speed_full_duplex |= SOC_PA_SPEED_10MB | 1801 SOC_PA_SPEED_100MB; 1802 } 1803 1804 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 1805 ability->interface = SOC_PA_INTF_GMII | SOC_PA_INTF_SGMII; 1806 ability->medium = SOC_PA_MEDIUM_FIBER; 1807 ability->loopback = SOC_PA_LB_PHY; 1808 ability->flags = SOC_PA_AUTONEG; 1809 1810 return (SOC_E_NONE); 1811 } 1812 1813 STATIC int 1814 _phy_xgxs16g1l_control_tx_driver_set(int unit, phy_ctrl_t *pc, 1815 soc_phy_control_t type, uint32 value) 1816 { 1817 uint16 data; /* Temporary holder of reg value to be written */ 1818 uint16 mask; /* Bit mask of reg value to be updated */ 1819 1820 if (value > 15) { 1821 return SOC_E_PARAM; 1822 } 1823 1824 data = mask = 0; 1825 if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)){ 1826 switch(type) { 1827 case SOC_PHY_CONTROL_PREEMPHASIS: 1828 data = value << TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_SHIFT; 1829 mask = TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_MASK; 1830 break; 1831 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1832 data = value << TX_ALL_040_TX_DRIVER_IDRIVER_SHIFT; 1833 mask = TX_ALL_040_TX_DRIVER_IDRIVER_MASK; 1834 break; 1835 default: 1836 /* should never get here */ 1837 return SOC_E_PARAM; 1838 } 1839 /* Update preemphasis/driver/pre-driver current */ 1840 switch(pc->lane_num){ 1841 case 0: 1842 SOC_IF_ERROR_RETURN 1843 (MODIFY_XGXS13G_040_TX0_ACONTROL1r(unit, pc, data, mask)); 1844 break; 1845 case 1: 1846 SOC_IF_ERROR_RETURN 1847 (MODIFY_XGXS13G_040_TX1_ACONTROL1r(unit, pc, data, mask)); 1848 break; 1849 case 2: 1850 SOC_IF_ERROR_RETURN 1851 (MODIFY_XGXS13G_040_TX2_ACONTROL1r(unit, pc, data, mask)); 1852 break; 1853 case 3: 1854 SOC_IF_ERROR_RETURN 1855 (MODIFY_XGXS13G_040_TX3_ACONTROL1r(unit, pc, data, mask)); 1856 break; 1857 default: 1858 SOC_IF_ERROR_RETURN 1859 (MODIFY_XGXS13G_040_TX_ALL_ACONTROL1r(unit, pc, data, mask)); 1860 break; 1861 } 1862 } else { 1863 switch(type) { 1864 case SOC_PHY_CONTROL_PREEMPHASIS: 1865 data = value << TX_ALL_TX_DRIVER_PREEMPHASIS_SHIFT; 1866 mask = TX_ALL_TX_DRIVER_PREEMPHASIS_MASK; 1867 break; 1868 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1869 data = value << TX_ALL_TX_DRIVER_IDRIVER_SHIFT; 1870 mask = TX_ALL_TX_DRIVER_IDRIVER_MASK; 1871 break; 1872 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 1873 data = value << TX_ALL_TX_DRIVER_IPREDRIVER_SHIFT; 1874 mask = TX_ALL_TX_DRIVER_IPREDRIVER_MASK; 1875 break; 1876 default: 1877 /* should never get here */ 1878 return SOC_E_PARAM; 1879 } 1880 /* Update preemphasis/driver/pre-driver current */ 1881 switch(pc->lane_num){ 1882 case 0: 1883 SOC_IF_ERROR_RETURN 1884 (MODIFY_XGXS16G_TX0_TX_DRIVERr(unit, pc, data, mask)); 1885 break; 1886 case 1: 1887 SOC_IF_ERROR_RETURN 1888 (MODIFY_XGXS16G_TX1_TX_DRIVERr(unit, pc, data, mask)); 1889 break; 1890 case 2: 1891 SOC_IF_ERROR_RETURN 1892 (MODIFY_XGXS16G_TX2_TX_DRIVERr(unit, pc, data, mask)); 1893 break; 1894 case 3: 1895 SOC_IF_ERROR_RETURN 1896 (MODIFY_XGXS16G_TX3_TX_DRIVERr(unit, pc, data, mask)); 1897 break; 1898 default: 1899 SOC_IF_ERROR_RETURN 1900 (MODIFY_XGXS16G_TX_ALL_TX_DRIVERr(unit, pc, data, mask)); 1901 break; 1902 } 1903 1904 } 1905 return SOC_E_NONE; 1906 } 1907 1908 STATIC int 1909 _phy_xgxs16g1l_control_linkdown_transmit_set(int unit, soc_port_t port, 1910 uint32 value) 1911 { 1912 uint16 data; 1913 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 1914 1915 if (value) { 1916 data = (SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_BITS << 1917 SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_SHIFT) | 1918 (SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_BITS << 1919 SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_SHIFT) | 1920 (SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_BITS << 1921 SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_SHIFT); 1922 SOC_IF_ERROR_RETURN 1923 (WRITE_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, data)); 1924 } else { 1925 data = (SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_BITS << 1926 SERDESDIGITAL_CONTROL1000X2_DISABLE_FALSE_LINK_SHIFT) | 1927 (SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_BITS << 1928 SERDESDIGITAL_CONTROL1000X2_FILTER_FORCE_LINK_SHIFT) | 1929 (SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_BITS << 1930 SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_SHIFT); 1931 SOC_IF_ERROR_RETURN 1932 (WRITE_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, data)); 1933 } 1934 return SOC_E_NONE; 1935 } 1936 1937 STATIC int 1938 _phy_xgxs16g1l_control_linkdown_transmit_get(int unit, soc_port_t port, 1939 uint32 *value) 1940 { 1941 uint16 data; 1942 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 1943 1944 SOC_IF_ERROR_RETURN 1945 (READ_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, &data)); 1946 1947 *value = (data & 1948 (SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_BITS << 1949 SERDESDIGITAL_CONTROL1000X2_FORCE_XMIT_DATA_ON_TXSIDE_SHIFT)) 1950 ? 1 : 0; 1951 1952 return SOC_E_NONE; 1953 } 1954 1955 1956 STATIC int 1957 _phy_xgxs16g1l_control_prbs_polynomial_set(int unit, soc_port_t port, uint32 value) 1958 { 1959 uint16 data; 1960 1961 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 1962 uint32 prbs_lane_mask = 0; 1963 1964 value &= 7; 1965 1966 SOC_IF_ERROR_RETURN 1967 (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data)); 1968 1969 prbs_lane_mask = 0x7 << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num); 1970 data &= ~prbs_lane_mask; 1971 data |= value << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num); 1972 1973 1974 /* 1975 * write back updated configuration 1976 */ 1977 1978 SOC_IF_ERROR_RETURN 1979 (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data)); 1980 1981 return SOC_E_NONE; 1982 } 1983 1984 STATIC int 1985 _phy_xgxs16g1l_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value) 1986 { 1987 uint16 data; 1988 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);; 1989 1990 SOC_IF_ERROR_RETURN 1991 (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data)); 1992 1993 /* Extract prbs polynomial setting from register */ 1994 data = ((data >> (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num)) & 1995 XGXSBLK1_LANEPRBS_PRBS_ORDER0_MASK); 1996 *value = (uint32) data; 1997 1998 return SOC_E_NONE; 1999 } 2000 2001 2002 STATIC int 2003 _phy_xgxs16g1l_control_prbs_tx_invert_data_set(int unit, soc_port_t port, uint32 value) 2004 { 2005 uint16 data = 0; 2006 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2007 uint32 lane_mask = 1 << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num); 2008 2009 2010 SOC_IF_ERROR_RETURN 2011 (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data)); 2012 2013 /* prbs_inv is bit 2 per lane */ 2014 if (value) { 2015 data |= lane_mask << XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT; 2016 } else { 2017 data &= ~(lane_mask << XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT); 2018 } 2019 2020 /* write back updated configuration */ 2021 if (value > 0x8000) { 2022 SOC_IF_ERROR_RETURN 2023 (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, value)); 2024 } else { 2025 SOC_IF_ERROR_RETURN 2026 (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data)); 2027 } 2028 2029 return SOC_E_NONE; 2030 2031 } 2032 2033 STATIC int 2034 _phy_xgxs16g1l_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value) 2035 { 2036 uint16 data; 2037 uint16 inv_shifter = 0; 2038 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2039 2040 SOC_IF_ERROR_RETURN 2041 (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data)); 2042 2043 inv_shifter = (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num) + 2044 XGXSBLK1_LANEPRBS_PRBS_INV0_SHIFT; 2045 2046 data &= (1 << inv_shifter); 2047 2048 *value = (data) ? 1 : 0; 2049 2050 return SOC_E_NONE; 2051 } 2052 2053 2054 STATIC int 2055 _phy_xgxs16g1l_control_xgxs_prbs_tx_enable_set(int unit, soc_port_t port, 2056 uint32 value) 2057 { 2058 uint16 data = 0; 2059 uint16 pll_mode = 0; 2060 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2061 2062 if (value) { 2063 2064 /* Set double wide div/1: 0x8016=0xffff */ 2065 SOC_IF_ERROR_RETURN 2066 (WRITE_XGXS16G_XGXSBLK1_LANECTRL1r(unit, pc, 0xffff)); 2067 2068 /* clear multiPRT mode: 0x800d=0x0003 */ 2069 /*SOC_IF_ERROR_RETURN 2070 (WRITE_XGXS16G_XGXSBLK0_MMDSELECTr(unit, pc, 0x4003)); 2071 */ 2072 2073 /* Set in individual lane mode, Disable PLL Sequencer: 0x8000=0x063f */ 2074 SOC_IF_ERROR_RETURN 2075 (WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x063f)); 2076 2077 /* Force VCO based on current operating frequency */ 2078 SOC_IF_ERROR_RETURN 2079 (READ_XGXS16G_PLL_PLLSTATUSr(unit, pc, &pll_mode)); 2080 pll_mode &= 2081 (PLL_PLLSTATUS_PLL_MODE_AFE_MASK | PLL_PLLSTATUS_RESERVED0_MASK); 2082 SOC_IF_ERROR_RETURN 2083 (READ_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, &data)); 2084 data &= ~SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_MASK; 2085 data |= SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SEL_MASK | 2086 (pll_mode << SERDESDIGITAL_MISC1_FORCE_PLL_MODE_AFE_SHIFT); 2087 SOC_IF_ERROR_RETURN 2088 (WRITE_XGXS16G_SERDESDIGITAL_MISC1r(unit, pc, data)); 2089 2090 /* Disable asymmetric mode for 40nm UC_B0 */ 2091 if(XGXS16G_13G_REV_B0(pc)){ 2092 SOC_IF_ERROR_RETURN 2093 (MODIFY_XGXS16G_XGXSBLK8_TXLNSWAP1r(unit, pc, 0, 2094 XGXSBLK8_TXLNSWAP1_ASYMM_EN_MASK)); 2095 } 2096 2097 /* Turn AN off: 0x0=0x0 */ 2098 SOC_IF_ERROR_RETURN 2099 (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &data)); 2100 data &= ~IEEE0BLK_IEEECONTROL0_AUTONEG_ENABLE_MASK; 2101 SOC_IF_ERROR_RETURN 2102 (WRITE_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, 0)); 2103 2104 /* Turn CL36 PCS off: 0x8015=0x0 */ 2105 SOC_IF_ERROR_RETURN 2106 (WRITE_XGXS16G_XGXSBLK1_LANECTRL0r(unit, pc, 0)); 2107 2108 /* Put port in loopback if requested */ 2109 data = ((value & 0x8000) == 0x8000) ? 2110 XGXSBLK1_LANECTRL2_GLOOP1G_MASK : 0; 2111 /* CDED & EDEN off: 0x8017 */ 2112 SOC_IF_ERROR_RETURN 2113 (WRITE_XGXS16G_XGXSBLK1_LANECTRL2r(unit, pc, data)); 2114 2115 /* PRBS Polynomial for all lanes: 0x8019=0x8888 */ 2116 SOC_IF_ERROR_RETURN 2117 (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data)); 2118 data |= 0x8888; 2119 SOC_IF_ERROR_RETURN 2120 (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data)); 2121 2122 /* Enable PRBS read: 0x80f1=0x1c47 */ 2123 SOC_IF_ERROR_RETURN 2124 (WRITE_XGXS16G_RX_ALL_RX_CONTROLr(unit, pc, 0x1c47)); 2125 2126 /* Enable PLL Sequencer: 0x8000=0x263f */ 2127 SOC_IF_ERROR_RETURN 2128 (WRITE_XGXS16G_XGXSBLK0_XGXSCONTROLr(unit, pc, 0x263f)); 2129 2130 /* Delay a while */ 2131 sal_usleep(250000); 2132 } else { 2133 /* Restore port */ 2134 return phy_xgxs16g1l_init(unit, port); 2135 } 2136 return SOC_E_NONE; 2137 } 2138 2139 STATIC int 2140 _phy_xgxs16g1l_control_prbs_tx_enable_set(int unit, soc_port_t port, uint32 value) 2141 { 2142 SOC_IF_ERROR_RETURN( 2143 _phy_xgxs16g1l_control_xgxs_prbs_tx_enable_set(unit, port, value)); 2144 return SOC_E_NONE; 2145 } 2146 2147 2148 STATIC int 2149 _phy_xgxs16g1l_control_prbs_tx_rx_enable_get(int unit, soc_port_t port, 2150 uint32 *value) 2151 { 2152 uint16 data; 2153 uint16 inv_shifter = 0; 2154 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2155 /* 2156 * Hypercore PRBS - note that in the Hypercore there is only 1 enable 2157 * for both TX/RX 2158 */ 2159 SOC_IF_ERROR_RETURN 2160 (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data)); 2161 inv_shifter = (XGXSBLK1_LANEPRBS_PRBS_ORDER1_SHIFT * pc->lane_num) + 2162 XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT; 2163 data &= (1 << inv_shifter); 2164 *value = (data) ? 1 : 0; 2165 2166 return SOC_E_NONE; 2167 } 2168 2169 STATIC int 2170 _phy_xgxs16g1l_control_prbs_tx_enable_get(int unit, soc_port_t port, uint32 *value) 2171 { 2172 return _phy_xgxs16g1l_control_prbs_tx_rx_enable_get(unit, port, value); 2173 } 2174 2175 STATIC int 2176 _phy_xgxs16g1l_control_prbs_rx_enable_set(int unit, soc_port_t port, uint32 value) 2177 { 2178 uint16 data; 2179 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2180 uint32 lane_mask = 1 << (PHY_XGXS16G_LANEPRBS_LANE_SHIFT * pc->lane_num); 2181 2182 SOC_IF_ERROR_RETURN 2183 (READ_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, &data)); 2184 2185 if (value) { 2186 data |= lane_mask << XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT; 2187 } else { 2188 data &= ~(lane_mask << XGXSBLK1_LANEPRBS_PRBS_EN0_SHIFT); 2189 } 2190 2191 /* write back updated configuration */ 2192 SOC_IF_ERROR_RETURN 2193 (WRITE_XGXS16G_XGXSBLK1_LANEPRBSr(unit, pc, data)); 2194 2195 /* Set up status collection */ 2196 /* uPrbsRxControlReg = 0x80b1; 2197 * uPrbsRxControlReg += uLaneAddr * 0x10; 2198 */ 2199 SOC_IF_ERROR_RETURN 2200 (XGXS16G_REG_READ(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), &data)); 2201 2202 data &= ~RX0_RX_CONTROL_STATUS_SEL_MASK; 2203 if (value) { 2204 data |= RX0_RX_CONTROL_STATUS_SEL_prbsStatus; 2205 } else { 2206 data &= ~RX0_RX_CONTROL_STATUS_SEL_prbsStatus; 2207 } 2208 2209 SOC_IF_ERROR_RETURN 2210 (XGXS16G_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), data)); 2211 2212 return SOC_E_NONE; 2213 } 2214 2215 STATIC int 2216 _phy_xgxs16g1l_control_prbs_rx_enable_get(int unit, soc_port_t port, uint32 *value) 2217 { 2218 return _phy_xgxs16g1l_control_prbs_tx_rx_enable_get(unit, port, value); 2219 } 2220 2221 /* 2222 * Returns value 2223 * == 0: PRBS receive is in sync 2224 * == -1: PRBS receive never got into sync 2225 * == n: number of errors 2226 */ 2227 STATIC int 2228 _phy_xgxs16g1l_control_xgxs_prbs_rx_status_get(int unit, soc_port_t port, 2229 uint32 *value) 2230 { 2231 /*int lane;*/ 2232 uint16 data; 2233 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port);; 2234 2235 2236 /* Get status for one of the 4 lanes and check for sync 2237 * 0x80b0, 0x80c0, 0x80d0, 0x80e0 2238 */ 2239 *value = 0; 2240 2241 SOC_IF_ERROR_RETURN 2242 (XGXS16G_REG_READ(unit, pc, 0x0, 0x80b0 + (0x10 * pc->lane_num), &data)); 2243 if (data == (RX0_RX_STATUS_PRBS_STATUS_PRBS_LOCK_BITS << 2244 RX0_RX_STATUS_PRBS_STATUS_PRBS_LOCK_SHIFT)) { 2245 /* PRBS is in sync */ 2246 } else if (data == 0) { 2247 /* PRBS not in sync */ 2248 *value = -1; 2249 } else { 2250 /* Get errors */ 2251 *value += data & RX0_RX_STATUS_PRBS_STATUS_PTBS_ERRORS_MASK; 2252 } 2253 return SOC_E_NONE; 2254 } 2255 2256 2257 STATIC int 2258 _phy_xgxs16g1l_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value) 2259 { 2260 int rv; 2261 uint16 rx_sts, saved_rx_sts; 2262 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2263 2264 /* Set up prbs rx status collection */ 2265 SOC_IF_ERROR_RETURN 2266 (XGXS16G_REG_READ(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), &rx_sts)); 2267 saved_rx_sts = rx_sts; 2268 rx_sts = (rx_sts & ~RX0_RX_CONTROL_STATUS_SEL_MASK) | 2269 RX0_RX_CONTROL_STATUS_SEL_prbsStatus; 2270 SOC_IF_ERROR_RETURN 2271 (XGXS16G_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), rx_sts)); 2272 2273 rv = _phy_xgxs16g1l_control_xgxs_prbs_rx_status_get(unit, port, value); 2274 2275 2276 /* Restore rx status */ 2277 SOC_IF_ERROR_RETURN 2278 (XGXS16G_REG_WRITE(unit,pc,0x0,0x80B1 + (0x10 * pc->lane_num), saved_rx_sts)); 2279 2280 return rv; 2281 } 2282 2283 STATIC int 2284 _phy_xgxs16g1l_control_vco_disturbed_get(int unit, soc_port_t port, uint32 *value) 2285 { 2286 uint16 data; 2287 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2288 if(!pc) { 2289 return SOC_E_NONE; 2290 } 2291 SOC_IF_ERROR_RETURN(READ_XGXS16G_SERDESDIGITAL_PATGENCTRLr(unit, pc, &data)); 2292 SOC_IF_ERROR_RETURN(MODIFY_XGXS16G_SERDESDIGITAL_PATGENCTRLr(unit, pc, 0, SERDESDIGITAL_PATGENCTRL_PKT_SIZE_MASK)); 2293 2294 *value = (data & SERDESDIGITAL_PATGENCTRL_PKT_SIZE_MASK) ? 1 : 0; 2295 2296 return SOC_E_NONE; 2297 } 2298 2299 STATIC int 2300 _phy_xgxs16g1l_control_vco_disturbed_set(int unit, soc_port_t port) 2301 { 2302 uint16 data, mask; 2303 phy_ctrl_t *pc = INT_PHY_SW_STATE(unit, port); 2304 if(!pc) { 2305 return SOC_E_NONE; 2306 } 2307 data = 1 << SERDESDIGITAL_PATGENCTRL_PKT_SIZE_SHIFT; 2308 mask = SERDESDIGITAL_PATGENCTRL_PKT_SIZE_MASK; 2309 2310 SOC_IF_ERROR_RETURN(MODIFY_XGXS16G_SERDESDIGITAL_PATGENCTRLr(unit, pc, data, mask)); 2311 2312 return SOC_E_NONE; 2313 } 2314 2315 2316 /* 2317 * Function: 2318 * phy_xgxs16g1l_control_set 2319 * Purpose: 2320 * Configure PHY device specific control fucntion. 2321 * Parameters: 2322 * unit - StrataSwitch unit #. 2323 * port - StrataSwitch port #. 2324 * type - Control to update 2325 * value - New setting for the control 2326 * Returns: 2327 * SOC_E_NONE 2328 */ 2329 STATIC int 2330 phy_xgxs16g1l_control_set(int unit, soc_port_t port, 2331 soc_phy_control_t type, uint32 value) 2332 { 2333 int rv; 2334 phy_ctrl_t *pc; 2335 /* coverity[mixed_enums] */ 2336 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 2337 return SOC_E_PARAM; 2338 } 2339 2340 pc = INT_PHY_SW_STATE(unit, port); 2341 rv = SOC_E_UNAVAIL; 2342 switch(type) { 2343 case SOC_PHY_CONTROL_PREEMPHASIS: 2344 /* fall through */ 2345 case SOC_PHY_CONTROL_DRIVER_CURRENT: 2346 /* fall through */ 2347 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 2348 rv = _phy_xgxs16g1l_control_tx_driver_set(unit, pc, type, value); 2349 break; 2350 case SOC_PHY_CONTROL_EQUALIZER_BOOST: 2351 rv = MODIFY_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc, value, 2352 RX_ALL_RX_EQ_BOOST_EQUALIZER_CONTROL_MASK); 2353 break; 2354 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 2355 rv = _phy_xgxs16g1l_control_linkdown_transmit_set(unit, port, value); 2356 break; 2357 2358 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 2359 rv = _phy_xgxs16g1l_control_prbs_polynomial_set(unit, port, value); 2360 break; 2361 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 2362 rv = _phy_xgxs16g1l_control_prbs_tx_invert_data_set(unit, port, value); 2363 break; 2364 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 2365 rv = _phy_xgxs16g1l_control_prbs_tx_enable_set(unit, port, value); 2366 break; 2367 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 2368 rv = _phy_xgxs16g1l_control_prbs_rx_enable_set(unit, port, value); 2369 break; 2370 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 2371 /* enable 1000X parallel detect */ 2372 SOC_IF_ERROR_RETURN 2373 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc, 2374 value? SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK:0, SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK)); 2375 rv = SOC_E_NONE; 2376 break; 2377 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 2378 SOC_IF_ERROR_RETURN( 2379 MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, 2380 value ? SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK : 0, 2381 SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK)); 2382 rv = SOC_E_NONE; 2383 break; 2384 default: 2385 rv = (SOC_E_UNAVAIL); 2386 break; 2387 } 2388 return rv; 2389 } 2390 2391 STATIC int 2392 _phy_xgxs16g1l_control_tx_driver_get(int unit, phy_ctrl_t *pc, 2393 soc_phy_control_t type, uint32 *value) 2394 { 2395 uint16 data16; /* Temporary holder of 16 bit reg value */ 2396 2397 /* Read preemphasis/driver/pre-driver current */ 2398 if (XGXS16G_13G_ID(pc) || XGXS16G_2p5G_ID(pc)){ 2399 switch(pc->lane_num){ 2400 case 0: 2401 SOC_IF_ERROR_RETURN 2402 (READ_XGXS13G_040_TX0_ACONTROL1r(unit, pc, &data16)); 2403 break; 2404 case 1: 2405 SOC_IF_ERROR_RETURN 2406 (READ_XGXS13G_040_TX1_ACONTROL1r(unit, pc, &data16)); 2407 break; 2408 case 2: 2409 SOC_IF_ERROR_RETURN 2410 (READ_XGXS13G_040_TX2_ACONTROL1r(unit, pc, &data16)); 2411 break; 2412 case 3: 2413 SOC_IF_ERROR_RETURN 2414 (READ_XGXS13G_040_TX3_ACONTROL1r(unit, pc, &data16)); 2415 break; 2416 default: 2417 SOC_IF_ERROR_RETURN 2418 (READ_XGXS13G_040_TX_ALL_ACONTROL1r(unit, pc, &data16)); 2419 break; 2420 } 2421 switch(type) { 2422 case SOC_PHY_CONTROL_PREEMPHASIS: 2423 *value = (data16 & TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_MASK) >> 2424 TX_ALL_040_TX_DRIVER_PREEMPHASIS_POST_SHIFT; 2425 break; 2426 case SOC_PHY_CONTROL_DRIVER_CURRENT: 2427 *value = (data16 & TX_ALL_040_TX_DRIVER_IDRIVER_MASK) >> 2428 TX_ALL_040_TX_DRIVER_IDRIVER_SHIFT; 2429 break; 2430 default: 2431 /* should never get here */ 2432 return (SOC_E_PARAM); 2433 } 2434 } else { 2435 switch(pc->lane_num){ 2436 case 0: 2437 SOC_IF_ERROR_RETURN 2438 (READ_XGXS16G_TX0_TX_DRIVERr(unit, pc, &data16)); 2439 break; 2440 case 1: 2441 SOC_IF_ERROR_RETURN 2442 (READ_XGXS16G_TX1_TX_DRIVERr(unit, pc, &data16)); 2443 break; 2444 case 2: 2445 SOC_IF_ERROR_RETURN 2446 (READ_XGXS16G_TX2_TX_DRIVERr(unit, pc, &data16)); 2447 break; 2448 case 3: 2449 SOC_IF_ERROR_RETURN 2450 (READ_XGXS16G_TX3_TX_DRIVERr(unit, pc, &data16)); 2451 break; 2452 default: 2453 SOC_IF_ERROR_RETURN 2454 (READ_XGXS16G_TX_ALL_TX_DRIVERr(unit, pc, &data16)); 2455 break; 2456 } 2457 switch(type) { 2458 case SOC_PHY_CONTROL_PREEMPHASIS: 2459 *value = (data16 & TX_ALL_TX_DRIVER_PREEMPHASIS_MASK) >> 2460 TX_ALL_TX_DRIVER_PREEMPHASIS_SHIFT; 2461 break; 2462 case SOC_PHY_CONTROL_DRIVER_CURRENT: 2463 *value = (data16 & TX_ALL_TX_DRIVER_IDRIVER_MASK) >> 2464 TX_ALL_TX_DRIVER_IDRIVER_SHIFT; 2465 break; 2466 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 2467 *value = (data16 & TX_ALL_TX_DRIVER_IPREDRIVER_MASK) >> 2468 TX_ALL_TX_DRIVER_IPREDRIVER_SHIFT; 2469 break; 2470 default: 2471 /* should never get here */ 2472 return (SOC_E_PARAM); 2473 } 2474 } 2475 return (SOC_E_NONE); 2476 } 2477 2478 /* 2479 * Function: 2480 * phy_xgxs16g1l_control_get 2481 * Purpose: 2482 * Get current control settign of the PHY. 2483 * Parameters: 2484 * unit - StrataSwitch unit #. 2485 * port - StrataSwitch port #. 2486 * type - Control to update 2487 * value - (OUT)Current setting for the control 2488 * Returns: 2489 * SOC_E_NONE 2490 */ 2491 STATIC int 2492 phy_xgxs16g1l_control_get(int unit, soc_port_t port, 2493 soc_phy_control_t type, uint32 *value) 2494 { 2495 int rv; 2496 phy_ctrl_t *pc; 2497 uint16 data16; 2498 /* coverity[mixed_enums] */ 2499 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 2500 return (SOC_E_PARAM); 2501 } 2502 2503 pc = INT_PHY_SW_STATE(unit, port); 2504 rv = SOC_E_UNAVAIL; 2505 switch(type) { 2506 case SOC_PHY_CONTROL_PREEMPHASIS: 2507 /* fall through */ 2508 case SOC_PHY_CONTROL_DRIVER_CURRENT: 2509 /* fall through */ 2510 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 2511 rv = _phy_xgxs16g1l_control_tx_driver_get(unit, pc, type, value); 2512 break; 2513 case SOC_PHY_CONTROL_EQUALIZER_BOOST: 2514 SOC_IF_ERROR_RETURN 2515 (READ_XGXS16G_RX0_RX_ANALOGBIAS0r(unit, pc, &data16)); 2516 *value = data16 & RX_ALL_RX_EQ_BOOST_EQUALIZER_CONTROL_MASK; 2517 rv = SOC_E_NONE; 2518 break; 2519 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 2520 rv = _phy_xgxs16g1l_control_linkdown_transmit_get(unit, port, value); 2521 break; 2522 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 2523 rv = _phy_xgxs16g1l_control_prbs_polynomial_get(unit, port, value); 2524 break; 2525 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 2526 rv = _phy_xgxs16g1l_control_prbs_tx_invert_data_get(unit, port, value); 2527 break; 2528 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 2529 rv = _phy_xgxs16g1l_control_prbs_tx_enable_get(unit, port, value); 2530 break; 2531 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 2532 rv = _phy_xgxs16g1l_control_prbs_rx_enable_get(unit, port, value); 2533 break; 2534 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 2535 rv = _phy_xgxs16g1l_control_prbs_rx_status_get(unit, port, value); 2536 break; 2537 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 2538 SOC_IF_ERROR_RETURN 2539 (READ_XGXS16G_SERDESDIGITAL_CONTROL1000X2r(unit, pc,&data16)); 2540 *value = 2541 data16 & SERDESDIGITAL_CONTROL1000X2_ENABLE_PARALLEL_DETECTION_MASK? 2542 TRUE: FALSE; 2543 rv = SOC_E_NONE; 2544 break; 2545 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 2546 SOC_IF_ERROR_RETURN 2547 (READ_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, &data16)); 2548 * value = 2549 data16 & SERDESDIGITAL_CONTROL1000X1_REMOTE_LOOPBACK_MASK? 2550 TRUE : FALSE; 2551 rv = SOC_E_NONE; 2552 break; 2553 case SOC_PHY_CONTROL_VCO_DISTURBED: 2554 rv = _phy_xgxs16g1l_control_vco_disturbed_get(unit, port, value); 2555 break; 2556 default: 2557 rv = (SOC_E_UNAVAIL); 2558 break; 2559 } 2560 return rv; 2561 } 2562 2563 /* 2564 * Function: 2565 * phy_xgxs16g1l_reg_read 2566 * Purpose: 2567 * Routine to read PHY register 2568 * Parameters: 2569 * uint - BCM unit number 2570 * pc - PHY state 2571 * flags - Flags which specify the register type 2572 * phy_reg_addr - Encoded register address 2573 * phy_data - (OUT) Value read from PHY register 2574 * Note: 2575 * This register read function is not thread safe. Higher level 2576 * function that calls this function must obtain a per port lock 2577 * to avoid overriding register page mapping between threads. 2578 */ 2579 STATIC int 2580 phy_xgxs16g1l_reg_read(int unit, soc_port_t port, uint32 flags, 2581 uint32 phy_reg_addr, uint32 *phy_data) 2582 { 2583 uint16 data; /* Temporary holder for phy_data */ 2584 phy_ctrl_t *pc; /* PHY software state */ 2585 2586 pc = INT_PHY_SW_STATE(unit, port); 2587 2588 SOC_IF_ERROR_RETURN 2589 (phy_reg_aer_read(unit, pc, phy_reg_addr, &data)); 2590 2591 *phy_data = data; 2592 2593 return (SOC_E_NONE); 2594 } 2595 2596 /* 2597 * Function: 2598 * phy_xgxs16g1l_reg_write 2599 * Purpose: 2600 * Routine to write PHY register 2601 * Parameters: 2602 * uint - BCM unit number 2603 * pc - PHY state 2604 * flags - Flags which specify the register type 2605 * phy_reg_addr - Encoded register address 2606 * phy_data - Value write to PHY register 2607 * Note: 2608 * This register read function is not thread safe. Higher level 2609 * function that calls this function must obtain a per port lock 2610 * to avoid overriding register page mapping between threads. 2611 */ 2612 STATIC int 2613 phy_xgxs16g1l_reg_write(int unit, soc_port_t port, uint32 flags, 2614 uint32 phy_reg_addr, uint32 phy_data) 2615 { 2616 uint16 data; /* Temporary holder for phy_data */ 2617 phy_ctrl_t *pc; /* PHY software state */ 2618 2619 pc = INT_PHY_SW_STATE(unit, port); 2620 2621 data = (uint16) (phy_data & 0x0000FFFF); 2622 2623 SOC_IF_ERROR_RETURN 2624 (phy_reg_aer_write(unit, pc, phy_reg_addr, data)); 2625 2626 return (SOC_E_NONE); 2627 } 2628 2629 /* 2630 * Function: 2631 * phy_xgxs16g1l_reg_modify 2632 * Purpose: 2633 * Routine to write PHY register 2634 * Parameters: 2635 * uint - BCM unit number 2636 * pc - PHY state 2637 * flags - Flags which specify the register type 2638 * phy_reg_addr - Encoded register address 2639 * phy_mo_data - New value for the bits specified in phy_mo_mask 2640 * phy_mo_mask - Bit mask to modify 2641 * Note: 2642 * This register read function is not thread safe. Higher level 2643 * function that calls this function must obtain a per port lock 2644 * to avoid overriding register page mapping between threads. 2645 */ 2646 STATIC int 2647 phy_xgxs16g1l_reg_modify(int unit, soc_port_t port, uint32 flags, 2648 uint32 phy_reg_addr, uint32 phy_data, 2649 uint32 phy_data_mask) 2650 { 2651 uint16 data; /* Temporary holder for phy_data */ 2652 uint16 mask; 2653 phy_ctrl_t *pc; /* PHY software state */ 2654 2655 pc = INT_PHY_SW_STATE(unit, port); 2656 2657 data = (uint16) (phy_data & 0x0000FFFF); 2658 mask = (uint16) (phy_data_mask & 0x0000FFFF); 2659 2660 SOC_IF_ERROR_RETURN 2661 (phy_reg_aer_modify(unit, pc, phy_reg_addr, data, mask)); 2662 2663 return (SOC_E_NONE); 2664 } 2665 2666 STATIC int 2667 phy_xgxs16g1l_probe(int unit, phy_ctrl_t *pc) 2668 { 2669 uint16 serdes_id0; 2670 uint16 serdes_id2; 2671 soc_info_t *si; 2672 int phy_port; /* physical port number */ 2673 2674 si = &SOC_INFO(unit); 2675 if (soc_feature(unit, soc_feature_logical_port_num)) { 2676 phy_port = si->port_l2p_mapping[pc->port]; 2677 } else { 2678 phy_port = pc->port; 2679 } 2680 2681 SOC_IF_ERROR_RETURN 2682 (READ_XGXS16G_SERDESID_SERDESID0r(unit, pc, &serdes_id0)); 2683 SOC_IF_ERROR_RETURN 2684 (READ_XGXS16G_SERDESID_SERDESID2r(unit, pc, &serdes_id2)); 2685 2686 LOG_INFO(BSL_LS_SOC_PHY, 2687 (BSL_META_U(unit, 2688 "_phy_xgxs16g_probe u=%d p=%d: id0 = 0x%x, id1 = 0x%x\n"), 2689 unit, pc->port, serdes_id0,serdes_id2)); 2690 2691 if (((serdes_id0 & SERDESID_SERDESID0_MODEL_NUMBER_MASK) == 2692 SERDES_ID0_MODEL_NUMBER_XGXS_16G) && 2693 (serdes_id2 & SERDESID_SERDESID2_DR_16G_4L_MASK)) { 2694 LOG_INFO(BSL_LS_SOC_PHY, 2695 (BSL_META_U(unit, 2696 "_phy_xgxs16g_probe u=%d p=%d: xgxs16g\n"), 2697 unit, pc->port)); 2698 /* XGXS16G */ 2699 pc->size = sizeof(XGXS16G_DEV_DESC); 2700 return SOC_E_NONE; 2701 } 2702 2703 if (((serdes_id0 & SERDESID_SERDESID0_MODEL_NUMBER_MASK) == 2704 SERDES_ID0_MODEL_NUMBER_XGXS_16G) && 2705 (serdes_id2 & SERDESID_SERDESID2_DR_13G_4L_MASK)) { 2706 LOG_INFO(BSL_LS_SOC_PHY, 2707 (BSL_META_U(unit, 2708 "_phy_xgxs16g_probe u=%d p=%d: xgxs13g\n"), 2709 unit, pc->port)); 2710 /* XGXS13G new 40nm serdes */ 2711 pc->lane_num = SOC_PORT_BINDEX(unit, phy_port); 2712 pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port)); 2713 if (SOC_IS_TRIUMPH3(unit)) { 2714 pc->lane_num = pc->lane_num % 4; 2715 } else if (pc->lane_num >= 4) { 2716 LOG_WARN(BSL_LS_SOC_PHY, 2717 (BSL_META_U(unit, 2718 "_phy_xgxs16g_probe u=%d p=%d: wrong lane# 0x%x, set to 0\n"), 2719 unit, pc->port, pc->lane_num)); 2720 pc->lane_num = 0; 2721 } 2722 2723 pc->dev_name = "XGXS13G1l"; 2724 2725 pc->size = sizeof(XGXS16G_DEV_DESC); 2726 return SOC_E_NONE; 2727 } 2728 2729 if (((serdes_id0 & SERDESID_SERDESID0_MODEL_NUMBER_MASK) == 0xf) && 2730 (serdes_id2 & SERDESID_SERDESID2_DR_2P5G_SL_MASK)) { 2731 LOG_INFO(BSL_LS_SOC_PHY, 2732 (BSL_META_U(unit, 2733 "_phy_xgxs16g_probe u=%d p=%d: qs40\n"), 2734 unit, pc->port)); 2735 /* quad SGMII new 40nm serdes */ 2736 pc->lane_num = SOC_PORT_BINDEX(unit, phy_port); 2737 pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port)); 2738 pc->chip_num *= 2; 2739 pc->chip_num += pc->lane_num/4; 2740 pc->lane_num %= 4; 2741 2742 if (SOC_IS_TRIUMPH3(unit)) { 2743 pc->lane_num = pc->lane_num % 4; 2744 } else if (pc->lane_num >= 4) { 2745 LOG_WARN(BSL_LS_SOC_PHY, 2746 (BSL_META_U(unit, 2747 "_phy_xgxs16g_probe u=%d p=%d: wrong lane# 0x%x, set to 0\n"), 2748 unit, pc->port, pc->lane_num)); 2749 pc->lane_num = 0; 2750 } 2751 pc->dev_name = "QS40"; 2752 2753 pc->size = sizeof(XGXS16G_DEV_DESC); 2754 return SOC_E_NONE; 2755 } 2756 2757 return SOC_E_NOT_FOUND; 2758 } 2759 2760 STATIC int 2761 phy_xgxs16g1l_notify(int unit, soc_port_t port, 2762 soc_phy_event_t event, uint32 value) 2763 { 2764 int rv; 2765 2766 if (event >= phyEventCount) { 2767 return SOC_E_PARAM; 2768 } 2769 2770 rv = SOC_E_NONE; 2771 switch(event) { 2772 case phyEventInterface: 2773 rv = (_phy_xgxs16g1l_notify_interface(unit, port, value)); 2774 break; 2775 case phyEventDuplex: 2776 rv = (_phy_xgxs16g1l_notify_duplex(unit, port, value)); 2777 break; 2778 case phyEventSpeed: 2779 rv = (_phy_xgxs16g1l_notify_speed(unit, port, value)); 2780 break; 2781 case phyEventStop: 2782 rv = (_phy_xgxs16g1l_notify_stop(unit, port, value)); 2783 break; 2784 case phyEventResume: 2785 rv = (_phy_xgxs16g1l_notify_resume(unit, port, value)); 2786 break; 2787 default: 2788 rv = SOC_E_PARAM; 2789 break; 2790 } 2791 2792 return rv; 2793 } 2794 2795 /* 2796 * Function: 2797 * phy_xgxs16g1l_duplex_set 2798 * Purpose: 2799 * Set the current duplex mode (forced). 2800 * Parameters: 2801 * unit - StrataSwitch unit #. 2802 * port - StrataSwitch port #. 2803 * duplex - Boolean, true indicates full duplex, false indicates half. 2804 * Returns: 2805 * SOC_E_XXX 2806 */ 2807 2808 STATIC int 2809 phy_xgxs16g1l_duplex_set(int unit, soc_port_t port, int duplex) 2810 { 2811 uint16 data16; 2812 phy_ctrl_t *pc; 2813 2814 pc = INT_PHY_SW_STATE(unit, port); 2815 2816 SOC_IF_ERROR_RETURN 2817 (READ_XGXS16G_GP_STATUS_STATUS1000X1r(unit, pc, &data16)); 2818 2819 if (!(data16 & GP_STATUS_STATUS1000X1_SGMII_MODE_MASK)) { 2820 /* 1000X fiber mode, always full duplex */ 2821 duplex = TRUE; 2822 } 2823 2824 data16 = duplex? MII_CTRL_FD: 0; 2825 2826 /* program the duplex setting */ 2827 SOC_IF_ERROR_RETURN 2828 (MODIFY_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, data16,MII_CTRL_FD)); 2829 2830 return SOC_E_NONE; 2831 } 2832 2833 STATIC int 2834 phy_xgxs16g1l_duplex_get(int unit, soc_port_t port, int *duplex) 2835 { 2836 uint16 reg0_16; 2837 uint16 mii_ctrl; 2838 phy_ctrl_t *pc; 2839 2840 pc = INT_PHY_SW_STATE(unit, port); 2841 2842 *duplex = TRUE; 2843 2844 SOC_IF_ERROR_RETURN 2845 (READ_XGXS16G_GP_STATUS_STATUS1000X1r(unit, pc, ®0_16)); 2846 2847 if (reg0_16 & GP_STATUS_STATUS1000X1_SGMII_MODE_MASK) { 2848 2849 /* retrieve the duplex setting in SGMII mode */ 2850 SOC_IF_ERROR_RETURN 2851 (READ_XGXS16G_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl)); 2852 2853 if (mii_ctrl & MII_CTRL_AE) { 2854 SOC_IF_ERROR_RETURN 2855 (READ_XGXS16G_COMBO_IEEE0_AUTONEGLPABILr(unit,pc,®0_16)); 2856 2857 /* make sure link partner is also in SGMII mode 2858 * otherwise fall through to use the FD bit in MII_CTRL reg 2859 */ 2860 if (reg0_16 & MII_ANP_SGMII_MODE) { 2861 if (reg0_16 & MII_ANP_SGMII_FD) { 2862 *duplex = TRUE; 2863 } else { 2864 *duplex = FALSE; 2865 } 2866 return SOC_E_NONE; 2867 } 2868 } 2869 *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE; 2870 } 2871 2872 return SOC_E_NONE; 2873 } 2874 2875 /* 2876 * Variable: 2877 * phy_xgxs16g1l_drv 2878 * Purpose: 2879 * Phy Driver for 10G (XAUI x 4) Serdes PHY. 2880 */ 2881 2882 phy_driver_t phy_xgxs16g1l_ge = { 2883 /* .drv_name = */ "XGXS16G/1 Unicore PHY Driver", 2884 /* .pd_init = */ phy_xgxs16g1l_init, 2885 /* .pd_reset = */ phy_null_reset, 2886 /* .pd_link_get = */ phy_xgxs16g1l_link_get, 2887 /* .pd_enable_set = */ phy_xgxs16g1l_enable_set, 2888 /* .pd_enable_get = */ phy_null_enable_get, 2889 /* .pd_duplex_set = */ phy_xgxs16g1l_duplex_set, 2890 /* .pd_duplex_get = */ phy_xgxs16g1l_duplex_get, 2891 /* .pd_speed_set = */ phy_xgxs16g1l_speed_set, 2892 /* .pd_speed_get = */ phy_xgxs16g1l_speed_get, 2893 /* .pd_master_set = */ phy_null_set, 2894 /* .pd_master_get = */ phy_xgxs16g1l_master_get, 2895 /* .pd_an_set = */ phy_xgxs16g1l_an_set, 2896 /* .pd_an_get = */ phy_xgxs16g1l_an_get, 2897 /* .pd_adv_local_set = */ NULL, /* Deprecated */ 2898 /* .pd_adv_local_get = */ NULL, /* Deprecated */ 2899 /* .pd_adv_remote_get = */ NULL, /* Deprecated */ 2900 /* .pd_lb_set = */ phy_xgxs16g1l_lb_set, 2901 /* .pd_lb_get = */ phy_xgxs16g1l_lb_get, 2902 /* .pd_interface_set = */ phy_null_interface_set, 2903 /* .pd_interface_get = */ phy_xgxs16g1l_interface_get, 2904 /* .pd_ability = */ NULL, /* Deprecated */ 2905 /* .pd_linkup_evt = */ NULL, 2906 /* .pd_linkdn_evt = */ NULL, 2907 /* .pd_mdix_set = */ phy_null_mdix_set, 2908 /* .pd_mdix_get = */ phy_null_mdix_get, 2909 /* .pd_mdix_status_get = */ phy_null_mdix_status_get, 2910 /* .pd_medium_config_set = */ phy_xgxs16g1l_medium_config_set, 2911 /* .pd_medium_config_get = */ NULL, 2912 /* .pd_medium_get = */ phy_xgxs16g1l_medium_get, 2913 /* .pd_cable_diag = */ NULL, 2914 /* .pd_link_change = */ NULL, 2915 /* .pd_control_set = */ phy_xgxs16g1l_control_set, 2916 /* .pd_control_get = */ phy_xgxs16g1l_control_get, 2917 /* .pd_reg_read = */ phy_xgxs16g1l_reg_read, 2918 /* .pd_reg_write = */ phy_xgxs16g1l_reg_write, 2919 /* .pd_reg_modify = */ phy_xgxs16g1l_reg_modify, 2920 /* .pd_notify = */ phy_xgxs16g1l_notify, 2921 /* .pd_probe = */ phy_xgxs16g1l_probe, 2922 /* .pd_ability_advert_set = */ phy_xgxs16g1l_ability_advert_set, 2923 /* .pd_ability_advert_get = */ phy_xgxs16g1l_ability_advert_get, 2924 /* .pd_ability_remote_get = */ phy_xgxs16g1l_ability_remote_get, 2925 /* .pd_ability_local_get = */ phy_xgxs16g1l_ability_local_get 2926 }; 2927 2928 /*********************************************************************** 2929 * 2930 * PASS-THROUGH NOTIFY ROUTINES 2931 */ 2932 2933 /* 2934 * Function: 2935 * phy_xgxs16g1l_notify_duplex 2936 * Purpose: 2937 * Program duplex if (and only if) 56xxx is an intermediate PHY. 2938 * Parameters: 2939 * unit - StrataSwitch unit #. 2940 * port - StrataSwitch port #. 2941 * duplex - Boolean, TRUE indicates full duplex, FALSE 2942 * indicates half. 2943 * Returns: 2944 * SOC_E_XXX 2945 * Notes: 2946 * If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to 2947 * talk directly to an external fiber module. 2948 * 2949 * If PHY_FLAGS_FIBER is clear, the PHY is being used in 2950 * pass-through mode to talk to an external SGMII PHY. 2951 * 2952 * When used in SGMII mode, autoneg must be turned off and 2953 * the speed/duplex forced to match that of the external PHY. 2954 */ 2955 STATIC int 2956 _phy_xgxs16g1l_notify_duplex(int unit, soc_port_t port, uint32 duplex) 2957 { 2958 int fiber; 2959 2960 fiber = PHY_FIBER_MODE(unit, port); 2961 LOG_INFO(BSL_LS_SOC_PHY, 2962 (BSL_META_U(unit, 2963 "_phy_xgxs16g1l_notify_duplex: " 2964 "u=%d p=%d duplex=%d fiber=%d\n"), 2965 unit, port, duplex, fiber)); 2966 2967 if (SAL_BOOT_SIMULATION) { 2968 return SOC_E_NONE; 2969 } 2970 2971 /* Put SERDES PHY in reset */ 2972 2973 SOC_IF_ERROR_RETURN 2974 (_phy_xgxs16g1l_notify_stop(unit, port, PHY_STOP_DUPLEX_CHG)); 2975 2976 SOC_IF_ERROR_RETURN 2977 (phy_xgxs16g1l_duplex_set(unit,port,duplex)); 2978 2979 /* Take SERDES PHY out of reset */ 2980 SOC_IF_ERROR_RETURN 2981 (_phy_xgxs16g1l_notify_resume(unit, port, PHY_STOP_DUPLEX_CHG)); 2982 2983 /* Autonegotiation must be turned off to talk to external PHY if 2984 * SGMII autoneg is not enabled. 2985 */ 2986 if (!PHY_SGMII_AUTONEG_MODE(unit, port)) { 2987 SOC_IF_ERROR_RETURN 2988 (phy_xgxs16g1l_an_set(unit, port, FALSE)); 2989 } 2990 return SOC_E_NONE; 2991 } 2992 2993 /* 2994 * Function: 2995 * phy_xgxs16g1l_notify_speed 2996 * Purpose: 2997 * Program duplex if (and only if) 56xxx is an intermediate PHY. 2998 * Parameters: 2999 * unit - StrataSwitch unit #. 3000 * port - StrataSwitch port #. 3001 * speed - Speed to program. 3002 * Returns: 3003 * SOC_E_XXX 3004 * Notes: 3005 * If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to 3006 * talk directly to an external fiber module. 3007 * 3008 * If PHY_FLAGS_FIBER is clear, the PHY is being used in 3009 * pass-through mode to talk to an external SGMII PHY. 3010 * 3011 * When used in pass-through mode, autoneg must be turned off and 3012 * the speed/duplex forced to match that of the external PHY. 3013 */ 3014 3015 STATIC int 3016 _phy_xgxs16g1l_notify_speed(int unit, soc_port_t port, uint32 speed) 3017 { 3018 /* Put SERDES PHY in reset */ 3019 SOC_IF_ERROR_RETURN 3020 (_phy_xgxs16g1l_notify_stop(unit, port, PHY_STOP_SPEED_CHG)); 3021 3022 /* Update speed */ 3023 SOC_IF_ERROR_RETURN 3024 (phy_xgxs16g1l_speed_set(unit, port, speed)); 3025 3026 /* Take SERDES PHY out of reset */ 3027 SOC_IF_ERROR_RETURN 3028 (_phy_xgxs16g1l_notify_resume(unit, port, PHY_STOP_SPEED_CHG)); 3029 3030 /* Autonegotiation must be turned off to talk to external PHY */ 3031 if (!PHY_SGMII_AUTONEG_MODE(unit, port) && PHY_EXTERNAL_MODE(unit, port)) { SOC_IF_ERROR_RETURN 3032 (phy_xgxs16g1l_an_set(unit, port, FALSE)); 3033 } 3034 3035 return (SOC_E_NONE); 3036 } 3037 3038 /* 3039 * Function: 3040 * _phy_xgxs16g1l_stop 3041 * Purpose: 3042 * Put 56xxx SERDES in or out of reset depending on conditions 3043 */ 3044 3045 STATIC int 3046 _phy_xgxs16g1l_stop(int unit, soc_port_t port) 3047 { 3048 uint16 mask16,data16; 3049 int stop, copper; 3050 phy_ctrl_t *pc; 3051 3052 pc = INT_PHY_SW_STATE(unit, port); 3053 3054 copper = (pc->stop & 3055 PHY_STOP_COPPER) != 0; 3056 stop = ((pc->stop & 3057 (PHY_STOP_PHY_DIS | 3058 PHY_STOP_DRAIN)) != 0 || 3059 (copper && 3060 (pc->stop & 3061 (PHY_STOP_MAC_DIS | 3062 PHY_STOP_DUPLEX_CHG | 3063 PHY_STOP_SPEED_CHG)) != 0)); 3064 3065 LOG_INFO(BSL_LS_SOC_PHY, 3066 (BSL_META_U(unit, 3067 "phy_xgxs16g1l_stop: u=%d p=%d copper=%d stop=%d flg=0x%x\n"), 3068 unit, port, copper, stop, 3069 pc->stop)); 3070 3071 mask16 = (1 << pc->lane_num); /* rx lane */ 3072 mask16 |= (mask16 << 4); /* add tx lane */ 3073 3074 if (stop) { 3075 mask16 |= 0x800; 3076 data16 = mask16; 3077 } else { 3078 data16 = 0; 3079 } 3080 3081 SOC_IF_ERROR_RETURN 3082 (MODIFY_XGXS16G_XGXSBLK1_LANECTRL3r(unit,pc,data16,mask16)); 3083 3084 return SOC_E_NONE; 3085 } 3086 3087 /* 3088 * Function: 3089 * phy_xgxs16g1l_notify_stop 3090 * Purpose: 3091 * Add a reason to put 56xxx PHY in reset. 3092 * Parameters: 3093 * unit - StrataSwitch unit #. 3094 * port - StrataSwitch port #. 3095 * flags - Reason to stop 3096 * Returns: 3097 * SOC_E_XXX 3098 */ 3099 STATIC int 3100 _phy_xgxs16g1l_notify_stop(int unit, soc_port_t port, uint32 flags) 3101 { 3102 phy_ctrl_t *pc; 3103 3104 pc = INT_PHY_SW_STATE(unit, port); 3105 3106 pc->stop |= flags; 3107 3108 return _phy_xgxs16g1l_stop(unit, port); 3109 } 3110 3111 /* 3112 * Function: 3113 * phy_xgxs16g1l_notify_resume 3114 * Purpose: 3115 * Remove a reason to put 56xxx PHY in reset. 3116 * Parameters: 3117 * unit - StrataSwitch unit #. 3118 * port - StrataSwitch port #. 3119 * flags - Reason to stop 3120 * Returns: 3121 * SOC_E_XXX 3122 */ 3123 STATIC int 3124 _phy_xgxs16g1l_notify_resume(int unit, soc_port_t port, uint32 flags) 3125 { 3126 phy_ctrl_t *pc; 3127 3128 pc = INT_PHY_SW_STATE(unit, port); 3129 3130 pc->stop &= ~flags; 3131 3132 return _phy_xgxs16g1l_stop(unit, port); 3133 } 3134 3135 3136 STATIC int 3137 _phy_xgxs16g1l_notify_interface(int unit, soc_port_t port, uint32 intf) 3138 { 3139 phy_ctrl_t *pc; 3140 uint16 data16; 3141 3142 pc = INT_PHY_SW_STATE(unit, port); 3143 3144 data16 = (intf == SOC_PORT_IF_SGMII) ? 3145 0 : SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; 3146 3147 /* Disable 1000X/SGMII auto detect and force to 1000X. 3148 * 1000X mode is not supported in this driver. 3149 */ 3150 SOC_IF_ERROR_RETURN 3151 (MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, data16, 3152 SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK)); 3153 3154 return SOC_E_NONE; 3155 } 3156 3157 /* 3158 * Function: 3159 * phy_xgxs16g1l_master_get 3160 * Purpose: 3161 * this function is meant for 1000Base-T PHY. Added here to support 3162 * internal PHY regression test 3163 * Parameters: 3164 * unit - StrataSwitch unit #. 3165 * port - StrataSwitch port #. 3166 * master - (OUT) SOC_PORT_MS_* 3167 * Returns: 3168 * SOC_E_NONE 3169 * Notes: 3170 * The master mode is retrieved for the ACTIVE medium. 3171 */ 3172 3173 STATIC int 3174 phy_xgxs16g1l_master_get(int unit, soc_port_t port, int *master) 3175 { 3176 *master = SOC_PORT_MS_NONE; 3177 return SOC_E_NONE; 3178 } 3179 /* 3180 * Function: 3181 * phy_xgxs16g1l_interface_get 3182 * Purpose: 3183 * this function is meant for 1000Base-T PHY. Added here to support 3184 * internal PHY regression test 3185 * Parameters: 3186 * unit - StrataSwitch unit #. 3187 * port - StrataSwitch port #. 3188 * master - (OUT) SOC_PORT_IF_* 3189 * Returns: 3190 * SOC_E_NONE 3191 * Notes: 3192 * Interface mode is retrieved for the ACTIVE medium. 3193 */ 3194 3195 STATIC int 3196 phy_xgxs16g1l_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 3197 { 3198 int speed; 3199 SOC_IF_ERROR_RETURN(phy_xgxs16g1l_speed_get(unit, port, &speed)); 3200 switch(speed) 3201 { 3202 case 10: 3203 case 100: 3204 *pif = SOC_PORT_IF_MII; 3205 break; 3206 case 1000: 3207 case 2500: 3208 default: 3209 *pif = SOC_PORT_IF_GMII; 3210 break; 3211 } 3212 return SOC_E_NONE; 3213 } 3214 3215 /* 3216 * Function: 3217 * phy_xgxs16g1l_medium_config_set 3218 * Purpose: 3219 * set the configured medium the device is operating on. 3220 * Parameters: 3221 * unit - StrataSwitch unit # 3222 * port - Port number 3223 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 3224 * cfg - not used 3225 * Returns: 3226 * SOC_E_XXX 3227 */ 3228 STATIC int 3229 phy_xgxs16g1l_medium_config_set(int unit, soc_port_t port, soc_port_medium_t medium, soc_phy_config_t *cfg) 3230 { 3231 phy_ctrl_t *pc; 3232 uint16 fiber_mode = 0; 3233 3234 pc = INT_PHY_SW_STATE(unit, port); 3235 3236 switch (medium) { 3237 case SOC_PORT_MEDIUM_COPPER: 3238 fiber_mode = 0; 3239 break; 3240 case SOC_PORT_MEDIUM_FIBER: 3241 fiber_mode = SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK; 3242 break; 3243 default: 3244 return SOC_E_PARAM; 3245 } 3246 3247 SOC_IF_ERROR_RETURN(MODIFY_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, fiber_mode, 3248 SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK)); 3249 3250 return SOC_E_NONE; 3251 } 3252 3253 /* 3254 * Function: 3255 * phy_xgxs16g1l_medium_get 3256 * Purpose: 3257 * get the configured medium the device is operating on. 3258 * Parameters: 3259 * unit - StrataSwitch unit # 3260 * port - Port number 3261 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 3262 * cfg - not used 3263 * Returns: 3264 * SOC_E_XXX 3265 */ 3266 STATIC int 3267 phy_xgxs16g1l_medium_get(int unit, soc_port_t port, soc_port_medium_t *medium) 3268 { 3269 phy_ctrl_t *pc; 3270 uint16 data16 = 0; 3271 3272 if (NULL == medium) { 3273 return (SOC_E_PARAM); 3274 } 3275 3276 pc = INT_PHY_SW_STATE(unit, port); 3277 3278 SOC_IF_ERROR_RETURN(READ_XGXS16G_SERDESDIGITAL_CONTROL1000X1r(unit, pc, &data16)); 3279 3280 *medium = data16 & SERDESDIGITAL_CONTROL1000X1_FIBER_MODE_1000X_MASK ? SOC_PORT_MEDIUM_FIBER : SOC_PORT_MEDIUM_COPPER; 3281 3282 return SOC_E_NONE; 3283 } 3284 3285 #ifdef BROADCOM_DEBUG 3286 int _phy_xgxs16g1l_cfg_dump(int unit, soc_port_t port) 3287 { 3288 phy_ctrl_t *pc; 3289 soc_phy_info_t *pi; 3290 XGXS16G_DEV_DESC *pCfg; 3291 3292 pc = INT_PHY_SW_STATE(unit, port); 3293 pCfg = (XGXS16G_DEV_DESC *)(pc + 1); 3294 pi = &SOC_PHY_INFO(unit, port); 3295 3296 LOG_CLI((BSL_META_U(unit, 3297 "serdesid0 0x%04x\n"), pCfg->serdes_id0)); 3298 LOG_CLI((BSL_META_U(unit, 3299 "serdesid2 0x%04x\n"), 3300 pCfg->serdes_id2)); 3301 LOG_CLI((BSL_META_U(unit, 3302 "chip_num 0x%04x\n"), pc->chip_num)); 3303 LOG_CLI((BSL_META_U(unit, 3304 "lane_num 0x%04x\n"), pc->lane_num)); 3305 LOG_CLI((BSL_META_U(unit, 3306 "speedMax 0x%04x\n"), pc->speed_max)); 3307 LOG_CLI((BSL_META_U(unit, 3308 "pc->flags 0x%04x\n"), pc->flags)); 3309 LOG_CLI((BSL_META_U(unit, 3310 "pc->stop 0x%04x\n"), pc->stop)); 3311 LOG_CLI((BSL_META_U(unit, 3312 "pi->phy_flags 0x%04x\n"), pi->phy_flags)); 3313 return 0; 3314 } 3315 #endif 3316 3317 #else 3318 int _phy_xgxs16g1l_not_empty; 3319 #endif /* INCLUDE_XGXS_16G */ 3320