fapi::ReturnCode _fapiGetSpyImage(const fapi::Target& i_target, const char * const i_spyId, ecmdDataBufferBase & o_data, const ecmdDataBufferBase & i_imageData) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platGetSpyImage( i_target, i_spyId, o_data, i_imageData ); if (l_rc) { FAPI_ERR("fapiGetSpyImage failed - Target %s, SpyId %s", i_target.toEcmdString(), i_spyId); } if( l_traceit ) { FAPI_SCAN( "TRACE : GETSPYIMAGE : %s : %s %.16llX", i_target.toEcmdString(), i_spyId, o_data.getDoubleWord(0)); } return l_rc; }
fapi::ReturnCode fapiMultiScom ( const fapi::Target& i_target, fapi::MultiScom& io_multiScomObj) { FAPI_DBG (ENTER_MRK "fapiMultiScom - i_target: %s, # input ops: %d", i_target.toEcmdString (), io_multiScomObj.iv_ScomList.size ()); fapi::ReturnCode l_rc; // Call the platform specific implemetation l_rc = platMultiScom (i_target, io_multiScomObj); if (!l_rc.ok ()) { uint32_t l_retCode = l_rc; FAPI_ERR ("fapiMultiScom Failed with RC: 0x%.8X! i_target: %s, " "# input ops: %d, # ops complete: %d", l_retCode, i_target.toEcmdString (), io_multiScomObj.iv_ScomList.size (), io_multiScomObj.iv_NumOfCompletes); } FAPI_DBG (EXIT_MRK "fapiMultiScom - i_target: %s, # input ops: %d, " "#ops complete: %d", i_target.toEcmdString (), io_multiScomObj.iv_ScomList.size (), io_multiScomObj.iv_NumOfCompletes); return l_rc; }
fapi::ReturnCode _fapiPutSpyImage(const fapi::Target& i_target, const spyId_t i_spyId, const ecmdDataBufferBase & i_data, ecmdDataBufferBase & io_imageData) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platPutSpyImage( i_target, i_spyId, i_data, io_imageData ); if (l_rc) { FAPI_ERR("fapiPutSpyImage failed - Target %s, SpyId 0x%.16llX", i_target.toEcmdString(), i_spyId); } if( l_traceit ) { FAPI_SCAN( "TRACE : PUTSPYIMG : %s : %.16llX %.16llX", i_target.toEcmdString(), i_spyId, i_data.getDoubleWord(0)); } return l_rc; }
//------------------------------------------------------------------------------ // function: apply PBCQ/AIB customization via SCOM initfile // parameters: i_target => processor chip target // returns: FAPI_RC_SUCCESS if initfile evaluation is successful, // else error //------------------------------------------------------------------------------ fapi::ReturnCode proc_pcie_config_pbcq( const fapi::Target & i_target) { fapi::ReturnCode rc; std::vector<fapi::Target> targets; // mark function entry FAPI_INF("proc_pcie_config_pbcq: Start"); do { // execute Phase2 SCOM initfile targets.push_back(i_target); FAPI_INF("proc_pcie_config_pbcq: Executing %s on %s", PROC_PCIE_CONFIG_PHASE2_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, targets, PROC_PCIE_CONFIG_PHASE2_IF); if (!rc.ok()) { FAPI_ERR("proc_pcie_config_pbcq: Error from fapiHwpExecInitfile executing %s on %s", PROC_PCIE_CONFIG_PHASE2_IF, i_target.toEcmdString()); break; } } while(0); // mark function exit FAPI_INF("proc_pcie_config_pbcq: End"); return rc; }
//****************************************************************************** // fapiPutScom function //****************************************************************************** fapi::ReturnCode fapiPutScom(const fapi::Target& i_target, const uint64_t i_address, ecmdDataBufferBase & i_data) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platPutScom( i_target, i_address, i_data ); if (l_rc) { FAPI_ERR("fapiPutScom failed - Target %s, Addr %.16llX", i_target.toEcmdString(), i_address); } if( l_traceit ) { FAPI_SCAN( "TRACE : PUTSCOM : %s : %.16llX %.16llX", i_target.toEcmdString(), i_address, i_data.getDoubleWord( 0 ) ); } return l_rc; }
fapi::ReturnCode mss_eff_config_thermal(const fapi::Target & i_target_mba) { fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; FAPI_INF("*** Running mss_eff_config_thermal on %s ***", i_target_mba.toEcmdString()); rc = mss_eff_config_thermal_powercurve(i_target_mba); if (rc) { FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_powercurve", static_cast<uint32_t>(rc)); return rc; } rc = mss_eff_config_thermal_throttles(i_target_mba); if (rc) { FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_throttles", static_cast<uint32_t>(rc)); return rc; } FAPI_INF("*** mss_eff_config_thermal COMPLETE on %s ***", i_target_mba.toEcmdString()); return rc; }
/** * Trace PCBS FSMs across primary and secondary chips * * @param[in] i_target Chip target * @param[in] i_msg String to put out in the trace * * @retval ECMD_SUCCESS * @retval ERROR defined in xml */ fapi::ReturnCode p4rs_pcbs_fsm_trace(const fapi::Target& i_primary_target, const fapi::Target& i_secondary_target, const char * i_msg) { fapi::ReturnCode rc; do { rc = p8_pm_pcbs_fsm_trace_chip (i_primary_target, i_msg); if (rc) { FAPI_ERR("pcbs_fsm_trace_chip failed for Target %s", i_primary_target.toEcmdString()); break; } if ( i_secondary_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_pcbs_fsm_trace_chip (i_secondary_target, i_msg); if (rc) { FAPI_ERR("pcbs_fsm_trace_chip failed for Target %s", i_secondary_target.toEcmdString()); break; } } } while(0); return rc; }
//****************************************************************************** // fapiPutCfamRegister function //****************************************************************************** fapi::ReturnCode fapiPutCfamRegister(const fapi::Target& i_target, const uint32_t i_address, ecmdDataBufferBase & i_data) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platPutCfamRegister( i_target, i_address, i_data ); if (l_rc) { FAPI_ERR("platPutCfamRegister failed - Target %s, Addr %.8X", i_target.toEcmdString(), i_address); } if( l_traceit ) { FAPI_SCAN( "TRACE : PUTCFAMREG : %s : %.8X %.8X", i_target.toEcmdString(), i_address, i_data.getWord(0) ); } return l_rc; }
fapi::ReturnCode fapiGetRing(const fapi::Target& i_target, const scanRingId_t i_address, ecmdDataBufferBase & o_data, const uint32_t i_ringMode) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platGetRing( i_target, i_address, o_data, i_ringMode ); if (l_rc) { FAPI_ERR("fapiGetRing failed - Target %s, Addr 0x%.16llX", i_target.toEcmdString(), i_address); } if( l_traceit ) { FAPI_SCAN( "TRACE : GETRING : %s : %.16llX %.16llX", i_target.toEcmdString(), i_address, o_data.getDoubleWord( 0 ) ); } return l_rc; }
fapi::ReturnCode fapiModifyRing(const fapi::Target& i_target, const scanRingId_t i_address, ecmdDataBufferBase & i_data, const fapi::ChipOpModifyMode i_modifyMode, const uint32_t i_ringMode) { fapi::ReturnCode l_rc; bool l_traceit = platIsScanTraceEnabled(); // call the platform implementation l_rc = platModifyRing( i_target, i_address, i_data, i_modifyMode, i_ringMode ); if (l_rc) { FAPI_ERR("platModifyRing failed - Target %s, Addr 0x%.16llX," "ModifyMode 0x%.8X", i_target.toEcmdString(), i_address, i_modifyMode); } if( l_traceit ) { // get string representation of the modify mode const char * l_pMode = NULL; if (i_modifyMode == fapi::CHIP_OP_MODIFY_MODE_OR) { l_pMode = "OR"; } else if (i_modifyMode == fapi::CHIP_OP_MODIFY_MODE_AND) { l_pMode = "AND"; } else if (i_modifyMode == fapi::CHIP_OP_MODIFY_MODE_XOR) { l_pMode = "XOR"; } else { l_pMode = "?"; } FAPI_SCAN( "TRACE : MODRING : %s : %.16llX %.16llX %s", i_target.toEcmdString(), i_address, i_data.getDoubleWord(0), l_pMode); } return l_rc; }
//****************************************************************************** //* name=mss_eff_config_rank_group, param=i_target_mba, return=ReturnCode //****************************************************************************** fapi::ReturnCode mss_eff_config_rank_group(const fapi::Target i_target_mba) { fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; const char * const PROCEDURE_NAME = "mss_eff_config_rank_group"; const fapi::Target& TARGET_MBA = i_target_mba; FAPI_INF("*** Running %s on %s ... ***", PROCEDURE_NAME, i_target_mba.toEcmdString()); const uint8_t PORT_SIZE = 2; const uint8_t DIMM_SIZE = 2; // ATTR_EFF_DRAM_GEN: EMPTY = 0, DDR3 = 1, DDR4 = 2, // ATTR_EFF_DIMM_TYPE: CDIMM = 0, RDIMM = 1, UDIMM = 2, LRDIMM = 3, uint8_t num_ranks_per_dimm_u8array[PORT_SIZE][DIMM_SIZE]; uint8_t dram_gen_u8; uint8_t dimm_type_u8; rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target_mba, num_ranks_per_dimm_u8array); if(rc) return rc; rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target_mba, dram_gen_u8); if(rc) return rc; rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_TYPE, &i_target_mba, dimm_type_u8); if(rc) return rc; uint8_t primary_rank_group0_u8array[PORT_SIZE]; uint8_t primary_rank_group1_u8array[PORT_SIZE]; uint8_t primary_rank_group2_u8array[PORT_SIZE]; uint8_t primary_rank_group3_u8array[PORT_SIZE]; uint8_t secondary_rank_group0_u8array[PORT_SIZE]; uint8_t secondary_rank_group1_u8array[PORT_SIZE]; uint8_t secondary_rank_group2_u8array[PORT_SIZE]; uint8_t secondary_rank_group3_u8array[PORT_SIZE]; uint8_t tertiary_rank_group0_u8array[PORT_SIZE]; uint8_t tertiary_rank_group1_u8array[PORT_SIZE]; uint8_t tertiary_rank_group2_u8array[PORT_SIZE]; uint8_t tertiary_rank_group3_u8array[PORT_SIZE]; uint8_t quanternary_rank_group0_u8array[PORT_SIZE]; uint8_t quanternary_rank_group1_u8array[PORT_SIZE]; uint8_t quanternary_rank_group2_u8array[PORT_SIZE]; uint8_t quanternary_rank_group3_u8array[PORT_SIZE]; for (uint8_t cur_port = 0; cur_port < PORT_SIZE; cur_port += 1) { //Removed 32G CDIMM 1R dualdrop workaround. //NOTE: Needs mss_draminit_training.C v1.57 or newer. //if ((dimm_type_u8 == CDIMM) && (num_ranks_per_dimm_u8array[cur_port][0] == 1) && (num_ranks_per_dimm_u8array[cur_port][1] == 1)) { // NOTE: 32G CDIMM 1R dualdrop workaround, normally primary_rank_group0=0, primary_rank_group1=4. //primary_rank_group0_u8array[cur_port] = 0; //primary_rank_group1_u8array[cur_port] = INVALID; //primary_rank_group2_u8array[cur_port] = INVALID; //primary_rank_group3_u8array[cur_port] = INVALID; //secondary_rank_group0_u8array[cur_port] = 4; //secondary_rank_group1_u8array[cur_port] = INVALID; //secondary_rank_group2_u8array[cur_port] = INVALID; //secondary_rank_group3_u8array[cur_port] = INVALID; //tertiary_rank_group0_u8array[cur_port] = INVALID; //tertiary_rank_group1_u8array[cur_port] = INVALID; //tertiary_rank_group2_u8array[cur_port] = INVALID; //tertiary_rank_group3_u8array[cur_port] = INVALID; //quanternary_rank_group0_u8array[cur_port] = INVALID; //quanternary_rank_group1_u8array[cur_port] = INVALID; //quanternary_rank_group2_u8array[cur_port] = INVALID; //quanternary_rank_group3_u8array[cur_port] = INVALID; //} else if (dimm_type_u8 == LRDIMM) { if (dimm_type_u8 == LRDIMM) { primary_rank_group2_u8array[cur_port] = INVALID; secondary_rank_group2_u8array[cur_port] = INVALID; tertiary_rank_group2_u8array[cur_port] = INVALID; quanternary_rank_group2_u8array[cur_port] = INVALID; primary_rank_group3_u8array[cur_port] = INVALID; secondary_rank_group3_u8array[cur_port] = INVALID; tertiary_rank_group3_u8array[cur_port] = INVALID; quanternary_rank_group3_u8array[cur_port] = INVALID; // dimm 0 (far socket) switch (num_ranks_per_dimm_u8array[cur_port][0]) { case 4: // 4 rank lrdimm primary_rank_group0_u8array[cur_port] = 0; secondary_rank_group0_u8array[cur_port] = 1; tertiary_rank_group0_u8array[cur_port] = 2; quanternary_rank_group0_u8array[cur_port] = 3; break; case 8: // 8 rank lrdimm falls through to 2 rank case // Rank Multiplication mode needed, CS2 & CS3 used as address lines into LRBuffer // RM=4 -> only 2 CS valid, each CS controls 4 ranks with CS2 & CS3 as address // CS0 = rank 0, 2, 4, 6; CS1 = rank 1, 3, 5, 7 case 2: // 2 rank lrdimm primary_rank_group0_u8array[cur_port] = 0; secondary_rank_group0_u8array[cur_port] = 1; tertiary_rank_group0_u8array[cur_port] = INVALID; quanternary_rank_group0_u8array[cur_port] = INVALID; break; case 1: // 1 rank lrdimm primary_rank_group0_u8array[cur_port] = 0; secondary_rank_group0_u8array[cur_port] = INVALID; tertiary_rank_group0_u8array[cur_port] = INVALID; quanternary_rank_group0_u8array[cur_port] = INVALID; break; default: // not 1, 2, 4, or 8 ranks primary_rank_group0_u8array[cur_port] = INVALID; secondary_rank_group0_u8array[cur_port] = INVALID; tertiary_rank_group0_u8array[cur_port] = INVALID; quanternary_rank_group0_u8array[cur_port] = INVALID; } // dimm 1 (near socket) switch (num_ranks_per_dimm_u8array[cur_port][1]) { case 4: // 4 rank lrdimm primary_rank_group1_u8array[cur_port] = 4; secondary_rank_group1_u8array[cur_port] = 5; tertiary_rank_group1_u8array[cur_port] = 6; quanternary_rank_group1_u8array[cur_port] = 7; break; case 8: // 8 rank lrdimm falls through to case 2 // Rank Multiplication mode needed, CS6 & CS7 used as address lines into LRBuffer // RM=4 -> only 2 CS valid, each CS controls 4 ranks with CS6 & CS7 as address // CS4 = rank 0, 2, 4, 6; CS5 = rank 1, 3, 5, 7 case 2: // 2 rank lrdimm, RM=0 primary_rank_group1_u8array[cur_port] = 4; secondary_rank_group1_u8array[cur_port] = 5; tertiary_rank_group1_u8array[cur_port] = INVALID; quanternary_rank_group1_u8array[cur_port] = INVALID; break; case 1: // 1 rank lrdimm primary_rank_group1_u8array[cur_port] = 4; secondary_rank_group1_u8array[cur_port] = INVALID; tertiary_rank_group1_u8array[cur_port] = INVALID; quanternary_rank_group1_u8array[cur_port] = INVALID; break; default: // not 1, 2, 4, or 8 ranks primary_rank_group1_u8array[cur_port] = INVALID; secondary_rank_group1_u8array[cur_port] = INVALID; tertiary_rank_group1_u8array[cur_port] = INVALID; quanternary_rank_group1_u8array[cur_port] = INVALID; } } else { // RDIMM or CDIMM if ((num_ranks_per_dimm_u8array[cur_port][0] > 0) && (num_ranks_per_dimm_u8array[cur_port][1] == 0)) { primary_rank_group0_u8array[cur_port] = 0; if (num_ranks_per_dimm_u8array[cur_port][0] > 1) { primary_rank_group1_u8array[cur_port] = 1; } else { primary_rank_group1_u8array[cur_port] = INVALID; } if (num_ranks_per_dimm_u8array[cur_port][0] > 2) { primary_rank_group2_u8array[cur_port] = 2; primary_rank_group3_u8array[cur_port] = 3; } else { primary_rank_group2_u8array[cur_port] = INVALID; primary_rank_group3_u8array[cur_port] = INVALID; } secondary_rank_group0_u8array[cur_port] = INVALID; secondary_rank_group1_u8array[cur_port] = INVALID; secondary_rank_group2_u8array[cur_port] = INVALID; secondary_rank_group3_u8array[cur_port] = INVALID; } else if ((num_ranks_per_dimm_u8array[cur_port][0] > 0) && (num_ranks_per_dimm_u8array[cur_port][1] > 0)) { if (num_ranks_per_dimm_u8array[cur_port][0] != num_ranks_per_dimm_u8array[cur_port][1]) { FAPI_ERR("%s: FAILED!", PROCEDURE_NAME); FAPI_ERR("Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0], num_ranks_per_dimm_u8array[cur_port][1], i_target_mba.toEcmdString(), cur_port); FAPI_SET_HWP_ERROR(rc, RC_MSS_EFF_CONFIG_RANK_GROUP_NON_MATCH_RANKS); return rc; } primary_rank_group0_u8array[cur_port] = 0; primary_rank_group1_u8array[cur_port] = 4; primary_rank_group2_u8array[cur_port] = INVALID; primary_rank_group3_u8array[cur_port] = INVALID; secondary_rank_group0_u8array[cur_port] = INVALID; secondary_rank_group1_u8array[cur_port] = INVALID; secondary_rank_group2_u8array[cur_port] = INVALID; secondary_rank_group3_u8array[cur_port] = INVALID; if (num_ranks_per_dimm_u8array[cur_port][0] == 2) { primary_rank_group2_u8array[cur_port] = 1; primary_rank_group3_u8array[cur_port] = 5; } else if (num_ranks_per_dimm_u8array[cur_port][0] == 4) { primary_rank_group2_u8array[cur_port] = 2; primary_rank_group3_u8array[cur_port] = 6; secondary_rank_group0_u8array[cur_port] = 1; secondary_rank_group1_u8array[cur_port] = 5; secondary_rank_group2_u8array[cur_port] = 3; secondary_rank_group3_u8array[cur_port] = 7; } else if (num_ranks_per_dimm_u8array[cur_port][0] != 1) { FAPI_ERR("%s: FAILED!", PROCEDURE_NAME); FAPI_ERR("Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0], num_ranks_per_dimm_u8array[cur_port][1], i_target_mba.toEcmdString(), cur_port); FAPI_SET_HWP_ERROR(rc, RC_MSS_EFF_CONFIG_RANK_GROUP_NUM_RANKS_NEQ1); return rc; } } else if ((num_ranks_per_dimm_u8array[cur_port][0] == 0) && (num_ranks_per_dimm_u8array[cur_port][1] == 0)) { primary_rank_group0_u8array[cur_port] = INVALID; primary_rank_group1_u8array[cur_port] = INVALID; primary_rank_group2_u8array[cur_port] = INVALID; primary_rank_group3_u8array[cur_port] = INVALID; secondary_rank_group0_u8array[cur_port] = INVALID; secondary_rank_group1_u8array[cur_port] = INVALID; secondary_rank_group2_u8array[cur_port] = INVALID; secondary_rank_group3_u8array[cur_port] = INVALID; } else { FAPI_ERR("%s: FAILED!", PROCEDURE_NAME); FAPI_ERR("Plug rule violation, num_ranks_per_dimm=%d[0],%d[1] on %s PORT%d!", num_ranks_per_dimm_u8array[cur_port][0], num_ranks_per_dimm_u8array[cur_port][1], i_target_mba.toEcmdString(), cur_port); FAPI_SET_HWP_ERROR(rc, RC_MSS_EFF_CONFIG_RANK_GROUP_NO_MATCH); return rc; } tertiary_rank_group0_u8array[cur_port] = INVALID; tertiary_rank_group1_u8array[cur_port] = INVALID; tertiary_rank_group2_u8array[cur_port] = INVALID; tertiary_rank_group3_u8array[cur_port] = INVALID; quanternary_rank_group0_u8array[cur_port] = INVALID; quanternary_rank_group1_u8array[cur_port] = INVALID; quanternary_rank_group2_u8array[cur_port] = INVALID; quanternary_rank_group3_u8array[cur_port] = INVALID; } FAPI_INF("P[%02d][%02d][%02d][%02d],S[%02d][%02d][%02d][%02d],T[%02d][%02d][%02d][%02d],Q[%02d][%02d][%02d][%02d] on %s PORT%d.", primary_rank_group0_u8array[cur_port], primary_rank_group1_u8array[cur_port], primary_rank_group2_u8array[cur_port], primary_rank_group3_u8array[cur_port], secondary_rank_group0_u8array[cur_port], secondary_rank_group1_u8array[cur_port], secondary_rank_group2_u8array[cur_port], secondary_rank_group3_u8array[cur_port], tertiary_rank_group0_u8array[cur_port], tertiary_rank_group1_u8array[cur_port], tertiary_rank_group2_u8array[cur_port], tertiary_rank_group3_u8array[cur_port], quanternary_rank_group0_u8array[cur_port], quanternary_rank_group1_u8array[cur_port], quanternary_rank_group2_u8array[cur_port], quanternary_rank_group3_u8array[cur_port], i_target_mba.toEcmdString(), cur_port); } rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP0, &i_target_mba, primary_rank_group0_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP1, &i_target_mba, primary_rank_group1_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP2, &i_target_mba, primary_rank_group2_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_PRIMARY_RANK_GROUP3, &i_target_mba, primary_rank_group3_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP0, &i_target_mba, secondary_rank_group0_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP1, &i_target_mba, secondary_rank_group1_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP2, &i_target_mba, secondary_rank_group2_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_SECONDARY_RANK_GROUP3, &i_target_mba, secondary_rank_group3_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP0, &i_target_mba, tertiary_rank_group0_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP1, &i_target_mba, tertiary_rank_group1_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP2, &i_target_mba, tertiary_rank_group2_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_TERTIARY_RANK_GROUP3, &i_target_mba, tertiary_rank_group3_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP0, &i_target_mba, quanternary_rank_group0_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP1, &i_target_mba, quanternary_rank_group1_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP2, &i_target_mba, quanternary_rank_group2_u8array); if(rc) return rc; rc = FAPI_ATTR_SET(ATTR_EFF_QUATERNARY_RANK_GROUP3, &i_target_mba, quanternary_rank_group3_u8array); if(rc) return rc; FAPI_INF("%s on %s COMPLETE", PROCEDURE_NAME, i_target_mba.toEcmdString()); return rc; }
fapi::ReturnCode parse_addr(const fapi::Target & i_target_mba, char addr_string[], uint8_t mr3_valid, uint8_t mr2_valid, uint8_t mr1_valid, uint8_t l_dram_rows, uint8_t l_dram_cols, uint8_t l_addr_inter) { fapi::ReturnCode rc; uint8_t i = MAX_ADDR_BITS; uint8_t l_slave_rank = 0; uint8_t l_value; uint32_t l_value32 = 0; uint32_t l_sbit, rc_num; uint32_t l_start = 0; uint32_t l_len = 0; uint64_t l_readscom_value = 0; uint64_t l_end = 0; uint64_t l_start_addr = 0; uint8_t l_value_zero = 0; uint8_t l_user_end_addr = 0; ecmdDataBufferBase l_data_buffer_64(64); ecmdDataBufferBase l_data_buffer_rd64(64); uint8_t l_attr_addr_mode = 0; uint8_t l_num_cols = 0; uint8_t l_num_rows = 0; rc = FAPI_ATTR_GET(ATTR_EFF_SCHMOO_ADDR_MODE, &i_target_mba, l_attr_addr_mode); if (rc) return rc; rc = FAPI_ATTR_GET(ATTR_MCBIST_ADDR_NUM_COLS, &i_target_mba, l_num_cols); if (rc) return rc; rc = FAPI_ATTR_GET(ATTR_MCBIST_ADDR_NUM_ROWS, &i_target_mba, l_num_rows); if (rc) return rc; if (l_num_cols == 0) { l_num_cols = l_dram_cols; } if (l_num_rows == 0) { l_num_rows = l_dram_rows; } //Set all the addr reg to 0 //Define Custom String //Set all Params based on the string. rc_num = l_data_buffer_64.flushTo0(); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } l_sbit = 0; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; l_sbit = 54; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i--; ////FAPI_INF("Inside strcmp ba2"); l_sbit = 48; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i--; ////FAPI_INF("Inside strcmp ba3"); l_sbit = 42; l_value = i; //------- Enable these for DDR4 --- for now constant map to zero rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //FAPI_INF("ba3 Invalid"); rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i++; ////FAPI_INF("Inside strcmp mr3"); l_sbit = 18; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; if (mr3_valid == 1) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //FAPI_INF("mr3 Invalid"); i++; } ////FAPI_INF("Inside strcmp mr2"); l_sbit = 12; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; if (mr2_valid == 1) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } //FAPI_INF("Inside mr2 --- l_addr_inter"); rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //FAPI_INF("mr2 Invalid"); i++; } ////FAPI_INF("Inside strcmp mr1"); l_sbit = 6; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; if (mr1_valid == 1) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } //FAPI_INF("Inside mr1 --- l_addr_inter"); rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //FAPI_INF("mr1 Invalid"); i++; } ////FAPI_INF("Inside strcmp mr0"); l_sbit = 0; l_value = i; //------- Enable these for DDR4 --- for now constant map to zero rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i++; ////FAPI_INF("Value of i = %d",i); //FAPI_INF("mr0 Invalid\n"); ////FAPI_INF("Inside strcmp cl3"); l_sbit = 42; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i++; //FAPI_INF("col2 Invalid"); ////FAPI_INF("Value of i = %d",i); ////FAPI_INF("Inside strcmp cl3"); l_sbit = 36; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 1) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 3 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp cl4"); l_sbit = 30; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 2) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 4 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp cl5"); l_sbit = 24; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 3) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 5 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp cl6"); l_sbit = 18; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 4) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 6 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp cl7"); l_sbit = 12; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 5) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 7 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp cl8"); l_sbit = 6; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 6) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 8 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp cl9"); l_sbit = 0; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 7) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106cb, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 9 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp cl11"); l_sbit = 54; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 11) { if (l_dram_cols >= 11) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_DBG("%s: Inside l_dram_cols > 10"); i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; FAPI_DBG("%s:Col 11 -- Invalid", i_target_mba.toEcmdString()); i++; } } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 11 -- Invalid"); i++; } ////FAPI_INF("Value of i = %d",i); ////FAPI_INF("Inside strcmp cl13"); l_sbit = 48; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_cols >= 12) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("Col 13 Invalid"); i++; } ////FAPI_INF("Value of i = %d",i); ////FAPI_INF("Inside strcmp r0"); l_sbit = 42; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 0) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 0 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r1"); l_sbit = 36; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 1) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 1 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r2"); l_sbit = 30; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 2) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 2 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r3"); l_sbit = 24; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 3) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 3 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r4"); l_sbit = 18; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 4) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 4 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r5"); l_sbit = 12; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 5) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 5 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r6"); l_sbit = 6; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 6) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 6 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r7"); l_sbit = 0; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 7) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106ca, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 7 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r8"); l_sbit = 54; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 8) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 8 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r9"); l_sbit = 48; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 9) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 9 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r10"); l_sbit = 42; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 10) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 10 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r11"); l_sbit = 36; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 11) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 11 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r12"); l_sbit = 30; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 12) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 12 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r13"); l_sbit = 24; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 13) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 13 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r14"); l_sbit = 18; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 14) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } ////FAPI_INF("Value of i = %d",i); else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 14 -- Invalid"); i++; } ////FAPI_INF("Inside strcmp r15"); l_sbit = 12; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_num_rows > 15) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } else { rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; //FAPI_INF("row 15 -- Invalid"); i++; } ////FAPI_INF("Value of i = %d",i); ////FAPI_INF("Inside strcmp r16 and l_dram_rows = %d",l_dram_rows); l_sbit = 6; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; if (l_dram_rows >= 17) { rc_num = l_data_buffer_64.insertFromRight(l_value, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i--; } else { ////FAPI_INF("r16 not used"); rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } //FAPI_INF("Row 16 Invalid"); rc = fapiPutScom(i_target_mba, 0x030106c9, l_data_buffer_64); if (rc) return rc; i++; } ////FAPI_INF("Value of i = %d",i); ////FAPI_INF("Inside strcmp sl2"); l_sbit = 36; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //------- Enable these for later --- for now constant map to zero if (l_slave_rank == 0) { l_value = 0; } rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //FAPI_INF("sl2 Invalid"); i++; ////FAPI_INF("Value of i = %d",i); ////FAPI_INF("Inside strcmp sl1"); l_sbit = 30; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //------- Enable these for later --- for now constant map to zero if (l_slave_rank == 0) { l_value = 0; } rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; i++; //FAPI_INF("sl1 Invalid"); ////FAPI_INF("Value of i = %d",i); ////FAPI_INF("Inside strcmp sl0"); l_sbit = 24; l_value = i; rc = fapiGetScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //------- Enable these for later --- for now constant map to zero if (l_slave_rank == 0) { l_value = 0; } rc_num = l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106c8, l_data_buffer_64); if (rc) return rc; //FAPI_INF("sl0 Invalid"); i++; ////FAPI_INF("Value of i = %d",i); //------ Setting Start and end addr counters //FAPI_INF("Debug - --------------- Setting Start and End Counters -----------\n"); rc_num = l_data_buffer_rd64.flushTo0(); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106d0, l_data_buffer_rd64); if (rc) return rc; l_value = i + 1; //FAPI_INF("Setting end_addr Value of i = %d",i); rc_num = l_data_buffer_rd64.flushTo0(); //Calculate and set Valid bits for end_addr for (i = l_value; i <= 37; i++) { rc_num |= l_data_buffer_rd64.clearBit(i); rc_num |= l_data_buffer_rd64.setBit(i); } if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } l_readscom_value = l_data_buffer_rd64.getDoubleWord(0); rc = FAPI_ATTR_GET(ATTR_EFF_SCHMOO_ADDR_MODE, &i_target_mba, l_attr_addr_mode); if (rc) return rc; rc = FAPI_ATTR_GET(ATTR_MCBIST_START_ADDR, &i_target_mba, l_start_addr); if (rc) return rc; //FAPI_INF("User Defined ATTR - Start = %016llX",l_start_addr); rc = FAPI_ATTR_GET(ATTR_MCBIST_END_ADDR, &i_target_mba, l_end); if (rc) return rc; rc = FAPI_ATTR_GET(ATTR_MCBIST_RANK, &i_target_mba, l_user_end_addr); if (rc) return rc; if (l_user_end_addr == 1) { //Setting start and end Temp rc_num = l_data_buffer_rd64.setDoubleWord(0, l_start_addr); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106d0, l_data_buffer_rd64); if (rc) return rc; rc = fapiPutScom(i_target_mba, 0x030106d1, l_data_buffer_rd64); if (rc) return rc; rc_num = l_data_buffer_rd64.setDoubleWord(0, l_end); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106d2, l_data_buffer_rd64); if (rc) return rc; rc = fapiPutScom(i_target_mba, 0x030106d3, l_data_buffer_rd64); if (rc) return rc; } else { if (l_attr_addr_mode == 0) { //FAPI_INF("ATTR_EFF_SCHMOO_ADDR_MODE - %d ---- Few Address Mode --------",l_attr_addr_mode); l_sbit = 32; rc_num = l_data_buffer_rd64.flushTo0(); l_start = 24; l_len = 8; l_value32 = 28; rc_num |= l_data_buffer_rd64.insert(l_value32, l_sbit, l_len, l_start); l_readscom_value = 0x000003FFF8000000ull; rc_num |= l_data_buffer_rd64.setDoubleWord(0, l_readscom_value); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106d2, l_data_buffer_rd64); if (rc) return rc; rc = fapiPutScom(i_target_mba, 0x030106d3, l_data_buffer_rd64); if (rc) return rc; l_readscom_value = l_data_buffer_rd64.getDoubleWord(0); //FAPI_INF("Debug - Final End addr for 0x030106d2 = %016llX",l_readscom_value); } else if (l_attr_addr_mode == 1) { //FAPI_INF("ATTR_EFF_SCHMOO_ADDR_MODE - %d ---- QUARTER ADDRESSING Mode --------",l_attr_addr_mode); l_readscom_value = l_readscom_value >> 2; //FAPI_INF("Debug - Final End addr for 0x030106d2 = %016llX",l_readscom_value); rc_num = l_data_buffer_rd64.setDoubleWord(0, l_readscom_value); if (rc_num) { FAPI_ERR("Error in function parse_addr:"); rc.setEcmdError(rc_num); return rc; } rc = fapiPutScom(i_target_mba, 0x030106d2, l_data_buffer_rd64); if (rc) return rc; rc = fapiPutScom(i_target_mba, 0x030106d3, l_data_buffer_rd64); if (rc) return rc; } else if (l_attr_addr_mode == 2)
fapi::ReturnCode mss_eff_config_thermal_powercurve(const fapi::Target & i_target_mba) { fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; FAPI_INF("*** Running mss_eff_config_thermal_powercurve on %s ***", i_target_mba.toEcmdString()); // other variables used in this function fapi::Target target_chip; uint8_t port; uint8_t dimm; uint8_t custom_dimm; uint8_t dimm_ranks_array[NUM_PORTS][NUM_DIMMS]; uint32_t power_slope_array[NUM_PORTS][NUM_DIMMS]; uint32_t power_int_array[NUM_PORTS][NUM_DIMMS]; uint32_t power_slope2_array[NUM_PORTS][NUM_DIMMS]; uint32_t power_int2_array[NUM_PORTS][NUM_DIMMS]; uint32_t total_power_slope_array[NUM_PORTS][NUM_DIMMS]; uint32_t total_power_int_array[NUM_PORTS][NUM_DIMMS]; uint32_t total_power_slope2_array[NUM_PORTS][NUM_DIMMS]; uint32_t total_power_int2_array[NUM_PORTS][NUM_DIMMS]; uint32_t cdimm_master_power_slope; uint32_t cdimm_master_power_intercept; uint32_t cdimm_supplier_power_slope; uint32_t cdimm_supplier_power_intercept; uint32_t cdimm_master_total_power_slope = 0; uint32_t cdimm_master_total_power_intercept = 0; uint32_t cdimm_supplier_total_power_slope = 0; uint32_t cdimm_supplier_total_power_intercept = 0; uint8_t l_dram_gen; uint8_t l_logged_error_power_curve = 0; uint8_t l_logged_error_total_power_curve = 0; //------------------------------------------------------------------------------ // Get input attributes //------------------------------------------------------------------------------ // Get Centaur target for the given MBA rc = fapiGetParentChip(i_target_mba, target_chip); if (rc) { FAPI_ERR("Error from fapiGetParentChip"); return rc; } rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, custom_dimm); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_CUSTOM_DIMM"); return rc; } rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target_mba, dimm_ranks_array); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_NUM_RANKS_PER_DIMM"); return rc; } rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target_mba, l_dram_gen); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_GEN"); return rc; } // Only get power curve values for custom dimms to prevent errors if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) { // These are the CDIMM power curve values for only VMEM (DDR3 and DDR4) rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_MASTER_POWER_SLOPE, &target_chip, cdimm_master_power_slope); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_MASTER_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_MASTER_POWER_INTERCEPT, &target_chip, cdimm_master_power_intercept); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_MASTER_POWER_INTERCEPT"); return rc; } rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_SUPPLIER_POWER_SLOPE, &target_chip, cdimm_supplier_power_slope); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_SUPPLIER_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_SUPPLIER_POWER_INTERCEPT, &target_chip, cdimm_supplier_power_intercept); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_SUPPLIER_POWER_INTERCEPT"); return rc; } // These are for the total CDIMM power (VMEM+VPP for DDR4) if (l_dram_gen == fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_MASTER_TOTAL_POWER_SLOPE, &target_chip, cdimm_master_total_power_slope); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_MASTER_TOTAL_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_MASTER_TOTAL_POWER_INTERCEPT, &target_chip, cdimm_master_total_power_intercept); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_MASTER_TOTAL_POWER_INTERCEPT"); return rc; } rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_SUPPLIER_TOTAL_POWER_SLOPE, &target_chip, cdimm_supplier_total_power_slope); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_SUPPLIER_TOTAL_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_GET(ATTR_CDIMM_VPD_SUPPLIER_TOTAL_POWER_INTERCEPT, &target_chip, cdimm_supplier_total_power_intercept); if (rc) { FAPI_ERR("Error getting attribute ATTR_CDIMM_VPD_SUPPLIER_TOTAL_POWER_INTERCEPT"); return rc; } } else { // Set total power curve variables to the VMEM power curve variables for DDR3 cdimm_master_total_power_slope = cdimm_master_power_slope; cdimm_master_total_power_intercept = cdimm_master_power_intercept; cdimm_supplier_total_power_slope = cdimm_supplier_power_slope; cdimm_supplier_total_power_intercept = cdimm_supplier_power_intercept; } } //------------------------------------------------------------------------------ // Power Curve Determination //------------------------------------------------------------------------------ // Iterate through the MBA ports to get power slope/intercept values for (port=0; port < NUM_PORTS; port++) { // iterate through the dimms on each port again to determine power slope and // intercept for (dimm=0; dimm < NUM_DIMMS; dimm++) { // initialize dimm entries to zero power_slope_array[port][dimm] = 0; power_int_array[port][dimm] = 0; power_slope2_array[port][dimm] = 0; power_int2_array[port][dimm] = 0; total_power_slope_array[port][dimm] = 0; total_power_int_array[port][dimm] = 0; total_power_slope2_array[port][dimm] = 0; total_power_int2_array[port][dimm] = 0; // only update values for dimms that are physically present if (dimm_ranks_array[port][dimm] > 0) { // CDIMM power slope/intercept will come from VPD // Data in VPD needs to be the power per virtual dimm on the CDIMM if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) { power_slope_array[port][dimm] = cdimm_master_power_slope; power_int_array[port][dimm] = cdimm_master_power_intercept; power_slope2_array[port][dimm] = cdimm_supplier_power_slope; power_int2_array[port][dimm] = cdimm_supplier_power_intercept; total_power_slope_array[port][dimm] = cdimm_master_total_power_slope; total_power_int_array[port][dimm] = cdimm_master_total_power_intercept; total_power_slope2_array[port][dimm] = cdimm_supplier_total_power_slope; total_power_int2_array[port][dimm] = cdimm_supplier_total_power_intercept; // check to see if VMEM power curve data is valid if ( (((cdimm_master_power_slope & 0x8000) != 0) && ((cdimm_master_power_intercept & 0x8000) != 0)) && (((cdimm_supplier_power_slope & 0x8000) != 0) && ((cdimm_supplier_power_intercept & 0x8000) != 0)) ) { power_slope_array[port][dimm] = cdimm_master_power_slope & 0x1FFF; power_int_array[port][dimm] = cdimm_master_power_intercept & 0x1FFF; power_slope2_array[port][dimm] = cdimm_supplier_power_slope & 0x1FFF; power_int2_array[port][dimm] = cdimm_supplier_power_intercept & 0x1FFF; // check to see if data is lab data if ( (((cdimm_master_power_slope & 0x4000) == 0) || ((cdimm_master_power_intercept & 0x4000) == 0)) || (((cdimm_supplier_power_slope & 0x4000) == 0) || ((cdimm_supplier_power_intercept & 0x4000) == 0)) ) { FAPI_INF("WARNING: VMEM power curve data is lab data, not ship level data. Using data anyways."); } // check total power curve (VMEM+VPP) values for DDR4 if (l_dram_gen == fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { if ( (((cdimm_master_total_power_slope & 0x8000) != 0) && ((cdimm_master_total_power_intercept & 0x8000) != 0)) && (((cdimm_supplier_total_power_slope & 0x8000) != 0) && ((cdimm_supplier_total_power_intercept & 0x8000) != 0)) ) { total_power_slope_array[port][dimm] = cdimm_master_total_power_slope & 0x1FFF; total_power_int_array[port][dimm] = cdimm_master_total_power_intercept & 0x1FFF; total_power_slope2_array[port][dimm] = cdimm_supplier_total_power_slope & 0x1FFF; total_power_int2_array[port][dimm] = cdimm_supplier_total_power_intercept & 0x1FFF; // check to see if data is lab data if ( (((cdimm_master_total_power_slope & 0x4000) == 0) || ((cdimm_master_total_power_intercept & 0x4000) == 0)) || (((cdimm_supplier_total_power_slope & 0x4000) == 0) || ((cdimm_supplier_total_power_intercept & 0x4000) == 0)) ) { FAPI_INF("WARNING: Total power curve data is lab data, not ship level data. Using data anyways."); } } else { // Set to VMEM power curve values if total values are not valid and log an error // early DDR4 CDIMMs will have the total power curve entries all zero (not valid) total_power_slope_array[port][dimm] = power_slope_array[port][dimm]; total_power_int_array[port][dimm] = power_int_array[port][dimm]; total_power_slope2_array[port][dimm] = power_slope2_array[port][dimm]; total_power_int2_array[port][dimm] = power_int2_array[port][dimm]; // only log the error once per MBA, since all dimms will have the same power curve values if (l_logged_error_total_power_curve == 0) { l_logged_error_total_power_curve = 1; FAPI_ERR("Total power curve data not valid, use default values"); const fapi::Target & MEM_CHIP = target_chip; uint32_t FFDC_DATA_1 = cdimm_master_total_power_slope; uint32_t FFDC_DATA_2 = cdimm_master_total_power_intercept; uint32_t FFDC_DATA_3 = cdimm_supplier_total_power_slope; uint32_t FFDC_DATA_4 = cdimm_supplier_total_power_intercept; FAPI_SET_HWP_ERROR (rc, RC_MSS_DIMM_POWER_CURVE_DATA_INVALID); if (rc) fapiLogError(rc); } } } else { // Set total power curve values to VMEM power curve values for anything other than DDR4 (ie. DDR3) total_power_slope_array[port][dimm] = power_slope_array[port][dimm]; total_power_int_array[port][dimm] = power_int_array[port][dimm]; total_power_slope2_array[port][dimm] = power_slope2_array[port][dimm]; total_power_int2_array[port][dimm] = power_int2_array[port][dimm]; } } else { // Set to default values and log an error if VMEM power curve values are not valid power_slope_array[port][dimm] = CDIMM_POWER_SLOPE_DEFAULT; power_int_array[port][dimm] = CDIMM_POWER_INT_DEFAULT; power_slope2_array[port][dimm] = CDIMM_POWER_SLOPE_DEFAULT; power_int2_array[port][dimm] = CDIMM_POWER_INT_DEFAULT; total_power_slope_array[port][dimm] = CDIMM_POWER_SLOPE_DEFAULT; total_power_int_array[port][dimm] = CDIMM_POWER_INT_DEFAULT; total_power_slope2_array[port][dimm] = CDIMM_POWER_SLOPE_DEFAULT; total_power_int2_array[port][dimm] = CDIMM_POWER_INT_DEFAULT; // only log the error once per MBA, since all dimms will have the same power curve values if (l_logged_error_power_curve == 0) { l_logged_error_power_curve = 1; FAPI_ERR("VMEM power curve data not valid, use default values"); const fapi::Target & MEM_CHIP = target_chip; uint32_t FFDC_DATA_1 = cdimm_master_power_slope; uint32_t FFDC_DATA_2 = cdimm_master_power_intercept; uint32_t FFDC_DATA_3 = cdimm_supplier_power_slope; uint32_t FFDC_DATA_4 = cdimm_supplier_power_intercept; FAPI_SET_HWP_ERROR (rc, RC_MSS_DIMM_POWER_CURVE_DATA_INVALID); if (rc) fapiLogError(rc); } } FAPI_DBG("CDIMM VMEM Power [P%d:D%d][SLOPE=%d:INT=%d cW][SLOPE2=%d:INT2=%d cW]", port, dimm, power_slope_array[port][dimm], power_int_array[port][dimm], power_slope2_array[port][dimm], power_int2_array[port][dimm]); FAPI_DBG("CDIMM Total Power [P%d:D%d][VMEM SLOPE=%d:INT=%d cW][VMEM SLOPE2=%d:INT2=%d cW]", port, dimm, total_power_slope_array[port][dimm], total_power_int_array[port][dimm], total_power_slope2_array[port][dimm], total_power_int2_array[port][dimm]); } // non custom dimms will no longer use power curves // These will use a simplified approach of using throttle values for certain ranges of power // in mss_bulk_pwr_throttles. } } } // write output attributes rc = FAPI_ATTR_SET(ATTR_MSS_POWER_SLOPE, &i_target_mba, power_slope_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_POWER_INT, &i_target_mba, power_int_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_POWER_INT"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_POWER_SLOPE2, &i_target_mba, power_slope2_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_POWER_SLOPE2"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_POWER_INT2, &i_target_mba, power_int2_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_POWER_INT2"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_SLOPE, &i_target_mba, total_power_slope_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_INT, &i_target_mba, total_power_int_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_INT"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_SLOPE2, &i_target_mba, total_power_slope2_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_SLOPE2"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_INT2, &i_target_mba, total_power_int2_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_INT2"); return rc; } FAPI_INF("*** mss_eff_config_thermal_powercurve COMPLETE on %s ***", i_target_mba.toEcmdString()); return rc; }
fapi::ReturnCode mss_eff_config_thermal_throttles(const fapi::Target & i_target_mba) { fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; FAPI_INF("*** Running mss_eff_config_thermal_throttles on %s ***", i_target_mba.toEcmdString()); // variables used in this function fapi::Target target_chip; std::vector<fapi::Target> target_mba_array; std::vector<fapi::Target> target_dimm_array; uint8_t custom_dimm; uint8_t num_dimms_on_port; uint32_t runtime_throttle_n_per_mba; uint32_t runtime_throttle_n_per_chip; uint32_t runtime_throttle_d; uint32_t dimm_thermal_power_limit; uint32_t channel_pair_thermal_power_limit; uint8_t num_mba_with_dimms = 0; uint8_t mba_index; uint8_t ras_increment; uint8_t cas_increment; uint32_t l_max_dram_databus_util; uint32_t l_dimm_reg_power_limit_per_dimm_adj; uint32_t l_dimm_reg_power_limit_per_dimm; uint8_t l_max_number_dimms_per_reg; uint8_t l_dimm_reg_power_limit_adj_enable; uint8_t l_reg_max_dimm_count; uint8_t l_dram_gen; uint32_t l_power_slope_array[NUM_PORTS][NUM_DIMMS]; uint32_t l_power_int_array[NUM_PORTS][NUM_DIMMS]; uint32_t l_total_power_slope_array[NUM_PORTS][NUM_DIMMS]; uint32_t l_total_power_int_array[NUM_PORTS][NUM_DIMMS]; //------------------------------------------------------------------------------ // Get input attributes //------------------------------------------------------------------------------ // Get Centaur target for the given MBA rc = fapiGetParentChip(i_target_mba, target_chip); if (rc) { FAPI_ERR("Error from fapiGetParentChip"); return rc; } rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, custom_dimm); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_CUSTOM_DIMM"); return rc; } rc = FAPI_ATTR_GET(ATTR_EFF_NUM_DROPS_PER_PORT, &i_target_mba, num_dimms_on_port); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_NUM_DROPS_PER_PORT"); return rc; } rc = FAPI_ATTR_GET(ATTR_MRW_THERMAL_MEMORY_POWER_LIMIT, NULL, dimm_thermal_power_limit); if (rc) { FAPI_ERR("Error getting attribute ATTR_MRW_THERMAL_MEMORY_POWER_LIMIT"); return rc; } rc = FAPI_ATTR_GET(ATTR_MRW_MEM_THROTTLE_DENOMINATOR, NULL, runtime_throttle_d); if (rc) { FAPI_ERR("Error getting attribute ATTR_MRW_MEM_THROTTLE_DENOMINATOR"); return rc; } rc = FAPI_ATTR_GET(ATTR_MRW_MAX_DRAM_DATABUS_UTIL, NULL, l_max_dram_databus_util); if (rc) { FAPI_ERR("Error getting attribute ATTR_MRW_MAX_DRAM_DATABUS_UTIL"); return rc; } rc = FAPI_ATTR_GET(ATTR_MRW_VMEM_REGULATOR_MEMORY_POWER_LIMIT_PER_DIMM, NULL, l_dimm_reg_power_limit_per_dimm); if (rc) { FAPI_ERR("Error getting attribute ATTR_MRW_VMEM_REGULATOR_MEMORY_POWER_LIMIT_PER_DIMM"); return rc; } rc = FAPI_ATTR_GET(ATTR_MRW_MAX_NUMBER_DIMMS_POSSIBLE_PER_VMEM_REGULATOR, NULL, l_max_number_dimms_per_reg); if (rc) { FAPI_ERR("Error getting attribute ATTR_MRW_MAX_NUMBER_DIMMS_POSSIBLE_PER_VMEM_REGULATOR"); return rc; } rc = FAPI_ATTR_GET(ATTR_MRW_VMEM_REGULATOR_POWER_LIMIT_PER_DIMM_ADJ_ENABLE, NULL, l_dimm_reg_power_limit_adj_enable); if (rc) { FAPI_ERR("Error getting attribute ATTR_MRW_VMEM_REGULATOR_POWER_LIMIT_PER_DIMM_ADJ_ENABLE"); return rc; } rc = FAPI_ATTR_GET(ATTR_MSS_VMEM_REGULATOR_MAX_DIMM_COUNT, NULL, l_reg_max_dimm_count); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_VMEM_REGULATOR_MAX_DIMM_COUNT"); return rc; } rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target_mba, l_dram_gen); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_GEN"); return rc; } rc = FAPI_ATTR_GET(ATTR_MSS_POWER_SLOPE, &i_target_mba, l_power_slope_array); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_GET(ATTR_MSS_POWER_INT, &i_target_mba, l_power_int_array); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_POWER_INT"); return rc; } rc = FAPI_ATTR_GET(ATTR_MSS_TOTAL_POWER_SLOPE, &i_target_mba, l_total_power_slope_array); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_TOTAL_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_GET(ATTR_MSS_TOTAL_POWER_INT, &i_target_mba, l_total_power_int_array); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_TOTAL_POWER_INT"); return rc; } // Get number of Centaur MBAs that have dimms present // Custom dimms (CDIMMs) use mba/chip throttling, so count number of mbas that have dimms if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) { rc = fapiGetChildChiplets(target_chip, fapi::TARGET_TYPE_MBA_CHIPLET, target_mba_array, fapi::TARGET_STATE_PRESENT); if (rc) { FAPI_ERR("Error from fapiGetChildChiplets"); return rc; } num_mba_with_dimms = 0; for (mba_index=0; mba_index < target_mba_array.size(); mba_index++) { rc = fapiGetAssociatedDimms(target_mba_array[mba_index], target_dimm_array, fapi::TARGET_STATE_PRESENT); if (rc) { FAPI_ERR("Error from fapiGetAssociatedDimms"); return rc; } if (target_dimm_array.size() > 0) { num_mba_with_dimms++; } } } // ISDIMM (non custom dimm) uses dimm/mba throttling, so set num_mba_with_dimms to 1 else { num_mba_with_dimms = 1; } //------------------------------------------------------------------------------ // Memory Throttle Determination //------------------------------------------------------------------------------ // Determine memory throttle settings needed based on dimm thermal power limit //------------------------------------------------------------------------------ // Determine the thermal power limit to use, which represents a single channel // pair power limit for the dimms on that channel pair (ie. power for all dimms // attached to one MBA). The procedure mss_bulk_power_throttles takes the // input of channel pair power to determine throttles. // CDIMM thermal power limit from MRW is per CDIMM, so divide by number of mbas // that have dimms to get channel pair power // CDIMM: Allow all commands to be directed toward one MBA to achieve the power // limit // This means that the power limit for a MBA channel pair must be the total // CDIMM power limit minus the idle power of the other MBAs logical dimms //------------------------------------------------------------------------------ // adjust the regulator power limit per dimm if enabled and use this if less than the thermal limit // If reg power limit is zero, then set to thermal limit - needed for ISDIMM systems since some of these MRW attributes are not defined if (l_dimm_reg_power_limit_per_dimm == 0) { l_dimm_reg_power_limit_per_dimm = dimm_thermal_power_limit; } l_dimm_reg_power_limit_per_dimm_adj = l_dimm_reg_power_limit_per_dimm; if (l_dimm_reg_power_limit_adj_enable == fapi::ENUM_ATTR_MRW_VMEM_REGULATOR_POWER_LIMIT_PER_DIMM_ADJ_ENABLE_TRUE) { // adjust reg power limit per cdimm only if l_reg_max_dimm_count>0 and l_reg_max_dimm_count<l_max_number_dimms_per_reg if ( (l_reg_max_dimm_count > 0) && (l_reg_max_dimm_count < l_max_number_dimms_per_reg) ) { l_dimm_reg_power_limit_per_dimm_adj = l_dimm_reg_power_limit_per_dimm * l_max_number_dimms_per_reg / l_reg_max_dimm_count; FAPI_INF("VMEM Regulator Power/DIMM Limit Adjustment from %d to %d cW (DIMMs under regulator %d/%d)", l_dimm_reg_power_limit_per_dimm, l_dimm_reg_power_limit_per_dimm_adj, l_reg_max_dimm_count, l_max_number_dimms_per_reg); } } // Use the smaller of the thermal limit and regulator power limit per dimm if (l_dimm_reg_power_limit_per_dimm_adj < dimm_thermal_power_limit) { dimm_thermal_power_limit = l_dimm_reg_power_limit_per_dimm_adj; } // Adjust the thermal/power limit to represent the power for all dimms under an MBA if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) { channel_pair_thermal_power_limit = dimm_thermal_power_limit / num_mba_with_dimms; } // ISDIMMs thermal power limit from MRW is per DIMM, so multiply by number of dimms on channel to get channel power and multiply by 2 to get channel pair power else { // ISDIMMs channel_pair_thermal_power_limit = dimm_thermal_power_limit * num_dimms_on_port * 2; } // Update the channel pair power limit attribute rc = FAPI_ATTR_SET(ATTR_MSS_MEM_WATT_TARGET, &i_target_mba, channel_pair_thermal_power_limit); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_MEM_WATT_TARGET"); return rc; } // Initialize the runtime throttle attributes to an unthrottled value for mss_bulk_pwr_throttles // max utilization comes from MRW value in c% - convert to % float MAX_UTIL = (float) l_max_dram_databus_util / 100; runtime_throttle_n_per_mba = (int)(runtime_throttle_d * (MAX_UTIL / 100) / 4); runtime_throttle_n_per_chip = (int)(runtime_throttle_d * (MAX_UTIL / 100) / 4) * num_mba_with_dimms; // for better custom dimm performance for DDR4, set the per mba throttle to the per chip throttle // Not planning on doing this for DDR3 if ( (l_dram_gen == fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR4) && (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) ) { runtime_throttle_n_per_mba = runtime_throttle_n_per_chip; } rc = FAPI_ATTR_SET(ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA, &i_target_mba, runtime_throttle_n_per_mba); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP, &i_target_mba, runtime_throttle_n_per_chip); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR, &i_target_mba, runtime_throttle_d); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR"); return rc; } FAPI_INF("Min Power/Thermal Limit per MBA %d cW. Unthrottled values [%d/%d/%d].", channel_pair_thermal_power_limit, runtime_throttle_n_per_mba, runtime_throttle_n_per_chip, runtime_throttle_d); // For DDR4, use the VMEM power to determine the runtime throttle settings that are based // on a VMEM power limit (not a VMEM+VPP power limit which is to be used at runtime for tmgt) // Need to temporarily override attributes for mss_bulk_pwr_throttles to use // Needed to determines runtime memory throttle settings based on any VMEM power limits if (l_dram_gen == fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_SLOPE, &i_target_mba, l_power_slope_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_INT, &i_target_mba, l_power_int_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_INT"); return rc; } } // Call the procedure function that takes a channel pair power limit and // converts it to throttle values FAPI_EXEC_HWP(rc, mss_bulk_pwr_throttles, i_target_mba); if (rc) { FAPI_ERR("Error (0x%x) calling mss_bulk_pwr_throttles", static_cast<uint32_t>(rc)); return rc; } // Reset the total power curve attributes back to the original values if (l_dram_gen == fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_SLOPE, &i_target_mba, l_total_power_slope_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_SLOPE"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_TOTAL_POWER_INT, &i_target_mba, l_total_power_int_array); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_TOTAL_POWER_INT"); return rc; } } // Read back in the updated throttle attribute values (these are now set to // values that will give dimm/channel power underneath the thermal power limit) rc = FAPI_ATTR_GET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA, &i_target_mba, runtime_throttle_n_per_mba); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA"); return rc; } rc = FAPI_ATTR_GET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP, &i_target_mba, runtime_throttle_n_per_chip); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP"); return rc; } rc = FAPI_ATTR_GET(ATTR_MSS_MEM_THROTTLE_DENOMINATOR, &i_target_mba, runtime_throttle_d); if (rc) { FAPI_ERR("Error getting attribute ATTR_MSS_MEM_THROTTLE_DENOMINATOR"); return rc; } // Setup the RAS and CAS increments used in the throttling register ras_increment=0; cas_increment=1; // update output attributes rc = FAPI_ATTR_SET(ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA, &i_target_mba, runtime_throttle_n_per_mba); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP, &i_target_mba, runtime_throttle_n_per_chip); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR, &i_target_mba, runtime_throttle_d); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_THROTTLE_CONTROL_RAS_WEIGHT, &i_target_mba, ras_increment); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_THROTTLE_CONTROL_RAS_WEIGHT"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_THROTTLE_CONTROL_CAS_WEIGHT, &i_target_mba, cas_increment); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_THROTTLE_CONTROL_CAS_WEIGHT"); return rc; } FAPI_INF("*** mss_eff_config_thermal_throttles COMPLETE on %s ***", i_target_mba.toEcmdString()); return rc; }
// HWP entry point, comments in header fapi::ReturnCode proc_chiplet_scominit(const fapi::Target & i_target) { fapi::ReturnCode rc; uint32_t rc_ecmd = 0; fapi::TargetType target_type; std::vector<fapi::Target> initfile_targets; std::vector<fapi::Target> ex_targets; std::vector<fapi::Target> mcs_targets; uint8_t nx_enabled; uint8_t mcs_pos; uint8_t ex_pos; uint8_t num_ex_targets; uint8_t master_mcs_pos = 0xFF; fapi::Target master_mcs; uint8_t enable_xbus_resonant_clocking = 0x0; uint8_t i2c_slave_address = 0x0; uint8_t dual_capp_present = 0x0; ecmdDataBufferBase data(64); ecmdDataBufferBase cfam_data(32); ecmdDataBufferBase mask(64); bool is_master = false; // mark HWP entry FAPI_INF("proc_chiplet_scominit: Start"); do { rc = proc_check_master_sbe_seeprom(i_target, is_master); if (!rc.ok()) { FAPI_ERR("proc_cen_ref_clk_enable: Error from proc_check_master_sbe_seeprom"); break; } // obtain target type to determine which initfile(s) to execute target_type = i_target.getType(); // chip level target if (target_type == fapi::TARGET_TYPE_PROC_CHIP) { // execute FBC SCOM initfile initfile_targets.push_back(i_target); FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_FBC_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_FBC_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_FBC_IF, i_target.toEcmdString()); break; } // execute PSI SCOM initfile FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_PSI_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_PSI_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_PSI_IF, i_target.toEcmdString()); break; } // execute TP bridge SCOM initfile FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_TPBRIDGE_IF, i_target.toEcmdString()); break; } // query NX partial good attribute rc = FAPI_ATTR_GET(ATTR_PROC_NX_ENABLE, &i_target, nx_enabled); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_PROC_NX_ENABLE"); break; } // apply NX/AS SCOM initfiles only if partial good attribute is set if (nx_enabled == fapi::ENUM_ATTR_PROC_NX_ENABLE_ENABLE) { // execute NX SCOM initfile FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_NX_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_NX_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_NX_IF, i_target.toEcmdString()); break; } // execute CXA SCOM initfile FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_CXA_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_CXA_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_CXA_IF, i_target.toEcmdString()); break; } // configure CXA APC master LCO settings rc = fapiGetChildChiplets(i_target, fapi::TARGET_TYPE_EX_CHIPLET, ex_targets, fapi::TARGET_STATE_FUNCTIONAL); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiGetChildChiplets (EX) on %s", i_target.toEcmdString()); break; } // form valid LCO target list for (std::vector<fapi::Target>::iterator i = ex_targets.begin(); i != ex_targets.end(); i++) { // determine EX chiplet number rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*i), ex_pos); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS) on %s", i->toEcmdString()); break; } rc_ecmd |= data.setBit(ex_pos-((ex_pos < 8)?(1):(3))); } if (!rc.ok()) { break; } num_ex_targets = ex_targets.size(); rc_ecmd |= data.insertFromRight( num_ex_targets, CAPP_APC_MASTER_LCO_TARGET_MIN_START_BIT, (CAPP_APC_MASTER_LCO_TARGET_MIN_END_BIT- CAPP_APC_MASTER_LCO_TARGET_MIN_START_BIT+1)); if (rc_ecmd) { FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting APC Master LCO Target register data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, CAPP_APC_MASTER_LCO_TARGET_0x02013021, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (CAPP_APC_MASTER_LCO_TARGET_0x02013021) on %s", i_target.toEcmdString()); break; } // get dual CAPP presence attribute FAPI_DBG("proc_chiplet_scominit: Querying dual CAPP feature attribute"); rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_DUAL_CAPP_PRESENT, &i_target, dual_capp_present); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_CHIP_EC_FEATURE_DUAL_CAPP_PRESENT"); break; } if (dual_capp_present != 0) { rc = fapiPutScom(i_target, CAPP1_APC_MASTER_LCO_TARGET_0x020131A1, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (CAPP1_APC_MASTER_LCO_TARGET_0x020131A1) on %s", i_target.toEcmdString()); break; } } // execute AS SCOM initfile FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_AS_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_AS_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_AS_IF, i_target.toEcmdString()); break; } } else { FAPI_DBG("proc_chiplet_scominit: Skipping execution of %s/%s/%s (partial good)", PROC_CHIPLET_SCOMINIT_NX_IF, PROC_CHIPLET_SCOMINIT_CXA_IF, PROC_CHIPLET_SCOMINIT_AS_IF); } // conditionally enable I2C Slave rc = FAPI_ATTR_GET(ATTR_I2C_SLAVE_ADDRESS, &i_target, i2c_slave_address); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_I2C_SLAVE_ADDRESS on %s", i_target.toEcmdString()); break; } rc = fapiGetScom(i_target, I2C_SLAVE_CONFIG_REG_0x000D0000, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiGetScom error (I2C_SLAVE_CONFIG_REG_0x000D0000) on %s", i_target.toEcmdString()); break; } if (i2c_slave_address) { FAPI_DBG("proc_chiplet_scominit: I2C Slave enabled (%s) address = %d", i_target.toEcmdString(),i2c_slave_address); //set I2C address rc_ecmd |= data.insert(i2c_slave_address,0,7); // disable error state. when this is enabled and there // is an error from I2CS it locks up the I2CS and no // more operations are allowed unless cleared // through FSI. Not good for a FSPless system. rc_ecmd |= data.clearBit(23); // enable I2C interface rc_ecmd |= data.setBit(21); } else { FAPI_DBG("proc_chiplet_scominit: I2C Slave disabled (%s)", i_target.toEcmdString()); // disable I2C interface when attribute = 0x0 rc_ecmd |= data.clearBit(21); } if (rc_ecmd) { FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting I2C Slave register data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, I2C_SLAVE_CONFIG_REG_0x000D0000, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (I2C_SLAVE_CONFIG_REG_0x000D0000) on %s", i_target.toEcmdString()); break; } // conditionally enable resonant clocking for XBUS rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_XBUS_RESONANT_CLK_VALID, &i_target, enable_xbus_resonant_clocking); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error querying ATTR_CHIP_EC_FEATURE_XBUS_RESONANT_CLK_VALID on %s", i_target.toEcmdString()); break; } if (enable_xbus_resonant_clocking) { FAPI_DBG("proc_chiplet_scominit: Enabling XBUS resonant clocking"); rc = fapiGetScom(i_target, MBOX_FSIGP6_0x00050015, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiGetScom error (MBOX_FSIGP6_0x00050015) on %s", i_target.toEcmdString()); break; } rc_ecmd |= data.insertFromRight( XBUS_RESONANT_CLOCK_CONFIG, MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_START_BIT, (MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_END_BIT- MBOX_FSIGP6_XBUS_RESONANT_CLOCK_CONFIG_START_BIT+1)); if (rc_ecmd) { FAPI_ERR("proc_chiplet_scominit: Error 0x%x setting FSI GP6 register data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } if (is_master) { rc = fapiPutScom(i_target, MBOX_FSIGP6_0x00050015, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (MBOX_FSIGP6_0x00050015) on %s", i_target.toEcmdString()); break; } } else { cfam_data.insert(data, 0, 32, 0); rc = fapiPutCfamRegister(i_target, CFAM_FSI_GP6_0x00002815, cfam_data); if (rc) { FAPI_ERR("proc_cen_ref_clk_enable: fapiPutCfamRegister error (CFAM_FSI_GP8_0x00001017)"); break; } } } // execute A/X/PCI/DMI FIR init SCOM initfile FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_A_X_PCI_DMI_IF, i_target.toEcmdString()); break; } // execute NV scominit file uint8_t exist_NV = 0x00; rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_NV_PRESENT, &i_target, exist_NV); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error getting attribute value ATTR_CHIP_EC_FEATURE_NV_PRESENT"); break; } if (exist_NV) { FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_NPU_IF, i_target.toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_NPU_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_NPU_IF, i_target.toEcmdString()); break; } // cleanup FIR bit (NPU FIR bit 27) caused by NDL/NTL parity error rc_ecmd = data.flushTo1(); rc_ecmd = data.clearBit(NPU_FIR_NTL_DL2TL_PARITY_ERR_BIT); if (rc_ecmd) { FAPI_ERR("proc_chiplet_scominit: Error 0x%Xforming NPU FIR cleanup data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, NPU_FIR_AND_0x08013D81, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (NPU_FIR_AND_0x08013D81) on %s", i_target.toEcmdString()); break; } rc = fapiPutScom(i_target, NPU_FIR_MASK_AND_0x08013D84, data); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiPutScom error (NPU_FIR_MASK_AND_0x08013D84) on %s", i_target.toEcmdString()); break; } } else { FAPI_INF("proc_chiplet_scominit: NV link logic not present, scom initfile processing skipped"); } // determine set of functional MCS chiplets rc = fapiGetChildChiplets(i_target, fapi::TARGET_TYPE_MCS_CHIPLET, mcs_targets, fapi::TARGET_STATE_FUNCTIONAL); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiGetChildChiplets (MCS) on %s", i_target.toEcmdString()); break; } // apply MCS SCOM initfile only for functional chiplets for (std::vector<fapi::Target>::iterator i = mcs_targets.begin(); (i != mcs_targets.end()) && rc.ok(); i++) { // execute MCS SCOM initfile initfile_targets.clear(); initfile_targets.push_back(*i); initfile_targets.push_back(i_target); FAPI_INF("proc_chiplet_scominit: Executing %s on %s", PROC_CHIPLET_SCOMINIT_MCS_IF, i->toEcmdString()); FAPI_EXEC_HWP( rc, fapiHwpExecInitFile, initfile_targets, PROC_CHIPLET_SCOMINIT_MCS_IF); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from fapiHwpExecInitfile executing %s on %s", PROC_CHIPLET_SCOMINIT_MCS_IF, i->toEcmdString()); break; } // determine MCS position rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &(*i), mcs_pos); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: Error from FAPI_ATTR_GET (ATTR_CHIP_UNIT_POS) on %s", i->toEcmdString()); break; } if (mcs_pos < master_mcs_pos) { fapi::Target cen_target_unused; rc = fapiGetOtherSideOfMemChannel(*i, cen_target_unused, fapi::TARGET_STATE_FUNCTIONAL); // use return code only to indicate presence of connected Centaur, // do not propogate/emit error if not connected if (rc.ok()) { FAPI_DBG("Updating master_mcs_pos to %d", mcs_pos); FAPI_DBG(" Target: %s", cen_target_unused.toEcmdString()); master_mcs = *i; master_mcs_pos = mcs_pos; } else { rc = fapi::FAPI_RC_SUCCESS; } } } if (!rc.ok()) { break; } if (master_mcs.getType() == fapi::TARGET_TYPE_MCS_CHIPLET) { // set MCMODE0Q_ENABLE_CENTAUR_SYNC on first target only // (this bit is required to be set on at most one MCS/chip) rc_ecmd |= data.flushTo0(); rc_ecmd |= data.setBit(MCSMODE0_EN_CENTAUR_SYNC_BIT); rc_ecmd |= mask.setBit(MCSMODE0_EN_CENTAUR_SYNC_BIT); // check buffer manipulation return codes if (rc_ecmd) { FAPI_ERR("proc_chiplet_scominit: Error 0x%X setting up MCSMODE0 data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } // write register with updated content rc = fapiPutScomUnderMask(master_mcs, MCS_MCSMODE0_0x02011807, data, mask); if (!rc.ok()) { FAPI_ERR("proc_chiplet_scominit: fapiPutScomUnderMask error (MCS_MCSMODE0_0x02011807) on %s", master_mcs.toEcmdString()); break; } } } // unsupported target type else { FAPI_ERR("proc_chiplet_scominit: Unsupported target type"); const fapi::Target & TARGET = i_target; FAPI_SET_HWP_ERROR(rc, RC_PROC_CHIPLET_SCOMINIT_INVALID_TARGET); break; } } while(0); // mark HWP exit FAPI_INF("proc_chiplet_scominit: End"); return rc; }
/** * p8_pm_prep_for_reset Call underlying unit procedure to perform readiness for * reinitialization of PM complex. * * @param[in] i_primary_chip_target Primary Chip target which will be passed * to all the procedures * @param[in] i_secondary_chip_target Secondary Chip target will be passed for * pmc_init -reset only if it is DCM otherwise this should be NULL. * @param[in] i_mode (PM_RESET (hard - will kill the PMC); * PM_RESET_SOFT (will not fully reset the PMC)) * * @retval ECMD_SUCCESS * @retval ERROR defined in xml */ fapi::ReturnCode p8_pm_prep_for_reset( const fapi::Target &i_primary_chip_target, const fapi::Target &i_secondary_chip_target, uint32_t i_mode ) { fapi::ReturnCode rc; fapi::ReturnCode rc_hold; uint32_t e_rc = 0; std::vector<fapi::Target> l_exChiplets; ecmdDataBufferBase data(64); ecmdDataBufferBase mask(64); uint64_t address = 0; const char * PM_MODE_NAME_VAR; // Defines storage for PM_MODE_NAME bool b_special_wakeup_pri = false; bool b_special_wakeup_sec = false; fapi::Target dummy; do { FAPI_INF("p8_pm_prep_for_reset start ...."); uint8_t ipl_mode = 0; rc = FAPI_ATTR_GET(ATTR_IS_MPIPL, NULL, ipl_mode); if (!rc.ok()) { FAPI_ERR("fapiGetAttribute of ATTR_IS_MPIPL rc = 0x%x", (uint32_t)rc); break; } FAPI_INF("IPL mode = %s", ipl_mode ? "MPIPL" : "NORMAL"); if (i_mode == PM_RESET) { FAPI_INF("Hard reset detected"); } else if (i_mode == PM_RESET_SOFT) { FAPI_INF("Soft reset detected. Idle functions will not be affected"); } else { FAPI_ERR("Mode parameter value not supported: %u", i_mode); uint32_t & MODE = i_mode; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_PREP_UNSUPPORTED_MODE_ERR); break; } if ( i_secondary_chip_target.getType() == TARGET_TYPE_NONE ) { if ( i_primary_chip_target.getType() == TARGET_TYPE_NONE ) { FAPI_ERR("Set primay target properly for SCM " ); const fapi::Target PRIMARY_TARGET = i_primary_chip_target; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_PREP_TARGET_ERR); break; } FAPI_INF("Running on SCM"); } else { FAPI_INF("Running on DCM"); } // ****************************************************************** // Clear the Deep Exit Masks to allow Special Wake-up to occur // ****************************************************************** // Primary rc = clear_deep_exit_mask(i_primary_chip_target); if (rc) { FAPI_ERR("clear_deep_exit_mask: Failed for Primary Target %s", i_primary_chip_target.toEcmdString()); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = clear_deep_exit_mask(i_secondary_chip_target); if (rc) { FAPI_ERR("clear_deep_exit_mask: Failed for Secondary Target %s", i_secondary_chip_target.toEcmdString()); break; } } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "start of prep for reset"); if (!rc.ok()) { break; } // ****************************************************************** // Put all EX chiplets in special wakeup // ***************************************************************** // This is done before FIR masking to ensure that idle functions // are properly monitored // Primary rc = special_wakeup_all (i_primary_chip_target, true); if (rc) { FAPI_ERR("special_wakeup_all - Enable: Failed for Target %s", i_primary_chip_target.toEcmdString()); break; } b_special_wakeup_pri = true; rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after SPWKUP"); if (!rc.ok()) { break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = special_wakeup_all (i_secondary_chip_target, true); if (rc) { FAPI_ERR("special_wakeup_all - Enable: Failed for Target %s", i_secondary_chip_target.toEcmdString()); break; } b_special_wakeup_sec = true; rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after SPWKUP"); if (!rc.ok()) { break; } } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after special wake-up setting"); if (!rc.ok()) { break; } // ****************************************************************** // Mask the FIRs as error can occur in what follows // ****************************************************************** FAPI_INF("Executing:p8_pm_firinit in mode PM_RESET"); FAPI_EXEC_HWP(rc, p8_pm_firinit, i_primary_chip_target , i_mode ); if (rc) { FAPI_ERR("ERROR: p8_pm_firinit detected failed result"); break; } rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after Masking"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_pm_firinit, i_secondary_chip_target , PM_RESET ); if (rc) { FAPI_ERR("ERROR: p8_pm_firinit detected failed result"); break; } rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after Masking"); if (!rc.ok()) { break; } } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after FIR masking"); if (!rc.ok()) { break; } // ****************************************************************** // Disable PMC OCC HEARTBEAT before reset OCC // ****************************************************************** // Primary rc = fapiGetScom(i_primary_chip_target, PMC_OCC_HEARTBEAT_REG_0x00062066 , data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_OCC_HEARTBEAT_REG_0x00062066) failed."); break; } e_rc = data.clearBit(16); if (e_rc) { FAPI_ERR("ecmdDataBufferBase error setting up PMC_OCC_HEARTBEAT_REG_0x00062066 on master during reset"); rc.setEcmdError(e_rc); break; } rc = fapiPutScom(i_primary_chip_target, PMC_OCC_HEARTBEAT_REG_0x00062066 , data ); if (rc) { FAPI_ERR("fapiPutScom(PMC_OCC_HEARTBEAT_REG_0x00062066) failed."); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = fapiGetScom(i_secondary_chip_target, PMC_OCC_HEARTBEAT_REG_0x00062066 , data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_OCC_HEARTBEAT_REG_0x00062066) failed."); break; } e_rc = data.clearBit(16); if (e_rc) { FAPI_ERR("ecmdDataBufferBase error setting up PMC_OCC_HEARTBEAT_REG_0x00062066 on slave during reset"); rc.setEcmdError(e_rc); break; } rc = fapiPutScom(i_secondary_chip_target, PMC_OCC_HEARTBEAT_REG_0x00062066 , data ); if (rc) { FAPI_ERR("fapiPutScom(PMC_OCC_HEARTBEAT_REG_0x00062066) failed."); break; } } // ****************************************************************** // Put OCC PPC405 into reset safely // ****************************************************************** FAPI_INF("Put OCC PPC405 into reset safely"); FAPI_DBG("Executing: p8_occ_control.C"); FAPI_EXEC_HWP(rc, p8_occ_control, i_primary_chip_target, PPC405_RESET_SEQUENCE, 0); if (rc) { FAPI_ERR("p8_occ_control: Failed to prepare OCC for RESET. With rc = 0x%x", (uint32_t)rc); break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_occ_control, i_secondary_chip_target, PPC405_RESET_SEQUENCE, 0); if (rc) { FAPI_ERR("p8_occ_control: Failed to prepare OCC for RESET. With rc = 0x%x", (uint32_t)rc); break; } } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after OCC Reset"); if (!rc.ok()) { break; } // Check for xstops and recoverables rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after OCC Reset"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after OCC Reset"); if (!rc.ok()) { break; } } // ****************************************************************** // Force Vsafe value into voltage controller // ****************************************************************** FAPI_INF("Force Vsafe value into voltage controller"); FAPI_DBG("Executing: p8_pmc_force_vsafe.C"); // Primary // Secondary passed in for FFDC reasons upon error FAPI_EXEC_HWP(rc, p8_pmc_force_vsafe, i_primary_chip_target, i_secondary_chip_target); if (rc) { FAPI_ERR("Failed to force Vsafe value into voltage controller. With rc = 0x%x", (uint32_t)rc); break; } // Secondary // Primary passed in for FFDC reasons upon error if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_pmc_force_vsafe, i_secondary_chip_target, i_primary_chip_target); if (rc) { FAPI_ERR("Failed to force Vsafe value into voltage controller. With rc = 0x%x", (uint32_t)rc); break; } } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after force Vsafe"); if (!rc.ok()) { break; } // Check for xstops and recoverables rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after Force Vsafe"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after Force Vsafe"); if (!rc.ok()) { break; } } // ****************************************************************** // Prepare PCBS_PM for RESET // ****************************************************************** // - p8_pcbs_init internally loops over all enabled chiplets FAPI_INF("Prepare PCBSLV_PM for RESET"); FAPI_DBG("Executing: p8_pcbs_init.C"); // Primary FAPI_EXEC_HWP(rc, p8_pcbs_init, i_primary_chip_target, PM_RESET); if (rc) { FAPI_ERR("p8_pcbs_init: Failed to prepare PCBSLV_PM for RESET. With rc = 0x%x", (uint32_t)rc); break; } address = READ_GLOBAL_RECOV_FIR_0x570F001C; GETSCOM(rc, i_primary_chip_target, address, data); if (data.getNumBitsSet(0,64)) { FAPI_INF("Recoverable attention is **ACTIVE** in prep_for_reset after PCBS reset"); } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_pcbs_init, i_secondary_chip_target, PM_RESET); if (rc) { FAPI_ERR("p8_pcbs_init: Failed to prepare PCBSLV_PM for RESET. With rc = 0x%x", (uint32_t)rc); break; } GETSCOM(rc, i_secondary_chip_target, address, data); if (data.getNumBitsSet(0,64)) { FAPI_INF("Recoverable attention is **ACTIVE** in prep_for_reset after PCBS reset"); } } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after PCBS reset"); if (!rc.ok()) { break; } // Check for xstops and recoverables rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after PCBS reset"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after PCBS reset"); if (!rc.ok()) { break; } } // ****************************************************************** // Reset PMC // ****************************************************************** FAPI_INF("Issue reset to PMC"); FAPI_DBG("Executing: p8_pmc_init"); FAPI_EXEC_HWP(rc, p8_pmc_init, i_primary_chip_target, i_secondary_chip_target, i_mode); if (rc) { FAPI_ERR("p8_pmc_init: Failed to issue PMC reset. With rc = 0x%x", (uint32_t)rc); break; } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after PMC reset"); if (!rc.ok()) { break; } // ****************************************************************** // As the PMC reset kills ALL of the configuration, the idle portion // must be reestablished to allow that portion to operate. This is // what p8_poreslw_init -init does. Additionally, this lets us drop // special wake-up before exiting. // ****************************************************************** // - call p8_poreslw_init.C *chiptarget, ENUM:PM_INIT // FAPI_INF("Re-establish PMC Idle configuration"); FAPI_DBG("Executing: p8_poreslw_init in mode %s", PM_MODE_NAME(PM_INIT_PMC)); // Primary FAPI_EXEC_HWP(rc, p8_poreslw_init, i_primary_chip_target, PM_INIT_PMC); if (rc) { FAPI_ERR("p8_poreslw_init: Failed to to reinialize the idle portion of the PMC. With rc = 0x%x", (uint32_t)rc); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_poreslw_init, i_secondary_chip_target, PM_INIT_PMC); if (rc) { FAPI_ERR("p8_poreslw_init: Failed to to reinialize the idle portion of the PMC. With rc = 0x%x", (uint32_t)rc); break; } } // Check for xstops and recoverables rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after PMC and SLW reinit"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after PMC and SLW reinit"); if (!rc.ok()) { break; } } // ****************************************************************** // Issue reset to PSS macro // ****************************************************************** FAPI_INF("Issue reset to PSS macro"); FAPI_DBG("Executing: p8_pss_init.C"); // Primary FAPI_EXEC_HWP(rc, p8_pss_init, i_primary_chip_target, PM_RESET); if (rc) { FAPI_ERR("p8_pss_init: Failed to issue reset to PSS macro. With rc = 0x%x", (uint32_t)rc); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_DBG("FAPI_EXEC_HWP(rc, p8_pss_init, i_secondary_chip_target, PM_RESET);"); FAPI_EXEC_HWP(rc, p8_pss_init, i_secondary_chip_target, PM_RESET); if (rc) { FAPI_ERR("p8_pss_init: Failed to issue reset to PSS macro. With rc = 0x%x", (uint32_t)rc); break; } } // ****************************************************************** // Issue reset to PORE General Purpose Engine // ****************************************************************** FAPI_INF("Issue reset to PORE General Purpose Engine"); FAPI_DBG("Executing: p8_poregpe_init.C"); // Primary FAPI_EXEC_HWP(rc, p8_poregpe_init, i_primary_chip_target, PM_RESET, GPEALL ); if (rc) { FAPI_ERR("p8_poregpe_init: Failed to issue reset to PORE General Purpose Engine. With rc = 0x%x", (uint32_t)rc); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_poregpe_init, i_secondary_chip_target, PM_RESET, GPEALL ); if (rc) { FAPI_ERR("p8_poregpe_init: Failed to issue reset to PORE General Purpose Engine. With rc = 0x%x", (uint32_t)rc); break; } } // ****************************************************************** // Issue reset to PBA // ****************************************************************** // Note: this voids the channel used by the SLW engine FAPI_INF("Issue reset to PBA"); FAPI_DBG("Executing: p8_pba_init.C"); // Primary FAPI_EXEC_HWP(rc, p8_pba_init, i_primary_chip_target, PM_RESET ); if (rc) { FAPI_ERR("p8_pba_init: Failed to issue reset to PBA. With rc = 0x%x", (uint32_t)rc); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_pba_init, i_secondary_chip_target, PM_RESET ); if (rc) { FAPI_ERR("p8_pba_init: Failed to issue reset to PBA. With rc = 0x%x", (uint32_t)rc); break; } } // Check for xstops and recoverables rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after PBA reset"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after PBA reset"); if (!rc.ok()) { break; } } // ****************************************************************** // Issue reset to OCC-SRAM // ****************************************************************** FAPI_INF("Issue reset to OCC-SRAM"); FAPI_DBG("Executing: p8_occ_sram_init.C"); // Primary FAPI_EXEC_HWP(rc, p8_occ_sram_init, i_primary_chip_target, PM_RESET ); if (rc) { FAPI_ERR("p8_occ_sram_init: Failed to issue reset to OCC-SRAM. With rc = 0x%x", (uint32_t)rc); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_occ_sram_init, i_secondary_chip_target, PM_RESET ); if (rc) { FAPI_ERR("p8_occ_sram_init: Failed to issue reset to OCC-SRAM. With rc = 0x%x", (uint32_t)rc); break; } } // ****************************************************************** // Issue reset to OCB // ****************************************************************** FAPI_INF("Issue reset to OCB"); FAPI_DBG("Executing: p8_ocb_init.C"); // Primary FAPI_EXEC_HWP(rc, p8_ocb_init, i_primary_chip_target, PM_RESET,0 , 0, 0, 0, 0, 0 ); if (rc) { FAPI_ERR("p8_ocb_init: Failed to issue reset to OCB. With rc = 0x%x", (uint32_t)rc); break; } // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { FAPI_EXEC_HWP(rc, p8_ocb_init, i_secondary_chip_target, PM_RESET,0 , 0, 0, 0, 0, 0 ); if (rc) { FAPI_ERR("p8_ocb_init: Failed to issue reset to OCB. With rc = 0x%x", (uint32_t)rc); break; } } // Check for xstops and recoverables rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after OCB reset"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after OCB reset"); if (!rc.ok()) { break; } } // ****************************************************************** // Remove the EX chiplet special wakeups // ***************************************************************** // Primary rc = special_wakeup_all (i_primary_chip_target, false); if (rc) { FAPI_ERR("special_wakeup_all - Disable: Failed for Target %s", i_primary_chip_target.toEcmdString()); break; } b_special_wakeup_pri = false; // Secondary if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = special_wakeup_all (i_secondary_chip_target, false); if (rc) { FAPI_ERR("special_wakeup_all - Disable: Failed for Target %s", i_secondary_chip_target.toEcmdString()); break; } b_special_wakeup_sec = false; } // ****************************************************************** // FSM trace // ****************************************************************** rc = p4rs_pcbs_fsm_trace (i_primary_chip_target, i_secondary_chip_target, "after special wake-up clearing"); if (!rc.ok()) { break; } // Check for xstops and recoverables rc = p8_pm_glob_fir_trace (i_primary_chip_target, "after special wake-up clearing"); if (!rc.ok()) { break; } if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE ) { rc = p8_pm_glob_fir_trace (i_secondary_chip_target, "after special wake-up clearing"); if (!rc.ok()) { break; } } } while(0); // Clear special wakeups that might have been set before a subsequent // error occured. Only attempts them on targets that have the boolean // flag set that they were successfully put into special wakeup. if (!rc.ok()) { // Save the original RC rc_hold = rc; do { // Primary if (b_special_wakeup_pri) { // Primary rc = special_wakeup_all (i_primary_chip_target, false); if (rc) { FAPI_ERR("special_wakeup_all - Disable: Failed during cleanup from a previous error for Target %s", i_primary_chip_target.toEcmdString()); FAPI_ERR("special_wakeup_all - Disable: The original error is being returned"); fapiLogError(rc, fapi::FAPI_ERRL_SEV_RECOVERED); break; } } // Secondary if (b_special_wakeup_sec) { rc = special_wakeup_all (i_secondary_chip_target, false); if (rc) { FAPI_ERR("special_wakeup_all - Disable: Failed during cleanup from a previous error for Target %s", i_primary_chip_target.toEcmdString()); FAPI_ERR("special_wakeup_all - Disable: The original error is being returned"); fapiLogError(rc, fapi::FAPI_ERRL_SEV_RECOVERED); break; } } } while(0); // Restore the original RC rc = rc_hold; } FAPI_INF("p8_pm_prep_for_reset end ...."); return rc; } // Procedure
/** * @brief Execute procedures and steps necessary * to load OCC data in specified processor * * @param[in] i_target Target proc to load * @param[in] i_homerVirtAddrBase Virtual * address of current * proc's HOMER * @param[in] i_homerPhysAddrBase Physical * address of current * proc's HOMER * * @return errlHndl_t Error log image load failed */ errlHndl_t loadOCC(TARGETING::Target* i_target, uint64_t i_homerPhysAddr, uint64_t i_homerVirtAddr, uint64_t i_commonPhysAddr) { errlHndl_t l_errl = NULL; TRACFCOMP( g_fapiTd, ENTER_MRK"loadOCC" ); do{ // Remember where we put things if( i_target ) { i_target->setAttr<ATTR_HOMER_PHYS_ADDR>(i_homerPhysAddr); i_target->setAttr<ATTR_HOMER_VIRT_ADDR>(i_homerVirtAddr); } // cast OUR type of target to a FAPI type of target. const fapi::Target l_fapiTarg(fapi::TARGET_TYPE_PROC_CHIP, (const_cast<Target*>(i_target))); TRACFCOMP( g_fapiTd, "FapiTarget: %s",l_fapiTarg.toEcmdString()); //============================== //Setup for OCC Load //============================== // BAR0 is the Entire HOMER (start of HOMER contains OCC base Image) // Bar size is in MB, obtained value of 4MB from Greg Still TRACUCOMP( g_fapiImpTd, INFO_MRK"loadOCC: OCC Address: 0x%.8X, size=0x%.8X", i_homerPhysAddr, VMM_HOMER_INSTANCE_SIZE_IN_MB); FAPI_INVOKE_HWP( l_errl, p8_pba_bar_config, l_fapiTarg, 0, i_homerPhysAddr, VMM_HOMER_INSTANCE_SIZE_IN_MB, PBA_CMD_SCOPE_NODAL ); if (l_errl) { TRACFCOMP( g_fapiImpTd, ERR_MRK"loadOCC: Bar0 config failed!" ); l_errl->collectTrace(FAPI_TRACE_NAME,256); l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); break; } // BAR1 is what OCC uses to talk to the Centaur // Bar size is in MB uint64_t centaur_addr = i_target->getAttr<ATTR_IBSCOM_PROC_BASE_ADDR>(); FAPI_INVOKE_HWP( l_errl, p8_pba_bar_config, l_fapiTarg, 1, //i_index centaur_addr, //i_pba_bar_addr (uint64_t)OCC_IBSCOM_RANGE_IN_MB, //i_pba_bar_size PBA_CMD_SCOPE_NODAL ); //i_pba_cmd_scope if ( l_errl ) { TRACFCOMP( g_fapiImpTd, ERR_MRK"loadOCC: Bar1 config failed!" ); l_errl->collectTrace(FAPI_TRACE_NAME,256); l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); break; } // BAR3 is the OCC Common Area // Bar size is in MB, obtained value of 8MB from Tim Hallett TRACUCOMP( g_fapiImpTd, INFO_MRK"loadOCC: OCC Common Addr: 0x%.8X,size=0x%.8X", i_commonPhysAddr,VMM_OCC_COMMON_SIZE_IN_MB); FAPI_INVOKE_HWP( l_errl, p8_pba_bar_config, l_fapiTarg, 3, i_commonPhysAddr, VMM_OCC_COMMON_SIZE_IN_MB, PBA_CMD_SCOPE_NODAL ); if ( l_errl != NULL ) { TRACFCOMP( g_fapiImpTd, ERR_MRK"loadOCC: Bar3 config failed!" ); l_errl->collectTrace(FAPI_TRACE_NAME,256); l_errl->collectTrace(FAPI_IMP_TRACE_NAME,256); break; } //============================== //Load the OCC HOMER image //============================== void* occVirt = reinterpret_cast<void *>(i_homerVirtAddr); l_errl = loadOCCImageToHomer( occVirt ); if( l_errl != NULL ) { TRACFCOMP(g_fapiImpTd, ERR_MRK"loadOCC: loadOCCImageToHomer failed!"); break; } }while(0); TRACFCOMP( g_fapiTd, EXIT_MRK"loadOCC"); return l_errl; }
//------------------------------------------------------------------------------ // name: proc_mpipl_chip_cleanup //------------------------------------------------------------------------------ // purpose: // To enable MCD recovery // // Note: PHBs are left in ETU reset state after executing proc_mpipl_nest_cleanup, which runs before this procedure. PHYP releases PHBs from ETU reset post HostBoot IPL. // // SCOM regs // // 1) MCD even recovery control register // 0000000002013410 (SCOM) // bit 0 (MCD_REC_EVEN_ENABLE): 0 to 1 transition needed to start, reset to 0 at end of request. // bit 5 (MCD_REC_EVEN_REQ_PEND) // // // 2) MCD odd recovery control register // 0000000002013411 (SCOM) // bit 0 (MCD_REC_ODD_ENABLE): 0 to 1 transition needed to start, reset to 0 at end of request. // bit 5 (MCD_REC_ODD_REQ_PEND) // // 3) Clear PCI Nest FIR registers // 02012000 (SCOM) // 02012400 (SCOM) // 02012800 (SCOM) // // parameters: // 'i_target' is reference to chip target // // returns: // FAPI_RC_SUCCESS (success, MCD recovery enabled for odd and even slices) // // RC_MCD_RECOVERY_NOT_DISABLED_RC (MCD recovery for even or odd slice is not disabled; therefore can't re-enable MCD recovery) // (Note: refer to file eclipz/chips/p8/working/procedures/xml/error_info/proc_mpipl_chip_cleanup_errors.xml) // // getscom/putscom fapi errors // fapi error assigned from eCMD function failure // //------------------------------------------------------------------------------ fapi::ReturnCode proc_mpipl_chip_cleanup(const fapi::Target &i_target){ const char *procedureName = "proc_mpipl_chip_cleanup"; //Name of this procedure fapi::ReturnCode rc; //fapi return code value uint32_t rc_ecmd = 0; //ecmd return code value const uint32_t data_size = 64; //Size of data buffer const int MAX_MCD_DIRS = 2; //Max of 2 MCD Directories (even and odd) ecmdDataBufferBase fsi_data[MAX_MCD_DIRS]; const uint64_t ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[MAX_MCD_DIRS] = { 0x0000000002013410, //MCD even recovery control register address 0x0000000002013411 //MCD odd recovery control register address }; const uint32_t MCD_RECOVERY_CTRL_REG_BIT_POS0 = 0; //Bit 0 of MCD even and odd recovery control regs const char *ARY_MCD_DIR_STRS[MAX_MCD_DIRS] = { "Even", //Ptr to char string "Even" for even MCD "Odd" //Ptr to char string "Odd" for odd MCD }; const int MAX_PHBS = 3; const uint64_t PCI_NEST_FIR_REG_ADDRS[MAX_PHBS] = { 0x02012000, 0x02012400, 0x02012800 }; do { //Set bit length for 64-bit buffers rc_ecmd = fsi_data[0].setBitLength(data_size); rc_ecmd |= fsi_data[1].setBitLength(data_size); if(rc_ecmd) { rc.setEcmdError(rc_ecmd); break; } //Verify MCD recovery was previously disabled for even and odd slices //If not, this is an error condition for (int counter = 0; counter < MAX_MCD_DIRS; counter++) { FAPI_DBG("Verifying MCD %s Recovery is disabled, target=%s", ARY_MCD_DIR_STRS[counter], i_target.toEcmdString()); //Get data from MCD Even or Odd Recovery Ctrl reg rc = fapiGetScom(i_target, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], fsi_data[counter]); if (!rc.ok()) { FAPI_ERR("%s: fapiGetScom error (addr: 0x%08llX), target=%s", procedureName, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], i_target.toEcmdString()); break; } //Check whether bit 0 is 0, meaning MCD recovery is disabled as expected if( fsi_data[counter].getBit(MCD_RECOVERY_CTRL_REG_BIT_POS0) ) { FAPI_ERR("%s: MCD %s Recovery not disabled as expected, target=%s", procedureName, ARY_MCD_DIR_STRS[counter], i_target.toEcmdString()); const fapi::Target & CHIP_TARGET = i_target; const uint64_t & MCD_RECOV_CTRL_REG_ADDR = ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter]; ecmdDataBufferBase & MCD_RECOV_CTRL_REG_DATA = fsi_data[counter]; FAPI_SET_HWP_ERROR(rc, RC_MPIPL_MCD_RECOVERY_NOT_DISABLED_RC); break; } } if(!rc.ok()) { break; } //Assert bit 0 of MCD Recovery Ctrl regs to enable MCD recovery for (int counter = 0; counter < MAX_MCD_DIRS; counter++) { FAPI_DBG("Enabling MCD %s Recovery, target=%s", ARY_MCD_DIR_STRS[counter], i_target.toEcmdString()); //Assert bit 0 of MCD Even or Odd Recovery Control reg to enable recovery rc_ecmd = fsi_data[counter].setBit(MCD_RECOVERY_CTRL_REG_BIT_POS0 ); if(rc_ecmd) { FAPI_ERR("%s: Error (%u) asserting bit pos %u in ecmdDataBufferBase that stores value of MCD %s Recovery Control reg (addr: 0x%08llX), target=%s", procedureName, rc_ecmd, MCD_RECOVERY_CTRL_REG_BIT_POS0, ARY_MCD_DIR_STRS[counter], ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], i_target.toEcmdString()); rc.setEcmdError(rc_ecmd); break; } //Write data to MCD Even or Odd Recovery Control reg rc = fapiPutScom(i_target, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], fsi_data[counter]); if (!rc.ok()) { FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX), target=%s", procedureName, ARY_MCD_RECOVERY_CTRL_REGS_ADDRS[counter], i_target.toEcmdString()); break; } } if(!rc.ok()) { break; } // SW227429: clear PCI Nest FIR registers // hostboot is blindly sending EOIs in order to ensure no interrupts are pending when PHYP starts up again // with ETU held in reset, these get trapped in PCI and force a freeze to occur (PCI Nest FIR(14)) // clearing the FIR should remove the freeze condition rc_ecmd = fsi_data[0].flushTo0(); if (rc_ecmd) { FAPI_ERR("%s: Error (%u) forming PCI Nest FIR clear data buffer, target=%s", procedureName, rc_ecmd, i_target.toEcmdString()); rc.setEcmdError(rc_ecmd); break; } for (int counter = 0; counter < MAX_PHBS; counter++) { FAPI_DBG("Clearing PCI%d Nest FIR, target=%s", counter, i_target.toEcmdString()); rc = fapiPutScom(i_target, PCI_NEST_FIR_REG_ADDRS[counter], fsi_data[0]); if (!rc.ok()) { FAPI_ERR("%s: fapiPutScom error (addr: 0x%08llX), target=%s", procedureName, PCI_NEST_FIR_REG_ADDRS[counter], i_target.toEcmdString()); break; } } } while(0); FAPI_IMP("Exiting %s", procedureName); return rc; }
/// \retval PM_SUCCESS if something good happens, /// \retval PM_PROCPM_SPCWKUP* otherwise fapi::ReturnCode p8_cpu_special_wakeup( const fapi::Target& i_ex_target, PROC_SPCWKUP_OPS i_operation , PROC_SPCWKUP_ENTITY i_entity ) { fapi::ReturnCode rc; fapi::ReturnCode oha_rc; uint32_t e_rc = 0; ecmdDataBufferBase data(64); ecmdDataBufferBase fsi_data(64); ecmdDataBufferBase polldata(64); fapi::Target l_parentTarget; uint8_t attr_chip_unit_pos = 0; const char* PROC_SPCWKUP_ENTITY_NAMES[] = { "HOST", "FSP", "OCC", "PHYP", "SPW_ALL" }; const char* PROC_SPCWKUP_OPS_NAMES[] = { "DISABLE", "ENABLE", "INIT" }; uint32_t special_wakeup_max_polls; /// Time (binary in milliseconds) for the first poll check (running/nap /// case. /// uint32_t special_wakeup_quick_poll_time = 1; /// Get an attribute that defines the maximum special wake-up polling /// timing (binary in milliseconds). /// Increased timeout to 200ms - 6/10/13 uint32_t special_wakeup_timeout = 200; /// Get an attribute that defines the special wake-up polling interval /// (binary in milliseconds). uint32_t special_wakeup_poll_interval = 5; uint32_t pollcount = 0; uint32_t count = 0; std::vector<fapi::Target> l_chiplets; std::vector<Target>::iterator itr; uint8_t oha_spwkup_flag = 0; uint8_t ignore_xstop_flag = 0; bool poll_during_xstop_flag = false; bool xstop_flag = false; bool bSpwuSetOnEntry = false; uint8_t inst_pm_state = INST_PM_STATE_UNDEFINED; //-------------------------------------------------------------------------- // Read the counts of different ENTITY (FSP,OCC,PHYP) from the Attributes //-------------------------------------------------------------------------- uint32_t phyp_spwkup_count = 0; uint32_t fsp_spwkup_count = 0; uint32_t occ_spwkup_count = 0; uint64_t spwkup_address = 0; uint64_t history_address = 0; // detect AISS capaiblity uint8_t chipHasAISSSWUP = 0; do { FAPI_INF("Executing p8_cpu_special_wakeup %s for %s ...", PROC_SPCWKUP_OPS_NAMES[i_operation], PROC_SPCWKUP_ENTITY_NAMES[i_entity]); // Initialize the attributes to 0. if (i_operation == SPCWKUP_INIT) { FAPI_INF("Processing target %s", i_ex_target.toEcmdString()); FAPI_INF("Initializing ATTR_PM_SPWUP_FSP"); rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_FSP, &i_ex_target, fsp_spwkup_count); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_FSP with rc = 0x%x", (uint32_t)rc); break ; } FAPI_INF("Initializing ATTR_PM_SPWUP_OCC"); rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_OCC, &i_ex_target, occ_spwkup_count); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_OCC with rc = 0x%x", (uint32_t)rc); break; } FAPI_INF("Initializing ATTR_PM_SPWUP_PHYP"); rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_PHYP, &i_ex_target, phyp_spwkup_count); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_PHYP with rc = 0x%x", (uint32_t)rc); break; } FAPI_INF("Initializing ATTR_PM_SPWUP_OHA_FLAG"); rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_OHA_FLAG, &i_ex_target, oha_spwkup_flag); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_OHA_FLAG with rc = 0x%x", (uint32_t)rc); break; } FAPI_INF("Initializing ATTR_PM_SPWUP_IGNORE_XSTOP_FLAG"); rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_IGNORE_XSTOP_FLAG, &i_ex_target, ignore_xstop_flag); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_IGNORE_XSTOP_FLAG with rc = 0x%x", (uint32_t)rc); break ; } // Leave the procedure break; } //-------------------------------------------------------------------------- // Checking the ENTITY who raised this OPERATION //-------------------------------------------------------------------------- // Get the parent chip to target the registers rc = fapiGetParentChip(i_ex_target, l_parentTarget); if (rc) { break; // throw error } // Get the core number rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_ex_target, attr_chip_unit_pos); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_CHIP_UNIT_POS with rc = 0x%x", (uint32_t)rc); break; } FAPI_DBG("Core number = %d", attr_chip_unit_pos); // Read the Attributes to know the Special_wake counts from each entity // This should be different for different EX chiplets. rc = FAPI_ATTR_GET(ATTR_PM_SPWUP_FSP, &i_ex_target, fsp_spwkup_count); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_SPWUP_FSP with rc = 0x%x", (uint32_t)rc); break; } rc = FAPI_ATTR_GET(ATTR_PM_SPWUP_OCC, &i_ex_target, occ_spwkup_count ); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_SPWUP_OCC with rc = 0x%x", (uint32_t)rc); break; } rc = FAPI_ATTR_GET(ATTR_PM_SPWUP_PHYP,&i_ex_target , phyp_spwkup_count ); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_SPWUP_PHYP with rc = 0x%x", (uint32_t)rc); break; } /// Calculate the maximum number of polls until a timeout is thrown special_wakeup_max_polls = special_wakeup_timeout / special_wakeup_poll_interval; // Process counts based on the calling entity if (i_entity == OCC) { count = occ_spwkup_count ; FAPI_INF("OCC count before = %d" , count); spwkup_address = PM_SPECIAL_WKUP_OCC_0x100F010C; history_address = EX_PMSTATEHISTOCC_REG_0x100F0112; } else if (i_entity == FSP) { count = fsp_spwkup_count ; FAPI_INF("FSP count before = %d" , count); spwkup_address = PM_SPECIAL_WKUP_FSP_0x100F010B; history_address = EX_PMSTATEHISTFSP_REG_0x100F0111; } else if (i_entity == PHYP) { count = phyp_spwkup_count ; FAPI_INF("PHYP count before = %d" , count); spwkup_address = PM_SPECIAL_WKUP_PHYP_0x100F010D; history_address = EX_PMSTATEHISTPHYP_REG_0x100F0110; } else { FAPI_ERR("Unknown entity passed to proc_special_wakeup. Entity %x ....", i_entity); // I_ENTITY = i_entity; PROC_SPCWKUP_ENTITY & I_ENTITY = i_entity ; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_SPCWKUP_CODE_BAD_ENTITY); break; } ///////////////////////////////////////////////////////////////////////////// // Checking the type of OPERATION and process the request ///////////////////////////////////////////////////////////////////////////// rc=fapiGetScom(i_ex_target, EX_PMGP0_0x100F0100, data); if(rc) { break; } if (i_operation == SPCWKUP_ENABLE) { // If the OHA flag is set, then any subsequent calls to the this // procedure must return a "good" response or else an infinite // loop results for any calling algorithm that first sets // special wake-up, does a SCOM, and then clears special // wake-up. rc = FAPI_ATTR_GET( ATTR_PM_SPWUP_OHA_FLAG, &i_ex_target, oha_spwkup_flag); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_SPWUP_OHA_FLAG with rc = 0x%x", (uint32_t)rc); break; } if (oha_spwkup_flag) { FAPI_INF("OHA special wakeup flag is set so returning with good response to break recursion. Counts are NOT updated."); // This is a purposeful mid-procedure return return rc; } // Determine if xstop checking should be ignored base on a caller // set attribute. // // This is used during MPIPL clean-up to a core to clear FIRs that // will eventually clear the xstop condition. However, to do so // needs the xstop check to not keep the special wake-up operation // from happening. rc = FAPI_ATTR_GET( ATTR_PM_SPWUP_IGNORE_XSTOP_FLAG, &i_ex_target, ignore_xstop_flag); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_SPWUP_IGNORE_XSTOP_FLAG with rc = 0x%x", (uint32_t)rc); break ; } FAPI_INF("Ignore XSTOP: %s", (ignore_xstop_flag ? "YES" : "NO")); // Read system checkstop indicator GETSCOM(rc, l_parentTarget, PCBMS_INTERRUPT_TYPE_REG_0x000F001A, data); if( data.isBitSet( 2 ) ) { FAPI_INF( "Checkstop present" ); xstop_flag = true; } // Error out if system is checkstopped and not told to ignore it if (!ignore_xstop_flag && xstop_flag) { FAPI_ERR( "This chip is xstopped and the attribute ATTR_PM_SPWUP_IGNORE_XSTOP_FLAG is NOT set" ); const uint64_t& PCBSINTRTYPE = data.getDoubleWord(0); const uint8_t & ATTRIGNOREXSTOP = ignore_xstop_flag; const fapi::Target & EX_TARGET = i_ex_target; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_CHKSTOP); break; } // Proceed FAPI_INF("Setting Special Wake-up ...") ; if (count == 0) { GETSCOM(rc, i_ex_target, spwkup_address, data); //cmo-20140710: Make a note of spwu is already asserted. if (data.isBitSet(0)) bSpwuSetOnEntry = true; // Due to rogue direct hw access. else bSpwuSetOnEntry = false; // Just goodness.. e_rc = data.flushTo0(); e_rc |= data.setBit(0); E_RC_CHECK(e_rc, rc); PUTSCOM(rc, i_ex_target, spwkup_address, data); // Determine whether to poll for completion of Special wake-up. // Running and Nap - can alsways be polled as these are not // dependent on an xstop condition. // Sleep and Winkle - poll only if not in an xstop condition // Get the IPMS state rc = ex_determine_inst_pm_state(i_ex_target, 10000, 1, inst_pm_state); if (!rc.ok() && inst_pm_state!=INST_PM_STATE_UNRESOLVED) { FAPI_ERR("ex_determine_inst_pm_state() failed w/rc=0x%x", (uint32_t)rc); break; } FAPI_DBG("IPMS State = 0x%x", inst_pm_state); switch(inst_pm_state) { case INST_PM_STATE_RUN : // Running case INST_PM_STATE_RUN_OHA_ENTRY : // OHA purging idle entry case INST_PM_STATE_NAP_STATIC : // Nap poll_during_xstop_flag = true; break; default : // Any other IPMS state poll_during_xstop_flag = false; break; } // Poll for completion if conditions are right if ( (!xstop_flag) || (xstop_flag && poll_during_xstop_flag) ) { // poll for the set completion pollcount = 0; e_rc=data.flushTo0(); E_RC_CHECK(e_rc, rc); while (data.isBitClear(31) && pollcount < special_wakeup_max_polls) { GETSCOM(rc, i_ex_target, EX_PMGP0_0x100F0100, data); FAPI_DBG(" Loop get for PMGP0(31) to goto 1 => 0x%016llx", data.getDoubleWord(0)); rc = fapiDelay(special_wakeup_poll_interval*1000, 1000000); if (rc) { break; } pollcount ++ ; } if (!rc.ok()) { break; } rc = FAPI_ATTR_GET(ATTR_CHIP_EC_FEATURE_AISS_SPECIAL_WAKEUP, &i_ex_target, chipHasAISSSWUP); if (rc) { FAPI_ERR("Error querying Chip EC feature: " "ATTR_CHIP_EC_FEATURE_PCBS_ERR_RESET"); break; } FAPI_INF("AISS Special Wake-up fix is %sbeing performed", (chipHasAISSSWUP ? "NOT " : "")); if (!chipHasAISSSWUP) { // Workaround for HW255321 start here // at timeout time: // - check for existing external interrupts or malf alerts pending : PMGP0 bit52 // AND if OHA is in the AISS-FSM-state P7_SEQ_WAIT_INT_PENDING EX_OHA_RO_STATUS_REG_0x1002000B // If yes - then OHA hangs // To leave this FSM state: // - Set Bit 9 of OHA_ARCH_IDLE_STATE_REG( RESET_IDLE_STATE_SEQUENCER). EX_OHA_ARCH_IDLE_STATE_REG_RWx10020011 // This resets the idle sequencer and force OHA into the DO_NOTHING_STATE ...should be completed in the next cycle // // Continue further down and check special_wakeup completion by checking bit31 of EX_PMGP0_0x100F0100 // If set then is OHA awake else error GETSCOM(rc, i_ex_target, EX_PMGP0_0x100F0100, data); if (data.isBitClear(31) && data.isBitSet(52) ) { FAPI_DBG("Timed out setting Special wakeup with regular wake-up available, the logical OR of external interrupt and malfunction alert ... "); FAPI_DBG("Checking for Hang-Situation in AISS-FSM-State P7_SEQ_WAIT_INT_PENDING ... "); FAPI_DBG("Special Wake-up Done NOT asserted (PMGP0(31,52)!! =>0x%016llx", data.getDoubleWord(0)); oha_spwkup_flag = 1; rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_OHA_FLAG, &i_ex_target, oha_spwkup_flag); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_OHA_FLAG with rc = 0x%x", (uint32_t)rc); break; } FAPI_INF("Set OHA special wakeup flag"); // Check now if OHA is in the AISS-FSM-state P7_SEQ_WAIT_INT_PENDING EX_OHA_RO_STATUS_REG_0x1002000B (bit 13-19) 0b0011100 GETSCOM(rc, i_ex_target, EX_OHA_RO_STATUS_REG_0x1002000B, data); FAPI_DBG("\tCURRENT_AISS_FSM_STATE_VECTOR (OHA_RO_STATUS(13:19) => 0x%016llx", data.getDoubleWord(0)); if (data.isBitClear(13) && // 0 data.isBitClear(14) && // 0 data.isBitSet(15) && // 1 data.isBitSet(16) && // 1 data.isBitSet(17) && // 1 data.isBitClear(18) && // 0 data.isBitClear(19) ) // 0 { FAPI_DBG("OHA hanging in AISS-FSM-state P7_SEQ_WAIT_INT_PENDING (0b11100) (OHA_RO_STATUS_REG(13:19) => 0x%016llx", data.getDoubleWord(0)); FAPI_DBG("Start reset of IDLE STATE SEQUENCER: Set OHA_ARCH_IDLE_STATE_REG(9)"); GETSCOM(rc, i_ex_target, EX_OHA_ARCH_IDLE_STATE_REG_RWx10020011, data); FAPI_DBG("\tEX_OHA_ARCH_IDLE_STATE_REG_RWx10020011 : 0x%016llx", data.getDoubleWord(0)); //Set RESET_IDLE_STATE_SEQUENCER ... Bit 9 of OHA_ARCH_IDLE_STATE_REG e_rc=data.setBit(9); E_RC_CHECK(e_rc, rc); PUTSCOM(rc, i_ex_target, EX_OHA_ARCH_IDLE_STATE_REG_RWx10020011, data); // This resets the idle sequencer and force OHA into the // DO_NOTHING_STATE ... should be completed in the next // cycle since special wakeup is still asserted, OHA should // not leave the DO_NOTHING_STATE // Check again for AISS-FSM-state P7_SEQ_WAIT_INT_PENDING EX_OHA_RO_STATUS_REG_0x1002000B (bit 13-19) 0b11100 GETSCOM(rc, i_ex_target, EX_OHA_RO_STATUS_REG_0x1002000B, data); FAPI_DBG("\tCURRENT_AISS_FSM_STATE_VECTOR (OHA_RO_STATUS(13:19) => 0x%016llx", data.getDoubleWord(0)); // We're done accessing the OHA so clear the flag oha_spwkup_flag = 0; rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_OHA_FLAG, &i_ex_target, oha_spwkup_flag); if (rc) { FAPI_ERR("fapiSetAttribute to clear ATTR_PM_SPWUP_OHA_FLAG with rc = 0x%x", (uint32_t)rc); // This is a purposeful mid-procedure return return rc; } FAPI_INF("Cleared OHA special wakeup flag"); } } // Check again if special_wakeup completed GETSCOM(rc, i_ex_target, EX_PMGP0_0x100F0100, data); } // Workaround for HW255321 ends here if (data.isBitClear(31)) { FAPI_ERR("Timed out in setting the CPU in Special wakeup ... "); GETSCOM(rc, i_ex_target, EX_PMGP0_0x100F0100, data); FAPI_DBG("Special Wake-up Done NOT asserted (PMGP0(31)!! =>0x%016llx", data.getDoubleWord(0)); const uint64_t& PMGP0 = data.getDoubleWord(0); // The following are put in the procedure (vs the XML) to capture // for Cronus debug GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After set of SPWKUP_REG (0x%08llx) => 0x%016llx", spwkup_address, data.getDoubleWord(0)); const uint64_t& SP_WKUP_REG_ADDRESS = spwkup_address; const uint64_t& SP_WKUP_REG_VALUE = data.getDoubleWord(0); GETSCOM(rc, i_ex_target, history_address , data); FAPI_DBG(" History addreess (0x%08llx) => 0x%016llx", history_address, data.getDoubleWord(0)); const uint64_t& HISTORY_ADDRESS = history_address; const uint64_t& HISTORY_VALUE = data.getDoubleWord(0); //cmo-20140710: We can't leave a latent spwu bit in 0x100f010b/c/d. Even though // we gave it a very long time to complete, we can't take the chance that it // fires later. So, lets clear it now. This will do no harm since the presumption // at this point, anyway, is that it failed and so therefore it should be cleared // too. // Note, we only want to do this for count=0 and if bSpwuSetOnEntry==false as // this would be an indication that we, right now, just asserted the spwu // from a deasserted state. Therefore, we can safely also deassert it. // Question is though, do we also wanna do the following if count>0, which // would be a pretty messed up situation? if (!bSpwuSetOnEntry) { e_rc=data.flushTo0(); E_RC_CHECK(e_rc, rc); PUTSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" Clearing SPWKUP_REG (0x%08llx) => 0x%016llx", spwkup_address, data.getDoubleWord(0)); GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After read (delay) of SPWKUP_REG (0x%08llx) 0x%016llx", spwkup_address, data.getDoubleWord(0)); } const uint64_t& POLLCOUNT = (uint64_t)pollcount; const uint64_t& EX = (uint64_t)attr_chip_unit_pos; const uint64_t& ENTITY = (uint64_t)i_entity; PROC_SPCWKUP_OPS& I_OPERATION = i_operation ; const fapi::Target & EX_IN_ERROR = i_ex_target; const fapi::Target & CHIP = l_parentTarget; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_SPCWKUP_TIMEOUT); break; } else { count++ ; FAPI_INF("Special wakeup done is set. SUCCESS! ... "); } } // Done checking else { FAPI_INF("Special wakeup with a checkstop active was attempted to a chiplet in an idle state that cannot succeed"); const fapi::Target & EX_TARGET = i_ex_target; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_SPCWKUP_SLW_IN_CHKSTOP); break; } } // Count > 0 else { // Check that we really are in special wakeup. // If not, the counts are messed up GETSCOM(rc, i_ex_target, EX_PMGP0_0x100F0100, data); if (data.isBitSet(31)) { count++ ; } else { FAPI_ERR("Enabling special wakeup failed."); FAPI_ERR("--> Reason is that %s COUNT > 0 but PMGP0(31) is not set", PROC_SPCWKUP_ENTITY_NAMES[i_entity]); FAPI_ERR(" FSP_COUNT = %d , OCC_COUNT = %d , PHYP_COUNT = %d ", fsp_spwkup_count ,occ_spwkup_count ,phyp_spwkup_count); const fapi::Target & EX_TARGET = i_ex_target; const uint64_t & PMGP0 = data.getDoubleWord(0); const uint32_t & ENTITY_COUNT = count; const PROC_SPCWKUP_ENTITY & I_ENTITY = i_entity ; FAPI_SET_HWP_ERROR( rc, RC_PROCPM_SPCWKUP_NOT_SET); break; } } } else if (i_operation == SPCWKUP_DISABLE) { FAPI_INF("Clearing Special Wake-up..."); // If the OHA flag is set, then any subsequent calls to the this // procedure must return a "good" response or elso an infinite // loop results for any calling algorithm that first sets // special wake-up, does a SCOM, and then clears special // wake-up. rc = FAPI_ATTR_GET(ATTR_PM_SPWUP_OHA_FLAG, &i_ex_target, oha_spwkup_flag); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_SPWUP_OHA_FLAG with rc = 0x%x", (uint32_t)rc); break; } if (oha_spwkup_flag) { FAPI_INF("OHA special wakeup flag is set so returning with good response to break recursion. Counts are NOT updated."); // This is a purposeful mid-procedure return return rc; } if ( count == 1 ) { GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" Before clear of SPWKUP_REG (0x%08llx) => =>0x%016llx", spwkup_address, data.getDoubleWord(0)); e_rc=data.flushTo0(); E_RC_CHECK(e_rc, rc); PUTSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After clear putscom of SPWKUP_REG (0x%08llx) => 0x%016llx", spwkup_address, data.getDoubleWord(0)); // This puts an inherent delay in the propagation of the reset transition. GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After read (delay) of SPWKUP_REG (0x%08llx) 0x%016llx", spwkup_address, data.getDoubleWord(0)); count -- ; } else if ( count > 1 ) { FAPI_INF("Other processes have clear Special Wake-up pending. Chiplet is still in Special Wake-up state."); count -- ; } else // Equal 0 { // Check that we really are NOT in special wakeup. // If not, clear that platform bit. This can occur in Cronus startup GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" Checking of SPWKUP_REG disable (0x%08llx) => =>0x%016llx", spwkup_address, data.getDoubleWord(0)); if (data.isBitSet(0)) { e_rc=data.flushTo0(); E_RC_CHECK(e_rc, rc); PUTSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" Clearing SPWKUP_REG (0x%08llx) => 0x%016llx", spwkup_address, data.getDoubleWord(0)); // This puts an inherent delay in the propagation of the reset transition. GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After read (delay) of SPWKUP_REG (0x%08llx) 0x%016llx", spwkup_address, data.getDoubleWord(0)); } } GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After configuring SPWKUP_REG value =>0x%016llx", data.getDoubleWord(0)); } else if (i_operation == SPCWKUP_FORCE_DEASSERT) { GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" Before clear of SPWKUP_REG (0x%08llx) => =>0x%016llx", spwkup_address, data.getDoubleWord(0)); e_rc=data.flushTo0(); E_RC_CHECK(e_rc, rc); PUTSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After clear putscom of SPWKUP_REG (0x%08llx) => 0x%016llx", spwkup_address, data.getDoubleWord(0)); // This puts an inherent delay in the propagation of the reset transition. GETSCOM(rc, i_ex_target, spwkup_address , data); FAPI_DBG(" After read (delay) of SPWKUP_REG (0x%08llx) 0x%016llx", spwkup_address, data.getDoubleWord(0)); count = 0; } else { FAPI_ERR("ENABLE, DISABLE or INIT must be specified. Operation %x", i_operation ); PROC_SPCWKUP_OPS & I_OPERATION = i_operation ; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_SPCWKUP_CODE_BAD_OP); break; } ///////////////////////////////////////////////// // Update the attributes ///////////////////////////////////////////////// if ( i_entity == OCC ) { occ_spwkup_count = count ; rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_OCC, &i_ex_target, occ_spwkup_count ); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_OCC with rc = 0x%x", (uint32_t)rc); break; } } else if (i_entity == FSP) { fsp_spwkup_count = count ; rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_FSP, &i_ex_target, fsp_spwkup_count ); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_FSP with rc = 0x%x", (uint32_t)rc); break; } } else if (i_entity == PHYP) { phyp_spwkup_count = count; rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_PHYP, &i_ex_target, phyp_spwkup_count ); if (rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_PHYP with rc = 0x%x", (uint32_t)rc); break; } } FAPI_INF (" FSP_COUNT = %d , OCC_COUNT = %d , PHYP_COUNT = %d ", fsp_spwkup_count ,occ_spwkup_count ,phyp_spwkup_count); } while (0); // Clean up the OHA flag as it should not be set out of this exit (normal // and error) path. Note: there is ia mid-procedure return above. oha_rc = FAPI_ATTR_GET(ATTR_PM_SPWUP_OHA_FLAG, &i_ex_target, oha_spwkup_flag); if (oha_rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_SPWUP_OHA_FLAG with rc = 0x%x", (uint32_t)oha_rc); } else { if (oha_spwkup_flag) { oha_spwkup_flag = 0; oha_rc = FAPI_ATTR_SET(ATTR_PM_SPWUP_OHA_FLAG, &i_ex_target, oha_spwkup_flag); if (oha_rc) { FAPI_ERR("fapiSetAttribute of ATTR_PM_SPWUP_OHA_FLAG with rc = 0x%x", (uint32_t)oha_rc); } FAPI_ERR("Clearing OHA flag attribute upon procedure exit. This is NOT expected"); PROC_SPCWKUP_OPS& I_OPERATION = i_operation ; const uint64_t& EX = (uint64_t)attr_chip_unit_pos; const uint64_t& ENTITY = (uint64_t)i_entity; const uint64_t& PHYP_SPCWKUP_COUNT = (uint64_t)phyp_spwkup_count; const uint64_t& FSP_SPCWKUP_COUNT = (uint64_t)fsp_spwkup_count; const uint64_t& OCC_SPCWKUP_COUNT = (uint64_t)occ_spwkup_count; FAPI_SET_HWP_ERROR(oha_rc, RC_PROCPM_SPCWKUP_OHA_FLAG_SET_ON_EXIT); } } // Exit with the proper return code. rc has priority over oha_rc as it indicates // the first failure. if (!rc.ok()) { return rc ; } else if (!oha_rc.ok()) { return oha_rc ; } else { return rc; } }
// function: xxx /// \param[in] i_target Chip target // returns: ECMD_SUCCESS if something good happens, // BAD_RETURN_CODE otherwise fapi::ReturnCode p8_pmc_force_vsafe( const fapi::Target& i_target, const fapi::Target& i_dcm_target) { fapi::ReturnCode rc; ecmdDataBufferBase data(64); ecmdDataBufferBase pmcstatusreg(64); uint32_t e_rc = 0; // maximum number of status poll attempts to make before giving up const uint32_t MAX_POLL_ATTEMPTS = 0x200; uint32_t count = 0; uint16_t pvsafe = 0; bool l_set; uint16_t pstate_target = 0; uint16_t pstate_step_target = 0; uint16_t pstate_actual = 0; uint8_t DONE_FLAG = 0; uint8_t pmc_error = 0; uint8_t intchp_error = 0; uint8_t any_error = 0; uint8_t any_ongoing = 0; uint8_t dummy = 0; FAPI_INF("p8_pmc_force_vsafe start to primary target %s", i_target.toEcmdString()); do { // ****************************************************************** // - PMC_MODE_REG checking // ****************************************************************** rc = fapiGetScom(i_target, PMC_MODE_REG_0x00062000, data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_MODE_REG_0x00062000) failed."); break; } if ( (data.isBitClear(0) && data.isBitClear(1) )) { FAPI_INF("PMC is not in HARDWARE or FIRMWARE AUCTION MODE so hardware mechanism cannot be used."); break; } if ( ( data.isBitClear(3) )) { FAPI_ERR("PMC is disabled for Voltage changes"); const fapi::Target & CHIP = i_target; const uint64_t & PMCMODE = data.getDoubleWord(0); FAPI_SET_HWP_ERROR(rc, RC_PROCPM_VOLTAGE_CHANGE_MODE_ERR); break; } if ( ( !data.isBitClear(5) )) { FAPI_ERR("PMC is disabled PMC_MASTER_SEQUENCER"); const fapi::Target & CHIP = i_target; const uint64_t & PMCMODE = data.getDoubleWord(0); FAPI_SET_HWP_ERROR(rc, RC_PROCPM_MST_SEQUENCER_STATE_ERR); break; } // **************************************************************************** // - PMC_STATE_MONITOR_AND_CTRL_REG PMC_PARAMETER_REG1 before the psafe // **************************************************************************** rc = fapiGetScom(i_target, PMC_PARAMETER_REG1_0x00062006, data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_PARAMETER_REG1_0x00062006) failed."); break; } e_rc |= data.extractToRight( &pvsafe,22,8); if (e_rc) { rc.setEcmdError(e_rc); break; } rc = fapiGetScom(i_target, PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002, data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002) failed."); break; } e_rc |= data.extractToRight( &pstate_target,0,8); e_rc |= data.extractToRight( &pstate_step_target,8,8); e_rc |= data.extractToRight( &pstate_actual,16,8); if (e_rc) { rc.setEcmdError(e_rc); break; } FAPI_INF(" voltage values before the hearbeat loss " ); FAPI_INF(" pvsafe => %x , ptarget => %x , pstarget => %x ,pactual => %x " , pvsafe , pstate_target ,pstate_step_target , pstate_actual); // ****************************************************************** // - SEE PMC_STATUS_REG if debug_mode ==1 // ****************************************************************** rc = fapiGetScom(i_target, PMC_STATUS_REG_0x00062009, data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); break; } FAPI_DBG(" debug_mode : status_b4_heartbeat_loss => 0x%16llx", data.getDoubleWord(0)); l_set = data.isBitSet(0); FAPI_DBG(" pstate_processing_is_susp => %x ", l_set ) ; l_set = data.isBitSet(1); FAPI_DBG(" gpsa_bdcst_error => %x ", l_set ); e_rc = data.extractToRight( &dummy,2,3); if (e_rc) { rc.setEcmdError(e_rc); break; } FAPI_DBG(" gpsa_bdcst_resp_info => %x ", dummy ); l_set = data.isBitSet(5); FAPI_DBG(" gpsa_vchg_error => %x ", l_set ); l_set = data.isBitSet(6); FAPI_DBG(" gpsa_timeout_error => %x ", l_set ); l_set = data.isBitSet(7); FAPI_DBG(" gpsa_chg_ongoing => %x ", l_set ); l_set = data.isBitSet(8); FAPI_DBG(" volt_chg_ongoing => %x ", l_set ); l_set = data.isBitSet(9); FAPI_DBG(" brd_cst_ongoing => %x ", l_set ); l_set = data.isBitSet(10); FAPI_DBG(" gpsa_table_error => %x ", l_set ); l_set = data.isBitSet(11); FAPI_DBG(" pstate_interchip_error => %x ", l_set ); l_set = data.isBitSet(12); FAPI_DBG(" istate_processing_is_susp => %x ", l_set ); // ****************************************************************** // - PMC_OCC_HEARTBEAT_REG // ****************************************************************** FAPI_INF("Forcing PMC Heartbeat loss "); e_rc |= data.flushTo0(); e_rc |= data.setBit(16); if (e_rc) { rc.setEcmdError(e_rc); break; } rc = fapiPutScom(i_target, PMC_OCC_HEARTBEAT_REG_0x00062066, data ); if (rc) { FAPI_ERR("fapiPutScom(PMC_OCC_HEARTBEAT_REG_0x00062066) failed."); break; } // delay to reduce number of polling loops rc = fapiDelay(1000, 1000); // ****************************************************************** // POLL for PMC_STATUS_REG --> BIT_8 to go to 0 or any errors // ****************************************************************** FAPI_DBG("Start polling for ongoing to go low ... "); // Loop only if count is less thean poll attempts and DONE_FLAG = 0 and no error for(count=0; ((count<=MAX_POLL_ATTEMPTS) && (DONE_FLAG == 0) && (any_error == 0)); count++) { rc = fapiGetScom(i_target, PMC_STATUS_REG_0x00062009, pmcstatusreg ); if (rc) { FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); break; } FAPI_DBG(" PMC Status poll => 0x%16llx", pmcstatusreg.getDoubleWord(0)); pmc_error = ( pmcstatusreg.isBitSet(1) || // GPSA_BDCST_ERROR pmcstatusreg.isBitSet(5) || // GPSA_VCHG_ERROR pmcstatusreg.isBitSet(6) || // GPSA_TIMEOUT_ERROR pmcstatusreg.isBitSet(10) || // GPS_TABLE_ERROR pmcstatusreg.isBitSet(12) ); // ISTATE_PROCESSING_IS_SUSPENDED any_ongoing = ( pmcstatusreg.isBitSet(7) || // GPSA_CHG_ONGOING pmcstatusreg.isBitSet(8) || // VOLT_CHG_ONGOING pmcstatusreg.isBitSet(9) ); // BRD_CST_ONGOING // If there is an interchip error, determine if it is expected or not // Unexpected: gpsa_timeout or ECC UE error if (pmcstatusreg.isBitSet(11)) // PSTATE_INTERCHIP_ERROR { rc = fapiGetScom(i_target, PMC_INTCHP_STATUS_REG_0x00062013, data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_STATUS_REG_0x00062009) failed."); break; } intchp_error = (data.isBitSet(18) || // GPSA_TIMEOUT_ERROR data.isBitSet(19) ); // ECC UE ERROR } any_error = (pmc_error || intchp_error); // log status if voltage change has any error // Due to SW258130 // This block only dumps any detected hw error status // without taking out an error log and stop the reset flow. // Since this procedure is only used by p8_pm_prep_for_reset // we will and should be able to recover from such hardware errors // by going through occ reset flow, thus no FAPI error logged. // Also since if hardware error occurs, there is no need to check // for pstate ongoing or pstate equals to pvsafe due to possible // hardware stuck; therefore, this if/else logic remains. if (any_error) { // dump individual error status FAPI_INF(" PMC_STATUS_REG upon Error"); if (pmcstatusreg.isBitSet(0)) FAPI_INF(" pstate_processing_is_susp active"); if (pmcstatusreg.isBitSet(1)) FAPI_INF(" gpsa_bdcst_error active"); e_rc = pmcstatusreg.extractToRight( &dummy,2,3); if (e_rc) { rc.setEcmdError(e_rc); break; } if (dummy) FAPI_INF(" gpsa_bdcst_resp_info is non-zero => %x ", dummy ); if (pmcstatusreg.isBitSet(5)) FAPI_INF(" gpsa_vchg_error active"); if (pmcstatusreg.isBitSet(6)) FAPI_INF(" gpsa_timeout_error active"); if (pmcstatusreg.isBitSet(7)) FAPI_INF(" gpsa_chg_ongoing active"); if (pmcstatusreg.isBitSet(8)) FAPI_INF(" volt_chg_ongoing active"); if (pmcstatusreg.isBitSet(9)) FAPI_INF(" brd_cst_ongoing active"); if (pmcstatusreg.isBitSet(10)) FAPI_INF(" gpsa_table_error active"); if (pmcstatusreg.isBitSet(11)) FAPI_INF(" pstate_interchip_error active"); if (pmcstatusreg.isBitSet(12)) FAPI_INF(" istate_processing_is_susp active"); FAPI_INF("Status dumpped with PMC on-going deassertion during safe voltage movement, now continue on reset"); } // end of status log if else if (any_ongoing == 0) { // Voltage change done (not on-going) and not errors FAPI_INF("PMC completed performing safe mode transition"); l_set = pmcstatusreg.isBitSet(0); if (l_set) FAPI_INF(" pstate_processing_is_susp => %x ", l_set ) ; l_set = pmcstatusreg.isBitSet(1); if (l_set) FAPI_INF(" gpsa_bdcst_error => %x ", l_set ); e_rc = pmcstatusreg.extractToRight( &dummy,2,3); if (e_rc) { rc.setEcmdError(e_rc); break; } if (l_set) FAPI_INF(" gpsa_bdcst_resp_info => %x ", dummy ); l_set = pmcstatusreg.isBitSet(5); if (l_set) FAPI_INF(" gpsa_vchg_error => %x ", l_set ); l_set = pmcstatusreg.isBitSet(6); if (l_set) FAPI_INF(" gpsa_timeout_error => %x ", l_set ); l_set = pmcstatusreg.isBitSet(7); if (l_set) FAPI_INF(" gpsa_chg_ongoing => %x ", l_set ); l_set = pmcstatusreg.isBitSet(8); if (l_set) FAPI_INF(" volt_chg_ongoing => %x ", l_set ); l_set = pmcstatusreg.isBitSet(9); if (l_set) FAPI_INF(" brd_cst_ongoing => %x ", l_set ); l_set = pmcstatusreg.isBitSet(10); if (l_set) FAPI_INF(" gpsa_table_error => %x ", l_set ); l_set = pmcstatusreg.isBitSet(11); if (l_set) FAPI_INF(" pstate_interchip_error => %x ", l_set ); l_set = pmcstatusreg.isBitSet(12); if (l_set) FAPI_INF(" istate_processing_is_susp => %x ", l_set ); rc = fapiGetScom(i_target, PMC_PARAMETER_REG1_0x00062006, data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_PARAMETER_REG1_0x00062006) failed."); break; } e_rc = data.extractToRight( &pvsafe,22,8); if (e_rc) { rc.setEcmdError(e_rc); break; } rc = fapiGetScom(i_target, PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002, data ); if (rc) { FAPI_ERR("fapiGetScom(PMC_PSTATE_MONITOR_AND_CTRL_REG_0x00062002) failed."); break; } e_rc |= data.extractToRight( &pstate_target,0,8); e_rc |= data.extractToRight( &pstate_step_target,8,8); e_rc |= data.extractToRight( &pstate_actual,16,8); if (e_rc) { rc.setEcmdError(e_rc); break; } FAPI_INF(" pvsafe => %x , ptarget => %x , pstarget => %x ,pactual => %x " , pvsafe , pstate_target ,pstate_step_target , pstate_actual); // Check that PVSAFE Pstate (in PMC Parameter Reg1) is the value // in the voltage stepper in the following fields of // PMC_STATE_MONITOR_AND_CRTL_REG // 0:7 - Global Pstate Target // 8:15 - Global Pstate Step Target // 16:23 - Global Pstate Actual // if the above do not match, post an error if (pstate_target != pvsafe || pstate_step_target != pvsafe || pstate_actual != pvsafe ) { FAPI_ERR("Pstate monitor and control register targets did not match"); const fapi::Target & THISCHIP = i_target; const fapi::Target & DCMCHIP = i_dcm_target; const uint64_t & PSTATETARGET = (uint64_t)pstate_target; const uint64_t & PSTATESTEPTARGET = (uint64_t)pstate_step_target; const uint64_t & PSTATEACTUAL = (uint64_t)pstate_actual; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_PSTATE_MONITOR_ERR); break; } DONE_FLAG = 1; } else // voltage change is ongoing so wait and then poll again { // wait for 1 millisecond in hardware rc = fapiDelay(1000*1000, 20000000); if (rc) { FAPI_ERR("fapi delay ends up with error"); break; } } } // For loop // Inner loop error check if (!rc.ok()) { break; } // Check if the above loop timed out if (count>=MAX_POLL_ATTEMPTS) { FAPI_ERR("Timed out wait for voltage change on-going to drop"); const uint64_t & PSTATETARGET = (uint64_t)pstate_target; const uint64_t & PSTATESTEPTARGET = (uint64_t)pstate_step_target; const uint64_t & PSTATEACTUAL = (uint64_t)pstate_actual; const fapi::Target & THISCHIP = i_target; const fapi::Target & DCMCHIP = i_dcm_target; FAPI_SET_HWP_ERROR(rc, RC_PROCPM_VLT_TIMEOUT); break; } } while(0); FAPI_INF("p8_pmc_force_vsafe end ...."); return rc ; } // Procedure
// HWP entry point fapi::ReturnCode proc_getecid( const fapi::Target& i_target, ecmdDataBufferBase& io_fuseString) { // return code fapi::ReturnCode rc; uint32_t rc_ecmd = 0; uint64_t attr_data[2]; // mark HWP entry FAPI_DBG("proc_getecid: Start"); io_fuseString.setBitLength(112); // sets size and zeros out buffer ecmdDataBufferBase otprom_mode_data(64); ecmdDataBufferBase ecid_data(64); do { // // clear ECC enable before reading ECID data (read-modify-write OTPROM Mode register) // rc = fapiGetScom(i_target, OTPC_M_MODE_REGISTER_0x00010008, otprom_mode_data); if (!rc.ok()) { FAPI_ERR("proc_getecid: fapiGetScom error (OTPC_M_MODE_REGISTER_0x00010008) for %s", i_target.toEcmdString()); break; } rc_ecmd |= otprom_mode_data.clearBit(OTPC_M_MODE_REGISTER_ECC_ENABLE_BIT); if (rc_ecmd) { FAPI_ERR("proc_getecid: Error 0x%X setting up OTPROM Mode register data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, OTPC_M_MODE_REGISTER_0x00010008, otprom_mode_data); if (!rc.ok()) { FAPI_ERR("proc_getecid: fapiPutScom error (OTPC_M_MODE_REGISTER_0x00010008) for %s", i_target.toEcmdString()); break; } // // extract and manipulate ECID data // rc = fapiGetScom(i_target, ECID_PART_0_0x00018000, ecid_data); if (!rc.ok()) { FAPI_ERR("proc_getecid: fapiGetScom error (ECID_PART_0_0x00018000) for %s", i_target.toEcmdString()); break; } // 0:63 become 63:0 rc_ecmd |= ecid_data.reverse(); // copy bits 0:63 from the scom into 0:63 of the fuseString/attribute data rc_ecmd |= io_fuseString.insert(ecid_data, 0, 64); attr_data[0] = ecid_data.getDoubleWord(0); if (rc_ecmd) { FAPI_ERR("proc_getecid: Error 0x%X processing ECID (part 0) data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiGetScom(i_target, ECID_PART_1_0x00018001, ecid_data); if (!rc.ok()) { FAPI_ERR("proc_getecid: fapiGetScom error (ECID_PART_1_0x00018001) for %s", i_target.toEcmdString()); break; } // 0:63 become 63:0 rc_ecmd |= ecid_data.reverse(); // copy bits 0:47 from the scom into 64:111 of the fuseString // all bits into attribute data rc_ecmd |= io_fuseString.insert(ecid_data, 64, 48); attr_data[1] = ecid_data.getDoubleWord(0); if (rc_ecmd) { FAPI_ERR("proc_getecid: Error 0x%X processing ECID (part 1) data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } // push fuse string into attribute rc = FAPI_ATTR_SET(ATTR_ECID, &i_target, attr_data); if (!rc.ok()) { FAPI_ERR("proc_getecid: Error from FAPI_ATTR_SET (ATTR_ECID) for %s (attr_data[0] = %016llX, attr_data[1] = %016llX", i_target.toEcmdString(), attr_data[0], attr_data[1]); break; } // // restore ECC enable setting // rc_ecmd |= otprom_mode_data.setBit(OTPC_M_MODE_REGISTER_ECC_ENABLE_BIT); if (rc_ecmd) { FAPI_ERR("proc_getecid: Error 0x%X setting up OTPROM Mode register data buffer", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, OTPC_M_MODE_REGISTER_0x00010008, otprom_mode_data); if (!rc.ok()) { FAPI_ERR("proc_getecid: fapiPutScom error (OTPC_M_MODE_REGISTER_0x00010008) for %s", i_target.toEcmdString()); break; } } while(0); // mark HWP exit FAPI_DBG("proc_getecid: End"); return rc; }
// parameters: // 'i_target' is chip target // // returns: // FAPI_RC_SUCCESS (success, EX chiplets entered fast winkle) // // getscom/putscom/getattribute fapi errors // fapi error assigned from eCMD function failure // //------------------------------------------------------------------------------ fapi::ReturnCode proc_mpipl_ex_cleanup(const fapi::Target & i_target) { const char *procedureName = "proc_mpipl_ex_cleanup"; fapi::ReturnCode rc; //fapi return code uint32_t rc_ecmd = 0; //ecmd return code value ecmdDataBufferBase fsi_data(64); //64-bit data buffer uint8_t attr_chip_unit_pos; //EX chiplet's unit offset within chip with respect to similar EX units const uint64_t EX_OFFSET_MULT = 0x01000000; //Multiplier used to calculate offset for respective EX chiplet uint64_t address; // Varible for computed addresses uint64_t offset; char reg_name[32]; // Character array for register names // Relevant PMGP0 bits // const uint32_t PM_DISABLE = 0; const uint32_t BLOCK_REG_WKUP_SOURCE = 53; // Relevant PMGP1 bits const uint32_t WINKLE_POWER_OFF_SEL = 5; std::vector<fapi::Target> v_ex_chiplets; //Vector of EX chiplets do { //Entering fapi function FAPI_INF("Entering %s", procedureName); //Get vector of EX chiplets rc = fapiGetChildChiplets( i_target, fapi::TARGET_TYPE_EX_CHIPLET, v_ex_chiplets, fapi::TARGET_STATE_FUNCTIONAL); if (rc) { FAPI_ERR("%s: fapiGetChildChiplets error", procedureName); break; } FAPI_INF("Processing target %s", i_target.toEcmdString()); //Parse thru EX chiplets and prepare fast-winkled cores for deep operations //Loop thru EX chiplets in vector for (uint32_t counter = 0; counter < v_ex_chiplets.size(); counter++) { // Get EX chiplet number rc = FAPI_ATTR_GET( ATTR_CHIP_UNIT_POS, &(v_ex_chiplets[counter]), attr_chip_unit_pos); if (rc) { FAPI_ERR("%s: fapiGetAttribute error (ATTR_CHIP_UNIT_POS)", procedureName); break; } FAPI_INF("EX chiplet pos = 0x%02X", attr_chip_unit_pos); // Calculate the address offset based on chiplet number offset = EX_OFFSET_MULT * attr_chip_unit_pos; // ----------------------------------------------------------------- FAPI_DBG("\tOriginal register contents"); address = EX_GP3_0x100F0012 + offset; strcpy(reg_name, "GP3"); rc = fapiGetScom( i_target, address, fsi_data ); if (rc) { FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); break; } FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); address = EX_PMGP0_0x100F0100 + offset; strcpy(reg_name, "PMGP0"); rc = fapiGetScom( i_target, address, fsi_data ); if (rc) { FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); break; } FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); address = EX_PMGP1_0x100F0103 + offset; strcpy(reg_name, "PMGP1"); rc = fapiGetScom( i_target, address, fsi_data ); if (rc) { FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); break; } FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); // ----------------------------------------------------------------- // Clean up configuration remnants of the fast-winkle configuration // that was used to flush the chiplets after checkstop. EX chiplets // will have been through SBE EX Init with certain step skippled due // to MPIPL. FAPI_INF("Re-establish Deep Winkle mode default"); address = EX_PMGP1_OR_0x100F0105 + offset; strcpy(reg_name, "PMGP1 OR"); rc_ecmd |= fsi_data.flushTo0(); rc_ecmd |= fsi_data.setBit(WINKLE_POWER_OFF_SEL); if(rc_ecmd) { FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX) with rc %x", reg_name, address, rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, address, fsi_data); if (rc) { FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address); break; } FAPI_INF("Clear block wakeup sources to PM logic. PM is NOT re-enabled"); // (eg clear Block Interrrupt Sources) address = EX_PMGP0_AND_0x100F0101 + offset; strcpy(reg_name, "PMGP0 AND"); rc_ecmd |= fsi_data.flushTo1(); // rc_ecmd |= fsi_data.clearBit(PM_DISABLE); rc_ecmd |= fsi_data.clearBit(BLOCK_REG_WKUP_SOURCE); if(rc_ecmd) { FAPI_ERR("ecmdDatatBuffer error preparing %s reg (addr: 0x%08llX)", reg_name, address); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, address, fsi_data); if (rc) { FAPI_ERR("fapiPutScom error (addr: 0x%08llX)", address); break; } // ----------------------------------------------------------------- FAPI_DBG("\tUpdated register contents"); address = EX_GP3_0x100F0012 + offset; strcpy(reg_name, "GP3"); rc = fapiGetScom( i_target, address, fsi_data ); if (rc) { FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); break; } FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); address = EX_PMGP0_0x100F0100 + offset; strcpy(reg_name, "PMGP0"); rc = fapiGetScom( i_target, address, fsi_data ); if (rc) { FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); break; } FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); address = EX_PMGP1_0x100F0103 + offset; strcpy(reg_name, "PMGP1"); rc = fapiGetScom( i_target, address, fsi_data ); if (rc) { FAPI_ERR("fapiGetScom error (addr: 0x%08llX)", address); break; } FAPI_DBG("\t%s (addr: 0x%08llX), val=0x%016llX", reg_name, address, fsi_data.getDoubleWord(0)); // ----------------------------------------------------------------- } // chiplet loop // Error exit from above loop // Not really needed as outer while(0) is next but here for consistent structure if (!rc.ok()) { break; } } while (0); //Exiting fapi function FAPI_INF("Exiting %s", procedureName); return rc; }
/** * Trace PCBS FSMs for a given EX * * @param[in] i_target Chip target * @param[in] i_msg String to put out in the trace * * @retval ECMD_SUCCESS */ fapi::ReturnCode p8_pm_pcbs_fsm_trace ( const fapi::Target& i_target, uint32_t i_ex_number, const char * i_msg) { fapi::ReturnCode rc; ecmdDataBufferBase data(64); uint64_t address; uint8_t trace_en_flag = false; uint64_t ex_offset; do { rc = FAPI_ATTR_GET(ATTR_PM_PCBS_FSM_TRACE_EN, NULL, trace_en_flag); if (rc) { FAPI_ERR("fapiGetAttribute of ATTR_PM_PCBS_FSM_TRACE_EN with rc = 0x%x", (uint32_t)rc); break; } // If trace is not enabled, leave. if (!trace_en_flag) { break; } ex_offset = i_ex_number * 0x01000000; // Note: i_msg is put on on each record to allow for trace "greps" // so as to see the "big picture" across when // ****************************************************************** // Read PCBS FSM Monitor0 // ****************************************************************** address = EX_PCBS_FSM_MONITOR1_REG_0x100F0170 + ex_offset; GETSCOM(rc, i_target, address, data); FAPI_INF("PCBS Monitor0 = 0x%016llX; %s target:%s" , data.getDoubleWord(0), i_msg, i_target.toEcmdString()); // ****************************************************************** // Read PCBS FSM Monitor1 // ****************************************************************** address = EX_PCBS_FSM_MONITOR2_REG_0x100F0171 + ex_offset; GETSCOM(rc, i_target, address, data); FAPI_INF("PCBS Monitor1 = 0x%016llX; %s target:%s" , data.getDoubleWord(0), i_msg, i_target.toEcmdString()); // ****************************************************************** // Read PCBS DPLL CPM PARM REG // ****************************************************************** address = EX_DPLL_CPM_PARM_REG_0x100F0152 + ex_offset; GETSCOM(rc, i_target, address, data); FAPI_INF("DPLLC Monitor = 0x%016llX; %s target:%s" , data.getDoubleWord(0), i_msg, i_target.toEcmdString()); // ****************************************************************** // Read PCBS PMGP0 // ****************************************************************** address = EX_PMGP0_0x100F0100 + ex_offset; GETSCOM(rc, i_target, address, data); FAPI_INF("PMGP0 Monitor = 0x%016llX; %s target:%s" , data.getDoubleWord(0), i_msg, i_target.toEcmdString()); } while(0); return rc; }