diff options
Diffstat (limited to 'src/import/chips')
6 files changed, 294 insertions, 16 deletions
diff --git a/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H b/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H index aeadb9905..df319eff1 100644 --- a/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H +++ b/src/import/chips/ocmb/explorer/common/include/exp_data_structs.H @@ -55,6 +55,14 @@ enum exp_struct_sizes ARGUMENT_SIZE = 28, SENSOR_CACHE_PADDING_SIZE_0 = 3, SENSOR_CACHE_PADDING_SIZE_1 = 15, + + // Training response constants + TIMING_RESPONSE_2D_ARRAY_SIZE = 16, + TRAINING_RESPONSE_NUM_RANKS = 4, + TRAINING_RESPONSE_NUM_DRAM = 20, + TRAINING_RESPONSE_NUM_LANES = 80, + TRAINING_RESPONSE_NUM_RC = 27, + TRAINING_RESPONSE_MR6_SIZE = TRAINING_RESPONSE_NUM_RANKS * TRAINING_RESPONSE_NUM_DRAM, }; /// @@ -604,17 +612,17 @@ typedef struct user_response_timing_msdg //DFI rank-to rank space timing must be determined by the actual board delay (DQ/DQS bus turnarounds). //PHY firmware training result provide CDD (critical delay difference) information to help to calculate the minimum required timing spacing for memory controllers. //Minimal possible gap between rank-to-rank read-read transaction is defined by tCCDmin(R_rank[i], R_rank[j]) = 4 + max(abs(CDD_RR_[i]_[j])); - int8_t CDD_RR[4][4]; // CDD_RR[n][m]: This is a signed integer value. Read to read critical delay difference from cs n to cs m + int8_t CDD_RR[TRAINING_RESPONSE_NUM_RANKS][TRAINING_RESPONSE_NUM_RANKS]; // CDD_RR[n][m]: This is a signed integer value. Read to read critical delay difference from cs n to cs m // CDD_RR[0][0], CDD_RR[1][1], CDD_RR[2][2], CDD_RR[3][3] are always 0; //Minimal possible gap between rank-to-rank write-write transaction is defined by tCCDmin(W_rank[i], W_rank[j]) = 4 + max(abs(CDD_WW_[i]_[j])); - int8_t CDD_WW[4][4]; // CDD_WW[n][m]: This is a signed integer value. Write to write critical delay difference from cs n to cs m + int8_t CDD_WW[TRAINING_RESPONSE_NUM_RANKS][TRAINING_RESPONSE_NUM_RANKS]; // CDD_WW[n][m]: This is a signed integer value. Write to write critical delay difference from cs n to cs m // CDD_WW[0][0], CDD_WW[1][1], CDD_WW[2][2], CDD_WW[3][3] are always 0; //Minimal possible gap between rank-to-rank read-write transaction is defined by tCCDmin(R_rank[i], W_rank[j]) = (RL + BL/2 + 1 + WR_PREAMBLE - WL) + max(abs(CDD_RW_[i]_[j])); //RL: Read Latency; WL: Write Latency; BL: Burst Length; WR_PREAMBLE: Write Preamble cycles - int8_t CDD_RW[4][4]; // CDD_RW[n][m]This is a signed integer value. Read to write critical delay difference from cs 3 to cs 3 + int8_t CDD_RW[TRAINING_RESPONSE_NUM_RANKS][TRAINING_RESPONSE_NUM_RANKS]; // CDD_RW[n][m]This is a signed integer value. Read to write critical delay difference from cs 3 to cs 3 //Minimal possible gap between rank-to-rank write-read transaction is defined by tCCDmin(W_rank[i], R_rank[j]) = (WL + PL + BL/2 + tWTR_L) + max(abs(CDD_RW_[i]_[j])); //WL: Write Latency; BL: Burst Length; PL: CA Parity Latency; tWTR_L: delay from internal write to internal read for same bank group - int8_t CDD_WR[4][4]; // CDD_WR[n][m]This is a signed integer value. Write to read critical delay difference from cs 3 to cs 3 + int8_t CDD_WR[TRAINING_RESPONSE_NUM_RANKS][TRAINING_RESPONSE_NUM_RANKS]; // CDD_WR[n][m]This is a signed integer value. Write to read critical delay difference from cs 3 to cs 3 } user_response_timing_msdg_t; /// @@ -623,7 +631,7 @@ typedef struct user_response_timing_msdg /// typedef struct user_response_error_msdg { - uint16_t Failure_Lane[80]; // error code of DQ[n] on Rank 3,2,1 & 0. Rank 0 is in LS Nibble. + uint16_t Failure_Lane[TRAINING_RESPONSE_NUM_LANES]; // error code of DQ[n] on Rank 3,2,1 & 0. Rank 0 is in LS Nibble. //Failure status of training. Each uint16_t field contains the training error code of all 4 ranks on 1 DQ lane. //4-bit error code reports the training errors: //0x0: No Error @@ -646,12 +654,12 @@ typedef struct user_response_error_msdg typedef struct user_response_mrs_msdg_t { uint16_t MR0; // Value of DDR mode register MR0 for all ranks, all devices - uint16_t MR1[4]; // Value of DDR mode register MR1 for each rank (up to 4 ranks) - uint16_t MR2[4]; // Value of DDR mode register MR2 for each rank (up to 4 ranks) + uint16_t MR1[TRAINING_RESPONSE_NUM_RANKS]; // Value of DDR mode register MR1 for each rank (up to 4 ranks) + uint16_t MR2[TRAINING_RESPONSE_NUM_RANKS]; // Value of DDR mode register MR2 for each rank (up to 4 ranks) uint16_t MR3; // Value of DDR mode register MR3 for all ranks, all devices uint16_t MR4; // Value of DDR mode register MR4 for all ranks, all devices - uint16_t MR5[4]; // Value of DDR mode register MR5 for each rank (up to 4 ranks) - uint16_t MR6[4][20]; // Value of DDR mode register MR6 for each nibble on each rank + uint16_t MR5[TRAINING_RESPONSE_NUM_RANKS]; // Value of DDR mode register MR5 for each rank (up to 4 ranks) + uint16_t MR6[TRAINING_RESPONSE_NUM_RANKS][TRAINING_RESPONSE_NUM_DRAM]; // Value of DDR mode register MR6 for each nibble on each rank // for X8,X16 DRAMs MR6[i][2n+1] = MR6[i][2n] (n = 0~9) } user_response_mrs_msdg_t; @@ -661,16 +669,16 @@ typedef struct user_response_mrs_msdg_t /// typedef struct user_response_rc_msdg_t { - uint8_t F0RC_D0[27]; // RCD control words for DIMM0; Invalid for UDIMM + uint8_t F0RC_D0[TRAINING_RESPONSE_NUM_RC]; // RCD control words for DIMM0; Invalid for UDIMM // F0RC_D0[15:0] BIT [3:0]: 4-bit value of F0RC00~F0RC0F // F0RC_D0[26:16] BIT [7:0]: 8-bit value of F0RC1x~F0RCBx - uint8_t F1RC_D0[27]; // RCD control words for DIMM0; Invalid for UDIMM + uint8_t F1RC_D0[TRAINING_RESPONSE_NUM_RC]; // RCD control words for DIMM0; Invalid for UDIMM // F1RC_D0[15:0] BIT [3:0]: 4-bit value of F1RC00~F1RC0F // F1RC_D0[26:16] BIT [7:0]: 8-bit value of F1RC1x~F1RCBx - uint8_t F0RC_D1[27]; // RCD control words for DIMM1; Invalid for UDIMM + uint8_t F0RC_D1[TRAINING_RESPONSE_NUM_RC]; // RCD control words for DIMM1; Invalid for UDIMM // F0RC_D0[15:0] BIT [3:0]: 4-bit value of F0RC00~F0RC0F // F0RC_D0[26:16] BIT [7:0]: 8-bit value of F0RC1x~F0RCBx - uint8_t F1RC_D1[27]; // RCD control words for DIMM1; Invalid for UDIMM + uint8_t F1RC_D1[TRAINING_RESPONSE_NUM_RC]; // RCD control words for DIMM1; Invalid for UDIMM // F1RC_D0[15:0] BIT [3:0]: 4-bit value of F1RC00~F1RC0F // F1RC_D0[26:16] BIT [7:0]: 8-bit value of F1RC1x~F1RCBx } user_response_rc_msdg_t; diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C index e022ad49b..1b59893bb 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C @@ -34,9 +34,11 @@ // *HWP Consumed by: FSP:HB #include <exp_inband.H> +#include <lib/shared/exp_consts.H> #include <generic/memory/lib/utils/c_str.H> #include <lib/exp_draminit_utils.H> -#include <lib/shared/exp_consts.H> +#include <lib/phy/exp_train_display.H> +#include <lib/phy/exp_train_handler.H> extern "C" { @@ -68,16 +70,45 @@ extern "C" // Read the response message from EXP-FW RESP buffer { host_fw_response_struct l_response; + user_response_msdg l_train_response; + std::vector<uint8_t> l_rsp_data; + fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); + FAPI_TRY( mss::exp::ib::getRSP(i_target, l_response, l_rsp_data), "Failed getRSP() for %s", mss::c_str(i_target) ); + // Proccesses the response data + FAPI_TRY( mss::exp::read_training_response(i_target, l_rsp_data, l_train_response), + "Failed read_training_response for %s", mss::c_str(i_target)); + + // Displays the training response + FAPI_TRY( mss::exp::train::display_info(i_target, l_train_response)); + // Check if cmd was successful - FAPI_TRY(mss::exp::check::response(i_target, l_response), - "Failed check::response() for %s", mss::c_str(i_target) ); + l_rc = mss::exp::check::response(i_target, l_response); + + // If not, then we need to process the bad bitmap + if(l_rc != fapi2::FAPI2_RC_SUCCESS) + { + mss::exp::bad_bit_interface l_interface; + + // Record bad bits should only fail if we have an attributes issue - that's a major issue + FAPI_TRY(mss::record_bad_bits<mss::mc_type::EXPLORER>(i_target, l_interface)); + + // Now, go to our true error handling procedure + FAPI_TRY(l_rc, "mss::exp::check::response failed for %s", mss::c_str(i_target)); + } } fapi_try_exit: + FAPI_INF("Draminit training - %s %s", + (fapi2::current_err == fapi2::FAPI2_RC_SUCCESS ? "success" : "errors reported"), + mss::c_str(i_target)); + + // TK update this to check FIR's or PLL failures - that will be updated in another commit + // For now, return current_err return fapi2::current_err; + } } diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H index 0ccf265ac..f4afb90f7 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.H @@ -22,3 +22,47 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file exp_train_display.H +/// @brief Procedures used to display the training response information +/// +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#ifndef _EXP_TRAIN_DISPLAY_H_ +#define _EXP_TRAIN_DISPLAY_H_ + +#include <fapi2.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> +#include <generic/memory/lib/utils/index.H> +#include <generic/memory/lib/utils/c_str.H> +#include <exp_data_structs.H> + +namespace mss +{ +namespace exp +{ +namespace train +{ +/// +/// @brief Displays all training information +/// @param[in] i_target the OCMB target +/// @param[in] i_training_info the training information to display +/// @return returns FAPI2_RC_SUCCESS iff the procedure executes successfully +/// @note This is a place holder to help avoid merge conflicts +/// +inline fapi2::ReturnCode display_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const user_response_msdg_t& i_training_info) +{ + return fapi2::FAPI2_RC_SUCCESS; +} + + +} // ns train +} // ns exp +} // ns mss +#endif diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C index eaec113d2..976812fc0 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.C @@ -22,3 +22,126 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file exp_train_handler.C +/// @brief Procedure handle any training fails from the explorer +/// +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include <fapi2.H> +#include <lib/shared/exp_consts.H> +#include <exp_data_structs.H> +#include <generic/memory/lib/utils/mss_bad_bits.H> +#include <generic/memory/lib/utils/endian_utils.H> +#include <generic/memory/lib/mss_generic_attribute_setters.H> +#include <generic/memory/lib/mss_generic_attribute_getters.H> +#include <exp_train_handler.H> + + +namespace mss +{ + +/// +/// @brief A generic bad bits setter +/// @tparam MC type memory controller type +/// @param[in] i_target the fapi2 target oon which training was conducted +/// @param[in] i_array the bad bits to set +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired +/// +template <> +fapi2::ReturnCode set_bad_dq_bitmap<mss::mc_type::EXPLORER>(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + uint8_t (&i_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) +{ + return mss::attr::set_bad_dq_bitmap(i_target, i_array); +} + +namespace check +{ + +/// +/// @brief Checks whether any FIRs have lit up on a target - EXPLOER/OCMB specialization +/// @param[in] i_target - the target on which to operate +/// @param[in,out] io_rc - the return code for the function +/// @param[out] o_fir_error - true iff a FIR was hit +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// +// TK update this when FIR's are fully reviewed +template<> +fapi2::ReturnCode bad_fir_bits<mss::mc_type::EXPLORER>( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error ) +{ + o_fir_error = false; + return fapi2::FAPI2_RC_SUCCESS; +} + +} // ns check + +namespace exp +{ + +/// +/// @brief Reads the training response structure +/// @param[in] i_target the target associated with the response data +/// @param[in] i_data the response data to read +/// @param[out] o_resp the processed training response class +/// @return FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode read_training_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const std::vector<uint8_t>& i_data, + user_response_msdg& o_resp) +{ + + // True if we pass + // We assert at the end to avoid LOTS of fapi asserts + uint32_t l_idx = 0; + bool l_pass = readLE(i_data, l_idx, o_resp.version_number); + + // Reads in the timing portion of the training response + l_pass &= readLE(i_data, l_idx, o_resp.tm_resp.DFIMRL_DDRCLK_trained); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_RR[0][0]); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_WW[0][0]); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_RW[0][0]); + l_pass &= readLEArray(i_data, TIMING_RESPONSE_2D_ARRAY_SIZE, l_idx, &o_resp.tm_resp.CDD_WR[0][0]); + + // Error response + l_pass &= readLEArray(i_data, 80, l_idx, o_resp.err_resp.Failure_Lane); + + // MRS response + l_pass &= readLE(i_data, l_idx, o_resp.mrs_resp.MR0); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR1); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR2); + l_pass &= readLE(i_data, l_idx, o_resp.mrs_resp.MR3); + l_pass &= readLE(i_data, l_idx, o_resp.mrs_resp.MR4); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RANKS, l_idx, o_resp.mrs_resp.MR5); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_MR6_SIZE, l_idx, &o_resp.mrs_resp.MR6[0][0]); + + // Register Control Word (RCW) response + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F0RC_D0); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F1RC_D0); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F0RC_D1); + l_pass &= readLEArray(i_data, TRAINING_RESPONSE_NUM_RC, l_idx, o_resp.rc_resp.F1RC_D1); + + // Check if we have errors + FAPI_ASSERT( l_pass, + fapi2::EXP_INBAND_LE_DATA_RANGE() + .set_TARGET(i_target) + .set_FUNCTION(mss::exp::READ_TRAINING_RESPONSE_STRUCT) + .set_DATA_SIZE(i_data.size()) + .set_MAX_INDEX(sizeof(user_response_msdg)), + "%s Failed to convert from data to host_fw_response_struct data size %u expected size %u", + mss::c_str(i_target), i_data.size(), sizeof(user_response_msdg)); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +} // ns exp +} // ns mss diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H index 1a41c395d..bb6bca47a 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_handler.H @@ -22,3 +22,74 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file exp_train_handler.H +/// @brief Procedure handle any training fails from the explorer +/// +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#ifndef __EXP_TRAIN_HANDLER_H__ +#define __EXP_TRAIN_HANDLER_H__ + +#include <fapi2.H> +#include <lib/shared/exp_consts.H> +#include <exp_data_structs.H> +#include <generic/memory/lib/utils/mss_bad_bits.H> +#include <generic/memory/lib/mss_generic_attribute_setters.H> +#include <generic/memory/lib/mss_generic_attribute_getters.H> + +namespace mss +{ +namespace exp +{ + +/// +/// @brief Reads the training response structure +/// @param[in] i_target the target associated with the response data +/// @param[in] i_data the response data to read +/// @param[out] o_resp the processed training response class +/// @return FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode read_training_response(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target, + const std::vector<uint8_t>& i_data, + user_response_msdg& o_resp); + +/// +/// @brief Explorer's bad bit interface class +/// @note L1 functionality Place holder to avoid merge conflicts. This will be updated in another commit +/// +class bad_bit_interface +{ + public: + + /// + /// @brief Default constructor + /// + bad_bit_interface() = default; + + /// + /// @brief Default destructor + /// + ~bad_bit_interface() = default; + + /// + /// @param[in] i_target the DIMM to record training results on + /// @param[out] o_bad_bits the processed bad bits + /// @return FAPI2_RC_SUCCESS if ok + /// + fapi2::ReturnCode record_bad_bits_interface( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + uint8_t (&o_bad_dq)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) const + { + return fapi2::FAPI2_RC_SUCCESS; + } +}; + +} // ns exp +} // ns mss + +#endif diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H index ec90cfe72..9d4857b72 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H @@ -91,6 +91,7 @@ enum ffdc_codes READ_HOST_FW_RESPONSE_STRUCT = 0x0003, READ_SENSOR_CACHE_STRUCT = 0x0004, READ_CRCT_ENDIAN = 0x0005, + READ_TRAINING_RESPONSE_STRUCT = 0x0006, SET_BYTE_ENABLES = 0x1041, SET_NIBBLE_ENABLES = 0x1042, |