tscf16.c (154101B)
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 #ifndef _DV_TB_ 11 #define _SDK_TEFMOD16_ 1 12 #endif 13 14 #include <phymod/phymod.h> 15 #include <phymod/phymod_system.h> 16 #include <phymod/phymod_util.h> 17 #include <phymod/chip/bcmi_tscf_16nm_xgxs_defs.h> 18 #include <phymod/chip/falcon16.h> 19 #include <phymod/chip/tscf16.h> 20 #include "../../tscf16/tier1/tefmod16.h" 21 #include "../../tscf16/tier1/tefmod16_enum_defines.h" 22 #include "../../tscf16/tier1/tefmod16_device.h" 23 #include "../../tscf16/tier1/tefmod16_sc_lkup_table.h" 24 #include "../../tscf16/tier1/tf16PCSRegEnums.h" 25 #include "../../falcon16/tier1/src/falcon16_cfg_seq.h" 26 #include "../../falcon16/tier1/include/falcon16_tsc_common.h" 27 #include "../../falcon16/tier1/include/falcon16_tsc_interface.h" 28 #include "../../falcon16/tier1/include/falcon16_tsc_internal.h" 29 #include "../../falcon16/tier1/include/falcon16_tsc_dependencies.h" 30 #include "../../falcon16/tier1/include/falcon16_tsc_types.h" 31 #include "../../falcon16/tier1/include/falcon16_tsc_config.h" 32 #include "../../falcon16/tier1/include/common/srds_api_enum.h" 33 #include "../../falcon16/tier1/include/falcon16_tsc_debug_functions.h" 34 35 #define TSCF16_ID0 0x600d 36 #define TSCF16_ID1 0x8770 37 #define TSC4F_GEN2_MODEL 0x15 38 #define TSCF16_TECH_PROC 0x4 39 #define FALCON16_MODEL 0x1b 40 #define TSCF16_NOF_LANES_IN_CORE 4 41 #define TSCF16_LANE_SWAP_LANE_MASK 3 42 #define TSCF16_NOF_DFES 6 43 #define TSCF16_PHY_ALL_LANES 0xf 44 45 #define TSCF16_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \ 46 do{\ 47 PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\ 48 (_phy_access)->type = (_core_access)->type; \ 49 (_phy_access)->port_loc = (_core_access)->port_loc; \ 50 (_phy_access)->device_op_mode = (_core_access)->device_op_mode; \ 51 (_phy_access)->access.lane_mask = TSCF16_PHY_ALL_LANES; \ 52 }while(0) 53 54 55 #define TSCF16_MAX_FIRMWARES (5) 56 57 #define TSCF16_PMD_CRC_UCODE_VERIFY 1 58 59 #define DEFAULT_OSR2P5_SET 1 60 61 /* uController's firmware */ 62 extern unsigned char falcon16_ucode[]; 63 extern unsigned short falcon16_ucode_ver; 64 extern unsigned short falcon16_ucode_crc; 65 extern unsigned short falcon16_ucode_len; 66 67 STATIC 68 int _tscf16_pll_multiplier_get(uint32_t pll_div, uint32_t *pll_multiplier) 69 { 70 switch (pll_div) { 71 case FALCON16_TSC_PLL_DIV_80: 72 *pll_multiplier = 80; 73 break; 74 case FALCON16_TSC_PLL_DIV_96: 75 *pll_multiplier = 96; 76 break; 77 case FALCON16_TSC_PLL_DIV_100: 78 *pll_multiplier = 100; 79 break; 80 case FALCON16_TSC_PLL_DIV_128: 81 *pll_multiplier = 128; 82 break; 83 case FALCON16_TSC_PLL_DIV_132: 84 *pll_multiplier = 132; 85 break; 86 case FALCON16_TSC_PLL_DIV_140: 87 *pll_multiplier = 140; 88 break; 89 case FALCON16_TSC_PLL_DIV_160: 90 *pll_multiplier = 160; 91 break; 92 case FALCON16_TSC_PLL_DIV_165: 93 *pll_multiplier = 165; 94 break; 95 case FALCON16_TSC_PLL_DIV_168: 96 *pll_multiplier = 168; 97 break; 98 case FALCON16_TSC_PLL_DIV_170: 99 *pll_multiplier = 170; 100 break; 101 case FALCON16_TSC_PLL_DIV_175: 102 *pll_multiplier = 175; 103 break; 104 case FALCON16_TSC_PLL_DIV_180: 105 *pll_multiplier = 180; 106 break; 107 case FALCON16_TSC_PLL_DIV_184: 108 *pll_multiplier = 184; 109 break; 110 case FALCON16_TSC_PLL_DIV_200: 111 *pll_multiplier = 200; 112 break; 113 case FALCON16_TSC_PLL_DIV_224: 114 *pll_multiplier = 224; 115 break; 116 case FALCON16_TSC_PLL_DIV_264: 117 *pll_multiplier = 264; 118 break; 119 case FALCON16_TSC_PLL_DIV_120: 120 *pll_multiplier = 120; 121 break; 122 case FALCON16_TSC_PLL_DIV_144: 123 *pll_multiplier = 144; 124 break; 125 case FALCON16_TSC_PLL_DIV_198: 126 *pll_multiplier = 198; 127 break; 128 default: 129 *pll_multiplier = 165; 130 break; 131 } 132 133 return PHYMOD_E_NONE; 134 } 135 136 STATIC 137 int _tscf16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 138 { 139 struct falcon16_tsc_uc_lane_config_st serdes_firmware_config; 140 phymod_phy_access_t phy_copy; 141 int start_lane, num_lane, i; 142 uint32_t rst_status; 143 uint32_t is_warm_boot; 144 145 PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config)); 146 PHYMOD_IF_ERR_RETURN 147 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 148 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 149 150 for (i = 0; i < num_lane; i++) { 151 phy_copy.access.lane_mask = 1 << (start_lane + i); 152 serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS; 153 serdes_firmware_config.field.an_enabled = fw_config.AnEnabled; 154 serdes_firmware_config.field.dfe_on = fw_config.DfeOn; 155 serdes_firmware_config.field.force_brdfe_on = fw_config.ForceBrDfe; 156 serdes_firmware_config.field.scrambling_dis = fw_config.ScramblingDisable; 157 serdes_firmware_config.field.unreliable_los = fw_config.UnreliableLos; 158 serdes_firmware_config.field.media_type = fw_config.MediaType; 159 serdes_firmware_config.field.dfe_lp_mode = fw_config.LpDfeOn; 160 serdes_firmware_config.field.cl72_auto_polarity_en = fw_config.Cl72AutoPolEn; 161 serdes_firmware_config.field.cl72_restart_timeout_en = fw_config.Cl72RestTO; 162 163 PHYMOD_IF_ERR_RETURN(PHYMOD_IS_WRITE_DISABLED(&phy_copy.access, &is_warm_boot)); 164 165 if (!is_warm_boot) { 166 PHYMOD_IF_ERR_RETURN(falcon16_lane_soft_reset_read(&phy_copy.access, &rst_status)); 167 if (rst_status) PHYMOD_IF_ERR_RETURN (falcon16_lane_soft_reset_release(&phy_copy.access, 0)); 168 PHYMOD_IF_ERR_RETURN(falcon16_tsc_set_uc_lane_cfg(&phy_copy.access, serdes_firmware_config)); 169 if (rst_status) PHYMOD_IF_ERR_RETURN (falcon16_lane_soft_reset_release(&phy_copy.access, 1)); 170 } 171 } 172 return PHYMOD_E_NONE; 173 } 174 175 /* 176 * Identify PHYID2 and PHYID3 Read From register 0x2 and 0x3 177 * param core core access information 178 * param core_id predetermined core id 179 * param is_identified if identification IDS match 180 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 181 */ 182 int tscf16_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified) 183 { 184 int ioerr = 0; 185 const phymod_access_t *pm_acc = &core->access; 186 PHYID2r_t id2; 187 PHYID3r_t id3; 188 MAIN0_SERDESIDr_t serdesid; 189 /* DIG_REVID0r_t revid; */ 190 uint32_t model; 191 192 *is_identified = 0; 193 194 if (core_id == 0){ 195 ioerr += READ_PHYID2r(pm_acc, &id2); 196 ioerr += READ_PHYID3r(pm_acc, &id3); 197 } 198 else{ 199 PHYID2r_SET(id2, ((core_id >> 16) & 0xffff)); 200 PHYID3r_SET(id3, core_id & 0xffff); 201 } 202 203 if (PHYID2r_REGID1f_GET(id2) == TSCF16_ID0 && 204 (PHYID3r_REGID2f_GET(id3) == TSCF16_ID1)) { 205 /* PHY IDs match - now check PCS model */ 206 ioerr += READ_MAIN0_SERDESIDr(pm_acc, &serdesid); 207 model = MAIN0_SERDESIDr_MODEL_NUMBERf_GET(serdesid); 208 if (model == TSC4F_GEN2_MODEL) { 209 if (MAIN0_SERDESIDr_TECH_PROCf_GET(serdesid) == TSCF16_TECH_PROC) { 210 *is_identified = 1; 211 } 212 } 213 } 214 215 return ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE; 216 } 217 218 /* 219 * Retrive core information 220 * param core core access information 221 * param info core information (core_version,serdes_id,PHYID2,PHYID3) 222 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 223 */ 224 int tscf16_core_info_get(const phymod_core_access_t* core, phymod_core_info_t* info) 225 { 226 uint32_t serdes_id; 227 char core_name[15] = "Tscf16"; 228 PHYID2r_t id2; 229 PHYID3r_t id3; 230 const phymod_access_t *pm_acc = &core->access; 231 232 PHYMOD_IF_ERR_RETURN 233 (tefmod16_revid_read(&core->access, &serdes_id)); 234 PHYMOD_IF_ERR_RETURN 235 (phymod_core_name_get(core, serdes_id, core_name, info)); 236 info->serdes_id = serdes_id; 237 info->core_version = phymodCoreVersionTscf16; 238 239 PHYMOD_IF_ERR_RETURN(READ_PHYID2r(pm_acc, &id2)); 240 PHYMOD_IF_ERR_RETURN(READ_PHYID3r(pm_acc, &id3)); 241 242 info->phy_id0 = (uint16_t) id2.v[0]; 243 info->phy_id1 = (uint16_t) id3.v[0]; 244 245 return PHYMOD_E_NONE; 246 } 247 248 /* 249 * set lane swapping for core 250 * The pcs tx/rx swap - logical to physical mapping 251 * The pmd tx/rx addr - logical address associated with the PMD lane with physcal index at the PCS interface 252 * 253 * lane_map_tx and lane_map_rx[lane=logic_lane] are logic-lane base. 254 */ 255 256 int tscf16_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map) 257 { 258 uint32_t lane, pcs_tx_swap = 0, pcs_rx_swap = 0; 259 uint8_t pmd_tx_addr[4], pmd_rx_addr[4]; 260 uint32_t uc_enable = 0; 261 phymod_phy_access_t phy_access; 262 263 if (lane_map->num_of_lanes != TSCF16_NOF_LANES_IN_CORE){ 264 return PHYMOD_E_CONFIG; 265 } 266 267 TSCF16_CORE_TO_PHY_ACCESS(&phy_access, core); 268 PHYMOD_IF_ERR_RETURN 269 (falcon16_uc_active_get(&phy_access.access, &uc_enable)); 270 271 for (lane = 0; lane < TSCF16_NOF_LANES_IN_CORE; lane++){ 272 if ((lane_map->lane_map_tx[lane] >= TSCF16_NOF_LANES_IN_CORE)|| 273 (lane_map->lane_map_rx[lane] >= TSCF16_NOF_LANES_IN_CORE)){ 274 return PHYMOD_E_CONFIG; 275 } 276 /*encode each lane as four bits*/ 277 pcs_tx_swap += lane_map->lane_map_tx[lane]<<(lane*4); 278 pcs_rx_swap += lane_map->lane_map_rx[lane]<<(lane*4); 279 } 280 /* PMD lane addr is based on PCS logical to physical mapping*/ 281 for (lane = 0; lane < TSCF16_NOF_LANES_IN_CORE; lane++){ 282 pmd_tx_addr[((pcs_tx_swap >> (lane*4)) & 0xf)] = lane; 283 pmd_rx_addr[((pcs_rx_swap >> (lane*4)) & 0xf)] = lane; 284 } 285 286 PHYMOD_IF_ERR_RETURN 287 (tefmod16_pcs_tx_lane_swap(&core->access, pcs_tx_swap)); 288 PHYMOD_IF_ERR_RETURN 289 (tefmod16_pcs_rx_lane_swap(&core->access, pcs_rx_swap)); 290 291 /* If re-program lane swap while micro is running, it needs to put micro in reset state first */ 292 if (uc_enable){ 293 PHYMOD_IF_ERR_RETURN 294 (falcon16_tsc_core_dp_reset(&phy_access.access, 1)); 295 PHYMOD_IF_ERR_RETURN 296 (falcon16_tsc_uc_reset(&phy_access.access,1)); 297 } 298 PHYMOD_IF_ERR_RETURN 299 (falcon16_tsc_map_lanes(&core->access, TSCF16_NOF_LANES_IN_CORE, pmd_tx_addr, pmd_rx_addr)); 300 if (uc_enable){ 301 PHYMOD_IF_ERR_RETURN 302 (falcon16_tsc_uc_reset(&phy_access.access,0)); 303 PHYMOD_IF_ERR_RETURN 304 (falcon16_tsc_core_dp_reset(&phy_access.access,0)); 305 } 306 307 return PHYMOD_E_NONE; 308 } 309 310 /* 311 * Get lane map information 312 * param core core access information 313 * param lane_map (num_of_lanes, lane_map_rx, lane_map_tx) 314 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 315 */ 316 int tscf16_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map) 317 { 318 uint32_t pcs_tx_swap = 0 , pcs_rx_swap = 0, lane; 319 320 PHYMOD_IF_ERR_RETURN(tefmod16_pcs_tx_lane_swap_get(&core->access, &pcs_tx_swap)); 321 PHYMOD_IF_ERR_RETURN(tefmod16_pcs_rx_lane_swap_get(&core->access, &pcs_rx_swap)); 322 323 for (lane = 0; lane < TSCF16_NOF_LANES_IN_CORE ; lane++){ 324 /*decode each lane from four bits*/ 325 lane_map->lane_map_tx[lane] = (pcs_tx_swap>>(lane*4)) & TSCF16_LANE_SWAP_LANE_MASK; 326 lane_map->lane_map_rx[lane] = (pcs_rx_swap>>(lane*4)) & TSCF16_LANE_SWAP_LANE_MASK; 327 } 328 lane_map->num_of_lanes = TSCF16_NOF_LANES_IN_CORE; 329 330 return PHYMOD_E_NONE; 331 } 332 333 334 int tscf16_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 335 { 336 337 return PHYMOD_E_UNAVAIL; 338 339 } 340 341 int tscf16_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction) 342 { 343 344 return PHYMOD_E_UNAVAIL; 345 346 } 347 348 349 int tscf16_core_firmware_info_get(const phymod_core_access_t* core, phymod_core_firmware_info_t* fw_info) 350 { 351 352 return PHYMOD_E_NONE; 353 354 } 355 356 357 /* 358 * Tscf16 firmware load 359 * param core core access information 360 * param load_method firmware load method: external fw load is valid 361 * fw_loader firmware loader 362 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 363 */ 364 365 STATIC 366 int _tscf16_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader) 367 { 368 switch(load_method){ 369 case phymodFirmwareLoadMethodInternal: 370 PHYMOD_IF_ERR_RETURN(falcon16_tsc_ucode_mdio_load(&core->access, falcon16_ucode, falcon16_ucode_len)); 371 break; 372 case phymodFirmwareLoadMethodExternal: 373 PHYMOD_NULL_CHECK(fw_loader); 374 PHYMOD_IF_ERR_RETURN(falcon16_tsc_ucode_init(&core->access)); 375 PHYMOD_IF_ERR_RETURN 376 (falcon16_pram_firmware_enable(&core->access, 1, 0)); 377 PHYMOD_IF_ERR_RETURN(fw_loader(core, falcon16_ucode_len, falcon16_ucode)); 378 PHYMOD_IF_ERR_RETURN 379 (falcon16_pram_firmware_enable(&core->access, 0, 0)); 380 break; 381 case phymodFirmwareLoadMethodNone: 382 break; 383 default: 384 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method)); 385 } 386 if (load_method != phymodFirmwareLoadMethodNone){ 387 /* PHYMOD_IF_ERR_RETURN(tscf_core_firmware_info_get(core, &actual_fw)); 388 if ((falcon16_ucode_crc != actual_fw.fw_crc) || (falcon16_ucode_ver != actual_fw.fw_version)){ 389 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("fw load validation was failed"))); 390 } */ 391 } 392 393 return PHYMOD_E_NONE; 394 395 } 396 397 /* 398 * Set firmware configure 399 * param phy phy access information 400 * param fw_core_config firmare core config 401 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 402 */ 403 int tscf16_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_core_config) 404 { 405 struct falcon16_tsc_uc_core_config_st serdes_firmware_core_config; 406 uint32_t rst_status; 407 408 PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(serdes_firmware_core_config)); 409 serdes_firmware_core_config.field.core_cfg_from_pcs = fw_core_config.CoreConfigFromPCS; 410 serdes_firmware_core_config.field.vco_rate = fw_core_config.VcoRate; 411 serdes_firmware_core_config.field.osr_2p5_available = fw_core_config.osr_2p5_available; 412 413 PHYMOD_IF_ERR_RETURN(falcon16_core_soft_reset_read(&phy->access, &rst_status)); 414 if (rst_status) PHYMOD_IF_ERR_RETURN (falcon16_tsc_core_dp_reset(&phy->access, 1)); 415 PHYMOD_IF_ERR_RETURN(falcon16_tsc_INTERNAL_set_uc_core_config(&phy->access, serdes_firmware_core_config)); 416 if (rst_status) PHYMOD_IF_ERR_RETURN (falcon16_tsc_core_dp_reset(&phy->access, 0)); 417 418 return PHYMOD_E_NONE; 419 } 420 421 /* 422 * Get firmware configure 423 * param phy phy access information 424 * param fw_core_config firmare core config 425 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 426 */ 427 int tscf16_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_core_config) 428 { 429 struct falcon16_tsc_uc_core_config_st serdes_firmware_core_config; 430 431 PHYMOD_IF_ERR_RETURN(falcon16_tsc_get_uc_core_config(&phy->access, &serdes_firmware_core_config)); 432 PHYMOD_MEMSET(fw_core_config, 0, sizeof(*fw_core_config)); 433 fw_core_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs; 434 fw_core_config->VcoRate = serdes_firmware_core_config.field.vco_rate; 435 fw_core_config->osr_2p5_available = serdes_firmware_core_config.field.osr_2p5_available; 436 437 return PHYMOD_E_NONE; 438 } 439 440 /* 441 * Set firmware lane configure 442 * param phy phy access information 443 * param fw_lane_config firmare lane config 444 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 445 */ 446 447 int tscf16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_lane_config) 448 { 449 phymod_phy_access_t phy_copy; 450 int start_lane, num_lane, i; 451 452 PHYMOD_IF_ERR_RETURN 453 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 454 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 455 456 /*Hold the per lne soft reset bit*/ 457 for (i = 0; i < num_lane; i++) { 458 phy_copy.access.lane_mask = 1 << (start_lane + i); 459 PHYMOD_IF_ERR_RETURN 460 (falcon16_lane_soft_reset_release(&phy_copy.access, 0)); 461 } 462 463 PHYMOD_IF_ERR_RETURN 464 (_tscf16_phy_firmware_lane_config_set(phy, fw_lane_config)); 465 /*Hold the per lane soft reset bit*/ 466 for (i = 0; i < num_lane; i++) { 467 phy_copy.access.lane_mask = 1 << (start_lane + i); 468 PHYMOD_IF_ERR_RETURN 469 (falcon16_lane_soft_reset_release(&phy_copy.access, 1)); 470 } 471 472 /* next we need to toggle the pcs data path reset */ 473 PHYMOD_IF_ERR_RETURN 474 (tefmod16_trigger_speed_change(&phy->access)); 475 476 return PHYMOD_E_NONE; 477 } 478 479 /* 480 * Get firmware lane configure 481 * param phy phy access information 482 * param fw_lane_config firmare lane config 483 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 484 */ 485 int tscf16_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_lane_config) 486 { 487 struct falcon16_tsc_uc_lane_config_st serdes_firmware_config; 488 489 PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config)); 490 PHYMOD_IF_ERR_RETURN(falcon16_tsc_get_uc_lane_cfg(&phy->access, &serdes_firmware_config)); 491 PHYMOD_MEMSET(fw_lane_config, 0, sizeof(*fw_lane_config)); 492 fw_lane_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs; 493 fw_lane_config->AnEnabled = serdes_firmware_config.field.an_enabled; 494 fw_lane_config->DfeOn = serdes_firmware_config.field.dfe_on; 495 fw_lane_config->LpDfeOn = serdes_firmware_config.field.dfe_lp_mode; 496 fw_lane_config->ForceBrDfe = serdes_firmware_config.field.force_brdfe_on; 497 fw_lane_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis; 498 fw_lane_config->UnreliableLos = serdes_firmware_config.field.unreliable_los; 499 fw_lane_config->MediaType = serdes_firmware_config.field.media_type; 500 fw_lane_config->Cl72AutoPolEn = serdes_firmware_config.field.cl72_auto_polarity_en; 501 fw_lane_config->Cl72RestTO = serdes_firmware_config.field.cl72_restart_timeout_en; 502 503 return PHYMOD_E_NONE; 504 } 505 506 507 int tscf16_core_pll_sequencer_restart(const phymod_core_access_t* core, uint32_t flags, phymod_sequencer_operation_t operation) 508 { 509 return PHYMOD_E_UNAVAIL; 510 511 } 512 513 514 int tscf16_core_wait_event(const phymod_core_access_t* core, phymod_core_event_t event, uint32_t timeout) 515 { 516 switch(event){ 517 case phymodCoreEventPllLock: 518 /* PHYMOD_IF_ERR_RETURN(tefmod16_pll_lock_wait(&core->access, timeout)); */ 519 break; 520 default: 521 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal wait event %u"), event)); 522 } 523 524 return PHYMOD_E_NONE; 525 526 } 527 528 /* 529 * Re-tune rx path 530 * param phy phy access information 531 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 532 */ 533 int tscf16_phy_rx_restart(const phymod_phy_access_t* phy) 534 { 535 PHYMOD_IF_ERR_RETURN(falcon16_tsc_rx_restart(&phy->access, 1)); 536 537 return PHYMOD_E_NONE; 538 539 } 540 541 /* 542 * Set phy polarity 543 * param phy phy access information 544 * param polarity 545 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 546 */ 547 int tscf16_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity) 548 { 549 PHYMOD_IF_ERR_RETURN 550 (tefmod16_tx_rx_polarity_set(&phy->access, polarity->tx_polarity, polarity->rx_polarity)); 551 552 return PHYMOD_E_NONE; 553 554 } 555 556 /* 557 * Get phy polarity 558 * param phy phy access information 559 * param polarity 560 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 561 */ 562 int tscf16_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity) 563 { 564 PHYMOD_IF_ERR_RETURN 565 (tefmod16_tx_rx_polarity_get(&phy->access, &polarity->tx_polarity, &polarity->rx_polarity)); 566 567 return PHYMOD_E_NONE; 568 } 569 570 /* 571 * Set tx fir parameters 572 * param phy phy access information 573 * param tx struct tx parameter (pre, main, post, post2, post3, rpara) 574 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 575 */ 576 int tscf16_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 577 { 578 PHYMOD_IF_ERR_RETURN 579 (falcon16_tsc_apply_txfir_cfg(&phy->access, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2, (int8_t)tx->post3)); 580 581 return PHYMOD_E_NONE; 582 } 583 584 /* 585 * Get tx fir parameters 586 * param phy phy access information 587 * param tx struct tx parameter (pre, main, post, post2, post3, rpara) 588 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 589 */ 590 int tscf16_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 591 { 592 int8_t value = 0; 593 594 PHYMOD_IF_ERR_RETURN 595 (falcon16_tsc_read_tx_afe(&phy->access, TX_AFE_PRE, &value)); 596 tx->pre = value; 597 PHYMOD_IF_ERR_RETURN 598 (falcon16_tsc_read_tx_afe(&phy->access, TX_AFE_MAIN, &value)); 599 tx->main = value; 600 PHYMOD_IF_ERR_RETURN 601 (falcon16_tsc_read_tx_afe(&phy->access, TX_AFE_POST1, &value)); 602 tx->post = value; 603 PHYMOD_IF_ERR_RETURN 604 (falcon16_tsc_read_tx_afe(&phy->access, TX_AFE_POST2, &value)); 605 tx->post2 = value; 606 PHYMOD_IF_ERR_RETURN 607 (falcon16_tsc_read_tx_afe(&phy->access, TX_AFE_POST3, &value)); 608 tx->post3 = value; 609 PHYMOD_IF_ERR_RETURN 610 (falcon16_tsc_read_tx_afe(&phy->access, TX_AFE_RPARA, &value)); 611 tx->rpara = value; 612 613 return PHYMOD_E_NONE; 614 } 615 616 /* 617 * Set TX parameters using override 618 * param phy phy access information 619 * param tx struct tx override (enable, value) 620 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 621 */ 622 int tscf16_phy_tx_override_set(const phymod_phy_access_t* phy, const phymod_tx_override_t* tx_override) 623 { 624 PHYMOD_IF_ERR_RETURN 625 (falcon16_tsc_tx_pi_freq_override(&phy->access, 626 tx_override->phase_interpolator.enable, 627 tx_override->phase_interpolator.value)); 628 629 return PHYMOD_E_NONE; 630 631 } 632 633 /* 634 * Get TX override 635 * param phy phy access information 636 * param tx struct tx override (enable, value) 637 * Returns PHYMOD_E_NONE if successful else PHYMOD_E_ERROR 638 */ 639 int tscf16_phy_tx_override_get(const phymod_phy_access_t* phy, phymod_tx_override_t* tx_override) 640 { 641 uint16_t pi_value; 642 643 PHYMOD_IF_ERR_RETURN 644 (falcon16_tsc_tx_pi_control_get(&phy->access, &pi_value)); 645 646 tx_override->phase_interpolator.value = (int32_t) pi_value; 647 648 return PHYMOD_E_NONE; 649 650 } 651 652 int tscf16_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx) 653 { 654 uint32_t i; 655 uint8_t uc_lane_stopped; 656 phymod_phy_access_t pm_phy_copy; 657 int start_lane, num_lane, k; 658 659 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 660 /* next program the tx fir taps and driver current based on the input */ 661 PHYMOD_IF_ERR_RETURN 662 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 663 664 /*params check*/ 665 if ((rx->num_of_dfe_taps == 0) || (rx->num_of_dfe_taps > TSCF16_NOF_DFES)){ 666 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal number of DFEs to set %u"), (unsigned int)rx->num_of_dfe_taps)); 667 } 668 669 for (k = 0; k < num_lane; k++) { 670 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + k)) { 671 continue; 672 } 673 pm_phy_copy.access.lane_mask = 1 << (start_lane + k); 674 675 /*vga set*/ 676 /* first check if uc lane is stopped already */ 677 PHYMOD_IF_ERR_RETURN(falcon16_tsc_stop_uc_lane_status(&pm_phy_copy.access, &uc_lane_stopped)); 678 if (!uc_lane_stopped) { 679 PHYMOD_IF_ERR_RETURN(falcon16_tsc_stop_rx_adaptation(&pm_phy_copy.access, 1)); 680 } 681 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_VGA, rx->vga.value)); 682 /*dfe set*/ 683 for (i = 0 ; i < rx->num_of_dfe_taps ; i++){ 684 switch (i) { 685 case 0: 686 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_DFE1, rx->dfe[i].value)); 687 break; 688 case 1: 689 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_DFE2, rx->dfe[i].value)); 690 break; 691 case 2: 692 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_DFE3, rx->dfe[i].value)); 693 break; 694 case 3: 695 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_DFE4, rx->dfe[i].value)); 696 break; 697 case 4: 698 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_DFE5, rx->dfe[i].value)); 699 break; 700 case 5: 701 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_DFE6, rx->dfe[i].value)); 702 break; 703 default: 704 return PHYMOD_E_PARAM; 705 } 706 } 707 /*peaking filter set*/ 708 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_PF, rx->peaking_filter.value)); 709 710 /* low freq peak filter */ 711 PHYMOD_IF_ERR_RETURN(falcon16_tsc_write_rx_afe(&pm_phy_copy.access, RX_AFE_PF2, (int8_t)rx->low_freq_peaking_filter.value)); 712 } 713 714 return PHYMOD_E_NONE; 715 716 } 717 718 int tscf16_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx) 719 { 720 int8_t tmpData; 721 722 PHYMOD_IF_ERR_RETURN 723 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_VGA, &tmpData)); 724 rx->vga.value = tmpData; 725 PHYMOD_IF_ERR_RETURN 726 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_DFE1, &tmpData)); 727 rx->dfe[0].value = tmpData; 728 PHYMOD_IF_ERR_RETURN 729 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_DFE2, &tmpData)); 730 rx->dfe[1].value = tmpData; 731 PHYMOD_IF_ERR_RETURN 732 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_DFE3, &tmpData)); 733 rx->dfe[2].value = tmpData; 734 PHYMOD_IF_ERR_RETURN 735 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_DFE4, &tmpData)); 736 rx->dfe[3].value = tmpData; 737 PHYMOD_IF_ERR_RETURN 738 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_DFE5, &tmpData)); 739 rx->dfe[4].value = tmpData; 740 PHYMOD_IF_ERR_RETURN 741 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_DFE6, &tmpData)); 742 rx->dfe[5].value = tmpData; 743 PHYMOD_IF_ERR_RETURN 744 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_PF, &tmpData)); 745 rx->peaking_filter.value = tmpData; 746 PHYMOD_IF_ERR_RETURN 747 (falcon16_tsc_read_rx_afe(&phy->access, RX_AFE_PF2, &tmpData)); 748 rx->low_freq_peaking_filter.value = tmpData; 749 750 rx->num_of_dfe_taps = TSCF16_NOF_DFES; 751 rx->dfe[0].enable = 1; 752 rx->dfe[1].enable = 1; 753 rx->dfe[2].enable = 1; 754 rx->dfe[3].enable = 1; 755 rx->dfe[4].enable = 1; 756 rx->dfe[5].enable = 1; 757 rx->vga.enable = 1; 758 rx->low_freq_peaking_filter.enable = 1; 759 rx->peaking_filter.enable = 1; 760 761 return PHYMOD_E_NONE; 762 } 763 764 765 int tscf16_phy_rx_adaptation_resume(const phymod_phy_access_t* phy) 766 { 767 768 uint8_t uc_lane_stopped; 769 770 PHYMOD_IF_ERR_RETURN(falcon16_tsc_stop_uc_lane_status(&phy->access, &uc_lane_stopped)); 771 if (uc_lane_stopped) { 772 PHYMOD_IF_ERR_RETURN(falcon16_tsc_stop_rx_adaptation(&phy->access, 0)); 773 } 774 775 return PHYMOD_E_NONE; 776 } 777 778 779 int tscf16_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset) 780 { 781 PHYMOD_IF_ERR_RETURN(tefmod16_disable_set(&phy->access)); 782 783 return PHYMOD_E_NONE; 784 } 785 786 int tscf16_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset) 787 { 788 uint32_t value = 0; 789 790 PHYMOD_IF_ERR_RETURN(tefmod16_enable_get(&phy->access, &value)); 791 reset->tx = value & phymodResetDirectionCount; 792 reset->rx = value & phymodResetDirectionCount; 793 794 return PHYMOD_E_NONE; 795 796 } 797 798 799 int tscf16_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 800 { 801 phymod_phy_access_t pm_phy_copy; 802 int start_lane, num_lane, i; 803 804 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 805 /* next program the tx fir taps and driver current based on the input */ 806 PHYMOD_IF_ERR_RETURN 807 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 808 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) { 809 for (i = 0; i < num_lane; i++) { 810 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 811 continue; 812 } 813 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 814 PHYMOD_IF_ERR_RETURN(tefmod16_port_enable_set(&pm_phy_copy.access, 0)); 815 } 816 } 817 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) { 818 for (i = 0; i < num_lane; i++) { 819 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 820 continue; 821 } 822 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 823 PHYMOD_IF_ERR_RETURN(tefmod16_port_enable_set(&pm_phy_copy.access, 1)); 824 PHYMOD_IF_ERR_RETURN(tefmod16_power_control(&phy->access, 0, 0)); 825 } 826 } 827 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) { 828 /*disable tx on the PMD side */ 829 PHYMOD_IF_ERR_RETURN(falcon16_tsc_tx_disable(&phy->access, 1)); 830 } 831 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) { 832 /*enable tx on the PMD side */ 833 PHYMOD_IF_ERR_RETURN(falcon16_tsc_tx_disable(&phy->access, 0)); 834 } 835 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) { 836 /* disable rx on the PMD side */ 837 PHYMOD_IF_ERR_RETURN(tefmod16_rx_squelch_set(&phy->access, 1)); 838 } 839 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) { 840 /*enable rx on the PMD side */ 841 PHYMOD_IF_ERR_RETURN(tefmod16_rx_squelch_set(&phy->access, 0)); 842 } 843 844 return PHYMOD_E_NONE; 845 846 } 847 848 int tscf16_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 849 { 850 int enable; 851 uint32_t lb_enable; 852 phymod_phy_access_t pm_phy_copy; 853 int start_lane, num_lane; 854 855 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 856 /* next program the tx fir taps and driver current based on the input */ 857 PHYMOD_IF_ERR_RETURN 858 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 859 860 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 861 862 PHYMOD_IF_ERR_RETURN(tefmod16_rx_squelch_get(&pm_phy_copy.access, &enable)); 863 864 /* next check if PMD loopback is on */ 865 if (enable) { 866 PHYMOD_IF_ERR_RETURN(falcon16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 867 if (lb_enable) enable = 0; 868 } 869 870 power->rx = (enable == 1)? phymodPowerOff: phymodPowerOn; 871 /* Commented the following line. Because if in PMD loopback mode, we squelch the 872 xmit, and we should still see the correct port status */ 873 /* PHYMOD_IF_ERR_RETURN(tefmod16_tx_squelch_get(&pm_phy_copy.access, &enable)); */ 874 power->tx = (enable == 1)? phymodPowerOff: phymodPowerOn; 875 876 return PHYMOD_E_NONE; 877 878 } 879 880 881 int tscf16_phy_hg2_codec_control_set(const phymod_phy_access_t* phy, phymod_phy_hg2_codec_t hg2_codec) 882 /* disable rx on the PMD side */ 883 { 884 tefmod16_hg2_codec_t local_copy; 885 886 switch (hg2_codec) { 887 case phymodBcmHG2CodecOff: local_copy = TEFMOD16_HG2_CODEC_OFF; 888 break; 889 case phymodBcmHG2CodecOnWith8ByteIPG: local_copy = TEFMOD16_HG2_CODEC_ON_8BYTE_IPG; 890 break; 891 case phymodBcmHG2CodecOnWith9ByteIPG: local_copy = TEFMOD16_HG2_CODEC_ON_9BYTE_IPG; 892 break; 893 default: local_copy = TEFMOD16_HG2_CODEC_OFF; 894 break; 895 } 896 PHYMOD_IF_ERR_RETURN(tefmod16_hg2_codec_set(&phy->access, local_copy)); 897 898 return PHYMOD_E_NONE; 899 900 } 901 902 int tscf16_phy_hg2_codec_control_get(const phymod_phy_access_t* phy, phymod_phy_hg2_codec_t* hg2_codec) 903 { 904 tefmod16_hg2_codec_t local_copy; 905 906 PHYMOD_IF_ERR_RETURN(tefmod16_hg2_codec_get(&phy->access, &local_copy)); 907 908 switch (local_copy) { 909 case TEFMOD16_HG2_CODEC_OFF: *hg2_codec = phymodBcmHG2CodecOff; 910 break; 911 case TEFMOD16_HG2_CODEC_ON_8BYTE_IPG: *hg2_codec = phymodBcmHG2CodecOnWith8ByteIPG; 912 break; 913 case TEFMOD16_HG2_CODEC_ON_9BYTE_IPG: *hg2_codec = phymodBcmHG2CodecOnWith9ByteIPG; 914 break; 915 default: *hg2_codec = phymodBcmHG2CodecOff; 916 break; 917 } 918 919 return PHYMOD_E_NONE; 920 921 } 922 923 924 int tscf16_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control) 925 { 926 phymod_firmware_lane_config_t fw_lane_config; 927 PHYMOD_IF_ERR_RETURN (tscf16_phy_firmware_lane_config_get(phy, &fw_lane_config)); 928 929 switch (tx_control) { 930 case phymodTxTrafficDisable: 931 PHYMOD_IF_ERR_RETURN(tefmod16_tx_lane_control_set(&phy->access, TEFMOD16_TX_LANE_TRAFFIC_DISABLE)); 932 break; 933 case phymodTxTrafficEnable: 934 PHYMOD_IF_ERR_RETURN(tefmod16_tx_lane_control_set(&phy->access, TEFMOD16_TX_LANE_TRAFFIC_ENABLE)); 935 break; 936 case phymodTxReset: 937 PHYMOD_IF_ERR_RETURN(tefmod16_tx_lane_control_set(&phy->access, TEFMOD16_TX_LANE_RESET)); 938 break; 939 case phymodTxSquelchOn: 940 PHYMOD_IF_ERR_RETURN(tefmod16_tx_squelch_set(&phy->access, 1)); 941 break; 942 case phymodTxSquelchOff: 943 PHYMOD_IF_ERR_RETURN(tefmod16_tx_squelch_set(&phy->access, 0)); 944 break; 945 case phymodTxElectricalIdleEnable: 946 if (fw_lane_config.LaneConfigFromPCS == 0) { 947 PHYMOD_IF_ERR_RETURN(falcon16_electrical_idle_set(&phy->access, 1)); 948 }else{ 949 return PHYMOD_E_UNAVAIL; /*autoneg */ 950 } 951 break; 952 case phymodTxElectricalIdleDisable: 953 if (fw_lane_config.LaneConfigFromPCS == 0) { 954 PHYMOD_IF_ERR_RETURN(falcon16_electrical_idle_set(&phy->access, 0)); 955 }else{ 956 return PHYMOD_E_UNAVAIL; 957 } 958 break; 959 default: 960 break; 961 } 962 963 return PHYMOD_E_NONE; 964 965 } 966 967 int tscf16_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control) 968 { 969 int enable, reset, tx_lane; 970 uint32_t lb_enable; 971 phymod_phy_access_t pm_phy_copy; 972 int start_lane, num_lane; 973 974 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 975 /* next program the tx fir taps and driver current based on the input */ 976 PHYMOD_IF_ERR_RETURN 977 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 978 979 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 980 981 PHYMOD_IF_ERR_RETURN(tefmod16_tx_squelch_get(&pm_phy_copy.access, &enable)); 982 983 /* next check if PMD loopback is on */ 984 if (enable) { 985 PHYMOD_IF_ERR_RETURN(falcon16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 986 if (lb_enable) enable = 0; 987 } 988 989 if (enable) { 990 *tx_control = phymodTxSquelchOn; 991 } else { 992 PHYMOD_IF_ERR_RETURN(tefmod16_tx_lane_control_get(&pm_phy_copy.access, &reset, &tx_lane)); 993 if (!reset) { 994 *tx_control = phymodTxReset; 995 } else if (!tx_lane) { 996 *tx_control = phymodTxTrafficDisable; 997 } else { 998 *tx_control = phymodTxTrafficEnable; 999 } 1000 } 1001 1002 return PHYMOD_E_NONE; 1003 1004 } 1005 1006 1007 int tscf16_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control) 1008 { 1009 phymod_phy_access_t pm_phy_copy; 1010 int start_lane, num_lane, i; 1011 1012 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1013 /* next program the tx fir taps and driver current based on the input */ 1014 PHYMOD_IF_ERR_RETURN 1015 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1016 1017 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1018 1019 switch (rx_control) { 1020 case phymodRxReset: 1021 PHYMOD_IF_ERR_RETURN(tefmod16_rx_lane_control_set(&phy->access, 1)); 1022 break; 1023 case phymodRxDisable: 1024 PHYMOD_IF_ERR_RETURN(tefmod16_rx_lane_control_set(&phy->access, 0)); 1025 break; 1026 case phymodRxSquelchOn: 1027 for (i = 0; i < num_lane; i++) { 1028 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1029 continue; 1030 } 1031 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1032 PHYMOD_IF_ERR_RETURN(tefmod16_rx_squelch_set(&pm_phy_copy.access, 1)); 1033 } 1034 break; 1035 case phymodRxSquelchOff: 1036 for (i = 0; i < num_lane; i++) { 1037 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1038 continue; 1039 } 1040 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1041 PHYMOD_IF_ERR_RETURN(tefmod16_rx_squelch_set(&pm_phy_copy.access, 0)); 1042 } 1043 break; 1044 default: 1045 break; 1046 } 1047 1048 return PHYMOD_E_NONE; 1049 1050 } 1051 1052 int tscf16_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control) 1053 { 1054 int enable, reset; 1055 uint32_t lb_enable; 1056 phymod_phy_access_t pm_phy_copy; 1057 int start_lane, num_lane; 1058 1059 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1060 /* next program the tx fir taps and driver current based on the input */ 1061 PHYMOD_IF_ERR_RETURN 1062 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1063 1064 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1065 1066 PHYMOD_IF_ERR_RETURN(tefmod16_rx_squelch_get(&pm_phy_copy.access, &enable)); 1067 /* next check if PMD loopback is on */ 1068 if (enable) { 1069 PHYMOD_IF_ERR_RETURN(falcon16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 1070 if (lb_enable) enable = 0; 1071 } 1072 if (enable) { 1073 *rx_control = phymodRxSquelchOn; 1074 } else { 1075 PHYMOD_IF_ERR_RETURN(tefmod16_rx_lane_control_get(&pm_phy_copy.access, &reset)); 1076 if (reset == 0) { 1077 *rx_control = phymodRxReset; 1078 } else { 1079 *rx_control = phymodRxSquelchOff; 1080 } 1081 } 1082 1083 return PHYMOD_E_NONE; 1084 1085 } 1086 1087 /* 1088 * Enables/Disables FEC override bit. 1089 * 0xc055 field[4:3] 1090 * 0x1 Enable for NOFEC 100G AN 1091 */ 1092 int tscf16_phy_fec_override_set(const phymod_phy_access_t* phy, uint32_t enable) 1093 { 1094 if ((enable == 0) || (enable == 1)) { 1095 PHYMOD_IF_ERR_RETURN(tefmod16_fec_override_set(&phy->access, enable)); 1096 } else { 1097 PHYMOD_DEBUG_ERROR(("ERROR :: Supported input values: 1 to set FEC override, 0 to disable FEC override\n")); 1098 } 1099 1100 return PHYMOD_E_NONE; 1101 } 1102 1103 int tscf16_phy_fec_override_get(const phymod_phy_access_t* phy, uint32_t* enable) 1104 { 1105 1106 PHYMOD_IF_ERR_RETURN(tefmod16_fec_override_get(&phy->access, enable)); 1107 1108 return PHYMOD_E_NONE; 1109 1110 } 1111 1112 int tscf16_phy_fec_enable_set(const phymod_phy_access_t* phy, uint32_t enable) 1113 { 1114 int fec_en; 1115 tefmod16_fec_type_t fec_type; 1116 1117 /* first check FEC type */ 1118 if (PHYMOD_FEC_CL91_GET(enable)) { 1119 fec_type = TEFMOD16_CL91; 1120 } else if (PHYMOD_FEC_CL108_GET(enable)) { 1121 fec_type = TEFMOD16_CL108; 1122 } else { 1123 fec_type = TEFMOD16_CL74; 1124 } 1125 1126 /* check FEC on/off */ 1127 fec_en = enable & TEFMOD16_PHY_CONTROL_FEC_MASK; 1128 PHYMOD_IF_ERR_RETURN( 1129 tefmod16_FEC_control(&phy->access, fec_type, fec_en, 0)); 1130 1131 return PHYMOD_E_NONE; 1132 1133 } 1134 1135 int tscf16_phy_fec_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 1136 { 1137 int fec_en; 1138 tefmod16_fec_type_t fec_type; 1139 1140 /* first check FEC type */ 1141 if (PHYMOD_FEC_CL91_GET(*enable)) { 1142 fec_type = TEFMOD16_CL91; 1143 } else if (PHYMOD_FEC_CL108_GET(*enable)) { 1144 fec_type = TEFMOD16_CL108; 1145 } else { 1146 fec_type = TEFMOD16_CL74; 1147 } 1148 1149 PHYMOD_IF_ERR_RETURN( 1150 tefmod16_FEC_get(&phy->access, fec_type, &fec_en)); 1151 PHYMOD_DEBUG_VERBOSE(("FEC enable state :: %x :: fec_type :: %x\n", fec_en, fec_type)); 1152 *enable = (uint32_t) fec_en; 1153 1154 return PHYMOD_E_NONE; 1155 } 1156 1157 1158 int tscf16_phy_autoneg_oui_set(const phymod_phy_access_t* phy, phymod_autoneg_oui_t an_oui) 1159 { 1160 tefmod16_an_oui_t oui; 1161 1162 oui.oui = an_oui.oui; 1163 oui.oui_override_hpam_adv = an_oui.oui_override_hpam_adv; 1164 oui.oui_override_hpam_det = an_oui.oui_override_hpam_det; 1165 oui.oui_override_bam73_adv = an_oui.oui_override_bam73_adv; 1166 oui.oui_override_bam73_det = an_oui.oui_override_bam73_det; 1167 PHYMOD_IF_ERR_RETURN(tefmod16_an_oui_set(&phy->access, oui)); 1168 1169 return PHYMOD_E_NONE; 1170 1171 } 1172 1173 int tscf16_phy_autoneg_oui_get(const phymod_phy_access_t* phy, phymod_autoneg_oui_t* an_oui) 1174 { 1175 tefmod16_an_oui_t oui; 1176 1177 PHYMOD_IF_ERR_RETURN(tefmod16_an_oui_get(&phy->access, &oui)); 1178 an_oui->oui_override_hpam_adv = oui.oui_override_hpam_adv; 1179 an_oui->oui_override_hpam_det = oui.oui_override_hpam_det; 1180 an_oui->oui_override_bam73_adv = oui.oui_override_bam73_adv; 1181 an_oui->oui_override_bam73_det = oui.oui_override_bam73_det; 1182 1183 return PHYMOD_E_NONE; 1184 1185 } 1186 1187 1188 int tscf16_phy_eee_set(const phymod_phy_access_t* phy, uint32_t enable) 1189 { 1190 uint32_t lpi_bypass; 1191 int rv = PHYMOD_E_NONE; 1192 1193 lpi_bypass = PHYMOD_LPI_BYPASS_GET(enable); 1194 enable &= 0x1; 1195 if (lpi_bypass) { 1196 rv = tefmod16_eee_control_set(&phy->access,enable); 1197 } else { 1198 return PHYMOD_E_UNAVAIL; 1199 } 1200 1201 return rv; 1202 } 1203 1204 int tscf16_phy_eee_get(const phymod_phy_access_t* phy, uint32_t* enable) 1205 { 1206 if (PHYMOD_LPI_BYPASS_GET(*enable)) { 1207 PHYMOD_IF_ERR_RETURN(tefmod16_eee_control_get(&phy->access, enable)); 1208 PHYMOD_LPI_BYPASS_SET(*enable); 1209 } else { 1210 return PHYMOD_E_UNAVAIL; 1211 } 1212 1213 return PHYMOD_E_NONE; 1214 } 1215 1216 int tscf16_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 1217 { 1218 uint32_t current_pll_div = 0; 1219 uint32_t new_pll_div = 0; 1220 int16_t new_os_mode =-1; 1221 tefmod16_spd_intfc_type_t spd_intf = TEFMOD16_SPD_ILLEGAL; 1222 phymod_phy_access_t pm_phy_copy; 1223 int start_lane, num_lane, i, pll_switch=0; 1224 int lane_bkup, os_mode; 1225 enum falcon16_tsc_pll_refclk_enum refclk = FALCON16_TSC_PLL_REFCLK_156P25MHZ; 1226 uint32_t vco_rate; 1227 phymod_firmware_lane_config_t firmware_lane_config; 1228 int is_10g_spd_override = 0; 1229 1230 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 1231 1232 /*next program the tx fir taps and driver current based on the input*/ 1233 PHYMOD_IF_ERR_RETURN 1234 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1235 1236 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1237 1238 /* first hold the pcs lane reset */ 1239 tefmod16_disable_set(&phy->access); 1240 1241 /*Hold the per lane PMD soft reset bit*/ 1242 for (i = 0; i < num_lane; i++) { 1243 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1244 continue; 1245 } 1246 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1247 PHYMOD_IF_ERR_RETURN 1248 (falcon16_lane_soft_reset_release(&pm_phy_copy.access, 0)); 1249 } 1250 /* remove pmd_tx_disable_pin_dis it may be asserted because of ILKn */ 1251 for (i = 0; i < num_lane; i++) { 1252 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1253 continue; 1254 } 1255 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1256 PHYMOD_IF_ERR_RETURN 1257 (falcon16_pmd_tx_disable_pin_dis_set(&pm_phy_copy.access, 0)); 1258 } 1259 1260 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1261 PHYMOD_IF_ERR_RETURN 1262 (tscf16_phy_firmware_lane_config_get(&pm_phy_copy, &firmware_lane_config)); 1263 1264 /*make sure that an and config from pcs is off*/ 1265 firmware_lane_config.AnEnabled = 0; 1266 firmware_lane_config.LaneConfigFromPCS = 0; 1267 firmware_lane_config.DfeOn = 1; 1268 firmware_lane_config.LpDfeOn = 0; 1269 /* enable pmd_rx_restart after 600ms if the link has faield to complete training */ 1270 firmware_lane_config.Cl72RestTO = 1; 1271 firmware_lane_config.Cl72AutoPolEn = 0; 1272 1273 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1274 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1275 } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1276 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1277 } else { 1278 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1279 } 1280 /* this field is used only when MediaType is optical */ 1281 if (PHYMOD_INTF_MODES_UNRELIABLE_LOS_GET(config)) { 1282 firmware_lane_config.UnreliableLos = 1; 1283 } else { 1284 /* los is reliable */ 1285 firmware_lane_config.UnreliableLos = 0; 1286 } 1287 if (config->data_rate == 1000) { 1288 firmware_lane_config.DfeOn = 0; 1289 } 1290 1291 PHYMOD_IF_ERR_RETURN 1292 (tefmod16_update_port_mode(&phy->access, (int *) &pll_switch)); 1293 1294 if (config->interface_type == phymodInterface1000X) { 1295 if (config->pll_divider_req == 165) { 1296 spd_intf = TEFMOD16_SPD_1G_25G; 1297 } else { 1298 spd_intf = TEFMOD16_SPD_1G_20G; 1299 } 1300 } else if (config->interface_type == phymodInterfaceSGMII) { 1301 if (config->pll_divider_req == 165) { 1302 spd_intf = TEFMOD16_SPD_1G_25G; 1303 } else { 1304 spd_intf = TEFMOD16_SPD_1G_20G; 1305 } 1306 } else if ((config->interface_type == phymodInterfaceBypass) || 1307 (num_lane == 1)) { 1308 switch (config->data_rate) { 1309 case 10000: 1310 spd_intf = TEFMOD16_SPD_10000_XFI; 1311 if (!PHYMOD_INTF_MODES_COPPER_GET(config)) { 1312 firmware_lane_config.DfeOn = 0; 1313 } 1314 if (config->interface_type != phymodInterfaceBypass) { 1315 if (config->pll_divider_req == 165) { 1316 is_10g_spd_override = 1; 1317 PHYMOD_IF_ERR_RETURN 1318 (tefmod16_override_10g_x1_spd_intf(&phy->access, 1)); 1319 } else { 1320 /*Remove the 10G speed override only when setting 10G working at 20G*/ 1321 PHYMOD_IF_ERR_RETURN 1322 (tefmod16_override_10g_x1_spd_intf(&phy->access, 0)); 1323 } 1324 } 1325 break; 1326 case 12000: 1327 spd_intf = TEFMOD16_SPD_10000_XFI; 1328 if (!PHYMOD_INTF_MODES_COPPER_GET(config)) { 1329 firmware_lane_config.DfeOn = 0; 1330 } 1331 break; 1332 case 10600: 1333 case 11000: 1334 spd_intf = TEFMOD16_SPD_10600_XFI_HG; 1335 if (!PHYMOD_INTF_MODES_COPPER_GET(config)) { 1336 firmware_lane_config.DfeOn = 0; 1337 } 1338 break; 1339 case 20000: 1340 spd_intf = TEFMOD16_SPD_20000_XFI; 1341 break; 1342 case 21200: 1343 spd_intf = TEFMOD16_SPD_21200_XFI_HG; 1344 break; 1345 case 25000: 1346 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1347 spd_intf = TEFMOD16_SPD_26500_XFI_HG; 1348 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1349 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1350 } else { 1351 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1352 } 1353 } else { 1354 spd_intf = TEFMOD16_SPD_25000_XFI; 1355 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1356 firmware_lane_config.DfeOn = 0; 1357 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1358 } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1359 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1360 } else { 1361 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1362 } 1363 } 1364 break; 1365 case 27000: 1366 spd_intf = TEFMOD16_SPD_26500_XFI_HG; 1367 firmware_lane_config.DfeOn = 1; 1368 firmware_lane_config.LpDfeOn = 0; 1369 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1370 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1371 } else { 1372 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1373 } 1374 break; 1375 default: 1376 /* if the interface is pcs bypass mode and check the speed */ 1377 if (config->interface_type == phymodInterfaceBypass) { 1378 /* disable DFE for lower speed */ 1379 if (config->data_rate < 10000) { 1380 firmware_lane_config.DfeOn = 0; 1381 } 1382 } else { 1383 spd_intf = TEFMOD16_SPD_10000_XFI; 1384 firmware_lane_config.DfeOn = 0; 1385 } 1386 break; 1387 } 1388 } else if ((config->interface_type == phymodInterfaceKR2) || 1389 (config->interface_type == phymodInterfaceCR2) || 1390 (config->interface_type == phymodInterfaceXLAUI2) || 1391 (config->interface_type == phymodInterfaceRXAUI) || 1392 (config->interface_type == phymodInterfaceX2) || 1393 (num_lane == 2)) { 1394 switch (config->data_rate) { 1395 case 20000: 1396 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1397 spd_intf = TEFMOD16_SPD_21G_MLD_HG_X2; 1398 firmware_lane_config.DfeOn = 0; 1399 firmware_lane_config.LpDfeOn = 0; 1400 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1401 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1402 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1403 } else { 1404 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1405 } 1406 } else { 1407 spd_intf = TEFMOD16_SPD_20G_MLD_X2; 1408 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1409 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1410 } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1411 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1412 } else { 1413 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1414 } 1415 } 1416 break; 1417 case 21000: 1418 case 21200: 1419 firmware_lane_config.DfeOn = 0; 1420 firmware_lane_config.LpDfeOn = 0; 1421 spd_intf = TEFMOD16_SPD_21G_MLD_HG_X2; 1422 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1423 break; 1424 case 40000: 1425 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1426 spd_intf = TEFMOD16_SPD_42G_MLD_HG_X2; 1427 firmware_lane_config.DfeOn = 1; 1428 firmware_lane_config.LpDfeOn = 1; 1429 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1430 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1431 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1432 } else { 1433 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1434 } 1435 } else { 1436 spd_intf = TEFMOD16_SPD_40G_MLD_X2; 1437 if (config->interface_type == phymodInterfaceXLAUI2) { 1438 firmware_lane_config.DfeOn = 0; 1439 firmware_lane_config.LpDfeOn = 0; 1440 } else { 1441 firmware_lane_config.DfeOn = 1; 1442 firmware_lane_config.LpDfeOn = 1; 1443 } 1444 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1445 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1446 } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1447 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1448 } else { 1449 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1450 } 1451 } 1452 break; 1453 case 42000: 1454 spd_intf = TEFMOD16_SPD_42G_MLD_HG_X2; 1455 firmware_lane_config.DfeOn = 1; 1456 firmware_lane_config.LpDfeOn = 1; 1457 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1458 break; 1459 case 50000: 1460 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1461 spd_intf = TEFMOD16_SPD_53G_MLD_HG_X2; 1462 } else { 1463 spd_intf = TEFMOD16_SPD_50G_MLD_X2; 1464 } 1465 break; 1466 case 53000: 1467 spd_intf = TEFMOD16_SPD_53G_MLD_HG_X2; 1468 break; 1469 default: 1470 spd_intf = TEFMOD16_SPD_20G_MLD_X2; 1471 break; 1472 } 1473 } else { 1474 switch (config->data_rate) { 1475 case 40000: 1476 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1477 spd_intf = TEFMOD16_SPD_42G_MLD_HG_X4; 1478 firmware_lane_config.DfeOn = 1; 1479 firmware_lane_config.LpDfeOn = 1; 1480 } else if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1481 spd_intf = TEFMOD16_SPD_40G_MLD_X4; 1482 firmware_lane_config.DfeOn = 0; 1483 firmware_lane_config.LpDfeOn = 0; 1484 } else { 1485 if (config->interface_type == phymodInterfaceXLAUI) { 1486 spd_intf = TEFMOD16_SPD_40G_MLD_X4; 1487 firmware_lane_config.DfeOn = 0; 1488 firmware_lane_config.LpDfeOn = 0; 1489 } else { 1490 spd_intf = TEFMOD16_SPD_40G_MLD_X4; 1491 firmware_lane_config.DfeOn = 1; 1492 firmware_lane_config.LpDfeOn = 1; 1493 } 1494 } 1495 break; 1496 case 42000: 1497 spd_intf = TEFMOD16_SPD_42G_MLD_HG_X4; 1498 firmware_lane_config.DfeOn = 1; 1499 firmware_lane_config.LpDfeOn = 1; 1500 break; 1501 case 48000: 1502 spd_intf = TEFMOD16_SPD_40G_MLD_X4; 1503 firmware_lane_config.DfeOn = 0; 1504 firmware_lane_config.LpDfeOn = 0; 1505 break; 1506 case 50000: 1507 spd_intf = TEFMOD16_SPD_50G_MLD_X4; 1508 break; 1509 case 53000: 1510 spd_intf = TEFMOD16_SPD_53G_MLD_HG_X4; 1511 break; 1512 case 100000: 1513 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1514 spd_intf = TEFMOD16_SPD_106G_MLD_HG_X4; 1515 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1516 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1517 } else { 1518 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1519 } 1520 } else { 1521 spd_intf = TEFMOD16_SPD_100G_MLD_X4; 1522 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1523 firmware_lane_config.DfeOn = 0; 1524 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1525 } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1526 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1527 } else { 1528 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1529 } 1530 if (config->interface_type == phymodInterfaceCAUI4 || config->interface_type == phymodInterfaceCAUI) { 1531 firmware_lane_config.LpDfeOn = 1; 1532 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1533 } 1534 } 1535 break; 1536 case 106000: 1537 spd_intf = TEFMOD16_SPD_106G_MLD_HG_X4; 1538 firmware_lane_config.DfeOn = 1; 1539 firmware_lane_config.LpDfeOn = 0; 1540 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 1541 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 1542 } else { 1543 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 1544 } 1545 break; 1546 default: 1547 spd_intf = TEFMOD16_SPD_40G_MLD_X4; 1548 firmware_lane_config.DfeOn = 0; 1549 break; 1550 } 1551 } 1552 1553 /*only when 10G working at 25G, the 10G clock is enabled*/ 1554 if (is_10g_spd_override) { 1555 PHYMOD_IF_ERR_RETURN 1556 (tefmod16_10g_clock_enable(&phy->access, 1)); 1557 } else { 1558 PHYMOD_IF_ERR_RETURN 1559 (tefmod16_10g_clock_enable(&phy->access, 0)); 1560 } 1561 /* get current pll */ 1562 PHYMOD_IF_ERR_RETURN 1563 (falcon16_tsc_INTERNAL_read_pll_div(&phy->access, ¤t_pll_div)); 1564 1565 if (config->interface_type == phymodInterfaceBypass) { 1566 PHYMOD_IF_ERR_RETURN 1567 (falcon16_tsc_get_pll_vco_osmode(config, &vco_rate, &new_pll_div, &new_os_mode)); 1568 } else { 1569 PHYMOD_IF_ERR_RETURN 1570 (tefmod16_plldiv_lkup_get(&phy->access, spd_intf, config->ref_clock, &new_pll_div)); 1571 if ((config->data_rate == 10000) && (num_lane == 1)) { 1572 if (is_10g_spd_override) { 1573 new_pll_div = TEFMOD16_PLL_MODE_DIV_165; 1574 new_os_mode = 0; 1575 } 1576 } 1577 /* For 12GG XFI , data rate specified is 12000, and pll_div is set to 160 ( 6 ) */ 1578 if ((config->data_rate == 12000) && (num_lane == 1)) { 1579 if (config->ref_clock == phymodRefClk125Mhz) { 1580 new_pll_div = TEFMOD16_PLL_MODE_DIV_200; 1581 } else { 1582 new_pll_div = TEFMOD16_PLL_MODE_DIV_160; 1583 } 1584 } 1585 if ((config->data_rate == 20000) && 1586 PHYMOD_INTF_MODES_HIGIG_GET(config) && (num_lane == 2)) { 1587 new_pll_div = TEFMOD16_PLL_MODE_DIV_132; 1588 } 1589 if ((config->data_rate == 40000) && 1590 PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1591 if (num_lane == 4) { 1592 if (config->ref_clock == phymodRefClk125Mhz) { 1593 new_pll_div = TEFMOD16_PLL_MODE_DIV_165; 1594 } else { 1595 new_pll_div = TEFMOD16_PLL_MODE_DIV_132; 1596 } 1597 } 1598 if (num_lane == 2) { 1599 new_pll_div = TEFMOD16_PLL_MODE_DIV_132; 1600 } 1601 } 1602 if ((config->data_rate == 48000) && (num_lane == 4)) { 1603 if (config->ref_clock == phymodRefClk125Mhz) { 1604 new_pll_div = TEFMOD16_PLL_MODE_DIV_200; 1605 } else { 1606 new_pll_div = TEFMOD16_PLL_MODE_DIV_160; 1607 } 1608 } 1609 if ((config->data_rate == 100000) && 1610 PHYMOD_INTF_MODES_HIGIG_GET(config) && 1611 (num_lane == 4)) { 1612 new_pll_div = TEFMOD16_PLL_MODE_DIV_165; 1613 } 1614 1615 if ((config->data_rate == 50000) && 1616 PHYMOD_INTF_MODES_HIGIG_GET(config) && 1617 (num_lane == 2)) { 1618 new_pll_div = TEFMOD16_PLL_MODE_DIV_165; 1619 } 1620 if ((config->data_rate == 25000) && 1621 PHYMOD_INTF_MODES_HIGIG_GET(config) && 1622 (num_lane == 1)) { 1623 new_pll_div = TEFMOD16_PLL_MODE_DIV_165; 1624 } 1625 } 1626 1627 if (new_os_mode>=0) { 1628 os_mode = new_os_mode | 0x80000000 ; 1629 } else { 1630 os_mode = 0 ; 1631 } 1632 PHYMOD_IF_ERR_RETURN 1633 (tefmod16_pmd_osmode_set(&phy->access, spd_intf, config->ref_clock, os_mode)); 1634 1635 /*if pll change is enabled*/ 1636 if ((current_pll_div != new_pll_div) && (PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)){ 1637 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 1638 (_PHYMOD_MSG("pll has to change for speed_set from %u to %u but DONT_TURN_OFF_PLL flag is enabled"), 1639 (unsigned int)current_pll_div, (unsigned int)new_pll_div)); 1640 } 1641 1642 /*pll switch is required and expected */ 1643 if ((current_pll_div != new_pll_div) && !(PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) { 1644 1645 /* Change in PLL, so reset all the ports first. */ 1646 lane_bkup = pm_phy_copy.access.lane_mask; 1647 pm_phy_copy.access.lane_mask = 0xf; 1648 tefmod16_disable_set(&pm_phy_copy.access); 1649 pm_phy_copy.access.lane_mask = lane_bkup; 1650 1651 /*set the PLL divider */ 1652 if (config->ref_clock == phymodRefClk125Mhz){ 1653 refclk = FALCON16_TSC_PLL_REFCLK_125MHZ; 1654 } 1655 PHYMOD_IF_ERR_RETURN 1656 (falcon16_tsc_core_dp_reset(&pm_phy_copy.access, 1)); 1657 1658 PHYMOD_IF_ERR_RETURN 1659 (falcon16_tsc_configure_pll_refclk_div(&pm_phy_copy.access, refclk, new_pll_div)); 1660 1661 PHYMOD_IF_ERR_RETURN 1662 (falcon16_tsc_core_dp_reset(&pm_phy_copy.access, 0)); 1663 1664 PHYMOD_IF_ERR_RETURN 1665 (tefmod16_master_port_num_set(&phy->access, start_lane)); 1666 1667 PHYMOD_IF_ERR_RETURN 1668 (tefmod16_pll_reset_enable_set(&phy->access, 1)); 1669 1670 1671 } 1672 if (config->interface_type != phymodInterfaceBypass) { 1673 PHYMOD_IF_ERR_RETURN 1674 (tefmod16_set_spd_intf(&phy->access, spd_intf)); 1675 } 1676 1677 for (i = 0; i < num_lane; i++) { 1678 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1679 continue; 1680 } 1681 pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i); 1682 PHYMOD_IF_ERR_RETURN 1683 (_tscf16_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config)); 1684 } 1685 1686 /*release the per lne soft reset bit*/ 1687 for (i = 0; i < num_lane; i++) { 1688 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1689 continue; 1690 } 1691 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1692 PHYMOD_IF_ERR_RETURN 1693 (falcon16_lane_soft_reset_release(&pm_phy_copy.access, 1)); 1694 } 1695 1696 return PHYMOD_E_NONE; 1697 1698 } 1699 1700 1701 1702 STATIC 1703 int _tscf16_speed_id_interface_config_get(const phymod_phy_access_t* phy, int speed_id, phymod_phy_inf_config_t* config) 1704 { 1705 int ilkn_set; 1706 int osr_mode; 1707 int div_osr_value; 1708 uint32_t vco_rate; 1709 uint32_t pll_multiplier; 1710 uint32_t plldiv_r_val; 1711 1712 PHYMOD_IF_ERR_RETURN(tefmod16_pcs_ilkn_chk(&phy->access, &ilkn_set)); 1713 PHYMOD_IF_ERR_RETURN(tefmod16_get_plldiv(&phy->access, &plldiv_r_val)); 1714 1715 if (ilkn_set) { 1716 config->interface_type = phymodInterfaceBypass; 1717 PHYMOD_IF_ERR_RETURN(tefmod16_get_plldiv(&phy->access, &plldiv_r_val)); 1718 PHYMOD_IF_ERR_RETURN 1719 (_tscf16_pll_multiplier_get(plldiv_r_val, &pll_multiplier)); 1720 PHYMOD_IF_ERR_RETURN 1721 (falcon16_osr_mode_get(&phy->access, &osr_mode)); 1722 1723 switch (config->ref_clock) { 1724 case phymodRefClk156Mhz: 1725 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100; 1726 break; 1727 case phymodRefClk125Mhz: 1728 vco_rate = pll_multiplier * 125; 1729 break; 1730 default: 1731 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100; 1732 break; 1733 } 1734 div_osr_value = 1 << osr_mode; 1735 config->data_rate = vco_rate/div_osr_value; 1736 } else { 1737 switch (speed_id) { 1738 case 0x0: 1739 config->data_rate = 10000; 1740 config->interface_type = phymodInterfaceCR; 1741 break; 1742 case 0x1: 1743 config->data_rate = 10000; 1744 config->interface_type = phymodInterfaceKR; 1745 break; 1746 case 0x2: 1747 config->data_rate = 10000; 1748 config->interface_type = phymodInterfaceKR; 1749 /*next check the PLL divider to see if 10G or 12G */ 1750 PHYMOD_IF_ERR_RETURN(tefmod16_get_plldiv(&phy->access, &plldiv_r_val)); 1751 if ((config->ref_clock == phymodRefClk125Mhz) && 1752 (plldiv_r_val == 0xd)) { 1753 config->data_rate = 12000; 1754 } 1755 1756 if ((config->ref_clock == phymodRefClk156Mhz) && 1757 (plldiv_r_val == 0x6)) { 1758 config->data_rate = 12000; 1759 } 1760 break; 1761 case 0x4: 1762 config->data_rate = 11000; 1763 config->interface_type = phymodInterfaceCR; 1764 break; 1765 case 0x5: 1766 config->data_rate = 11000; 1767 config->interface_type = phymodInterfaceKR; 1768 break; 1769 case 0x6: 1770 config->data_rate = 11000; 1771 config->interface_type = phymodInterfaceKR; 1772 break; 1773 case 0x8: 1774 config->data_rate = 20000; 1775 config->interface_type = phymodInterfaceCR; 1776 break; 1777 case 0x9: 1778 config->data_rate = 20000; 1779 config->interface_type = phymodInterfaceKR; 1780 break; 1781 case 0xa: 1782 config->data_rate = 20000; 1783 config->interface_type = phymodInterfaceKR; 1784 break; 1785 case 0xc: 1786 config->data_rate = 21000; 1787 config->interface_type = phymodInterfaceCR; 1788 break; 1789 case 0xd: 1790 config->data_rate = 21000; 1791 config->interface_type = phymodInterfaceKR; 1792 break; 1793 case 0xe: 1794 config->data_rate = 21000; 1795 config->interface_type = phymodInterfaceKR; 1796 break; 1797 /* 25G_CR1_MSA */ 1798 case 0x10: 1799 config->data_rate = 25000; 1800 config->interface_type = phymodInterfaceCR; 1801 break; 1802 case 0x11: 1803 /* 25G_KR1_MSA */ 1804 config->data_rate = 25000; 1805 config->interface_type = phymodInterfaceKR; 1806 break; 1807 /* 25G_X1_MSA */ 1808 case 0x12: 1809 config->data_rate = 25000; 1810 config->interface_type = phymodInterfaceKR; 1811 break; 1812 /* 25G_HG2_CR1_MSA */ 1813 case 0x14: 1814 config->data_rate = 27000; 1815 if (plldiv_r_val == 0x7) { 1816 config->data_rate = 25000; 1817 } 1818 config->interface_type = phymodInterfaceCR; 1819 break; 1820 /* 25G_HG2_KR1_MSA */ 1821 case 0x15: 1822 config->data_rate = 27000; 1823 if (plldiv_r_val == 0x7) { 1824 config->data_rate = 25000; 1825 } 1826 config->interface_type = phymodInterfaceKR; 1827 break; 1828 /* 25G_HG2_X1_MSA */ 1829 case 0x16: 1830 config->data_rate = 27000; 1831 if (plldiv_r_val == 0x7) { 1832 config->data_rate = 25000; 1833 } 1834 config->interface_type = phymodInterfaceKR; 1835 break; 1836 case 0x18: 1837 config->data_rate = 20000; 1838 config->interface_type = phymodInterfaceCR2; 1839 break; 1840 case 0x19: 1841 config->data_rate = 20000; 1842 config->interface_type = phymodInterfaceKR2; 1843 break; 1844 case 0x1a: 1845 config->data_rate = 20000; 1846 config->interface_type = phymodInterfaceKR2; 1847 break; 1848 case 0x1c: 1849 config->data_rate = 21000; 1850 config->interface_type = phymodInterfaceCR2; 1851 break; 1852 case 0x1d: 1853 config->data_rate = 21000; 1854 config->interface_type = phymodInterfaceKR2; 1855 break; 1856 case 0x1e: 1857 config->data_rate = 21000; 1858 if ((config->ref_clock == phymodRefClk156Mhz) && 1859 (plldiv_r_val == 0x4)) { 1860 config->data_rate =20000; 1861 } 1862 config->interface_type = phymodInterfaceKR2; 1863 break; 1864 case 0x20: 1865 config->data_rate = 40000; 1866 config->interface_type = phymodInterfaceCR2; 1867 break; 1868 case 0x21: 1869 config->data_rate = 40000; 1870 config->interface_type = phymodInterfaceKR2; 1871 break; 1872 case 0x22: 1873 config->data_rate = 40000; 1874 config->interface_type = phymodInterfaceKR2; 1875 break; 1876 case 0x24: 1877 config->data_rate = 42000; 1878 config->interface_type = phymodInterfaceCR2; 1879 break; 1880 case 0x25: 1881 config->data_rate = 42000; 1882 config->interface_type = phymodInterfaceKR2; 1883 break; 1884 case 0x26: 1885 config->data_rate = 42000; 1886 if ((config->ref_clock == phymodRefClk156Mhz) && 1887 (plldiv_r_val == 0x4)) { 1888 config->data_rate = 40000; 1889 } 1890 config->interface_type = phymodInterfaceKR2; 1891 break; 1892 case 0x28: 1893 config->data_rate = 40000; 1894 if ((config->ref_clock == phymodRefClk156Mhz) && 1895 (plldiv_r_val == 0x5)) { 1896 config->data_rate =42000; 1897 } 1898 if ((config->ref_clock == phymodRefClk156Mhz) && 1899 (plldiv_r_val == 0x6)) { 1900 config->data_rate =48000; 1901 } 1902 if ((config->ref_clock == phymodRefClk125Mhz) && 1903 (plldiv_r_val == 0xa)) { 1904 config->data_rate =42000; 1905 } 1906 if ((config->ref_clock == phymodRefClk125Mhz) && 1907 (plldiv_r_val == 0xd)) { 1908 config->data_rate =48000; 1909 } 1910 1911 config->interface_type = phymodInterfaceCR4; 1912 break; 1913 case 0x29: 1914 config->data_rate = 40000; 1915 if ((config->ref_clock == phymodRefClk156Mhz) && 1916 (plldiv_r_val == 0x5)) { 1917 config->data_rate =42000; 1918 } 1919 if ((config->ref_clock == phymodRefClk156Mhz) && 1920 (plldiv_r_val == 0x6)) { 1921 config->data_rate =48000; 1922 } 1923 if ((config->ref_clock == phymodRefClk125Mhz) && 1924 (plldiv_r_val == 0xa)) { 1925 config->data_rate =42000; 1926 } 1927 if ((config->ref_clock == phymodRefClk125Mhz) && 1928 (plldiv_r_val == 0xd)) { 1929 config->data_rate =48000; 1930 } 1931 config->interface_type = phymodInterfaceKR4; 1932 break; 1933 case 0x2a: 1934 config->data_rate = 40000; 1935 if ((config->ref_clock == phymodRefClk156Mhz) && 1936 (plldiv_r_val == 0x5)) { 1937 config->data_rate =42000; 1938 } 1939 if ((config->ref_clock == phymodRefClk156Mhz) && 1940 (plldiv_r_val == 0x6)) { 1941 config->data_rate =48000; 1942 } 1943 if ((config->ref_clock == phymodRefClk125Mhz) && 1944 (plldiv_r_val == 0xa)) { 1945 config->data_rate =42000; 1946 } 1947 if ((config->ref_clock == phymodRefClk125Mhz) && 1948 (plldiv_r_val == 0xd)) { 1949 config->data_rate =48000; 1950 } 1951 config->interface_type = phymodInterfaceKR4; 1952 break; 1953 case 0x2c: 1954 config->data_rate = 42000; 1955 config->interface_type = phymodInterfaceCR4; 1956 break; 1957 case 0x2d: 1958 config->data_rate = 42000; 1959 config->interface_type = phymodInterfaceKR4; 1960 break; 1961 case 0x2e: 1962 config->data_rate = 42000; 1963 if ((config->ref_clock == phymodRefClk156Mhz) && 1964 (plldiv_r_val == 0x4)) { 1965 config->data_rate =40000; 1966 } 1967 if ((config->ref_clock == phymodRefClk125Mhz) && 1968 (plldiv_r_val == 0x7)) { 1969 config->data_rate =40000; 1970 } 1971 config->interface_type = phymodInterfaceKR4; 1972 break; 1973 case 0x30: 1974 config->data_rate = 50000; 1975 config->interface_type = phymodInterfaceCR2; 1976 break; 1977 case 0x31: 1978 config->data_rate = 50000; 1979 config->interface_type = phymodInterfaceKR2; 1980 break; 1981 case 0x32: 1982 config->data_rate = 50000; 1983 config->interface_type = phymodInterfaceKR2; 1984 break; 1985 case 0x34: 1986 config->data_rate = 53000; 1987 config->interface_type = phymodInterfaceCR2; 1988 break; 1989 case 0x35: 1990 config->data_rate = 53000; 1991 config->interface_type = phymodInterfaceKR2; 1992 break; 1993 case 0x36: 1994 if ((config->ref_clock == phymodRefClk156Mhz) && 1995 (plldiv_r_val == 0x7)) { 1996 config->data_rate = 50000; 1997 } else { 1998 config->data_rate = 53000; 1999 } 2000 config->interface_type = phymodInterfaceKR2; 2001 break; 2002 case 0x38: 2003 config->data_rate = 50000; 2004 config->interface_type = phymodInterfaceCR4; 2005 break; 2006 case 0x39: 2007 config->data_rate = 50000; 2008 config->interface_type = phymodInterfaceKR4; 2009 break; 2010 case 0x3a: 2011 config->data_rate = 50000; 2012 config->interface_type = phymodInterfaceKR4; 2013 break; 2014 case 0x3c: 2015 config->data_rate = 53000; 2016 config->interface_type = phymodInterfaceCR4; 2017 break; 2018 case 0x3d: 2019 config->data_rate = 53000; 2020 config->interface_type = phymodInterfaceKR4; 2021 break; 2022 case 0x3e: 2023 config->data_rate = 53000; 2024 config->interface_type = phymodInterfaceKR4; 2025 break; 2026 case 0x40: 2027 config->data_rate = 100000; 2028 config->interface_type = phymodInterfaceCR4; 2029 break; 2030 case 0x41: 2031 config->data_rate = 100000; 2032 config->interface_type = phymodInterfaceKR4; 2033 break; 2034 case 0x42: 2035 config->data_rate = 100000; 2036 config->interface_type = phymodInterfaceKR4; 2037 break; 2038 case 0x44: 2039 config->data_rate = 106000; 2040 if (plldiv_r_val == 7) { 2041 config->data_rate = 100000; 2042 } 2043 config->interface_type = phymodInterfaceCR4; 2044 break; 2045 case 0x45: 2046 config->data_rate = 106000; 2047 if (plldiv_r_val == 7) { 2048 config->data_rate = 100000; 2049 } 2050 config->interface_type = phymodInterfaceKR4; 2051 break; 2052 case 0x46: 2053 config->data_rate = 106000; 2054 if (plldiv_r_val == 7) { 2055 config->data_rate = 100000; 2056 } 2057 config->interface_type = phymodInterfaceKR4; 2058 break; 2059 case 0x48: 2060 config->data_rate = 20000; 2061 config->interface_type = phymodInterfaceKR2; 2062 break; 2063 case 0x50: 2064 config->data_rate = 25000; 2065 config->interface_type = phymodInterfaceKR2; 2066 break; 2067 case 0x58: 2068 config->data_rate = 1000; 2069 config->interface_type = phymodInterfaceSGMII; 2070 break; 2071 case 0x60: 2072 config->data_rate = 1000; 2073 config->interface_type = phymodInterfaceSGMII; 2074 break; 2075 case 0x62: 2076 config->data_rate = 10000; 2077 config->interface_type = phymodInterfaceXAUI; 2078 break; 2079 /* 25G_CR_IEEE*/ 2080 case 0x70: 2081 config->data_rate = 25000; 2082 config->interface_type = phymodInterfaceCR; 2083 break; 2084 /* 25G_CRS_IEEE*/ 2085 case 0x71: 2086 config->data_rate = 25000; 2087 config->interface_type = phymodInterfaceCR; 2088 break; 2089 /* 25G_KR_IEEE*/ 2090 case 0x72: 2091 config->data_rate = 25000; 2092 config->interface_type = phymodInterfaceKR; 2093 break; 2094 /* 25G_KRS_IEEE*/ 2095 case 0x73: 2096 config->data_rate = 25000; 2097 config->interface_type = phymodInterfaceKR; 2098 break; 2099 default: 2100 config->data_rate = 10000; 2101 config->interface_type = phymodInterfaceKR; 2102 break; 2103 } 2104 } 2105 return PHYMOD_E_NONE; 2106 } 2107 2108 2109 2110 int tscf16_phy_interface_config_get(const phymod_phy_access_t* phy, uint32_t flags /*unused */, phymod_ref_clk_t ref_clock, phymod_phy_inf_config_t* config) 2111 { 2112 int speed_id; 2113 phymod_firmware_lane_config_t firmware_lane_config; 2114 phymod_phy_access_t pm_phy_copy; 2115 int start_lane, num_lane; 2116 phymod_autoneg_control_t an_control; 2117 int an_complete=0; 2118 2119 config->ref_clock = ref_clock; 2120 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2121 PHYMOD_MEMSET(&an_control, 0, sizeof(an_control)); 2122 2123 PHYMOD_IF_ERR_RETURN 2124 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2125 PHYMOD_IF_ERR_RETURN 2126 (tefmod16_speed_id_get(&phy->access, &speed_id)); 2127 PHYMOD_IF_ERR_RETURN 2128 (_tscf16_speed_id_interface_config_get(phy, speed_id, config)); 2129 2130 /* read the current media type */ 2131 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 2132 PHYMOD_IF_ERR_RETURN 2133 (tscf16_phy_firmware_lane_config_get(&pm_phy_copy, &firmware_lane_config)); 2134 if (firmware_lane_config.MediaType == phymodFirmwareMediaTypeOptics) { 2135 PHYMOD_INTF_MODES_FIBER_SET(config); 2136 } else if (firmware_lane_config.MediaType == phymodFirmwareMediaTypeCopperCable) { 2137 PHYMOD_INTF_MODES_FIBER_CLR(config); 2138 PHYMOD_INTF_MODES_COPPER_SET(config); 2139 } else { 2140 PHYMOD_INTF_MODES_FIBER_CLR(config); 2141 PHYMOD_INTF_MODES_BACKPLANE_SET(config); 2142 } 2143 /* next need to check for 40G 4 lanes mode, it's for XLAUI or KR4 */ 2144 if ((config->data_rate == 40000) && (!(firmware_lane_config.DfeOn)) && 2145 (firmware_lane_config.MediaType == phymodFirmwareMediaTypePcbTraceBackPlane)) { 2146 if (num_lane == 2) { 2147 config->interface_type = phymodInterfaceXLAUI2; 2148 } else { 2149 config->interface_type = phymodInterfaceXLAUI; 2150 } 2151 } 2152 2153 PHYMOD_IF_ERR_RETURN 2154 (tscf16_phy_autoneg_get(phy, &an_control, (uint32_t *) &an_complete)); 2155 2156 /* next need to check if we are CAUI4 100G mode */ 2157 if (!(an_control.enable && an_complete)) { 2158 if ((config->data_rate == 100000) && (firmware_lane_config.LpDfeOn) && 2159 (firmware_lane_config.MediaType == phymodFirmwareMediaTypePcbTraceBackPlane)) { 2160 config->interface_type = phymodInterfaceCAUI4; 2161 } 2162 } 2163 2164 switch (config->interface_type) { 2165 case phymodInterfaceSGMII: 2166 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 2167 config->interface_type = phymodInterface1000X; 2168 } else { 2169 config->interface_type = phymodInterfaceSGMII; 2170 } 2171 /* 2172 * Speed ID 0x58 and 0x60 are interpreted as phymodInterfaceSGMII 2173 * by _tscf_speed_id_interface_config_get(). This is correct when 2174 * the port is in forced speed mode. However, when AN is enabled 2175 * and completed the interface type cannot be SGMII because TSCF 2176 * does not support CL37 & CL37bam. The correct interface type in 2177 * this scenario should be phymodInterfaceKX. 2178 */ 2179 if (an_control.enable && an_complete) { 2180 config->interface_type = phymodInterfaceKX; 2181 } 2182 break; 2183 case phymodInterfaceXFI: 2184 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 2185 config->interface_type = phymodInterfaceCR; 2186 } else { 2187 config->interface_type = phymodInterfaceXFI; 2188 } 2189 break; 2190 case phymodInterfaceKR2: 2191 if (!an_control.enable) { 2192 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 2193 config->interface_type = phymodInterfaceSR2; 2194 } else { 2195 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 2196 config->interface_type = phymodInterfaceCR2; 2197 } else { 2198 config->interface_type = phymodInterfaceKR2; 2199 } 2200 } 2201 } 2202 break; 2203 case phymodInterfaceKR4: 2204 if (!an_control.enable) { 2205 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 2206 config->interface_type = phymodInterfaceSR4; 2207 } else { 2208 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 2209 config->interface_type = phymodInterfaceCR4; 2210 } else { 2211 config->interface_type = phymodInterfaceKR4; 2212 } 2213 } 2214 } 2215 break; 2216 case phymodInterfaceKR: 2217 { 2218 if (!an_control.enable) { 2219 if (config->data_rate == 10000) { 2220 if ( !PHYMOD_INTF_MODES_FIBER_GET(config)) { 2221 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 2222 config->interface_type = phymodInterfaceCR; 2223 } else { 2224 config->interface_type = phymodInterfaceXFI; 2225 } 2226 } else { 2227 config->interface_type = phymodInterfaceSFI; 2228 } 2229 } else { 2230 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 2231 config->interface_type = phymodInterfaceSR; 2232 } else { 2233 if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 2234 config->interface_type = phymodInterfaceCR; 2235 } else { 2236 config->interface_type = phymodInterfaceKR; 2237 } 2238 } 2239 } 2240 } else { 2241 config->interface_type = phymodInterfaceKR; 2242 } 2243 break; 2244 } 2245 2246 default: 2247 break; 2248 } 2249 2250 return PHYMOD_E_NONE; 2251 } 2252 2253 int tscf16_phy_training_tx_fir_post_set(const phymod_phy_access_t* phy, uint8_t tx_post) 2254 { 2255 phymod_phy_access_t phy_copy; 2256 int start_lane, num_lane, i; 2257 2258 PHYMOD_IF_ERR_RETURN 2259 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2260 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2261 2262 /* lane reset */ 2263 for (i = 0; i < num_lane; i++) { 2264 phy_copy.access.lane_mask = 1 << (start_lane + i); 2265 PHYMOD_IF_ERR_RETURN 2266 (falcon16_lane_soft_reset_release(&phy_copy.access, 0)); 2267 } 2268 2269 /* set TXFIR Post value in uC RAM*/ 2270 PHYMOD_IF_ERR_RETURN 2271 (falcon16_tsc_txfir_post_uc_set(&phy->access, tx_post)); 2272 2273 /* Release lane reset */ 2274 for (i = 0; i < num_lane; i++) { 2275 phy_copy.access.lane_mask = 1 << (start_lane + i); 2276 PHYMOD_IF_ERR_RETURN 2277 (falcon16_lane_soft_reset_release(&phy_copy.access, 1)); 2278 } 2279 2280 return PHYMOD_E_NONE; 2281 2282 } 2283 2284 int tscf16_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en) 2285 { 2286 struct falcon16_tsc_uc_lane_config_st serdes_firmware_config; 2287 PHYMOD_IF_ERR_RETURN(falcon16_tsc_get_uc_lane_cfg(&phy->access, &serdes_firmware_config)); 2288 2289 if (serdes_firmware_config.field.dfe_on == 0) { 2290 PHYMOD_DEBUG_ERROR(("ERROR :: DFE is off : Can not start CL72/CL93 with no DFE\n")); 2291 return PHYMOD_E_CONFIG; 2292 } 2293 2294 PHYMOD_IF_ERR_RETURN 2295 (tefmod16_clause72_control(&phy->access, cl72_en)); 2296 2297 2298 return PHYMOD_E_NONE; 2299 2300 } 2301 2302 int tscf16_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en) 2303 { 2304 PHYMOD_IF_ERR_RETURN 2305 (falcon16_clause72_control_get(&phy->access, cl72_en)); 2306 2307 return PHYMOD_E_NONE; 2308 2309 } 2310 2311 2312 int tscf16_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status) 2313 { 2314 uint32_t local_status; 2315 2316 PHYMOD_IF_ERR_RETURN 2317 (falcon16_pmd_cl72_receiver_status(&phy->access, &local_status)); 2318 status->locked = local_status; 2319 2320 2321 return PHYMOD_E_NONE; 2322 2323 } 2324 2325 2326 int tscf16_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability) 2327 { 2328 2329 tefmod16_an_adv_ability_t value; 2330 int start_lane, num_lane; 2331 phymod_phy_access_t phy_copy; 2332 phymod_core_info_t core_info; 2333 2334 /* next program the tx fir taps and driver current based on the input */ 2335 PHYMOD_IF_ERR_RETURN 2336 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2337 2338 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2339 phy_copy.access.lane_mask = 0x1 << start_lane; 2340 2341 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 2342 PHYMOD_MEMSET(&core_info, 0x0, sizeof(core_info)); 2343 2344 PHYMOD_IF_ERR_RETURN 2345 (tscf16_core_info_get((phymod_core_access_t *)phy, &core_info)); 2346 2347 value.an_cl72 = an_ability->an_cl72; 2348 2349 /* Check FEC/CL74/CL91 support */ 2350 if (PHYMOD_AN_FEC_OFF_GET(an_ability->an_fec)) { 2351 value.an_fec = TEFMOD16_FEC_SUPRTD_NOT_REQSTD; 2352 } else { 2353 if (PHYMOD_AN_FEC_CL74_GET(an_ability->an_fec)) 2354 value.an_fec = TEFMOD16_FEC_CL74_SUPRTD_REQSTD; 2355 if (PHYMOD_AN_FEC_CL91_GET(an_ability->an_fec)) 2356 value.an_fec |= TEFMOD16_FEC_CL91_SUPRTD_REQSTD; 2357 } 2358 2359 value.an_hg2 = an_ability->an_hg2; 2360 2361 /* Check pause */ 2362 if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability)) { 2363 value.an_pause = TEFMOD16_SYMM_PAUSE; 2364 } 2365 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 2366 value.an_pause = TEFMOD16_ASYM_PAUSE; 2367 } 2368 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 2369 value.an_pause = TEFMOD16_ASYM_SYMM_PAUSE; 2370 } 2371 2372 /* Check cl73 ability */ 2373 if (PHYMOD_AN_CAP_1G_KX_GET(an_ability->an_cap)){ 2374 value.an_base_speed |= 1 << TEFMOD16_CL73_1GBASE_KX; 2375 } 2376 if (PHYMOD_AN_CAP_10G_KR_GET(an_ability->an_cap)) { 2377 value.an_base_speed |= 1 << TEFMOD16_CL73_10GBASE_KR1; 2378 } 2379 if (PHYMOD_AN_CAP_40G_KR4_GET(an_ability->an_cap)) { 2380 value.an_base_speed |= 1 << TEFMOD16_CL73_40GBASE_KR4; 2381 } 2382 if (PHYMOD_AN_CAP_40G_CR4_GET(an_ability->an_cap)) { 2383 value.an_base_speed |= 1 << TEFMOD16_CL73_40GBASE_CR4; 2384 } 2385 if (PHYMOD_AN_CAP_100G_KR4_GET(an_ability->an_cap)) { 2386 value.an_base_speed |= 1 << TEFMOD16_CL73_100GBASE_KR4; 2387 } 2388 if (PHYMOD_AN_CAP_100G_CR4_GET(an_ability->an_cap)) { 2389 value.an_base_speed |= 1 << TEFMOD16_CL73_100GBASE_CR4; 2390 } 2391 if (PHYMOD_AN_CAP_25G_CR1_GET(an_ability->an_cap)) { 2392 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_CR1; 2393 } 2394 if (PHYMOD_AN_CAP_25G_KR1_GET(an_ability->an_cap)) { 2395 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_KR1; 2396 } 2397 if (PHYMOD_AN_CAP_25G_CRS1_GET(an_ability->an_cap)) { 2398 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_CRS1; 2399 } 2400 if (PHYMOD_AN_CAP_25G_KRS1_GET(an_ability->an_cap)) { 2401 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_KRS1; 2402 } 2403 /* check cl73 bam ability */ 2404 if (PHYMOD_BAM_CL73_CAP_20G_KR2_GET(an_ability->cl73bam_cap)) { 2405 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_20GBASE_KR2; 2406 } 2407 if (PHYMOD_BAM_CL73_CAP_20G_CR2_GET(an_ability->cl73bam_cap)) { 2408 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_20GBASE_CR2; 2409 } 2410 if (PHYMOD_BAM_CL73_CAP_40G_KR2_GET(an_ability->cl73bam_cap)) { 2411 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_40GBASE_KR2; 2412 } 2413 if (PHYMOD_BAM_CL73_CAP_40G_CR2_GET(an_ability->cl73bam_cap)) { 2414 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_40GBASE_CR2; 2415 } 2416 if (PHYMOD_BAM_CL73_CAP_50G_KR2_GET(an_ability->cl73bam_cap)) { 2417 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_KR2; 2418 } 2419 if (PHYMOD_BAM_CL73_CAP_50G_CR2_GET(an_ability->cl73bam_cap)) { 2420 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_CR2; 2421 } 2422 /* 50G 4-lane is not supported for TSCF16(TH2 and TD3) chips 2423 if (PHYMOD_BAM_CL73_CAP_50G_KR4_GET(an_ability->cl73bam_cap)) { 2424 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_KR4; 2425 } 2426 if (PHYMOD_BAM_CL73_CAP_50G_CR4_GET(an_ability->cl73bam_cap)) { 2427 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_CR4; 2428 }*/ 2429 2430 if (PHYMOD_BAM_CL73_CAP_20G_KR1_GET(an_ability->cl73bam_cap)) { 2431 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_20GBASE_KR1; 2432 } 2433 if (PHYMOD_BAM_CL73_CAP_20G_CR1_GET(an_ability->cl73bam_cap)) { 2434 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_20GBASE_CR1; 2435 } 2436 if (PHYMOD_BAM_CL73_CAP_25G_KR1_GET(an_ability->cl73bam_cap)) { 2437 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_25GBASE_KR1; 2438 } 2439 if (PHYMOD_BAM_CL73_CAP_25G_CR1_GET(an_ability->cl73bam_cap)) { 2440 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_25GBASE_CR1; 2441 } 2442 2443 PHYMOD_IF_ERR_RETURN 2444 (tefmod16_autoneg_set(&phy_copy.access, &value)); 2445 2446 return PHYMOD_E_NONE; 2447 2448 } 2449 2450 int tscf16_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 2451 { 2452 tefmod16_an_adv_ability_t value; 2453 phymod_phy_access_t phy_copy; 2454 int start_lane, num_lane; 2455 2456 PHYMOD_IF_ERR_RETURN 2457 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2458 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2459 phy_copy.access.lane_mask = 0x1 << start_lane; 2460 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 2461 2462 PHYMOD_IF_ERR_RETURN 2463 (tefmod16_autoneg_local_ability_get(&phy_copy.access, &value)); 2464 2465 an_ability_get_type->an_cl72 = value.an_cl72; 2466 an_ability_get_type->an_hg2 = value.an_hg2; 2467 2468 an_ability_get_type->an_fec = 0; 2469 if (value.an_fec == TEFMOD16_FEC_SUPRTD_NOT_REQSTD) { 2470 PHYMOD_AN_FEC_OFF_SET(an_ability_get_type->an_fec); 2471 } else { 2472 if (value.an_fec == TEFMOD16_FEC_CL74_SUPRTD_REQSTD) { 2473 PHYMOD_AN_FEC_CL74_SET(an_ability_get_type->an_fec); 2474 } 2475 if (value.an_fec == TEFMOD16_FEC_CL91_SUPRTD_REQSTD) { 2476 PHYMOD_AN_FEC_CL91_SET(an_ability_get_type->an_fec); 2477 } 2478 } 2479 2480 if (value.an_pause == TEFMOD16_ASYM_PAUSE) { 2481 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 2482 } else if (value.an_pause == TEFMOD16_SYMM_PAUSE) { 2483 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 2484 } else if (value.an_pause == TEFMOD16_ASYM_SYMM_PAUSE) { 2485 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 2486 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 2487 } 2488 2489 /* First check cl73 base ability */ 2490 if (value.an_base_speed & 1 << TEFMOD16_CL73_100GBASE_CR4) { 2491 PHYMOD_AN_CAP_100G_CR4_SET(an_ability_get_type->an_cap); 2492 } 2493 if (value.an_base_speed & 1 << TEFMOD16_CL73_100GBASE_KR4) { 2494 PHYMOD_AN_CAP_100G_KR4_SET(an_ability_get_type->an_cap); 2495 } 2496 if (value.an_base_speed & 1 << TEFMOD16_CL73_40GBASE_CR4) { 2497 PHYMOD_AN_CAP_40G_CR4_SET(an_ability_get_type->an_cap); 2498 } 2499 if (value.an_base_speed & 1 << TEFMOD16_CL73_40GBASE_KR4) { 2500 PHYMOD_AN_CAP_40G_KR4_SET(an_ability_get_type->an_cap); 2501 } 2502 if (value.an_base_speed & 1 << TEFMOD16_CL73_10GBASE_KR1) { 2503 PHYMOD_AN_CAP_10G_KR_SET(an_ability_get_type->an_cap); 2504 } 2505 if (value.an_base_speed & 1 << TEFMOD16_CL73_1GBASE_KX) { 2506 PHYMOD_AN_CAP_1G_KX_SET(an_ability_get_type->an_cap); 2507 } 2508 if (value.an_base_speed & 1 << TEFMOD16_CL73_25GBASE_KR1) { 2509 PHYMOD_AN_CAP_25G_KR1_SET(an_ability_get_type->an_cap); 2510 } 2511 if (value.an_base_speed & 1 << TEFMOD16_CL73_25GBASE_CR1) { 2512 PHYMOD_AN_CAP_25G_CR1_SET(an_ability_get_type->an_cap); 2513 } 2514 if (value.an_base_speed & 1 << TEFMOD16_CL73_25GBASE_KRS1) { 2515 PHYMOD_AN_CAP_25G_KRS1_SET(an_ability_get_type->an_cap); 2516 } 2517 if (value.an_base_speed & 1 << TEFMOD16_CL73_25GBASE_CRS1) { 2518 PHYMOD_AN_CAP_25G_CRS1_SET(an_ability_get_type->an_cap); 2519 } 2520 2521 /* Next check cl73 bam ability */ 2522 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_20GBASE_KR2) { 2523 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_ability_get_type->cl73bam_cap); 2524 } 2525 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_20GBASE_CR2) { 2526 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_ability_get_type->cl73bam_cap); 2527 } 2528 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_40GBASE_KR2) { 2529 PHYMOD_BAM_CL73_CAP_40G_KR2_SET(an_ability_get_type->cl73bam_cap); 2530 } 2531 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_40GBASE_CR2) { 2532 PHYMOD_BAM_CL73_CAP_40G_CR2_SET(an_ability_get_type->cl73bam_cap); 2533 } 2534 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_50GBASE_KR2) { 2535 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_ability_get_type->cl73bam_cap); 2536 } 2537 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_50GBASE_CR2) { 2538 PHYMOD_BAM_CL73_CAP_50G_CR2_SET(an_ability_get_type->cl73bam_cap); 2539 } 2540 /* 2541 * 50G 4-lane is not supported for TSCF16(TH2 and TD3) chips. 2542 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_50GBASE_KR4) { 2543 PHYMOD_BAM_CL73_CAP_50G_KR4_SET(an_ability_get_type->cl73bam_cap); 2544 } 2545 if (value.an_bam_speed & 1 << TEFMOD16_CL73_BAM_50GBASE_CR4) { 2546 PHYMOD_BAM_CL73_CAP_50G_CR4_SET(an_ability_get_type->cl73bam_cap); 2547 } 2548 */ 2549 if (value.an_bam_speed1 & 1 << TEFMOD16_CL73_BAM_20GBASE_KR1) { 2550 PHYMOD_BAM_CL73_CAP_20G_KR1_SET(an_ability_get_type->cl73bam_cap); 2551 } 2552 if (value.an_bam_speed1 & 1 << TEFMOD16_CL73_BAM_20GBASE_CR1) { 2553 PHYMOD_BAM_CL73_CAP_20G_CR1_SET(an_ability_get_type->cl73bam_cap); 2554 } 2555 if (value.an_bam_speed1 & 1 << TEFMOD16_CL73_BAM_25GBASE_KR1) { 2556 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_ability_get_type->cl73bam_cap); 2557 } 2558 if (value.an_bam_speed1 & 1 << TEFMOD16_CL73_BAM_25GBASE_CR1) { 2559 PHYMOD_BAM_CL73_CAP_25G_CR1_SET(an_ability_get_type->cl73bam_cap); 2560 } 2561 2562 return PHYMOD_E_NONE; 2563 2564 } 2565 2566 2567 int tscf16_phy_autoneg_remote_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 2568 { 2569 tefmod16_an_adv_ability_t value; 2570 2571 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 2572 PHYMOD_IF_ERR_RETURN 2573 (tefmod16_autoneg_lp_status_get(&phy->access, &value)); 2574 2575 /* cl73 technology abilities A0 - D21 */ 2576 if (value.an_base_speed & ( 1 << TEFMOD16_CL73_1GBASE_KX)){ 2577 PHYMOD_AN_CAP_1G_KX_SET(an_ability_get_type->an_cap); 2578 } 2579 2580 /* cl73 technology abilities A2 - D23 */ 2581 if (value.an_base_speed & (1 << TEFMOD16_CL73_10GBASE_KR1)){ 2582 PHYMOD_AN_CAP_10G_KR_SET(an_ability_get_type->an_cap); 2583 } 2584 /* cl73 technology abilities A3 - D24 */ 2585 if (value.an_base_speed & ( 1 << TEFMOD16_CL73_40GBASE_KR4)){ 2586 PHYMOD_AN_CAP_40G_KR4_SET(an_ability_get_type->an_cap); 2587 } 2588 /* cl73 technology abilities A4 - D25 */ 2589 if (value.an_base_speed & ( 1 << TEFMOD16_CL73_40GBASE_CR4)){ 2590 PHYMOD_AN_CAP_40G_CR4_SET(an_ability_get_type->an_cap); 2591 } 2592 /* cl73 technology abilities A7 - D28 */ 2593 if (value.an_base_speed & (1 << TEFMOD16_CL73_100GBASE_KR4)){ 2594 PHYMOD_AN_CAP_100G_KR4_SET(an_ability_get_type->an_cap); 2595 } 2596 /* cl73 technology abilities A8 - D29 */ 2597 if (value.an_base_speed & (1 << TEFMOD16_CL73_100GBASE_CR4)){ 2598 PHYMOD_AN_CAP_100G_CR4_SET(an_ability_get_type->an_cap); 2599 } 2600 /* cl73 technology abilities A9 - D30 */ 2601 if (value.an_base_speed & (1 << TEFMOD16_CL73_25GBASE_KRS1)) { 2602 PHYMOD_AN_CAP_25G_KRS1_SET(an_ability_get_type->an_cap); 2603 } 2604 if (value.an_base_speed & (1 << TEFMOD16_CL73_25GBASE_CRS1)) { 2605 PHYMOD_AN_CAP_25G_CRS1_SET(an_ability_get_type->an_cap); 2606 } 2607 /* cl73 technology abilities A10 - D31 */ 2608 if (value.an_base_speed & (1 << TEFMOD16_CL73_25GBASE_KR1)) { 2609 PHYMOD_AN_CAP_25G_KR1_SET(an_ability_get_type->an_cap); 2610 } 2611 if (value.an_base_speed & (1 << TEFMOD16_CL73_25GBASE_CR1)) { 2612 PHYMOD_AN_CAP_25G_CR1_SET(an_ability_get_type->an_cap); 2613 } 2614 2615 /* FEC[F0:F1] is encoded in bits [D44:D47] */ 2616 an_ability_get_type->an_fec = 0; 2617 if ((value.an_fec == TEFMOD16_FEC_SUPRTD_NOT_REQSTD) 2618 || (value.an_fec == TEFMOD16_FEC_NOT_SUPRTD)) { 2619 PHYMOD_AN_FEC_OFF_SET(an_ability_get_type->an_fec); 2620 } else { 2621 if (value.an_fec & TEFMOD16_FEC_CL74_SUPRTD_REQSTD) { 2622 PHYMOD_AN_FEC_CL74_SET(an_ability_get_type->an_fec); 2623 } 2624 if (value.an_fec & TEFMOD16_FEC_CL91_SUPRTD_REQSTD) { 2625 PHYMOD_AN_FEC_CL91_SET(an_ability_get_type->an_fec); 2626 } 2627 } 2628 2629 /* advertise pause capabilities C[0:1] - D[10:11]*/ 2630 if (value.an_pause & TEFMOD16_SYMM_PAUSE) { 2631 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 2632 } 2633 if (value.an_pause & TEFMOD16_ASYM_PAUSE) { 2634 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 2635 } 2636 2637 /* BAM73 OUI UP bit 16 */ 2638 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_20GBASE_KR2)) { 2639 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_ability_get_type->cl73bam_cap); 2640 } 2641 /* BAM73 OUI UP bit 17 */ 2642 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_20GBASE_CR2)) { 2643 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_ability_get_type->cl73bam_cap); 2644 } 2645 /* BAM73 OUI UP bit 18 */ 2646 if (value.an_bam_speed1 & (1 << TEFMOD16_CL73_BAM_20GBASE_KR1)) { 2647 PHYMOD_BAM_CL73_CAP_20G_KR1_SET(an_ability_get_type->cl73bam_cap); 2648 } 2649 /* BAM73 OUI UP bit 19 */ 2650 if (value.an_bam_speed1 & (1 << TEFMOD16_CL73_BAM_20GBASE_CR1)) { 2651 PHYMOD_BAM_CL73_CAP_20G_CR1_SET(an_ability_get_type->cl73bam_cap); 2652 } 2653 /* BAM73 OUI UP bit 20 */ 2654 if (value.an_bam_speed1 & (1 << TEFMOD16_CL73_BAM_25GBASE_KR1)) { 2655 PHYMOD_BAM_CL73_CAP_25G_KR1_SET(an_ability_get_type->cl73bam_cap); 2656 } 2657 /* BAM73 OUI UP bit 21 */ 2658 if (value.an_bam_speed1 & (1 << TEFMOD16_CL73_BAM_25GBASE_CR1)) { 2659 PHYMOD_BAM_CL73_CAP_25G_CR1_SET(an_ability_get_type->cl73bam_cap); 2660 } 2661 /* BAM73 OUI UP bit 22 */ 2662 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_40GBASE_KR2)) { 2663 PHYMOD_BAM_CL73_CAP_40G_KR2_SET(an_ability_get_type->cl73bam_cap); 2664 } 2665 /* BAM73 OUI UP bit 23 */ 2666 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_40GBASE_CR2)) { 2667 PHYMOD_BAM_CL73_CAP_40G_CR2_SET(an_ability_get_type->cl73bam_cap); 2668 } 2669 /* BAM73 OUI UP bit 24 */ 2670 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_50GBASE_KR2)) { 2671 PHYMOD_BAM_CL73_CAP_50G_KR2_SET(an_ability_get_type->cl73bam_cap); 2672 } 2673 /* BAM73 OUI UP bit 25 */ 2674 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_50GBASE_CR2)) { 2675 PHYMOD_BAM_CL73_CAP_50G_CR2_SET(an_ability_get_type->cl73bam_cap); 2676 } 2677 /* 50G 4-lane is not supported for TSCF16(TH2 and TD3) */ 2678 /* BAM73 OUI UP bit 32 */ 2679 /* 2680 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_50GBASE_KR4)) { 2681 PHYMOD_BAM_CL73_CAP_50G_KR4_SET(an_ability_get_type->cl73bam_cap); 2682 }*/ 2683 2684 /* BAM73 OUI UP bit 33 */ 2685 /* 2686 if (value.an_bam_speed & (1 << TEFMOD16_CL73_BAM_50GBASE_CR4)) { 2687 PHYMOD_BAM_CL73_CAP_50G_CR4_SET(an_ability_get_type->cl73bam_cap); 2688 } 2689 */ 2690 2691 return PHYMOD_E_NONE; 2692 2693 } 2694 2695 2696 int tscf16_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 2697 { 2698 int num_lane_adv_encoded; 2699 int start_lane, num_lane; 2700 int i, an_enable_bitmap, single_port_mode = 0; 2701 int do_lane_config_set, do_core_config_set; 2702 phymod_firmware_lane_config_t firmware_lane_config; 2703 phymod_firmware_core_config_t firmware_core_config_tmp; 2704 tefmod16_an_control_t an_control; 2705 phymod_phy_access_t phy_copy; 2706 2707 /* TSCF16 doesn't support 10G KX4 parallel detection */ 2708 if(PHYMOD_AN_F_SET_CL73_PDET_KX4_ENABLE_GET(an)) { 2709 return PHYMOD_E_UNAVAIL; 2710 } 2711 2712 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 2713 PHYMOD_MEMSET(&firmware_core_config_tmp, 0x0, sizeof(firmware_core_config_tmp)); 2714 2715 PHYMOD_MEMSET(&an_control, 0x0, sizeof(an_control)); 2716 PHYMOD_IF_ERR_RETURN 2717 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2718 2719 if (PHYMOD_AN_F_ALLOW_PLL_CHANGE_GET(an) || (num_lane == 0x4)) { 2720 single_port_mode = 1; 2721 } 2722 2723 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2724 phy_copy.access.lane_mask = 0x1 << start_lane; 2725 2726 switch (an->num_lane_adv) { 2727 case 1: 2728 num_lane_adv_encoded = 0; 2729 break; 2730 case 2: 2731 num_lane_adv_encoded = 1; 2732 break; 2733 case 4: 2734 num_lane_adv_encoded = 2; 2735 break; 2736 case 10: 2737 num_lane_adv_encoded = 3; 2738 break; 2739 default: 2740 return PHYMOD_E_PARAM; 2741 } 2742 2743 /* first check if cl72 is allowed to change */ 2744 if (PHYMOD_AN_F_ALLOW_CL72_CONFIG_CHANGE_GET(an)) { 2745 an_control.cl72_config_allowed = 1; 2746 } else { 2747 an_control.cl72_config_allowed = 0; 2748 } 2749 2750 if (PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_GET(an)) { 2751 an_control.pd_kx_en = 1 ; 2752 } 2753 an_control.num_lane_adv = num_lane_adv_encoded; 2754 an_control.enable = an->enable; 2755 an_control.an_property_type = 0x0; /* for now disable */ 2756 switch (an->an_mode) { 2757 case phymod_AN_MODE_CL73: 2758 an_control.an_type = TEFMOD16_AN_MODE_CL73; 2759 break; 2760 case phymod_AN_MODE_CL73BAM: 2761 an_control.an_type = TEFMOD16_AN_MODE_CL73_BAM; 2762 break; 2763 case phymod_AN_MODE_MSA: 2764 an_control.an_type = TEFMOD16_AN_MODE_MSA; 2765 break; 2766 case phymod_AN_MODE_CL73_MSA: 2767 an_control.an_type = TEFMOD16_AN_MODE_CL73_MSA; 2768 break; 2769 case phymod_AN_MODE_HPAM: 2770 an_control.an_type = TEFMOD16_AN_MODE_HPAM; 2771 break; 2772 default: 2773 an_control.an_type = TEFMOD16_AN_MODE_CL73; 2774 break; 2775 } 2776 2777 tefmod16_disable_set(&phy->access); 2778 2779 if (single_port_mode) { 2780 PHYMOD_IF_ERR_RETURN 2781 (tefmod16_set_an_single_port_mode(&phy->access, an->enable)); 2782 } 2783 /* first check if any other lane has An on */ 2784 an_enable_bitmap = 0; 2785 if (!an->enable) { 2786 for (i = 0; i < 4; i++ ) { 2787 phy_copy.access.lane_mask = 0x1 << i; 2788 if (phy_copy.access.lane_mask & phy->access.lane_mask) continue; 2789 PHYMOD_IF_ERR_RETURN 2790 (tscf16_phy_firmware_lane_config_get(&phy_copy, &firmware_lane_config)); 2791 if (firmware_lane_config.AnEnabled) { 2792 an_enable_bitmap |= 1 << i; 2793 } 2794 } 2795 2796 } 2797 2798 phy_copy.access.lane_mask = 0x1 << start_lane; 2799 2800 /* make sure the firmware config is set to an enabled */ 2801 PHYMOD_IF_ERR_RETURN 2802 (tscf16_phy_firmware_lane_config_get(&phy_copy, &firmware_lane_config)); 2803 /* make sure the firmware config is set to an enabled */ 2804 PHYMOD_IF_ERR_RETURN 2805 (tscf16_phy_firmware_core_config_get(&phy_copy, &firmware_core_config_tmp)); 2806 do_lane_config_set = 0; 2807 do_core_config_set = 0; 2808 2809 if (an->enable) { 2810 if (firmware_lane_config.AnEnabled != 1) { 2811 firmware_lane_config.AnEnabled = 1; 2812 do_lane_config_set = 1; 2813 } 2814 if (firmware_lane_config.LaneConfigFromPCS != 1) { 2815 firmware_lane_config.LaneConfigFromPCS = 1; 2816 do_lane_config_set = 1; 2817 } 2818 if (firmware_core_config_tmp.CoreConfigFromPCS != 1) { 2819 firmware_core_config_tmp.CoreConfigFromPCS = 1; 2820 do_core_config_set = 1; 2821 } 2822 firmware_lane_config.Cl72RestTO = 0; 2823 } else { 2824 if (firmware_lane_config.AnEnabled != 0) { 2825 firmware_lane_config.AnEnabled = 0; 2826 do_lane_config_set = 1; 2827 } 2828 if (firmware_lane_config.LaneConfigFromPCS != 0) { 2829 firmware_lane_config.LaneConfigFromPCS = 0; 2830 do_lane_config_set = 1; 2831 } 2832 if (firmware_core_config_tmp.CoreConfigFromPCS != 0) { 2833 if (!an_enable_bitmap) { 2834 firmware_core_config_tmp.CoreConfigFromPCS = 0; 2835 do_core_config_set = 1; 2836 } 2837 } 2838 firmware_lane_config.Cl72RestTO = 1; 2839 } 2840 2841 if (do_core_config_set && single_port_mode) { 2842 PHYMOD_IF_ERR_RETURN 2843 (falcon16_tsc_core_dp_reset(&phy_copy.access, 1)); 2844 PHYMOD_USLEEP(1000); 2845 2846 PHYMOD_IF_ERR_RETURN 2847 (tscf16_phy_firmware_core_config_set(&phy_copy, firmware_core_config_tmp)); 2848 2849 PHYMOD_IF_ERR_RETURN 2850 (falcon16_tsc_core_dp_reset(&phy_copy.access, 0)); 2851 } 2852 2853 /* To support 10G AN @25G VCO, need to override the speed id S_10G_KR1(0x1)*/ 2854 if (firmware_core_config_tmp.osr_2p5_available) { 2855 PHYMOD_IF_ERR_RETURN 2856 (tefmod16_override_10g_kr1_spd_intf(&phy->access, an->enable)); 2857 } 2858 2859 if (do_lane_config_set) { 2860 for (i = 0; i < num_lane; i++) { 2861 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2862 continue; 2863 } 2864 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2865 PHYMOD_IF_ERR_RETURN 2866 (falcon16_lane_soft_reset_release(&phy_copy.access, 0)); 2867 } 2868 PHYMOD_USLEEP(1000); 2869 for (i = 0; i < num_lane; i++) { 2870 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2871 continue; 2872 } 2873 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2874 PHYMOD_IF_ERR_RETURN 2875 (_tscf16_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config)); 2876 } 2877 2878 for (i = 0; i < num_lane; i++) { 2879 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2880 continue; 2881 } 2882 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2883 PHYMOD_IF_ERR_RETURN 2884 (falcon16_lane_soft_reset_release(&phy_copy.access, 1)); 2885 } 2886 } 2887 2888 phy_copy.access.lane_mask = 0x1 << start_lane; 2889 2890 if (an->enable && single_port_mode) { 2891 PHYMOD_IF_ERR_RETURN 2892 (tefmod16_master_port_num_set(&phy_copy.access, start_lane)); 2893 } 2894 2895 PHYMOD_IF_ERR_RETURN 2896 (tefmod16_autoneg_control(&phy_copy.access, &an_control)); 2897 2898 if (!an->enable) { 2899 PHYMOD_IF_ERR_RETURN(tefmod16_enable_set(&phy->access)); 2900 } 2901 2902 return PHYMOD_E_NONE; 2903 2904 } 2905 2906 int tscf16_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done) 2907 { 2908 tefmod16_an_control_t an_control; 2909 phymod_phy_access_t phy_copy; 2910 int start_lane, num_lane; 2911 int an_complete = 0; 2912 2913 /* next program the tx fir taps and driver current based on the input */ 2914 PHYMOD_IF_ERR_RETURN 2915 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2916 2917 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2918 phy_copy.access.lane_mask = 0x1 << start_lane; 2919 2920 PHYMOD_MEMSET(&an_control, 0x0, sizeof(tefmod16_an_control_t)); 2921 PHYMOD_IF_ERR_RETURN 2922 (tefmod16_autoneg_control_get(&phy_copy.access, &an_control, &an_complete)); 2923 2924 if (an_control.enable) { 2925 an->enable = 1; 2926 *an_done = an_complete; 2927 } else { 2928 an->enable = 0; 2929 } 2930 2931 if(an_control.pd_kx_en) { 2932 PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_SET(an); 2933 } else { 2934 PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_CLR(an); 2935 } 2936 2937 switch (an_control.an_type) { 2938 case TEFMOD16_AN_MODE_CL73: 2939 an->an_mode = phymod_AN_MODE_CL73; 2940 break; 2941 case TEFMOD16_AN_MODE_CL73_BAM: 2942 an->an_mode = phymod_AN_MODE_CL73BAM; 2943 break; 2944 case TEFMOD16_AN_MODE_MSA: 2945 an->an_mode = phymod_AN_MODE_MSA; 2946 break; 2947 case TEFMOD16_AN_MODE_CL73_MSA: 2948 an->an_mode = phymod_AN_MODE_CL73_MSA; 2949 break; 2950 case TEFMOD16_AN_MODE_HPAM: 2951 an->an_mode = phymod_AN_MODE_HPAM; 2952 break; 2953 default: 2954 an->an_mode = phymod_AN_MODE_NONE; 2955 break; 2956 } 2957 2958 return PHYMOD_E_NONE; 2959 2960 } 2961 2962 2963 int tscf16_phy_autoneg_status_get(const phymod_phy_access_t* phy, phymod_autoneg_status_t* status) 2964 { 2965 int speed_id, an_en, an_done; 2966 phymod_phy_inf_config_t config; 2967 phymod_ref_clk_t ref_clock; 2968 const phymod_access_t *pm_acc = &phy->access; 2969 2970 PHYMOD_IF_ERR_RETURN 2971 (tefmod16_autoneg_status_get(&phy->access, &an_en, &an_done)); 2972 2973 PHYMOD_IF_ERR_RETURN 2974 (tefmod16_speed_id_get(&phy->access, &speed_id)); 2975 2976 PHYMOD_IF_ERR_RETURN 2977 (tefmod16_refclk_get(pm_acc, &ref_clock)); 2978 2979 config.ref_clock = ref_clock; 2980 PHYMOD_IF_ERR_RETURN 2981 (_tscf16_speed_id_interface_config_get(phy, speed_id, &config)); 2982 2983 status->enabled = an_en; 2984 status->locked = an_done; 2985 status->data_rate = config.data_rate; 2986 status->interface = config.interface_type; 2987 2988 return PHYMOD_E_NONE; 2989 } 2990 2991 2992 /* Core initialization 2993 * 1. De-assert PMD core and PMD lane reset 2994 * 2. Set heartbeat for comclk 2995 * 3. Configure lane mapping 2996 * 4. Micro code load and verify 2997 * 5. De-assert micro reset 2998 * 6. Wait for uc_active = 1 2999 * 7. Initialize software information table for the micro 3000 * 8. PLL configuration 3001 * 9. Release core DP soft reset 3002 */ 3003 STATIC 3004 int _tscf16_core_init_post_firmware_load(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 3005 { 3006 phymod_phy_access_t phy_access, phy_access_copy; 3007 phymod_core_access_t core_copy; 3008 3009 TSCF16_CORE_TO_PHY_ACCESS(&phy_access, core); 3010 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 3011 core_copy.access.lane_mask = 0x1; 3012 3013 phy_access_copy = phy_access; 3014 phy_access_copy.access = core->access; 3015 phy_access_copy.access.lane_mask = 0x1; 3016 phy_access_copy.type = core->type; 3017 3018 /* need to check if the ucode load is correct or not */ 3019 #ifndef TSCF16_PMD_CRC_UCODE_VERIFY 3020 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 3021 int rv; 3022 3023 rv = falcon16_tsc_ucode_load_verify(&core_copy.access, (uint8_t *) &falcon16_ucode, falcon16_ucode_len); 3024 if (rv != PHYMOD_E_NONE) { 3025 PHYMOD_DEBUG_ERROR(("devad 0x%x lane 0x%x: UC load-verify failed\n", core->access.addr, core->access.lane_mask)); 3026 PHYMOD_IF_ERR_RETURN(rv); 3027 } 3028 } 3029 #endif 3030 3031 /* 5. De-assert micro reset */ 3032 PHYMOD_IF_ERR_RETURN 3033 (falcon16_tsc_uc_reset(&core_copy.access, 0)); 3034 3035 /* 6. Wait for uc_active = 1 */ 3036 PHYMOD_IF_ERR_RETURN 3037 (falcon16_tsc_wait_uc_active(&phy_access.access)); 3038 3039 /* pmd lane hard reset */ 3040 PHYMOD_IF_ERR_RETURN 3041 (falcon16_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x1)); 3042 3043 /* 7. Initialize software information table for the micro */ 3044 PHYMOD_IF_ERR_RETURN 3045 (falcon16_tsc_init_falcon16_tsc_info(&core_copy.access)); 3046 3047 if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 3048 #ifdef TSCF16_PMD_CRC_UCODE_VERIFY 3049 PHYMOD_IF_ERR_RETURN( 3050 falcon16_tsc_start_ucode_crc_calc(&core_copy.access, falcon16_ucode_len)); 3051 #endif 3052 } 3053 3054 return PHYMOD_E_NONE; 3055 } 3056 3057 STATIC 3058 int _tscf16_core_init_pass1(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 3059 { 3060 int rv, lane; 3061 phymod_phy_access_t phy_access; 3062 phymod_core_access_t core_copy; 3063 uint32_t uc_enable = 0; 3064 3065 TSCF16_CORE_TO_PHY_ACCESS(&phy_access, core); 3066 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 3067 core_copy.access.lane_mask = 0x1; 3068 3069 /* 1. De-assert PMD core power and core data path reset */ 3070 PHYMOD_IF_ERR_RETURN 3071 (tefmod16_pmd_reset_seq(&core_copy.access, core_status->pmd_active)); 3072 3073 /* De-assert PMD lane reset */ 3074 for (lane = 0; lane < TSCF16_NOF_LANES_IN_CORE; lane++) { 3075 phy_access.access.lane_mask = 1 << lane; 3076 PHYMOD_IF_ERR_RETURN 3077 (tefmod16_pmd_x4_reset(&phy_access.access)); 3078 } 3079 3080 /* 2. Set the heart beat, default is for 156.25M */ 3081 if (init_config->interface.ref_clock == phymodRefClk125Mhz) { 3082 PHYMOD_IF_ERR_RETURN 3083 (tefmod16_refclk_set(&core_copy.access, phymodRefClk125Mhz)); 3084 } 3085 3086 /* 3. Configure lane mapping */ 3087 PHYMOD_IF_ERR_RETURN 3088 (tscf16_core_lane_map_set(&core_copy, &init_config->lane_map)); 3089 3090 PHYMOD_IF_ERR_RETURN 3091 (falcon16_uc_active_get(&phy_access.access, &uc_enable)); 3092 if (uc_enable) return PHYMOD_E_NONE; 3093 3094 #ifndef FW_BCAST_DOWNLOAD 3095 /* 4. Micro code load and verify */ 3096 rv = _tscf16_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader); 3097 if (rv != PHYMOD_E_NONE) { 3098 PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask)); 3099 PHYMOD_IF_ERR_RETURN(rv); 3100 } 3101 3102 PHYMOD_IF_ERR_RETURN( 3103 _tscf16_core_init_post_firmware_load(core, init_config, core_status)); 3104 #else 3105 if (!PHYMOD_CORE_INIT_F_SERDES_FW_BCAST_GET(init_config)) { 3106 /* 4. Micro code load and verify */ 3107 rv = _tscf16_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader); 3108 if (rv != PHYMOD_E_NONE) { 3109 PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask)); 3110 PHYMOD_IF_ERR_RETURN(rv); 3111 } 3112 3113 PHYMOD_IF_ERR_RETURN( 3114 _tscf16_core_init_post_firmware_load(core, init_config, core_status)); 3115 } 3116 #endif 3117 3118 return PHYMOD_E_NONE; 3119 } 3120 3121 3122 STATIC 3123 int _tscf16_core_init_pass2(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 3124 { 3125 phymod_phy_access_t phy_access, phy_access_copy; 3126 phymod_core_access_t core_copy; 3127 enum falcon16_tsc_pll_refclk_enum refclk; 3128 enum falcon16_tsc_pll_div_enum div; 3129 #ifdef DEFAULT_OSR2P5_SET 3130 int i; 3131 #endif /* DEFAULT_OSR2P5_SET */ 3132 phymod_firmware_core_config_t firmware_core_config; 3133 3134 PHYMOD_MEMSET(&firmware_core_config, 0x0, sizeof(firmware_core_config)); 3135 3136 TSCF16_CORE_TO_PHY_ACCESS(&phy_access, core); 3137 phy_access_copy = phy_access; 3138 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 3139 core_copy.access.lane_mask = 0x1; 3140 phy_access_copy = phy_access; 3141 phy_access_copy.access = core->access; 3142 phy_access_copy.access.lane_mask = 0x1; 3143 phy_access_copy.type = core->type; 3144 3145 refclk = FALCON16_TSC_PLL_REFCLK_156P25MHZ; 3146 div = FALCON16_TSC_PLL_DIV_175; 3147 3148 if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 3149 #ifndef TSCF16_PMD_CRC_UCODE 3150 /* poll the ready bit in 10 ms */ 3151 enum srds_pmd_uc_cmd_enum cmd; 3152 cmd = CMD_CALC_CRC; 3153 PHYMOD_IF_ERR_RETURN( 3154 falcon16_tsc_INTERNAL_poll_uc_dsc_ready_for_cmd_equals_1(&core_copy.access, 100, cmd)); 3155 #else 3156 PHYMOD_IF_ERR_RETURN( 3157 falcon16_tsc_check_ucode_crc(&core_copy.access, falcon16_ucode_crc, 200)); 3158 #endif 3159 } 3160 3161 /* release pmd lane hard reset */ 3162 PHYMOD_IF_ERR_RETURN( 3163 falcon16_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0)); 3164 3165 /* set charge pump current */ 3166 PHYMOD_IF_ERR_RETURN 3167 (falcon16_afe_pll_reg_set(&core_copy.access, &init_config->afe_pll)); 3168 3169 /* 8. PLL configuration */ 3170 if (init_config->interface.ref_clock == phymodRefClk125Mhz) { 3171 refclk = FALCON16_TSC_PLL_REFCLK_125MHZ; 3172 } 3173 3174 #ifdef DEFAULT_OSR2P5_SET 3175 if (PHYMOD_CORE_INIT_F_DEFAULT_OSR2P5_GET(init_config)) { 3176 /* set all lanes at OSR2p5 by default */ 3177 for (i = 0; i < 4; i++) { 3178 phy_access_copy.access.lane_mask = 1 << i; 3179 PHYMOD_IF_ERR_RETURN 3180 (tefmod16_10g_clock_enable(&phy_access_copy.access, 1)); 3181 PHYMOD_IF_ERR_RETURN 3182 (tefmod16_pmd_osmode_set(&phy_access_copy.access, TEFMOD16_SPD_10000_XFI, phymodRefClk156Mhz, 0x80000000)); 3183 } 3184 /* set back to original value */ 3185 phy_access_copy.access.lane_mask = 0x1; 3186 } 3187 #endif /* DEFAULT_OSR2P5_SET */ 3188 3189 /* reset core DP */ 3190 PHYMOD_IF_ERR_RETURN 3191 (falcon16_tsc_core_dp_reset(&core_copy.access, 1)); 3192 3193 if (165 == init_config->interface.pll_divider_req) { 3194 PHYMOD_IF_ERR_RETURN 3195 (tscf16_phy_firmware_core_config_get(&phy_access_copy, &firmware_core_config)); 3196 firmware_core_config.osr_2p5_available = 1; 3197 PHYMOD_IF_ERR_RETURN 3198 (tscf16_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config)); 3199 } 3200 3201 if (PHYMOD_CORE_INIT_F_CLK4PCS_3BIT_40T_GET(init_config)) { 3202 PHYMOD_IF_ERR_RETURN 3203 (falcon16_clk4pcs_3bit_40t_config(&core_copy.access)); 3204 } 3205 3206 PHYMOD_IF_ERR_RETURN 3207 (falcon16_tsc_configure_pll_refclk_div(&core_copy.access, refclk, div)); 3208 3209 /* select tsc_clk_credit */ 3210 PHYMOD_IF_ERR_RETURN 3211 (tefmod16_default_init(&core->access)); 3212 3213 PHYMOD_IF_ERR_RETURN 3214 (tefmod16_autoneg_timer_init(&core->access)); 3215 3216 PHYMOD_IF_ERR_RETURN 3217 (tefmod16_master_port_num_set(&core->access, 0)); 3218 3219 PHYMOD_IF_ERR_RETURN 3220 (tefmod16_cl74_chng_default (&core_copy.access)); 3221 3222 PHYMOD_IF_ERR_RETURN 3223 (tefmod16_cl91_ecc_clear(&core_copy.access)); 3224 3225 /* 9. Release core DP soft reset */ 3226 PHYMOD_IF_ERR_RETURN 3227 (falcon16_tsc_core_dp_reset(&core_copy.access, 0)); 3228 3229 return PHYMOD_E_NONE; 3230 } 3231 3232 #ifdef FW_BCAST_DOWNLOAD 3233 STATIC 3234 int _tscf16_core_init_bcast(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 3235 { 3236 phymod_core_access_t core_copy; 3237 phymod_phy_access_t phy_access; 3238 uint32_t uc_enable = 0; 3239 3240 TSCF16_CORE_TO_PHY_ACCESS(&phy_access, core); 3241 PHYMOD_IF_ERR_RETURN 3242 (falcon16_uc_active_get(&phy_access.access, &uc_enable)); 3243 if (uc_enable) { 3244 return PHYMOD_E_NONE; 3245 } 3246 3247 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 3248 core_copy.access.lane_mask = 0x1; 3249 3250 if (PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD_GET(init_config)) { 3251 /* do nothing */ 3252 } else if (PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_GET(init_config)) { 3253 PHYMOD_IF_ERR_RETURN(falcon16_tsc_ucode_init(&core_copy.access)); 3254 PHYMOD_IF_ERR_RETURN 3255 (falcon16_pram_firmware_enable(&core_copy.access, 1, 0)); 3256 } else if (PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_GET(init_config)) { 3257 PHYMOD_IF_ERR_RETURN(init_config->firmware_loader(core, falcon16_ucode_len, falcon16_ucode)); 3258 } else if (PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_GET(init_config)) { 3259 PHYMOD_IF_ERR_RETURN 3260 (falcon16_pram_firmware_enable(&core_copy.access, 0, 0)); 3261 } else if (PHYMOD_CORE_INIT_F_FW_LOAD_END_GET(init_config)) { 3262 PHYMOD_IF_ERR_RETURN( 3263 _tscf16_core_init_post_firmware_load(core, init_config, core_status)); 3264 } 3265 3266 return PHYMOD_E_NONE; 3267 } 3268 #endif 3269 3270 int tscf16_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 3271 { 3272 #ifdef FW_BCAST_DOWNLOAD 3273 if (PHYMOD_CORE_INIT_F_SERDES_FW_BCAST_GET(init_config) 3274 && !PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) 3275 && !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) { 3276 return _tscf16_core_init_bcast(core, init_config, core_status); 3277 } 3278 #endif 3279 3280 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 3281 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 3282 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 3283 PHYMOD_IF_ERR_RETURN 3284 (_tscf16_core_init_pass1(core, init_config, core_status)); 3285 3286 if (PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 3287 return PHYMOD_E_NONE; 3288 } 3289 } 3290 3291 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 3292 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 3293 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) { 3294 PHYMOD_IF_ERR_RETURN 3295 (_tscf16_core_init_pass2(core, init_config, core_status)); 3296 } 3297 3298 return PHYMOD_E_NONE; 3299 3300 } 3301 3302 3303 int tscf16_phy_pll_multiplier_get(const phymod_phy_access_t* phy, uint32_t* core_vco_pll_multiplier) 3304 { 3305 phymod_phy_access_t pm_phy_copy; 3306 uint32_t pll_mode = 0; 3307 3308 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 3309 pm_phy_copy.access.lane_mask = 0x1; 3310 3311 PHYMOD_IF_ERR_RETURN 3312 (falcon16_pll_mode_get(&pm_phy_copy.access, &pll_mode)); 3313 _tscf16_pll_multiplier_get(pll_mode, core_vco_pll_multiplier); 3314 3315 return PHYMOD_E_NONE; 3316 3317 } 3318 3319 3320 int tscf16_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config) 3321 { 3322 int pll_restart = 0; 3323 const phymod_access_t *pm_acc = &phy->access; 3324 phymod_phy_access_t pm_phy_copy; 3325 int start_lane, num_lane, i; 3326 int lane_bkup; 3327 phymod_polarity_t tmp_pol; 3328 phymod_firmware_lane_config_t firmware_lane_config; 3329 3330 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 3331 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 3332 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 3333 3334 PHYMOD_IF_ERR_RETURN 3335 (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane)); 3336 /* per lane based reset release */ 3337 PHYMOD_IF_ERR_RETURN 3338 (tefmod16_pmd_x4_reset(pm_acc)); 3339 3340 lane_bkup = pm_phy_copy.access.lane_mask; 3341 for (i = 0; i < num_lane; i++) { 3342 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 3343 PHYMOD_IF_ERR_RETURN 3344 (falcon16_lane_soft_reset_release(&pm_phy_copy.access, 1)); 3345 } 3346 pm_phy_copy.access.lane_mask = lane_bkup; 3347 3348 /* clearing all the lane config */ 3349 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 3350 3351 /* program the rx/tx polarity */ 3352 for (i = 0; i < num_lane; i++) { 3353 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 3354 tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) >> i & 0x1; 3355 tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) >> i & 0x1; 3356 PHYMOD_IF_ERR_RETURN 3357 (tscf16_phy_polarity_set(&pm_phy_copy, &tmp_pol)); 3358 } 3359 3360 for (i = 0; i < num_lane; i++) { 3361 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 3362 /* set tx parameters */ 3363 PHYMOD_IF_ERR_RETURN 3364 (tscf16_phy_tx_set(&pm_phy_copy, &init_config->tx[i])); 3365 } 3366 3367 for (i = 0; i < num_lane; i++) { 3368 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 3369 PHYMOD_IF_ERR_RETURN 3370 (_tscf16_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config)); 3371 } 3372 3373 /* next check if pcs-bypass mode */ 3374 if (PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 3375 PHYMOD_IF_ERR_RETURN 3376 (falcon16_pmd_tx_disable_pin_dis_set(&phy->access, 1)); 3377 PHYMOD_IF_ERR_RETURN 3378 (tefmod16_init_pcs_ilkn(&phy->access)); 3379 } 3380 3381 PHYMOD_IF_ERR_RETURN 3382 (tefmod16_update_port_mode(pm_acc, &pll_restart)); 3383 3384 PHYMOD_IF_ERR_RETURN 3385 (tefmod16_rx_lane_control_set(pm_acc, 1)); 3386 PHYMOD_IF_ERR_RETURN 3387 (tefmod16_tx_lane_control_set(pm_acc, TEFMOD16_TX_LANE_RESET_TRAFFIC_ENABLE)); /* TX_LANE_CONTROL */ 3388 3389 PHYMOD_IF_ERR_RETURN 3390 (tefmod16_25g_rsfec_am_init(pm_acc)); 3391 3392 /* Enable FEC error bypass indication */ 3393 PHYMOD_IF_ERR_RETURN 3394 (tefmod16_fec_bypass_indication_set(pm_acc, 1)); 3395 3396 return PHYMOD_E_NONE; 3397 3398 } 3399 3400 3401 int tscf16_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable) 3402 { 3403 int i; 3404 int start_lane, num_lane; 3405 int rv = PHYMOD_E_NONE; 3406 uint32_t cl72_en; 3407 phymod_phy_access_t phy_copy; 3408 3409 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3410 3411 /* next figure out the lane num and start_lane based on the input */ 3412 PHYMOD_IF_ERR_RETURN 3413 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3414 3415 switch (loopback) { 3416 case phymodLoopbackGlobal : 3417 PHYMOD_IF_ERR_RETURN 3418 (tscf16_phy_cl72_get(phy, &cl72_en)); 3419 if (cl72_en == 1) { 3420 PHYMOD_DEBUG_ERROR(("adr=%0x,lane 0x%x: Error! pcs gloop not supported with cl72 enabled\n", phy_copy.access.addr, start_lane)); 3421 break; 3422 } 3423 PHYMOD_IF_ERR_RETURN(tefmod16_tx_loopback_control(&phy->access, enable, start_lane, num_lane)); 3424 break; 3425 case phymodLoopbackGlobalPMD : 3426 PHYMOD_IF_ERR_RETURN 3427 (tscf16_phy_cl72_get(phy, &cl72_en)); 3428 if (cl72_en == 1) { 3429 PHYMOD_DEBUG_ERROR(("adr=%0x,lane 0x%x: Error! pmd gloop not supported with cl72 enabled\n", phy_copy.access.addr, start_lane)); 3430 break; 3431 } 3432 for (i = 0; i < num_lane; i++) { 3433 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 3434 PHYMOD_IF_ERR_RETURN(tefmod16_tx_squelch_set(&phy_copy.access, enable)); 3435 PHYMOD_IF_ERR_RETURN(falcon16_tsc_dig_lpbk(&phy_copy.access, (uint8_t) enable)); 3436 PHYMOD_IF_ERR_RETURN(falcon16_pmd_force_signal_detect(&phy_copy.access, (int) enable)); 3437 PHYMOD_IF_ERR_RETURN(tefmod16_rx_lane_control_set(&phy->access, 1)); 3438 } 3439 break; 3440 case phymodLoopbackRemotePMD : 3441 PHYMOD_IF_ERR_RETURN(falcon16_tsc_rmt_lpbk(&phy->access, (uint8_t)enable)); 3442 break; 3443 case phymodLoopbackRemotePCS : 3444 /* PHYMOD_IF_ERR_RETURN(tefmod16_rx_loopback_control(&phy->access, enable, enable, enable)); */ /* RAVI */ 3445 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 3446 (_PHYMOD_MSG("PCS Remote LoopBack not supported"))); 3447 break; 3448 default : 3449 break; 3450 } 3451 3452 return rv; 3453 } 3454 3455 int tscf16_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable) 3456 { 3457 uint32_t enable_core; 3458 int start_lane, num_lane; 3459 3460 *enable = 0; 3461 3462 /* next figure out the lane num and start_lane based on the input */ 3463 PHYMOD_IF_ERR_RETURN 3464 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3465 3466 switch (loopback) { 3467 case phymodLoopbackGlobal : 3468 PHYMOD_IF_ERR_RETURN(tefmod16_tx_loopback_get(&phy->access, &enable_core)); 3469 *enable = (enable_core >> start_lane) & 0x1; 3470 break; 3471 case phymodLoopbackGlobalPMD : 3472 PHYMOD_IF_ERR_RETURN(falcon16_tsc_dig_lpbk_get(&phy->access, enable)); 3473 break; 3474 case phymodLoopbackRemotePMD : 3475 PHYMOD_IF_ERR_RETURN(falcon16_tsc_rmt_lpbk_get(&phy->access, enable)); 3476 break; 3477 case phymodLoopbackRemotePCS : 3478 /* PHYMOD_IF_ERR_RETURN(tefmod16_rx_loopback_control(&phy->access, enable, enable, enable)); */ /* RAVI */ 3479 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 3480 (_PHYMOD_MSG("PCS Remote LoopBack not supported"))); 3481 break; 3482 default : 3483 break; 3484 } 3485 3486 return PHYMOD_E_NONE; 3487 3488 } 3489 3490 3491 int tscf16_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_pmd_locked) 3492 { 3493 PHYMOD_IF_ERR_RETURN(tefmod16_pmd_lock_get(&phy->access, rx_pmd_locked)); 3494 3495 return PHYMOD_E_NONE; 3496 3497 } 3498 3499 3500 int tscf16_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status) 3501 { 3502 if (1) { 3503 PHYMOD_IF_ERR_RETURN(tefmod16_get_pcs_latched_link_status(&phy->access, link_status)); 3504 } else { 3505 PHYMOD_IF_ERR_RETURN(tefmod16_get_pcs_link_status(&phy->access, link_status)); 3506 } 3507 3508 return PHYMOD_E_NONE; 3509 3510 } 3511 3512 3513 int tscf16_phy_pcs_userspeed_set(const phymod_phy_access_t* phy, const phymod_pcs_userspeed_config_t* config) 3514 { 3515 3516 return PHYMOD_E_UNAVAIL; 3517 3518 } 3519 3520 int tscf16_phy_pcs_userspeed_get(const phymod_phy_access_t* phy, phymod_pcs_userspeed_config_t* config) 3521 { 3522 return PHYMOD_E_UNAVAIL; 3523 3524 } 3525 3526 3527 int tscf16_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val) 3528 { 3529 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_read(&phy->access, reg_addr, val)); 3530 3531 return PHYMOD_E_NONE; 3532 3533 } 3534 3535 3536 int tscf16_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val) 3537 { 3538 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_write(&phy->access, reg_addr, val)); 3539 3540 return PHYMOD_E_NONE; 3541 3542 } 3543 3544 3545 int tscf16_phy_eye_margin_est_get(const phymod_phy_access_t* phy, phymod_eye_margin_mode_t eye_margin_mode, uint32_t* value) 3546 { 3547 int start_lane, num_lane; 3548 phymod_phy_access_t phy_copy; 3549 int hz_l, hz_r, vt_u, vt_d; 3550 3551 3552 /* first get the start_lane */ 3553 PHYMOD_IF_ERR_RETURN 3554 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3555 3556 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3557 phy_copy.access.lane_mask = 0x1 << start_lane; 3558 3559 PHYMOD_IF_ERR_RETURN 3560 (falcon16_tsc_get_eye_margin_est(&phy_copy.access, &hz_l, &hz_r, &vt_u, &vt_d)); 3561 3562 switch (eye_margin_mode) { 3563 case phymod_eye_marign_HZ_L: 3564 *value = hz_l; 3565 break; 3566 case phymod_eye_marign_HZ_R: 3567 *value = hz_r; 3568 break; 3569 case phymod_eye_marign_VT_U: 3570 *value = vt_u; 3571 break; 3572 case phymod_eye_marign_VT_D: 3573 *value = vt_d; 3574 break; 3575 default: 3576 *value = 0; 3577 break; 3578 } 3579 3580 return PHYMOD_E_NONE; 3581 } 3582 3583 3584 int tscf16_phy_rescal_set(const phymod_phy_access_t* phy, uint32_t enable, uint32_t value) 3585 { 3586 PHYMOD_IF_ERR_RETURN(falcon16_rescal_val_set(&phy->access, enable, value)); 3587 3588 return PHYMOD_E_NONE; 3589 3590 } 3591 3592 3593 int tscf16_phy_rescal_get(const phymod_phy_access_t* phy, uint32_t* value) 3594 { 3595 PHYMOD_IF_ERR_RETURN(falcon16_rescal_val_get(&phy->access, value)); 3596 3597 return PHYMOD_E_NONE; 3598 3599 } 3600 3601 int tscf16_phy_rx_signal_detect_get(const phymod_phy_access_t* phy, uint32_t* value) 3602 { 3603 uint32_t local_rx_signal_det; 3604 int start_lane, num_lane, i; 3605 3606 *value = 1; 3607 3608 PHYMOD_IF_ERR_RETURN 3609 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3610 3611 for (i = 0; i < num_lane; i++) { 3612 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 3613 continue; 3614 } 3615 PHYMOD_IF_ERR_RETURN 3616 (falcon16_tsc_signal_detect(&phy->access, &local_rx_signal_det)); 3617 *value = *value & local_rx_signal_det; 3618 } 3619 3620 return PHYMOD_E_NONE; 3621 } 3622 3623 int tscf16_phy_sw_an_advert_set(const phymod_phy_access_t* phy, 3624 const phymod_autoneg_ability_t* an_ability, 3625 phymod_sw_an_ctxt_t* an_ctxt) 3626 { 3627 tefmod16_an_adv_ability_t value; 3628 int start_lane, num_lane; 3629 phymod_phy_access_t phy_copy; 3630 phymod_core_info_t core_info; 3631 3632 /* next program the tx fir taps and driver current based on the input */ 3633 PHYMOD_IF_ERR_RETURN 3634 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3635 3636 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3637 phy_copy.access.lane_mask = 0x1 << start_lane; 3638 3639 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 3640 PHYMOD_MEMSET(&core_info, 0x0, sizeof(core_info)); 3641 3642 PHYMOD_IF_ERR_RETURN 3643 (tscf16_core_info_get((phymod_core_access_t *)phy, &core_info)); 3644 3645 value.an_cl72 = an_ability->an_cl72; 3646 3647 if (PHYMOD_AN_FEC_OFF_GET(an_ability->an_fec)) { 3648 value.an_fec = TEFMOD16_FEC_SUPRTD_NOT_REQSTD; 3649 } else { 3650 if (PHYMOD_AN_FEC_CL74_GET(an_ability->an_fec)) 3651 value.an_fec = TEFMOD16_FEC_CL74_SUPRTD_REQSTD; 3652 if (PHYMOD_AN_FEC_CL91_GET(an_ability->an_fec)) 3653 value.an_fec |= TEFMOD16_FEC_CL91_SUPRTD_REQSTD; 3654 } 3655 3656 /* value.an_fec = an_ability->an_fec; */ 3657 value.an_hg2 = an_ability->an_hg2; 3658 3659 /* next check pause */ 3660 if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability)) { 3661 value.an_pause = TEFMOD16_SYMM_PAUSE; 3662 } 3663 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 3664 value.an_pause = TEFMOD16_ASYM_PAUSE; 3665 } 3666 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 3667 value.an_pause = TEFMOD16_ASYM_SYMM_PAUSE; 3668 } 3669 3670 /* check cl73 and cl73 bam ability */ 3671 if (PHYMOD_AN_CAP_1G_KX_GET(an_ability->an_cap)) 3672 value.an_base_speed |= 1 << TEFMOD16_CL73_1GBASE_KX; 3673 if (PHYMOD_AN_CAP_10G_KR_GET(an_ability->an_cap)) 3674 value.an_base_speed |= 1 << TEFMOD16_CL73_10GBASE_KR1; 3675 if (PHYMOD_AN_CAP_40G_KR4_GET(an_ability->an_cap)) 3676 value.an_base_speed |= 1 << TEFMOD16_CL73_40GBASE_KR4; 3677 if (PHYMOD_AN_CAP_40G_CR4_GET(an_ability->an_cap)) 3678 value.an_base_speed |= 1 << TEFMOD16_CL73_40GBASE_CR4; 3679 if (PHYMOD_AN_CAP_100G_KR4_GET(an_ability->an_cap)) { 3680 if (core_info.core_version == phymodCoreVersionTscfA0) { 3681 value.an_fec = TEFMOD16_FEC_NOT_SUPRTD; 3682 } 3683 value.an_base_speed |= 1 << TEFMOD16_CL73_100GBASE_KR4; 3684 } 3685 if (PHYMOD_AN_CAP_100G_CR4_GET(an_ability->an_cap)) { 3686 if (core_info.core_version == phymodCoreVersionTscfA0) { 3687 value.an_fec = TEFMOD16_FEC_NOT_SUPRTD; 3688 } 3689 value.an_base_speed |= 1 << TEFMOD16_CL73_100GBASE_CR4; 3690 } 3691 if (PHYMOD_AN_CAP_25G_CR1_GET(an_ability->an_cap)) 3692 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_CR1; 3693 if (PHYMOD_AN_CAP_25G_KR1_GET(an_ability->an_cap)) 3694 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_KR1; 3695 if (PHYMOD_AN_CAP_25G_CRS1_GET(an_ability->an_cap)) 3696 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_CRS1; 3697 if (PHYMOD_AN_CAP_25G_KRS1_GET(an_ability->an_cap)) 3698 value.an_base_speed |= 1 << TEFMOD16_CL73_25GBASE_KRS1; 3699 3700 /* check cl73 bam ability */ 3701 if (PHYMOD_BAM_CL73_CAP_20G_KR2_GET(an_ability->cl73bam_cap)) 3702 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_20GBASE_KR2; 3703 if (PHYMOD_BAM_CL73_CAP_20G_CR2_GET(an_ability->cl73bam_cap)) 3704 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_20GBASE_CR2; 3705 if (PHYMOD_BAM_CL73_CAP_40G_KR2_GET(an_ability->cl73bam_cap)) 3706 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_40GBASE_KR2; 3707 if (PHYMOD_BAM_CL73_CAP_40G_CR2_GET(an_ability->cl73bam_cap)) 3708 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_40GBASE_CR2; 3709 if (PHYMOD_BAM_CL73_CAP_50G_KR2_GET(an_ability->cl73bam_cap)) 3710 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_KR2; 3711 if (PHYMOD_BAM_CL73_CAP_50G_CR2_GET(an_ability->cl73bam_cap)) 3712 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_CR2; 3713 /* 3714 * 50G 4-lane is not supported for TSCF16(TH2 and TD3) chips 3715 if (PHYMOD_BAM_CL73_CAP_50G_KR4_GET(an_ability->cl73bam_cap)) 3716 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_KR4; 3717 if (PHYMOD_BAM_CL73_CAP_50G_CR4_GET(an_ability->cl73bam_cap)) 3718 value.an_bam_speed |= 1 << TEFMOD16_CL73_BAM_50GBASE_CR4; 3719 */ 3720 if (PHYMOD_BAM_CL73_CAP_20G_KR1_GET(an_ability->cl73bam_cap)) 3721 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_20GBASE_KR1; 3722 if (PHYMOD_BAM_CL73_CAP_20G_CR1_GET(an_ability->cl73bam_cap)) 3723 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_20GBASE_CR1; 3724 if (PHYMOD_BAM_CL73_CAP_25G_KR1_GET(an_ability->cl73bam_cap)) 3725 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_25GBASE_KR1; 3726 if (PHYMOD_BAM_CL73_CAP_25G_CR1_GET(an_ability->cl73bam_cap)) 3727 value.an_bam_speed1 |= 1 << TEFMOD16_CL73_BAM_25GBASE_CR1; 3728 3729 3730 PHYMOD_IF_ERR_RETURN 3731 (tefmod16_sw_an_advert_set(&phy_copy.access, &value, an_ctxt)); 3732 return PHYMOD_E_NONE; 3733 3734 } 3735 3736 static int _tscf16_sw_an_pmd_lane_cfg_set(phymod_phy_access_t* phy, int enable) 3737 { 3738 int start_lane, num_lane, i=0; 3739 phymod_phy_access_t phy_copy; 3740 phymod_firmware_lane_config_t firmware_lane_config; 3741 3742 3743 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 3744 3745 PHYMOD_IF_ERR_RETURN 3746 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 3747 3748 3749 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 3750 phy_copy.access.lane_mask = 0x1 << start_lane; 3751 3752 /* make sure the firmware config is set to an eenabled */ 3753 PHYMOD_IF_ERR_RETURN 3754 (tscf16_phy_firmware_lane_config_get(&phy_copy, &firmware_lane_config)); 3755 if (enable) { 3756 firmware_lane_config.AnEnabled = 1; 3757 firmware_lane_config.LaneConfigFromPCS = 1; 3758 } else { 3759 firmware_lane_config.AnEnabled = 0; 3760 firmware_lane_config.LaneConfigFromPCS = 0; 3761 } 3762 3763 for (i = 0; i < num_lane; i++) { 3764 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 3765 continue; 3766 } 3767 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 3768 PHYMOD_IF_ERR_RETURN 3769 (falcon16_lane_soft_reset_release(&phy_copy.access, 0)); 3770 } 3771 3772 PHYMOD_USLEEP(1000); 3773 for (i = 0; i < num_lane; i++) { 3774 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 3775 continue; 3776 } 3777 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 3778 PHYMOD_IF_ERR_RETURN 3779 (_tscf16_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config)); 3780 } 3781 3782 for (i = 0; i < num_lane; i++) { 3783 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 3784 continue; 3785 } 3786 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 3787 PHYMOD_IF_ERR_RETURN 3788 (falcon16_lane_soft_reset_release(&phy_copy.access, 1)); 3789 } 3790 3791 return PHYMOD_E_NONE; 3792 } 3793 3794 3795 static int 3796 _resolve_speed(const phymod_phy_access_t* phy, phymod_sw_an_ctxt_t *an_ctxt) 3797 { 3798 uint16_t common_tech_ability = 0; 3799 uint16_t hcd_speed = HCD_SPEED_ID_UNDEFINED; 3800 uint8_t is_krs = 0; 3801 uint8_t cl74_fec = 0, cl91_fec = 0, cl74_25gkrs_fec = 0; 3802 uint32_t msa_code_13_23 = 0, msa_code_2_12 = 0, msa_code_0_1 =0; 3803 uint8_t ld_cl91_sup, ld_cl91_req, rd_cl91_sup, rd_cl91_req; 3804 uint8_t ld_cl74_sup, ld_cl74_req, rd_cl74_sup, rd_cl74_req; 3805 uint8_t rd_base_cl74_fec_req, rd_base_cl74_fec_sup, ld_base_cl74_fec_req, ld_base_cl74_fec_sup; 3806 tefmod16_fec_type_t fec_type; 3807 3808 /* Resolve base page tech ability */ 3809 if ((an_ctxt->rx_pages.base_page.page_1 >> AN_BASE1_PAGE_ABILITY_OFFSET) & 3810 AN_BASE1_PAGE_ABILITY_MASK) { 3811 common_tech_ability = (((an_ctxt->rx_pages.base_page.page_1) & 3812 (an_ctxt->tx_pages.base_page.page_1)) & 3813 (AN_BASE1_PAGE_ABILITY_MASK << AN_BASE1_PAGE_ABILITY_OFFSET)); 3814 if ((common_tech_ability >> AN_BASE_TECH_ABILITY_100GKR4_OFFSET) & AN_BASE_TECH_ABILITY_100GKR4_MASK) { 3815 hcd_speed = TEFMOD16_100G_KR4_SPD_IF; 3816 } else if ((common_tech_ability >> AN_BASE_TECH_ABILITY_100GCR4_OFFSET) & AN_BASE_TECH_ABILITY_100GCR4_MASK) { 3817 hcd_speed = TEFMOD16_100G_CR4_SPD_IF; 3818 } else if ((common_tech_ability >> AN_BASE_TECH_ABILITY_25GKR_OFFSET) & AN_BASE_TECH_ABILITY_25GKR_MASK) { 3819 /* speed is 25G KR */ 3820 hcd_speed = TEFMOD16_25G_KR_IEEE_SPD_IF; /* speed ID for 25G KR */ 3821 } else if ((common_tech_ability >> AN_BASE_TECH_ABILITY_25GKRS_OFFSET) & AN_BASE_TECH_ABILITY_25GKRS_MASK) { 3822 hcd_speed = TEFMOD16_25G_KRS_IEEE_SPD_IF; /* IEEE AN does not differntiate between KR and CR, KRS and CRS */ 3823 is_krs = 1; 3824 } else { 3825 /* TH SW AN will be used only for IEEE 100/25G and MSA 3826 * NO need to look for 10G and 40G 3827 */ 3828 hcd_speed = HCD_SPEED_ID_UNDEFINED; 3829 } 3830 3831 /* Resolve base page FEC ability */ 3832 if (an_ctxt->rx_pages.base_page.page_2) { 3833 /* always advertise cl91/74 supported mask */ 3834 cl91_fec = (((an_ctxt->rx_pages.base_page.page_2 >> AN_BASE_CL91_ABILITY_REQ_OFFSET) & 3835 AN_BASE_CL91_ABILITY_REQ_MASK) | 3836 ((an_ctxt->tx_pages.base_page.page_2 >> AN_BASE_CL91_ABILITY_REQ_OFFSET) & 3837 AN_BASE_CL91_ABILITY_REQ_MASK)); 3838 3839 cl74_25gkrs_fec = (((an_ctxt->rx_pages.base_page.page_2 >> AN_BASE_CL74_25GKRS_REQ_OFFSET) & 3840 AN_BASE_CL74_25GKRS_REQ_MASK) | 3841 ((an_ctxt->tx_pages.base_page.page_2 >> AN_BASE_CL74_25GKRS_REQ_OFFSET) & 3842 AN_BASE_CL74_25GKRS_REQ_MASK)); 3843 3844 cl74_fec = (((an_ctxt->rx_pages.base_page.page_2 >> AN_BASE_CL74_ABILITY_REQ_OFFSET) & 3845 AN_BASE_CL74_ABILITY_REQ_MASK) | 3846 ((an_ctxt->tx_pages.base_page.page_2 >> AN_BASE_CL74_ABILITY_REQ_OFFSET) & 3847 AN_BASE_CL74_ABILITY_REQ_MASK)); 3848 } 3849 3850 } 3851 3852 if (hcd_speed == HCD_SPEED_ID_UNDEFINED) { 3853 /* NO IEEE Common speed found look for MSA Speeds */ 3854 msa_code_13_23 = ((an_ctxt->rx_pages.msg_page.page_1 >> AN_MSG_PAGE1_OUI_13to23_OFFSET) & 3855 AN_MSG_PAGE1_OUI_13to23_MASK); 3856 msa_code_2_12 = ((an_ctxt->rx_pages.msg_page.page_2 >> AN_MSG_PAGE2_OUI_2to12_OFFSET) & 3857 AN_MSG_PAGE2_OUI_2to12_MASK); 3858 msa_code_0_1 = ((an_ctxt->tx_pages.ufmt_page.page_0 >> AN_UF_PAGE0_OUI_OFFSET) & 3859 AN_UF_PAGE0_OUI_MASK); 3860 3861 if ((msa_code_13_23 == MSA_OUI_13to23) && 3862 (msa_code_2_12 == MSA_OUT_2to12) && 3863 (msa_code_0_1 == MSA_OUI_0to1)) { 3864 3865 /* MSA PAGE FOUND. Now parse the MSA pages */ 3866 common_tech_ability = (an_ctxt->tx_pages.ufmt_page.page_1 & an_ctxt->rx_pages.ufmt_page.page_1); 3867 3868 if ((common_tech_ability >> AN_UF_PAGE1_50G_KR2_ABILITY_OFFSET) & 3869 AN_UF_PAGE1_50G_KR2_ABILITY_MASK) { 3870 hcd_speed = TEFMOD16_50G_KR2_SPD_IF; 3871 } else if ((common_tech_ability >> AN_UF_PAGE1_50G_CR2_ABILITY_OFFSET) & 3872 AN_UF_PAGE1_50G_CR2_ABILITY_MASK) { 3873 hcd_speed = TEFMOD16_50G_CR2_SPD_IF; 3874 } else if ((common_tech_ability >> AN_UF_PAGE1_25G_KR1_ABILITY_OFFSET) & 3875 AN_UF_PAGE1_25G_KR1_ABILITY_MASK) { 3876 hcd_speed = TEFMOD16_25G_KR_SPD_IF; 3877 } else if ((common_tech_ability >> AN_UF_PAGE1_25G_CR1_ABILITY_OFFSET) & 3878 AN_UF_PAGE1_25G_CR1_ABILITY_MASK) { 3879 hcd_speed = TEFMOD16_25G_CR_SPD_IF; 3880 } else { 3881 /* Resolution error */ 3882 return PHYMOD_E_CONFIG; 3883 } 3884 3885 /* resolve FEC */ 3886 if (an_ctxt->tx_pages.ufmt_page.page_2 & an_ctxt->rx_pages.ufmt_page.page_2) { 3887 ld_cl91_sup = ((an_ctxt->tx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL91_SUPPORT_OFFSET) & 3888 AN_UF_PAGE2_CL91_SUPPORT_MASK); 3889 ld_cl91_req = ((an_ctxt->tx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL91_REQ_OFFSET) & 3890 AN_UF_PAGE2_CL91_REQ_MASK); 3891 ld_cl74_sup = ((an_ctxt->tx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL74_SUPPORT_OFFSET) & 3892 AN_UF_PAGE2_CL74_SUPPORT_MASK); 3893 ld_cl74_req = ((an_ctxt->tx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL74_REQ_OFFSET) & 3894 AN_UF_PAGE2_CL74_REQ_MASK); 3895 3896 rd_cl91_sup = ((an_ctxt->rx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL91_SUPPORT_OFFSET) & 3897 AN_UF_PAGE2_CL91_SUPPORT_MASK); 3898 rd_cl91_req = ((an_ctxt->rx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL91_REQ_OFFSET) & 3899 AN_UF_PAGE2_CL91_REQ_MASK); 3900 rd_cl74_sup = ((an_ctxt->rx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL74_SUPPORT_OFFSET) & 3901 AN_UF_PAGE2_CL74_SUPPORT_MASK); 3902 rd_cl74_req = ((an_ctxt->rx_pages.ufmt_page.page_2 >> AN_UF_PAGE2_CL74_REQ_OFFSET) & 3903 AN_UF_PAGE2_CL74_REQ_MASK); 3904 3905 rd_base_cl74_fec_req = ((an_ctxt->rx_pages.base_page.page_2 >> AN_BASE_CL74_ABILITY_REQ_OFFSET) & 3906 AN_BASE_CL74_ABILITY_REQ_MASK); 3907 ld_base_cl74_fec_req = ((an_ctxt->tx_pages.base_page.page_2 >> AN_BASE_CL74_ABILITY_REQ_OFFSET) & 3908 AN_BASE_CL74_ABILITY_REQ_MASK); 3909 rd_base_cl74_fec_sup = ((an_ctxt->rx_pages.base_page.page_2 >> AN_BASE_CL74_ABILITY_SUP_OFFSET) & 3910 AN_BASE_CL74_ABILITY_SUP_MASK); 3911 ld_base_cl74_fec_sup = ((an_ctxt->tx_pages.base_page.page_2 >> AN_BASE_CL74_ABILITY_SUP_OFFSET) & 3912 AN_BASE_CL74_ABILITY_SUP_MASK); 3913 3914 if ((ld_cl91_req || rd_cl91_req) && 3915 (ld_cl91_sup && rd_cl91_sup)) { 3916 cl91_fec = 1; 3917 } else if ((ld_cl74_req || rd_cl74_req) && 3918 (ld_cl74_sup && rd_cl74_sup)) { 3919 cl74_fec = 1; 3920 } else if ((rd_base_cl74_fec_req || ld_base_cl74_fec_req) && 3921 (rd_base_cl74_fec_sup && ld_base_cl74_fec_sup)) { 3922 cl74_fec =1; 3923 } 3924 3925 } 3926 3927 } 3928 } 3929 3930 if (is_krs) { 3931 /* For 25GBASE-KR-S and 25GBASE-CR-S PHYs if either PHY requests RS-FEC or BASE-R FEC then 3932 * BASE-R operation is enabled. This is because 25GBASE-KR-S and 25GBASE-CR-S PHYs do not support 3933 * RS-FEC operation 3934 */ 3935 if (cl91_fec) { 3936 cl74_25gkrs_fec = 1; 3937 } 3938 cl91_fec = 0; 3939 } 3940 3941 if (cl91_fec) { 3942 /* enable cl91 FEC */ 3943 fec_type = TEFMOD16_CL91; 3944 } else if (cl74_fec || cl74_25gkrs_fec) { 3945 /* enable cl74 FEC */ 3946 fec_type = TEFMOD16_CL74; 3947 } else { 3948 /* NO FEC enable */ 3949 fec_type = 0x0; 3950 } 3951 3952 if (fec_type) { 3953 PHYMOD_IF_ERR_RETURN 3954 (tefmod16_FEC_control(&phy->access, fec_type, 1, 0)); 3955 /* HW AN logic does not drive the FEC control in SW AN mode 3956 * Need to override fec control 3957 */ 3958 PHYMOD_IF_ERR_RETURN 3959 (tefmod16_sw_an_fec_override(&phy->access, fec_type, 1)); 3960 } 3961 /* Program the resolved speed Id to speed control */ 3962 PHYMOD_IF_ERR_RETURN 3963 (tefmod16_set_speed_id(&phy->access, hcd_speed)); 3964 3965 return PHYMOD_E_NONE; 3966 } 3967 3968 static int _is_send_ack(phymod_sw_an_ctxt_t *an_ctxt) 3969 { 3970 3971 phymod_an_page_t *tx_page = 0; 3972 phymod_an_page_t *rx_page = 0; 3973 int send_ack = 0; 3974 int is_valid_tx_page =1, is_valid_rx_page = 1; 3975 3976 3977 3978 /** 3979 * check the current Tx page and Current Rx page and if the NP bit is set then send the ack 3980 */ 3981 switch (an_ctxt->tx_pages_cnt) { 3982 case TEFMOD16_AN_PAGE_ID_BASE_PAGE: 3983 /* check the base page NP bit */ 3984 tx_page = &an_ctxt->tx_pages.base_page; 3985 break; 3986 case TEFMOD16_AN_PAGE_ID_MSG_PAGE: 3987 /* check the message page NP bit */ 3988 tx_page = &an_ctxt->tx_pages.msg_page; 3989 break; 3990 case TEFMOD16_AN_PAGE_ID_UP_PAGE: 3991 /* check the UF page NP bit */ 3992 tx_page = &an_ctxt->tx_pages.ufmt_page; 3993 break; 3994 default: 3995 tx_page = &an_ctxt->tx_pages.null_page; 3996 is_valid_tx_page = 0; 3997 break; 3998 } 3999 4000 switch (an_ctxt->rx_pages_cnt) { 4001 case TEFMOD16_AN_PAGE_ID_NONE: 4002 /* No page has been rcvd yet */ 4003 is_valid_rx_page = 0; 4004 break; 4005 case TEFMOD16_AN_PAGE_ID_BASE_PAGE: 4006 /* Rcvd base page NP bit */ 4007 rx_page = &an_ctxt->rx_pages.base_page; 4008 break; 4009 case TEFMOD16_AN_PAGE_ID_MSG_PAGE: 4010 /* Rcvd msg page NP bit */ 4011 rx_page = &an_ctxt->rx_pages.msg_page; 4012 break; 4013 case TEFMOD16_AN_PAGE_ID_UP_PAGE: 4014 /* Rcvd ufmt page NP bit */ 4015 rx_page = &an_ctxt->rx_pages.ufmt_page; 4016 break; 4017 default: 4018 /* check the cahed page at null page location*/ 4019 rx_page = &an_ctxt->rx_pages.null_page; 4020 break; 4021 } 4022 4023 if ( is_valid_tx_page && tx_page->page_0) { 4024 if ((tx_page->page_0 >> AN_BASE0_PAGE_NP_OFFSET) & 0x1) { 4025 send_ack = 1; 4026 } 4027 } 4028 if (is_valid_rx_page && rx_page->page_0) { 4029 if ((rx_page->page_0 >> AN_BASE0_PAGE_NP_OFFSET) & 0x1) { 4030 send_ack = 1; 4031 } 4032 } 4033 4034 return send_ack; 4035 } 4036 4037 int tscf16_phy_sw_an_control_status_get(const phymod_phy_access_t* phy, phymod_sw_an_ctrl_status_t* an_ctrl_status) 4038 { 4039 4040 PHYMOD_MEMSET(an_ctrl_status, 0, sizeof(phymod_sw_an_ctrl_status_t)); 4041 4042 PHYMOD_IF_ERR_RETURN 4043 (tefmod16_sw_an_ctl_sts_get(&phy->access, an_ctrl_status)); 4044 4045 return PHYMOD_E_NONE; 4046 } 4047 4048 int tscf16_phy_sw_an_base_page_exchange_handler(const phymod_phy_access_t* phy, phymod_sw_an_ctxt_t* an_ctxt) 4049 { 4050 phymod_phy_access_t phy_copy; 4051 int start_lane, num_lane; 4052 4053 PHYMOD_IF_ERR_RETURN 4054 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4055 4056 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4057 phy_copy.access.lane_mask = 0x1 << start_lane; 4058 4059 PHYMOD_IF_ERR_RETURN 4060 (tefmod16_setup_for_sw_an(&phy_copy.access, num_lane)); 4061 PHYMOD_IF_ERR_RETURN 4062 (tefmod16_sw_an_ld_page_load(&phy_copy.access, &an_ctxt->tx_pages.base_page, 1)); 4063 an_ctxt->tx_pages_cnt++; 4064 4065 PHYMOD_IF_ERR_RETURN 4066 (_tscf16_sw_an_pmd_lane_cfg_set((phymod_phy_access_t*)phy, 1)); 4067 PHYMOD_USLEEP(1); 4068 PHYMOD_IF_ERR_RETURN 4069 (tefmod16_sw_an_control(&phy_copy.access, 1)); 4070 4071 return PHYMOD_E_NONE; 4072 4073 } 4074 int tscf16_phy_sw_an_lp_page_rdy_handler(const phymod_phy_access_t* phy, phymod_sw_an_ctxt_t* an_ctxt) 4075 { 4076 phymod_phy_access_t phy_copy; 4077 int start_lane, num_lane; 4078 4079 4080 PHYMOD_IF_ERR_RETURN 4081 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4082 4083 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4084 phy_copy.access.lane_mask = 0x1 << start_lane; 4085 /* 1. Incerement the Rx page count 4086 * 2. read the lp page and cache it in the rx page buffer 4087 * 3. if the current tx page NP bit is 1 or rcvd page NP bit is 1 4088 * send the ack 4089 * 4. else 4090 * a. parse the received pages 4091 * b. resolve speed 4092 * c. program the speed control based on resolved speed 4093 * d. set the ack 4094 */ 4095 4096 an_ctxt->rx_pages_cnt++; 4097 switch(an_ctxt->rx_pages_cnt) { 4098 case TEFMOD16_AN_PAGE_ID_BASE_PAGE: 4099 /* recevied LP base page */ 4100 PHYMOD_IF_ERR_RETURN 4101 (tefmod16_sw_an_lp_page_read(&phy_copy.access, &an_ctxt->rx_pages.base_page)); 4102 break; 4103 case TEFMOD16_AN_PAGE_ID_MSG_PAGE: 4104 /* rcvd LP message page */ 4105 PHYMOD_IF_ERR_RETURN 4106 (tefmod16_sw_an_lp_page_read(&phy_copy.access, &an_ctxt->rx_pages.msg_page)); 4107 break; 4108 case TEFMOD16_AN_PAGE_ID_UP_PAGE: 4109 /* rcvd LP UF page */ 4110 PHYMOD_IF_ERR_RETURN 4111 (tefmod16_sw_an_lp_page_read(&phy_copy.access, &an_ctxt->rx_pages.ufmt_page)); 4112 break; 4113 default: 4114 /* we are only interested in first 3 pages rest of the pages won't be parsed 4115 * use the null page entry as a scratch buffer to look for NP bit 4116 */ 4117 PHYMOD_IF_ERR_RETURN 4118 (tefmod16_sw_an_lp_page_read(&phy_copy.access, &an_ctxt->rx_pages.null_page)); 4119 break; 4120 } 4121 4122 if (_is_send_ack(an_ctxt)) { 4123 /* Load the next page while the state IEEE SM is in ack det state */ 4124 switch(an_ctxt->tx_pages_cnt) { 4125 case 0: 4126 /* Invalid. Atleast base page shoould have beem txed before 4127 * receving ld_page event 4128 */ 4129 break; 4130 case TEFMOD16_AN_PAGE_ID_BASE_PAGE: 4131 /* Tx Message Page */ 4132 PHYMOD_IF_ERR_RETURN 4133 (tefmod16_sw_an_ld_page_load(&phy_copy.access, &an_ctxt->tx_pages.msg_page, 0)); 4134 an_ctxt->tx_pages_cnt++; 4135 break; 4136 case TEFMOD16_AN_PAGE_ID_MSG_PAGE: 4137 /* Tx unformatted Page for BAM abilities */ 4138 PHYMOD_IF_ERR_RETURN 4139 (tefmod16_sw_an_ld_page_load(&phy_copy.access, &an_ctxt->tx_pages.ufmt_page, 0)); 4140 an_ctxt->tx_pages_cnt++; 4141 break; 4142 default: 4143 /* request for page when no more valid pages are available to Tx 4144 * Tx NULL pages 4145 */ 4146 PHYMOD_IF_ERR_RETURN 4147 (tefmod16_sw_an_ld_page_load(&phy_copy.access, &an_ctxt->tx_pages.null_page, 0)); 4148 an_ctxt->tx_pages_cnt++; 4149 break; 4150 } 4151 4152 } else { 4153 PHYMOD_IF_ERR_RETURN 4154 (_resolve_speed(phy, an_ctxt)); 4155 } 4156 PHYMOD_IF_ERR_RETURN 4157 (tefmod16_sw_an_set_ack(&phy_copy.access)); 4158 4159 return PHYMOD_E_NONE; 4160 } 4161 4162 4163 int tscf16_phy_sw_autoneg_enable(const phymod_phy_access_t* phy, int enable) 4164 { 4165 phymod_phy_access_t phy_copy; 4166 int start_lane, num_lane; 4167 4168 PHYMOD_IF_ERR_RETURN 4169 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4170 4171 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4172 phy_copy.access.lane_mask = 0x1 << start_lane; 4173 4174 PHYMOD_IF_ERR_RETURN 4175 (_tscf16_sw_an_pmd_lane_cfg_set((phymod_phy_access_t*)phy, enable)); 4176 PHYMOD_USLEEP(10); 4177 4178 PHYMOD_IF_ERR_RETURN 4179 (tefmod16_sw_an_control(&phy_copy.access, enable)); 4180 4181 /* When disable SW AN, remove AN FEC override */ 4182 if (!enable) { 4183 PHYMOD_IF_ERR_RETURN 4184 (tefmod16_sw_an_fec_override(&phy->access, 0, 0)); 4185 } 4186 return PHYMOD_E_NONE; 4187 4188 } 4189 4190 int tscf16_phy_synce_clk_ctrl_set(const phymod_phy_access_t* phy, 4191 phymod_synce_clk_ctrl_t cfg) 4192 { 4193 phymod_phy_access_t phy_copy; 4194 int start_lane, num_lane; 4195 4196 PHYMOD_IF_ERR_RETURN 4197 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4198 4199 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 4200 phy_copy.access.lane_mask = 0x1 << start_lane; 4201 4202 PHYMOD_IF_ERR_RETURN 4203 (tefmod16_synce_stg0_mode_set(&phy_copy.access, cfg.stg0_mode)); 4204 4205 PHYMOD_IF_ERR_RETURN 4206 (tefmod16_synce_stg1_mode_set(&phy_copy.access, cfg.stg1_mode)); 4207 4208 PHYMOD_IF_ERR_RETURN 4209 (tefmod16_synce_clk_ctrl_set(&phy_copy.access, cfg.sdm_val)); 4210 4211 return PHYMOD_E_NONE; 4212 } 4213 4214 int tscf16_phy_synce_clk_ctrl_get(const phymod_phy_access_t* phy, 4215 phymod_synce_clk_ctrl_t *cfg) 4216 { 4217 PHYMOD_IF_ERR_RETURN 4218 (tefmod16_synce_stg0_mode_get(&phy->access, &(cfg->stg0_mode))); 4219 4220 PHYMOD_IF_ERR_RETURN 4221 (tefmod16_synce_stg1_mode_get(&phy->access, &(cfg->stg1_mode))); 4222 4223 PHYMOD_IF_ERR_RETURN 4224 (tefmod16_synce_clk_ctrl_get(&phy->access, &(cfg->sdm_val))); 4225 4226 return PHYMOD_E_NONE; 4227 } 4228 4229 int tscf16_phy_rx_ppm_get(const phymod_phy_access_t* phy, int16_t* rx_ppm) 4230 { 4231 int start_lane, num_lane; 4232 phymod_phy_access_t pm_phy_copy; 4233 4234 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 4235 4236 PHYMOD_IF_ERR_RETURN 4237 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4238 4239 pm_phy_copy.access.lane_mask = 1 << start_lane; 4240 PHYMOD_IF_ERR_RETURN 4241 (falcon16_tsc_rx_ppm(&pm_phy_copy.access, rx_ppm)); 4242 4243 return PHYMOD_E_NONE; 4244 } 4245 4246 int tscf16_phy_fec_bypass_indication_set(const phymod_phy_access_t* phy, 4247 uint32_t enable) 4248 { 4249 PHYMOD_IF_ERR_RETURN( 4250 tefmod16_fec_bypass_indication_set(&phy->access, enable)); 4251 4252 return PHYMOD_E_NONE; 4253 } 4254 4255 int tscf16_phy_fec_bypass_indication_get(const phymod_phy_access_t* phy, 4256 uint32_t *enable) 4257 { 4258 int start_lane, num_lane; 4259 phymod_phy_access_t pm_phy_copy; 4260 4261 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 4262 4263 PHYMOD_IF_ERR_RETURN 4264 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 4265 4266 pm_phy_copy.access.lane_mask = 1 << start_lane; 4267 4268 PHYMOD_IF_ERR_RETURN( 4269 tefmod16_fec_bypass_indication_get(&pm_phy_copy.access, enable)); 4270 4271 return PHYMOD_E_NONE; 4272 } 4273