diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2016-10-03 14:04:35 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-11-04 22:29:04 -0400 |
commit | 188ebfe49375b350936f22c6530cf34428f7205f (patch) | |
tree | 795fbaff78416b9f44481ed74cba8c431f904853 /src/import/chips | |
parent | eb3a62f3eda2e5965914e5e9b026651b8df18322 (diff) | |
download | talos-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')
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 |