viper.c (29580B)
1 /* 2 * 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 */ 9 10 #include <phymod/phymod.h> 11 #include <phymod/phymod_system.h> 12 #include <phymod/phymod_dispatch.h> 13 #include <phymod/phymod_util.h> 14 #include <phymod/chip/bcmi_viper_xgxs_defs.h> 15 16 #include "../../viper/tier1/viper_inc.h" 17 18 19 #define VMOD_ID0 0x0143 20 #define VMOD_ID1 0xbff0 21 22 #define VXMOD_MODEL 0x8 /*XGXS10G core*/ 23 #define VGMOD_MODEL 0xF /*QUAD_SGMII core*/ 24 25 #define VIPER_NOF_DFES (5) 26 #define VIPER_NOF_LANES_IN_CORE (4) 27 #define VIPER_LANE_SWAP_LANE_MASK (0x3) 28 #define VIPER_PHY_ALL_LANES (0xf) 29 30 #define VIPER_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \ 31 do{\ 32 PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\ 33 (_phy_access)->type = (_core_access)->type; \ 34 (_phy_access)->access.lane_mask = VIPER_PHY_ALL_LANES; \ 35 }while(0) 36 37 38 int viper_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified) 39 { 40 int ioerr = 0 ; 41 int rv = PHYMOD_E_NONE; 42 const phymod_access_t * pm_acc = &core->access; 43 COMBO_ID1r_t id1; 44 COMBO_ID2r_t id2; 45 SERDESID0r_t serdes_id; 46 uint32_t model = 0; 47 *is_identified = 0; 48 49 if (core_id == 0){ 50 ioerr += READ_COMBO_ID1r(pm_acc, &id1); 51 ioerr += READ_COMBO_ID2r(pm_acc, &id2); 52 } else { 53 COMBO_ID1r_SET(id1, (core_id >> 16) & 0xffff); 54 COMBO_ID2r_SET(id2, (core_id & 0xffff)); 55 } 56 57 if ((COMBO_ID1r_GET(id1) == VMOD_ID0) && (COMBO_ID2r_GET(id2) == VMOD_ID1)){ 58 /* PHY IDs match - now check Serdes model */ 59 ioerr += READ_SERDESID0r(pm_acc, &serdes_id); 60 model = SERDESID0r_MODEL_NUMBERf_GET(serdes_id); 61 if ((model == VGMOD_MODEL) || (model == VXMOD_MODEL)){ 62 *is_identified = 1; 63 } 64 } 65 #if 0 66 PHYMOD_VDBG(DBG_CFG, pm_acc, ("%-22s: core_id=%0x identified=%0d adr=%0x lmask=%0x rv=%d\n", 67 __func__, core_id, *is_identified, pm_acc->addr, pm_acc->lane_mask, rv)); 68 #endif 69 rv = ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE; 70 71 return rv; 72 } 73 74 75 int viper_core_info_get(const phymod_core_access_t* core, phymod_core_info_t* info) 76 { 77 uint32_t serdes_id; 78 COMBO_ID1r_t id1; 79 COMBO_ID2r_t id2; 80 char core_name[15]="viper"; 81 const phymod_access_t * pm_acc = &core->access; 82 83 PHYMOD_IF_ERR_RETURN(viper_revid_read(&core->access, &serdes_id)); 84 info->serdes_id = serdes_id; 85 if ((serdes_id & 0x3f) == VXMOD_MODEL) { 86 info->core_version = phymodCoreVersionViperXA0; 87 } else { 88 info->core_version = phymodCoreVersionViperGA0; 89 } 90 PHYMOD_IF_ERR_RETURN 91 (phymod_core_name_get(core, serdes_id, core_name, info)); 92 93 PHYMOD_IF_ERR_RETURN(READ_COMBO_ID1r(pm_acc, &id1)); 94 PHYMOD_IF_ERR_RETURN(READ_COMBO_ID2r(pm_acc, &id2)); 95 96 info->phy_id0 = (uint16_t) id1.v[0]; 97 info->phy_id1 = (uint16_t) id2.v[0]; 98 99 return PHYMOD_E_NONE; 100 } 101 102 /* 103 * The tx swap is TX Digital to Analog 104 * The rx swap is RX Analog to Digital 105 */ 106 int viper_core_lane_map_set(phymod_core_access_t* core, const phymod_lane_map_t* lane_map) 107 { 108 uint32_t pcs_swap = 0, pmd_swap = 0, lane; 109 110 /* SGMIIPLUS2_X4 core doesn't support lane swap */ 111 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&core->access)) { 112 return PHYMOD_E_UNAVAIL; 113 } 114 115 if(lane_map->num_of_lanes != VIPER_NOF_LANES_IN_CORE){ 116 return PHYMOD_E_CONFIG; 117 } 118 119 for( lane = 0; lane < VIPER_NOF_LANES_IN_CORE; lane++){ 120 if(lane_map->lane_map_rx[lane] >= VIPER_NOF_LANES_IN_CORE){ 121 return PHYMOD_E_CONFIG; 122 } 123 pmd_swap += lane_map->lane_map_rx[lane]<<(lane*4); 124 } 125 126 for( lane = 0; lane < VIPER_NOF_LANES_IN_CORE; lane++){ 127 if(lane_map->lane_map_tx[lane] >= VIPER_NOF_LANES_IN_CORE){ 128 return PHYMOD_E_CONFIG; 129 } 130 pcs_swap += lane_map->lane_map_tx[lane]<<(lane*4); 131 } 132 PHYMOD_IF_ERR_RETURN(viper_tx_lane_swap(&core->access, pcs_swap)); 133 134 PHYMOD_IF_ERR_RETURN(viper_rx_lane_swap(&core->access, pmd_swap)); 135 136 return PHYMOD_E_NONE; 137 138 } 139 140 int viper_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map) 141 { 142 uint32_t pmd_swap = 0, pcs_swap = 0, lane; 143 144 /* SGMIIPLUS2_X4 core doesn't support lane swap */ 145 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&core->access)) { 146 return PHYMOD_E_UNAVAIL; 147 } 148 149 PHYMOD_IF_ERR_RETURN(viper_tx_lane_swap_get(&core->access, &pcs_swap)); 150 PHYMOD_IF_ERR_RETURN(viper_rx_lane_swap_get(&core->access, &pmd_swap)); 151 152 for( lane = 0 ; lane < VIPER_NOF_LANES_IN_CORE ; lane++){ 153 /* Deccode each lane from four bits */ 154 lane_map->lane_map_rx[lane] = (pmd_swap >> (lane*4)) & VIPER_LANE_SWAP_LANE_MASK; 155 lane_map->lane_map_tx[lane] = (pcs_swap >> (lane*4)) & VIPER_LANE_SWAP_LANE_MASK; 156 } 157 lane_map->num_of_lanes = VIPER_NOF_LANES_IN_CORE; 158 159 return PHYMOD_E_NONE; 160 } 161 162 163 int viper_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 164 { 165 166 /* Place your code here */ 167 168 return PHYMOD_E_NONE; 169 } 170 171 int viper_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction) 172 { 173 174 /* Place your code here */ 175 176 return PHYMOD_E_NONE; 177 } 178 179 180 int viper_core_pll_sequencer_restart(const phymod_core_access_t* core, uint32_t flags, phymod_sequencer_operation_t operation) 181 { 182 switch (operation) { 183 case phymodSeqOpStop: 184 PHYMOD_IF_ERR_RETURN 185 (viper_pll_sequencer_control(&core->access, 0)); 186 break; 187 case phymodSeqOpStart: 188 PHYMOD_IF_ERR_RETURN 189 (viper_pll_sequencer_control(&core->access, 1)); 190 191 /* PHYMOD_IF_ERR_RETURN 192 (viper_pll_lock_wait(&core->access, 250000)); */ 193 break; 194 case phymodSeqOpRestart: 195 PHYMOD_IF_ERR_RETURN 196 (viper_pll_sequencer_control(&core->access, 0)); 197 198 PHYMOD_IF_ERR_RETURN 199 (viper_pll_sequencer_control(&core->access, 1)); 200 201 /* PHYMOD_IF_ERR_RETURN 202 (viper_pll_lock_wait(&core->access, 250000)); */ 203 break; 204 default: 205 return PHYMOD_E_UNAVAIL; 206 break; 207 } 208 209 return PHYMOD_E_NONE; 210 } 211 212 213 int viper_core_wait_event(const phymod_core_access_t* core, phymod_core_event_t event, uint32_t timeout) 214 { 215 216 217 /* NOT NEED, REMOVE LATER */ 218 219 return PHYMOD_E_NONE; 220 221 } 222 223 224 int viper_phy_rx_restart(const phymod_phy_access_t* phy) 225 { 226 227 /* NOT NEED, REMOVE LATER */ 228 229 return PHYMOD_E_NONE; 230 231 } 232 233 234 int viper_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity) 235 { 236 int rv = PHYMOD_E_NONE; 237 phymod_access_t phy_copy; 238 239 PHYMOD_MEMCPY(&phy_copy, &(phy->access), sizeof(phy_copy)); 240 rv = viper_tx_pol_set(&phy_copy, polarity->tx_polarity); 241 if (rv != PHYMOD_E_NONE) return (rv); 242 243 rv = viper_rx_pol_set(&phy_copy, polarity->rx_polarity); 244 245 return rv; 246 } 247 248 int viper_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity) 249 { 250 int rv = PHYMOD_E_NONE; 251 phymod_access_t phy_copy; 252 253 PHYMOD_MEMCPY(&phy_copy, &(phy->access), sizeof(phy_copy)); 254 255 rv = viper_tx_pol_get(&phy_copy, &polarity->tx_polarity); 256 if (rv != PHYMOD_E_NONE) return (rv); 257 258 rv = viper_rx_pol_get(&phy_copy, &polarity->rx_polarity); 259 260 return rv; 261 } 262 263 264 int viper_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 265 { 266 phymod_access_t phy_copy; 267 int start_lane = 0, num_lane = 0, i; 268 269 PHYMOD_MEMCPY(&phy_copy, &(phy->access), sizeof(phy_copy)); 270 271 PHYMOD_IF_ERR_RETURN 272 (phymod_util_lane_config_get(&phy_copy, &start_lane, &num_lane)); 273 274 for (i = 0; i < num_lane; i++) { 275 phy_copy.lane_mask = 0x1 << (i + start_lane); 276 277 PHYMOD_IF_ERR_RETURN(viper_tx_post_set(&phy_copy, 1, (tx->post & 0xff))); 278 PHYMOD_IF_ERR_RETURN(viper_tx_main_set(&phy_copy, (tx->main & 0xff))); 279 } 280 281 return PHYMOD_E_NONE; 282 283 } 284 285 int viper_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 286 { 287 uint32_t tx_value, enable; 288 phymod_access_t phy_copy; 289 290 PHYMOD_MEMCPY(&phy_copy, &(phy->access), sizeof(phy_copy)); 291 292 PHYMOD_IF_ERR_RETURN(viper_tx_post_get(&phy_copy, &enable, &tx_value)); 293 tx->post = tx_value & 0xff; 294 295 PHYMOD_IF_ERR_RETURN(viper_tx_main_get(&phy_copy, &tx_value)); 296 tx->main = tx_value & 0xff; 297 298 return PHYMOD_E_NONE; 299 } 300 301 302 int viper_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx) 303 { 304 phymod_access_t phy_copy; 305 306 PHYMOD_MEMCPY(&phy_copy, &(phy->access), sizeof(phy_copy)); 307 PHYMOD_IF_ERR_RETURN(viper_rx_pf_set(&phy_copy, rx->peaking_filter.value)); 308 309 return PHYMOD_E_NONE; 310 311 } 312 313 int viper_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx) 314 { 315 uint32_t rx_value; 316 phymod_access_t phy_copy; 317 318 PHYMOD_MEMCPY(&phy_copy, &(phy->access), sizeof(phy_copy)); 319 320 PHYMOD_IF_ERR_RETURN(viper_rx_pf_get(&phy_copy, &rx_value)); 321 rx->peaking_filter.value = rx_value; 322 323 return PHYMOD_E_NONE; 324 325 } 326 327 328 int viper_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset) 329 { 330 331 332 /* Place your code here */ 333 334 335 return PHYMOD_E_NONE; 336 337 } 338 339 int viper_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset) 340 { 341 342 343 /* Place your code here */ 344 345 346 return PHYMOD_E_NONE; 347 348 } 349 350 351 int viper_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 352 { 353 int rv = PHYMOD_E_NONE; 354 int combo = 0; 355 viper_actual_speed_id_t speed_id; 356 357 PHYMOD_IF_ERR_RETURN(viper_actual_speed_get(&phy->access, &speed_id)); 358 if (speed_id == VIPER_SPD_10G_CX4) { 359 combo = 1; 360 } 361 362 if (power->tx | power->rx){ 363 rv = viper_phy_enable_set(&phy->access, 1, combo); 364 } else { 365 rv = viper_phy_enable_set(&phy->access, 0, combo); 366 } 367 368 return rv; 369 } 370 371 int viper_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 372 { 373 374 int rv = PHYMOD_E_NONE; 375 int enable = 0; 376 377 rv = viper_phy_enable_get(&phy->access, &enable); 378 if (rv != PHYMOD_E_NONE) return (rv); 379 power->tx = enable; 380 power->rx = enable; 381 382 return rv; 383 384 } 385 386 387 int viper_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control) 388 { 389 390 391 /*NOT NEED, REMOVE LATER */ 392 393 return PHYMOD_E_NONE; 394 395 } 396 397 int viper_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control) 398 { 399 400 401 /*NOT NEED, REMOVE LATER */ 402 403 return PHYMOD_E_NONE; 404 405 } 406 407 408 int viper_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control) 409 { 410 411 412 /*NOT NEED, REMOVE LATER */ 413 414 return PHYMOD_E_NONE; 415 416 } 417 418 int viper_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control) 419 { 420 421 422 /*NOT NEED, REMOVE LATER */ 423 424 return PHYMOD_E_NONE; 425 426 } 427 428 429 int viper_phy_fec_enable_set(const phymod_phy_access_t* phy, uint32_t enable) 430 { 431 432 433 /*NOT NEED, REMOVE LATER */ 434 435 return PHYMOD_E_NONE; 436 437 } 438 439 int viper_phy_fec_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 440 { 441 442 443 /*NOT NEED, REMOVE LATER */ 444 445 return PHYMOD_E_NONE; 446 447 } 448 449 450 int viper_phy_eee_set(const phymod_phy_access_t* phy, uint32_t enable) 451 { 452 uint32_t lpi_bypass; 453 int rv = PHYMOD_E_NONE ; 454 lpi_bypass = PHYMOD_LPI_BYPASS_GET(enable); 455 enable &= 0x1; 456 if (lpi_bypass) { 457 rv = viper_lpi_enable_set(&phy->access,enable); 458 } else { 459 return PHYMOD_E_UNAVAIL; 460 } 461 462 return rv; 463 } 464 465 int viper_phy_eee_get(const phymod_phy_access_t* phy, uint32_t* enable) 466 { 467 if (PHYMOD_LPI_BYPASS_GET(*enable)) { 468 PHYMOD_IF_ERR_RETURN(viper_lpi_enable_get(&phy->access, enable)); 469 PHYMOD_LPI_BYPASS_SET(*enable); 470 } else { 471 return PHYMOD_E_UNAVAIL; 472 } 473 return PHYMOD_E_NONE; 474 } 475 476 int viper_phy_linkdown_transmit_set(const phymod_phy_access_t* phy, uint32_t enable) 477 { 478 PHYMOD_IF_ERR_RETURN(viper_linkdown_transmit_set(&phy->access, enable)); 479 480 return PHYMOD_E_NONE; 481 } 482 483 int viper_phy_linkdown_transmit_get(const phymod_phy_access_t* phy, uint32_t* enable) 484 { 485 PHYMOD_IF_ERR_RETURN(viper_linkdown_transmit_get(&phy->access, enable)); 486 487 return PHYMOD_E_NONE; 488 } 489 490 int viper_phy_interface_config_set(phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 491 { 492 493 viper_spd_intfc_type_t spd_intf = VIPER_SPD_ILLEGAL; 494 495 if (config->interface_type == phymodInterfaceSGMII) { 496 switch (config->data_rate) { 497 case 10: 498 spd_intf = VIPER_SPD_10_SGMII; 499 break; 500 case 100: 501 spd_intf = VIPER_SPD_100_SGMII; 502 break; 503 case 1000: 504 spd_intf = VIPER_SPD_1000_SGMII; 505 break; 506 default: 507 spd_intf = VIPER_SPD_1000_SGMII; 508 break; 509 } 510 } else if (config->interface_type == phymodInterface1000X) { 511 switch (config->data_rate) { 512 case 100: 513 spd_intf = VIPER_SPD_100_FX; 514 break; 515 case 1000: 516 spd_intf = VIPER_SPD_1000_X1; 517 break; 518 case 2500: 519 spd_intf = VIPER_SPD_2500; 520 break; 521 default: 522 spd_intf = VIPER_SPD_1000_X1; 523 break; 524 } 525 } else if (config->interface_type == phymodInterfaceXAUI) { 526 /* SGMIIPLUS2_X4 core doesn't support 10G */ 527 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&phy->access)) { 528 return PHYMOD_E_UNAVAIL; 529 } 530 531 if (config->data_rate == 10000) { 532 spd_intf = VIPER_SPD_10000_CX4; 533 } 534 } 535 PHYMOD_IF_ERR_RETURN 536 (viper_set_spd_intf(&phy->access, spd_intf)); 537 538 if (config->interface_type == phymodInterfaceXAUI){ 539 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&phy->access)) { 540 return PHYMOD_E_UNAVAIL; 541 } 542 PHYMOD_IF_ERR_RETURN 543 (viper_10G_CX4_compliance_set(&phy->access, 0xe)); 544 } 545 546 return PHYMOD_E_NONE; 547 548 } 549 550 551 int viper_phy_interface_config_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_ref_clk_t ref_clock, phymod_phy_inf_config_t* config) 552 { 553 viper_actual_speed_id_t speed_id; 554 555 PHYMOD_IF_ERR_RETURN(viper_actual_speed_get(&phy->access, &speed_id)); 556 PHYMOD_IF_ERR_RETURN(viper_speed_id_interface_config_get(phy, speed_id, config)); 557 558 return PHYMOD_E_NONE; 559 560 } 561 562 563 int viper_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability_set_type) 564 { 565 viper_an_ability_t value; 566 567 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 568 569 /* check if sgmii or not */ 570 if (PHYMOD_AN_CAP_SGMII_GET(an_ability_set_type)) { 571 switch (an_ability_set_type->sgmii_speed) { 572 case phymod_CL37_SGMII_10M: 573 value.cl37_sgmii_speed = VIPER_CL37_SGMII_10M; 574 break; 575 case phymod_CL37_SGMII_100M: 576 value.cl37_sgmii_speed = VIPER_CL37_SGMII_100M; 577 break; 578 case phymod_CL37_SGMII_1000M: 579 value.cl37_sgmii_speed = VIPER_CL37_SGMII_1000M; 580 break; 581 default: 582 value.cl37_sgmii_speed = VIPER_CL37_SGMII_1000M; 583 break; 584 } 585 } 586 587 /* next check pause */ 588 if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability_set_type) && !PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability_set_type)) { 589 value.an_pause = VIPER_SYMM_PAUSE; 590 } 591 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability_set_type) && !PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability_set_type)) { 592 value.an_pause = VIPER_ASYM_PAUSE; 593 } 594 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability_set_type) && PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability_set_type)) { 595 value.an_pause = VIPER_ASYM_SYMM_PAUSE; 596 } 597 598 PHYMOD_IF_ERR_RETURN(viper_autoneg_local_ability_set(&phy->access, &value)); 599 600 return PHYMOD_E_NONE; 601 } 602 603 int viper_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 604 { 605 viper_an_adv_ability_t value; 606 607 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 608 609 PHYMOD_IF_ERR_RETURN(viper_autoneg_local_ability_get(&phy->access, &value)); 610 switch (value.cl37_sgmii_speed){ 611 case VIPER_CL37_SGMII_10M: 612 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M; 613 break; 614 case VIPER_CL37_SGMII_100M: 615 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M; 616 break; 617 case VIPER_CL37_SGMII_1000M: 618 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M; 619 break; 620 default: 621 break; 622 } 623 624 switch(value.an_pause) { 625 case VIPER_ASYM_PAUSE: 626 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 627 break; 628 case VIPER_SYMM_PAUSE: 629 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 630 break; 631 case VIPER_ASYM_SYMM_PAUSE: 632 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 633 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 634 break; 635 default: 636 break; 637 } 638 639 return PHYMOD_E_NONE; 640 641 } 642 643 644 int viper_phy_autoneg_remote_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 645 { 646 viper_an_adv_ability_t value; 647 648 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 649 650 PHYMOD_IF_ERR_RETURN(viper_autoneg_remote_ability_get(&phy->access, &value)); 651 switch (value.cl37_sgmii_speed){ 652 case VIPER_CL37_SGMII_10M: 653 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M; 654 break; 655 case VIPER_CL37_SGMII_100M: 656 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M; 657 break; 658 case VIPER_CL37_SGMII_1000M: 659 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M; 660 break; 661 default: 662 break; 663 } 664 665 switch(value.an_pause) { 666 case VIPER_ASYM_PAUSE: 667 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 668 break; 669 case VIPER_SYMM_PAUSE: 670 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 671 break; 672 case VIPER_ASYM_SYMM_PAUSE: 673 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 674 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 675 break; 676 default: 677 break; 678 } 679 680 return PHYMOD_E_NONE; 681 } 682 683 684 int viper_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 685 { 686 PHYMOD_IF_ERR_RETURN(viper_autoneg_set(&phy->access, an)); 687 688 return PHYMOD_E_NONE; 689 690 } 691 692 int viper_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done) 693 { 694 695 PHYMOD_IF_ERR_RETURN(viper_autoneg_get(&phy->access, an, an_done)); 696 697 return PHYMOD_E_NONE; 698 699 } 700 701 702 int viper_phy_autoneg_status_get(const phymod_phy_access_t* phy, phymod_autoneg_status_t* status) 703 { 704 return (viper_autoneg_status_get(&phy->access, status)); 705 } 706 707 int viper_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 708 { 709 phymod_core_access_t core_copy; 710 phymod_core_access_t core_copy2; 711 712 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 713 core_copy.access.lane_mask = 0x1; 714 PHYMOD_MEMCPY(&core_copy2, core, sizeof(core_copy2)); 715 716 /* Enable multiple MMD */ 717 PHYMOD_IF_ERR_RETURN(viper_multimmds_set(&core_copy.access, 1)); 718 719 if (init_config->interface.interface_type == phymodInterfaceXAUI){ 720 /* SGMIIPLUS2_X4 core doesn't support 10G */ 721 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&core->access)) { 722 return PHYMOD_E_UNAVAIL; 723 } 724 PHYMOD_IF_ERR_RETURN(viper_multimmds_set(&core_copy.access, 0)); 725 PHYMOD_IF_ERR_RETURN(viper_pll_disable_forced_10G(&core_copy.access)); 726 PHYMOD_IF_ERR_RETURN 727 (viper_xgxs_sel_enable(&core_copy.access, 1)); 728 729 if ((core_copy2.access.lane_mask == 0x1) || (core_copy2.access.lane_mask == 0xf)){ 730 PHYMOD_IF_ERR_RETURN 731 (viper_core_lane_map_set(&core_copy2, &init_config->lane_map)); 732 } 733 PHYMOD_IF_ERR_RETURN(viper_pll_enable_forced_10G(&core_copy.access)); 734 } else { 735 /* Some cores' TXPLL are not stable when reset chip with default cal_th value 0x6. 736 * To get TXPLL stable, change SGMIIPlus2 PLL calibration threshold from 0x6 to 0xc before PLL disable/enable. 737 * To be fixed after ASIC/DEV team confirm the rootcause. 738 */ 739 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&core->access)) { 740 PHYMOD_IF_ERR_RETURN(viper_cal_th_set(&core_copy.access, 0xc)); 741 } 742 743 PHYMOD_IF_ERR_RETURN(viper_pll_disable(&core_copy.access)); 744 PHYMOD_IF_ERR_RETURN 745 (viper_xgxs_sel_enable(&core_copy.access, 1)); 746 /* SGMIIPLUS2_X4 doesn't support lane swap */ 747 if (VIPER_CORE_IS_XGXS_10G_028(&core->access)) { 748 if ((core_copy2.access.lane_mask == 0x1) || (core_copy2.access.lane_mask == 0xf)){ 749 PHYMOD_IF_ERR_RETURN 750 (viper_core_lane_map_set(&core_copy2, &init_config->lane_map)); 751 } 752 } 753 PHYMOD_IF_ERR_RETURN(viper_pll_enable(&core_copy.access)); 754 755 } 756 return PHYMOD_E_NONE; 757 } 758 759 760 int viper_phy_pll_multiplier_get(const phymod_phy_access_t* phy, uint32_t* core_vco_pll_multiplier) 761 { 762 763 /* NOT NEED REMOVE LATER */ 764 765 return PHYMOD_E_NONE; 766 767 } 768 769 770 int viper_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config) 771 { 772 773 /*int pll_restart = 0;*/ 774 const phymod_access_t *pm_acc = &phy->access; 775 phymod_phy_access_t pm_phy_copy; 776 phymod_polarity_t tmp_pol; 777 int start_lane = 0, num_lane = 0, i; 778 779 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 780 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 781 782 PHYMOD_IF_ERR_RETURN 783 (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane)); 784 785 /* set the receive input voltage (differential pk-pk) to 1200 mVppd */ 786 for ( i = 0; i < num_lane; i++){ 787 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 788 789 PHYMOD_IF_ERR_RETURN 790 (viper_rx_large_swing_set(&pm_phy_copy.access, init_config->rx_swing)); 791 } 792 793 /* program the rx/tx polarity */ 794 for (i = 0; i < num_lane; i++) { 795 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 796 tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) >> i & 0x1; 797 tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) >> i & 0x1; 798 PHYMOD_IF_ERR_RETURN 799 (viper_phy_polarity_set(&pm_phy_copy, &tmp_pol)); 800 } 801 802 for(i = 0; i < num_lane; i++) 803 { 804 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 805 /*init hw rx_los:enable signal detect*/ 806 if(init_config->rx_los.rx_los_en) 807 { 808 PHYMOD_IF_ERR_RETURN 809 (viper_signal_detect_set(&pm_phy_copy.access)); 810 } 811 812 /*init hw rx_los:invert signal detect*/ 813 if(init_config->rx_los.rx_los_invert_en) 814 { 815 PHYMOD_IF_ERR_RETURN 816 (viper_signal_invert_set(&pm_phy_copy.access)); 817 } 818 } 819 #if 0 820 for (i = 0; i < num_lane; i++) { 821 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 822 PHYMOD_IF_ERR_RETURN 823 (viper_phy_tx_set(&pm_phy_copy, &init_config->tx[i])); 824 } 825 #endif 826 pm_phy_copy.access.lane_mask = 0x1; 827 828 /* PHYMOD_IF_ERR_RETURN 829 (viper_update_port_mode(pm_acc, &pll_restart)); 830 831 PHYMOD_IF_ERR_RETURN 832 (viper_rx_lane_control_set(pm_acc, 1)); 833 PHYMOD_IF_ERR_RETURN 834 (viper_tx_lane_control_set(pm_acc, TEMOD_TX_LANE_RESET_TRAFFIC_ENABLE)); 835 */ 836 837 return PHYMOD_E_NONE; 838 839 } 840 841 842 int viper_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable) 843 { 844 /*PHYMOD_IF_ERR_RETURN(viper_global_loopback_set(&phy->access, (uint8_t) enable));*/ 845 viper_actual_speed_id_t speed_id; 846 uint32_t fx_mode = 0; 847 848 PHYMOD_IF_ERR_RETURN(viper_actual_speed_get(&phy->access, &speed_id)); 849 850 switch (loopback) { 851 case phymodLoopbackGlobal : 852 if (speed_id == VIPER_SPD_10G_CX4) { 853 /* SGMIIPLUS2_X4 core doesn't support 10G */ 854 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&phy->access)) { 855 return PHYMOD_E_UNAVAIL; 856 } 857 PHYMOD_IF_ERR_RETURN(viper_10g_global_loopback_set(&phy->access, (uint8_t) enable)); 858 } else { 859 PHYMOD_IF_ERR_RETURN(viper_fiber_force_100FX_get(&phy->access, &fx_mode)); 860 if ((speed_id == VIPER_SPD_100M) && fx_mode ){ 861 PHYMOD_IF_ERR_RETURN(viper_100FX_global_loopback_set(&phy->access, (uint8_t) enable)); 862 } else { 863 PHYMOD_IF_ERR_RETURN(viper_global_loopback_set(&phy->access, (uint8_t) enable)); 864 } 865 } 866 break; 867 case phymodLoopbackGlobalPMD : 868 return PHYMOD_E_UNAVAIL; 869 case phymodLoopbackRemotePCS : 870 break; 871 case phymodLoopbackRemotePMD : 872 PHYMOD_IF_ERR_RETURN(viper_remote_loopback_set(&phy->access, speed_id, (uint8_t)enable)); 873 break; 874 default : 875 break; 876 } 877 878 return PHYMOD_E_NONE; 879 } 880 881 int viper_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable) 882 { 883 viper_actual_speed_id_t speed_id; 884 uint32_t fx_mode = 0; 885 886 PHYMOD_IF_ERR_RETURN(viper_actual_speed_get(&phy->access, &speed_id)); 887 888 switch (loopback) { 889 case phymodLoopbackGlobal : 890 if (speed_id == VIPER_SPD_10G_CX4) { 891 /* SGMIIPLUS2_X4 core doesn't support 10G */ 892 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&phy->access)) { 893 return PHYMOD_E_UNAVAIL; 894 } 895 PHYMOD_IF_ERR_RETURN(viper_10g_global_loopback_get(&phy->access, enable)); 896 } else { 897 PHYMOD_IF_ERR_RETURN(viper_fiber_force_100FX_get(&phy->access, &fx_mode)); 898 if ((speed_id == VIPER_SPD_100M) && fx_mode ){ 899 PHYMOD_IF_ERR_RETURN(viper_100FX_global_loopback_get(&phy->access, enable)); 900 } else { 901 PHYMOD_IF_ERR_RETURN(viper_global_loopback_get(&phy->access, enable)); 902 } 903 } 904 break; 905 case phymodLoopbackGlobalPMD : 906 return PHYMOD_E_UNAVAIL; 907 case phymodLoopbackRemotePCS : 908 break; 909 case phymodLoopbackRemotePMD : 910 PHYMOD_IF_ERR_RETURN(viper_remote_loopback_get(&phy->access, speed_id, enable)); 911 break; 912 default : 913 break; 914 } 915 return PHYMOD_E_NONE; 916 } 917 918 919 int viper_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_pmd_locked) 920 { 921 922 923 /* NOT NEED REMOVE LATER */ 924 925 926 *rx_pmd_locked = 1; 927 928 return PHYMOD_E_NONE; 929 930 } 931 932 933 int viper_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status) 934 { 935 viper_actual_speed_id_t speed_id; 936 937 PHYMOD_IF_ERR_RETURN(viper_actual_speed_get(&phy->access, &speed_id)); 938 939 if (speed_id == VIPER_SPD_10G_CX4 ) { 940 /* SGMIIPLUS2_X4 core doesn't support 10G */ 941 if(VIPER_CORE_IS_SGMIIPLUS2_X4(&phy->access)) { 942 return PHYMOD_E_UNAVAIL; 943 } 944 PHYMOD_IF_ERR_RETURN (viper_get_link_status_10G(&phy->access, link_status)); 945 } else { 946 PHYMOD_IF_ERR_RETURN (viper_get_link_status(&phy->access, link_status)); 947 } 948 return PHYMOD_E_NONE; 949 950 951 } 952 953 954 int viper_phy_pcs_userspeed_set(const phymod_phy_access_t* phy, const phymod_pcs_userspeed_config_t* config) 955 { 956 957 958 /* NOT NEED REMOVE LATER */ 959 960 return PHYMOD_E_NONE; 961 962 } 963 964 int viper_phy_pcs_userspeed_get(const phymod_phy_access_t* phy, phymod_pcs_userspeed_config_t* config) 965 { 966 /* NOT NEED REMOVE LATER */ 967 968 return PHYMOD_E_NONE; 969 970 } 971 972 973 int viper_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val) 974 { 975 return(phymod_tsc_iblk_read(&phy->access, reg_addr, val)); 976 } 977 978 979 int viper_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val) 980 { 981 return (phymod_tsc_iblk_write(&phy->access, reg_addr, val)); 982 } 983 984 int viper_phy_rx_ppm_get(const phymod_phy_access_t* phy, uint32_t* rx_ppm) 985 { 986 /* Viper doesn't support rx_ppm which is from DSC. */ 987 return PHYMOD_E_UNAVAIL; 988 } 989 990 int viper_phy_duplex_set(const phymod_phy_access_t* phy, phymod_duplex_mode_t duplex) 991 { 992 viper_duplex_mode_t duplex_mode; 993 994 switch (duplex) { 995 case phymodDuplexHalf: 996 duplex_mode = VIPER_DUPLEX_HALF; 997 break; 998 case phymodDuplexFull: 999 duplex_mode = VIPER_DUPLEX_FULL; 1000 break; 1001 default: 1002 duplex_mode = VIPER_DUPLEX_FULL; 1003 break; 1004 } 1005 PHYMOD_IF_ERR_RETURN(viper_duplex_set(&phy->access, duplex_mode)); 1006 1007 return PHYMOD_E_NONE; 1008 } 1009 1010 int viper_phy_duplex_get(const phymod_phy_access_t* phy, phymod_duplex_mode_t* duplex) 1011 { 1012 viper_duplex_mode_t duplex_mode; 1013 1014 PHYMOD_IF_ERR_RETURN(viper_duplex_get(&phy->access, &duplex_mode)); 1015 switch (duplex_mode) { 1016 case VIPER_DUPLEX_HALF: 1017 *duplex = phymodDuplexHalf; 1018 break; 1019 case VIPER_DUPLEX_FULL: 1020 *duplex = phymodDuplexFull; 1021 break; 1022 default: 1023 *duplex = phymodDuplexFull; 1024 break; 1025 } 1026 1027 return PHYMOD_E_NONE; 1028 } 1029