merlin16.c (54843B)
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_dispatch.h> 13 #include <phymod/phymod_util.h> 14 #include <phymod/phymod_debug.h> 15 #include <phymod/chip/merlin16.h> 16 #include <phymod/phymod_acc.h> 17 #include <phymod/chip/bcmi_tsce16_xgxs_defs.h> 18 #include "../../merlin16/tier1/merlin16_cfg_seq.h" 19 #include "../../merlin16/tier1/merlin16_enum.h" 20 #include "../../merlin16/tier1/merlin16_common.h" 21 #include "../../merlin16/tier1/merlin16_interface.h" 22 #include "../../merlin16/tier1/merlin16_dependencies.h" 23 #include "../../merlin16/tier1/merlin16_debug_functions.h" 24 #include "../../merlin16/tier1/merlin16_internal.h" 25 26 #define MERLIN16_MODEL 0x23 27 #define MERLIN16_PHY_ALL_LANES 0xf 28 #define MERLIN16_NOF_LANES_IN_CORE 4 29 30 #define MERLIN16_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \ 31 do{\ 32 PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\ 33 (_phy_access)->type = (_core_access)->type; \ 34 (_phy_access)->port_loc = (_core_access)->port_loc; \ 35 (_phy_access)->device_op_mode = (_core_access)->device_op_mode; \ 36 (_phy_access)->access.lane_mask = MERLIN16_PHY_ALL_LANES; \ 37 }while(0) 38 39 #define MERLIN16_NOF_DFES 5 40 41 #define MERILIN16_PMD_CRC_UCODE 1 42 /* uController's firmware */ 43 extern unsigned char merlin16_ucode[]; 44 extern unsigned short merlin16_ucode_ver; 45 extern unsigned short merlin16_ucode_crc; 46 extern unsigned short merlin16_ucode_len; 47 48 49 /*Initialize phymod module*/ 50 int merlin16_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified) 51 { 52 merlin16_rev_id0_t rev_id0; 53 merlin16_rev_id1_t rev_id1; 54 const phymod_access_t *pm_acc = &core->access; 55 *is_identified = 0; 56 57 PHYMOD_IF_ERR_RETURN(merlin16_identify(pm_acc, &rev_id0, &rev_id1)); 58 if (rev_id0.revid_model == MERLIN16_MODEL) { 59 *is_identified = 1; 60 } 61 62 return PHYMOD_E_NONE; 63 } 64 65 /*Retrive core information*/ 66 int merlin16_core_info_get(const phymod_core_access_t* core, phymod_core_info_t* info) 67 { 68 info->core_version = phymodCoreVersionMerlin16; 69 PHYMOD_STRNCPY(info->name, "Merlin16", PHYMOD_STRLEN("Merlin16") + 1); 70 info->phy_id0 = 0; 71 info->phy_id1= 0; 72 73 return PHYMOD_E_NONE; 74 } 75 76 /*Set\get lane mapping*/ 77 int merlin16_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map) 78 { 79 /*Just suport lane address mapping, not support lane swapping*/ 80 return PHYMOD_E_NONE; 81 } 82 int merlin16_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map) 83 { 84 /*Just suport lane address mapping, not support lane swapping*/ 85 return PHYMOD_E_NONE; 86 } 87 88 /*Reset Core*/ 89 int merlin16_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 90 { 91 return PHYMOD_E_NONE; 92 } 93 int merlin16_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction) 94 { 95 return PHYMOD_E_NONE; 96 } 97 98 /*Retrive firmware information*/ 99 int merlin16_core_firmware_info_get(const phymod_core_access_t* core, phymod_core_firmware_info_t* fw_info) 100 { 101 return PHYMOD_E_NONE; 102 } 103 104 /*Start\Stop the sequencer*/ 105 int merlin16_core_pll_sequencer_restart(const phymod_core_access_t* core, uint32_t flags, phymod_sequencer_operation_t operation) 106 { 107 return PHYMOD_E_NONE; 108 } 109 110 /*Wait for core event*/ 111 int merlin16_core_wait_event(const phymod_core_access_t* core, phymod_core_event_t event, uint32_t timeout) 112 { 113 return PHYMOD_E_NONE; 114 } 115 116 /* re-tune rx path*/ 117 int merlin16_phy_rx_restart(const phymod_phy_access_t* phy) 118 { 119 phymod_phy_access_t phy_copy; 120 int start_lane, num_lane, i; 121 122 PHYMOD_IF_ERR_RETURN 123 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 124 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 125 126 for (i = 0; i < num_lane; i++) { 127 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 128 continue; 129 } 130 phy_copy.access.lane_mask = 1 << (start_lane + i); 131 132 PHYMOD_IF_ERR_RETURN(merlin16_rx_restart(&phy_copy.access, 1)); 133 } 134 return PHYMOD_E_NONE; 135 } 136 137 /*Set phy polarity*/ 138 int merlin16_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity) 139 { 140 phymod_phy_access_t phy_copy; 141 int start_lane, num_lane, i; 142 143 PHYMOD_IF_ERR_RETURN 144 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 145 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 146 147 for (i = 0; i < num_lane; i++) { 148 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 149 continue; 150 } 151 phy_copy.access.lane_mask = 1 << (start_lane + i); 152 153 PHYMOD_IF_ERR_RETURN 154 (merlin16_polarity_set(&phy_copy.access, polarity->tx_polarity, polarity->rx_polarity)); 155 } 156 157 return PHYMOD_E_NONE; 158 } 159 int merlin16_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity) 160 { 161 PHYMOD_IF_ERR_RETURN 162 (merlin16_polarity_get(&phy->access, &polarity->tx_polarity, &polarity->rx_polarity)); 163 164 return PHYMOD_E_NONE; 165 } 166 167 /*Set\Get TX Parameters*/ 168 int merlin16_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 169 { 170 phymod_phy_access_t phy_copy; 171 int start_lane, num_lane, i; 172 173 PHYMOD_IF_ERR_RETURN 174 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 175 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 176 177 for (i = 0; i < num_lane; i++) { 178 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 179 continue; 180 } 181 phy_copy.access.lane_mask = 1 << (start_lane + i); 182 183 PHYMOD_IF_ERR_RETURN 184 (merlin16_apply_txfir_cfg(&phy_copy.access, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2)); 185 } 186 187 return PHYMOD_E_NONE; 188 } 189 int merlin16_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 190 { 191 int8_t value = 0; 192 193 PHYMOD_IF_ERR_RETURN 194 (merlin16_read_tx_afe(&phy->access, TX_AFE_PRE, &value)); 195 tx->pre = value; 196 PHYMOD_IF_ERR_RETURN 197 (merlin16_read_tx_afe(&phy->access, TX_AFE_MAIN, &value)); 198 tx->main = value; 199 PHYMOD_IF_ERR_RETURN 200 (merlin16_read_tx_afe(&phy->access, TX_AFE_POST1, &value)); 201 tx->post = value; 202 PHYMOD_IF_ERR_RETURN 203 (merlin16_read_tx_afe(&phy->access, TX_AFE_POST2, &value)); 204 tx->post2 = value; 205 206 return PHYMOD_E_NONE; 207 } 208 209 /*Request for default TX parameters configuration per media type*/ 210 int merlin16_phy_media_type_tx_get(const phymod_phy_access_t* phy, phymod_media_typed_t media, phymod_tx_t* tx) 211 { 212 switch (media) { 213 case phymodMediaTypeChipToChip: 214 tx->pre = 0x0; 215 tx->main = 0x32; 216 tx->post = 0xa; 217 tx->post2 = 0x0; 218 break; 219 case phymodMediaTypeShort: 220 tx->pre = 0x0; 221 tx->main = 0x32; 222 tx->post = 0xa; 223 tx->post2 = 0x0; 224 break; 225 case phymodMediaTypeMid: 226 tx->pre = 0x0; 227 tx->main = 0x32; 228 tx->post = 0xa; 229 tx->post2 = 0x0; 230 break; 231 case phymodMediaTypeLong: 232 tx->pre = 0x0; 233 tx->main = 0x32; 234 tx->post = 0xa; 235 tx->post2 = 0x0; 236 break; 237 default: 238 tx->pre = 0x0; 239 tx->main = 0x32; 240 tx->post = 0xa; 241 tx->post2 = 0x0; 242 break; 243 } 244 245 return PHYMOD_E_NONE; 246 } 247 248 249 /*Set\Get TX override Parameters*/ 250 int merlin16_phy_tx_override_set(const phymod_phy_access_t* phy, const phymod_tx_override_t* tx_override) 251 { 252 phymod_phy_access_t phy_copy; 253 int start_lane, num_lane, i; 254 255 PHYMOD_IF_ERR_RETURN 256 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 257 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 258 259 for (i = 0; i < num_lane; i++) { 260 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 261 continue; 262 } 263 phy_copy.access.lane_mask = 1 << (start_lane + i); 264 265 PHYMOD_IF_ERR_RETURN 266 (merlin16_tx_pi_freq_override(&phy_copy.access, 267 tx_override->phase_interpolator.enable, 268 tx_override->phase_interpolator.value)); 269 } 270 271 return PHYMOD_E_NONE; 272 } 273 int merlin16_phy_tx_override_get(const phymod_phy_access_t* phy, phymod_tx_override_t* tx_override) 274 { 275 return PHYMOD_E_NONE; 276 } 277 278 /*Set\Get RX Parameters*/ 279 int merlin16_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx) 280 { 281 uint32_t i; 282 phymod_phy_access_t phy_copy; 283 int start_lane, num_lane, lane; 284 285 PHYMOD_IF_ERR_RETURN 286 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 287 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 288 289 /*params check*/ 290 if((rx->num_of_dfe_taps == 0) || (rx->num_of_dfe_taps < MERLIN16_NOF_DFES)){ 291 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal number of DFEs to set %u"), rx->num_of_dfe_taps)); 292 } 293 294 for (lane = 0; lane < num_lane; lane++) { 295 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + lane)) { 296 continue; 297 } 298 phy_copy.access.lane_mask = 1 << (start_lane + lane); 299 300 /*vga set*/ 301 if (rx->vga.enable) { 302 /* first stop the rx adaption */ 303 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1)); 304 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_VGA, rx->vga.value)); 305 } else { 306 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0)); 307 } 308 309 /*dfe set*/ 310 for (i = 0 ; i < rx->num_of_dfe_taps ; i++){ 311 if(rx->dfe[i].enable){ 312 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1)); 313 switch (i) { 314 case 0: 315 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE1, rx->dfe[i].value)); 316 break; 317 case 1: 318 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE2, rx->dfe[i].value)); 319 break; 320 case 2: 321 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE3, rx->dfe[i].value)); 322 break; 323 case 3: 324 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE4, rx->dfe[i].value)); 325 break; 326 case 4: 327 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE5, rx->dfe[i].value)); 328 break; 329 default: 330 return PHYMOD_E_PARAM; 331 } 332 } else { 333 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0)); 334 } 335 336 337 } 338 339 /*peaking filter set*/ 340 if(rx->peaking_filter.enable){ 341 /* first stop the rx adaption */ 342 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1)); 343 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_PF, rx->peaking_filter.value)); 344 } else { 345 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0)); 346 } 347 348 if(rx->low_freq_peaking_filter.enable){ 349 /* first stop the rx adaption */ 350 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1)); 351 PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_PF2, rx->low_freq_peaking_filter.value)); 352 } else { 353 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0)); 354 } 355 } 356 357 return PHYMOD_E_NONE; 358 } 359 360 int merlin16_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx) 361 { 362 int8_t val; 363 364 PHYMOD_IF_ERR_RETURN 365 (merlin16_read_rx_afe(&phy->access, RX_AFE_PF, &val)); 366 rx->peaking_filter.value = val; 367 368 PHYMOD_IF_ERR_RETURN 369 (merlin16_read_rx_afe(&phy->access, RX_AFE_PF2, &val)); 370 rx->low_freq_peaking_filter.value = val; 371 372 PHYMOD_IF_ERR_RETURN 373 (merlin16_read_rx_afe(&phy->access, RX_AFE_VGA, &val)); 374 rx->vga.value = val; 375 376 PHYMOD_IF_ERR_RETURN 377 (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE1, &val)); 378 rx->dfe[0].value = val; 379 380 PHYMOD_IF_ERR_RETURN 381 (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE2, &val)); 382 rx->dfe[1].value = val; 383 384 PHYMOD_IF_ERR_RETURN 385 (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE3, &val)); 386 rx->dfe[2].value = val; 387 388 PHYMOD_IF_ERR_RETURN 389 (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE4, &val)); 390 rx->dfe[3].value = val; 391 392 PHYMOD_IF_ERR_RETURN 393 (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE5, &val)); 394 rx->dfe[4].value = val; 395 396 rx->num_of_dfe_taps = 5; 397 rx->dfe[0].enable = 1; 398 rx->dfe[1].enable = 1; 399 rx->dfe[2].enable = 1; 400 rx->dfe[3].enable = 1; 401 rx->dfe[4].enable = 1; 402 rx->vga.enable = 1; 403 rx->low_freq_peaking_filter.enable = 1; 404 rx->peaking_filter.enable = 1; 405 406 return PHYMOD_E_NONE; 407 } 408 409 410 /*Reset phy*/ 411 int merlin16_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset) 412 { 413 uint32_t rst, rst_rx, rst_tx; 414 int start_lane, num_lane, i; 415 phymod_phy_access_t phy_copy; 416 417 PHYMOD_IF_ERR_RETURN 418 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 419 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 420 421 if (reset->rx == reset->tx) { 422 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release_get(&phy_copy.access, &rst_tx)); 423 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release_get(&phy_copy.access, &rst_rx)); 424 for (i = 0; i < num_lane; i++) { 425 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 426 continue; 427 } 428 phy_copy.access.lane_mask = 1 << (start_lane + i); 429 /*If tx is in reset, release tx lane*/ 430 if (rst_tx == 0) { 431 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 1)); 432 PHYMOD_USLEEP(10); 433 } 434 /*If rx is in reset, release rx lane*/ 435 if (rst_rx == 0) { 436 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 1)); 437 PHYMOD_USLEEP(10); 438 } 439 switch (reset->tx) { 440 case phymodResetDirectionIn: 441 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 0)); 442 break; 443 case phymodResetDirectionOut: 444 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 445 break; 446 case phymodResetDirectionInOut: 447 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 0)); 448 PHYMOD_USLEEP(10); 449 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 450 break; 451 default: 452 break; 453 } 454 } 455 } else { 456 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release_get(&phy->access, &rst)); 457 for (i = 0; i < num_lane; i++) { 458 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 459 continue; 460 } 461 phy_copy.access.lane_mask = 1 << (start_lane + i); 462 /*If ln_rst is is in reset , release ln_rst first*/ 463 if (rst == 0) { 464 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 465 PHYMOD_USLEEP(10); 466 } 467 switch (reset->tx) { 468 case phymodResetDirectionIn: 469 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 0)); 470 break; 471 case phymodResetDirectionOut: 472 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 1)); 473 break; 474 case phymodResetDirectionInOut: 475 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 0)); 476 PHYMOD_USLEEP(10); 477 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 1)); 478 break; 479 default: 480 break; 481 } 482 switch (reset ->rx) { 483 case phymodResetDirectionIn: 484 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 0)); 485 break; 486 case phymodResetDirectionOut: 487 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 1)); 488 break; 489 case phymodResetDirectionInOut: 490 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 0)); 491 PHYMOD_USLEEP(10); 492 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 1)); 493 break; 494 default: 495 break; 496 } 497 } 498 } 499 500 return PHYMOD_E_NONE; 501 } 502 503 504 int merlin16_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset) 505 { 506 uint32_t rst, rst_rx, rst_tx; 507 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release_get(&phy->access, &rst)); 508 if(rst == 0) { 509 reset->tx = phymodResetDirectionIn; 510 reset->rx = phymodResetDirectionIn; 511 } else { 512 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release_get(&phy->access, &rst_tx)); 513 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release_get(&phy->access, &rst_rx)); 514 if (rst_tx == 0) { 515 reset->tx = phymodResetDirectionIn; 516 } else { 517 reset->tx = phymodResetDirectionOut; 518 } 519 520 if(rst_rx == 0) { 521 reset->rx = phymodResetDirectionIn; 522 } else { 523 reset->rx = phymodResetDirectionOut; 524 } 525 } 526 527 return PHYMOD_E_NONE; 528 } 529 530 531 /*Control phy power*/ 532 int merlin16_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 533 { 534 enum srds_core_pwrdn_mode_enum mode; 535 phymod_phy_access_t phy_copy; 536 int start_lane, num_lane, i; 537 538 PHYMOD_IF_ERR_RETURN 539 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 540 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 541 542 for (i = 0; i < num_lane; i++) { 543 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 544 continue; 545 } 546 phy_copy.access.lane_mask = 1 << (start_lane + i); 547 548 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) { 549 /*disable tx on the PMD side */ 550 mode = PWRDN_TX; 551 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode)); 552 } 553 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) { 554 /*enable tx on the PMD side */ 555 PHYMOD_IF_ERR_RETURN(merlin16_pwrdn_set(&phy_copy.access, 1, 0)); 556 } 557 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) { 558 /*disable rx on the PMD side */ 559 mode = PWRDN_RX; 560 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode)); 561 } 562 if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) { 563 PHYMOD_IF_ERR_RETURN(merlin16_pwrdn_set(&phy_copy.access, 0, 0)); 564 /*enable rx on the PMD side */ 565 } 566 if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) { 567 mode = PWR_ON; 568 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode)); 569 } 570 if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) { 571 /* Both Tx and Rx power down */ 572 mode = PWRDN; 573 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode)); 574 } 575 } 576 return PHYMOD_E_NONE; 577 } 578 579 580 int merlin16_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 581 { 582 power_status_t pwrdn; 583 PHYMOD_IF_ERR_RETURN(merlin16_pwrdn_get(&phy->access, &pwrdn)); 584 power->rx = (pwrdn.rx_s_pwrdn == 0)? phymodPowerOn: phymodPowerOff; 585 power->tx = (pwrdn.tx_s_pwrdn == 0)? phymodPowerOn: phymodPowerOff; 586 return PHYMOD_E_NONE; 587 } 588 589 /*TX transmission control*/ 590 int merlin16_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control) 591 { 592 phymod_phy_access_t phy_copy; 593 int start_lane, num_lane, i; 594 595 PHYMOD_IF_ERR_RETURN 596 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 597 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 598 599 switch (tx_control) 600 { 601 case phymodTxSquelchOn: 602 for (i = 0; i < num_lane; i++) { 603 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 604 continue; 605 } 606 phy_copy.access.lane_mask = 1 << (start_lane + i); 607 PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&phy_copy.access, 1)); 608 } 609 break; 610 case phymodTxSquelchOff: 611 for (i = 0; i < num_lane; i++) { 612 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 613 continue; 614 } 615 phy_copy.access.lane_mask = 1 << (start_lane + i); 616 PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&phy_copy.access, 0)); 617 } 618 break; 619 default: 620 PHYMOD_DEBUG_ERROR(("This control is NOT SUPPORTED!! (eagle_phy_tx_lane_control_set) \n")); 621 break; 622 } 623 624 return PHYMOD_E_NONE; 625 626 } 627 628 int merlin16_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control) 629 { 630 uint32_t enable; 631 632 PHYMOD_IF_ERR_RETURN(merlin16_tx_disable_get(&phy->access, &enable)); 633 634 if(enable){ 635 *tx_control = phymodTxSquelchOn; 636 } else { 637 *tx_control = phymodTxSquelchOff; 638 } 639 640 return PHYMOD_E_NONE; 641 642 } 643 644 /*Rx control*/ 645 int merlin16_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control) 646 { 647 phymod_phy_access_t phy_copy; 648 int start_lane, num_lane, i; 649 650 PHYMOD_IF_ERR_RETURN 651 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 652 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 653 654 switch (rx_control) 655 { 656 case phymodRxSquelchOn: 657 for (i = 0; i < num_lane; i++) { 658 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 659 continue; 660 } 661 phy_copy.access.lane_mask = 1 << (start_lane + i); 662 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_control_set(&phy_copy.access, 1)); 663 } 664 break; 665 case phymodRxSquelchOff: 666 for (i = 0; i < num_lane; i++) { 667 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 668 continue; 669 } 670 phy_copy.access.lane_mask = 1 << (start_lane + i); 671 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_control_set(&phy_copy.access, 0)); 672 } 673 break; 674 default: 675 PHYMOD_DEBUG_ERROR(("This control is NOT SUPPORTED!! (eagle_phy_rx_lane_control_set) \n")); 676 break; 677 } 678 679 return PHYMOD_E_NONE; 680 } 681 682 683 int merlin16_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control) 684 { 685 686 uint32_t enable; 687 688 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_control_get(&phy->access, &enable)); 689 690 if(enable){ 691 *rx_control = phymodRxSquelchOn; 692 } else { 693 *rx_control = phymodRxSquelchOff; 694 } 695 696 return PHYMOD_E_NONE; 697 698 } 699 700 int merlin16_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_config) 701 { 702 struct merlin16_uc_core_config_st serdes_firmware_core_config; 703 PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(serdes_firmware_core_config)); 704 serdes_firmware_core_config.field.core_cfg_from_pcs = fw_config.CoreConfigFromPCS; 705 serdes_firmware_core_config.field.vco_rate = fw_config.VcoRate; 706 707 PHYMOD_IF_ERR_RETURN(merlin16_INTERNAL_set_uc_core_config(&phy->access, serdes_firmware_core_config)); 708 return PHYMOD_E_NONE; 709 } 710 711 int merlin16_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_config) 712 { 713 struct merlin16_uc_core_config_st serdes_firmware_core_config; 714 PHYMOD_IF_ERR_RETURN(merlin16_get_uc_core_config(&phy->access, &serdes_firmware_core_config)); 715 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 716 fw_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs; 717 fw_config->VcoRate = serdes_firmware_core_config.field.vco_rate; 718 return PHYMOD_E_NONE; 719 } 720 721 int merlin16_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config) 722 { 723 struct merlin16_uc_lane_config_st serdes_firmware_config; 724 PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config)); 725 726 PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy->access, &serdes_firmware_config)); 727 PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config)); 728 fw_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs; 729 fw_config->AnEnabled = serdes_firmware_config.field.an_enabled; 730 fw_config->DfeOn = serdes_firmware_config.field.dfe_on; 731 fw_config->ForceBrDfe = serdes_firmware_config.field.force_brdfe_on; 732 fw_config->Cl72AutoPolEn = serdes_firmware_config.field.cl72_auto_polarity_en; 733 fw_config->Cl72RestTO = serdes_firmware_config.field.cl72_restart_timeout_en; 734 fw_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis; 735 fw_config->UnreliableLos = serdes_firmware_config.field.unreliable_los; 736 fw_config->MediaType = serdes_firmware_config.field.media_type; 737 fw_config->Cl72AutoPolEn = serdes_firmware_config.field.cl72_auto_polarity_en; 738 fw_config->Cl72RestTO = serdes_firmware_config.field.cl72_restart_timeout_en; 739 740 return PHYMOD_E_NONE; 741 } 742 743 STATIC 744 int _merlin16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 745 { 746 struct merlin16_uc_lane_config_st serdes_firmware_config; 747 phymod_phy_access_t phy_copy; 748 int start_lane, num_lane, i; 749 /* uint32_t rst_status; */ 750 uint32_t is_warm_boot; 751 752 PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config)); 753 PHYMOD_IF_ERR_RETURN 754 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 755 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 756 757 for (i = 0; i < num_lane; i++) { 758 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 759 continue; 760 } 761 phy_copy.access.lane_mask = 1 << (start_lane + i); 762 serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS; 763 serdes_firmware_config.field.an_enabled = fw_config.AnEnabled; 764 serdes_firmware_config.field.dfe_on = fw_config.DfeOn; 765 serdes_firmware_config.field.force_brdfe_on = fw_config.ForceBrDfe; 766 /* serdes_firmware_config.field.cl72_emulation_en = fw_config.Cl72Enable; */ 767 serdes_firmware_config.field.scrambling_dis = fw_config.ScramblingDisable; 768 serdes_firmware_config.field.unreliable_los = fw_config.UnreliableLos; 769 serdes_firmware_config.field.media_type = fw_config.MediaType; 770 serdes_firmware_config.field.cl72_auto_polarity_en = fw_config.Cl72AutoPolEn; 771 serdes_firmware_config.field.cl72_restart_timeout_en = fw_config.Cl72RestTO; 772 773 PHYMOD_IF_ERR_RETURN(PHYMOD_IS_WRITE_DISABLED(&phy_copy.access, &is_warm_boot)); 774 775 if (!is_warm_boot) { 776 /* PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_read(&phy_copy.access, &rst_status)); */ 777 /* if (rst_status) */ PHYMOD_IF_ERR_RETURN (merlin16_lane_soft_reset_release(&phy_copy.access, 0)); 778 PHYMOD_IF_ERR_RETURN(merlin16_set_uc_lane_cfg(&phy_copy.access, serdes_firmware_config)); 779 /* if (rst_status) */ PHYMOD_IF_ERR_RETURN (merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 780 } 781 } 782 783 return PHYMOD_E_NONE; 784 } 785 786 int merlin16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 787 { 788 phymod_phy_access_t phy_copy; 789 int start_lane, num_lane, i; 790 791 PHYMOD_IF_ERR_RETURN 792 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 793 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 794 795 /*Hold the per lne soft reset bit*/ 796 for (i = 0; i < num_lane; i++) { 797 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 798 continue; 799 } 800 phy_copy.access.lane_mask = 1 << (start_lane + i); 801 PHYMOD_IF_ERR_RETURN 802 (merlin16_lane_soft_reset_release(&phy_copy.access, 0)); 803 } 804 805 PHYMOD_IF_ERR_RETURN 806 (_merlin16_phy_firmware_lane_config_set(phy, fw_config)); 807 /*Hold the per lne soft reset bit*/ 808 for (i = 0; i < num_lane; i++) { 809 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 810 continue; 811 } 812 phy_copy.access.lane_mask = 1 << (start_lane + i); 813 PHYMOD_IF_ERR_RETURN 814 (merlin16_lane_soft_reset_release(&phy_copy.access, 1)); 815 } 816 817 return PHYMOD_E_NONE; 818 } 819 820 821 /*Set the interface mode, speed and other configuration related to interface.*/ 822 int merlin16_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 823 { 824 uint32_t new_pll_div; 825 int16_t new_os_mode = 0; 826 phymod_phy_access_t pm_phy_copy; 827 int start_lane=0, num_lane, i; 828 uint32_t current_pll_div; 829 phymod_firmware_lane_config_t firmware_lane_config; 830 enum merlin16_pll_refclk_enum refclk = MERLIN16_PLL_REFCLK_156P25MHZ; 831 832 #ifdef PHYMOD_DIAG 833 const phymod_access_t *pm_acc; 834 pm_acc = &phy->access; 835 PHYMOD_VDBG(DBG_SPD, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" speed=%0d intf=%0d(%s) flags=%0x\n", 836 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, config->data_rate, config->interface_type, 837 phymod_interface_t_mapping[config->interface_type].key, flags)); 838 #endif 839 840 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 841 PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config)); 842 843 /* end of special mode */ 844 firmware_lane_config.MediaType = 0; 845 846 /* next program the tx fir taps and driver current based on the input */ 847 PHYMOD_IF_ERR_RETURN 848 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 849 850 851 /* Hold the per lne soft reset bit */ 852 for (i = 0; i < num_lane; i++) { 853 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 854 continue; 855 } 856 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 857 PHYMOD_IF_ERR_RETURN 858 (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 0)); 859 } 860 861 pm_phy_copy.access.lane_mask = 0x1 << start_lane; 862 PHYMOD_IF_ERR_RETURN 863 (merlin16_phy_firmware_lane_config_get(&pm_phy_copy, &firmware_lane_config)); 864 865 firmware_lane_config.AnEnabled = 0; 866 firmware_lane_config.LaneConfigFromPCS = 0; 867 firmware_lane_config.DfeOn = 1; 868 firmware_lane_config.LpDfeOn = 0; 869 firmware_lane_config.Cl72RestTO = 1; 870 if (config->data_rate < 10000) { 871 firmware_lane_config.DfeOn = 0; 872 } 873 if (PHYMOD_INTF_MODES_FIBER_GET(config)) { 874 firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics; 875 } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) { 876 firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable; 877 } else { 878 firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 879 } 880 881 /* get the current PLL setting */ 882 pm_phy_copy.access.lane_mask = 1 << start_lane; 883 PHYMOD_IF_ERR_RETURN 884 (merlin16_INTERNAL_read_pll_div(&pm_phy_copy.access, ¤t_pll_div)); 885 886 /*Get new pll div through ref_clk and data rate*/ 887 PHYMOD_IF_ERR_RETURN 888 (merlin16_get_pll_vco_osmode(config, &new_pll_div, &new_os_mode)); 889 890 /* if pll change is enabled. new_pll_div is the reg vector value */ 891 if ((current_pll_div != new_pll_div) && (PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) { 892 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 893 (_PHYMOD_MSG("pll has to change for speed_set from %u to %u but DONT_TURN_OFF_PLL flag is enabled"), 894 (unsigned int)current_pll_div, (unsigned int)new_pll_div)); 895 } 896 897 /* pll switch is required and expected */ 898 if((current_pll_div != new_pll_div) && !(PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) { 899 PHYMOD_IF_ERR_RETURN 900 (merlin16_core_soft_reset_release(&pm_phy_copy.access, 0)); 901 902 switch (config->ref_clock) { 903 case phymodRefClk156Mhz: 904 refclk = MERLIN16_PLL_REFCLK_156P25MHZ; 905 break; 906 case phymodRefClk125Mhz: 907 refclk = MERLIN16_PLL_REFCLK_125MHZ; 908 break; 909 case phymodRefClk161Mhz: 910 refclk = MERLIN16_PLL_REFCLK_161P1328125MHZ; 911 break; 912 default: 913 refclk = MERLIN16_PLL_REFCLK_156P25MHZ; 914 break; 915 } 916 /* set the PLL divider */ 917 PHYMOD_IF_ERR_RETURN 918 (merlin16_configure_pll_refclk_div(&pm_phy_copy.access, refclk, new_pll_div)); 919 920 PHYMOD_IF_ERR_RETURN 921 (merlin16_core_soft_reset_release(&pm_phy_copy.access, 1)); 922 } 923 924 /*Set os mode*/ 925 for (i = 0; i < num_lane; i++) { 926 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 927 continue; 928 } 929 pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i); 930 PHYMOD_IF_ERR_RETURN 931 (merlin16_osmode_set(&pm_phy_copy.access, new_os_mode)); 932 } 933 934 for (i = 0; i < num_lane; i++) { 935 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 936 continue; 937 } 938 pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i); 939 PHYMOD_IF_ERR_RETURN 940 (_merlin16_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config)); 941 } 942 943 /* release the per lne soft reset bit */ 944 for (i = 0; i < num_lane; i++) { 945 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 946 continue; 947 } 948 pm_phy_copy.access.lane_mask = 1 << (start_lane + i); 949 PHYMOD_IF_ERR_RETURN 950 (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1)); 951 } 952 953 return PHYMOD_E_NONE; 954 } 955 956 STATIC 957 int _merlin16_pll_multiplier_get(uint32_t pll_div, uint32_t *pll_multiplier) 958 { 959 switch (pll_div) { 960 case MERLIN16_PLL_DIV_70: *pll_multiplier = 70; 961 break; 962 case MERLIN16_PLL_DIV_66: *pll_multiplier = 66; 963 break; 964 case MERLIN16_PLL_DIV_64: *pll_multiplier = 64; 965 break; 966 case MERLIN16_PLL_DIV_60: *pll_multiplier = 60; 967 break; 968 case MERLIN16_PLL_DIV_92: *pll_multiplier = 92; 969 break; 970 case MERLIN16_PLL_DIV_80: *pll_multiplier = 80; 971 break; 972 case MERLIN16_PLL_DIV_54P4: *pll_multiplier = 54.4; 973 break; 974 default: return PHYMOD_E_NONE; 975 break; 976 } 977 return PHYMOD_E_NONE; 978 } 979 980 STATIC 981 int _merlin16_actual_osr_get(int16_t osr_mode, int* actual_os) 982 { 983 switch(osr_mode) { 984 case 0: *actual_os = 1; break; 985 case 1: *actual_os = 2; break; 986 case 2: *actual_os = 3; break; 987 case 4: *actual_os = 4; break; 988 case 5: *actual_os = 5; break; 989 case 7: *actual_os = 8; break; 990 case 8: *actual_os = 8 + 1/4; break; 991 case 9: *actual_os = 10; break; 992 default: 993 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("unsupported OS mode %d"), osr_mode)); 994 } 995 return PHYMOD_E_NONE; 996 } 997 998 999 int merlin16_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) 1000 { 1001 int osr_mode; 1002 uint32_t pll_div; 1003 uint32_t pll_multiplier = 1, refclk; 1004 phymod_phy_access_t phy_copy; 1005 int actual_osr; 1006 1007 config->ref_clock = ref_clock; 1008 1009 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1010 phy_copy.access.lane_mask = 0x1; 1011 1012 PHYMOD_IF_ERR_RETURN 1013 (merlin16_osr_mode_get(&phy->access, &osr_mode)); 1014 PHYMOD_IF_ERR_RETURN 1015 (merlin16_INTERNAL_read_pll_div(&phy_copy.access, &pll_div)); 1016 PHYMOD_IF_ERR_RETURN 1017 (_merlin16_pll_multiplier_get(pll_div, &pll_multiplier)); 1018 1019 if (ref_clock == phymodRefClk156Mhz) { 1020 refclk = 15625; 1021 } else if (ref_clock == phymodRefClk125Mhz) { 1022 refclk = 12500; 1023 } else { 1024 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("Unknown refclk"))); 1025 } 1026 1027 PHYMOD_IF_ERR_RETURN(_merlin16_actual_osr_get(osr_mode, &actual_osr)); 1028 1029 config->data_rate = (refclk*pll_multiplier)/(100*actual_osr); 1030 config->interface_type = phymodInterfaceBypass; 1031 1032 if(osr_mode == 1) { 1033 PHYMOD_INTF_MODES_OS2_SET(config); 1034 } 1035 1036 return PHYMOD_E_NONE; 1037 } 1038 1039 1040 /*Set\Get CL72*/ 1041 int merlin16_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en) 1042 { 1043 struct merlin16_uc_lane_config_st serdes_firmware_config; 1044 phymod_phy_access_t phy_copy; 1045 int start_lane, num_lane, i; 1046 #ifdef PHYMOD_DIAG 1047 const phymod_access_t *pm_acc; 1048 #endif 1049 1050 PHYMOD_IF_ERR_RETURN 1051 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1052 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1053 1054 #ifdef PHYMOD_DIAG 1055 pm_acc = &phy->access; 1056 PHYMOD_VDBG(DBG_CL72, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" cl72_en=%d\n", 1057 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, (int)cl72_en)); 1058 #endif 1059 1060 PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy->access, &serdes_firmware_config)); 1061 1062 if (serdes_firmware_config.field.dfe_on == 0) { 1063 PHYMOD_DEBUG_ERROR(("ERROR :: DFE is off : Can not start CL72 with no DFE\n")); 1064 return PHYMOD_E_CONFIG; 1065 } 1066 1067 for (i = 0; i < num_lane; i++) { 1068 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1069 continue; 1070 } 1071 phy_copy.access.lane_mask = 1 << (start_lane + i); 1072 PHYMOD_IF_ERR_RETURN 1073 (merlin16_clause72_control(&phy_copy.access, cl72_en)); 1074 } 1075 return PHYMOD_E_NONE; 1076 } 1077 1078 int merlin16_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en) 1079 { 1080 uint32_t local_en;; 1081 PHYMOD_IF_ERR_RETURN 1082 (merlin16_pmd_cl72_enable_get(&phy->access, &local_en)); 1083 *cl72_en = local_en; 1084 return PHYMOD_E_NONE; 1085 } 1086 1087 1088 /*Get CL72 status*/ 1089 int merlin16_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status) 1090 { 1091 uint32_t local_status; 1092 PHYMOD_IF_ERR_RETURN 1093 (merlin16_pmd_cl72_receiver_status(&phy->access, &local_status)); 1094 status->locked = local_status; 1095 return PHYMOD_E_NONE; 1096 } 1097 1098 /*Set\Get autoneg*/ 1099 int merlin16_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability_set_type) 1100 { 1101 /* Not supported */ 1102 PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_ability_set) \n")); 1103 return PHYMOD_E_NONE; 1104 1105 } 1106 int merlin16_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type) 1107 { 1108 /* Not supported */ 1109 PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_ability_get) \n")); 1110 1111 return PHYMOD_E_NONE; 1112 } 1113 1114 /*Set\Get autoneg*/ 1115 int merlin16_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 1116 { 1117 /* Not supported */ 1118 PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_set) \n")); 1119 1120 return PHYMOD_E_NONE; 1121 } 1122 int merlin16_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done) 1123 { 1124 /* Not supported */ 1125 PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_get) \n")); 1126 1127 return PHYMOD_E_NONE; 1128 } 1129 1130 /*Get Autoneg status*/ 1131 int merlin16_phy_autoneg_status_get(const phymod_phy_access_t* phy, phymod_autoneg_status_t* status) 1132 { 1133 /* Not supported */ 1134 PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_status_get) \n")); 1135 1136 return PHYMOD_E_NONE; 1137 } 1138 1139 /* load tsce fw. the fw_loader parameter is valid just for external fw load */ 1140 STATIC 1141 int _merlin16_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader) 1142 { 1143 #ifdef PHYMOD_DIAG 1144 const phymod_access_t *pm_acc; 1145 pm_acc = &core->access; 1146 PHYMOD_VDBG(DBG_CFG, pm_acc, 1147 ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" load_meth=%0d", 1148 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, (int)load_method)); 1149 #endif 1150 1151 switch (load_method) { 1152 case phymodFirmwareLoadMethodInternal: 1153 PHYMOD_IF_ERR_RETURN(merlin16_ucode_mdio_load(&core->access, merlin16_ucode, merlin16_ucode_len)); 1154 break; 1155 case phymodFirmwareLoadMethodExternal: 1156 PHYMOD_NULL_CHECK(fw_loader); 1157 PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_pre(&core->access)); 1158 PHYMOD_IF_ERR_RETURN(fw_loader(core, merlin16_ucode_len, merlin16_ucode)); 1159 PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_post(&core->access)); 1160 break; 1161 case phymodFirmwareLoadMethodNone: 1162 break; 1163 default: 1164 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method)); 1165 } 1166 return PHYMOD_E_NONE; 1167 } 1168 1169 STATIC 1170 int _merlin16_core_init_pass1(const phymod_core_access_t* core, 1171 const phymod_core_init_config_t* init_config, 1172 const phymod_core_status_t* core_status) 1173 { 1174 phymod_phy_access_t phy_access, phy_access_copy; 1175 phymod_core_access_t core_copy; 1176 uint32_t uc_active = 0; 1177 int i, start_lane, num_lane; 1178 1179 MERLIN16_CORE_TO_PHY_ACCESS(&phy_access, core); 1180 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 1181 core_copy.access.lane_mask = 0x1; 1182 1183 phy_access_copy = phy_access; 1184 phy_access_copy.access = core->access; 1185 phy_access_copy.access.lane_mask = 0x1; 1186 phy_access_copy.type = core->type; 1187 1188 /* 1189 * First step to program merlin16 is to do power reset. That is to 1190 * program field POR_H_RSTB and CORE_DP_H_RSTB in register PMD_X1_CTL 1191 */ 1192 PHYMOD_IF_ERR_RETURN 1193 (merlin16_pmd_reset_seq(&core_copy.access, core_status->pmd_active)); 1194 1195 PHYMOD_IF_ERR_RETURN 1196 (phymod_util_lane_config_get(&phy_access.access, &start_lane, &num_lane)); 1197 1198 /* 1199 * Before programming the PMD lane address map register, the PMD lanes 1200 * have to be reset. Without do this, writing the PMD lane address map 1201 * regsiter will not take effect, meaning the reading value != writing 1202 * value. 1203 */ 1204 for (i = 0; i < MERLIN16_NOF_LANES_IN_CORE; i++) { 1205 phy_access.access.lane_mask = 1 << (start_lane + i); 1206 PHYMOD_IF_ERR_RETURN 1207 (merlin16_lane_hard_soft_reset_release(&phy_access.access, 0)); 1208 PHYMOD_IF_ERR_RETURN 1209 (merlin16_lane_soft_reset_release(&phy_access.access, 0)); 1210 1211 PHYMOD_IF_ERR_RETURN 1212 (merlin16_lane_hard_soft_reset_release(&phy_access.access, 1)); 1213 PHYMOD_IF_ERR_RETURN 1214 (merlin16_lane_soft_reset_release(&phy_access.access, 1)); 1215 } 1216 1217 PHYMOD_IF_ERR_RETURN(merlin16_uc_active_get(&core_copy.access, &uc_active)); 1218 if (uc_active) { 1219 return(PHYMOD_E_NONE); 1220 } 1221 1222 /* need to set the heart beat default is for 156.25M */ 1223 PHYMOD_IF_ERR_RETURN (merlin16_refclk_set(&core_copy.access, init_config->interface.ref_clock)); 1224 1225 /* 1226 * In 28nm TSCE code the lane map programming was done in core_init_pass2. 1227 * Now it is moved to pass1 because merlin16 requires that PMD lane address 1228 * map be done before loading the uCode. Notice that before programming the 1229 * PMD lane address map, lane and lane DP has to be reset by calling 1230 * temod16_pmd_x4_reset(). 1231 */ 1232 PHYMOD_IF_ERR_RETURN 1233 (merlin16_core_lane_map_set(&core_copy, &init_config->lane_map)); 1234 1235 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 1236 if (_merlin16_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader)) { 1237 PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask)); 1238 PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT); 1239 } 1240 1241 } 1242 1243 PHYMOD_IF_ERR_RETURN 1244 (merlin16_pmd_ln_h_rstb_pkill_override(&phy_access_copy.access, 0x1)); 1245 PHYMOD_IF_ERR_RETURN 1246 (merlin16_uc_reset(&phy_access_copy.access, 0)); 1247 PHYMOD_IF_ERR_RETURN 1248 (merlin16_wait_uc_active(&phy_access_copy.access)); 1249 1250 /* Initialize software information table for the micro */ 1251 PHYMOD_IF_ERR_RETURN 1252 (merlin16_init_merlin16_info(&core_copy.access)); 1253 1254 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 1255 if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 1256 PHYMOD_IF_ERR_RETURN 1257 (merlin16_start_ucode_crc_calc(&core_copy.access, merlin16_ucode_len)); 1258 } 1259 } 1260 1261 return (PHYMOD_E_NONE); 1262 } 1263 1264 STATIC 1265 int _merlin16_core_init_pass2(const phymod_core_access_t* core, 1266 const phymod_core_init_config_t* init_config, 1267 const phymod_core_status_t* core_status) 1268 { 1269 phymod_phy_access_t phy_access, phy_access_copy; 1270 phymod_core_access_t core_copy; 1271 phymod_firmware_core_config_t firmware_core_config_tmp; 1272 1273 MERLIN16_CORE_TO_PHY_ACCESS(&phy_access, core); 1274 PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy)); 1275 core_copy.access.lane_mask = 0x1; 1276 1277 phy_access_copy = phy_access; 1278 phy_access_copy.access = core->access; 1279 phy_access_copy.access.lane_mask = 0x1; 1280 phy_access_copy.type = core->type; 1281 1282 if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) { 1283 if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) { 1284 PHYMOD_IF_ERR_RETURN 1285 (merlin16_check_ucode_crc(&core_copy.access, merlin16_ucode_crc, 250)); 1286 } 1287 } 1288 1289 PHYMOD_IF_ERR_RETURN( 1290 merlin16_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0)); 1291 1292 phy_access_copy.access.lane_mask = 0x1; 1293 1294 PHYMOD_IF_ERR_RETURN 1295 (merlin16_core_soft_reset_release(&core_copy.access, 0)); 1296 1297 /* After loading the PMD uCode, PLL needs to be configured. */ 1298 PHYMOD_IF_ERR_RETURN 1299 (merlin16_configure_pll_refclk_div(&phy_access_copy.access, MERLIN16_PLL_REFCLK_156P25MHZ, 1300 MERLIN16_PLL_DIV_66)); 1301 1302 PHYMOD_IF_ERR_RETURN 1303 (merlin16_phy_firmware_core_config_get(&phy_access_copy, &firmware_core_config_tmp)); 1304 firmware_core_config_tmp.CoreConfigFromPCS = 0; 1305 1306 PHYMOD_IF_ERR_RETURN 1307 (merlin16_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config_tmp)); 1308 1309 /* 1310 * After programming the PMD PLL, we need to release the core reset and lane reset. 1311 * Core reset is done below, and lane reset is done in tsce16_phy_init() by calling 1312 * temod16_pmd_x4_reset(). 1313 */ 1314 PHYMOD_IF_ERR_RETURN 1315 (merlin16_core_soft_reset_release(&core_copy.access, 1)); 1316 1317 return PHYMOD_E_NONE; 1318 } 1319 1320 /*Core Initialization*/ 1321 int merlin16_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status) 1322 { 1323 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 1324 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 1325 PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 1326 PHYMOD_IF_ERR_RETURN 1327 (_merlin16_core_init_pass1(core, init_config, core_status)); 1328 1329 if (PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 1330 return PHYMOD_E_NONE; 1331 } 1332 } 1333 1334 if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) && 1335 !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) || 1336 PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) { 1337 PHYMOD_IF_ERR_RETURN 1338 (_merlin16_core_init_pass2(core, init_config, core_status)); 1339 } 1340 1341 return PHYMOD_E_NONE; 1342 1343 } 1344 1345 1346 /*Phy Initialization*/ 1347 int merlin16_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config) 1348 { 1349 const phymod_access_t *pm_acc = &phy->access; 1350 phymod_phy_access_t pm_phy_copy; 1351 int start_lane, num_lane, i; 1352 phymod_polarity_t tmp_pol; 1353 #ifdef PHYMOD_DIAG 1354 PHYMOD_VDBG(DBG_CFG, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32"\n", 1355 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask)); 1356 #endif 1357 PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol)); 1358 PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy)); 1359 1360 /* next program the tx fir taps and driver current based on the input */ 1361 PHYMOD_IF_ERR_RETURN 1362 (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane)); 1363 1364 /* per lane based reset release */ 1365 for (i = 0; i < num_lane; i++) { 1366 PHYMOD_IF_ERR_RETURN 1367 (merlin16_lane_hard_soft_reset_release(&pm_phy_copy.access, 0)); 1368 PHYMOD_IF_ERR_RETURN 1369 (merlin16_lane_hard_soft_reset_release(&pm_phy_copy.access, 1)); 1370 1371 PHYMOD_IF_ERR_RETURN 1372 (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 0)); 1373 PHYMOD_IF_ERR_RETURN 1374 (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1)); 1375 } 1376 1377 /* program the rx/tx polarity */ 1378 for (i = 0; i < num_lane; i++) { 1379 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1380 continue; 1381 } 1382 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1383 tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) >> i & 0x1; 1384 tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) >> i & 0x1; 1385 PHYMOD_IF_ERR_RETURN 1386 (merlin16_phy_polarity_set(&pm_phy_copy, &tmp_pol)); 1387 } 1388 1389 for (i = 0; i < num_lane; i++) { 1390 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1391 continue; 1392 } 1393 pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1394 PHYMOD_IF_ERR_RETURN 1395 (merlin16_phy_tx_set(&pm_phy_copy, &init_config->tx[i])); 1396 } 1397 1398 /* next check if pcs-bypass mode */ 1399 if (PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) { 1400 PHYMOD_IF_ERR_RETURN 1401 (merlin16_pmd_tx_disable_pin_dis_set(&phy->access, 1)); 1402 } 1403 1404 return PHYMOD_E_NONE; 1405 } 1406 1407 1408 /*Set\get loopback mode*/ 1409 int merlin16_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable) 1410 { 1411 int start_lane, num_lane, i; 1412 phymod_phy_access_t phy_copy; 1413 const phymod_access_t *pm_acc; 1414 1415 pm_acc = &phy->access; 1416 #ifdef PHYMOD_DIAG 1417 PHYMOD_VDBG(DBG_LPK, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" lpbk=%0d(%s) en=%0d\n", 1418 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, loopback, 1419 phymod_loopback_mode_t_mapping[loopback].key, enable)); 1420 #endif 1421 PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy)); 1422 1423 /* next figure out the lane num and start_lane based on the input */ 1424 PHYMOD_IF_ERR_RETURN 1425 (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane)); 1426 1427 switch (loopback) { 1428 case phymodLoopbackGlobal: 1429 break; 1430 case phymodLoopbackGlobalPMD: 1431 for (i = 0; i < num_lane; i++) { 1432 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1433 continue; 1434 } 1435 phy_copy.access.lane_mask = 0x1 << (i + start_lane); 1436 PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_set(&phy->access, enable)); 1437 } 1438 break; 1439 case phymodLoopbackRemotePMD: 1440 for (i = 0; i < num_lane; i++) { 1441 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) { 1442 continue; 1443 } 1444 PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk(&phy->access, enable)); 1445 } 1446 break; 1447 case phymodLoopbackRemotePCS: 1448 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 1449 (_PHYMOD_MSG("PCS Remote LoopBack not supported"))); 1450 break; 1451 default: 1452 break; 1453 } 1454 1455 return PHYMOD_E_NONE; 1456 } 1457 1458 int merlin16_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable) 1459 { 1460 *enable = 0; 1461 1462 switch (loopback) { 1463 case phymodLoopbackGlobal : 1464 break; 1465 case phymodLoopbackGlobalPMD : 1466 PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&phy->access, enable)); 1467 break; 1468 case phymodLoopbackRemotePMD : 1469 PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk_get(&phy->access, enable)); 1470 break; 1471 case phymodLoopbackRemotePCS : 1472 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 1473 (_PHYMOD_MSG("PCS Remote LoopBack not supported"))); 1474 break; 1475 default : 1476 break; 1477 } 1478 return PHYMOD_E_NONE; 1479 } 1480 1481 1482 /*Get rx pmd locked indication*/ 1483 int merlin16_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_pmd_locked) 1484 { 1485 uint8_t rx_lock; 1486 PHYMOD_IF_ERR_RETURN(merlin16_pmd_lock_status(&phy->access, &rx_lock)); 1487 *rx_pmd_locked = (uint32_t)rx_lock; 1488 1489 return PHYMOD_E_NONE; 1490 } 1491 1492 /*Get link up status indication*/ 1493 int merlin16_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status) 1494 { 1495 unsigned char rx_lock; 1496 PHYMOD_IF_ERR_RETURN(merlin16_pmd_lock_status(&phy->access, &rx_lock)); 1497 *link_status = (uint32_t ) rx_lock; 1498 1499 return PHYMOD_E_NONE; 1500 } 1501 1502 /*Read phymod register*/ 1503 int merlin16_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val) 1504 { 1505 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_read(&phy->access, reg_addr, val)); 1506 return PHYMOD_E_NONE; 1507 } 1508 1509 1510 /*Write phymod register*/ 1511 int merlin16_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val) 1512 { 1513 PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_write(&phy->access, reg_addr, val)); 1514 return PHYMOD_E_NONE; 1515 } 1516