summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2017-04-12 13:45:43 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-04-27 09:16:15 -0400
commitfcd4f43af5012d7f1ef57f68b06b1a8b4678f89f (patch)
tree3b94d3b34b4e515cdffbdecd172ac17f99b7b8f4 /src/import/chips/p9/procedures/hwp/memory/lib
parent74a9324db23d799735f88b012ab002343011c9d1 (diff)
downloadtalos-hostboot-fcd4f43af5012d7f1ef57f68b06b1a8b4678f89f.tar.gz
talos-hostboot-fcd4f43af5012d7f1ef57f68b06b1a8b4678f89f.zip
Added read ctr bad delay workaround
The workaround finds the median and moves delays below a specified percentage of this median to be the median value. Change-Id: I058c61a1e7734771ab31be3f48760030fbf945b5 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39178 Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com> Dev-Ready: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: Thi N. Tran <thi@us.ibm.com> Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Matt K. Light <mklight@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39181 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.H1
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H23
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C40
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H7
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C309
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H76
6 files changed, 450 insertions, 6 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.H
index 4a3700f54..bdd0a7a3d 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.H
@@ -81,6 +81,7 @@ enum rank_functions
GET_RANK_FIELD = 4,
GET_PAIR_VALID = 5,
SET_RANK_FIELD = 6,
+ RD_CTR_WORKAROUND_READ_DATA = 7,
};
///
/// @class rankPairTraits
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H
index cccb0d57e..069b24625 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H
@@ -337,6 +337,29 @@ fapi_try_exit:
}
///
+/// @brief ATTR_CHIP_EC_FEATURE_MSS_RUN_RD_CTR_WOKRAROUND getter
+/// @tparam T the fapi2 target type of the target
+/// @param[in] const ref to the target
+/// @return bool true iff feature is enabled
+///
+template< fapi2::TargetType T >
+inline bool chip_ec_feature_mss_run_rd_ctr_workaround(const fapi2::Target<T>& i_target)
+{
+ const auto l_chip = mss::find_target<fapi2::TARGET_TYPE_PROC_CHIP>(i_target);
+ uint8_t l_value = 0;
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_MSS_RUN_RD_CTR_WOKRAROUND, l_chip, l_value) );
+
+ return l_value != 0;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_CHIP_EC_FEATURE_MSS_RUN_RD_CTR_WOKRAROUND: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ fapi2::Assert(false);
+ return false;
+}
+
+///
/// @brief ATTR_SKIP_RD_VREF_VREFSENSE_OVERRIDE getter
/// @tparam T the fapi2 target type of the target
/// @param[in] const ref to the target
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C
index 6f9bc77c0..c3d3151f5 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C
@@ -423,7 +423,7 @@ fapi2::ReturnCode rank_pair_primary_to_dimm( const fapi2::Target<TARGET_TYPE_MCA
// Sanity check the rank pair
FAPI_INF("%s rank pair: %d", mss::c_str(i_target), i_rp);
- FAPI_ASSERT( i_rp < MAX_RANK_PER_DIMM,
+ FAPI_ASSERT( i_rp < MAX_RANK_PAIRS,
fapi2::MSS_INVALID_RANK_PAIR()
.set_RANK_PAIR(i_rp)
.set_MCA_TARGET(i_target)
@@ -1067,12 +1067,42 @@ fapi2::ReturnCode setup_and_execute_cal( const fapi2::Target<fapi2::TARGET_TYPE_
}
}
- // Run cal steps after WR_LEVEL if any are selected
- if (i_cal_steps_enabled.getBit<mss::cal_steps::DQS_ALIGN, mss::cal_steps::STEPS_AFTER_WR_LEVEL>())
+ // Run cal steps between WR_LEVEL and RD_CTR if any are selected - note DQS_ALIGN takes place after WR_LEVEL
+ if (i_cal_steps_enabled.getBit
+ < mss::cal_steps::DQS_ALIGN, mss::cal_steps::STEPS_FROM_DQS_ALIGN_TO_AFTER_RD_CTR_LEN > ())
{
- FAPI_DBG("%s Running remaining cal steps on RP%d", mss::c_str(i_target), i_rp);
+ // Sets up the cal steps in the buffer
fapi2::buffer<uint16_t> l_steps_to_execute = i_cal_steps_enabled;
- l_steps_to_execute.clearBit<mss::cal_steps::EXT_ZQCAL>().clearBit<mss::cal_steps::WR_LEVEL>();
+ l_steps_to_execute.clearBit<mss::cal_steps::EXT_ZQCAL>()
+ .clearBit<mss::cal_steps::WR_LEVEL>()
+ .clearBit<mss::cal_steps::WRITE_CTR, mss::cal_steps::STEPS_FROM_WR_CTR_TO_COARSE_RD_LEN>();
+
+ FAPI_INF("%s Running cal steps through read centering on RP%d 0x%04x", mss::c_str(i_target), i_rp,
+ uint16_t(l_steps_to_execute));
+
+ // Undertake the calibration steps
+ FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) );
+
+ // Now run the read centering workaround
+ if(l_steps_to_execute.getBit<READ_CTR>())
+ {
+ FAPI_TRY(mss::workarounds::dp16::rd_dq::fix_delay_values(i_target, i_rp),
+ "%s Failed to run read centering workaround on rp %d", mss::c_str(i_target), i_rp);
+ }
+ }
+
+ // Run cal steps after RD_CTR if any are selected - note: WRITE_CTR takes place after RD_CTR
+ if (i_cal_steps_enabled.getBit<mss::cal_steps::WRITE_CTR, mss::cal_steps::STEPS_FROM_WR_CTR_TO_COARSE_RD_LEN>())
+ {
+ fapi2::buffer<uint16_t> l_steps_to_execute = i_cal_steps_enabled;
+
+ // Clear until we hit write centering
+ l_steps_to_execute.clearBit<mss::cal_steps::EXT_ZQCAL, mss::cal_steps::WRITE_CTR>();
+
+ FAPI_INF("%s Running remaining cal steps after read centering on RP%d 0x%04x", mss::c_str(i_target), i_rp,
+ uint16_t(l_steps_to_execute));
+
+ // Undertake the calibration steps
FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) );
}
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
index 4cb69e317..0c9d0194b 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
@@ -57,6 +57,7 @@ enum sizes
BITS_PER_DQS = 2, ///< Differential clock pair
MAX_RANKS_DIMM1 = 2, ///< DIMM1 (inner DIMM) can't be a 4R DIMM
MAX_PRIMARY_RANKS_PER_PORT = 4,
+ MAX_RANK_PAIRS = 4,
MAX_MRANK_PER_PORT = MAX_DIMM_PER_PORT * MAX_RANK_PER_DIMM,
RANK_MID_POINT = 4, ///< Which rank number indicates the switch to the other DIMM
DEFAULT_POLL_LIMIT = 50, ///< the number of poll attempts in the event we can't calculate another
@@ -153,7 +154,11 @@ enum cal_steps
WRITE_CTR_2D_VREF = 7,
COARSE_WR = 8,
COARSE_RD = 9,
- STEPS_AFTER_WR_LEVEL = 8, // represents the number of bits in cal_step_enable after the WR_LEVEL bit
+ // We can do math here, so this pretties up the code
+ // Note: a function was investigated but abandoned due to unresolvable compile issues
+ // Note: for STEPS_FROM_DQS_ALIGN_TO_AFTER_RD_CTR_LEN - READ_CTR/READ_CTR_2D_VREF are run together pick the larger of the steps
+ STEPS_FROM_DQS_ALIGN_TO_AFTER_RD_CTR_LEN = (READ_CTR_2D_VREF - DQS_ALIGN) + 1,
+ STEPS_FROM_WR_CTR_TO_COARSE_RD_LEN = (COARSE_RD - WRITE_CTR) + 1,
};
// Static consts for DDR4 voltages used in p9_mss_volt
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C
index 16d56cf69..ed85cd1d6 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C
@@ -416,6 +416,315 @@ fapi2::ReturnCode modify_calibration_results( const fapi2::Target<fapi2::TARGET_
return fix_blue_waterfall_gate( i_target );
}
+namespace rd_dq
+{
+
+///
+/// @brief Reads out the read dq registers and stores the values in a vector
+/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_rank_pair the rank pair to operate on
+/// @param[out] o_reg_data register conglomerate
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode get_delay_data(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rank_pair,
+ std::vector<delay_data>& o_reg_data)
+{
+ static const std::vector<std::vector<uint64_t>> REGISTER =
+ {
+ // RANK_PAIR0
+ {
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR0_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR0_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR0_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR0_P0_4,
+ },
+ // RANK_PAIR1
+ {
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR1_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR1_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR1_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR1_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR1_P0_4,
+ },
+ // RANK_PAIR2
+ {
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR2_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR2_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR2_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR2_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR2_P0_4,
+ },
+ // RANK_PAIR3
+ {
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_0,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_1,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_2,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY4_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY5_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY6_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY7_RANK_PAIR3_P0_3,
+ MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR3_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY1_RANK_PAIR3_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY2_RANK_PAIR3_P0_4,
+ MCA_DDRPHY_DP16_READ_DELAY3_RANK_PAIR3_P0_4,
+ },
+ };
+
+ // Bombs out if the rank pair is out of range
+
+ FAPI_ASSERT( i_rank_pair < MAX_RANK_PAIRS,
+ fapi2::MSS_INVALID_RANK_PAIR()
+ .set_RANK_PAIR(i_rank_pair)
+ .set_MCA_TARGET(i_target)
+ .set_FUNCTION(RD_CTR_WORKAROUND_READ_DATA),
+ "%s Invalid rank pair (%d) in get_ranks_in_pair",
+ mss::c_str(i_target),
+ i_rank_pair);
+
+ // loops and gets the registers
+ o_reg_data.clear();
+
+ for(const auto l_reg : REGISTER[i_rank_pair])
+ {
+ constexpr uint64_t EVEN_START = MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_0_01_RD;
+ constexpr uint64_t ODD_START = MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_0_01_RD_DELAY1;
+ fapi2::buffer<uint64_t> l_buff;
+ uint64_t l_data = 0;
+
+ // Reads the register information
+ FAPI_TRY(mss::getScom(i_target, l_reg, l_buff), "%s failed getscom to register 0x%016lx", mss::c_str(i_target), l_reg);
+
+ // Gets out the specific information and stores it
+ // Even delay
+ l_buff.extractToRight<EVEN_START, delay_data::LEN>(l_data);
+ o_reg_data.push_back({l_reg, EVEN_START, l_data});
+
+ // Odd delay
+ l_buff.extractToRight<ODD_START, delay_data::LEN>(l_data);
+ o_reg_data.push_back({l_reg, ODD_START, l_data});
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+///
+/// @brief Finds the median and sorts the vector
+/// @param[in,out] io_reg_data register data
+/// @param[out] o_median the median value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode find_median_and_sort(std::vector<delay_data>& io_reg_data, uint64_t& o_median)
+{
+
+ // The fapi_try is in an if statement, this ensures we have a good value
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // Bomb out if the vector is empty to avoid accessing a non-existant element
+ FAPI_ASSERT(!io_reg_data.empty(),
+ fapi2::MSS_RD_CTR_WORKAROUND_EMPTY_VECTOR(),
+ "Empty vector passed in to find_median_and_sort"
+ );
+
+ // Sorts first
+ std::sort(io_reg_data.begin(), io_reg_data.end());
+
+ // TODO:RTC172759 Add generic median function - that can replace the below code
+ // Finding the median is simply a matter of finding the midway point and getting the data there
+ {
+ const auto l_median_it = io_reg_data.begin() + io_reg_data.size() / 2;
+ o_median = l_median_it->iv_data;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Overrides any bad (out of range) read delay values with the median value
+/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_rank_pair the rank pair to operate on
+/// @param[in] i_percent the percentage below the median outside of which to override values to be the median - OPTIONAL - defaults to 66
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode fix_delay_values(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rank_pair,
+ const uint64_t i_percent)
+{
+ if(!mss::chip_ec_feature_mss_run_rd_ctr_workaround(i_target))
+ {
+ FAPI_INF("%s skipping the rd centering workaround!", mss::c_str(i_target));
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ std::vector<delay_data> l_reg_data;
+ uint64_t l_median = 0;
+
+ FAPI_TRY(get_delay_data(i_target, i_rank_pair, l_reg_data), "%s i_rank_pair %d failed to get the delay data",
+ mss::c_str(i_target), i_rank_pair);
+
+ FAPI_TRY(find_median_and_sort(l_reg_data, l_median), "%s i_rank_pair %d failed to find median value and sort",
+ mss::c_str(i_target), i_rank_pair);
+
+ FAPI_INF("%s i_rank_pair %d found a median of 0x%02x any value below %d %% of the median will be modified",
+ mss::c_str(i_target), i_rank_pair, l_median, i_percent);
+
+ // Overrides the bad delay values - the ones that are i_percent below the median
+ {
+ // Finds the iterator corresponding to the first location where we are within i_percent of the median
+ const auto l_last = std::find_if(l_reg_data.begin(), l_reg_data.end(), [ i_percent,
+ l_median]( const delay_data & i_rhs) -> bool
+ {
+ // Does this funky compare to avoid underflow
+ const auto l_comp_value = (i_percent * l_median) / 100;
+ return l_comp_value < i_rhs.iv_data;
+ });
+
+ // Loops and does the overrides
+ // Note: does a simple RMW, we can speed this up by doing a more complex algorithm to sort registers together.
+ // Keeping it simple for now
+ for( auto l_it = l_reg_data.begin(); l_it < l_last; ++l_it)
+ {
+ fapi2::buffer<uint64_t> l_buff;
+ FAPI_INF("%s i_rank_pair %d modifying delay position %d on register 0x%016lx from 0x%02x to be 0x%02x",
+ mss::c_str(i_target), i_rank_pair, l_it->iv_bit, l_it->iv_register, l_it->iv_data, l_median);
+
+ // Read
+ FAPI_TRY(mss::getScom(i_target, l_it->iv_register, l_buff));
+
+ // Modify
+ FAPI_TRY(l_buff.insertFromRight(l_median, l_it->iv_bit, delay_data::LEN));
+
+ // Write
+ FAPI_TRY(mss::putScom(i_target, l_it->iv_register, l_buff));
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // close namespace rd_dq
+
namespace wr_vref
{
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H
index 03ecb9b2e..2db02bf34 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H
@@ -279,6 +279,82 @@ fapi2::ReturnCode rd_vref_vref_sense_setup( const fapi2::Target<fapi2::TARGET_TY
fapi2::ReturnCode post_training_workarounds( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
const fapi2::buffer<uint16_t>& i_cal_steps_enabled );
+namespace rd_dq
+{
+
+///
+/// @brief Declares a struct to simplify the rd_dq workaround
+///
+struct delay_data
+{
+ // Deletes base constructor
+ delay_data() = delete;
+
+ ///
+ /// @brief Constructor
+ /// @param[in] i_register - register info
+ /// @param[in] i_bit - bit position info
+ /// @param[in] i_data - data stored in the register
+ ///
+ delay_data(const uint64_t i_register, const uint64_t i_bit, const uint64_t& i_data) :
+ iv_register(i_register),
+ iv_bit(i_bit),
+ iv_data(i_data)
+ {}
+
+ ///
+ /// @brief Default destructor
+ ///
+ ~delay_data() = default;
+
+ ///
+ /// @brief Comparison operator
+ /// @param[in] i_rhs - delay_info to compare against
+ /// @return bool - true if the right hand side is greater
+ bool operator<(const delay_data& i_rhs) const
+ {
+ // For this class, we only care about the delay value
+ return iv_data < i_rhs.iv_data;
+ }
+
+ static constexpr uint64_t LEN = MCA_DDRPHY_DP16_READ_DELAY0_RANK_PAIR0_P0_0_01_RD_LEN;
+ uint64_t iv_register;
+ uint64_t iv_bit;
+ uint64_t iv_data;
+};
+
+///
+/// @brief Reads out the read dq registers and stores the values in a vector
+/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_rank_pair the rank pair to operate on
+/// @param[out] o_reg_data register conglomerate
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode get_delay_data(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rank_pair,
+ std::vector<delay_data>& o_reg_data);
+
+///
+/// @brief Finds the median and sorts the vector
+/// @param[in,out] io_reg_data register data
+/// @param[out] o_median the median value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode find_median_and_sort(std::vector<delay_data>& io_reg_data, uint64_t& o_median);
+
+///
+/// @brief Overrides any bad (out of range) read delay values with the median value
+/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_rank_pair the rank pair to operate on
+/// @param[in] i_percent the percentage below the median outside of which to override values to be the median - OPTIONAL - defaults to 66
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode fix_delay_values(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rank_pair,
+ const uint64_t i_percent = 66);
+
+} // close namespace rd_dq
+
namespace wr_vref
{
OpenPOWER on IntegriCloud