qtce.c (84791B)
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_debug.h> 13 #include <phymod/phymod_util.h> 14 #include <phymod/chip/bcmi_qtce_xgxs_defs.h> 15 #include <phymod/chip/eagle_common.h> 16 17 #include "../../qtce/tier1/qePCSRegEnums.h" 18 #include "../../qtce/tier1/qmod_enum_defines.h" 19 #include "../../qtce/tier1/qmod_device.h" 20 #include "../../qtce/tier1/qmod.h" 21 #include "../../qtce/tier1/qmod_defines.h" 22 #include "../../qtce/tier1/qmod_sc_lkup_table.h" 23 #include "../../qtce/tier1/phy_tsc_iblk.h" 24 #include "../../eagle/tier1/eagle_cfg_seq.h" 25 #include "../../eagle/tier1/eagle_tsc_common.h" 26 #include "../../eagle/tier1/eagle_tsc_interface.h" 27 #include "../../eagle/tier1/eagle_tsc_dependencies.h" 28 29 #ifdef PHYMOD_QTCE_SUPPORT 30 31 #define QTCE_ID0 0x600d 32 #define QTCE_ID1 0x8770 33 #define QTCE_REV_MASK 0x0 34 35 #define QTCE4_MODEL 0x15 36 #define EAGLE_MODEL 0x1a 37 38 #define QTCE_NOF_DFES (5) 39 #define QTCE_NOF_LANES_IN_CORE (4) 40 #define QTCE_LANE_SWAP_LANE_MASK (0x3) 41 #define QTCE_PHY_ALL_LANES (0xf) 42 #define QTCE_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \ 43 do{\ 44 PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\ 45 (_phy_access)->type = (_core_access)->type; \ 46 (_phy_access)->access.lane_mask = QTCE_PHY_ALL_LANES; \ 47 }while(0) 48 49 #define QTCE_PMD_CRC_UCODE 1 50 /* uController's firmware */ 51 extern unsigned char qtce_ucode[]; 52 extern unsigned short qtce_ucode_ver; 53 extern unsigned short qtce_ucode_crc; 54 extern unsigned short qtce_ucode_len; 55 56 typedef int (*sequncer_control_f)(const phymod_access_t* core, uint32_t enable); 57 typedef int (*rx_DFE_tap_control_set_f)(const phymod_access_t* phy, uint32_t val); 58 59 STATIC 60 int _qtce_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 61 { 62 struct eagle_tsc_uc_lane_config_st serdes_firmware_config; 63 phymod_phy_access_t phy_copy; 64 int start_lane, num_lane, i; 65 /* uint32_t rst_status; */ 66 uint32_t is_warm_boot; 67 68 PHYMOD_IF_ERR_RETURN 69 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 70 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 71 72 for (i = 0; i < num_lane; i++) { 73 phy_copy.access.lane_mask = 1 << (start_lane + i); 74 serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS; 75 serdes_firmware_config.field.an_enabled = fw_config.AnEnabled; 76 serdes_firmware_config.field.dfe_on = fw_config.DfeOn; 77 serdes_firmware_config.field.force_brdfe_on = fw_config.ForceBrDfe; 78 /* serdes_firmware_config.field.cl72_emulation_en = fw_config.Cl72Enable; */ 79 serdes_firmware_config.field.scrambling_dis = fw_config.ScramblingDisable; 80 serdes_firmware_config.field.unreliable_los = fw_config.UnreliableLos; 81 serdes_firmware_config.field.media_type = fw_config.MediaType; 82 83 PHYMOD_IF_ERR_RETURN(PHYMOD_IS_WRITE_DISABLED(&phy_copy.access, &is_warm_boot)); 84 85 86 if(!is_warm_boot) { 87 /* PHYMOD_IF_ERR_RETURN(eagle_lane_soft_reset_read(&phy_copy.access, &rst_status)); */ 88 /* if(rst_status) */ PHYMOD_IF_ERR_RETURN (eagle_lane_soft_reset_release(&phy_copy.access, 0)); 89 PHYMOD_USLEEP(100); 90 PHYMOD_IF_ERR_RETURN(eagle_tsc_set_uc_lane_cfg(&phy_copy.access, serdes_firmware_config)); 91 /* if(rst_status) */ PHYMOD_IF_ERR_RETURN (eagle_lane_soft_reset_release(&phy_copy.access, 1)); 92 } 93 } 94 return PHYMOD_E_NONE; 95 } 96 97 98 int qtce_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified) 99 { 100 int ioerr = 0; 101 const phymod_access_t *pm_acc = &core->access; 102 PHYID2r_t id2; 103 PHYID3r_t id3; 104 MAIN_SERDESIDr_t serdesid; 105 /* DIG_REVID0r_t revid; */ 106 uint32_t model; 107 int rv ; 108 *is_identified = 0; 109 110 if(core_id == 0){ 111 ioerr += READ_PHYID2r(pm_acc, &id2); 112 ioerr += READ_PHYID3r(pm_acc, &id3); 113 } 114 else{ 115 PHYID2r_SET(id2, ((core_id >> 16) & 0xffff)); 116 PHYID3r_SET(id3, core_id & 0xffff); 117 } 118 119 if (PHYID2r_GET(id2) == QTCE_ID0 && 120 (PHYID3r_GET(id3) &= ~QTCE_REV_MASK) == QTCE_ID1) { 121 /* PHY IDs match - now check PCS model */ 122 ioerr += READ_MAIN_SERDESIDr(pm_acc, &serdesid); 123 model = MAIN_SERDESIDr_MODEL_NUMBERf_GET(serdesid); 124 if (model == QTCE4_MODEL) { 125 /* PCS model matches - now check PMD model */ 126 /* for now bypass the pmd register rev check */ 127 /* ioerr += READ_DIG_REVID0r(pm_acc, &revid); 128 if (DIG_REVID0r_REVID_MODELf_GET(revid) == EAGLE_MODEL) */ { 129 *is_identified = 1; 130 } 131 } 132 } 133 rv = ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE; 134 return rv ; 135 } 136 137 int qtce_core_info_get(const phymod_core_access_t* phy, phymod_core_info_t* info) 138 { 139 uint32_t serdes_id; 140 char core_name[15]; 141 PHYID2r_t id2; 142 PHYID3r_t id3; 143 const phymod_access_t *pm_acc = &phy->access; 144 145 PHYMOD_IF_ERR_RETURN 146 (qmod_revid_read(&phy->access, &serdes_id)); 147 PHYMOD_IF_ERR_RETURN 148 (phymod_core_name_get(phy, serdes_id, core_name, info)); 149 info->serdes_id = serdes_id; 150 151 if ((serdes_id & 0x3f) == QTCE4_MODEL) { 152 info->core_version = phymodCoreVersionQtceA0; 153 PHYMOD_STRNCPY(core_name, "QtceA0", PHYMOD_STRLEN("QtceA0")+1); 154 } else { 155 info->core_version = phymodCoreVersionTsce12A0; 156 PHYMOD_STRNCPY(core_name, "Tsce4", PHYMOD_STRLEN("Tsce4")+1); 157 } 158 PHYMOD_IF_ERR_RETURN 159 (phymod_core_name_get(phy, serdes_id, core_name, info)); 160 161 PHYMOD_IF_ERR_RETURN(READ_PHYID2r(pm_acc, &id2)); 162 PHYMOD_IF_ERR_RETURN(READ_PHYID3r(pm_acc, &id3)); 163 164 info->phy_id0 = (uint16_t) id2.v[0]; 165 info->phy_id1 = (uint16_t) id3.v[0]; 166 return PHYMOD_E_NONE; 167 } 168 169 /* 170 * Write 1 to pmd_x4_override.rx_lock_ovrd & pmd_x4_override.signal_detect_ovrd 171 * fields of all 4 ports at core init time. 172 * This function is used to solve the following issues: 173 * 1.rx_lock and signal_ok indications from PMD are not swapped correctly.(SDK-132662) 174 * 2.GH2 requires the Rx clock before we put the unimac port into MAC loopback.(SDK-115895) 175 */ 176 STATIC 177 int _qtce_core_lane_override_set(const phymod_core_access_t* core) 178 { 179 uint32_t lane; 180 phymod_phy_access_t phy_copy; 181 182 QTCE_CORE_TO_PHY_ACCESS(&phy_copy, core); 183 for(lane = 0 ; lane < QTCE_NOF_LANES_IN_CORE ; lane++){ 184 phy_copy.access.lane_mask = 1 << lane; 185 PHYMOD_IF_ERR_RETURN 186 (qmod_pmd_lane_override(&phy_copy.access, QMOD_PMD_LANE_SIGNAL_DETECT_OVRD)); 187 PHYMOD_IF_ERR_RETURN 188 (qmod_pmd_lane_override(&phy_copy.access, QMOD_PMD_LANE_RX_LOCK_OVRD)); 189 } 190 191 return PHYMOD_E_NONE; 192 } 193 194 /* 195 * set lane swapping for core 196 * The tx swap is composed of PCS swap and after that the PMD swap. 197 * The rx swap is composed just by PCS swap 198 * 199 * lane_map_tx and lane_map_rx[lane=logic_lane] are logic-lane base. 200 * pcs_swap and register is logic_lane base. 201 * but pmd_tx_map and addr_index_swap (and registers) are physical lane base 202 */ 203 204 int qtce_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map) 205 { 206 uint32_t pcs_swap = 0 , pmd_swap = 0, lane; 207 uint32_t addr_index_swap = 0, pmd_tx_map =0; 208 209 210 if(lane_map->num_of_lanes != QTCE_NOF_LANES_IN_CORE){ 211 return PHYMOD_E_CONFIG; 212 } 213 for( lane = 0 ; lane < QTCE_NOF_LANES_IN_CORE ; lane++){ 214 if(lane_map->lane_map_rx[lane] >= QTCE_NOF_LANES_IN_CORE){ 215 return PHYMOD_E_CONFIG; 216 } 217 /* encode each lane as four bits */ 218 /* pcs_map[lane] = rx_map[lane] */ 219 pcs_swap += lane_map->lane_map_rx[lane]<<(lane*4); 220 } 221 222 for( lane = 0 ; lane < QTCE_NOF_LANES_IN_CORE ; lane++){ 223 if(lane_map->lane_map_tx[lane] >= QTCE_NOF_LANES_IN_CORE){ 224 return PHYMOD_E_CONFIG; 225 } 226 /* encode each lane as four bits. pmd_swap is logic base */ 227 /* considering the pcs lane swap: pmd_map[pcs_map[lane]] = tx_map[lane] */ 228 pmd_swap += lane_map->lane_map_tx[lane]<<(lane_map->lane_map_rx[lane]*4); 229 } 230 231 for( lane = 0 ; lane < QTCE_NOF_LANES_IN_CORE ; lane++){ 232 addr_index_swap |= (lane << 4*((pcs_swap >> lane*4) & 0xf)) ; 233 pmd_tx_map |= (lane << 4*((pmd_swap >> lane*4) & 0xf)) ; 234 } 235 PHYMOD_IF_ERR_RETURN(qmod_pcs_lane_swap(&core->access, pcs_swap)); 236 237 PHYMOD_IF_ERR_RETURN 238 (qmod_pmd_addr_lane_swap(&core->access, addr_index_swap)); 239 PHYMOD_IF_ERR_RETURN 240 (qmod_pmd_lane_swap_tx(&core->access, pmd_tx_map)); 241 242 return PHYMOD_E_NONE; 243 } 244 245 246 int qtce_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map) 247 { 248 uint32_t pmd_swap = 0 , pcs_swap = 0, lane; 249 PHYMOD_IF_ERR_RETURN(qmod_pcs_lane_swap_get(&core->access, &pcs_swap)); 250 PHYMOD_IF_ERR_RETURN(qmod_pmd_lane_swap_tx_get(&core->access, &pmd_swap)); 251 for( lane = 0 ; lane < QTCE_NOF_LANES_IN_CORE ; lane++){ 252 /* deccode each lane from four bits */ 253 lane_map->lane_map_rx[lane] = (pcs_swap>>(lane*4)) & QTCE_LANE_SWAP_LANE_MASK; 254 /* considering the pcs lane swap: tx_map[lane] = pmd_map[pcs_map[lane]] */ 255 lane_map->lane_map_tx[lane] = (pmd_swap>>(lane_map->lane_map_rx[lane]*4)) & QTCE_LANE_SWAP_LANE_MASK; 256 } 257 lane_map->num_of_lanes = QTCE_NOF_LANES_IN_CORE; 258 return PHYMOD_E_NONE; 259 } 260 261 262 int qtce_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 263 { 264 265 /* Place your code here */ 266 267 268 return PHYMOD_E_NONE; 269 } 270 271 272 int qtce_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction) 273 { 274 return PHYMOD_E_UNAVAIL; 275 } 276 277 int qtce_core_firmware_info_get(const phymod_core_access_t* core, phymod_core_firmware_info_t* fw_info) 278 { 279 280 /* 281 * It's O.K to use this code as is since the firmware CRC is already checked at 282 * at the time we load it. 283 */ 284 fw_info->fw_crc = qtce_ucode_crc; 285 fw_info->fw_version = qtce_ucode_ver; 286 return PHYMOD_E_NONE; 287 } 288 289 /* load qtce fw. the fw_loader parameter is valid just for external fw load */ 290 STATIC 291 int _qtce_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader) 292 { 293 #ifndef QTCE_PMD_CRC_UCODE 294 phymod_core_firmware_info_t actual_fw; 295 #endif 296 297 298 switch(load_method){ 299 case phymodFirmwareLoadMethodInternal: 300 PHYMOD_IF_ERR_RETURN(eagle_tsc_ucode_mdio_load(&core->access, qtce_ucode, qtce_ucode_len)); 301 break; 302 case phymodFirmwareLoadMethodExternal: 303 PHYMOD_NULL_CHECK(fw_loader); 304 305 eagle_pram_flop_set(&core->access, 0x0); 306 307 PHYMOD_IF_ERR_RETURN(eagle_tsc_ucode_init(&core->access)); 308 309 PHYMOD_IF_ERR_RETURN 310 (qmod_pram_abl_enable_set(&core->access,1)); 311 PHYMOD_IF_ERR_RETURN 312 (eagle_pram_firmware_enable(&core->access, 1)); 313 314 PHYMOD_IF_ERR_RETURN(fw_loader(core, qtce_ucode_len, qtce_ucode)); 315 316 PHYMOD_IF_ERR_RETURN 317 (eagle_pram_firmware_enable(&core->access, 0)); 318 PHYMOD_IF_ERR_RETURN 319 (qmod_pram_abl_enable_set(&core->access,0)); 320 break; 321 case phymodFirmwareLoadMethodNone: 322 break; 323 default: 324 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method)); 325 } 326 return PHYMOD_E_NONE; 327 } 328 329 int qtce_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_config) 330 { 331 struct eagle_tsc_uc_core_config_st serdes_firmware_core_config; 332 PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(serdes_firmware_core_config)); 333 serdes_firmware_core_config.field.core_cfg_from_pcs = fw_config.CoreConfigFromPCS; 334 serdes_firmware_core_config.field.vco_rate = fw_config.VcoRate; 335 PHYMOD_IF_ERR_RETURN(eagle_tsc_set_uc_core_config(&phy->access, serdes_firmware_core_config)); 336 return PHYMOD_E_NONE; 337 } 338 339 340 int qtce_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_config) 341 { 342 struct eagle_tsc_uc_core_config_st serdes_firmware_core_config; 343 PHYMOD_IF_ERR_RETURN(eagle_tsc_get_uc_core_config(&phy->access, &serdes_firmware_core_config)); 344 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 345 fw_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs; 346 fw_config->VcoRate = serdes_firmware_core_config.field.vco_rate; 347 return PHYMOD_E_NONE; 348 } 349 350 351 int qtce_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 352 { 353 phymod_phy_access_t phy_copy; 354 int start_lane, num_lane, i, lane_id, sub_port; 355 356 PHYMOD_IF_ERR_RETURN 357 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 358 PHYMOD_IF_ERR_RETURN 359 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 360 start_lane = lane_id; 361 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 362 363 /*Hold the per lne soft reset bit*/ 364 for (i = 0; i < num_lane; i++) { 365 phy_copy.access.lane_mask = 1 << (start_lane + i); 366 PHYMOD_IF_ERR_RETURN 367 (eagle_lane_soft_reset_release(&phy_copy.access, 0)); 368 } 369 370 PHYMOD_USLEEP(500); 371 for (i = 0; i < num_lane; i++) { 372 phy_copy.access.lane_mask = 1 << (start_lane + i); 373 PHYMOD_IF_ERR_RETURN 374 (_qtce_phy_firmware_lane_config_set(&phy_copy, fw_config)); 375 } 376 /*Hold the per lne soft reset bit*/ 377 for (i = 0; i < num_lane; i++) { 378 phy_copy.access.lane_mask = 1 << (start_lane + i); 379 PHYMOD_IF_ERR_RETURN 380 (eagle_lane_soft_reset_release(&phy_copy.access, 1)); 381 } 382 383 PHYMOD_IF_ERR_RETURN 384 (qmod_trigger_speed_change(&phy->access)); 385 386 return PHYMOD_E_NONE; 387 } 388 389 390 int qtce_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config) 391 { 392 struct eagle_tsc_uc_lane_config_st serdes_firmware_config; 393 phymod_phy_access_t phy_copy; 394 int lane_id, sub_port; 395 396 PHYMOD_IF_ERR_RETURN 397 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 398 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 399 phy_copy.access.lane_mask = 1 << lane_id; 400 401 PHYMOD_IF_ERR_RETURN(eagle_tsc_get_uc_lane_cfg(&phy_copy.access, &serdes_firmware_config)); 402 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 403 fw_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs; 404 fw_config->AnEnabled = serdes_firmware_config.field.an_enabled; 405 fw_config->DfeOn = serdes_firmware_config.field.dfe_on; 406 fw_config->ForceBrDfe = serdes_firmware_config.field.force_brdfe_on; 407 fw_config->Cl72AutoPolEn = serdes_firmware_config.field.cl72_auto_polarity_en; 408 fw_config->Cl72RestTO = serdes_firmware_config.field.cl72_restart_timeout_en; 409 fw_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis; 410 fw_config->UnreliableLos = serdes_firmware_config.field.unreliable_los; 411 fw_config->MediaType = serdes_firmware_config.field.media_type; 412 413 return PHYMOD_E_NONE; 414 } 415 416 /* reset pll sequencer 417 * flags - unused parameter 418 */ 419 int qtce_core_pll_sequencer_restart(const phymod_core_access_t* core, uint32_t flags, phymod_sequencer_operation_t operation) 420 { 421 switch (operation) { 422 case phymodSeqOpStop: 423 PHYMOD_IF_ERR_RETURN 424 (qmod_pll_sequencer_control(&core->access, 0)); 425 break; 426 case phymodSeqOpStart: 427 PHYMOD_IF_ERR_RETURN 428 (qmod_pll_sequencer_control(&core->access, 1)); 429 430 /* PHYMOD_IF_ERR_RETURN 431 (qtce_pll_lock_wait(&core->access, 250000)); */ 432 break; 433 case phymodSeqOpRestart: 434 PHYMOD_IF_ERR_RETURN 435 (qmod_pll_sequencer_control(&core->access, 0)); 436 437 PHYMOD_IF_ERR_RETURN 438 (qmod_pll_sequencer_control(&core->access, 1)); 439 440 /* PHYMOD_IF_ERR_RETURN 441 (qtce_pll_lock_wait(&core->access, 250000)); */ 442 break; 443 default: 444 return PHYMOD_E_UNAVAIL; 445 break; 446 } 447 return PHYMOD_E_NONE; 448 } 449 450 int qtce_core_wait_event(const phymod_core_access_t* core, phymod_core_event_t event, uint32_t timeout) 451 { 452 switch(event){ 453 case phymodCoreEventPllLock: 454 /* PHYMOD_IF_ERR_RETURN(qtce_pll_lock_wait(&core->access, timeout)); */ 455 break; 456 default: 457 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal wait event %u"), event)); 458 } 459 return PHYMOD_E_NONE; 460 } 461 462 int qtce_phy_pll_multiplier_get(const phymod_phy_access_t* core, uint32_t* pll_multiplier) 463 { 464 return PHYMOD_E_NONE; 465 } 466 467 468 /* reset rx sequencer 469 * flags - unused parameter 470 */ 471 int qtce_phy_rx_restart(const phymod_phy_access_t* phy) 472 { 473 phymod_phy_access_t phy_copy; 474 int lane_id, sub_port; 475 476 PHYMOD_IF_ERR_RETURN 477 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 478 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 479 phy_copy.access.lane_mask = 1 << lane_id; 480 481 PHYMOD_IF_ERR_RETURN(eagle_tsc_rx_restart(&phy_copy.access, 1)); 482 return PHYMOD_E_NONE; 483 } 484 485 486 int qtce_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity) 487 { 488 phymod_phy_access_t phy_copy; 489 int lane_id, sub_port; 490 491 PHYMOD_IF_ERR_RETURN 492 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 493 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 494 phy_copy.access.lane_mask = 1 << lane_id; 495 496 PHYMOD_IF_ERR_RETURN 497 (qmod_tx_rx_polarity_set(&phy_copy.access, polarity->tx_polarity, polarity->rx_polarity)); 498 return PHYMOD_E_NONE; 499 } 500 501 502 int qtce_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity) 503 { 504 phymod_phy_access_t phy_copy; 505 int lane_id, sub_port; 506 507 PHYMOD_IF_ERR_RETURN 508 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 509 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 510 phy_copy.access.lane_mask = 1 << lane_id; 511 512 PHYMOD_IF_ERR_RETURN 513 (qmod_tx_rx_polarity_get(&phy_copy.access, &polarity->tx_polarity, &polarity->rx_polarity)); 514 return PHYMOD_E_NONE; 515 } 516 517 int _qtce_phy_tx_set(phymod_phy_access_t* phy, const phymod_tx_t* tx) 518 { 519 PHYMOD_IF_ERR_RETURN 520 (eagle_tsc_write_tx_afe(&phy->access, TX_AFE_PRE, (int8_t)tx->pre)); 521 PHYMOD_IF_ERR_RETURN 522 (eagle_tsc_write_tx_afe(&phy->access, TX_AFE_MAIN, (int8_t)tx->main)); 523 PHYMOD_IF_ERR_RETURN 524 (eagle_tsc_write_tx_afe(&phy->access, TX_AFE_POST1, (int8_t)tx->post)); 525 PHYMOD_IF_ERR_RETURN 526 (eagle_tsc_write_tx_afe(&phy->access, TX_AFE_POST2, (int8_t)tx->post2)); 527 PHYMOD_IF_ERR_RETURN 528 (eagle_tsc_write_tx_afe(&phy->access, TX_AFE_POST3, (int8_t)tx->post3)); 529 PHYMOD_IF_ERR_RETURN 530 (eagle_tsc_write_tx_afe(&phy->access, TX_AFE_AMP, (int8_t)tx->amp)); 531 532 return PHYMOD_E_NONE; 533 } 534 535 int qtce_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 536 { 537 phymod_phy_access_t phy_copy; 538 int lane_id, sub_port; 539 540 PHYMOD_IF_ERR_RETURN 541 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 542 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 543 phy_copy.access.lane_mask = 1 << lane_id; 544 545 PHYMOD_IF_ERR_RETURN(_qtce_phy_tx_set(&phy_copy, tx)); 546 547 return PHYMOD_E_NONE; 548 } 549 550 int qtce_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 551 { 552 phymod_phy_access_t phy_copy; 553 int lane_id, sub_port; 554 int8_t value = 0; 555 556 PHYMOD_IF_ERR_RETURN 557 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 558 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 559 phy_copy.access.lane_mask = 1 << lane_id; 560 561 PHYMOD_IF_ERR_RETURN 562 (eagle_tsc_read_tx_afe(&phy_copy.access, TX_AFE_PRE, &value)); 563 tx->pre = value; 564 PHYMOD_IF_ERR_RETURN 565 (eagle_tsc_read_tx_afe(&phy_copy.access, TX_AFE_MAIN, &value)); 566 tx->main = value; 567 PHYMOD_IF_ERR_RETURN 568 (eagle_tsc_read_tx_afe(&phy_copy.access, TX_AFE_POST1, &value)); 569 tx->post = value; 570 PHYMOD_IF_ERR_RETURN 571 (eagle_tsc_read_tx_afe(&phy_copy.access, TX_AFE_POST2, &value)); 572 tx->post2 = value; 573 PHYMOD_IF_ERR_RETURN 574 (eagle_tsc_read_tx_afe(&phy_copy.access, TX_AFE_POST3, &value)); 575 tx->post3 = value; 576 PHYMOD_IF_ERR_RETURN 577 (eagle_tsc_read_tx_afe(&phy_copy.access, TX_AFE_AMP, &value)); 578 tx->amp = value; 579 580 return PHYMOD_E_NONE; 581 } 582 583 int qtce_phy_tx_override_set(const phymod_phy_access_t* phy, const phymod_tx_override_t* tx_override) 584 { 585 phymod_phy_access_t phy_copy; 586 int lane_id, sub_port; 587 588 PHYMOD_IF_ERR_RETURN 589 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 590 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 591 phy_copy.access.lane_mask = 1 << lane_id; 592 593 PHYMOD_IF_ERR_RETURN 594 (eagle_tsc_tx_pi_freq_override(&phy_copy.access, 595 tx_override->phase_interpolator.enable, 596 tx_override->phase_interpolator.value)); 597 return PHYMOD_E_NONE; 598 } 599 600 int qtce_phy_tx_override_get(const phymod_phy_access_t* phy, phymod_tx_override_t* tx_override) 601 { 602 /* 603 PHYMOD_IF_ERR_RETURN 604 (qtce_tx_pi_control_get(&phy->access, &tx_override->phase_interpolator.value)); 605 */ 606 return PHYMOD_E_NONE; 607 } 608 609 610 int qtce_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx) 611 { 612 uint32_t i; 613 phymod_phy_access_t phy_copy; 614 int lane_id, sub_port; 615 616 PHYMOD_IF_ERR_RETURN 617 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 618 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 619 phy_copy.access.lane_mask = 1 << lane_id; 620 621 /* params check */ 622 if((rx->num_of_dfe_taps == 0) || (rx->num_of_dfe_taps < QTCE_NOF_DFES)){ 623 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal number of DFEs to set %u"), rx->num_of_dfe_taps)); 624 } 625 626 /*vga set*/ 627 if (rx->vga.enable) { 628 /* first stop the rx adaption */ 629 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 1)); 630 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_VGA, rx->vga.value)); 631 } else { 632 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 0)); 633 } 634 635 /* dfe set */ 636 for (i = 0 ; i < rx->num_of_dfe_taps ; i++){ 637 if(rx->dfe[i].enable){ 638 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 1)); 639 switch (i) { 640 case 0: 641 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_DFE1, rx->dfe[i].value)); 642 break; 643 case 1: 644 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_DFE2, rx->dfe[i].value)); 645 break; 646 case 2: 647 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_DFE3, rx->dfe[i].value)); 648 break; 649 case 3: 650 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_DFE4, rx->dfe[i].value)); 651 break; 652 case 4: 653 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_DFE5, rx->dfe[i].value)); 654 break; 655 default: 656 return PHYMOD_E_PARAM; 657 } 658 } else { 659 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 0)); 660 } 661 } 662 663 /* peaking filter set */ 664 if(rx->peaking_filter.enable){ 665 /* first stop the rx adaption */ 666 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 1)); 667 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_PF, rx->peaking_filter.value)); 668 } else { 669 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 0)); 670 } 671 672 if(rx->low_freq_peaking_filter.enable){ 673 /* first stop the rx adaption */ 674 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 1)); 675 PHYMOD_IF_ERR_RETURN(eagle_tsc_write_rx_afe(&phy_copy.access, RX_AFE_PF2, rx->low_freq_peaking_filter.value)); 676 } else { 677 PHYMOD_IF_ERR_RETURN(eagle_tsc_stop_rx_adaptation(&phy_copy.access, 0)); 678 } 679 return PHYMOD_E_NONE; 680 } 681 682 683 int qtce_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx) 684 { 685 phymod_phy_access_t phy_copy; 686 int lane_id, sub_port; 687 int8_t tmpData; 688 689 PHYMOD_IF_ERR_RETURN 690 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 691 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 692 phy_copy.access.lane_mask = 1 << lane_id; 693 694 PHYMOD_IF_ERR_RETURN 695 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_PF, &tmpData)); 696 rx->peaking_filter.value = tmpData; 697 PHYMOD_IF_ERR_RETURN 698 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_PF2, &tmpData)); 699 rx->low_freq_peaking_filter.value = tmpData; 700 PHYMOD_IF_ERR_RETURN 701 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_VGA, &tmpData)); 702 rx->vga.value = tmpData; 703 PHYMOD_IF_ERR_RETURN 704 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_DFE1, &tmpData)); 705 rx->dfe[0].value = tmpData; 706 PHYMOD_IF_ERR_RETURN 707 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_DFE2, &tmpData)); 708 rx->dfe[1].value = tmpData; 709 PHYMOD_IF_ERR_RETURN 710 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_DFE3, &tmpData)); 711 rx->dfe[2].value = tmpData; 712 PHYMOD_IF_ERR_RETURN 713 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_DFE4, &tmpData)); 714 rx->dfe[3].value = tmpData; 715 PHYMOD_IF_ERR_RETURN 716 (eagle_tsc_read_rx_afe(&phy_copy.access, RX_AFE_DFE5, &tmpData)); 717 rx->dfe[4].value = tmpData; 718 719 rx->num_of_dfe_taps = 5; 720 rx->dfe[0].enable = 1; 721 rx->dfe[1].enable = 1; 722 rx->dfe[2].enable = 1; 723 rx->dfe[3].enable = 1; 724 rx->dfe[4].enable = 1; 725 rx->vga.enable = 1; 726 rx->low_freq_peaking_filter.enable = 1; 727 rx->peaking_filter.enable = 1; 728 return PHYMOD_E_NONE; 729 } 730 731 732 int qtce_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset) 733 { 734 735 736 737 /* Place your code here */ 738 739 740 return PHYMOD_E_NONE; 741 742 743 } 744 745 746 int qtce_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset) 747 { 748 749 750 751 /* Place your code here */ 752 753 754 return PHYMOD_E_NONE; 755 756 757 } 758 759 760 int qtce_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 761 { 762 phymod_phy_access_t pm_phy_copy; 763 int start_lane, num_lane, lane_id, sub_port; 764 765 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 766 /* next program the tx fir taps and driver current based on the input */ 767 PHYMOD_IF_ERR_RETURN 768 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 769 770 PHYMOD_IF_ERR_RETURN 771 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 772 773 start_lane = lane_id ; 774 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 775 776 777 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) { 778 PHYMOD_IF_ERR_RETURN(qmod_port_enable_set(&pm_phy_copy.access, 0)); 779 } 780 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) { 781 PHYMOD_IF_ERR_RETURN(qmod_port_enable_set(&pm_phy_copy.access, 1)); 782 } 783 784 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) { 785 /* disable tx on the PMD side */ 786 PHYMOD_IF_ERR_RETURN(eagle_tsc_tx_disable(&pm_phy_copy.access, 1)); 787 } 788 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) { 789 /* enable tx on the PMD side */ 790 PHYMOD_IF_ERR_RETURN(eagle_tsc_tx_disable(&pm_phy_copy.access, 0)); 791 } 792 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) { 793 /* disable rx on the PMD side */ 794 PHYMOD_IF_ERR_RETURN(qmod_rx_squelch_set(&pm_phy_copy.access, 1)); 795 } 796 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) { 797 /* enable rx on the PMD side */ 798 PHYMOD_IF_ERR_RETURN(qmod_rx_squelch_set(&pm_phy_copy.access, 0)); 799 } 800 return PHYMOD_E_NONE; 801 } 802 803 int qtce_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 804 { 805 int enable; 806 uint32_t lb_enable; 807 phymod_phy_access_t pm_phy_copy; 808 int start_lane, num_lane, lane_id, sub_port; 809 810 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 811 /* next program the tx fir taps and driver current based on the input */ 812 PHYMOD_IF_ERR_RETURN 813 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 814 815 PHYMOD_IF_ERR_RETURN 816 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 817 818 start_lane = lane_id ; 819 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 820 821 PHYMOD_IF_ERR_RETURN(qmod_rx_squelch_get(&pm_phy_copy.access, &enable)); 822 823 /* next check if PMD loopback is on */ 824 if (enable) { 825 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 826 if (lb_enable) enable = 0; 827 } 828 829 power->rx = (enable == 1)? phymodPowerOff: phymodPowerOn; 830 /* Commented the following line. Because if in PMD loopback mode, we squelch the 831 xmit, and we should still see the correct port status */ 832 /* PHYMOD_IF_ERR_RETURN(qtce_tx_squelch_get(&pm_phy_copy.access, &enable)); */ 833 power->tx = (enable == 1)? phymodPowerOff: phymodPowerOn; 834 return PHYMOD_E_NONE; 835 } 836 837 int qtce_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control) 838 { 839 phymod_phy_access_t pm_phy_copy; 840 int start_lane, num_lane, lane_id, sub_port; 841 int qmode = 0, subports = 0, sq_value = 0; 842 843 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 844 /* next program the tx fir taps and driver current based on the input */ 845 PHYMOD_IF_ERR_RETURN 846 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 847 848 PHYMOD_IF_ERR_RETURN 849 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 850 851 start_lane = lane_id ; 852 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 853 854 if (PHYMOD_ACC_F_QMODE_GET(&phy->access)) { 855 qmode = 1; 856 PHYMOD_IF_ERR_RETURN(qmod_port_state_get(&pm_phy_copy.access, QMOD_PORT_STATE_CONFIGED, &subports)); 857 } 858 859 switch (tx_control) { 860 case phymodTxTrafficDisable: 861 PHYMOD_IF_ERR_RETURN(qmod_tx_lane_control_set(&pm_phy_copy.access, QMOD_TX_LANE_TRAFFIC_DISABLE)); 862 break; 863 case phymodTxTrafficEnable: 864 PHYMOD_IF_ERR_RETURN(qmod_tx_lane_control_set(&pm_phy_copy.access, QMOD_TX_LANE_TRAFFIC_ENABLE)); 865 break; 866 case phymodTxReset: 867 PHYMOD_IF_ERR_RETURN(qmod_tx_lane_control_set(&pm_phy_copy.access, QMOD_TX_LANE_RESET)); 868 break; 869 case phymodTxSquelchOn: 870 PHYMOD_IF_ERR_RETURN(qmod_port_state_set(&pm_phy_copy.access, QMOD_PORT_STATE_TX_SQUELCH, sub_port, 1)); 871 PHYMOD_IF_ERR_RETURN(qmod_port_state_get(&pm_phy_copy.access, QMOD_PORT_STATE_TX_SQUELCH, &sq_value)); 872 if ((qmode == 0) || (sq_value == subports)) { 873 /* not qmode or all subports want to squelch*/ 874 PHYMOD_IF_ERR_RETURN(qmod_tx_squelch_set(&pm_phy_copy.access, 1)); 875 } 876 break; 877 case phymodTxSquelchOff: 878 PHYMOD_IF_ERR_RETURN(qmod_port_state_set(&pm_phy_copy.access, QMOD_PORT_STATE_TX_SQUELCH, sub_port, 0)); 879 PHYMOD_IF_ERR_RETURN(qmod_tx_squelch_set(&pm_phy_copy.access, 0)); 880 break; 881 default: 882 break; 883 } 884 return PHYMOD_E_NONE; 885 } 886 887 int qtce_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control) 888 { 889 int enable, reset, tx_lane; 890 uint32_t lb_enable; 891 phymod_phy_access_t pm_phy_copy; 892 int start_lane, num_lane, lane_id, sub_port; 893 894 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 895 /* next program the tx fir taps and driver current based on the input */ 896 PHYMOD_IF_ERR_RETURN 897 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 898 899 PHYMOD_IF_ERR_RETURN 900 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 901 start_lane = lane_id ; 902 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 903 904 PHYMOD_IF_ERR_RETURN(qmod_tx_squelch_get(&pm_phy_copy.access, &enable)); 905 906 /* next check if PMD loopback is on */ 907 if (enable) { 908 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 909 if (lb_enable) enable = 0; 910 } 911 912 if(enable) { 913 *tx_control = phymodTxSquelchOn; 914 } else { 915 PHYMOD_IF_ERR_RETURN(qmod_tx_lane_control_get(&pm_phy_copy.access, &reset, &tx_lane)); 916 if (!reset) { 917 *tx_control = phymodTxReset; 918 } else if (!tx_lane) { 919 *tx_control = phymodTxTrafficDisable; 920 } else { 921 *tx_control = phymodTxTrafficEnable; 922 } 923 } 924 return PHYMOD_E_NONE; 925 } 926 927 928 int qtce_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control) 929 { 930 phymod_phy_access_t pm_phy_copy; 931 int start_lane, num_lane, lane_id, sub_port; 932 int qmode = 0, subports = 0, sq_value = 0; 933 934 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 935 /* next program the tx fir taps and driver current based on the input */ 936 PHYMOD_IF_ERR_RETURN 937 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 938 939 PHYMOD_IF_ERR_RETURN 940 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 941 942 start_lane = lane_id ; 943 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 944 945 if (PHYMOD_ACC_F_QMODE_GET(&phy->access)) { 946 qmode = 1; 947 PHYMOD_IF_ERR_RETURN(qmod_port_state_get(&pm_phy_copy.access, QMOD_PORT_STATE_CONFIGED, &subports)); 948 } 949 switch (rx_control) { 950 case phymodRxReset: 951 PHYMOD_IF_ERR_RETURN(qmod_rx_lane_control_set(&pm_phy_copy.access, 0)); 952 break; 953 case phymodRxSquelchOn: 954 PHYMOD_IF_ERR_RETURN(qmod_port_state_set(&pm_phy_copy.access, QMOD_PORT_STATE_RX_SQUELCH, sub_port, 1)); 955 PHYMOD_IF_ERR_RETURN(qmod_port_state_get(&pm_phy_copy.access, QMOD_PORT_STATE_RX_SQUELCH, &sq_value)); 956 if ((qmode == 0) || (sq_value == subports)) { 957 /* not qmode or all subports want to squelch */ 958 PHYMOD_IF_ERR_RETURN(qmod_rx_squelch_set(&pm_phy_copy.access, 1)); 959 } 960 break; 961 case phymodRxSquelchOff: 962 PHYMOD_IF_ERR_RETURN(qmod_port_state_set(&pm_phy_copy.access, QMOD_PORT_STATE_RX_SQUELCH, sub_port, 0)); 963 PHYMOD_IF_ERR_RETURN(qmod_rx_squelch_set(&pm_phy_copy.access, 0)); 964 break; 965 default: 966 break; 967 } 968 return PHYMOD_E_NONE; 969 } 970 971 int qtce_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control) 972 { 973 int enable, reset; 974 uint32_t lb_enable; 975 phymod_phy_access_t pm_phy_copy; 976 int start_lane, num_lane, lane_id, sub_port; 977 978 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 979 /* next program the tx fir taps and driver current based on the input */ 980 PHYMOD_IF_ERR_RETURN 981 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 982 983 PHYMOD_IF_ERR_RETURN 984 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 985 986 start_lane = lane_id ; 987 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 988 989 PHYMOD_IF_ERR_RETURN(qmod_rx_squelch_get(&pm_phy_copy.access, &enable)); 990 /* next check if PMD loopback is on */ 991 if (enable) { 992 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 993 if (lb_enable) enable = 0; 994 } 995 if(enable) { 996 *rx_control = phymodRxSquelchOn; 997 } else { 998 PHYMOD_IF_ERR_RETURN(qmod_rx_lane_control_get(&pm_phy_copy.access, &reset)); 999 if (reset == 0) { 1000 *rx_control = phymodRxReset; 1001 } else { 1002 *rx_control = phymodRxSquelchOff; 1003 } 1004 } 1005 return PHYMOD_E_NONE; 1006 } 1007 1008 int qtce_phy_tx_disable_set(const phymod_phy_access_t* phy, uint32_t tx_disable) 1009 { 1010 return PHYMOD_E_NONE; 1011 } 1012 1013 1014 int qtce_phy_tx_disable_get(const phymod_phy_access_t* phy, uint32_t* tx_disable) 1015 { 1016 return PHYMOD_E_NONE; 1017 } 1018 1019 int qtce_phy_fec_enable_set(const phymod_phy_access_t* phy, uint32_t enable) 1020 { 1021 return PHYMOD_E_UNAVAIL; 1022 1023 } 1024 1025 int qtce_phy_fec_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 1026 { 1027 return PHYMOD_E_UNAVAIL; 1028 1029 } 1030 1031 int _qtce_pll_multiplier_get(uint32_t pll_div, uint32_t *pll_multiplier) 1032 { 1033 switch (pll_div) { 1034 case 0x0: 1035 *pll_multiplier = 46; 1036 break; 1037 case 0x1: 1038 *pll_multiplier = 72; 1039 break; 1040 case QMOD_PLL_MODE_DIV_40: 1041 *pll_multiplier = 40; 1042 break; 1043 case QMOD_PLL_MODE_DIV_42: 1044 *pll_multiplier = 42; 1045 break; 1046 case QMOD_PLL_MODE_DIV_48: 1047 *pll_multiplier = 48; 1048 break; 1049 case 0x5: 1050 *pll_multiplier = 50; 1051 break; 1052 case QMOD_PLL_MODE_DIV_52: 1053 *pll_multiplier = 52; 1054 break; 1055 case QMOD_PLL_MODE_DIV_54: 1056 *pll_multiplier = 54; 1057 break; 1058 case QMOD_PLL_MODE_DIV_60: 1059 *pll_multiplier = 60; 1060 break; 1061 case QMOD_PLL_MODE_DIV_64: 1062 *pll_multiplier = 64; 1063 break; 1064 case QMOD_PLL_MODE_DIV_66: 1065 *pll_multiplier = 66; 1066 break; 1067 case 0xb: 1068 *pll_multiplier = 68; 1069 break; 1070 case QMOD_PLL_MODE_DIV_70: 1071 *pll_multiplier = 70; 1072 break; 1073 case QMOD_PLL_MODE_DIV_80: 1074 *pll_multiplier = 80; 1075 break; 1076 case QMOD_PLL_MODE_DIV_92: 1077 *pll_multiplier = 92; 1078 break; 1079 case 0xf: 1080 *pll_multiplier = 100; 1081 break; 1082 default: 1083 *pll_multiplier = 66; 1084 break; 1085 } 1086 return PHYMOD_E_NONE; 1087 } 1088 1089 /* to modify the sub-port speed */ 1090 STATIC 1091 int _qtce_qsgmii_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 1092 { 1093 qmod_spd_intfc_type spd_intf = QMOD_SPD_ILLEGAL, old_spd_intf; 1094 qmod_spd_intfc_type qmod_spd_intf = QMOD_SPD_ILLEGAL; 1095 phymod_phy_access_t pm_phy_copy; 1096 int start_lane, lane_id, sub_port, num_lane ; 1097 1098 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1099 1100 /* next program the tx fir taps and driver current based on the input */ 1101 /* get num_lane only in QTC */ 1102 PHYMOD_IF_ERR_RETURN 1103 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1104 1105 PHYMOD_IF_ERR_RETURN 1106 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1107 1108 start_lane = lane_id ; 1109 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1110 1111 spd_intf = QMOD_SPD_1000_SGMII; /* to prevent undefinded QMOD_SPD_ILLEGAL accessing tables */ 1112 1113 switch(config->data_rate) { 1114 case 10: 1115 if(config->pll_divider_req==40) { 1116 spd_intf = QMOD_SPD_10_SGMII; 1117 } else { 1118 /* spd_intf = QMOD_SPD_10_X1_SGMII; */ 1119 spd_intf = QMOD_SPD_10_SGMII; 1120 } 1121 break; 1122 case 100: 1123 if(config->pll_divider_req==40) { 1124 spd_intf = QMOD_SPD_100_SGMII; 1125 } else { 1126 /*spd_intf = QMOD_SPD_100_X1_SGMII; */ 1127 spd_intf = QMOD_SPD_100_SGMII; 1128 } 1129 break; 1130 case 1000: 1131 if(config->pll_divider_req==40) { 1132 spd_intf = QMOD_SPD_1000_SGMII; 1133 } else { 1134 /*spd_intf = QMOD_SPD_1000_X1_SGMII; */ 1135 spd_intf = QMOD_SPD_1000_SGMII; 1136 } 1137 break; 1138 default: 1139 spd_intf = QMOD_SPD_ILLEGAL; 1140 break; 1141 } 1142 1143 PHYMOD_IF_ERR_RETURN 1144 (qmod_get_qport_spd(&pm_phy_copy.access, sub_port, &old_spd_intf)); 1145 1146 qmod_spd_intf = spd_intf; 1147 spd_intf = QMOD_SPD_4000; 1148 1149 if (old_spd_intf != QMOD_SPD_1000_SGMII) { 1150 PHYMOD_IF_ERR_RETURN 1151 (qmod_set_qport_spd(&pm_phy_copy.access, sub_port, QMOD_SPD_1000_SGMII)); 1152 } 1153 1154 if (qmod_spd_intf != QMOD_SPD_1000_SGMII) { 1155 PHYMOD_USLEEP(200); 1156 PHYMOD_IF_ERR_RETURN 1157 (qmod_set_qport_spd(&pm_phy_copy.access, sub_port, qmod_spd_intf)); 1158 } 1159 1160 return PHYMOD_E_NONE; 1161 1162 } 1163 1164 int qtce_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 1165 { 1166 uint32_t current_pll_div=0; 1167 uint32_t new_pll_div=0; 1168 uint16_t new_speed_vec=0; 1169 qmod_spd_intfc_type spd_intf = QMOD_SPD_ILLEGAL; 1170 qmod_spd_intfc_type qmod_spd_intf = QMOD_SPD_ILLEGAL; 1171 phymod_phy_access_t pm_phy_copy; 1172 int start_lane, num_lane, i, pll_switch = 0; 1173 uint32_t u_os_mode = 0; 1174 int lane_bkup; 1175 uint32_t pll_multiplier, vco_rate; 1176 int lane_id, sub_port ; 1177 uint32_t sc_enable = 0; 1178 1179 /* sc_table_entry exp_entry; RAVI */ 1180 phymod_firmware_lane_config_t firmware_lane_config; 1181 phymod_firmware_core_config_t firmware_core_config; 1182 1183 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1184 1185 firmware_lane_config.MediaType = 0; 1186 1187 /* next program the tx fir taps and driver current based on the input */ 1188 /* get num_lane only in QTC */ 1189 PHYMOD_IF_ERR_RETURN 1190 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1191 1192 PHYMOD_IF_ERR_RETURN 1193 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1194 1195 start_lane = lane_id ; 1196 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1197 1198 /* special call path for QSGMII FS mode for port not repeated calls on the same lane */ 1199 if (PHYMOD_ACC_F_QMODE_GET(&phy->access)) { 1200 qmod_speedchange_get(&pm_phy_copy.access, &sc_enable) ; 1201 if (sc_enable) { 1202 return _qtce_qsgmii_interface_config_set(phy, flags, config); 1203 } 1204 } 1205 1206 PHYMOD_IF_ERR_RETURN 1207 (qmod_reset(&pm_phy_copy.access)); 1208 1209 /* Hold the per lane soft reset bit */ 1210 for (i = 0; i < num_lane; i++) { 1211 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1212 PHYMOD_IF_ERR_RETURN 1213 (eagle_lane_soft_reset_release(&pm_phy_copy.access, 0)); 1214 } 1215 1216 PHYMOD_USLEEP(500); 1217 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1218 PHYMOD_IF_ERR_RETURN 1219 (qtce_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 1220 1221 /* make sure that an and config from pcs is off */ 1222 firmware_core_config.CoreConfigFromPCS = 0; 1223 firmware_lane_config.AnEnabled = 0; 1224 firmware_lane_config.LaneConfigFromPCS = 0; 1225 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1226 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1227 } 1228 1229 PHYMOD_IF_ERR_RETURN 1230 (qmod_update_port_mode(&phy->access, (int *) &pll_switch)); 1231 1232 spd_intf = QMOD_SPD_1000_SGMII; /* to prevent undefinded QMOD_SPD_ILLEGAL accessing tables */ 1233 1234 /* find the speed */ 1235 if (config->interface_type == phymodInterfaceXFI) { 1236 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1237 } else if(config->interface_type == phymodInterfaceSFI) { 1238 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1239 } 1240 switch(config->data_rate) { 1241 case 10: 1242 if(config->pll_divider_req==40) { 1243 spd_intf = QMOD_SPD_10_SGMII; 1244 } else { 1245 /* spd_intf = QMOD_SPD_10_X1_SGMII; */ 1246 spd_intf = QMOD_SPD_10_SGMII; 1247 } 1248 break; 1249 case 100: 1250 if(config->pll_divider_req==40) { 1251 spd_intf = QMOD_SPD_100_SGMII; 1252 } else { 1253 /*spd_intf = QMOD_SPD_100_X1_SGMII; */ 1254 spd_intf = QMOD_SPD_100_SGMII; 1255 } 1256 break; 1257 case 1000: 1258 if(config->pll_divider_req==40) { 1259 spd_intf = QMOD_SPD_1000_SGMII; 1260 } else { 1261 /*spd_intf = QMOD_SPD_1000_X1_SGMII; */ 1262 spd_intf = QMOD_SPD_1000_SGMII; 1263 } 1264 break; 1265 case 2500: 1266 if(config->pll_divider_req==40) { 1267 spd_intf = QMOD_SPD_2500; 1268 } else { 1269 /*spd_intf = QMOD_SPD_2500_X1; */ 1270 spd_intf = QMOD_SPD_2500; 1271 } 1272 break; 1273 case 5000: 1274 case 10500: 1275 case 11000: 1276 case 12000: 1277 case 13000: 1278 case 15750: 1279 case 16000: 1280 case 20000: 1281 case 21000: 1282 case 3000: 1283 case 35000: 1284 case 40000: 1285 case 42000: 1286 case 100000: 1287 case 106000: 1288 case 107000: 1289 case 120000: 1290 case 127000: 1291 spd_intf = QMOD_SPD_ILLEGAL; 1292 break; 1293 default: 1294 break; 1295 } 1296 1297 if(config->data_rate==10||config->data_rate==100|| config->data_rate==1000) { 1298 if (config->interface_type == phymodInterfaceSGMII) { 1299 firmware_lane_config.MediaType =phymodFirmwareMediaTypePcbTraceBackPlane; 1300 } 1301 if (config->interface_type == phymodInterface1000X) { 1302 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1303 } 1304 } 1305 1306 PHYMOD_IF_ERR_RETURN 1307 (qmod_get_plldiv(&phy->access, ¤t_pll_div)); 1308 1309 /* next check if we are in qsgmii mode */ 1310 if (PHYMOD_ACC_F_QMODE_GET(&phy->access)) { 1311 qmod_spd_intf = spd_intf; 1312 spd_intf = QMOD_SPD_4000; 1313 1314 PHYMOD_IF_ERR_RETURN 1315 (qmod_set_qport_spd(&pm_phy_copy.access, sub_port, QMOD_SPD_1000_SGMII)); 1316 1317 if (qmod_spd_intf != QMOD_SPD_1000_SGMII) { 1318 PHYMOD_USLEEP(200); 1319 PHYMOD_IF_ERR_RETURN 1320 (qmod_set_qport_spd(&pm_phy_copy.access, sub_port, qmod_spd_intf)); 1321 } 1322 } 1323 1324 PHYMOD_IF_ERR_RETURN 1325 (qmod_plldiv_lkup_get(&pm_phy_copy.access, spd_intf, &new_pll_div, &new_speed_vec)); 1326 1327 1328 PHYMOD_IF_ERR_RETURN 1329 (qmod_pmd_osmode_set(&pm_phy_copy.access, spd_intf, u_os_mode)); 1330 1331 /* if pll change is enabled. new_pll_div is the reg vector value */ 1332 if((current_pll_div != new_pll_div) && (PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)){ 1333 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 1334 (_PHYMOD_MSG("pll has to change for speed_set from %u to %u but DONT_TURN_OFF_PLL flag is enabled"), 1335 current_pll_div, new_pll_div)); 1336 } 1337 /* pll switch is required and expected */ 1338 if((current_pll_div != new_pll_div) && !(PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) { 1339 /* phymod_access_t tmp_phy_access; */ 1340 1341 /* Change in PLL, so reset all the ports first. Check for TSC12 */ 1342 lane_bkup = pm_phy_copy.access.lane_mask; 1343 pm_phy_copy.access.lane_mask = 0xf; 1344 qmod_disable_set(&pm_phy_copy.access); 1345 pm_phy_copy.access.lane_mask = lane_bkup; 1346 1347 /* tmp_phy_access = phy->access; */ 1348 1349 PHYMOD_IF_ERR_RETURN 1350 (eagle_core_soft_reset_release(&pm_phy_copy.access, 0)); 1351 1352 /* release the uc reset */ 1353 PHYMOD_IF_ERR_RETURN 1354 (eagle_uc_reset(&pm_phy_copy.access ,1)); 1355 1356 /* set the PLL divider */ 1357 PHYMOD_IF_ERR_RETURN 1358 (eagle_pll_mode_set(&pm_phy_copy.access, new_pll_div)); 1359 PHYMOD_IF_ERR_RETURN 1360 (_qtce_pll_multiplier_get(new_pll_div, &pll_multiplier)); 1361 /* update the VCO rate properly */ 1362 switch (config->ref_clock) { 1363 case phymodRefClk156Mhz: 1364 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100; 1365 break; 1366 case phymodRefClk125Mhz: 1367 vco_rate = pll_multiplier * 125; 1368 break; 1369 default: 1370 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100; 1371 break; 1372 } 1373 firmware_core_config.VcoRate = (vco_rate - 5750) / 250 + 1; 1374 1375 /* change the master port num to the current caller port */ 1376 PHYMOD_IF_ERR_RETURN 1377 (qmod_master_port_num_set(&pm_phy_copy.access, start_lane)); 1378 1379 PHYMOD_IF_ERR_RETURN 1380 (qmod_pll_reset_enable_set(&pm_phy_copy.access, 1)); 1381 1382 /* update the firmware config properly */ 1383 PHYMOD_IF_ERR_RETURN 1384 (qtce_phy_firmware_core_config_set(&pm_phy_copy, firmware_core_config)); 1385 PHYMOD_IF_ERR_RETURN 1386 (eagle_core_soft_reset_release(&pm_phy_copy.access, 1)); 1387 } 1388 1389 1390 for (i = 0; i < num_lane; i++) { 1391 pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i); 1392 PHYMOD_IF_ERR_RETURN 1393 (_qtce_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config)); 1394 } 1395 1396 /* release the per lne soft reset bit */ 1397 for (i = 0; i < num_lane; i++) { 1398 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1399 PHYMOD_IF_ERR_RETURN 1400 (eagle_lane_soft_reset_release(&pm_phy_copy.access, 1)); 1401 } 1402 1403 if (config->interface_type == phymodInterfaceBypass) { 1404 return PHYMOD_E_FAIL; 1405 } else { 1406 /* if(flags & PHYMOD_INTF_F_SET_SPD_NO_TRIGGER) { 1407 (qmod_set_spd_intf(&pm_phy_copy.access, spd_intf, 1)); 1408 } else { */ 1409 PHYMOD_IF_ERR_RETURN 1410 (qmod_set_spd_intf(&pm_phy_copy.access, spd_intf, 0)); 1411 /* } */ 1412 } 1413 PHYMOD_USLEEP(10000); 1414 /* TX Params are set outside this func */ 1415 /* change TX parameters if enabled */ 1416 /* if((PHYMOD_IF_F_DONT_OVERIDE_TX_PARAMS & flags) == 0) 1417 PHYMOD_IF_ERR_RETURN 1418 (qtce_phy_media_type_tx_get(phy, phymodMediaTypeMid, &tx_params)); 1419 PHYMOD_IF_ERR_RETURN 1420 (qtce_phy_tx_set(phy, &tx_params)); 1421 */ 1422 1423 1424 1425 return PHYMOD_E_NONE; 1426 } 1427 1428 int _qtce_speed_id_interface_config_get(const phymod_phy_access_t* phy, int speed_id, 1429 phymod_phy_inf_config_t* config, uint16_t an_enable, 1430 phymod_firmware_lane_config_t *lane_config) 1431 { 1432 int ilkn_set; 1433 int osr_mode; 1434 uint32_t vco_rate; 1435 uint32_t pll_multiplier; 1436 uint32_t current_pll_div=0; 1437 int u_os_mode = 0xff; 1438 uint32_t actual_osr, actual_osr_rem; 1439 phymod_osr_mode_t osr_mode_enum; 1440 1441 PHYMOD_IF_ERR_RETURN 1442 (qmod_get_plldiv(&phy->access, ¤t_pll_div)); 1443 1444 ilkn_set = 0; 1445 /* coverity[dead_error_condition] */ 1446 if(ilkn_set) { 1447 /* coverity[dead_error_begin] */ 1448 config->interface_type = phymodInterfaceBypass; 1449 PHYMOD_IF_ERR_RETURN 1450 (_qtce_pll_multiplier_get(current_pll_div, &pll_multiplier)); 1451 PHYMOD_IF_ERR_RETURN 1452 (eagle_osr_mode_get(&phy->access, &osr_mode)); 1453 1454 switch (config->ref_clock) { 1455 case phymodRefClk156Mhz: 1456 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100; 1457 break; 1458 case phymodRefClk125Mhz: 1459 vco_rate = pll_multiplier * 125; 1460 break; 1461 default: 1462 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100; 1463 break; 1464 } 1465 1466 PHYMOD_IF_ERR_RETURN(eagle_osr_mode_to_enum(osr_mode, &osr_mode_enum)); 1467 PHYMOD_IF_ERR_RETURN(phymod_osr_mode_to_actual_os(osr_mode_enum, &actual_osr, &actual_osr_rem)); 1468 config->data_rate = vco_rate/actual_osr; 1469 } else { 1470 1471 switch (speed_id) { 1472 case 0x1: 1473 config->data_rate = 10; 1474 config->interface_type = phymodInterfaceSGMII; 1475 break; 1476 case 0x2: 1477 config->data_rate = 100; 1478 config->interface_type = phymodInterfaceSGMII; 1479 break; 1480 case 0x3: 1481 { 1482 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1483 config->interface_type = phymodInterface1000X; 1484 } else { 1485 config->interface_type = phymodInterfaceSGMII; 1486 } 1487 config->data_rate = 1000; 1488 break; 1489 } 1490 case 0x4: 1491 config->data_rate = 1000; 1492 config->interface_type = phymodInterfaceCX; 1493 break; 1494 case 0x5: 1495 config->data_rate = 1000; 1496 config->interface_type = phymodInterfaceKX; 1497 break; 1498 case 0x6: 1499 config->data_rate = 2500; 1500 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1501 config->interface_type = phymodInterface1000X; 1502 } else { 1503 config->interface_type = phymodInterfaceSGMII; 1504 } 1505 break; 1506 case 0x7: 1507 config->data_rate = 5000; 1508 config->interface_type = phymodInterfaceSR; 1509 break; 1510 case 0x8: 1511 config->data_rate = 10000; 1512 config->interface_type = phymodInterfaceCX4; 1513 break; 1514 case 0x9: 1515 config->data_rate = 10000; 1516 config->interface_type = phymodInterfaceKX4; 1517 break; 1518 case 0xa: 1519 case 0xb: 1520 case 0xc: 1521 case 0xd: 1522 case 0xe: 1523 case 0xf: 1524 PHYMOD_IF_ERR_RETURN 1525 (qmod_pmd_osmode_get(&phy->access, &u_os_mode)); 1526 if(u_os_mode == QMOD_PMA_OS_MODE_2) { 1527 config->data_rate = 5000; 1528 config->interface_type = phymodInterfaceRXAUI; 1529 } else { 1530 config->data_rate = 10000; 1531 config->interface_type = phymodInterfaceCR2; 1532 } 1533 break; 1534 case 0x31: 1535 config->data_rate = 5000; 1536 config->interface_type = phymodInterfaceKR; 1537 break; 1538 case 0x32: 1539 case 0x35: 1540 config->data_rate = 10; 1541 config->interface_type = phymodInterfaceSGMII; 1542 break; 1543 case 0x36: 1544 config->data_rate = 100; 1545 config->interface_type = phymodInterfaceSGMII; 1546 break; 1547 case 0x37: 1548 config->data_rate = 1000; 1549 config->interface_type = phymodInterfaceSGMII; 1550 break; 1551 /* this is qsgmii mode */ 1552 case 0x3c: 1553 config->data_rate = 1000; 1554 config->interface_type = phymodInterfaceQSGMII; 1555 break; 1556 case 0x38: 1557 case 0x10: 1558 case 0x11: 1559 case 0x12: 1560 case 0x13: 1561 case 0x14: 1562 case 0x15: 1563 case 0x16: 1564 case 0x17: 1565 case 0x18: 1566 case 0x19: 1567 case 0x1a: 1568 case 0x1b: /* digital_operationSpeeds_SPEED_40G_X4; BRCM */ 1569 case 0x1c: 1570 case 0x1d: 1571 case 0x1e: 1572 case 0x1f: 1573 case 0x20: 1574 case 0x21: /* digital_operationSpeeds_SPEED_40G_KR4 */ 1575 case 0x22: 1576 case 0x23: /* digital_operationSpeeds_SPEED_42G_X4; atcually MLD */ 1577 case 0x24: 1578 case 0x25: 1579 case 0x26: 1580 case 0x27: 1581 default: 1582 config->data_rate = 0; 1583 config->interface_type = phymodInterfaceSGMII; 1584 break; 1585 } 1586 } 1587 return PHYMOD_E_NONE; 1588 } 1589 1590 1591 /* flags- unused parameter */ 1592 int qtce_phy_interface_config_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_ref_clk_t ref_clock, phymod_phy_inf_config_t* config) 1593 { 1594 int speed_id; 1595 phymod_firmware_lane_config_t firmware_lane_config; 1596 phymod_phy_access_t pm_phy_copy; 1597 int start_lane, num_lane; 1598 qmod_an_control_t an_control; 1599 int an_complete = 0; 1600 int lane_id, sub_port ; 1601 1602 config->ref_clock = ref_clock; 1603 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1604 PHYMOD_IF_ERR_RETURN 1605 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1606 1607 PHYMOD_IF_ERR_RETURN 1608 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1609 start_lane = lane_id ; 1610 1611 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1612 PHYMOD_IF_ERR_RETURN 1613 (qmod_speed_id_get(&pm_phy_copy.access, &speed_id, sub_port)); 1614 1615 PHYMOD_MEMSET(&an_control, 0x0, sizeof(qmod_an_control_t)); 1616 PHYMOD_IF_ERR_RETURN 1617 (qmod_autoneg_control_get(&pm_phy_copy.access, sub_port, &an_control, &an_complete)); 1618 1619 PHYMOD_IF_ERR_RETURN 1620 (qtce_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 1621 1622 PHYMOD_IF_ERR_RETURN 1623 (_qtce_speed_id_interface_config_get(&pm_phy_copy, speed_id, config, an_control.enable, &firmware_lane_config)); 1624 1625 if (firmware_lane_config.MediaType == phymodFirmwareMediaTypeOptics) { 1626 PHYMOD_INTF_MODES_FIBER_SET(config); 1627 } else { 1628 PHYMOD_INTF_MODES_FIBER_CLR(config); 1629 } 1630 1631 return PHYMOD_E_NONE; 1632 } 1633 1634 1635 int qtce_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en) 1636 { 1637 return PHYMOD_E_FAIL; 1638 } 1639 1640 int qtce_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en) 1641 { 1642 return PHYMOD_E_FAIL; 1643 } 1644 1645 int qtce_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status) 1646 { 1647 return PHYMOD_E_FAIL; 1648 } 1649 1650 int qtce_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability) 1651 { 1652 qmod_an_ability_t value; 1653 int start_lane, num_lane; 1654 phymod_phy_access_t phy_copy; 1655 int lane_id, sub_port ; 1656 1657 /* next program the tx fir taps and driver current based on the input */ 1658 PHYMOD_IF_ERR_RETURN 1659 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1660 1661 PHYMOD_IF_ERR_RETURN 1662 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1663 1664 start_lane = lane_id ; 1665 1666 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1667 phy_copy.access.lane_mask = 0x1 << start_lane; 1668 1669 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 1670 1671 /* check if sgmii or not */ 1672 if (PHYMOD_AN_CAP_SGMII_GET(an_ability)) { 1673 switch (an_ability->sgmii_speed) { 1674 case phymod_CL37_SGMII_10M: 1675 value.cl37_adv.cl37_sgmii_speed = QMOD_CL37_SGMII_10M; 1676 break; 1677 case phymod_CL37_SGMII_100M: 1678 value.cl37_adv.cl37_sgmii_speed = QMOD_CL37_SGMII_100M; 1679 break; 1680 case phymod_CL37_SGMII_1000M: 1681 value.cl37_adv.cl37_sgmii_speed = QMOD_CL37_SGMII_1000M; 1682 break; 1683 default: 1684 value.cl37_adv.cl37_sgmii_speed = QMOD_CL37_SGMII_1000M; 1685 break; 1686 } 1687 if( PHYMOD_AN_CAP_HALF_DUPLEX_GET(an_ability)) { 1688 value.cl37_adv.an_duplex = QMOD_AN_HALF_DUPLEX_SET ; 1689 } 1690 } 1691 /* next check pause */ 1692 if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability)) { 1693 value.cl37_adv.an_pause = QMOD_SYMM_PAUSE; 1694 } 1695 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 1696 value.cl37_adv.an_pause = QMOD_ASYM_PAUSE; 1697 } 1698 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 1699 value.cl37_adv.an_pause = QMOD_ASYM_SYMM_PAUSE; 1700 } 1701 1702 /* check cl37 and cl37 bam ability */ 1703 if (PHYMOD_AN_CAP_CL37BAM_GET(an_ability)) { 1704 value.cl37_adv.an_bam_speed |= 1 << QMOD_CL37_BAM_2p5GBASE_X; 1705 PHYMOD_IF_ERR_RETURN 1706 (qmod_an_cl37_bam_abilities(&phy_copy.access, &value, sub_port)); 1707 } else { 1708 PHYMOD_IF_ERR_RETURN 1709 (qmod_autoneg_cl37_base_abilities(&phy_copy.access, &value, sub_port)); 1710 } 1711 1712 1713 /* PHYMOD_IF_ERR_RETURN 1714 (qmod_autoneg_set(&phy_copy.access, &value, sub_port));*/ 1715 1716 return PHYMOD_E_NONE; 1717 } 1718 1719 int qtce_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type){ 1720 qmod_an_ability_t value; 1721 phymod_phy_access_t phy_copy; 1722 int lane_id, sub_port ; 1723 1724 1725 PHYMOD_IF_ERR_RETURN 1726 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1727 1728 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1729 phy_copy.access.lane_mask = 0x1 << lane_id; 1730 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 1731 1732 PHYMOD_IF_ERR_RETURN 1733 (qmod_autoneg_local_ability_get(&phy_copy.access, &value, sub_port)); 1734 1735 if(value.cl37_adv.an_type != QMOD_AN_MODE_NONE) { 1736 if (value.cl37_adv.an_pause == QMOD_ASYM_PAUSE) { 1737 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1738 } else if (value.cl37_adv.an_pause == QMOD_SYMM_PAUSE) { 1739 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1740 } else if (value.cl37_adv.an_pause == QMOD_ASYM_SYMM_PAUSE) { 1741 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1742 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1743 } 1744 if(value.cl37_adv.an_type & QMOD_AN_MODE_CL37) { 1745 PHYMOD_AN_CAP_CL37_SET(an_ability_get_type) ; 1746 PHYMOD_AN_CAP_HALF_DUPLEX_CLR(an_ability_get_type) ; 1747 } 1748 if(value.cl37_adv.an_type & QMOD_AN_MODE_SGMII) { 1749 PHYMOD_AN_CAP_SGMII_SET(an_ability_get_type) ; 1750 /* get the cl37 sgmii speed */ 1751 switch (value.cl37_adv.cl37_sgmii_speed) { 1752 case QMOD_CL37_SGMII_10M: 1753 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M; 1754 break; 1755 case QMOD_CL37_SGMII_100M: 1756 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M; 1757 break; 1758 case QMOD_CL37_SGMII_1000M: 1759 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M; 1760 break; 1761 default: 1762 break; 1763 } 1764 if(value.cl37_adv.an_duplex & QMOD_AN_HALF_DUPLEX_SET ) { 1765 PHYMOD_AN_CAP_HALF_DUPLEX_SET(an_ability_get_type) ; 1766 } else { 1767 PHYMOD_AN_CAP_HALF_DUPLEX_CLR(an_ability_get_type) ; 1768 } 1769 } 1770 if(value.cl37_adv.an_type & QMOD_AN_MODE_CL37BAM) { 1771 /* check cl37 bam ability */ 1772 if (value.cl37_adv.an_bam_speed & 1 << QMOD_CL37_BAM_2p5GBASE_X) 1773 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_ability_get_type->cl37bam_cap); 1774 } 1775 } 1776 return PHYMOD_E_NONE; 1777 } 1778 1779 int qtce_phy_autoneg_remote_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 1780 { 1781 1782 qmod_an_ability_t value; 1783 phymod_phy_access_t phy_copy; 1784 int lane_id, sub_port ; 1785 1786 PHYMOD_IF_ERR_RETURN 1787 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1788 1789 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1790 phy_copy.access.lane_mask = 0x1 << lane_id; 1791 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 1792 1793 PHYMOD_IF_ERR_RETURN 1794 (qmod_autoneg_remote_ability_get(&phy_copy.access, &value, sub_port)); 1795 1796 if (value.cl37_adv.an_pause == QMOD_ASYM_PAUSE) { 1797 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1798 } else if (value.cl37_adv.an_pause == QMOD_SYMM_PAUSE) { 1799 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1800 } else if (value.cl37_adv.an_pause == QMOD_ASYM_SYMM_PAUSE) { 1801 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1802 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1803 } 1804 if(value.cl37_adv.an_type != QMOD_AN_MODE_NONE) { 1805 if(value.cl37_adv.an_type & QMOD_AN_MODE_CL37) { 1806 PHYMOD_AN_CAP_CL37_SET(an_ability_get_type) ; 1807 PHYMOD_AN_CAP_HALF_DUPLEX_CLR(an_ability_get_type) ; 1808 } 1809 if(value.cl37_adv.an_type & QMOD_AN_MODE_SGMII) { 1810 PHYMOD_AN_CAP_SGMII_SET(an_ability_get_type) ; 1811 /* get the cl37 sgmii speed */ 1812 switch (value.cl37_adv.cl37_sgmii_speed) { 1813 case QMOD_CL37_SGMII_10M: 1814 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M; 1815 break; 1816 case QMOD_CL37_SGMII_100M: 1817 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M; 1818 break; 1819 case QMOD_CL37_SGMII_1000M: 1820 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M; 1821 break; 1822 default: 1823 break; 1824 } 1825 } 1826 /* check cl37 bam ability */ 1827 if (value.cl37_adv.an_bam_speed & 1 << QMOD_CL37_BAM_2p5GBASE_X) 1828 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_ability_get_type->cl37bam_cap); 1829 } 1830 return PHYMOD_E_NONE; 1831 } 1832 1833 STATIC 1834 int _qtc_qsgmii_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 1835 { 1836 int num_lane_adv_encoded; 1837 int start_lane, num_lane, lane_id, sub_port; 1838 phymod_phy_access_t phy_copy; 1839 qmod_an_control_t an_control; 1840 1841 1842 /* next program the tx fir taps and driver current based on the input */ 1843 PHYMOD_IF_ERR_RETURN 1844 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1845 1846 PHYMOD_IF_ERR_RETURN 1847 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1848 1849 start_lane = lane_id ; 1850 1851 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1852 phy_copy.access.lane_mask = 0x1 << start_lane; 1853 1854 num_lane_adv_encoded = 0; /* one lane */ 1855 an_control.pd_kx4_en = 0; /* for now disable */ 1856 an_control.pd_kx_en = 0; /* for now disable */ 1857 an_control.num_lane_adv = num_lane_adv_encoded; 1858 an_control.enable = an->enable; 1859 an_control.an_property_type = 0x0; /* for now disable */ 1860 1861 switch (an->an_mode) { 1862 case phymod_AN_MODE_CL37: 1863 an_control.an_type = QMOD_AN_MODE_CL37; 1864 break; 1865 case phymod_AN_MODE_CL37BAM: 1866 { 1867 1868 an_control.an_type = QMOD_AN_MODE_CL37BAM; 1869 /* PHYMOD_IF_ERR_RETURN 1870 (qmod_an_cl37_bam_abilities(&phy_copy.access, &value, sub_port)); */ 1871 break; 1872 } 1873 case phymod_AN_MODE_SGMII: 1874 an_control.an_type = QMOD_AN_MODE_SGMII; 1875 break; 1876 default: 1877 an_control.an_type = QMOD_AN_MODE_CL37; 1878 break; 1879 } 1880 1881 phy_copy.access.lane_mask = 0x1 << start_lane; 1882 1883 PHYMOD_IF_ERR_RETURN 1884 (qmod_autoneg_control(&phy_copy.access, &an_control, sub_port)); 1885 1886 return PHYMOD_E_NONE; 1887 1888 } 1889 1890 int qtce_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 1891 { 1892 int num_lane_adv_encoded; 1893 phymod_firmware_lane_config_t firmware_lane_config; 1894 phymod_firmware_core_config_t firmware_core_config_tmp; 1895 int start_lane, num_lane, i, lane_id, sub_port; 1896 phymod_phy_access_t phy_copy; 1897 qmod_an_control_t an_control; 1898 int ctrl_port ; 1899 1900 if (PHYMOD_ACC_F_QMODE_GET(&phy->access)) { 1901 return _qtc_qsgmii_autoneg_set(phy, an); 1902 } 1903 1904 /* next program the tx fir taps and driver current based on the input */ 1905 PHYMOD_IF_ERR_RETURN 1906 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1907 1908 PHYMOD_IF_ERR_RETURN 1909 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 1910 1911 start_lane = lane_id ; 1912 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1913 phy_copy.access.lane_mask = 0x1 << start_lane; 1914 1915 /* make sure the firmware config is set to an eenabled */ 1916 PHYMOD_IF_ERR_RETURN 1917 (qtce_phy_firmware_core_config_get(&phy_copy, &firmware_core_config_tmp)); 1918 1919 1920 switch (an->num_lane_adv) { 1921 case 1: 1922 num_lane_adv_encoded = 0; 1923 break; 1924 case 2: 1925 num_lane_adv_encoded = 1; 1926 break; 1927 case 4: 1928 num_lane_adv_encoded = 0; 1929 break; 1930 case 10: 1931 num_lane_adv_encoded = 3; 1932 break; 1933 default: 1934 return PHYMOD_E_PARAM; 1935 } 1936 1937 an_control.pd_kx4_en = 0; /* for now disable */ 1938 an_control.pd_kx_en = 0; /* for now disable */ 1939 an_control.num_lane_adv = num_lane_adv_encoded; 1940 an_control.enable = an->enable; 1941 an_control.an_property_type = 0x0; /* for now disable */ 1942 switch (an->an_mode) { 1943 case phymod_AN_MODE_CL37: 1944 an_control.an_type = QMOD_AN_MODE_CL37; 1945 break; 1946 case phymod_AN_MODE_CL37BAM: 1947 { 1948 1949 an_control.an_type = QMOD_AN_MODE_CL37BAM; 1950 /* PHYMOD_IF_ERR_RETURN 1951 (qmod_an_cl37_bam_abilities(&phy_copy.access, &value, sub_port)); */ 1952 break; 1953 } 1954 case phymod_AN_MODE_SGMII: 1955 an_control.an_type = QMOD_AN_MODE_SGMII; 1956 break; 1957 default: 1958 an_control.an_type = QMOD_AN_MODE_CL37; 1959 break; 1960 } 1961 1962 /* put pcs into reset */ 1963 PHYMOD_IF_ERR_RETURN 1964 (qmod_reset(&phy_copy.access)); 1965 1966 1967 for (i = 0; i < num_lane; i++) { 1968 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1969 PHYMOD_IF_ERR_RETURN 1970 (eagle_lane_soft_reset_release(&phy_copy.access, 0)); 1971 } 1972 1973 PHYMOD_USLEEP(500); 1974 1975 /* make sure the firmware config is set to an eenabled */ 1976 PHYMOD_IF_ERR_RETURN 1977 (qtce_phy_firmware_lane_config_get(phy, &firmware_lane_config)); 1978 if (an->enable) { 1979 firmware_lane_config.AnEnabled = 1; 1980 firmware_lane_config.LaneConfigFromPCS = 1; 1981 firmware_core_config_tmp.CoreConfigFromPCS = 1; 1982 } else { 1983 firmware_lane_config.AnEnabled = 0; 1984 firmware_lane_config.LaneConfigFromPCS = 0; 1985 firmware_core_config_tmp.CoreConfigFromPCS = 0; 1986 } 1987 1988 1989 for (i = 0; i < num_lane; i++) { 1990 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1991 PHYMOD_IF_ERR_RETURN 1992 (_qtce_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config)); 1993 } 1994 1995 /* Release core soft reset */ 1996 /* 1997 if ((an->num_lane_adv == 4) || (an->an_mode == phymod_AN_MODE_CL37BAM)) { 1998 phy_copy.access.lane_mask = 0x1 << start_lane; 1999 PHYMOD_IF_ERR_RETURN 2000 (eagle_core_soft_reset_release(&phy_copy.access, 1)); 2001 } 2002 */ 2003 2004 for (i = 0; i < num_lane; i++) { 2005 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2006 PHYMOD_IF_ERR_RETURN 2007 (eagle_lane_soft_reset_release(&phy_copy.access, 1)); 2008 } 2009 2010 2011 PHYMOD_USLEEP(1000); 2012 2013 PHYMOD_IF_ERR_RETURN 2014 (qmod_trigger_speed_change(&phy_copy.access)); 2015 2016 2017 phy_copy.access.lane_mask = 0x1 << start_lane; 2018 if (an->enable) { 2019 ctrl_port = 0 ; 2020 if((an->an_mode == phymod_AN_MODE_CL37BAM) || (an->num_lane_adv == 4 )) 2021 ctrl_port = 1 ; 2022 PHYMOD_IF_ERR_RETURN 2023 (qmod_set_an_port_mode(&phy_copy.access, num_lane_adv_encoded, start_lane, ctrl_port)); 2024 } else { 2025 ctrl_port =0 ; 2026 PHYMOD_IF_ERR_RETURN 2027 (qmod_set_an_port_mode(&phy_copy.access, num_lane_adv_encoded, start_lane, ctrl_port)); 2028 } 2029 PHYMOD_IF_ERR_RETURN 2030 (qmod_autoneg_control(&phy_copy.access, &an_control, sub_port)); 2031 2032 return PHYMOD_E_NONE; 2033 2034 } 2035 2036 int qtce_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done) 2037 { 2038 qmod_an_control_t an_control; 2039 phymod_phy_access_t phy_copy; 2040 int start_lane, num_lane, lane_id, sub_port; 2041 int an_complete = 0; 2042 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2043 2044 PHYMOD_IF_ERR_RETURN 2045 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2046 2047 PHYMOD_IF_ERR_RETURN 2048 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2049 2050 start_lane = lane_id ; 2051 phy_copy.access.lane_mask = 0x1 << start_lane; 2052 2053 PHYMOD_MEMSET(&an_control, 0x0, sizeof(qmod_an_control_t)); 2054 PHYMOD_IF_ERR_RETURN 2055 (qmod_autoneg_control_get(&phy_copy.access, sub_port, &an_control, &an_complete)); 2056 2057 if (an_control.enable) { 2058 an->enable = 1; 2059 *an_done = an_complete; 2060 } else { 2061 an->enable = 0; 2062 } 2063 2064 return PHYMOD_E_NONE; 2065 } 2066 2067 2068 int qtce_phy_autoneg_status_get(const phymod_phy_access_t* phy, phymod_autoneg_status_t* status) 2069 { 2070 /* Place your code here */ 2071 2072 2073 return PHYMOD_E_NONE; 2074 } 2075 2076 2077 int qtce_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 2078 { 2079 phymod_phy_access_t phy_access, phy_access_copy; 2080 phymod_core_access_t core_copy; 2081 phymod_firmware_core_config_t firmware_core_config_tmp; 2082 uint32_t uc_active = 0; 2083 #if 0 2084 qmod_an_init_t an; 2085 #endif 2086 QTCE_CORE_TO_PHY_ACCESS(&phy_access, core); 2087 phy_access_copy = phy_access; 2088 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 2089 core_copy.access.lane_mask = 0x1; 2090 phy_access_copy = phy_access; 2091 phy_access_copy.access = core->access; 2092 phy_access_copy.access.lane_mask = 0x1; 2093 phy_access_copy.type = core->type; 2094 2095 PHYMOD_IF_ERR_RETURN(eagle_uc_active_get(&core_copy.access, &uc_active)); 2096 if(uc_active) { 2097 return(PHYMOD_E_NONE); 2098 } 2099 2100 PHYMOD_IF_ERR_RETURN 2101 (qmod_pmd_reset_seq(&core_copy.access, core_status->pmd_active)); 2102 2103 /* need to set the heart beat default is for 156.25M */ 2104 if (init_config->interface.ref_clock == phymodRefClk125Mhz) { 2105 PHYMOD_IF_ERR_RETURN 2106 (qmod_refclk_set(&core_copy.access, QMODREFCLK125MHZ)) ; 2107 } else { 2108 PHYMOD_IF_ERR_RETURN 2109 (qmod_refclk_set(&core_copy.access, QMODREFCLK156MHZ)) ; 2110 } 2111 2112 if (_qtce_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader)) { 2113 PHYMOD_DEBUG_ERROR(("devad 0x%x lane 0x%x: UC firmware-load failed\n", core->access.addr, core->access.lane_mask)); 2114 PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT); 2115 } 2116 #ifndef QTCE_PMD_CRC_UCODE 2117 /* next we need to check if the load is correct or not */ 2118 if (eagle_tsc_ucode_load_verify(&core_copy.access, (uint8_t *) &qtce_ucode, qtce_ucode_len)) { 2119 PHYMOD_DEBUG_ERROR(("devad 0x%x lane 0x%x: UC load-verify failed\n", core->access.addr, core->access.lane_mask)); 2120 PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT); 2121 } 2122 #endif /* QTCE_PMD_CRC_UCODE */ 2123 2124 PHYMOD_IF_ERR_RETURN 2125 (eagle_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x1)); 2126 2127 /* next we need to set the uc active and release uc */ 2128 PHYMOD_IF_ERR_RETURN 2129 (eagle_uc_active_set(&core_copy.access ,1)); 2130 /* release the uc reset */ 2131 PHYMOD_IF_ERR_RETURN 2132 (eagle_uc_reset(&core_copy.access ,1)); 2133 /* we need to wait at least 10ms for the uc to settle */ 2134 PHYMOD_USLEEP(10000); 2135 2136 if(PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 2137 #ifndef QTCE_PMD_CRC_UCODE 2138 /* poll the ready bit in 10 ms */ 2139 eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1(&phy_access_copy.access, 1); 2140 #else 2141 PHYMOD_IF_ERR_RETURN( 2142 eagle_tsc_ucode_crc_verify( &core_copy.access, qtce_ucode_len,qtce_ucode_crc)); 2143 #endif /* QTCE_PMD_CRC_UCODE */ 2144 } 2145 2146 PHYMOD_IF_ERR_RETURN( 2147 eagle_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0)); 2148 2149 PHYMOD_IF_ERR_RETURN 2150 (eagle_core_soft_reset_release(&core_copy.access, 0)); 2151 2152 /* plldiv CONFIG */ 2153 if (PHYMOD_ACC_F_QMODE_GET(&core->access)) { 2154 PHYMOD_IF_ERR_RETURN 2155 (eagle_pll_mode_set(&core->access, 0x9)); 2156 } else { 2157 PHYMOD_IF_ERR_RETURN 2158 (eagle_pll_mode_set(&core->access, 0xa)); 2159 } 2160 2161 PHYMOD_IF_ERR_RETURN 2162 (qtce_core_lane_map_set(core, &init_config->lane_map)); 2163 PHYMOD_IF_ERR_RETURN 2164 (_qtce_core_lane_override_set(core)); 2165 PHYMOD_IF_ERR_RETURN 2166 (qmod_autoneg_timer_init(&core->access)); 2167 PHYMOD_IF_ERR_RETURN 2168 (qmod_master_port_num_set(&core->access, 0)); 2169 /* don't overide the fw that set in config set if not specified */ 2170 firmware_core_config_tmp = init_config->firmware_core_config; 2171 firmware_core_config_tmp.CoreConfigFromPCS = 0; 2172 /* set the vco rate to be default at 10.0000G */ 2173 if (PHYMOD_ACC_F_QMODE_GET(&core->access)) { 2174 firmware_core_config_tmp.VcoRate = 0x12; 2175 } else { 2176 firmware_core_config_tmp.VcoRate = 0x3; 2177 } 2178 2179 PHYMOD_IF_ERR_RETURN 2180 (qtce_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config_tmp)); 2181 2182 /* release core soft reset */ 2183 PHYMOD_IF_ERR_RETURN 2184 (eagle_core_soft_reset_release(&core_copy.access, 1)); 2185 2186 return PHYMOD_E_NONE; 2187 } 2188 2189 2190 int qtce_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config) 2191 { 2192 int pll_restart = 0; 2193 const phymod_access_t *pm_acc = &phy->access; 2194 phymod_phy_access_t pm_phy_copy; 2195 int start_lane, num_lane, i, lane_id, sub_port; 2196 phymod_polarity_t tmp_pol; 2197 uint32_t sc_enable = 0; 2198 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 2199 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2200 2201 /* next program the tx fir taps and driver current based on the input */ 2202 PHYMOD_IF_ERR_RETURN 2203 (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane)); 2204 PHYMOD_IF_ERR_RETURN 2205 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2206 2207 start_lane = lane_id ; 2208 pm_phy_copy.access.lane_mask = 1 << start_lane; 2209 2210 if (PHYMOD_ACC_F_QMODE_GET(&phy->access)) { 2211 PHYMOD_IF_ERR_RETURN(qmod_port_state_set(&pm_phy_copy.access, QMOD_PORT_STATE_CONFIGED, sub_port, 1)); 2212 2213 PHYMOD_IF_ERR_RETURN(qmod_speedchange_get(&pm_phy_copy.access, &sc_enable)) ; 2214 if (sc_enable) { 2215 return PHYMOD_E_NONE; 2216 } 2217 } 2218 2219 /* per lane based reset release */ 2220 PHYMOD_IF_ERR_RETURN 2221 (qmod_pmd_x4_reset(&pm_phy_copy.access)); 2222 2223 /* poll for per lane uc_dsc_ready */ 2224 for (i = 0; i < num_lane; i++) { 2225 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 2226 PHYMOD_IF_ERR_RETURN 2227 (eagle_lane_soft_reset_release(&pm_phy_copy.access, 1)); 2228 } 2229 2230 /* program the rx/tx polarity */ 2231 tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) & 0x1; 2232 tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) & 0x1; 2233 PHYMOD_IF_ERR_RETURN 2234 (qtce_phy_polarity_set(phy, &tmp_pol)); 2235 2236 for (i = 0; i < num_lane; i++) { 2237 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 2238 PHYMOD_IF_ERR_RETURN 2239 (_qtce_phy_tx_set(&pm_phy_copy, &init_config->tx[i])); 2240 } 2241 2242 pm_phy_copy.access.lane_mask = 0x1; 2243 2244 PHYMOD_IF_ERR_RETURN 2245 (qmod_update_port_mode(&pm_phy_copy.access, &pll_restart)); 2246 2247 pm_phy_copy.access.lane_mask = 1 << start_lane; 2248 PHYMOD_IF_ERR_RETURN 2249 (qmod_rx_lane_control_set(&pm_phy_copy.access, 1)); 2250 PHYMOD_IF_ERR_RETURN 2251 (qmod_tx_lane_control_set(&pm_phy_copy.access, QMOD_TX_LANE_RESET_TRAFFIC_ENABLE)); /* TX_LANE_CONTROL */ 2252 2253 return PHYMOD_E_NONE; 2254 } 2255 2256 2257 int qtce_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable) 2258 { 2259 int start_lane, num_lane, lane_id, sub_port; 2260 int rv = PHYMOD_E_NONE; 2261 int i = 0; 2262 phymod_phy_access_t phy_copy; 2263 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2264 2265 /* next figure out the lane num and start_lane based on the input */ 2266 PHYMOD_IF_ERR_RETURN 2267 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2268 2269 PHYMOD_IF_ERR_RETURN 2270 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2271 start_lane = lane_id ; 2272 2273 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2274 2275 2276 switch (loopback) { 2277 case phymodLoopbackGlobal : 2278 PHYMOD_IF_ERR_RETURN(qmod_tx_loopback_control(&phy_copy.access, enable, start_lane, num_lane)); 2279 break; 2280 case phymodLoopbackGlobalPMD : 2281 for (i = 0; i < num_lane; i++) { 2282 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2283 PHYMOD_IF_ERR_RETURN(qmod_tx_squelch_set(&phy_copy.access, enable)); 2284 PHYMOD_IF_ERR_RETURN(eagle_tsc_dig_lpbk(&phy_copy.access, (uint8_t) enable)); 2285 PHYMOD_IF_ERR_RETURN(eagle_pmd_force_signal_detect(&phy_copy.access, (int) enable)); 2286 PHYMOD_IF_ERR_RETURN(qmod_rx_lane_control_set(&phy_copy.access, 1)); 2287 } 2288 break; 2289 case phymodLoopbackRemotePMD : 2290 PHYMOD_IF_ERR_RETURN(eagle_tsc_rmt_lpbk(&phy_copy.access, (uint8_t)enable)); 2291 break; 2292 case phymodLoopbackRemotePCS : 2293 PHYMOD_IF_ERR_RETURN(qmod_rx_loopback_control(&phy_copy.access, enable, enable, enable)); /* RAVI */ 2294 break; 2295 default : 2296 break; 2297 } 2298 return rv; 2299 } 2300 2301 int qtce_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable) 2302 { 2303 uint32_t enable_core; 2304 int start_lane, num_lane, lane_id, sub_port; 2305 phymod_phy_access_t phy_copy; 2306 2307 *enable = 0; 2308 2309 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2310 /* next figure out the lane num and start_lane based on the input */ 2311 PHYMOD_IF_ERR_RETURN 2312 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2313 2314 PHYMOD_IF_ERR_RETURN 2315 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2316 start_lane = lane_id ; 2317 2318 phy_copy.access.lane_mask = 0x1 << start_lane; 2319 2320 2321 switch (loopback) { 2322 case phymodLoopbackGlobal : 2323 PHYMOD_IF_ERR_RETURN(qmod_tx_loopback_get(&phy_copy.access, &enable_core)); 2324 *enable = (enable_core >> start_lane) & 0x1; 2325 break; 2326 case phymodLoopbackGlobalPMD : 2327 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&phy_copy.access, enable)); 2328 break; 2329 case phymodLoopbackRemotePMD : 2330 /* PHYMOD_IF_ERR_RETURN(eagle_tsc_rmt_lpbk(&phy->access, (uint8_t)enable)); */ 2331 break; 2332 case phymodLoopbackRemotePCS : 2333 /* PHYMOD_IF_ERR_RETURN(qtce_rx_loopback_control(&phy->access, enable, enable, enable)); */ /* RAVI */ 2334 break; 2335 default : 2336 break; 2337 } 2338 return PHYMOD_E_NONE; 2339 } 2340 2341 2342 int qtce_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_seq_done){ 2343 int lane_id, sub_port; 2344 phymod_phy_access_t phy_copy; 2345 2346 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2347 PHYMOD_IF_ERR_RETURN 2348 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2349 phy_copy.access.lane_mask = 1 << lane_id; 2350 2351 PHYMOD_IF_ERR_RETURN(qmod_pmd_lock_get(&phy_copy.access, rx_seq_done)); 2352 return PHYMOD_E_NONE; 2353 } 2354 2355 2356 int qtce_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status) 2357 { 2358 int lane_id, sub_port; 2359 phymod_phy_access_t pm_phy_copy; 2360 2361 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2362 PHYMOD_IF_ERR_RETURN 2363 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2364 pm_phy_copy.access.lane_mask = 1 << lane_id; 2365 2366 PHYMOD_IF_ERR_RETURN(qmod_get_pcs_link_status(&pm_phy_copy.access, sub_port, link_status)); 2367 return PHYMOD_E_NONE; 2368 } 2369 2370 2371 int qtce_phy_pcs_userspeed_set(const phymod_phy_access_t* phy, const phymod_pcs_userspeed_config_t* config) 2372 { 2373 return PHYMOD_E_UNAVAIL; 2374 } 2375 2376 int qtce_phy_pcs_userspeed_get(const phymod_phy_access_t* phy, const phymod_pcs_userspeed_config_t* config) 2377 { 2378 return PHYMOD_E_UNAVAIL; 2379 } 2380 2381 2382 int qtce_phy_status_dump(const phymod_phy_access_t* phy) 2383 { 2384 int lane_id, sub_port; 2385 phymod_phy_access_t phy_copy; 2386 2387 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2388 PHYMOD_IF_ERR_RETURN 2389 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2390 phy_copy.access.lane_mask = 1 << lane_id; 2391 2392 PHYMOD_IF_ERR_RETURN 2393 (eagle_tsc_display_core_state(&phy_copy.access)); 2394 PHYMOD_IF_ERR_RETURN 2395 (eagle_tsc_display_lane_debug_status(&phy_copy.access)); 2396 2397 return PHYMOD_E_NONE; 2398 } 2399 2400 int qtce_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t *val) 2401 { 2402 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_read(&phy->access, reg_addr, val)); 2403 return PHYMOD_E_NONE; 2404 } 2405 2406 2407 int qtce_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val) 2408 { 2409 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_write(&phy->access, reg_addr, val)); 2410 return PHYMOD_E_NONE; 2411 } 2412 2413 int qtce_phy_eee_set(const phymod_phy_access_t* phy, uint32_t enable) 2414 { 2415 uint32_t lpi_bypass; 2416 lpi_bypass = PHYMOD_LPI_BYPASS_GET(enable); 2417 enable &= 0x1; 2418 if (lpi_bypass) { 2419 PHYMOD_IF_ERR_RETURN(qmod_eee_control_set(&phy->access, enable)); 2420 } else { 2421 return PHYMOD_E_UNAVAIL; 2422 } 2423 return PHYMOD_E_NONE; 2424 } 2425 2426 int qtce_phy_eee_get(const phymod_phy_access_t* phy, uint32_t* enable) 2427 { 2428 if (PHYMOD_LPI_BYPASS_GET(*enable)) { 2429 PHYMOD_IF_ERR_RETURN(qmod_eee_control_get(&phy->access, enable)); 2430 PHYMOD_LPI_BYPASS_SET(*enable); 2431 } else { 2432 return PHYMOD_E_UNAVAIL; 2433 } 2434 return PHYMOD_E_NONE; 2435 } 2436 2437 int qtce_phy_rx_ppm_get(const phymod_phy_access_t* phy, int16_t* rx_ppm) 2438 { 2439 int start_lane, num_lane; 2440 phymod_phy_access_t pm_phy_copy; 2441 2442 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2443 2444 PHYMOD_IF_ERR_RETURN 2445 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2446 2447 pm_phy_copy.access.lane_mask = 1 << start_lane; 2448 PHYMOD_IF_ERR_RETURN 2449 (eagle_tsc_rx_ppm(&pm_phy_copy.access, rx_ppm)); 2450 2451 return PHYMOD_E_NONE; 2452 } 2453 2454 int qtce_phy_synce_clk_ctrl_set(const phymod_phy_access_t* phy, 2455 phymod_synce_clk_ctrl_t cfg) 2456 { 2457 int lane_id, sub_port; 2458 phymod_phy_access_t phy_copy; 2459 2460 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2461 PHYMOD_IF_ERR_RETURN 2462 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2463 phy_copy.access.lane_mask = 1 << lane_id; 2464 2465 PHYMOD_IF_ERR_RETURN 2466 (qmod_synce_mode_set(&phy_copy.access, cfg.stg0_mode, cfg.stg1_mode)); 2467 2468 PHYMOD_IF_ERR_RETURN 2469 (qmod_synce_clk_ctrl_set(&phy_copy.access, cfg.sdm_val)); 2470 2471 return PHYMOD_E_NONE; 2472 } 2473 2474 int qtce_phy_synce_clk_ctrl_get(const phymod_phy_access_t* phy, 2475 phymod_synce_clk_ctrl_t *cfg) 2476 { 2477 int lane_id, sub_port; 2478 phymod_phy_access_t phy_copy; 2479 2480 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2481 PHYMOD_IF_ERR_RETURN 2482 (qmod_lane_info(&phy->access, &lane_id, &sub_port)); 2483 phy_copy.access.lane_mask = 1 << lane_id; 2484 2485 PHYMOD_IF_ERR_RETURN 2486 (qmod_synce_mode_get(&phy_copy.access, &(cfg->stg0_mode), &(cfg->stg1_mode))); 2487 2488 PHYMOD_IF_ERR_RETURN 2489 (qmod_synce_clk_ctrl_get(&phy_copy.access, &(cfg->sdm_val))); 2490 2491 return PHYMOD_E_NONE; 2492 } 2493 2494 #endif /* PHYMOD_QTCE_SUPPORT */