// ---------------------------------------------------------------------- // Function definitions // ---------------------------------------------------------------------- fapi2::ReturnCode p9_pm_firinit( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const p9pm::PM_FLOW_MODE i_mode) { FAPI_IMP("p9_pm_firinit start"); fapi2::ReturnCode l_rc; uint8_t l_pm_firinit_flag; fapi2::buffer<uint64_t> l_data64; // CHECKING FOR FIRS BEFORE RESET and INIT FAPI_DBG("Checking PBA FIRs"); FAPI_TRY(fapi2::getScom(i_target, PU_PBAFIR , l_data64), "ERROR: Failed to fetch PBA FIR"); if(l_data64) { FAPI_INF("WARNING: PBA has active error(s)"); } // Handle PBA FIRs, Masks and actions FAPI_DBG("Calling PBA firinit ..."); FAPI_EXEC_HWP(l_rc, p9_pm_pba_firinit, i_target, i_mode); FAPI_TRY(l_rc); // Handle Core and Quad errors FAPI_DBG("Calling PPM firinit ..."); FAPI_EXEC_HWP(l_rc, p9_pm_ppm_firinit, i_target, i_mode); FAPI_TRY(l_rc); // Handle CME FIRs, Masks and actions FAPI_DBG("Calling CME firinit ..."); FAPI_EXEC_HWP(l_rc, p9_pm_cme_firinit, i_target, i_mode); FAPI_TRY(l_rc); FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PM_FIRINIT_DONE_ONCE_FLAG, i_target, l_pm_firinit_flag), "ERROR: Failed to fetch the firinit call status flag"); // Set the ATTR_PM_FIRINIT_DONE_ONCE_FLAG attribute if (i_mode == p9pm::PM_INIT) { if (l_pm_firinit_flag != 1) { l_pm_firinit_flag = 1; FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PM_FIRINIT_DONE_ONCE_FLAG, i_target, l_pm_firinit_flag), "ERROR: Failed to set firinit call status after init"); } } fapi_try_exit: FAPI_INF("p9_pm_firinit end"); return fapi2::current_err; } // END p9_pm_firinit
/** * @brief A HWP that runs Restore eRepair. This procedure should update the * bad lane vector and power down the bad lanes. The rx bad lanes will update * the bad lane vector of the passed target. The lanes specified in the * i_rx_bad_lanes and in the i_tx_bad_lanes vectors will be powered down on the * target that is passed in. Note: This procedure does not power down any * bad lanes on the connected target. * @param[in] i_target FAPI2 Target * @param[in] i_rx_bad_lanes Vector of Rx Bad Lanes * @param[in] i_tx_bad_lanes Vector of Tx Bad Lanes * @retval ReturnCode */ fapi2::ReturnCode p9_io_dmi_restore_erepair( const fapi2::Target< fapi2::TARGET_TYPE_DMI >& i_target, const std::vector< uint8_t >& i_rx_bad_lanes, const std::vector< uint8_t >& i_tx_bad_lanes) { FAPI_IMP("Entering..."); FAPI_DBG("Rx Bad Lanes Size: %d", i_rx_bad_lanes.size()); FAPI_DBG("Tx Bad Lanes Size: %d", i_tx_bad_lanes.size()); if(!i_rx_bad_lanes.empty()) { FAPI_TRY(set_rx_bad_lane_vectors(i_target, i_rx_bad_lanes), "Setting Rx Bad Lane Vectors Failed"); } // This function will power down the rx & tx lanes specified in the vectors // on the target that is passed in. FAPI_EXEC_HWP(fapi2::current_err, p9_io_dmi_pdwn_lanes, i_target, i_rx_bad_lanes, i_tx_bad_lanes); fapi_try_exit: FAPI_IMP("Exiting..."); return fapi2::current_err; }
/// /// @brief Scominit for Explorer /// @param[in] i_target the OCMB target to operate on /// @return FAPI2_RC_SUCCESS iff ok /// fapi2::ReturnCode exp_scominit( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target) { mss::display_git_commit_info("exp_scominit"); if (mss::count_dimm(i_target) == 0) { FAPI_INF("... skipping mss_scominit %s - no DIMM ...", mss::c_str(i_target)); return fapi2::FAPI2_RC_SUCCESS; } // We need to make sure we hit all ports const auto& l_port_targets = mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target); fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM; const auto& l_mc = i_target.getParent<fapi2::TARGET_TYPE_OMI>() .getParent<fapi2::TARGET_TYPE_MCC>() .getParent<fapi2::TARGET_TYPE_MI>() .getParent<fapi2::TARGET_TYPE_MC>(); for(const auto& l_port : l_port_targets) { fapi2::ReturnCode l_rc; FAPI_INF("phy scominit for %s", mss::c_str(l_port)); FAPI_EXEC_HWP(l_rc, explorer_scom, i_target, l_port, FAPI_SYSTEM, l_mc); FAPI_TRY(l_rc, "Error from explorer.scom.initfile %s", mss::c_str(l_port)); } return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: FAPI_INF("End MSS SCOM init"); return fapi2::current_err; }
/// /// @brief MBvpd accessor for the ATTR_VPD_POWER_CONTROL_CAPABLE attribute /// @param[in] i_mbTarget - Reference to mb Target /// @param[out] o_val - retrieved MR value /// @return fapi::ReturnCode FAPI_RC_SUCCESS if success, else error code /// fapi2::ReturnCode getControlCapableData( const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_mbTarget, uint8_t& o_val) { fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; FAPI_DBG("getControlCapableData: start on %s", mss::c_str(i_mbTarget)); // ATTR_VPD_POWER_CONTROL_CAPABLE is at the membuf level, but the // getMBvpdAttr() function takes a mba, so need to do a // conversion const auto l_mbas = i_mbTarget.getChildren<fapi2::TARGET_TYPE_MBA>(); // If we don't have any functional MBAs then we will fail in // the other function so just return a default value here if( l_mbas.empty() ) { o_val = fapi2::ENUM_ATTR_CEN_VPD_POWER_CONTROL_CAPABLE_NONE; return l_rc; } // Call a VPD Accessor HWP to get the data FAPI_EXEC_HWP(l_rc, getMBvpdAttr, l_mbas[0], fapi2::ATTR_CEN_VPD_POWER_CONTROL_CAPABLE, &o_val, sizeof(fapi2::ATTR_CEN_VPD_POWER_CONTROL_CAPABLE_Type)); FAPI_DBG("getControlCapableData: end on %s", mss::c_str(i_mbTarget)); 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; }
// HWP entry point, comments in header fapi2::ReturnCode p9_io_obus_scominit( const fapi2::Target<fapi2::TARGET_TYPE_OBUS>& i_target ) { // mark HWP entry FAPI_INF("p9_io_obus_scominit: Entering..."); const uint8_t GROUP_00 = 0; const uint8_t LANE_00 = 0; const uint8_t SET_RESET = 1; const uint8_t CLEAR_RESET = 0; fapi2::ReturnCode rc = fapi2::FAPI2_RC_SUCCESS; // get system target const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_system_target; // get a proc target fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_proc_target = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); // assert IO reset to power-up bus endpoint logic FAPI_TRY( io::rmw( OPT_IORESET_HARD_BUS0, i_target, GROUP_00, LANE_00, SET_RESET ) ); // Bus Reset is relatively fast, only needing < a hundred cycles to allow the signal to propogate. FAPI_TRY( fapi2::delay( 10, 1000 ) ); FAPI_TRY( io::rmw( OPT_IORESET_HARD_BUS0, i_target, GROUP_00, LANE_00, CLEAR_RESET ) ); FAPI_INF("Invoke FAPI procedure core: input_target"); FAPI_EXEC_HWP(rc, p9_obus_scom, i_target, l_system_target, l_proc_target); // configure FIR { FAPI_TRY(fapi2::putScom(i_target, OBUS_FIR_ACTION0_REG, OBUS_PHY_FIR_ACTION0), "Error from putScom (OBUS_FIR_ACTION0_REG)"); FAPI_TRY(fapi2::putScom(i_target, OBUS_FIR_ACTION1_REG, OBUS_PHY_FIR_ACTION1), "Error from putScom (OBUS_FIR_ACTION1_REG)"); FAPI_TRY(fapi2::putScom(i_target, OBUS_FIR_MASK_REG, OBUS_PHY_FIR_MASK), "Error from putScom (OBUS_FIR_MASK_REG)"); } // mark HWP exit FAPI_INF("p9_io_obus_scominit: ...Exiting"); fapi_try_exit: return fapi2::current_err; }
fapi2::ReturnCode p9_pm_ocb_indir_setup_circular( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, const p9ocb::PM_OCB_CHAN_NUM i_ocb_chan, const p9ocb::PM_OCB_CHAN_TYPE i_ocb_type, const uint32_t i_ocb_bar, const uint8_t i_ocb_q_len, const p9ocb::PM_OCB_CHAN_OUFLOW i_ocb_flow, const p9ocb::PM_OCB_ITPTYPE i_ocb_itp) { FAPI_IMP("p9_pm_ocb_indir_setup_circular Enter"); FAPI_DBG("Channel: %d; Mode: %d; OCB BAR: 0x%08X; Queue length: %d;", i_ocb_chan, i_ocb_type, i_ocb_bar, i_ocb_q_len); FAPI_DBG("Flow Notification Mode: %d; Interrupt Behaviour: %d", i_ocb_flow, i_ocb_itp); fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; FAPI_EXEC_HWP(l_rc, p9_pm_ocb_init, i_target, p9pm::PM_SETUP_ALL, i_ocb_chan, i_ocb_type, i_ocb_bar, i_ocb_q_len, i_ocb_flow, i_ocb_itp); if (l_rc == fapi2::FAPI2_RC_SUCCESS) { FAPI_INF("Circular setup of channel %d successful.", i_ocb_chan); } else { FAPI_ERR("ERROR: Failed to setup channel %d to circular mode.", i_ocb_chan); } FAPI_IMP("p9_pm_ocb_indir_setup_circular Exit"); return l_rc; }
uint32_t rcTestCalloutNoneDeconfig() { uint32_t l_result = 0; errlHndl_t l_errl = NULL; bool l_hw_callout_found = false; FAPI_INF("rcTestCalloutNoneDeconfig running"); TARGETING::TargetHandleList l_dimmList; TARGETING::getAllLogicalCards(l_dimmList, TARGETING::TYPE_DIMM, false); TARGETING::Target * l_Dimm = NULL; //Take the first dimm if (l_dimmList.size() > 0) { l_Dimm = l_dimmList[0]; } else { TS_FAIL("No dimms found"); } //Convert to fapi2 target for the HWP below fapi2::Target<fapi2::TARGET_TYPE_DIMM> fapi2_dimmTarget(l_Dimm); FAPI_INVOKE_HWP(l_errl, p9_deconfigCalloutNone, fapi2_dimmTarget); if(l_errl != NULL) { FAPI_INF("rcTestCalloutNoneDeconfig: p9_deconfigCalloutNone " "returned errl (expected)"); //Get the User Data fields of the errl. They are returned as //vector<void*>, so iterate over them. for( auto l_callout_raw : l_errl-> getUDSections( ERRL_COMP_ID, ERRORLOG::ERRL_UDT_CALLOUT ) ) { HWAS::callout_ud_t* l_callout_entry = reinterpret_cast<HWAS::callout_ud_t*>(l_callout_raw); if(l_callout_entry->type == HWAS::HW_CALLOUT) { l_hw_callout_found = true; FAPI_INF("rcTestCalloutNoneDeconfig: hw callout found"); if(l_callout_entry->deconfigState == HWAS::DELAYED_DECONFIG) { FAPI_INF("rcTestCalloutNoneDeconfig: Target is deconfigured"); } else { TS_FAIL("rcTestCalloutNoneDeconfig: Target is NOT deconfigured"); l_result = 1; break; } } } if(!l_hw_callout_found) { TS_FAIL("rcTestCalloutNoneDeconfig: hw callout NOT found"); l_result = 2; } } else { TS_FAIL("rcTestCalloutNoneDeconfig: No error was returned from" " p9_deconfigCalloutNone !!"); l_result = 3; } //l_errl->setSev(ERRORLOG::ERRL_SEV_RECOVERED); //errlCommit(l_errl,CXXTEST_COMP_ID); delete l_errl; l_errl = NULL; // Now try it the way HWP people do it ReturnCode l_rc; FAPI_EXEC_HWP(l_rc, p9_deconfigCalloutNone, fapi2_dimmTarget); if (l_rc != fapi2::FAPI2_RC_SUCCESS) { // log the error but don't fail the unit test FAPI_INF("rcTestCalloutNoneDeconfig: logError called"); fapi2::logError(l_rc, fapi2::FAPI2_ERRL_SEV_RECOVERED, true); } else { TS_FAIL("rcTestCalloutNoneDeconfig: No error was returned from " "FAPI_EXEC_HWP p9_deconfigCalloutNone !!"); l_result = 4; } FAPI_INF("rcTestCalloutNoneDeconfig finished"); return l_result; }
// 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; }
fapi2::ReturnCode pm_cme_fir_reset( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target) { FAPI_IMP("pm_cme_fir_reset start"); auto l_eqChiplets = i_target.getChildren<fapi2::TARGET_TYPE_EQ> (fapi2::TARGET_STATE_FUNCTIONAL); uint8_t firinit_done_flag; FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_PM_FIRINIT_DONE_ONCE_FLAG, i_target, firinit_done_flag), "ERROR: Failed to fetch the entry status of FIRINIT"); for (auto l_eq_chplt : l_eqChiplets) { //We cannot rely on the HWAS state because during an MPIPL //the cores get stopped and the SP doesnt know until an //attr sync occurs with the platform. We must use the //query_cache_state to safely determine if we can scom //the ex targets fapi2::ReturnCode l_rc; bool l_l2_is_scanable[MAX_L2_PER_QUAD]; bool l_l2_is_scomable[MAX_L2_PER_QUAD]; bool l_l3_is_scanable[MAX_L3_PER_QUAD]; bool l_l3_is_scomable[MAX_L3_PER_QUAD]; for (auto cnt = 0; cnt < MAX_L2_PER_QUAD; ++cnt) { l_l2_is_scomable[cnt] = false; l_l2_is_scanable[cnt] = false; } for (auto cnt = 0; cnt < MAX_L3_PER_QUAD; ++cnt) { l_l3_is_scanable[cnt] = false; l_l3_is_scomable[cnt] = false; } uint8_t l_chip_unit_pos; FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_eq_chplt, l_chip_unit_pos), "ERROR: Failed to get the chip unit pos attribute from the eq"); FAPI_EXEC_HWP(l_rc, p9_query_cache_access_state, l_eq_chplt, l_l2_is_scomable, l_l2_is_scanable, l_l3_is_scomable, l_l3_is_scanable); FAPI_TRY(l_rc, "ERROR: failed to query cache access state for EQ %d", l_chip_unit_pos); auto l_exChiplets = l_eq_chplt.getChildren<fapi2::TARGET_TYPE_EX> (fapi2::TARGET_STATE_FUNCTIONAL); for(auto l_ex_chplt : l_exChiplets) { FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, l_ex_chplt, l_chip_unit_pos), "ERROR: Failed to get the chip unit pos attribute from the ex"); //look ex is scommable l_chip_unit_pos = l_chip_unit_pos % 2; if ((!(l_l2_is_scomable[l_chip_unit_pos]) && !(l_l3_is_scomable[l_chip_unit_pos]))) { continue; } p9pmFIR::PMFir <p9pmFIR::FIRTYPE_CME_LFIR> l_cmeFir(l_ex_chplt); /* Only save off the FIR masks if they have been initialized */ if ( firinit_done_flag != fapi2::ENUM_ATTR_PM_FIRINIT_DONE_ONCE_FLAG_FIRS_RESET_IN_HB ) { FAPI_TRY(l_cmeFir.get(p9pmFIR::REG_FIRMASK), "ERROR: Failed to get the PBA FIR MASK value"); /* Fetch the CME FIR MASK; Save it to HWP attribute; clear it */ FAPI_TRY(l_cmeFir.saveMask(), "ERROR: Failed to save CME FIR Mask to the attribute"); FAPI_TRY(l_cmeFir.setAllRegBits(p9pmFIR::REG_FIRMASK), "ERROR: Faled to set the CME FIR MASK"); FAPI_TRY(l_cmeFir.put(), "ERROR:Failed to write to the CME FIR MASK"); } } } if (firinit_done_flag == fapi2::ENUM_ATTR_PM_FIRINIT_DONE_ONCE_FLAG_NO_INIT) { firinit_done_flag = fapi2::ENUM_ATTR_PM_FIRINIT_DONE_ONCE_FLAG_FIRS_RESET_IN_HB; FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PM_FIRINIT_DONE_ONCE_FLAG, i_target, firinit_done_flag ), "ERROR: Failed to set attribute PM_FIRINIT_DONE_ONCE_FLAG to RESET_IN_HB in pm_cme_fir_reset"); } fapi_try_exit: return fapi2::current_err; }
//------------------------------------------------------------------------------ // function: // Check if the SBE is still running // Wait 1 sec, then check again if still running // When stopped, check if the SBE halt code, istep, and substep are correct // // parameters: i_target => slave chip target // i_pSEEPROM => pointer to the seeprom image (for errors) // i_wait_in_ms => pointer to the seeprom image (for errors) // // returns: FAPI_RC_SUCCESS if the slave SBE stopped with success at the correct // location, else error //------------------------------------------------------------------------------ fapi::ReturnCode proc_check_slave_sbe_seeprom_complete( const fapi::Target & i_target, const void * i_pSEEPROM, const size_t i_wait_in_ms) { // data buffer to hold register values ecmdDataBufferBase data(64); // return codes uint32_t rc_ecmd = 0; fapi::ReturnCode rc; // track if procedure has cleared I2C master bus fence bool i2cm_bus_fence_cleared = false; // mark function entry FAPI_INF("Entry"); do { //Check if the SBE is still running. Loop until stopped //or loop time is exceeded. bool still_running = true; size_t loop_time = 0; rc = proc_check_slave_sbe_seeprom_complete_check_running( i_target, still_running ); if( rc ) { break; } while (still_running && (loop_time < i_wait_in_ms)) { //Not done -- sleep 10ms, then check again loop_time += MS_TO_FINISH; rc = fapiDelay(NS_TO_FINISH, SIM_CYCLES_TO_FINISH); if( rc ) { FAPI_ERR("Error with delay\n"); break; } rc = proc_check_slave_sbe_seeprom_complete_check_running( i_target, still_running ); if( rc ) { break; } } //Break if took an error if( rc ) { break; } FAPI_INF("SBE is running [%d], wait time in ms[%zd]", still_running, loop_time); //Give up if we're still running if( still_running ) { FAPI_ERR( "SBE still running after waiting (%zdns, %lld cycles)", loop_time, loop_time/MS_TO_FINISH*SIM_CYCLES_TO_FINISH ); const fapi::Target & CHIP_IN_ERROR = i_target; FAPI_SET_HWP_ERROR(rc, RC_PROC_CHECK_SLAVE_SBE_SEEPROM_COMPLETE_STILL_RUNNING); break; } //end if(still_running) //SBE is stopped. Let's see where uint8_t halt_code = 0; uint16_t istep_num = 0; uint8_t substep_num = 0; // before analysis proceeds, make sure that I2C master bus fence is cleared FAPI_EXEC_HWP(rc, proc_reset_i2cm_bus_fence, i_target); if (!rc.ok()) { FAPI_ERR("Error from proc_reset_i2cm_bus_fence"); break; } // mark that fence has been cleared i2cm_bus_fence_cleared = true; //Get current location from SBE VITAL rc = proc_check_slave_sbe_seeprom_complete_get_location( i_target, halt_code, istep_num, substep_num ); if( rc ) { FAPI_ERR("Unable to get the current SBE location"); break; } //Did it stop with success? if( halt_code != SBE_EXIT_SUCCESS_0xF ) { FAPI_ERR( "SBE halted with error %i (istep 0x%X, substep %i)", halt_code, istep_num, substep_num); //Get the error code from the SBE code FAPI_EXEC_HWP(rc, proc_extract_sbe_rc, i_target, NULL, i_pSEEPROM, SBE); break; } //Halt code was success //Did it stop in the correct istep? if(( istep_num != PROC_SBE_CHECK_MASTER_MAGIC_ISTEP_NUM ) && ( istep_num != PROC_SBE_ENABLE_PNOR_MAGIC_ISTEP_NUM ) && ( istep_num != PROC_SBE_EX_HOST_RUNTIME_SCOM_MAGIC_ISTEP_NUM )) { FAPI_ERR( "SBE halted in wrong istep (istep 0x%X, substep %i)", istep_num, substep_num); const fapi::Target & CHIP_IN_ERROR = i_target; uint16_t & ISTEP_NUM = istep_num; uint8_t & SUBSTEP_NUM = substep_num; FAPI_SET_HWP_ERROR(rc, RC_PROC_CHECK_SLAVE_SBE_SEEPROM_COMPLETE_BAD_ISTEP_NUM); break; } //Istep is correct //Did it stop in the correct substep? if( (( istep_num == PROC_SBE_CHECK_MASTER_MAGIC_ISTEP_NUM ) && ( substep_num != SUBSTEP_CHECK_MASTER_SLAVE_CHIP )) || (( istep_num == PROC_SBE_ENABLE_PNOR_MAGIC_ISTEP_NUM ) && ( substep_num != SUBSTEP_ENABLE_PNOR_SLAVE_CHIP ))) { FAPI_ERR( "SBE halted in wrong substep (istep 0x%X, substep %i)", istep_num, substep_num); const fapi::Target & CHIP_IN_ERROR = i_target; uint16_t & ISTEP_NUM = istep_num; uint8_t & SUBSTEP_NUM = substep_num; FAPI_SET_HWP_ERROR(rc, RC_PROC_CHECK_SLAVE_SBE_SEEPROM_COMPLETE_BAD_SUBSTEP_NUM); break; } //Substep is correct //Looks good! // Reset the SBE so it can be used for MPIPL if needed rc_ecmd |= data.flushTo0(); rc_ecmd |= data.setBit(0); if(rc_ecmd) { FAPI_ERR("Error (0x%x) setting up ecmdDataBufferBase", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } rc = fapiPutScom(i_target, PORE_SBE_RESET_0x000E0002, data); if(!rc.ok()) { FAPI_ERR("Scom error resetting SBE\n"); break; } } while (0); // if an error occurred prior to the I2C master bus fence // being cleared, attempt to clear it prior to exit if (!rc.ok() && !i2cm_bus_fence_cleared) { // discard rc, return that of original fail fapi::ReturnCode rc_unused; FAPI_EXEC_HWP(rc_unused, proc_reset_i2cm_bus_fence, i_target); } // mark function exit FAPI_INF("Exit"); return rc; }
/////////////////////////////////////////////////////////////////////////////// // See header for doxygen documentation /////////////////////////////////////////////////////////////////////////////// errlHndl_t mmioScomPerformOp(DeviceFW::OperationType i_opType, TARGETING::Target* i_target, void* io_buffer, size_t& io_buflen, int64_t i_accessType, va_list i_args) { errlHndl_t l_err = nullptr; fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; // The only extra arg should be the scomAddress uint64_t l_expAddr = va_arg(i_args,uint64_t); // The fapi2 put/get mmioScom interfaces require a fapi2::buffer so convert // to a uint64_t buffer (for IBM scom) and uint32_t buffer (for Microchip scoms) fapi2::buffer<uint64_t> l_fapi2Buffer64(*reinterpret_cast<uint64_t *>(io_buffer)); fapi2::buffer<uint32_t> l_fapi2Buffer32; l_fapi2Buffer64.extractToRight<32,32>(l_fapi2Buffer32); do { // First make sure the inputs are valid l_err = EXPSCOM::validateInputs ( i_opType, i_target, io_buflen, l_expAddr); if(l_err) { // Write a trace out to the buffer and then collect it on the log // this way we can know if the fail was in i2cScomPerformOp or mmioScomPerformOp TRACFCOMP( g_trac_expscom, ERR_MRK "mmioscomPerformOp> Validation of inputs failed see error logs for details "); l_err->collectTrace(EXPSCOM_COMP_NAME); break; } // Check if this is a IBM_SCOM address by &ing the address with IBM_SCOM_INDICATOR // If the indicator is not set, then we will assume this is a microChip address if( (l_expAddr & mss::exp::i2c::IBM_SCOM_INDICATOR) == mss::exp::i2c::IBM_SCOM_INDICATOR) { // READ and WRITE equates to mss::exp::ib::getScom and mss::exp::ib::putScom respectively. // any other OP is invalid. i/o data is expected to be 8 bytes for IBM scoms if(i_opType == DeviceFW::READ) { FAPI_EXEC_HWP(l_rc , mss::exp::ib::getScom, i_target, l_expAddr, l_fapi2Buffer64); l_err = fapi2::rcToErrl(l_rc); if(l_err) { l_err->collectTrace(FAPI_IMP_TRACE_NAME,256); l_err->collectTrace(FAPI_TRACE_NAME,384); TRACFCOMP( g_trac_expscom, ERR_MRK "mmioscomPerformOp> mss::exp::ib::getScom failed for HUID 0x%x Address 0x%lx ", TARGETING::get_huid(i_target), l_expAddr ); } else { // Copy contents of what we read to io_buffer memcpy(io_buffer, reinterpret_cast<uint8_t *>(l_fapi2Buffer64.pointer()), sizeof(uint64_t)); } } else { FAPI_EXEC_HWP(l_rc , mss::exp::ib::putScom, i_target, l_expAddr, l_fapi2Buffer64); l_err = fapi2::rcToErrl(l_rc); if(l_err) { l_err->collectTrace(FAPI_IMP_TRACE_NAME,256); l_err->collectTrace(FAPI_TRACE_NAME,384); TRACFCOMP( g_trac_expscom, ERR_MRK "mmioscomPerformOp> mss::exp::ib::putScom failed for HUID 0x%x Address 0x%lx ", TARGETING::get_huid(i_target), l_expAddr ); } } } else { // READ and WRITE equates to mss::exp::ib::gettMMIO32 and mss::exp::ib::putMMIO32 respectively. // any other OP is invalid. if(i_opType == DeviceFW::READ) { FAPI_EXEC_HWP(l_rc , mss::exp::ib::getMMIO32, i_target, l_expAddr, l_fapi2Buffer32); l_err = fapi2::rcToErrl(l_rc); if(l_err) { TRACFCOMP( g_trac_expscom, ERR_MRK "mmioscomPerformOp> getMMIO32 failed for HUID 0x%x Address 0x%lx ", TARGETING::get_huid(i_target), l_expAddr ); } else { // Put the contexts of the 32 bit buffer right justified into the 64 bit buffer l_fapi2Buffer64.flush<0>(); l_fapi2Buffer64.insertFromRight<32,32>(l_fapi2Buffer32); // Copy contents of 64 bit buffer to io_buffer memcpy(io_buffer, reinterpret_cast<uint8_t *>(l_fapi2Buffer64.pointer()), sizeof(uint64_t)); } } else { FAPI_EXEC_HWP(l_rc , mss::exp::ib::putMMIO32, i_target, l_expAddr, l_fapi2Buffer32); l_err = fapi2::rcToErrl(l_rc); if(l_err) { TRACFCOMP( g_trac_expscom, ERR_MRK "mmioscomPerformOp> putMMIO32 failed for HUID 0x%x Address 0x%lx ", TARGETING::get_huid(i_target), l_expAddr ); } } } } while (0); return l_err; }
/// /// @brief Creates and loads the OCC memory boot launcher /// @param[in] i_target Chip target /// @param[in] i_data64 32 bit instruction representing the branch /// instruction to the SRAM boot loader /// @return FAPI2_RC_SUCCESS on success, else error /// fapi2::ReturnCode bootMemory( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target, fapi2::buffer<uint64_t>& i_data64) { static const uint32_t SRAM_PROGRAM_SIZE = 2; // in double words uint64_t l_sram_program[SRAM_PROGRAM_SIZE]; fapi2::ReturnCode l_rc; uint32_t l_ocb_length_act = 0; // Setup use OCB channel 1 for placing instruction in SRAM // Channel will be returned to Linear Stream, Circular upon exit FAPI_EXEC_HWP(l_rc, p9_pm_ocb_indir_setup_linear, i_target, p9ocb::OCB_CHAN1, p9ocb::OCB_TYPE_LINSTR, OCC_SRAM_BOOT_ADDR); // Bar FAPI_TRY(l_rc); // lis r1, 0x8000 l_sram_program[0] = ((uint64_t)ppc_lis(1, 0x8000) << 32); FAPI_DBG("ppc_lis: 0x%08X with data 0x%08X", ppc_lis(1, 0x8000), 0x8000); // ori r1, r1, OCC_BOOT_OFFSET l_sram_program[0] |= (ppc_ori(1, 1, OCC_BOOT_OFFSET)); FAPI_DBG("ppc_ori: 0x%08X with data 0x%08X", ppc_ori(1, 1, OCC_BOOT_OFFSET), OCC_BOOT_OFFSET); // mtctr (mtspr r1, CTR ) l_sram_program[1] = ((uint64_t)ppc_mtspr(1, CTR) << 32); FAPI_DBG("ppc_mtspr: 0x%08X with spr 0x%08X", ppc_mtspr(1, CTR), CTR); // bctr l_sram_program[1] |= ppc_bctr(); FAPI_DBG("ppc_bctr: 0x%08X", ppc_bctr()); FAPI_DBG("SRAM PGM[0]: 0x%016llX", l_sram_program[0]); FAPI_DBG("SRAM PGM[1]: 0x%016llX", l_sram_program[1]); // Write to SRAM FAPI_EXEC_HWP(l_rc, p9_pm_ocb_indir_access, i_target, p9ocb::OCB_CHAN1, p9ocb::OCB_PUT, SRAM_PROGRAM_SIZE, false, 0, l_ocb_length_act, l_sram_program); FAPI_ASSERT(l_ocb_length_act == SRAM_PROGRAM_SIZE, fapi2::OCC_CONTROL_MEM_BOOT_LENGTH_MISMATCH() .set_ACTLENGTH(l_ocb_length_act) .set_LENGTH(SRAM_PROGRAM_SIZE), "OCC memory boot launcher length mismatch"); // b OCC_SRAM_BOOT_ADDR2 i_data64.insertFromRight<0, 32>(ppc_b(OCC_SRAM_BOOT_ADDR2)); fapi_try_exit: // Channel 1 returned to Linear Stream, Circular upon exit FAPI_EXEC_HWP(l_rc, p9_pm_ocb_indir_setup_circular, i_target, p9ocb::OCB_CHAN1, p9ocb::OCB_TYPE_CIRC, 0, // Bar 0, // Length p9ocb::OCB_Q_OUFLOW_NULL, p9ocb::OCB_Q_ITPTYPE_NULL); fapi2::current_err = l_rc; return fapi2::current_err; }
fapi2::ReturnCode p9_chiplet_fabric_scominit(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target) { fapi2::ReturnCode l_rc; char l_procTargetStr[fapi2::MAX_ECMD_STRING_LEN]; char l_chipletTargetStr[fapi2::MAX_ECMD_STRING_LEN]; fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> FAPI_SYSTEM; std::vector<fapi2::Target<fapi2::TARGET_TYPE_XBUS>> l_xbus_chiplets; std::vector<fapi2::Target<fapi2::TARGET_TYPE_OBUS>> l_obus_chiplets; fapi2::ATTR_PROC_FABRIC_OPTICS_CONFIG_MODE_Type l_fbc_optics_cfg_mode = { fapi2::ENUM_ATTR_PROC_FABRIC_OPTICS_CONFIG_MODE_SMP }; FAPI_DBG("Start"); // Get proc target string fapi2::toString(i_target, l_procTargetStr, sizeof(l_procTargetStr)); // apply FBC non-hotplug initfile FAPI_DBG("Invoking p9.fbc.no_hp.scom.initfile on target %s...", l_procTargetStr); FAPI_EXEC_HWP(l_rc, p9_fbc_no_hp_scom, i_target, FAPI_SYSTEM); if (l_rc) { FAPI_ERR("Error from p9_fbc_no_hp_scom"); fapi2::current_err = l_rc; goto fapi_try_exit; } // setup IOE (XBUS FBC IO) TL SCOMs FAPI_DBG("Invoking p9.fbc.ioe_tl.scom.initfile on target %s...", l_procTargetStr); FAPI_EXEC_HWP(l_rc, p9_fbc_ioe_tl_scom, i_target, FAPI_SYSTEM); if (l_rc) { FAPI_ERR("Error from p9_fbc_ioe_tl_scom"); fapi2::current_err = l_rc; goto fapi_try_exit; } l_xbus_chiplets = i_target.getChildren<fapi2::TARGET_TYPE_XBUS>(); if (l_xbus_chiplets.size()) { FAPI_TRY(fapi2::putScom(i_target, PU_PB_IOE_FIR_ACTION0_REG, FBC_IOE_TL_FIR_ACTION0), "Error from putScom (PU_PB_IOE_FIR_ACTION0_REG)"); FAPI_TRY(fapi2::putScom(i_target, PU_PB_IOE_FIR_ACTION1_REG, FBC_IOE_TL_FIR_ACTION1), "Error from putScom (PU_PB_IOE_FIR_ACTION1_REG)"); FAPI_TRY(fapi2::putScom(i_target, PU_PB_IOE_FIR_MASK_REG, FBC_IOE_TL_FIR_MASK), "Error from putScom (PU_PB_IOE_FIR_MASK_REG)"); } // setup IOE (XBUS FBC IO) DL SCOMs for (auto l_iter = l_xbus_chiplets.begin(); l_iter != l_xbus_chiplets.end(); l_iter++) { fapi2::toString(*l_iter, l_chipletTargetStr, sizeof(l_chipletTargetStr)); FAPI_DBG("Invoking p9.fbc.ioe_dl.scom.initfile on target %s...", l_chipletTargetStr); FAPI_EXEC_HWP(l_rc, p9_fbc_ioe_dl_scom, *l_iter, i_target); if (l_rc) { FAPI_ERR("Error from p9_fbc_ioe_dl_scom"); fapi2::current_err = l_rc; goto fapi_try_exit; } // configure action registers & unmask FAPI_TRY(fapi2::putScom(*l_iter, XBUS_LL0_IOEL_FIR_ACTION0_REG, FBC_IOE_DL_FIR_ACTION0), "Error from putScom (XBUS_LL0_IOEL_FIR_ACTION0_REG)"); FAPI_TRY(fapi2::putScom(*l_iter, XBUS_LL0_IOEL_FIR_ACTION1_REG, FBC_IOE_DL_FIR_ACTION1), "Error from putScom (XBUS_LL0_IOEL_FIR_ACTION1_REG)"); FAPI_TRY(fapi2::putScom(*l_iter, XBUS_LL0_LL0_LL0_IOEL_FIR_MASK_REG, FBC_IOE_DL_FIR_MASK), "Error from putScom (XBUS_LL0_LL0_LL0_IOEL_FIR_MASK_REG)"); } // set FBC optics config mode attribute l_obus_chiplets = i_target.getChildren<fapi2::TARGET_TYPE_OBUS>(); for (auto l_iter = l_obus_chiplets.begin(); l_iter != l_obus_chiplets.end(); l_iter++) { uint8_t l_unit_pos; FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, *l_iter, l_unit_pos), "Error from FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS)"); FAPI_INF("Updating index: %d\n", l_unit_pos); FAPI_INF(" before: %d\n", l_fbc_optics_cfg_mode[l_unit_pos]); FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_OPTICS_CONFIG_MODE, *l_iter, l_fbc_optics_cfg_mode[l_unit_pos]), "Error from FAPI_ATTR_GET(ATTR_OPTICS_CONFIG_MODE)"); FAPI_INF(" after: %d\n", l_fbc_optics_cfg_mode[l_unit_pos]); } FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_PROC_FABRIC_OPTICS_CONFIG_MODE, i_target, l_fbc_optics_cfg_mode), "Error from FAPI_ATTR_SET(ATTR_PROC_FABRIC_OPTICS_CONFIG_MODE)"); fapi_try_exit: FAPI_DBG("End"); return fapi2::current_err; }
//------------------------------------------------------------------------------ // function: // Stop SBE runtime scan service // // parameters: i_target => chip target // returns: FAPI_RC_SUCCESS if operation was successful, else error //------------------------------------------------------------------------------ fapi::ReturnCode proc_stop_sbe_scan_service( const fapi::Target& i_target, const void* i_pSEEPROM) { // return codes fapi::ReturnCode rc; uint32_t rc_ecmd = 0; // track if procedure has cleared I2C master bus fence bool i2cm_bus_fence_cleared = false; // mark function entry FAPI_DBG("Start"); do { // check SBE progress bool sbe_running = true; size_t loop_time = 0; uint8_t halt_code = 0; uint16_t istep_num = 0; uint8_t substep_num = 0; bool scan_service_loop_reached = false; // retrieve status rc = proc_sbe_utils_check_status( i_target, sbe_running, halt_code, istep_num, substep_num); if (!rc.ok()) { FAPI_ERR("Error from proc_check_sbe_state_check_status"); break; } // get HB->SBE request mailbox, check that it is clear ecmdDataBufferBase mbox_data(64); bool sbe_ready = false; rc = fapiGetScom(i_target, MBOX_SCRATCH_REG0_0x00050038, mbox_data); if (!rc.ok()) { FAPI_ERR("Scom error reading SBE MBOX0 Register"); break; } sbe_ready = (mbox_data.getDoubleWord(0) == 0); scan_service_loop_reached = sbe_running && sbe_ready && !halt_code && (istep_num == PROC_SBE_SCAN_SERVICE_ISTEP_NUM) && (substep_num == SUBSTEP_SBE_READY); FAPI_INF("SBE is running [%d], loop time [%zd], scan service loop reached [%d]", sbe_running, loop_time, scan_service_loop_reached); if (!sbe_running) { FAPI_INF("SBE is stopped, exiting!"); break; } else if (scan_service_loop_reached) { // format stop request rc_ecmd |= mbox_data.setBit(MBOX0_REQUEST_VALID_BIT); rc_ecmd |= mbox_data.insertFromRight(MBOX0_HALT_PATTERN, MBOX0_HALT_PATTERN_START_BIT, (MBOX0_HALT_PATTERN_END_BIT- MBOX0_HALT_PATTERN_START_BIT)+1); if (rc_ecmd) { FAPI_ERR("Error 0x%x setting up SBE MBOX0 data buffer.", rc_ecmd); rc.setEcmdError(rc_ecmd); break; } // submit stop request to SBE FAPI_DBG("Submitting stop request to SBE"); rc = fapiPutScom(i_target, MBOX_SCRATCH_REG0_0x00050038, mbox_data); if (!rc.ok()) { FAPI_ERR("Error writing SBE MBOX0 Register"); break; } // pause to allow request to be processed uint32_t loop_num = 0; while (sbe_running && (loop_num < SBE_HALT_POLL_MAX_LOOPS)) { loop_num++; rc = fapiDelay(SBE_HALT_POLL_DELAY_HW, SBE_HALT_POLL_DELAY_SIM); if (!rc.ok()) { FAPI_ERR("Error from fapiDelay"); break; } // retrieve status rc = proc_sbe_utils_check_status( i_target, sbe_running, halt_code, istep_num, substep_num); if (!rc.ok()) { FAPI_ERR("Error from proc_check_sbe_state_check_status"); break; } } if (rc) { break; } if (sbe_running) { FAPI_ERR("SBE is STILL running!"); const fapi::Target & TARGET = i_target; FAPI_SET_HWP_ERROR(rc, RC_PROC_STOP_SBE_SCAN_SERVICE_SBE_NOT_STOPPED); break; } // before analysis proceeds, make sure that I2C master bus fence is cleared FAPI_EXEC_HWP(rc, proc_reset_i2cm_bus_fence, i_target); if (!rc.ok()) { FAPI_ERR("Error from proc_reset_i2cm_bus_fence"); break; } // mark that fence has been cleared i2cm_bus_fence_cleared = true; // ensure correct halt code is captured rc = proc_sbe_utils_check_status( i_target, sbe_running, halt_code, istep_num, substep_num); if (!rc.ok()) { FAPI_ERR("Error from proc_check_sbe_state_check_status"); break; } // confirm that expected halt point was reached if (halt_code != SBE_EXIT_SUCCESS_0xF) { FAPI_ERR("SBE halted with error 0x%X (istep 0x%03X, substep 0x%X)", halt_code, istep_num, substep_num); // extract & return error code from analyzing SBE state FAPI_EXEC_HWP(rc, proc_extract_sbe_rc, i_target, NULL, i_pSEEPROM, SBE); break; } if ((istep_num != PROC_SBE_SCAN_SERVICE_ISTEP_NUM) || (substep_num != SUBSTEP_HALT_SUCCESS)) { FAPI_ERR("Expected SBE istep 0x%03llX, substep 0x%X but found istep 0x%03X, substep 0x%X", PROC_SBE_SCAN_SERVICE_ISTEP_NUM, SUBSTEP_HALT_SUCCESS, istep_num, substep_num); const fapi::Target & TARGET = i_target; const uint32_t & ISTEP_NUM = istep_num; const uint32_t & SUBSTEP_NUM = substep_num; FAPI_SET_HWP_ERROR(rc, RC_PROC_STOP_SBE_SCAN_SERVICE_SBE_BAD_HALT); break; } // Reset the SBE so it can be used for MPIPL if needed ecmdDataBufferBase sbe_reset_data(64); rc = fapiPutScom(i_target, PORE_SBE_RESET_0x000E0002, sbe_reset_data); if (!rc.ok()) { FAPI_ERR("Scom error resetting SBE\n"); break; } } // error else { FAPI_ERR("SBE did not reach acceptable final state!"); const fapi::Target & TARGET = i_target; const bool & SBE_RUNNING = sbe_running; const uint8_t & HALT_CODE = halt_code; const uint16_t & ISTEP_NUM = istep_num; const uint8_t & SUBSTEP_NUM = substep_num; FAPI_SET_HWP_ERROR(rc, RC_PROC_STOP_SBE_SCAN_SERVICE_UNEXPECTED_FINAL_STATE); break; } } while(0); // if an error occurred prior to the I2C master bus fence // being cleared, attempt to clear it prior to exit if (!rc.ok() && !i2cm_bus_fence_cleared) { // discard rc, return that of original fail fapi::ReturnCode rc_unused; FAPI_EXEC_HWP(rc_unused, proc_reset_i2cm_bus_fence, i_target); } // mark function entry FAPI_DBG("End"); return rc; }