summaryrefslogtreecommitdiffstats
path: root/src/import/chips
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2016-10-03 14:04:35 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-11-04 22:29:04 -0400
commit188ebfe49375b350936f22c6530cf34428f7205f (patch)
tree795fbaff78416b9f44481ed74cba8c431f904853 /src/import/chips
parenteb3a62f3eda2e5965914e5e9b026651b8df18322 (diff)
downloadtalos-hostboot-188ebfe49375b350936f22c6530cf34428f7205f.tar.gz
talos-hostboot-188ebfe49375b350936f22c6530cf34428f7205f.zip
Added WR VREF latch command
Change-Id: Ibb8ce5b66b0b2359c6da8066b99cbb6381c7ff92 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/30697 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31098 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C238
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H108
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H1
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.H41
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H28
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C35
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H6
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C298
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H79
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C9
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H8
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C2
12 files changed, 837 insertions, 16 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C
index 209188afd..59e21d3ca 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.C
@@ -32,3 +32,241 @@
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB Memory
+
+#include <vector>
+#include <fapi2.H>
+#include <lib/utils/c_str.H>
+#include <lib/dimm/ddr4/mrs_load_ddr4.H>
+#include <lib/dimm/ddr4/latch_wr_vref.H>
+#include <lib/dimm/rank.H>
+
+using fapi2::TARGET_TYPE_MCBIST;
+using fapi2::TARGET_TYPE_DIMM;
+
+namespace mss
+{
+
+namespace ddr4
+{
+
+///
+/// @brief Add latching commands for WR VREF to the instruction array - allows for custom MR06 data
+/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_DIMM>
+/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
+/// @param[in] i_rank, rank on which to latch MRS 06
+/// @param[in,out] a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode add_latch_wr_vref_commands( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const mrs06_data& i_mrs06,
+ const uint64_t& i_rank,
+ std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
+{
+ // JEDEC has a 3 step latching process for WR VREF
+ // 1) enter into VREFDQ training mode, with the desired range value is XXXXXX
+ // 2) set the VREFDQ value while in training mode - this actually latches the value
+ // 3) exit VREFDQ training mode and go into normal operation mode
+
+ // Adds both VREFDQ train enables
+ // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
+ ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_a_side;
+ ccs::instruction_t<TARGET_TYPE_MCBIST> l_inst_b_side;
+
+ auto l_mr_override = i_mrs06;
+
+ enable_vref_train_enable(l_mr_override);
+
+ FAPI_TRY(setup_ab_side_vref_train_enable(
+ i_target,
+ l_mr_override,
+ i_rank,
+ l_inst_a_side,
+ l_inst_b_side)
+ );
+
+ // Add both to the CCS program - JEDEC step 1
+ io_inst.push_back(l_inst_a_side);
+ io_inst.push_back(l_inst_b_side);
+
+ // Add both to the CCS program - JEDEC step 2
+ io_inst.push_back(l_inst_a_side);
+ io_inst.push_back(l_inst_b_side);
+
+ disable_vref_train_enable(l_mr_override);
+
+ // Hits VREFDQ train disable - putting the DRAM's back in mainline mode
+ FAPI_TRY(setup_ab_side_vref_train_enable(
+ i_target,
+ l_mr_override,
+ i_rank,
+ l_inst_a_side,
+ l_inst_b_side)
+ );
+
+ // Add both to the CCS program - JEDEC step 3
+ io_inst.push_back(l_inst_a_side);
+ io_inst.push_back(l_inst_b_side);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Add latching commands for WR VREF to the instruction array
+/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
+/// @param[in] i_rank_pair, rank pair on which to latch MRS 06 - hits all ranks in the rank pair
+/// @param[in] i_train_range, VREF range to setup
+/// @param[in] i_train_value, VREF value to setup
+/// @param[in,out] a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode latch_wr_vref_commands_by_rank_pair( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t& i_rank_pair,
+ const uint8_t& i_train_range,
+ const uint8_t& i_train_value)
+{
+ // Declares variables
+ const auto l_mcbist = find_target<fapi2::TARGET_TYPE_MCBIST>(i_target);
+ const auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target);
+ mss::ccs::program<fapi2::TARGET_TYPE_MCBIST, fapi2::TARGET_TYPE_MCA> l_program;
+ std::vector<uint64_t> l_ranks;
+
+ // Gets the ranks on which to latch the VREF's
+ FAPI_TRY(mss::rank::get_ranks_in_pair( i_target, i_rank_pair, l_ranks));
+
+ // Adds in latching commands for all ranks
+ for( const auto& l_rank : l_ranks)
+ {
+ // Skips this rank if no rank is configured
+ if( l_rank == NO_RANK)
+ {
+ continue;
+ }
+
+ // Sets up the DIMM target
+ const auto l_dimm = (l_rank < MAX_RANK_PER_DIMM) ? l_dimms[0] : l_dimms[1];
+
+ // Adds the latching commands to the CCS program for this current rank
+ FAPI_TRY(setup_latch_wr_vref_commands_by_rank(l_dimm,
+ l_rank,
+ i_train_range,
+ i_train_value,
+ l_program.iv_instructions));
+ }
+
+ // Executes the CCS commands
+ FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Add latching commands for WR VREF to the instruction array by a given rank
+/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
+/// @param[in] i_rank, rank on which to latch MRS 06 - hits all ranks in the rank pair
+/// @param[in] i_train_range, VREF range to setup
+/// @param[in] i_train_value, VREF value to setup
+/// @param[in,out] a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode setup_latch_wr_vref_commands_by_rank( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t& i_rank,
+ const uint8_t& i_train_range,
+ const uint8_t& i_train_value,
+ std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst)
+{
+ // Check to make sure our ctor worked ok
+ mrs06_data l_mrs06( i_target, fapi2::current_err );
+ FAPI_TRY( fapi2::current_err, "Unable to construct MRS06 data from attributes");
+
+ // Setup training range if the value is not the default
+ if(i_train_range != wr_vref_override::USE_DEFAULT_WR_VREF_SETTINGS)
+ {
+ FAPI_INF("%s Overriding vrefdq train %s data to be 0x%02x for rank %lu", mss::c_str(i_target), "range", i_train_value,
+ i_rank);
+
+ // Sets up the MR information
+ for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
+ {
+ l_mrs06.iv_vrefdq_train_range[i] = i_train_range;
+ }
+ }
+
+ // Setup training value if the value is not the default
+ if(i_train_value != wr_vref_override::USE_DEFAULT_WR_VREF_SETTINGS)
+ {
+ FAPI_INF("%s Overriding vrefdq train %s data to be 0x%02x for rank %lu", mss::c_str(i_target), "value", i_train_value,
+ i_rank);
+
+ // Sets up the MR information
+ for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
+ {
+ l_mrs06.iv_vrefdq_train_value[i] = i_train_value;
+ }
+ }
+
+ // Adds the latching commands
+ FAPI_TRY(add_latch_wr_vref_commands(i_target,
+ l_mrs06,
+ i_rank,
+ io_inst));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief helper function to setup a/b side MR06 commands for the latching function based upon TRAIN_ENABLE
+/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
+/// @param[in] i_rank, rank on which to latch MRS 06
+/// @param[out] o_a_side, a-side MR06 command
+/// @param[out] o_b_side, b-side MR06 command
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode setup_ab_side_vref_train_enable(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const mrs06_data& i_mrs06,
+ const uint64_t& i_rank,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_a_side,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_b_side)
+{
+ // commands to be latched are MR06
+ constexpr uint8_t WR_VREF_MRS = 6;
+
+ // Note: this isn't general - assumes Nimbus via MCBIST instruction here BRS
+ o_a_side = ccs::mrs_command<fapi2::TARGET_TYPE_MCBIST>(i_target, i_rank, WR_VREF_MRS);
+
+ // Sets up variables
+ const auto l_delay_enter = mss::tvrefdqe(i_target);
+
+ // Thou shalt send 2 MRS, one for the a-side and the other inverted for the b-side.
+ // If we're on an odd-rank then we need to mirror
+ // So configure the A-side, mirror if necessary and invert for the B-side
+ // Gets the actual MR data to pass into CCS
+ FAPI_TRY( mrs06(i_target, i_mrs06, o_a_side, i_rank) );
+
+ FAPI_TRY( mss::address_mirror(i_target, i_rank, o_a_side) );
+ o_b_side = mss::address_invert(o_a_side);
+
+ // Not sure if we can get tricky here and only delay after the b-side MR. The question is whether the delay
+ // is needed/assumed by the register or is purely a DRAM mandated delay. We know we can't go wrong having
+ // both delays but if we can ever confirm that we only need one we can fix this. BRS
+ o_a_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
+ MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(l_delay_enter);
+ o_b_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
+ MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(l_delay_enter);
+
+ // Dump out the 'decoded' MRS and trace the CCS instructions.
+ FAPI_TRY( mrs06_decode(o_a_side, i_rank) );
+
+ FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d a-side", WR_VREF_MRS, l_delay_enter,
+ o_a_side.arr0, o_a_side.arr1, mss::c_str(i_target), i_rank);
+ FAPI_INF("MRS%02d (%d) 0x%016llx:0x%016llx %s:rank %d b-side", WR_VREF_MRS, l_delay_enter,
+ o_b_side.arr0, o_b_side.arr1, mss::c_str(i_target), i_rank);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // close namespace DDR4
+} // close namespace mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H
index 02895d994..b6b521c04 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/latch_wr_vref.H
@@ -32,3 +32,111 @@
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB Memory
+
+#ifndef _LATCH_WR_VREF_H_
+#define _LATCH_WR_VREF_H_
+
+#include <vector>
+#include <fapi2.H>
+#include <lib/utils/c_str.H>
+#include <lib/dimm/mrs_load.H>
+#include <lib/dimm/ddr4/mrs_load_ddr4.H>
+#include <lib/eff_config/timing.H>
+
+namespace mss
+{
+
+namespace ddr4
+{
+// Declares an enum for using the default WR VREF values
+enum wr_vref_override : uint8_t
+{
+ USE_DEFAULT_WR_VREF_SETTINGS = 0xff,
+};
+
+///
+/// @brief Add latching commands for WR VREF to the instruction array - allows for custom MR06 data
+/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_DIMM>
+/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
+/// @param[in] i_rank, rank on which to latch MRS 06
+/// @param[in,out] a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode add_latch_wr_vref_commands( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const mrs06_data& i_mrs06,
+ const uint64_t& i_rank,
+ std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst);
+
+///
+/// @brief Add latching commands for WR VREF to the instruction array
+/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
+/// @param[in] i_rank_pair, rank pair on which to latch MRS 06 - hits all ranks in the rank pair
+/// @param[in] i_train_range, VREF range to setup
+/// @param[in] i_train_value, VREF value to setup
+/// @param[in,out] a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode latch_wr_vref_commands_by_rank_pair( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t& i_rank_pair,
+ const uint8_t& i_train_range,
+ const uint8_t& i_train_value);
+
+///
+/// @brief enables VREF train enable in an MRS06 class
+/// @param[in,out] io_mrs06
+///
+inline void enable_vref_train_enable(mrs06_data& io_mrs06)
+{
+ // Sets up the MR information
+ for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
+ {
+ io_mrs06.iv_vrefdq_train_enable[i] = fapi2::ENUM_ATTR_EFF_VREF_DQ_TRAIN_ENABLE_ENABLE;
+ }
+}
+
+///
+/// @brief disables VREF train enable in an MRS06 class
+/// @param[in,out] io_mrs06
+///
+inline void disable_vref_train_enable(mrs06_data& io_mrs06)
+{
+ // Sets up the MR information
+ for(uint64_t i = 0; i < MAX_RANK_PER_DIMM; ++i)
+ {
+ io_mrs06.iv_vrefdq_train_enable[i] = fapi2::ENUM_ATTR_EFF_VREF_DQ_TRAIN_ENABLE_DISABLE;
+ }
+}
+
+///
+/// @brief helper function to setup a/b side MR06 commands for the latching function based upon TRAIN_ENABLE
+/// @param[in] i_mrs06, base MRS 06 allows the user to setup custom values and pass it in
+/// @param[in] i_rank, rank on which to latch MRS 06
+/// @param[out] o_a_side, a-side MR06 command
+/// @param[out] o_b_side, b-side MR06 command
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode setup_ab_side_vref_train_enable(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const mrs06_data& i_mrs06,
+ const uint64_t& i_rank,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_a_side,
+ ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>& o_b_side);
+
+///
+/// @brief Add latching commands for WR VREF to the instruction array by a given rank
+/// @param[in] i_target, a fapi2::Target<TARGET_TYPE_MCA>
+/// @param[in] i_rank, rank on which to latch MRS 06 - hits all ranks in the rank pair
+/// @param[in] i_train_range, VREF range to setup
+/// @param[in] i_train_value, VREF value to setup
+/// @param[in,out] a vector of CCS instructions we should add to
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+fapi2::ReturnCode setup_latch_wr_vref_commands_by_rank( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t& i_rank,
+ const uint8_t& i_train_range,
+ const uint8_t& i_train_value,
+ std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> >& io_inst);
+
+} // close namespace DDR4
+} // close namespace mss
+
+#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H
index d7108dad3..db3fc7feb 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.H
@@ -41,6 +41,7 @@
#include <lib/utils/c_str.H>
#include <lib/shared/mss_kind.H>
+#include <lib/ccs/ccs.H>
namespace mss
{
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 167f9eaab..74cfbe566 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
@@ -865,6 +865,47 @@ fapi2::ReturnCode is_mirrored( const fapi2::Target<T>& i_target,
}
return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief get_ranks_in_pair
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] RP rank pair gets ranks in pairs
+/// @param[out] o_ranks vector of rank numbers (primary, secondary, tertiary, quaternary)
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_ranks_in_pair( const fapi2::Target<T>& i_target,
+ const uint64_t& i_rp,
+ std::vector<uint64_t>& o_ranks )
+{
+ // Switches based upon the number of rank pairs
+ switch(i_rp)
+ {
+ case 0:
+ FAPI_TRY((get_ranks_in_pair<0, T>(i_target, o_ranks)));
+ break;
+
+ case 1:
+ FAPI_TRY((get_ranks_in_pair<1, T>(i_target, o_ranks)));
+ break;
+
+ case 2:
+ FAPI_TRY((get_ranks_in_pair<2, T>(i_target, o_ranks)));
+ break;
+
+ case 3:
+ FAPI_TRY((get_ranks_in_pair<3, T>(i_target, o_ranks)));
+ break;
+
+ // Error case
+ default:
+ FAPI_ERR("Invalid number of rankpairs entered. num: %lu max: %lu", i_rp, MAX_PRIMARY_RANKS_PER_PORT);
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER);
+ break;
+ }
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
index 9180aaa9c..7bc06dbc6 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
@@ -1299,5 +1299,33 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief VREF DQ Enter time *in clocks*
+/// @tparam T the fapi2::TargetType of i_target
+/// @param[in] i_target a target for attributes
+/// @return VREF DQ Enter time *in clocks*
+///
+template< fapi2::TargetType T >
+inline uint64_t tvrefdqe( const fapi2::Target<T>& i_target )
+{
+ // JEDEC tVREFDQE in ns
+ constexpr uint64_t tVREFDQE = 150;
+ return ns_to_cycles(i_target, tVREFDQE);
+}
+
+///
+/// @brief VREF DQ Exit time *in clocks*
+/// @tparam T the fapi2::TargetType of i_target
+/// @param[in] i_target a target for attributes
+/// @return VREF DQ Exit time *in clocks*
+///
+template< fapi2::TargetType T >
+inline uint64_t tvrefdqx( const fapi2::Target<T>& i_target )
+{
+ // JEDEC tVREFDQX in ns
+ constexpr uint64_t tVREFDQX = 150;
+ return ns_to_cycles(i_target, tVREFDQX);
+}
+
} // mss
#endif
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 1b9dedada..f6e8b01e8 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
@@ -48,6 +48,7 @@
#include <lib/phy/seq.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/workarounds/wr_vref_workarounds.H>
+#include <lib/dimm/ddr4/latch_wr_vref.H>
#include <lib/utils/bit_count.H>
#include <lib/utils/find.H>
@@ -865,8 +866,10 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
{
static const std::vector<uint64_t> l_vref_regs =
{
- MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_0, MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_1,
- MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_2, MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_3,
+ MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_0,
+ MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_1,
+ MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_2,
+ MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_3,
MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_4
};
@@ -875,13 +878,31 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
l_vref_config.setBit<MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_0_01_CTR_1D_CHICKEN_SWITCH>();
}
- if (i_cal_steps_enabled.getBit<WRITE_CTR_2D_VREF>())
+ // loops through all RP's running workarounds and latching the VREF's as need be
+ for(const auto& l_rp : i_rank_pairs)
{
- l_vref_config.clearBit<MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_0_01_CTR_1D_CHICKEN_SWITCH>();
+ // Overrides will be set by mss::workarounds::wr_vref::execute.
+ // If the execute code is skipped, then it will read from the attributes
+ uint8_t l_vrefdq_train_range_override = mss::ddr4::USE_DEFAULT_WR_VREF_SETTINGS;
+ uint8_t l_vrefdq_train_value_override = mss::ddr4::USE_DEFAULT_WR_VREF_SETTINGS;
- // Runs WR VREF workarounds if needed
- // it will check and see if it needs to run, if not it will return success
- FAPI_TRY( mss::workarounds::wr_vref::execute(i_target) );
+ // Runs the workaround
+ if (i_cal_steps_enabled.getBit<WRITE_CTR_2D_VREF>())
+ {
+ l_vref_config.clearBit<MCA_DDRPHY_DP16_WR_VREF_CONFIG0_P0_0_01_CTR_1D_CHICKEN_SWITCH>();
+
+ // Runs WR VREF workarounds if needed
+ // it will check and see if it needs to run, if not it will return success - needs 0th rankpair to hit
+
+ FAPI_TRY( mss::workarounds::wr_vref::execute(i_target, l_rp, l_vrefdq_train_range_override,
+ l_vrefdq_train_value_override) );
+ }
+
+ // Latches the VREF's
+ FAPI_TRY( mss::ddr4::latch_wr_vref_commands_by_rank_pair( i_target,
+ l_rp,
+ l_vrefdq_train_range_override,
+ l_vrefdq_train_value_override ) );
}
FAPI_INF("wr_vref_config: 0x%016lu", l_vref_config);
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H
index c224f28c9..5991aa0b3 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H
@@ -470,11 +470,9 @@ inline fapi2::ReturnCode reset_rtt_wr_swap_enable( const fapi2::Target<T>& i_tar
l_data.clearBit<TT::RTT_WR_SWAP_ENABLE_P0_WL>();
l_data.clearBit<TT::RTT_WR_SWAP_ENABLE_P0_CTR>();
- // taken from JEDEC DDR4 SPEC 2015 specification
- // specific value is for tVREFDQE/tVREFDQX - both are 150 ns
+ // gets and sets the VREF counter reset value, max of vrefdq enter or exit time
{
- constexpr uint64_t VREFDQ_LATCH_TIME_NS = 150;
- const uint64_t l_vref_counter_reset = ns_to_cycles(i_target, VREFDQ_LATCH_TIME_NS);
+ const uint64_t l_vref_counter_reset = std::max(mss::tvrefdqe(i_target), mss::tvrefdqx(i_target));
l_data.insertFromRight<TT::VREF_COUNTER_RESET_VAL, TT::VREF_COUNTER_RESET_VAL_LEN>(l_vref_counter_reset);
}
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 18b12c875..a06246ed2 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
@@ -43,6 +43,7 @@
#include <lib/utils/pos.H>
#include <lib/workarounds/dp16_workarounds.H>
#include <lib/phy/dp16.H>
+#include <lib/dimm/rank.H>
namespace mss
{
@@ -182,6 +183,303 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief DP16 big step/small step check and modify workaround - MCA specialization
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure that the big step is divisible by the small step
+/// This function converts the small step value over to the closest allowable value as to what was entered
+/// @param[in] i_big_step - WR VREF big step value
+/// @param[in,out] io_small_step - WR VREF small step value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< >
+fapi2::ReturnCode modify_small_step_for_big_step<fapi2::TARGET_TYPE_MCA>(const uint8_t i_big_step,
+ uint8_t& io_small_step)
+{
+ // TODO RTC:160353 - Need module/chip rev EC support for workarounds
+
+ // Step size constants
+ constexpr uint8_t MAX_BIG_STEP = 0x10;
+ constexpr uint8_t MAX_SMALL_STEP = 0x08;
+
+ // Conversion over to the nearest allowable small step
+ // The algorithm takes the register value + 1 when it runs.
+ // This avoids cases where it would infinite loop if it had a 0 value in the register
+ // As such, the math to figure out if a big/small step combination is allowed is ((big_step + 1) % (small_step + 1)) == 0
+ // This below chart takes the allowable combinations or the next smallest allowable value.
+ constexpr uint8_t SMALL_STEP_CONVERSION[MAX_BIG_STEP][MAX_SMALL_STEP] =
+ {
+ {0, 0, 0, 0, 0, 0, 0, 0,},
+ {0, 1, 1, 1, 1, 1, 1, 1,},
+ {0, 0, 2, 2, 2, 2, 2, 2,},
+ {0, 1, 1, 3, 3, 3, 3, 3,},
+ {0, 0, 0, 0, 4, 4, 4, 4,},
+ {0, 1, 2, 2, 2, 5, 5, 5,},
+ {0, 0, 0, 0, 0, 0, 6, 6,},
+ {0, 1, 1, 3, 3, 3, 3, 7,},
+ {0, 0, 2, 2, 2, 2, 2, 2,},
+ {0, 1, 1, 1, 4, 4, 4, 4,},
+ {0, 0, 0, 0, 0, 0, 0, 0,},
+ {0, 1, 2, 3, 3, 5, 5, 5,},
+ {0, 0, 0, 0, 0, 0, 0, 0,},
+ {0, 1, 1, 1, 1, 1, 6, 6,},
+ {0, 0, 2, 2, 4, 4, 4, 4,},
+ {0, 1, 1, 3, 3, 3, 3, 7,},
+ };
+
+ // Makes sure that the values passed in were not out of range
+ if(MAX_BIG_STEP <= i_big_step)
+ {
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "WR VREF %s step is out of range. %s step 0x%02x max", "big", "big",
+ i_big_step);
+ }
+
+ if(MAX_SMALL_STEP <= io_small_step)
+ {
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "WR VREF %s step is out of range. %s step 0x%02x max", "small", "small",
+ io_small_step);
+ }
+
+ // Converts the value
+ io_small_step = SMALL_STEP_CONVERSION[i_big_step][io_small_step];
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief DP16 writes config 0 overriding bad small step/big step values
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure that the big step is divisible by the small step
+/// This function converts the small step value over to the closest allowable value as to what was entered
+/// @param[in] i_target the fapi2 target type MCA of the port
+/// @param[out] o_big_step - WR VREF big step value
+/// @param[out] o_small_step - WR VREF small step value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode write_config0( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint8_t& o_big_step,
+ uint8_t& o_small_step)
+{
+ // TODO RTC:160353 - Need module/chip rev EC support for workarounds
+
+ // Traits declaration
+ typedef dp16Traits<fapi2::TARGET_TYPE_MCA> TT;
+
+ // Variable declaration
+ fapi2::buffer<uint64_t> l_data;
+
+ // Reads the register - note assumes ALL DP's have the same value. Will overwrite different values
+ FAPI_TRY(mss::dp16::read_wr_vref_config0<0>(i_target, l_data));
+
+ // Sets these values to 0's to avoid undesired values
+ o_small_step = 0;
+ o_big_step = 0;
+
+ // Gets out the current values of the big and small step
+ l_data.extractToRight<TT::WR_VREF_CONFIG0_2D_SMALL_STEP_VAL, TT::WR_VREF_CONFIG0_2D_SMALL_STEP_VAL_LEN>(o_small_step)
+ .extractToRight<TT::WR_VREF_CONFIG0_2D_BIG_STEP_VAL, TT::WR_VREF_CONFIG0_2D_BIG_STEP_VAL_LEN>(o_big_step);
+
+ // Does the workaround conversion
+ FAPI_TRY(modify_small_step_for_big_step<fapi2::TARGET_TYPE_MCA>(o_big_step, o_small_step));
+
+ // Sets up the good values
+ l_data.insertFromRight<TT::WR_VREF_CONFIG0_2D_SMALL_STEP_VAL, TT::WR_VREF_CONFIG0_2D_SMALL_STEP_VAL_LEN>(o_small_step)
+ .insertFromRight<TT::WR_VREF_CONFIG0_2D_BIG_STEP_VAL, TT::WR_VREF_CONFIG0_2D_BIG_STEP_VAL_LEN>(o_big_step);
+
+ // Blasts em out
+ FAPI_TRY(scom_blastah(i_target, TT::WR_VREF_CONFIG0_REG, l_data));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief DP16 converts the VREF training values to start calibration
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure the WR VREF is an integer number of big steps away from the 0 value and one big step from the top of the range
+/// This function converts values over to the required rules
+/// @tparam T fapi2 Target Type - just here to ensure that this won't be called on a non-Nimbus system
+/// @param[in] i_big_step - WR VREF big step value
+/// @param[in,out] io_train_range - VREF train range converted value
+/// @param[in,out] io_train_value - VREF train value converted value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template <>
+fapi2::ReturnCode convert_train_values<fapi2::TARGET_TYPE_MCA>( const uint8_t i_big_step,
+ uint8_t& io_train_range,
+ uint8_t& io_train_value)
+{
+ // Number of big steps
+ constexpr uint8_t NUM_BIG_STEP = 16;
+
+ // Value at which Range 2 equals Range 1's 0 value
+ constexpr uint8_t CROSSOVER_RANGE = 0b011000;
+
+ // List of allowable maximum ranges. The math is max = (absolute_max - (big_step_val + 1)) - (absolute_max - (big_step_val + 1)) % (big_step_val + 1)
+ constexpr uint8_t l_max_allowable_values[NUM_BIG_STEP] =
+ {
+ 73, 72, 69, 68,
+ 65, 66, 63, 64,
+ 63, 60, 55, 60,
+ 52, 56, 45, 48,
+ };
+
+ // Declares temporary variable
+ uint8_t l_continuous_range = 0;
+ const uint8_t l_big_step_alg = i_big_step + 1;
+
+ // Errors out if the big step is out of range
+ FAPI_TRY(i_big_step < NUM_BIG_STEP ? fapi2::FAPI2_RC_SUCCESS : fapi2::FAPI2_RC_INVALID_PARAMETER,
+ "Big step of %d passed in. Max allowable value is %d", i_big_step, NUM_BIG_STEP - 1);
+
+ // Converts the values over to the algorithm's continuous range
+ l_continuous_range = io_train_range == fapi2::ENUM_ATTR_EFF_VREF_DQ_TRAIN_RANGE_RANGE1 ?
+ (io_train_value + CROSSOVER_RANGE) : (io_train_value);
+
+ // Does the math for what makes a good continuous range
+ // At least 1 big step away from the top of the range
+ l_continuous_range = std::min(l_continuous_range, l_max_allowable_values[i_big_step]);
+
+ // At least 1 big step away from the bottom of the range
+ l_continuous_range = std::max(l_continuous_range, l_big_step_alg);
+
+ // Moves to be an even number of big steps away
+ l_continuous_range -= (l_continuous_range % l_big_step_alg);
+
+ // Now converts the range/value from the continuous range - defaults to range 1
+ // If above the crossover range, use range1. If not, use range 2.
+ io_train_range = (l_continuous_range >= CROSSOVER_RANGE) ? fapi2::ENUM_ATTR_EFF_VREF_DQ_TRAIN_RANGE_RANGE1 :
+ fapi2::ENUM_ATTR_EFF_VREF_DQ_TRAIN_RANGE_RANGE2;
+ // If above the crossover range, convert to range 1. If not use range 2
+ io_train_value = (l_continuous_range >= CROSSOVER_RANGE) ? (l_continuous_range - CROSSOVER_RANGE) :
+ (l_continuous_range);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief DP16 gets the VREF training values to start calibration
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure that the big step is divisible by the small step
+/// This function converts the small step value over to the closest allowable value as to what was entered
+/// @param[in] i_target the fapi2 target type MCA of the port
+/// @param[in] i_big_step - WR VREF big step value
+/// @param[out] o_train_range - JEDEC MR6 WR VREF training range
+/// @param[out] o_train_value - JEDEC MR6 WR VREF training value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode get_train_values( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ const uint8_t i_big_step,
+ uint8_t& o_train_range,
+ uint8_t& o_train_value)
+{
+ // Declares variables
+ std::vector<uint64_t> l_ranks;
+ uint64_t l_rank = 0;
+ uint8_t l_vrefdq_train_value[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {0};
+ uint8_t l_vrefdq_train_range[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {0};
+
+ // Gets the ranks on which to latch the VREF's
+ FAPI_TRY(mss::rank::get_ranks_in_pair( i_target, i_rp, l_ranks));
+
+ // Only uses the first rank in the rank pair, as there is only one set of registers per rank pair
+ // If no ranks are configured, exit
+ l_rank = l_ranks[0];
+
+ if(l_rank == NO_RANK)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // Now gets the train value and range for the given rank
+ FAPI_TRY( mss::eff_vref_dq_train_value(i_target, &(l_vrefdq_train_value[0][0])) );
+ FAPI_TRY( mss::eff_vref_dq_train_range(i_target, &(l_vrefdq_train_range[0][0])) );
+
+ o_train_range = l_vrefdq_train_range[l_rank / MAX_RANK_PER_DIMM][l_rank % MAX_RANK_PER_DIMM];
+ o_train_value = l_vrefdq_train_value[l_rank / MAX_RANK_PER_DIMM][l_rank % MAX_RANK_PER_DIMM];
+
+ // Converts over the values
+ FAPI_TRY(convert_train_values<fapi2::TARGET_TYPE_MCA>(i_big_step, o_train_range, o_train_value));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief DP16 sets up the VREF train range and value
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure the WR VREF is an integer number of big steps away from the 0 value and one big step from the top of the range
+/// This function converts the WR VREF values over to be good values
+/// @param[in] i_target the fapi2 target type MCA of the port
+/// @param[in] i_rp - rank pair to check and modify
+/// @param[out] o_train_range - JEDEC MR6 WR VREF training range
+/// @param[out] o_train_value - JEDEC MR6 WR VREF training value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode setup_values( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ uint8_t& o_train_range,
+ uint8_t& o_train_value)
+{
+ // TODO RTC:160353 - Need module/chip rev EC support for workarounds
+
+ // Traits declaration
+ typedef dp16Traits<fapi2::TARGET_TYPE_MCA> TT;
+
+ // Declares variables
+ uint8_t l_big_step = 0;
+ uint8_t l_small_step = 0;
+
+ // Sets up the wr_vref_config0 register and returns out the big/small step values
+ FAPI_TRY(write_config0(i_target, l_big_step, l_small_step));
+
+ // Gets the train values
+ FAPI_TRY(get_train_values(i_target, i_rp, l_big_step, o_train_range, o_train_value));
+
+ // Sets up the WR VREF values in the RP register
+ {
+ // Creates and sets up the buffer
+ fapi2::buffer<uint64_t> l_buff;
+
+ l_buff.writeBit<TT::WR_VREF_VALUE_RANGE_DRAM_EVEN>(o_train_range)
+ .writeBit<TT::WR_VREF_VALUE_RANGE_DRAM_ODD>(o_train_range)
+ .insertFromRight<TT::WR_VREF_VALUE_VALUE_DRAM_EVEN, TT::WR_VREF_VALUE_VALUE_DRAM_EVEN_LEN>(o_train_value)
+ .insertFromRight<TT::WR_VREF_VALUE_VALUE_DRAM_ODD, TT::WR_VREF_VALUE_VALUE_DRAM_ODD_LEN>(o_train_value);
+
+ // Hits only the desired RP
+ switch(i_rp)
+ {
+ case 0:
+ FAPI_TRY(mss::scom_blastah(i_target, TT::WR_VREF_VALUE_RP0_REG, l_buff));
+ break;
+
+ case 1:
+ FAPI_TRY(mss::scom_blastah(i_target, TT::WR_VREF_VALUE_RP1_REG, l_buff));
+ break;
+
+ case 2:
+ FAPI_TRY(mss::scom_blastah(i_target, TT::WR_VREF_VALUE_RP2_REG, l_buff));
+ break;
+
+ case 3:
+ FAPI_TRY(mss::scom_blastah(i_target, TT::WR_VREF_VALUE_RP3_REG, l_buff));
+ break;
+
+ // Weird. There shouldn't be more than RP3. Error out
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s RP%lu was passed in. Maximum allowable value is 3.",
+ mss::c_str(i_target), i_rp);
+ break;
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
} // close namespace wr_vref
} // close namespace dp16
} // close namespace workarounds
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 825e9bd5f..2f4209395 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
@@ -83,13 +83,88 @@ namespace wr_vref
///
/// @brief DP16 WR VREF error latching workaround
-/// In DD1 Nimbus in the WR VREF algorithm ,DRAM's 2/3 latch over error information from DRAM's 0/1.
+/// In DD1 Nimbus in the WR VREF algorithm, DRAM's 2/3 latch over error information from DRAM's 0/1.
/// The workaround is to set the error mask for DRAM's 2/3 to be 0xFFFF (informational but not errors)
-/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_target the fapi2 target type MCA of the port
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
fapi2::ReturnCode error_dram23( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );
+///
+/// @brief DP16 big step/small step check and modify workaround
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure that the big step is divisible by the small step
+/// This function converts the small step value over to the closest allowable value as to what was entered
+/// @tparam T fapi2 Target Type - just here to ensure that this won't be called on a non-Nimbus system
+/// @param[in] i_big_step - WR VREF big step value
+/// @param[in,out] io_small_step - WR VREF small step value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode modify_small_step_for_big_step(const uint8_t i_big_step, uint8_t& io_small_step);
+
+///
+/// @brief DP16 writes config 0 overriding bad small step/big step values
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure that the big step is divisible by the small step
+/// This function converts the small step value over to the closest allowable value as to what was entered
+/// @param[in] i_target the fapi2 target type MCA of the port
+/// @param[out] o_big_step - WR VREF big step value
+/// @param[out] o_small_step - WR VREF small step value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode write_config0( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint8_t& o_big_step,
+ uint8_t& o_small_step);
+
+///
+/// @brief DP16 converts the VREF training values to start calibration
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure the WR VREF is an integer number of big steps away from the 0 value and one big step from the top of the range
+/// This function converts values over to the required rules
+/// @tparam T fapi2 Target Type - just here to ensure that this won't be called on a non-Nimbus system
+/// @param[in] i_big_step - WR VREF big step value
+/// @param[in,out] io_train_range - VREF train range converted value
+/// @param[in,out] io_train_value - VREF train value converted value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode convert_train_values( const uint8_t i_big_step,
+ uint8_t& io_train_range,
+ uint8_t& io_train_value);
+
+///
+/// @brief DP16 gets the VREF training values to start calibration
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure the WR VREF is an integer number of big steps away from the 0 value and one big step from the top of the range
+/// This function gets and converts the train values over to good values
+/// @param[in] i_target the fapi2 target type MCA of the port
+/// @param[in] i_big_step - WR VREF big step value
+/// @param[out] o_train_range - JEDEC MR6 WR VREF training range
+/// @param[out] o_train_value - JEDEC MR6 WR VREF training value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode get_train_values( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ const uint8_t i_big_step,
+ uint8_t& o_train_range,
+ uint8_t& o_train_value);
+
+///
+/// @brief DP16 sets up the VREF train range and value. also sets up the VREF value registers
+/// In DD1 Nimbus in the WR VREF algorithm, the out of bounds checks are broken.
+/// One aspect of fixing this bug is to ensure the WR VREF is an integer number of big steps away from the 0 value and one big step from the top of the range
+/// This function converts the WR VREF values over to be good values and writes the good values out to the chip
+/// @param[in] i_target the fapi2 target type MCA of the port
+/// @param[in] i_rp - rank pair to check and modify
+/// @param[out] o_train_range - JEDEC MR6 WR VREF training range
+/// @param[out] o_train_value - JEDEC MR6 WR VREF training value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode setup_values( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ uint8_t& o_train_range,
+ uint8_t& o_train_value);
+
} // close namespace wr_vref
} // close namespace dp16
} // close namespace workarounds
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C
index 7641fc091..c1ba205ad 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C
@@ -51,12 +51,19 @@ namespace wr_vref
///
/// @brief Executes WR VREF workarounds
/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_rp - the rank pair to execute the override on
+/// @param[out] o_vrefdq_train_range - training range value
+/// @param[out] o_vrefdq_train_value - training value value
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
-fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target )
+fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t& i_rp,
+ uint8_t& o_vrefdq_train_range,
+ uint8_t& o_vrefdq_train_value )
{
// TODO RTC:160353 - Need module/chip rev EC support for workarounds
FAPI_TRY(mss::workarounds::dp16::wr_vref::error_dram23(i_target));
+ FAPI_TRY(mss::workarounds::dp16::wr_vref::setup_values(i_target, i_rp, o_vrefdq_train_range, o_vrefdq_train_value));
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H
index 7b23cbe42..016236357 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H
@@ -52,9 +52,15 @@ namespace wr_vref
///
/// @brief Executes WR VREF workarounds
/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_rp - the rank pair to execute the override on
+/// @param[out] o_vrefdq_train_range - training range value
+/// @param[out] o_vrefdq_train_value - training value value
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
///
-fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );
+fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t& i_rp,
+ uint8_t& o_vrefdq_train_range,
+ uint8_t& o_vrefdq_train_value );
} // close namespace wr_vref
} // close namespace workarounds
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C
index b1a0401df..0c1035d2f 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C
@@ -174,7 +174,7 @@ extern "C"
FAPI_TRY( mss::cal_abort_on_error(cal_abort_on_error) );
}
- FAPI_DBG("exeecuting training CCS instruction: 0x%llx, 0x%llx", l_inst.arr0, l_inst.arr1);
+ FAPI_DBG("executing training CCS instruction: 0x%llx, 0x%llx", l_inst.arr0, l_inst.arr1);
l_program.iv_instructions.push_back(l_inst);
// We need to figure out how long to wait before we start polling. Each cal step has an expected
OpenPOWER on IntegriCloud