summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Silver <bsilver@us.ibm.com>2016-01-07 14:35:20 -0600
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-04-01 21:23:41 -0400
commit3a11ab737feeb6695f949f355f41081e64dec2f5 (patch)
tree4f1e16a5ac0351f8b8eb236322916ea587159db0
parentdba9ee6be396b29a072d9c5fc87ff346542c396e (diff)
downloadtalos-hostboot-3a11ab737feeb6695f949f355f41081e64dec2f5.tar.gz
talos-hostboot-3a11ab737feeb6695f949f355f41081e64dec2f5.zip
Add mcbist L2 function
Change-Id: Ie902a404323fe781aca99af2c20ca6ba564a06da Original-Change-Id: I8b98c188d6a642eb49d89deffcbd697d9cf7afdc Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/23895 Tested-by: Jenkins Server Reviewed-by: Craig C. Hamilton <cchamilt@us.ibm.com> Reviewed-by: Andre A. Marin <aamarin@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22768 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H85
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C133
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H2
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C214
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.C171
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H940
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mss.H8
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H86
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H2
9 files changed, 1557 insertions, 84 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
new file mode 100644
index 000000000..6dc0c5c45
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
@@ -0,0 +1,85 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/hwp/memory/lib/dimm/kind.H $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* EKB Project */
+/* */
+/* COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file dimm.H
+/// @brief Encapsulation for dimms of all types
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Craig Hamilton <cchamilt@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_DIMM_H_
+#define _MSS_DIMM_H_
+
+#include <fapi2.H>
+
+#include <mss_attribute_accessors.H>
+#include "../utils/c_str.H"
+
+namespace mss
+{
+
+namespace dimm
+{
+
+///
+/// @class mss::dimm::kind
+/// @brief A class containing information about a dimm like ranks, density, configuration - what kind of dimm is it?
+///
+class kind
+{
+ public:
+
+ kind(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target):
+ iv_target(i_target)
+ {
+ FAPI_TRY( mss::eff_dram_gen(i_target, iv_dram_generation) );
+ FAPI_TRY( mss::eff_dimm_type(i_target, iv_dimm_type) );
+ FAPI_TRY( mss::eff_dram_density(i_target, iv_dram_density) );
+ FAPI_TRY( mss::eff_dram_width(i_target, iv_dram_width) );
+ FAPI_TRY( mss::eff_num_master_ranks_per_dimm(i_target, iv_master_ranks) );
+ FAPI_TRY( mss::eff_dram_rows(i_target, iv_rows) );
+ FAPI_TRY( mss::eff_dimm_size(i_target, iv_size) );
+
+ // TK: Attribute for slave ranks.
+ iv_slave_ranks = 0;
+
+ fapi_try_exit:
+ // Not 100% sure what to do here ...
+ FAPI_ERR("error initializing DIMM structure: %s 0x%016lx", mss::c_str(i_target), uint64_t(fapi2::current_err));
+ }
+
+ const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target;
+ uint8_t iv_master_ranks;
+ uint8_t iv_slave_ranks;
+ uint8_t iv_dram_density;
+ uint8_t iv_dram_width;
+ uint8_t iv_dram_generation;
+ uint8_t iv_dimm_type;
+ uint8_t iv_rows;
+ uint8_t iv_size;
+};
+
+}
+
+}
+#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C
index 4b76445f9..274ec94a9 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.C
@@ -28,11 +28,11 @@
// *HWP Consumed by: FSP:HB
#include <fapi2.H>
-
#include <p9_mc_scom_addresses.H>
#include "../utils/dump_regs.H"
#include "../utils/scom.H"
+#include "mc.H"
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
@@ -40,6 +40,10 @@ using fapi2::TARGET_TYPE_MCS;
namespace mss
{
+const uint64_t mcTraits<TARGET_TYPE_MCS>::xlate0_reg[] = {MCS_PORT02_MCP0XLT0, MCS_PORT13_MCP0XLT0};
+const uint64_t mcTraits<TARGET_TYPE_MCS>::xlate1_reg[] = {MCS_PORT02_MCP0XLT1, MCS_PORT13_MCP0XLT1};
+const uint64_t mcTraits<TARGET_TYPE_MCS>::xlate2_reg[] = {MCS_PORT02_MCP0XLT2, MCS_PORT13_MCP0XLT2};
+
///
/// @brief Dump the registers of the MC (MCA_MBA, MCS)
/// @param[in] i_target the MCS target
@@ -178,4 +182,131 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Perform initializations for the MC (MCA)
+/// @param[in] i_target, the MCA to initialize
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template<>
+fapi2::ReturnCode mc<TARGET_TYPE_MCA>::scominit(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
+{
+ uint32_t l_throttle_denominator = 0;
+ FAPI_TRY( mss::runtime_mem_throttle_denominator(i_target, l_throttle_denominator) );
+
+ // #Register Name Final Arb Parms
+ // #Mnemonic MBA_FARB0Q
+ // #Attributes PAR:EVEN Bit Field Mnemonic Attribute or Setting to use
+ // #Description FARB command control
+ // #1. FARB0 bit 38: cfg_parity_after_cmd
+ // # - set this bit if DDR3 and (RDIMM or LDRIMM)
+ //
+ // # - clear this bit if DDR4 and (RDIMM or LDRIMM)
+ // #2. FARB0 bit 60: cfg_ignore_rcd_parity_err
+ // # - clear this bit if (RDIMM or LDRIMM)
+ // #3. FARB0 bit 61: cfg_enable_rcd_rw_retry
+ // # - set this bit if (RDIMM or LDRIMM)
+
+ // Nimbus is always LR/RDIMM, DDR4.
+ // Not sure what happened to cfg_ignore_rcd_parity_err, cfg_enable_rcd_rw_retry - perhaps they're always ok since we don't
+ // support anything else?
+ {
+ fapi2::buffer<uint64_t> l_data;
+
+ l_data.setBit<MCA_MBA_FARB0Q_CFG_PARITY_AFTER_CMD>();
+ FAPI_TRY( mss::putScom(i_target, MCA_MBA_FARB0Q, l_data) );
+ }
+
+ {
+ // FABR1Q - Chip ID bits
+ }
+ {
+ // FARB2Q - ODT bits
+ }
+
+ // #Register Name N/M Throttling Control
+ // #Mnemonic MBA_FARB3Q
+ // #Attributes PAR:EVEN Bit Field Mnemonic Attribute or Setting to use
+ // #Description N/M throttling control (Centaur only)
+ // # 0:14 cfg_nm_n_per_mba MSS_MEM_THROTTLE_NUMERATOR_PER_MBA (Centaur)
+ // # 15:30 cfg_nm_n_per_chip MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP (Centaur)
+ // # 0:14 cfg_nm_n_per_slot MSS_MEM_THROTTLE_NUMERATOR_PER_SLOT (Nimbus)
+ // # 15:30 cfg_nm_n_per_port MSS_MEM_THROTTLE_NUMERATOR_PER_PORT (Nimbus)
+ // # 31:44 cfg_nm_m MSS_MEM_THROTTLE_DENOMINATOR
+ // # 51 cfg_nm_per_slot_enabled 1 (not on Nimbus?)
+ // # 52 cfg_nm_count_other_mba_dis Set to 0 for CDIMM, Set to 1 for everything else (not on Nimbus?)
+ // #cfg_nm_ras_weight, bits 45:47 = ATTR_MSS_THROTTLE_CONTROL_RAS_WEIGHT
+ // #cfg_nm_cas_weight, bits 48:50 = ATTR_MSS_THROTTLE_CONTROL_CAS_WEIGHT
+ {
+ fapi2::buffer<uint64_t> l_data;
+ uint32_t l_throttle_per_slot = 0;
+ uint32_t l_throttle_per_port = 0;
+ uint8_t l_ras_weight = 0;
+ uint8_t l_cas_weight = 0;
+
+ FAPI_TRY( mss::runtime_mem_throttle_numerator_per_slot(i_target, l_throttle_per_slot) );
+ FAPI_TRY( mss::runtime_mem_throttle_numerator_per_port(i_target, l_throttle_per_port) );
+ FAPI_TRY( mss::throttle_control_ras_weight(i_target, l_ras_weight) );
+ FAPI_TRY( mss::throttle_control_cas_weight(i_target, l_cas_weight) );
+
+ l_data.insertFromRight<MCA_MBA_FARB3Q_CFG_NM_N_PER_SLOT, MCA_MBA_FARB3Q_CFG_NM_N_PER_SLOT_LEN>(l_throttle_per_slot);
+ l_data.insertFromRight<MCA_MBA_FARB3Q_CFG_NM_N_PER_PORT, MCA_MBA_FARB3Q_CFG_NM_N_PER_PORT_LEN>(l_throttle_per_port);
+ l_data.insertFromRight<MCA_MBA_FARB3Q_CFG_NM_M, MCA_MBA_FARB3Q_CFG_NM_M_LEN>(l_throttle_denominator);
+ l_data.insertFromRight<MCA_MBA_FARB3Q_CFG_NM_RAS_WEIGHT, MCA_MBA_FARB3Q_CFG_NM_RAS_WEIGHT_LEN>(l_ras_weight);
+ l_data.insertFromRight<MCA_MBA_FARB3Q_CFG_NM_CAS_WEIGHT, MCA_MBA_FARB3Q_CFG_NM_CAS_WEIGHT_LEN>(l_ras_weight);
+
+ FAPI_TRY( mss::putScom(i_target, MCA_MBA_FARB3Q, l_data) );
+ }
+
+ // Doesn't appear to be a row-hammer-mode in Nimbus
+ // # -- bits 27:41 (cfg_emer_n) = ATTR_MRW_SAFEMODE_MEM_THROTTLE_NUMERATOR_PER_SLOT
+ // # -- bits 42:55 (cfg_emer_m) = ATTR_MRW_MEM_THROTTLE_DENOMINATOR
+ {
+ fapi2::buffer<uint64_t> l_data;
+ uint32_t l_throttle_per_slot = 0;
+
+ FAPI_TRY( mss::mrw_safemode_mem_throttle_numerator_per_slot(l_throttle_per_slot) );
+
+ l_data.insertFromRight<MCA_MBA_FARB4Q_EMERGENCY_M, MCA_MBA_FARB4Q_EMERGENCY_M_LEN>(l_throttle_denominator);
+ l_data.insertFromRight<MCA_MBA_FARB4Q_EMERGENCY_N, MCA_MBA_FARB4Q_EMERGENCY_N_LEN>(l_throttle_per_slot);
+
+ FAPI_TRY( mss::putScom(i_target, MCA_MBA_FARB4Q, l_data) );
+ }
+
+ {
+ // TMR0Q - DDR data bus timing parameters
+ }
+
+ {
+ // TMR1Q - DDR bank busy parameters
+ }
+
+ {
+ // DSM0Q - Data State Machine Configurations
+ }
+
+ {
+ // MBAREF0Q mba01 refresh settings
+ }
+
+ {
+ // MBAPC0Q power control settings reg 0
+ // MBAPC1Q power control settings reg 1
+ }
+
+ {
+ // MBAREF1Q MBA01 Rank-to-primary-CKE mapping table
+ // Doesn't exist in Nimbus. Leaving this as a comment to note that we didn't forget it.
+ // CKEs are fixed to chip selects for all P9 configs
+ }
+
+ {
+ // CAL0Q (this timer to be used for zq cal)
+ // CAL1Q (this timer to be used for mem cal)
+ // CAL3Q (this timer to be used for mem cal)
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
}
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H
index f239dd0c7..1e295dc8f 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/mc.H
@@ -116,7 +116,7 @@ enum
{
THIS_ENTRY_VALID = 0,
VALUE_OF_D_BIT_INDEX = 1,
- 12GB_ENABLE_INDEX = 2,
+ GB12_ENABLE_INDEX = 2,
MASTER_BIT_0_VALID_INDEX = 3,
MASTER_BIT_1_VALID_INDEX = 4,
SLAVE_BIT_0_VALID_INDEX = 5,
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C
new file mode 100644
index 000000000..f9f778ce6
--- /dev/null
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C
@@ -0,0 +1,214 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: chips/p9/procedures/hwp/memory/lib/mc/xlate.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* EKB Project */
+/* */
+/* COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file xlate.C
+/// @brief Subroutines to manipulate the memory controller translation registers
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.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 "mss_attribute_accessors.H"
+
+#include "mc.H"
+#include "../utils/scom.H"
+#include "../dimm/kind.H"
+
+using fapi2::TARGET_TYPE_MCBIST;
+using fapi2::TARGET_TYPE_PROC_CHIP;
+using fapi2::TARGET_TYPE_SYSTEM;
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+using fapi2::FAPI2_RC_SUCCESS;
+
+
+namespace mss
+{
+
+///
+/// @brief Perform initializations of the MC translation
+/// @tparm P, the fapi2::TargetType of the port
+/// @tparm TT, the typename of the traits
+/// @param[in] i_target, the target which has the MCA to map
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template<>
+template<>
+fapi2::ReturnCode mc<TARGET_TYPE_MCS>::setup_xlate_map(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
+{
+ fapi2::buffer<uint64_t> l_xlate;
+ fapi2::buffer<uint64_t> l_xlate1;
+ fapi2::buffer<uint64_t> l_xlate2;
+
+ const auto l_dimms = i_target.getChildren<TARGET_TYPE_DIMM>();
+
+ FAPI_INF("Setting up xlate registers for MCA%d (%d)", mss::pos(i_target), mss::index(i_target));
+
+ // We enable the DIMM select bit for slot1 if we have two DIMM installed
+ l_xlate.writeBit<MCS_PORT13_MCP0XLT0_SLOT1_D_VALUE>(l_dimms.size() == 2);
+
+ // Get the functional DIMM on this port.
+ for (auto d : l_dimms)
+ {
+ // Our slot (0, 1) is the same as our general index.
+ const uint64_t l_slot = mss::index(d);
+
+ // Our slot offset tells us which 16 bit section in the xlt register to use for this DIMM
+ // We'll either use the left most bits (slot 0) or move 16 bits to the right for slot 1.
+ const uint64_t l_slot_offset = l_slot * 16;
+
+ // Get the translation array, based on this specific DIMM's config
+ dimm::kind l_dimm(d);
+
+ // TK: Get the information from the translation table for this DIMM.
+
+ FAPI_DBG("address translation for DIMM %s %dR %dgbx%d in slot %d",
+ mss::c_str(d), l_dimm.iv_master_ranks, l_dimm.iv_dram_density, l_dimm.iv_dram_width, l_slot);
+
+
+ // Set the proper bit if there is a DIMM in this slot. If there wasn't, we wouldn't see
+ // this DIMM in the vector, so this is always safe.
+ l_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_VALID + l_slot_offset);
+
+
+ // Set the 12G DIMM bit if either DIMM is 12G
+ // Is this correct? BRS
+ l_xlate.writeBit<MCS_PORT13_MCP0XLT0_12GB_ENABLE>(l_dimm.iv_size == 12);
+
+ // Check our master ranks, and enable the proper bits.
+ // Note this seems a little backward. M0 is the left most bit, M1 the right most.
+ // So, M1 changes for ranks 0,1 and M0 changes for ranks 3,4
+ if (l_dimm.iv_master_ranks > 0)
+ {
+ l_xlate.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M1_VALID + l_slot_offset);
+ }
+
+ if (l_dimm.iv_master_ranks > 2)
+ {
+ l_xlate.setBit(MCS_PORT13_MCP0XLT0_SLOT0_M0_VALID + l_slot_offset);
+ }
+
+
+ // Check slave ranks
+ // Note this sems a little backward. S0 is the left-most slave bit. So,
+ // if there are more than 0 slave ranks, S2 will increment first.
+ if (l_dimm.iv_slave_ranks > 0)
+ {
+ l_xlate.setBit(MCS_PORT13_MCP0XLT0_SLOT0_S2_VALID + l_slot_offset);
+ }
+
+ if (l_dimm.iv_slave_ranks > 2)
+ {
+ l_xlate.setBit(MCS_PORT13_MCP0XLT0_SLOT0_S1_VALID + l_slot_offset);
+ }
+
+ if (l_dimm.iv_slave_ranks > 4)
+ {
+ l_xlate.setBit(MCS_PORT13_MCP0XLT0_SLOT0_S0_VALID + l_slot_offset);
+ }
+
+
+ // Tell the MC which of the row bits are valid.
+ if (l_dimm.iv_rows >= 16)
+ {
+ l_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW15_VALID + l_slot_offset);
+ }
+
+ if (l_dimm.iv_rows >= 17)
+ {
+ l_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW16_VALID + l_slot_offset);
+ }
+
+ if (l_dimm.iv_rows >= 18)
+ {
+ l_xlate.setBit(MCS_PORT02_MCP0XLT0_SLOT0_ROW17_VALID + l_slot_offset);
+ }
+
+ }
+
+ // TK: remove and make general in the loop above BRS
+
+ // Two rank DIMM, so master bit 1 (least significant) bit needs to be mapped.
+ l_xlate.insertFromRight<MCS_PORT02_MCP0XLT0_M1_BIT_MAP, MCS_PORT02_MCP0XLT0_M1_BIT_MAP_LEN>(0b01111);
+
+ // Slot 1 isn't populated, so forget those bits for now.
+
+ // DIMM bit map isn't exactly ignored for only one populated slot. It still needs to be
+ // set in the map. Per S. Powell.
+ // Master rank 0, 1 bit maps are ignored.
+ // Row 16,17 bit maps are ignored.
+ // Row 15 maps to Port Address bit 6
+ l_xlate.insertFromRight<MCS_PORT02_MCP0XLT0_D_BIT_MAP, MCS_PORT02_MCP0XLT0_D_BIT_MAP_LEN>(0b00101);
+ l_xlate.insertFromRight<MCS_PORT02_MCP0XLT0_R15_BIT_MAP, MCS_PORT02_MCP0XLT0_R15_BIT_MAP_LEN>(0b00110);
+
+ // Drop down the column assignments
+ l_xlate1.insertFromRight<MCS_PORT02_MCP0XLT1_COL4_BIT_MAP,
+ MCS_PORT02_MCP0XLT1_COL4_BIT_MAP_LEN>(0b01101);
+
+ l_xlate1.insertFromRight<MCS_PORT02_MCP0XLT1_COL5_BIT_MAP,
+ MCS_PORT02_MCP0XLT1_COL5_BIT_MAP_LEN>(0b01100);
+
+ l_xlate1.insertFromRight<MCS_PORT02_MCP0XLT1_COL6_BIT_MAP,
+ MCS_PORT02_MCP0XLT1_COL6_BIT_MAP_LEN>(0b01011);
+
+ l_xlate1.insertFromRight<MCS_PORT02_MCP0XLT1_COL7_BIT_MAP,
+ MCS_PORT02_MCP0XLT1_COL7_BIT_MAP_LEN>(0b01010);
+
+ l_xlate2.insertFromRight<MCS_PORT02_MCP0XLT2_COL8_BIT_MAP,
+ MCS_PORT02_MCP0XLT2_COL8_BIT_MAP_LEN>(0b01001);
+
+ l_xlate2.insertFromRight<MCS_PORT02_MCP0XLT2_COL9_BIT_MAP,
+ MCS_PORT02_MCP0XLT2_COL9_BIT_MAP_LEN>(0b00111);
+
+ l_xlate2.insertFromRight<MCS_PORT02_MCP0XLT2_BANK0_BIT_MAP,
+ MCS_PORT02_MCP0XLT2_BANK0_BIT_MAP_LEN>(0b01110);
+
+ l_xlate2.insertFromRight<MCS_PORT02_MCP0XLT2_BANK1_BIT_MAP,
+ MCS_PORT02_MCP0XLT2_BANK1_BIT_MAP_LEN>(0b10000);
+
+ l_xlate2.insertFromRight<MCS_PORT02_MCP0XLT2_BANK_GROUP0_BIT_MAP,
+ MCS_PORT02_MCP0XLT2_BANK_GROUP0_BIT_MAP_LEN>(0b10001);
+
+ l_xlate2.insertFromRight<MCS_PORT02_MCP0XLT2_BANK_GROUP1_BIT_MAP,
+ MCS_PORT02_MCP0XLT2_BANK_GROUP1_BIT_MAP_LEN>(0b10010);
+
+ FAPI_DBG("HACK: Cramming 0x%016lx in for MCP0XLT0", l_xlate);
+ FAPI_DBG("HACK: Cramming 0x%016lx in for MCP0XLT1", l_xlate1);
+ FAPI_DBG("HACK: Cramming 0x%016lx in for MCP0XLT2", l_xlate2);
+
+ FAPI_TRY( mss::putScom(i_target.getParent<TARGET_TYPE_MCS>(), MCS_0_PORT02_MCP0XLT0, l_xlate) );
+ FAPI_TRY( mss::putScom(i_target.getParent<TARGET_TYPE_MCS>(), MCS_0_PORT02_MCP0XLT1, l_xlate1) );
+ FAPI_TRY( mss::putScom(i_target.getParent<TARGET_TYPE_MCS>(), MCS_0_PORT02_MCP0XLT2, l_xlate2) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+} // namespace
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 f2184f89b..c06df116a 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
@@ -7,7 +7,7 @@
/* */
/* EKB Project */
/* */
-/* COPYRIGHT 2015 */
+/* COPYRIGHT 2015,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -29,13 +29,182 @@
#include <fapi2.H>
#include "mcbist.H"
+#include "../utils/dump_regs.H"
using fapi2::TARGET_TYPE_MCBIST;
+using fapi2::TARGET_TYPE_MCA;
namespace mss
{
namespace mcbist
{
+///
+/// @brief Load a set of MCBIST subtests in to the MCBIST registers
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note assumes the MCBIST engine has been configured.
+///
+template<>
+fapi2::ReturnCode load_mcbmr( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ const mcbist::program<TARGET_TYPE_MCBIST>& i_program )
+{
+
+ // Leave if there are no subtests.
+ if (0 == i_program.iv_subtests.size())
+ {
+ FAPI_DBG("no subtests, noting to do");
+ return fapi2::current_err;
+ }
+
+ // List of the 8 MCBIST registers - each holds 4 subtests.
+ static const std::vector< uint64_t > l_memory_registers =
+ {
+ MCBIST_MCBMR0Q, MCBIST_MCBMR1Q, MCBIST_MCBMR2Q, MCBIST_MCBMR3Q,
+ MCBIST_MCBMR4Q, MCBIST_MCBMR5Q, MCBIST_MCBMR6Q, MCBIST_MCBMR7Q,
+ };
+
+ std::vector< uint64_t > l_memory_register_buffers =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+ static const size_t SUBTEST_PER_REG = 4;
+ static const size_t SUBTEST_PER_PROGRAM = 32;
+
+ static const auto BITS_IN_SUBTEST = sizeof(mcbist::subtest_t<TARGET_TYPE_MCBIST>().iv_mcbmr) * 8;
+ static const auto LEFT_SHIFT = (sizeof(uint64_t) * 8) - BITS_IN_SUBTEST;
+
+ ssize_t l_bin = -1;
+ size_t l_register_shift = 0;
+
+ // We'll shift this in to position to indicate which subtest is the last
+ static const uint64_t l_done_bit( 0x8000000000000000 >> MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_DONE );
+
+ // TK: For now limit MCBIST programs to 32 subtests.
+ const auto l_program_size = i_program.iv_subtests.size();
+ FAPI_ASSERT( l_program_size <= SUBTEST_PER_PROGRAM,
+ fapi2::MSS_MCBIST_PROGRAM_TOO_BIG().set_PROGRAM_LENGTH(l_program_size),
+ "mcbist program of length %d exceeds arbitrary maximum of %d", l_program_size, SUBTEST_PER_PROGRAM );
+
+ // Distribute the program over the 8 MCBIST subtest registers
+ // We need the index, so increment thru i_program.iv_subtests.size()
+ for (size_t l_index = 0; l_index < l_program_size; ++l_index)
+ {
+ l_bin = (l_index % SUBTEST_PER_REG) == 0 ? l_bin + 1 : l_bin;
+ l_register_shift = (l_index % SUBTEST_PER_REG) * BITS_IN_SUBTEST;
+
+ l_memory_register_buffers[l_bin] |=
+ (uint64_t(i_program.iv_subtests[l_index].iv_mcbmr) << LEFT_SHIFT) >> l_register_shift;
+
+ FAPI_DBG("putting subtest %d (0x%x) in MCBMR%dQ shifted %d 0x%016llx",
+ l_index, i_program.iv_subtests[l_index].iv_mcbmr, l_bin,
+ l_register_shift, l_memory_register_buffers[l_bin]);
+ }
+
+ // l_bin and l_register_shift are the values for the last subtest we'll tell the MCBIST about.
+ // We need to set that subtest's done-bit so the MCBIST knows it's the end of the line
+ l_memory_register_buffers[l_bin] |= l_done_bit >> l_register_shift;
+ FAPI_DBG("setting MCBMR%dQ subtest %llu as the last subtest 0x%016llx",
+ l_bin, l_register_shift, l_memory_register_buffers[l_bin]);
+
+ // ... and slam the values in to the registers.
+ // Could just decrement l_bin, but that scoms the subtests in backwards and is confusing
+ for (auto l_index = 0; l_index <= l_bin; ++l_index)
+ {
+ FAPI_TRY( mss::putScom(i_target, l_memory_registers[l_index], l_memory_register_buffers[l_index]) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Execute the mcbist program
+/// @param[in] i_target the target to effect
+/// @param[in] i_program, the mcbist program to execute
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template<>
+fapi2::ReturnCode execute( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ const program<TARGET_TYPE_MCBIST>& i_program )
+{
+ typedef mcbistTraits<TARGET_TYPE_MCBIST> TT;
+
+ static const uint64_t l_done = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_DONE>();
+ static const uint64_t l_fail = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_FAIL>();
+
+ fapi2::buffer<uint64_t> l_status;
+
+ // Slam the subtests in to the mcbist registers
+ FAPI_TRY( load_mcbmr(i_target, i_program) );
+
+ // Slam the parameters in to the mcbist parameter register
+ FAPI_TRY( load_mcbparm(i_target, i_program) );
+
+ // Slam the address generator config
+ FAPI_TRY( load_addr_gen(i_target, i_program) );
+
+ // Slam the configured address maps down
+ FAPI_TRY( load_mcbamr( i_target, i_program) );
+
+ // Slam the config register down
+ FAPI_TRY( load_config( i_target, i_program) );
+
+ // Slam the control register down
+ FAPI_TRY( load_control( i_target, i_program) );
+
+ // Start the engine, and then poll for completion
+ // Note: We need to have a bit in the program for 'async' mode where an attention
+ // bit is set and we can fire-and-forget BRS
+ FAPI_TRY(start_stop(i_target, mss::START));
+
+ mss::poll(i_target, TT::STATQ_REG, i_program.iv_poll,
+ [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_DBG("mcbist statq 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ l_status = stat_reg;
+ return l_status.getBit<TT::MCBIST_IN_PROGRESS>() != 1;
+ });
+
+ // The control register has a bit for done-and-happy and a bit for done-and-unhappy
+ if ((l_status & l_done) == l_done)
+ {
+ FAPI_DBG("MCBIST executed successfully.");
+ return fapi2::current_err;
+ }
+
+ if ((l_status & l_fail) == l_fail)
+ {
+ FAPI_DBG("MCBIST failed execution.");
+ return fapi2::FAPI2_RC_FALSE;
+ }
+
+ // So something set more than one bit in the control register?
+ FAPI_DBG("MCBIST executed <shrug>. Something's not good 0x%016llx", l_status);
+ return fapi2::FAPI2_RC_FALSE;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
} // namespace
+
+// Note: outside of the mcbist namespace
+
+///
+/// @brief Dump the registers of an mcbist
+/// @param[in] i_target, the mcbist in question
+/// @return fapi2::FAPI2_RC_SUCCESS if ok
+///
+template<>
+fapi2::ReturnCode dump_regs( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
+{
+ return fapi2::current_err;
+}
+
+
} // namespace
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 464f7278c..77998302c 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
@@ -37,6 +37,7 @@
#include "../utils/poll.H"
#include "../shared/mss_const.H"
+#include "../utils/bit_count.H"
namespace mss
{
@@ -72,6 +73,26 @@ class mcbistTraits<fapi2::TARGET_TYPE_MCBIST>
public:
/// MCBIST "memory registers" - config for subtests.
static const uint64_t MCBMR0_REG = MCBIST_MCBMR0Q;
+ static const uint64_t CFGQ_REG = MCBIST_MCBCFGQ;
+ static const uint64_t CNTLQ_REG = MCBIST_MCB_CNTLQ;
+ static const uint64_t STATQ_REG = MCBIST_MCB_CNTLSTATQ;
+ static const uint64_t MCBPARMQ_REG = MCBIST_MCBPARMQ;
+ static const uint64_t MCBAGRAQ_REG = MCBIST_MCBAGRAQ;
+
+ static const uint64_t MCBAMR0A0Q_REG = MCBIST_MCBAMR0A0Q;
+ static const uint64_t MCBAMR1A0Q_REG = MCBIST_MCBAMR1A0Q;
+ static const uint64_t MCBAMR2A0Q_REG = MCBIST_MCBAMR2A0Q;
+ static const uint64_t MCBAMR3A0Q_REG = MCBIST_MCBAMR3A0Q;
+
+ static const uint64_t START_ADDRESS_0 = MCBIST_MCBSA0Q;
+ static const uint64_t START_ADDRESS_1 = MCBIST_MCBSA1Q;
+ static const uint64_t START_ADDRESS_2 = MCBIST_MCBSA2Q;
+ static const uint64_t START_ADDRESS_3 = MCBIST_MCBSA3Q;
+
+ static const uint64_t END_ADDRESS_0 = MCBIST_MCBEA0Q;
+ static const uint64_t END_ADDRESS_1 = MCBIST_MCBEA1Q;
+ static const uint64_t END_ADDRESS_2 = MCBIST_MCBEA2Q;
+ static const uint64_t END_ADDRESS_3 = MCBIST_MCBEA3Q;
enum
{
@@ -86,6 +107,74 @@ class mcbistTraits<fapi2::TARGET_TYPE_MCBIST>
DATA_MODE_LEN = MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_DATA_MODE_LEN,
ADDR_SEL = MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_ADDR_SEL,
ADDR_SEL_LEN = MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_ADDR_SEL_LEN,
+ OP_TYPE = MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_OP_TYPE,
+ OP_TYPE_LEN = MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_OP_TYPE_LEN,
+ DONE = MCBIST_MCBMR0Q_MCBIST_CFG_TEST00_DONE,
+
+ SYNC_EN = MCBIST_MCBCFGQ_BROADCAST_SYNC_EN,
+ SYNC_WAIT = MCBIST_MCBCFGQ_BROADCAST_SYNC_WAIT,
+ SYNC_WAIT_LEN = MCBIST_MCBCFGQ_BROADCAST_SYNC_WAIT_LEN,
+
+ PORT_SEL = MCBIST_MCB_CNTLQ_MCBCNTL_PORT_SEL,
+ PORT_SEL_LEN = MCBIST_MCB_CNTLQ_MCBCNTL_PORT_SEL_LEN,
+
+ MCBIST_START = MCBIST_MCB_CNTLQ_START,
+ MCBIST_STOP = MCBIST_MCB_CNTLQ_STOP,
+
+ MCBIST_IN_PROGRESS = MCBIST_MCB_CNTLSTATQ_IP,
+ MCBIST_DONE = MCBIST_MCB_CNTLSTATQ_DONE,
+ MCBIST_FAIL = MCBIST_MCB_CNTLSTATQ_FAIL,
+
+ MIN_CMD_GAP = MCBIST_MCBPARMQ_CFG_MIN_CMD_GAP,
+ MIN_CMD_GAP_LEN = MCBIST_MCBPARMQ_CFG_MIN_CMD_GAP_LEN,
+ MIN_GAP_TIMEBASE = MCBIST_MCBPARMQ_CFG_MIN_GAP_TIMEBASE,
+ MIN_CMD_GAP_BLIND_STEER = MCBIST_MCBPARMQ_CFG_MIN_CMD_GAP_BLIND_STEER,
+ MIN_CMD_GAP_BLIND_STEER_LEN = MCBIST_MCBPARMQ_CFG_MIN_CMD_GAP_BLIND_STEER_LEN,
+ MIN_GAP_TIMEBASE_BLIND_STEER = MCBIST_MCBPARMQ_CFG_MIN_GAP_TIMEBASE_BLIND_STEER,
+ RANDCMD_WGT = MCBIST_MCBPARMQ_CFG_RANDCMD_WGT,
+ RANDCMD_WGT_LEN = MCBIST_MCBPARMQ_CFG_RANDCMD_WGT_LEN,
+ CLOCK_MONITOR_EN = MCBIST_MCBPARMQ_CFG_CLOCK_MONITOR_EN,
+ EN_RANDCMD_GAP = MCBIST_MCBPARMQ_CFG_EN_RANDCMD_GAP,
+ RANDGAP_WGT = MCBIST_MCBPARMQ_CFG_RANDGAP_WGT,
+ RANDGAP_WGT_LEN = MCBIST_MCBPARMQ_CFG_RANDGAP_WGT_LEN,
+ BC4_EN = MCBIST_MCBPARMQ_CFG_BC4_EN,
+
+ FIXED_WIDTH = MCBIST_MCBAGRAQ_CFG_FIXED_WIDTH,
+ FIXED_WIDTH_LEN = MCBIST_MCBAGRAQ_CFG_FIXED_WIDTH_LEN,
+ ADDR_COUNTER_MODE = MCBIST_MCBAGRAQ_CFG_ADDR_COUNTER_MODE,
+ ADDR_COUNTER_MODE_LEN = MCBIST_MCBAGRAQ_CFG_ADDR_COUNTER_MODE_LEN,
+ MAINT_ADDR_MODE_EN = MCBIST_MCBAGRAQ_CFG_MAINT_ADDR_MODE_EN,
+ MAINT_BROADCAST_MODE_EN = MCBIST_MCBAGRAQ_CFG_MAINT_BROADCAST_MODE_EN,
+ MAINT_DETECT_SRANK_BOUNDARIES = MCBIST_MCBAGRAQ_CFG_MAINT_DETECT_SRANK_BOUNDARIES,
+
+ BROADCAST_SYNC_EN = MCBIST_MCBCFGQ_BROADCAST_SYNC_EN,
+ BROADCAST_SYNC_WAIT = MCBIST_MCBCFGQ_BROADCAST_SYNC_WAIT,
+ BROADCAST_SYNC_WAIT_LEN = MCBIST_MCBCFGQ_BROADCAST_SYNC_WAIT_LEN,
+ CFG_CMD_TIMEOUT_MODE = MCBIST_MCBCFGQ_CFG_CMD_TIMEOUT_MODE,
+ CFG_CMD_TIMEOUT_MODE_LEN = MCBIST_MCBCFGQ_CFG_CMD_TIMEOUT_MODE_LEN,
+ RESET_KEEPER = MCBIST_MCBCFGQ_RESET_KEEPER,
+ CFG_CURRENT_ADDR_TRAP_UPDATE_DIS = MCBIST_MCBCFGQ_CFG_CURRENT_ADDR_TRAP_UPDATE_DIS,
+ CFG_CCS_RETRY_DIS = MCBIST_MCBCFGQ_CFG_CCS_RETRY_DIS,
+ RESERVED_13_34 = MCBIST_MCBCFGQ_RESERVED_13_34,
+ RESERVED_13_34_LEN = MCBIST_MCBCFGQ_RESERVED_13_34_LEN,
+ CFG_RESET_CNTS_START_OF_RANK = MCBIST_MCBCFGQ_CFG_RESET_CNTS_START_OF_RANK,
+ CFG_LOG_COUNTS_IN_TRACE = MCBIST_MCBCFGQ_CFG_LOG_COUNTS_IN_TRACE,
+ SKIP_INVALID_ADDR_DIMM_DIS = MCBIST_MCBCFGQ_SKIP_INVALID_ADDR_DIMM_DIS,
+ REFRESH_ONLY_SUBTEST_EN = MCBIST_MCBCFGQ_REFRESH_ONLY_SUBTEST_EN,
+ REFRESH_ONLY_SUBTEST_TIMEBASE_SEL = MCBIST_MCBCFGQ_REFRESH_ONLY_SUBTEST_TIMEBASE_SEL,
+ REFRESH_ONLY_SUBTEST_TIMEBASE_SEL_LEN = MCBIST_MCBCFGQ_REFRESH_ONLY_SUBTEST_TIMEBASE_SEL_LEN,
+ RAND_ADDR_ALL_ADDR_MODE_EN = MCBIST_MCBCFGQ_RAND_ADDR_ALL_ADDR_MODE_EN,
+ MCBIST_CFG_REF_WAIT_TIME = MCBIST_MCBCFGQ_MCBIST_CFG_REF_WAIT_TIME,
+ MCBIST_CFG_REF_WAIT_TIME_LEN = MCBIST_MCBCFGQ_MCBIST_CFG_REF_WAIT_TIME_LEN,
+ CFG_MCB_LEN64 = MCBIST_MCBCFGQ_CFG_MCB_LEN64,
+ CFG_PAUSE_ON_ERROR_MODE = MCBIST_MCBCFGQ_CFG_PAUSE_ON_ERROR_MODE,
+ CFG_PAUSE_ON_ERROR_MODE_LEN = MCBIST_MCBCFGQ_CFG_PAUSE_ON_ERROR_MODE_LEN,
+ MCBIST_CFG_PAUSE_AFTER_CCS_SUBTEST = MCBIST_MCBCFGQ_MCBIST_CFG_PAUSE_AFTER_CCS_SUBTEST,
+ MCBIST_CFG_FORCE_PAUSE_AFTER_ADDR = MCBIST_MCBCFGQ_MCBIST_CFG_FORCE_PAUSE_AFTER_ADDR,
+ MCBIST_CFG_FORCE_PAUSE_AFTER_SUBTEST = MCBIST_MCBCFGQ_MCBIST_CFG_FORCE_PAUSE_AFTER_SUBTEST,
+ CFG_ENABLE_SPEC_ATTN = MCBIST_MCBCFGQ_CFG_ENABLE_SPEC_ATTN,
+ CFG_ENABLE_HOST_ATTN = MCBIST_MCBCFGQ_CFG_ENABLE_HOST_ATTN,
+
};
};
@@ -98,6 +187,156 @@ template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
class subtest_t
{
public:
+ subtest_t( const uint16_t i_data = 0 ):
+ iv_mcbmr(i_data)
+ {}
+
+ ///
+ /// @brief Complement the data for the first subcommand
+ /// @param[in] i_state, the desired state, mss::ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_compliment_1st_cmd( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_1ST_CMD>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Complement the data for the second subcommand
+ /// @param[in] i_state, the desired state, mss::ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_compliment_2nd_cmd( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_2ND_CMD>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Complement the data for the third subcommand
+ /// @param[in] i_state, the desired state, mss::ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_compliment_3rd_cmd( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_3RD_CMD>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Enable a specific port for this test - maint address mode
+ /// @param[in] i_port, the port desired to be enabled - int 0, 1, 2, 3
+ /// @return void
+ ///
+ inline void enable_port( const uint64_t i_port )
+ {
+ constexpr uint64_t l_len = (TT::COMPL_2ND_CMD - TT::COMPL_1ST_CMD) + 1;
+ iv_mcbmr.template insertFromRight<TT::COMPL_1ST_CMD, l_len>(i_port);
+ return;
+ }
+
+ ///
+ /// @brief Enable a specific dimm for this test - maint address mode
+ /// @param[in] i_dimm, the dimm desired to be enabled - int 0, 1
+ /// @return void
+ ///
+ inline void enable_dimm( const uint64_t i_dimm )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_3RD_CMD>(i_dimm);
+ return;
+ }
+
+
+ ///
+ /// @brief Generate addresses in reverse order
+ /// @param[in] i_state, the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_addr_rev_mode( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::ADDR_REV_MODE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Generate addresses in random order
+ /// @param[in] i_state, the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_addr_rand_mode( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::ADDR_RAND_MODE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Generate and check data with ECC
+ /// @param[in] i_state, the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_ecc_mode( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::ECC_MODE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Set the 'done after this test' bit
+ /// @param[in] i_state, the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_done( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::DONE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Set the data mode for this subtest
+ /// @param[in] i_mode, the desired mcbist::data_mode
+ /// @return void
+ ///
+ inline void change_data_mode( const data_mode i_mode )
+ {
+ iv_mcbmr.template insertFromRight<TT::DATA_MODE, TT::DATA_MODE_LEN>(i_mode);
+ return;
+ }
+
+ ///
+ /// @brief Set the operation type for this subtest
+ /// @param[in] i_mode, the desired mcbist::op_type
+ /// @return void
+ ///
+ inline void change_op_type( const op_type i_type )
+ {
+ iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(i_type);
+ return;
+ }
+
+ ///
+ /// @brief Configure which address registers to use for this subtest
+ /// @param[in] i_index, 0 = MCBSA0Q, 1 = MCBSA1Q, ...
+ /// @note wraps to 0-3 no matter what value you pass in.
+ /// @return void
+ ///
+ inline void change_addr_sel( const uint16_t i_index )
+ {
+ // Roll the index around - tidy support for an index which is out of range.
+ static const uint16_t MAX_ADDRESS_START_END_REGISTERS = 3 + 1;
+ iv_mcbmr.template insertFromRight<TT::ADDR_SEL, TT::ADDR_SEL_LEN>(i_index % MAX_ADDRESS_START_END_REGISTERS);
+ return;
+ }
+
+ //
+ // @brief operator== for mcbist subtests
+ // @param[in] i_rhs, the right hand side of the compare
+ // @return bool, true iff i_rhs == this
+ inline bool operator==(const subtest_t<T>& i_rhs) const
+ {
+ return i_rhs.iv_mcbmr == iv_mcbmr;
+ }
+
/// The mcbist 'memory register' for this subtest.
// Note that it is only 16 bits.
// Each 64b memory register contains multiple 16 bit subtest definitions.
@@ -107,149 +346,694 @@ class subtest_t
};
///
+/// @brief Return a write 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> write_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<T> l_subtest;
+
+ // 0:3 = 0000 - we want subtest type to be a Write (W)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::WRITE);
+
+ // - 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 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> read_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<T> l_subtest;
+
+ // 0:3 = 0001 - we want subtest type to be a Read (R)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::READ);
+
+ // - 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 A class representing a series of MCBIST subtests, and the
/// MCBIST engine parameters associated with running the subtests
/// @tparam T fapi2::TargetType representing the fapi2 target which
/// contains the MCBIST engine (e.g., fapi2::TARGET_TYPE_MCBIST)
+/// @tparam TT, the mssTraits associtated with T
+/// @note MCBIST Memory Parameter Register defaults to
+/// - issue commands as fast as possible
+/// - even weighting of read/write if random addressing
+/// - disable clock monitoring
+/// - random command gap is disabled
+/// - BC4 disabled
+/// - no selected ports
+/// @note Address Generation Config Register defaults to
+/// - 0 fixed slots
+/// - All address counter modes on (so addr configs are start + len)
+/// - maint address mode enabled
+/// - maint broadcast mode disabled
+/// - maint slave rank boundary detect disabled
+/// @note Config register defaults to
+/// - BROADCAST_SYNC_EN disabled
+/// - BROADCAST_SYNC_WAIT 0
+/// - TIMEOUT_MODE - wait 524288 cycles until timeout is called
+/// - RESET_KEEPER - 0
+/// - CURRENT_ADDR_TRAP_UPDATE_DIS - 0
+/// - CCS_RETRY_DIS - 0
+/// - RESET_CNTS_START_OF_RANK - 0
+/// - LOG_COUNTS_IN_TRACE - 0
+/// - SKIP_INVALID_ADDR_DIMM_DIS - 0
+/// - REFRESH_ONLY_SUBTEST_EN - 0
+/// - REFRESH_ONLY_SUBTEST_TIMEBASE_SEL(0:1) - 0
+/// - RAND_ADDR_ALL_ADDR_MODE_EN - 0
+/// - REF_WAIT_TIME(0:13) - 0
+/// - MCB_LEN64 - 1
+/// - PAUSE_ON_ERROR_MODE(0:1) - don't pause on error
+/// - PAUSE_AFTER_CCS_SUBTEST - don't puase after CCS subtest
+/// - FORCE_PAUSE_AFTER_ADDR - don't pause after current address
+/// - FORCE_PAUSE_AFTER_SUBTEST - no pause after subtest
+/// - ENABLE_SPEC_ATTN - disabled
+/// - ENABLE_HOST_ATTN - disabled
///
-template< fapi2::TargetType T >
+
+template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
class program
{
public:
- // Setup our poll parameters so the CCS executer can see
+ // Setup our poll parameters so the MCBIST executer can see
// whether to use the delays in the instruction stream or not
- program(): iv_poll(0, 0)
- {}
+ program():
+ iv_parameters(0),
+ iv_addr_gen(0),
+ iv_test_type(CENSHMOO), // Used as default in Centaur
+ iv_addr_map0(0),
+ iv_addr_map1(0),
+ iv_addr_map2(0),
+ iv_addr_map3(0),
+ iv_config(0),
+ iv_control(0)
+ {
+ // Enable the maintenance mode addressing
+ change_maint_address_mode(mss::ON);
+
+ // Enable 64b lengths, required in maint mode.
+ change_len64(mss::ON);
+
+ // Turn on counting mode for all address configs
+ iv_addr_gen.insertFromRight<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(0b1111);
+ }
+
+ ///
+ /// @brief Change the mcbist 64/128 bit control
+ /// @param[in] i_state, mss::ON if you want 64b,mss::OFF if you want 128b
+ /// @return void
+ ///
+ inline void change_len64( const mss::states i_state )
+ {
+ iv_config.writeBit<TT::CFG_MCB_LEN64>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist min command gap
+ /// @param[in] i_gap minimum number of cycles between commands when cfg_en_randcmd_gap is a 0 (disabled)
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_cmd_gap( const uint64_t i_gap )
+ {
+ iv_parameters.insertFromRight<TT::MIN_CMD_GAP, TT::MIN_CMD_GAP_LEN>(i_gap);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist gap timebase
+ /// @param[in] i_tb When set to mss::ON and cfg_en_randcmd_gap is a 0, then the number of minimum
+ /// cycles between commands will be cfg_min_cmd_gap multiplied by 2^13.
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_gap_timebase( const bool i_tb )
+ {
+ iv_parameters.writeBit<TT::MIN_GAP_TIMEBASE>(i_tb);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist min command gap blind steer
+ /// @param[in] i_gap min gap between commands when doing steering
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_cmd_gap_blind_steer( const uint64_t i_gap )
+ {
+ iv_parameters.insertFromRight<TT::MIN_CMD_GAP_BLIND_STEER, TT::MIN_CMD_GAP_BLIND_STEER_LEN>(i_gap);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist gap timebase for blind steer
+ /// @param[in] i_program, the program in question
+ /// @param[in] i_tb When set to mss::ON and cfg_en_randcmd_gap is a 0, then the number of minimum
+ /// cycles between commands will be cfg_min_cmd_gap multiplied by 2^13.
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_gap_timebase_blind_steer( const bool i_tb )
+ {
+ iv_parameters.writeBit<TT::MIN_GAP_TIMEBASE_BLIND_STEER>(i_tb);
+ return;
+ }
+
+ ///
+ /// @brief Change the weights for random mcbist reads, writes
+ /// @param[in] i_weight
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_randcmd_wgt( const uint64_t i_weight )
+ {
+ iv_parameters.insertFromRight<TT::RANDCMD_WGT, TT::RANDCMD_WGT_LEN>(i_weight);
+ return;
+ }
+
+ ///
+ /// @brief Change the weights for random mcbist command gaps
+ /// @param[in] i_program, the program in question
+ /// @param[in] i_weight
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_randgap_wgt( const uint64_t i_weight )
+ {
+ iv_parameters.insertFromRight<TT::RANDGAP_WGT, TT::RANDGAP_WGT_LEN>(i_weight);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable mcbist clock monitoring
+ /// @param[in] i_monitor mss::ON to monitor
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_clock_monitor_en( const bool i_monitor )
+ {
+ iv_parameters.writeBit<TT::CLOCK_MONITOR_EN>(i_monitor);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable mcbist random command gaps
+ /// @param[in] i_rndgap mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_en_randcmd_gap( const bool i_rndgap )
+ {
+ iv_parameters.writeBit<TT::EN_RANDCMD_GAP>(i_rndgap);
+ return;
+ }
- // Vector of subtests
+ ///
+ /// @brief Enable or disable mcbist BC4 support
+ /// @param[in] i_bc4 mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_bc4_en( const bool i_bc4 )
+ {
+ iv_parameters.writeBit<TT::BC4_EN>(i_bc4);
+ return;
+ }
+
+ ///
+ /// @brief Change fixed width address generator config
+ /// @param[in] i_width
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_fixed_width( const uint64_t i_width )
+ {
+ iv_addr_gen.insertFromRight<TT::FIXED_WIDTH, TT::FIXED_WIDTH_LEN>(i_width);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 0
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode0( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ l_value.writeBit<0>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 1
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode1( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ l_value.writeBit<1>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 2
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode2( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ l_value.writeBit<2>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 3
+ /// @param[in] i_program, the program in question
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode3( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ l_value.writeBit<3>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+
+ ///
+ /// @brief Enable or disable maint address mode
+ /// @param[in] i_program, the program in question
+ /// @param[in] i_mode mss::ON to enable
+ /// @warn Address counter modes must be 0 for this to work.
+ /// @note When enabled subtest complement bits become 3-bit port-dimm selector field
+ /// (Note: when turning this off, make sure you clear or reprogram complement bits)
+ /// @return void
+ ///
+ inline void change_maint_address_mode( const bool i_mode )
+ {
+ iv_addr_gen.writeBit<TT::MAINT_ADDR_MODE_EN>(i_mode);
+ return;
+ }
+
+
+ ///
+ /// @brief Enable or disable broadcast mode
+ /// @param[in] i_program, the program in question
+ /// @param[in] i_mode mss::ON to enable
+ /// @warn Maint address mode must be enabled for this to work
+ /// @return void
+ ///
+ inline void change_maint_broadcast_mode( const bool i_mode )
+ {
+ iv_addr_gen.writeBit<TT::MAINT_BROADCAST_MODE_EN>(i_mode);
+ return;
+ }
+
+
+ ///
+ /// @brief Enable or disable slave rank boundary detect
+ /// @param[in] i_program, the program in question
+ /// @param[in] i_mode mss::ON to enable
+ /// @return void
+ ///
+ inline void change_srank_boundaries( const bool i_mode )
+ {
+ iv_addr_gen.writeBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>(i_mode);
+ return;
+ }
+
+ ///
+ /// @brief Select the port(s) to be used by the MCBIST
+ /// @param[in] i_ports uint64_t representing the ports. Multiple bits set imply broadcast
+ /// i_ports is a right-aligned uint64_t, of which only the right-most 4 bits are used. The register
+ /// field is defined such that the left-most bit in the field represents port 0, the right most
+ /// bit in the field represents port 3. So, to run on port 0, i_ports should be 0b1000. 0b0001
+ /// (or 0x1) is port 3 - not port 0
+ /// @param[in] i_wait_time representing the sync wait time for broadcast operations (optional)
+ /// @return void
+ /// @note If multiple bits are set, the MCBIST will be configured for broadcast mode.
+ /// This implies all subtests are individual reads/writes. Uses i_wait parameter.
+ /// @note i_wait is the number of 1024 2:1 cycle timebases to wait starting up MCBIST for SRQ's to get
+ /// synchornized for broadcast mode (ranges 0-127).
+ ///
+ inline void select_ports( const uint64_t i_ports, const uint64_t i_wait = 0)
+ {
+ fapi2::buffer<uint64_t> l_data;
+ fapi2::buffer<uint64_t> l_ports;
+
+ if (0 == i_ports)
+ {
+ FAPI_DBG("no ports selected for mcbist");
+ return;
+ }
+
+ if (1 != mss::bit_count(i_ports))
+ {
+ // We're in broadcast mode, so setup the broadcast inforamtion registers
+ FAPI_INF("mcbist select ports seeing broadcast requested: ports 0x%x", i_ports);
+ iv_config.setBit<TT::SYNC_EN>();
+ iv_config.insertFromRight<TT::SYNC_WAIT, TT::SYNC_WAIT_LEN>(i_wait);
+
+ // Should we check for maint mode and set the MCBAGRAQ_CFG_MAINT_BROADCAST_MODE_EN? BRS
+ }
+
+ iv_control.insertFromRight<TT::PORT_SEL, TT::PORT_SEL_LEN>(i_ports);
+ FAPI_DBG("mcbist select ports: 0x%016lx (0x%x)", iv_control, i_ports);
+
+ return;
+ }
+
+ // Vector of subtests. Note the MCBIST subtests are spread across
+ // 8 registers - 4 subtests fit in one 64b register
+ // (16 bits/test, 4 x 16 == 64, 4x8 = 32 subtests)
+ // We keep a vector of 16 bit subtests here, and we program the
+ // MCBIST engine (i.e., spread the subtests over the 8 registers)
+ // when we're told to execute the program.
std::vector< subtest_t<T> > iv_subtests;
+
+ // Place to hold the value of the MCBIST Memory Parameter Register. We'll scom
+ // it when we execute the program.
+ fapi2::buffer<uint64_t> iv_parameters;
+
+ // Place to hold the value of the MCBIST Address Generation Config. We'll scom
+ // it when we execute the program.
+ fapi2::buffer<uint64_t> iv_addr_gen;
+
+ test_type iv_test_type;
+
poll_parameters iv_poll;
+
+ // Address Map Registers
+ // We might want to refactor to a vector ... BRS
+ uint64_t iv_addr_map0;
+ uint64_t iv_addr_map1;
+ uint64_t iv_addr_map2;
+ uint64_t iv_addr_map3;
+
+ // Config register
+ fapi2::buffer<uint64_t> iv_config;
+
+ // Control register
+ fapi2::buffer<uint64_t> iv_control;
};
///
-/// @brief Complement the data for the first subcommand
+/// @brief Load the mcbist config register
/// @tparam T fapi2::TargetType of the MCBIST engine
/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_state the desired state of the function
-/// @return void
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_compliment_1st_cmd( subtest_t<T>& io_subtest, const mss::states i_state )
+inline fapi2::ReturnCode load_config( const fapi2::Target<T>& i_target, const mcbist::program<T>& i_program )
{
- io_subtest.iv_mcbmr.template writeBit<TT::COMPL_1ST_CMD>(i_state);
- return;
+ FAPI_DBG("loading MCBIST Config 0x%016lx", i_program.iv_config);
+ return mss::putScom(i_target, TT::CFGQ_REG, i_program.iv_config);
}
+
///
-/// @brief Complement the data for the second subcommand
-/// @tparam T fapi2::TargetType of the MCBIST engine
-/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_state the desired state of the function
-/// @return void
+/// @brief Load the mcbist control register
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_compliment_2nd_cmd( subtest_t<T>& io_subtest, const mss::states i_state )
+inline fapi2::ReturnCode load_control( const fapi2::Target<T>& i_target, const mcbist::program<T>& i_program )
{
- io_subtest.iv_mcbmr.template writeBit<TT::COMPL_2ND_CMD>(i_state);
- return;
+ FAPI_DBG("loading MCBIST Control 0x%016lx", i_program.iv_control);
+ return mss::putScom(i_target, TT::CFGQ_REG, i_program.iv_control);
}
+
///
-/// @brief Complement the data for the third subcommand
-/// @tparam T fapi2::TargetType of the MCBIST engine
-/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_state the desired state of the function
-/// @return void
+/// @brief Load the address generator config
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_compliment_3rd_cmd( subtest_t<T>& io_subtest, const mss::states i_state )
+inline fapi2::ReturnCode load_addr_gen( const fapi2::Target<T>& i_target, const mcbist::program<T>& i_program )
{
- io_subtest.iv_mcbmr.template writeBit<TT::COMPL_3RD_CMD>(i_state);
- return;
+ FAPI_DBG("loading MCBIST Address Generation 0x%016lx", i_program.iv_addr_gen);
+ return mss::putScom(i_target, TT::MCBAGRAQ_REG, i_program.iv_addr_gen);
}
///
-/// @brief Generate addresses in reverse order
-/// @tparam T fapi2::TargetType of the MCBIST engine
-/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_state the desired state of the function
-/// @return void
+/// @brief Configure address range 0
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+/// @warn if address counting mode is enabled in the MCBIST program, these bits are start, len
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_addr_rev_mode( subtest_t<T>& io_subtest, const mss::states i_state )
+inline fapi2::ReturnCode config_address_range0( const fapi2::Target<T>& i_target, const uint64_t i_start,
+ const uint64_t i_end )
{
- io_subtest.iv_mcbmr.template writeBit<TT::ADDR_REV_MODE>(i_state);
- return;
+ FAPI_DBG("config MCBIST address range 0 start: 0x%016lx (0x%016lx), end/len 0x%016lx (0x%016lx)",
+ i_start, (i_start << 26), i_end, (i_end << 26));
+ FAPI_TRY( mss::putScom(i_target, TT::START_ADDRESS_0, i_start << 26) );
+ FAPI_TRY( mss::putScom(i_target, TT::END_ADDRESS_0, i_end << 26) );
+
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Generate addresses in random order
-/// @tparam T fapi2::TargetType of the MCBIST engine
-/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_state the desired state of the function
-/// @return void
+/// @brief Configure address range 1
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+/// @warn if address counting mode is enabled in the MCBIST program, these bits are start, len
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_addr_rand_mode( subtest_t<T>& io_subtest, const mss::states i_state )
+inline fapi2::ReturnCode config_address_range1( const fapi2::Target<T>& i_target, const uint64_t i_start,
+ const uint64_t i_end )
{
- io_subtest.iv_mcbmr.template writeBit<TT::ADDR_RAND_MODE>(i_state);
- return;
+ FAPI_DBG("config MCBIST address range 1 start: 0x%016lx (0x%016lx), end/len 0x%016lx (0x%016lx)",
+ i_start, (i_start << 26), i_end, (i_end << 26));
+ FAPI_TRY( mss::putScom(i_target, TT::START_ADDRESS_1, i_start << 26) );
+ FAPI_TRY( mss::putScom(i_target, TT::END_ADDRESS_1, i_end << 26) );
+
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Generate and check data with ECC
-/// @tparam T fapi2::TargetType of the MCBIST engine
-/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_state the desired state of the function
-/// @return void
+/// @brief Configure address range 2
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+/// @warn if address counting mode is enabled in the MCBIST program, these bits are start, len
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_ecc_mode( subtest_t<T>& io_subtest, const mss::states i_state )
+inline fapi2::ReturnCode config_address_range2( const fapi2::Target<T>& i_target, const uint64_t i_start,
+ const uint64_t i_end )
{
- io_subtest.iv_mcbmr.template writeBit<TT::ECC_MODE>(i_state);
- return;
+ FAPI_DBG("config MCBIST address range 2 start: 0x%016lx (0x%016lx), end/len 0x%016lx (0x%016lx)",
+ i_start, (i_start << 26), i_end, (i_end << 26));
+ FAPI_TRY( mss::putScom(i_target, TT::START_ADDRESS_2, i_start << 26) );
+ FAPI_TRY( mss::putScom(i_target, TT::END_ADDRESS_2, i_end << 26) );
+
+fapi_try_exit:
+ return fapi2::current_err;
}
+
///
-/// @brief Set the data mode for this subtest
-/// @tparam T fapi2::TargetType of the MCBIST engine
-/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_mode the desired mcbist::data_mode
-/// @return void
+/// @brief Configure address range 3
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_data_mode( subtest_t<T>& io_subtest, const data_mode i_mode )
+inline fapi2::ReturnCode config_address_range3( const fapi2::Target<T>& i_target, const uint64_t i_start,
+ const uint64_t i_end )
{
- io_subtest.iv_mcbmr.template insertFromRight<TT::DATA_MODE, TT::DATA_MODE_LEN>(i_mode);
- return;
+ FAPI_DBG("config MCBIST address range 3 start: 0x%016lx (0x%016lx), end/len 0x%016lx (0x%016lx)",
+ i_start, (i_start << 26), i_end, (i_end << 26));
+ FAPI_TRY( mss::putScom(i_target, TT::START_ADDRESS_3, i_start << 26) );
+ FAPI_TRY( mss::putScom(i_target, TT::END_ADDRESS_3, i_end << 26) );
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
-/// @brief Configure which address registers to use for this subtest
-/// @tparam T fapi2::TargetType of the MCBIST engine
-/// @tparam TT the mssTraits associtated with T
-/// @param[in,out] io_subtest a subtest
-/// @param[in] i_index 0 = MCBSA0Q, 1 = MCBSA1Q, ...
-/// @note wraps to 0-3 no matter what value you pass in.
-/// @return void
+/// @brief Start or stop the MCBIST engine
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start_stop bool START for starting, STOP otherwise
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
///
template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
-void change_addr_sel( subtest_t<T>& io_subtest, const uint16_t i_index )
+inline fapi2::ReturnCode start_stop( const fapi2::Target<T>& i_target, bool i_start_stop )
{
- // Roll the index around - tidy support for an index which is out of range.
- static const uint16_t MAX_ADDRESS_START_END_REGISTERS = 3 + 1;
- io_subtest.iv_mcbmr.template insertFromRight<TT::ADDR_SEL, TT::ADDR_SEL_LEN>(i_index % MAX_ADDRESS_START_END_REGISTERS);
- return;
+ // This is the same as the CCS start_stop ... perhaps we need one template for all
+ // 'engine' control functions? BRS
+ fapi2::buffer<uint64_t> l_buf;
+ FAPI_TRY(mss::getScom(i_target, TT::CNTLQ_REG, l_buf));
+
+ FAPI_TRY( mss::putScom(i_target, TT::CNTLQ_REG,
+ i_start_stop ? l_buf.setBit<TT::MCBIST_START>() : l_buf.setBit<TT::MCBIST_STOP>()) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Execute the mcbist program
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist program to execute
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode execute( const fapi2::Target<T>& i_target, const program<T>& i_program );
+
+///
+/// @brief Load a set of MCBIST subtests in to the MCBIST registers
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
+fapi2::ReturnCode load_mcbmr( const fapi2::Target<T>& i_target, const mcbist::program<T>& i_program );
+
+
+///
+/// @brief Load a set of MCBIST address map registers
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
+fapi2::ReturnCode load_mcbamr( const fapi2::Target<T>& i_target, const mcbist::program<T>& i_program )
+{
+ // Vector? Can decide when we fully understand the methods to twiddle the maps themselves. BRS
+ FAPI_DBG("load MCBIST address map register 0: 0x%016lx", i_program.iv_addr_map0);
+ FAPI_TRY( mss::putScom(i_target, TT::MCBAMR0A0Q_REG, i_program.iv_addr_map0) );
+
+ FAPI_DBG("load MCBIST address map register 1: 0x%016lx", i_program.iv_addr_map1);
+ FAPI_TRY( mss::putScom(i_target, TT::MCBAMR1A0Q_REG, i_program.iv_addr_map1) );
+
+ FAPI_DBG("load MCBIST address map register 2: 0x%016lx", i_program.iv_addr_map2);
+ FAPI_TRY( mss::putScom(i_target, TT::MCBAMR1A0Q_REG, i_program.iv_addr_map2) );
+
+ FAPI_DBG("load MCBIST address map register 3: 0x%016lx", i_program.iv_addr_map3);
+ FAPI_TRY( mss::putScom(i_target, TT::MCBAMR1A0Q_REG, i_program.iv_addr_map3) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Load MCBIST Memory Parameter Register
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = mcbistTraits<T> >
+inline fapi2::ReturnCode load_mcbparm( const fapi2::Target<T>& i_target, const mcbist::program<T>& i_program )
+{
+ FAPI_DBG("load MCBIST parameter register: 0x%016lx", i_program.iv_parameters);
+ return mss::putScom(i_target, TT::MCBPARMQ_REG, i_program.iv_parameters);
}
} // namespace
+
} // namespace
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss.H
index a55f6f6c2..41bd9b34a 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mss.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss.H
@@ -7,7 +7,7 @@
/* */
/* EKB Project */
/* */
-/* COPYRIGHT 2015 */
+/* COPYRIGHT 2015,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -51,6 +51,7 @@
#include "utils/dump_regs.H"
#include "ccs/ccs.H"
+#include "mcbist/mcbist.H"
#include "port/port.H"
@@ -58,9 +59,14 @@
#include "dimm/rcd_load.H"
#include "dimm/mrs_load.H"
#include "dimm/rank.H"
+#include "dimm/kind.H"
#include "phy/ddr_phy.H"
#include "phy/dp16.H"
#include "phy/cal_timers.H"
+#include "utils/dump_regs.H"
+
+#include "mc/mc.H"
+
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
index b6b8c25aa..cf2c5a142 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
@@ -7,7 +7,7 @@
/* */
/* EKB Project */
/* */
-/* COPYRIGHT 2015 */
+/* COPYRIGHT 2015,2016 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -98,6 +98,10 @@ enum states
OFF = 0,
ON_N = 0,
OFF_N = 1,
+ YES = 1,
+ NO = 0,
+ YES_N = 0,
+ NO_N = 1,
INVALID = 0xFF,
// This needs to be an attribute I think - BRS. Used as a boolean.
@@ -134,6 +138,86 @@ enum data_mode
ROTATE_LEFT_MODE = 0b110,
ROTATE_RIGHT_MODE = 0b111,
};
+
+// 0:3 Operation Type
+enum op_type
+{
+ WRITE = 0b0000, // fast, with no concurrent traffic
+ READ = 0b0001, // fast, with no concurrent traffic
+ READ_WRITE = 0b0010,
+ WRITE_READ = 0b0011,
+ READ_WRITE_READ = 0b0100,
+ READ_WRITE_WRITE = 0b0101,
+ RAND_SEQ = 0b0110,
+ READ_READ_WRITE = 0b1000,
+ SCRUB_RRWR = 0b1001,
+ STEER_RW = 0b1010,
+ ALTER = 0b1011, // (W)
+ DISPLAY = 0b1100, // (R, slow)
+ CCS_EXECUTE = 0b1111,
+
+ // if bits 9:11 (Data Mode bits) = 000 (bits 4:8 used to specify which subtest to go to)
+ // Refresh only cmd if bits 9:11 (Data Mode bits) /= 000
+ GOTO_SUBTEST_N = 0b0111,
+};
+
+enum test_type
+{
+ USER_MODE = 0,
+ CENSHMOO = 1,
+ SUREFAIL = 2,
+ MEMWRITE = 3,
+ MEMREAD = 4,
+ CBR_REFRESH = 5,
+ MCBIST_SHORT = 6,
+ SHORT_SEQ = 7,
+ DELTA_I = 8,
+ DELTA_I_LOOP = 9,
+ SHORT_RAND = 10,
+ LONG1 = 11,
+ BUS_TAT = 12,
+ SIMPLE_FIX = 13,
+ SIMPLE_RAND = 14,
+ SIMPLE_RAND_2W = 15,
+ SIMPLE_RAND_FIXD = 16,
+ SIMPLE_RA_RD_WR = 17,
+ SIMPLE_RA_RD_R = 18,
+ SIMPLE_RA_FD_R = 19,
+ SIMPLE_RA_FD_R_INF = 20,
+ SIMPLE_SA_FD_R = 21,
+ SIMPLE_RA_FD_W = 22,
+ INFINITE = 23,
+ WR_ONLY = 24,
+ W_ONLY = 25,
+ R_ONLY = 26,
+ W_ONLY_RAND = 27,
+ R_ONLY_RAND = 28,
+ R_ONLY_MULTI = 29,
+ SHORT = 30,
+ SIMPLE_RAND_BARI = 31,
+ W_R_INFINITE = 32,
+ W_R_RAND_INFINITE = 33,
+ R_INFINITE1 = 34,
+ R_INFINITE_RF = 35,
+ MARCH = 36,
+ SIMPLE_FIX_RF = 37,
+ SHMOO_STRESS = 38,
+ SIMPLE_RAND_RA = 39,
+ SIMPLE_FIX_RA = 40,
+ SIMPLE_FIX_RF_RA = 41,
+ TEST_RR = 42,
+ TEST_RF = 43,
+ W_ONLY_INFINITE_RAND = 44,
+ MCB_2D_CUP_SEQ = 45,
+ MCB_2D_CUP_RAND = 46,
+ SHMOO_STRESS_INFINITE = 47,
+ HYNIX_1_COL = 48,
+ RMWFIX = 49,
+ RMWFIX_I = 50,
+ W_INFINITE = 51,
+ R_INFINITE = 52,
+};
+
} // namespace mcbist
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
index 7fd1079d1..c39ebf057 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
@@ -66,7 +66,7 @@ inline uint64_t mhz_to_ps(const uint64_t i_mhz)
return FREQ_TO_PS[FREQ_2400];
default:
- FAPI_ERR("unsupported frequency %d", i_mhz);
+ FAPI_ERR("unsupported frequency %llu", i_mhz);
fapi2::Assert(false);
// Keeps compiler happy
OpenPOWER on IntegriCloud