From 40bcbd0f3a78e74a6c23c050f7cef854cc2c283a Mon Sep 17 00:00:00 2001 From: Tsung Yeung Date: Tue, 19 Mar 2019 09:21:53 -0400 Subject: Enable median rank wr_vref value on NVDIMM - The NVDIMM restore procedure is required to restore the wr vref values. The current method is to latch in the per-dram wr vref value with PDA. However, this requires multiple CCS sequences due to hardware limitation and would break refresh timing between sequences, introduce possible UEs. To get around this, we will use the median value of all the drams per rank-pair instead of per-dram value. Previous attempt was to use average value but after the speaking with Stephen G. median value is a better approach due to the possibility that bad vref value from failing dram - Added NVDIMM-specifc CCS execute procedure Change-Id: Ie7d1e063c423a4374ca22422395ee5524d70a124 CQ:SW459457 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/74753 Tested-by: FSP CI Jenkins Reviewed-by: Louis Stermole Reviewed-by: STEPHEN GLANCY Tested-by: Jenkins Server Tested-by: Hostboot CI Tested-by: HWSV CI Reviewed-by: Jennifer A. Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/74790 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Christian R. Geddes --- .../hwp/memory/lib/dimm/ddr4/latch_wr_vref.C | 20 +++- .../hwp/memory/lib/dimm/ddr4/latch_wr_vref.H | 7 +- .../hwp/memory/lib/dimm/ddr4/nvdimm_utils.C | 122 ++++++++------------- .../hwp/memory/lib/dimm/ddr4/nvdimm_utils.H | 52 +++++++-- .../p9/procedures/hwp/memory/lib/dimm/mrs_load.C | 23 +++- .../p9/procedures/hwp/memory/lib/dimm/mrs_load.H | 5 +- 6 files changed, 132 insertions(+), 97 deletions(-) (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/dimm') 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 def06a0df..0d2cad989 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 @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -39,6 +39,7 @@ #include #include #include +#include using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_DIMM; @@ -96,13 +97,14 @@ fapi_try_exit: /// @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 +/// @param[in] i_nvdimm_workaround switch to indicate nvdimm workaround. Default to false /// @return FAPI2_RC_SUCCESS if and only if ok /// fapi2::ReturnCode latch_wr_vref_commands_by_rank_pair( const fapi2::Target& i_target, const uint64_t i_rank_pair, const uint8_t i_train_range, - const uint8_t i_train_value) + const uint8_t i_train_value, + const bool i_nvdimm_workaround) { // Declares variables const auto l_mcbist = find_target(i_target); @@ -141,7 +143,17 @@ fapi2::ReturnCode latch_wr_vref_commands_by_rank_pair( const fapi2::Target& i_target, const uint64_t i_rank_pair, const uint8_t i_train_range, - const uint8_t i_train_value); + const uint8_t i_train_value, + const bool i_nvdimm_workaround = false); /// /// @brief enables VREF train enable in an MRS06 class diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C index ed63071d5..fe2f396f1 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C @@ -53,8 +53,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -321,70 +321,6 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief PDA support for post restore transition -/// Specialization for TARGET_TYPE_DIMM -/// @param[in] i_target the target associated with this subroutine -/// @return FAPI2_RC_SUCCESS iff setup was successful -/// -template<> -fapi2::ReturnCode pda_vref_latch( const fapi2::Target& i_target ) -{ - std::vector l_ranks; - const auto& l_mca = mss::find_target(i_target); - fapi2::buffer l_value, l_range; - fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); - - // Creates the MRS container class - mss::ddr4::pda::commands l_container; - - // Get all the ranks in the dimm - mss::rank::ranks(i_target, l_ranks); - - // Get the number of DRAMs - uint8_t l_width = 0; - mss::eff_dram_width(i_target, l_width); - const uint64_t l_num_drams = (l_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? MAX_DRAMS_X8 : MAX_DRAMS_X4; - - for (const auto& l_rank : l_ranks) - { - - uint64_t l_rp = 0; - uint64_t l_wr_vref_value = 0; - bool l_wr_vref_range = 0; - fapi2::buffer l_data ; - - mss::rank::get_pair_from_rank(l_mca, l_rank, l_rp); - - // create mrs06 - mss::ddr4::mrs06_data l_mrs(i_target, l_rc); - - // loop through all the dram - for(uint64_t l_dram = 0; l_dram < l_num_drams; l_dram++) - { - mss::dp16::wr_vref::read_wr_vref_register( l_mca, l_rp, l_dram, l_data); - mss::dp16::wr_vref::get_wr_vref_range( l_data, l_dram, l_wr_vref_range); - mss::dp16::wr_vref::get_wr_vref_value( l_data, l_dram, l_wr_vref_value); - - l_mrs.iv_vrefdq_train_value[mss::index(l_rank)] = l_wr_vref_value; - l_mrs.iv_vrefdq_train_range[mss::index(l_rank)] = l_wr_vref_range; - l_container.add_command(i_target, l_rank, l_mrs, l_dram); - } - } - - // Disable refresh - FAPI_TRY( mss::change_refresh_enable(l_mca, states::LOW) ); - - // execute_wr_vref_latch(l_container) - FAPI_TRY( mss::ddr4::pda::execute_wr_vref_latch(l_container) ) - - // Enable refresh - FAPI_TRY( mss::change_refresh_enable(l_mca, states::HIGH) ); - -fapi_try_exit: - return fapi2::current_err; -} - /// /// @brief Disable powerdown mode in rc09 /// @param[in] i_target, a fapi2::Target @@ -540,7 +476,7 @@ fapi2::ReturnCode rcd_restore( const fapi2::Target& i_target ) // Exit STR first so CKE is back to high and rcd isn't ignoring us FAPI_TRY( self_refresh_exit( i_target ) ); - FAPI_TRY( ccs::execute(l_mcbist, l_program, i_target), + FAPI_TRY( mss::ccs::workarounds::nvdimm::execute(l_mcbist, l_program, i_target), "Failed to execute ccs for %s", mss::c_str(i_target) ); // Now, drive CKE back to low via STR entry instead of pde (we have data in the drams!) @@ -557,7 +493,7 @@ fapi2::ReturnCode rcd_restore( const fapi2::Target& i_target ) }// dimms // Restore the rcd - FAPI_TRY( ccs::execute(l_mcbist, l_program, i_target), + FAPI_TRY( mss::ccs::workarounds::nvdimm::execute(l_mcbist, l_program, i_target), "Failed to execute ccs for %s", mss::c_str(i_target) ); fapi_try_exit: @@ -597,13 +533,53 @@ fapi2::ReturnCode post_restore_zqcal( const fapi2::Target& i_target ) +{ + std::vector l_pairs; + const bool NVDIMM_WORKAROUND = true; + + // We are latching in the averaged value and we should have the averaged value + // (this step should be run after all the draminit) so just the first dram is fine + constexpr uint64_t l_dram = 0; + + // Get our rank pairs. + FAPI_TRY( mss::rank::get_rank_pairs(i_target, l_pairs) ); + + for (const auto& l_rp : l_pairs) + { + FAPI_INF("NVDIMM wr_vref_latch on rp %d %s", l_rp, mss::c_str(i_target)); + fapi2::buffer l_data ; + uint64_t l_wr_vref_value = 0; + bool l_wr_vref_range = 0; + + mss::dp16::wr_vref::read_wr_vref_register( i_target, l_rp, l_dram, l_data); + mss::dp16::wr_vref::get_wr_vref_range( l_data, l_dram, l_wr_vref_range); + mss::dp16::wr_vref::get_wr_vref_value( l_data, l_dram, l_wr_vref_value); + + FAPI_TRY( mss::ddr4::latch_wr_vref_commands_by_rank_pair(i_target, + l_rp, + l_wr_vref_range, + l_wr_vref_value, + NVDIMM_WORKAROUND) ); + + }// rank pairs + +fapi_try_exit: + return fapi2::current_err; +} + /// /// @brief Post restore transition to support restoring nvdimm to /// a functional state after the restoring the data from NAND flash @@ -616,6 +592,7 @@ template<> fapi2::ReturnCode post_restore_transition( const fapi2::Target& i_target ) { mss::states l_maint_addr_enabled = mss::states::LOW; + const bool NVDIMM_WORKAROUND = true; FAPI_TRY(get_maint_addr_mode_en(i_target, l_maint_addr_enabled)); @@ -633,16 +610,13 @@ fapi2::ReturnCode post_restore_transition( const fapi2::Target(i_target)) - { - FAPI_TRY( pda_vref_latch( l_dimm ) ); - } + // Latch in the rank averaged vref value + FAPI_TRY(wr_vref_latch(i_target)); //Restore main_addr_mode_en to previous setting FAPI_TRY(change_maint_addr_mode_en(i_target, l_maint_addr_enabled)); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H index 538a650ba..5df44c13c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.H @@ -37,6 +37,7 @@ #include #include #include +#include namespace mss { @@ -113,16 +114,6 @@ fapi2::ReturnCode self_refresh_entry( const fapi2::Target& i_target ); template< fapi2::TargetType T > fapi2::ReturnCode self_refresh_exit( const fapi2::Target& i_target ); -/// -/// @brief Latch write vref at per-dram basis -/// @tparam T the target type associated with this subroutine -/// @param[in] i_target the target associated with this subroutine -/// @return FAPI2_RC_SUCCESS iff setup was successful -/// - -template< fapi2::TargetType T > -fapi2::ReturnCode pda_vref_latch( const fapi2::Target& i_target ); - /// /// @brief Disable powerdown mode in rc09 /// @param[in] i_target, a fapi2::Target @@ -162,6 +153,13 @@ fapi2::ReturnCode rcd_restore( const fapi2::Target& i_ta /// fapi2::ReturnCode post_restore_zqcal( const fapi2::Target& i_target); +/// +/// @brief Latch write vref +/// @param[in] i_target the target associated with this subroutine +/// @return FAPI2_RC_SUCCESS iff setup was successful +/// +fapi2::ReturnCode wr_vref_latch( const fapi2::Target& i_target ); + /// /// @brief Full post-restore transition for NVDIMM /// @tparam T the target type associated with this subroutine @@ -180,6 +178,40 @@ fapi2::ReturnCode post_restore_transition( const fapi2::Target& i_target ); /// fapi2::ReturnCode preload_epow_sequence( const fapi2::Target& i_target ); +namespace wr_vref +{ + +/// +/// @brief Helper to extract the values and ranges from wr_vref_value reg, and +/// convert JEDEC value to composite +/// @param[in] i_data - wr vref reg data +/// @param[out] o_values - vector of composite value +/// +inline void get_wr_vref_composite_value_helper(const fapi2::buffer i_data, + std::vector& o_values) +{ + FAPI_DBG("get_wr_vref_composite_value_helper() i_data = 0x%016lx", i_data); + const std::vector DRAMS = {0, 1}; + + for (const auto l_dram : DRAMS) + { + uint64_t l_wr_vref_val = 0; + bool l_wr_vref_range = 0; + uint64_t l_composite_vref = 0; + + mss::dp16::wr_vref::get_wr_vref_value(i_data, l_dram, l_wr_vref_val); + mss::dp16::wr_vref::get_wr_vref_range(i_data, l_dram, l_wr_vref_range); + + l_composite_vref = mss::dp16::wr_vref::compute_composite_value(l_wr_vref_range, l_wr_vref_val); + + FAPI_DBG("l_composite_vref: 0x%016lx", l_composite_vref); + + o_values.push_back(l_composite_vref); + } +} + +}//ns wr_vref + }//ns nvdimm }//ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C index 609251cb1..aae4cce28 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/mrs_load.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,6 +38,7 @@ #include #include #include +#include using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_DIMM; @@ -51,10 +52,12 @@ namespace mss /// /// @brief Perform the mrs_load operations - TARGET_TYPE_MCA specialization /// @param[in] i_target a fapi2::Target +/// @param[in] i_nvdimm_workaround switch to indicate nvdimm workaround. Default to false /// @return FAPI2_RC_SUCCESS if and only if ok /// template<> -fapi2::ReturnCode mrs_load( const fapi2::Target& i_target ) +fapi2::ReturnCode mrs_load( const fapi2::Target& i_target, + const bool i_nvdimm_workaround ) { const auto& l_mcbist = mss::find_target(i_target); @@ -75,7 +78,17 @@ fapi2::ReturnCode mrs_load( const fapi2::Target +/// @param[in] i_nvdimm_workaround switch to indicate nvdimm workaround. Default to false /// @return FAPI2_RC_SUCCESS if and only if ok /// template<> -fapi2::ReturnCode mrs_load( const fapi2::Target& i_target ) +fapi2::ReturnCode mrs_load( const fapi2::Target& i_target, + const bool i_nvdimm_workaround ) { for ( const auto& p : find_targets(i_target) ) { 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 2b0418cfb..f19679bc7 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 @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2018 */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -111,10 +111,11 @@ struct mrs_data /// @brief Perform the mrs_load operations /// @tparam T, the fapi2::TargetType of i_target /// @param[in] i_target, a fapi2::Target +/// @param[in] i_nvdimm_workaround switch to indicate nvdimm workaround. Default to false /// @return FAPI2_RC_SUCCESS if and only if ok /// template< fapi2::TargetType T > -fapi2::ReturnCode mrs_load( const fapi2::Target& i_target ); +fapi2::ReturnCode mrs_load( const fapi2::Target& i_target, const bool i_nvdimm_workaround = false ); // // Implement the polymorphism for mrs_load -- cgit v1.2.1