From 3a11ab737feeb6695f949f355f41081e64dec2f5 Mon Sep 17 00:00:00 2001 From: Brian Silver Date: Thu, 7 Jan 2016 14:35:20 -0600 Subject: 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 Reviewed-by: Andre A. Marin Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22768 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell --- .../chips/p9/procedures/hwp/memory/lib/dimm/kind.H | 85 ++ .../chips/p9/procedures/hwp/memory/lib/mc/mc.C | 133 ++- .../chips/p9/procedures/hwp/memory/lib/mc/mc.H | 2 +- .../chips/p9/procedures/hwp/memory/lib/mc/xlate.C | 214 +++++ .../p9/procedures/hwp/memory/lib/mcbist/mcbist.C | 171 +++- .../p9/procedures/hwp/memory/lib/mcbist/mcbist.H | 940 +++++++++++++++++++-- .../chips/p9/procedures/hwp/memory/lib/mss.H | 8 +- .../procedures/hwp/memory/lib/shared/mss_const.H | 86 +- .../procedures/hwp/memory/lib/utils/conversions.H | 2 +- 9 files changed, 1557 insertions(+), 84 deletions(-) create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H create mode 100644 src/import/chips/p9/procedures/hwp/memory/lib/mc/xlate.C 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 +// *HWP HWP Backup: Craig Hamilton +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_DIMM_H_ +#define _MSS_DIMM_H_ + +#include + +#include +#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& 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 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 - #include #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::xlate0_reg[] = {MCS_PORT02_MCP0XLT0, MCS_PORT13_MCP0XLT0}; +const uint64_t mcTraits::xlate1_reg[] = {MCS_PORT02_MCP0XLT1, MCS_PORT13_MCP0XLT1}; +const uint64_t mcTraits::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::scominit(const fapi2::Target& 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 l_data; + + l_data.setBit(); + 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 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(l_throttle_per_slot); + l_data.insertFromRight(l_throttle_per_port); + l_data.insertFromRight(l_throttle_denominator); + l_data.insertFromRight(l_ras_weight); + l_data.insertFromRight(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 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(l_throttle_denominator); + l_data.insertFromRight(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 +// *HWP HWP Backup: Andre Marin +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include + +#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::setup_xlate_map(const fapi2::Target& i_target) +{ + fapi2::buffer l_xlate; + fapi2::buffer l_xlate1; + fapi2::buffer l_xlate2; + + const auto l_dimms = i_target.getChildren(); + + 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(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(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(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(0b00101); + l_xlate.insertFromRight(0b00110); + + // Drop down the column assignments + l_xlate1.insertFromRight(0b01101); + + l_xlate1.insertFromRight(0b01100); + + l_xlate1.insertFromRight(0b01011); + + l_xlate1.insertFromRight(0b01010); + + l_xlate2.insertFromRight(0b01001); + + l_xlate2.insertFromRight(0b00111); + + l_xlate2.insertFromRight(0b01110); + + l_xlate2.insertFromRight(0b10000); + + l_xlate2.insertFromRight(0b10001); + + l_xlate2.insertFromRight(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(), MCS_0_PORT02_MCP0XLT0, l_xlate) ); + FAPI_TRY( mss::putScom(i_target.getParent(), MCS_0_PORT02_MCP0XLT1, l_xlate1) ); + FAPI_TRY( mss::putScom(i_target.getParent(), 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 #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& i_target, + const mcbist::program& 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().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& i_target, + const program& i_program ) +{ + typedef mcbistTraits TT; + + static const uint64_t l_done = fapi2::buffer().setBit(); + static const uint64_t l_fail = fapi2::buffer().setBit(); + + fapi2::buffer 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& stat_reg) -> bool + { + FAPI_DBG("mcbist statq 0x%llx, remaining: %d", stat_reg, poll_remaining); + l_status = stat_reg; + return l_status.getBit() != 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 . 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& 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 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 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 > 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(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(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(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(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(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(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(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(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(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(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(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(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& 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. @@ -106,150 +345,695 @@ class subtest_t fapi2::buffer iv_mcbmr; }; +/// +/// @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 > +inline subtest_t write_subtest() +{ + // Starts life full of 0's + subtest_t l_subtest; + + // 0:3 = 0000 - we want subtest type to be a Write (W) + l_subtest.iv_mcbmr.template insertFromRight(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 > +inline subtest_t read_subtest() +{ + // Starts life full of 0's + subtest_t l_subtest; + + // 0:3 = 0001 - we want subtest type to be a Read (R) + l_subtest.iv_mcbmr.template insertFromRight(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 > 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(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(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(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(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(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(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(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(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(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(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(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(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 l_value; + iv_addr_gen.extract(l_value); + l_value.writeBit<0>(i_mode); + iv_addr_gen.insert(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 l_value; + iv_addr_gen.extract(l_value); + l_value.writeBit<1>(i_mode); + iv_addr_gen.insert(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 l_value; + iv_addr_gen.extract(l_value); + l_value.writeBit<2>(i_mode); + iv_addr_gen.insert(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 l_value; + iv_addr_gen.extract(l_value); + l_value.writeBit<3>(i_mode); + iv_addr_gen.insert(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(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(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(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 l_data; + fapi2::buffer 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(); + iv_config.insertFromRight(i_wait); + + // Should we check for maint mode and set the MCBAGRAQ_CFG_MAINT_BROADCAST_MODE_EN? BRS + } + + iv_control.insertFromRight(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 > iv_subtests; + + // Place to hold the value of the MCBIST Memory Parameter Register. We'll scom + // it when we execute the program. + fapi2::buffer iv_parameters; + + // Place to hold the value of the MCBIST Address Generation Config. We'll scom + // it when we execute the program. + fapi2::buffer 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 iv_config; + + // Control register + fapi2::buffer 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 > -void change_compliment_1st_cmd( subtest_t& io_subtest, const mss::states i_state ) +inline fapi2::ReturnCode load_config( const fapi2::Target& i_target, const mcbist::program& i_program ) { - io_subtest.iv_mcbmr.template writeBit(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 > -void change_compliment_2nd_cmd( subtest_t& io_subtest, const mss::states i_state ) +inline fapi2::ReturnCode load_control( const fapi2::Target& i_target, const mcbist::program& i_program ) { - io_subtest.iv_mcbmr.template writeBit(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 > -void change_compliment_3rd_cmd( subtest_t& io_subtest, const mss::states i_state ) +inline fapi2::ReturnCode load_addr_gen( const fapi2::Target& i_target, const mcbist::program& i_program ) { - io_subtest.iv_mcbmr.template writeBit(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 > -void change_addr_rev_mode( subtest_t& io_subtest, const mss::states i_state ) +inline fapi2::ReturnCode config_address_range0( const fapi2::Target& i_target, const uint64_t i_start, + const uint64_t i_end ) { - io_subtest.iv_mcbmr.template writeBit(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 > -void change_addr_rand_mode( subtest_t& io_subtest, const mss::states i_state ) +inline fapi2::ReturnCode config_address_range1( const fapi2::Target& i_target, const uint64_t i_start, + const uint64_t i_end ) { - io_subtest.iv_mcbmr.template writeBit(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 > -void change_ecc_mode( subtest_t& io_subtest, const mss::states i_state ) +inline fapi2::ReturnCode config_address_range2( const fapi2::Target& i_target, const uint64_t i_start, + const uint64_t i_end ) { - io_subtest.iv_mcbmr.template writeBit(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 > -void change_data_mode( subtest_t& io_subtest, const data_mode i_mode ) +inline fapi2::ReturnCode config_address_range3( const fapi2::Target& i_target, const uint64_t i_start, + const uint64_t i_end ) { - io_subtest.iv_mcbmr.template insertFromRight(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 > -void change_addr_sel( subtest_t& io_subtest, const uint16_t i_index ) +inline fapi2::ReturnCode start_stop( const fapi2::Target& 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(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 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() : l_buf.setBit()) ); + +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& i_target, const program& 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 > +fapi2::ReturnCode load_mcbmr( const fapi2::Target& i_target, const mcbist::program& 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 > +fapi2::ReturnCode load_mcbamr( const fapi2::Target& i_target, const mcbist::program& 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 > +inline fapi2::ReturnCode load_mcbparm( const fapi2::Target& i_target, const mcbist::program& 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 -- cgit v1.2.1