tsce16.c (103536B)
1 /* 2 * 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 */ 9 10 #include <phymod/phymod.h> 11 #include <phymod/phymod_system.h> 12 #include <phymod/phymod_debug.h> 13 #include <phymod/phymod_util.h> 14 #include <phymod/chip/bcmi_tsce16_xgxs_defs.h> 15 #include <phymod/chip/tsce16.h> 16 #include "tsce16/tier1/temod16_enum_defines.h" 17 #include "tsce16/tier1/temod16.h" 18 #include "tsce16/tier1/te16PCSRegEnums.h" 19 #include "merlin16/tier1/merlin16_cfg_seq.h" 20 #include "merlin16/tier1/merlin16_common.h" 21 #include "merlin16/tier1/merlin16_interface.h" 22 #include "merlin16/tier1/merlin16_debug_functions.h" 23 #include "merlin16/tier1/merlin16_dependencies.h" 24 #include "merlin16/tier1/merlin16_internal.h" 25 26 #define TSCE16_ID0 0x600d 27 #define TSCE16_ID1 0x8770 28 29 #define TSCE16_MODEL 0x12 30 #define TSCE16_TECH_PROC 0x4 /* 16nm */ 31 32 #define TSCE16_NOF_LANES_IN_CORE (4) 33 #define TSCE16_PHY_ALL_LANES (0xf) 34 #define TSCE16_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \ 35 do{\ 36 PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\ 37 (_phy_access)->type = (_core_access)->type; \ 38 (_phy_access)->port_loc = (_core_access)->port_loc; \ 39 (_phy_access)->device_op_mode = (_core_access)->device_op_mode; \ 40 (_phy_access)->access.lane_mask = TSCE16_PHY_ALL_LANES; \ 41 }while(0) 42 43 #define TSCE16_PMD_CRC_UCODE 1 44 /* uController's firmware */ 45 extern unsigned char merlin16_ucode[]; 46 extern unsigned short merlin16_ucode_ver; 47 extern unsigned short merlin16_ucode_crc; 48 extern unsigned short merlin16_ucode_len; 49 50 typedef int (*sequncer_control_f)(const phymod_access_t* core, uint32_t enable); 51 typedef int (*rx_DFE_tap_control_set_f)(const phymod_access_t* phy, uint32_t val); 52 extern int tsce16_phy_interface_config_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_ref_clk_t ref_clock, phymod_phy_inf_config_t* config); 53 54 55 STATIC 56 int _tsce16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 57 { 58 struct merlin16_uc_lane_config_st serdes_firmware_config; 59 phymod_phy_access_t phy_copy; 60 int start_lane, num_lane, i; 61 /* uint32_t rst_status; */ 62 uint32_t is_warm_boot; 63 64 PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config)); 65 PHYMOD_IF_ERR_RETURN 66 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 67 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 68 69 for (i = 0; i < num_lane; i++) { 70 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 71 continue; 72 } 73 phy_copy.access.lane_mask = 1 << (start_lane + i); 74 serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS; 75 serdes_firmware_config.field.an_enabled = fw_config.AnEnabled; 76 serdes_firmware_config.field.dfe_on = fw_config.DfeOn; 77 serdes_firmware_config.field.force_brdfe_on = fw_config.ForceBrDfe; 78 /* serdes_firmware_config.field.cl72_emulation_en = fw_config.Cl72Enable; */ 79 serdes_firmware_config.field.scrambling_dis = fw_config.ScramblingDisable; 80 serdes_firmware_config.field.unreliable_los = fw_config.UnreliableLos; 81 serdes_firmware_config.field.media_type = fw_config.MediaType; 82 serdes_firmware_config.field.cl72_auto_polarity_en = fw_config.Cl72AutoPolEn; 83 serdes_firmware_config.field.cl72_restart_timeout_en = fw_config.Cl72RestTO; 84 85 PHYMOD_IF_ERR_RETURN(PHYMOD_IS_WRITE_DISABLED(&phy_copy.access, &is_warm_boot)); 86 87 88 if (!is_warm_boot) { 89 /* PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_read(&phy_copy.access, &rst_status)); */ 90 /* if (rst_status) */ PHYMOD_IF_ERR_RETURN (merlin16_lane_soft_reset_release(&phy_copy.access, 0)); 91 PHYMOD_IF_ERR_RETURN(merlin16_set_uc_lane_cfg(&phy_copy.access, serdes_firmware_config)); 92 /* if (rst_status) */ PHYMOD_IF_ERR_RETURN (merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 93 } 94 } 95 return PHYMOD_E_NONE; 96 } 97 98 int tsce16_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified) 99 { 100 int ioerr = 0; 101 const phymod_access_t *pm_acc = &core->access; 102 PHYID2r_t id2; 103 PHYID3r_t id3; 104 MAIN0_SERDESIDr_t serdesid; 105 /* DIG_REVID0r_t revid; */ 106 uint32_t model; 107 int rv; 108 *is_identified = 0; 109 110 #ifdef PHYMOD_DIAG 111 /* 112 LOG_ERROR(BSL_LS_SOC_PHYMOD,("%-22s: core_id=%0d adr=%0x lane_mask=%0x v_adr=%0x v_mask=%0x\n", 113 __func__, core_id, pm_acc->addr, pm_acc->lane_mask, phymod_dbg_addr, phymod_dbg_mask)); */ 114 PHYMOD_VDBG(DBG_CFG, pm_acc,("%-22s: core_id=%0d adr=%0"PRIx32" lane_mask=%0"PRIx32"\n", 115 __func__, (int)core_id, pm_acc->addr, pm_acc->lane_mask)); 116 #endif 117 if (core_id == 0) { 118 ioerr += READ_PHYID2r(pm_acc, &id2); 119 ioerr += READ_PHYID3r(pm_acc, &id3); 120 } else { 121 PHYID2r_SET(id2, ((core_id >> 16) & 0xffff)); 122 PHYID3r_SET(id3, core_id & 0xffff); 123 } 124 125 if (PHYID2r_GET(id2) == TSCE16_ID0 && PHYID3r_GET(id3) == TSCE16_ID1) { 126 /* PHY IDs match - now check PCS model */ 127 ioerr += READ_MAIN0_SERDESIDr(pm_acc, &serdesid); 128 model = MAIN0_SERDESIDr_MODEL_NUMBERf_GET(serdesid); 129 if (model == TSCE16_MODEL) { 130 if (MAIN0_SERDESIDr_TECH_PROCf_GET(serdesid) == TSCE16_TECH_PROC) { 131 *is_identified = 1; 132 } 133 } 134 } 135 rv = ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE; 136 #ifdef PHYMOD_DIAG 137 PHYMOD_VDBG(DBG_CFG, pm_acc,("%-22s: core_id=%0d identified=%0d rv=%0d adr=%0"PRIx32" lmask=%0"PRIx32"\n", 138 __func__, (int)core_id, (int)*is_identified, rv, pm_acc->addr, pm_acc->lane_mask)); 139 #endif 140 return rv; 141 } 142 143 int tsce16_core_info_get(const phymod_core_access_t* phy, phymod_core_info_t* info) 144 { 145 uint32_t serdes_id; 146 PHYID2r_t id2; 147 PHYID3r_t id3; 148 char core_name[15]="Tsce16"; 149 const phymod_access_t *pm_acc = &phy->access; 150 151 PHYMOD_IF_ERR_RETURN 152 (temod16_revid_read(&phy->access, &serdes_id)); 153 PHYMOD_IF_ERR_RETURN 154 (phymod_core_name_get(phy, serdes_id, core_name, info)); 155 156 info->serdes_id = serdes_id; 157 info->core_version = phymodCoreVersionTsce16; 158 159 PHYMOD_IF_ERR_RETURN(READ_PHYID2r(pm_acc, &id2)); 160 PHYMOD_IF_ERR_RETURN(READ_PHYID3r(pm_acc, &id3)); 161 162 info->phy_id0 = (uint16_t) id2.v[0]; 163 info->phy_id1 = (uint16_t) id3.v[0]; 164 165 return PHYMOD_E_NONE; 166 } 167 168 /* set lane swapping for core 169 */ 170 int tsce16_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map) 171 { 172 uint32_t pcs_swap = 0 , lane; 173 uint8_t pmd_tx_lane_map[PHYMOD_MAX_LANES_PER_CORE]; 174 uint8_t pmd_rx_lane_map[PHYMOD_MAX_LANES_PER_CORE]; 175 uint8_t num_lanes = (uint8_t) lane_map->num_of_lanes; 176 177 #ifdef PHYMOD_DIAG 178 const phymod_access_t *pm_acc; 179 pm_acc = &core->access; 180 PHYMOD_VDBG(DBG_TOP, pm_acc, 181 ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" rx_lane_map=%0"PRIx32"%0"PRIx32"%0"PRIx32"%0"PRIx32" tx_lane_map=%0"PRIx32"%0"PRIx32"%0"PRIx32"%0"PRIx32"\n", 182 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, 183 lane_map->lane_map_rx[3], lane_map->lane_map_rx[2], 184 lane_map->lane_map_rx[1], lane_map->lane_map_rx[0], 185 lane_map->lane_map_tx[3], lane_map->lane_map_tx[2], 186 lane_map->lane_map_tx[1], lane_map->lane_map_tx[0])); 187 #endif 188 189 /* PCS lane map; PCS lane map specifies which board-side lane a switch-side lane should 190 * connect to. For instance, on the bring-up board, for TX, lane[0] on the switch is 191 * actually routed to lane[2] on the board; lane[2] on the switch is routed to lane[0] 192 * on the board. In this case, "2" should be put in lane_map_tx[0], and "0" should be 193 * put in lane_map_tx[2]. 194 */ 195 if (lane_map->num_of_lanes != TSCE16_NOF_LANES_IN_CORE) { 196 return PHYMOD_E_CONFIG; 197 } 198 199 for (lane = 0; lane < TSCE16_NOF_LANES_IN_CORE; lane++) { 200 pcs_swap += lane_map->lane_map_tx[lane] << (lane*4); 201 pcs_swap += lane_map->lane_map_rx[lane] << (lane*4 + 16); 202 } 203 204 if (!PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(core->device_op_mode)) { 205 PHYMOD_IF_ERR_RETURN(temod16_pcs_lane_swap(&core->access, pcs_swap)); 206 } 207 208 /* PMD lane address map; PCS lane map specifies the lane map from switch's point of 209 * view, while PMD lane address map specifies the same lane map from board's point 210 * of view. 211 * For instance, if PCS specify that lane[0] on the switch TX side connects to lane[2] 212 * on the board TX side, PCS would put "2" in lane_map_tx[0], and PMD would put "0" 213 * in lane_map_tx[2]. From PMD's point of view, this means that board lane[2] should 214 * connect to switch lane[0]. 215 */ 216 for (lane = 0; lane < TSCE16_NOF_LANES_IN_CORE; lane++) { 217 pmd_tx_lane_map[(int)lane_map->lane_map_tx[lane]] = lane; 218 pmd_rx_lane_map[(int)lane_map->lane_map_rx[lane]] = lane; 219 } 220 221 PHYMOD_IF_ERR_RETURN 222 (merlin16_map_lanes(&core->access, num_lanes, pmd_tx_lane_map, pmd_rx_lane_map)); 223 224 return PHYMOD_E_NONE; 225 } 226 227 /* load tsce fw. the fw_loader parameter is valid just for external fw load */ 228 STATIC 229 int _tsce16_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader) 230 { 231 #ifdef PHYMOD_DIAG 232 const phymod_access_t *pm_acc; 233 pm_acc = &core->access; 234 PHYMOD_VDBG(DBG_CFG, pm_acc, 235 ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" load_meth=%0d", 236 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, (int)load_method)); 237 #endif 238 239 switch (load_method) { 240 case phymodFirmwareLoadMethodInternal: 241 PHYMOD_IF_ERR_RETURN(merlin16_ucode_mdio_load(&core->access, merlin16_ucode, merlin16_ucode_len)); 242 break; 243 case phymodFirmwareLoadMethodExternal: 244 PHYMOD_NULL_CHECK(fw_loader); 245 PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_pre(&core->access)); 246 PHYMOD_IF_ERR_RETURN(fw_loader(core, merlin16_ucode_len, merlin16_ucode)); 247 PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_post(&core->access)); 248 break; 249 case phymodFirmwareLoadMethodNone: 250 break; 251 default: 252 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method)); 253 } 254 return PHYMOD_E_NONE; 255 } 256 257 int tsce16_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_config) 258 { 259 struct merlin16_uc_core_config_st serdes_firmware_core_config; 260 PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(serdes_firmware_core_config)); 261 serdes_firmware_core_config.field.core_cfg_from_pcs = fw_config.CoreConfigFromPCS; 262 serdes_firmware_core_config.field.vco_rate = fw_config.VcoRate; 263 264 PHYMOD_IF_ERR_RETURN(merlin16_INTERNAL_set_uc_core_config(&phy->access, serdes_firmware_core_config)); 265 return PHYMOD_E_NONE; 266 } 267 268 int tsce16_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_config) 269 { 270 struct merlin16_uc_core_config_st serdes_firmware_core_config; 271 PHYMOD_IF_ERR_RETURN(merlin16_get_uc_core_config(&phy->access, &serdes_firmware_core_config)); 272 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 273 fw_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs; 274 fw_config->VcoRate = serdes_firmware_core_config.field.vco_rate; 275 return PHYMOD_E_NONE; 276 } 277 278 int tsce16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 279 { 280 phymod_phy_access_t phy_copy; 281 int start_lane, num_lane, i; 282 283 PHYMOD_IF_ERR_RETURN 284 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 285 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 286 287 /*Hold the per lne soft reset bit*/ 288 for (i = 0; i < num_lane; i++) { 289 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 290 continue; 291 } 292 phy_copy.access.lane_mask = 1 << (start_lane + i); 293 PHYMOD_IF_ERR_RETURN 294 (merlin16_lane_soft_reset_release(&phy_copy.access, 0)); 295 } 296 297 PHYMOD_IF_ERR_RETURN 298 (_tsce16_phy_firmware_lane_config_set(phy, fw_config)); 299 /*Hold the per lne soft reset bit*/ 300 for (i = 0; i < num_lane; i++) { 301 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 302 continue; 303 } 304 phy_copy.access.lane_mask = 1 << (start_lane + i); 305 PHYMOD_IF_ERR_RETURN 306 (merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 307 } 308 309 PHYMOD_IF_ERR_RETURN 310 (temod16_trigger_speed_change(&phy->access)); 311 312 return PHYMOD_E_NONE; 313 } 314 315 int tsce16_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config) 316 { 317 struct merlin16_uc_lane_config_st serdes_firmware_config; 318 PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config)); 319 320 PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy->access, &serdes_firmware_config)); 321 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 322 fw_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs; 323 fw_config->AnEnabled = serdes_firmware_config.field.an_enabled; 324 fw_config->DfeOn = serdes_firmware_config.field.dfe_on; 325 fw_config->ForceBrDfe = serdes_firmware_config.field.force_brdfe_on; 326 fw_config->Cl72AutoPolEn = serdes_firmware_config.field.cl72_auto_polarity_en; 327 fw_config->Cl72RestTO = serdes_firmware_config.field.cl72_restart_timeout_en; 328 fw_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis; 329 fw_config->UnreliableLos = serdes_firmware_config.field.unreliable_los; 330 fw_config->MediaType = serdes_firmware_config.field.media_type; 331 fw_config->Cl72AutoPolEn = serdes_firmware_config.field.cl72_auto_polarity_en; 332 fw_config->Cl72RestTO = serdes_firmware_config.field.cl72_restart_timeout_en; 333 334 return PHYMOD_E_NONE; 335 } 336 337 int tsce16_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity) 338 { 339 PHYMOD_IF_ERR_RETURN 340 (merlin16_polarity_set(&phy->access, polarity->tx_polarity, polarity->rx_polarity)); 341 342 return PHYMOD_E_NONE; 343 } 344 345 int tsce16_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity) 346 { 347 PHYMOD_IF_ERR_RETURN 348 (merlin16_polarity_get(&phy->access, &polarity->tx_polarity, &polarity->rx_polarity)); 349 350 return PHYMOD_E_NONE; 351 } 352 353 int tsce16_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 354 { 355 PHYMOD_IF_ERR_RETURN 356 (merlin16_apply_txfir_cfg(&phy->access, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2)); 357 358 return PHYMOD_E_NONE; 359 } 360 361 int tsce16_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 362 { 363 phymod_phy_access_t pm_phy_copy; 364 int start_lane, num_lane, i; 365 366 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 367 PHYMOD_IF_ERR_RETURN 368 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 369 370 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) { 371 for (i = 0; i < num_lane; i++) { 372 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 373 continue; 374 } 375 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 376 PHYMOD_IF_ERR_RETURN(temod16_port_enable_set(&pm_phy_copy.access, 0)); 377 } 378 } 379 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) { 380 for (i = 0; i < num_lane; i++) { 381 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 382 continue; 383 } 384 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 385 PHYMOD_IF_ERR_RETURN(temod16_port_enable_set(&pm_phy_copy.access, 1)); 386 } 387 } 388 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) { 389 /* disable tx on the PMD side */ 390 PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&phy->access, 1)); 391 } 392 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) { 393 /* enable tx on the PMD side */ 394 PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&phy->access, 0)); 395 } 396 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) { 397 /* disable rx on the PMD side */ 398 PHYMOD_IF_ERR_RETURN(temod16_rx_squelch_set(&phy->access, 1)); 399 } 400 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) { 401 /* enable rx on the PMD side */ 402 PHYMOD_IF_ERR_RETURN(temod16_rx_squelch_set(&phy->access, 0)); 403 } 404 return PHYMOD_E_NONE; 405 } 406 407 int tsce16_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control) 408 { 409 switch (tx_control) { 410 case phymodTxTrafficDisable: 411 PHYMOD_IF_ERR_RETURN(temod16_tx_lane_control_set(&phy->access, TEMOD16_TX_LANE_TRAFFIC_DISABLE)); 412 break; 413 case phymodTxTrafficEnable: 414 PHYMOD_IF_ERR_RETURN(temod16_tx_lane_control_set(&phy->access, TEMOD16_TX_LANE_TRAFFIC_ENABLE)); 415 break; 416 case phymodTxReset: 417 PHYMOD_IF_ERR_RETURN(temod16_tx_lane_control_set(&phy->access, TEMOD16_TX_LANE_RESET)); 418 break; 419 case phymodTxSquelchOn: 420 PHYMOD_IF_ERR_RETURN(temod16_tx_squelch_set(&phy->access, 1)); 421 break; 422 case phymodTxSquelchOff: 423 PHYMOD_IF_ERR_RETURN(temod16_tx_squelch_set(&phy->access, 0)); 424 break; 425 default: 426 break; 427 } 428 return PHYMOD_E_NONE; 429 } 430 431 int tsce16_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control) 432 { 433 int enable, reset, tx_lane; 434 uint32_t lb_enable; 435 phymod_phy_access_t pm_phy_copy; 436 int start_lane, num_lane; 437 438 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 439 /* next program the tx fir taps and driver current based on the input */ 440 PHYMOD_IF_ERR_RETURN 441 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 442 443 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 444 445 PHYMOD_IF_ERR_RETURN(temod16_tx_squelch_get(&pm_phy_copy.access, &enable)); 446 447 /* next check if PMD loopback is on */ 448 if (enable) { 449 PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 450 if (lb_enable) enable = 0; 451 } 452 453 if (enable) { 454 *tx_control = phymodTxSquelchOn; 455 } else { 456 PHYMOD_IF_ERR_RETURN(temod16_tx_lane_control_get(&pm_phy_copy.access, &reset, &tx_lane)); 457 if (!reset) { 458 *tx_control = phymodTxReset; 459 } else if (!tx_lane) { 460 *tx_control = phymodTxTrafficDisable; 461 } else { 462 *tx_control = phymodTxTrafficEnable; 463 } 464 } 465 return PHYMOD_E_NONE; 466 } 467 468 int tsce16_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control) 469 { 470 phymod_phy_access_t pm_phy_copy; 471 int start_lane, num_lane, i; 472 473 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 474 /* next program the tx fir taps and driver current based on the input */ 475 PHYMOD_IF_ERR_RETURN 476 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 477 478 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 479 480 switch (rx_control) { 481 case phymodRxReset: 482 PHYMOD_IF_ERR_RETURN(temod16_rx_lane_control_set(&phy->access, 1)); 483 break; 484 case phymodRxSquelchOn: 485 for (i = 0; i < num_lane; i++) { 486 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 487 continue; 488 } 489 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 490 PHYMOD_IF_ERR_RETURN(temod16_rx_squelch_set(&pm_phy_copy.access, 1)); 491 } 492 break; 493 case phymodRxSquelchOff: 494 for (i = 0; i < num_lane; i++) { 495 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 496 continue; 497 } 498 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 499 PHYMOD_IF_ERR_RETURN(temod16_rx_squelch_set(&pm_phy_copy.access, 0)); 500 } 501 break; 502 default: 503 break; 504 } 505 return PHYMOD_E_NONE; 506 } 507 508 int tsce16_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control) 509 { 510 int enable, reset; 511 uint32_t lb_enable; 512 phymod_phy_access_t pm_phy_copy; 513 int start_lane, num_lane; 514 515 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 516 /* next program the tx fir taps and driver current based on the input */ 517 PHYMOD_IF_ERR_RETURN 518 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 519 520 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 521 522 PHYMOD_IF_ERR_RETURN(temod16_rx_squelch_get(&pm_phy_copy.access, &enable)); 523 /* next check if PMD loopback is on */ 524 if (enable) { 525 PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 526 if (lb_enable) enable = 0; 527 } 528 if (enable) { 529 *rx_control = phymodRxSquelchOn; 530 } else { 531 PHYMOD_IF_ERR_RETURN(temod16_rx_lane_control_get(&pm_phy_copy.access, &reset)); 532 if (reset == 0) { 533 *rx_control = phymodRxReset; 534 } else { 535 *rx_control = phymodRxSquelchOff; 536 } 537 } 538 return PHYMOD_E_NONE; 539 } 540 541 542 int tsce16_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 543 { 544 uint32_t current_pll_div=0; 545 uint32_t new_pll_div=0; 546 uint16_t new_speed_vec=0; 547 int16_t new_os_mode =-1; 548 temod16_spd_intfc_type spd_intf = TEMOD16_SPD_ILLEGAL; 549 phymod_phy_access_t pm_phy_copy; 550 int start_lane=0, num_lane, i, pll_switch = 0; 551 uint32_t os_dfeon=0; 552 uint32_t scrambling_dis=0; 553 uint32_t u_os_mode = 0; 554 int dfe_adjust = -1; 555 int lane_bkup; 556 int cl72_allowed=0, cl72_req=0; 557 phymod_phy_inf_config_t temp_config; 558 temod16_pll_mode_type pll_mode; 559 uint16_t or_val=0; 560 561 /* sc_table_entry exp_entry; RAVI */ 562 phymod_firmware_lane_config_t firmware_lane_config; 563 #ifdef PHYMOD_DIAG 564 const phymod_access_t *pm_acc; 565 pm_acc = &phy->access; 566 PHYMOD_VDBG(DBG_SPD, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" speed=%0d intf=%0d(%s) flags=%0x\n", 567 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, config->data_rate, config->interface_type, 568 phymod_interface_t_mapping[config->interface_type].key, flags)); 569 #endif 570 571 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 572 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 573 PHYMOD_MEMSET(&temp_config, 0x0, sizeof(temp_config)); 574 575 /* end of special mode */ 576 firmware_lane_config.MediaType = 0; 577 578 /* next program the tx fir taps and driver current based on the input */ 579 PHYMOD_IF_ERR_RETURN 580 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 581 582 /* reset pcs */ 583 temod16_disable_set(&phy->access); 584 585 /* Hold the per lne soft reset bit */ 586 for (i = 0; i < num_lane; i++) { 587 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 588 continue; 589 } 590 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 591 PHYMOD_IF_ERR_RETURN 592 (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 0)); 593 } 594 /* deassert pmd_tx_disable_pin_dis if it is set by ILKn */ 595 /* remove pmd_tx_disable_pin_dis it may be asserted because of ILKn */ 596 if (config->interface_type != phymodInterfaceBypass) { 597 for (i = 0; i < num_lane; i++) { 598 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 599 continue; 600 } 601 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 602 PHYMOD_IF_ERR_RETURN 603 (merlin16_pmd_tx_disable_pin_dis_set(&phy->access, 0)); 604 } 605 } 606 /* disable CL72 */ 607 for (i = 0; i < num_lane; i++) { 608 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 609 continue; 610 } 611 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 612 PHYMOD_IF_ERR_RETURN 613 (temod16_clause72_control(&pm_phy_copy.access, 0)); 614 } 615 616 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 617 PHYMOD_IF_ERR_RETURN 618 (tsce16_phy_firmware_lane_config_get(&pm_phy_copy, &firmware_lane_config)); 619 620 /* make sure that an and config from pcs is off */ 621 firmware_lane_config.AnEnabled = 0; 622 firmware_lane_config.LaneConfigFromPCS = 0; 623 624 /* and also make sure the cl72 restart timeout is enabled */ 625 firmware_lane_config.Cl72RestTO = 1; 626 firmware_lane_config.Cl72AutoPolEn = 0; 627 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 628 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 629 } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 630 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 631 } else { 632 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 633 } 634 635 PHYMOD_IF_ERR_RETURN 636 (temod16_update_port_mode(&phy->access, (int *) &pll_switch)); 637 638 spd_intf = TEMOD16_SPD_10_X1_SGMII; /* to prevent undefinded TEMOD16_SPD_ILLEGAL accessing tables */ 639 640 /* find the speed */ 641 if (config->interface_type == phymodInterfaceXFI) { 642 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 643 } else if (config->interface_type == phymodInterfaceSFI) { 644 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 645 } else if (config->interface_type == phymodInterfaceSFPDAC) { 646 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 647 } else if (config->interface_type == phymodInterface1000X) { 648 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 649 } else if (config->interface_type == phymodInterfaceSGMII) { 650 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 651 } else if (config->interface_type == phymodInterfaceLR) { 652 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 653 } else if (config->interface_type == phymodInterfaceSR) { 654 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 655 } 656 657 cl72_req = (flags & (PHYMOD_INTF_F_CL72_REQUESTED_BY_CNFG|PHYMOD_INTF_F_CL72_REQUESTED_BY_API))?1:0; 658 switch (config->data_rate) { 659 case 10: 660 if(config->pll_divider_req==80) { 661 spd_intf = TEMOD16_SPD_10_SGMII; 662 /* high_vco_1G = 0; */ 663 } else { 664 spd_intf = TEMOD16_SPD_10_X1_SGMII; 665 } 666 break; 667 case 100: 668 if(config->pll_divider_req==80) { 669 spd_intf = TEMOD16_SPD_100_SGMII; 670 /* high_vco_1G = 0; */ 671 } else { 672 spd_intf = TEMOD16_SPD_100_X1_SGMII; 673 } 674 break; 675 case 1000: 676 if(config->pll_divider_req==80) { 677 spd_intf = TEMOD16_SPD_1000_SGMII; 678 /* high_vco_1G = 0; */ 679 } else { 680 spd_intf = TEMOD16_SPD_1000_X1_SGMII; 681 } 682 break; 683 case 2500: 684 if(config->pll_divider_req==80) { 685 spd_intf = TEMOD16_SPD_2500; 686 /* high_vco_1G = 0; */ 687 } else { 688 spd_intf = TEMOD16_SPD_2500_X1; 689 } 690 break; 691 case 5000: 692 if(config->pll_divider_req==80) { 693 spd_intf = TEMOD16_SPD_5000; 694 } else { 695 spd_intf = TEMOD16_SPD_5000_XFI; 696 } 697 break; 698 case 10000: 699 if (config->interface_type == phymodInterfaceXAUI) { 700 spd_intf = TEMOD16_SPD_10000; 701 } else if (config->interface_type == phymodInterfaceRXAUI) { 702 spd_intf = TEMOD16_SPD_10000_X2; 703 } else if(config->interface_type == phymodInterfaceX2) { 704 spd_intf = TEMOD16_SPD_10000_X2; 705 } else { 706 cl72_allowed = 1 ; 707 if (config->interface_type == phymodInterfaceSFI) { 708 spd_intf = TEMOD16_SPD_10000_XFI; 709 dfe_adjust = 0; 710 } else if (config->interface_type == phymodInterfaceXFI) { 711 spd_intf = TEMOD16_SPD_10000_XFI; 712 dfe_adjust = 0; 713 } else if (config->interface_type == phymodInterfaceXGMII) { 714 spd_intf = TEMOD16_SPD_10000; 715 } else if (config->interface_type == phymodInterfaceKR) { 716 spd_intf = TEMOD16_SPD_10000_XFI; 717 dfe_adjust = 1; 718 } else { 719 spd_intf = TEMOD16_SPD_10000_XFI; 720 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 721 dfe_adjust = 0; 722 } 723 } 724 } 725 break; 726 case 11000: 727 cl72_allowed = 1 ; 728 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 729 spd_intf = TEMOD16_SPD_10600_XFI_HG; 730 } else { 731 spd_intf = TEMOD16_SPD_10000_XFI; 732 } 733 break; 734 case 12000: 735 cl72_allowed = 1 ; 736 spd_intf = TEMOD16_SPD_12P12_XFI; 737 if ((config->interface_type == phymodInterfaceSFI) || 738 (config->interface_type == phymodInterfaceXFI)) { 739 dfe_adjust = 0 ; 740 } 741 break; 742 case 15000: 743 spd_intf = TEMOD16_SPD_15000; 744 break; 745 case 16000: 746 spd_intf = TEMOD16_SPD_16000; 747 break; 748 case 20000: 749 if(config->interface_type == phymodInterfaceKR2 || 750 config->interface_type == phymodInterfaceCR2) { 751 cl72_allowed = 1 ; 752 spd_intf = TEMOD16_SPD_20G_MLD_DXGXS ; 753 } else if(config->interface_type == phymodInterfaceRXAUI) { 754 cl72_allowed = 1 ; 755 spd_intf = TEMOD16_SPD_20G_DXGXS; 756 } else { 757 if (PHYMOD_INTF_MODES_SCR_GET(config)) { 758 spd_intf = TEMOD16_SPD_20000_SCR; 759 } else { 760 spd_intf = TEMOD16_SPD_20000; 761 } 762 } 763 break; 764 case 21000: 765 if(config->interface_type == phymodInterfaceRXAUI) { 766 spd_intf = TEMOD16_SPD_20G_DXGXS; 767 } else if(config->interface_type == phymodInterfaceKR2 || 768 config->interface_type == phymodInterfaceCR2) { 769 spd_intf = TEMOD16_SPD_21G_HI_MLD_DXGXS; 770 } else { 771 spd_intf = TEMOD16_SPD_21000; 772 } 773 break; 774 case 24000: 775 if (num_lane == 2) { 776 cl72_allowed = 1; 777 spd_intf = TEMOD16_SPD_24P24_MLD_DXGXS; 778 } 779 break; 780 case 40000: 781 cl72_allowed = 1 ; 782 spd_intf = TEMOD16_SPD_40G_XLAUI; 783 if (config->interface_type == phymodInterfaceXLAUI) { 784 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 785 dfe_adjust = 0 ; 786 } else if(PHYMOD_INTF_MODES_FIBER_GET(config)) { 787 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics ; 788 dfe_adjust = 0 ; 789 } else if(config->interface_type == phymodInterfaceCR4) { 790 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable ; 791 } else if (config->interface_type == phymodInterfaceKR4) { 792 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 793 } else if((config->interface_type == phymodInterfaceXGMII) || PHYMOD_INTF_MODES_HIGIG_GET(config)) { 794 spd_intf = TEMOD16_SPD_40G_X4; 795 } else { 796 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane ; 797 } 798 break; 799 case 42000: 800 cl72_allowed = 1 ; 801 if ((config->interface_type == phymodInterfaceKR4) && 802 PHYMOD_INTF_MODES_HIGIG_GET(config)) { 803 spd_intf = TEMOD16_SPD_42G_XLAUI; 804 }else if((config->interface_type == phymodInterfaceCR4) && 805 PHYMOD_INTF_MODES_HIGIG_GET(config)) { 806 spd_intf = TEMOD16_SPD_42G_XLAUI; 807 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 808 }else if((config->interface_type == phymodInterfaceXGMII) || PHYMOD_INTF_MODES_HIGIG_GET(config)) { 809 spd_intf = TEMOD16_SPD_40G_X4; 810 } else { 811 spd_intf = TEMOD16_SPD_42G_XLAUI; 812 } 813 break; 814 case 48000: 815 cl72_allowed = 1 ; 816 spd_intf = TEMOD16_SPD_48P48_MLD; 817 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 818 dfe_adjust = 0; 819 break; 820 default: 821 PHYMOD_RETURN_WITH_ERR 822 (PHYMOD_E_CONFIG, (_PHYMOD_MSG("this speed %d is not supported by tsce16"), 823 config->data_rate)); 824 break; 825 } 826 827 828 if(PHYMOD_INTF_MODES_HIGIG_GET(config)) { 829 PHYMOD_IF_ERR_RETURN 830 (temod16_encode_set(&phy->access, spd_intf, 1)); 831 PHYMOD_IF_ERR_RETURN 832 (temod16_decode_set(&phy->access, spd_intf, 1)); 833 } else { 834 PHYMOD_IF_ERR_RETURN 835 (temod16_encode_set(&phy->access, spd_intf, 0)); 836 PHYMOD_IF_ERR_RETURN 837 (temod16_decode_set(&phy->access, spd_intf, 0)); 838 } 839 840 if (config->data_rate==10 || 841 config->data_rate==100 || 842 config->data_rate==1000) { 843 if (config->interface_type == phymodInterfaceSGMII) { 844 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 845 } 846 if (config->interface_type == phymodInterface1000X) { 847 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 848 } 849 } 850 851 /* get the current PLL setting */ 852 pm_phy_copy.access.lane_mask = 1 << start_lane; 853 PHYMOD_IF_ERR_RETURN 854 (temod16_pll_config_get(&pm_phy_copy.access, &pll_mode)); 855 current_pll_div = (uint32_t) pll_mode; 856 857 /* find the new os mode and new pll div */ 858 if (config->interface_type == phymodInterfaceBypass) { 859 new_pll_div = TEMOD16_PLL_MODE_DIV_66; 860 if (config->data_rate == 1000) { 861 new_os_mode = 8; 862 } 863 /* the other supported speed could only be 10G */ 864 else { 865 new_os_mode = 0; 866 } 867 } else { 868 PHYMOD_IF_ERR_RETURN 869 (temod16_plldiv_lkup_get(&phy->access, spd_intf, config->ref_clock, &new_pll_div, &new_speed_vec)); 870 871 if (config->ref_clock == phymodRefClk156Mhz) { 872 switch (config->data_rate) { 873 case 21000: 874 if (num_lane == 2) { 875 new_pll_div = TEMOD16_PLL_MODE_DIV_70; 876 } 877 break; 878 case 42000: 879 new_pll_div = TEMOD16_PLL_MODE_DIV_70; 880 break; 881 default: 882 break; 883 } 884 } 885 } 886 887 if (new_os_mode>=0) { 888 /* 0x80000000 causes PMD OS mode to be configured based on new_os_mode, 889 * otherwise the PMD OS mode will be based on spd_intf. 890 */ 891 u_os_mode = new_os_mode | 0x80000000; 892 } else { 893 u_os_mode = 0; 894 } 895 896 897 PHYMOD_IF_ERR_RETURN 898 (temod16_pmd_osmode_set(&phy->access, spd_intf, u_os_mode)); 899 PHYMOD_IF_ERR_RETURN(temod16_osdfe_on_lkup_get(&phy->access, spd_intf, &os_dfeon)); 900 PHYMOD_IF_ERR_RETURN(temod16_scrambling_dis_lkup_get(&phy->access, spd_intf, &scrambling_dis)); 901 firmware_lane_config.DfeOn = 0; 902 firmware_lane_config.ScramblingDisable = scrambling_dis; 903 /* Override scrambler settings in PCS when disable scrambler is needed*/ 904 if(PHYMOD_INTF_F_SCRAMBLE_FORCED_ON & flags) { 905 firmware_lane_config.ScramblingDisable = 0 ; 906 907 or_val = 1; 908 PHYMOD_IF_ERR_RETURN 909 (temod16_override_set(&phy->access, TEMOD16_OVERRIDE_SCR_MODE , or_val)); 910 PHYMOD_IF_ERR_RETURN 911 (temod16_override_set(&phy->access, TEMOD16_OVERRIDE_DESCR_MODE, or_val)); 912 } else if (PHYMOD_INTF_F_SCRAMBLE_FORCED_OFF & flags) { 913 firmware_lane_config.ScramblingDisable = 1 ; 914 915 or_val = 0; 916 PHYMOD_IF_ERR_RETURN 917 (temod16_override_set(&phy->access, TEMOD16_OVERRIDE_SCR_MODE , or_val)); 918 PHYMOD_IF_ERR_RETURN 919 (temod16_override_set(&phy->access, TEMOD16_OVERRIDE_DESCR_MODE, or_val)); 920 } else { 921 /* Override scrambler settings in PCS when disable scrambler is needed*/ 922 if (scrambling_dis){ 923 or_val = 0; 924 PHYMOD_IF_ERR_RETURN 925 (temod16_override_set(&phy->access, TEMOD16_OVERRIDE_SCR_MODE , or_val)); 926 PHYMOD_IF_ERR_RETURN 927 (temod16_override_set(&phy->access, TEMOD16_OVERRIDE_DESCR_MODE, or_val)); 928 } 929 else { 930 PHYMOD_IF_ERR_RETURN 931 (temod16_override_clear(&phy->access, TEMOD16_OVERRIDE_SCR_MODE)); 932 PHYMOD_IF_ERR_RETURN 933 (temod16_override_clear(&phy->access, TEMOD16_OVERRIDE_DESCR_MODE)); 934 } 935 } 936 937 if (os_dfeon == 0x1) 938 firmware_lane_config.DfeOn = 1; 939 940 if (dfe_adjust >=0) 941 firmware_lane_config.DfeOn = dfe_adjust; 942 943 /* the speed is not supported */ 944 if (new_pll_div == TEMOD16_PLL_MODE_DIV_ILLEGAL) { 945 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 946 (_PHYMOD_MSG("this speed %d is not supported at this ref clock %d"), 947 config->data_rate, config->ref_clock)); 948 } 949 950 951 952 /* if pll change is enabled. new_pll_div is the reg vector value */ 953 if ((current_pll_div != new_pll_div) && (PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) { 954 if (config->interface_type != phymodInterfaceBypass) { 955 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 956 (_PHYMOD_MSG("pll has to change for speed_set from %u to %u but DONT_TURN_OFF_PLL flag is enabled"), 957 (unsigned int)current_pll_div, (unsigned int)new_pll_div)); 958 } 959 } 960 961 /* pll switch is required and expected */ 962 if((current_pll_div != new_pll_div) && !(PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) { 963 lane_bkup = pm_phy_copy.access.lane_mask; 964 pm_phy_copy.access.lane_mask = 0xf; 965 temod16_disable_set(&pm_phy_copy.access); 966 pm_phy_copy.access.lane_mask = lane_bkup; 967 968 PHYMOD_IF_ERR_RETURN 969 (merlin16_core_soft_reset_release(&pm_phy_copy.access, 0)); 970 971 /* set the PLL divider */ 972 PHYMOD_IF_ERR_RETURN 973 (temod16_pll_config_set(&pm_phy_copy.access, new_pll_div, config->ref_clock)); 974 975 /* change the master port num to the current caller port */ 976 PHYMOD_IF_ERR_RETURN 977 (temod16_master_port_num_set(&pm_phy_copy.access, start_lane)); 978 979 PHYMOD_IF_ERR_RETURN 980 (temod16_pll_reset_enable_set(&pm_phy_copy.access, 1)); 981 982 PHYMOD_IF_ERR_RETURN 983 (merlin16_core_soft_reset_release(&pm_phy_copy.access, 1)); 984 } 985 986 if (cl72_req & cl72_allowed) { 987 for (i = 0; i < num_lane; i++) { 988 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 989 continue; 990 } 991 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 992 PHYMOD_IF_ERR_RETURN 993 (temod16_clause72_control(&pm_phy_copy.access, 1)); 994 } 995 } 996 997 if (config->interface_type != phymodInterfaceBypass) { 998 if (flags & PHYMOD_INTF_F_SET_SPD_NO_TRIGGER) { 999 (temod16_set_spd_intf(&phy->access, spd_intf, 1)); 1000 } else { 1001 PHYMOD_IF_ERR_RETURN 1002 (temod16_set_spd_intf(&phy->access, spd_intf, 0)); 1003 } 1004 } 1005 1006 for (i = 0; i < num_lane; i++) { 1007 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1008 continue; 1009 } 1010 pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i); 1011 PHYMOD_IF_ERR_RETURN 1012 (_tsce16_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config)); 1013 } 1014 1015 /* release the per lne soft reset bit */ 1016 for (i = 0; i < num_lane; i++) { 1017 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1018 continue; 1019 } 1020 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1021 PHYMOD_IF_ERR_RETURN 1022 (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1)); 1023 } 1024 #ifdef PHYMOD_DIAG 1025 PHYMOD_VDBG(DBG_SPD, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" spd=%0d(%s) media=%0d\n", 1026 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, spd_intf, e2s_temod16_spd_intfc_type[spd_intf], 1027 firmware_lane_config.MediaType)); 1028 #endif 1029 1030 return PHYMOD_E_NONE; 1031 } 1032 1033 1034 1035 STATIC 1036 int _tsce16_speed_id_interface_config_get(const phymod_phy_access_t* phy, int speed_id, 1037 phymod_phy_inf_config_t* config, uint16_t an_enable, 1038 phymod_firmware_lane_config_t *lane_config) 1039 { 1040 int hg_enable = 0; 1041 uint32_t current_pll_div=0; 1042 temod16_pll_mode_type pll_mode; 1043 1044 PHYMOD_IF_ERR_RETURN 1045 (temod16_pll_config_get(&phy->access, &pll_mode)); 1046 current_pll_div = (uint32_t) pll_mode; 1047 1048 PHYMOD_IF_ERR_RETURN 1049 (temod16_hg_enable_get(&phy->access, &hg_enable)); 1050 1051 switch (speed_id) { 1052 case 0x1: 1053 config->data_rate = 10; 1054 config->interface_type = phymodInterfaceSGMII; 1055 break; 1056 case 0x2: 1057 config->data_rate = 100; 1058 config->interface_type = phymodInterfaceSGMII; 1059 break; 1060 case 0x3: 1061 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1062 config->interface_type = phymodInterface1000X; 1063 } else { 1064 config->interface_type = phymodInterfaceSGMII; 1065 } 1066 config->data_rate = 1000; 1067 break; 1068 case 0x4: 1069 config->data_rate = 1000; 1070 config->interface_type = phymodInterfaceCX; 1071 break; 1072 case 0x5: 1073 config->data_rate = 1000; 1074 config->interface_type = phymodInterfaceKX; 1075 break; 1076 case 0x6: 1077 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1078 config->interface_type = phymodInterface1000X; 1079 } else { 1080 config->interface_type = phymodInterfaceSGMII; 1081 } 1082 config->data_rate = 2500; 1083 break; 1084 case 0x7: 1085 config->data_rate = 5000; 1086 config->interface_type = phymodInterface1000X; 1087 break; 1088 case 0x8: 1089 config->data_rate = 10000; 1090 config->interface_type = phymodInterfaceCX4; 1091 break; 1092 case 0x9: 1093 config->data_rate = 10000; 1094 config->interface_type = phymodInterfaceXAUI; 1095 break; 1096 case 0xa: 1097 config->data_rate = 10000; 1098 config->interface_type = phymodInterfaceXGMII; 1099 break; 1100 case 0xb: 1101 config->data_rate = 13000; 1102 config->interface_type = phymodInterfaceXGMII; 1103 break; 1104 case 0xc: 1105 config->data_rate = 15000; 1106 config->interface_type = phymodInterfaceXGMII; 1107 break; 1108 case 0xd: 1109 config->data_rate = 16000; 1110 config->interface_type = phymodInterfaceXGMII; 1111 break; 1112 case 0xe: 1113 config->data_rate = 20000; 1114 config->interface_type = phymodInterfaceCX4; 1115 break; 1116 case 0xf: 1117 config->data_rate = 10000; 1118 config->interface_type = phymodInterfaceRXAUI; 1119 break; 1120 case 0x10: 1121 config->data_rate = 10000; 1122 config->interface_type = phymodInterfaceX2; 1123 break; 1124 case 0x11: 1125 config->data_rate = 20000; 1126 config->interface_type = phymodInterfaceXGMII; 1127 break; 1128 case 0x12: 1129 config->data_rate = 10500; 1130 config->interface_type = phymodInterfaceX2; 1131 break; 1132 case 0x13: 1133 config->data_rate = 21000; 1134 config->interface_type = phymodInterfaceCX4; 1135 break; 1136 case 0x14: 1137 config->data_rate = 13000; /* round up from 12700 */ 1138 config->interface_type = phymodInterfaceX2; 1139 break; 1140 case 0x15: 1141 config->data_rate = 25450; 1142 config->interface_type = phymodInterfaceKR4; 1143 break; 1144 case 0x16: 1145 config->data_rate = 15750; 1146 config->interface_type = phymodInterfaceX2; 1147 break; 1148 case 0x17: 1149 config->data_rate = 31500; 1150 config->interface_type = phymodInterfaceXGMII; 1151 break; 1152 case 0x18: 1153 config->data_rate = 31500; 1154 config->interface_type = phymodInterfaceKR4; 1155 break; 1156 case 0x19: 1157 config->data_rate = 20000; 1158 config->interface_type = phymodInterfaceCX2; 1159 break; 1160 case 0x1a: 1161 if(current_pll_div==TEMOD16_PLL_MODE_DIV_70) { 1162 config->data_rate = 21000; 1163 } else { 1164 config->data_rate = 20000; 1165 } 1166 config->interface_type = phymodInterfaceX2; 1167 break; 1168 case 0x1b: /* digital_operationSpeeds_SPEED_40G_X4; BRCM */ 1169 if(current_pll_div==TEMOD16_PLL_MODE_DIV_70) { 1170 config->data_rate = 42000; 1171 } else { 1172 config->data_rate = 40000; 1173 } 1174 config->interface_type = phymodInterfaceXGMII; 1175 break; 1176 case 0x1c: 1177 if(current_pll_div==TEMOD16_PLL_MODE_DIV_80) { 1178 config->data_rate = 12000; 1179 } else if(current_pll_div==TEMOD16_PLL_MODE_DIV_70) { 1180 config->data_rate = 11000; 1181 } else { 1182 config->data_rate = 10000; 1183 } 1184 config->interface_type = phymodInterfaceKR; 1185 if(!an_enable) { 1186 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1187 if(config->interface_type == phymodInterfaceSR) { 1188 config->interface_type = phymodInterfaceSR; 1189 } else { 1190 config->interface_type = phymodInterfaceSFI; 1191 } 1192 } else if (lane_config->MediaType == phymodFirmwareMediaTypeCopperCable) { 1193 config->interface_type = phymodInterfaceCR; 1194 } else if (lane_config->DfeOn == 1) { 1195 config->interface_type = phymodInterfaceKR; 1196 } else { 1197 config->interface_type = phymodInterfaceXFI; 1198 } 1199 } 1200 break; 1201 case 0x1d: 1202 config->data_rate = 11000; 1203 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1204 if(config->interface_type == phymodInterfaceSR) { 1205 config->interface_type = phymodInterfaceSR; 1206 } else { 1207 config->interface_type = phymodInterfaceSFI; 1208 } 1209 } else { 1210 config->interface_type = phymodInterfaceXFI; 1211 } 1212 break; 1213 case 0x1e: 1214 if(current_pll_div == TEMOD16_PLL_MODE_DIV_80) { 1215 config->data_rate = 25000; 1216 } else if(current_pll_div == TEMOD16_PLL_MODE_DIV_70) { 1217 config->data_rate = 21000; 1218 } else { 1219 config->data_rate = 20000; 1220 } 1221 if (lane_config->MediaType == phymodFirmwareMediaTypeCopperCable) { 1222 config->interface_type = phymodInterfaceCR2; 1223 } else { 1224 config->interface_type = phymodInterfaceKR2; 1225 } 1226 break; 1227 case 0x1f: 1228 if(current_pll_div == TEMOD16_PLL_MODE_DIV_80) { 1229 config->data_rate = 25000; 1230 } else if(current_pll_div == TEMOD16_PLL_MODE_DIV_70) { 1231 config->data_rate = 21000; 1232 } else { 1233 config->data_rate = 20000; 1234 } 1235 config->interface_type = phymodInterfaceCR2; 1236 break; 1237 case 0x20: 1238 config->data_rate = 21000; 1239 config->interface_type = phymodInterfaceKR2; 1240 break; 1241 case 0x21: /* digital_operationSpeeds_SPEED_40G_KR4 */ 1242 if (current_pll_div == TEMOD16_PLL_MODE_DIV_80) { 1243 config->data_rate = 48000; 1244 } else if (current_pll_div == TEMOD16_PLL_MODE_DIV_70) { 1245 config->data_rate = 42000; 1246 } else { 1247 config->data_rate = 40000; 1248 } 1249 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1250 config->interface_type = phymodInterfaceSR4; 1251 } else if (lane_config->MediaType == phymodFirmwareMediaTypeCopperCable) { 1252 config->interface_type = phymodInterfaceCR4; 1253 } else if ((lane_config->MediaType == phymodFirmwareMediaTypePcbTraceBackPlane) && hg_enable) { 1254 config->interface_type = phymodInterfaceKR4; 1255 } else if(lane_config->DfeOn) { 1256 config->interface_type = phymodInterfaceKR4; 1257 } else { 1258 config->interface_type = phymodInterfaceXLAUI; 1259 } 1260 break; 1261 case 0x22: 1262 config->data_rate = 40000; 1263 config->interface_type = phymodInterfaceCR4; 1264 break; 1265 case 0x23: /* digital_operationSpeeds_SPEED_42G_X4; atcually MLD */ 1266 config->data_rate = 42000; 1267 if(lane_config->MediaType == phymodFirmwareMediaTypeCopperCable){ 1268 config->interface_type = phymodInterfaceCR4; 1269 }else if(lane_config->DfeOn) { 1270 config->interface_type = phymodInterfaceKR4; 1271 } else { 1272 config->interface_type = phymodInterfaceXLAUI; 1273 } 1274 break; 1275 case 0x24: 1276 config->data_rate = 100000; 1277 config->interface_type = phymodInterfaceCR10; 1278 break; 1279 case 0x25: 1280 config->data_rate = 106000; 1281 config->interface_type = phymodInterfaceCAUI; 1282 break; 1283 case 0x26: 1284 config->data_rate = 120000; 1285 /* config->interface_type = phymodInterfaceXGMII; */ 1286 config->interface_type = phymodInterfaceCAUI; 1287 break; 1288 case 0x27: 1289 config->data_rate = 127000; 1290 config->interface_type = phymodInterfaceCAUI; 1291 break; 1292 case 0x28: 1293 config->data_rate = 12000; 1294 config->interface_type = phymodInterfaceKR; 1295 break; 1296 case 0x29: 1297 config->data_rate = 24000; 1298 config->interface_type = phymodInterfaceKR2; 1299 break; 1300 case 0x2a: 1301 config->data_rate = 48000; 1302 config->interface_type = phymodInterfaceKR4; 1303 break; 1304 case 0x31: 1305 config->data_rate = 5000; 1306 config->interface_type = phymodInterfaceKR; 1307 break; 1308 case 0x32: 1309 config->data_rate = 10500; 1310 config->interface_type = phymodInterfaceXGMII; 1311 break; 1312 case 0x35: 1313 config->data_rate = 10; 1314 config->interface_type = phymodInterfaceSGMII; 1315 break; 1316 case 0x36: 1317 config->data_rate = 100; 1318 config->interface_type = phymodInterfaceSGMII; 1319 break; 1320 case 0x37: 1321 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1322 config->interface_type = phymodInterface1000X; 1323 } else { 1324 config->interface_type = phymodInterfaceSGMII; 1325 } 1326 config->data_rate = 1000; 1327 break; 1328 case 0x38: 1329 if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) { 1330 config->interface_type = phymodInterface1000X; 1331 } else { 1332 config->interface_type = phymodInterfaceSGMII; 1333 } 1334 config->data_rate = 2500; 1335 break; 1336 case 0x39: 1337 config->data_rate = 10000; 1338 config->interface_type = phymodInterfaceXAUI; 1339 break; 1340 case 0x3a: 1341 config->data_rate = 10000; 1342 config->interface_type = phymodInterfaceXAUI; 1343 break; 1344 default: 1345 config->data_rate = 0; 1346 config->interface_type = phymodInterfaceSGMII; 1347 break; 1348 } 1349 1350 return PHYMOD_E_NONE; 1351 } 1352 1353 1354 /* flags- unused parameter */ 1355 int tsce16_phy_interface_config_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_ref_clk_t ref_clock, phymod_phy_inf_config_t* config) 1356 { 1357 int speed_id; 1358 phymod_firmware_lane_config_t firmware_lane_config; 1359 phymod_phy_access_t pm_phy_copy; 1360 int start_lane, num_lane; 1361 temod16_an_control_t an_control; 1362 int an_complete = 0; 1363 1364 #ifdef PHYMOD_DIAG 1365 const phymod_access_t *pm_acc; 1366 pm_acc = &phy->access; 1367 PHYMOD_VDBG(DBG_LNK, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" flags=%"PRIx32"\n", 1368 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, flags)); 1369 #endif 1370 config->ref_clock = ref_clock; 1371 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1372 PHYMOD_IF_ERR_RETURN 1373 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1374 1375 PHYMOD_IF_ERR_RETURN 1376 (temod16_speed_id_get(&phy->access, &speed_id)); 1377 1378 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 1379 1380 PHYMOD_MEMSET(&an_control, 0x0, sizeof(temod16_an_control_t)); 1381 PHYMOD_IF_ERR_RETURN 1382 (temod16_autoneg_control_get(&pm_phy_copy.access, &an_control, &an_complete)); 1383 1384 PHYMOD_IF_ERR_RETURN 1385 (tsce16_phy_firmware_lane_config_get(&pm_phy_copy, &firmware_lane_config)); 1386 1387 PHYMOD_IF_ERR_RETURN 1388 (_tsce16_speed_id_interface_config_get(phy, speed_id, config, an_control.enable, &firmware_lane_config)); 1389 1390 if (firmware_lane_config.MediaType == phymodFirmwareMediaTypeOptics) { 1391 PHYMOD_INTF_MODES_FIBER_SET(config); 1392 } else if (firmware_lane_config.MediaType == phymodFirmwareMediaTypeCopperCable) { 1393 PHYMOD_INTF_MODES_FIBER_CLR(config); 1394 PHYMOD_INTF_MODES_COPPER_SET(config); 1395 } else { 1396 PHYMOD_INTF_MODES_FIBER_CLR(config); 1397 PHYMOD_INTF_MODES_BACKPLANE_SET(config); 1398 } 1399 1400 switch (config->interface_type) { 1401 case phymodInterfaceSGMII: 1402 { 1403 if (config->data_rate == 1000) { 1404 if (!PHYMOD_INTF_MODES_FIBER_GET(config)) { 1405 config->interface_type = phymodInterfaceSGMII; 1406 } else { 1407 config->interface_type = phymodInterface1000X; 1408 } 1409 } else { 1410 config->interface_type = phymodInterfaceSGMII; 1411 } 1412 break; 1413 } 1414 case phymodInterfaceKR: 1415 { 1416 if (!an_control.enable) { 1417 if (config->data_rate == 10000) { 1418 if (!PHYMOD_INTF_MODES_FIBER_GET(config)) { 1419 if (firmware_lane_config.DfeOn == 1) { 1420 config->interface_type = phymodInterfaceKR; 1421 } else { 1422 config->interface_type = phymodInterfaceXFI; 1423 } 1424 } else { 1425 config->interface_type = phymodInterfaceSFI; 1426 } 1427 } else { 1428 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 1429 config->interface_type = phymodInterfaceSR; 1430 } else { 1431 config->interface_type = phymodInterfaceKR; 1432 } 1433 } 1434 } else { 1435 config->interface_type = phymodInterfaceKR; 1436 } 1437 break; 1438 } 1439 default: 1440 break; 1441 } 1442 1443 #ifdef PHYMOD_DIAG 1444 PHYMOD_VDBG(DBG_CFG, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" sp_id=0x%0x rate=%0d phy_intf=%0d(%s) intf_md=%0x\n", 1445 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, speed_id, config->data_rate, 1446 config->interface_type, phymod_interface_t_mapping[config->interface_type].key, config->interface_modes)); 1447 #endif 1448 return PHYMOD_E_NONE; 1449 } 1450 1451 int tsce16_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability) 1452 { 1453 temod16_an_ability_t value; 1454 int start_lane, num_lane; 1455 phymod_phy_access_t phy_copy; 1456 1457 PHYMOD_IF_ERR_RETURN 1458 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1459 1460 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1461 phy_copy.access.lane_mask = 0x1 << start_lane; 1462 1463 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 1464 1465 value.cl37_adv.an_cl72 = an_ability->an_cl72; 1466 value.cl73_adv.an_cl72 = an_ability->an_cl72; 1467 value.cl37_adv.an_hg2 = an_ability->an_hg2; 1468 1469 if (PHYMOD_AN_FEC_CL74_GET(an_ability->an_fec)) { 1470 value.cl37_adv.an_fec = TEMOD16_FEC_CL74_SUPRTD_REQSTD; 1471 value.cl73_adv.an_fec = TEMOD16_FEC_CL74_SUPRTD_REQSTD; 1472 } else if (PHYMOD_AN_FEC_OFF_GET(an_ability->an_fec)) { 1473 value.cl37_adv.an_fec = TEMOD16_FEC_SUPRTD_NOT_REQSTD; 1474 value.cl73_adv.an_fec = TEMOD16_FEC_SUPRTD_NOT_REQSTD; 1475 } 1476 1477 /* check if sgmii or not */ 1478 if (PHYMOD_AN_CAP_SGMII_GET(an_ability)) { 1479 switch (an_ability->sgmii_speed) { 1480 case phymod_CL37_SGMII_10M: 1481 value.cl37_adv.cl37_sgmii_speed = TEMOD16_CL37_SGMII_10M; 1482 break; 1483 case phymod_CL37_SGMII_100M: 1484 value.cl37_adv.cl37_sgmii_speed = TEMOD16_CL37_SGMII_100M; 1485 break; 1486 case phymod_CL37_SGMII_1000M: 1487 value.cl37_adv.cl37_sgmii_speed = TEMOD16_CL37_SGMII_1000M; 1488 break; 1489 default: 1490 value.cl37_adv.cl37_sgmii_speed = TEMOD16_CL37_SGMII_1000M; 1491 break; 1492 } 1493 } 1494 1495 /* check pause */ 1496 if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability)) { 1497 value.cl37_adv.an_pause = TEMOD16_SYMM_PAUSE; 1498 value.cl73_adv.an_pause = TEMOD16_SYMM_PAUSE; 1499 } 1500 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 1501 value.cl37_adv.an_pause = TEMOD16_ASYM_PAUSE; 1502 value.cl73_adv.an_pause = TEMOD16_ASYM_PAUSE; 1503 } 1504 if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 1505 value.cl37_adv.an_pause = TEMOD16_ASYM_SYMM_PAUSE; 1506 value.cl73_adv.an_pause = TEMOD16_ASYM_SYMM_PAUSE; 1507 } 1508 1509 /* check cl73 and cl73 bam ability */ 1510 if (PHYMOD_AN_CAP_1G_KX_GET(an_ability->an_cap)) 1511 value.cl73_adv.an_base_speed |= 1 << TEMOD16_CL73_1000BASE_KX; 1512 if (PHYMOD_AN_CAP_10G_KX4_GET(an_ability->an_cap)) 1513 value.cl73_adv.an_base_speed |= 1 << TEMOD16_CL73_10GBASE_KX4; 1514 if (PHYMOD_AN_CAP_10G_KR_GET(an_ability->an_cap)) 1515 value.cl73_adv.an_base_speed |= 1 << TEMOD16_CL73_10GBASE_KR; 1516 if (PHYMOD_AN_CAP_40G_KR4_GET(an_ability->an_cap)) 1517 value.cl73_adv.an_base_speed |= 1 << TEMOD16_CL73_40GBASE_KR4; 1518 if (PHYMOD_AN_CAP_40G_CR4_GET(an_ability->an_cap)) 1519 value.cl73_adv.an_base_speed |= 1 << TEMOD16_CL73_40GBASE_CR4; 1520 if (PHYMOD_AN_CAP_100G_CR10_GET(an_ability->an_cap)) 1521 value.cl73_adv.an_base_speed |= 1 << TEMOD16_CL73_100GBASE_CR10; 1522 1523 /* next check cl73 bam ability */ 1524 if (PHYMOD_BAM_CL73_CAP_20G_KR2_GET(an_ability->cl73bam_cap)) 1525 value.cl73_adv.an_bam_speed |= 1 << TEMOD16_CL73_BAM_20GBASE_KR2; 1526 if (PHYMOD_BAM_CL73_CAP_20G_CR2_GET(an_ability->cl73bam_cap)) 1527 value.cl73_adv.an_bam_speed |= 1 << TEMOD16_CL73_BAM_20GBASE_CR2; 1528 1529 /* check cl37 and cl37 bam ability */ 1530 if (PHYMOD_BAM_CL37_CAP_2P5G_GET(an_ability->cl37bam_cap)) 1531 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_2p5GBASE_X; 1532 if (PHYMOD_BAM_CL37_CAP_5G_X4_GET(an_ability->cl37bam_cap)) 1533 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_5GBASE_X4; 1534 if (PHYMOD_BAM_CL37_CAP_6G_X4_GET(an_ability->cl37bam_cap)) 1535 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_6GBASE_X4; 1536 if (PHYMOD_BAM_CL37_CAP_10G_HIGIG_GET(an_ability->cl37bam_cap)) 1537 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_10GBASE_X4; 1538 if (PHYMOD_BAM_CL37_CAP_10G_CX4_GET(an_ability->cl37bam_cap)) 1539 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_10GBASE_X4_CX4; 1540 if (PHYMOD_BAM_CL37_CAP_12G_X4_GET(an_ability->cl37bam_cap)) 1541 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_12GBASE_X4; 1542 if (PHYMOD_BAM_CL37_CAP_12P5_X4_GET(an_ability->cl37bam_cap)) 1543 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_12p5GBASE_X4; 1544 if (PHYMOD_BAM_CL37_CAP_10G_X2_CX4_GET(an_ability->cl37bam_cap)) 1545 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_10GBASE_X2_CX4; 1546 if (PHYMOD_BAM_CL37_CAP_10G_DXGXS_GET(an_ability->cl37bam_cap)) 1547 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_10GBASE_X2; 1548 if (PHYMOD_BAM_CL37_CAP_10P5G_DXGXS_GET(an_ability->cl37bam_cap)) 1549 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_BAM_10p5GBASE_X2; 1550 if (PHYMOD_BAM_CL37_CAP_12P7_DXGXS_GET(an_ability->cl37bam_cap)) 1551 value.cl37_adv.an_bam_speed |= 1 << TEMOD16_CL37_BAM_12p7GBASE_X2; 1552 if (PHYMOD_BAM_CL37_CAP_20G_X2_CX4_GET(an_ability->cl37bam_cap)) 1553 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_20GBASE_X2_CX4; 1554 if (PHYMOD_BAM_CL37_CAP_20G_X2_GET(an_ability->cl37bam_cap)) 1555 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_20GBASE_X2; 1556 if (PHYMOD_BAM_CL37_CAP_13G_X4_GET(an_ability->cl37bam_cap)) 1557 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_13GBASE_X4; 1558 if (PHYMOD_BAM_CL37_CAP_15G_X4_GET(an_ability->cl37bam_cap)) 1559 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_15GBASE_X4; 1560 if (PHYMOD_BAM_CL37_CAP_16G_X4_GET(an_ability->cl37bam_cap)) 1561 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_16GBASE_X4; 1562 if (PHYMOD_BAM_CL37_CAP_20G_X4_CX4_GET(an_ability->cl37bam_cap)) 1563 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_20GBASE_X4_CX4; 1564 if (PHYMOD_BAM_CL37_CAP_20G_X4_GET(an_ability->cl37bam_cap)) 1565 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_20GBASE_X4; 1566 if (PHYMOD_BAM_CL37_CAP_21G_X4_GET(an_ability->cl37bam_cap)) 1567 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_21GBASE_X4; 1568 if (PHYMOD_BAM_CL37_CAP_25P455G_GET(an_ability->cl37bam_cap)) 1569 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_25p455GBASE_X4; 1570 if (PHYMOD_BAM_CL37_CAP_31P5G_GET(an_ability->cl37bam_cap)) 1571 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_31p5GBASE_X4; 1572 if (PHYMOD_BAM_CL37_CAP_32P7G_GET(an_ability->cl37bam_cap)) 1573 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_32p7GBASE_X4; 1574 if (PHYMOD_BAM_CL37_CAP_40G_GET(an_ability->cl37bam_cap)) 1575 value.cl37_adv.an_bam_speed1 |= 1 << TEMOD16_CL37_BAM_40GBASE_X4; 1576 1577 PHYMOD_IF_ERR_RETURN 1578 (temod16_autoneg_set(&phy_copy.access, &value)); 1579 1580 return PHYMOD_E_NONE; 1581 } 1582 1583 int tsce16_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) { 1584 temod16_an_ability_t value; 1585 phymod_phy_access_t phy_copy; 1586 int start_lane, num_lane; 1587 temod16_an_control_t an_control; 1588 int an_complete = 0; 1589 int an_fec = 0; 1590 1591 PHYMOD_IF_ERR_RETURN 1592 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1593 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1594 phy_copy.access.lane_mask = 0x1 << start_lane; 1595 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 1596 1597 PHYMOD_IF_ERR_RETURN 1598 (temod16_autoneg_local_ability_get(&phy_copy.access, &value)); 1599 PHYMOD_IF_ERR_RETURN 1600 (temod16_autoneg_control_get(&phy_copy.access, &an_control, &an_complete)); 1601 an_ability_get_type->an_cl72 = value.cl37_adv.an_cl72 | value.cl73_adv.an_cl72; 1602 an_ability_get_type->an_hg2 = value.cl37_adv.an_hg2; 1603 1604 an_fec = value.cl37_adv.an_fec | value.cl73_adv.an_fec; 1605 an_ability_get_type->an_fec = 0; 1606 if (an_fec == TEMOD16_FEC_CL74_SUPRTD_REQSTD) { 1607 PHYMOD_AN_FEC_CL74_SET(an_ability_get_type->an_fec); 1608 } else { 1609 PHYMOD_AN_FEC_OFF_SET(an_ability_get_type->an_fec); 1610 } 1611 1612 /* get AN Clause */ 1613 switch (an_control.an_type) { 1614 case TEMOD16_AN_MODE_CL73: 1615 PHYMOD_AN_CAP_CL73_SET(an_ability_get_type); 1616 break; 1617 case TEMOD16_AN_MODE_CL37: 1618 PHYMOD_AN_CAP_CL37_SET(an_ability_get_type); 1619 break; 1620 case TEMOD16_AN_MODE_CL73BAM: 1621 PHYMOD_AN_CAP_CL73BAM_SET(an_ability_get_type); 1622 break; 1623 case TEMOD16_AN_MODE_CL37BAM: 1624 PHYMOD_AN_CAP_CL37BAM_SET(an_ability_get_type); 1625 break; 1626 case TEMOD16_AN_MODE_HPAM: 1627 PHYMOD_AN_CAP_HPAM_SET(an_ability_get_type); 1628 break; 1629 case TEMOD16_AN_MODE_SGMII: 1630 PHYMOD_AN_CAP_SGMII_SET(an_ability_get_type); 1631 break; 1632 case TEMOD16_AN_MODE_CL37_SGMII: 1633 PHYMOD_AN_CAP_SGMII_SET(an_ability_get_type); 1634 break; 1635 default: 1636 break; 1637 } 1638 1639 if ((value.cl37_adv.an_pause == TEMOD16_ASYM_PAUSE)||(value.cl73_adv.an_pause == TEMOD16_ASYM_PAUSE)) { 1640 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1641 } else if ((value.cl37_adv.an_pause == TEMOD16_SYMM_PAUSE)||(value.cl73_adv.an_pause == TEMOD16_SYMM_PAUSE)) { 1642 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1643 } else if ((value.cl37_adv.an_pause == TEMOD16_ASYM_SYMM_PAUSE)||(value.cl73_adv.an_pause == TEMOD16_ASYM_SYMM_PAUSE)) { 1644 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1645 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1646 } 1647 1648 /* get the cl37 sgmii speed */ 1649 switch (value.cl37_adv.cl37_sgmii_speed) { 1650 case TEMOD16_CL37_SGMII_10M: 1651 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M; 1652 break; 1653 case TEMOD16_CL37_SGMII_100M: 1654 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M; 1655 break; 1656 case TEMOD16_CL37_SGMII_1000M: 1657 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M; 1658 break; 1659 default: 1660 break; 1661 } 1662 /* first check cl73 ability */ 1663 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_100GBASE_CR10) 1664 PHYMOD_AN_CAP_100G_CR10_SET(an_ability_get_type->an_cap); 1665 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_40GBASE_CR4) 1666 PHYMOD_AN_CAP_40G_CR4_SET(an_ability_get_type->an_cap); 1667 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_40GBASE_KR4) 1668 PHYMOD_AN_CAP_40G_KR4_SET(an_ability_get_type->an_cap); 1669 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_10GBASE_KR) 1670 PHYMOD_AN_CAP_10G_KR_SET(an_ability_get_type->an_cap); 1671 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_10GBASE_KX4) 1672 PHYMOD_AN_CAP_10G_KX4_SET(an_ability_get_type->an_cap); 1673 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_1000BASE_KX) 1674 PHYMOD_AN_CAP_1G_KX_SET(an_ability_get_type->an_cap); 1675 1676 /* next check cl73 bam ability */ 1677 if (value.cl73_adv.an_bam_speed & 1 << TEMOD16_CL73_BAM_20GBASE_KR2) 1678 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_ability_get_type->cl73bam_cap); 1679 if (value.cl73_adv.an_bam_speed & 1 << TEMOD16_CL73_BAM_20GBASE_CR2) 1680 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_ability_get_type->cl73bam_cap); 1681 1682 /* check cl37 bam ability */ 1683 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_2p5GBASE_X) 1684 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_ability_get_type->cl37bam_cap); 1685 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_5GBASE_X4) 1686 PHYMOD_BAM_CL37_CAP_5G_X4_SET(an_ability_get_type->cl37bam_cap); 1687 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_6GBASE_X4) 1688 PHYMOD_BAM_CL37_CAP_6G_X4_SET(an_ability_get_type->cl37bam_cap); 1689 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X4) 1690 PHYMOD_BAM_CL37_CAP_10G_HIGIG_SET(an_ability_get_type->cl37bam_cap); 1691 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X4_CX4) 1692 PHYMOD_BAM_CL37_CAP_10G_CX4_SET(an_ability_get_type->cl37bam_cap); 1693 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X2) 1694 PHYMOD_BAM_CL37_CAP_10G_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1695 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X2_CX4) 1696 PHYMOD_BAM_CL37_CAP_10G_X2_CX4_SET(an_ability_get_type->cl37bam_cap); 1697 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_BAM_10p5GBASE_X2) 1698 PHYMOD_BAM_CL37_CAP_10P5G_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1699 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_12GBASE_X4) 1700 PHYMOD_BAM_CL37_CAP_12G_X4_SET(an_ability_get_type->cl37bam_cap); 1701 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_12p5GBASE_X4) 1702 PHYMOD_BAM_CL37_CAP_12P5_X4_SET(an_ability_get_type->cl37bam_cap); 1703 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_12p7GBASE_X2) 1704 PHYMOD_BAM_CL37_CAP_12P7_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1705 1706 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_13GBASE_X4) 1707 PHYMOD_BAM_CL37_CAP_13G_X4_SET(an_ability_get_type->cl37bam_cap); 1708 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_15GBASE_X4) 1709 PHYMOD_BAM_CL37_CAP_15G_X4_SET(an_ability_get_type->cl37bam_cap); 1710 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_15p75GBASE_X2) 1711 PHYMOD_BAM_CL37_CAP_12P7_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1712 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_16GBASE_X4) 1713 PHYMOD_BAM_CL37_CAP_16G_X4_SET(an_ability_get_type->cl37bam_cap); 1714 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X4_CX4) 1715 PHYMOD_BAM_CL37_CAP_20G_X4_CX4_SET(an_ability_get_type->cl37bam_cap); 1716 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X4) 1717 PHYMOD_BAM_CL37_CAP_20G_X4_SET(an_ability_get_type->cl37bam_cap); 1718 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X2) 1719 PHYMOD_BAM_CL37_CAP_20G_X2_SET(an_ability_get_type->cl37bam_cap); 1720 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X2_CX4) 1721 PHYMOD_BAM_CL37_CAP_20G_X2_CX4_SET(an_ability_get_type->cl37bam_cap); 1722 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_21GBASE_X4) 1723 PHYMOD_BAM_CL37_CAP_21G_X4_SET(an_ability_get_type->cl37bam_cap); 1724 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_25p455GBASE_X4) 1725 PHYMOD_BAM_CL37_CAP_25P455G_SET(an_ability_get_type->cl37bam_cap); 1726 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_31p5GBASE_X4) 1727 PHYMOD_BAM_CL37_CAP_31P5G_SET(an_ability_get_type->cl37bam_cap); 1728 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_32p7GBASE_X4) 1729 PHYMOD_BAM_CL37_CAP_32P7G_SET(an_ability_get_type->cl37bam_cap); 1730 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_40GBASE_X4) 1731 PHYMOD_BAM_CL37_CAP_40G_SET(an_ability_get_type->cl37bam_cap); 1732 1733 return PHYMOD_E_NONE; 1734 } 1735 1736 int tsce16_phy_autoneg_remote_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 1737 { 1738 temod16_an_ability_t value; 1739 temod16_an_control_t an_control; 1740 phymod_phy_access_t phy_copy; 1741 int an_complete = 0; 1742 int start_lane, num_lane; 1743 1744 PHYMOD_IF_ERR_RETURN 1745 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1746 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1747 phy_copy.access.lane_mask = 0x1 << start_lane; 1748 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 1749 PHYMOD_MEMSET(&an_control, 0x0, sizeof(an_control)); 1750 1751 PHYMOD_IF_ERR_RETURN 1752 (temod16_autoneg_remote_ability_get(&phy_copy.access, &value)); 1753 an_ability_get_type->an_cl72 = value.cl37_adv.an_cl72 | value.cl73_adv.an_cl72; 1754 an_ability_get_type->an_hg2 = value.cl37_adv.an_hg2; 1755 an_ability_get_type->an_fec = value.cl37_adv.an_fec | value.cl73_adv.an_fec; 1756 PHYMOD_IF_ERR_RETURN 1757 (temod16_autoneg_control_get(&phy_copy.access, &an_control, &an_complete)); 1758 1759 if (an_control.an_type == TEMOD16_AN_MODE_CL73 || an_control.an_type == TEMOD16_AN_MODE_CL73BAM) { 1760 if (value.cl73_adv.an_pause == TEMOD16_ASYM_PAUSE) { 1761 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1762 } else if (value.cl73_adv.an_pause == TEMOD16_SYMM_PAUSE) { 1763 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1764 } else if (value.cl73_adv.an_pause == TEMOD16_ASYM_SYMM_PAUSE) { 1765 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1766 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1767 } 1768 } else { 1769 if (value.cl37_adv.an_pause == TEMOD16_ASYM_PAUSE) { 1770 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1771 } else if (value.cl37_adv.an_pause == TEMOD16_SYMM_PAUSE) { 1772 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1773 } else if (value.cl37_adv.an_pause == TEMOD16_ASYM_SYMM_PAUSE) { 1774 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 1775 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 1776 } 1777 } 1778 1779 if (an_control.an_type == TEMOD16_AN_MODE_CL37) { 1780 PHYMOD_AN_CAP_CL37_SET(an_ability_get_type); 1781 } 1782 1783 /* get the cl37 sgmii speed */ 1784 switch (value.cl37_adv.cl37_sgmii_speed) { 1785 case TEMOD16_CL37_SGMII_10M: 1786 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M; 1787 break; 1788 case TEMOD16_CL37_SGMII_100M: 1789 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M; 1790 break; 1791 case TEMOD16_CL37_SGMII_1000M: 1792 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M; 1793 break; 1794 default: 1795 break; 1796 } 1797 1798 /* first check cl73 ability */ 1799 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_100GBASE_CR10) 1800 PHYMOD_AN_CAP_100G_CR10_SET(an_ability_get_type->an_cap); 1801 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_40GBASE_CR4) 1802 PHYMOD_AN_CAP_40G_CR4_SET(an_ability_get_type->an_cap); 1803 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_40GBASE_KR4) 1804 PHYMOD_AN_CAP_40G_KR4_SET(an_ability_get_type->an_cap); 1805 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_10GBASE_KR) 1806 PHYMOD_AN_CAP_10G_KR_SET(an_ability_get_type->an_cap); 1807 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_10GBASE_KX4) 1808 PHYMOD_AN_CAP_10G_KX4_SET(an_ability_get_type->an_cap); 1809 if (value.cl73_adv.an_base_speed & 1 << TEMOD16_CL73_1000BASE_KX) 1810 PHYMOD_AN_CAP_1G_KX_SET(an_ability_get_type->an_cap); 1811 1812 /* next check cl73 bam ability */ 1813 if (value.cl73_adv.an_bam_speed & 1 << TEMOD16_CL73_BAM_20GBASE_KR2) 1814 PHYMOD_BAM_CL73_CAP_20G_KR2_SET(an_ability_get_type->cl73bam_cap); 1815 if (value.cl73_adv.an_bam_speed & 1 << TEMOD16_CL73_BAM_20GBASE_CR2) 1816 PHYMOD_BAM_CL73_CAP_20G_CR2_SET(an_ability_get_type->cl73bam_cap); 1817 1818 /* check cl37 bam ability */ 1819 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_2p5GBASE_X) 1820 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_ability_get_type->cl37bam_cap); 1821 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_5GBASE_X4) 1822 PHYMOD_BAM_CL37_CAP_5G_X4_SET(an_ability_get_type->cl37bam_cap); 1823 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_6GBASE_X4) 1824 PHYMOD_BAM_CL37_CAP_6G_X4_SET(an_ability_get_type->cl37bam_cap); 1825 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X4) 1826 PHYMOD_BAM_CL37_CAP_10G_HIGIG_SET(an_ability_get_type->cl37bam_cap); 1827 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X4_CX4) 1828 PHYMOD_BAM_CL37_CAP_10G_CX4_SET(an_ability_get_type->cl37bam_cap); 1829 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X2) 1830 PHYMOD_BAM_CL37_CAP_10G_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1831 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_10GBASE_X2_CX4) 1832 PHYMOD_BAM_CL37_CAP_10G_X2_CX4_SET(an_ability_get_type->cl37bam_cap); 1833 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_BAM_10p5GBASE_X2) 1834 PHYMOD_BAM_CL37_CAP_10P5G_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1835 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_12GBASE_X4) 1836 PHYMOD_BAM_CL37_CAP_12G_X4_SET(an_ability_get_type->cl37bam_cap); 1837 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_12p5GBASE_X4) 1838 PHYMOD_BAM_CL37_CAP_12P5_X4_SET(an_ability_get_type->cl37bam_cap); 1839 if (value.cl37_adv.an_bam_speed & 1 << TEMOD16_CL37_BAM_12p7GBASE_X2) 1840 PHYMOD_BAM_CL37_CAP_12P7_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1841 1842 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_13GBASE_X4) 1843 PHYMOD_BAM_CL37_CAP_13G_X4_SET(an_ability_get_type->cl37bam_cap); 1844 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_15GBASE_X4) 1845 PHYMOD_BAM_CL37_CAP_15G_X4_SET(an_ability_get_type->cl37bam_cap); 1846 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_15p75GBASE_X2) 1847 PHYMOD_BAM_CL37_CAP_12P7_DXGXS_SET(an_ability_get_type->cl37bam_cap); 1848 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_16GBASE_X4) 1849 PHYMOD_BAM_CL37_CAP_16G_X4_SET(an_ability_get_type->cl37bam_cap); 1850 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X4_CX4) 1851 PHYMOD_BAM_CL37_CAP_20G_X4_CX4_SET(an_ability_get_type->cl37bam_cap); 1852 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X4) 1853 PHYMOD_BAM_CL37_CAP_20G_X4_SET(an_ability_get_type->cl37bam_cap); 1854 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X2) 1855 PHYMOD_BAM_CL37_CAP_20G_X2_SET(an_ability_get_type->cl37bam_cap); 1856 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_20GBASE_X2_CX4) 1857 PHYMOD_BAM_CL37_CAP_20G_X2_CX4_SET(an_ability_get_type->cl37bam_cap); 1858 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_21GBASE_X4) 1859 PHYMOD_BAM_CL37_CAP_21G_X4_SET(an_ability_get_type->cl37bam_cap); 1860 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_25p455GBASE_X4) 1861 PHYMOD_BAM_CL37_CAP_25P455G_SET(an_ability_get_type->cl37bam_cap); 1862 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_31p5GBASE_X4) 1863 PHYMOD_BAM_CL37_CAP_31P5G_SET(an_ability_get_type->cl37bam_cap); 1864 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_32p7GBASE_X4) 1865 PHYMOD_BAM_CL37_CAP_32P7G_SET(an_ability_get_type->cl37bam_cap); 1866 if (value.cl37_adv.an_bam_speed1 & 1 << TEMOD16_CL37_BAM_40GBASE_X4) 1867 PHYMOD_BAM_CL37_CAP_40G_SET(an_ability_get_type->cl37bam_cap); 1868 1869 return PHYMOD_E_NONE; 1870 } 1871 1872 int tsce16_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 1873 { 1874 int num_lane_adv_encoded; 1875 phymod_firmware_lane_config_t firmware_lane_config; 1876 phymod_firmware_core_config_t firmware_core_config_tmp; 1877 int start_lane, num_lane, i; 1878 phymod_phy_access_t phy_copy; 1879 temod16_an_control_t an_control; 1880 int single_port = 0 ; 1881 1882 PHYMOD_IF_ERR_RETURN 1883 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1884 1885 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 1886 PHYMOD_MEMSET(&an_control, 0x0, sizeof(an_control)); 1887 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1888 phy_copy.access.lane_mask = 0x1 << start_lane; 1889 1890 switch (an->num_lane_adv) { 1891 case 1: 1892 num_lane_adv_encoded = 0; 1893 break; 1894 case 2: 1895 num_lane_adv_encoded = 1; 1896 break; 1897 case 4: 1898 num_lane_adv_encoded = 2; 1899 break; 1900 case 10: 1901 num_lane_adv_encoded = 3; 1902 break; 1903 default: 1904 return PHYMOD_E_PARAM; 1905 } 1906 1907 if(PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_GET(an)) { 1908 an_control.pd_kx_en = 1; 1909 } else { 1910 an_control.pd_kx_en = 0; 1911 } 1912 if(PHYMOD_AN_F_SET_CL73_PDET_KX4_ENABLE_GET(an)) { 1913 an_control.pd_kx4_en = 1; 1914 } else { 1915 an_control.pd_kx4_en = 0; 1916 } 1917 an_control.num_lane_adv = num_lane_adv_encoded; 1918 an_control.enable = an->enable; 1919 an_control.an_property_type = 0x0; 1920 1921 switch (an->an_mode) { 1922 case phymod_AN_MODE_CL73: 1923 an_control.an_type = TEMOD16_AN_MODE_CL73; 1924 break; 1925 case phymod_AN_MODE_CL37: 1926 an_control.an_type = TEMOD16_AN_MODE_CL37; 1927 break; 1928 case phymod_AN_MODE_CL73BAM: 1929 an_control.an_type = TEMOD16_AN_MODE_CL73BAM; 1930 break; 1931 case phymod_AN_MODE_CL37BAM: 1932 an_control.an_type = TEMOD16_AN_MODE_CL37BAM; 1933 break; 1934 case phymod_AN_MODE_HPAM: 1935 an_control.an_type = TEMOD16_AN_MODE_HPAM; 1936 break; 1937 case phymod_AN_MODE_SGMII: 1938 an_control.an_type = TEMOD16_AN_MODE_SGMII; 1939 break; 1940 default: 1941 if(an->an_mode ==(phymod_AN_MODE_CL37_SGMII)) { 1942 an_control.an_type = TEMOD16_AN_MODE_CL37_SGMII ; 1943 } else { 1944 an_control.an_type = TEMOD16_AN_MODE_CL73; 1945 } 1946 break; 1947 } 1948 1949 PHYMOD_IF_ERR_RETURN 1950 (temod16_disable_set(&phy->access)); 1951 1952 if (an->num_lane_adv == 4) { 1953 phy_copy.access.lane_mask = 0x1 << start_lane; 1954 PHYMOD_IF_ERR_RETURN 1955 (tsce16_phy_firmware_core_config_get(&phy_copy, &firmware_core_config_tmp)); 1956 PHYMOD_IF_ERR_RETURN 1957 (merlin16_core_soft_reset_release(&phy_copy.access, 0)); 1958 1959 if (an->enable) { 1960 firmware_core_config_tmp.CoreConfigFromPCS = 1; 1961 } else { 1962 firmware_core_config_tmp.CoreConfigFromPCS = 0; 1963 } 1964 1965 PHYMOD_IF_ERR_RETURN 1966 (tsce16_phy_firmware_core_config_set(&phy_copy, firmware_core_config_tmp)); 1967 PHYMOD_IF_ERR_RETURN 1968 (merlin16_core_soft_reset_release(&phy_copy.access, 1)); 1969 } 1970 1971 1972 for (i = 0; i < num_lane; i++) { 1973 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1974 continue; 1975 } 1976 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1977 PHYMOD_IF_ERR_RETURN 1978 (merlin16_lane_soft_reset_release(&phy_copy.access, 0)); 1979 } 1980 1981 PHYMOD_IF_ERR_RETURN 1982 (tsce16_phy_firmware_lane_config_get(&phy_copy, &firmware_lane_config)); 1983 1984 if (!PHYMOD_AN_F_IGNORE_MEDIUM_CHECK_GET(an)) { 1985 if(an_control.an_type == TEMOD16_AN_MODE_CL37) { 1986 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 1987 } 1988 } 1989 1990 if (an->enable) { 1991 firmware_lane_config.AnEnabled = 1; 1992 firmware_lane_config.LaneConfigFromPCS = 1; 1993 firmware_lane_config.Cl72RestTO = 0; 1994 } else { 1995 firmware_lane_config.AnEnabled = 0; 1996 firmware_lane_config.LaneConfigFromPCS = 0; 1997 firmware_lane_config.Cl72RestTO = 1; 1998 } 1999 2000 for (i = 0; i < num_lane; i++) { 2001 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2002 continue; 2003 } 2004 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2005 PHYMOD_IF_ERR_RETURN 2006 (_tsce16_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config)); 2007 } 2008 2009 for (i = 0; i < num_lane; i++) { 2010 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2011 continue; 2012 } 2013 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2014 PHYMOD_IF_ERR_RETURN 2015 (merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 2016 } 2017 2018 phy_copy.access.lane_mask = 0x1 << start_lane; 2019 if (!an->enable) { 2020 PHYMOD_IF_ERR_RETURN 2021 (temod16_trigger_speed_change(&phy_copy.access)); 2022 } 2023 2024 if (an->enable) { 2025 if (an->num_lane_adv == 4) { 2026 single_port = 1 ; 2027 } else { 2028 single_port = 0 ; 2029 } 2030 PHYMOD_IF_ERR_RETURN 2031 (temod16_set_an_port_mode(&phy->access, an->enable, num_lane_adv_encoded, start_lane, single_port)); 2032 } else { 2033 single_port = 0; 2034 PHYMOD_IF_ERR_RETURN 2035 (temod16_set_an_port_mode(&phy->access, an->enable, num_lane_adv_encoded, start_lane, single_port)); 2036 } 2037 2038 2039 PHYMOD_IF_ERR_RETURN 2040 (temod16_autoneg_control(&phy_copy.access, &an_control)); 2041 2042 return PHYMOD_E_NONE; 2043 } 2044 2045 int tsce16_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done) 2046 { 2047 temod16_an_control_t an_control; 2048 phymod_phy_access_t phy_copy; 2049 int start_lane, num_lane; 2050 int an_complete = 0; 2051 2052 PHYMOD_IF_ERR_RETURN 2053 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2054 2055 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2056 phy_copy.access.lane_mask = 0x1 << start_lane; 2057 2058 PHYMOD_MEMSET(&an_control, 0x0, sizeof(temod16_an_control_t)); 2059 PHYMOD_IF_ERR_RETURN 2060 (temod16_autoneg_control_get(&phy_copy.access, &an_control, &an_complete)); 2061 2062 if (an_control.enable) { 2063 an->enable = 1; 2064 *an_done = an_complete; 2065 } else { 2066 an->enable = 0; 2067 *an_done = 0; 2068 } 2069 if(an_control.pd_kx_en) { 2070 PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_SET(an); 2071 } else { 2072 PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_CLR(an); 2073 } 2074 if(an_control.pd_kx4_en) { 2075 PHYMOD_AN_F_SET_CL73_PDET_KX4_ENABLE_SET(an); 2076 } else { 2077 PHYMOD_AN_F_SET_CL73_PDET_KX4_ENABLE_CLR(an); 2078 } 2079 2080 switch (an_control.an_type) { 2081 case TEMOD16_AN_MODE_CL73: 2082 an->an_mode = phymod_AN_MODE_CL73; 2083 break; 2084 case TEMOD16_AN_MODE_CL37: 2085 an->an_mode = phymod_AN_MODE_CL37; 2086 break; 2087 case TEMOD16_AN_MODE_CL73BAM: 2088 an->an_mode = phymod_AN_MODE_CL73BAM; 2089 break; 2090 case TEMOD16_AN_MODE_CL37BAM: 2091 an->an_mode = phymod_AN_MODE_CL37BAM; 2092 break; 2093 case TEMOD16_AN_MODE_HPAM: 2094 an->an_mode = phymod_AN_MODE_HPAM; 2095 break; 2096 case TEMOD16_AN_MODE_SGMII: 2097 an->an_mode = phymod_AN_MODE_SGMII; 2098 break; 2099 default: 2100 an->an_mode = phymod_AN_MODE_NONE; 2101 break; 2102 } 2103 2104 return PHYMOD_E_NONE; 2105 } 2106 2107 2108 /* 2109 * There is a significant change from TSCE 28nm to 16nm in terms of the 2110 * PMD programming sequence. Please be aware that the underlying PMD changed 2111 * from eagle to merlin16. The PCS programming sequence remained the same. 2112 * Some comments are added below to highlight the PMD programming changes. 2113 */ 2114 STATIC 2115 int _tsce16_core_init_pass1(const phymod_core_access_t* core, 2116 const phymod_core_init_config_t* init_config, 2117 const phymod_core_status_t* core_status) 2118 { 2119 phymod_phy_access_t phy_access, phy_access_copy; 2120 phymod_core_access_t core_copy; 2121 uint32_t uc_active = 0; 2122 int i, start_lane, num_lane; 2123 2124 TSCE16_CORE_TO_PHY_ACCESS(&phy_access, core); 2125 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 2126 core_copy.access.lane_mask = 0x1; 2127 2128 phy_access_copy = phy_access; 2129 phy_access_copy.access = core->access; 2130 phy_access_copy.access.lane_mask = 0x1; 2131 phy_access_copy.type = core->type; 2132 2133 /* 2134 * First step to program merlin16 is to do power reset. That is to 2135 * program field POR_H_RSTB and CORE_DP_H_RSTB in register PMD_X1_CTL 2136 */ 2137 PHYMOD_IF_ERR_RETURN 2138 (temod16_pmd_reset_seq(&core_copy.access, core_status->pmd_active)); 2139 2140 PHYMOD_IF_ERR_RETURN 2141 (phymod_util_lane_config_get(&phy_access.access, &start_lane, &num_lane)); 2142 2143 /* 2144 * Before programming the PMD lane address map register, the PMD lanes 2145 * have to be reset. Without do this, writing the PMD lane address map 2146 * regsiter will not take effect, meaning the reading value != writing 2147 * value. 2148 */ 2149 for (i = 0; i < num_lane; i++) { 2150 phy_access.access.lane_mask = 1 << (start_lane + i); 2151 PHYMOD_IF_ERR_RETURN 2152 (temod16_pmd_x4_reset(&phy_access.access)); 2153 } 2154 2155 PHYMOD_IF_ERR_RETURN(merlin16_uc_active_get(&core_copy.access, &uc_active)); 2156 if (uc_active) { 2157 return(PHYMOD_E_NONE); 2158 } 2159 2160 /* need to set the heart beat default is for 156.25M */ 2161 PHYMOD_IF_ERR_RETURN (temod16_refclk_set(&core_copy.access, 2162 init_config->interface.ref_clock)); 2163 2164 /* 2165 * In 28nm TSCE code the lane map programming was done in core_init_pass2. 2166 * Now it is moved to pass1 because merlin16 requires that PMD lane address 2167 * map be done before loading the uCode. Notice that before programming the 2168 * PMD lane address map, lane and lane DP has to be reset by calling 2169 * temod16_pmd_x4_reset(). 2170 */ 2171 PHYMOD_IF_ERR_RETURN 2172 (tsce16_core_lane_map_set(&core_copy, &init_config->lane_map)); 2173 2174 PHYMOD_IF_ERR_RETURN 2175 (merlin16_uc_reset(&phy_access_copy.access, 1)); 2176 2177 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 2178 if (_tsce16_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader)) { 2179 PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask)); 2180 PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT); 2181 } 2182 2183 } 2184 2185 PHYMOD_IF_ERR_RETURN 2186 (merlin16_pmd_ln_h_rstb_pkill_override(&phy_access_copy.access, 0x1)); 2187 PHYMOD_IF_ERR_RETURN 2188 (merlin16_uc_reset(&phy_access_copy.access, 0)); 2189 PHYMOD_IF_ERR_RETURN 2190 (merlin16_wait_uc_active(&phy_access_copy.access)); 2191 2192 /* Initialize software information table for the micro */ 2193 PHYMOD_IF_ERR_RETURN 2194 (merlin16_init_merlin16_info(&core_copy.access)); 2195 2196 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 2197 if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 2198 PHYMOD_IF_ERR_RETURN 2199 (merlin16_start_ucode_crc_calc(&core_copy.access, merlin16_ucode_len)); 2200 } 2201 } 2202 2203 return (PHYMOD_E_NONE); 2204 } 2205 2206 STATIC 2207 int _tsce16_core_init_pass2(const phymod_core_access_t* core, 2208 const phymod_core_init_config_t* init_config, 2209 const phymod_core_status_t* core_status) 2210 { 2211 phymod_phy_access_t phy_access, phy_access_copy; 2212 phymod_core_access_t core_copy; 2213 phymod_firmware_core_config_t firmware_core_config_tmp; 2214 2215 TSCE16_CORE_TO_PHY_ACCESS(&phy_access, core); 2216 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 2217 core_copy.access.lane_mask = 0x1; 2218 2219 phy_access_copy = phy_access; 2220 phy_access_copy.access = core->access; 2221 phy_access_copy.access.lane_mask = 0x1; 2222 phy_access_copy.type = core->type; 2223 2224 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 2225 if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 2226 PHYMOD_IF_ERR_RETURN 2227 (merlin16_check_ucode_crc(&core_copy.access, merlin16_ucode_crc, 250)); 2228 } 2229 } 2230 2231 PHYMOD_IF_ERR_RETURN( 2232 merlin16_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0)); 2233 2234 /* next check if in pcs-bypass mode */ 2235 if (PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(core->device_op_mode)) { 2236 phy_access_copy.access.lane_mask = 0xf; 2237 PHYMOD_IF_ERR_RETURN( 2238 temod16_pcs_ilkn_mode_set(&phy_access_copy.access)); 2239 phy_access_copy.access.lane_mask = 0x1; 2240 } 2241 2242 PHYMOD_IF_ERR_RETURN 2243 (temod16_autoneg_timer_init(&core->access)); 2244 2245 phy_access_copy.access.lane_mask = 0x1; 2246 2247 PHYMOD_IF_ERR_RETURN 2248 (temod16_master_port_num_set(&core->access, 0)); 2249 2250 PHYMOD_IF_ERR_RETURN 2251 (merlin16_core_soft_reset_release(&core_copy.access, 0)); 2252 2253 /* After loading the PMD uCode, PLL needs to be configured. */ 2254 PHYMOD_IF_ERR_RETURN 2255 (merlin16_configure_pll_refclk_div(&phy_access_copy.access, MERLIN16_PLL_REFCLK_156P25MHZ, 2256 MERLIN16_PLL_DIV_66)); 2257 2258 PHYMOD_IF_ERR_RETURN 2259 (tsce16_phy_firmware_core_config_get(&phy_access_copy, &firmware_core_config_tmp)); 2260 firmware_core_config_tmp.CoreConfigFromPCS = 0; 2261 2262 PHYMOD_IF_ERR_RETURN 2263 (tsce16_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config_tmp)); 2264 2265 2266 PHYMOD_IF_ERR_RETURN 2267 (temod16_cl74_chng_default (&core_copy.access)); 2268 2269 /* 2270 * After programming the PMD PLL, we need to release the core reset and lane reset. 2271 * Core reset is done below, and lane reset is done in tsce16_phy_init() by calling 2272 * temod16_pmd_x4_reset(). 2273 */ 2274 PHYMOD_IF_ERR_RETURN 2275 (merlin16_core_soft_reset_release(&core_copy.access, 1)); 2276 2277 return PHYMOD_E_NONE; 2278 } 2279 2280 int tsce16_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 2281 { 2282 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 2283 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 2284 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 2285 PHYMOD_IF_ERR_RETURN 2286 (_tsce16_core_init_pass1(core, init_config, core_status)); 2287 2288 if (PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 2289 return PHYMOD_E_NONE; 2290 } 2291 } 2292 2293 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 2294 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 2295 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) { 2296 PHYMOD_IF_ERR_RETURN 2297 (_tsce16_core_init_pass2(core, init_config, core_status)); 2298 } 2299 2300 return PHYMOD_E_NONE; 2301 2302 } 2303 2304 int tsce16_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config) 2305 { 2306 int pll_restart = 0; 2307 const phymod_access_t *pm_acc = &phy->access; 2308 phymod_phy_access_t pm_phy_copy; 2309 int start_lane, num_lane, i; 2310 int lane_bkup; 2311 phymod_polarity_t tmp_pol; 2312 #ifdef PHYMOD_DIAG 2313 PHYMOD_VDBG(DBG_CFG, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32"\n", 2314 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask)); 2315 #endif 2316 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 2317 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2318 2319 /* next program the tx fir taps and driver current based on the input */ 2320 PHYMOD_IF_ERR_RETURN 2321 (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane)); 2322 /* per lane based reset release */ 2323 PHYMOD_IF_ERR_RETURN 2324 (temod16_pmd_x4_reset(pm_acc)); 2325 2326 /* poll for per lane uc_dsc_ready */ 2327 lane_bkup = pm_phy_copy.access.lane_mask; 2328 for (i = 0; i < num_lane; i++) { 2329 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2330 continue; 2331 } 2332 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 2333 PHYMOD_IF_ERR_RETURN 2334 (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1)); 2335 } 2336 pm_phy_copy.access.lane_mask = lane_bkup; 2337 2338 /* program the rx/tx polarity */ 2339 for (i = 0; i < num_lane; i++) { 2340 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2341 continue; 2342 } 2343 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2344 tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) >> i & 0x1; 2345 tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) >> i & 0x1; 2346 PHYMOD_IF_ERR_RETURN 2347 (tsce16_phy_polarity_set(&pm_phy_copy, &tmp_pol)); 2348 } 2349 2350 for (i = 0; i < num_lane; i++) { 2351 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2352 continue; 2353 } 2354 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 2355 PHYMOD_IF_ERR_RETURN 2356 (tsce16_phy_tx_set(&pm_phy_copy, &init_config->tx[i])); 2357 } 2358 2359 /* next check if pcs-bypass mode */ 2360 if (PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 2361 PHYMOD_IF_ERR_RETURN 2362 (merlin16_pmd_tx_disable_pin_dis_set(&phy->access, 1)); 2363 PHYMOD_IF_ERR_RETURN 2364 (temod16_init_pcs_ilkn(&phy->access)); 2365 } 2366 2367 2368 pm_phy_copy.access.lane_mask = 0x1; 2369 2370 PHYMOD_IF_ERR_RETURN 2371 (temod16_update_port_mode(pm_acc, &pll_restart)); 2372 2373 PHYMOD_IF_ERR_RETURN 2374 (temod16_rx_lane_control_set(pm_acc, 1)); 2375 PHYMOD_IF_ERR_RETURN 2376 (temod16_tx_lane_control_set(pm_acc, TEMOD16_TX_LANE_RESET_TRAFFIC_ENABLE)); /* TX_LANE_CONTROL */ 2377 2378 return PHYMOD_E_NONE; 2379 } 2380 2381 int tsce16_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en) 2382 { 2383 struct merlin16_uc_lane_config_st serdes_firmware_config; 2384 #ifdef PHYMOD_DIAG 2385 const phymod_access_t *pm_acc; 2386 pm_acc = &phy->access; 2387 PHYMOD_VDBG(DBG_CL72, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" cl72_en=%d\n", 2388 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, (int)cl72_en)); 2389 #endif 2390 2391 PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy->access, &serdes_firmware_config)); 2392 2393 if (serdes_firmware_config.field.dfe_on == 0) { 2394 PHYMOD_DEBUG_ERROR(("ERROR :: DFE is off : Can not start CL72 with no DFE\n")); 2395 return PHYMOD_E_CONFIG; 2396 } 2397 2398 PHYMOD_IF_ERR_RETURN 2399 (temod16_clause72_control(&phy->access, cl72_en)); 2400 return PHYMOD_E_NONE; 2401 } 2402 2403 int tsce16_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status) 2404 { 2405 uint32_t local_status; 2406 PHYMOD_IF_ERR_RETURN 2407 (merlin16_pmd_cl72_receiver_status(&phy->access, &local_status)); 2408 status->locked = local_status; 2409 return PHYMOD_E_NONE; 2410 } 2411 2412 int tsce16_phy_eee_set(const phymod_phy_access_t* phy, uint32_t enable) 2413 { 2414 uint32_t lpi_bypass; 2415 int rv = PHYMOD_E_NONE; 2416 2417 lpi_bypass = PHYMOD_LPI_BYPASS_GET(enable); 2418 enable &= 0x1; 2419 if (lpi_bypass) { 2420 rv = temod16_eee_control_set(&phy->access,enable); 2421 } else { 2422 return PHYMOD_E_UNAVAIL; 2423 } 2424 2425 return rv; 2426 } 2427 2428 int tsce16_phy_eee_get(const phymod_phy_access_t* phy, uint32_t* enable) 2429 { 2430 if (PHYMOD_LPI_BYPASS_GET(*enable)) { 2431 PHYMOD_IF_ERR_RETURN(temod16_eee_control_get(&phy->access, enable)); 2432 PHYMOD_LPI_BYPASS_SET(*enable); 2433 } else { 2434 return PHYMOD_E_UNAVAIL; 2435 } 2436 2437 return PHYMOD_E_NONE; 2438 } 2439 2440 int tsce16_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en) 2441 { 2442 uint32_t local_en;; 2443 PHYMOD_IF_ERR_RETURN 2444 (merlin16_pmd_cl72_enable_get(&phy->access, &local_en)); 2445 *cl72_en = local_en; 2446 return PHYMOD_E_NONE; 2447 } 2448 2449 int tsce16_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable) 2450 { 2451 2452 int start_lane, num_lane; 2453 uint32_t cl72_en; 2454 phymod_phy_access_t phy_copy; 2455 const phymod_access_t *pm_acc; 2456 2457 pm_acc = &phy->access; 2458 #ifdef PHYMOD_DIAG 2459 PHYMOD_VDBG(DBG_LPK, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" lpbk=%0d(%s) en=%0d\n", 2460 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, loopback, 2461 phymod_loopback_mode_t_mapping[loopback].key, enable)); 2462 #endif 2463 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2464 2465 /* next figure out the lane num and start_lane based on the input */ 2466 PHYMOD_IF_ERR_RETURN 2467 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2468 2469 switch (loopback) { 2470 case phymodLoopbackGlobal: 2471 PHYMOD_IF_ERR_RETURN 2472 (tsce16_phy_cl72_get(phy, &cl72_en)); 2473 if ((cl72_en == 1) && (enable == 1)) { 2474 PHYMOD_DEBUG_ERROR(("adr=%0"PRIx32",lane 0x%x: Error! pcs gloop not supported with cl72 enabled\n", pm_acc->addr, start_lane)); 2475 break; 2476 } 2477 PHYMOD_IF_ERR_RETURN(temod16_tx_loopback_control(&phy->access, enable, start_lane, num_lane)); 2478 break; 2479 case phymodLoopbackGlobalPMD: 2480 PHYMOD_IF_ERR_RETURN(temod16_tx_squelch_set(&phy_copy.access, enable)); 2481 PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_set(&phy->access, enable)); 2482 2483 break; 2484 case phymodLoopbackRemotePMD: 2485 PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk(&phy->access, enable)); 2486 break; 2487 case phymodLoopbackRemotePCS: 2488 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 2489 (_PHYMOD_MSG("PCS Remote LoopBack not supported"))); 2490 break; 2491 default: 2492 break; 2493 } 2494 2495 return PHYMOD_E_NONE; 2496 } 2497 2498 int tsce16_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable) 2499 { 2500 uint32_t enable_core; 2501 int start_lane, num_lane; 2502 2503 *enable = 0; 2504 2505 /* next figure out the lane num and start_lane based on the input */ 2506 PHYMOD_IF_ERR_RETURN 2507 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2508 2509 switch (loopback) { 2510 case phymodLoopbackGlobal : 2511 PHYMOD_IF_ERR_RETURN(temod16_tx_loopback_get(&phy->access, &enable_core)); 2512 *enable = (enable_core >> start_lane) & 0x1; 2513 break; 2514 case phymodLoopbackGlobalPMD : 2515 PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&phy->access, enable)); 2516 break; 2517 case phymodLoopbackRemotePMD : 2518 PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk_get(&phy->access, enable)); 2519 break; 2520 case phymodLoopbackRemotePCS : 2521 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 2522 (_PHYMOD_MSG("PCS Remote LoopBack not supported"))); 2523 break; 2524 default : 2525 break; 2526 } 2527 return PHYMOD_E_NONE; 2528 } 2529 2530 int tsce16_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status) 2531 { 2532 PHYMOD_IF_ERR_RETURN(temod16_get_pcs_latched_link_status(&phy->access, link_status)); 2533 2534 return PHYMOD_E_NONE; 2535 } 2536 2537 int tsce16_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t *val) 2538 { 2539 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_read(&phy->access, reg_addr, val)); 2540 return PHYMOD_E_NONE; 2541 } 2542 2543 int tsce16_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val) 2544 { 2545 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_write(&phy->access, reg_addr, val)); 2546 return PHYMOD_E_NONE; 2547 } 2548 2549 int tsce16_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map) 2550 { 2551 return PHYMOD_E_UNAVAIL; 2552 } 2553 2554 int tsce16_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 2555 { 2556 int8_t value = 0; 2557 2558 PHYMOD_IF_ERR_RETURN 2559 (merlin16_read_tx_afe(&phy->access, TX_AFE_PRE, &value)); 2560 tx->pre = value; 2561 PHYMOD_IF_ERR_RETURN 2562 (merlin16_read_tx_afe(&phy->access, TX_AFE_MAIN, &value)); 2563 tx->main = value; 2564 PHYMOD_IF_ERR_RETURN 2565 (merlin16_read_tx_afe(&phy->access, TX_AFE_POST1, &value)); 2566 tx->post = value; 2567 PHYMOD_IF_ERR_RETURN 2568 (merlin16_read_tx_afe(&phy->access, TX_AFE_POST2, &value)); 2569 tx->post2 = value; 2570 2571 return PHYMOD_E_NONE; 2572 } 2573 2574 int tsce16_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 2575 { 2576 return PHYMOD_E_UNAVAIL; 2577 } 2578 2579 int tsce16_phy_fec_enable_set(const phymod_phy_access_t* phy, uint32_t enable) 2580 { 2581 int i, start_lane, num_lane; 2582 phymod_phy_access_t phy_copy; 2583 2584 PHYMOD_IF_ERR_RETURN 2585 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2586 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2587 2588 for (i = 0; i < num_lane; i++) { 2589 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 2590 continue; 2591 } 2592 phy_copy.access.lane_mask = 1 << (start_lane + i); 2593 PHYMOD_IF_ERR_RETURN(temod16_fecmode_set(&phy_copy.access, enable)); 2594 } 2595 2596 return PHYMOD_E_NONE; 2597 } 2598 2599 int tsce16_phy_fec_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 2600 { 2601 PHYMOD_IF_ERR_RETURN(temod16_fecmode_get(&phy->access, enable)); 2602 2603 return PHYMOD_E_NONE; 2604 } 2605 2606 int tsce16_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_pmd_locked) 2607 { 2608 PHYMOD_IF_ERR_RETURN(temod16_pmd_lock_get(&phy->access, rx_pmd_locked)); 2609 2610 return PHYMOD_E_NONE; 2611 } 2612 2613 int tsce16_phy_rx_ppm_get(const phymod_phy_access_t* phy, int16_t* rx_ppm) 2614 { 2615 int start_lane, num_lane; 2616 phymod_phy_access_t pm_phy_copy; 2617 2618 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 2619 2620 PHYMOD_IF_ERR_RETURN 2621 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2622 2623 pm_phy_copy.access.lane_mask = 1 << start_lane; 2624 PHYMOD_IF_ERR_RETURN 2625 (merlin16_tsc_rx_ppm(&pm_phy_copy.access, rx_ppm)); 2626 2627 return PHYMOD_E_NONE; 2628 } 2629 2630 int tsce16_phy_synce_clk_ctrl_set(const phymod_phy_access_t* phy, 2631 phymod_synce_clk_ctrl_t cfg) 2632 { 2633 phymod_phy_access_t phy_copy; 2634 int start_lane, num_lane; 2635 2636 PHYMOD_IF_ERR_RETURN 2637 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 2638 2639 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 2640 phy_copy.access.lane_mask = 0x1 << start_lane; 2641 2642 PHYMOD_IF_ERR_RETURN 2643 (temod16_synce_stg0_mode_set(&phy_copy.access, cfg.stg0_mode)); 2644 2645 PHYMOD_IF_ERR_RETURN 2646 (temod16_synce_stg1_mode_set(&phy_copy.access, cfg.stg1_mode)); 2647 2648 PHYMOD_IF_ERR_RETURN 2649 (temod16_synce_clk_ctrl_set(&phy_copy.access, cfg.sdm_val)); 2650 2651 return PHYMOD_E_NONE; 2652 } 2653 2654 int tsce16_phy_synce_clk_ctrl_get(const phymod_phy_access_t* phy, 2655 phymod_synce_clk_ctrl_t *cfg) 2656 { 2657 PHYMOD_IF_ERR_RETURN 2658 (temod16_synce_stg0_mode_get(&phy->access, &(cfg->stg0_mode))); 2659 2660 PHYMOD_IF_ERR_RETURN 2661 (temod16_synce_stg1_mode_get(&phy->access, &(cfg->stg1_mode))); 2662 2663 PHYMOD_IF_ERR_RETURN 2664 (temod16_synce_clk_ctrl_get(&phy->access, &(cfg->sdm_val))); 2665 2666 return PHYMOD_E_NONE; 2667 }