qsgmiie.c (42610B)
1 /* 2 * 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 */ 9 10 #include <phymod/phymod.h> 11 #include <phymod/phymod_system.h> 12 #include <phymod/phymod_util.h> 13 #include <phymod/chip/bcmi_qsgmiie_serdes_defs.h> 14 #include <phymod/chip/qsgmiie.h> 15 #include "../tier1/tqmod_cfg_seq.h" 16 #include "../../tsce/tier1/temod_enum_defines.h" 17 #include "../../tsce/tier1/temod.h" 18 #include "../../tsce/tier1/tePCSRegEnums.h" 19 #include "../../eagle/tier1/eagle_cfg_seq.h" 20 #include "../../eagle/tier1/eagle_tsc_interface.h" 21 #include "../../eagle/tier1/eagle_tsc_dependencies.h" 22 #include "../../../include/phymod/chip/eagle.h" 23 24 25 #define QSGMIIE_ID0 0x0143 26 #define QSGMIIE_ID1 0xbff0 27 #define QSGMIIE_REV_MASK 0x0 28 #define TSCE4_MODEL 0x12 29 30 #define PHY_REG_ADDR_DEVAD(_phy_reg) (((_phy_reg) >> 27) & 0x1f) 31 #define QSGMII_REG_ADDR_REG(_phy_reg) ((((_phy_reg) & 0x8000) >> 11) | ((_phy_reg) & 0xf)) 32 #define IS_QSGMII_REGISTER(_phy_reg) (((_phy_reg) & 0xf800f000) == 0x8000) 33 34 #define QSGMII_MODEL 0x07 35 #define EAGLE_MODEL 0x1a 36 37 #define TSCE_NOF_LANES_IN_CORE (4) 38 #define TSCE_PHY_ALL_LANES (0xf) 39 #define TSCE_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \ 40 do{\ 41 PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\ 42 (_phy_access)->type = (_core_access)->type; \ 43 (_phy_access)->port_loc = (_core_access)->port_loc; \ 44 (_phy_access)->device_op_mode = (_core_access)->device_op_mode; \ 45 (_phy_access)->access.lane_mask = TSCE_PHY_ALL_LANES; \ 46 }while(0) 47 48 /* uController's firmware */ 49 extern unsigned char tsce_ucode[]; 50 extern unsigned short tsce_ucode_ver; 51 extern unsigned short tsce_ucode_crc; 52 extern unsigned short tsce_ucode_len; 53 54 int qsgmiie_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified) 55 { 56 int ioerr = 0; 57 const phymod_access_t *pm_acc = &core->access; 58 PHYID2r_t id2; 59 PHYID3r_t id3; 60 MAIN0_SERDESIDr_t serdesid; 61 uint32_t model; 62 63 *is_identified = 0; 64 65 if(core_id == 0){ 66 ioerr += READ_PHYID2r(pm_acc, &id2); 67 ioerr += READ_PHYID3r(pm_acc, &id3); 68 } 69 else{ 70 PHYID2r_SET(id2, ((core_id >> 16) & 0xffff)); 71 PHYID3r_SET(id3, core_id & 0xffff); 72 } 73 74 if (PHYID2r_GET(id2) == QSGMIIE_ID0 && 75 (PHYID3r_GET(id3) &= ~QSGMIIE_REV_MASK) == QSGMIIE_ID1) { 76 /* PHY IDs match - now check PCS model */ 77 ioerr += READ_MAIN0_SERDESIDr(pm_acc, &serdesid); 78 model = MAIN0_SERDESIDr_MODEL_NUMBERf_GET(serdesid); 79 if (model == TSCE4_MODEL) { 80 *is_identified = 1; 81 } 82 } 83 84 return ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE; 85 return PHYMOD_E_NONE; 86 87 } 88 89 90 int qsgmiie_core_info_get(const phymod_core_access_t* core, phymod_core_info_t* info) 91 { 92 93 94 /* Place your code here */ 95 96 97 return PHYMOD_E_UNAVAIL; 98 99 } 100 101 /* 102 * set lane swapping for core 103 * The tx swap is composed of PCS swap and after that the PMD swap. 104 * The rx swap is composed just by PCS swap 105 * 106 * lane_map_tx and lane_map_rx[lane=logic_lane] are logic-lane base. 107 * pcs_swap and register is logic_lane base. 108 * but pmd_tx_map and addr_index_swap (and registers) are physical lane base 109 */ 110 111 112 int qsgmiie_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map) 113 { 114 uint32_t pcs_swap = 0 , pmd_swap = 0, lane; 115 uint32_t addr_index_swap = 0, pmd_tx_map =0; 116 117 if(lane_map->num_of_lanes != TSCE_NOF_LANES_IN_CORE){ 118 return PHYMOD_E_CONFIG; 119 } 120 for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){ 121 if(lane_map->lane_map_rx[lane] >= TSCE_NOF_LANES_IN_CORE){ 122 return PHYMOD_E_CONFIG; 123 } 124 /* encode each lane as four bits */ 125 /* pcs_map[lane] = rx_map[lane] */ 126 pcs_swap += lane_map->lane_map_rx[lane]<<(lane*4); 127 } 128 129 for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){ 130 if(lane_map->lane_map_tx[lane] >= TSCE_NOF_LANES_IN_CORE){ 131 return PHYMOD_E_CONFIG; 132 } 133 /* encode each lane as four bits. pmd_swap is logic base */ 134 /* considering the pcs lane swap: pmd_map[pcs_map[lane]] = tx_map[lane] */ 135 pmd_swap += lane_map->lane_map_tx[lane]<<(lane_map->lane_map_rx[lane]*4); 136 } 137 138 for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){ 139 addr_index_swap |= (lane << 4*((pcs_swap >> lane*4) & 0xf)) ; 140 pmd_tx_map |= (lane << 4*((pmd_swap >> lane*4) & 0xf)) ; 141 } 142 PHYMOD_IF_ERR_RETURN(tqmod_pcs_lane_swap(&core->access, pcs_swap)); 143 144 PHYMOD_IF_ERR_RETURN 145 (temod_pmd_addr_lane_swap(&core->access, addr_index_swap)); 146 PHYMOD_IF_ERR_RETURN 147 (temod_pmd_lane_swap_tx(&core->access, pmd_tx_map)); 148 return PHYMOD_E_NONE; 149 } 150 151 int qsgmiie_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map) 152 { 153 uint32_t pmd_swap = 0 , pcs_swap = 0, lane; 154 PHYMOD_IF_ERR_RETURN(tqmod_pcs_lane_swap_get(&core->access, &pcs_swap)); 155 PHYMOD_IF_ERR_RETURN(temod_pmd_lane_swap_tx_get(&core->access, &pmd_swap)); 156 for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){ 157 lane_map->lane_map_rx[lane] = (pcs_swap>>(lane*4)) & 3; 158 lane_map->lane_map_tx[lane] = (pmd_swap>>(lane_map->lane_map_rx[lane]*4)) & 3; 159 } 160 lane_map->num_of_lanes = TSCE_NOF_LANES_IN_CORE; 161 162 return PHYMOD_E_NONE; 163 164 } 165 166 167 int qsgmiie_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 168 { 169 170 171 /* Place your code here */ 172 173 174 return PHYMOD_E_UNAVAIL; 175 176 } 177 178 int qsgmiie_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction) 179 { 180 181 182 /* Place your code here */ 183 184 185 return PHYMOD_E_UNAVAIL; 186 187 } 188 189 190 int qsgmiie_core_firmware_info_get(const phymod_core_access_t* core, phymod_core_firmware_info_t* fw_info) 191 { 192 193 194 fw_info->fw_crc = tsce_ucode_crc; 195 fw_info->fw_version = tsce_ucode_ver; 196 return PHYMOD_E_NONE; 197 } 198 199 /* load tsce fw. the fw_loader parameter is valid just for external fw load */ 200 STATIC 201 int _qsgmiie_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader) 202 { 203 phymod_core_firmware_info_t actual_fw; 204 205 switch(load_method){ 206 case phymodFirmwareLoadMethodInternal: 207 PHYMOD_IF_ERR_RETURN(eagle_tsc_ucode_mdio_load(&core->access, tsce_ucode, tsce_ucode_len)); 208 break; 209 case phymodFirmwareLoadMethodExternal: 210 PHYMOD_NULL_CHECK(fw_loader); 211 212 eagle_pram_flop_set(&core->access, 0x0); 213 214 PHYMOD_IF_ERR_RETURN(eagle_tsc_ucode_init(&core->access)); 215 216 PHYMOD_IF_ERR_RETURN 217 (temod_pram_abl_enable_set(&core->access,1)); 218 PHYMOD_IF_ERR_RETURN 219 (eagle_pram_firmware_enable(&core->access, 1)); 220 221 PHYMOD_IF_ERR_RETURN(fw_loader(core, tsce_ucode_len, tsce_ucode)); 222 223 PHYMOD_IF_ERR_RETURN 224 (eagle_pram_firmware_enable(&core->access, 0)); 225 PHYMOD_IF_ERR_RETURN 226 (temod_pram_abl_enable_set(&core->access,0)); 227 break; 228 case phymodFirmwareLoadMethodNone: 229 break; 230 default: 231 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method)); 232 } 233 if(load_method != phymodFirmwareLoadMethodNone){ 234 PHYMOD_IF_ERR_RETURN(qsgmiie_core_firmware_info_get(core, &actual_fw)); 235 if((tsce_ucode_crc != actual_fw.fw_crc) || (tsce_ucode_ver != actual_fw.fw_version)){ 236 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("fw load validation was failed"))); 237 } 238 } 239 return PHYMOD_E_NONE; 240 } 241 242 int qsgmiie_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_config) 243 { 244 struct eagle_tsc_uc_core_config_st serdes_firmware_core_config; 245 /* coverity fix: deferencing &serdes_firmware_core_config in sizeof() 246 * so that entire struct is set to value 0 by PHYMOD_MEMSET 247 */ 248 PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(*&serdes_firmware_core_config)); 249 serdes_firmware_core_config.field.core_cfg_from_pcs = fw_config.CoreConfigFromPCS; 250 serdes_firmware_core_config.field.vco_rate = fw_config.VcoRate; 251 PHYMOD_IF_ERR_RETURN(eagle_tsc_set_uc_core_config(&phy->access, serdes_firmware_core_config)); 252 return PHYMOD_E_NONE; 253 } 254 255 int qsgmiie_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_config) 256 { 257 struct eagle_tsc_uc_core_config_st serdes_firmware_core_config; 258 PHYMOD_IF_ERR_RETURN(eagle_tsc_get_uc_core_config(&phy->access, &serdes_firmware_core_config)); 259 /* coverity fix: deferencing pointer fw_config in sizeof() 260 * so that entire struct is set to value 0 by PHYMOD_MEMSET 261 */ 262 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 263 fw_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs; 264 fw_config->VcoRate = serdes_firmware_core_config.field.vco_rate; 265 return PHYMOD_E_NONE; 266 } 267 268 int qsgmiie_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 269 { 270 struct eagle_tsc_uc_lane_config_st serdes_firmware_config; 271 serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS; 272 serdes_firmware_config.field.an_enabled = fw_config.AnEnabled; 273 serdes_firmware_config.field.dfe_on = fw_config.DfeOn; 274 serdes_firmware_config.field.force_brdfe_on = fw_config.ForceBrDfe; 275 serdes_firmware_config.field.cl72_auto_polarity_en = fw_config.Cl72AutoPolEn; 276 serdes_firmware_config.field.cl72_restart_timeout_en = fw_config.Cl72RestTO; 277 serdes_firmware_config.field.scrambling_dis = fw_config.ScramblingDisable; 278 serdes_firmware_config.field.unreliable_los = fw_config.UnreliableLos; 279 serdes_firmware_config.field.media_type = fw_config.MediaType; 280 PHYMOD_IF_ERR_RETURN(eagle_tsc_set_uc_lane_cfg(&phy->access, serdes_firmware_config)); 281 return PHYMOD_E_NONE; 282 } 283 284 int qsgmiie_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config) 285 { 286 struct eagle_tsc_uc_lane_config_st serdes_firmware_config; 287 PHYMOD_IF_ERR_RETURN(eagle_tsc_get_uc_lane_cfg(&phy->access, &serdes_firmware_config)); 288 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 289 fw_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs; 290 fw_config->AnEnabled = serdes_firmware_config.field.an_enabled; 291 fw_config->DfeOn = serdes_firmware_config.field.dfe_on; 292 fw_config->ForceBrDfe = serdes_firmware_config.field.force_brdfe_on; 293 fw_config->Cl72AutoPolEn = serdes_firmware_config.field.cl72_auto_polarity_en; 294 fw_config->Cl72RestTO = serdes_firmware_config.field.cl72_restart_timeout_en; 295 fw_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis; 296 fw_config->UnreliableLos = serdes_firmware_config.field.unreliable_los; 297 fw_config->MediaType = serdes_firmware_config.field.media_type; 298 299 return PHYMOD_E_NONE; 300 } 301 302 303 int qsgmiie_core_pll_sequencer_restart(const phymod_core_access_t* core, uint32_t flags, phymod_sequencer_operation_t operation) 304 { 305 306 307 /* Place your code here */ 308 309 310 return PHYMOD_E_UNAVAIL; 311 312 } 313 314 315 int qsgmiie_core_wait_event(const phymod_core_access_t* core, phymod_core_event_t event, uint32_t timeout) 316 { 317 318 319 /* Place your code here */ 320 321 322 return PHYMOD_E_UNAVAIL; 323 324 } 325 326 327 int qsgmiie_phy_rx_restart(const phymod_phy_access_t* phy) 328 { 329 return PHYMOD_E_UNAVAIL; 330 } 331 332 333 int qsgmiie_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity) 334 { 335 336 PHYMOD_IF_ERR_RETURN 337 (tqmod_tx_rx_polarity_set(&phy->access, polarity->tx_polarity, polarity->rx_polarity)); 338 339 return PHYMOD_E_NONE; 340 341 } 342 343 int qsgmiie_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity) 344 { 345 346 PHYMOD_IF_ERR_RETURN 347 (tqmod_tx_rx_polarity_get(&phy->access, &polarity->tx_polarity, &polarity->rx_polarity)); 348 return PHYMOD_E_NONE; 349 350 } 351 352 353 int qsgmiie_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 354 { 355 phymod_phy_access_t pm_phy_copy; 356 int start_lane, num_lane; 357 358 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 359 PHYMOD_IF_ERR_RETURN 360 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 361 362 pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4); 363 364 365 PHYMOD_IF_ERR_RETURN 366 (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_PRE, (int8_t)tx->pre)); 367 PHYMOD_IF_ERR_RETURN 368 (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_MAIN, (int8_t)tx->main)); 369 PHYMOD_IF_ERR_RETURN 370 (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_POST1, (int8_t)tx->post)); 371 PHYMOD_IF_ERR_RETURN 372 (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_POST2, (int8_t)tx->post2)); 373 PHYMOD_IF_ERR_RETURN 374 (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_POST3, (int8_t)tx->post3)); 375 PHYMOD_IF_ERR_RETURN 376 (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_AMP, (int8_t)tx->amp)); 377 if((tx->drivermode != -1) && 378 (phy->device_op_mode & PHYMOD_INTF_CONFIG_TX_FIR_DRIVERMODE_ENABLE)) { 379 PHYMOD_IF_ERR_RETURN 380 (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_DRIVERMODE, (int8_t)tx->drivermode)); 381 } 382 383 return PHYMOD_E_NONE; 384 385 } 386 387 int qsgmiie_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 388 { 389 phymod_phy_access_t pm_phy_copy; 390 int start_lane, num_lane; 391 int8_t value = 0; 392 393 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 394 PHYMOD_IF_ERR_RETURN 395 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 396 397 pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4); 398 399 PHYMOD_IF_ERR_RETURN 400 (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_PRE, &value)); 401 tx->pre = value; 402 PHYMOD_IF_ERR_RETURN 403 (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_MAIN, &value)); 404 tx->main = value; 405 PHYMOD_IF_ERR_RETURN 406 (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_POST1, &value)); 407 tx->post = value; 408 PHYMOD_IF_ERR_RETURN 409 (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_POST2, &value)); 410 tx->post2 = value; 411 PHYMOD_IF_ERR_RETURN 412 (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_POST3, &value)); 413 tx->post3 = value; 414 PHYMOD_IF_ERR_RETURN 415 (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_AMP, &value)); 416 tx->amp = value; 417 PHYMOD_IF_ERR_RETURN 418 (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_DRIVERMODE, &value)); 419 tx->drivermode = value; 420 421 return PHYMOD_E_NONE; 422 423 } 424 425 426 int qsgmiie_phy_tx_override_set(const phymod_phy_access_t* phy, const phymod_tx_override_t* tx_override) 427 { 428 429 430 /* Place your code here */ 431 432 433 return PHYMOD_E_UNAVAIL; 434 435 } 436 437 int qsgmiie_phy_tx_override_get(const phymod_phy_access_t* phy, phymod_tx_override_t* tx_override) 438 { 439 440 441 /* Place your code here */ 442 443 444 return PHYMOD_E_UNAVAIL; 445 446 } 447 448 449 int qsgmiie_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx) 450 { 451 452 453 /* Place your code here */ 454 455 456 return PHYMOD_E_UNAVAIL; 457 458 } 459 460 int qsgmiie_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx) 461 { 462 463 464 /* Place your code here */ 465 466 467 return PHYMOD_E_UNAVAIL; 468 469 } 470 471 472 int qsgmiie_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset) 473 { 474 475 476 /* Place your code here */ 477 478 479 return PHYMOD_E_UNAVAIL; 480 481 } 482 483 int qsgmiie_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset) 484 { 485 486 487 /* Place your code here */ 488 489 490 return PHYMOD_E_UNAVAIL; 491 492 } 493 494 495 int qsgmiie_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 496 { 497 498 499 phymod_phy_access_t pm_phy_copy; 500 int start_lane, num_lane; 501 502 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 503 /*next program the tx fir taps and driver current based on the input*/ 504 PHYMOD_IF_ERR_RETURN 505 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 506 507 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) { 508 PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&pm_phy_copy.access, 1)); 509 PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 1)); 510 } 511 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) { 512 PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&pm_phy_copy.access, 0)); 513 PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 0)); 514 } 515 516 pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4); 517 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) { 518 /*disable tx on the PMD side */ 519 PHYMOD_IF_ERR_RETURN(eagle_tsc_tx_disable(&pm_phy_copy.access, 1)); 520 } 521 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) { 522 /*enable tx on the PMD side */ 523 PHYMOD_IF_ERR_RETURN(eagle_tsc_tx_disable(&pm_phy_copy.access, 0)); 524 } 525 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) { 526 /*disable rx on the PMD side */ 527 PHYMOD_IF_ERR_RETURN(temod_rx_squelch_set(&pm_phy_copy.access, 1)); 528 } 529 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) { 530 /*enable rx on the PMD side */ 531 PHYMOD_IF_ERR_RETURN(temod_rx_squelch_set(&pm_phy_copy.access, 0)); 532 } 533 534 return PHYMOD_E_NONE; 535 536 } 537 538 int qsgmiie_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 539 { 540 int enable; 541 uint32_t lb_enable; 542 phymod_phy_access_t pm_phy_copy; 543 int start_lane, num_lane; 544 545 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 546 /* next program the tx fir taps and driver current based on the input */ 547 PHYMOD_IF_ERR_RETURN 548 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 549 550 pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4); 551 552 PHYMOD_IF_ERR_RETURN(temod_rx_squelch_get(&pm_phy_copy.access, &enable)); 553 554 /* next check if PMD loopback is on */ 555 if (enable) { 556 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 557 if (lb_enable) enable = 0; 558 } 559 560 power->rx = (enable == 1)? phymodPowerOff: phymodPowerOn; 561 PHYMOD_IF_ERR_RETURN(temod_tx_squelch_get(&pm_phy_copy.access, &enable)); 562 power->tx = (enable == 1)? phymodPowerOff: phymodPowerOn; 563 return PHYMOD_E_NONE; 564 } 565 566 int qsgmiie_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control) 567 { 568 switch (tx_control) { 569 case phymodTxTrafficDisable: 570 PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_set(&phy->access, TEMOD_TX_LANE_TRAFFIC_DISABLE)); 571 break; 572 case phymodTxTrafficEnable: 573 PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_set(&phy->access, TEMOD_TX_LANE_TRAFFIC_ENABLE)); 574 break; 575 case phymodTxReset: 576 PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_set(&phy->access, TEMOD_TX_LANE_RESET)); 577 break; 578 case phymodTxSquelchOn: 579 PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&phy->access, 1)); 580 break; 581 case phymodTxSquelchOff: 582 PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&phy->access, 0)); 583 break; 584 default: 585 break; 586 } 587 return PHYMOD_E_NONE; 588 589 } 590 591 592 int qsgmiie_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control) 593 { 594 int enable, reset, tx_lane; 595 uint32_t lb_enable; 596 phymod_phy_access_t pm_phy_copy; 597 int start_lane, num_lane; 598 599 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 600 /* next program the tx fir taps and driver current based on the input */ 601 PHYMOD_IF_ERR_RETURN 602 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 603 604 PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_get(&phy->access, &enable)); 605 606 pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4); 607 /* next check if PMD loopback is on */ 608 if (enable) { 609 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 610 if (lb_enable) enable = 0; 611 } 612 613 if(enable) { 614 *tx_control = phymodTxSquelchOn; 615 } else { 616 PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_get(&phy->access, &reset, &tx_lane)); 617 if (!reset) { 618 *tx_control = phymodTxReset; 619 } else if (!tx_lane) { 620 *tx_control = phymodTxTrafficDisable; 621 } else { 622 *tx_control = phymodTxTrafficEnable; 623 } 624 } 625 return PHYMOD_E_NONE; 626 } 627 628 /*Rx control*/ 629 int qsgmiie_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control) 630 { 631 phymod_phy_access_t pm_phy_copy; 632 int start_lane, num_lane, i; 633 634 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 635 /* next program the tx fir taps and driver current based on the input */ 636 PHYMOD_IF_ERR_RETURN 637 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 638 639 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 640 641 switch (rx_control) { 642 case phymodRxReset: 643 PHYMOD_IF_ERR_RETURN(tqmod_rx_lane_control_set(&phy->access, 1)); 644 break; 645 case phymodRxSquelchOn: 646 for (i = 0; i < num_lane; i++) { 647 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 648 continue; 649 } 650 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 651 PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 1)); 652 } 653 break; 654 case phymodRxSquelchOff: 655 for (i = 0; i < num_lane; i++) { 656 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 657 continue; 658 } 659 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 660 PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 0)); 661 } 662 break; 663 default: 664 break; 665 } 666 return PHYMOD_E_NONE; 667 } 668 669 int qsgmiie_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control) 670 { 671 int enable, reset; 672 uint32_t lb_enable; 673 phymod_phy_access_t pm_phy_copy; 674 int start_lane, num_lane; 675 676 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 677 /* next program the tx fir taps and driver current based on the input */ 678 PHYMOD_IF_ERR_RETURN 679 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 680 681 PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_get(&phy->access, &enable)); 682 683 pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4); 684 /* next check if PMD loopback is on */ 685 if (enable) { 686 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable)); 687 if (lb_enable) enable = 0; 688 } 689 if(enable) { 690 *rx_control = phymodRxSquelchOn; 691 } else { 692 PHYMOD_IF_ERR_RETURN(tqmod_rx_lane_control_get(&phy->access, &reset)); 693 if (reset == 0) { 694 *rx_control = phymodRxReset; 695 } else { 696 *rx_control = phymodRxSquelchOff; 697 } 698 } 699 return PHYMOD_E_NONE; 700 } 701 702 STATIC 703 int _qsgmiie_speed_id_interface_config_get(const phymod_phy_access_t* phy, int speed_id, phymod_phy_inf_config_t* config) 704 { 705 switch (speed_id) { 706 case 0x0: 707 config->data_rate = 10; 708 break; 709 case 0x1: 710 config->data_rate = 100; 711 break; 712 case 0x2: 713 config->data_rate = 1000; 714 break; 715 default: 716 config->data_rate = 0; 717 break; 718 } 719 config->interface_type = phymodInterfaceSGMII; 720 721 return PHYMOD_E_NONE; 722 } 723 724 725 int qsgmiie_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 726 { 727 728 PHYMOD_IF_ERR_RETURN 729 (tqmod_set_spd_intf(&phy->access, config->data_rate)); 730 731 return PHYMOD_E_NONE; 732 733 } 734 735 int qsgmiie_phy_interface_config_get(const phymod_phy_access_t* phy, 736 uint32_t flags, 737 phymod_ref_clk_t ref_clock, 738 phymod_phy_inf_config_t* config) 739 { 740 int speed_id; 741 742 config->ref_clock = ref_clock; 743 744 PHYMOD_IF_ERR_RETURN 745 (tqmod_speed_id_get(&phy->access, &speed_id)); 746 747 PHYMOD_IF_ERR_RETURN 748 (_qsgmiie_speed_id_interface_config_get(phy, speed_id, config)); 749 750 return PHYMOD_E_NONE; 751 } 752 753 int qsgmiie_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability) 754 { 755 tqmod_an_ability_t value; 756 int start_lane, num_lane; 757 phymod_phy_access_t phy_copy; 758 759 /* next program the tx fir taps and driver current based on the input */ 760 PHYMOD_IF_ERR_RETURN 761 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 762 763 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 764 phy_copy.access.lane_mask = 0x1 << start_lane; 765 766 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 767 768 /* check if sgmii or not */ 769 if (PHYMOD_AN_CAP_SGMII_GET(an_ability)) { 770 switch (an_ability->sgmii_speed) { 771 case phymod_CL37_SGMII_10M: 772 value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_10M; 773 break; 774 case phymod_CL37_SGMII_100M: 775 value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_100M; 776 break; 777 case phymod_CL37_SGMII_1000M: 778 value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_1000M; 779 break; 780 default: 781 value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_1000M; 782 break; 783 } 784 } 785 786 /* next check pause */ 787 if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) { 788 value.cl37_adv.an_pause = TEMOD_SYMM_PAUSE; 789 } else if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability)) { 790 value.cl37_adv.an_pause = TEMOD_ASYM_PAUSE; 791 } 792 793 794 return PHYMOD_E_NONE; 795 796 } 797 798 int qsgmiie_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 799 { 800 801 tqmod_an_ability_t value; 802 phymod_phy_access_t phy_copy; 803 int start_lane, num_lane; 804 805 PHYMOD_IF_ERR_RETURN 806 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 807 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 808 phy_copy.access.lane_mask = 0x1 << start_lane; 809 PHYMOD_MEMSET(&value, 0x0, sizeof(value)); 810 811 /* PHYMOD_IF_ERR_RETURN 812 (tqmod_autoneg_local_ability_get(&phy_copy.access, &value));*/ 813 value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_10M | 814 TEMOD_CL37_SGMII_100M | 815 TEMOD_CL37_SGMII_1000M; 816 value.cl37_adv.an_pause = TEMOD_NO_PAUSE | TEMOD_ASYM_PAUSE; 817 switch (value.cl37_adv.an_pause) { 818 case TEMOD_ASYM_PAUSE: 819 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type); 820 break; 821 case TEMOD_SYMM_PAUSE: 822 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type); 823 break; 824 default: 825 break; 826 } 827 return PHYMOD_E_NONE; 828 829 } 830 831 832 int qsgmiie_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 833 { 834 835 phymod_firmware_lane_config_t firmware_lane_config; 836 int start_lane, num_lane; 837 phymod_phy_access_t phy_copy; 838 tqmod_an_control_t an_control; 839 int enable; 840 841 /* next program the tx fir taps and driver current based on the input */ 842 PHYMOD_IF_ERR_RETURN 843 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 844 845 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 846 phy_copy.access.lane_mask = 0x1 << start_lane; 847 848 an_control.enable = an->enable; 849 an_control.an_property_type = 0x0; /* for now disable */ 850 switch (an->an_mode) { 851 case phymod_AN_MODE_CL73: 852 an_control.an_type = TEMOD_AN_MODE_CL73; 853 break; 854 case phymod_AN_MODE_CL37: 855 an_control.an_type = TEMOD_AN_MODE_CL37; 856 break; 857 case phymod_AN_MODE_CL73BAM: 858 an_control.an_type = TEMOD_AN_MODE_CL73BAM; 859 break; 860 case phymod_AN_MODE_CL37BAM: 861 an_control.an_type = TEMOD_AN_MODE_CL37BAM; 862 break; 863 case phymod_AN_MODE_HPAM: 864 an_control.an_type = TEMOD_AN_MODE_HPAM; 865 break; 866 case phymod_AN_MODE_SGMII: 867 an_control.an_type = TEMOD_AN_MODE_SGMII; 868 break; 869 default: 870 return PHYMOD_E_PARAM; 871 } 872 enable = an_control.enable; 873 874 /* make sure the firmware config is set to an eenabled */ 875 phy_copy.access.lane_mask = 0x1 << (start_lane / 4); 876 PHYMOD_IF_ERR_RETURN 877 (eagle_lane_soft_reset_release(&phy_copy.access, 0)); 878 879 880 PHYMOD_IF_ERR_RETURN 881 (qsgmiie_phy_firmware_lane_config_get(&phy_copy, &firmware_lane_config)); 882 if (an->enable) { 883 firmware_lane_config.AnEnabled = 1; 884 firmware_lane_config.LaneConfigFromPCS = 1; 885 } else { 886 firmware_lane_config.AnEnabled = 0; 887 firmware_lane_config.LaneConfigFromPCS = 0; 888 } 889 PHYMOD_IF_ERR_RETURN 890 (qsgmiie_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config)); 891 892 PHYMOD_IF_ERR_RETURN 893 (eagle_lane_soft_reset_release(&phy_copy.access, 1)); 894 895 phy_copy.access.lane_mask = 0x1 << start_lane; 896 PHYMOD_IF_ERR_RETURN 897 (tqmod_autoneg_set(&phy_copy.access, &enable)); 898 899 return PHYMOD_E_NONE; 900 901 } 902 903 int qsgmiie_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done) 904 { 905 906 tqmod_an_control_t an_control; 907 phymod_phy_access_t phy_copy; 908 int start_lane, num_lane; 909 /* int an_complete = 0;*/ 910 911 /* next program the tx fir taps and driver current based on the input */ 912 PHYMOD_IF_ERR_RETURN 913 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 914 915 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 916 phy_copy.access.lane_mask = 0x1 << start_lane; 917 918 PHYMOD_MEMSET(&an_control, 0x0, sizeof(tqmod_an_control_t)); 919 /* PHYMOD_IF_ERR_RETURN 920 (temod_autoneg_control_get(&phy_copy.access, &an_control, &an_complete));*/ 921 922 if (an_control.enable) { 923 an->enable = 1; 924 *an_done = 0; 925 } else { 926 an->enable = 0; 927 } 928 return PHYMOD_E_NONE; 929 } 930 931 int qsgmiie_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 932 { 933 phymod_phy_access_t phy_access, phy_access_copy; 934 phymod_core_access_t core_copy; 935 phymod_firmware_core_config_t firmware_core_config_tmp; 936 #if 0 937 temod_an_init_t an; 938 #endif 939 940 TSCE_CORE_TO_PHY_ACCESS(&phy_access, core); 941 phy_access_copy = phy_access; 942 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 943 core_copy.access.lane_mask = 0x1; 944 phy_access_copy = phy_access; 945 phy_access_copy.access = core->access; 946 phy_access_copy.access.lane_mask = 0x1; 947 phy_access_copy.type = core->type; 948 949 PHYMOD_IF_ERR_RETURN 950 (temod_pmd_reset_seq(&core_copy.access, core_status->pmd_active)); 951 952 /* need to set the heart beat default is for 156.25M */ 953 if (init_config->interface.ref_clock == phymodRefClk125Mhz) { 954 /* we need to set the ref clock config differently */ 955 } 956 if (_qsgmiie_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader)) { 957 PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask)); 958 PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT); 959 } 960 /* next we need to check if the load is correct or not */ 961 if (eagle_tsc_ucode_load_verify(&core_copy.access, (uint8_t *) &tsce_ucode, tsce_ucode_len)) { 962 PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC load-verify failed\n", core->access.addr, core->access.lane_mask)); 963 PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT); 964 } 965 966 PHYMOD_IF_ERR_RETURN 967 (eagle_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x1)); 968 969 /* next we need to set the uc active and release uc */ 970 PHYMOD_IF_ERR_RETURN 971 (eagle_uc_active_set(&core_copy.access ,1)); 972 /* release the uc reset */ 973 PHYMOD_IF_ERR_RETURN 974 (eagle_uc_reset(&core_copy.access ,1)); 975 /* we need to wait at least 10ms for the uc to settle */ 976 PHYMOD_USLEEP(10000); 977 978 /* poll the ready bit in 10 ms */ 979 PHYMOD_IF_ERR_RETURN 980 (eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1(&phy_access_copy.access, 1)); 981 982 PHYMOD_IF_ERR_RETURN( 983 eagle_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0)); 984 985 /* plldiv CONFIG */ 986 PHYMOD_IF_ERR_RETURN 987 (eagle_pll_mode_set(&core->access, 0x9)); 988 989 /* now config the lane mapping and polarity */ 990 PHYMOD_IF_ERR_RETURN 991 (qsgmiie_core_lane_map_set(core, &init_config->lane_map)); 992 #if 0 993 /* NEED TO REVISIT */ 994 PHYMOD_IF_ERR_RETURN 995 (temod_autoneg_set_init(&core->access, &an)); 996 #endif 997 /* PHYMOD_IF_ERR_RETURN 998 (temod_autoneg_timer_init(&core->access));*/ 999 PHYMOD_IF_ERR_RETURN 1000 (temod_master_port_num_set(&core->access, 0)); 1001 /* don't overide the fw that set in config set if not specified */ 1002 firmware_core_config_tmp = init_config->firmware_core_config; 1003 firmware_core_config_tmp.CoreConfigFromPCS = 0; 1004 /* set the vco rate to be default at 10.0000G */ 1005 firmware_core_config_tmp.VcoRate = 0x12; 1006 1007 PHYMOD_IF_ERR_RETURN 1008 (qsgmiie_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config_tmp)); 1009 1010 /* release core soft reset */ 1011 PHYMOD_IF_ERR_RETURN 1012 (eagle_core_soft_reset_release(&core_copy.access, 1)); 1013 1014 return PHYMOD_E_NONE; 1015 1016 } 1017 1018 1019 int qsgmiie_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config) 1020 { 1021 1022 const phymod_access_t *pm_acc = &phy->access; 1023 phymod_phy_access_t pm_phy_copy; 1024 int start_lane, num_lane, i; 1025 int an_en=init_config->an_en; 1026 int lane_bkup; 1027 phymod_polarity_t tmp_pol; 1028 1029 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 1030 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1031 1032 /* next program the tx fir taps and driver current based on the input */ 1033 PHYMOD_IF_ERR_RETURN 1034 (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane)); 1035 1036 /* Enable autoneg for QSGMII pcs*/ 1037 PHYMOD_IF_ERR_RETURN 1038 (tqmod_autoneg_set(&pm_phy_copy.access, &an_en)); 1039 1040 /* exit if lane number >4 (for pmd and tsce)*/ 1041 if(start_lane>4) 1042 return PHYMOD_E_NONE; 1043 /* per lane based reset release */ 1044 PHYMOD_IF_ERR_RETURN 1045 (tqmod_pmd_x4_reset(pm_acc)); 1046 1047 /* poll for per lane uc_dsc_ready */ 1048 lane_bkup = pm_phy_copy.access.lane_mask; 1049 for (i = 0; i < num_lane; i++) { 1050 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 1051 PHYMOD_IF_ERR_RETURN 1052 (eagle_lane_soft_reset_release(&pm_phy_copy.access, 1)); 1053 } 1054 pm_phy_copy.access.lane_mask = lane_bkup; 1055 1056 /* program the rx/tx polarity */ 1057 for (i = 0; i < num_lane; i++) { 1058 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1059 tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) >> i & 0x1; 1060 tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) >> i & 0x1; 1061 PHYMOD_IF_ERR_RETURN 1062 (qsgmiie_phy_polarity_set(&pm_phy_copy, &tmp_pol)); 1063 } 1064 1065 for (i = 0; i < num_lane; i++) { 1066 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1067 PHYMOD_IF_ERR_RETURN 1068 (qsgmiie_phy_tx_set(&pm_phy_copy, &init_config->tx[i])); 1069 } 1070 1071 pm_phy_copy.access.lane_mask = 0x1; 1072 1073 /*PHYMOD_IF_ERR_RETURN 1074 (temod_update_port_mode(pm_acc, &pll_restart));*/ 1075 1076 PHYMOD_IF_ERR_RETURN 1077 (tqmod_rx_lane_control_set(pm_acc, 1)); 1078 PHYMOD_IF_ERR_RETURN 1079 (tqmod_tx_lane_control_set(pm_acc, TQMOD_TX_LANE_RESET_TRAFFIC_ENABLE)); /* TX_LANE_CONTROL */ 1080 1081 1082 for (i = 0; i < num_lane; i++) { 1083 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1084 PHYMOD_IF_ERR_RETURN 1085 (tqmod_txfir_tx_disable_set(&pm_phy_copy.access)); 1086 1087 PHYMOD_IF_ERR_RETURN 1088 (tqmod_pmd_osmode_set(&pm_phy_copy.access, 0x1)); 1089 1090 PHYMOD_IF_ERR_RETURN 1091 (tqmod_init_pcs_ilkn(&pm_phy_copy.access)); 1092 1093 } 1094 1095 return PHYMOD_E_NONE; 1096 1097 } 1098 1099 1100 int qsgmiie_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable) 1101 { 1102 int start_lane, num_lane; 1103 int rv = PHYMOD_E_NONE; 1104 phymod_phy_access_t phy_copy; 1105 1106 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1107 1108 /* next figure out the lane num and start_lane based on the input */ 1109 PHYMOD_IF_ERR_RETURN 1110 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1111 1112 switch (loopback) { 1113 case phymodLoopbackGlobal : 1114 case phymodLoopbackGlobalPMD : 1115 phy_copy.access.lane_mask = 0x1 << (start_lane / 4); 1116 PHYMOD_IF_ERR_RETURN(eagle_tsc_dig_lpbk(&phy_copy.access, (uint8_t) enable)); 1117 PHYMOD_IF_ERR_RETURN(eagle_pmd_force_signal_detect(&phy_copy.access, (int) enable)); 1118 break; 1119 case phymodLoopbackRemotePMD : 1120 phy_copy.access.lane_mask = 0x1 << (start_lane / 4); 1121 PHYMOD_IF_ERR_RETURN(eagle_tsc_rmt_lpbk(&phy_copy.access, (uint8_t)enable)); 1122 break; 1123 case phymodLoopbackRemotePCS : 1124 PHYMOD_IF_ERR_RETURN(temod_rx_loopback_control(&phy->access, enable, enable, enable)); /* RAVI */ 1125 break; 1126 default : 1127 break; 1128 } 1129 return rv; 1130 return PHYMOD_E_NONE; 1131 1132 } 1133 1134 int qsgmiie_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable) 1135 { 1136 int start_lane, num_lane; 1137 phymod_phy_access_t phy_copy; 1138 1139 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1140 1141 /* next figure out the lane num and start_lane based on the input */ 1142 PHYMOD_IF_ERR_RETURN 1143 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1144 1145 switch (loopback) { 1146 case phymodLoopbackGlobal : 1147 case phymodLoopbackGlobalPMD : 1148 phy_copy.access.lane_mask = 0x1 << (start_lane / 4); 1149 PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&phy_copy.access, enable)); 1150 break; 1151 case phymodLoopbackRemotePMD : 1152 phy_copy.access.lane_mask = 0x1 << (start_lane / 4); 1153 PHYMOD_IF_ERR_RETURN(eagle_tsc_rmt_lpbk_get(&phy_copy.access, enable)); 1154 break; 1155 case phymodLoopbackRemotePCS : 1156 /* PHYMOD_IF_ERR_RETURN(temod_rx_loopback_control(&phy->access, enable, enable, enable)); */ /* RAVI */ 1157 break; 1158 default : 1159 break; 1160 } 1161 1162 return PHYMOD_E_NONE; 1163 } 1164 1165 1166 int qsgmiie_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_seq_done) 1167 { 1168 int start_lane, num_lane; 1169 phymod_phy_access_t phy_copy; 1170 1171 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1172 1173 /* next figure out the lane num and start_lane based on the input */ 1174 PHYMOD_IF_ERR_RETURN 1175 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1176 1177 phy_copy.access.lane_mask = 0x1 << (start_lane/4); 1178 1179 PHYMOD_IF_ERR_RETURN(temod_pmd_lock_get(&phy_copy.access, rx_seq_done)); 1180 1181 1182 return PHYMOD_E_NONE; 1183 1184 } 1185 1186 1187 int qsgmiie_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status) 1188 { 1189 1190 PHYMOD_IF_ERR_RETURN(tqmod_get_pcs_link_status(&phy->access, link_status)); 1191 1192 return PHYMOD_E_NONE; 1193 1194 } 1195 1196 1197 STATIC 1198 int qsgmiie_phy_reg_is_pcs_get(uint32_t reg_addr, int* is_qsgmii_pcs_reg) { 1199 1200 *is_qsgmii_pcs_reg = (PHY_REG_ADDR_DEVAD(reg_addr) == 0) && 1201 ((IS_QSGMII_REGISTER(reg_addr)) || (QSGMII_REG_ADDR_REG(reg_addr) < 0x10)); 1202 return PHYMOD_E_NONE; 1203 } 1204 1205 int qsgmiie_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val) 1206 { 1207 int start_lane, num_lane, is_qsgmii_pcs; 1208 phymod_phy_access_t phy_copy; 1209 1210 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1211 1212 /* next figure out the lane num and start_lane based on the input */ 1213 PHYMOD_IF_ERR_RETURN 1214 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1215 1216 PHYMOD_IF_ERR_RETURN 1217 (qsgmiie_phy_reg_is_pcs_get(reg_addr, &is_qsgmii_pcs)); 1218 1219 if (!is_qsgmii_pcs) { 1220 phy_copy.access.lane_mask = 0x1 << (start_lane/4); 1221 } 1222 1223 PHYMOD_IF_ERR_RETURN 1224 (phymod_tsc_iblk_read(&phy_copy.access, reg_addr, val)); 1225 1226 return PHYMOD_E_NONE; 1227 } 1228 1229 int qsgmiie_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val) 1230 { 1231 int start_lane, num_lane, is_qsgmii_pcs; 1232 phymod_phy_access_t phy_copy; 1233 1234 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1235 1236 /* next figure out the lane num and start_lane based on the input */ 1237 PHYMOD_IF_ERR_RETURN 1238 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1239 1240 PHYMOD_IF_ERR_RETURN 1241 (qsgmiie_phy_reg_is_pcs_get(reg_addr, &is_qsgmii_pcs)); 1242 1243 if (!is_qsgmii_pcs) { 1244 phy_copy.access.lane_mask = 0x1 << (start_lane/4); 1245 } 1246 1247 PHYMOD_IF_ERR_RETURN 1248 (phymod_tsc_iblk_write(&phy_copy.access, reg_addr, val)); 1249 1250 return PHYMOD_E_NONE; 1251 } 1252 1253 int qsgmiie_phy_rx_signal_detect_get(const phymod_phy_access_t* phy, uint32_t* value) 1254 { 1255 uint32_t local_rx_signal_det; 1256 int start_lane, num_lane, i; 1257 1258 *value = 1; 1259 1260 PHYMOD_IF_ERR_RETURN 1261 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1262 1263 for (i = 0; i < num_lane; i++) { 1264 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1265 continue; 1266 } 1267 PHYMOD_IF_ERR_RETURN 1268 (eagle_tsc_signal_detect(&phy->access, &local_rx_signal_det)); 1269 *value = *value & local_rx_signal_det; 1270 } 1271 1272 return PHYMOD_E_NONE; 1273 } 1274 1275 int qsgmiie_phy_rx_ppm_get(const phymod_phy_access_t* phy, int16_t* rx_ppm) 1276 { 1277 int start_lane, num_lane; 1278 phymod_phy_access_t pm_phy_copy; 1279 1280 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1281 1282 PHYMOD_IF_ERR_RETURN 1283 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1284 1285 pm_phy_copy.access.lane_mask = 1 << start_lane; 1286 PHYMOD_IF_ERR_RETURN 1287 (eagle_tsc_rx_ppm(&pm_phy_copy.access, rx_ppm)); 1288 1289 return PHYMOD_E_NONE; 1290 } 1291