diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2018-10-18 21:32:31 -0500 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2018-10-29 17:38:19 -0500 |
commit | 74c643ef35c61ab0f7f7979b9b20f2b518e0c792 (patch) | |
tree | 8fb25ac8f43774d3a952e74c717ed003b723787c /src/import/chips | |
parent | a2f59106caececf9bc92b9f8279578d58b85b3aa (diff) | |
download | talos-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')
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 |