xgxs5.c (24218B)
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: xgxs.c 8 * Purpose: Broadcom 10/100/1000/2500/10000/12000/13000/16000 SerDes 9 * (SerDes-XGXS5/Unicore) 10 */ 11 12 #include <sal/types.h> 13 #include <sal/core/spl.h> 14 #include <shared/bsl.h> 15 #include <soc/drv.h> 16 #include <soc/debug.h> 17 #include <soc/error.h> 18 #include <soc/phyreg.h> 19 20 #include <soc/phy.h> 21 #include <soc/phy/phyctrl.h> 22 #include <soc/phy/drv.h> 23 24 #include "phydefs.h" /* Must include before other phy related includes */ 25 26 #if defined(INCLUDE_PHY_XGXS5) 27 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 28 #include "phyident.h" 29 #include "phyreg.h" 30 #include "phynull.h" 31 #include "xgxs.h" 32 #include "xgxs5.h" 33 34 STATIC int phy_xgxs5_lb_set(int unit, soc_port_t port, int enable); 35 36 /* 37 * Configure specified port for Independent channel mode operation 38 */ 39 STATIC int 40 _xgxs5_independent_channel_mode_set(int unit, phy_ctrl_t *pc) 41 { 42 SOC_IF_ERROR_RETURN /* Independent Channdel Mode */ 43 (WRITE_PHYXGXS5_BLK0_CTRLr(unit, pc, 0x261f)); 44 45 /* Set all lanes to full rate mode */ 46 SOC_IF_ERROR_RETURN /* Div /1 mode select */ 47 (WRITE_PHYXGXS5_BLK1_LANE_CTRL1r(unit, pc, 0xffff)); 48 49 SOC_IF_ERROR_RETURN /* Set Comma detect and 8/B/10B ON */ 50 (WRITE_PHYXGXS5_BLK1_LANE_CTRL2r(unit, pc, 0xff00)); 51 52 SOC_IF_ERROR_RETURN /* Set 1G link enable & comma_adj_sync_sel */ 53 (WRITE_PHYXGXS5_RXALL_CTRL_PCIEr(unit, pc, 0x9130)); 54 55 return SOC_E_NONE; 56 } 57 58 /* 59 * Function: 60 * phy_xgxs5_init 61 * Purpose: 62 * Initialize xgxs phys 63 * Parameters: 64 * unit - StrataSwitch unit #. 65 * port - StrataSwitch port #. 66 * Returns: 67 * SOC_E_NONE 68 */ 69 70 STATIC int 71 phy_xgxs5_init(int unit, soc_port_t port) 72 { 73 int preemph, idriver, pdriver; 74 int locked; 75 uint16 pll_stat; 76 phy_ctrl_t *pc; 77 soc_timeout_t to; 78 79 pc = INT_PHY_SW_STATE(unit, port); 80 81 if (PHY_SINGLE_LANE_MODE(unit, port)) { 82 SOC_IF_ERROR_RETURN 83 (_xgxs5_independent_channel_mode_set(unit, pc)); 84 } 85 86 /* Power on the Core */ 87 SOC_IF_ERROR_RETURN 88 (MODIFY_PHYXGXS5_BLK1_LANE_TESTr(unit, pc, (1 << 10), (1 << 10))); 89 90 /* Disable PLL State Machine */ 91 SOC_IF_ERROR_RETURN 92 (WRITE_PHYXGXS5_PLL_CTRLr(unit, pc, 0x5006)); 93 94 /* Turn off slowdn_xor */ 95 SOC_IF_ERROR_RETURN 96 (WRITE_PHYXGXS5_PLL_CAP_CTRLr(unit, pc, 0x0000)); 97 98 if (IS_HG_PORT(unit,port)) { 99 if (!PHY_SINGLE_LANE_MODE(unit, port)) { 100 /* 101 * Do this only for regular 10G/12G mode. 102 * Independent Lane mode is configured above. 103 */ 104 SOC_IF_ERROR_RETURN /* Disable LssQ */ 105 (WRITE_PHYXGXS5_BLK0_CTRLr(unit, pc, 0x292f)); 106 } 107 SOC_IF_ERROR_RETURN /* Enable DTE mdio reg mapping */ 108 (WRITE_PHYXGXS5_BLK0_MISC_CTRL1r(unit, pc, 0x0000)); 109 preemph = 0x8; 110 idriver = 0x7; 111 pdriver = 0x9; 112 } else { 113 SOC_IF_ERROR_RETURN /* Enable PMA/PMD mdio reg mapping */ 114 (WRITE_PHYXGXS5_BLK0_MISC_CTRL1r(unit, pc, 0x0200)); 115 preemph = 0xa; 116 idriver = 0xf; 117 pdriver = 0xf; 118 } 119 120 /* Enable PLL state machine */ 121 SOC_IF_ERROR_RETURN 122 (WRITE_PHYXGXS5_PLL_CTRLr(unit, pc, 0xf01e)); 123 124 /* 125 * Transform CX4 pin out on the board to HG pinout 126 */ 127 if (soc_property_port_get(unit, port, spn_CX4_TO_HIGIG, FALSE)) { 128 /* Swap TX lanes */ 129 SOC_IF_ERROR_RETURN /* Enable TX Lane swap */ 130 (WRITE_PHYXGXS5_BLK2_TX_LANE_SWAPr(unit, pc, 0x80e4)); 131 /* Flip TX Lane polarity */ 132 SOC_IF_ERROR_RETURN /* Flip TX Lane polarity */ 133 (WRITE_PHYXGXS5_TXALL_ACTRL0r(unit, pc, 0x1020)); 134 } else { 135 /* If CX4 to HG conversion is enabled, do not allow individual lane 136 * swapping. 137 */ 138 uint16 lane_map, i; 139 uint16 lane, hw_map, chk_map; 140 141 /* Update RX lane map */ 142 lane_map = soc_property_port_get(unit, port, 143 spn_XGXS_RX_LANE_MAP, 0x0123) & 0xffff; 144 145 if (lane_map != 0x0123) { 146 hw_map = 0; 147 chk_map = 0; 148 for (i = 0; i < 4; i++) { 149 lane = (lane_map >> (i * 4)) & 0xf; 150 hw_map |= lane << (i * 2); 151 chk_map |= 1 << lane; 152 } 153 if (chk_map == 0xf) { 154 SOC_IF_ERROR_RETURN /* Enable RX Lane swap */ 155 (MODIFY_PHYXGXS5_BLK2_RX_LANE_SWAPr(unit, pc, 156 0x8000 | hw_map, 0x80ff)); 157 } else { 158 LOG_ERROR(BSL_LS_SOC_PHY, 159 (BSL_META_U(unit, 160 "unit %d port %s: Invalid RX lane map 0x%04x.\n"), 161 unit, SOC_PORT_NAME(unit, port), lane_map)); 162 } 163 } 164 165 /* Update TX lane map */ 166 lane_map = soc_property_port_get(unit, port, 167 spn_XGXS_TX_LANE_MAP, 0x0123) & 0xffff; 168 169 if (lane_map != 0x0123) { 170 hw_map = 0; 171 chk_map = 0; 172 for (i = 0; i < 4; i++) { 173 lane = (lane_map >> (i * 4)) & 0xf; 174 hw_map |= lane << (i * 2); 175 chk_map |= 1 << lane; 176 } 177 if (chk_map == 0xf) { 178 SOC_IF_ERROR_RETURN /* Enable TX Lane swap */ 179 (MODIFY_PHYXGXS5_BLK2_TX_LANE_SWAPr(unit, pc, 180 0x8000 | hw_map, 0x80ff)); 181 } else { 182 LOG_ERROR(BSL_LS_SOC_PHY, 183 (BSL_META_U(unit, 184 "unit %d port %s: Invalid TX lane map 0x%04x.\n"), 185 unit, SOC_PORT_NAME(unit, port), lane_map)); 186 } 187 } 188 } 189 190 /* 191 * Flip TX lane polarity 192 */ 193 if (soc_property_port_get(unit, port, "polarity_swap", FALSE)) { 194 /* Flip TX Lane polarity */ 195 SOC_IF_ERROR_RETURN /* Flip TX Lane polarity */ 196 (WRITE_PHYXGXS5_TXALL_ACTRL0r(unit, pc, 0x1020)); 197 } 198 199 /* Allow config setting to override preemphasis, driver current, 200 * and pre-driver current. 201 */ 202 preemph = soc_property_port_get(unit, port, 203 spn_XGXS_PREEMPHASIS, preemph); 204 preemph = _shr_bit_rev8(preemph) >> 4; 205 idriver = soc_property_port_get(unit, port, 206 spn_XGXS_DRIVER_CURRENT, idriver); 207 idriver = _shr_bit_rev8(idriver) >> 4; 208 pdriver = soc_property_port_get(unit, port, 209 spn_XGXS_PRE_DRIVER_CURRENT, pdriver); 210 pdriver = _shr_bit_rev8(pdriver) >> 4; 211 212 SOC_IF_ERROR_RETURN 213 (WRITE_PHYXGXS5_TXALL_DRIVERr(unit, pc, ((preemph & 0xf) << 12) | 214 ((idriver & 0xf) << 8) | 215 ((pdriver & 0xf) << 4))); 216 217 /* Wait up to 0.1 sec for TX PLL lock. */ 218 soc_timeout_init(&to, 100000, 0); 219 220 locked = 0; 221 while (!soc_timeout_check(&to)) { 222 SOC_IF_ERROR_RETURN 223 (READ_PHYXGXS5_PLL_STATr(unit, pc, &pll_stat)); 224 /* Check pllSeqDone, freqDone, capDone, and ampDone */ 225 locked = ((pll_stat & (0xf000)) == 0xf000); 226 if (locked) { 227 break; 228 } 229 } 230 231 if (!locked) { 232 LOG_ERROR(BSL_LS_SOC_PHY, 233 (BSL_META_U(unit, 234 "unit %d port %s: XGXS PLL did not lock PLL_STAT %04x\n"), 235 unit, SOC_PORT_NAME(unit, port), pll_stat)); 236 } else { 237 LOG_VERBOSE(BSL_LS_SOC_PHY, 238 (BSL_META_U(unit, 239 "unit %d port %s: XGXS PLL locked in %d usec\n"), 240 unit, SOC_PORT_NAME(unit, port), 241 soc_timeout_elapsed(&to))); 242 } 243 244 if (PHY_EXTERNAL_MODE(unit, port)) { 245 if (IS_HG_PORT(unit, port)) { 246 uint16 value; 247 248 /* Enable XgxsNoCC if the HiGig port has external PHY. 249 * XgxsNoCC enables in-band link signaling, per the 802.3ae 250 * standard (|Q| ordered sets). XgxsNoLssQNoCC is legacy 251 * HiG mode, which does not support in-band link signaling. 252 * Current XAUI cores support both 802.3ae compliant 253 * signaling, as well as backwards compatibility with 254 * prior (legacy) protocols. 255 */ 256 SOC_IF_ERROR_RETURN 257 (READ_PHYXGXS5_BLK0_CTRLr(unit, pc, &value)); 258 value &= ~(0x0f00); 259 value |= (1 << 8); 260 SOC_IF_ERROR_RETURN 261 (WRITE_PHYXGXS5_BLK0_CTRLr(unit, pc, value)); 262 } 263 } 264 265 /* clear loopback (just in case) */ 266 SOC_IF_ERROR_RETURN 267 (phy_xgxs5_lb_set(unit, port, FALSE)); 268 269 LOG_INFO(BSL_LS_SOC_PHY, 270 (BSL_META_U(unit, 271 "phy_xgxs5_init: u=%d p=%d\n"), 272 unit, port)); 273 return SOC_E_NONE; 274 } 275 276 /* 277 * Function: 278 * phy_xgxs5_link_get 279 * Purpose: 280 * Get layer2 connection status. 281 * Parameters: 282 * unit - StrataSwitch unit #. 283 * port - StrataSwitch port #. 284 * link - address of memory to store link up/down state. 285 * Returns: 286 * SOC_E_NONE 287 */ 288 289 STATIC int 290 phy_xgxs5_link_get(int unit, soc_port_t port, int *link) 291 { 292 phy_ctrl_t *pc; 293 294 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 295 *link = FALSE; 296 return SOC_E_NONE; 297 } 298 299 pc = INT_PHY_SW_STATE(unit, port); 300 301 if (PHY_SINGLE_LANE_MODE(unit, port)) { 302 uint16 o_misctrl1; 303 uint16 n_misctrl1; 304 uint16 sync_stat; 305 306 SOC_IF_ERROR_RETURN /* Get mdio reg mapping mode */ 307 (READ_PHYXGXS5_BLK0_MISC_CTRL1r(unit, pc, &o_misctrl1)); 308 n_misctrl1 = 0x0000; 309 if (n_misctrl1 != o_misctrl1) { 310 SOC_IF_ERROR_RETURN 311 (WRITE_PHYXGXS5_BLK0_MISC_CTRL1r(unit, pc, n_misctrl1)); 312 } 313 SOC_IF_ERROR_RETURN 314 (READ_PHYXGXS5_IEEE1_LANE_STATr(unit, pc, &sync_stat)); 315 316 if (n_misctrl1 != o_misctrl1) { /* Restore PMA/PMD mdio reg mapping */ 317 SOC_IF_ERROR_RETURN 318 (WRITE_PHYXGXS5_BLK0_MISC_CTRL1r(unit, pc, o_misctrl1)); 319 } 320 321 *link = (sync_stat & 1) ? TRUE : FALSE; 322 } else { 323 uint16 mii_stat; 324 325 SOC_IF_ERROR_RETURN 326 (READ_PHYXGXS5_XAUI_MII_STATr(unit, pc, &mii_stat)); 327 *link = (mii_stat & MII_STAT_LA) ? TRUE : FALSE; 328 } 329 330 return SOC_E_NONE; 331 } 332 333 STATIC int 334 _phy_xgxs5_enable_set(int unit, soc_port_t port, int enable) 335 { 336 uint16 disable_tx_xe; 337 uint16 disable_tx_hg; 338 phy_ctrl_t *pc; 339 340 pc = INT_PHY_SW_STATE(unit, port); 341 342 /* PMA/PMD mapping are different between HG and XE ports. 343 * Therefore, we need two different settings for HG and XE ports. 344 */ 345 if (enable) { 346 disable_tx_xe = 0; /* Clear Tx disable bit for XE*/ 347 disable_tx_hg = 0; /* Clear Tx disable bit for HG*/ 348 } else { 349 disable_tx_xe = (1 << 0); /* Set disable Global PMD TX bit for XE */ 350 disable_tx_hg = (1 << 11); /* Set disable Global PMD TX bit for HG */ 351 } 352 353 if (IS_XE_PORT(unit, port)) { 354 SOC_IF_ERROR_RETURN 355 (MODIFY_PHYXGXS5_XAUI_TX_DISABLEr(unit, pc, disable_tx_xe, 1 << 0)); 356 } else { 357 SOC_IF_ERROR_RETURN 358 (MODIFY_PHYXGXS5_BLK0_MISC_CTRL1r(unit, pc, disable_tx_hg, 359 (1 << 11))); 360 } 361 362 /* hold/release rxSeqStart to disable/enable the Rx */ 363 SOC_IF_ERROR_RETURN 364 (MODIFY_PHYXGXS5_RXALL_CTRLr(unit, pc, 365 (enable) ? 0 : (1 << 15), (1 << 15))); 366 367 return SOC_E_NONE; 368 } 369 370 /* 371 * Function: 372 * phy_xgxs5_enable_set 373 * Purpose: 374 * Enable/Disable phy 375 * Parameters: 376 * unit - StrataSwitch unit #. 377 * port - StrataSwitch port #. 378 * enable - on/off state to set 379 * Returns: 380 * SOC_E_NONE 381 */ 382 383 STATIC int 384 phy_xgxs5_enable_set(int unit, soc_port_t port, int enable) 385 { 386 if (enable) { 387 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 388 } else { 389 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 390 } 391 return _phy_xgxs5_enable_set(unit,port,enable); 392 } 393 /* 394 * Function: 395 * phy_xgxs5_speed_get 396 * Purpose: 397 * Get PHY speed 398 * Parameters: 399 * unit - StrataSwitch unit #. 400 * port - StrataSwitch port #. 401 * speed - current link speed in Mbps 402 * Returns: 403 * SOC_E_NONE 404 */ 405 406 STATIC int 407 phy_xgxs5_speed_get(int unit, soc_port_t port, int *speed) 408 { 409 /* Default speed */ 410 *speed = 10000; 411 412 if (PHY_SINGLE_LANE_MODE(unit, port)) { 413 *speed >>= 2; /* Div by 4 */ 414 } 415 416 COMPILER_REFERENCE(unit); 417 COMPILER_REFERENCE(port); 418 419 return SOC_E_NONE; 420 } 421 422 /* 423 * Function: 424 * phy_xgxs5_lb_set 425 * Purpose: 426 * Put XGXS5/FusionCore in PHY loopback 427 * Parameters: 428 * unit - StrataSwitch unit #. 429 * port - StrataSwitch port #. 430 * enable - binary value for on/off (1/0) 431 * Returns: 432 * SOC_E_NONE 433 */ 434 435 STATIC int 436 phy_xgxs5_lb_set(int unit, soc_port_t port, int enable) 437 { 438 int rv; 439 phy_ctrl_t *pc; 440 uint16 lb_bit; 441 442 rv = SOC_E_NONE; 443 444 pc = INT_PHY_SW_STATE(unit, port); 445 446 if (PHY_SINGLE_LANE_MODE(unit, port)) { 447 SOC_IF_ERROR_RETURN 448 (WRITE_PHYXGXS5_BLK1_LANE_CTRL2r(unit, pc, 449 (enable) ? 0xFF0F : 0xFF00)); 450 return SOC_E_NONE; 451 } 452 453 /* 454 * control RX signal detect, so that a cable is not needed for loopback 455 */ 456 SOC_IF_ERROR_RETURN 457 (MODIFY_PHYXGXS5_RXALL_CTRLr(unit, pc, (enable) ? 0x0010 : 0, 0x0010)); 458 459 /* 460 * control the actual loopback bit 461 */ 462 lb_bit = XGXS5_IEEE_CTRL_LB_ENA; 463 if (IS_XE_PORT(unit, port)) { 464 if (soc_feature(unit, soc_feature_xgxs_v5)) { 465 lb_bit = 1; 466 } 467 } 468 SOC_IF_ERROR_RETURN 469 (MODIFY_PHYXGXS5_XAUI_MII_CTRLr(unit, pc, 470 (enable) ? lb_bit : 0, lb_bit)); 471 472 return rv; 473 } 474 475 /* 476 * Function: 477 * phy_xgxs5_lb_get 478 * Purpose: 479 * Get XGXS5/FusionCore PHY loopback state 480 * Parameters: 481 * unit - StrataSwitch unit #. 482 * port - StrataSwitch port #. 483 * enable - address of location to store binary value for on/off (1/0) 484 * Returns: 485 * SOC_E_NONE 486 */ 487 488 STATIC int 489 phy_xgxs5_lb_get(int unit, soc_port_t port, int *enable) 490 { 491 uint16 reg_val; 492 uint16 lb_bit; 493 phy_ctrl_t *pc; 494 495 pc = INT_PHY_SW_STATE(unit, port); 496 497 if (PHY_SINGLE_LANE_MODE(unit, port)) { 498 SOC_IF_ERROR_RETURN /* Get Loopback status*/ 499 (READ_PHYXGXS5_BLK1_LANE_CTRL2r(unit, pc, ®_val)); 500 501 *enable = ((reg_val & 0x000F) == 0x000f) ? TRUE : FALSE; 502 return SOC_E_NONE; 503 } 504 505 lb_bit = XGXS5_IEEE_CTRL_LB_ENA; 506 if (IS_XE_PORT(unit, port)) { 507 lb_bit = 1; 508 } 509 510 SOC_IF_ERROR_RETURN 511 (READ_PHYXGXS5_XAUI_MII_CTRLr(unit, pc, ®_val)); 512 513 *enable = (reg_val & lb_bit) ? TRUE : FALSE; 514 515 return SOC_E_NONE; 516 } 517 518 STATIC int 519 phy_xgxs5_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 520 { 521 *mode = SOC_PM_MII | SOC_PM_XGMII | SOC_PM_LB_PHY | 522 SOC_PM_PAUSE | SOC_PM_PAUSE_ASYMM; 523 524 if (PHY_SINGLE_LANE_MODE(unit, port)) { 525 *mode |= SOC_PM_2500MB_FD | SOC_PM_3000MB_FD; 526 } else { 527 *mode |= SOC_PM_10GB_FD | SOC_PM_12GB_FD; 528 } 529 530 return SOC_E_NONE; 531 } 532 533 STATIC int 534 _phy_xgxs5_control_tx_driver_set(int unit, phy_ctrl_t *pc, 535 soc_phy_control_t type, uint32 value) 536 { 537 uint16 data; /* Temporary holder of reg value to be written */ 538 uint16 mask; /* Bit mask of reg value to be updated */ 539 540 if (value > 15) { 541 return SOC_E_PARAM; 542 } 543 544 data = mask = 0; 545 switch(type) { 546 case SOC_PHY_CONTROL_PREEMPHASIS: 547 data = _shr_bit_rev8((uint8)value) << 8; 548 mask = 0xF000; 549 break; 550 case SOC_PHY_CONTROL_DRIVER_CURRENT: 551 data = _shr_bit_rev8((uint8)value) << 4; 552 mask = 0x0F00; 553 break; 554 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 555 data = _shr_bit_rev8((uint8)value); 556 mask = 0x00F0; 557 break; 558 default: 559 /* should never get here */ 560 return SOC_E_PARAM; 561 } 562 563 /* Update preemphasis/driver/pre-driver current */ 564 SOC_IF_ERROR_RETURN 565 (MODIFY_PHYXGXS5_TXALL_DRIVERr(unit, pc, data, mask)); 566 567 return SOC_E_NONE; 568 } 569 570 STATIC int 571 _phy_xgxs5_control_tx_driver_get(int unit, phy_ctrl_t *pc, 572 soc_phy_control_t type, uint32 *value) 573 { 574 uint16 data16; /* Temporary holder of 16 bit reg value */ 575 uint8 data8; /* Temporary holder of 8 bit reg value */ 576 577 /* Read preemphasis/driver/pre-driver current */ 578 SOC_IF_ERROR_RETURN 579 (READ_PHYXGXS5_TXALL_DRIVERr(unit, pc, &data16)); 580 581 switch(type) { 582 case SOC_PHY_CONTROL_PREEMPHASIS: 583 data8 = (uint8)((data16 & 0xF000) >> 8); 584 *value = _shr_bit_rev8(data8); 585 break; 586 case SOC_PHY_CONTROL_DRIVER_CURRENT: 587 data8 = (uint8)((data16 & 0x0F00) >> 4); 588 *value = _shr_bit_rev8(data8); 589 break; 590 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 591 data8 = (uint8)(data16 & 0x00F0); 592 *value = _shr_bit_rev8(data8); 593 break; 594 default: 595 /* should never get here */ 596 return SOC_E_PARAM; 597 } 598 599 return SOC_E_NONE; 600 } 601 602 603 /* 604 * Function: 605 * phy_xgxs5_control_set 606 * Purpose: 607 * Configure PHY device specific control fucntion. 608 * Parameters: 609 * unit - StrataSwitch unit #. 610 * port - StrataSwitch port #. 611 * type - Control to update 612 * value - New setting for the control 613 * Returns: 614 * SOC_E_NONE 615 */ 616 STATIC int 617 phy_xgxs5_control_set(int unit, soc_port_t port, 618 soc_phy_control_t type, uint32 value) 619 { 620 int rv; 621 phy_ctrl_t *pc; 622 /* coverity[mixed_enums] */ 623 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 624 return SOC_E_PARAM; 625 } 626 627 pc = INT_PHY_SW_STATE(unit, port); 628 rv = SOC_E_UNAVAIL; 629 switch(type) { 630 case SOC_PHY_CONTROL_PREEMPHASIS: 631 /* fall through */ 632 case SOC_PHY_CONTROL_DRIVER_CURRENT: 633 /* fall through */ 634 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 635 rv = _phy_xgxs5_control_tx_driver_set(unit, pc, type, value); 636 break; 637 default: 638 rv = SOC_E_UNAVAIL; 639 break; 640 } 641 return rv; 642 } 643 644 /* 645 * Function: 646 * phy_xgxs5_control_get 647 * Purpose: 648 * Get current control settign of the PHY. 649 * Parameters: 650 * unit - StrataSwitch unit #. 651 * port - StrataSwitch port #. 652 * type - Control to update 653 * value - (OUT)Current setting for the control 654 * Returns: 655 * SOC_E_NONE 656 */ 657 STATIC int 658 phy_xgxs5_control_get(int unit, soc_port_t port, 659 soc_phy_control_t type, uint32 *value) 660 { 661 int rv; 662 phy_ctrl_t *pc; 663 664 if (NULL == value) { 665 return SOC_E_PARAM; 666 } 667 /* coverity[mixed_enums] */ 668 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 669 return SOC_E_PARAM; 670 } 671 672 pc = INT_PHY_SW_STATE(unit, port); 673 rv = SOC_E_UNAVAIL; 674 switch(type) { 675 case SOC_PHY_CONTROL_PREEMPHASIS: 676 /* fall through */ 677 case SOC_PHY_CONTROL_DRIVER_CURRENT: 678 /* fall through */ 679 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 680 rv = _phy_xgxs5_control_tx_driver_get(unit, pc, type, value); 681 break; 682 default: 683 rv = SOC_E_UNAVAIL; 684 break; 685 } 686 687 return rv; 688 } 689 690 STATIC int 691 _phy_xgxs5_stop(int unit, soc_port_t port) 692 { 693 int stop, copper; 694 phy_ctrl_t *pc; 695 696 pc = INT_PHY_SW_STATE(unit, port); 697 698 copper = (pc->stop & 699 PHY_STOP_COPPER) != 0; 700 701 stop = ((pc->stop & 702 (PHY_STOP_PHY_DIS | 703 PHY_STOP_DRAIN)) != 0 || 704 (copper && 705 (pc->stop & 706 (PHY_STOP_MAC_DIS | 707 PHY_STOP_DUPLEX_CHG | 708 PHY_STOP_SPEED_CHG)) != 0)); 709 710 LOG_INFO(BSL_LS_SOC_PHY, 711 (BSL_META_U(unit, 712 "phy_xgxs5_stop: u=%d p=%d copper=%d stop=%d flg=0x%x\n"), 713 unit, port, copper, stop, 714 pc->stop)); 715 716 717 return _phy_xgxs5_enable_set(unit,port,stop?FALSE:TRUE); 718 } 719 720 /* 721 * Function: 722 * _phy_xgxs5_notify_stop 723 * Purpose: 724 * Add a reason to put serdesxgxs5 PHY in reset. 725 * Parameters: 726 * unit - StrataSwitch unit #. 727 * port - StrataSwitch port #. 728 * flags - Reason to stop 729 * Returns: 730 * SOC_E_XXX 731 */ 732 733 STATIC int 734 _phy_xgxs5_notify_stop(int unit, soc_port_t port, uint32 flags) 735 { 736 INT_PHY_SW_STATE(unit, port)->stop |= flags; 737 return _phy_xgxs5_stop(unit, port); 738 } 739 740 /* 741 * Function: 742 * _phy_xgxs5_notify_resume 743 * Purpose: 744 * Remove a reason to put serdesxgxs5 PHY in reset. 745 * Parameters: 746 * unit - StrataSwitch unit #. 747 * port - StrataSwitch port #. 748 * flags - Reason to stop 749 * Returns: 750 * SOC_E_XXX 751 */ 752 753 STATIC int 754 _phy_xgxs5_notify_resume(int unit, soc_port_t port, uint32 flags) 755 { 756 INT_PHY_SW_STATE(unit, port)->stop &= ~flags; 757 return _phy_xgxs5_stop(unit, port); 758 } 759 760 STATIC int 761 phy_xgxs5_notify(int unit, soc_port_t port, 762 soc_phy_event_t event, uint32 value) 763 { 764 int rv; 765 766 if (event >= phyEventCount) { 767 return SOC_E_PARAM; 768 } 769 770 rv = SOC_E_NONE; 771 switch(event) { 772 case phyEventInterface: 773 break; 774 case phyEventDuplex: 775 break; 776 case phyEventSpeed: 777 break; 778 case phyEventStop: 779 rv = (_phy_xgxs5_notify_stop(unit, port, value)); 780 break; 781 case phyEventResume: 782 rv = (_phy_xgxs5_notify_resume(unit, port, value)); 783 break; 784 case phyEventAutoneg: 785 break; 786 default: 787 rv = SOC_E_UNAVAIL; 788 break; 789 } 790 791 return rv; 792 } 793 794 /* 795 * Variable: 796 * phy_xgxs5_drv 797 * Purpose: 798 * Phy Driver for 10G (XAUI x 4) Serdes PHY. 799 */ 800 801 phy_driver_t phy_xgxs5_hg = { 802 "XGXS5 10G PHY Driver", 803 phy_xgxs5_init, /* Init */ 804 phy_null_reset, /* Reset (dummy) */ 805 phy_xgxs5_link_get, /* Link get */ 806 phy_xgxs5_enable_set, /* Enable set */ 807 phy_null_enable_get, /* Enable get */ 808 phy_null_set, /* Duplex set */ 809 phy_null_one_get, /* Duplex get */ 810 phy_null_speed_set, /* Speed set */ 811 phy_xgxs5_speed_get, /* Speed get */ 812 phy_null_set, /* Master set */ 813 phy_null_zero_get, /* Master get */ 814 phy_null_set, /* ANA set */ 815 phy_null_an_get, /* ANA get */ 816 phy_null_mode_set, /* Local Advert set */ 817 phy_null_mode_get, /* Local Advert get */ 818 phy_null_mode_get, /* Remote Advert get */ 819 phy_xgxs5_lb_set, /* PHY loopback set */ 820 phy_xgxs5_lb_get, /* PHY loopback set */ 821 phy_null_interface_set, /* IO Interface set */ 822 phy_null_interface_get, /* IO Interface get */ 823 phy_xgxs5_ability_get, /* PHY abilities mask */ 824 NULL, /* Link up event */ 825 NULL, /* Link down event */ 826 phy_null_mdix_set, 827 phy_null_mdix_get, 828 phy_null_mdix_status_get, 829 NULL, /* Medium config set */ 830 NULL, /* Medium config get */ 831 phy_null_medium_get, 832 NULL, /* phy_cable_diag */ 833 NULL, /* phy_link_change */ 834 phy_xgxs5_control_set, 835 phy_xgxs5_control_get, 836 phy_xgxs_reg_read, 837 phy_xgxs_reg_write, 838 phy_xgxs_reg_modify, 839 phy_xgxs5_notify /* Notify event */ 840 }; 841 842 #else /* BCM_XGS5_SUPPORT */ 843 int _phy_xgxs5_not_empty; 844 #endif /* BCM_XGS5_SUPPORT */ 845