tscbh.c (156291B)
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_util.h> 13 #include <phymod/phymod_dispatch.h> 14 #include <phymod/chip/bcmi_tscbh_xgxs_defs.h> 15 #include <phymod/chip/tscbh.h> 16 #include "tscbh/tier1/tbhmod.h" 17 #include "tscbh/tier1/tbhmod_sc_lkup_table.h" 18 #include "tscbh/tier1/tbhmod_1588_lkup_table.h" 19 #include "tscbh/tier1/tbhPCSRegEnums.h" 20 #include "blackhawk/tier1/blackhawk_cfg_seq.h" 21 #include "blackhawk/tier1/blackhawk_tsc_enum.h" 22 #include "blackhawk/tier1/blackhawk_tsc_common.h" 23 #include "blackhawk/tier1/blackhawk_tsc_interface.h" 24 #include "blackhawk/tier1/blackhawk_tsc_dependencies.h" 25 #include "blackhawk/tier1/blackhawk_tsc_internal.h" 26 #include "blackhawk/tier1/public/blackhawk_api_uc_vars_rdwr_defns_public.h" 27 #include "blackhawk/tier1/blackhawk_tsc_access.h" 28 29 30 extern unsigned char blackhawk_ucode_rev0[]; 31 extern unsigned int blackhawk_ucode_len_rev0; 32 extern unsigned short blackhawk_ucode_crc_rev0; 33 extern unsigned short blackhawk_ucode_stack_size_rev0; 34 35 extern unsigned char blackhawk_ucode_rev1[]; 36 extern unsigned int blackhawk_ucode_len_rev1; 37 extern unsigned short blackhawk_ucode_crc_rev1; 38 extern unsigned short blackhawk_ucode_stack_size_rev1; 39 40 extern uint32_t spd_id_entry_26[TSCBH_SPEED_ID_TABLE_SIZE][TSCBH_SPEED_ID_ENTRY_SIZE]; 41 extern uint32_t spd_id_entry_25[TSCBH_SPEED_ID_TABLE_SIZE][TSCBH_SPEED_ID_ENTRY_SIZE]; 42 extern uint32_t spd_id_entry_20[TSCBH_SPEED_ID_TABLE_SIZE][TSCBH_SPEED_ID_ENTRY_SIZE]; 43 extern uint32_t am_table_entry[TSCBH_AM_TABLE_SIZE][TSCBH_AM_ENTRY_SIZE]; 44 extern uint32_t um_table_entry[TSCBH_UM_TABLE_SIZE][TSCBH_UM_ENTRY_SIZE]; 45 extern uint32_t speed_priority_mapping_table[TSCBH_SPEED_PRIORITY_MAPPING_TABLE_SIZE][TSCBH_SPEED_PRIORITY_MAPPING_ENTRY_SIZE]; 46 47 extern const ts_table_entry ts_table_rx_sop[TBHMOD_SPEED_MODE_COUNT]; 48 extern const ts_table_entry ts_table_tx_sop[TBHMOD_SPEED_MODE_COUNT]; 49 50 #define TSCBH_SERDES_ID 0x25 /* 0x9008 Main0_serdesID - Serdes ID Register */ 51 52 int tscbh_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified) 53 { 54 PHYID2r_t id2; 55 PHYID3r_t id3; 56 MAIN0_SERDESIDr_t serdesid; 57 int ioerr = 0; 58 59 *is_identified = 0; 60 ioerr += READ_PHYID2r(&core->access, &id2); 61 ioerr += READ_PHYID3r(&core->access, &id3); 62 63 if (PHYID2r_REGID1f_GET(id2) == TSCBH_ID0 && 64 (PHYID3r_REGID2f_GET(id3) == TSCBH_ID1)) { 65 /* PHY IDs match - now check PCS model */ 66 ioerr += READ_MAIN0_SERDESIDr(&core->access, &serdesid); 67 if ( (MAIN0_SERDESIDr_MODEL_NUMBERf_GET(serdesid)) == TSCBH_SERDES_ID) { 68 *is_identified = 1; 69 } 70 } 71 return ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE; 72 } 73 74 75 int tscbh_core_info_get(const phymod_core_access_t* core, phymod_core_info_t* info) 76 { 77 int rv = 0; 78 MAIN0_SERDESIDr_t serdes_id; 79 char core_name[15] = "Tscbh16"; 80 PHYID2r_t id2; 81 PHYID3r_t id3; 82 const phymod_access_t *pm_acc = &core->access; 83 84 rv = READ_MAIN0_SERDESIDr(&core->access, &serdes_id); 85 86 info->serdes_id = MAIN0_SERDESIDr_GET(serdes_id); 87 PHYMOD_IF_ERR_RETURN 88 (phymod_core_name_get(core, MAIN0_SERDESIDr_GET(serdes_id), core_name, info)); 89 info->serdes_id = MAIN0_SERDESIDr_GET(serdes_id); 90 info->core_version = phymodCoreVersionTscbh16; 91 92 PHYMOD_IF_ERR_RETURN(READ_PHYID2r(pm_acc, &id2)); 93 PHYMOD_IF_ERR_RETURN(READ_PHYID3r(pm_acc, &id3)); 94 95 info->phy_id0 = (uint16_t) id2.v[0]; 96 info->phy_id1 = (uint16_t) id3.v[0]; 97 98 return rv; 99 } 100 101 102 int tscbh_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map) 103 { 104 return PHYMOD_E_NONE; 105 } 106 107 108 int tscbh_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 109 { 110 return PHYMOD_E_NONE; 111 112 } 113 114 int tscbh_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction) 115 { 116 return PHYMOD_E_NONE; 117 118 } 119 120 int tscbh_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control) 121 { 122 phymod_firmware_lane_config_t fw_lane_config; 123 phymod_phy_access_t phy_copy; 124 125 PHYMOD_IF_ERR_RETURN (tscbh_phy_firmware_lane_config_get(phy, &fw_lane_config)); 126 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 127 128 switch (tx_control) { 129 case phymodTxTrafficDisable: 130 PHYMOD_IF_ERR_RETURN(tbhmod_tx_lane_control(&phy_copy.access, 0, TBHMOD_TX_LANE_TRAFFIC_DISABLE)); 131 break; 132 case phymodTxTrafficEnable: 133 /* whenever the second inpout which is enable is set, then the thrid parameter is do not care */ 134 PHYMOD_IF_ERR_RETURN(tbhmod_tx_lane_control(&phy_copy.access, 1, TBHMOD_TX_LANE_ILLEGAL)); 135 break; 136 case phymodTxReset: 137 PHYMOD_IF_ERR_RETURN(tbhmod_tx_lane_control(&phy_copy.access, 0, TBHMOD_TX_LANE_RESET)); 138 break; 139 case phymodTxElectricalIdleEnable: 140 if (fw_lane_config.LaneConfigFromPCS == 0) { 141 PHYMOD_IF_ERR_RETURN(blackhawk_electrical_idle_set(&phy_copy.access, 1)); 142 } else { 143 return PHYMOD_E_PARAM; 144 } 145 break; 146 case phymodTxElectricalIdleDisable: 147 PHYMOD_IF_ERR_RETURN(blackhawk_electrical_idle_set(&phy_copy.access, 0)); 148 break; 149 case phymodTxSquelchOn: 150 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_tx_disable(&phy_copy.access, 1)); 151 break; 152 case phymodTxSquelchOff: 153 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_tx_disable(&phy_copy.access, 0)); 154 break; 155 default: 156 return PHYMOD_E_PARAM; 157 } 158 return PHYMOD_E_NONE; 159 160 } 161 162 163 int tscbh_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t *tx_control) 164 { 165 uint8_t tx_disable; 166 int reset, tx_lane; 167 uint32_t lb_enable; 168 phymod_phy_access_t pm_phy_copy; 169 int start_lane, num_lane; 170 171 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 172 /* next program the tx fir taps and driver current based on the input */ 173 PHYMOD_IF_ERR_RETURN 174 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 175 176 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 177 178 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_tx_disable_get(&pm_phy_copy.access, &tx_disable)); 179 180 /* next check if PMD loopback is on */ 181 if (tx_disable) { 182 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_dig_lpbk_get(&pm_phy_copy.access, &lb_enable)); 183 if (lb_enable) tx_disable = 0; 184 } 185 186 if(tx_disable) { 187 *tx_control = phymodTxSquelchOn; 188 } else { 189 PHYMOD_IF_ERR_RETURN(tbhmod_tx_lane_control_get(&pm_phy_copy.access, &reset, &tx_lane)); 190 if (!reset) { 191 *tx_control = phymodTxReset; 192 } else if (!tx_lane) { 193 *tx_control = phymodTxTrafficDisable; 194 } else { 195 *tx_control = phymodTxTrafficEnable; 196 } 197 } 198 return PHYMOD_E_NONE; 199 } 200 201 /*Rx control*/ 202 int tscbh_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control) 203 { 204 phymod_phy_access_t pm_phy_copy; 205 206 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 207 208 switch (rx_control) { 209 case phymodRxReset: 210 PHYMOD_IF_ERR_RETURN(tbhmod_rx_lane_control(&pm_phy_copy.access, 0)); 211 break; 212 case phymodRxSquelchOn: 213 PHYMOD_IF_ERR_RETURN(blackhawk_pmd_force_signal_detect(&pm_phy_copy.access, 1, 0)); 214 break; 215 case phymodRxSquelchOff: 216 PHYMOD_IF_ERR_RETURN(blackhawk_pmd_force_signal_detect(&pm_phy_copy.access, 0, 0)); 217 break; 218 default: 219 return PHYMOD_E_PARAM; 220 } 221 222 return PHYMOD_E_NONE; 223 } 224 225 int tscbh_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control) 226 { 227 int reset, rx_squelch_enable; 228 uint32_t lb_enable; 229 uint8_t force_en, force_val; 230 phymod_phy_access_t pm_phy_copy; 231 232 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 233 234 /* first get the force enabled bit and forced value */ 235 PHYMOD_IF_ERR_RETURN(blackhawk_pmd_force_signal_detect_get(&pm_phy_copy.access, &force_en, &force_val)); 236 237 if (force_en & (!force_val)) { 238 rx_squelch_enable = 1; 239 } else { 240 rx_squelch_enable = 0; 241 } 242 243 /* next check if PMD loopback is on */ 244 if (rx_squelch_enable) { 245 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_dig_lpbk_get(&pm_phy_copy.access, &lb_enable)); 246 if (lb_enable) rx_squelch_enable = 0; 247 } 248 if(rx_squelch_enable) { 249 *rx_control = phymodRxSquelchOn; 250 } else { 251 PHYMOD_IF_ERR_RETURN(tbhmod_rx_lane_control_get(&pm_phy_copy.access, &reset)); 252 if (reset == 0) { 253 *rx_control = phymodRxReset; 254 } else { 255 *rx_control = phymodRxSquelchOff; 256 } 257 } 258 return PHYMOD_E_NONE; 259 260 } 261 262 /* load tscbh fw. the fw_loader parameter is valid just for external fw load*/ 263 STATIC 264 int _tscbh_core_firmware_load(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config) 265 { 266 phymod_core_access_t core_copy; 267 phymod_phy_access_t phy_access; 268 unsigned int blackhawk_ucode_len; 269 unsigned char *blackhawk_ucode; 270 uint32_t rev_num = 0; 271 272 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 273 TSCBH_CORE_TO_PHY_ACCESS(&phy_access, core); 274 275 phy_access.access.lane_mask = 0x1; 276 PHYMOD_IF_ERR_RETURN 277 (tbhmod_revid_get(&phy_access.access, &rev_num)); 278 if (rev_num == TBHMOD_REV_NUM_0) { 279 blackhawk_ucode = blackhawk_ucode_rev0; 280 blackhawk_ucode_len = blackhawk_ucode_len_rev0; 281 } else { 282 blackhawk_ucode = blackhawk_ucode_rev1; 283 blackhawk_ucode_len = blackhawk_ucode_len_rev1; 284 } 285 286 switch(init_config->firmware_load_method){ 287 case phymodFirmwareLoadMethodInternal: 288 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_ucode_mdio_load(&core_copy.access, blackhawk_ucode, blackhawk_ucode_len)); 289 break; 290 case phymodFirmwareLoadMethodExternal: 291 PHYMOD_NULL_CHECK(init_config->firmware_loader); 292 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_ucode_init(&core_copy.access)); 293 PHYMOD_IF_ERR_RETURN 294 (blackhawk_pram_firmware_enable(&core_copy.access, 1, 0)); 295 PHYMOD_IF_ERR_RETURN(init_config->firmware_loader(core, blackhawk_ucode_len, blackhawk_ucode)); 296 PHYMOD_IF_ERR_RETURN 297 (blackhawk_pram_firmware_enable(&core_copy.access, 0, 0)); 298 break; 299 case phymodFirmwareLoadMethodNone: 300 break; 301 default: 302 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), init_config->firmware_load_method)); 303 } 304 305 return PHYMOD_E_NONE; 306 307 } 308 309 int tscbh_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config) 310 { 311 struct blackhawk_tsc_uc_lane_config_st lane_config; 312 phymod_phy_access_t pm_phy_copy; 313 314 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 315 316 PHYMOD_MEMSET(&lane_config, 0x0, sizeof(lane_config)); 317 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 318 319 PHYMOD_IF_ERR_RETURN 320 (blackhawk_tsc_get_uc_lane_cfg(&pm_phy_copy.access, &lane_config)); 321 322 fw_config->LaneConfigFromPCS = lane_config.field.lane_cfg_from_pcs; 323 fw_config->AnEnabled = lane_config.field.an_enabled; 324 fw_config->DfeOn = lane_config.field.dfe_on; 325 fw_config->LpDfeOn = lane_config.field.dfe_lp_mode; 326 fw_config->ForceBrDfe = lane_config.field.force_brdfe_on; 327 fw_config->MediaType = lane_config.field.media_type; 328 fw_config->UnreliableLos = lane_config.field.unreliable_los; 329 fw_config->Cl72AutoPolEn = lane_config.field.cl72_auto_polarity_en; 330 fw_config->ScramblingDisable = lane_config.field.scrambling_dis; 331 fw_config->Cl72RestTO = lane_config.field.cl72_restart_timeout_en; 332 fw_config->ForceExtenedReach = lane_config.field.force_es; 333 fw_config->ForceNormalReach = lane_config.field.force_ns; 334 fw_config->LpPrecoderEnabled = lane_config.field.lp_has_prec_en; 335 fw_config->ForcePAM4Mode = lane_config.field.force_pam4_mode; 336 fw_config->ForceNRZMode = lane_config.field.force_nrz_mode; 337 338 return PHYMOD_E_NONE; 339 } 340 341 int tscbh_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 342 { 343 phymod_phy_access_t phy_copy; 344 int start_lane, num_lane, i; 345 enum blackhawk_tsc_txfir_tap_enable_enum enable_taps = NRZ_6TAP; 346 uint32_t lane_reset, pcs_lane_enable; 347 348 PHYMOD_IF_ERR_RETURN 349 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 350 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 351 352 /*next check if PCS lane is in reset */ 353 PHYMOD_IF_ERR_RETURN 354 (tbhmod_enable_get(&phy_copy.access, &pcs_lane_enable)); 355 356 /*first check if lane is in reset */ 357 PHYMOD_IF_ERR_RETURN 358 (blackhawk_lane_soft_reset_get(&phy_copy.access, &lane_reset)); 359 360 /* disable pcs lane if pcs lane not in rset */ 361 if (pcs_lane_enable) { 362 phy_copy.access.lane_mask = 1 << start_lane; 363 PHYMOD_IF_ERR_RETURN 364 (tbhmod_disable_set(&phy_copy.access)); 365 } 366 if (!lane_reset) { 367 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 368 PHYMOD_IF_ERR_RETURN 369 (blackhawk_lane_soft_reset(&phy_copy.access, 1)); 370 } 371 372 for (i = 0; i < num_lane; i++) { 373 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 374 continue; 375 } 376 phy_copy.access.lane_mask = 1 << (start_lane + i); 377 /*next check 3 tap mode or 6 tap mode */ 378 if (tx->tap_mode == phymodTxTapMode3Tap) { 379 if (tx->sig_method == phymodSignallingMethodNRZ) { 380 enable_taps= NRZ_LP_3TAP; 381 } else { 382 enable_taps= PAM4_LP_3TAP; 383 } 384 PHYMOD_IF_ERR_RETURN 385 (blackhawk_tsc_apply_txfir_cfg(&phy_copy.access, 386 enable_taps, 387 0, 388 tx->pre, 389 tx->main, 390 tx->post, 391 0, 392 0)); 393 } else { 394 if (tx->sig_method == phymodSignallingMethodNRZ) { 395 enable_taps= NRZ_6TAP; 396 } else { 397 enable_taps= PAM4_6TAP; 398 } 399 PHYMOD_IF_ERR_RETURN 400 (blackhawk_tsc_apply_txfir_cfg(&phy_copy.access, 401 enable_taps, 402 tx->pre2, 403 tx->pre, 404 tx->main, 405 tx->post, 406 tx->post2, 407 tx->post3)); 408 } 409 } 410 411 if (!lane_reset) { 412 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 413 PHYMOD_IF_ERR_RETURN 414 (blackhawk_lane_soft_reset(&phy_copy.access, 0)); 415 } 416 417 /* re-enable pcs lane if pcs lane not in rset */ 418 if (pcs_lane_enable) { 419 phy_copy.access.lane_mask = 1 << start_lane; 420 PHYMOD_IF_ERR_RETURN 421 (tbhmod_enable_set(&phy_copy.access)); 422 } 423 return PHYMOD_E_NONE; 424 } 425 426 int tscbh_phy_media_type_tx_get(const phymod_phy_access_t* phy, phymod_media_typed_t media, phymod_tx_t* tx) 427 { 428 429 return PHYMOD_E_NONE; 430 431 } 432 433 434 /* 435 * set lane swapping for core 436 */ 437 438 int tscbh_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map) 439 { 440 phymod_core_access_t core_copy; 441 uint32_t lane, pcs_tx_swap = 0, pcs_rx_swap = 0; 442 uint8_t pmd_tx_addr[8], pmd_rx_addr[8]; 443 444 if (lane_map->num_of_lanes != TSCBH_NOF_LANES_IN_CORE){ 445 return PHYMOD_E_CONFIG; 446 } 447 448 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 449 core_copy.access.lane_mask = 0x1; 450 451 for (lane = 0; lane < TSCBH_NOF_LANES_IN_CORE; lane++){ 452 if ((lane_map->lane_map_tx[lane] >= TSCBH_NOF_LANES_IN_CORE)|| 453 (lane_map->lane_map_rx[lane] >= TSCBH_NOF_LANES_IN_CORE)){ 454 return PHYMOD_E_CONFIG; 455 } 456 /*encode each lane as four bits*/ 457 458 pcs_tx_swap += lane_map->lane_map_tx[lane]<<(lane*4); 459 pcs_rx_swap += lane_map->lane_map_rx[lane]<<(lane*4); 460 } 461 /* PMD lane addr is based on PCS logical to physical mapping*/ 462 for (lane = 0; lane < TSCBH_NOF_LANES_IN_CORE; lane++){ 463 pmd_tx_addr[((pcs_tx_swap >> (lane*4)) & 0xf)] = lane; 464 pmd_rx_addr[((pcs_rx_swap >> (lane*4)) & 0xf)] = lane; 465 } 466 467 PHYMOD_IF_ERR_RETURN 468 (tbhmod_pcs_tx_lane_swap(&core_copy.access, pcs_tx_swap)); 469 PHYMOD_IF_ERR_RETURN 470 (tbhmod_pcs_rx_lane_swap(&core_copy.access, pcs_rx_swap)); 471 PHYMOD_IF_ERR_RETURN 472 (blackhawk_tsc_map_lanes(&core_copy.access, TSCBH_NOF_LANES_IN_CORE, pmd_tx_addr, pmd_rx_addr)); 473 474 return PHYMOD_E_NONE; 475 } 476 477 #if 0 478 STATIC 479 int _tscbh_speed_config_get(uint32_t speed, uint32_t *pll_multiplier, uint32_t *is_pam4, uint32_t *osr_mode) 480 { 481 return PHYMOD_E_NONE; 482 } 483 #endif 484 485 int _tscbh_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 486 { 487 uint32_t is_warm_boot; 488 struct blackhawk_tsc_uc_lane_config_st serdes_firmware_config; 489 phymod_phy_access_t phy_copy; 490 int start_lane, num_lane, i; 491 uint32_t rst_status; 492 493 PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config)); 494 PHYMOD_IF_ERR_RETURN 495 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 496 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 497 498 for (i = 0; i < num_lane; i++) { 499 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 500 continue; 501 } 502 phy_copy.access.lane_mask = 1 << (start_lane + i); 503 serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS; 504 serdes_firmware_config.field.an_enabled = fw_config.AnEnabled; 505 serdes_firmware_config.field.dfe_on = fw_config.DfeOn; 506 serdes_firmware_config.field.force_brdfe_on = fw_config.ForceBrDfe; 507 /* serdes_firmware_config.field.cl72_emulation_en = fw_config.Cl72Enable; */ 508 serdes_firmware_config.field.scrambling_dis = fw_config.ScramblingDisable; 509 serdes_firmware_config.field.unreliable_los = fw_config.UnreliableLos; 510 serdes_firmware_config.field.media_type = fw_config.MediaType; 511 serdes_firmware_config.field.dfe_lp_mode = fw_config.LpDfeOn; 512 serdes_firmware_config.field.cl72_auto_polarity_en = fw_config.Cl72AutoPolEn; 513 serdes_firmware_config.field.cl72_restart_timeout_en = fw_config.Cl72RestTO; 514 serdes_firmware_config.field.force_es = fw_config.ForceExtenedReach; 515 serdes_firmware_config.field.force_ns = fw_config.ForceNormalReach; 516 serdes_firmware_config.field.force_nrz_mode = fw_config.ForceNRZMode; 517 serdes_firmware_config.field.force_pam4_mode = fw_config.ForcePAM4Mode; 518 serdes_firmware_config.field.lp_has_prec_en = fw_config.LpPrecoderEnabled; 519 520 PHYMOD_IF_ERR_RETURN(PHYMOD_IS_WRITE_DISABLED(&phy->access, &is_warm_boot)); 521 522 if (!is_warm_boot) { 523 PHYMOD_IF_ERR_RETURN(blackhawk_lane_soft_reset_get(&phy_copy.access, &rst_status)); 524 if (!rst_status) PHYMOD_IF_ERR_RETURN (blackhawk_lane_soft_reset(&phy_copy.access, 1)); 525 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_set_uc_lane_cfg(&phy_copy.access, serdes_firmware_config)); 526 if (!rst_status) PHYMOD_IF_ERR_RETURN (blackhawk_lane_soft_reset(&phy_copy.access, 0)); 527 } 528 } 529 530 return PHYMOD_E_NONE; 531 } 532 533 int tscbh_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 534 { 535 phymod_phy_access_t phy_copy; 536 uint32_t lane_reset, pcs_lane_enable; 537 int start_lane, num_lane; 538 539 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 540 PHYMOD_IF_ERR_RETURN 541 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 542 543 /*first check if lane is in reset */ 544 PHYMOD_IF_ERR_RETURN 545 (blackhawk_lane_soft_reset_get(&phy_copy.access, &lane_reset)); 546 547 /*next check if PCS lane is in reset */ 548 PHYMOD_IF_ERR_RETURN 549 (tbhmod_enable_get(&phy_copy.access, &pcs_lane_enable)); 550 551 /* disable pcs lane if pcs lane not in rset */ 552 if (pcs_lane_enable) { 553 phy_copy.access.lane_mask = 1 << start_lane; 554 PHYMOD_IF_ERR_RETURN 555 (tbhmod_disable_set(&phy_copy.access)); 556 } 557 558 /* if lane is not in reset, then reset the lane first */ 559 if (!lane_reset) { 560 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 561 PHYMOD_IF_ERR_RETURN 562 (blackhawk_lane_soft_reset(&phy_copy.access, 1)); 563 } 564 565 PHYMOD_IF_ERR_RETURN 566 (_tscbh_phy_firmware_lane_config_set(phy, fw_config)); 567 568 if (!lane_reset) { 569 PHYMOD_IF_ERR_RETURN 570 (blackhawk_lane_soft_reset(&phy_copy.access, 0)); 571 } 572 573 /* re-enable pcs lane if pcs lane not in rset */ 574 if (pcs_lane_enable) { 575 phy_copy.access.lane_mask = 1 << start_lane; 576 PHYMOD_IF_ERR_RETURN 577 (tbhmod_enable_set(&phy_copy.access)); 578 } 579 580 return PHYMOD_E_NONE; 581 } 582 583 584 /* reset rx sequencer 585 * flags - unused parameter 586 */ 587 int tscbh_phy_rx_restart(const phymod_phy_access_t* phy) 588 { 589 590 return PHYMOD_E_NONE; 591 } 592 593 594 int tscbh_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity) 595 { 596 phymod_phy_access_t phy_copy; 597 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 598 599 PHYMOD_IF_ERR_RETURN 600 (blackhawk_tx_rx_polarity_set(&phy_copy.access, polarity->tx_polarity, polarity->rx_polarity)); 601 602 return PHYMOD_E_NONE; 603 } 604 605 606 int tscbh_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity) 607 { 608 int start_lane, num_lane, i; 609 phymod_polarity_t temp_pol; 610 phymod_phy_access_t phy_copy; 611 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 612 613 /* figure out the lane num and start_lane based on the input */ 614 PHYMOD_IF_ERR_RETURN 615 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 616 617 polarity->tx_polarity = 0; 618 polarity->rx_polarity = 0; 619 for (i = 0; i < num_lane; i++) { 620 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 621 continue; 622 } 623 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 624 temp_pol.tx_polarity = 0; 625 temp_pol.rx_polarity = 0; 626 PHYMOD_IF_ERR_RETURN 627 (blackhawk_tx_rx_polarity_get(&phy_copy.access, &temp_pol.tx_polarity, &temp_pol.rx_polarity)); 628 polarity->tx_polarity |= ((temp_pol.tx_polarity & 0x1) << i); 629 polarity->rx_polarity |= ((temp_pol.rx_polarity & 0x1) << i); 630 } 631 632 return PHYMOD_E_NONE; 633 } 634 635 int tscbh_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 636 { 637 uint8_t pmd_tx_tap_mode; 638 uint16_t tx_tap_nrz_mode = 0; 639 int16_t val; 640 phymod_phy_access_t phy_copy; 641 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 642 643 /* read current tx tap mode */ 644 PHYMOD_IF_ERR_RETURN 645 (blackhawk_tsc_tx_tap_mode_get(&phy_copy.access, &pmd_tx_tap_mode)); 646 647 /*read current tx NRZ mode control info */ 648 PHYMOD_IF_ERR_RETURN 649 (blackhawk_tsc_tx_nrz_mode_get(&phy_copy.access, &tx_tap_nrz_mode)); 650 651 if (pmd_tx_tap_mode == 0) { 652 /* 3 tap mode */ 653 tx->tap_mode = phymodTxTapMode3Tap; 654 } else { 655 tx->tap_mode = phymodTxTapMode6Tap; 656 } 657 658 if (tx_tap_nrz_mode) { 659 tx->sig_method = phymodSignallingMethodNRZ; 660 } else { 661 tx->sig_method = phymodSignallingMethodPAM4; 662 } 663 664 /*next check 3 tap mode or 6 tap mode */ 665 if (tx->tap_mode == phymodTxTapMode3Tap) { 666 PHYMOD_IF_ERR_RETURN 667 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP0, &val)); 668 tx->pre = val; 669 PHYMOD_IF_ERR_RETURN 670 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP1, &val)); 671 tx->main = val; 672 PHYMOD_IF_ERR_RETURN 673 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP2, &val)); 674 tx->post = val; 675 tx->pre2 = 0; 676 tx->post2 = 0; 677 tx->post3 = 0; 678 } else { 679 PHYMOD_IF_ERR_RETURN 680 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP0, &val)); 681 tx->pre2 = val; 682 PHYMOD_IF_ERR_RETURN 683 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP1, &val)); 684 tx->pre = val; 685 PHYMOD_IF_ERR_RETURN 686 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP2, &val)); 687 tx->main = val; 688 PHYMOD_IF_ERR_RETURN 689 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP3, &val)); 690 tx->post = val; 691 PHYMOD_IF_ERR_RETURN 692 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP4, &val)); 693 tx->post2 = val; 694 PHYMOD_IF_ERR_RETURN 695 (blackhawk_tsc_read_tx_afe(&phy_copy.access, TX_AFE_TAP5, &val)); 696 tx->post3 = val; 697 } 698 699 return PHYMOD_E_NONE; 700 } 701 702 703 704 int tscbh_phy_tx_override_set(const phymod_phy_access_t* phy, const phymod_tx_override_t* tx_override) 705 { 706 phymod_phy_access_t phy_copy; 707 int start_lane, num_lane, i; 708 709 PHYMOD_IF_ERR_RETURN 710 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 711 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 712 713 PHYMOD_IF_ERR_RETURN 714 (blackhawk_lane_soft_reset(&phy_copy.access, 1)); 715 716 for (i = 0; i < num_lane; i++) { 717 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 718 continue; 719 } 720 phy_copy.access.lane_mask = 1 << (start_lane + i); 721 PHYMOD_IF_ERR_RETURN 722 (blackhawk_tsc_tx_pi_freq_override(&phy_copy.access, 723 tx_override->phase_interpolator.enable, 724 tx_override->phase_interpolator.value)); 725 } 726 727 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 728 PHYMOD_IF_ERR_RETURN 729 (blackhawk_lane_soft_reset(&phy_copy.access, 0)); 730 731 return PHYMOD_E_NONE; 732 } 733 734 int tscbh_phy_tx_override_get(const phymod_phy_access_t* phy, phymod_tx_override_t* tx_override) 735 { 736 phymod_phy_access_t phy_copy; 737 int16_t temp_value; 738 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 739 740 PHYMOD_IF_ERR_RETURN 741 (blackhawk_tx_pi_control_get(&phy_copy.access, &temp_value)); 742 743 tx_override->phase_interpolator.value = (int32_t) temp_value; 744 return PHYMOD_E_NONE; 745 } 746 747 int tscbh_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset) 748 { 749 750 return PHYMOD_E_UNAVAIL; 751 } 752 753 754 int tscbh_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset) 755 { 756 757 return PHYMOD_E_UNAVAIL; 758 759 } 760 761 762 int tscbh_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 763 { 764 return PHYMOD_E_UNAVAIL; 765 } 766 767 int tscbh_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 768 { 769 return PHYMOD_E_UNAVAIL; 770 } 771 772 /* This function based on num_lane, data_rate and fec_type 773 * assign force speed SW speed_id. 774 */ 775 STATIC 776 int _tscbh_phy_speed_id_set(int num_lane, 777 uint32_t data_rate, 778 phymod_fec_type_t fec_type, 779 tbhmod_spd_intfc_type_t* spd_intf) 780 { 781 if (num_lane == 1) { 782 switch (data_rate) { 783 case 10000: 784 if (fec_type == phymod_fec_None) { 785 *spd_intf = TBHMOD_SPD_10000_XFI; 786 } else if (fec_type == phymod_fec_CL74) { 787 *spd_intf = TBHMOD_SPD_10G_FEC_BASE_R_KR1_CR1; 788 } else { 789 return PHYMOD_E_UNAVAIL; 790 } 791 break; 792 case 12000: 793 *spd_intf = TBHMOD_SPD_12P5G_BRCM_KR1; 794 break; 795 case 20000: 796 if (fec_type == phymod_fec_None) { 797 *spd_intf = TBHMOD_SPD_20000_XFI; 798 } else if (fec_type == phymod_fec_CL74) { 799 *spd_intf = TBHMOD_SPD_20G_FEC_BASE_R_KR1_CR1; 800 } else { 801 return PHYMOD_E_UNAVAIL; 802 } 803 break; 804 case 25000: 805 if (fec_type == phymod_fec_None) { 806 *spd_intf = TBHMOD_SPD_25000_XFI; 807 } else if (fec_type == phymod_fec_CL74) { 808 *spd_intf = TBHMOD_SPD_25G_FEC_BASE_R_KR1_CR1; 809 } else if (fec_type == phymod_fec_CL91) { 810 *spd_intf = TBHMOD_SPD_25G_FEC_RS_FEC_KR1_CR1; 811 } else { 812 return PHYMOD_E_UNAVAIL; 813 } 814 break; 815 case 50000: 816 if (fec_type == phymod_fec_CL91) { 817 *spd_intf = TBHMOD_SPD_50G_BRCM_FEC_528_CR1_KR1; 818 } else if (fec_type == phymod_fec_RS544) { 819 *spd_intf = TBHMOD_SPD_50G_IEEE_KR1_CR1; 820 } else if (fec_type == phymod_fec_RS272) { 821 *spd_intf = TBHMOD_SPD_50G_BRCM_FEC_272_KR1_CR1; 822 } else { 823 return PHYMOD_E_UNAVAIL; 824 } 825 break; 826 default: 827 return PHYMOD_E_UNAVAIL; 828 } 829 } else if (num_lane == 2) { 830 switch (data_rate) { 831 case 40000: 832 if (fec_type == phymod_fec_None) { 833 *spd_intf = TBHMOD_SPD_40G_MLD_X2; 834 } else { 835 return PHYMOD_E_UNAVAIL; 836 } 837 break; 838 case 50000: 839 if (fec_type == phymod_fec_None) { 840 *spd_intf = TBHMOD_SPD_50G_MLD_X2; 841 } else if (fec_type == phymod_fec_CL91) { 842 *spd_intf = TBHMOD_SPD_50G_MLD_FEC_528_X2; 843 } else if (fec_type == phymod_fec_RS544) { 844 *spd_intf = TBHMOD_SPD_50G_BRCM_FEC_544_CR2_KR2; 845 } else { 846 return PHYMOD_E_UNAVAIL; 847 } 848 break; 849 case 100000: 850 if (fec_type == phymod_fec_None) { 851 *spd_intf = TBHMOD_SPD_100G_BRCM_NOFEC_KR2_CR2; 852 } else if (fec_type == phymod_fec_CL91) { 853 *spd_intf = TBHMOD_SPD_100G_BRCM_FEC_528_KR2_CR2; 854 } else if (fec_type == phymod_fec_RS544) { 855 *spd_intf = TBHMOD_SPD_100G_IEEE_KR2_CR2; 856 } else if (fec_type == phymod_fec_RS272) { 857 *spd_intf = TBHMOD_SPD_100G_BRCM_FEC_272_KR2_CR2; 858 } else { 859 return PHYMOD_E_UNAVAIL; 860 } 861 break; 862 default: 863 return PHYMOD_E_UNAVAIL; 864 } 865 } else if (num_lane == 4) { 866 switch (data_rate) { 867 case 40000: 868 if (fec_type == phymod_fec_None) { 869 *spd_intf = TBHMOD_SPD_40G_MLD_X4; 870 } else if (fec_type == phymod_fec_CL74) { 871 *spd_intf = TBHMOD_SPD_40G_FEC_BASE_R_KR4_CR4; 872 } else { 873 return PHYMOD_E_UNAVAIL; 874 } 875 break; 876 case 100000: 877 if (fec_type == phymod_fec_None) { 878 *spd_intf = TBHMOD_SPD_100G_MLD_NO_FEC_X4; 879 } else if (fec_type == phymod_fec_CL91) { 880 *spd_intf = TBHMOD_SPD_100G_MLD_X4; 881 } else if (fec_type == phymod_fec_RS544) { 882 *spd_intf = TBHMOD_SPD_100G_BRCM_FEC_544_1XN_KR4_CR4; 883 } else { 884 return PHYMOD_E_UNAVAIL; 885 } 886 break; 887 case 200000: 888 if (fec_type == phymod_fec_None) { 889 *spd_intf = TBHMOD_SPD_200G_BRCM_NO_FEC_KR4_CR4; 890 } else if (fec_type == phymod_fec_RS544) { 891 *spd_intf = TBHMOD_SPD_200G_BRCM_FEC_544_1XN_KR4_CR4; 892 } else if (fec_type == phymod_fec_RS544_2XN) { 893 *spd_intf = TBHMOD_SPD_200G_IEEE_FEC_544_2XN_KR4_CR4; 894 } else if (fec_type == phymod_fec_RS272) { 895 *spd_intf = TBHMOD_SPD_200G_BRCM_FEC_272_1XN_KR4_CR4; 896 } else { 897 return PHYMOD_E_UNAVAIL; 898 } 899 break; 900 default: 901 return PHYMOD_E_UNAVAIL; 902 } 903 } else if (num_lane == 8) { 904 if (data_rate == 400000 && fec_type == phymod_fec_RS544_2XN) { 905 *spd_intf = TBHMOD_SPD_400G_BRCM_FEC_544_2XN_X8; 906 } else { 907 return PHYMOD_E_UNAVAIL; 908 } 909 } else { 910 return PHYMOD_E_UNAVAIL; 911 } 912 913 return PHYMOD_E_NONE; 914 } 915 916 int tscbh_phy_speed_config_set(const phymod_phy_access_t* phy, 917 const phymod_phy_speed_config_t* speed_config, 918 const phymod_phy_pll_state_t* old_pll_state, 919 phymod_phy_pll_state_t* new_pll_state) 920 { 921 uint32_t ovco_is_pwrdn, tvco_is_pwrdn = 0; 922 phymod_phy_access_t pm_phy_copy; 923 uint32_t lane_mask_backup; 924 uint32_t tvco_pll_index, ovco_pll_index, tvco_pll_div = 0, ovco_pll_div = 0, request_pll_div = 0, pll_index = 0; 925 uint32_t loss_in_db; 926 int i, start_lane, num_lane, mapped_speed_id, ilkn_set; 927 phymod_firmware_lane_config_t firmware_lane_config; 928 phymod_firmware_core_config_t firmware_core_config; 929 tbhmod_spd_intfc_type_t spd_intf = 0; 930 tbhmod_refclk_t ref_clk; 931 uint32_t is_pam4, osr_mode; 932 933 firmware_lane_config = speed_config->pmd_lane_config; 934 /*first make sure that tvco pll index is valid */ 935 if (phy->access.tvco_pll_index > 1) { 936 PHYMOD_DEBUG_ERROR(("Unsupported tvco index\n")); 937 return PHYMOD_E_UNAVAIL; 938 } 939 940 tvco_pll_index = phy->access.tvco_pll_index; 941 ovco_pll_index = tvco_pll_index ? 0 : 1; 942 943 PHYMOD_MEMSET(&firmware_core_config, 0x0, sizeof(firmware_core_config)); 944 945 /* Copy the PLL state */ 946 *new_pll_state = *old_pll_state; 947 948 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 949 PHYMOD_IF_ERR_RETURN 950 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 951 lane_mask_backup = phy->access.lane_mask; 952 953 /* Hold the pcs lane reset */ 954 pm_phy_copy.access.lane_mask = 1 << start_lane; 955 PHYMOD_IF_ERR_RETURN 956 (tbhmod_disable_set(&pm_phy_copy.access)); 957 958 /* write this port forced speed id entry */ 959 PHYMOD_IF_ERR_RETURN 960 (tbhmod_set_sc_speed(&pm_phy_copy.access, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, 0)); 961 962 /*Hold the per lane PMD soft reset bit*/ 963 pm_phy_copy.access.lane_mask = lane_mask_backup; 964 PHYMOD_IF_ERR_RETURN 965 (blackhawk_lane_soft_reset(&pm_phy_copy.access, 1)); 966 967 /* first check if current lane are in ILKN mode */ 968 PHYMOD_IF_ERR_RETURN 969 (tbhmod_pcs_ilkn_chk(&pm_phy_copy.access, &ilkn_set)); 970 971 /* if previous config is ILKN and reqeust config is ethernet 972 need to clear some ILKN config */ 973 if (ilkn_set && !PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 974 /* Remove pmd_tx_disable_pin_dis it may be asserted because of ILKn */ 975 for (i = 0; i < num_lane; i++) { 976 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 977 continue; 978 } 979 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 980 PHYMOD_IF_ERR_RETURN 981 (blackhawk_pmd_tx_disable_pin_dis_set(&pm_phy_copy.access, 0)); 982 } 983 pm_phy_copy.access.lane_mask = lane_mask_backup; 984 /*disable PCS ilkn mode */ 985 PHYMOD_IF_ERR_RETURN 986 (tbhmod_pcs_ilkn_enable(&pm_phy_copy.access, 0)); 987 /* previous config is ethernet and request is ILKN mode */ 988 } else if (!ilkn_set && PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 989 for (i = 0; i < num_lane; i++) { 990 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 991 continue; 992 } 993 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 994 PHYMOD_IF_ERR_RETURN 995 (blackhawk_pmd_tx_disable_pin_dis_set(&pm_phy_copy.access, 1)); 996 } 997 /*enable PCS ilkn mode */ 998 for (i = 0; i < num_lane; i++) { 999 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1000 continue; 1001 } 1002 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1003 PHYMOD_IF_ERR_RETURN 1004 (tbhmod_pcs_ilkn_enable(&pm_phy_copy.access, 1)); 1005 } 1006 } 1007 1008 /*only update the port mode for ethernet port */ 1009 if (!PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1010 PHYMOD_IF_ERR_RETURN 1011 (tbhmod_update_port_mode(&pm_phy_copy.access)); 1012 } 1013 1014 /*for ethernet speed mode config set */ 1015 if (!PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1016 PHYMOD_IF_ERR_RETURN(_tscbh_phy_speed_id_set(num_lane, speed_config->data_rate, 1017 speed_config->fec_type, &spd_intf)); 1018 1019 PHYMOD_IF_ERR_RETURN 1020 (tbhmod_get_mapped_speed(spd_intf, &mapped_speed_id)); 1021 1022 /* set the rs fec CW properly */ 1023 if ((speed_config->fec_type == phymod_fec_RS544) || 1024 (speed_config->fec_type == phymod_fec_RS544_2XN)) { 1025 if (start_lane < 4) { 1026 pm_phy_copy.access.lane_mask = 1 << 0; 1027 } else { 1028 pm_phy_copy.access.lane_mask = 1 << 4; 1029 } 1030 PHYMOD_IF_ERR_RETURN 1031 (tbhmod_rsfec_cw_type(&pm_phy_copy.access, 0, 0)); 1032 } else if ((speed_config->fec_type == phymod_fec_RS272) || 1033 (speed_config->fec_type == phymod_fec_RS272_2XN)) { 1034 if (start_lane < 4) { 1035 pm_phy_copy.access.lane_mask = 1 << 0; 1036 } else { 1037 pm_phy_copy.access.lane_mask = 1 << 4; 1038 } 1039 PHYMOD_IF_ERR_RETURN 1040 (tbhmod_rsfec_cw_type(&pm_phy_copy.access, 1, 0)); 1041 } 1042 } 1043 1044 /* Check if ovco is power down */ 1045 pm_phy_copy.access.pll_idx = ovco_pll_index; 1046 PHYMOD_IF_ERR_RETURN 1047 (blackhawk_tsc_pll_pwrdn_get(&pm_phy_copy.access, &ovco_is_pwrdn)); 1048 1049 /* if ovco is NOT pwoer down, then get the ovco div*/ 1050 if (!ovco_is_pwrdn) { 1051 PHYMOD_IF_ERR_RETURN 1052 (blackhawk_tsc_INTERNAL_read_pll_div(&pm_phy_copy.access, &ovco_pll_div)); 1053 } 1054 1055 /* next check if pcs bypass mode, yes, then need to check tvco is power down */ 1056 if (PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1057 pm_phy_copy.access.pll_idx = tvco_pll_index; 1058 PHYMOD_IF_ERR_RETURN 1059 (blackhawk_tsc_pll_pwrdn_get(&pm_phy_copy.access, &tvco_is_pwrdn)); 1060 } 1061 1062 if (!tvco_is_pwrdn) { 1063 /* Get TVCO because it's not allowed to change during speed set */ 1064 pm_phy_copy.access.pll_idx = tvco_pll_index; 1065 PHYMOD_IF_ERR_RETURN 1066 (blackhawk_tsc_INTERNAL_read_pll_div(&pm_phy_copy.access, &tvco_pll_div)); 1067 } 1068 1069 /* based on the current TVCO PLL div, decide which copy of speed id entry to load */ 1070 /* and this step only applies to (non)ilkn port*/ 1071 if (!PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1072 /* first set the lane mask to be 0x1 */ 1073 pm_phy_copy.access.lane_mask = 1 << 0; 1074 if ((tvco_pll_div == TBHMOD_PLL_MODE_DIV_170) || (tvco_pll_div == TBHMOD_PLL_MODE_DIV_85)) { 1075 /* then load 26G TVCO speed id entry */ 1076 PHYMOD_IF_ERR_RETURN 1077 (phymod_mem_write(&pm_phy_copy.access, phymodMemSpeedIdTable, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, &spd_id_entry_26[mapped_speed_id][0])); 1078 } else if ((tvco_pll_div == TBHMOD_PLL_MODE_DIV_165) || (tvco_pll_div == TBHMOD_PLL_MODE_DIV_82P5)) { 1079 /* then load 25G TVCO speed id entry */ 1080 PHYMOD_IF_ERR_RETURN 1081 (phymod_mem_write(&pm_phy_copy.access, phymodMemSpeedIdTable, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, &spd_id_entry_25[mapped_speed_id][0])); 1082 } else { 1083 /* then load 20G TVCO speed id entry */ 1084 PHYMOD_IF_ERR_RETURN 1085 (phymod_mem_write(&pm_phy_copy.access, phymodMemSpeedIdTable, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, &spd_id_entry_20[mapped_speed_id][0])); 1086 } 1087 } 1088 1089 /* Check the request speed VCO */ 1090 pm_phy_copy.access.lane_mask = 1 << start_lane; 1091 PHYMOD_IF_ERR_RETURN 1092 (tbhmod_refclk_get(&pm_phy_copy.access, &ref_clk)); 1093 1094 /* Get requested PLL */ 1095 /*for ethernet speed mode config set */ 1096 if (!PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1097 PHYMOD_IF_ERR_RETURN 1098 (tbhmod_plldiv_lkup_get(&pm_phy_copy.access, mapped_speed_id, ref_clk, &request_pll_div)); 1099 } else { 1100 /*first check the ref clock */ 1101 int ref_clk_is_156p25 = 0; 1102 if (ref_clk == TBHMOD_REF_CLK_156P25MHZ) { 1103 ref_clk_is_156p25 = 1; 1104 } 1105 PHYMOD_IF_ERR_RETURN 1106 (blackhawk_speed_config_get(speed_config->data_rate, ref_clk_is_156p25, &request_pll_div, &is_pam4, &osr_mode)); 1107 } 1108 1109 if ((ovco_pll_div == request_pll_div) || (tvco_pll_div == request_pll_div)) { 1110 /* First check if pll0 is active and the new speed can be 1111 supported with existing VCO */ 1112 pll_index = (ovco_pll_div == request_pll_div)? ovco_pll_index : tvco_pll_index; 1113 } else { 1114 /*this speed request can not be configured */ 1115 PHYMOD_DEBUG_ERROR(("ERROR :: this speed can not be configured \n")); 1116 return PHYMOD_E_CONFIG; 1117 } 1118 1119 /* choose the right pll index for the port */ 1120 for (i = 0; i < num_lane; i++) { 1121 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1122 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1123 continue; 1124 } 1125 PHYMOD_IF_ERR_RETURN 1126 (blackhawk_lane_pll_selection_set(&pm_phy_copy.access, pll_index)); 1127 } 1128 1129 pm_phy_copy.access.lane_mask = lane_mask_backup; 1130 /* Program OS mode */ 1131 if (!PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1132 PHYMOD_IF_ERR_RETURN 1133 (tbhmod_pmd_osmode_set(&pm_phy_copy.access, mapped_speed_id, ref_clk)); 1134 } else { 1135 for (i = 0; i < num_lane; i++) { 1136 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1137 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1138 continue; 1139 } 1140 PHYMOD_IF_ERR_RETURN 1141 (blackhawk_osr_mode_set(&pm_phy_copy.access, osr_mode)); 1142 } 1143 } 1144 1145 /*next need to set certain firmware lane config to be zero*/ 1146 firmware_lane_config.LaneConfigFromPCS = 0; 1147 firmware_lane_config.AnEnabled = 0; 1148 1149 for (i = 0; i < num_lane; i++) { 1150 pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i); 1151 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1152 continue; 1153 } 1154 PHYMOD_IF_ERR_RETURN 1155 (_tscbh_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config)); 1156 } 1157 1158 /* if the PAM4 mode, need to program the channel loss. In NRZ mode it is zeroed. */ 1159 loss_in_db = firmware_lane_config.ForcePAM4Mode? speed_config->PAM4_channel_loss : 0; 1160 for (i = 0; i < num_lane; i++) { 1161 pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i); 1162 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1163 continue; 1164 } 1165 PHYMOD_IF_ERR_RETURN 1166 (blackhawk_channel_loss_set(&pm_phy_copy.access, loss_in_db)); 1167 } 1168 1169 /* next need to enable/disable link training based on the input */ 1170 PHYMOD_IF_ERR_RETURN 1171 (tscbh_phy_cl72_set(phy, speed_config->linkTraining)); 1172 1173 /*release the lne soft reset bit*/ 1174 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1175 PHYMOD_IF_ERR_RETURN 1176 (blackhawk_lane_soft_reset(&pm_phy_copy.access, 0)); 1177 1178 /* Release the pcs lane reset */ 1179 pm_phy_copy.access.lane_mask = 1 << start_lane; 1180 PHYMOD_IF_ERR_RETURN 1181 (tbhmod_enable_set(&pm_phy_copy.access)); 1182 1183 /* first clear the current lane _mask from both */ 1184 new_pll_state->pll1_lanes_bitmap &= ~(phy->access.lane_mask); 1185 new_pll_state->pll0_lanes_bitmap &= ~(phy->access.lane_mask); 1186 1187 /* need to update the pll_state */ 1188 if (pll_index) { 1189 new_pll_state->pll1_lanes_bitmap |= phy->access.lane_mask; 1190 } else { 1191 new_pll_state->pll0_lanes_bitmap |= phy->access.lane_mask; 1192 } 1193 1194 return PHYMOD_E_NONE; 1195 } 1196 1197 STATIC 1198 int _tscbh_speed_table_entry_to_speed_config_get(const phymod_phy_access_t* phy, 1199 spd_id_tbl_entry_t* speed_config_entry, 1200 phymod_phy_speed_config_t* speed_config) 1201 { 1202 uint32_t pll_div, refclk_in_hz, data_rate_lane; 1203 uint32_t pll_index; 1204 int osr_mode; 1205 tbhmod_refclk_t ref_clk; 1206 uint32_t vco_rate; 1207 phymod_phy_access_t phy_copy; 1208 phymod_firmware_lane_config_t firmware_lane_config; 1209 int num_lane; 1210 1211 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1212 1213 switch (speed_config_entry->num_lanes) { 1214 case 0: num_lane = 1; 1215 break; 1216 case 1: num_lane = 2; 1217 break; 1218 case 2: num_lane = 4; 1219 break; 1220 case 3: num_lane = 8; 1221 break; 1222 case 4: num_lane = 3; 1223 break; 1224 case 5: num_lane = 6; 1225 break; 1226 case 6: num_lane = 7; 1227 break; 1228 default: 1229 PHYMOD_DEBUG_ERROR(("Unsupported number of lane \n")); 1230 return PHYMOD_E_UNAVAIL; 1231 } 1232 1233 /*first figure out which pll the current port is using */ 1234 PHYMOD_IF_ERR_RETURN 1235 (blackhawk_lane_pll_selection_get(&phy_copy.access, &pll_index)); 1236 1237 phy_copy.access.pll_idx = pll_index; 1238 1239 PHYMOD_IF_ERR_RETURN 1240 (tscbh_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 1241 1242 /* get the PLL div from HW */ 1243 PHYMOD_IF_ERR_RETURN 1244 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 1245 1246 PHYMOD_IF_ERR_RETURN 1247 (tbhmod_refclk_get(&phy_copy.access, &ref_clk)); 1248 1249 if (ref_clk == TBHMOD_REF_CLK_312P5MHZ) { 1250 refclk_in_hz = 312500000; 1251 } else { 1252 refclk_in_hz = 156250000; 1253 } 1254 PHYMOD_IF_ERR_RETURN 1255 (blackhawk_tsc_get_vco_from_refclk_div(&phy_copy.access, refclk_in_hz, pll_div, &vco_rate, 0)); 1256 1257 PHYMOD_IF_ERR_RETURN 1258 (blackhawk_osr_mode_get(&phy_copy.access, &osr_mode)); 1259 1260 /* 1261 * data_rate_lane = vco_rate / 66 * 64. 1262 * For 25G VCO case, round down the data_rate_lane to 24000 by convention. 1263 */ 1264 if (vco_rate == 20625000) { 1265 data_rate_lane = 20000; 1266 } else if (vco_rate == 25000000) { 1267 data_rate_lane = 24000; 1268 } else { 1269 data_rate_lane = 25000; 1270 } 1271 1272 /* next check if PAM4 mode enabled */ 1273 if (firmware_lane_config.ForcePAM4Mode) { 1274 data_rate_lane = data_rate_lane << 1; 1275 } else { 1276 /* to get the over sample value */ 1277 data_rate_lane = data_rate_lane >> osr_mode; 1278 } 1279 1280 speed_config->data_rate = data_rate_lane * num_lane; 1281 1282 PHYMOD_IF_ERR_RETURN 1283 (tbhmod_fec_arch_decode_get(speed_config_entry->fec_arch, &(speed_config->fec_type))); 1284 1285 return PHYMOD_E_NONE; 1286 } 1287 1288 1289 STATIC 1290 int _tscbh_speed_id_to_speed_config_get(const phymod_phy_access_t* phy, 1291 int speed_id, 1292 int num_lane, 1293 phymod_phy_speed_config_t* speed_config) 1294 { 1295 uint32_t pll_div, refclk_in_hz, data_rate_lane; 1296 uint32_t pll_index; 1297 int osr_mode; 1298 tbhmod_refclk_t ref_clk; 1299 uint32_t vco_rate; 1300 phymod_phy_access_t phy_copy; 1301 phymod_firmware_lane_config_t firmware_lane_config; 1302 spd_id_tbl_entry_t speed_config_entry; 1303 uint32_t packed_entry[5]; 1304 1305 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1306 1307 /*first figure out which pll the current port is using */ 1308 PHYMOD_IF_ERR_RETURN 1309 (blackhawk_lane_pll_selection_get(&phy_copy.access, &pll_index)); 1310 1311 phy_copy.access.pll_idx = pll_index; 1312 1313 PHYMOD_IF_ERR_RETURN 1314 (tscbh_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 1315 1316 /* get the PLL div from HW */ 1317 PHYMOD_IF_ERR_RETURN 1318 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 1319 1320 PHYMOD_IF_ERR_RETURN 1321 (tbhmod_refclk_get(&phy_copy.access, &ref_clk)); 1322 1323 if (ref_clk == TBHMOD_REF_CLK_312P5MHZ) { 1324 refclk_in_hz = 312500000; 1325 } else { 1326 refclk_in_hz = 156250000; 1327 } 1328 PHYMOD_IF_ERR_RETURN 1329 (blackhawk_tsc_get_vco_from_refclk_div(&phy_copy.access, refclk_in_hz, pll_div, &vco_rate, 0)); 1330 1331 PHYMOD_IF_ERR_RETURN 1332 (blackhawk_osr_mode_get(&phy_copy.access, &osr_mode)); 1333 /* 1334 * data_rate_lane = vco_rate / 66 * 64. 1335 * For 25G VCO case, round down the data_rate_lane to 24000 by convention. 1336 */ 1337 if (vco_rate == 20625000) { 1338 data_rate_lane = 20000; 1339 } else if (vco_rate == 25000000) { 1340 data_rate_lane = 24000; 1341 } else { 1342 data_rate_lane = 25000; 1343 } 1344 1345 /* next check if PAM4 mode enabled */ 1346 if (firmware_lane_config.ForcePAM4Mode) { 1347 data_rate_lane = data_rate_lane << 1; 1348 } else { 1349 /* to get the over sample value */ 1350 data_rate_lane = data_rate_lane >> osr_mode; 1351 } 1352 1353 speed_config->data_rate = data_rate_lane * num_lane; 1354 1355 PHYMOD_IF_ERR_RETURN 1356 (phymod_mem_read(&phy_copy.access, phymodMemSpeedIdTable, speed_id, packed_entry)); 1357 1358 spd_ctrl_unpack_spd_id_tbl_entry(packed_entry, &speed_config_entry); 1359 1360 PHYMOD_IF_ERR_RETURN 1361 (tbhmod_fec_arch_decode_get(speed_config_entry.fec_arch, &(speed_config->fec_type))); 1362 1363 return PHYMOD_E_NONE; 1364 } 1365 1366 int tscbh_phy_speed_config_get(const phymod_phy_access_t* phy, phymod_phy_speed_config_t* speed_config) 1367 { 1368 uint32_t cl72_enable; 1369 phymod_phy_access_t phy_copy; 1370 phymod_firmware_lane_config_t firmware_lane_config; 1371 int start_lane, num_lane, speed_id; 1372 uint32_t packed_entry[20]; 1373 spd_id_tbl_entry_t speed_config_entry; 1374 int an_en, an_done, osr_mode; 1375 uint32_t pll_div, vco_freq_khz, pll_index, lane_mask_backup; 1376 tbhmod_refclk_t ref_clk; 1377 1378 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1379 lane_mask_backup = phy->access.lane_mask; 1380 1381 PHYMOD_IF_ERR_RETURN 1382 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1383 1384 PHYMOD_IF_ERR_RETURN 1385 (tscbh_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 1386 1387 speed_config->pmd_lane_config.AnEnabled = firmware_lane_config.AnEnabled; 1388 speed_config->pmd_lane_config.Cl72AutoPolEn = firmware_lane_config.Cl72AutoPolEn; 1389 speed_config->pmd_lane_config.Cl72RestTO = firmware_lane_config.Cl72RestTO; 1390 speed_config->pmd_lane_config.DfeOn = firmware_lane_config.DfeOn; 1391 speed_config->pmd_lane_config.ForceBrDfe = firmware_lane_config.ForceBrDfe; 1392 speed_config->pmd_lane_config.ForceExtenedReach = firmware_lane_config.ForceExtenedReach; 1393 speed_config->pmd_lane_config.ForceNormalReach = firmware_lane_config.ForceNormalReach; 1394 speed_config->pmd_lane_config.ForceNRZMode = firmware_lane_config.ForceNRZMode; 1395 speed_config->pmd_lane_config.ForcePAM4Mode = firmware_lane_config.ForcePAM4Mode; 1396 speed_config->pmd_lane_config.LaneConfigFromPCS = firmware_lane_config.LaneConfigFromPCS; 1397 speed_config->pmd_lane_config.LpDfeOn = firmware_lane_config.LpDfeOn; 1398 speed_config->pmd_lane_config.LpPrecoderEnabled = firmware_lane_config.LpPrecoderEnabled; 1399 speed_config->pmd_lane_config.MediaType = firmware_lane_config.MediaType; 1400 speed_config->pmd_lane_config.ScramblingDisable = firmware_lane_config.ScramblingDisable; 1401 speed_config->pmd_lane_config.UnreliableLos = firmware_lane_config.UnreliableLos; 1402 1403 /* for ethernet port */ 1404 if (!PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1405 /* first read speed id from resolved status */ 1406 PHYMOD_IF_ERR_RETURN 1407 (tbhmod_speed_id_get(&phy_copy.access, &speed_id)); 1408 1409 /* next check check if AN enabled */ 1410 PHYMOD_IF_ERR_RETURN 1411 (tbhmod_autoneg_status_get(&phy_copy.access, &an_en, &an_done)); 1412 1413 /* first read the speed entry and then decode the speed and FEC type */ 1414 phy_copy.access.lane_mask = 1 << 0; 1415 PHYMOD_IF_ERR_RETURN 1416 (phymod_mem_read(&phy_copy.access, phymodMemSpeedIdTable, speed_id, packed_entry)); 1417 1418 /*decode speed entry */ 1419 spd_ctrl_unpack_spd_id_tbl_entry(packed_entry, &speed_config_entry); 1420 1421 1422 PHYMOD_IF_ERR_RETURN 1423 (_tscbh_speed_table_entry_to_speed_config_get(phy, &speed_config_entry, speed_config)); 1424 1425 /* if autoneg enabled, needs to update the FEC_ARCH based on the An resolved status */ 1426 if (an_en && an_done) { 1427 uint8_t fec_arch; 1428 phy_copy.access.lane_mask = 0x1 << start_lane; 1429 PHYMOD_IF_ERR_RETURN 1430 (tbhmod_autoneg_fec_status_get(&phy_copy.access, &fec_arch)); 1431 PHYMOD_IF_ERR_RETURN 1432 (tbhmod_fec_arch_decode_get(fec_arch, &(speed_config->fec_type))); 1433 } 1434 } else { 1435 /*first figure out which pll the current port is using */ 1436 PHYMOD_IF_ERR_RETURN 1437 (blackhawk_lane_pll_selection_get(&phy_copy.access, &pll_index)); 1438 1439 phy_copy.access.pll_idx = pll_index; 1440 /* get the PLL div from HW */ 1441 PHYMOD_IF_ERR_RETURN 1442 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 1443 1444 phy_copy.access.lane_mask = 0x1; 1445 /* next read what's the ref clock */ 1446 PHYMOD_IF_ERR_RETURN 1447 (tbhmod_refclk_get(&phy_copy.access, &ref_clk)); 1448 1449 if (ref_clk == TBHMOD_REF_CLK_156P25MHZ) { 1450 PHYMOD_IF_ERR_RETURN 1451 (blackhawk_tsc_get_vco_from_refclk_div(&phy_copy.access, REF_CLOCK_156P25, pll_div, &vco_freq_khz, 0)); 1452 } else { 1453 PHYMOD_IF_ERR_RETURN 1454 (blackhawk_tsc_get_vco_from_refclk_div(&phy_copy.access, REF_CLOCK_312P5, pll_div, &vco_freq_khz, 0)); 1455 } 1456 1457 phy_copy.access.lane_mask = lane_mask_backup; 1458 1459 PHYMOD_IF_ERR_RETURN 1460 (blackhawk_osr_mode_get(&phy_copy.access, &osr_mode)); 1461 /* next check if PAM4 mode enabled */ 1462 if (firmware_lane_config.ForcePAM4Mode) { 1463 speed_config->data_rate = (vco_freq_khz << 1) / 1000; 1464 } else { 1465 /* to get the over sample value */ 1466 if (osr_mode == 0) { 1467 speed_config->data_rate = (vco_freq_khz) / 1000; 1468 } else if(osr_mode == 1) { 1469 speed_config->data_rate = (vco_freq_khz >> 1) / 1000; 1470 } else if (osr_mode == 2) { 1471 speed_config->data_rate = (vco_freq_khz >> 2) / 1000; 1472 } 1473 } 1474 } 1475 1476 /* next get the cl72 enable status */ 1477 phy_copy.access.lane_mask = 0x1 << start_lane; 1478 PHYMOD_IF_ERR_RETURN 1479 (blackhawk_clause72_control_get(&phy_copy.access, &cl72_enable)); 1480 speed_config->linkTraining = cl72_enable; 1481 1482 return PHYMOD_E_NONE; 1483 } 1484 1485 1486 int tscbh_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en) 1487 { 1488 struct blackhawk_tsc_uc_lane_config_st serdes_firmware_config; 1489 phymod_firmware_lane_config_t firmware_lane_config; 1490 int start_lane, num_lane, i; 1491 uint32_t lane_reset, pcs_lane_enable; 1492 phymod_phy_access_t pm_phy_copy; 1493 1494 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1495 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_get_uc_lane_cfg(&pm_phy_copy.access, &serdes_firmware_config)); 1496 1497 if ((serdes_firmware_config.field.dfe_on == 0) && cl72_en) { 1498 PHYMOD_DEBUG_ERROR(("ERROR :: DFE is off : Can not start CL72/CL93 with no DFE\n")); 1499 return PHYMOD_E_CONFIG; 1500 } 1501 1502 PHYMOD_IF_ERR_RETURN 1503 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1504 1505 /*first check if lane is in reset */ 1506 PHYMOD_IF_ERR_RETURN 1507 (blackhawk_lane_soft_reset_get(&pm_phy_copy.access, &lane_reset)); 1508 1509 /*next check if PCS lane is in reset */ 1510 PHYMOD_IF_ERR_RETURN 1511 (tbhmod_enable_get(&pm_phy_copy.access, &pcs_lane_enable)); 1512 1513 /* disable pcs lane if pcs lane not in rset */ 1514 if (pcs_lane_enable) { 1515 pm_phy_copy.access.lane_mask = 1 << start_lane; 1516 PHYMOD_IF_ERR_RETURN 1517 (tbhmod_disable_set(&pm_phy_copy.access)); 1518 } 1519 1520 /* if lane is not in reset, then reset the lane first */ 1521 if (!lane_reset) { 1522 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1523 PHYMOD_IF_ERR_RETURN 1524 (blackhawk_lane_soft_reset(&pm_phy_copy.access, 1)); 1525 } 1526 1527 /* next need to clear both force ER and NR config on the firmware lane config side 1528 if link training enable is set */ 1529 if (cl72_en) { 1530 PHYMOD_IF_ERR_RETURN 1531 (tscbh_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 1532 1533 firmware_lane_config.ForceNormalReach = 0; 1534 firmware_lane_config.ForceExtenedReach = 0; 1535 1536 PHYMOD_IF_ERR_RETURN 1537 (_tscbh_phy_firmware_lane_config_set(phy, firmware_lane_config)); 1538 } 1539 for (i = 0; i < num_lane; i++) { 1540 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1541 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1542 continue; 1543 } 1544 PHYMOD_IF_ERR_RETURN 1545 (blackhawk_clause72_control(&pm_phy_copy.access, cl72_en)); 1546 } 1547 1548 /* release the ln dp reset */ 1549 if (!lane_reset) { 1550 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1551 PHYMOD_IF_ERR_RETURN 1552 (blackhawk_lane_soft_reset(&pm_phy_copy.access, 0)); 1553 } 1554 1555 /* re-enable pcs lane if pcs lane not in rset */ 1556 if (pcs_lane_enable) { 1557 pm_phy_copy.access.lane_mask = 1 << start_lane; 1558 PHYMOD_IF_ERR_RETURN 1559 (tbhmod_enable_set(&pm_phy_copy.access)); 1560 } 1561 1562 return PHYMOD_E_NONE; 1563 } 1564 1565 int tscbh_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en) 1566 { 1567 phymod_phy_access_t pm_phy_copy; 1568 1569 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1570 1571 PHYMOD_IF_ERR_RETURN 1572 (blackhawk_clause72_control_get(&pm_phy_copy.access, cl72_en)); 1573 1574 return PHYMOD_E_NONE; 1575 } 1576 1577 1578 int tscbh_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status) 1579 { 1580 int i; 1581 uint32_t tmp_status; 1582 int start_lane, num_lane; 1583 phymod_phy_access_t phy_copy; 1584 int an_en, an_done, speed_id; 1585 spd_id_tbl_entry_t speed_config_entry; 1586 uint32_t packed_entry[5]; 1587 1588 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1589 status->locked = 1; 1590 1591 /* next figure out the lane num and start_lane based on the input */ 1592 PHYMOD_IF_ERR_RETURN 1593 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1594 /* check check if AN enabled */ 1595 PHYMOD_IF_ERR_RETURN 1596 (tbhmod_autoneg_status_get(&phy_copy.access, &an_en, &an_done)); 1597 1598 if (an_en && an_done) { 1599 PHYMOD_IF_ERR_RETURN 1600 (tbhmod_speed_id_get(&phy_copy.access, &speed_id)); 1601 PHYMOD_IF_ERR_RETURN 1602 (phymod_mem_read(&phy_copy.access, phymodMemSpeedIdTable, speed_id, packed_entry)); 1603 spd_ctrl_unpack_spd_id_tbl_entry(packed_entry, &speed_config_entry); 1604 /* Update num_lane and lane_mask for AN port */ 1605 num_lane = 1 << speed_config_entry.num_lanes; 1606 /* Update lane_mask */ 1607 phy_copy.access.lane_mask = 0x0; 1608 for (i = 0; i < num_lane; i++) { 1609 phy_copy.access.lane_mask |= 0x1 << (i + start_lane); 1610 } 1611 } 1612 1613 for (i = 0; i < num_lane; i++) { 1614 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1615 continue; 1616 } 1617 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1618 tmp_status = 1; 1619 PHYMOD_IF_ERR_RETURN(blackhawk_pmd_cl72_receiver_status(&phy_copy.access, &tmp_status)); 1620 if (tmp_status == 0) { 1621 status->locked = 0; 1622 return PHYMOD_E_NONE; 1623 } 1624 } 1625 1626 return PHYMOD_E_NONE; 1627 } 1628 1629 int tscbh_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable) 1630 { 1631 int i; 1632 int start_lane, num_lane; 1633 phymod_phy_access_t phy_copy; 1634 1635 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1636 1637 /* next figure out the lane num and start_lane based on the input */ 1638 PHYMOD_IF_ERR_RETURN 1639 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1640 1641 switch (loopback) { 1642 case phymodLoopbackGlobal : 1643 case phymodLoopbackGlobalPMD : 1644 if (enable) { 1645 phy_copy.access.lane_mask = 1 << start_lane; 1646 PHYMOD_IF_ERR_RETURN 1647 (tbhmod_disable_set(&phy_copy.access)); 1648 /*first squelch rx */ 1649 for (i = 0; i < num_lane; i++) { 1650 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1651 continue; 1652 } 1653 PHYMOD_IF_ERR_RETURN(blackhawk_pmd_force_signal_detect(&phy_copy.access, (int) enable, (int) 0)); 1654 } 1655 phy_copy.access.lane_mask = 1 << start_lane; 1656 PHYMOD_IF_ERR_RETURN 1657 (tbhmod_enable_set(&phy_copy.access)); 1658 } 1659 for (i = 0; i < num_lane; i++) { 1660 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1661 continue; 1662 } 1663 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1664 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_tx_disable(&phy_copy.access, enable)); 1665 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_dig_lpbk(&phy_copy.access, (uint8_t) enable)); 1666 } 1667 if (!enable) { 1668 for (i = 0; i < num_lane; i++) { 1669 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1670 continue; 1671 } 1672 PHYMOD_IF_ERR_RETURN(blackhawk_pmd_force_signal_detect(&phy_copy.access, (int) enable, (int) 0)); 1673 } 1674 } 1675 break; 1676 case phymodLoopbackRemotePMD : 1677 for (i = 0; i < num_lane; i++) { 1678 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1679 continue; 1680 } 1681 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1682 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_rmt_lpbk(&phy_copy.access, (uint8_t)enable)); 1683 } 1684 break; 1685 case phymodLoopbackRemotePCS : 1686 default : 1687 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_UNAVAIL, 1688 (_PHYMOD_MSG("This mode is not supported\n"))); 1689 break; 1690 } 1691 return PHYMOD_E_NONE; 1692 } 1693 1694 int tscbh_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable) 1695 { 1696 int start_lane, num_lane; 1697 phymod_phy_access_t phy_copy; 1698 1699 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1700 1701 /*next figure out the lane num and start_lane based on the input*/ 1702 PHYMOD_IF_ERR_RETURN 1703 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1704 1705 switch (loopback) { 1706 case phymodLoopbackGlobal : 1707 case phymodLoopbackGlobalPMD : 1708 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_dig_lpbk_get(&phy_copy.access, enable)); 1709 break; 1710 case phymodLoopbackRemotePMD : 1711 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_rmt_lpbk_get(&phy_copy.access, enable)); 1712 break; 1713 case phymodLoopbackRemotePCS : 1714 default : 1715 return PHYMOD_E_UNAVAIL; 1716 } 1717 return PHYMOD_E_NONE; 1718 } 1719 1720 /* Core initialization 1721 * (PASS1) 1722 * 1. De-assert PMD core and PMD lane reset 1723 * 2. Set heartbeat for comclk 1724 * 3. Configure PMD lane mapping and PCS lane swap 1725 * 4. Micro code load and verify 1726 * 5. Start CRC Calculation (opt) 1727 * (PASS2) 1728 * 6. De-assert micro reset 1729 * 7. Wait for uc_active = 1 1730 * 8. Initialize software information table for the micro 1731 * 9. Config PMD polarity 1732 * 10. AFE/PLL configuration 1733 * 11. Set core_from_pcs_config 1734 * 12. Program AN default timer 1735 * 13. Load sd_id_table, am_table and um_table into TSC memory 1736 * 14. Release core DP soft reset 1737 */ 1738 STATIC 1739 int _tscbh_core_init_pass1(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 1740 { 1741 int rv, lane; 1742 phymod_phy_access_t phy_access; 1743 phymod_core_access_t core_copy; 1744 uint32_t uc_enable = 0, rev_num; 1745 phymod_polarity_t tmp_pol; 1746 ucode_info_t ucode; 1747 unsigned int blackhawk_ucode_len; 1748 unsigned char *blackhawk_ucode; 1749 1750 TSCBH_CORE_TO_PHY_ACCESS(&phy_access, core); 1751 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 1752 core_copy.access.lane_mask = 0x1; 1753 1754 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 1755 1756 /* 1. De-assert PMD core power and core data path reset */ 1757 PHYMOD_IF_ERR_RETURN 1758 (tbhmod_pmd_reset_seq(&core_copy.access, core_status->pmd_active)); 1759 1760 core_copy.access.pll_idx = 1; 1761 PHYMOD_IF_ERR_RETURN 1762 (blackhawk_tsc_core_dp_reset(&core_copy.access, 1)); 1763 core_copy.access.pll_idx = 0; 1764 PHYMOD_IF_ERR_RETURN 1765 (blackhawk_tsc_core_dp_reset(&core_copy.access, 1)); 1766 1767 /* De-assert PMD lane reset */ 1768 1769 for (lane = 0; lane < TSCBH_NOF_LANES_IN_CORE; lane++) { 1770 phy_access.access.lane_mask = 1 << lane; 1771 PHYMOD_IF_ERR_RETURN 1772 (tbhmod_pmd_x4_reset(&phy_access.access)); 1773 } 1774 1775 PHYMOD_IF_ERR_RETURN 1776 (blackhawk_uc_active_get(&phy_access.access, &uc_enable)); 1777 if (uc_enable) return PHYMOD_E_NONE; 1778 1779 /* 2. Set the heart beat, default is 156.25M */ 1780 if (init_config->interface.ref_clock != phymodRefClk156Mhz) { 1781 PHYMOD_IF_ERR_RETURN 1782 (blackhawk_refclk_set(&core_copy.access, init_config->interface.ref_clock)); 1783 PHYMOD_IF_ERR_RETURN 1784 (tbhmod_refclk_set(&phy_access.access, TBHMOD_REF_CLK_312P5MHZ)); 1785 } 1786 1787 /* 3. Configure PMD lane mapping and PCS lane swap */ 1788 PHYMOD_IF_ERR_RETURN 1789 (tscbh_core_lane_map_set(&core_copy, &init_config->lane_map)); 1790 1791 /* 4. set the micro stack size */ 1792 phy_access.access.lane_mask = 0x1; 1793 PHYMOD_IF_ERR_RETURN 1794 (tbhmod_revid_get(&phy_access.access, &rev_num)); 1795 if (rev_num == TBHMOD_REV_NUM_0) { 1796 ucode.stack_size = blackhawk_ucode_stack_size_rev0; 1797 ucode.ucode_size = blackhawk_ucode_len_rev0; 1798 blackhawk_ucode_len = blackhawk_ucode_len_rev0; 1799 blackhawk_ucode = blackhawk_ucode_rev0; 1800 } else { 1801 ucode.stack_size = blackhawk_ucode_stack_size_rev1; 1802 ucode.ucode_size = blackhawk_ucode_len_rev1; 1803 blackhawk_ucode_len = blackhawk_ucode_len_rev1; 1804 blackhawk_ucode = blackhawk_ucode_rev1; 1805 } 1806 1807 PHYMOD_IF_ERR_RETURN 1808 (blackhawk_tsc_uc_reset_with_info(&core_copy.access , 1, ucode)); 1809 1810 /* 5. Micro code load and verify */ 1811 rv = _tscbh_core_firmware_load(&core_copy, init_config); 1812 if (rv != PHYMOD_E_NONE) { 1813 PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask)); 1814 PHYMOD_IF_ERR_RETURN(rv); 1815 } 1816 1817 /* need to check if the ucode load is correct or not */ 1818 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 1819 /* Read-back uCode from Program RAM and verify against ucode_image. 1820 * The comparison is 4-byte at a time, which is time-consuming. 1821 * Thus, this code is only needed for debug purpose. 1822 */ 1823 if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 1824 rv = blackhawk_tsc_ucode_load_verify(&core_copy.access, (uint8_t *) blackhawk_ucode, blackhawk_ucode_len); 1825 if (rv != PHYMOD_E_NONE) { 1826 PHYMOD_DEBUG_ERROR(("devad 0x%x lane 0x%x: UC load-verify failed\n", core->access.addr, core->access.lane_mask)); 1827 PHYMOD_IF_ERR_RETURN(rv); 1828 } 1829 } 1830 } 1831 1832 return PHYMOD_E_NONE; 1833 } 1834 1835 1836 STATIC 1837 int _tscbh_core_init_pass2(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 1838 { 1839 phymod_phy_access_t phy_access, phy_access_copy; 1840 phymod_core_access_t core_copy; 1841 enum blackhawk_tsc_pll_refclk_enum refclk; 1842 phymod_polarity_t tmp_pol; 1843 int lane, pll_index; 1844 uint32_t speed_id_load_size, am_table_load_size, um_table_load_size; 1845 uint32_t tvco_rate, i, tvco_pll_index, rev_num; 1846 1847 TSCBH_CORE_TO_PHY_ACCESS(&phy_access, core); 1848 phy_access_copy = phy_access; 1849 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 1850 core_copy.access.lane_mask = 0x1; 1851 phy_access_copy = phy_access; 1852 phy_access_copy.access = core->access; 1853 phy_access_copy.access.lane_mask = 0x1; 1854 phy_access_copy.type = core->type; 1855 tvco_pll_index = core->access.tvco_pll_index; 1856 1857 if (init_config->interface.ref_clock == phymodRefClk156Mhz) { 1858 refclk = BLACKHAWK_TSC_PLL_REFCLK_156P25MHZ; 1859 /* first check tvco index */ 1860 if (tvco_pll_index == 1) { 1861 PHYMOD_IF_ERR_RETURN( 1862 tbhmod_pll_to_vco_get(TBHMOD_REF_CLK_156P25MHZ, init_config->pll1_div_init_value, &tvco_rate)); 1863 } else if (tvco_pll_index == 0) { 1864 PHYMOD_IF_ERR_RETURN( 1865 tbhmod_pll_to_vco_get(TBHMOD_REF_CLK_156P25MHZ, init_config->pll0_div_init_value, &tvco_rate)); 1866 } else { 1867 PHYMOD_DEBUG_ERROR(("Unsupported tvco index\n")); 1868 return PHYMOD_E_UNAVAIL; 1869 } 1870 } else if (init_config->interface.ref_clock == phymodRefClk312Mhz) { 1871 refclk = BLACKHAWK_TSC_PLL_REFCLK_312P5MHZ; 1872 /* first check tvco index */ 1873 if (tvco_pll_index == 1) { 1874 PHYMOD_IF_ERR_RETURN( 1875 tbhmod_pll_to_vco_get(TBHMOD_REF_CLK_312P5MHZ, init_config->pll1_div_init_value, &tvco_rate)); 1876 } else if (tvco_pll_index == 0) { 1877 PHYMOD_IF_ERR_RETURN( 1878 tbhmod_pll_to_vco_get(TBHMOD_REF_CLK_312P5MHZ, init_config->pll0_div_init_value, &tvco_rate)); 1879 } else { 1880 PHYMOD_DEBUG_ERROR(("Unsupported tvco index\n")); 1881 return PHYMOD_E_UNAVAIL; 1882 } 1883 } else { 1884 PHYMOD_DEBUG_ERROR(("Unsupported reference clock.\n")); 1885 return PHYMOD_E_UNAVAIL; 1886 } 1887 1888 /*next need to load speed id table and AM table */ 1889 speed_id_load_size = TSCBH_SPEED_ID_TABLE_SIZE > TSCBH_HW_SPEED_ID_TABLE_SIZE ? TSCBH_HW_SPEED_ID_TABLE_SIZE : TSCBH_SPEED_ID_TABLE_SIZE; 1890 am_table_load_size = TSCBH_AM_TABLE_SIZE > TSCBH_HW_AM_TABLE_SIZE ? TSCBH_HW_AM_TABLE_SIZE : TSCBH_AM_TABLE_SIZE; 1891 um_table_load_size = TSCBH_UM_TABLE_SIZE > TSCBH_HW_UM_TABLE_SIZE ? TSCBH_HW_UM_TABLE_SIZE : TSCBH_UM_TABLE_SIZE; 1892 1893 if (tvco_rate == TBHMOD_VCO_26G) { 1894 for (i = 0; i < speed_id_load_size; i++) { 1895 PHYMOD_IF_ERR_RETURN 1896 (phymod_mem_write(&core_copy.access, phymodMemSpeedIdTable, i, &spd_id_entry_26[i][0])); 1897 } 1898 } else if (tvco_rate == TBHMOD_VCO_25G) { 1899 for (i = 0; i < speed_id_load_size; i++) { 1900 PHYMOD_IF_ERR_RETURN 1901 (phymod_mem_write(&core_copy.access, phymodMemSpeedIdTable, i, &spd_id_entry_25[i][0])); 1902 } 1903 } else if (tvco_rate == TBHMOD_VCO_20G) { 1904 for (i = 0; i < speed_id_load_size; i++) { 1905 PHYMOD_IF_ERR_RETURN 1906 (phymod_mem_write(&core_copy.access, phymodMemSpeedIdTable, i, &spd_id_entry_20[i][0])); 1907 } 1908 } 1909 1910 for (i = 0; i < am_table_load_size; i++) { 1911 PHYMOD_IF_ERR_RETURN 1912 (phymod_mem_write(&core_copy.access, phymodMemAMTable, i, &am_table_entry[i][0])); 1913 } 1914 1915 for (i = 0; i < um_table_load_size; i++) { 1916 PHYMOD_IF_ERR_RETURN 1917 (phymod_mem_write(&core_copy.access, phymodMemUMTable, i, &um_table_entry[i][0])); 1918 } 1919 1920 /*need to update speed_priority_mapping_table with correct speed id */ 1921 PHYMOD_IF_ERR_RETURN 1922 (phymod_mem_write(&core_copy.access, phymodMemSpeedPriorityMapTable, 0, &speed_priority_mapping_table[0][0])); 1923 1924 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 1925 ucode_info_t ucode; 1926 PHYMOD_IF_ERR_RETURN 1927 (tbhmod_revid_get(&phy_access.access, &rev_num)); 1928 if (rev_num == TBHMOD_REV_NUM_0) { 1929 ucode.stack_size = blackhawk_ucode_stack_size_rev0; 1930 ucode.ucode_size = blackhawk_ucode_len_rev0; 1931 ucode.crc_value = blackhawk_ucode_crc_rev0; 1932 } else { 1933 ucode.stack_size = blackhawk_ucode_stack_size_rev1; 1934 ucode.ucode_size = blackhawk_ucode_len_rev1; 1935 ucode.crc_value = blackhawk_ucode_crc_rev1; 1936 } 1937 1938 /* per PLP, uc will set this bit, so SW does not need to do this anymore */ 1939 /* PHYMOD_IF_ERR_RETURN 1940 (blackhawk_uc_active_set(&core_copy.access ,1)); */ 1941 1942 /* 6. Release uc reset */ 1943 PHYMOD_IF_ERR_RETURN 1944 (blackhawk_tsc_uc_reset_with_info(&core_copy.access , 0, ucode)); 1945 1946 /* 7. Wait for uc_active = 1 */ 1947 PHYMOD_IF_ERR_RETURN 1948 (blackhawk_tsc_wait_uc_active(&phy_access.access)); 1949 1950 for (lane = 0; lane < TSCBH_NOF_LANES_IN_CORE; lane++) { 1951 phy_access_copy.access.lane_mask = 1 << lane; 1952 PHYMOD_IF_ERR_RETURN 1953 (blackhawk_pmd_ln_h_rstb_pkill_override(&phy_access_copy.access, 0x1)); 1954 } 1955 1956 /* 8. Initialize software information table for the macro */ 1957 PHYMOD_IF_ERR_RETURN 1958 (blackhawk_tsc_init_blackhawk_tsc_info(&core_copy.access)); 1959 1960 /* check the FW crc checksum error */ 1961 if (!PHYMOD_CORE_INIT_F_BYPASS_CRC_CHECK_GET(init_config)) { 1962 PHYMOD_IF_ERR_RETURN 1963 (blackhawk_tsc_check_ucode_crc(&core_copy.access, ucode.crc_value, 200)); 1964 } 1965 1966 /* release pmd lane hard reset */ 1967 for (lane = 0; lane < TSCBH_NOF_LANES_IN_CORE; lane++) { 1968 phy_access_copy.access.lane_mask = 1 << lane; 1969 PHYMOD_IF_ERR_RETURN 1970 (blackhawk_pmd_ln_h_rstb_pkill_override(&phy_access_copy.access, 0x0)); 1971 } 1972 } else { 1973 PHYMOD_IF_ERR_RETURN 1974 (blackhawk_tsc_firmware_load_none_init_blackhawk_tsc_info(&core_copy.access)); 1975 } 1976 1977 /* 9. RX/TX polarity configuration */ 1978 1979 for (lane = 0; lane < TSCBH_NOF_LANES_IN_CORE; lane++) { 1980 phy_access_copy.access.lane_mask = 1 << lane; 1981 tmp_pol.tx_polarity = (init_config->polarity_map.tx_polarity) >> lane & 0x1; 1982 tmp_pol.rx_polarity = (init_config->polarity_map.rx_polarity) >> lane & 0x1; 1983 PHYMOD_IF_ERR_RETURN 1984 (tscbh_phy_polarity_set(&phy_access_copy, &tmp_pol)); 1985 /* clear the tmp vairiable */ 1986 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 1987 } 1988 1989 /* 10. AFE/PLL configuration */ 1990 for (pll_index = 0; pll_index < 2; pll_index++) { 1991 core_copy.access.pll_idx = pll_index; 1992 PHYMOD_IF_ERR_RETURN 1993 (blackhawk_afe_pll_reg_set(&core_copy.access, &init_config->afe_pll)); 1994 } 1995 1996 /* PLL_DIV config for both PLL0 and PLL1 */ 1997 1998 if (init_config->pll0_div_init_value != phymod_TSCBH_PLL_DIVNONE) { 1999 core_copy.access.pll_idx = 0; 2000 PHYMOD_IF_ERR_RETURN 2001 (blackhawk_tsc_configure_pll_refclk_div(&core_copy.access, 2002 refclk, 2003 init_config->pll0_div_init_value)); 2004 } 2005 2006 if (init_config->pll1_div_init_value != phymod_TSCBH_PLL_DIVNONE) { 2007 core_copy.access.pll_idx = 1; 2008 PHYMOD_IF_ERR_RETURN 2009 (blackhawk_tsc_configure_pll_refclk_div(&core_copy.access, 2010 refclk, 2011 init_config->pll1_div_init_value)); 2012 } 2013 2014 /* 12. Program AN default timer for both MMP0 and MMP1*/ 2015 core_copy.access.lane_mask = 0x1; 2016 core_copy.access.pll_idx = 0; 2017 PHYMOD_IF_ERR_RETURN 2018 (tbhmod_set_an_timers(&core_copy.access, init_config->interface.ref_clock, NULL)); 2019 2020 core_copy.access.lane_mask = 0x10; 2021 core_copy.access.pll_idx = 0; 2022 PHYMOD_IF_ERR_RETURN 2023 (tbhmod_set_an_timers(&core_copy.access, init_config->interface.ref_clock, NULL)); 2024 2025 /* 13. Load spd_id_table, am_table and um_table into TSC memory */ 2026 2027 /* 14. Release core DP soft reset for both PLLs */ 2028 core_copy.access.lane_mask = 0x1; 2029 core_copy.access.pll_idx = 0; 2030 /* next need to config PMD micro clock source, chip defualt is PLL0 and SW driver will overwrite the 2031 default to use PLL1 */ 2032 PHYMOD_IF_ERR_RETURN 2033 (blackhawk_micro_clk_source_select(&core_copy.access, 1)); 2034 PHYMOD_IF_ERR_RETURN 2035 (blackhawk_tsc_core_dp_reset(&core_copy.access, 0)); 2036 core_copy.access.pll_idx = 1; 2037 PHYMOD_IF_ERR_RETURN 2038 (blackhawk_tsc_core_dp_reset(&core_copy.access, 0)); 2039 2040 return PHYMOD_E_NONE; 2041 2042 } 2043 2044 int tscbh_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 2045 { 2046 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 2047 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 2048 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 2049 PHYMOD_IF_ERR_RETURN 2050 (_tscbh_core_init_pass1(core, init_config, core_status)); 2051 2052 if (PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 2053 return PHYMOD_E_NONE; 2054 } 2055 } 2056 2057 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 2058 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 2059 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) { 2060 PHYMOD_IF_ERR_RETURN 2061 (_tscbh_core_init_pass2(core, init_config, core_status)); 2062 } 2063 2064 return PHYMOD_E_NONE; 2065 } 2066 2067 int tscbh_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config) 2068 { 2069 /*int pll_restart = 0;*/ 2070 const phymod_access_t *pm_acc = &phy->access; 2071 phymod_phy_access_t pm_phy_copy; 2072 int start_lane, num_lane, i; 2073 phymod_firmware_lane_config_t firmware_lane_config; 2074 uint32_t rev_num, pll_power_down = 0; 2075 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2076 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 2077 2078 PHYMOD_IF_ERR_RETURN 2079 (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane)); 2080 /* per lane based reset release */ 2081 PHYMOD_IF_ERR_RETURN 2082 (tbhmod_pmd_x4_reset(&pm_phy_copy.access)); 2083 2084 /* Put PMD lane into soft reset */ 2085 PHYMOD_IF_ERR_RETURN 2086 (blackhawk_lane_soft_reset(&pm_phy_copy.access, 1)); 2087 2088 /* next get version number */ 2089 pm_phy_copy.access.lane_mask = 0x1; 2090 PHYMOD_IF_ERR_RETURN 2091 (tbhmod_revid_get(&pm_phy_copy.access, &rev_num)); 2092 2093 2094 /* clearing all the lane config */ 2095 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 2096 2097 for (i = 0; i < num_lane; i++) { 2098 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2099 continue; 2100 } 2101 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2102 /* set tx parameters */ 2103 PHYMOD_IF_ERR_RETURN 2104 (tscbh_phy_tx_set(&pm_phy_copy, &init_config->tx[i])); 2105 } 2106 2107 2108 for (i = 0; i < num_lane; i++) { 2109 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2110 continue; 2111 } 2112 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2113 PHYMOD_IF_ERR_RETURN 2114 (_tscbh_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config)); 2115 /* FROM PMD team: 2116 * The best initial analog calibration is achieved using the information 2117 * from the PMD RX PRBS checker. Using the FW register value of 3 enables 2118 * a continuous version that does not rely on PRBS traffic anymore. 2119 * the value of 3 o will apply to A0 part only, and for B0 the value will be 0 2120 */ 2121 if (rev_num == TBHMOD_REV_NUM_0) { 2122 PHYMOD_IF_ERR_RETURN 2123 (blackhawk_tsc_lane_cfg_fwapi_data1_set(&pm_phy_copy.access, 3)); 2124 } else { 2125 PHYMOD_IF_ERR_RETURN 2126 (blackhawk_tsc_lane_cfg_fwapi_data1_set(&pm_phy_copy.access, 0)); 2127 } 2128 } 2129 2130 #if 0 2131 /* next check if pcs-bypass mode */ 2132 if (PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 2133 pm_phy_copy.access.lane_mask = lane_bkup; 2134 PHYMOD_IF_ERR_RETURN 2135 (blackhawk_pmd_tx_disable_pin_dis_set(&pm_phy_copy.access, 1)); 2136 PHYMOD_IF_ERR_RETURN 2137 (tbhmod_init_pcs_ilkn(&phy->access)); 2138 } 2139 2140 PHYMOD_IF_ERR_RETURN 2141 (tbhmod_update_port_mode(pm_acc, &pll_restart)); 2142 #endif 2143 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2144 PHYMOD_IF_ERR_RETURN 2145 (tbhmod_rx_lane_control(&pm_phy_copy.access, 1)); 2146 PHYMOD_IF_ERR_RETURN 2147 (tbhmod_tx_lane_control(&pm_phy_copy.access, 1, 0)); /* TX_LANE_CONTROL */ 2148 2149 /* make sure that power up PLL is locked */ 2150 pm_phy_copy.access.pll_idx = 0; 2151 pm_phy_copy.access.lane_mask = 1 << 0; 2152 PHYMOD_IF_ERR_RETURN 2153 (blackhawk_tsc_pll_pwrdn_get(&pm_phy_copy.access, &pll_power_down)); 2154 2155 /* need to check pll0 lock if not power up */ 2156 /* put the check here is to save on boot up time */ 2157 if (!pll_power_down) { 2158 uint32_t cnt = 0, pll_lock = 0; 2159 cnt = 0; 2160 while (cnt < 500) { 2161 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_pll_lock_get(&pm_phy_copy.access, &pll_lock)); 2162 cnt = cnt + 1; 2163 if (pll_lock) { 2164 break; 2165 } else { 2166 if(cnt == 500) { 2167 PHYMOD_DEBUG_ERROR(("WARNING :: core 0x%x PLL0 is not locked within 5 milli second \n", pm_phy_copy.access.addr)); 2168 break; 2169 } 2170 } 2171 PHYMOD_USLEEP(10); 2172 } 2173 } 2174 2175 pm_phy_copy.access.pll_idx = 1; 2176 pm_phy_copy.access.lane_mask = 1 << 0; 2177 PHYMOD_IF_ERR_RETURN 2178 (blackhawk_tsc_pll_pwrdn_get(&pm_phy_copy.access, &pll_power_down)); 2179 2180 /* need to check pll1 lock if not power up */ 2181 if (!pll_power_down) { 2182 uint32_t cnt = 0, pll_lock = 0; 2183 cnt = 0; 2184 while (cnt < 500) { 2185 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_pll_lock_get(&pm_phy_copy.access, &pll_lock)); 2186 cnt = cnt + 1; 2187 if (pll_lock) { 2188 break; 2189 } else { 2190 if(cnt == 500) { 2191 PHYMOD_DEBUG_ERROR(("WARNING :: core 0x%x PLL1 is not locked within 5 milli second \n", pm_phy_copy.access.addr)); 2192 break; 2193 } 2194 } 2195 PHYMOD_USLEEP(10); 2196 } 2197 } 2198 2199 return PHYMOD_E_NONE; 2200 } 2201 2202 2203 /* this function gives the PMD_RX_LOCK_STATUS */ 2204 int tscbh_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status) 2205 { 2206 phymod_phy_access_t pm_phy_copy; 2207 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2208 2209 PHYMOD_IF_ERR_RETURN(tbhmod_get_pcs_latched_link_status(&pm_phy_copy.access, link_status)); 2210 return PHYMOD_E_NONE; 2211 } 2212 2213 2214 int tscbh_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* pmd_lock) 2215 { 2216 int start_lane, num_lane, i; 2217 phymod_phy_access_t pm_phy_copy; 2218 uint8_t tmp_lock; 2219 2220 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2221 *pmd_lock = 1; 2222 2223 PHYMOD_IF_ERR_RETURN 2224 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2225 2226 for (i = 0; i < num_lane; i++) { 2227 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 2228 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2229 continue; 2230 } 2231 PHYMOD_IF_ERR_RETURN 2232 (blackhawk_tsc_pmd_lock_status(&pm_phy_copy.access, &tmp_lock)); 2233 *pmd_lock &= (uint32_t) tmp_lock; 2234 } 2235 return PHYMOD_E_NONE; 2236 2237 } 2238 2239 /* this function gives the PMD_RX_LOCK_STATUS */ 2240 int tscbh_phy_rx_signal_detect_get(const phymod_phy_access_t* phy, uint32_t* signal_detect) 2241 { 2242 int start_lane, num_lane, i; 2243 phymod_phy_access_t pm_phy_copy; 2244 uint32_t tmp_detect; 2245 2246 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2247 *signal_detect = 1; 2248 2249 PHYMOD_IF_ERR_RETURN 2250 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2251 2252 for (i = 0; i < num_lane; i++) { 2253 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 2254 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2255 continue; 2256 } 2257 PHYMOD_IF_ERR_RETURN 2258 (blackhawk_tsc_signal_detect(&pm_phy_copy.access, &tmp_detect)); 2259 *signal_detect &= tmp_detect; 2260 } 2261 return PHYMOD_E_NONE; 2262 2263 } 2264 2265 int tscbh_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val) 2266 { 2267 PHYMOD_IF_ERR_RETURN(phymod_tscbh_iblk_read(&phy->access, reg_addr, val)); 2268 return PHYMOD_E_NONE; 2269 } 2270 2271 2272 int tscbh_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val) 2273 { 2274 PHYMOD_IF_ERR_RETURN(phymod_tscbh_iblk_write(&phy->access, reg_addr, val)); 2275 return PHYMOD_E_NONE; 2276 } 2277 2278 /* get default tx taps*/ 2279 int tscbh_phy_tx_taps_default_get(const phymod_phy_access_t* phy, phymod_phy_signalling_method_t mode, phymod_tx_t* tx) 2280 { 2281 /*always default to 6-taps mode */ 2282 tx->tap_mode = phymodTxTapMode6Tap; 2283 tx->sig_method = mode; 2284 if (mode == phymodSignallingMethodNRZ) { 2285 tx->pre2 = 0; 2286 tx->pre = 0; 2287 tx->main = 127; 2288 tx->post = 0; 2289 tx->post2 = 0; 2290 tx->post3 = 0; 2291 } else { 2292 tx->pre2 = 0; 2293 tx->pre = -24; 2294 tx->main = 132; 2295 tx->post = -12; 2296 tx->post2 = 0; 2297 tx->post3 = 0; 2298 } 2299 2300 return PHYMOD_E_NONE; 2301 } 2302 2303 /* get default tx taps*/ 2304 int tscbh_phy_lane_config_default_get(const phymod_phy_access_t* phy, phymod_phy_signalling_method_t mode, phymod_firmware_lane_config_t* lane_config) 2305 { 2306 /* default always assume backplane as the medium type and with dfe on */ 2307 if (mode == phymodSignallingMethodNRZ) { 2308 lane_config->ForceNRZMode = 1; 2309 lane_config->ForcePAM4Mode = 0; 2310 lane_config->ForceNormalReach = 0; 2311 } else { 2312 lane_config->ForceNRZMode = 0; 2313 lane_config->ForcePAM4Mode = 1; 2314 lane_config->ForceNormalReach = 1; 2315 } 2316 lane_config->LaneConfigFromPCS = 0; 2317 lane_config->AnEnabled = 0; 2318 lane_config->DfeOn = 1; 2319 lane_config->LpDfeOn = 0; 2320 lane_config->ForceBrDfe = 0; 2321 lane_config->MediaType = 0; 2322 lane_config->ScramblingDisable = 0; 2323 lane_config->Cl72AutoPolEn = 0; 2324 lane_config->Cl72RestTO = 0; 2325 lane_config->ForceExtenedReach = 0; 2326 lane_config->LpPrecoderEnabled = 0; 2327 lane_config->UnreliableLos = 0; 2328 2329 return PHYMOD_E_NONE; 2330 } 2331 2332 int tscbh_phy_pll_multiplier_get(const phymod_phy_access_t* phy, uint32_t* core_vco_pll_multiplier) 2333 { 2334 phymod_phy_access_t pm_phy_copy; 2335 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2336 2337 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_INTERNAL_read_pll_div(&pm_phy_copy.access, core_vco_pll_multiplier)); 2338 return PHYMOD_E_NONE; 2339 } 2340 2341 int tscbh_phy_firmware_load_info_get(const phymod_phy_access_t* phy, phymod_firmware_load_info_t* info) 2342 { 2343 uint32_t rev_num; 2344 phymod_phy_access_t phy_copy; 2345 2346 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2347 phy_copy.access.lane_mask = 0x1; 2348 2349 PHYMOD_IF_ERR_RETURN 2350 (tbhmod_revid_get(&(phy_copy.access), &rev_num)); 2351 if (rev_num == TBHMOD_REV_NUM_0) { 2352 info->ucode_ptr = &blackhawk_ucode_rev0[0]; 2353 info->ucode_len = blackhawk_ucode_len_rev0; 2354 } else { 2355 info->ucode_ptr = &blackhawk_ucode_rev1[0]; 2356 info->ucode_len = blackhawk_ucode_len_rev1; 2357 } 2358 return PHYMOD_E_NONE; 2359 } 2360 2361 int _tscbh_phy_autoneg_ability_to_vco_get(const phymod_autoneg_advert_abilities_t* an_advert_abilities, 2362 uint16_t* request_vco) 2363 { 2364 phymod_autoneg_advert_ability_t* an_ability; 2365 int i; 2366 2367 an_ability = an_advert_abilities->autoneg_abilities; 2368 /* We do not validate each abilities here since they are supposed to be validated in portmod. */ 2369 for (i = 0; i < an_advert_abilities->num_abilities; i++) { 2370 switch (an_ability[i].speed) { 2371 case 10000: 2372 /* CL73-10G-1lane */ 2373 *request_vco |= TBHMOD_VCO_20G; 2374 break; 2375 case 20000: 2376 /* CL73BAM-20G-2lanes */ 2377 *request_vco |= TBHMOD_VCO_20G; 2378 break; 2379 case 25000: 2380 /* CL73-1lane; CL73BAM-1lane; MSA-1lane */ 2381 *request_vco |= TBHMOD_VCO_25G; 2382 break; 2383 case 40000: 2384 /* CL73-40G-4lanes */ 2385 /* CL73BAM-40G-2lanes */ 2386 *request_vco |= TBHMOD_VCO_20G; 2387 break; 2388 case 50000: 2389 if (an_ability[i].fec == phymod_fec_RS544) { 2390 /* CL73-50G-1lane */ 2391 /* CL73BAM-50G-2lanes-RS544 */ 2392 *request_vco |= TBHMOD_VCO_26G; 2393 } else { 2394 /* CL73BAM-50G-1lane*/ 2395 /* CL73BAM-50G-2lanes-Nofec/CL74/RS528 */ 2396 /* MSA-50G-2lanes */ 2397 *request_vco |= TBHMOD_VCO_25G; 2398 } 2399 break; 2400 case 100000: 2401 if (an_ability[i].fec == phymod_fec_RS544) { 2402 /* CL73-100G-2lanes */ 2403 /* CL73BAM-100G-4lanes-RS544 */ 2404 *request_vco |= TBHMOD_VCO_26G; 2405 } else { 2406 /* CL73-100G-4lanes */ 2407 /* CL73BAM-100G-2lanes-RS528 */ 2408 /* CL73BAM-100G-2lanes-Nofec */ 2409 /* CL73BAM-100G-4lanes-Nofec */ 2410 *request_vco |= TBHMOD_VCO_25G; 2411 } 2412 break; 2413 case 200000: 2414 if ((an_ability[i].fec == phymod_fec_RS544) 2415 || (an_ability[i].fec == phymod_fec_RS544_2XN)) { 2416 /* CL73-200G-4lanes-RS544_2XN */ 2417 /* CL73BAM-200G-4lanes-RS544_1XN */ 2418 *request_vco |= TBHMOD_VCO_26G; 2419 } else { 2420 /* CL73BAM-200G-4lanes-Nofec */ 2421 *request_vco |= TBHMOD_VCO_25G; 2422 } 2423 break; 2424 default: 2425 break; 2426 } 2427 2428 } 2429 2430 return PHYMOD_E_NONE; 2431 } 2432 2433 int tscbh_phy_autoneg_advert_ability_set(const phymod_phy_access_t* phy, 2434 const phymod_autoneg_advert_abilities_t* an_advert_abilities, 2435 const phymod_phy_pll_state_t* old_pll_adv_state, 2436 phymod_phy_pll_state_t* new_pll_adv_state) 2437 { 2438 uint16_t request_vco = 0; 2439 int start_lane, num_lane, i = 0, requested_pll_num; 2440 phymod_phy_access_t phy_copy; 2441 tbhmod_refclk_t ref_clk; 2442 uint32_t request_pll_div[3], ovco_is_pwrdn = 0; 2443 uint32_t ovco_pll_div = 0, tvco_pll_div = 0, pll_index = 0; 2444 uint8_t ovco_pll_index; 2445 uint32_t cnt, pll_lock = 0; 2446 2447 PHYMOD_IF_ERR_RETURN 2448 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2449 2450 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2451 phy_copy.access.lane_mask = 0x1 << start_lane; 2452 2453 ovco_pll_index = phy->access.tvco_pll_index ? 0 : 1; 2454 2455 /* Program local advert abilitiy registers */ 2456 PHYMOD_IF_ERR_RETURN 2457 (tbhmod_autoneg_ability_set(&phy_copy.access, an_advert_abilities)); 2458 2459 PHYMOD_IF_ERR_RETURN 2460 (_tscbh_phy_autoneg_ability_to_vco_get(an_advert_abilities, &request_vco)); 2461 2462 PHYMOD_IF_ERR_RETURN 2463 (tbhmod_refclk_get(&phy_copy.access, &ref_clk)); 2464 /* Check the request speed VCO */ 2465 if (request_vco & TBHMOD_VCO_20G) { 2466 PHYMOD_IF_ERR_RETURN 2467 (tbhmod_vco_to_pll_lkup(TBHMOD_VCO_20G, ref_clk, &request_pll_div[i])); 2468 i++; 2469 } 2470 if (request_vco & TBHMOD_VCO_25G) { 2471 PHYMOD_IF_ERR_RETURN 2472 (tbhmod_vco_to_pll_lkup(TBHMOD_VCO_25G, ref_clk, &request_pll_div[i])); 2473 i++; 2474 } 2475 if (request_vco & TBHMOD_VCO_26G) { 2476 PHYMOD_IF_ERR_RETURN 2477 (tbhmod_vco_to_pll_lkup(TBHMOD_VCO_26G, ref_clk, &request_pll_div[i])); 2478 i++; 2479 } 2480 if (i > 2) { 2481 /* More than 2 vcos are needed */ 2482 return PHYMOD_E_PARAM; 2483 } 2484 requested_pll_num = i - 1; 2485 2486 /* Get OVCO info */ 2487 phy_copy.access.pll_idx = ovco_pll_index; 2488 PHYMOD_IF_ERR_RETURN 2489 (blackhawk_tsc_pll_pwrdn_get(&phy_copy.access, &ovco_is_pwrdn)); 2490 if (!ovco_is_pwrdn) { 2491 PHYMOD_IF_ERR_RETURN 2492 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &ovco_pll_div)); 2493 } 2494 2495 /* Get TVCO info */ 2496 phy_copy.access.pll_idx = phy->access.tvco_pll_index; 2497 PHYMOD_IF_ERR_RETURN 2498 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &tvco_pll_div)); 2499 2500 /* Copy existing PLL lane bitmap */ 2501 *new_pll_adv_state = *old_pll_adv_state; 2502 2503 /* Clear current lane_map from both PLL lane bitmap */ 2504 new_pll_adv_state->pll1_lanes_bitmap &= ~(phy->access.lane_mask); 2505 new_pll_adv_state->pll0_lanes_bitmap &= ~(phy->access.lane_mask); 2506 2507 for (i = requested_pll_num; i >= 0; i--) { 2508 if (request_pll_div[i] == ovco_pll_div) { 2509 /* if ovco is using PLL 0 */ 2510 if (!ovco_pll_index) { 2511 new_pll_adv_state->pll0_lanes_bitmap |= phy->access.lane_mask; 2512 } else { 2513 new_pll_adv_state->pll1_lanes_bitmap |= phy->access.lane_mask; 2514 } 2515 } else if (request_pll_div[i] == tvco_pll_div) { 2516 /* if ovco is using PLL 0 */ 2517 if (!ovco_pll_index) { 2518 new_pll_adv_state->pll1_lanes_bitmap |= phy->access.lane_mask; 2519 } else { 2520 new_pll_adv_state->pll0_lanes_bitmap |= phy->access.lane_mask; 2521 } 2522 } else { 2523 /* Need VCO change */ 2524 pll_index = ovco_pll_index; 2525 phy_copy.access.pll_idx = pll_index; 2526 2527 if (ovco_is_pwrdn) { 2528 /* Power up PLL0 */ 2529 PHYMOD_IF_ERR_RETURN 2530 (blackhawk_tsc_core_pwrdn(&phy_copy.access, PWR_ON)); 2531 } 2532 /*toggle core dp reset */ 2533 phy_copy.access.lane_mask = 0x1; 2534 PHYMOD_IF_ERR_RETURN 2535 (blackhawk_tsc_core_dp_reset(&phy_copy.access, 1)); 2536 2537 /*config the PLL to the requested VCO */ 2538 if (ref_clk == TBHMOD_REF_CLK_312P5MHZ) { 2539 PHYMOD_IF_ERR_RETURN 2540 (blackhawk_tsc_configure_pll_refclk_div(&phy_copy.access, 2541 BLACKHAWK_TSC_PLL_REFCLK_312P5MHZ, 2542 request_pll_div[i])); 2543 } else { 2544 PHYMOD_IF_ERR_RETURN 2545 (blackhawk_tsc_configure_pll_refclk_div(&phy_copy.access, 2546 BLACKHAWK_TSC_PLL_REFCLK_156P25MHZ, 2547 request_pll_div[i])); 2548 } 2549 /* release core soft reset */ 2550 PHYMOD_IF_ERR_RETURN 2551 (blackhawk_tsc_core_dp_reset(&phy_copy.access, 0)); 2552 ovco_pll_div = request_pll_div[i]; 2553 new_pll_adv_state->pll0_lanes_bitmap |= phy->access.lane_mask; 2554 2555 /* need to wait for the PLL lock */ 2556 cnt = 0; 2557 while (cnt < 500) { 2558 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_pll_lock_get(&phy_copy.access, &pll_lock)); 2559 cnt = cnt + 1; 2560 if(pll_lock) { 2561 break; 2562 } else { 2563 if(cnt == 500) { 2564 PHYMOD_DEBUG_ERROR(("WARNING :: core 0x%x PLL Index %d is not locked within 5 milli second \n", phy_copy.access.addr, pll_index)); 2565 break; 2566 } 2567 } 2568 PHYMOD_USLEEP(10); 2569 } 2570 2571 } 2572 } 2573 2574 return PHYMOD_E_NONE; 2575 } 2576 2577 int tscbh_phy_autoneg_advert_ability_get(const phymod_phy_access_t* phy, 2578 phymod_autoneg_advert_abilities_t* an_advert_abilities) 2579 { 2580 phymod_phy_access_t phy_copy; 2581 int start_lane, num_lane, i; 2582 phymod_firmware_lane_config_t firmware_lane_config; 2583 2584 PHYMOD_IF_ERR_RETURN 2585 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2586 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2587 phy_copy.access.lane_mask = 0x1 << start_lane; 2588 2589 PHYMOD_IF_ERR_RETURN 2590 (tbhmod_autoneg_ability_get(&phy_copy.access, an_advert_abilities)); 2591 2592 /* Get Medium type from fw_lane_config */ 2593 PHYMOD_IF_ERR_RETURN 2594 (tscbh_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 2595 2596 for (i = 0; i < an_advert_abilities->num_abilities; i++) { 2597 an_advert_abilities->autoneg_abilities[i].medium = firmware_lane_config.MediaType; 2598 } 2599 2600 return PHYMOD_E_NONE; 2601 } 2602 2603 int tscbh_phy_autoneg_remote_advert_ability_get(const phymod_phy_access_t* phy, 2604 phymod_autoneg_advert_abilities_t* an_advert_abilities) 2605 { 2606 phymod_phy_access_t phy_copy; 2607 int start_lane, num_lane, i, is_copper = 0; 2608 2609 PHYMOD_IF_ERR_RETURN 2610 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2611 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2612 phy_copy.access.lane_mask = 0x1 << start_lane; 2613 2614 PHYMOD_IF_ERR_RETURN 2615 (tbhmod_autoneg_remote_ability_get(&phy_copy.access, an_advert_abilities)); 2616 2617 for (i = 0; i < an_advert_abilities->num_abilities; i++) { 2618 if (an_advert_abilities->autoneg_abilities[i].medium == phymodFirmwareMediaTypeCopperCable) { 2619 is_copper = 1; 2620 break; 2621 } 2622 } 2623 2624 for (i = 0; i < an_advert_abilities->num_abilities; i++) { 2625 if (is_copper) { 2626 an_advert_abilities->autoneg_abilities[i].medium = phymodFirmwareMediaTypeCopperCable; 2627 } else { 2628 an_advert_abilities->autoneg_abilities[i].medium = phymodFirmwareMediaTypePcbTraceBackPlane; 2629 } 2630 } 2631 2632 return PHYMOD_E_NONE; 2633 } 2634 2635 int tscbh_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 2636 { 2637 int num_lane_adv_encoded, mapped_speed_id; 2638 int start_lane, num_lane; 2639 int i, do_lane_config_set; 2640 uint32_t pll_1_div, vco_rate, refclk_in_hz; 2641 phymod_firmware_lane_config_t firmware_lane_config; 2642 tbhmod_an_control_t an_control; 2643 phymod_phy_access_t phy_copy; 2644 tbhmod_refclk_t ref_clk; 2645 tbhmod_spd_intfc_type_t spd_intf = 0; 2646 2647 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 2648 2649 PHYMOD_MEMSET(&an_control, 0x0, sizeof(an_control)); 2650 PHYMOD_IF_ERR_RETURN 2651 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2652 2653 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2654 phy_copy.access.lane_mask = 0x1 << start_lane; 2655 2656 if (an->enable) { 2657 PHYMOD_IF_ERR_RETURN(tbhmod_disable_set(&phy_copy.access)); 2658 /* adjust FEC arch for RS544 */ 2659 if (PHYMOD_AN_F_FEC_RS272_CLR_GET(an)) { 2660 PHYMOD_IF_ERR_RETURN(tbhmod_rsfec_cw_type(&phy_copy.access, 0, 0)); 2661 } 2662 2663 /*next choose TVCO as the PLL selelction for all the lanes*/ 2664 for (i = 0; i < num_lane; i++) { 2665 phy_copy.access.lane_mask = 1 << (start_lane + i); 2666 PHYMOD_IF_ERR_RETURN 2667 (blackhawk_lane_pll_selection_set(&phy_copy.access, phy->access.tvco_pll_index)); 2668 } 2669 } 2670 2671 switch (an->num_lane_adv) { 2672 case 1: 2673 num_lane_adv_encoded = 0; 2674 break; 2675 case 2: 2676 num_lane_adv_encoded = 1; 2677 break; 2678 case 4: 2679 num_lane_adv_encoded = 2; 2680 break; 2681 case 8: 2682 num_lane_adv_encoded = 3; 2683 break; 2684 default: 2685 return PHYMOD_E_PARAM; 2686 } 2687 2688 an_control.num_lane_adv = num_lane_adv_encoded; 2689 an_control.enable = an->enable; 2690 switch (an->an_mode) { 2691 case phymod_AN_MODE_CL73: 2692 an_control.an_type = TBHMOD_AN_MODE_CL73; 2693 break; 2694 case phymod_AN_MODE_CL73BAM: 2695 an_control.an_type = TBHMOD_AN_MODE_CL73_BAM; 2696 break; 2697 case phymod_AN_MODE_CL73_MSA: 2698 an_control.an_type = TBHMOD_AN_MODE_CL73_MSA; 2699 break; 2700 default: 2701 return PHYMOD_E_PARAM; 2702 break; 2703 } 2704 2705 /* SW WAR for 400G AN */ 2706 /* if AN is enabled, first needs to disable timer */ 2707 if (num_lane == 8) { 2708 if (an->enable) { 2709 PHYMOD_IF_ERR_RETURN 2710 (tbhmod_400g_autoneg_timer_disable(&phy_copy.access, 1)); 2711 } else { 2712 PHYMOD_IF_ERR_RETURN 2713 (tbhmod_400g_autoneg_timer_disable(&phy_copy.access, 0)); 2714 } 2715 } 2716 2717 if (an->enable) { 2718 /* Set AN port mode */ 2719 PHYMOD_IF_ERR_RETURN 2720 (tbhmod_set_an_port_mode(&phy_copy.access, start_lane)); 2721 2722 /* Get TVCO rate (PLL1 for now) */ 2723 PHYMOD_IF_ERR_RETURN 2724 (tbhmod_refclk_get(&phy_copy.access, &ref_clk)); 2725 2726 if (ref_clk == TBHMOD_REF_CLK_312P5MHZ) { 2727 refclk_in_hz = 312500000; 2728 } else { 2729 refclk_in_hz = 156250000; 2730 } 2731 2732 /* next read current TVCO pll divider*/ 2733 phy_copy.access.pll_idx = phy->access.tvco_pll_index; 2734 PHYMOD_IF_ERR_RETURN 2735 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_1_div)); 2736 2737 PHYMOD_IF_ERR_RETURN 2738 (blackhawk_tsc_get_vco_from_refclk_div(&phy_copy.access, refclk_in_hz, pll_1_div, &vco_rate, 0)); 2739 2740 if (vco_rate == 20625000) { 2741 /* load 20G VCO spd_id */ 2742 spd_intf = TBHMOD_SPD_CL73_20G; 2743 } else if (vco_rate == 25781250) { 2744 /* load 25G VCO spd_id */ 2745 spd_intf = TBHMOD_SPD_CL73_25G; 2746 } else if (vco_rate == 26562500) { 2747 /* load 26G VCO spd_id */ 2748 spd_intf = TBHMOD_SPD_CL73_26G; 2749 } else { 2750 return PHYMOD_E_PARAM; 2751 } 2752 2753 PHYMOD_IF_ERR_RETURN 2754 (tbhmod_get_mapped_speed(spd_intf, &mapped_speed_id)); 2755 2756 phy_copy.access.lane_mask = 0x1 << start_lane; 2757 2758 /* Load 1G speed ID */ 2759 PHYMOD_IF_ERR_RETURN 2760 (tbhmod_set_sc_speed(&phy_copy.access, mapped_speed_id, 0)); 2761 } 2762 2763 do_lane_config_set = 0; 2764 if (an->enable) { 2765 /* make sure the firmware config is set to an enabled */ 2766 PHYMOD_IF_ERR_RETURN 2767 (tscbh_phy_firmware_lane_config_get(&phy_copy, &firmware_lane_config)); 2768 /* make sure the firmware config is set to an enabled */ 2769 if (firmware_lane_config.AnEnabled != 1) { 2770 firmware_lane_config.AnEnabled = 1; 2771 do_lane_config_set = 1; 2772 } 2773 if (firmware_lane_config.LaneConfigFromPCS != 1) { 2774 firmware_lane_config.LaneConfigFromPCS = 1; 2775 do_lane_config_set = 1; 2776 } 2777 firmware_lane_config.Cl72RestTO = 0; 2778 firmware_lane_config.ForceNormalReach = 0; 2779 firmware_lane_config.ForceExtenedReach = 0; 2780 firmware_lane_config.ForceNRZMode= 0; 2781 firmware_lane_config.ForcePAM4Mode = 0; 2782 } 2783 2784 if (do_lane_config_set) { 2785 for (i = 0; i < num_lane; i++) { 2786 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2787 continue; 2788 } 2789 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2790 PHYMOD_IF_ERR_RETURN 2791 (blackhawk_lane_soft_reset(&phy_copy.access, 1)); 2792 } 2793 PHYMOD_USLEEP(1000); 2794 for (i = 0; i < num_lane; i++) { 2795 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2796 continue; 2797 } 2798 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2799 PHYMOD_IF_ERR_RETURN 2800 (_tscbh_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config)); 2801 } 2802 for (i = 0; i < num_lane; i++) { 2803 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2804 continue; 2805 } 2806 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2807 PHYMOD_IF_ERR_RETURN 2808 (blackhawk_lane_soft_reset(&phy_copy.access, 0)); 2809 } 2810 } 2811 2812 phy_copy.access.lane_mask = 0x1 << start_lane; 2813 2814 PHYMOD_IF_ERR_RETURN 2815 (tbhmod_autoneg_control(&phy_copy.access, &an_control)); 2816 /* for now comment out, need to revisit */ 2817 #if 0 2818 if (!an->enable) { 2819 tbhmod_enable_set(&phy_copy.access); 2820 } 2821 #endif 2822 2823 return PHYMOD_E_NONE; 2824 } 2825 2826 int tscbh_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done) 2827 { 2828 tbhmod_an_control_t an_control; 2829 phymod_phy_access_t phy_copy; 2830 int start_lane, num_lane; 2831 int an_complete = 0; 2832 2833 PHYMOD_IF_ERR_RETURN 2834 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2835 2836 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2837 phy_copy.access.lane_mask = 0x1 << start_lane; 2838 2839 PHYMOD_MEMSET(&an_control, 0x0, sizeof(tbhmod_an_control_t)); 2840 PHYMOD_IF_ERR_RETURN 2841 (tbhmod_autoneg_control_get(&phy_copy.access, &an_control, &an_complete)); 2842 2843 if (an_control.enable) { 2844 an->enable = 1; 2845 *an_done = an_complete; 2846 } else { 2847 an->enable = 0; 2848 } 2849 2850 switch (an_control.num_lane_adv) { 2851 case 0: 2852 an->num_lane_adv = 1; 2853 break; 2854 case 1: 2855 an->num_lane_adv = 2; 2856 break; 2857 case 2: 2858 an->num_lane_adv = 4; 2859 break; 2860 case 3: 2861 an->num_lane_adv = 8; 2862 break; 2863 default: 2864 an->num_lane_adv = 0; 2865 break; 2866 } 2867 2868 switch (an_control.an_type) { 2869 case TBHMOD_AN_MODE_CL73: 2870 an->an_mode = phymod_AN_MODE_CL73; 2871 break; 2872 case TBHMOD_AN_MODE_CL73_BAM: 2873 an->an_mode = phymod_AN_MODE_CL73BAM; 2874 break; 2875 case TBHMOD_AN_MODE_MSA: 2876 an->an_mode = phymod_AN_MODE_MSA; 2877 break; 2878 case TBHMOD_AN_MODE_CL73_MSA: 2879 an->an_mode = phymod_AN_MODE_CL73_MSA; 2880 break; 2881 default: 2882 an->an_mode = phymod_AN_MODE_NONE; 2883 break; 2884 } 2885 2886 return PHYMOD_E_NONE; 2887 } 2888 2889 int tscbh_phy_autoneg_status_get(const phymod_phy_access_t* phy, phymod_autoneg_status_t* status) 2890 { 2891 int an_en, an_done; 2892 phymod_phy_speed_config_t speed_config; 2893 phymod_phy_access_t phy_copy; 2894 int start_lane, num_lane, speed_id; 2895 uint32_t packed_entry[5]; 2896 spd_id_tbl_entry_t speed_config_entry; 2897 2898 PHYMOD_IF_ERR_RETURN 2899 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2900 2901 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2902 phy_copy.access.lane_mask = 0x1 << start_lane; 2903 2904 PHYMOD_IF_ERR_RETURN 2905 (tbhmod_autoneg_status_get(&phy_copy.access, &an_en, &an_done)); 2906 2907 PHYMOD_IF_ERR_RETURN 2908 (tscbh_phy_speed_config_get(phy, &speed_config)); 2909 2910 if (an_en && an_done) { 2911 uint32_t an_resolved_mode; 2912 /* if an resolves and link up */ 2913 PHYMOD_IF_ERR_RETURN 2914 (tbhmod_speed_id_get(&phy_copy.access, &speed_id)); 2915 /*read the speed id entry and get the num_lane info */ 2916 phy_copy.access.lane_mask = 1 << start_lane; 2917 PHYMOD_IF_ERR_RETURN 2918 (phymod_mem_read(&phy_copy.access, phymodMemSpeedIdTable, speed_id, packed_entry)); 2919 spd_ctrl_unpack_spd_id_tbl_entry(packed_entry, &speed_config_entry); 2920 num_lane = 1 << speed_config_entry.num_lanes; 2921 /* read the AN final resolved port mode */ 2922 PHYMOD_IF_ERR_RETURN 2923 (tbhmod_resolved_port_mode_get(&phy_copy.access, &an_resolved_mode)); 2924 status->resolved_port_mode = an_resolved_mode; 2925 } 2926 2927 status->enabled = an_en; 2928 status->locked = an_done; 2929 status->data_rate = speed_config.data_rate; 2930 status->resolved_num_lane = num_lane; 2931 2932 return PHYMOD_E_NONE; 2933 } 2934 2935 int tscbh_phy_pll_reconfig(const phymod_phy_access_t* phy, 2936 uint8_t pll_index, 2937 uint32_t pll_div) 2938 { 2939 phymod_phy_access_t pm_phy_copy; 2940 tbhmod_refclk_t ref_clk; 2941 /*phymod_tscbh_pll_multiplier_t pll_0, pll_1; */ 2942 uint32_t tvco_rate = 0, speed_id_load_size, i, pll_is_pwrdn; 2943 uint8_t tvco_pll_index, tvco_reconfig = 0; 2944 enum blackhawk_tsc_pll_refclk_enum refclk; 2945 uint32_t cnt = 0, pll_lock = 0; 2946 2947 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2948 tvco_pll_index = phy->access.tvco_pll_index; 2949 2950 if (pll_index > 1) { 2951 PHYMOD_DEBUG_ERROR(("Unsupported PLL index\n")); 2952 return PHYMOD_E_UNAVAIL; 2953 } 2954 2955 tvco_reconfig = (tvco_pll_index == pll_index) ? 1 : 0; 2956 2957 pm_phy_copy.access.lane_mask = 1 << 0; 2958 /* first needs to read the ref clock from main reg*/ 2959 PHYMOD_IF_ERR_RETURN 2960 (tbhmod_refclk_get(&pm_phy_copy.access, &ref_clk)); 2961 2962 if (ref_clk == TBHMOD_REF_CLK_156P25MHZ) { 2963 refclk = BLACKHAWK_TSC_PLL_REFCLK_156P25MHZ; 2964 } else if (ref_clk == TBHMOD_REF_CLK_312P5MHZ) { 2965 refclk = BLACKHAWK_TSC_PLL_REFCLK_312P5MHZ; 2966 } else { 2967 PHYMOD_DEBUG_ERROR(("Unsupported reference clock.\n")); 2968 return PHYMOD_E_UNAVAIL; 2969 } 2970 2971 if (tvco_reconfig) { 2972 PHYMOD_IF_ERR_RETURN 2973 (tbhmod_pll_to_vco_get(ref_clk, pll_div, &tvco_rate)); 2974 } 2975 2976 /* next disable pcs datapath only if TVCO re-config*/ 2977 if (tvco_reconfig) { 2978 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2979 PHYMOD_IF_ERR_RETURN 2980 (tbhmod_disable_set(&pm_phy_copy.access)); 2981 } 2982 2983 /*only need to load speed id table for tvco re-config */ 2984 /*then reload the speed id table based on the new tvco */ 2985 if (tvco_reconfig) { 2986 speed_id_load_size = TSCBH_SPEED_ID_TABLE_SIZE > TSCBH_HW_SPEED_ID_TABLE_SIZE ? TSCBH_HW_SPEED_ID_TABLE_SIZE : TSCBH_SPEED_ID_TABLE_SIZE; 2987 if (tvco_rate == TBHMOD_VCO_26G) { 2988 for (i = 0; i < speed_id_load_size; i++) { 2989 PHYMOD_IF_ERR_RETURN 2990 (phymod_mem_write(&pm_phy_copy.access, phymodMemSpeedIdTable, i, &spd_id_entry_26[i][0])); 2991 } 2992 } else if (tvco_rate == TBHMOD_VCO_25G) { 2993 for (i = 0; i < speed_id_load_size; i++) { 2994 PHYMOD_IF_ERR_RETURN 2995 (phymod_mem_write(&pm_phy_copy.access, phymodMemSpeedIdTable, i, &spd_id_entry_25[i][0])); 2996 } 2997 } else if (tvco_rate == TBHMOD_VCO_20G) { 2998 for (i = 0; i < speed_id_load_size; i++) { 2999 PHYMOD_IF_ERR_RETURN 3000 (phymod_mem_write(&pm_phy_copy.access, phymodMemSpeedIdTable, i, &spd_id_entry_20[i][0])); 3001 } 3002 } 3003 } 3004 3005 /*next check if the PLL is power down or not */ 3006 pm_phy_copy.access.pll_idx = pll_index; 3007 pm_phy_copy.access.lane_mask = 1 << 0; 3008 PHYMOD_IF_ERR_RETURN 3009 (blackhawk_tsc_pll_pwrdn_get(&pm_phy_copy.access, &pll_is_pwrdn)); 3010 3011 /* if PLL is power down, need to power up first */ 3012 if (pll_is_pwrdn) { 3013 /* Power up ovco if it's power down */ 3014 PHYMOD_IF_ERR_RETURN 3015 (blackhawk_tsc_core_pwrdn(&pm_phy_copy.access, PWR_ON)); 3016 } 3017 3018 PHYMOD_IF_ERR_RETURN 3019 (blackhawk_tsc_core_dp_reset(&pm_phy_copy.access, 1)); 3020 3021 /*next re-config pll divider */ 3022 PHYMOD_IF_ERR_RETURN 3023 (blackhawk_tsc_configure_pll_refclk_div(&pm_phy_copy.access, 3024 refclk, 3025 pll_div)); 3026 3027 PHYMOD_IF_ERR_RETURN 3028 (blackhawk_tsc_core_dp_reset(&pm_phy_copy.access, 0)); 3029 3030 /* need to wait for the PLL lock */ 3031 cnt = 0; 3032 while (cnt < 500) { 3033 PHYMOD_IF_ERR_RETURN(blackhawk_tsc_pll_lock_get(&pm_phy_copy.access, &pll_lock)); 3034 cnt = cnt + 1; 3035 if(pll_lock) { 3036 break; 3037 } else { 3038 if(cnt == 500) { 3039 PHYMOD_DEBUG_ERROR(("WARNING :: core 0x%x PLL Index %d is not locked within 5 milli second \n", pm_phy_copy.access.addr, pll_index)); 3040 break; 3041 } 3042 } 3043 PHYMOD_USLEEP(10); 3044 } 3045 3046 return PHYMOD_E_NONE; 3047 } 3048 3049 int tscbh_phy_tx_pam4_precoder_enable_set(const phymod_phy_access_t* phy, int enable) 3050 { 3051 phymod_phy_access_t phy_copy; 3052 int start_lane, num_lane, i; 3053 uint32_t lane_reset, pcs_lane_enable; 3054 3055 PHYMOD_IF_ERR_RETURN 3056 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3057 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3058 3059 /*first check if lane is in reset */ 3060 PHYMOD_IF_ERR_RETURN 3061 (blackhawk_lane_soft_reset_get(&phy_copy.access, &lane_reset)); 3062 3063 /*next check if PCS lane is in reset */ 3064 PHYMOD_IF_ERR_RETURN 3065 (tbhmod_enable_get(&phy_copy.access, &pcs_lane_enable)); 3066 3067 /* disable pcs lane if pcs lane not in rset */ 3068 if (pcs_lane_enable) { 3069 phy_copy.access.lane_mask = 1 << start_lane; 3070 PHYMOD_IF_ERR_RETURN 3071 (tbhmod_disable_set(&phy_copy.access)); 3072 } 3073 3074 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3075 /* if lane is not in reset, then reset the lane first */ 3076 if (!lane_reset) { 3077 PHYMOD_IF_ERR_RETURN 3078 (blackhawk_lane_soft_reset(&phy_copy.access, 1)); 3079 } 3080 3081 for (i = 0; i < num_lane; i++) { 3082 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 3083 continue; 3084 } 3085 phy_copy.access.lane_mask = 1 << (start_lane + i); 3086 PHYMOD_IF_ERR_RETURN 3087 (blackhawk_tsc_tx_pam4_precoder_enable_set(&phy_copy.access, enable)); 3088 } 3089 3090 /* release the ln dp reset */ 3091 if (!lane_reset) { 3092 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3093 PHYMOD_IF_ERR_RETURN 3094 (blackhawk_lane_soft_reset(&phy_copy.access, 0)); 3095 } 3096 3097 /* re-enable pcs lane if pcs lane not in rset */ 3098 if (pcs_lane_enable) { 3099 phy_copy.access.lane_mask = 1 << start_lane; 3100 PHYMOD_IF_ERR_RETURN 3101 (tbhmod_enable_set(&phy_copy.access)); 3102 } 3103 3104 return PHYMOD_E_NONE; 3105 } 3106 3107 int tscbh_phy_tx_pam4_precoder_enable_get(const phymod_phy_access_t* phy, int *enable) 3108 { 3109 phymod_phy_access_t pm_phy_copy; 3110 3111 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 3112 PHYMOD_IF_ERR_RETURN 3113 (blackhawk_tsc_tx_pam4_precoder_enable_get(&pm_phy_copy.access, enable)); 3114 return PHYMOD_E_NONE; 3115 } 3116 3117 /*Set/Get timesync enable*/ 3118 int tscbh_timesync_enable_set(const phymod_phy_access_t* phy, uint32_t flags, uint32_t enable) 3119 { 3120 phymod_phy_access_t phy_copy; 3121 int start_lane, num_lane, is_sfd = 0; 3122 uint32_t pcs_lane_enable; 3123 uint32_t fclk_div_mode = 0; 3124 3125 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3126 PHYMOD_IF_ERR_RETURN 3127 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3128 3129 phy_copy.access.lane_mask = 0x1 << start_lane; 3130 3131 /* RX timestamping control */ 3132 if (PHYMOD_TIMESYNC_ENABLE_F_RX_GET(flags)) { 3133 PHYMOD_IF_ERR_RETURN 3134 (tbhmod_pcs_rx_ts_en(&phy_copy.access, enable, is_sfd)); 3135 } 3136 3137 /* Core related control: 3138 * 1. Enable fclk on PMD, with default div_mode. 3139 */ 3140 if (PHYMOD_TIMESYNC_ENABLE_F_CORE_GET(flags)) { 3141 phy_copy.access.pll_idx = phy_copy.access.tvco_pll_index; 3142 PHYMOD_IF_ERR_RETURN 3143 (blackhawk_tsc_clk4sync_enable_set(&phy_copy.access, enable, fclk_div_mode)); 3144 } 3145 3146 /* One-Step Timestamp Pipeline */ 3147 if (PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_GET(flags)){ 3148 /* check if PCS lane is in reset */ 3149 PHYMOD_IF_ERR_RETURN 3150 (tbhmod_enable_get(&phy_copy.access, &pcs_lane_enable)); 3151 3152 /* disable pcs lane if pcs lane not in rset */ 3153 if (pcs_lane_enable) { 3154 PHYMOD_IF_ERR_RETURN 3155 (tbhmod_disable_set(&phy_copy.access)); 3156 } 3157 3158 PHYMOD_IF_ERR_RETURN 3159 (tbhmod_osts_pipeline(&phy_copy.access, enable)); 3160 3161 /* re-enable pcs lane if pcs lane not in rset */ 3162 if (pcs_lane_enable) { 3163 PHYMOD_IF_ERR_RETURN 3164 (tbhmod_enable_set(&phy_copy.access)); 3165 } 3166 } 3167 3168 return PHYMOD_E_NONE; 3169 } 3170 3171 /* Only one flag can be served each time. 3172 */ 3173 int tscbh_timesync_enable_get(const phymod_phy_access_t* phy, uint32_t flags, uint32_t* enable) 3174 { 3175 phymod_phy_access_t phy_copy; 3176 uint32_t fclk_div_mode; 3177 3178 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3179 3180 if (PHYMOD_TIMESYNC_ENABLE_F_RX_GET(flags)) { 3181 PHYMOD_IF_ERR_RETURN 3182 (tbhmod_pcs_rx_ts_en_get(&phy_copy.access, enable)); 3183 } 3184 3185 if (PHYMOD_TIMESYNC_ENABLE_F_ONE_STEP_PIPELINE_GET(flags)){ 3186 PHYMOD_IF_ERR_RETURN 3187 (tbhmod_osts_pipeline_get(&phy_copy.access, enable)); 3188 } 3189 3190 if (PHYMOD_TIMESYNC_ENABLE_F_CORE_GET(flags)) { 3191 phy_copy.access.pll_idx = phy_copy.access.tvco_pll_index; 3192 PHYMOD_IF_ERR_RETURN 3193 (blackhawk_tsc_clk4sync_enable_get(&phy_copy.access, enable, &fclk_div_mode)); 3194 } 3195 3196 return PHYMOD_E_NONE; 3197 } 3198 3199 /*Set timesync adjust*/ 3200 int tscbh_timesync_adjust_set(const phymod_phy_access_t* phy, uint32_t ts_am_norm_mode) 3201 { 3202 int start_lane, num_lane, i, is_pam4, is_valid = 0; 3203 uint8_t fec_arch; 3204 int speed_id, mapped_speed_id; 3205 int an_en, an_done; 3206 phymod_phy_access_t phy_copy; 3207 spd_id_tbl_entry_t speed_config_entry; 3208 uint32_t packed_entry[5]; 3209 phymod_phy_speed_config_t speed_config; 3210 phymod_firmware_lane_config_t firmware_lane_config; 3211 tbhmod_spd_intfc_type_t spd_intf = 0; 3212 phymod_mem_type_t tx_mem,rx_mem; 3213 int ts_table_index; 3214 int osr_mode; 3215 ts_table_entry *ts_tx_entry = NULL, *ts_rx_entry = NULL; 3216 ts_table_entry ts_update_table; 3217 uint32_t psll_entry[TBHMOD_TS_TABLE_SIZE * TBHMOD_TS_PSLL_BASED_ENTRY_SIZE]; 3218 uint32_t psll_entry_size; 3219 uint32_t pll_div, pll_index; 3220 tbhmod_refclk_t ref_clk; 3221 uint32_t tvco, current_vco; 3222 int mem_offset; 3223 3224 if (ts_am_norm_mode == 0x2) { 3225 PHYMOD_DEBUG_ERROR(("TSCBH does not supported Latestlane Mode.\n")); 3226 return PHYMOD_E_UNAVAIL; 3227 } 3228 3229 /* Here starts the sequence to enable Timestamping based on the current speed config */ 3230 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3231 PHYMOD_IF_ERR_RETURN 3232 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3233 PHYMOD_IF_ERR_RETURN 3234 (tbhmod_autoneg_status_get(&phy_copy.access, &an_en, &an_done)); 3235 PHYMOD_IF_ERR_RETURN 3236 (tscbh_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 3237 3238 is_pam4 = firmware_lane_config.ForcePAM4Mode; 3239 psll_entry_size = TBHMOD_TS_TABLE_SIZE * TBHMOD_TS_PSLL_BASED_ENTRY_SIZE; 3240 if (start_lane < 4) { 3241 /* MPP0 */ 3242 mem_offset = start_lane * TBHMOD_TS_TABLE_SIZE; 3243 } else { 3244 /* MPP1 */ 3245 mem_offset = (start_lane - 4) * TBHMOD_TS_TABLE_SIZE; 3246 } 3247 3248 /* 1. Find default 1588 Table */ 3249 3250 /* 1.1 Get current speed id */ 3251 PHYMOD_IF_ERR_RETURN 3252 (tbhmod_speed_id_get(&phy_copy.access, &speed_id)); 3253 3254 PHYMOD_IF_ERR_RETURN 3255 (phymod_mem_read(&phy_copy.access, phymodMemSpeedIdTable, speed_id, packed_entry)); 3256 spd_ctrl_unpack_spd_id_tbl_entry(packed_entry, &speed_config_entry); 3257 /* 1.2 Update num_lane and lane_mask for AN port */ 3258 if (an_en && an_done) { 3259 num_lane = 1 << speed_config_entry.num_lanes; 3260 /* Update lane_mask */ 3261 phy_copy.access.lane_mask = 0x0; 3262 for (i = 0; i < num_lane; i++) { 3263 phy_copy.access.lane_mask |= 0x1 << (i + start_lane); 3264 } 3265 } 3266 /* 1.3 Get FEC type */ 3267 PHYMOD_IF_ERR_RETURN 3268 (_tscbh_speed_id_to_speed_config_get(phy, speed_id, num_lane, &speed_config)); 3269 3270 if (an_en && an_done) { 3271 PHYMOD_IF_ERR_RETURN 3272 (tbhmod_autoneg_fec_status_get(&phy_copy.access, &fec_arch)); 3273 PHYMOD_IF_ERR_RETURN 3274 (tbhmod_fec_arch_decode_get(fec_arch, &(speed_config.fec_type))); 3275 } 3276 3277 /* 10G-CL74 does not support 1588 */ 3278 if ((speed_config.data_rate == 10000) && (speed_config.fec_type == phymod_fec_CL74)) { 3279 PHYMOD_DEBUG_ERROR(("1588 is not supported in current speed config.\n")); 3280 return PHYMOD_E_UNAVAIL; 3281 } 3282 3283 /* 1.4 Get mapped speed id */ 3284 if (speed_id <= 0x25) { 3285 /* AN speed IDs */ 3286 mapped_speed_id = speed_id; 3287 } else { 3288 /* Customized speed ID, need extra mapping. */ 3289 /* Only applys to FS */ 3290 PHYMOD_IF_ERR_RETURN(_tscbh_phy_speed_id_set(num_lane, speed_config.data_rate, 3291 speed_config.fec_type, &spd_intf)); 3292 PHYMOD_IF_ERR_RETURN 3293 (tbhmod_get_mapped_speed(spd_intf, &mapped_speed_id)); 3294 } 3295 3296 /* 1.5 Get the table index of the 1588 table */ 3297 PHYMOD_IF_ERR_RETURN 3298 (tbhmod_1588_table_index_get(mapped_speed_id, speed_config.fec_type, &ts_table_index)); 3299 3300 if (ts_table_index == -1) { 3301 PHYMOD_DEBUG_ERROR(("1588 is not supported in current speed config.\n")); 3302 return PHYMOD_E_UNAVAIL; 3303 } 3304 3305 /* 1.6 Find the 1588 table */ 3306 ts_tx_entry = (ts_table_entry*) &(ts_table_tx_sop[ts_table_index]); 3307 ts_rx_entry = (ts_table_entry*) &(ts_table_rx_sop[ts_table_index]); 3308 3309 if (num_lane == 8) { 3310 tx_mem = phymodMemTxLkup1588400G; 3311 rx_mem = phymodMemRxLkup1588400G; 3312 } else if (start_lane < 4) { 3313 tx_mem = phymodMemTxLkup1588Mpp0; 3314 rx_mem = phymodMemRxLkup1588Mpp0; 3315 } else { 3316 tx_mem = phymodMemTxLkup1588Mpp1; 3317 rx_mem = phymodMemRxLkup1588Mpp1; 3318 } 3319 /* Get OS mode */ 3320 PHYMOD_IF_ERR_RETURN 3321 (blackhawk_osr_mode_get(&phy_copy.access, &osr_mode)); 3322 3323 PHYMOD_IF_ERR_RETURN 3324 (tbhmod_refclk_get(&phy_copy.access, &ref_clk)); 3325 3326 /* Get current used VCO */ 3327 PHYMOD_IF_ERR_RETURN 3328 (blackhawk_lane_pll_selection_get(&phy_copy.access, &pll_index)); 3329 phy_copy.access.pll_idx = pll_index; 3330 PHYMOD_IF_ERR_RETURN 3331 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 3332 PHYMOD_IF_ERR_RETURN 3333 (tbhmod_pll_to_vco_get(ref_clk, pll_div, ¤t_vco)); 3334 /* Get TVCO */ 3335 phy_copy.access.pll_idx = phy_copy.access.tvco_pll_index; 3336 PHYMOD_IF_ERR_RETURN 3337 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 3338 PHYMOD_IF_ERR_RETURN 3339 (tbhmod_pll_to_vco_get(ref_clk, pll_div, &tvco)); 3340 3341 /* 2. Program UI */ 3342 3343 PHYMOD_IF_ERR_RETURN 3344 (tbhmod_pcs_set_1588_ui(&phy_copy.access, current_vco, tvco, osr_mode, 0, is_pam4)); 3345 3346 /* 3. Program PMD lantency */ 3347 PHYMOD_IF_ERR_RETURN 3348 (tbhmod_1588_pmd_latency(&phy_copy.access, current_vco, osr_mode, is_pam4)); 3349 3350 /* 4. Enable rx deskew 3351 * Need low to high transition to trigger HW recording the current status. 3352 */ 3353 if (ts_am_norm_mode == 0x1) { 3354 PHYMOD_IF_ERR_RETURN 3355 (tbhmod_pcs_rx_deskew_en(&phy_copy.access, 0)); 3356 PHYMOD_USLEEP(10); 3357 PHYMOD_IF_ERR_RETURN 3358 (tbhmod_pcs_rx_deskew_en(&phy_copy.access, 1)); 3359 } 3360 3361 /* 5. Load 1588 TX table */ 3362 /* Different MPPs have different memory space. 3363 * Different logical ports have different memory offset. 3364 */ 3365 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3366 PHYMOD_IF_ERR_RETURN 3367 (phymod_mem_write(&phy_copy.access, tx_mem, (i + mem_offset), &(*ts_tx_entry)[i][0])); 3368 } 3369 3370 /* 6. Load 1588 RX table */ 3371 if (ts_am_norm_mode == 0x1) { 3372 /* RX tbl need to update deskew before writing to mem */ 3373 /* 6.1 Check for deskew valid */ 3374 for (i = 0; i < 1000; i++) { 3375 PHYMOD_USLEEP(10); 3376 PHYMOD_IF_ERR_RETURN 3377 (tbhmod_pcs_ts_deskew_valid(&phy_copy.access, speed_config_entry.bit_mux_mode, &is_valid)); 3378 if (is_valid) { 3379 break; 3380 } 3381 } 3382 if (!is_valid) { 3383 return PHYMOD_E_TIMEOUT; 3384 } 3385 3386 /* 6.2 Update deskew to 1588 table */ 3387 /* 6.2.1 Translate RX table to psuedo logical lane(PSLL) based array */ 3388 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3389 PHYMOD_IF_ERR_RETURN 3390 (tbhmod_tbl_entry_to_psll_entry_map(&(*ts_rx_entry)[i][0], &psll_entry[i * TBHMOD_TS_PSLL_BASED_ENTRY_SIZE])); 3391 } 3392 3393 /* 6.2.2 Calculate deskew and update time value for each PSLL */ 3394 PHYMOD_IF_ERR_RETURN 3395 (tbhmod_pcs_mod_rx_1588_tbl_val(&phy_copy.access, speed_config_entry.bit_mux_mode, 3396 current_vco, osr_mode, is_pam4, psll_entry_size, psll_entry)); 3397 3398 /* 6.2.3 Translate PSLL based array back to 1588 entry format */ 3399 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3400 PHYMOD_IF_ERR_RETURN 3401 (tbhmod_psll_entry_to_tbl_entry_map(&psll_entry[i * TBHMOD_TS_PSLL_BASED_ENTRY_SIZE], &ts_update_table[i][0])); 3402 } 3403 3404 /* 6.3 Write the updated RX table to memroy */ 3405 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3406 PHYMOD_IF_ERR_RETURN 3407 (phymod_mem_write(&phy_copy.access, rx_mem, (i + mem_offset), &ts_update_table[i][0])); 3408 } 3409 } else { 3410 /* If deskew update is not required, load default tables */ 3411 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3412 PHYMOD_IF_ERR_RETURN 3413 (phymod_mem_write(&phy_copy.access, rx_mem, (i + mem_offset), &(*ts_rx_entry)[i][0])); 3414 } 3415 } 3416 3417 /* 7. Enable SFD/SOP timestamping on tx and rx */ 3418 /* In Gen1, only applys to 10G, 20G and 25G. */ 3419 PHYMOD_IF_ERR_RETURN 3420 (tbhmod_pcs_set_1588_xgmii(&phy_copy.access, 0, current_vco, osr_mode)); 3421 3422 return PHYMOD_E_NONE; 3423 } 3424 3425 3426 int _tscbh_flexport_sw_workaround(const phymod_phy_access_t* phy) 3427 { 3428 phymod_phy_access_t phy_copy; 3429 int start_lane, num_lane, mapped_speed_id; 3430 uint32_t pll_div, pll_index; 3431 uint32_t packed_entry[5]; 3432 tbhmod_spd_intfc_type_t spd_intf = 0; 3433 3434 PHYMOD_IF_ERR_RETURN 3435 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3436 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3437 /* enable PMD lane override */ 3438 phy_copy.access.lane_mask = 1 << start_lane; 3439 3440 /* Hold the pcs lane reset */ 3441 PHYMOD_IF_ERR_RETURN 3442 (tbhmod_disable_set(&phy_copy.access)); 3443 3444 /* get PLL index */ 3445 PHYMOD_IF_ERR_RETURN 3446 (blackhawk_lane_pll_selection_get(&phy_copy.access, &pll_index)); 3447 3448 /* get the PLL div */ 3449 phy_copy.access.lane_mask = 0x1; 3450 phy_copy.access.pll_idx = pll_index; 3451 PHYMOD_IF_ERR_RETURN 3452 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 3453 3454 /* for 26G VCO, use speed id 5 3455 for 25G vco, use speed id 2 3456 for 20G vco, use speed id 0 */ 3457 if ((pll_div == TBHMOD_PLL_MODE_DIV_170) || (pll_div == TBHMOD_PLL_MODE_DIV_85)) { 3458 spd_intf = TBHMOD_SPD_50G_IEEE_KR1_CR1; 3459 } else if ((pll_div == TBHMOD_PLL_MODE_DIV_165) || (pll_div == TBHMOD_PLL_MODE_DIV_82P5)) { 3460 spd_intf = TBHMOD_SPD_25000_XFI; 3461 } else { 3462 spd_intf = TBHMOD_SPD_10000_XFI; 3463 } 3464 3465 PHYMOD_IF_ERR_RETURN 3466 (tbhmod_get_mapped_speed(spd_intf, &mapped_speed_id)); 3467 3468 /*next read the speed id entry and then copy to the right forced speed */ 3469 phy_copy.access.lane_mask = 1 << 0; 3470 PHYMOD_IF_ERR_RETURN 3471 (phymod_mem_read(&phy_copy.access, phymodMemSpeedIdTable, mapped_speed_id, packed_entry)); 3472 PHYMOD_IF_ERR_RETURN 3473 (phymod_mem_write(&phy_copy.access, phymodMemSpeedIdTable, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, packed_entry)); 3474 3475 /* next update the port_mode */ 3476 phy_copy.access.lane_mask = 1 << start_lane; 3477 PHYMOD_IF_ERR_RETURN 3478 (tbhmod_update_port_mode(&phy_copy.access)); 3479 3480 /* add rx lock override */ 3481 PHYMOD_IF_ERR_RETURN 3482 (tbhmod_pmd_rx_lock_override_enable(&phy_copy.access, 1)); 3483 /* clear state machine state */ 3484 PHYMOD_IF_ERR_RETURN 3485 (tbhmod_read_sc_fsm_status(&phy_copy.access)); 3486 PHYMOD_IF_ERR_RETURN 3487 (tbhmod_read_sc_done(&phy_copy.access)); 3488 PHYMOD_IF_ERR_RETURN 3489 (tbhmod_enable_set(&phy_copy.access)); 3490 PHYMOD_IF_ERR_RETURN 3491 (tbhmod_polling_for_sc_done(&phy_copy.access)); 3492 /* disable pcs again */ 3493 PHYMOD_IF_ERR_RETURN 3494 (tbhmod_disable_set(&phy_copy.access)); 3495 PHYMOD_USLEEP(10000); 3496 /* disable rx lock override */ 3497 PHYMOD_IF_ERR_RETURN 3498 (tbhmod_pmd_rx_lock_override_enable(&phy_copy.access, 0)); 3499 3500 return PHYMOD_E_NONE; 3501 } 3502 3503 int tscbh_phy_pcs_enable_set(const phymod_phy_access_t* phy, uint32_t enable) 3504 { 3505 phymod_phy_access_t phy_copy; 3506 int start_lane, num_lane; 3507 3508 PHYMOD_IF_ERR_RETURN 3509 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3510 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3511 3512 if (enable == 1) { 3513 phy_copy.access.lane_mask = 1 << start_lane; 3514 PHYMOD_IF_ERR_RETURN 3515 (tbhmod_enable_set(&phy_copy.access)); 3516 } else if (enable == 0) { 3517 PHYMOD_IF_ERR_RETURN 3518 (tbhmod_disable_set(&phy_copy.access)); 3519 } else { 3520 /* this is the SW WAR for the 16nm flexport HW issue */ 3521 PHYMOD_IF_ERR_RETURN 3522 (_tscbh_flexport_sw_workaround(phy)); 3523 } 3524 3525 return PHYMOD_E_NONE; 3526 } 3527 3528 int tscbh_phy_synce_clk_ctrl_set(const phymod_phy_access_t* phy, 3529 phymod_synce_clk_ctrl_t cfg) 3530 { 3531 phymod_phy_access_t phy_copy; 3532 uint32_t current_pll_index, pll_div, sdm_val; 3533 int osr_mode; 3534 3535 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3536 3537 PHYMOD_IF_ERR_RETURN 3538 (tbhmod_synce_mode_set(&phy_copy.access, cfg.stg0_mode, cfg.stg1_mode)); 3539 3540 /* next check if SDM mode, if yes, needs to figure out the SDM value based on the current */ 3541 if ((cfg.stg0_mode == 0x2) && (cfg.stg1_mode == 0x0)) { 3542 /* vco the port is using */ 3543 /* first get the PLL index */ 3544 PHYMOD_IF_ERR_RETURN 3545 (blackhawk_lane_pll_selection_get(&phy_copy.access, ¤t_pll_index)); 3546 3547 /* next get the OSR the port is current using */ 3548 PHYMOD_IF_ERR_RETURN 3549 (blackhawk_osr_mode_get(&phy_copy.access, &osr_mode)); 3550 3551 /* next get the VCO the port is current using */ 3552 phy_copy.access.pll_idx = current_pll_index; 3553 phy_copy.access.lane_mask = 0x1; 3554 PHYMOD_IF_ERR_RETURN 3555 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 3556 3557 /* next based on the VCO value and osr mode, set the SDM value properly */ 3558 /* first check 26G VCO */ 3559 if ((pll_div == TBHMOD_PLL_MODE_DIV_170) || (pll_div == TBHMOD_PLL_MODE_DIV_85)) { 3560 sdm_val = TSCBH_SYNCE_SDM_DIVISOR_26G_VCO; 3561 } else if ((pll_div == TBHMOD_PLL_MODE_DIV_165) || (pll_div == TBHMOD_PLL_MODE_DIV_82P5)) { 3562 sdm_val = TSCBH_SYNCE_SDM_DIVISOR_25GP78125_VCO; 3563 } else if ((pll_div == TBHMOD_PLL_MODE_DIV_132) || (pll_div == TBHMOD_PLL_MODE_DIV_66)) { 3564 sdm_val = TSCBH_SYNCE_SDM_DIVISOR_20G_VCO; 3565 } else if ((pll_div == TBHMOD_PLL_MODE_DIV_160) || (pll_div == TBHMOD_PLL_MODE_DIV_80)) { 3566 sdm_val = TSCBH_SYNCE_SDM_DIVISOR_25G_VCO; 3567 } else { 3568 PHYMOD_DEBUG_ERROR(("Unsupported VCOs\n")); 3569 return PHYMOD_E_UNAVAIL; 3570 } 3571 3572 /* need to adjust the SDM value based on OSR mode */ 3573 if (osr_mode == 1) { 3574 sdm_val >>= 1; 3575 } 3576 3577 /* next configure the SDM value */ 3578 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3579 PHYMOD_IF_ERR_RETURN 3580 (tbhmod_synce_clk_ctrl_set(&phy_copy.access, sdm_val)); 3581 } 3582 3583 return PHYMOD_E_NONE; 3584 } 3585 3586 int tscbh_phy_synce_clk_ctrl_get(const phymod_phy_access_t* phy, 3587 phymod_synce_clk_ctrl_t *cfg) 3588 { 3589 phymod_phy_access_t phy_copy; 3590 3591 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3592 3593 PHYMOD_IF_ERR_RETURN 3594 (tbhmod_synce_mode_get(&phy_copy.access, &(cfg->stg0_mode), &(cfg->stg1_mode))); 3595 3596 PHYMOD_IF_ERR_RETURN 3597 (tbhmod_synce_clk_ctrl_get(&phy_copy.access, &(cfg->sdm_val))); 3598 3599 return PHYMOD_E_NONE; 3600 } 3601 3602 int tscbh_phy_rx_ppm_get(const phymod_phy_access_t* phy, int16_t* rx_ppm) 3603 { 3604 int start_lane, num_lane; 3605 phymod_phy_access_t pm_phy_copy; 3606 3607 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 3608 3609 PHYMOD_IF_ERR_RETURN 3610 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3611 3612 pm_phy_copy.access.lane_mask = 1 << start_lane; 3613 PHYMOD_IF_ERR_RETURN 3614 (blackhawk_tsc_rx_ppm(&pm_phy_copy.access, rx_ppm)); 3615 return PHYMOD_E_NONE; 3616 } 3617 3618 /* This function will handle PCS ECC interrupts. 3619 * 1. Clear interrupt status. 3620 * 2. Re-load the config table if error is in UM, AM table. 3621 * 3. Re-load the 1588 tables and SPEED_ID table for 1b error. 3622 * 4. Return is_handled = 0 if 2b-error happens and Phymod can not recover. 3623 */ 3624 int tscbh_intr_handler(const phymod_phy_access_t* phy, 3625 phymod_interrupt_type_t type, 3626 uint32_t* is_handled) 3627 { 3628 phymod_phy_access_t phy_copy; 3629 tbhmod_intr_status_t intr_status; 3630 uint32_t am_table_load_size, um_table_load_size; 3631 uint32_t speed_id_table[TSCBH_HW_SPEED_ID_TABLE_SIZE][TSCBH_SPEED_ID_ENTRY_SIZE]; 3632 int i, j, mem_offset; 3633 ts_table_entry ts_table; 3634 3635 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3636 intr_status.type = type; 3637 3638 /* Get and clear interrupt status */ 3639 PHYMOD_IF_ERR_RETURN 3640 (tbhmod_intr_status_get(&phy_copy.access, &intr_status)); 3641 3642 phy_copy.access.lane_mask = 0x1; 3643 3644 if (intr_status.is_2b_err) { 3645 *is_handled = 0; 3646 } else { 3647 *is_handled = 1; 3648 } 3649 3650 switch (type) { 3651 case phymodIntrEccAMTable: 3652 *is_handled = 1; 3653 /* Reload AM table */ 3654 am_table_load_size = TSCBH_AM_TABLE_SIZE > TSCBH_HW_AM_TABLE_SIZE ? TSCBH_HW_AM_TABLE_SIZE : TSCBH_AM_TABLE_SIZE; 3655 for (i = 0; i < am_table_load_size; i++) { 3656 PHYMOD_IF_ERR_RETURN 3657 (phymod_mem_write(&phy_copy.access, phymodMemAMTable, i, &am_table_entry[i][0])); 3658 } 3659 break; 3660 case phymodIntrEccSpeedTable: 3661 if (intr_status.is_1b_err) { 3662 for (i = 0; i < TSCBH_HW_SPEED_ID_TABLE_SIZE; i++) { 3663 PHYMOD_IF_ERR_RETURN 3664 (phymod_mem_read(&phy_copy.access, phymodMemSpeedIdTable, i, &speed_id_table[i][0])); 3665 } 3666 for (i = 0; i < TSCBH_HW_SPEED_ID_TABLE_SIZE; i++) { 3667 PHYMOD_IF_ERR_RETURN 3668 (phymod_mem_write(&phy_copy.access, phymodMemSpeedIdTable, i, &speed_id_table[i][0])); 3669 } 3670 } 3671 break; 3672 case phymodIntrEccUMTable: 3673 *is_handled = 1; 3674 /* Reload UM table */ 3675 um_table_load_size = TSCBH_UM_TABLE_SIZE > TSCBH_HW_UM_TABLE_SIZE ? TSCBH_HW_UM_TABLE_SIZE : TSCBH_UM_TABLE_SIZE; 3676 for (i = 0; i < um_table_load_size; i++) { 3677 PHYMOD_IF_ERR_RETURN 3678 (phymod_mem_write(&phy_copy.access, phymodMemUMTable, i, &um_table_entry[i][0])); 3679 } 3680 break; 3681 case phymodIntrEccRx1588400g: 3682 if (intr_status.is_1b_err) { 3683 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3684 PHYMOD_IF_ERR_RETURN 3685 (phymod_mem_read(&phy_copy.access, phymodMemRxLkup1588400G, i, &ts_table[i][0])); 3686 } 3687 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3688 PHYMOD_IF_ERR_RETURN 3689 (phymod_mem_write(&phy_copy.access, phymodMemRxLkup1588400G, i, &ts_table[i][0])); 3690 } 3691 } 3692 break; 3693 case phymodIntrEccRx1588Mpp1: 3694 if (intr_status.is_1b_err) { 3695 for (j = 0; j < TBHMOD_TS_MPP_MEM_TABLE_CNT; j++) { 3696 mem_offset = j * TBHMOD_TS_TABLE_SIZE; 3697 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3698 PHYMOD_IF_ERR_RETURN 3699 (phymod_mem_read(&phy_copy.access, phymodMemRxLkup1588Mpp1, 3700 i + mem_offset, &ts_table[i][0])); 3701 } 3702 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3703 PHYMOD_IF_ERR_RETURN 3704 (phymod_mem_write(&phy_copy.access, phymodMemRxLkup1588Mpp1, 3705 i + mem_offset, &ts_table[i][0])); 3706 } 3707 } 3708 } 3709 break; 3710 case phymodIntrEccRx1588Mpp0: 3711 if (intr_status.is_1b_err) { 3712 for (j = 0; j < TBHMOD_TS_MPP_MEM_TABLE_CNT; j++) { 3713 mem_offset = j * TBHMOD_TS_TABLE_SIZE; 3714 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3715 PHYMOD_IF_ERR_RETURN 3716 (phymod_mem_read(&phy_copy.access, phymodMemRxLkup1588Mpp0, 3717 i + mem_offset, &ts_table[i][0])); 3718 } 3719 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3720 PHYMOD_IF_ERR_RETURN 3721 (phymod_mem_write(&phy_copy.access, phymodMemRxLkup1588Mpp0, 3722 i + mem_offset, &ts_table[i][0])); 3723 } 3724 } 3725 } 3726 break; 3727 case phymodIntrEccTx1588400g: 3728 if (intr_status.is_1b_err) { 3729 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3730 PHYMOD_IF_ERR_RETURN 3731 (phymod_mem_read(&phy_copy.access, phymodMemTxLkup1588400G, i, &ts_table[i][0])); 3732 } 3733 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3734 PHYMOD_IF_ERR_RETURN 3735 (phymod_mem_write(&phy_copy.access, phymodMemTxLkup1588400G, i, &ts_table[i][0])); 3736 } 3737 } 3738 break; 3739 case phymodIntrEccTx1588Mpp1: 3740 if (intr_status.is_1b_err) { 3741 for (j = 0; j < TBHMOD_TS_MPP_MEM_TABLE_CNT; j++) { 3742 mem_offset = j * TBHMOD_TS_TABLE_SIZE; 3743 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3744 PHYMOD_IF_ERR_RETURN 3745 (phymod_mem_read(&phy_copy.access, phymodMemTxLkup1588Mpp1, 3746 i + mem_offset, &ts_table[i][0])); 3747 } 3748 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3749 PHYMOD_IF_ERR_RETURN 3750 (phymod_mem_write(&phy_copy.access, phymodMemTxLkup1588Mpp1, 3751 i + mem_offset, &ts_table[i][0])); 3752 } 3753 } 3754 } 3755 break; 3756 case phymodIntrEccTx1588Mpp0: 3757 if (intr_status.is_1b_err) { 3758 for (j = 0; j < TBHMOD_TS_MPP_MEM_TABLE_CNT; j++) { 3759 mem_offset = j * TBHMOD_TS_TABLE_SIZE; 3760 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3761 PHYMOD_IF_ERR_RETURN 3762 (phymod_mem_read(&phy_copy.access, phymodMemTxLkup1588Mpp0, 3763 i + mem_offset, &ts_table[i][0])); 3764 } 3765 for (i = 0; i < TBHMOD_TS_TABLE_SIZE; i++) { 3766 PHYMOD_IF_ERR_RETURN 3767 (phymod_mem_write(&phy_copy.access, phymodMemTxLkup1588Mpp0, 3768 i + mem_offset, &ts_table[i][0])); 3769 } 3770 } 3771 } 3772 break; 3773 default: 3774 break; 3775 } 3776 3777 return PHYMOD_E_NONE; 3778 } 3779 3780 int tscbh_timesync_tx_info_get(const phymod_phy_access_t* phy, phymod_ts_fifo_status_t* ts_tx_info) 3781 { 3782 phymod_phy_access_t phy_copy; 3783 tbhmod_ts_tx_info_t local_ts_tx_info; 3784 3785 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3786 PHYMOD_MEMSET(&local_ts_tx_info, 0, sizeof(tbhmod_ts_tx_info_t)); 3787 3788 PHYMOD_IF_ERR_RETURN(tbhmod_1588_tx_info_get(&phy_copy.access, &local_ts_tx_info)); 3789 3790 ts_tx_info->ts_in_fifo_lo = ((uint32_t)(local_ts_tx_info.ts_val_mid << 16)) | ((uint32_t)local_ts_tx_info.ts_val_lo); 3791 ts_tx_info->ts_in_fifo_hi = (uint32_t)local_ts_tx_info.ts_val_hi; 3792 ts_tx_info->ts_seq_id = (uint32_t)local_ts_tx_info.ts_seq_id; 3793 ts_tx_info->ts_sub_nanosec = (uint32_t)local_ts_tx_info.ts_sub_nanosec; 3794 3795 return PHYMOD_E_NONE; 3796 } 3797 3798 int tscbh_phy_pcs_lane_swap_adjust(const phymod_phy_access_t* phy, uint32_t active_lane_map, uint32_t original_tx_lane_map, uint32_t original_rx_lane_map) 3799 { 3800 phymod_phy_access_t phy_copy; 3801 int start_lane, num_lane, i, disable_lane[2]= {0,0}, disable_lane_num = 0; 3802 int tx_physical_lane, tx_logical_lane, rx_physical_lane, rx_logical_lane; 3803 uint32_t new_tx_lane_map, new_rx_lane_map, swap_mask, tmp_tx_lane_map, tmp_rx_lane_map; 3804 3805 PHYMOD_IF_ERR_RETURN 3806 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3807 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3808 3809 /* next based on active_lane_map, figure out the disable lane num and index*/ 3810 for (i = 0; i < num_lane; i++) 3811 { 3812 if(active_lane_map & (1 << i)) 3813 { 3814 continue; 3815 } else { 3816 disable_lane[disable_lane_num] = i + start_lane; 3817 disable_lane_num++; 3818 } 3819 } 3820 3821 /* next check if disable_lane_num 0 */ 3822 if (disable_lane_num == 0) { 3823 new_tx_lane_map = original_tx_lane_map; 3824 new_rx_lane_map = original_rx_lane_map; 3825 3826 /* next check if 4 lane or 8 lane port */ 3827 if (num_lane == 8) { 3828 PHYMOD_IF_ERR_RETURN 3829 (tbhmod_pcs_tx_lane_swap(&phy_copy.access, new_tx_lane_map)); 3830 PHYMOD_IF_ERR_RETURN 3831 (tbhmod_pcs_rx_lane_swap(&phy_copy.access, new_rx_lane_map)); 3832 } else { /* 4 lane port */ 3833 for (i = 0; i < num_lane; i++) { 3834 tx_logical_lane = i + start_lane; 3835 rx_logical_lane = i + start_lane; 3836 tx_physical_lane = (original_tx_lane_map & (0xf << (tx_logical_lane * 4)) ) >> (tx_logical_lane * 4); 3837 rx_physical_lane = (original_rx_lane_map & (0xf << (rx_logical_lane * 4)) ) >> (rx_logical_lane * 4); 3838 tx_physical_lane &= 0xf; 3839 rx_physical_lane &= 0xf; 3840 PHYMOD_IF_ERR_RETURN 3841 (tbhmod_pcs_single_tx_lane_swap_set(&phy_copy.access, tx_physical_lane, tx_logical_lane)); 3842 PHYMOD_IF_ERR_RETURN 3843 (tbhmod_pcs_single_rx_lane_swap_set(&phy_copy.access, rx_physical_lane, rx_logical_lane)); 3844 } 3845 } 3846 } else { 3847 if (num_lane == 4) { 3848 /* first check if disable lane is the last, if yes, then need to adjust */ 3849 if ((disable_lane[0] == 3) || (disable_lane[0] == 7)) { 3850 return PHYMOD_E_NONE; 3851 } else if (disable_lane[0] < 4) { 3852 /* mpp0 */ 3853 tx_logical_lane = disable_lane[0]; 3854 rx_logical_lane = disable_lane[0]; 3855 tx_physical_lane = (original_tx_lane_map & (0xf << (3 * 4)) & 0xffff) >> (3 * 4); 3856 rx_physical_lane = (original_rx_lane_map & (0xf << (3 * 4)) & 0xffff) >> (3 * 4); 3857 tx_physical_lane &= 0xf; 3858 rx_physical_lane &= 0xf; 3859 PHYMOD_IF_ERR_RETURN 3860 (tbhmod_pcs_single_tx_lane_swap_set(&phy_copy.access, tx_physical_lane, tx_logical_lane)); 3861 PHYMOD_IF_ERR_RETURN 3862 (tbhmod_pcs_single_rx_lane_swap_set(&phy_copy.access, rx_physical_lane, rx_logical_lane)); 3863 /* mpp0 */ 3864 tx_logical_lane = 3; 3865 rx_logical_lane = 3; 3866 tx_physical_lane = (original_tx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffff) >> (disable_lane[0] * 4); 3867 rx_physical_lane = (original_rx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffff) >> (disable_lane[0] * 4); 3868 tx_physical_lane &= 0xf; 3869 rx_physical_lane &= 0xf; 3870 PHYMOD_IF_ERR_RETURN 3871 (tbhmod_pcs_single_tx_lane_swap_set(&phy_copy.access, tx_physical_lane, tx_logical_lane)); 3872 PHYMOD_IF_ERR_RETURN 3873 (tbhmod_pcs_single_rx_lane_swap_set(&phy_copy.access, rx_physical_lane, rx_logical_lane)); 3874 } else { 3875 /* mpp1 */ 3876 tx_logical_lane = disable_lane[0]; 3877 rx_logical_lane = disable_lane[0]; 3878 tx_physical_lane = (original_tx_lane_map & (0xf << (7 * 4)) & 0xffff0000) >> (7 * 4); 3879 rx_physical_lane = (original_rx_lane_map & (0xf << (7 * 4)) & 0xffff0000) >> (7 * 4); 3880 tx_physical_lane &= 0xf; 3881 rx_physical_lane &= 0xf; 3882 PHYMOD_IF_ERR_RETURN 3883 (tbhmod_pcs_single_tx_lane_swap_set(&phy_copy.access, tx_physical_lane, tx_logical_lane)); 3884 PHYMOD_IF_ERR_RETURN 3885 (tbhmod_pcs_single_rx_lane_swap_set(&phy_copy.access, rx_physical_lane, rx_logical_lane)); 3886 /* mpp1 */ 3887 tx_logical_lane = 7; 3888 rx_logical_lane = 7; 3889 tx_physical_lane = (original_tx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffff0000) >> (disable_lane[0] * 4); 3890 rx_physical_lane = (original_rx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffff0000) >> (disable_lane[0] * 4); 3891 tx_physical_lane &= 0xf; 3892 rx_physical_lane &= 0xf; 3893 PHYMOD_IF_ERR_RETURN 3894 (tbhmod_pcs_single_tx_lane_swap_set(&phy_copy.access, tx_physical_lane, tx_logical_lane)); 3895 PHYMOD_IF_ERR_RETURN 3896 (tbhmod_pcs_single_rx_lane_swap_set(&phy_copy.access, rx_physical_lane, rx_logical_lane)); 3897 } 3898 } else if (num_lane == 8) { 3899 /* first check if disable lane is the last, if yes, then no need to adjust */ 3900 if (disable_lane_num == 1) { 3901 /* no need to do pcs adjust */ 3902 if (disable_lane[0] == 7) { 3903 return PHYMOD_E_NONE; 3904 } else { 3905 new_tx_lane_map = (original_tx_lane_map & (0xf << (7 * 4)) & 0xffffffff) >> (4 * (7 - disable_lane[0])); 3906 new_tx_lane_map |= (original_tx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffffffff) << (4 * (7 - disable_lane[0])); 3907 new_rx_lane_map = (original_rx_lane_map & (0xf << (7 * 4)) & 0xffffffff) >> (4 * (7 - disable_lane[0])); 3908 new_rx_lane_map |= (original_rx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffffffff) << (4 * (7 - disable_lane[0])); 3909 swap_mask = ~(0xf << (4 * 7) | 0xf << (4 * disable_lane[0])); 3910 new_tx_lane_map |= (original_tx_lane_map & swap_mask); 3911 new_rx_lane_map |= (original_rx_lane_map & swap_mask); 3912 } 3913 } else { /*2 lane disabled */ 3914 if ((disable_lane[0] == 6) && (disable_lane[1] == 7)) { 3915 /* no need to do pcs adjust */ 3916 return PHYMOD_E_NONE; 3917 } else if (disable_lane[1] != 6) { 3918 new_tx_lane_map = (original_tx_lane_map & (0xf << (6 * 4)) & 0xffffffff) >> (4 * (6 - disable_lane[0])); 3919 new_tx_lane_map |= (original_tx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffffffff) << (4 * (6 - disable_lane[0])); 3920 tmp_tx_lane_map = (original_tx_lane_map & (0xf << (7 * 4)) & 0xffffffff) >> (4 * (7 - disable_lane[1])); 3921 tmp_tx_lane_map |= (original_tx_lane_map & (0xf << (disable_lane[1] * 4)) & 0xffffffff) << (4 * (7 - disable_lane[1])); 3922 new_tx_lane_map |= tmp_tx_lane_map; 3923 new_rx_lane_map = (original_rx_lane_map & (0xf << (6 * 4)) & 0xffffffff) >> (4 * (6 - disable_lane[0])); 3924 new_rx_lane_map |= (original_rx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffffffff) << (4 * (6 - disable_lane[0])); 3925 tmp_rx_lane_map = (original_rx_lane_map & (0xf << (7 * 4)) & 0xffffffff) >> (4 * (7 - disable_lane[1])); 3926 tmp_rx_lane_map |= (original_rx_lane_map & (0xf << (disable_lane[1] * 4)) & 0xffffffff) << (4 * (7 - disable_lane[1])); 3927 new_rx_lane_map |= tmp_rx_lane_map; 3928 swap_mask = ~(0xff << (4 * 6) | 0xf << (4 * disable_lane[0]) | 0xf << (4 * disable_lane[1])); 3929 new_tx_lane_map |= (original_tx_lane_map & swap_mask); 3930 new_rx_lane_map |= (original_rx_lane_map & swap_mask); 3931 } else { 3932 tmp_tx_lane_map = (original_tx_lane_map & (0xf << (7 * 4)) & 0xffffffff) >> (4 * (7 - disable_lane[0])); 3933 tmp_tx_lane_map |= (original_tx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffffffff) << (4 * (7 - disable_lane[0])); 3934 new_tx_lane_map = tmp_tx_lane_map; 3935 tmp_rx_lane_map = (original_rx_lane_map & (0xf << (7 * 4)) & 0xffffffff) >> (4 * (7 - disable_lane[0])); 3936 tmp_rx_lane_map |= (original_rx_lane_map & (0xf << (disable_lane[0] * 4)) & 0xffffffff) << (4 * (7 - disable_lane[0])); 3937 new_rx_lane_map = tmp_rx_lane_map; 3938 swap_mask = ~(0xf << (4 * 7) | 0xf << (4 * disable_lane[0])); 3939 new_tx_lane_map |= (original_tx_lane_map & swap_mask); 3940 new_rx_lane_map |= (original_rx_lane_map & swap_mask); 3941 } 3942 } 3943 3944 PHYMOD_IF_ERR_RETURN 3945 (tbhmod_pcs_tx_lane_swap(&phy_copy.access, new_tx_lane_map)); 3946 PHYMOD_IF_ERR_RETURN 3947 (tbhmod_pcs_rx_lane_swap(&phy_copy.access, new_rx_lane_map)); 3948 } 3949 } 3950 return PHYMOD_E_NONE; 3951 } 3952 3953 int tscbh_phy_load_speed_id_entry(const phymod_phy_access_t* phy, uint32_t speed, uint32_t num_lane, phymod_fec_type_t fec_type) 3954 { 3955 phymod_phy_access_t phy_copy; 3956 int start_lane, local_num_lane, mapped_speed_id; 3957 tbhmod_spd_intfc_type_t spd_intf; 3958 uint32_t tvco_pll_div; 3959 3960 PHYMOD_IF_ERR_RETURN 3961 (phymod_util_lane_config_get(&phy->access, &start_lane, &local_num_lane)); 3962 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3963 3964 /* first check the speed */ 3965 switch (speed) { 3966 case 150000: 3967 spd_intf = TBHMOD_SPD_150G_FEC_544_2XN_N3; 3968 break; 3969 case 350000: 3970 spd_intf = TBHMOD_SPD_350G_FEC_544_2XN_N7; 3971 break; 3972 case 300000: 3973 spd_intf = TBHMOD_SPD_300G_FEC_544_2XN_N6; 3974 break; 3975 case 400000: 3976 spd_intf = TBHMOD_SPD_400G_BRCM_FEC_544_2XN_X8; 3977 break; 3978 case 200000: 3979 if (fec_type == phymod_fec_RS544_2XN) { 3980 spd_intf = TBHMOD_SPD_200G_IEEE_FEC_544_2XN_KR4_CR4; 3981 } else if (fec_type == phymod_fec_RS544) { 3982 spd_intf = TBHMOD_SPD_200G_BRCM_FEC_544_1XN_KR4_CR4; 3983 } else if (fec_type == phymod_fec_RS272) { 3984 spd_intf = TBHMOD_SPD_200G_BRCM_FEC_272_1XN_KR4_CR4; 3985 } else { 3986 PHYMOD_DEBUG_ERROR(("Unsupported 200G fec type\n")); 3987 return PHYMOD_E_UNAVAIL; 3988 } 3989 break; 3990 default: 3991 PHYMOD_DEBUG_ERROR(("Unsupported speed for speed id load function \n")); 3992 return PHYMOD_E_UNAVAIL; 3993 } 3994 3995 PHYMOD_IF_ERR_RETURN 3996 (tbhmod_get_mapped_speed(spd_intf, &mapped_speed_id)); 3997 3998 /* Get TVCO because it's not allowed to change during speed set */ 3999 phy_copy.access.pll_idx = phy->access.tvco_pll_index; 4000 4001 PHYMOD_IF_ERR_RETURN 4002 (blackhawk_tsc_INTERNAL_read_pll_div(&phy_copy.access, &tvco_pll_div)); 4003 4004 /* based on the current TVCO PLL div, decide which copy of speed id entry to load */ 4005 /* first set the lane mask to be 0x1 */ 4006 phy_copy.access.lane_mask = 1 << 0; 4007 if ((tvco_pll_div == TBHMOD_PLL_MODE_DIV_170) || (tvco_pll_div == TBHMOD_PLL_MODE_DIV_85)) { 4008 /* then load 26G TVCO speed id entry */ 4009 PHYMOD_IF_ERR_RETURN 4010 (phymod_mem_write(&phy_copy.access, phymodMemSpeedIdTable, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, &spd_id_entry_26[mapped_speed_id][0])); 4011 } else if ((tvco_pll_div == TBHMOD_PLL_MODE_DIV_165) || (tvco_pll_div == TBHMOD_PLL_MODE_DIV_82P5)) { 4012 /* then load 25G TVCO speed id entry */ 4013 PHYMOD_IF_ERR_RETURN 4014 (phymod_mem_write(&phy_copy.access, phymodMemSpeedIdTable, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, &spd_id_entry_25[mapped_speed_id][0])); 4015 } else { 4016 /* then load 20G TVCO speed id entry */ 4017 PHYMOD_IF_ERR_RETURN 4018 (phymod_mem_write(&phy_copy.access, phymodMemSpeedIdTable, TSCBH_FORCED_SPEED_ID_OFFSET + start_lane, &spd_id_entry_20[mapped_speed_id][0])); 4019 } 4020 4021 return PHYMOD_E_NONE; 4022 } 4023 4024 int tscbh_phy_pmd_override_enable_set(const phymod_phy_access_t* phy, 4025 phymod_override_type_t pmd_override_type, 4026 uint32_t override_enable, 4027 uint32_t override_val) 4028 { 4029 phymod_phy_access_t phy_copy; 4030 int start_lane, num_lane; 4031 4032 PHYMOD_IF_ERR_RETURN 4033 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4034 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4035 4036 PHYMOD_IF_ERR_RETURN 4037 (tbhmod_pmd_override_enable_set(&phy_copy.access, pmd_override_type, override_enable, override_val)); 4038 4039 return PHYMOD_E_NONE; 4040 } 4041 4042 int tscbh_phy_pll_powerdown_get(const phymod_phy_access_t* phy, uint32_t pll_index, uint32_t* powerdown) 4043 { 4044 phymod_phy_access_t phy_copy; 4045 4046 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4047 4048 phy_copy.access.pll_idx = pll_index; 4049 phy_copy.access.lane_mask = 1 << 0; 4050 PHYMOD_IF_ERR_RETURN 4051 (blackhawk_tsc_pll_pwrdn_get(&phy_copy.access, powerdown)); 4052 4053 return PHYMOD_E_NONE; 4054 } 4055 4056 int tscbh_phy_fec_bypass_indication_set(const phymod_phy_access_t* phy, 4057 uint32_t enable) 4058 { 4059 int start_lane, num_lane; 4060 phymod_phy_access_t phy_copy; 4061 uint32_t lane_reset, pcs_lane_enable; 4062 4063 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4064 4065 PHYMOD_IF_ERR_RETURN 4066 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4067 4068 /*first check if lane is in reset */ 4069 PHYMOD_IF_ERR_RETURN 4070 (blackhawk_lane_soft_reset_get(&phy_copy.access, &lane_reset)); 4071 4072 /*next check if PCS lane is in reset */ 4073 PHYMOD_IF_ERR_RETURN 4074 (tbhmod_enable_get(&phy_copy.access, &pcs_lane_enable)); 4075 4076 /* disable pcs lane if pcs lane not in rset */ 4077 if (pcs_lane_enable) { 4078 phy_copy.access.lane_mask = 1 << start_lane; 4079 PHYMOD_IF_ERR_RETURN 4080 (tbhmod_disable_set(&phy_copy.access)); 4081 } 4082 4083 /* if lane is not in reset, then reset the lane first */ 4084 if (!lane_reset) { 4085 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4086 PHYMOD_IF_ERR_RETURN 4087 (blackhawk_lane_soft_reset(&phy_copy.access, 1)); 4088 } 4089 4090 phy_copy.access.lane_mask = 1 << start_lane; 4091 PHYMOD_IF_ERR_RETURN( 4092 tbhmod_fec_bypass_indication_set(&phy_copy.access, enable)); 4093 4094 /* release the lane soft reset bit */ 4095 if (!lane_reset) { 4096 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4097 PHYMOD_IF_ERR_RETURN 4098 (blackhawk_lane_soft_reset(&phy_copy.access, 0)); 4099 } 4100 4101 /* re-enable pcs lane if pcs lane not in rset */ 4102 if (pcs_lane_enable) { 4103 phy_copy.access.lane_mask = 1 << start_lane; 4104 PHYMOD_IF_ERR_RETURN 4105 (tbhmod_enable_set(&phy_copy.access)); 4106 } 4107 4108 return PHYMOD_E_NONE; 4109 } 4110 4111 int tscbh_phy_fec_bypass_indication_get(const phymod_phy_access_t* phy, 4112 uint32_t *enable) 4113 { 4114 int start_lane, num_lane; 4115 phymod_phy_access_t phy_copy; 4116 4117 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4118 4119 PHYMOD_IF_ERR_RETURN 4120 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4121 4122 phy_copy.access.lane_mask = 1 << start_lane; 4123 4124 PHYMOD_IF_ERR_RETURN( 4125 tbhmod_fec_bypass_indication_get(&phy_copy.access, enable)); 4126 4127 return PHYMOD_E_NONE; 4128 } 4129