merlin16_pcieg3_config.c (28381B)
1 /*********************************************************************************** 2 *********************************************************************************** 3 * File Name : merlin16_pcieg3_config.c * 4 * Created On : 03 Nov 2015 * 5 * Created By : Brent Roberts * 6 * Description : APIs for Serdes IPs * 7 * Revision : * 8 * * 9 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 10 * 11 * Copyright 2007-2019 Broadcom Inc. All rights reserved. * 12 * No portions of this material may be reproduced in any form without * 13 * the written permission of: * 14 * Broadcom Corporation * 15 * 5300 California Avenue * 16 * Irvine, CA 92617 * 17 * * 18 * All information contained in this document is Broadcom Corporation * 19 * company private proprietary, and trade secret. * 20 */ 21 22 /** @file merlin16_pcieg3_config.c 23 * Implementation of API config functions 24 */ 25 26 #include "merlin16_pcieg3_config.h" 27 #include "merlin16_pcieg3_access.h" 28 #include "merlin16_pcieg3_common.h" 29 #include "merlin16_pcieg3_functions.h" 30 #include "merlin16_pcieg3_internal.h" 31 #include "merlin16_pcieg3_internal_error.h" 32 #include "merlin16_pcieg3_select_defns.h" 33 #include "merlin16_pcieg3_enum.h" 34 #include "merlin16_pcieg3_dependencies.h" 35 36 /* If SERDES_EVAL is defined, then is_ate_log_enabled() is queried to *\ 37 \* know whether to log ATE. merlin16_pcieg3_access.h provides that function. */ 38 39 /*******************************/ 40 /* Stop/Resume RX Adaptation */ 41 /*******************************/ 42 43 err_code_t merlin16_pcieg3_stop_rx_adaptation(srds_access_t *sa__, uint8_t enable) { 44 45 if (enable) { 46 return(merlin16_pcieg3_pmd_uc_control(sa__, CMD_UC_CTRL_STOP_GRACEFULLY,GRACEFUL_STOP_TIME)); 47 } 48 else { 49 return(merlin16_pcieg3_pmd_uc_control(sa__, CMD_UC_CTRL_RESUME,50)); 50 } 51 } 52 53 err_code_t merlin16_pcieg3_request_stop_rx_adaptation(srds_access_t *sa__) { 54 55 return(merlin16_pcieg3_pmd_uc_control_return_immediate(sa__, CMD_UC_CTRL_STOP_GRACEFULLY)); 56 } 57 58 /**********************/ 59 /* uCode CRC Verify */ 60 /**********************/ 61 62 err_code_t merlin16_pcieg3_ucode_crc_verify(srds_access_t *sa__, uint16_t ucode_len,uint16_t expected_crc_value) { 63 uint16_t calc_crc; 64 EFUN(merlin16_pcieg3_pmd_uc_cmd_with_data(sa__, CMD_CALC_CRC,0,ucode_len,200)); 65 66 ESTM(calc_crc = rd_uc_dsc_data()); 67 if(calc_crc != expected_crc_value) { 68 EFUN_PRINTF(("Microcode CRC did not match expected=%04x : calculated=%04x\n",expected_crc_value, calc_crc)); 69 return(_error(ERR_CODE_UC_CRC_NOT_MATCH)); 70 } else { 71 EFUN_PRINTF(("Microcode CRC Matched expected=0x%04X\n",expected_crc_value)); 72 } 73 74 return(ERR_CODE_NONE); 75 } 76 77 err_code_t merlin16_pcieg3_start_ucode_crc_calc(srds_access_t *sa__, uint16_t ucode_len) { 78 EFUN(merlin16_pcieg3_pmd_uc_cmd_with_data_return_immediate(sa__, CMD_CALC_CRC, 0, ucode_len)); /* Invoke Calculate CRC command and return control immediately */ 79 return(ERR_CODE_NONE); 80 } 81 82 err_code_t merlin16_pcieg3_check_ucode_crc(srds_access_t *sa__, uint16_t expected_crc_value, uint32_t timeout_ms) { 83 uint16_t calc_crc; 84 err_code_t err_code; 85 86 err_code = merlin16_pcieg3_INTERNAL_poll_uc_dsc_ready_for_cmd_equals_1(sa__, timeout_ms, CMD_CALC_CRC); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate merlin16_pcieg3 ready for command */ 87 if (err_code) { 88 EFUN_PRINTF(("ERROR : DSC ready for command timed out. Previous uC command not finished yet\n")); 89 return (err_code); 90 } 91 ESTM(calc_crc = rd_uc_dsc_data()); 92 if(calc_crc != expected_crc_value) { 93 EFUN_PRINTF(("UC CRC did not match expected=%04x : calculated=%04x\n",expected_crc_value, calc_crc)); 94 return(_error(ERR_CODE_UC_CRC_NOT_MATCH)); 95 } 96 97 return(ERR_CODE_NONE); 98 } 99 100 101 /*--------------------------------------------*/ 102 /* APIs to Enable or Disable datapath reset */ 103 /*--------------------------------------------*/ 104 105 err_code_t merlin16_pcieg3_tx_dp_reset(srds_access_t *sa__, uint8_t enable) { 106 if (enable) { 107 EFUN(wr_tx_ln_dp_s_rstb(0x0)); 108 } else { 109 EFUN(wr_tx_ln_dp_s_rstb(0x1)); 110 EFUN(wr_tx_uc_ack_lane_dp_reset(0x1)); 111 EFUN(wr_tx_uc_ack_lane_cfg_done(0x1)); 112 } 113 return ERR_CODE_NONE; 114 } 115 116 err_code_t merlin16_pcieg3_rx_dp_reset(srds_access_t *sa__, uint8_t enable) { 117 if (enable) { 118 EFUN(wr_rx_ln_dp_s_rstb(0x0)); 119 } else { 120 EFUN(wr_rx_ln_dp_s_rstb(0x1)); 121 } 122 return ERR_CODE_NONE; 123 } 124 125 err_code_t merlin16_pcieg3_core_dp_reset(srds_access_t *sa__, uint8_t enable){ 126 if (enable) { 127 EFUN(wrc_core_dp_s_rstb(0x0)); 128 } else { 129 EFUN(wrc_core_dp_s_rstb(0x1)); 130 } 131 return ERR_CODE_NONE; 132 } 133 134 /********************************/ 135 /* Loading ucode through PRAM */ 136 /********************************/ 137 138 err_code_t merlin16_pcieg3_ucode_pram_load(srds_access_t *sa__, char const * ucode_image, uint16_t ucode_len) { 139 uint16_t ucode_len_remainder = ((ucode_len + 3) & 0xFFFC) - ucode_len; 140 141 if(!ucode_image) { 142 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 143 } 144 145 if (ucode_len > UCODE_MAX_SIZE) { /* uCode size should be less than UCODE_MAX_SIZE */ 146 return (_error(ERR_CODE_INVALID_UCODE_LEN)); 147 } 148 149 EFUN(wrc_micro_master_clk_en(0x1)); /* Enable clock to microcontroller subsystem */ 150 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 151 EFUN(wrc_micro_master_rstb(0x0)); /* Assert reset to microcontroller sybsystem - Toggling reset*/ 152 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 153 154 EFUN(wrc_micro_ra_init(0x1)); /* Set initialization command to initialize code RAM */ 155 EFUN(merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(sa__, 250));/* Poll for micro_ra_initdone = 1 to indicate initialization done */ 156 EFUN(wrc_micro_ra_init(0x0)); /* Clear initialization command */ 157 158 159 EFUN(wrc_micro_pramif_ahb_wraddr_msw(0x0000)); 160 EFUN(wrc_micro_pramif_ahb_wraddr_lsw(0x0000)); 161 EFUN(wrc_micro_pram_if_rstb(1)); 162 EFUN(wrc_micro_pramif_en(1)); 163 164 /* Wait 8 pram clocks */ 165 EFUN(USR_DELAY_US(1)); 166 167 /* write ucode into pram */ 168 while (ucode_len > 0) { 169 EFUN(merlin16_pcieg3_pmd_wr_pram(sa__, *ucode_image)); 170 --ucode_len; 171 ++ucode_image; 172 } 173 174 /* Pad to 32 bits */ 175 while (ucode_len_remainder > 0) { 176 EFUN(merlin16_pcieg3_pmd_wr_pram(sa__, 0)); 177 --ucode_len_remainder; 178 } 179 180 /* Wait 8 pram clocks */ 181 EFUN(USR_DELAY_US(1)); 182 183 184 EFUN(wrc_micro_pramif_en(0)); 185 EFUN(wrc_micro_core_clk_en(1)); 186 /* EFUN(wrc_micro_core_rstb(1)); */ 187 return(ERR_CODE_NONE); 188 } 189 190 191 /************************/ 192 /* Serdes API Version */ 193 /************************/ 194 195 err_code_t merlin16_pcieg3_version(uint32_t *api_version) { 196 197 if(!api_version) { 198 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 199 } 200 *api_version = 0xA10700; 201 return (ERR_CODE_NONE); 202 } 203 204 /*****************/ 205 /* PMD_RX_LOCK */ 206 /*****************/ 207 208 err_code_t merlin16_pcieg3_pmd_lock_status(srds_access_t *sa__, uint8_t *pmd_rx_lock) { 209 if(!pmd_rx_lock) { 210 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 211 } 212 ESTM(*pmd_rx_lock = rd_pmd_rx_lock()); 213 return (ERR_CODE_NONE); 214 } 215 216 /**********************************/ 217 /* Serdes TX disable/RX Restart */ 218 /**********************************/ 219 220 err_code_t merlin16_pcieg3_tx_disable(srds_access_t *sa__, uint8_t enable) { 221 222 if (enable) { 223 EFUN(wr_sdk_tx_disable(0x1)); 224 } 225 else { 226 EFUN(wr_sdk_tx_disable(0x0)); 227 } 228 return(ERR_CODE_NONE); 229 } 230 231 232 /******************************************************/ 233 /* Single function to set/get all RX AFE parameters */ 234 /******************************************************/ 235 236 err_code_t merlin16_pcieg3_write_rx_afe(srds_access_t *sa__, enum srds_rx_afe_settings_enum param, int8_t val) { 237 /* Assumes the micro is not actively tuning */ 238 239 switch(param) { 240 case RX_AFE_PF: 241 return(merlin16_pcieg3_INTERNAL_set_rx_pf_main(sa__, val)); 242 243 case RX_AFE_PF2: 244 return(merlin16_pcieg3_INTERNAL_set_rx_pf2(sa__, val)); 245 246 case RX_AFE_VGA: 247 return(merlin16_pcieg3_INTERNAL_set_rx_vga(sa__, val)); 248 249 case RX_AFE_DFE1: 250 return(merlin16_pcieg3_INTERNAL_set_rx_dfe1(sa__, val)); 251 252 case RX_AFE_DFE2: 253 return(merlin16_pcieg3_INTERNAL_set_rx_dfe2(sa__, val)); 254 255 case RX_AFE_DFE3: 256 return(merlin16_pcieg3_INTERNAL_set_rx_dfe3(sa__, val)); 257 258 case RX_AFE_DFE4: 259 return(merlin16_pcieg3_INTERNAL_set_rx_dfe4(sa__, val)); 260 261 case RX_AFE_DFE5: 262 return(merlin16_pcieg3_INTERNAL_set_rx_dfe5(sa__, val)); 263 264 default: 265 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 266 } 267 } 268 269 270 err_code_t merlin16_pcieg3_read_rx_afe(srds_access_t *sa__, enum srds_rx_afe_settings_enum param, int8_t *val) { 271 /* Assumes the micro is not actively tuning */ 272 if(!val) { 273 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 274 } 275 276 switch(param) { 277 case RX_AFE_PF: 278 EFUN(merlin16_pcieg3_INTERNAL_get_rx_pf_main(sa__, val)); 279 break; 280 case RX_AFE_PF2: 281 EFUN(merlin16_pcieg3_INTERNAL_get_rx_pf2(sa__, val)); 282 break; 283 case RX_AFE_VGA: 284 EFUN(merlin16_pcieg3_INTERNAL_get_rx_vga(sa__, val)); 285 break; 286 287 case RX_AFE_DFE1: 288 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe1(sa__, val)); 289 break; 290 case RX_AFE_DFE2: 291 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe2(sa__, val)); 292 break; 293 case RX_AFE_DFE3: 294 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe3(sa__, val)); 295 break; 296 case RX_AFE_DFE4: 297 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe4(sa__, val)); 298 break; 299 case RX_AFE_DFE5: 300 EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe5(sa__, val)); 301 break; 302 default: 303 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 304 } 305 306 return(ERR_CODE_NONE); 307 } 308 309 310 /**********************************************/ 311 /* Loopback and Ultra-Low Latency Functions */ 312 /**********************************************/ 313 314 315 316 /********************************/ 317 /* TX_PI Fixed Frequency Mode */ 318 /********************************/ 319 320 /* TX_PI Frequency Override (Fixed Frequency Mode) */ 321 err_code_t merlin16_pcieg3_tx_pi_freq_override(srds_access_t *sa__, uint8_t enable, int16_t freq_override_val) { 322 if (enable) { 323 EFUN(wr_tx_pi_en(0x1)); /* TX_PI enable : 0 = disabled, 1 = enabled */ 324 EFUN(wr_tx_pi_freq_override_en(0x1)); /* Fixed freq mode enable: 0 = disabled, 1 = enabled */ 325 EFUN(wr_tx_pi_freq_override_val(freq_override_val)); /* Fixed Freq Override Value (+/-8192) */ 326 } 327 else { 328 EFUN(wr_tx_pi_freq_override_val(0)); /* Fixed Freq Override Value to 0 */ 329 EFUN(wr_tx_pi_freq_override_en(0x0)); /* Fixed freq mode enable: 0 = disabled, 1 = enabled */ 330 EFUN(wr_tx_pi_en(0x0)); /* TX_PI enable : 0 = disabled, 1 = enabled */ 331 } 332 return (ERR_CODE_NONE); 333 } 334 /*********************************/ 335 /* uc_active and uc_reset APIs */ 336 /*********************************/ 337 338 /* Enable or Disable the uC reset */ 339 err_code_t merlin16_pcieg3_uc_reset(srds_access_t *sa__, uint8_t enable) { 340 if (enable) { 341 /* Assert micro reset and reset all micro registers (all non-status registers written to default value) */ 342 EFUN(wrc_micro_core_clk_en(0x0)); /* Disable clock to M0 core */ 343 344 EFUN(wrc_micro_master_clk_en(0x0)); /* Disable clock to microcontroller subsystem */ 345 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD200, 0x0000)); 346 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD201, 0x0000)); 347 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD202, 0x0000)); 348 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD204, 0x0000)); 349 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD205, 0x0000)); 350 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD206, 0x0000)); 351 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD207, 0x0000)); 352 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD208, 0x0000)); 353 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD209, 0x0000)); 354 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20A, 0x0000)); 355 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20B, 0x0000)); 356 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20C, 0x0000)); 357 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20D, 0x0000)); 358 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20E, 0x0000)); 359 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD211, 0x0000)); 360 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD212, 0x0000)); 361 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD213, 0x0000)); 362 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD214, 0x0000)); 363 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD215, 0x0000)); 364 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD216, 0x0007)); 365 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD217, 0x0000)); 366 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD218, 0x0000)); 367 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD219, 0x0000)); 368 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD21A, 0x0000)); 369 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD21B, 0x0000)); 370 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD220, 0x0000)); 371 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD221, 0x0000)); 372 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD224, 0x0000)); 373 374 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD225, 0x8301)); 375 376 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD226, 0x0000)); 377 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD228, 0x0101)); 378 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD229, 0x0000)); 379 EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD22A, 0x0000)); 380 } 381 else { 382 /* De-assert micro reset - Start executing code */ 383 EFUN(wrc_micro_master_clk_en (0x1)); /* Enable clock to microcontroller subsystem */ 384 EFUN(wrc_micro_master_rstb (0x1)); /* De-assert reset to microcontroller sybsystem */ 385 EFUN(wrc_micro_ra_init (0x2)); /* Write command for data RAM initialization */ 386 EFUN(merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll status of data RAM initialization */ 387 EFUN(wrc_micro_ra_init (0x0)); /* Clear command for data RAM initialization */ 388 EFUN(wrc_micro_core_clk_en (0x1)); /* Enable clock to M0 core */ 389 EFUN(wrc_micro_core_rstb (0x1)); 390 } 391 return (ERR_CODE_NONE); 392 } 393 394 395 396 err_code_t merlin16_pcieg3_init_merlin16_pcieg3_info(srds_access_t *sa__) { 397 merlin16_pcieg3_info_t * const merlin16_pcieg3_info_ptr = merlin16_pcieg3_INTERNAL_get_merlin16_pcieg3_info_ptr(); 398 uint32_t info_table[INFO_TABLE_END / sizeof(uint32_t)]; 399 uint32_t info_table_signature; 400 uint8_t info_table_version; 401 402 ENULL_MEMSET(merlin16_pcieg3_info_ptr, 0, sizeof(merlin16_pcieg3_info_t)); 403 404 if (merlin16_pcieg3_info_ptr == 0) { 405 EFUN_PRINTF(("ERROR: Info table pointer is null.\n")); 406 return (_error(ERR_CODE_INFO_TABLE_ERROR)); 407 } 408 409 EFUN(merlin16_pcieg3_rdblk_uc_prog_ram(sa__, (uint8_t *)info_table, INFO_TABLE_RAM_BASE, INFO_TABLE_END)); 410 411 info_table_signature = info_table[INFO_TABLE_OFFS_SIGNATURE / sizeof(uint32_t)]; 412 info_table_version = (uint8_t)(info_table_signature >> 24); 413 if (((info_table_signature & 0x00FFFFFF) != 0x666E49) 414 || (!( ((info_table_version >= 0x32) && (info_table_version <= 0x39)) 415 || ((info_table_version >= 0x41) && (info_table_version <= 0x5A))))) { 416 return (_error(ERR_CODE_INFO_TABLE_ERROR)); 417 } 418 419 merlin16_pcieg3_info_ptr->lane_count = info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] & 0xFF; 420 merlin16_pcieg3_info_ptr->trace_memory_descending_writes = ((info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] & 0x1000000) != 0); 421 422 merlin16_pcieg3_info_ptr->core_var_ram_size = (info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] >> 8) & 0xFF; 423 424 merlin16_pcieg3_info_ptr->lane_var_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] >> 16) & 0xFFFF; 425 426 merlin16_pcieg3_info_ptr->diag_mem_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] & 0xFFFF) / merlin16_pcieg3_info_ptr->lane_count; 427 merlin16_pcieg3_info_ptr->trace_mem_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] & 0xFFFF); 428 429 merlin16_pcieg3_info_ptr->diag_mem_ram_base = info_table[INFO_TABLE_OFFS_TRACE_MEM_PTR / sizeof(uint32_t)]; 430 merlin16_pcieg3_info_ptr->trace_mem_ram_base = merlin16_pcieg3_info_ptr->diag_mem_ram_base; 431 432 merlin16_pcieg3_info_ptr->core_var_ram_base = info_table[INFO_TABLE_OFFS_CORE_MEM_PTR / sizeof(uint32_t)]; 433 434 merlin16_pcieg3_info_ptr->micro_var_ram_base = info_table[INFO_TABLE_OFFS_MICRO_MEM_PTR / sizeof(uint32_t)]; 435 merlin16_pcieg3_info_ptr->micro_var_ram_size = (info_table[INFO_TABLE_OFFS_OTHER_SIZE_2 / sizeof(uint32_t)] >> 4) & 0xFF; 436 437 merlin16_pcieg3_info_ptr->lane_var_ram_base = info_table[INFO_TABLE_OFFS_LANE_MEM_PTR / sizeof(uint32_t)]; 438 439 440 441 if (info_table_version < 0x34) { 442 merlin16_pcieg3_info_ptr->micro_count = 1; 443 } else { 444 merlin16_pcieg3_info_ptr->micro_count = info_table[INFO_TABLE_OFFS_OTHER_SIZE_2 / sizeof(uint32_t)] & 0xF; 445 } 446 merlin16_pcieg3_info_ptr->grp_ram_size = 0; 447 merlin16_pcieg3_info_ptr->signature = SRDS_INFO_SIGNATURE; 448 return (ERR_CODE_NONE); 449 } 450 451 452 /***********************************************/ 453 /* Microcode Load into Program RAM Functions */ 454 /***********************************************/ 455 456 /* uCode Load through Register (MDIO) Interface [Return Val = Error_Code (0 = PASS)] */ 457 err_code_t merlin16_pcieg3_ucode_mdio_load(srds_access_t *sa__, uint8_t *ucode_image, uint16_t ucode_len) { 458 uint16_t ucode_len_padded, count = 0; 459 uint16_t wrdata_lsw; 460 uint8_t wrdata_lsb; 461 462 if(!ucode_image) { 463 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 464 } 465 466 if (ucode_len > UCODE_MAX_SIZE) { /* uCode size should be less than UCODE_MAX_SIZE */ 467 return (_error(ERR_CODE_INVALID_UCODE_LEN)); 468 } 469 470 EFUN(wrc_micro_master_clk_en(0x1)); /* Enable clock to microcontroller subsystem */ 471 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 472 EFUN(wrc_micro_master_rstb(0x0)); /* Assert reset to microcontroller sybsystem - Toggling reset*/ 473 EFUN(wrc_micro_master_rstb(0x1)); /* De-assert reset to microcontroller sybsystem */ 474 475 EFUN(wrc_micro_ra_init(0x1)); /* Set initialization command to initialize code RAM */ 476 EFUN(merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll for micro_ra_initdone = 1 to indicate initialization done */ 477 EFUN(wrc_micro_ra_init(0x0)); /* Clear initialization command */ 478 479 ucode_len_padded = ((ucode_len + 3) & 0xFFFC); /* Aligning ucode size to 4-byte boundary */ 480 481 /* Code to Load microcode */ 482 EFUN(wrc_micro_autoinc_wraddr_en(0x1)); /* To auto increment RAM write address */ 483 EFUN(wrc_micro_ra_wrdatasize(0x1)); /* Select 16bit transfers */ 484 EFUN(wrc_micro_ra_wraddr_msw(0x0)); /* Upper 16bits of start address of Program RAM where the ucode is to be loaded */ 485 EFUN(wrc_micro_ra_wraddr_lsw(0x0)); /* Lower 16bits of start address of Program RAM where the ucode is to be loaded */ 486 487 do { /* ucode_image loaded 16bits at a time */ 488 wrdata_lsb = (count < ucode_len) ? ucode_image[count] : 0x0; /* wrdata_lsb read from ucode_image; zero padded to 4byte boundary */ 489 count++; 490 wrdata_lsw = (count < ucode_len) ? ucode_image[count] : 0x0; /* wrdata_msb read from ucode_image; zero padded to 4byte boundary */ 491 count++; 492 wrdata_lsw = ((wrdata_lsw << 8) | wrdata_lsb); /* 16bit wrdata_lsw formed from 8bit msb and lsb values read from ucode_image */ 493 EFUN(wrc_micro_ra_wrdata_lsw(wrdata_lsw)); /* Program RAM lower 16bits write data */ 494 } while (count < ucode_len_padded); /* Loop repeated till entire image loaded (upto the 4byte boundary) */ 495 496 EFUN(wrc_micro_ra_wrdatasize(0x2)); /* Select 32bit transfers as default */ 497 EFUN(wrc_micro_core_clk_en(0x1)); /* Enable clock to M0 core */ 498 /* EFUN(wrc_micro_core_rstb(0x1)); */ /* De-assert reset to micro to start executing microcode */ 499 return (ERR_CODE_NONE); /* NO Errors while loading microcode (uCode Load PASS) */ 500 } 501 502 503 /* Read-back uCode from Program RAM and verify against ucode_image [Return Val = Error_Code (0 = PASS)] */ 504 err_code_t merlin16_pcieg3_ucode_load_verify(srds_access_t *sa__, uint8_t *ucode_image, uint16_t ucode_len) { 505 506 uint16_t ucode_len_padded, count = 0; 507 uint16_t rddata_lsw; 508 uint16_t data_lsw; 509 uint8_t rddata_lsb; 510 511 if(!ucode_image) { 512 return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT)); 513 } 514 515 ucode_len_padded = ((ucode_len + 3) & 0xFFFC); /* Aligning ucode size to 4-byte boundary */ 516 517 if (ucode_len_padded > UCODE_MAX_SIZE) { /* uCode size should be less than UCODE_MAX_SIZE */ 518 return (_error(ERR_CODE_INVALID_UCODE_LEN)); 519 } 520 521 EFUN(wrc_micro_autoinc_rdaddr_en(0x1)); /* To auto increment RAM read address */ 522 EFUN(wrc_micro_ra_rddatasize(0x1)); /* Select 16bit transfers */ 523 EFUN(wrc_micro_ra_rdaddr_msw(0x0)); /* Upper 16bits of start address of Program RAM from where to read ucode */ 524 EFUN(wrc_micro_ra_rdaddr_lsw(0x0)); /* Lower 16bits of start address of Program RAM from where to read ucode */ 525 526 do { /* ucode_image read 16bits at a time */ 527 rddata_lsb = (count < ucode_len) ? ucode_image[count] : 0x0; /* rddata_lsb read from ucode_image; zero padded to 4byte boundary */ 528 count++; 529 rddata_lsw = (count < ucode_len) ? ucode_image[count] : 0x0; /* rddata_msb read from ucode_image; zero padded to 4byte boundary */ 530 count++; 531 rddata_lsw = ((rddata_lsw << 8) | rddata_lsb); /* 16bit rddata_lsw formed from 8bit msb and lsb values read from ucode_image */ 532 /* Compare Program RAM ucode to ucode_image (Read to micro_ra_rddata_lsw reg auto-increments the ram_address) */ 533 ESTM(data_lsw = rdc_micro_ra_rddata_lsw()); 534 if (data_lsw != rddata_lsw) { 535 EFUN_PRINTF(("Ucode_Load_Verify_FAIL: Addr = 0x%x: Read_data = 0x%x : Expected_data = 0x%x \n",(count-2),data_lsw,rddata_lsw)); 536 return (_error(ERR_CODE_UCODE_VERIFY_FAIL)); /* Verify uCode FAIL */ 537 } 538 539 } while (count < ucode_len_padded); /* Loop repeated till entire image loaded (upto the 4byte boundary) */ 540 541 EFUN(wrc_micro_ra_rddatasize(0x2)); /* Select 32bit transfers ad default */ 542 return (ERR_CODE_NONE); /* Verify uCode PASS */ 543 } 544 545 /******************************************************************/ 546 /* APIs to Align TX clocks */ 547 /******************************************************************/ 548 err_code_t merlin16_pcieg3_tx_clock_align(srds_access_t *sa__, int num_lanes, int enable) { 549 int current_lane, lane; 550 551 ESTM(current_lane = merlin16_pcieg3_get_lane(sa__)); 552 553 for(lane = 0;lane<num_lanes;++lane) { 554 EFUN(merlin16_pcieg3_set_lane(sa__,lane)); 555 if(enable) { 556 if(lane == current_lane) { /* Current Lane should be the master lane */ 557 EFUN(wr_ams_tx_sel_txmaster(1)); /* Select one lane as txmaster. For all other lanes, this should be 0. */ 558 EFUN(wr_ams_tx_pd_phasedet(0)); /* 1 - TCA PD powerdown, 0 - enable PD (enable only for the slave lanes) */ 559 } else { 560 /* Initial TX lane clock phase alignment. Program following registers only for slave lanes, master lane registers should not be programmed (can be kept in default values). */ 561 EFUN(wr_tx_pi_pd_bypass_vco(1)); /* for quick phase lock time */ 562 EFUN(wr_tx_pi_pd_bypass_flt(1)); /* for quick phase lock time */ 563 EFUN(wr_tx_pi_ext_pd_sel(0)); /* selects PD path based on tx_pi_repeater_mode_en */ 564 EFUN(wr_tx_pi_repeater_mode_en(1)); /* selects external PD from afe as input to tx_pi */ 565 EFUN(wr_tx_pi_en(1)); /* Enable TX_PI */ 566 EFUN(wr_tx_pi_jitter_filter_en(0)); /* turn off frequency lock for tx_pi as all te tclk clocks are derived from VCO and same frequency */ 567 EFUN(wr_tx_pi_ext_ctrl_en(1)); /* turn on PD path to TX_PI to lock the clocks */ 568 EFUN(USR_DELAY_US(25)); /* wait for the slave lane clocks to lock to the master lane clock */ 569 EFUN(wr_tx_pi_ext_phase_bwsel_integ(3)); /* 0 to 7: higher value means faster lock time */ 570 EFUN(wr_tx_pi_pd_bypass_vco(0)); /* disable filter bypass for more accurate lock */ 571 EFUN(wr_tx_pi_pd_bypass_flt(0)); /* disable filter bypass for more accurate lock */ 572 EFUN(USR_DELAY_US(60)); /* wait for the slave lane clocks to lock to the master lane clock withing 1/16th of UI. */ 573 /* that all TX lane clocks are correct frequency and aligned together within 1/16th of UI. */ 574 } 575 576 } else { 577 if(lane == current_lane) { /* Current Lane should be the master lane */ 578 EFUN(wr_ams_tx_sel_txmaster(0)); /* Select one lane as txmaster. For all other lanes, this should be 0. */ 579 EFUN(wr_ams_tx_pd_phasedet(1)); /* 1 - TCA PD powerdown, 0 - enable PD (enable only for the slave lanes) */ 580 } else { 581 /* Initial TX lane clock phase alignment. Program following registers only for slave lanes, master lane registers should not be programmed (can be kept in default values). */ 582 EFUN(wr_tx_pi_pd_bypass_vco(0)); /* for quick phase lock time */ 583 EFUN(wr_tx_pi_pd_bypass_flt(0)); /* for quick phase lock time */ 584 EFUN(wr_tx_pi_ext_pd_sel(0)); /* selects PD path based on tx_pi_repeater_mode_en */ 585 EFUN(wr_tx_pi_repeater_mode_en(1)); /* selects external PD from afe as input to tx_pi */ 586 EFUN(wr_tx_pi_en(0)); /* Enable TX_PI */ 587 EFUN(wr_tx_pi_jitter_filter_en(0)); /* turn off frequency lock for tx_pi as all te tclk clocks are derived from VCO and same frequency */ 588 EFUN(wr_tx_pi_ext_ctrl_en(0)); /* turn on PD path to TX_PI to lock the clocks */ 589 EFUN(wr_tx_pi_ext_phase_bwsel_integ(0)); /* 0 to 7: higher value means faster lock time */ 590 EFUN(wr_tx_pi_pd_bypass_vco(0)); /* disable filter bypass for more accurate lock */ 591 /* that all TX lane clocks are correct frequency and aligned together within 1/16th of UI. */ 592 } 593 594 } 595 } 596 EFUN(merlin16_pcieg3_set_lane(sa__,current_lane)); /* return lane to previous state */ 597 return(ERR_CODE_NONE); 598 } 599 600 601