summaryrefslogtreecommitdiffstats
path: root/src/import/chips
diff options
context:
space:
mode:
authorBrian Silver <bsilver@us.ibm.com>2016-09-28 16:48:11 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2016-10-04 18:47:54 -0400
commite1e8610960d9b5124a656b662144ff6b76631e85 (patch)
treee01487498c3234a8bea113951aeae99288fed12f /src/import/chips
parent7bc64f60dbbfe24d3c7c0b649a94d1ca77cba86a (diff)
downloadtalos-hostboot-e1e8610960d9b5124a656b662144ff6b76631e85.tar.gz
talos-hostboot-e1e8610960d9b5124a656b662144ff6b76631e85.zip
Add MCBIST workaround super-fast read & 1R DIMM
Change-Id: I6473dfd00e9636797619e0e3d3a6d54eb9cdb5b9 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/30553 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/30561 Reviewed-by: Hostboot Team <hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import/chips')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C12
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H42
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C4
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C104
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H55
5 files changed, 209 insertions, 8 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C
index 1c693bd36..ccd7c2700 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C
@@ -36,14 +36,13 @@
#include <fapi2.H>
#include <lib/mcbist/mcbist.H>
#include <lib/utils/dump_regs.H>
+#include <lib/workarounds/mcbist_workarounds.H>
using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_MCA;
namespace mss
{
-namespace mcbist
-{
const std::pair<uint64_t, uint64_t> mcbistTraits<fapi2::TARGET_TYPE_MCBIST>::address_pairs[] =
{
@@ -53,6 +52,8 @@ const std::pair<uint64_t, uint64_t> mcbistTraits<fapi2::TARGET_TYPE_MCBIST>::add
{ START_ADDRESS_3, END_ADDRESS_3 },
};
+namespace mcbist
+{
///
/// @brief Load a set of MCBIST subtests in to the MCBIST registers
@@ -225,6 +226,13 @@ fapi2::ReturnCode execute( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
fapi2::MSS_MEMDIAGS_NO_MCBIST_SUBTESTS().set_TARGET(i_target),
"Attempt to run an MCBIST program with no subtests on %s", mss::c_str(i_target));
+ // Implement any mcbist work-arounds.
+ // I'm going to do the unthinkable here - and cast away the const of the mcbist program input.
+ // The work arounds need to change this, and so it needs to not be const. However, I don't want
+ // to risk general const-correctness by changing the input parameter to non-const. So, I use
+ // const_cast<> (ducks out of the way of the flying adjectives.) These are work-arounds ...
+ FAPI_TRY( workarounds::mcbist::end_of_rank(i_target, const_cast<program<TARGET_TYPE_MCBIST>&>(i_program)) );
+
FAPI_TRY( clear_errors(i_target) );
// Slam the address generator config
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
index 7f71e1276..333698600 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H
@@ -50,8 +50,6 @@
namespace mss
{
-namespace mcbist
-{
// I have a dream that the MCBIST engine code can be shared among controllers. So, I drive the
// engine from a set of traits. This might be folly. Allow me to dream. BRS
@@ -291,6 +289,9 @@ class mcbistTraits<fapi2::TARGET_TYPE_MCBIST>
};
+namespace mcbist
+{
+
///
/// @class subtest_t
/// @brief encapsulation of an MCBIST subtest.
@@ -633,6 +634,39 @@ inline subtest_t<T> read_subtest()
}
///
+/// @brief Return a display subtest - configured simply
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
+inline subtest_t<T> display_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<T> l_subtest;
+
+ // 0:3 = 1100 - we want subtest type to be a DISPLAY (R, slow)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::DISPLAY);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
/// @brief Return a read write subtest - configured simply
/// @tparam T the fapi2::TargetType - derived
/// @tparam TT the mcbistTraits associated with T - derived
@@ -1406,10 +1440,10 @@ class program
// asked for a master rank detect.
iv_config.insertFromRight<TT::CFG_PAUSE_ON_ERROR_MODE, TT::CFG_PAUSE_ON_ERROR_MODE_LEN>(i_end);
- FAPI_INF("i_end 0x%016lx", i_end);
uint64_t l_detect_slave = fapi2::buffer<uint64_t>(i_end).getBit<SLAVE_RANK_INDICATED_BIT>();
iv_addr_gen.writeBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>( l_detect_slave );
- FAPI_INF("load MCBIST end boundaries: detect slave? %s", (l_detect_slave == 1 ? "yes" : "no") );
+ FAPI_INF("load MCBIST end boundaries 0x%016lx detect slave? %s",
+ i_end, (l_detect_slave == 1 ? "yes" : "no") );
}
///
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C
index e9ab2b992..6066b414e 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C
@@ -65,7 +65,7 @@ template<>
fapi2::ReturnCode stop( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
{
// Too long, make shorter
- using TT = mss::mcbist::mcbistTraits<TARGET_TYPE_MCBIST>;
+ using TT = mss::mcbistTraits<TARGET_TYPE_MCBIST>;
// Poll parameters are defined as TK so that we wait a nice time for operations
// For now use the defaults
@@ -576,7 +576,7 @@ fapi2::ReturnCode continue_cmd( const fapi2::Target<TARGET_TYPE_MCBIST>& i_targe
const speed i_speed )
{
// Too long, make shorter
- using TT = mss::mcbist::mcbistTraits<TARGET_TYPE_MCBIST>;
+ using TT = mss::mcbistTraits<TARGET_TYPE_MCBIST>;
// We can use a local mcbist::program to help with the bit processing, and then write just the registers we touch.
mss::mcbist::program<TARGET_TYPE_MCBIST> l_program;
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C
index 958e5f464..37217c300 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C
@@ -22,3 +22,107 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mcbist_workarounds.C
+/// @brief Workarounds for the MCBISt engine
+/// Workarounds are very deivce specific, so there is no attempt to generalize
+/// this code in any way.
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Steven Glancy <sglancy@usi.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: FSP:HB
+
+#include <fapi2.H>
+#include <p9_mc_scom_addresses.H>
+#include <p9_mc_scom_addresses_fld.H>
+
+#include <lib/utils/scom.H>
+#include <lib/utils/pos.H>
+#include <lib/dimm/kind.H>
+#include <lib/workarounds/mcbist_workarounds.H>
+#include <lib/mcbist/mcbist.H>
+
+using fapi2::TARGET_TYPE_MCBIST;
+using fapi2::TARGET_TYPE_DIMM;
+using fapi2::FAPI2_RC_SUCCESS;
+
+namespace mss
+{
+
+namespace workarounds
+{
+
+namespace mcbist
+{
+
+///
+/// @brief Replace reads with displays in the passed in MCBIST program
+/// @param[in] the MCBIST program to check for read/display replacement
+/// @note Useful for testing
+///
+void replace_read_helper(mss::mcbist::program<TARGET_TYPE_MCBIST>& i_program)
+{
+ using TT = mss::mcbistTraits<TARGET_TYPE_MCBIST>;
+
+ i_program.change_maint_broadcast_mode(mss::OFF);
+ i_program.change_end_boundary(mss::mcbist::end_boundary::STOP_AFTER_ADDRESS);
+
+ for (auto& st : i_program.iv_subtests)
+ {
+ uint64_t l_op = 0;
+ st.iv_mcbmr.extractToRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(l_op);
+
+ if (l_op == mss::mcbist::op_type::READ)
+ {
+ l_op = mss::mcbist::op_type::DISPLAY;
+ }
+
+ st.iv_mcbmr.insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(l_op);
+ }
+}
+
+///
+/// @brief End of rank work around
+/// For Nimbus DD1 the MCBIST engine doesn't detect the end of rank properly
+/// for a 1R DIMM during a super-fast read. To work around this, we check the
+/// MCBIST to see if any port has a 1R DIMM on it and if so we change our stop
+/// conditions to immediate. However, because that doesn't work (by design) with
+/// read, we also must change all reads to displays (slow read.)
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[in] i_program the mcbist program to check
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode end_of_rank( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ mss::mcbist::program<TARGET_TYPE_MCBIST>& i_program )
+{
+ // TODO RTC:160353 - implement DD1 checking when that attribute is available
+
+ // First things first - lets find out if we have an 1R DIMM on our side of the chip.
+ const auto l_dimm_kinds = dimm::kind::vector( mss::find_targets<TARGET_TYPE_DIMM>(i_target) );
+ auto l_kind = std::find_if(l_dimm_kinds.begin(), l_dimm_kinds.end(), [](const dimm::kind & k) -> bool
+ {
+ // If total ranks are 1, we have a 1R DIMM, SDP. This is the fellow of concern
+ return k.iv_total_ranks == 1;
+ });
+
+ // If we don't find the fellow of concern, we can get outta here
+ if (l_kind == l_dimm_kinds.end())
+ {
+ FAPI_INF("no 1R SDP DIMM on this MCBIST (%s), we're ok", mss::c_str(i_target));
+ return FAPI2_RC_SUCCESS;
+ }
+
+ // If we're here, we need to fix up our program. We need to set our stop to stop immediate, which implies
+ // we don't do broadcasts and we can't do read, we have to do display.
+ replace_read_helper(i_program);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+} // close namespace mcbist
+} // close namespace workarounds
+} // close namespace mss
+
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H
index e3320f13f..0f8e9c978 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H
@@ -22,3 +22,58 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mcbist_workarounds.H
+/// @brief Workarounds for the MCBISt engine
+/// Workarounds are very deivce specific, so there is no attempt to generalize
+/// this code in any way.
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Steven Glancy <sglancy@usi.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_WORKAROUNDS_MCBIST_H_
+#define _MSS_WORKAROUNDS_MCBIST_H_
+
+#include <fapi2.H>
+#include <lib/mcbist/mcbist.H>
+
+namespace mss
+{
+
+namespace workarounds
+{
+
+namespace mcbist
+{
+
+///
+/// @brief Replace reads with displays in the passed in MCBIST program
+/// @param[in] the MCBIST program to check for read/display replacement
+/// @note Useful for testing
+///
+void replace_read_helper(mss::mcbist::program<fapi2::TARGET_TYPE_MCBIST>& i_program);
+
+///
+/// @brief End of rank work around
+/// For Nimbus DD1 the MCBIST engine doesn't detect the end of rank properly
+/// for a 1R DIMM during a super-fast read. To work around this, we check the
+/// MCBIST to see if any port has a 1R DIMM on it and if so we change our stop
+/// conditions to immediate. However, because that doesn't work (by design) with
+/// read, we also must change all reads to displays (slow read.)
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[in] i_program the mcbist program to check
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode end_of_rank( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ mss::mcbist::program<fapi2::TARGET_TYPE_MCBIST>& i_program );
+
+} // close namespace mcbist
+} // close namespace workarounds
+} // close namespace mss
+
+#endif
+
OpenPOWER on IntegriCloud