summaryrefslogtreecommitdiffstats
path: root/src/import/chips
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2018-10-18 21:32:31 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2018-10-29 17:38:19 -0500
commit74c643ef35c61ab0f7f7979b9b20f2b518e0c792 (patch)
tree8fb25ac8f43774d3a952e74c717ed003b723787c /src/import/chips
parenta2f59106caececf9bc92b9f8279578d58b85b3aa (diff)
downloadtalos-hostboot-74c643ef35c61ab0f7f7979b9b20f2b518e0c792.tar.gz
talos-hostboot-74c643ef35c61ab0f7f7979b9b20f2b518e0c792.zip
Fixes b-side bug in MPR write function
MPR writes were being disabled due to b-side inversion. For MPR writes, the updated code now disables inversion. It is restored to nominal after words. Change-Id: Ibca550d9e6cadc6176df2a40c339e642f87f7770 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/67744 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/67753 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H16
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.C61
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H126
3 files changed, 164 insertions, 39 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H
index 5dae509a6..ab28d5b82 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/control_word_ddr4.H
@@ -580,6 +580,22 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Modifies the supplied CW to be in or out of address inversion mode
+/// @param[in,out] io_rc00 the RCW that contains address inversion
+/// @param[in] i_inversion_enable true if inversion is enabled
+/// @note Passed values should be OFF_N or ON_N
+///
+inline void set_address_inversion(cw_data& io_rc00, const mss::states i_inversion_enable)
+{
+ // Bit 0 is the inversion enable
+ // Note: the bits are actually in JEDEC order, so bit 0 is on the far right
+ constexpr uint64_t INVERSION_BIT = 7;
+
+ // Values should be OFF_N or ON_N
+ io_rc00.iv_data.template writeBit<INVERSION_BIT>(i_inversion_enable);
+}
+
}// mss
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.C
index fa4ba7166..e7c100874 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.C
@@ -40,9 +40,11 @@
#include <lib/phy/mss_lrdimm_training.H>
#include <lib/phy/mss_training.H>
-#include <lib/phy/seq.H>
#include <lib/dimm/rank.H>
#include <lib/dimm/ddr4/mrs_load_ddr4.H>
+#include <lib/dimm/ddr4/control_word_ddr4.H>
+#include <lib/dimm/ddr4/data_buffer_ddr4.H>
+#include <lib/workarounds/ccs_workarounds.H>
namespace mss
{
@@ -100,7 +102,6 @@ fapi2::ReturnCode mpr_pattern_wr_rank(const fapi2::Target<fapi2::TARGET_TYPE_MCA
mss::ccs::program<fapi2::TARGET_TYPE_MCBIST> l_program;
const auto& l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target);
- constexpr uint64_t NUM_MPR_PATTERNS = 4;
// The below code expects us to have ranks in terms of the DIMM values, so index 'em
const auto l_rank = mss::index(i_rank);
@@ -113,8 +114,11 @@ fapi2::ReturnCode mpr_pattern_wr_rank(const fapi2::Target<fapi2::TARGET_TYPE_MCA
// Ok, MPR write
// We need to
// 1) MRS into MPR mode
- // 2) Write the patterns in according to the bank address
- // 3) MRS out of MPR mode
+ // 2) Disable address inversion, so we set our values correctly
+ // We need to disable address inversion so both A-side and B-side get the same pattern written into the MPR registers
+ // 3) Write the patterns in according to the bank address
+ // 4) Restore the default address inversion
+ // 5) MRS out of MPR mode
// 1) MRS into MPR mode
FAPI_TRY( mss::ddr4::mpr_load(l_dimm,
@@ -122,48 +126,27 @@ fapi2::ReturnCode mpr_pattern_wr_rank(const fapi2::Target<fapi2::TARGET_TYPE_MCA
i_rank,
l_program.iv_instructions) );
- // 2) Write the patterns in according to the bank address
- {
- constexpr uint64_t MPR_WR_BG = 0;
- // First, swizzle the pattern
- fapi2::buffer<uint32_t> l_swizzled_pattern;
- FAPI_TRY(mss::seq::swizzle_mpr_pattern(i_pattern, l_swizzled_pattern),
- "%s rank%u failed to swizzle pattern", mss::c_str(i_target), i_rank);
-
- // Now add in writes with the appropriate data involved + the good old swizzle that we do based upon the ranks
- // Swizzle is required as we want the expected data for mirrored and non-mirrored ranks to be the same
- // For MPR writes the expected data is carried by the addresses, so mirroring matters
-
- // Loop through all MPR patterns and generate writes for 'em
- // The MPR number is defined by the bank address
- for(uint8_t l_ba = 0; l_ba < NUM_MPR_PATTERNS; ++l_ba)
- {
- constexpr uint64_t ADDR_START = 54;
- constexpr uint64_t PATTERN_LEN = 8;
- constexpr uint64_t MPR_WR_SAFE_DELAY = 0xff;
- uint64_t l_pattern = 0;
- FAPI_TRY(l_swizzled_pattern.extract(l_pattern, l_ba * PATTERN_LEN, PATTERN_LEN, ADDR_START), "%s ba%u",
- mss::c_str(l_dimm), l_ba);
- {
- auto l_wr = mss::ccs::wr_command<fapi2::TARGET_TYPE_MCBIST>( l_dimm,
- l_rank,
- l_ba,
- MPR_WR_BG,
- l_pattern);
- l_wr.arr1.template insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(MPR_WR_SAFE_DELAY);
- FAPI_TRY(address_mirror(l_dimm, l_rank, l_wr));
- l_program.iv_instructions.push_back(l_wr);
- }
- }
- }
+ // 2) Disable address inversion
+ // We need to disable address inversion so both A-side and B-side get the same pattern written into the MPR registers
+ FAPI_TRY(disable_address_inversion(l_dimm, l_program.iv_instructions));
+
+ // 3) Write the patterns in according to the bank address
+ FAPI_TRY(add_mpr_pattern_writes(l_dimm,
+ l_rank,
+ i_pattern,
+ l_program.iv_instructions));
+ // 4) Restore the default address inversion
+ FAPI_TRY(restore_address_inversion(l_dimm, l_program.iv_instructions));
- // 3) MRS out of MPR mode
+ // 5) MRS out of MPR mode
FAPI_TRY( mss::ddr4::mpr_load(l_dimm,
fapi2::ENUM_ATTR_EFF_MPR_MODE_DISABLE,
i_rank,
l_program.iv_instructions) );
+ // Make sure we leave everything powered on
+ mss::ccs::workarounds::hold_cke_high(l_program.iv_instructions);
FAPI_TRY( ccs::execute(l_mcbist,
l_program,
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H
index d74ee5fb9..4e0e92735 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_lrdimm_training.H
@@ -39,6 +39,12 @@
#define MSS_LRDIMM_TRAINING_H
#include <lib/phy/mss_training.H>
+#include <lib/ccs/ccs.H>
+#include <lib/dimm/ddr4/mrs_load_ddr4.H>
+#include <lib/dimm/ddr4/control_word_ddr4.H>
+#include <lib/dimm/ddr4/data_buffer_ddr4.H>
+#include <lib/phy/seq.H>
+#include <generic/memory/lib/utils/buffer_ops.H>
namespace mss
{
@@ -61,6 +67,126 @@ fapi2::ReturnCode mpr_pattern_wr_all_ranks(const fapi2::Target<fapi2::TARGET_TYP
const uint32_t i_pattern);
///
+/// @brief Adds all write commands for the passed in pattern
+/// @tparam fapi2::TargetType T target type for the CCS instruction
+/// @param[in] i_target DIMM target on which to operate
+/// @param[in] i_rank the DIMM rank to set the MPR on
+/// @param[in] i_pattern the pattern to write into the MPRS
+/// @param[in,out] io_insts CCS instructions
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok
+///
+template<fapi2::TargetType T>
+inline fapi2::ReturnCode add_mpr_pattern_writes(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_pattern,
+ std::vector<mss::ccs::instruction_t<T>>& io_insts)
+{
+
+ constexpr uint64_t NUM_MPR_PATTERNS = 4;
+ constexpr uint64_t MPR_WR_BG = 0;
+ // First, swizzle the pattern
+ fapi2::buffer<uint32_t> l_swizzled_pattern;
+ FAPI_TRY(mss::seq::swizzle_mpr_pattern(i_pattern, l_swizzled_pattern),
+ "%s rank%u failed to swizzle pattern", mss::c_str(i_target), i_rank);
+
+ // Now add in writes with the appropriate data involved + the good old swizzle that we do based upon the ranks
+ // Swizzle is required as we want the expected data for mirrored and non-mirrored ranks to be the same
+ // For MPR writes the expected data is carried by the addresses, so mirroring matters
+
+ // Loop through all MPR patterns and generate writes for 'em
+ // The MPR number is defined by the bank address
+ for(uint8_t l_ba = 0; l_ba < NUM_MPR_PATTERNS; ++l_ba)
+ {
+ constexpr uint64_t ADDR_START = 54;
+ constexpr uint64_t PATTERN_LEN = 8;
+ constexpr uint64_t MPR_WR_SAFE_DELAY = 0xff;
+ uint64_t l_pattern = 0;
+ FAPI_TRY(l_swizzled_pattern.extract(l_pattern, l_ba * PATTERN_LEN, PATTERN_LEN, ADDR_START), "%s ba%u",
+ mss::c_str(i_target), l_ba);
+ {
+ auto l_wr = mss::ccs::wr_command<fapi2::TARGET_TYPE_MCBIST>( i_target,
+ i_rank,
+ l_ba,
+ MPR_WR_BG,
+ l_pattern);
+ // Swaps the bank addresses so they're a true to the BA we tried to pass in above
+ swap<BA0, BA1>(l_wr.arr0);
+
+ l_wr.arr1.template insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES, MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(MPR_WR_SAFE_DELAY);
+ FAPI_TRY(address_mirror(i_target, i_rank, l_wr));
+ io_insts.push_back(l_wr);
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Helper function to disable address inversion
+/// @tparam fapi2::TargetType T target type for the CCS instruction
+/// @param[in] i_target DIMM target on which to operate
+/// @param[in,out] io_insts CCS instructions
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok
+///
+template<fapi2::TargetType T>
+inline fapi2::ReturnCode disable_address_inversion(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ std::vector<mss::ccs::instruction_t<T>>& io_insts)
+{
+ // Declares the default control word that handles address inversion
+ // Data of 0 as we're going to override it below
+ constexpr uint64_t CW_INVERSION = 0;
+ // uint64_t(0) is to avoid compile errors from overloaded functions
+ cw_data l_cw(FUNC_SPACE_0, CW_INVERSION, static_cast<uint64_t>(0), mss::tmrd());
+ constexpr uint64_t CKE_HIGH = mss::ON;
+
+ uint8_t l_sim = 0;
+ FAPI_TRY(mss::is_simulation(l_sim));
+
+ // Gets default values
+ FAPI_TRY(eff_dimm_ddr4_rc00(i_target, l_cw.iv_data));
+
+ // Modifies inversion
+ set_address_inversion(l_cw, mss::states::OFF_N);
+
+ // Creates the CCS instructions
+ FAPI_TRY( control_word_engine<RCW_4BIT>(i_target, l_cw, l_sim, io_insts, CKE_HIGH),
+ "Failed to generate control words for %s", mss::c_str(i_target));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to restore default address inversion
+/// @tparam fapi2::TargetType T target type for the CCS instruction
+/// @param[in] i_target DIMM target on which to operate
+/// @param[in,out] io_insts CCS instructions
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok
+///
+template<fapi2::TargetType T>
+inline fapi2::ReturnCode restore_address_inversion(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ std::vector<mss::ccs::instruction_t<T>>& io_insts)
+{
+ // Declares the default control word that handles address inversion
+ // Data of 0 as we're going to override it below
+ constexpr uint64_t CW_INVERSION = 0;
+ cw_data l_cw(FUNC_SPACE_0, CW_INVERSION, eff_dimm_ddr4_rc00, mss::tmrd());
+ constexpr uint64_t CKE_HIGH = mss::ON;
+
+ uint8_t l_sim = 0;
+ FAPI_TRY(mss::is_simulation(l_sim));
+
+ // Creates the CCS instructions
+ FAPI_TRY( control_word_engine<RCW_4BIT>(i_target, l_cw, l_sim, io_insts, CKE_HIGH),
+ "Failed to generate control words for %s", mss::c_str(i_target));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
/// @brief Issues initial pattern write a specific rank
/// @param[in] i_target the MCA target on which to operate
/// @parma[in] i_rank the rank to setup for initial pattern write
OpenPOWER on IntegriCloud