From 50b0357dd001a70e4e0da7a3e34b04d852dde21b Mon Sep 17 00:00:00 2001 From: Stephen Glancy Date: Fri, 11 Oct 2019 17:26:41 -0400 Subject: Adds NVDIMM RCW drive strength workaround An NVDIMM supplier updated the drive strength values for for the RCW's command/address/control signals. The new drive strength causes the parts to fail writes/reads. This commit restores the old drive strength values. Change-Id: If4d44f08cff2522de463b9a2ac57853950aa3356 CQ:SW478491 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/85229 Tested-by: FSP CI Jenkins Reviewed-by: Louis Stermole Tested-by: Jenkins Server Tested-by: Hostboot CI Dev-Ready: STEPHEN GLANCY Reviewed-by: JEREMY R NEATON Reviewed-by: TSUNG K YEUNG Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/85426 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Christian R Geddes --- .../p9/procedures/hwp/memory/lib/dimm/eff_dimm.C | 14 +++++ .../lib/workarounds/eff_config_workarounds.C | 70 ++++++++++++++++++++++ .../lib/workarounds/eff_config_workarounds.H | 51 ++++++++++++++++ 3 files changed, 135 insertions(+) (limited to 'src/import') diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C index 5074a5b4d..2c3a3a757 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C @@ -51,6 +51,7 @@ #include #include #include +#include namespace mss { @@ -1567,6 +1568,7 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dimm_rc03() { + constexpr uint8_t NVDIMM_RCW_WORKAROUND_VALUE = 0x08; fapi2::buffer l_buffer; uint8_t l_attrs_dimm_rc03[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; @@ -1589,6 +1591,10 @@ fapi2::ReturnCode eff_dimm::dimm_rc03() l_buffer.insertFromRight(l_ca_output_drive) .insertFromRight(l_cs_output_drive); } + + // Update the value if the NVDIMM workaround is needed + FAPI_TRY(mss::workarounds::eff_config::nvdimm_rc_drive_strength(iv_dimm, NVDIMM_RCW_WORKAROUND_VALUE, l_buffer)); + // Retrieve MCS attribute data FAPI_TRY( eff_dimm_ddr4_rc03(iv_mcs, &l_attrs_dimm_rc03[0][0]) ); @@ -1608,6 +1614,7 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dimm_rc04() { + constexpr uint8_t NVDIMM_RCW_WORKAROUND_VALUE = 0x0a; uint8_t l_attrs_dimm_rc04[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; uint8_t l_odt_output_drive = 0; uint8_t l_cke_output_drive = 0; @@ -1631,6 +1638,9 @@ fapi2::ReturnCode eff_dimm::dimm_rc04() .insertFromRight(l_odt_output_drive); } + // Update the value if the NVDIMM workaround is needed + FAPI_TRY(mss::workarounds::eff_config::nvdimm_rc_drive_strength(iv_dimm, NVDIMM_RCW_WORKAROUND_VALUE, l_buffer)); + // Retrieve MCS attribute data FAPI_TRY( eff_dimm_ddr4_rc04(iv_mcs, &l_attrs_dimm_rc04[0][0]) ); @@ -1650,6 +1660,7 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dimm_rc05() { + constexpr uint8_t NVDIMM_RCW_WORKAROUND_VALUE = 0x0a; uint8_t l_attrs_dimm_rc05[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; uint8_t l_a_side_output_drive = 0; uint8_t l_b_side_output_drive = 0; @@ -1673,6 +1684,9 @@ fapi2::ReturnCode eff_dimm::dimm_rc05() .insertFromRight(l_a_side_output_drive); } + // Update the value if the NVDIMM workaround is needed + FAPI_TRY(mss::workarounds::eff_config::nvdimm_rc_drive_strength(iv_dimm, NVDIMM_RCW_WORKAROUND_VALUE, l_buffer)); + // Retrieve MCS attribute data FAPI_TRY( eff_dimm_ddr4_rc05(iv_mcs, &l_attrs_dimm_rc05[0][0]) ); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.C index 080023b8a..dae18167b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.C @@ -22,3 +22,73 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + + +#include +#include +#include + +namespace mss +{ + +namespace workarounds +{ + +namespace eff_config +{ + +/// +/// @brief Checks if the NVDIMM RC drive strength workaround is needed +/// @param[in] i_target DIMM target on which to operate +/// @param[out] o_is_needed true if the workaround is needed +/// @return SUCCESS if the code executes successfully +/// +fapi2::ReturnCode is_nvdimm_rc_drive_strength_needed(const fapi2::Target& i_target, + bool& o_is_needed) +{ + o_is_needed = false; + + uint8_t l_hybrid = 0; + uint8_t l_hybrid_type = 0; + uint32_t l_size = 0; + + FAPI_TRY(mss::eff_hybrid(i_target, l_hybrid)); + FAPI_TRY(mss::eff_hybrid_memory_type(i_target, l_hybrid_type)); + FAPI_TRY(mss::eff_dimm_size(i_target, l_size)); + + if(l_hybrid == fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID && + l_hybrid_type == fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM && + l_size == fapi2::ENUM_ATTR_EFF_DIMM_SIZE_32GB) + { + o_is_needed = true; + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Updates the RC drive strength if the workaround is needed +/// @param[in] i_target DIMM target on which to operate +/// @param[in] i_override_value the value to override if the workaround needs to be applied +/// @param[in,out] io_rc_value Register Control word value to update +/// @return SUCCESS if the code executes successfully +/// +fapi2::ReturnCode nvdimm_rc_drive_strength(const fapi2::Target& i_target, + const uint8_t i_override_value, + fapi2::buffer& io_rc_value) +{ + bool l_is_needed = false; + FAPI_TRY(is_nvdimm_rc_drive_strength_needed(i_target, l_is_needed)); + + // If the workaround is needed, overwrite it to be ALL_MODERATE values + // Otherwise keep it as it is + io_rc_value = l_is_needed ? fapi2::buffer(i_override_value) : io_rc_value; + +fapi_try_exit: + return fapi2::current_err; +} + +} // ns eff_config +} // ns workarounds +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.H index ad8bee571..f41d9b89c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/eff_config_workarounds.H @@ -22,3 +22,54 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file eff_config_workarounds.H +/// @brief Workarounds for effective config +/// Workarounds are very device specific, so there is no attempt to generalize +/// this code in any way. +/// +// *HWP HWP Owner: Stephen Glancy +// *HWP HWP Backup: Andre Marin +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: FSP:HB + +#ifndef _EFF_CONFIG_WORKAROUNDS_H_ +#define _EFF_CONFIG_WORKAROUNDS_H_ + +#include + +namespace mss +{ + +namespace workarounds +{ + +namespace eff_config +{ + +/// +/// @brief Checks if the NVDIMM RC drive strength workaround is needed +/// @param[in] i_target DIMM target on which to operate +/// @param[out] o_is_needed true if the workaround is needed +/// @return SUCCESS if the code executes successfully +/// +fapi2::ReturnCode is_nvdimm_rc_drive_strength_needed(const fapi2::Target& i_target, + bool& o_is_needed); + +/// +/// @brief Updates the RC drive strength if the workaround is needed +/// @param[in] i_target DIMM target on which to operate +/// @param[in] i_override_value the value to override if the workaround needs to be applied +/// @param[in,out] io_rc_value Register Control word value to update +/// @return SUCCESS if the code executes successfully +/// +fapi2::ReturnCode nvdimm_rc_drive_strength(const fapi2::Target& i_target, + const uint8_t i_override_value, + fapi2::buffer& io_rc_value); + +} // ns eff_config +} // ns workarounds +} // ns mss +#endif -- cgit v1.2.1