summaryrefslogtreecommitdiffstats
path: root/src/import/chips/ocmb
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2019-02-14 11:33:59 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2019-04-29 09:40:24 -0500
commit290b29f13a8ace0ba6dfbfc75e73f5a2e2a80504 (patch)
tree85d72bcfaaf13994092c9e69406d35ad28e06b42 /src/import/chips/ocmb
parent510773cb52f9cd47366302bcd0152ece24c98d0b (diff)
downloadtalos-hostboot-290b29f13a8ace0ba6dfbfc75e73f5a2e2a80504.tar.gz
talos-hostboot-290b29f13a8ace0ba6dfbfc75e73f5a2e2a80504.zip
Adds explorer training response display functions
Change-Id: Id3467db3b28257565fab0db1bed94fe8a829c6d4 Original-Change-Id: I2e5c8ef08cda7abf83a322d2a3b0e01de2aaee41 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/71902 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: Mark Pizzutillo <mark.pizzutillo@ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/76598 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/ocmb')
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C302
1 files changed, 302 insertions, 0 deletions
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C
index be36f974b..c75014bdc 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C
@@ -22,3 +22,305 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_train_display.C
+/// @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
+
+#include <fapi2.H>
+#include <lib/shared/exp_consts.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 <generic/memory/lib/utils/find.H>
+#include <exp_data_structs.H>
+#include <lib/phy/exp_train_display.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+
+namespace mss
+{
+namespace exp
+{
+namespace train
+{
+///
+/// @brief Displays training information
+/// @param[in] i_target the OCMB target
+/// @param[in] i_lane the lane for the training information
+/// @param[in] i_data the training data for this lane
+///
+void display_lane_results(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint64_t i_lane,
+ const uint16_t i_data)
+{
+ // Extracts the per-rank information
+ fapi2::buffer<uint16_t> l_data(i_data);
+ uint8_t l_rank0 = 0;
+ uint8_t l_rank1 = 0;
+ uint8_t l_rank2 = 0;
+ uint8_t l_rank3 = 0;
+
+ l_data.extractToRight<0, BITS_PER_NIBBLE>(l_rank3)
+ .extractToRight<BITS_PER_NIBBLE, BITS_PER_NIBBLE>(l_rank2)
+ .extractToRight<BITS_PER_NIBBLE * 2, BITS_PER_NIBBLE>(l_rank1)
+ .extractToRight<BITS_PER_NIBBLE * 3, BITS_PER_NIBBLE>(l_rank0);
+
+ constexpr uint16_t CLEAN = 0;
+
+ // If we passed, display the information as only as debug - we don't want to clutter the screen with too much information
+ if(CLEAN == i_data)
+ {
+ FAPI_DBG("%s lane: %u PASSING R0:%u R1:%u R2:%u R3:%u",
+ mss::c_str(i_target), i_lane,
+ l_rank0, l_rank1, l_rank2, l_rank3);
+ }
+
+ // If we failed, display the information as INF
+ {
+ FAPI_INF("%s lane: %u FAILING R0:%u R1:%u R2:%u R3:%u",
+ mss::c_str(i_target), i_lane,
+ l_rank0, l_rank1, l_rank2, l_rank3);
+ }
+}
+
+///
+/// @brief Displays lane failure information after training
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+///
+void display_lane_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_response_msdg_t& i_training_info)
+{
+ for(uint8_t l_lane = 0; l_lane < exp_struct_sizes::TRAINING_RESPONSE_NUM_LANES; ++l_lane)
+ {
+ display_lane_results( i_target, l_lane, i_training_info.err_resp.Failure_Lane[l_lane]);
+ }
+}
+
+///
+/// @brief Displays MRS information
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+///
+fapi2::ReturnCode display_mrs_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_response_msdg_t& i_training_info)
+{
+ // Loop through all DIMM's
+ for(const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
+ {
+ // Gets the number of DIMM's and x4 vs x8 DRAM
+ // TK update ranks to use rank API
+ uint8_t l_num_master_ranks = 0;
+ uint8_t l_dram_width = 0;
+ FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(l_dimm, l_num_master_ranks));
+ FAPI_TRY(mss::attr::get_dram_width(l_dimm, l_dram_width));
+
+ // Loops through all of the ranks
+ for(uint8_t l_dimm_rank = 0; l_dimm_rank < l_num_master_ranks; ++l_dimm_rank)
+ {
+ // TK update to rank API
+ constexpr uint8_t DIMM_OFFSET = 2;
+ const auto l_rank = l_dimm_rank + mss::index(l_dimm) * DIMM_OFFSET;
+
+ // MRS0->5 are easy, just display the value
+ FAPI_DBG("%s rank%u MRS%u 0x%04x", mss::c_str(i_target), l_rank, 0, i_training_info.mrs_resp.MR0);
+ FAPI_DBG("%s rank%u MRS%u 0x%04x", mss::c_str(i_target), l_rank, 1, i_training_info.mrs_resp.MR1[l_rank]);
+ FAPI_DBG("%s rank%u MRS%u 0x%04x", mss::c_str(i_target), l_rank, 2, i_training_info.mrs_resp.MR2[l_rank]);
+ FAPI_DBG("%s rank%u MRS%u 0x%04x", mss::c_str(i_target), l_rank, 3, i_training_info.mrs_resp.MR3);
+ FAPI_DBG("%s rank%u MRS%u 0x%04x", mss::c_str(i_target), l_rank, 4, i_training_info.mrs_resp.MR4);
+ FAPI_DBG("%s rank%u MRS%u 0x%04x", mss::c_str(i_target), l_rank, 5, i_training_info.mrs_resp.MR5[l_rank]);
+
+ // The number of the DRAM's and the position to access each DRAM changes based upon x4 vs x8
+ const auto l_num_dram = l_dram_width == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ?
+ mss::exp::generic_consts::EXP_NUM_DRAM_X4 :
+ mss::exp::generic_consts::EXP_NUM_DRAM_X8;
+ // The correction factor is used to determine the correct DRAM position, as x8 DRAM's take up two entries
+ const auto l_correction_factor = l_dram_width == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ?
+ 1 : 2;
+
+ for(uint64_t l_dram = 0; l_dram < l_num_dram; ++l_dram)
+ {
+ const auto l_dram_pos = l_correction_factor * l_dram;
+ FAPI_DBG("%s rank%u MRS6 dram%u 0x%04x", mss::c_str(i_target), l_rank, l_dram,
+ i_training_info.mrs_resp.MR6[l_rank][l_dram_pos]);
+ }
+ }
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Displays all RCW information
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+///
+void display_rcw_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_response_msdg_t& i_training_info)
+{
+ constexpr uint64_t FUNC_SPACE0 = 0;
+ constexpr uint64_t FUNC_SPACE1 = 1;
+
+ // Only display the DIMM's that exist
+ const auto& l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target);
+
+ // Display DIMM0
+ if(l_dimms.size() >= 1)
+ {
+ // Display all of function space 0
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 0, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D0[l_rcw]);
+ }
+
+ // Display all of function space 1
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 0, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D0[l_rcw]);
+ }
+ }
+
+ // Display DIMM1
+ if(l_dimms.size() == 2)
+ {
+ // Display all of function space 0
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 1, FUNC_SPACE0, l_rcw, i_training_info.rc_resp.F0RC_D1[l_rcw]);
+ }
+
+ // Display all of function space 1
+ // Display all 4-bit numbers
+ for(uint8_t l_rcw = 0; l_rcw < exp_struct_sizes::RCW_8BIT_CUTOFF; ++l_rcw)
+ {
+ display_rcw_4bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]);
+ }
+
+ // Display all 8-bit numbers
+ for(uint8_t l_rcw = exp_struct_sizes::RCW_8BIT_CUTOFF; l_rcw < exp_struct_sizes::TRAINING_RESPONSE_NUM_RC; ++l_rcw)
+ {
+ display_rcw_8bit( i_target, 1, FUNC_SPACE1, l_rcw, i_training_info.rc_resp.F1RC_D1[l_rcw]);
+ }
+ }
+}
+
+///
+/// @brief Displays command to command response timing
+/// @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
+///
+fapi2::ReturnCode display_response_timing(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_response_msdg_t& i_training_info)
+{
+ uint8_t l_num_rank_per_ocmb = 0;
+
+ // Loop through all DIMM's
+ for(const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
+ {
+ // Gets the number of DIMM's and x4 vs x8 DRAM
+ // TK update ranks to use rank API
+ uint8_t l_num_master_ranks = 0;
+
+ FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(l_dimm, l_num_master_ranks));
+ l_num_rank_per_ocmb += l_num_master_ranks;
+ }
+
+ // DFIMRL_DDRCLK_trained training result
+ FAPI_INF("%s DFIMRL_DDRCLK_trained: %u", mss::c_str(i_target), i_training_info.tm_resp.DFIMRL_DDRCLK_trained);
+
+ // RD to RD
+ FAPI_DBG("%s RD-to-RD : 0 1 2 3", mss::c_str(i_target));
+
+ for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
+ {
+ FAPI_DBG("%s RD-to-RD rank%u: %2i %2i %2i %2i", i_training_info.tm_resp.CDD_RR[l_rank_n][0],
+ i_training_info.tm_resp.CDD_RR[l_rank_n][1], i_training_info.tm_resp.CDD_RR[l_rank_n][2],
+ i_training_info.tm_resp.CDD_RR[l_rank_n][3]);
+ }
+
+ // WR to WR
+ FAPI_DBG("%s WR-to-WR : 0 1 2 3", mss::c_str(i_target));
+
+ for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
+ {
+ FAPI_DBG("%s WR-to-WR rank%u: %2i %2i %2i %2i", i_training_info.tm_resp.CDD_WW[l_rank_n][0],
+ i_training_info.tm_resp.CDD_WW[l_rank_n][1], i_training_info.tm_resp.CDD_WW[l_rank_n][2],
+ i_training_info.tm_resp.CDD_WW[l_rank_n][3]);
+ }
+
+ // WR to RD
+ FAPI_DBG("%s WR-to-RD : 0 1 2 3", mss::c_str(i_target));
+
+ for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
+ {
+ FAPI_DBG("%s WR-to-RD rank%u: %2i %2i %2i %2i", i_training_info.tm_resp.CDD_WR[l_rank_n][0],
+ i_training_info.tm_resp.CDD_WR[l_rank_n][1], i_training_info.tm_resp.CDD_WR[l_rank_n][2],
+ i_training_info.tm_resp.CDD_WR[l_rank_n][3]);
+ }
+
+ // RD to WR
+ FAPI_DBG("%s RD-to-WR : 0 1 2 3", mss::c_str(i_target));
+
+ for(uint8_t l_rank_n = 0; l_rank_n < l_num_rank_per_ocmb; ++l_rank_n)
+ {
+ FAPI_DBG("%s RD-to-WR rank%u: %2i %2i %2i %2i", i_training_info.tm_resp.CDD_RW[l_rank_n][0],
+ i_training_info.tm_resp.CDD_RW[l_rank_n][1], i_training_info.tm_resp.CDD_RW[l_rank_n][2],
+ i_training_info.tm_resp.CDD_RW[l_rank_n][3]);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Displays all training information
+/// @param[in] i_target the OCMB target
+/// @param[in] i_training_info the training information to display
+///
+fapi2::ReturnCode display_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const user_response_msdg_t& i_training_info)
+{
+ FAPI_INF("%s displaying user response data version %u", mss::c_str(i_target), i_training_info.version_number)
+ display_rcw_info(i_target, i_training_info);
+ FAPI_TRY(display_mrs_info(i_target, i_training_info));
+ display_lane_info(i_target, i_training_info);
+ FAPI_TRY(display_response_timing(i_target, i_training_info));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // ns train
+} // ns exp
+} // ns mss
OpenPOWER on IntegriCloud