summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuke Mulkey <lwmulkey@us.ibm.com>2017-03-28 12:10:36 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-07-26 00:32:58 -0400
commit2e42018d1251f8e9c0c5f37834b393aee6663ca8 (patch)
tree9907363cc68f876b950ed478ce0d7ad73c5b410a
parentf89f707930c5bc4ae761030dec463c4664225a9a (diff)
downloadtalos-hostboot-2e42018d1251f8e9c0c5f37834b393aee6663ca8.tar.gz
talos-hostboot-2e42018d1251f8e9c0c5f37834b393aee6663ca8.zip
p9c_mss_draminit_training_advanced and APIs
Change-Id: Ia2f4915cd68f0c3e23aa7d2e20df85802cf6daad Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39445 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@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/43547 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/fapiTestHwpDq.H56
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H57
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_access_delay_reg.C20
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.C2367
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.H200
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.mk30
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C2
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk2
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.C44
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.H2
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.mk1
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.C1812
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.H194
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.mk39
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.C4591
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.H414
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.mk31
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.C845
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.H443
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.mk31
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.C934
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.H98
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.mk31
-rw-r--r--src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.C2583
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.mk31
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.C2
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.H2
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_shmoo_common.H107
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.C1430
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.H402
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.mk31
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H2
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.C262
-rwxr-xr-xsrc/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.mk29
34 files changed, 17074 insertions, 51 deletions
diff --git a/src/import/chips/centaur/procedures/hwp/memory/fapiTestHwpDq.H b/src/import/chips/centaur/procedures/hwp/memory/fapiTestHwpDq.H
new file mode 100644
index 000000000..4324d657e
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/fapiTestHwpDq.H
@@ -0,0 +1,56 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/fapiTestHwpDq.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file fapiTestHwpDq.H
+/// @brief Test Hardware Procedure that exercises the bad DQ data
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+
+#ifndef FAPITESTHWPDQ_H_
+#define FAPITESTHWPDQ_H_
+
+#include <fapi2.H>
+
+typedef fapi2::ReturnCode (*fapi2TestHwpDq_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA>&);
+
+extern "C"
+{
+
+ ///
+ /// @brief Test Hardware Procedure that exercises the bad DQ data
+ /// @param[in] i_mba Reference to MBA chiplet
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode fapi2TestHwpDq(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_mba);
+
+}
+
+#endif
diff --git a/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H b/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H
index 00b4e462e..36219296a 100644
--- a/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H
+++ b/src/import/chips/centaur/procedures/hwp/memory/lib/shared/dimmConsts.H
@@ -46,8 +46,13 @@ enum consts : size_t
NUM_RANK_GROUPS = 4, ///< Maximum number of rank groups
MAX_RANKS_PER_PORT = 8, ///< Maximum number of ranks on a port
DIMM_DQ_RANK_BITMAP_SIZE = 10, ///< Size in bytes of the Bad DQ bitmap for a rank.
+
+ BITS_PER_BYTE = 8,
+ BITS_PER_NIBBLE = 4,
+ MAX_NIBBLES_PER_BYTE = 2,
+
// This is the number of bits in DIMM_DQ_RANK_BITMAP_SIZE.
- DIMM_DQ_NUM_DQS = DIMM_DQ_RANK_BITMAP_SIZE * 8, ///< Number of DQs (data query pins).
+ DIMM_DQ_NUM_DQS = DIMM_DQ_RANK_BITMAP_SIZE * BITS_PER_BYTE, ///< Number of DQs (data query pins).
// This must be big enough to contain the bitmap for each rank
// (MAX_RANKS_PER_DIMM * DIMM_DQ_RANK_BITMAP_SIZE), plus the header
@@ -58,8 +63,9 @@ enum consts : size_t
DIMM_TO_C4_DQ_ENTRIES = 80, ///< Number of entries in the DQ attribute
DIMM_TO_C4_DQS_ENTRIES = 20, ///< Number of entries in the DQS attribute
- ISDIMM_MAX_DQ_72 = 72, ///< Number of DQ pins on an ISDIMM
- ISDIMM_MAX_DQS_18 = 18, ///< Number of DQS pins on an ISDIMM
+ ISDIMM_MAX_DQ_72 = 72, ///< Number of DQ pins on ISDIMM
+ ISDIMM_MAX_DQS_18 = 18, ///< Number of DQS pins on ISDIMM
+ CDIMM_MAX_DQ_80 = 80,
MAX_ADDR = 19,
MAX_CMD = 3,
@@ -68,14 +74,41 @@ enum consts : size_t
MAX_DATA_DISABLE = 5,
LANES_PER_BLOCK = 16,
- BITS_PER_BYTE = 8,
MAX_BLOCKS_PER_RANK = 5,
- MAX_NIBBLES_PER_BYTE = 2,
MAX_BYTES_PER_BLOCK = 2,
+ MAX_BYTES_PER_RANK = MAX_BYTES_PER_BLOCK * MAX_BLOCKS_PER_RANK,
+ LANES_PER_PORT = LANES_PER_BLOCK * MAX_BLOCKS_PER_RANK,
DP18_INSTANCES = 5,
BITS_PER_REG = 16,
BITS_PER_PORT = (LANES_PER_BLOCK * DP18_INSTANCES),
+
+};
+
+enum ohm : size_t
+{
+ OHM15 = 15, ///< 15 OHMs
+ OHM20 = 20, ///< 20 OHMs
+ OHM24 = 24, ///< 24 OHMs
+ OHM30 = 30, ///< 30 OHMs
+ OHM34 = 34, ///< 34 OHMs
+ OHM40 = 40, ///< 40 OHMs
+};
+
+enum slew : size_t
+{
+ SLEW_3V_NS = 3, ///< 3V/ns slew
+ SLEW_4V_NS = 4, ///< 4V/ns slew
+ SLEW_5V_NS = 5, ///< 5V/ns slew
+ SLEW_6V_NS = 6, ///< 6V/ns slew
+ SLEW_MAXV_NS = 7, ///< 7V/ns slew
+
+ SLEW_TYPE_DATA = 0, ///< Data line slew enum
+ SLEW_TYPE_ADR_ADDR = 1, ///< Address line slew enum
+ SLEW_TYPE_ADR_CNTL = 2, ///< Control line slew enum
+ SLEW_TYPE_ADR_CLK = 3, ///< Clock line slew enum
+ SLEW_TYPE_ADR_SPCKE = 4, ///< Spare CKE line slew enum
+ MAX_NUM_SLEW_TYPES = 5 ///< Max slew types
};
enum mrs : size_t
@@ -100,17 +133,17 @@ enum dimm_types : size_t
enum mss_ccs_status_query_result
{
- MSS_STAT_QUERY_PASS = 1,
- MSS_STAT_QUERY_IN_PROGRESS = 2,
- MSS_STAT_QUERY_FAIL = 3,
+ MSS_STAT_QUERY_PASS = 1, ///< CCS Pass Enum
+ MSS_STAT_QUERY_IN_PROGRESS = 2, ///< CCS In Progress Enum
+ MSS_STAT_QUERY_FAIL = 3 ///< CCS Fail Enum
};
enum mss_ccs_data_pattern
{
- MSS_CCS_DATA_PATTERN_00 = 1,
- MSS_CCS_DATA_PATTERN_0F = 2,
- MSS_CCS_DATA_PATTERN_F0 = 3,
- MSS_CCS_DATA_PATTERN_FF = 4
+ MSS_CCS_DATA_PATTERN_00 = 1, ///< 00 Pattern Enum
+ MSS_CCS_DATA_PATTERN_0F = 2, ///< 0F Pattern Enum
+ MSS_CCS_DATA_PATTERN_F0 = 3, ///< F0 Pattern Enum
+ MSS_CCS_DATA_PATTERN_FF = 4 ///< FF Pattern Enum
};
constexpr bool MSS_CCS_START = 0;
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_access_delay_reg.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_access_delay_reg.C
index 93a648b96..04ac28c78 100644
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_access_delay_reg.C
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_access_delay_reg.C
@@ -179,18 +179,18 @@ extern "C" {
{
if(l_dimmtype == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
{
- FAPI_ASSERT(i_input_index_u8 <= l_CDIMM_dqmax,
+ FAPI_ASSERT(i_input_index_u8 < CDIMM_MAX_DQ_80,
fapi2::CEN_MSS_ACCESS_DELAY_REG_INVALID_INPUT(),
"CDIMM_DQ: Wrong input index specified (%d, max %d)" ,
- i_input_index_u8, l_CDIMM_dqmax);
+ i_input_index_u8, CDIMM_MAX_DQ_80);
l_type = CDIMM_DQ;
}
else
{
- FAPI_ASSERT(i_input_index_u8 <= l_ISDIMM_dqmax,
+ FAPI_ASSERT(i_input_index_u8 < ISDIMM_MAX_DQ_72,
fapi2::CEN_MSS_ACCESS_DELAY_REG_INVALID_INPUT(),
"ISDIMM_DQ: Wrong input index specified (%d, max %d)",
- i_input_index_u8, l_ISDIMM_dqmax);
+ i_input_index_u8, ISDIMM_MAX_DQ_72);
l_type = ISDIMM_DQ;
}
@@ -218,10 +218,10 @@ extern "C" {
else if(i_input_type_e == RAW_CDIMM_WR_DQ || i_input_type_e == RAW_CDIMM_RD_DQ)
{
- FAPI_ASSERT(i_input_index_u8 <= l_CDIMM_dqmax,
+ FAPI_ASSERT(i_input_index_u8 <= CDIMM_MAX_DQ_80,
fapi2::CEN_MSS_ACCESS_DELAY_REG_INVALID_INPUT(),
"CDIMM_DQ: Wrong input index specified (%d, max %d)" ,
- i_input_index_u8, l_CDIMM_dqmax);
+ i_input_index_u8, CDIMM_MAX_DQ_80);
l_type = CDIMM_DQ;
FAPI_TRY(rosetta_map(i_target_mba, i_port_u8, l_type, i_input_index_u8, i_verbose, l_val));
@@ -3461,20 +3461,20 @@ extern "C" {
if(l_dimmtype == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
{
- FAPI_ASSERT(i_input_index_u8 <= l_CDIMM_dqmax,
+ FAPI_ASSERT(i_input_index_u8 < CDIMM_MAX_DQ_80,
fapi2::CEN_MSS_ACCESS_DELAY_REG_SCHMOO_INVALID_INPUT(),
"CDIMM_DQ: Wrong input index specified (%d, max %d)" ,
- i_input_index_u8, l_CDIMM_dqmax);
+ i_input_index_u8, CDIMM_MAX_DQ_80);
l_type = CDIMM_DQ;
}
else
{
- FAPI_ASSERT(i_input_index_u8 <= l_ISDIMM_dqmax,
+ FAPI_ASSERT(i_input_index_u8 < ISDIMM_MAX_DQ_72,
fapi2::CEN_MSS_ACCESS_DELAY_REG_SCHMOO_INVALID_INPUT(),
"ISDIMM_DQ: Wrong input index specified (%d, max %d)",
- i_input_index_u8, l_ISDIMM_dqmax);
+ i_input_index_u8, ISDIMM_MAX_DQ_72);
l_type = ISDIMM_DQ;
}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.C
new file mode 100755
index 000000000..9974c6c60
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.C
@@ -0,0 +1,2367 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_ddr4_pda.C
+/// @brief Tools for DDR4 DIMMs centaur procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <p9c_mss_ddr4_pda.H>
+#include <p9c_mss_funcs.H>
+#include <p9c_mss_ddr4_funcs.H>
+#include <cen_gen_scom_addresses.H>
+#include <dimmConsts.H>
+#include <p9c_mss_access_delay_reg.H>
+#include <algorithm>
+using namespace std;
+extern "C" {
+ ///
+ /// @brief PDA_Scom_Storage constructor
+ /// @param[in] sa Scom Address
+ /// @param[in] sb Start Bit
+ /// @param[in] nb Num Bits
+ ///
+ PDA_Scom_Storage::PDA_Scom_Storage(const uint64_t sa, const uint32_t sb, const uint32_t nb)
+ {
+ scom_addr = sa;
+ start_bit = sb;
+ num_bits = nb;
+ }
+ PDA_Scom_Storage::~PDA_Scom_Storage() {}
+
+ ///
+ /// @brief PDA_Scom_Storage class constructor
+ /// @param[in] ad Attribute Data
+ /// @param[in] an Attribute Name
+ /// @param[in] dr DRAM
+ /// @param[in] di DIMM
+ /// @param[in] r Rank
+ /// @param[in] p Port
+ ///
+ PDA_MRS_Storage::PDA_MRS_Storage(const uint8_t ad, const uint32_t an, const uint8_t dr, const uint8_t di,
+ const uint8_t r, const uint8_t p)
+ {
+ attribute_data = ad;
+ attribute_name = an;
+ dram = dr;
+ dimm = di;
+ rank = r;
+ port = p;
+ MRS = 0xFF;
+ pda_string[0] = '\0';
+ }
+
+ ///
+ /// @brief Generates the string
+ ///
+ void PDA_MRS_Storage::generatePDAString()
+ {
+ snprintf(pda_string, fapi2::MAX_ECMD_STRING_LEN,
+ "ATTR_CEN_NAME 0x%08x ATTR_CEN_DATA 0x%02x MRS %d P %d DI %d R %d DR %d", attribute_name, attribute_data, MRS, port,
+ dimm, rank, dram);
+ }
+
+ ///
+ /// @brief sends out the string
+ /// @return pda string
+ ///
+ char* PDA_MRS_Storage::c_str()
+ {
+ //generate new string
+ generatePDAString(); //note using a separate function here in case some other function would need to call the generation of the string
+ return pda_string;
+ }
+
+ ///
+ /// @brief Checks to make sure that
+ /// @param[in] i_target MBA target
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode PDA_MRS_Storage::checkPDAValid(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t num_ranks[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t num_spares[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t dram_width = 0;
+ uint8_t num_spare = 0;
+ uint8_t num_dram = 0;
+
+ //checks constants first
+ //ports out of range
+ FAPI_ASSERT(port < MAX_PORTS_PER_MBA,
+ fapi2::CEN_MSS_PDA_DRAM_DNE().
+ set_MBA_TARGET(i_target).
+ set_PORT_VALUE(port).
+ set_DIMM_VALUE(dimm).
+ set_RANK_VALUE(rank).
+ set_DRAM_VALUE(dram),
+ "ERROR!! Port out of valid range! Exiting...");
+
+ //DIMMs out of range
+ FAPI_ASSERT(dimm < MAX_DIMM_PER_PORT,
+ fapi2::CEN_MSS_PDA_DRAM_DNE().
+ set_MBA_TARGET(i_target).
+ set_PORT_VALUE(port).
+ set_DIMM_VALUE(dimm).
+ set_RANK_VALUE(rank).
+ set_DRAM_VALUE(dram),
+ "ERROR!! DIMM out of valid range! Exiting...");
+
+ //now checks based upon attributes
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target, dram_stack));
+
+ //get num master ranks per dimm for 3DS
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, num_ranks));
+ }
+ //get num ranks per dimm for non-3DS
+ else
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target, num_ranks));
+ }
+
+ //no ranks on the selected dimm
+ FAPI_ASSERT(num_ranks[port][dimm] != 0,
+ fapi2::CEN_MSS_PDA_DRAM_DNE().
+ set_MBA_TARGET(i_target).
+ set_PORT_VALUE(port).
+ set_DIMM_VALUE(dimm).
+ set_RANK_VALUE(rank).
+ set_DRAM_VALUE(dram),
+ "ERROR!! DIMM has no valid ranks! Exiting...");
+
+ //rank is out of range
+ FAPI_ASSERT(num_ranks[port][dimm] > rank,
+ fapi2::CEN_MSS_PDA_DRAM_DNE().
+ set_MBA_TARGET(i_target).
+ set_PORT_VALUE(port).
+ set_DIMM_VALUE(dimm).
+ set_RANK_VALUE(rank).
+ set_DRAM_VALUE(dram),
+ "ERROR!! Rank is out of bounds! Exiting...");
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DIMM_SPARE, i_target, num_spares));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, dram_width));
+
+ if(num_spares[port][dimm][rank] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_LOW_NIBBLE)
+ {
+ num_spare = 1;
+ }
+
+ if(num_spares[port][dimm][rank] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_HIGH_NIBBLE)
+ {
+ num_spare = 1;
+ }
+
+ if(num_spares[port][dimm][rank] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_FULL_BYTE
+ && dram_width == fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X4)
+ {
+ num_spare = 2;
+ }
+
+ if(num_spares[port][dimm][rank] == fapi2::ENUM_ATTR_CEN_VPD_DIMM_SPARE_FULL_BYTE
+ && dram_width == fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X8)
+ {
+ num_spare = 1;
+ }
+
+ num_dram = ISDIMM_MAX_DQ_72 / dram_width + num_spare;
+
+ FAPI_ASSERT(num_dram > dram,
+ fapi2::CEN_MSS_PDA_DRAM_DNE().
+ set_MBA_TARGET(i_target).
+ set_PORT_VALUE(port).
+ set_DIMM_VALUE(dimm).
+ set_RANK_VALUE(rank).
+ set_DRAM_VALUE(dram),
+ "ERROR!! DRAM is out of bounds! Exiting...");
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief sets the MRS variable based upon the inputted attribute name
+ /// @param[in] i_target Centaur MBA target
+ /// @return FAPI2_RC_SUCCESS
+ ///
+ fapi2::ReturnCode PDA_MRS_Storage::setMRSbyAttr(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ switch(attribute_name)
+ {
+ //MRS0
+ case fapi2::ATTR_CEN_EFF_DRAM_BL:
+ MRS = MRS0_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_RBT:
+ MRS = MRS0_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_CL:
+ MRS = MRS0_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_TM:
+ MRS = MRS0_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_DLL_RESET:
+ MRS = MRS0_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_WR:
+ MRS = MRS0_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_TRTP:
+ MRS = MRS0_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_DLL_PPD:
+ MRS = MRS0_BA;
+ break;
+
+ //MRS1
+ case fapi2::ATTR_CEN_EFF_DRAM_DLL_ENABLE:
+ MRS = MRS1_BA;
+ break;
+
+ case fapi2::ATTR_CEN_VPD_DRAM_RON:
+ MRS = MRS1_BA;
+ break;
+
+ case fapi2::ATTR_CEN_VPD_DRAM_RTT_NOM:
+ MRS = MRS1_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_AL:
+ MRS = MRS1_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_WR_LVL_ENABLE:
+ MRS = MRS1_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_TDQS:
+ MRS = MRS1_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_OUTPUT_BUFFER:
+ MRS = MRS1_BA;
+ break;
+
+ //MRS2
+ case fapi2::ATTR_CEN_EFF_DRAM_LPASR:
+ MRS = MRS2_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DRAM_CWL:
+ MRS = MRS2_BA;
+ break;
+
+ case fapi2::ATTR_CEN_VPD_DRAM_RTT_WR:
+ MRS = MRS2_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_WRITE_CRC:
+ MRS = MRS2_BA;
+ break;
+
+ //MRS3
+ case fapi2::ATTR_CEN_EFF_MPR_MODE:
+ MRS = MRS3_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_MPR_PAGE:
+ MRS = MRS3_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_GEARDOWN_MODE:
+ MRS = MRS3_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_PER_DRAM_ACCESS:
+ MRS = MRS3_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_TEMP_READOUT:
+ MRS = MRS3_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_FINE_REFRESH_MODE:
+ MRS = MRS3_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_CRC_WR_LATENCY:
+ MRS = MRS3_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_MPR_RD_FORMAT:
+ MRS = MRS3_BA;
+ break;
+
+ //MRS4
+ case fapi2::ATTR_CEN_EFF_MAX_POWERDOWN_MODE:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_TEMP_REF_RANGE:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_TEMP_REF_MODE:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_INT_VREF_MON:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_CS_CMD_LATENCY:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_SELF_REF_ABORT:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_RD_PREAMBLE_TRAIN:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_RD_PREAMBLE:
+ MRS = MRS4_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_WR_PREAMBLE:
+ MRS = MRS4_BA;
+ break;
+
+
+ //MRS5
+ case fapi2::ATTR_CEN_EFF_CA_PARITY_LATENCY :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_CRC_ERROR_CLEAR :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_CA_PARITY_ERROR_STATUS :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_ODT_INPUT_BUFF :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_VPD_DRAM_RTT_PARK :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_CA_PARITY :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_DATA_MASK :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_WRITE_DBI :
+ MRS = MRS5_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_READ_DBI :
+ MRS = MRS5_BA;
+ break;
+
+ //MRS6
+ case fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE:
+ MRS = MRS6_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE:
+ MRS = MRS6_BA;
+ break;
+
+ case fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE:
+ MRS = MRS6_BA;
+ break;
+
+ case fapi2::ATTR_CEN_TCCD_L:
+ MRS = MRS6_BA;
+ break;
+
+ //MRS attribute not found, error out
+ default:
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_PDA_NONMRS_ATTR_NAME().
+ set_NONMRS_ATTR_NAME(attribute_name).
+ set_MBA_TARGET(i_target),
+ "ERROR!! Found attribute name not associated with an MRS! Exiting...");
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }//end setMRSbyAttr
+
+ ///
+ /// @brief PDA_MRS_Storage class destructor
+ ///
+ PDA_MRS_Storage::~PDA_MRS_Storage() {}
+
+ ///
+ /// @brief PDA_MRS_Storage greater than operator
+ /// @param[in] PDA2 - PDA instance
+ /// @return DRAM/port/dimm/rank/mrs/attribute name for A is greater than B return true else false
+ ///
+ bool PDA_MRS_Storage::operator> (const PDA_MRS_Storage& PDA2) const
+ {
+ //check on the DRAM first
+ //DRAM for A is greater than B return true
+ if(dram > PDA2.dram)
+ {
+ return true;
+ }
+ //B > A -> false
+ else if(dram < PDA2.dram)
+ {
+ return false;
+ }
+ //B == A, so go to port
+ //A > B -> true
+ else if(port > PDA2.port)
+ {
+ return true;
+ }
+ //A < B -> false
+ else if(port < PDA2.port)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing dimms
+ //A > B -> true
+ else if(dimm > PDA2.dimm)
+ {
+ return true;
+ }
+ //A < B -> false
+ else if(dimm < PDA2.dimm)
+ {
+ return false;
+ }
+ //dimms are equal, so start comparing ranks
+ //A > B -> true
+ else if(rank > PDA2.rank)
+ {
+ return true;
+ }
+ //A < B -> false
+ else if(rank < PDA2.rank)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing the MRS number
+ //A > B -> true
+ else if(MRS > PDA2.MRS)
+ {
+ return true;
+ }
+ //A < B -> false
+ else if(MRS < PDA2.MRS)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing the attribute_name
+ //A > B -> true
+ else if(attribute_name > PDA2.attribute_name)
+ {
+ return true;
+ }
+ //A < B -> false
+ else if(attribute_name < PDA2.attribute_name)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing the attribute_data
+ //A > B -> true
+ else if(attribute_data > PDA2.attribute_data)
+ {
+ return true;
+ }
+
+ //equal or less than
+ return false;
+ }//end operator>
+
+ ///
+ /// @brief PDA_MRS_Storage less than operator
+ /// @param[in] PDA2 - PDA instance
+ /// @return DRAM/port/dimm/rank/mrs/attribute name for A is less than B return true else false
+ ///
+ bool PDA_MRS_Storage::operator< (const PDA_MRS_Storage& PDA2) const
+ {
+ //check on the DRAM first
+ //DRAM for A is less than B return true
+ if(dram < PDA2.dram)
+ {
+ return true;
+ }
+ //B < A -> false
+ else if(dram > PDA2.dram)
+ {
+ return false;
+ }
+ //B == A, so go to port
+ //A < B -> true
+ else if(port < PDA2.port)
+ {
+ return true;
+ }
+ //A > B -> false
+ else if(port > PDA2.port)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing dimms
+ //A < B -> true
+ else if(dimm < PDA2.dimm)
+ {
+ return true;
+ }
+ //A > B -> false
+ else if(dimm > PDA2.dimm)
+ {
+ return false;
+ }
+ //dimms are equal, so start comparing ranks
+ //A < B -> true
+ else if(rank < PDA2.rank)
+ {
+ return true;
+ }
+ //A > B -> false
+ else if(rank > PDA2.rank)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing the MRS number
+ //A < B -> true
+ else if(MRS < PDA2.MRS)
+ {
+ return true;
+ }
+ //A > B -> false
+ else if(MRS > PDA2.MRS)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing the attribute_name
+ //A < B -> true
+ else if(attribute_name < PDA2.attribute_name)
+ {
+ return true;
+ }
+ //A > B -> false
+ else if(attribute_name > PDA2.attribute_name)
+ {
+ return false;
+ }
+ //ports are equal, so start comparing the attribute_data
+ //A < B -> true
+ else if(attribute_data < PDA2.attribute_data)
+ {
+ return true;
+ }
+
+ //equal or greater than
+ return false;
+ }//end operator<
+
+ ///
+ /// @brief copies one PDA_MRS_Storage to this one
+ /// @param[in] temp MRS storage data structure
+ ///
+ void PDA_MRS_Storage::copy(PDA_MRS_Storage& temp)
+ {
+ attribute_data = temp.attribute_data;
+ attribute_name = temp.attribute_name;
+ MRS = temp.MRS ;
+ dram = temp.dram ;
+ dimm = temp.dimm ;
+ rank = temp.rank ;
+ port = temp.port ;
+ }
+
+ ///
+ /// @brief Checks the passed in PDA vector to ensure that all entries are good. then sorts the vector to ensure more efficient command stream
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in/out] io_pda: Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_checksort_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage>& io_pda)
+ {
+ //does the check to make sure all given attributes are associated with an MRS
+ for(auto& pda : io_pda)
+ {
+ FAPI_TRY(pda.setMRSbyAttr(i_target));
+ FAPI_TRY(pda.checkPDAValid(i_target));
+ }
+
+ //does the sort, sorting by the class comparator (should be DRAM first)
+ sort(io_pda.begin(), io_pda.end());
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+
+ ///
+ /// @brief sets up per-DRAM addressability funcitonality on both ports on the passed MBA
+ /// @param[in] i_target Centaur input mba
+ /// @param[in/out] io_ccs_inst_cnt CCS instance number
+ /// @param[in] i_dimm Centaur dimm to run
+ /// @param[in] i_rank Centaur rank to run
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_setup_pda(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t& io_ccs_inst_cnt,
+ const uint8_t i_dimm,
+ const uint8_t i_rank)
+ {
+ uint32_t l_port_number = 0;
+ uint32_t dimm_number = i_dimm;
+ uint32_t rank_number = i_rank;
+ const uint32_t NUM_POLL = 10;
+ const uint32_t WAIT_TIMER = 1500;
+ uint64_t reg_address = 0;
+ fapi2::buffer<uint64_t> data_buffer;
+ fapi2::variable_buffer address_16(16);
+ fapi2::variable_buffer bank_3(3);
+ fapi2::variable_buffer activate_1(1);
+ fapi2::variable_buffer rasn_1(1);
+ fapi2::variable_buffer casn_1(1);
+ fapi2::variable_buffer wen_1(1);
+ fapi2::variable_buffer cke_4(4);
+ fapi2::variable_buffer csn_8(8);
+ fapi2::variable_buffer odt_4(4);
+ fapi2::variable_buffer ddr_cal_type_4(4);
+ fapi2::variable_buffer num_idles_16(16);
+ fapi2::variable_buffer num_repeat_16(16);
+ fapi2::variable_buffer data_20(20);
+ fapi2::variable_buffer read_compare_1(1);
+ fapi2::variable_buffer rank_cal_4(4);
+ fapi2::variable_buffer ddr_cal_enable_1(1);
+ fapi2::variable_buffer ccs_end_1(1);
+ fapi2::variable_buffer mrs3(16);
+ uint16_t MRS3 = 0;
+ uint8_t num_ranks_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //[port][dimm]
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t dimm_type = 0;
+ uint8_t dram_gen = 0;
+ uint8_t is_sim = 0;
+ uint8_t address_mirror_map[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //address_mirror_map[port][dimm]
+ uint8_t mpr_op = 0; // MPR Op
+ uint8_t mpr_page = 0; // MPR Page Selection - NEW
+ uint8_t geardown_mode = 0; // Gear Down Mode - NEW
+ uint8_t temp_readout = 0; // Temperature sensor readout - NEW
+ uint8_t fine_refresh = 0; // fine refresh mode - NEW
+ uint8_t wr_latency = 0; // write latency for CRC and DM - NEW
+ uint8_t read_format = 0; // MPR READ FORMAT - NEW
+ uint8_t wl_launch_time = 0;
+ uint8_t odt_hold_time = 0;
+ uint8_t post_odt_nop_idle = 0;
+
+ FAPI_TRY(activate_1.setBit(0));
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target, dram_stack));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, i_target, dimm_type));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target, dram_gen));
+
+ //get num master ranks per dimm for 3DS
+ if(dram_stack[i_dimm][i_rank] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, num_ranks_array));
+ }
+ //get num ranks per dimm for non-3DS
+ else
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target, num_ranks_array));
+ }
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), is_sim));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target, address_mirror_map));
+ // WORKAROUNDS
+ FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_CCS_MODEQ, data_buffer));
+ //Setting up CCS mode
+ data_buffer.setBit<51>();
+
+ //if in DDR4 mode, count the parity bit and set it
+ if((dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4) && (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM
+ || dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM) )
+ {
+ FAPI_TRY(data_buffer.insertFromRight( static_cast<uint8_t>(0xff), 61, 1),
+ "mss_ddr4_setup_pda: Error setting up buffers");
+ }
+
+ FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_CCS_MODEQ, data_buffer));
+
+ //loops through port 0 and port 1 on the given MBA
+ for(l_port_number = 0; l_port_number < MAX_PORTS_PER_MBA; l_port_number++)
+ {
+ // Raise CKE high with NOPS, waiting min Reset CKE exit time (tXPR) - 400 cycles
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2));
+ FAPI_TRY(csn_8.clearBit(6, 2));
+ }
+
+ FAPI_TRY(address_16.clearBit(0, 16), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(odt_4.clearBit(0, 4), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(num_idles_16.insertFromRight(static_cast<uint32_t>(400), 0, 16),
+ "mss_ddr4_setup_pda: Error setting up buffers");
+
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+ }
+
+ //Does the RTT_WR to RTT_NOM swapping
+ //loops through all ports
+ for(l_port_number = 0; l_port_number < MAX_PORTS_PER_MBA; l_port_number++)
+ {
+ uint8_t io_dram_rtt_nom_original = 0xff;
+ FAPI_TRY(mss_ddr4_rtt_nom_rtt_wr_swap(i_target, 0, l_port_number, i_rank + i_dimm * 4, 0xFF, io_ccs_inst_cnt,
+ io_dram_rtt_nom_original));
+ io_ccs_inst_cnt = 0;
+ }
+
+
+ //Sets up MRS3 -> the MRS that has PDA
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_MPR_MODE, i_target, mpr_op));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_MPR_PAGE, i_target, mpr_page));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_GEARDOWN_MODE, i_target, geardown_mode));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_TEMP_READOUT, i_target, temp_readout));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_FINE_REFRESH_MODE, i_target, fine_refresh));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CRC_WR_LATENCY, i_target, wr_latency));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_MPR_RD_FORMAT, i_target, read_format));
+
+ //enables PDA mode
+ //loops through all ports
+ for(l_port_number = 0; l_port_number < MAX_PORTS_PER_MBA; l_port_number++)
+ {
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2));
+ FAPI_TRY(csn_8.clearBit(6, 2));
+ }
+
+ FAPI_TRY(csn_8.clearBit(rank_number + 4 * dimm_number));
+
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 0, 1, 7));
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 1, 1, 6));
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 2, 1, 5));
+
+ //sets up MRS3 ecmd buffer
+ FAPI_TRY(mrs3.insert((uint8_t) mpr_page, 0, 2));
+ FAPI_TRY(mrs3.insert((uint8_t) mpr_op, 2, 1));
+ FAPI_TRY(mrs3.insert((uint8_t) geardown_mode, 3, 1));
+ FAPI_TRY(mrs3.insert((uint8_t) 0xff, 4, 1)); //enables PDA mode!!!!
+ FAPI_TRY(mrs3.insert((uint8_t) temp_readout, 5, 1));
+ FAPI_TRY(mrs3.insert((uint8_t) fine_refresh, 6, 3));
+ FAPI_TRY(mrs3.insert((uint8_t) wr_latency, 9, 2));
+ FAPI_TRY(mrs3.insert((uint8_t) read_format, 11, 2));
+ FAPI_TRY(mrs3.insert((uint8_t) 0x00, 13, 2));
+ FAPI_TRY(mrs3.extract(MRS3, 0, 16));
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 24, 0, 16));
+ FAPI_TRY(address_16.insert(mrs3, 0, 16, 0));
+
+ if (( address_mirror_map[l_port_number][dimm_number] & (0x08 >> rank_number) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ //if the DIMM is an R or LR DIMM, then run inverted for the B-Side DRAM
+ if ( (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM)
+ || (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM) )
+ {
+ //reload all MRS values (removes address swizzling)
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2));
+ FAPI_TRY(csn_8.clearBit(6, 2));
+ }
+
+ FAPI_TRY(csn_8.clearBit(rank_number + 4 * dimm_number));
+
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 0, 1, 7), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 1, 1, 6), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 2, 1, 5), "mss_ddr4_setup_pda: Error setting up buffers");
+
+ //sets up MRS3 ecmd buffer
+ FAPI_TRY(address_16.insert(mrs3, 0, 16, 0), "mss_ddr4_setup_pda: Error setting up buffers");
+
+ //FLIPS all necessary bits
+ // Indicate B-Side DRAMS BG1=1
+ FAPI_TRY(address_16.setBit(15), "mss_ddr4_setup_pda: Error setting up buffers"); // Set BG1 = 1
+ FAPI_TRY(address_16.flipBit(3, 7)); // Invert A3:A9
+ FAPI_TRY(address_16.flipBit(11)); // Invert A11
+ FAPI_TRY(address_16.flipBit(13)); // Invert A13
+ FAPI_TRY(address_16.flipBit(14)); // Invert A17
+ FAPI_TRY(bank_3.flipBit(0, 3)); // Invert BA0,BA1,BG0
+
+ if (( address_mirror_map[l_port_number][dimm_number] & (0x08 >> rank_number) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+ } //if RDIMM or LRDIMM
+ } // for each port
+
+ //runs a NOP command for 24 cycle
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 24, 0, 16), "mss_ddr4_setup_pda: Error setting up buffers");
+ // Raise CKE high with NOPS, waiting min Reset CKE exit time (tXPR) - 400 cycles
+ FAPI_TRY(cke_4.setBit(0, 4), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(csn_8.setBit(0, 8), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(address_16.clearBit(0, 16), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(odt_4.clearBit(0, 4), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(num_idles_16.clearBit(0, 16), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 24, 0, 16), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(rasn_1.setBit(0, 1), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(casn_1.setBit(0, 1), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(wen_1.setBit(0, 1), "mss_ddr4_setup_pda: Error setting up buffers");
+
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+
+ //Setup end bit for CCS
+ FAPI_TRY(mss_ccs_set_end_bit (i_target, io_ccs_inst_cnt));
+
+ //Enable CCS and set RAS/CAS/WE high during idles
+ FAPI_INF("Enabling CCS\n");
+ reg_address = CEN_MBA_CCS_MODEQ;
+ FAPI_TRY(fapi2::getScom(i_target, reg_address, data_buffer));
+
+ data_buffer.setBit<29>(); //Enable CCS
+ data_buffer.setBit<52>(); //RAS high
+ data_buffer.setBit<53>(); //CAS high
+ data_buffer.setBit<54>(); //WE high
+
+ //if in DDR4 mode, count the parity bit and set it
+ if((dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4) && (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM
+ || dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM) )
+ {
+ FAPI_TRY(data_buffer.insertFromRight( (uint8_t)0xff, 61, 1), "enable ccs setup: Error setting up buffers");
+ }
+
+ FAPI_TRY(fapi2::putScom(i_target, reg_address, data_buffer));
+
+ //Execute the CCS array
+ FAPI_INF("Executing the CCS array\n");
+ FAPI_TRY(mss_execute_ccs_inst_array (i_target, NUM_POLL, WAIT_TIMER));
+ io_ccs_inst_cnt = 0;
+
+ //exits PDA
+ //loops through the DP18's and sets everything to 1's - no PDA
+ for(l_port_number = 0; l_port_number < MAX_PORTS_PER_MBA; l_port_number++)
+ {
+ for(uint8_t dp18 = 0; dp18 < MAX_BLOCKS_PER_RANK; dp18++)
+ {
+ reg_address = 0x800000010301143full + 0x0001000000000000ull * l_port_number + 0x0000040000000000ull * (dp18);
+ FAPI_TRY(fapi2::getScom(i_target, reg_address, data_buffer));
+
+ FAPI_TRY(data_buffer.setBit(60, 4), "enable ccs setup: Error setting up buffers"); //Enable CCS
+ FAPI_TRY(fapi2::putScom(i_target, reg_address, data_buffer));
+ }
+ }
+
+ //sets up the DRAM DQ drive time
+ FAPI_TRY(mss_get_pda_odt_timings(i_target, wl_launch_time, odt_hold_time, post_odt_nop_idle));
+ wl_launch_time -= 7;
+
+ FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P0, data_buffer));
+ //Setting up CCS mode
+ FAPI_TRY(data_buffer.setBit(48), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(data_buffer.insertFromRight(static_cast<uint8_t>(0x00), 49, 6),
+ "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(data_buffer.insertFromRight(static_cast<uint8_t>(0xFF), 55, 6),
+ "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P0, data_buffer));
+
+ FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P1, data_buffer));
+ //Setting up CCS mode
+ FAPI_TRY(data_buffer.setBit(48), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(data_buffer.insertFromRight(static_cast<uint8_t>(0x00), 49, 6),
+ "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(data_buffer.insertFromRight(static_cast<uint8_t>(0xFF), 55, 6),
+ "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P1, data_buffer));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }// end mss_ddr4_setup_pda
+
+
+ ///
+ /// @brief called by wrapper - sets up a PDA vector if it's not already configured
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in] i_pda: Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_ddr4_pda(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage> i_pda)
+ {
+ uint8_t dram_loop_end = 0;
+ uint8_t dram_loop_end_with_spare = 0;
+ FAPI_INF("Commonly used PDA attributes: fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE=0x%08x fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE=0x%08x",
+ fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE);
+ //gets the rank information
+ uint8_t num_ranks_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t num_spare[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t wr_vref[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t dram_width = 0;
+ uint8_t array[][2][19] = {{{0x18, 0x18, 0x1c, 0x1c, 0x18, 0x18, 0x1c, 0x1c, 0x18, 0x1c, 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x18, 0x1c, 0x18, 0x18}, {0x18, 0x1c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x20, 0x1c, 0x1c, 0x20, 0x1c, 0x18, 0x1c, 0x1c, 0x1c, 0x1c, 0x18, 0x18}}, {{0x18, 0x1c, 0x1c, 0x1c, 0x20, 0x1c, 0x20, 0x18, 0x18, 0x18, 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x1c, 0x18, 0x18, 0x1c}, {0x18, 0x1c, 0x18, 0x1c, 0x20, 0x1c, 0x18, 0x1c, 0x20, 0x1c, 0x1c, 0x1c, 0x1c, 0x24, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}}};
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target, dram_stack));
+
+ //get num master ranks per dimm for 3DS
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, num_ranks_array));
+ }
+ //get num ranks per dimm for non-3DS
+ else
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target, num_ranks_array));
+ }
+
+ //gets the spare information
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DIMM_SPARE, i_target, num_spare));
+
+ //gets the WR VREF information
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target, wr_vref));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, dram_width));
+
+ //sets the loop_end value, to ensure that the proper number of loops are conducted
+ if(dram_width == 0x08)
+ {
+ dram_loop_end = 9;
+ }
+ //must be a x4 DRAM
+ else
+ {
+ dram_loop_end = 18;
+ }
+
+ //if pda is empty then, sets up the vector for the MRS storage
+ if(i_pda.size() == 0)
+ {
+ //loops through each port each dimm each rank each dram and sets everything
+ for(uint8_t port = 0; port < MAX_PORTS_PER_MBA; port++)
+ {
+ for(uint8_t dimm = 0; dimm < MAX_DIMM_PER_PORT; dimm++)
+ {
+ for(uint8_t rank = 0; rank < num_ranks_array[port][dimm]; rank++)
+ {
+ //DIMM has a spare, add one DRAM to the loop
+ if(num_spare[port][dimm][rank])
+ {
+ dram_loop_end_with_spare = dram_loop_end + 1;
+ }
+ else
+ {
+ dram_loop_end_with_spare = dram_loop_end;
+ }
+
+ //loops through all dram
+ for(uint8_t dram = 0; dram < dram_loop_end_with_spare; dram++)
+ {
+ //uint8_t ad,uint32_t an,uint8_t d,uint8_t r,uint8_t
+ if(port == 0)
+ {
+ wr_vref[port][dimm][rank] = dram * 3;
+ }
+ else
+ {
+ wr_vref[port][dimm][rank] = 57 - dram * 3;
+ }
+
+ if(wr_vref[port][dimm][rank] > 50)
+ {
+ wr_vref[port][dimm][rank] = 50;
+ }
+
+ i_pda.push_back(PDA_MRS_Storage(array[port][dimm][dram], fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, dram, dimm, rank,
+ port));
+ FAPI_INF("PDA STRING: %d %s", i_pda.size() - 1, i_pda[i_pda.size() - 1].c_str());
+ }//for each dram
+ }//for each rank
+ }//for each dimm
+ }//for each port
+ }//if pda.size == 0
+
+ FAPI_TRY(mss_ddr4_run_pda(i_target, i_pda));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief runs through the vector of given PDA values and issues the PDA commands to the requested DRAMs
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in] i_pda: Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_run_pda(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage> i_pda)
+ {
+ if(i_pda.size() == 0)
+ {
+ return fapi2::FAPI2_RC_FALSE;
+ }
+
+ uint8_t num_ranks_array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //[port][dimm]
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target, dram_stack));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target, num_ranks_array));
+ }
+ else
+ {
+ FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, num_ranks_array);
+ }
+
+ //loops through all DIMMs all Ranks
+ for(uint8_t l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++)
+ {
+ uint8_t largest_num_ranks = num_ranks_array[0][l_dimm];
+
+ if(largest_num_ranks < num_ranks_array[1][l_dimm])
+ {
+ largest_num_ranks = num_ranks_array[1][l_dimm];
+ }
+
+ for(uint8_t l_rank = 0; l_rank < largest_num_ranks; l_rank++)
+ {
+ FAPI_INF("Running PDA on DIMM %d Rank %d!!", l_dimm, l_rank);
+ FAPI_TRY(mss_ddr4_run_pda_by_dimm_rank(i_target, i_pda, l_dimm, l_rank));
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+
+ ///
+ /// @brief runs per-DRAM addressability funcitonality on both ports on the passed MBA by dimm and rank
+ /// @param[in] i_target Centaur input mba
+ /// @param[in] i_pda Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @param[in] i_dimm Centaur dimm to run
+ /// @param[in] i_rank Centaur rank to run
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_run_pda_by_dimm_rank(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage> i_pda,
+ const uint8_t i_dimm,
+ const uint8_t i_rank)
+ {
+ //no PDA was entered, just exit
+ if(i_pda.size() == 0)
+ {
+ return fapi2::FAPI2_RC_FALSE;
+ }
+
+ //DIMM/rank not found - exit
+ if(mss_ddr4_check_pda_empty_for_rank(i_pda, i_dimm, i_rank))
+ {
+ return fapi2::FAPI2_RC_FALSE;
+ }
+
+ uint32_t io_ccs_inst_cnt = 0;
+ const uint32_t NUM_POLL = 10;
+ const uint32_t WAIT_TIMER = 1500;
+ fapi2::buffer<uint64_t> data_buffer_64;
+ fapi2::variable_buffer address_16(16);
+ fapi2::variable_buffer address_16_backup(16);
+ fapi2::variable_buffer bank_3(3);
+ fapi2::variable_buffer bank_3_backup(3);
+ fapi2::variable_buffer activate_1(1);
+ fapi2::variable_buffer rasn_1(1);
+ fapi2::variable_buffer casn_1(1);
+ fapi2::variable_buffer wen_1(1);
+ fapi2::variable_buffer rasn_1_odt(1);
+ fapi2::variable_buffer casn_1_odt(1);
+ fapi2::variable_buffer wen_1_odt(1);
+ fapi2::variable_buffer num_repeat_16_odt(16);
+ fapi2::variable_buffer num_idles_16_odt(16);
+ fapi2::variable_buffer csn_8_odt(8);
+ fapi2::variable_buffer cke_4(4);
+ fapi2::variable_buffer csn_8(8);
+ fapi2::variable_buffer odt_4(4);
+ fapi2::variable_buffer ddr_cal_type_4(4);
+ fapi2::variable_buffer num_idles_16(16);
+ fapi2::variable_buffer num_repeat_16(16);
+ fapi2::variable_buffer data_20(20);
+ fapi2::variable_buffer read_compare_1(1);
+ fapi2::variable_buffer rank_cal_4(4);
+ fapi2::variable_buffer ddr_cal_enable_1(1);
+ fapi2::variable_buffer ccs_end_1(1);
+ uint8_t dimm_type = 0;
+ uint8_t dram_width = 0;
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ fapi2::buffer<uint64_t> data_buffer;
+ uint8_t is_sim = 0;
+ uint8_t address_mirror_map[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //address_mirror_map[port][dimm]
+ uint8_t wl_launch_time = 0;
+ uint8_t odt_hold_time = 0;
+ uint8_t post_odt_nop_idle = 0;
+ uint8_t odt_wr[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ bool prev_dram_set = false;
+ vector<PDA_Scom_Storage> scom_storage;
+ uint8_t prev_dram = 0;
+ uint8_t prev_port = 0;
+ uint8_t prev_rank = 0;
+ uint8_t prev_dimm = 0;
+ uint8_t prev_mrs = 0;
+
+ FAPI_TRY(activate_1.setBit(0));
+ FAPI_TRY(rasn_1_odt.clearBit(0, 1));
+ FAPI_TRY(casn_1_odt.clearBit(0, 1));
+ FAPI_TRY(wen_1_odt.clearBit(0, 1));
+ FAPI_TRY(csn_8_odt.setBit(0, 8));
+ FAPI_TRY(csn_8_odt.clearBit(7, 1));
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+ //checks each MRS and saves each
+ FAPI_TRY(mss_ddr4_checksort_pda(i_target, i_pda));
+ //loads in dram type
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, i_target, dimm_type));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, dram_width));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target, dram_stack));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), is_sim));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target, address_mirror_map));
+
+ FAPI_TRY(mss_ddr4_setup_pda(i_target, io_ccs_inst_cnt, i_dimm, i_rank ));
+ FAPI_TRY(mss_get_pda_odt_timings(i_target, wl_launch_time, odt_hold_time, post_odt_nop_idle));
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 0, 0, 16));
+ FAPI_TRY(num_repeat_16.insertFromRight((uint32_t) 0, 0, 16));
+ FAPI_TRY(num_idles_16_odt.insertFromRight( post_odt_nop_idle, 0, 8));
+ FAPI_TRY(num_repeat_16_odt.insertFromRight( odt_hold_time, 0, 8));
+
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(address_16.clearBit(0, 16));
+ FAPI_TRY(odt_4.clearBit(0, 4));
+ FAPI_TRY(rasn_1.clearBit(0, 1));
+ FAPI_TRY(casn_1.clearBit(0, 1));
+ FAPI_TRY(wen_1.clearBit(0, 1));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_ODT_WR, i_target, odt_wr));
+
+ //runs through each PDA command
+ for(uint32_t i = 0; i < i_pda.size(); i++)
+ {
+ //did not find a PDA with the same DIMM and rank as requested
+ if(i_pda[i].rank != i_rank || i_pda[i].dimm != i_dimm)
+ {
+ continue;
+ }
+
+ //found a PDA of the same dimm and rank, but storage not set
+ if(!prev_dram_set)
+ {
+ //gets the start PDA values
+ prev_dram = i_pda[i].dram;
+ prev_port = i_pda[i].port;
+ prev_rank = i_pda[i].rank;
+ prev_dimm = i_pda[i].dimm;
+ prev_mrs = i_pda[i].MRS;
+ prev_dram_set = true;
+
+ FAPI_TRY(mss_ddr4_load_nominal_mrs_pda(i_target, bank_3, address_16, prev_mrs, prev_port, prev_dimm, prev_rank));
+
+ scom_storage.clear();
+ FAPI_TRY(mss_ddr4_add_dram_pda(i_target, prev_port, prev_dram, scom_storage));
+ }
+
+ FAPI_INF("Target %s On PDA %d is %s", mss::c_str(i_target), i, i_pda[i].c_str());
+
+ //dram, port, rank, dimm, and mrs are the same
+ if(prev_dram == i_pda[i].dram && prev_port == i_pda[i].port && prev_rank == i_pda[i].rank && prev_dimm == i_pda[i].dimm
+ && prev_mrs == i_pda[i].MRS)
+ {
+ //modifies this attribute
+ FAPI_TRY(mss_ddr4_modify_mrs_pda(i_target, address_16, i_pda[i].attribute_name, i_pda[i].attribute_data));
+ }
+ //another MRS, so set this MRS. do additional checks to later in the code
+ else
+ {
+ //adds values to a backup address_16 before doing the mirroring
+ FAPI_TRY(address_16_backup.clearBit(0, 16));
+ FAPI_TRY(address_16_backup.insert(address_16, 0, 16, 0));
+ FAPI_TRY(bank_3_backup.clearBit(0, 3));
+ FAPI_TRY(bank_3_backup.insert(bank_3, 0, 3, 0));
+
+ //loads the previous DRAM
+ if (( address_mirror_map[prev_port][prev_dimm] & (0x08 >> prev_rank) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(csn_8.clearBit(prev_rank + 4 * prev_dimm));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2));
+ FAPI_TRY(csn_8.clearBit(6, 2));
+ }
+
+ FAPI_TRY(odt_4.insert(odt_wr[prev_port][prev_dimm][prev_rank], 0, 4, 0));
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1_odt,
+ casn_1_odt,
+ wen_1_odt,
+ cke_4,
+ csn_8_odt,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16_odt,
+ num_repeat_16_odt,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ //is an R or LR DIMM -> do a B side MRS write
+ if ( (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM)
+ || (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM) )
+ {
+ //takes values from the backup
+ FAPI_TRY(address_16.clearBit(0, 16));
+ FAPI_TRY(address_16.insert(address_16_backup, 0, 16, 0));
+ FAPI_TRY(bank_3.clearBit(0, 3));
+ FAPI_TRY(bank_3.insert(bank_3_backup, 0, 3, 0));
+
+ //FLIPS all necessary bits
+ // Indicate B-Side DRAMS BG1=1
+ FAPI_TRY(address_16.setBit(15)); // Set BG1 = 1
+
+ FAPI_TRY(address_16.flipBit(3, 7)); // Invert A3:A9
+ FAPI_TRY(address_16.flipBit(11)); // Invert A11
+ FAPI_TRY(address_16.flipBit(13)); // Invert A13
+ FAPI_TRY(address_16.flipBit(14)); // Invert A17
+ FAPI_TRY(bank_3.flipBit(0, 3)); // Invert BA0,BA1,BG0
+
+ //loads the previous DRAM
+ if (( address_mirror_map[prev_port][prev_dimm] & (0x08 >> prev_rank) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(csn_8.clearBit(prev_rank + 4 * prev_dimm));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2));
+ FAPI_TRY(csn_8.clearBit(6, 2));
+ }
+
+ FAPI_TRY(odt_4.insert(odt_wr[prev_port][prev_dimm][prev_rank], 0, 4, 0));
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1_odt,
+ casn_1_odt,
+ wen_1_odt,
+ cke_4,
+ csn_8_odt,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16_odt,
+ num_repeat_16_odt,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+ }
+
+ //the DRAM are different, so kick off CCS, and clear out the MRS DRAMs and set up a new DRAM
+ if(prev_dram != i_pda[i].dram)
+ {
+ //sets a NOP as the last command
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(address_16.clearBit(0, 16));
+ FAPI_TRY(rasn_1.setBit(0, 1));
+ FAPI_TRY(casn_1.setBit(0, 1));
+ FAPI_TRY(wen_1.setBit(0, 1));
+ FAPI_TRY(odt_4.insert((uint8_t) 0, 0, 4, 0));
+
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ //Setup end bit for CCS
+ FAPI_TRY(mss_ccs_set_end_bit (i_target, io_ccs_inst_cnt - 1));
+
+ //Execute the CCS array
+ FAPI_INF("Executing the CCS array\n");
+ FAPI_TRY(mss_execute_ccs_inst_array (i_target, NUM_POLL, WAIT_TIMER));
+ io_ccs_inst_cnt = 0;
+
+ // Sets NOP as the first command
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(address_16.clearBit(0, 16));
+ FAPI_TRY(rasn_1.clearBit(0, 1));
+ FAPI_TRY(casn_1.clearBit(0, 1));
+ FAPI_TRY(wen_1.clearBit(0, 1));
+
+ //loops through and clears out the storage class
+ for(const auto& scom : scom_storage)
+ {
+ FAPI_TRY(fapi2::getScom(i_target, scom.scom_addr, data_buffer));
+
+ FAPI_TRY(data_buffer.setBit(scom.start_bit, scom.num_bits),
+ "enable ccs setup: Error setting up buffers"); //Enable CCS
+ FAPI_TRY(fapi2::putScom(i_target, scom.scom_addr, data_buffer));
+ }
+
+ scom_storage.clear();
+ //enables the next dram scom
+ FAPI_TRY(mss_ddr4_add_dram_pda(i_target, i_pda[i].port, i_pda[i].dram, scom_storage));
+ }
+ //different port but same DRAM, enable the next scom
+ else if(prev_port != i_pda[i].port)
+ {
+ //enables the next dram scom
+ FAPI_TRY(mss_ddr4_add_dram_pda(i_target, i_pda[i].port, i_pda[i].dram, scom_storage));
+ }
+
+ //loads in the nominal MRS for this target
+ prev_dram = i_pda[i].dram;
+ prev_port = i_pda[i].port;
+ prev_rank = i_pda[i].rank;
+ prev_dimm = i_pda[i].dimm;
+ prev_mrs = i_pda[i].MRS;
+
+ FAPI_TRY( mss_ddr4_load_nominal_mrs_pda(i_target, bank_3, address_16, prev_mrs, prev_port, prev_dimm, prev_rank));
+ //modifies the MRS
+ FAPI_TRY(mss_ddr4_modify_mrs_pda(i_target, address_16, i_pda[i].attribute_name, i_pda[i].attribute_data));
+ }
+ }
+
+ //runs the last PDA command, if and only if a PDA of the desired rank and dimm was run
+ if(prev_dram_set)
+ {
+ //adds values to a backup address_16 before doing the mirroring
+ FAPI_TRY(address_16_backup.clearBit(0, 16));
+ FAPI_TRY(address_16_backup.insert(address_16, 0, 16, 0));
+ FAPI_TRY(bank_3_backup.clearBit(0, 3));
+ FAPI_TRY(bank_3_backup.insert(bank_3, 0, 3, 0));
+ FAPI_TRY(odt_4.insert(odt_wr[prev_port][prev_dimm][prev_rank], 0, 4, 0));
+
+ //loads the previous DRAM
+ if (( address_mirror_map[prev_port][prev_dimm] & (0x08 >> prev_rank) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2));
+ FAPI_TRY(csn_8.clearBit(6, 2));
+ }
+
+ FAPI_TRY(csn_8.clearBit(prev_rank + 4 * prev_dimm));
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1_odt,
+ casn_1_odt,
+ wen_1_odt,
+ cke_4,
+ csn_8_odt,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16_odt,
+ num_repeat_16_odt,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ //is an R or LR DIMM -> do a B side MRS write
+ if ( (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM)
+ || (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM) )
+ {
+ //takes values from the backup
+ FAPI_TRY(address_16.clearBit(0, 16));
+ FAPI_TRY(address_16.insert(address_16_backup, 0, 16, 0));
+ FAPI_TRY(bank_3.clearBit(0, 3));
+ FAPI_TRY(bank_3.insert(bank_3_backup, 0, 3, 0));
+
+ //FLIPS all necessary bits
+ // Indicate B-Side DRAMS BG1=1
+ FAPI_TRY(address_16.setBit(15)); // Set BG1 = 1
+ FAPI_TRY(address_16.flipBit(3, 7)); // Invert A3:A9
+ FAPI_TRY(address_16.flipBit(11)); // Invert A11
+ FAPI_TRY(address_16.flipBit(13)); // Invert A13
+ FAPI_TRY(address_16.flipBit(14)); // Invert A17
+ FAPI_TRY(bank_3.flipBit(0, 3)); // Invert BA0,BA1,BG0
+
+ //loads the previous DRAM
+ if (( address_mirror_map[prev_port][prev_dimm] & (0x08 >> prev_rank) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8));
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2));
+ FAPI_TRY(csn_8.clearBit(6, 2));
+ }
+
+ FAPI_TRY(csn_8.clearBit(prev_rank + 4 * prev_dimm));
+
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1_odt,
+ casn_1_odt,
+ wen_1_odt,
+ cke_4,
+ csn_8_odt,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY( mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16_odt,
+ num_repeat_16_odt,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+ }
+ }
+
+ //sets a NOP as the last command
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(address_16.clearBit(0, 16));
+ FAPI_TRY(rasn_1.setBit(0, 1));
+ FAPI_TRY(casn_1.setBit(0, 1));
+ FAPI_TRY(wen_1.setBit(0, 1));
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8_odt,
+ odt_4,
+ ddr_cal_type_4,
+ prev_port));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ //Setup end bit for CCS
+ FAPI_TRY(mss_ccs_set_end_bit (i_target, io_ccs_inst_cnt - 1));
+
+ //Execute the CCS array
+ FAPI_INF("Executing the CCS array\n");
+ FAPI_TRY(mss_execute_ccs_inst_array (i_target, NUM_POLL, WAIT_TIMER));
+
+ //loops through and clears out the storage class
+ for(uint32_t scoms = 0; scoms < scom_storage.size(); scoms++)
+ for(const auto& scom : scom_storage)
+ {
+ FAPI_TRY(fapi2::getScom(i_target, scom.scom_addr, data_buffer));
+
+ FAPI_TRY(data_buffer.setBit(scom.start_bit, scom.num_bits),
+ "enable ccs setup: Error setting up buffers"); //Enable CCS
+ FAPI_TRY(fapi2::putScom(i_target, scom.scom_addr, data_buffer));
+ }
+
+ io_ccs_inst_cnt = 0;
+ FAPI_TRY(mss_ddr4_disable_pda(i_target, io_ccs_inst_cnt, i_dimm, i_rank));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+
+ ///
+ /// @brief Adds a given DRAM into the scom_storage vector
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in] i_port: identifies which port the given DRAM is on
+ /// @param[in] i_dram: identifies which DRAM identifier is to be added
+ /// @param[in/out] io_scom_storage: list of all DRAMs being modified by PDA. contains address, bit, and length
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_ddr4_add_dram_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target, const uint8_t i_port,
+ const uint8_t i_dram,
+ vector<PDA_Scom_Storage>& io_scom_storage)
+ {
+ fapi2::buffer<uint64_t> data_buffer;
+ //access delay regs function
+ uint8_t i_rank_pair = 0;
+ input_type_t i_input_type_e = WR_DQ;
+ uint8_t i_input_index = 75;
+ uint8_t i_verbose = 1;
+ uint8_t phy_lane = 6;
+ uint8_t phy_block = 6;
+ uint8_t flag = 0;
+ uint32_t scom_len = 0;
+ uint32_t scom_start = 0;
+ uint64_t reg_address = 0;
+ uint8_t dram_width = 0;
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, dram_width));
+
+ // C4 DQ to lane/block (flag = 0) in PHY or lane/block to C4 DQ (flag = 1)
+ // In this case moving from lane/block to C4 DQ to use access_delay_reg
+ i_input_index = 4 * i_dram;
+ FAPI_TRY( mss_c4_phy(i_target, i_port, i_rank_pair, i_input_type_e, i_input_index, i_verbose, phy_lane, phy_block,
+ flag));
+
+ reg_address = 0x800000010301143full + (0x0001000000000000ull * i_port) + (0x0000040000000000ull * phy_block);
+
+ //gets the lane and number of bits to set to 0's
+ if(dram_width == 0x04)
+ {
+ scom_start = 60 + (uint32_t)(phy_lane / 4);
+ scom_len = 1;
+ }
+ //x8 DIMM
+ else
+ {
+ scom_start = 60 + (uint32_t)((phy_lane / 8) * 2);
+ scom_len = 2;
+ }
+
+ FAPI_INF("Enabling %016llx start at %d for %d bits for port %d dram %d", reg_address, scom_start, scom_len, i_port,
+ i_dram);
+
+ FAPI_TRY(fapi2::getScom(i_target, reg_address, data_buffer));
+ FAPI_TRY(data_buffer.clearBit(scom_start, scom_len)); //Enable CCS
+ FAPI_TRY(fapi2::putScom(i_target, reg_address, data_buffer));
+
+ io_scom_storage.push_back(PDA_Scom_Storage(reg_address, scom_start, scom_len));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Takes the DRAM out of per-DRAM addressability mode (PDA mode)
+ /// @param[in] target: Reference to centaur.mba target,
+ /// @param[in/out] io_ccs_inst_cnt: starting point of CCS array - needed to properly setup CCS
+ /// @param[in] i_dimm: which DIMM to run PDA commands on
+ /// @param[in] i_rank: which rank on which DIMM to run PDA commands on
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_ddr4_disable_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target, uint32_t& io_ccs_inst_cnt,
+ const uint8_t i_dimm, const uint8_t i_rank)
+ {
+ uint32_t l_port_number = 0;
+ uint32_t dimm_number = i_dimm;
+ uint32_t rank_number = i_rank;
+ const uint32_t NUM_POLL = 10;
+ const uint32_t WAIT_TIMER = 1500;
+ uint64_t reg_address = 0;
+ fapi2::buffer<uint64_t> data_buffer;
+ fapi2::buffer<uint64_t> data_buffer_64;
+ fapi2::variable_buffer address_16(16);
+ fapi2::variable_buffer bank_3(3);
+ fapi2::variable_buffer activate_1(1);
+ fapi2::variable_buffer rasn_1(1);
+ fapi2::variable_buffer casn_1(1);
+ fapi2::variable_buffer wen_1(1);
+ fapi2::variable_buffer cke_4(4);
+ fapi2::variable_buffer csn_8(8);
+ fapi2::variable_buffer odt_4(4);
+ fapi2::variable_buffer ddr_cal_type_4(4);
+
+ fapi2::variable_buffer num_idles_16(16);
+ fapi2::variable_buffer num_repeat_16(16);
+ fapi2::variable_buffer data_20(20);
+ fapi2::variable_buffer read_compare_1(1);
+ fapi2::variable_buffer rank_cal_4(4);
+ fapi2::variable_buffer ddr_cal_enable_1(1);
+ fapi2::variable_buffer ccs_end_1(1);
+
+ fapi2::variable_buffer rasn_1_odt(1);
+ fapi2::variable_buffer casn_1_odt(1);
+ fapi2::variable_buffer wen_1_odt(1);
+ fapi2::variable_buffer num_repeat_16_odt(16);
+ fapi2::variable_buffer num_idles_16_odt(16);
+ fapi2::variable_buffer csn_8_odt(8);
+ uint8_t dram_gen = 0;
+ fapi2::variable_buffer mrs3(16);
+ uint8_t odt_wr[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t dimm_type = 0;
+ uint8_t is_sim = 0;
+ uint8_t address_mirror_map[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0}; //address_mirror_map[port][dimm]
+ uint8_t mpr_op = 0; // MPR Op
+ uint8_t mpr_page = 0; // MPR Page Selection
+ uint8_t geardown_mode = 0; // Gear Down Mode
+ uint8_t temp_readout = 0; // Temperature sensor readout
+ uint8_t fine_refresh = 0; // fine refresh mode
+ uint8_t wr_latency = 0; // write latency for CRC and DM
+ uint8_t read_format = 0; // MPR READ FORMAT
+ uint8_t wl_launch_time = 0;
+ uint8_t odt_hold_time = 0;
+ uint8_t post_odt_nop_idle = 0;
+ uint8_t io_dram_rtt_nom_original = 0;
+ uint16_t MRS3 = 0;
+
+ FAPI_TRY(activate_1.setBit(0));
+ FAPI_TRY(cke_4.setBit(0, 4));
+ FAPI_TRY(csn_8.setBit(0, 8));
+ FAPI_TRY(rasn_1_odt.clearBit(0, 1));
+ FAPI_TRY(casn_1_odt.clearBit(0, 1));
+ FAPI_TRY(wen_1_odt.clearBit(0, 1));
+ FAPI_TRY(csn_8_odt.setBit(0, 8));
+ FAPI_TRY(csn_8_odt.clearBit(7, 1));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target, dram_gen));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_ODT_WR, i_target, odt_wr));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target, dram_stack));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DIMM_TYPE, i_target, dimm_type));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), is_sim));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ADDRESS_MIRRORING, i_target, address_mirror_map));
+
+ // WORKAROUNDS
+ FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_CCS_MODEQ, data_buffer));
+ //Setting up CCS mode
+ data_buffer.setBit<51>();
+
+ //if in DDR4 mode, count the parity bit and set it
+ if((dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4) && (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM
+ || dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM) )
+ {
+ FAPI_TRY(data_buffer.insertFromRight( (uint8_t)0xff, 61, 1), "disable ccs setup: Error disabling up buffers");
+ }
+
+ FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_CCS_MODEQ, data_buffer));
+
+ //loops through port 0 and port 1 on the given MBA
+ for(l_port_number = 0; l_port_number < MAX_PORTS_PER_MBA; l_port_number++)
+ {
+ // Raise CKE high with NOPS, waiting min Reset CKE exit time (tXPR) - 400 cycles
+ FAPI_TRY(cke_4.setBit(0, 4), "disable ccs setup: Error disabling up buffers");
+ FAPI_TRY(csn_8.setBit(0, 8), "disable ccs setup: Error disabling up buffers");
+ FAPI_TRY(address_16.clearBit(0, 16), "disable ccs setup: Error disabling up buffers");
+ FAPI_TRY(odt_4.clearBit(0, 4), "disable ccs setup: Error disabling up buffers");
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 400, 0, 16), "disable ccs setup: Error disabling up buffers");
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+ }
+
+
+ //Sets up MRS3 -> the MRS that has PDA
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_MPR_MODE, i_target, mpr_op));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_MPR_PAGE, i_target, mpr_page));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_GEARDOWN_MODE, i_target, geardown_mode));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_TEMP_READOUT, i_target, temp_readout));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_FINE_REFRESH_MODE, i_target, fine_refresh));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CRC_WR_LATENCY, i_target, wr_latency));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_MPR_RD_FORMAT, i_target, read_format));
+
+
+ //sets up the DRAM DQ drive time
+ FAPI_TRY(mss_get_pda_odt_timings(i_target, wl_launch_time, odt_hold_time, post_odt_nop_idle));
+
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 0, 0, 16));
+ FAPI_TRY(num_repeat_16.insertFromRight((uint32_t) 0, 0, 16));
+ FAPI_TRY(num_idles_16_odt.insertFromRight( post_odt_nop_idle, 0, 8));
+ FAPI_TRY(num_repeat_16_odt.insertFromRight( odt_hold_time, 0, 8));
+
+ //exits PDA
+ for(l_port_number = 0; l_port_number < MAX_PORTS_PER_MBA; l_port_number++)
+ {
+ //loops through the DP18's and sets everything to 0's
+ for(uint8_t dp18 = 0; dp18 < MAX_BLOCKS_PER_RANK; dp18++)
+ {
+ reg_address = 0x800000010301143full + 0x0001000000000000ull * l_port_number + 0x0000040000000000ull * (dp18);
+ FAPI_TRY(fapi2::getScom(i_target, reg_address, data_buffer));
+ FAPI_TRY(data_buffer.clearBit(60, 4), "enable ccs setup: Error setting up buffers"); //Enable CCS
+ FAPI_TRY(fapi2::putScom(i_target, reg_address, data_buffer));
+ }
+ }
+
+ //exits PDA
+ for(l_port_number = 0; l_port_number < 2; l_port_number++)
+ {
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8), "mss_mrs_load: Error setting up buffers");
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(csn_8.clearBit(6, 2), "mss_mrs_load: Error setting up buffers");
+ }
+
+ FAPI_TRY(csn_8.clearBit(rank_number + 4 * dimm_number));
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 0, 1, 7), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 1, 1, 6), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 2, 1, 5), "mss_mrs_load: Error setting up buffers");
+
+ //enables PDA
+ FAPI_TRY(mrs3.insert((uint8_t) mpr_page, 0, 2), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) mpr_op, 2, 1), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) geardown_mode, 3, 1), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) 0x00, 4, 1), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) temp_readout, 5, 1), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) fine_refresh, 6, 3), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) wr_latency, 9, 2), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) read_format, 11, 2), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) 0x00, 13, 2), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(mrs3.extract(MRS3, 0, 16), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 100, 0, 16), "mss_mrs_load: Error setting up buffers");
+ FAPI_TRY(odt_4.insert(odt_wr[l_port_number][dimm_number][rank_number], 0, 4, 0),
+ "mss_mrs_load: Error setting up buffers");
+
+ //copies over values
+ FAPI_TRY(address_16.insert(mrs3, 0, 16, 0), "mss_mrs_load: Error setting up buffers");
+
+ if (( address_mirror_map[l_port_number][dimm_number] & (0x08 >> rank_number) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1_odt,
+ casn_1_odt,
+ wen_1_odt,
+ cke_4,
+ csn_8_odt,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16_odt,
+ num_repeat_16_odt,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ //if the DIMM is an R or LR DIMM, then run inverted for the B-Side DRAM
+ if ( (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_RDIMM)
+ || (dimm_type == fapi2::ENUM_ATTR_CEN_EFF_DIMM_TYPE_LRDIMM) )
+ {
+
+ //reload all MRS values (removes address swizzling)
+ // Only corresponding CS to rank
+ FAPI_TRY(csn_8.setBit(0, 8), "mss_ddr4_setup_pda: Error setting up buffers");
+
+ if(dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(csn_8.clearBit(2, 2), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(csn_8.clearBit(6, 2), "mss_ddr4_setup_pda: Error setting up buffers");
+ }
+
+ FAPI_TRY(csn_8.clearBit(rank_number + 4 * dimm_number));
+
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 0, 1, 7), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 1, 1, 6), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(bank_3.insert((uint8_t) MRS3_BA, 2, 1, 5), "mss_ddr4_setup_pda: Error setting up buffers");
+
+ //enables PDA
+ FAPI_TRY(mrs3.insert((uint8_t) mpr_page, 0, 2), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) mpr_op, 2, 1), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) geardown_mode, 3, 1), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) 0x00, 4, 1), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) temp_readout, 5, 1), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) fine_refresh, 6, 3), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) wr_latency, 9, 2), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) read_format, 11, 2), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.insert((uint8_t) 0x00, 13, 2), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(mrs3.extract(MRS3, 0, 16), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(num_idles_16.insertFromRight((uint32_t) 100, 0, 16), "mss_ddr4_setup_pda: Error setting up buffers");
+ //copies over values
+ FAPI_TRY(address_16.insert(mrs3, 0, 16, 0), "mss_ddr4_setup_pda: Error setting up buffers");
+
+ //FLIPS all necessary bits
+ // Indicate B-Side DRAMS BG1=1
+ FAPI_TRY(address_16.setBit(15), "mss_ddr4_setup_pda: Error setting up buffers"); // Set BG1 = 1
+
+ FAPI_TRY(address_16.flipBit(3, 7)); // Invert A3:A9
+ FAPI_TRY(address_16.flipBit(11)); // Invert A11
+ FAPI_TRY(address_16.flipBit(13)); // Invert A13
+ FAPI_TRY(address_16.flipBit(14)); // Invert A17
+ FAPI_TRY(bank_3.flipBit(0, 3)); // Invert BA0,BA1,BG0
+
+ FAPI_ERR("mss_ddr4_setup_pda: Error setting up buffers");
+
+ if (( address_mirror_map[l_port_number][dimm_number] & (0x08 >> rank_number) ) && (is_sim == 0))
+ {
+ FAPI_TRY(mss_address_mirror_swizzle(i_target, address_16, bank_3));
+ }
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1,
+ casn_1,
+ wen_1,
+ cke_4,
+ csn_8,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16,
+ num_repeat_16,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+
+ // Send out to the CCS array
+ FAPI_TRY(mss_ccs_inst_arry_0( i_target,
+ io_ccs_inst_cnt,
+ address_16,
+ bank_3,
+ activate_1,
+ rasn_1_odt,
+ casn_1_odt,
+ wen_1_odt,
+ cke_4,
+ csn_8_odt,
+ odt_4,
+ ddr_cal_type_4,
+ l_port_number));
+ FAPI_TRY(mss_ccs_inst_arry_1( i_target,
+ io_ccs_inst_cnt,
+ num_idles_16_odt,
+ num_repeat_16_odt,
+ data_20,
+ read_compare_1,
+ rank_cal_4,
+ ddr_cal_enable_1,
+ ccs_end_1));
+ io_ccs_inst_cnt ++;
+ }
+ }
+
+ //Setup end bit for CCS
+ FAPI_TRY(mss_ccs_set_end_bit (i_target, io_ccs_inst_cnt - 1));
+
+ //Execute the CCS array
+ FAPI_INF("Executing the CCS array\n");
+ FAPI_TRY(mss_execute_ccs_inst_array (i_target, NUM_POLL, WAIT_TIMER));
+
+ //Disable CCS
+ FAPI_INF("Disabling CCS\n");
+ reg_address = CEN_MBA_CCS_MODEQ;
+ FAPI_TRY(fapi2::getScom(i_target, reg_address, data_buffer));
+ FAPI_TRY(data_buffer.clearBit(29), "disable ccs setup: Error disabling up buffers");
+ FAPI_TRY(fapi2::putScom(i_target, reg_address, data_buffer));
+
+ //disables the DDR4 PDA mode writes
+ FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P0, data_buffer));
+ //Setting up CCS mode
+ FAPI_TRY(data_buffer.clearBit(48), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P0, data_buffer));
+
+ FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P1, data_buffer));
+ //Setting up CCS mode
+ FAPI_TRY(data_buffer.clearBit(48), "mss_ddr4_setup_pda: Error setting up buffers");
+ FAPI_TRY(fapi2::putScom(i_target, CEN_MBA_DDRPHY_WC_CONFIG3_P1, data_buffer));
+
+ FAPI_INF("Successfully exited out of PDA mode.");
+ io_ccs_inst_cnt = 0;
+
+ //Does the RTT_WR to RTT_NOM swapping
+ //loops through all ports
+ for(l_port_number = 0; l_port_number < MAX_PORTS_PER_MBA; l_port_number++)
+ {
+ FAPI_TRY(mss_ddr4_rtt_nom_rtt_wr_swap(i_target, 0, l_port_number, rank_number + dimm_number * 4, 0xFF, io_ccs_inst_cnt,
+ io_dram_rtt_nom_original));
+ io_ccs_inst_cnt = 0;
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+
+ ///
+ /// @brief sets up the ODT holdtime and number of idles to be issued after
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[out] o_wl_launch_time: holds the number of cycles that the data must be launched after the PDA command is issued
+ /// @param[out] o_odt_hold_time: holds the number of cycles that the ODT must be held for PDA
+ /// @param[out] o_post_odt_nop_idle: holds the number of cycles that
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_get_pda_odt_timings(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint8_t& o_wl_launch_time,
+ uint8_t& o_odt_hold_time,
+ uint8_t& o_post_odt_nop_idle)
+ {
+ fapi2::buffer<uint64_t> data_buffer;
+ //reads out the register values
+ //gets the hold time
+ uint8_t launch_delay = 0;
+ uint8_t dram_al = 0;
+ uint8_t dram_cl = 0;
+ FAPI_TRY(data_buffer.extractToRight(launch_delay, 12, 6));
+ FAPI_TRY(data_buffer.extractToRight(o_odt_hold_time, 18, 6));
+ FAPI_TRY(fapi2::getScom(i_target, CEN_MBA_MBA_DSM0Q, data_buffer));
+ o_odt_hold_time = o_odt_hold_time + launch_delay;
+
+ //gets write latency
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_CWL, i_target, o_wl_launch_time));
+
+ o_wl_launch_time += launch_delay;
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_AL, i_target, dram_al));
+
+ //Addative latency enabled - need to add CL-AL
+ if(dram_al != fapi2::ENUM_ATTR_CEN_EFF_DRAM_AL_DISABLE)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_CL, i_target, dram_cl));
+ o_wl_launch_time += (dram_cl - dram_al);
+ }
+
+ o_post_odt_nop_idle = o_wl_launch_time + o_odt_hold_time + 50;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief returns a 1 if the PDA is empty for the given DIMM rank - returns 0 if not empty
+ /// @param[in] i_pda Vector of PDA_MRS_Storage class elements
+ /// @param[in] i_dimm Centaur input dimm
+ /// @param[in] i_rank Centaur input rank
+ /// @return returns a 1 if the PDA is empty for the given DIMM rank - returns 0 if not empty
+ ///
+ uint32_t mss_ddr4_check_pda_empty_for_rank(
+ vector<PDA_MRS_Storage> i_pda,
+ const uint8_t i_dimm,
+ const uint8_t i_rank)
+ {
+ for(auto& pda : i_pda)
+ {
+ //found, return 0
+ if((pda.dimm == i_dimm) && (pda.rank == i_rank))
+ {
+ return 0;
+ }
+ }
+
+ //not found, return 1
+ return 1;
+ }
+}
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.H
new file mode 100755
index 000000000..fd64ccc3f
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.H
@@ -0,0 +1,200 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_ddr4_pda.H
+/// @brief Tools for DDR4 DIMMs centaur procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#ifndef _MSS_DDR4_PDA_H
+#define _MSS_DDR4_PDA_H
+#include <fapi2.H>
+#include <vector>
+using namespace std;
+///
+/// @brief PDA MRS storage structure
+///
+class PDA_MRS_Storage
+{
+ private:
+ static char pda_string[fapi2::MAX_ECMD_STRING_LEN];
+ public:
+ uint8_t attribute_data;
+ uint32_t attribute_name;
+ uint8_t MRS;
+ uint8_t dimm;
+ uint8_t dram;
+ uint8_t rank;
+ uint8_t port;
+ ///
+ /// @brief PDA MRS storage constructor
+ ///
+ PDA_MRS_Storage(const uint8_t ad, const uint32_t an, const uint8_t dr, const uint8_t di, const uint8_t r,
+ const uint8_t p);
+ ~PDA_MRS_Storage();
+ bool operator> (const PDA_MRS_Storage& PDA2) const;
+ bool operator< (const PDA_MRS_Storage& PDA2) const;
+ void copy(PDA_MRS_Storage& temp);
+ fapi2::ReturnCode setMRSbyAttr(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+ fapi2::ReturnCode checkPDAValid(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+ char* c_str();
+ void generatePDAString();
+};
+
+///
+/// @brief PDA scom storage structure
+///
+class PDA_Scom_Storage
+{
+ public:
+ uint64_t scom_addr;
+ uint32_t start_bit;
+ uint32_t num_bits;
+ ///
+ /// @brief PDA Scom storage constructor
+ ///
+ PDA_Scom_Storage(const uint64_t sa, const uint32_t sb, const uint32_t nb);
+ ~PDA_Scom_Storage();
+};
+
+typedef fapi2::ReturnCode (*mss_ddr4_pda_FP_t)(fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage> pda);
+
+extern "C"
+{
+ ///
+ /// @brief runs through the vector of given PDA values and issues the PDA commands to the requested DRAMs
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in] i_pda: Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_run_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage> i_pda);
+
+ ///
+ /// @brief Puts the DRAM in per-DRAM addressability mode (PDA mode)
+ /// @param[in] target: Reference to centaur.mba target,
+ /// @param[in/out] io_ccs_inst_cnt: starting point of CCS array - needed to properly setup CCS
+ /// @param[in] i_dimm Centaur dimm to run
+ /// @param[in] i_rank Centaur rank to run
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_setup_pda(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t& io_ccs_inst_cnt,
+ const uint8_t i_dimm,
+ const uint8_t i_rank);
+
+ ///
+ /// @brief Takes the DRAM out of per-DRAM addressability mode (PDA mode)
+ /// @param[in] target: Reference to centaur.mba target,
+ /// @param[in/out] io_ccs_inst_cnt: starting point of CCS array - needed to properly setup CCS
+ /// @param[in] i_dimm: which DIMM to run PDA commands on
+ /// @param[in] i_rank: which rank on which DIMM to run PDA commands on
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_disable_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target, uint32_t& io_ccs_inst_cnt,
+ const uint8_t i_dimm, const uint8_t i_rank);
+
+ ///
+ /// @brief called by wrapper - sets up a PDA vector if it's not already configured
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in] i_pda: Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target, vector<PDA_MRS_Storage> i_pda);
+
+ ///
+ /// @brief Checks the passed in PDA vector to ensure that all entries are good. then sorts the vector to ensure more efficient command stream
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in/out] io_pda: Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_checksort_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage>& io_pda);
+
+ ///
+ /// @brief Adds a given DRAM into the scom_storage vector
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[in] i_port: identifies which port the given DRAM is on
+ /// @param[in] i_dram: identifies which DRAM identifier is to be added
+ /// @param[in/out] io_scom_storage: list of all DRAMs being modified by PDA. contains address, bit, and length
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_add_dram_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target, const uint8_t i_port,
+ const uint8_t i_dram,
+ vector<PDA_Scom_Storage>& io_scom_storage);
+
+ ///
+ /// @brief sets up the ODT holdtime and number of idles to be issued after
+ /// @param[in] i_target: Reference to centaur.mba target,
+ /// @param[out] o_wl_launch_time: holds the number of cycles that the data must be launched after the PDA command is issued
+ /// @param[out] o_odt_hold_time: holds the number of cycles that the ODT must be held for PDA
+ /// @param[out] o_post_odt_nop_idle: holds the number of cycles that
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_get_pda_odt_timings(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint8_t& o_wl_launch_time,
+ uint8_t& o_odt_hold_time, uint8_t& o_post_odt_nop_idle);
+
+ ///
+ /// @brief runs per-DRAM addressability funcitonality on both ports on the passed MBA by dimm and rank
+ /// @param[in] i_target Centaur input mba
+ /// @param[in] i_pda Vector of PDA_MRS_Storage class elements - initialized by the user and contains DRAM information and attribute override information
+ /// @param[in] i_dimm Centaur dimm to run
+ /// @param[in] i_rank Centaur rank to run
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mss_ddr4_run_pda_by_dimm_rank(
+ const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ vector<PDA_MRS_Storage> i_pda,
+ const uint8_t i_dimm,
+ const uint8_t i_rank
+ );
+
+ ///
+ /// @brief returns a 1 if the PDA is empty for the given DIMM rank - returns 0 if not empty
+ /// @param[in] i_pda
+ /// @param[in] i_dimm
+ /// @param[in] i_rank
+ /// @return returns a 1 if the PDA is empty for the given DIMM rank - returns 0 if not empty
+ ///
+ uint32_t mss_ddr4_check_pda_empty_for_rank(
+ vector<PDA_MRS_Storage> i_pda,
+ const uint8_t i_dimm,
+ const uint8_t i_rank
+ );
+
+} // extern "C"
+
+#endif /* _MSS_DDR4_PDA_H */
+
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.mk
new file mode 100755
index 000000000..61a02e326
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.mk
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr4_pda.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+
+PROCEDURE=p9c_mss_ddr4_pda
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C
index 8a3f88864..9ca0770e3 100644
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.C
@@ -39,7 +39,7 @@
#include <cen_gen_scom_addresses_fld.H>
#include <p9c_mss_ddr_phy_reset.H>
#include <p9c_mss_unmask_errors.H>
-#include <p9c_mss_slew.H>
+#include <p9c_mss_termination_control.H>
#include <p9c_dimmBadDqBitmapFuncs.H>
#include <generic/memory/lib/utils/c_str.H>
#include <dimmConsts.H>
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk
index 16fdf0ced..c4c835cc1 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_ddr_phy_reset.mk
@@ -28,6 +28,6 @@
PROCEDURE=p9c_mss_ddr_phy_reset
OBJS+=p9c_dimmBadDqBitmapFuncs.o
OBJS+=p9c_mss_unmask_errors.o
-OBJS+=p9c_mss_slew.o
+OBJS+=p9c_mss_termination_control.o
$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.C
index 218bdf148..5c3107212 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.C
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.C
@@ -2857,7 +2857,7 @@ extern "C" {
{
// disable0=dq bits, disable1=dqs(+,-)
// wrclk_en=dqs follows quad, same as disable0
- const uint64_t l_disable_reg[MAX_PORTS_PER_MBA][MAX_RANKS_PER_DIMM][DP18_INSTANCES] =
+ const uint64_t l_disable_reg[MAX_PORTS_PER_MBA][MAX_RANKS_PER_DIMM][MAX_BLOCKS_PER_RANK] =
{
/* port 0 */
{
@@ -2950,15 +2950,15 @@ extern "C" {
// 0x800000050301143f from disable1 register
const uint64_t l_wrclk_en_addr_mask = 0xFFFFFF07FFFFFFFFull;
fapi2::buffer<uint64_t> l_data_buffer;
- fapi2::variable_buffer l_db_reg(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank0(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank1(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank2(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank3(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank4(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank5(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank6(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_rank7(BITS_PER_PORT);
+ fapi2::variable_buffer l_db_reg(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank0(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank1(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank2(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank3(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank4(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank5(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank6(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_rank7(LANES_PER_PORT);
fapi2::buffer<uint64_t> l_put_mask;
uint8_t l_prg[MAX_RANKS_PER_DIMM][MAX_PORTS_PER_MBA] = {0}; // primary rank group values
fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> l_target_centaur;
@@ -3414,7 +3414,7 @@ extern "C" {
const uint8_t i_training_success)
{
// Registers to Flash.
- const uint64_t l_disable_reg[MAX_PORTS_PER_MBA][MAX_RANKS_PER_DIMM][DP18_INSTANCES] =
+ const uint64_t l_disable_reg[MAX_PORTS_PER_MBA][MAX_RANKS_PER_DIMM][MAX_BLOCKS_PER_RANK] =
{
/* port 0 */
{
@@ -3498,8 +3498,8 @@ extern "C" {
};
fapi2::buffer<uint64_t> l_data_buffer;
- fapi2::variable_buffer l_db_reg(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_vpd(BITS_PER_PORT);
+ fapi2::variable_buffer l_db_reg(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_vpd(LANES_PER_PORT);
uint8_t l_prg[MAX_RANKS_PER_DIMM][MAX_PORTS_PER_MBA] = {0}; // primary rank group values
uint8_t l_dram_width = 0;
uint8_t l_dimm = 0;
@@ -3528,14 +3528,14 @@ extern "C" {
uint8_t l_port = 0;
uint8_t l_prank = 0;
//Storing all the errors across rank/eff dimm
- fapi2::variable_buffer l_db_reg_dimm0_rank0(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_dimm0_rank1(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_dimm0_rank2(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_dimm0_rank3(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_dimm1_rank0(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_dimm1_rank1(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_dimm1_rank2(BITS_PER_PORT);
- fapi2::variable_buffer l_db_reg_dimm1_rank3(BITS_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm0_rank0(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm0_rank1(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm0_rank2(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm0_rank3(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm1_rank0(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm1_rank1(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm1_rank2(LANES_PER_PORT);
+ fapi2::variable_buffer l_db_reg_dimm1_rank3(LANES_PER_PORT);
FAPI_INF("Running (get)registers->flash");
@@ -3661,7 +3661,7 @@ extern "C" {
for ( uint8_t i = 0; i < DP18_INSTANCES; ++i ) // dp18 [0:4]
{
// clear bits 48:63
- FAPI_TRY(l_data_buffer.clearBit(48, BITS_PER_REG));
+ FAPI_TRY(l_data_buffer.clearBit(48, LANES_PER_BLOCK));
FAPI_TRY(fapi2::getScom(i_mba_target, l_disable_reg[l_port][l_prank][i],
l_data_buffer));
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.H
index 04c2c4356..fd9e632e4 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.H
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.H
@@ -30,7 +30,7 @@
/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
/// *HWP Team: Memory
/// *HWP Level: 2
-/// *HWP Consumed by: Memtools
+/// *HWP Consumed by: HB:CI
#ifndef mss_draminit_training_H_
#define mss_draminit_training_H_
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.mk
index 55c4b8c1e..e00589054 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.mk
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training.mk
@@ -33,5 +33,4 @@ OBJS+=p9c_mss_ddr4_funcs.o
OBJS+=p9c_mss_access_delay_reg.o
OBJS+=p9c_mss_unmask_errors.o
$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
-#lib$(PROCEDURE)_DEPLIBS+=mss
$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.C
new file mode 100755
index 000000000..8411ff877
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.C
@@ -0,0 +1,1812 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file p9c_mss_draminit_training_advanced.C
+/// @brief Tools for centaur procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: SARAVANAN SETHURAMAN <saravanans@in.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+// This procedure Schmoo's DRV_IMP, SLEW, VREF (DDR, CEN), RCV_IMP based on attribute from effective config procedure
+// DQ & DQS Driver impedance, Slew rate, WR_Vref shmoo would call only write_eye shmoo for margin calculation
+// DQ & DQS VREF (rd_vref), RCV_IMP shmoo would call rd_eye for margin calculation
+// Internal Vref controlled by this function & external vref
+
+// Not supported
+// DDR4, DIMM Types
+//----------------------------------------------------------------------
+// Includes - FAPI
+//----------------------------------------------------------------------
+
+#include <fapi2.H>
+#include <p9c_mss_termination_control.H>
+#include <p9c_mss_mcbist.H>
+#include <dimmConsts.H>
+#include <p9c_mss_draminit_training_advanced.H>
+#include <p9c_mss_unmask_errors.H>
+#include <p9c_mss_mrs6_DDR4.H>
+#include <p9c_mss_ddr4_pda.H>
+#include <p9c_mss_generic_shmoo.H>
+#include <generic/memory/lib/utils/c_str.H>
+
+const uint32_t MASK = 1;
+
+extern "C"
+{
+ ///
+ /// @brief Save and restore registers before and after shmoo
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @param[in,out] io_content_array Storage array to save to and restore from
+ /// @param[in] i_mode 0 = save 1 = restore
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_SaveAndRestore(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ uint64_t io_content_array[],
+ const uint8_t i_mode)
+ {
+ uint8_t l_index = 0;
+ uint8_t l_index1 = 0;
+ uint64_t l_value = 0;
+ uint64_t l_val_u64 = 0;
+ fapi2::buffer<uint64_t> l_mcbem1ab;
+ uint64_t l_register_array[6] = {CEN_MBA_MCBCFGQ, CEN_MBA_MBA_WRQ0Q, CEN_MBA_MBA_RRQ0Q, CEN_MBA_MBA_WRD_MODE, CEN_MBA_MBA_FARB3Q, CEN_MBA_MBARPC0Q};
+ uint64_t l_mbs_reg[2] = {CEN_ECC01_MBSECCQ, CEN_ECC23_MBSECCQ};
+
+ const auto l_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+
+ if(i_mode == 0) // MODE == SAVE
+ {
+ FAPI_INF("%s: Saving Register contents", mss::c_str(i_target_mba));
+
+ for(l_index = 0; l_index < 6; l_index++)
+ {
+ l_value = l_register_array[l_index];
+ FAPI_TRY(fapi2::getScom(i_target_mba, l_value, l_mcbem1ab));
+
+ FAPI_TRY(l_mcbem1ab.extract(io_content_array[l_index], 0, 64));
+ }
+
+ for(l_index = 6; l_index < 8; l_index++)
+ {
+
+ l_value = l_mbs_reg[l_index1];
+ FAPI_TRY(fapi2::getScom(l_target_centaur, l_value, l_mcbem1ab));
+ FAPI_TRY(l_mcbem1ab.extract(io_content_array[l_index], 0, 64));
+ l_index1++;
+ }
+ }
+
+ else if(i_mode == 1) // MODE == RESTORE
+ {
+ FAPI_INF("%s: Restoring Register contents", mss::c_str(i_target_mba));
+
+ for(l_index = 0; l_index < 6; l_index++)
+ {
+ l_val_u64 = io_content_array[l_index];
+ l_value = l_register_array[l_index];
+ FAPI_TRY(l_mcbem1ab.insert(l_val_u64, 0, 64), "Error in function mcb_SaveAndRestore");
+ FAPI_TRY(fapi2::putScom(i_target_mba, l_value, l_mcbem1ab));
+ }
+
+ l_index1 = 0;
+
+ for(l_index = 6; l_index < 8; l_index++)
+ {
+ l_val_u64 = io_content_array[l_index];
+ l_value = l_mbs_reg[l_index1];
+ FAPI_TRY(l_mcbem1ab.insert(l_val_u64, 0, 64), "Error in function mcb_SaveAndRestore");
+ FAPI_TRY(fapi2::putScom(l_target_centaur, l_value, l_mcbem1ab));
+ l_index1++;
+ }
+ }
+ else
+ {
+ FAPI_INF("%s: Invalid value of MODE", mss::c_str(i_target_mba));
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+}
+//end of extern C
+
+///
+/// @brief: varies drv&rcv imp, slew, wr&rd vref based on attribute definition and runs either mcbist/delay shmoo based on attribute
+/// @param[in] i_target_mba : Centaur MBA
+/// @return FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode p9c_mss_draminit_training_advanced(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+ uint8_t i_mode = 0;
+ uint64_t i_content_array[8] = {0};
+ FAPI_INF("+++++++ Executing mss_draminit_training_advanced +++++++");
+
+ // Define attribute variables
+ uint32_t l_attr_mss_freq_u32 = 0;
+ uint32_t l_attr_mss_volt_u32 = 0;
+ uint8_t l_num_drops_per_port_u8 = 2;
+ uint8_t l_num_ranks_per_dimm_u8array[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {{0}};
+ uint8_t l_port = 0;
+ uint32_t l_left_margin = 0;
+ uint32_t l_right_margin = 0;
+ uint32_t l_shmoo_param = 0;
+ uint8_t l_dram_type = 0;
+ uint8_t bin_pda = 0;
+ uint8_t vref_cal_control = 0;
+ uint8_t temp_cal_control = 0;
+ uint32_t int32_cal_control[2] = {0};
+ uint64_t int64_cal_control = 0;
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+
+ // Define local variables
+ uint8_t l_shmoo_type_valid_t = 0;
+ uint8_t l_shmoo_param_valid_t = 0;
+ enum dram_type { EMPTY = 0, DDR3 = 1, DDR4 = 2};
+ const auto l_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ //Save registers pre-shmoo
+ FAPI_TRY(mcb_SaveAndRestore(i_target_mba, i_content_array, i_mode));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT, l_target_centaur, l_attr_mss_volt_u32));
+ //Preet Add MSS_CAL control here
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VREF_CAL_CNTL, l_target_centaur, vref_cal_control));
+ FAPI_INF("+++++++++++ - DDR4 - CAL Control - %d ++++++++++++++++++++", vref_cal_control);
+
+
+ //const fapi::Target is centaur.mba
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT, i_target_mba, l_num_drops_per_port_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, l_num_ranks_per_dimm_u8array));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, l_dram_type));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_USER_BANK, i_target_mba, bin_pda));
+
+ if ((vref_cal_control == 0) && (l_dram_type == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4) && (bin_pda != 3))
+ {
+ FAPI_INF("+++++++++++++++++++++++++++++ - DDR4 - Skipping - V-Ref CAL Control +++++++++++++++++++++++++++++++++++++++++++++");
+ int32_cal_control[0] = 37;
+ l_shmoo_param_valid_t = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_MODE, i_target_mba, l_shmoo_param_valid_t));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_TEST_TYPE, i_target_mba, int32_cal_control[0]));
+ FAPI_TRY(wr_vref_shmoo_ddr4_bin(i_target_mba), "Write Vref Schmoo Function Failed");
+
+ // Disable Refresh DDR4 Requirement
+ if (l_dram_type == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ FAPI_INF("************* Disabling Refresh - DDR4 **************");
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ }
+ }
+
+ else if ((vref_cal_control != 0) && (l_dram_type == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4) && (bin_pda != 3))
+ {
+ FAPI_INF("+++++++++++++++++++++++++++++ - DDR4 - CAL Control +++++++++++ Training ++++++++++++ in Progress ++++++++++++++++");
+
+ temp_cal_control = 8;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_PARAM_VALID, i_target_mba, temp_cal_control));
+ temp_cal_control = 6;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_MODE, i_target_mba, temp_cal_control));
+ temp_cal_control = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_USER_BANK, i_target_mba, temp_cal_control));
+ temp_cal_control = 2;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, temp_cal_control));
+ l_shmoo_param_valid_t = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_RANK, i_target_mba, l_shmoo_param_valid_t));
+ l_shmoo_param_valid_t = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_MODE, i_target_mba, l_shmoo_param_valid_t));
+ int32_cal_control[0] = 0xFFFFFFFF;
+ int32_cal_control[1] = 0xFFFFFFFF;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_DRAM_WR_VREF_SCHMOO, i_target_mba, int32_cal_control));
+ int32_cal_control[0] = 37;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_TEST_TYPE, i_target_mba, int32_cal_control[0]));
+ int64_cal_control = 0x0000000000000000ull;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_START_ADDR, i_target_mba, int64_cal_control));
+ int64_cal_control = 0x0000001fc0000000ull;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_END_ADDR, i_target_mba, int64_cal_control));
+ }
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_USER_BANK, i_target_mba, bin_pda));
+
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ FAPI_INF("freq = %d on %s.", l_attr_mss_freq_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("volt = %d on %s.", l_attr_mss_volt_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("num_drops_per_port = %d on %s.", l_num_drops_per_port_u8, mss::c_str(i_target_mba));
+ FAPI_INF("num_ranks_per_dimm = [%02d][%02d][%02d][%02d]",
+ l_num_ranks_per_dimm_u8array[0][0],
+ l_num_ranks_per_dimm_u8array[0][1],
+ l_num_ranks_per_dimm_u8array[1][0],
+ l_num_ranks_per_dimm_u8array[1][1]);
+
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_shmoo_type_valid_t));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_SCHMOO_PARAM_VALID, i_target_mba, l_shmoo_param_valid_t));
+
+ shmoo_type_t l_shmoo_type_valid;
+ shmoo_param l_shmoo_param_valid;
+
+ l_shmoo_type_valid = (shmoo_type_t)l_shmoo_type_valid_t;
+ l_shmoo_param_valid = (shmoo_param)l_shmoo_param_valid_t;
+ FAPI_INF("+++++++++++++++++++++++++ Read Schmoo Attributes ++++++++++++++++++++++++++");
+ FAPI_INF("Schmoo param valid = 0x%x on %s", l_shmoo_param_valid, mss::c_str(i_target_mba));
+ FAPI_INF("Schmoo test valid = 0x%x on %s", l_shmoo_type_valid, mss::c_str(i_target_mba));
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ //Check for Shmoo Parameter, if anyof them is enabled then go into the loop else the procedure exit
+
+ if ((l_num_ranks_per_dimm_u8array[0][0] > 0) ||
+ (l_num_ranks_per_dimm_u8array[0][1] > 0) ||
+ (l_num_ranks_per_dimm_u8array[1][0] > 0) ||
+ (l_num_ranks_per_dimm_u8array[1][1] > 0))
+ {
+ FAPI_INF("ranks per dimm");
+
+ if ((l_shmoo_param_valid != PARAM_NONE) ||
+ (l_shmoo_type_valid != TEST_NONE))
+ {
+ FAPI_INF("shmoo param/type");
+
+ if ((l_shmoo_param_valid & DRV_IMP) != 0)
+ {
+ FAPI_TRY(drv_imped_shmoo(i_target_mba, l_port), "Driver Impedance Schmoo function is Failed");
+ }
+
+ if ((l_shmoo_param_valid & SLEW_RATE) != 0)
+ {
+ FAPI_TRY(slew_rate_shmoo(i_target_mba, l_port), "Slew Rate Schmoo Function is Failed");
+ }
+
+ if ((l_shmoo_param_valid & WR_VREF) != 0)
+ {
+ if(bin_pda == 1)
+ {
+ FAPI_INF("************* Bin - PDA - Vref_Schmoo **************");
+
+ FAPI_TRY(wr_vref_shmoo_ddr4_bin(i_target_mba), "Write Vref Schmoo Function is Failed");
+ }
+ else
+ {
+ FAPI_TRY(wr_vref_shmoo_ddr4(i_target_mba), "Write Vref Schmoo Function is Failed");
+ }
+
+ }
+
+ if ((l_shmoo_param_valid & RD_VREF) != 0)
+ {
+ FAPI_TRY(rd_vref_shmoo_ddr4(i_target_mba), "Read Vref Schmoo Function Failed");
+ }
+
+ if ((l_shmoo_param_valid & RCV_IMP) != 0)
+ {
+ FAPI_TRY(rcv_imp_shmoo(i_target_mba, l_port), "Receiver Impedance Schmoo Function is Failed");
+ }
+
+ if (((l_shmoo_param_valid == PARAM_NONE)))
+ {
+ FAPI_TRY(delay_shmoo(i_target_mba, l_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ l_shmoo_param), "Delay Schmoo Function is Failed");
+ }
+ }
+ }
+
+ // Disable Refresh DDR4 Requirement
+ if (l_dram_type == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4)
+ {
+ FAPI_INF("************* Disabling Refresh - DDR4 **************");
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ }
+
+ // If mss_unmask_draminit_training_advanced_errors gets it's own bad rc,
+ // it will commit the passed in rc (if non-zero), and return it's own bad rc.
+ // Else if mss_unmask_draminit_training_advanced_errors runs clean,
+ // it will just return the passed in rc.
+ FAPI_TRY(mss_unmask_draminit_training_advanced_errors(i_target_mba), "Unmask Function is Failed");
+ FAPI_TRY(mcb_SaveAndRestore(i_target_mba, i_content_array, 1));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief This function varies the driver impedance in the nominal mode
+/// @param[in] i_target_mba : Centaur input MBA
+/// @param[in] i_port : Centaur input port
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode drv_imped_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port)
+{
+ // for both dq/dqs & adr/cmd signals - DQ_DQS<24,30,34,40>,CMD_CNTL<15,20,30,40>
+ // if there is any mcbist failure, that will be reported to put_bad_bits function
+ uint8_t l_drv_imp_dq_dqs[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_drv_imp_dq_dqs_nom[MAX_PORTS_PER_MBA] = {0};
+ uint8_t index = 0;
+ uint8_t l_slew_rate_dq_dqs[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_slew_rate_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = {0};
+ uint32_t l_drv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_drv_imp_dq_dqs_nom_fc = 0;
+ uint8_t l_drv_imp_dq_dqs_in = 0;
+ //Temporary
+ const shmoo_type_t l_shmoo_type_valid = WR_EYE; //Hard coded, since no other schmoo is applicable for this parameter
+ uint32_t l_left_margin_drv_imp_array[MAX_DRV_IMP] = {0};
+ uint32_t l_right_margin_drv_imp_array[MAX_DRV_IMP] = {0};
+ uint32_t l_left_margin = 0;
+ uint32_t l_right_margin = 0;
+ uint8_t count = 0;
+ uint8_t shmoo_param_count = 0;
+ uint8_t l_slew_type = 0; // Hard coded since this procedure will touch only DQ_DQS and not address
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS, i_target_mba, l_slew_rate_dq_dqs));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS, i_target_mba, l_drv_imp_dq_dqs_nom));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO, i_target_mba, l_drv_imp_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS_SCHMOO, i_target_mba, l_slew_rate_dq_dqs_schmoo));
+
+ FAPI_INF("+++++++++++++++++Read DRIVER IMP Attributes values++++++++++++++++");
+ FAPI_INF("CEN_DRV_IMP_DQ_DQS[%d] = [%02d] Ohms, on %s",
+ i_port,
+ l_drv_imp_dq_dqs_nom[i_port],
+ mss::c_str(i_target_mba));
+ FAPI_INF("CEN_DRV_IMP_DQ_DQS_SCHMOO[0] = [0x%x], CEN_DRV_IMP_DQ_DQS_SCHMOO[1] = [0x%x] on %s",
+ l_drv_imp_dq_dqs_schmoo[0],
+ l_drv_imp_dq_dqs_schmoo[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("CEN_SLEW_RATE_DQ_DQS[0] = [%02d]V/ns , CEN_SLEW_RATE_DQ_DQS[1] = [%02d]V/ns on %s",
+ l_slew_rate_dq_dqs[0],
+ l_slew_rate_dq_dqs[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("CEN_SLEW_RATE_DQ_DQS_SCHMOO[0] = [0x%x], CEN_SLEW_RATE_DQ_DQS_SCHMOO[1] = [0x%x] on %s",
+ l_slew_rate_dq_dqs_schmoo[0],
+ l_slew_rate_dq_dqs_schmoo[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ if(l_drv_imp_dq_dqs_schmoo[i_port] == 0) //Check for any of the bits enabled in the shmoo
+ {
+ FAPI_INF("DRIVER IMP Shmoo set to FAST Mode and won't do anything");
+ }
+ else
+ {
+ for (index = 0; index < MAX_DRV_IMP; index += 1)
+ {
+ if (l_drv_imp_dq_dqs_schmoo[i_port] & MASK)
+ {
+ l_drv_imp_dq_dqs[i_port] = drv_imp_array[index];
+ FAPI_INF("Current Driver Impedance Value = %d Ohms",
+ drv_imp_array[index]);
+ FAPI_INF("Configuring Driver Impedance Registers:");
+ FAPI_TRY(config_drv_imp(i_target_mba, i_port,
+ l_drv_imp_dq_dqs[i_port]));
+ l_drv_imp_dq_dqs_in = l_drv_imp_dq_dqs[i_port];
+ FAPI_INF("Configuring Slew Rate Registers:");
+ FAPI_TRY(config_slew_rate(i_target_mba, i_port, l_slew_type,
+ l_drv_imp_dq_dqs[i_port],
+ l_slew_rate_dq_dqs[i_port]));
+ FAPI_INF("Calling Shmoo for finding Timing Margin:");
+
+ if (shmoo_param_count)
+ {
+ FAPI_TRY(set_attribute(i_target_mba));
+ }
+
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ l_drv_imp_dq_dqs_in));
+ l_left_margin_drv_imp_array[index] = l_left_margin;
+ l_right_margin_drv_imp_array[index] = l_right_margin;
+ shmoo_param_count++;
+ }
+ else
+ {
+ l_left_margin_drv_imp_array[index] = 0;
+ l_right_margin_drv_imp_array[index] = 0;
+ }
+
+ l_drv_imp_dq_dqs_schmoo[i_port] = (l_drv_imp_dq_dqs_schmoo[i_port] >> 1);
+ }
+
+ l_drv_imp_dq_dqs_nom_fc = l_drv_imp_dq_dqs_nom[i_port];
+ find_best_margin(DRV_IMP, l_left_margin_drv_imp_array,
+ l_right_margin_drv_imp_array, MAX_DRV_IMP,
+ l_drv_imp_dq_dqs_nom_fc, count);
+
+ FAPI_ASSERT(count < MAX_DRV_IMP,
+ fapi2::CEN_DRV_IMPED_SHMOO_INVALID_MARGIN_DATA().
+ set_COUNT_DATA(count),
+ "Driver Imp new input %d out of bounds, >= %d",
+ count,
+ MAX_DRV_IMP);
+
+ FAPI_INF("Restoring the nominal values!");
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS, i_target_mba, l_drv_imp_dq_dqs_nom));
+ FAPI_TRY(config_drv_imp(i_target_mba, i_port, l_drv_imp_dq_dqs_nom[i_port]));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS, i_target_mba, l_slew_rate_dq_dqs));
+ FAPI_TRY(config_slew_rate(i_target_mba, i_port, l_slew_type,
+ l_drv_imp_dq_dqs_nom[i_port],
+ l_slew_rate_dq_dqs[i_port]));
+
+ FAPI_INF("Restoring mcbist setup attribute...");
+ FAPI_TRY(reset_attribute(i_target_mba));
+ FAPI_INF("++++ Driver impedance shmoo function executed successfully ++++");
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief varies the slew rate of the data & adr signals (fast/slow)
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode slew_rate_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port)
+{
+ uint8_t l_slew_rate_dq_dqs[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_slew_rate_dq_dqs_nom[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_slew_rate_dq_dqs_nom_fc = 0;
+ uint8_t l_slew_rate_dq_dqs_in = 0;
+ uint32_t l_slew_rate_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_drv_imp_dq_dqs_nom[MAX_PORTS_PER_MBA] = {0};
+ const shmoo_type_t l_shmoo_type_valid = WR_EYE; // Hard coded - Other shmoo type is not valid - Temporary
+ uint8_t count = 0;
+ uint8_t shmoo_param_count = 0;
+ uint32_t l_left_margin_slew_array[MAX_NUM_SLEW_RATES] = {0};
+ uint32_t l_right_margin_slew_array[MAX_NUM_SLEW_RATES] = {0};
+ uint32_t l_left_margin = 0;
+ uint32_t l_right_margin = 0;
+ uint8_t l_slew_type = 0; // Hard coded since this procedure will touch only DQ_DQS and not address
+
+ //Read Attributes - DRV IMP, SLEW, SLEW RATES values to be Schmoo'ed
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS, i_target_mba, l_slew_rate_dq_dqs_nom));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO, i_target_mba, l_slew_rate_dq_dqs_schmoo));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS, i_target_mba, l_drv_imp_dq_dqs_nom));
+
+ FAPI_INF("+++++++++++++++++Read Slew Shmoo Attributes values+++++++++++++++");
+ FAPI_INF("CEN_DRV_IMP_DQ_DQS[0] = [%02d] Ohms, CEN_DRV_IMP_DQ_DQS[1] = [%02d] Ohms on %s",
+ l_drv_imp_dq_dqs_nom[0],
+ l_drv_imp_dq_dqs_nom[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("CEN_SLEW_RATE_DQ_DQS[0] = [%02d]V/ns , CEN_SLEW_RATE_DQ_DQS[1] = [%02d]V/ns on %s",
+ l_slew_rate_dq_dqs_nom[0],
+ l_slew_rate_dq_dqs_nom[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("CEN_SLEW_RATE_DQ_DQS_SCHMOO[0] = [0x%x], CEN_SLEW_RATE_DQ_DQS_SCHMOO[1] = [0x%x] on %s",
+ l_slew_rate_dq_dqs_schmoo[0],
+ l_slew_rate_dq_dqs_schmoo[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ if(l_slew_rate_dq_dqs_schmoo == 0) //Check for any of the bits enabled in the shmoo
+ {
+ FAPI_INF("Slew Rate Shmoo set to FAST Mode and won't do anything");
+ }
+ else
+ {
+ for (uint8_t index = 0; index < MAX_NUM_SLEW_RATES; index += 1)
+ {
+ if (l_slew_rate_dq_dqs_schmoo[i_port] & MASK)
+ {
+ l_slew_rate_dq_dqs[i_port] = slew_rate_array[index];
+ FAPI_INF("Current Slew rate value is %d V/ns",
+ slew_rate_array[index]);
+ FAPI_INF("Configuring Slew registers:");
+ FAPI_TRY(config_slew_rate(i_target_mba, i_port, l_slew_type,
+ l_drv_imp_dq_dqs_nom[i_port],
+ l_slew_rate_dq_dqs[i_port]));
+ l_slew_rate_dq_dqs_in = l_slew_rate_dq_dqs[i_port];
+ FAPI_INF("Calling Shmoo for finding Timing Margin:");
+
+ if (shmoo_param_count)
+ {
+ FAPI_TRY(set_attribute(i_target_mba));
+ }
+
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ l_slew_rate_dq_dqs_in));
+
+ l_left_margin_slew_array[index] = l_left_margin;
+ l_right_margin_slew_array[index] = l_right_margin;
+ shmoo_param_count++;
+ }
+ else
+ {
+ l_left_margin_slew_array[index] = 0;
+ l_right_margin_slew_array[index] = 0;
+ }
+
+ l_slew_rate_dq_dqs_schmoo[i_port]
+ = (l_slew_rate_dq_dqs_schmoo[i_port] >> 1);
+ } // end for index
+
+ l_slew_rate_dq_dqs_nom_fc = l_slew_rate_dq_dqs_nom[i_port];
+ find_best_margin(SLEW_RATE, l_left_margin_slew_array,
+ l_right_margin_slew_array, MAX_NUM_SLEW_RATES,
+ l_slew_rate_dq_dqs_nom_fc, count);
+
+ FAPI_ASSERT(count < MAX_NUM_SLEW_RATES,
+ fapi2::CEN_CONFIG_SLEW_RATE_INVALID_INPUT(),
+ "Driver Imp new input(%d) out of bounds, (>= %d)",
+ count,
+ MAX_NUM_SLEW_RATES);
+
+ FAPI_INF("Restoring the nominal values!");
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS, i_target_mba, l_drv_imp_dq_dqs_nom));
+ FAPI_TRY(config_drv_imp(i_target_mba, i_port, l_drv_imp_dq_dqs_nom[i_port]));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS, i_target_mba, l_slew_rate_dq_dqs_nom));
+ FAPI_TRY(config_slew_rate(i_target_mba, i_port, l_slew_type,
+ l_drv_imp_dq_dqs_nom[i_port],
+ l_slew_rate_dq_dqs_nom[i_port]));
+
+ FAPI_INF("Restoring mcbist setup attribute...");
+ FAPI_TRY(reset_attribute(i_target_mba));
+ FAPI_INF("++++ Slew Rate shmoo function executed successfully ++++");
+ } // end else
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief perform wr vref shmoo on DDR4 dimms
+/// @param[in] i_target_mba Centaur input MBA
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode wr_vref_shmoo_ddr4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+ uint8_t max_ddr4_vrefs1 = 51;
+ shmoo_type_t l_shmoo_type_valid = MCBIST; // Hard coded - Temporary
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ uint32_t l_left_margin = 0;
+ uint32_t l_right_margin = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_MAX_RANKS[MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint32_t base_percent = 60000;
+ uint32_t index_mul_print = 650;
+ uint8_t l_attr_schmoo_test_type_u8 = 1;
+ uint32_t vref_val_print = 0;
+ uint8_t vrefdq_train_range[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t vrefdq_train_value[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t vrefdq_train_enable[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint32_t vref_val = 0;
+ uint8_t l_vref_num = 0;
+ uint8_t i_port = 0;
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, num_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE, i_target_mba, vrefdq_train_range));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_attr_schmoo_test_type_u8));
+
+ if(vrefdq_train_range[0][0][0] == 1)
+ {
+ base_percent = 45000;
+ }
+
+ l_MAX_RANKS[0] = num_ranks_per_dimm[0][0] + num_ranks_per_dimm[0][1];
+ l_MAX_RANKS[1] = num_ranks_per_dimm[1][0] + num_ranks_per_dimm[1][1];
+
+ if ( l_attr_eff_dimm_type_u8 == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES )
+ {
+ l_SCHMOO_NIBBLES = 20;
+ }
+ else
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ FAPI_DBG(" +++ l_SCHMOO_NIBBLES = %d +++ ", l_SCHMOO_NIBBLES);
+ ///// ddr4 vref //////
+ FAPI_DBG("+++++++++++++++++++++++++++++++++++++++++++++ Patch - WR_VREF - Check Sanity only at 500 ddr4 +++++++++++++++++++++++++++");
+ FAPI_TRY(delay_shmoo_ddr4(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ vref_val));
+
+ FAPI_DBG(" Setup and Sanity - Check disabled from now on..... Continuing .....");
+ FAPI_TRY(set_attribute(i_target_mba));
+
+ l_shmoo_type_valid = WR_EYE;
+ l_attr_schmoo_test_type_u8 = 2;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_attr_schmoo_test_type_u8));
+ //Initialize all to zero
+
+ for(l_vref_num = 0; l_vref_num < max_ddr4_vrefs1; l_vref_num++)
+ {
+ vref_val = l_vref_num;
+ vref_val_print = base_percent + (l_vref_num * index_mul_print);
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ FAPI_INF("\n After Clearing Refresh");
+
+ for(uint8_t l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ for(uint8_t l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++)
+ {
+ for(uint8_t l_rank = 0; l_rank < MAX_RANKS_PER_DIMM; l_rank++)
+ {
+ vrefdq_train_enable[l_port][l_dimm][l_rank] = 0x00; // disable vref train enable attr
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE, i_target_mba, vrefdq_train_range));
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba));
+
+ for(uint8_t l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ for(uint8_t l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++)
+ {
+ for(uint8_t l_rank = 0; l_rank < l_MAX_RANKS[l_port]; l_rank++)
+ {
+ vrefdq_train_value[l_port][l_dimm][l_rank] = vref_val;
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value));
+
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba));
+
+ FAPI_INF("The Vref value is %d .... The percent voltage bump = %d ", vref_val, vref_val_print);
+
+ for(uint8_t l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ for(uint8_t l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++)
+ {
+ for(uint8_t l_rank = 0; l_rank < l_MAX_RANKS[l_port]; l_rank++)
+ {
+ vrefdq_train_enable[l_port][l_dimm][l_rank] = 0x01;
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba));
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.setBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+ FAPI_TRY(delay_shmoo_ddr4(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ vref_val));
+
+ FAPI_INF("Wr Vref = %d ; Min Setup time = %d; Min Hold time = %d",
+ vref_val_print,
+ l_left_margin,
+ l_right_margin);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Call mrs6 function until MR latch
+/// @param[in] i_target_mba Centaur input mba
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode latch_mrs6_val(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ uint8_t vrefdq_train_enable[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t latch_values[3] = {fapi2::ENUM_ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE_ENABLE, fapi2::ENUM_ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE_ENABLE, fapi2::ENUM_ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE_DISABLE};
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+ for(uint8_t latch_val = 0; latch_val < 3; latch_val++)
+ {
+ for(uint8_t port = 0; port < MAX_PORTS_PER_MBA; port++)
+ {
+ for(uint8_t dimm = 0; dimm < MAX_DIMM_PER_PORT; dimm++)
+ {
+ for(uint8_t rank = 0; rank < 4; rank++)
+ {
+ vrefdq_train_enable[port][dimm][rank] = latch_values[latch_val];
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), " mrs_load Failed");
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.setBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief perform binary wr vref shmoo on DDR4 dimms
+/// @param[in] i_target_mba Centaur input MBA
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode wr_vref_shmoo_ddr4_bin(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+ //uint8_t max_ddr4_vrefs1 = 52;
+ shmoo_type_t l_shmoo_type_valid = MCBIST;
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ fapi2::buffer<uint64_t> refresh_reg;
+ uint32_t l_left_margin = 0;
+ uint32_t l_right_margin = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t vrefdq_train_range[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ //uint8_t l_MAX_RANKS[2];
+ uint32_t total_val = 0;
+ uint32_t last_total = 0;
+ uint32_t base_percent = 60000;
+ uint32_t pda_nibble_table[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM][16][2]; // Port,Dimm,Rank,Nibble,[2]
+ uint32_t best_pda_nibble_table[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM][16][2];
+ uint8_t cal_control = 0;
+ ///// ddr4 vref //////
+ uint8_t vrefdq_train_value[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t vrefdq_train_enable[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint32_t vref_val = 0;
+ uint8_t i = 0;
+ uint8_t j = 0;
+ uint8_t k = 0;
+ uint8_t a = 0;
+ uint8_t c = 0;
+ uint32_t avg_best_vref = 0;
+ uint8_t l_dimm = 0;
+ uint8_t i_port = 0;
+ uint8_t l_vref_mid = 0;
+ uint8_t imax = 39;
+ uint8_t imin = 13;
+ uint8_t last_known_vref = 0;
+ uint8_t l_loop_count = 0;
+ uint8_t dram_width = 0;
+ vector<PDA_MRS_Storage> pda;
+ pda.clear();
+ uint32_t index_mul_print = 650;
+ uint8_t l_attr_schmoo_test_type_u8 = 1;
+ uint32_t vref_val_print = 0;
+ uint8_t vpd_wr_vref_value[2] = {0};
+ const auto l_target_centaur1 = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target_mba, dram_width));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target_mba, num_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE, i_target_mba, vrefdq_train_range));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_attr_schmoo_test_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRAM_WRDDR4_VREF, i_target_mba, vpd_wr_vref_value));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VREF_CAL_CNTL, l_target_centaur1, cal_control));
+ //FAPI_INF("++++++++++++++ATTR_CEN_MSS_VREF_CAL_CNTL = %d +++++++++++++++++++++++++++",cal_control);
+
+ if(vrefdq_train_range[0][0][0] == 1)
+ {
+ base_percent = 45;
+ }
+
+ FAPI_INF("Setting MCBIST DONE bit MASK as FW reports FIR bits!...");
+ //Workaround MCBIST MASK Bit as FW reports FIR bits --- > SET
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBSPAMSKQ, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.setBit(10), "Buffer error in function wr_vref_shmoo_ddr4_bin Workaround MCBIST MASK Bit");
+
+
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++ WR_VREF - Check Sanity only MCBIST +++++++++++++++++++++++++++");
+ FAPI_TRY(delay_shmoo_ddr4_pda(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ vref_val, pda_nibble_table));
+
+ FAPI_INF(" Setup and Sanity - Check disabled from now on..... Continuing .....");
+ FAPI_TRY(set_attribute(i_target_mba));
+
+ if(cal_control == 3)
+ {
+ l_shmoo_type_valid = BOX;
+ FAPI_INF("Running cal control 3 - box shmoo!!!");
+ l_attr_schmoo_test_type_u8 = 0x20;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_attr_schmoo_test_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value));
+ uint8_t vrefdq_train_value_plus[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t vrefdq_train_value_minus[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint8_t vref_train_step_size = 0;
+ FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CEN_MRW_WR_VREF_CHECK_VREF_STEP_SIZE, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ vref_train_step_size));
+
+ //sets up values
+ for(a = 0; a < MAX_PORTS_PER_MBA; a++) //Port
+ {
+ for(l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++) //Max dimms
+ {
+ for(c = 0; c < 4; c++) //Ranks
+ {
+ //sets up +5%
+ vrefdq_train_value_plus[a][l_dimm][c] = vrefdq_train_value[a][l_dimm][c] + vref_train_step_size;
+
+ //if over the max, then set to max val
+ if(vrefdq_train_value_plus[a][l_dimm][c] > 0x32)
+ {
+ vrefdq_train_value_plus[a][l_dimm][c] = 0x32;
+ }
+
+ //sets up -5%
+ if(vrefdq_train_value[a][l_dimm][c] < vref_train_step_size)
+ {
+ vrefdq_train_value_minus[a][l_dimm][c] = 0x00;
+ }
+ else
+ {
+ vrefdq_train_value_minus[a][l_dimm][c] = vrefdq_train_value[a][l_dimm][c] - vref_train_step_size;
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value_minus));
+ FAPI_TRY(latch_mrs6_val(i_target_mba));
+
+ //should run MCBIST -% VREF +/-X ticks write delay
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ (uint32_t)vref_train_step_size));
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value_plus));
+ FAPI_TRY(latch_mrs6_val(i_target_mba));
+
+ //should run MCBIST +% VREF +/-X ticks write delay
+
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ (uint32_t)(0xff - vref_train_step_size)));
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value));
+ FAPI_TRY(latch_mrs6_val(i_target_mba));
+
+ }
+
+ else if (cal_control != 0)
+ {
+ l_shmoo_type_valid = WR_EYE;
+ l_attr_schmoo_test_type_u8 = 2;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_attr_schmoo_test_type_u8));
+
+ //Initialise All to Zero [MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM]
+ for(k = 0; k < MAX_PORTS_PER_MBA; k++) // port
+ {
+ for(l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++) //Dimm
+ {
+ for(j = 0; j < MAX_RANKS_PER_DIMM; j++) //Rank
+ {
+ for(i = 0; i < 16; i++) //Nibble
+ {
+ pda_nibble_table[k][l_dimm][j][i][0] = 0; // Index 0 Are V-refs
+ pda_nibble_table[k][l_dimm][j][i][1] = 0; // Index 1 are Total Margin Values
+ best_pda_nibble_table[k][l_dimm][j][i][0] = 0; // Index 0 Are V-refs
+ best_pda_nibble_table[k][l_dimm][j][i][1] = 0; // Index 1 are Total Margin Values
+ }
+ }
+ }
+ }
+
+ while(imax >= imin)
+ {
+
+ if(l_loop_count == 0)
+ {
+ l_vref_mid = imin;
+ }
+ else
+ {
+ l_vref_mid = (imax + imin) / 2;
+ }
+
+ vref_val = l_vref_mid;
+ vref_val_print = base_percent + (l_vref_mid * index_mul_print);
+ FAPI_INF("The Vref value is = %d; The percent voltage bump = %d ", vref_val, vref_val_print);
+ //FAPI_INF("\n Before Clearing Refresh");
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ //FAPI_INF("\n After Clearing Refresh");
+
+ for(i = 0; i < MAX_PORTS_PER_MBA; i++)
+ {
+ for(j = 0; j < MAX_DIMM_PER_PORT; j++)
+ {
+ for(k = 0; k < MAX_RANKS_PER_DIMM; k++)
+ {
+
+ vrefdq_train_enable[i][j][k] = 0x01;
+
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE, i_target_mba, vrefdq_train_range));
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+
+ for(a = 0; a < MAX_PORTS_PER_MBA; a++) //Port
+ {
+ for(l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++) //Max dimms
+ {
+ for(c = 0; c < MAX_RANKS_PER_DIMM; c++) //Ranks
+ {
+
+ vrefdq_train_value[a][l_dimm][c] = vref_val;
+
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+ // Call it Twice to Latch (Steve)
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+
+ for(i = 0; i < MAX_PORTS_PER_MBA; i++)
+ {
+ for(j = 0; j < MAX_DIMM_PER_PORT; j++)
+ {
+ for(k = 0; k < MAX_RANKS_PER_DIMM; k++)
+ {
+ vrefdq_train_enable[i][j][k] = 0x00;
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.setBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+
+ FAPI_TRY(delay_shmoo_ddr4_pda(i_target_mba, i_port, l_shmoo_type_valid, &l_left_margin, &l_right_margin, vref_val,
+ pda_nibble_table));
+
+ total_val = l_right_margin + l_left_margin;
+ FAPI_INF("%s: Preet2 - %d ; Wr Vref = %d ; Min Setup time = %d; Min Hold time = %d and Total = %d",
+ mss::c_str(i_target_mba), vref_val, vref_val_print, l_left_margin, l_right_margin, total_val);
+
+ if(total_val > last_total)
+ {
+ last_known_vref = vref_val;
+ last_total = total_val;
+
+ if(l_loop_count != 0)
+ {
+ imin = l_vref_mid + 1;
+ }
+ }
+ else
+ {
+ imax = l_vref_mid - 1;
+ }
+
+ l_loop_count ++;
+
+ for(uint8_t i_port = 0; i_port < MAX_PORTS_PER_MBA; i_port++)
+ {
+ for(l_dimm = 0; l_dimm < 2; l_dimm++)
+ {
+ for(uint8_t i_rank = 0; i_rank < num_ranks_per_dimm[i_port][l_dimm]; i_rank++)
+ {
+ for(uint8_t i_nibble = 0; i_nibble < 16; i_nibble++)
+ {
+ if (best_pda_nibble_table[i_port][l_dimm][i_rank][i_nibble][1] < pda_nibble_table[i_port][l_dimm][i_rank][i_nibble][1])
+ {
+ best_pda_nibble_table[i_port][l_dimm][i_rank][i_nibble][1] = pda_nibble_table[i_port][l_dimm][i_rank][i_nibble][1];
+ best_pda_nibble_table[i_port][l_dimm][i_rank][i_nibble][0] = vref_val;
+ }
+ }
+ } //Rank Loop
+ } //dimm loop
+ } //Port loop
+ } //end of While
+
+
+ vref_val_print = base_percent + (last_known_vref * index_mul_print);
+ FAPI_INF("%s: Best V-Ref - %d - %d ; Total Window = %d", mss::c_str(i_target_mba), last_known_vref, vref_val_print,
+ last_total);
+ // What do we do Once we know best V-Ref
+
+ FAPI_TRY(fapi2::getScom( i_target_mba, CEN_MBA_MBAREF0Q, refresh_reg));
+ refresh_reg.clearBit<0>();
+ FAPI_TRY(fapi2::putScom( i_target_mba, CEN_MBA_MBAREF0Q, refresh_reg));
+
+ if(cal_control == 2)
+ {
+ FAPI_INF("CAL_CONTROL in RANK_Wise Mode!! ");
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+ for(i = 0; i < MAX_PORTS_PER_MBA; i++)
+ {
+ for(j = 0; j < MAX_DIMM_PER_PORT; j++)
+ {
+ for(k = 0; k < MAX_RANKS_PER_DIMM; k++)
+ {
+
+ vrefdq_train_enable[i][j][k] = 0x01;
+
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ //Calculate the Average V-Ref Value
+
+ for(uint8_t i_port = 0; i_port < MAX_PORTS_PER_MBA; i_port++)
+ {
+ for(uint8_t i_dimm = 0; i_dimm < MAX_DIMM_PER_PORT; i_dimm++)
+ {
+ for(uint8_t i_rank = 0; i_rank < num_ranks_per_dimm[i_port][i_dimm]; i_rank++)
+ {
+ for(uint8_t i_nibble = 0; i_nibble < 16; i_nibble++)
+ {
+
+ avg_best_vref = best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0] + avg_best_vref;
+ }
+
+ avg_best_vref = avg_best_vref / 16;
+ FAPI_INF("++ RANK_Wise ++++ Best Avg V-Ref = %d !! ", avg_best_vref);
+ vrefdq_train_value[i_port][i_dimm][i_rank] = avg_best_vref;
+
+ } //End of Rank Loop
+ } //end of dimm loop
+ } //End of Port Loop
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value));
+
+ //issue call to run_pda (entering into train mode)
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+
+ // Call it Twice to Latch (Steve)
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+
+ for(i = 0; i < MAX_PORTS_PER_MBA; i++)
+ {
+ for(j = 0; j < MAX_DIMM_PER_PORT; j++)
+ {
+ for(k = 0; k < MAX_RANKS_PER_DIMM; k++)
+ {
+
+ vrefdq_train_enable[i][j][k] = 0x00;
+
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+
+ } //end of RANK wise if
+ else
+ {
+ //1 - Issue PDA commands with enable train enable 1 for all DRAMs with good VREF values
+ uint32_t max_vref = 0;
+ uint8_t dram_num = 0;
+
+ for(uint8_t i_port = 0; i_port < MAX_PORTS_PER_MBA; i_port++)
+ {
+ for(uint8_t i_dimm = 0; i_dimm < MAX_DIMM_PER_PORT; i_dimm++)
+ {
+ for(uint8_t i_rank = 0; i_rank < num_ranks_per_dimm[i_port][i_dimm]; i_rank++)
+ {
+ for(uint8_t i_nibble = 0; i_nibble < 16; i_nibble++)
+ {
+ FAPI_INF("\n Port %d Dimm %d Rank:%d Pda_Nibble: %d V-ref:%d Margin:%d", i_port, i_dimm, i_rank, i_nibble,
+ best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0], best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][1]);
+
+ //if x8, averages the two nibbles together and, regardless, converts the DRAM over to the nibble
+ dram_num = i_nibble;
+ max_vref = best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0];
+
+ if(dram_width == fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X8)
+ {
+ i_nibble++;
+ dram_num = dram_num / 2;
+ max_vref += best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0];
+ max_vref = max_vref / 2;
+ }
+
+ FAPI_INF("\n Port %d Dimm %d Rank:%d Pda_Nibble: %d DRAM_num %d V-ref:%d Margin:%d", i_port, i_dimm, i_rank, i_nibble,
+ dram_num, best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0],
+ best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][1]);
+
+ pda.push_back(PDA_MRS_Storage(0x01, fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, dram_num, i_dimm, i_rank, i_port));
+ FAPI_INF("PDA STRING: %s %d %s", mss::c_str(i_target_mba), pda.size() - 1, pda[pda.size() - 1].c_str());
+ pda.push_back(PDA_MRS_Storage(max_vref, fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, dram_num, i_dimm, i_rank, i_port));
+ FAPI_INF("PDA STRING: %s %d %s", mss::c_str(i_target_mba), pda.size() - 1, pda[pda.size() - 1].c_str());
+ }
+
+
+ } //End of Rank Loop
+ } //end of dimm loop
+ } //End of Port Loop
+
+ FAPI_INF("RUNNING PDA FOR 1ST TIME");
+ FAPI_TRY(mss_ddr4_run_pda((fapi2::Target<fapi2::TARGET_TYPE_MBA>&)i_target_mba, pda));
+ FAPI_INF("FINISHED RUNNING PDA FOR 1ST TIME");
+
+ //issue call to run PDA again (latching good value in train mode)
+ FAPI_INF("RUNNING PDA FOR 2ND TIME");
+ FAPI_TRY(mss_ddr4_run_pda((fapi2::Target<fapi2::TARGET_TYPE_MBA>&)i_target_mba, pda));
+ FAPI_INF("FINISHED RUNNING PDA FOR 2ND TIME");
+ //clear the PDA vector
+ pda.clear();
+
+ //build PDA vector with good VREF values and train enable DISABLED
+
+ for(uint8_t i_port = 0; i_port < MAX_PORTS_PER_MBA; i_port++)
+ {
+ for(uint8_t i_dimm = 0; i_dimm < MAX_DIMM_PER_PORT; i_dimm++)
+ {
+ for(uint8_t i_rank = 0; i_rank < num_ranks_per_dimm[i_port][i_dimm]; i_rank++)
+ {
+ for(uint8_t i_nibble = 0; i_nibble < 16; i_nibble++)
+ {
+ //if x8, averages the two nibbles together and, regardless, converts the DRAM over to the nibble
+ dram_num = i_nibble;
+ max_vref = best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0];
+
+ if(dram_width == fapi2::ENUM_ATTR_CEN_EFF_DRAM_WIDTH_X8)
+ {
+ i_nibble++;
+ dram_num = dram_num / 2;
+ max_vref += best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0];
+ max_vref = max_vref / 2;
+ }
+
+ FAPI_INF("\n Port %d Dimm %d Rank:%d Pda_Nibble: %d DRAM_num %d V-ref:%d Margin:%d", i_port, i_dimm, i_rank, i_nibble,
+ dram_num, best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][0],
+ best_pda_nibble_table[i_port][i_dimm][i_rank][i_nibble][1]);
+
+ pda.push_back(PDA_MRS_Storage(0x00, fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, dram_num, i_dimm, i_rank, i_port));
+ FAPI_INF("%s PDA STRING: %d %s", mss::c_str(i_target_mba), pda.size() - 1, pda[pda.size() - 1].c_str());
+ pda.push_back(PDA_MRS_Storage(max_vref, fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, dram_num, i_dimm, i_rank, i_port));
+ FAPI_INF("%s PDA STRING: %d %s", mss::c_str(i_target_mba), pda.size() - 1, pda[pda.size() - 1].c_str());
+ }
+ } //End of Rank Loop
+ } //end of dimm loop
+ } //End of Port Loop
+
+ FAPI_INF("RUNNING PDA FOR 3RD TIME");
+ //issue call to PDA command
+ FAPI_TRY(mss_ddr4_run_pda((fapi2::Target<fapi2::TARGET_TYPE_MBA>&)i_target_mba, pda));
+ FAPI_INF("FINISHED RUNNING PDA FOR 3RD TIME");
+ } //End of Else
+
+ //turn on refresh then exit
+ FAPI_TRY(fapi2::getScom( i_target_mba, CEN_MBA_MBAREF0Q, refresh_reg));
+ refresh_reg.setBit<0>();
+ FAPI_TRY(fapi2::putScom( i_target_mba, CEN_MBA_MBAREF0Q, refresh_reg));
+
+ } // end of if
+
+ else //Skipping Shmoos ... Writing VPD data directly
+
+ {
+ vref_val_print = base_percent + (vpd_wr_vref_value[0] * index_mul_print);
+ FAPI_INF("The Vref value is from VPD = %d; The Voltage bump = %d ", vpd_wr_vref_value[0], vref_val_print);
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ //FAPI_INF("\n After Clearing Refresh");
+
+ for(i = 0; i < MAX_PORTS_PER_MBA; i++)
+ {
+ for(j = 0; j < MAX_DIMM_PER_PORT; j++)
+ {
+ for(k = 0; k < MAX_RANKS_PER_DIMM; k++)
+ {
+
+ vrefdq_train_enable[i][j][k] = 0x01;
+
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE, i_target_mba, vrefdq_train_range));
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+
+ for(a = 0; a < MAX_PORTS_PER_MBA; a++) //Port
+ {
+ for(l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++) //Max dimms
+ {
+ for(c = 0; c < MAX_RANKS_PER_DIMM; c++) //Ranks
+ {
+
+ vrefdq_train_value[a][l_dimm][c] = vpd_wr_vref_value[0];
+
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target_mba, vrefdq_train_value));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+
+ for(i = 0; i < MAX_PORTS_PER_MBA; i++)
+ {
+ for(j = 0; j < MAX_DIMM_PER_PORT; j++)
+ {
+ for(k = 0; k < MAX_RANKS_PER_DIMM; k++)
+ {
+
+ vrefdq_train_enable[i][j][k] = 0x00;
+
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_ENABLE, i_target_mba, vrefdq_train_enable));
+ FAPI_TRY(p9c_mss_mrs6_DDR4(i_target_mba), "mrs_load failed");
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+ l_data_buffer_64.setBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+ }
+
+ //Workaround MCBIST MASK Bit as FW reports FIR bits --- > CLEAR
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBSPAMSKQ, l_data_buffer_64));
+ l_data_buffer_64.clearBit<10>();
+
+//Read the write vref attributes
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Receiver impedance shmoo function varies 9 values
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode rcv_imp_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port)
+{
+ uint8_t l_rcv_imp_dq_dqs[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_rcv_imp_dq_dqs_nom[MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_rcv_imp_dq_dqs_nom_fc = 0;
+ uint8_t l_rcv_imp_dq_dqs_in = 0;
+ uint32_t l_rcv_imp_dq_dqs_schmoo[MAX_PORTS_PER_MBA] = {0};
+ uint8_t index = 0;
+ uint8_t count = 0;
+ uint8_t shmoo_param_count = 0;
+ const shmoo_type_t l_shmoo_type_valid = RD_EYE; //Hard coded since no other shmoo is applicable - Temporary
+
+ uint32_t l_left_margin = 0;
+ uint32_t l_right_margin = 0;
+ uint32_t l_left_margin_rcv_imp_array[MAX_RCV_IMP] = {0};
+ uint32_t l_right_margin_rcv_imp_array[MAX_RCV_IMP] = {0};
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_RCV_IMP_DQ_DQS, i_target_mba, l_rcv_imp_dq_dqs_nom));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO, i_target_mba, l_rcv_imp_dq_dqs_schmoo));
+
+ FAPI_INF("+++++++++++++++++RECIVER IMP Read Shmoo Attributes values+++++++++++++++");
+ FAPI_INF("CEN_RCV_IMP_DQ_DQS[0] = %d , CEN_RCV_IMP_DQ_DQS[1] = %d on %s",
+ l_rcv_imp_dq_dqs_nom[0],
+ l_rcv_imp_dq_dqs_nom[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("CEN_RCV_IMP_DQ_DQS_SCHMOO[0] = [%d], CEN_RCV_IMP_DQ_DQS_SCHMOO[1] = [%d], on %s",
+ l_rcv_imp_dq_dqs_schmoo[0],
+ l_rcv_imp_dq_dqs_schmoo[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+
+ if (l_rcv_imp_dq_dqs_schmoo[i_port] == 0)
+ {
+ FAPI_INF("FAST Shmoo Mode: This function will not change any Write DRAM VREF settings");
+ }
+ else
+ {
+ for (index = 0; index < MAX_RCV_IMP; index += 1)
+ {
+ if ((l_rcv_imp_dq_dqs_schmoo[i_port] & MASK) == 1)
+ {
+ l_rcv_imp_dq_dqs[i_port] = rcv_imp_array[index];
+ FAPI_INF("Current Receiver Impedance: %d Ohms ",
+ rcv_imp_array[index]);
+ FAPI_INF("Configuring Receiver impedance registers:");
+ FAPI_TRY(config_rcv_imp(i_target_mba, i_port,
+ l_rcv_imp_dq_dqs[i_port]));
+ l_rcv_imp_dq_dqs_in = l_rcv_imp_dq_dqs[i_port];
+
+ //FAPI_INF("Calling Shmoo function to find out timing margin:");
+ if (shmoo_param_count)
+ {
+ FAPI_TRY(set_attribute(i_target_mba));
+ }
+
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ l_rcv_imp_dq_dqs_in));
+ l_left_margin_rcv_imp_array[index] = l_left_margin;
+ l_right_margin_rcv_imp_array[index] = l_right_margin;
+ shmoo_param_count++;
+ }
+ else
+ {
+ l_left_margin_rcv_imp_array[index] = 0;
+ l_right_margin_rcv_imp_array[index] = 0;
+ }
+
+ l_rcv_imp_dq_dqs_schmoo[i_port] = (l_rcv_imp_dq_dqs_schmoo[i_port] >> 1);
+ }
+
+ l_rcv_imp_dq_dqs_nom_fc = l_rcv_imp_dq_dqs_nom[i_port];
+ find_best_margin(RCV_IMP, l_left_margin_rcv_imp_array,
+ l_right_margin_rcv_imp_array, MAX_RCV_IMP,
+ l_rcv_imp_dq_dqs_nom_fc, count);
+
+ if(count >= MAX_RCV_IMP)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_RCV_IMP_SHMOO_INVALID_MARGIN_DATA(),
+ "Receiver Imp new input(%d) out of bounds, (>= %d)",
+ count, MAX_RCV_IMP);
+ }
+ else
+ {
+ FAPI_INF("Restoring the nominal values!");
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_CEN_RCV_IMP_DQ_DQS, i_target_mba,
+ l_rcv_imp_dq_dqs_nom));
+ FAPI_TRY(config_rcv_imp(i_target_mba, i_port,
+ l_rcv_imp_dq_dqs_nom[i_port]));
+ }
+
+ FAPI_TRY(reset_attribute(i_target_mba));
+ FAPI_INF("++++ Receiver Impdeance Shmoo function executed successfully ++++");
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Calls Delay shmoo function varies delay values of each dq and returns timing margin
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @param[in] i_shmoo_type_valid Shmoo type MCBIST, WR_EYE, RD_EYE, WR_DQS, RD_DQS
+/// @param[out] o_left_margin returns left margin delay (setup) in ps
+/// @param[out] o_right_margin returns right margin delay (hold) in ps
+/// @param[in] i_shmoo_param Shmoo
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode delay_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port,
+ const shmoo_type_t i_shmoo_type_valid,
+ uint32_t* o_left_margin,
+ uint32_t* o_right_margin,
+ const uint32_t i_shmoo_param)
+{
+ //need to use fapi allocator to avoid memory fragmentation issues in Hostboot
+ // then use an in-place new to put the object in the pre-allocated memory
+ void* l_mallocptr = malloc(sizeof(generic_shmoo));
+ generic_shmoo* l_pShmoo = new (l_mallocptr) generic_shmoo(i_port, i_shmoo_type_valid, SEQ_LIN);
+ FAPI_TRY(l_pShmoo->run(i_target_mba, o_left_margin, o_right_margin, i_shmoo_param), "Delay Schmoo Function is Failed");
+ free(l_mallocptr);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Calls Delay shmoo function varies delay values of each dq and returns timing margin
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @param[in] i_shmoo_type_valid Shmoo type MCBIST, WR_EYE, RD_EYE, WR_DQS, RD_DQS
+/// @param[out] o_left_margin returns left margin delay (setup) in ps
+/// @param[out] o_right_margin returns right margin delay (hold) in ps
+/// @param[in] i_shmoo_param Shmoo
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode delay_shmoo_ddr4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port,
+ const shmoo_type_t i_shmoo_type_valid,
+ uint32_t* o_left_margin,
+ uint32_t* o_right_margin,
+ const uint32_t i_shmoo_param)
+{
+
+ //need to use fapi allocator to avoid memory fragmentation issues in Hostboot
+ // then use an in-place new to put the object in the pre-allocated memory
+ void* l_mallocptr = malloc(sizeof(generic_shmoo));
+ generic_shmoo* l_pShmoo = new (l_mallocptr) generic_shmoo(i_port, i_shmoo_type_valid, SEQ_LIN);
+
+ FAPI_TRY(l_pShmoo->run(i_target_mba, o_left_margin, o_right_margin, i_shmoo_param));
+
+ free(l_mallocptr);
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Calls Delay shmoo function varies delay values of each dq and returns timing margin
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @param[in] i_shmoo_type_valid Shmoo type MCBIST, WR_EYE, RD_EYE, WR_DQS, RD_DQS
+/// @param[out] o_left_margin returns left margin delay (setup) in ps
+/// @param[out] o_right_margin returns right margin delay (hold) in ps
+/// @param[in] i_shmoo_param Shmoo
+/// @param[in] i_pda_nibble_table
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode delay_shmoo_ddr4_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, uint8_t i_port,
+ shmoo_type_t i_shmoo_type_valid,
+ uint32_t* o_left_margin,
+ uint32_t* o_right_margin,
+ uint32_t i_shmoo_param, uint32_t i_pda_nibble_table[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM][16][2])
+{
+
+ //need to use fapi allocator to avoid memory fragmentation issues in Hostboot
+ // then use an in-place new to put the object in the pre-allocated memory
+ void* l_mallocptr = malloc(sizeof(generic_shmoo));
+ generic_shmoo* l_pShmoo = new (l_mallocptr) generic_shmoo(i_port, i_shmoo_type_valid, SEQ_LIN);
+
+ FAPI_TRY(l_pShmoo->run(i_target_mba, o_left_margin, o_right_margin, i_shmoo_param));
+
+ FAPI_TRY(l_pShmoo->get_nibble_pda(i_target_mba, i_pda_nibble_table));
+
+ free(l_mallocptr);
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Sets the attribute ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL used by all functions
+/// @param[in] i_target_mba Centaur input mba
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode set_attribute(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+ uint8_t l_mcbist_setup_multiple_set = 1; //Hard coded it wont change
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL, i_target_mba, l_mcbist_setup_multiple_set));
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+///@brief Read VREF shmoo (ddr4 dimms)
+///@param[in] i_target_mba Centaur input mba
+///@return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode rd_vref_shmoo_ddr4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+ shmoo_type_t l_shmoo_type_valid = MCBIST; // Hard coded - Temporary
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ fapi2::buffer<uint64_t> data_buffer;
+ uint32_t l_rd_cen_vref_schmoo[MAX_PORTS_PER_MBA] = {0};
+ uint32_t l_left_margin = 0;
+ uint32_t l_right_margin = 0;
+ uint32_t l_rd_cen_vref_in = 0;
+ uint8_t l_attr_schmoo_test_type_u8 = 1;
+ uint8_t i_port = 0;
+ uint32_t diff_value = 1375;
+ uint32_t base = 70000;
+ uint32_t vref_value_print = 0;
+ uint32_t l_left_margin_rd_vref_array[16] = {0};
+ uint32_t l_right_margin_rd_vref_array[16] = {0};
+ uint8_t l_vref_num = 0;
+ uint8_t l_vref_num_tmp = 0;
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_attr_schmoo_test_type_u8));
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++ Patch - Preet - RD_VREF - Check Sanity only - DDR4 +++++++++++++++++++++++++++");
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid,
+ &l_left_margin, &l_right_margin,
+ l_rd_cen_vref_in));
+ FAPI_INF(" Setup and Sanity - Check disabled from now on..... Continuing .....");
+ FAPI_TRY(set_attribute(i_target_mba));
+
+ l_shmoo_type_valid = RD_EYE;
+ l_attr_schmoo_test_type_u8 = 4;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target_mba, l_attr_schmoo_test_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_RD_VREF_SCHMOO, i_target_mba, l_rd_cen_vref_schmoo));
+
+
+ FAPI_INF("CEN_RD_VREF_SCHMOO[0] = [%x], CEN_RD_VREF_SCHMOO[1] = [%x] on %s",
+ l_rd_cen_vref_schmoo[0],
+ l_rd_cen_vref_schmoo[1],
+ mss::c_str(i_target_mba));
+ FAPI_INF("+++++++++++++++++++++++++++++++++++++++++++++ Patch - Preet - RD_VREF DDR4 +++++++++++++++++++++++++++");
+
+ //For DDR3 - DDR4 Range
+ if (l_rd_cen_vref_schmoo[i_port] == 1)
+ {
+ FAPI_INF("\n Testing Range - DDR3 to DDR4 - Vrefs");
+ base = 50000;
+ }
+ else
+ {
+ FAPI_INF("\n Testing Range - DDR4 Range Only - Vrefs");
+
+ for(l_vref_num_tmp = 8; l_vref_num_tmp > 0 ; l_vref_num_tmp--)
+ {
+ l_vref_num = l_vref_num_tmp - 1;
+ l_rd_cen_vref_in = l_vref_num;
+ vref_value_print = base - (l_vref_num * diff_value);
+ FAPI_INF("Current Vref value is %d", vref_value_print);
+ FAPI_INF("Configuring Read Vref Registers:");
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(l_rd_cen_vref_in, 56, 4), "config_rd_vref: Error in setting up buffer");
+ data_buffer.setBit<60>();
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_4,
+ data_buffer));
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(l_rd_cen_vref_in, 56, 4), "config_rd_vref: Error in setting up buffer ");
+ data_buffer.setBit<60>();
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_4,
+ data_buffer));
+
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid, &l_left_margin, &l_right_margin, vref_value_print));
+ l_left_margin_rd_vref_array[l_vref_num] = l_left_margin;
+ l_right_margin_rd_vref_array[l_vref_num] = l_right_margin;
+
+ FAPI_INF("Read Vref = %d ; Min Setup time = %d; Min Hold time = %d", vref_value_print,
+ l_left_margin_rd_vref_array[l_vref_num], l_right_margin_rd_vref_array[l_vref_num]);
+ }
+
+ // For base + values
+
+ for(l_vref_num = 8; l_vref_num < 16; l_vref_num++)
+ {
+
+ l_rd_cen_vref_in = l_vref_num;
+ vref_value_print = base + ((l_vref_num - 7) * diff_value);
+ FAPI_INF("Current Vref value is %d", vref_value_print);
+ FAPI_INF("Configuring Read Vref Registers:");
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(l_rd_cen_vref_in, 56, 4), "config_rd_vref: Error in setting up buffer ");
+ data_buffer.setBit<60>();
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_4,
+ data_buffer));
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(l_rd_cen_vref_in, 56, 4), "config_rd_vref: Error in setting up buffer ");
+ data_buffer.setBit<60>();
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_4,
+ data_buffer));
+
+ FAPI_TRY(delay_shmoo(i_target_mba, i_port, l_shmoo_type_valid, &l_left_margin, &l_right_margin, vref_value_print));
+ l_left_margin_rd_vref_array[l_vref_num] = l_left_margin;
+ l_right_margin_rd_vref_array[l_vref_num] = l_right_margin;
+
+ FAPI_INF("Read Vref = %d ; Min Setup time = %d; Min Hold time = %d", vref_value_print,
+ l_left_margin_rd_vref_array[l_vref_num], l_right_margin_rd_vref_array[l_vref_num]);
+ }
+
+
+ }
+
+ FAPI_INF("++++ Centaur Read Vref Shmoo function DDR4 done ! ++++");
+ FAPI_INF("Restoring mcbist setup attribute...");
+ FAPI_TRY(reset_attribute(i_target_mba));
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Sets the attribute ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL used by all functions
+/// @param[in] i_target_mba Centaur input mba
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode reset_attribute(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+ uint8_t l_mcbist_setup_multiple_reset = 0; //Hard coded it wont change
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL, i_target_mba, l_mcbist_setup_multiple_reset));
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Finds better timing margin and returns the index
+/// @param[in] i_shmoo_param_valid PARAM_NONE, DRV_IMP, SLEW_RATE, WR_VREF, RD_VREF, RCV_IMP
+/// @param[in] i_left[] timing margin array
+/// @param[in] i_right[] timing margin array
+/// @param[in] i_max Max enum value of schmoo param
+/// @param[in] i_param_nom selected shmoo parameter (DRV_IMP, SLEW_RATE, WR_VREF, RD_VREF, RCV_IMP)
+/// @param[in] o_index returns index
+///
+void find_best_margin(const shmoo_param i_shmoo_param_valid,
+ const uint32_t i_left[],
+ const uint32_t i_right[],
+ const uint8_t i_max,
+ const uint32_t i_param_nom,
+ uint8_t& o_index)
+{
+ uint32_t left_margin = 0;
+ uint32_t right_margin = 0;
+ uint32_t left_margin_nom = 0;
+ uint32_t right_margin_nom = 0;
+ uint32_t diff_margin_nom = 0;
+ uint32_t diff_margin = 0;
+ uint8_t index = 0;
+ uint8_t index2 = 0;
+
+ for (index = 0; index < i_max; index += 1) //send max from top function
+ {
+ if (i_shmoo_param_valid & DRV_IMP)
+ {
+ if (drv_imp_array[index] == i_param_nom)
+ {
+ left_margin_nom = i_left[index];
+ right_margin_nom = i_right[index];
+ diff_margin_nom = (i_left[index] >= i_right[index]) ?
+ (i_left[index] - i_right[index]) :
+ (i_right[index] - i_left[index]);
+ break;
+ }
+ }
+ else if (i_shmoo_param_valid & SLEW_RATE)
+ {
+ if (slew_rate_array[index] == i_param_nom)
+ {
+ left_margin_nom = i_left[index];
+ right_margin_nom = i_right[index];
+ diff_margin_nom = (i_left[index] >= i_right[index]) ?
+ (i_left[index] - i_right[index]) :
+ (i_right[index] - i_left[index]);
+ break;
+ }
+ }
+ else if (i_shmoo_param_valid & WR_VREF)
+ {
+ if (wr_vref_array_fitness[index] == i_param_nom)
+ {
+ left_margin_nom = i_left[index];
+ right_margin_nom = i_right[index];
+ diff_margin_nom = (i_left[index] >= i_right[index]) ?
+ (i_left[index] - i_right[index]) :
+ (i_right[index] - i_left[index]);
+ break;
+ }
+ }
+ else if (i_shmoo_param_valid & RD_VREF)
+ {
+ if (rd_cen_vref_array_fitness[index] == i_param_nom)
+ {
+ left_margin_nom = i_left[index];
+ right_margin_nom = i_right[index];
+ diff_margin_nom = (i_left[index] >= i_right[index]) ?
+ (i_left[index] - i_right[index]) :
+ (i_right[index] - i_left[index]);
+ break;
+ }
+ }
+ else if (i_shmoo_param_valid & RCV_IMP)
+ {
+ if (rcv_imp_array[index] == i_param_nom)
+ {
+ left_margin_nom = i_left[index];
+ right_margin_nom = i_right[index];
+ diff_margin_nom = (i_left[index] >= i_right[index]) ?
+ (i_left[index] - i_right[index]) :
+ (i_right[index] - i_left[index]);
+ break;
+ }
+ }
+ }
+
+ for (index2 = 0; index2 < i_max; index2 += 1)
+ {
+ left_margin = i_left[index2];
+ right_margin = i_right[index2];
+ diff_margin = (i_left[index2] >= i_right[index2]) ? (i_left[index2]
+ - i_right[index2]) : (i_right[index2] - i_left[index2]);
+
+ if ((left_margin > 0 && right_margin > 0))
+ {
+ if ((left_margin >= left_margin_nom) && (right_margin
+ >= right_margin_nom) && (diff_margin <= diff_margin_nom))
+ {
+ o_index = index2;
+ }
+ }
+ }
+}
+
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.H
new file mode 100755
index 000000000..5c30fcfd8
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.H
@@ -0,0 +1,194 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file mss_draminit_training_advanced.H
+/// @brief Tools for centaur procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#ifndef _MSS_DRAMINIT_TRAINING_ADVANCED_H
+#define _MSS_DRAMINIT_TRAINING_ADVANCED_H
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+#include <p9c_mss_shmoo_common.H>
+typedef fapi2::ReturnCode (*p9c_mss_draminit_training_advanced_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_MBA>&);
+
+///
+/// @brief Shmoo Param enums
+///
+enum shmoo_param
+{
+ PARAM_NONE = 0x00,
+ DELAY_REG = 0x01,
+ DRV_IMP = 0x02,
+ SLEW_RATE = 0x04,
+ WR_VREF = 0x08,
+ RD_VREF = 0x10,
+ RCV_IMP = 0x20
+};
+
+extern "C"
+{
+ ///
+ /// @brief Draminit training advanced procedure shmoo's drv_impedance, slew, vref and receiver impedance and get the optimum value
+ /// @param[in] i_target Reference to MBA target
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode p9c_mss_draminit_training_advanced(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief This function varies the driver impedance in the nominal mode
+ /// @param[in] i_target_mba : Centaur input MBA
+ /// @param[in] i_port : Centuar input port
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode drv_imped_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port); //done
+
+ ///
+ /// @brief varies the slew rate of the data & adr signals (fast/slow)
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_port Centaur input port
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode slew_rate_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port);
+
+ ///
+ /// @brief perform wr vref shmoo on DDR4 dimms
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode wr_vref_shmoo_ddr4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief perform binary wr vref shmoo on DDR4 dimms
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode wr_vref_shmoo_ddr4_bin(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ ///@brief Read VREF shmoo (ddr4 dimms)
+ ///@param[in] i_target_mba Centaur input mba
+ ///@return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode rd_vref_shmoo_ddr4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief Receiver impedance shmoo function varies 9 values
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_port Centaur input port
+ /// @param[in] i_shmoo_type_valid MCBIST, WR_EYE, RD_EYE, WR_DQS, RD_DQS
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode rcv_imp_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, uint8_t i_port);
+
+ ///
+ /// @brief Calls Delay shmoo function varies delay values of each dq and returns timing margin
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_port Centaur input port
+ /// @param[in] i_shmoo_type_valid Shmoo type MCBIST, WR_EYE, RD_EYE, WR_DQS, RD_DQS
+ /// @param[out] o_left_margin returns left margin delay (setup) in ps
+ /// @param[out] o_right_margin returns right margin delay (hold) in ps
+ /// @param[in] i_shmoo_param Shmoo
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode delay_shmoo(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port,
+ const shmoo_type_t i_shmoo_type_valid,
+ uint32_t* o_left_margin, uint32_t* o_right_margin,
+ uint32_t i_shmoo_param);
+
+ ///
+ /// @brief Calls Delay shmoo function varies delay values of each dq and returns timing margin
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_port Centaur input port
+ /// @param[in] i_shmoo_type_valid Shmoo type MCBIST, WR_EYE, RD_EYE, WR_DQS, RD_DQS
+ /// @param[out] o_left_margin returns left margin delay (setup) in ps
+ /// @param[out] o_right_margin returns right margin delay (hold) in ps
+ /// @param[in] i_shmoo_param Shmoo
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode delay_shmoo_ddr4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port,
+ const shmoo_type_t i_shmoo_type_valid,
+ uint32_t* o_left_margin, uint32_t* o_right_margin,
+ const uint32_t i_shmoo_param);
+
+ ///
+ /// @brief Calls Delay shmoo function varies delay values of each dq and returns timing margin
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_port Centaur input port
+ /// @param[in] i_shmoo_type_valid Shmoo type MCBIST, WR_EYE, RD_EYE, WR_DQS, RD_DQS
+ /// @param[out] o_left_margin returns left margin delay (setup) in ps
+ /// @param[out] o_right_margin returns right margin delay (hold) in ps
+ /// @param[in] i_shmoo_param Shmoo
+ /// @param[in] i_pda_nibble_table
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode delay_shmoo_ddr4_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port,
+ const shmoo_type_t i_shmoo_type_valid,
+ uint32_t* o_left_margin, uint32_t* o_right_margin,
+ const uint32_t i_shmoo_param, uint32_t i_pda_nibble_table[2][2][4][16][2]);
+ ///
+ /// @brief Finds better timing margin and returns the index
+ /// @param[in] i_shmoo_param_valid PARAM_NONE, DRV_IMP, SLEW_RATE, WR_VREF, RD_VREF, RCV_IMP
+ /// @param[in] i_left[] timing margin array
+ /// @param[in] i_right[] timing margin array
+ /// @param[in] i_max Max enum value of schmoo param
+ /// @param[in] i_param_nom selected shmoo parameter (DRV_IMP, SLEW_RATE, WR_VREF, RD_VREF, RCV_IMP)
+ /// @param[in] o_index returns index
+ ///
+ void find_best_margin(const shmoo_param i_shmoo_param_valid,
+ const uint32_t i_left[],
+ const uint32_t i_right[],
+ const uint8_t l_max,
+ const uint32_t i_param_nom,
+ uint8_t& o_index);
+
+ ///
+ /// @brief Sets the attribute ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL used by all functions
+ /// @param[in] i_target_mba Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode set_attribute(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief resets the attribute ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL used by all functions
+ /// @param[in] i_target_mba Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode reset_attribute(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+
+} // extern C
+
+#endif// _MSS_DRAMINIT_TRAINING_ADVANCED_H
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.mk
new file mode 100755
index 000000000..1f9f90a04
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.mk
@@ -0,0 +1,39 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_draminit_training_advanced.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+PROCEDURE=p9c_mss_draminit_training_advanced
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+OBJS+=p9c_mss_mcbist.o
+OBJS+=p9c_mss_mcbist_common.o
+OBJS+=p9c_mss_mcbist_address.o
+OBJS+=p9c_dimmBadDqBitmapFuncs.o
+OBJS+=p9c_mss_termination_control.o
+OBJS+=p9c_mss_generic_shmoo.o
+OBJS+=p9c_mss_mrs6_DDR4.o
+OBJS+=p9c_mss_access_delay_reg.o
+OBJS+=p9c_mss_funcs.o
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.C
new file mode 100755
index 000000000..c2c8327fc
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.C
@@ -0,0 +1,4591 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file p9c_mss_generic_shmoo.C
+/// @brief MSS Generic Shmoo Implementation
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#include <fapi2.H>
+#include <p9c_mss_generic_shmoo.H>
+#include <p9c_mss_mcbist.H>
+#include <p9c_mss_draminit_training.H>
+#include <p9c_dimmBadDqBitmapFuncs.H>
+#include <p9c_mss_access_delay_reg.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <dimmConsts.H>
+
+extern "C"
+{
+ ///
+ /// @brief Constructor used to initialize variables and do the initial settings
+ /// @param[in] addr Port number
+ /// @param[in] shmoo_type_t shmoo_mask set what shmoos caller wants to run
+ /// @param[in] shmoo_algorithm SEQ_LIN, PARALLEL etc.
+ ///
+ generic_shmoo::generic_shmoo(uint8_t addr, shmoo_type_t shmoo_mask, shmoo_algorithm_t shmoo_algorithm)
+ {
+ this->shmoo_mask = shmoo_mask; //! Sets what Shmoos the caller wants to run
+ this->algorithm = shmoo_algorithm ;
+ this->iv_shmoo_type = shmoo_mask;
+ this->iv_addr = addr;
+ iv_MAX_BYTES = 10;
+ iv_DQS_ON = 0;
+ iv_pattern = 0;
+ iv_test_type = 0;
+ iv_dmm_type = 0;
+ iv_shmoo_param = 0;
+ iv_binary_diff = 2;
+ iv_vref_mul = 0;
+ iv_SHMOO_ON = 0;
+
+ for(uint8_t p = 0; p < MAX_PORT; p++)
+ {
+ for(uint8_t i = 0; i < MAX_RANK; i++)
+ {
+ valid_rank1[p][i] = 0;
+ valid_rank[i] = 0;
+ }
+ }
+
+ iv_MAX_RANKS[0] = 4;
+ iv_MAX_RANKS[1] = 4;
+
+ if (shmoo_mask & TEST_NONE)
+ {
+ FAPI_INF("mss_generic_shmoo : NONE selected %d", shmoo_mask);
+ }
+
+ if (shmoo_mask & MCBIST)
+ {
+ FAPI_INF("mss_generic_shmoo : MCBIST selected %d", shmoo_mask);
+ iv_shmoo_type = 1;
+ }
+
+ if (shmoo_mask & WR_EYE)
+ {
+ FAPI_INF("mss_generic_shmoo : WR_EYE selected %d", shmoo_mask);
+ iv_shmoo_type = 2;
+ }
+
+ if (shmoo_mask & RD_EYE)
+ {
+ FAPI_INF("mss_generic_shmoo : RD_EYE selected %d", shmoo_mask);
+ iv_shmoo_type = 8;
+ }
+
+ if (shmoo_mask & WRT_DQS)
+ {
+ FAPI_INF("mss_generic_shmoo : WRT_DQS selected %d", shmoo_mask);
+ iv_shmoo_type = 4;
+ iv_DQS_ON = 1;
+ }
+
+ if(iv_DQS_ON == 1)
+ {
+ for (uint8_t k = 0; k < MAX_SHMOO; k++)
+ {
+ for (uint8_t i = 0; i < MAX_PORT; i++)
+ {
+ for (uint8_t j = 0; j < iv_MAX_RANKS[i]; j++)
+ {
+ init_multi_array(SHMOO[k].MBA.P[i].S[j].K.nom_val, 250);
+ init_multi_array(SHMOO[k].MBA.P[i].S[j].K.lb_regval, 0);
+ init_multi_array(SHMOO[k].MBA.P[i].S[j].K.rb_regval, 512);
+ init_multi_array(SHMOO[k].MBA.P[i].S[j].K.last_pass, 0);
+ init_multi_array(SHMOO[k].MBA.P[i].S[j].K.last_fail, 0);
+ init_multi_array(SHMOO[k].MBA.P[i].S[j].K.curr_val, 0);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// @brief Delegator function that runs shmoo using other functions
+ /// @param[in] i_target Centaur input mba
+ /// @param[out] o_right_min_margin Minimum hold time
+ /// @param[out] o_left_min_margin Minimum setup time
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::run(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t* o_right_min_margin,
+ uint32_t* o_left_min_margin,
+ uint32_t i_vref_mul)
+ {
+ uint8_t num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t l_attr_schmoo_test_type_u8 = 0;
+ uint8_t l_attr_schmoo_multiple_setup_call_u8 = 0;
+ uint8_t l_mcbist_prnt_off = 0;
+ uint64_t i_content_array[10];
+ uint8_t l_rankpgrp0[2] = { 0 };
+ uint8_t l_rankpgrp1[2] = { 0 };
+ uint8_t l_rankpgrp2[2] = { 0 };
+ uint8_t l_rankpgrp3[2] = { 0 };
+ uint8_t l_totrg_0 = 0;
+ uint8_t l_totrg_1 = 0;
+ uint8_t l_pp = 0;
+ uint8_t l_shmoo_param = 0;
+ uint8_t rank_table_port0[8] = {0};
+ uint8_t rank_table_port1[8] = {0};
+ uint8_t l_dram_gen = 0;
+ uint8_t i_rp = 0;
+ uint8_t l_dram_width = 0;
+ uint8_t eff_stack_type[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_SCHMOO_MODE, i_target, l_shmoo_param));
+ iv_shmoo_param = l_shmoo_param;
+ FAPI_INF(" +++++ The iv_shmoo_param = %d ++++ ", iv_shmoo_param);
+ iv_vref_mul = i_vref_mul;
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, l_dram_width));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_PRINTING_DISABLE, i_target, l_mcbist_prnt_off));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, num_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_SCHMOO_TEST_VALID, i_target, l_attr_schmoo_test_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SCHMOO_MULTIPLE_SETUP_CALL, i_target, l_attr_schmoo_multiple_setup_call_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP0, i_target, l_rankpgrp0));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP1, i_target, l_rankpgrp1));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP2, i_target, l_rankpgrp2));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_PRIMARY_RANK_GROUP3, i_target, l_rankpgrp3));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target, eff_stack_type));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target, l_dram_gen));
+ iv_MAX_RANKS[0] = num_ranks_per_dimm[0][0] + num_ranks_per_dimm[0][1];
+ iv_MAX_RANKS[1] = num_ranks_per_dimm[1][0] + num_ranks_per_dimm[1][1];
+ iv_pattern = 0;
+ iv_test_type = 0;
+
+ if ( l_attr_eff_dimm_type_u8 == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES )
+ {
+ iv_MAX_BYTES = 10;
+ }
+ else
+ {
+ iv_dmm_type = 1;
+ iv_MAX_BYTES = 9;
+ }
+
+ for(uint8_t l_rnk = 0; l_rnk < iv_MAX_RANKS[0]; l_rnk++)
+ {
+ // Byte loop
+ FAPI_TRY(mss_getrankpair(i_target, 0, 0, &i_rp, rank_table_port0));
+ }
+
+ for(uint8_t l_rnk = 0; l_rnk < iv_MAX_RANKS[0]; l_rnk++)
+ {
+ // Byte loop
+ FAPI_TRY(mss_getrankpair(i_target, 1, 0, &i_rp, rank_table_port1));
+ }
+
+ for(uint8_t l_p = 0; l_p < MAX_PORTS_PER_MBA; l_p++)
+ {
+ for(uint8_t l_rnk = 0; l_rnk < MAX_RANKS_PER_PORT; l_rnk++)
+ {
+ // Byte loop
+ if(l_p == 0)
+ {
+ valid_rank1[l_p][l_rnk] = rank_table_port0[l_rnk];
+ }
+ else
+ {
+ valid_rank1[l_p][l_rnk] = rank_table_port1[l_rnk];
+ }
+
+ if((l_attr_eff_dimm_type_u8 == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ && (eff_stack_type[l_p][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ && (l_dram_gen == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4))
+ {
+ //3ds 256 GB Dimm
+ //FAPI_INF("3DS - 2H 256GB");
+ rank_table_port0[0] = 0;
+ rank_table_port0[1] = 4;
+ rank_table_port0[2] = 255;
+ rank_table_port0[3] = 255;
+ rank_table_port1[0] = 0;
+ rank_table_port1[1] = 4;
+ rank_table_port1[2] = 255;
+ rank_table_port1[3] = 255;
+ }
+ }
+ }
+
+ FAPI_DBG("mss_generic_shmoo : run() for shmoo type %d", shmoo_mask);
+ FAPI_DBG("mss_generic_shmoo : run() l_attr_schmoo_test_type_u8 %d", l_attr_schmoo_test_type_u8);
+ // Check if all bytes/bits are in a pass condition initially .Otherwise quit
+
+ //Value of l_attr_schmoo_test_type_u8 are 0x01, 0x02, 0x04, 0x08, 0x10 ===
+ // "MCBIST","WR_EYE","RD_EYE","WRT_DQS","RD_DQS" resp.
+
+ if (l_attr_schmoo_test_type_u8 == 0)
+ {
+ FAPI_INF("%s:This procedure wont change any delay settings",
+ mss::c_str(i_target));
+ }
+
+ if (l_attr_schmoo_test_type_u8 == 1)
+ {
+
+ FAPI_TRY(sanity_check(i_target),
+ "generic_shmoo::run MSS Generic Shmoo failed initial Sanity Check. Memory not in an all pass Condition");
+
+ }
+
+ else if (l_attr_schmoo_test_type_u8 == 8)
+ {
+ if (l_rankpgrp0[0] != 255)
+ {
+ l_totrg_0++;
+ }
+
+ if (l_rankpgrp1[0] != 255)
+ {
+ l_totrg_0++;
+ }
+
+ if (l_rankpgrp2[0] != 255)
+ {
+ l_totrg_0++;
+ }
+
+ if (l_rankpgrp3[0] != 255)
+ {
+ l_totrg_0++;
+ }
+
+ if (l_rankpgrp0[1] != 255)
+ {
+ l_totrg_1++;
+ }
+
+ if (l_rankpgrp1[1] != 255)
+ {
+ l_totrg_1++;
+ }
+
+ if (l_rankpgrp2[1] != 255)
+ {
+ l_totrg_1++;
+ }
+
+ if (l_rankpgrp3[1] != 255)
+ {
+ l_totrg_1++;
+ }
+
+ if ((l_totrg_0 == 1) || (l_totrg_1 == 1))
+ {
+ FAPI_TRY(shmoo_save_rest(i_target, i_content_array, 0));
+ l_pp = 1;
+ }
+
+ if (l_pp == 1)
+ {
+ FAPI_INF("%s:Ping pong is disabled", mss::c_str(i_target));
+ }
+ else
+ {
+ FAPI_INF("%s:Ping pong is enabled", mss::c_str(i_target));
+ }
+
+ if ((l_pp = 1) && ((l_totrg_0 == 1) || (l_totrg_1 == 1)))
+ {
+ FAPI_INF("%s:Rank group is not good with ping pong. Hope you have set W2W gap to 10",
+ mss::c_str(i_target));
+ }
+
+ iv_shmoo_type = 4; //for Gate Delays
+ FAPI_TRY(get_all_noms_dqs(i_target));
+
+ iv_shmoo_type = 2; // For Access delays
+ FAPI_TRY(get_all_noms(i_target));
+
+ FAPI_TRY(schmoo_setup_mcb(i_target));
+ //Find RIGHT BOUND OR SETUP BOUND
+ FAPI_TRY(find_bound(i_target, RIGHT));
+
+ //Find LEFT BOUND OR HOLD BOUND
+ FAPI_TRY(find_bound(i_target, LEFT));
+ iv_shmoo_type = 4;
+
+ if (l_dram_width == 4)
+ {
+ FAPI_TRY(get_margin_dqs_by4(i_target));
+ }
+ else
+ {
+ FAPI_TRY(get_margin_dqs_by8(i_target));
+ }
+
+ FAPI_TRY(print_report_dqs(i_target));
+
+ FAPI_TRY(get_min_margin_dqs(i_target, o_right_min_margin, o_left_min_margin));
+
+ if ((l_totrg_0 == 1) || (l_totrg_1 == 1))
+ {
+ FAPI_TRY(shmoo_save_rest(i_target, i_content_array, 1));
+ }
+
+ FAPI_INF("%s: Least tDQSSmin(ps)=%d ps and Least tDQSSmax=%d ps", mss::c_str(i_target), *o_left_min_margin,
+ *o_right_min_margin);
+ }
+ else
+ {
+ FAPI_INF("************ ++++++++++++++++++ ***************** +++++++++++++ *****************");
+ FAPI_TRY(get_all_noms(i_target));
+
+ if(l_attr_schmoo_multiple_setup_call_u8 == 0)
+ {
+ FAPI_TRY(schmoo_setup_mcb(i_target));
+ }
+
+ FAPI_TRY(set_all_binary(i_target, RIGHT));
+ //Find RIGHT BOUND OR SETUP BOUND
+ FAPI_TRY(find_bound(i_target, RIGHT));
+ FAPI_TRY(set_all_binary(i_target, LEFT));
+ //Find LEFT BOUND OR HOLD BOUND
+ FAPI_TRY(find_bound(i_target, LEFT));
+
+ //Find the margins in Ps i.e setup margin ,hold margin,Eye width
+ FAPI_TRY(get_margin2(i_target));
+
+ //It is used to find the lowest of setup and hold margin
+ if(iv_shmoo_param == 6)
+ {
+ get_min_margin2(i_target, o_right_min_margin, o_left_min_margin);
+ FAPI_TRY(print_report2(i_target));
+ FAPI_INF("%s:Minimum hold margin=%d ps and setup margin=%d ps", mss::c_str(i_target), *o_left_min_margin,
+ *o_right_min_margin);
+ }
+ else
+ {
+ get_min_margin2(i_target, o_right_min_margin, o_left_min_margin);
+ FAPI_TRY(print_report2(i_target));
+ FAPI_INF("%s:Minimum hold margin=%d ps and setup margin=%d ps", mss::c_str(i_target), *o_left_min_margin,
+ *o_right_min_margin);
+ }
+ }
+
+ l_mcbist_prnt_off = 0;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_PRINTING_DISABLE, i_target, l_mcbist_prnt_off));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief save and restore registers before and after shmoo
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] i_content_array register contents to save/restore
+ /// @param[in] i_mode 0 = save; 1 = restore
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::shmoo_save_rest(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint64_t i_content_array[],
+ const uint8_t i_mode)
+ {
+ uint8_t l_index = 0;
+ uint64_t l_value = 0;
+ uint64_t l_val_u64 = 0;
+ fapi2::buffer<uint64_t> l_shmoo1ab;
+ uint64_t l_Databitdir[10] = { 0x800000030301143full,
+ 0x800004030301143full,
+ 0x800008030301143full,
+ 0x80000c030301143full,
+ 0x800010030301143full,
+ 0x800100030301143full,
+ 0x800104030301143full,
+ 0x800108030301143full,
+ 0x80010c030301143full,
+ 0x800110030301143full
+ };
+
+ if (i_mode == 0)
+ {
+ FAPI_INF("%s: Saving DP18 data bit direction register contents",
+ mss::c_str(i_target));
+
+ for (l_index = 0; l_index < MAX_BYTE; l_index++)
+ {
+ l_value = l_Databitdir[l_index];
+ FAPI_TRY(fapi2::getScom(i_target, l_value, l_shmoo1ab));
+ l_shmoo1ab.setBit<57>();
+ FAPI_TRY(fapi2::putScom(i_target, l_value, l_shmoo1ab));
+ l_shmoo1ab.extract<0, 64>(i_content_array[l_index]);
+ }
+ }
+ else if (i_mode == 1)
+ {
+ FAPI_INF("%s: Restoring DP18 data bit direction register contents",
+ mss::c_str(i_target));
+
+ for (l_index = 0; l_index < MAX_BYTE; l_index++)
+ {
+ l_val_u64 = i_content_array[l_index];
+ l_value = l_Databitdir[l_index];
+ l_shmoo1ab.insert<0, 64>(l_val_u64);
+ FAPI_TRY(fapi2::putScom(i_target, l_value, l_shmoo1ab));
+ }
+ }
+ else
+ {
+ FAPI_INF("%s:Invalid value of MODE", mss::c_str(i_target));
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief do intial mcbist check in nominal and report spd if any bad bit found
+ /// @param[in] i_target Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff succesful
+ ///
+ fapi2::ReturnCode generic_shmoo::sanity_check(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ mcbist_mode = QUARTER_SLOW;
+ uint8_t l_mcb_status = 0;
+ uint8_t l_CDarray0[DIMM_TO_C4_DQ_ENTRIES] = { 0 };
+ uint8_t l_CDarray1[DIMM_TO_C4_DQ_ENTRIES] = { 0 };
+ uint8_t l_byte, l_rnk = 0;
+ uint8_t l_nibble = 0;
+ uint8_t l_p = 0;
+ uint8_t rank = 0;
+ uint8_t l_faulted_rank = 255;
+ uint8_t l_faulted_port = 255;
+ uint8_t l_faulted_dimm = 255;
+ uint8_t l_memory_health = 0;
+ uint8_t l_max_byte = 10;
+
+ struct subtest_info l_sub_info[30];
+
+ FAPI_TRY(schmoo_setup_mcb(i_target));
+ FAPI_DBG("%s: starting mcbist now", mss::c_str(i_target));
+ FAPI_TRY(start_mcb(i_target));
+ FAPI_DBG("%s: polling mcbist now", mss::c_str(i_target));
+ FAPI_TRY(poll_mcb(i_target, &l_mcb_status, l_sub_info, 1), "generic_shmoo::do_mcbist_test: POLL MCBIST failed !!");
+ FAPI_DBG("%s: checking error map ", mss::c_str(i_target));
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1,
+ count_bad_dq));
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ // Byte loop
+ rank = valid_rank1[l_p][l_rnk];
+
+ for (l_byte = 0; l_byte < l_max_byte; l_byte++)
+ {
+ //Nibble loop
+ for (l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ if (mcbist_error_map[l_p][rank][l_byte][l_nibble] == 1)
+ {
+ l_memory_health = 1;
+ l_faulted_rank = rank;
+ l_faulted_port = l_p;
+
+ if(rank > 3)
+ {
+ l_faulted_dimm = 1;
+ }
+ else
+ {
+ l_faulted_dimm = 0;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //////////////// changed the check condition ... The error call out need to gard the dimm=l_faulted_dimm(0 or 1) //// port=l_faulted_port(0 or 1) target=i_target ...
+ FAPI_ASSERT(!l_memory_health,
+ fapi2::CEN_MSS_GENERIC_SHMOO_MCBIST_FAILED().
+ set_MBA_CHIPLET(i_target).
+ set_MBA_PORT_NUMBER(l_faulted_port).
+ set_MBA_DIMM_NUMBER(l_faulted_dimm),
+ "generic_shmoo:sanity_check failed !! MCBIST failed on %s initial run , memory is not in good state needs investigation port=%d rank=%d dimm=%d",
+ mss::c_str(i_target),
+ l_faulted_port,
+ l_faulted_rank,
+ l_faulted_dimm);
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+ ///
+ /// @brief do mcbist reset
+ /// @param[in] i_target Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::do_mcbist_reset(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ const auto i_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ l_data_buffer_64.flush<0>();
+ //PORT - A
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBEMA1Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBEMA2Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBEMA3Q, l_data_buffer_64));
+
+ //PORT - B
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBEMB1Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBEMB2Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBEMB3Q, l_data_buffer_64));
+
+ // MBS 23
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201176a, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201176b, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201176c, l_data_buffer_64));
+
+ //PORT - B
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201176d, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201176e, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201176f, l_data_buffer_64));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief do mcbist check for error on particular nibble
+ /// @param[in] i_target: centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::do_mcbist_test(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_mcb_status = 0;
+ struct subtest_info l_sub_info[30];
+
+ FAPI_TRY(start_mcb(i_target), "generic_shmoo::do_mcbist_test: Start MCBIST failed !!");
+ FAPI_TRY(poll_mcb(i_target, &l_mcb_status, l_sub_info, 1), "generic_shmoo::do_mcbist_test: POLL MCBIST failed !!");
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief used by do_mcbist_test to check the error map for particular nibble
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] l_p Centaur input port
+ /// @param[out] pass 1 = error found in mcb_error_map
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::check_error_map(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint8_t l_p,
+ uint8_t& pass)
+ {
+ uint8_t l_byte, l_rnk = 0;
+ uint8_t l_nibble = 0;
+ uint8_t l_byte_is = 0;
+ uint8_t l_nibble_is = 0;
+ uint8_t l_n = 0;
+ pass = 1;
+ input_type l_input_type_e = ISDIMM_DQ;
+ uint8_t i_input_index_u8 = 0;
+ uint8_t l_val = 0;
+ uint8_t rank = 0;
+ uint8_t l_max_byte = 10;
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+
+ if(iv_dmm_type == 1)
+ {
+ l_max_byte = 9;
+ }
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ // Byte loop
+ rank = valid_rank1[l_p][l_rnk];
+ l_n = 0;
+
+ for(l_byte = 0; l_byte < l_max_byte; l_byte++)
+ {
+ //Nibble loop
+ for(l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ if(iv_dmm_type == 1)
+ {
+ i_input_index_u8 = 8 * l_byte + 4 * l_nibble;
+
+ FAPI_TRY(rosetta_map(i_target, l_p, l_input_type_e, i_input_index_u8, 0, l_val));
+
+ l_byte_is = l_val / 8;
+ l_nibble_is = l_val % 8;
+
+ if(l_nibble_is > 3)
+ {
+ l_nibble_is = 1;
+ }
+ else
+ {
+ l_nibble_is = 0;
+ }
+
+ if( mcbist_error_map [l_p][rank][l_byte_is][l_nibble_is] == 1)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ pass = 1;
+ }
+ else
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ pass = 0;
+ }
+ }
+ else
+ {
+ if( mcbist_error_map [l_p][rank][l_byte][l_nibble] == 1)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ pass = 1;
+ }
+ else
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ pass = 0;
+ }
+ }
+
+ l_n++;
+ }//end of nibble loop
+ }//end byte loop
+ }//end rank loop
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief used by do_mcbist_test to check the error map for particular nibble
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] l_p Centaur input port
+ /// @param[out] pass 1 = error found in mcb_error_map
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::check_error_map2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint8_t port,
+ uint8_t& pass)
+ {
+ uint8_t l_byte, l_rnk = 0;
+ uint8_t l_nibble = 0;
+ uint8_t l_byte_is = 0;
+ uint8_t l_nibble_is = 0;
+ uint8_t l_n = 0;
+ pass = 1;
+ uint8_t l_p = 0;
+ input_type l_input_type_e = ISDIMM_DQ;
+ uint8_t i_input_index_u8 = 0;
+ uint8_t l_val = 0;
+ uint8_t rank = 0;
+ uint8_t l_max_byte = 10;
+ uint8_t l_max_nibble = 20;
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+
+ if(iv_dmm_type == 1)
+ {
+ l_max_byte = 9;
+ l_max_nibble = 18;
+ }
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ rank = valid_rank1[l_p][l_rnk];
+ l_n = 0;
+
+ // Byte loop
+ for(l_byte = 0; l_byte < l_max_byte; l_byte++)
+ {
+ //Nibble loop
+ for(l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ if(iv_dmm_type == 1)
+ {
+ i_input_index_u8 = BITS_PER_BYTE * l_byte + BITS_PER_NIBBLE * l_nibble;
+
+ FAPI_TRY(rosetta_map(i_target, l_p, l_input_type_e, i_input_index_u8, 0, l_val));
+
+ l_byte_is = l_val / BITS_PER_BYTE;
+ l_nibble_is = l_val % BITS_PER_BYTE;
+
+ if(l_nibble_is > 3)
+ {
+ l_nibble_is = 1;
+ }
+ else
+ {
+ l_nibble_is = 0;
+ }
+
+ if( mcbist_error_map [l_p][rank][l_byte_is][l_nibble_is] == 1)
+ {
+ //pass=0;
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ else
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ }
+
+ }
+ else
+ {
+ if( mcbist_error_map [l_p][rank][l_byte][l_nibble] == 1)
+ {
+ //pass=0;
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ //FAPI_INF("We are in error and nibble is %d and rank is %d and port is %d \n",l_n,rank,l_p);
+ }
+ else
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ }
+ }
+
+ l_n++;
+ } // for nibble
+ } // for byte
+ } // for rank
+ } // for port
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ // Byte loop
+ rank = valid_rank1[l_p][l_rnk];
+
+ for (l_n = 0; l_n < l_max_nibble; l_n++)
+ {
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ pass = 0;
+ }
+
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+
+
+
+ ///
+ /// @brief This function does the initialization of various schmoo parameters
+ /// @param[out] array address
+ /// @param[in] init_val initial value to initialize to
+ ///
+ void generic_shmoo::init_multi_array(uint16_t(&array)[MAX_DQ],
+ const uint16_t init_val)
+ {
+ uint8_t l_byte, l_nibble, l_bit = 0;
+ uint8_t l_dq = 0;
+
+ // Byte loop
+ for (l_byte = 0; l_byte < iv_MAX_BYTES; l_byte++)
+ {
+ //Nibble loop
+ for (l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ //Bit loop
+ for (l_bit = 0; l_bit < MAX_BITS; l_bit++)
+ {
+ l_dq = 8 * l_byte + 4 * l_nibble + l_bit;
+ array[l_dq] = init_val;
+ }
+ }
+ }
+ }
+
+ ///
+ /// @brief set all bits
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::set_all_binary(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound)
+ {
+ uint8_t l_rnk, l_byte, l_nibble, l_bit = 0;
+ uint8_t l_dq = 0;
+ uint8_t l_p = 0;
+ uint32_t l_max = 512;
+ uint32_t l_max_offset = 64;
+ uint8_t rank = 0;
+
+ //if RD_EYE
+ if(iv_shmoo_type == 8)
+ {
+ l_max = 127;
+ }
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ rank = valid_rank1[l_p][l_rnk];
+
+ for(l_byte = 0; l_byte < iv_MAX_BYTES; l_byte++)
+ {
+ for(l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ for(l_bit = 0; l_bit < MAX_BITS; l_bit++)
+ {
+ l_dq = (BITS_PER_BYTE * l_byte) + (BITS_PER_NIBBLE * l_nibble) + l_bit;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq];
+
+ if(bound == RIGHT)
+ {
+ if((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] + l_max_offset) > l_max)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] = l_max;
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_max_offset;
+ }
+ }
+
+ else
+ {
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] > 64)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_max_offset;
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] = 0;
+ }
+ }
+ } // bit loop
+ } // nibble loop
+ } // byte loop
+ } // rank loop
+ } // port loop
+
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+
+ ///
+ /// @brief This function gets the nominal values for each DQ
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::get_all_noms(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk, l_byte, l_nibble, l_bit = 0;
+ uint8_t i_rnk = 0;
+ uint16_t val = 0;
+ uint8_t l_dq = 0;
+ uint8_t l_p = 0;
+ input_type_t l_input_type_e = WR_DQ;
+ access_type_t l_access_type_e = READ;
+ FAPI_DBG("mss_generic_shmoo : get_all_noms : Reading in all nominal values");
+
+ if(iv_shmoo_type == 2)
+ {
+ l_input_type_e = WR_DQ;
+ }
+ else if(iv_shmoo_type == 8)
+ {
+ l_input_type_e = RD_DQ;
+ }
+ else if(iv_shmoo_type == 16)
+ {
+ l_input_type_e = RD_DQS;
+ }
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ // Byte loop
+ i_rnk = valid_rank1[l_p][l_rnk];
+
+ for(l_byte = 0; l_byte < iv_MAX_BYTES; l_byte++)
+ {
+ //Nibble loop
+ for(l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ //Bit loop
+ for(l_bit = 0; l_bit < MAX_BITS; l_bit++)
+ {
+ l_dq = 8 * l_byte + 4 * l_nibble + l_bit;
+ FAPI_INF("Before access call");
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, i_rnk, l_input_type_e, l_dq, 1, val));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rnk].K.nom_val[l_dq] = val;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rnk].K.rb_regval[l_dq] = val;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rnk].K.lb_regval[l_dq] = val;
+
+ }
+ }
+ }
+ }
+ }
+
+ FAPI_INF("get all noms done");
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Read in all nominal values
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::get_all_noms_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk = 0;
+ uint32_t val = 0;
+ uint8_t l_p = 0;
+ uint8_t l_max_nibble = 20;
+ uint8_t rank = 0;
+ uint8_t l_n = 0;
+ FAPI_INF("%s:mss_generic_shmoo : get_all_noms_dqs : Reading in all nominal values and schmoo type=%d \n",
+ mss::c_str(i_target), 1);
+
+ if(iv_dmm_type == 1)
+ {
+ l_max_nibble = 18;
+ }
+
+ input_type_t l_input_type_e = WR_DQS;
+ access_type_t l_access_type_e = READ ;
+ FAPI_DBG("mss_generic_shmoo : get_all_noms : Reading in all nominal values");
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ rank = valid_rank1[l_p][l_rnk];
+
+ for (l_n = 0; l_n < l_max_nibble; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_n, 0, val));
+ SHMOO[1].MBA.P[l_p].S[rank].K.nom_val[l_n] = val;
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This is a key function is used to find right and left bound using new algorithm -- there is an option u can chose not to use it by setting a flag
+ /// @param[in] i_target Centaur input MBA Parameters: Target:MBA,bound:RIGHT/LEFT,scenario:type of schmoo,iv_port:0/1,rank:0-7,byte:0-7,nibble:0/1,bit:0-3,pass,
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::knob_update(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass)
+ {
+ fapi2::buffer<uint64_t> data_buffer_64;
+ fapi2::buffer<uint64_t> data_buffer_64_1;
+ input_type_t l_input_type_e = WR_DQ;
+ uint8_t l_dq = 0;
+ access_type_t l_access_type_e = WRITE;
+ uint8_t l_n = 0;
+ uint8_t l_i = 0;
+ uint8_t l_p = 0;
+ uint16_t l_delay = 0;
+ uint16_t l_max_limit = 500;
+ uint8_t rank = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint8_t l_CDarray0[CDIMM_MAX_DQ_80] = {0};
+ uint8_t l_CDarray1[CDIMM_MAX_DQ_80] = {0};
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ //l_SCHMOO_NIBBLES = 2; //temp preet del this
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+
+ FAPI_INF("Linear in Progress FW --> %d", scenario);
+
+ if(iv_shmoo_type == 2)
+ {
+ l_input_type_e = WR_DQ;
+ }
+ else if(iv_shmoo_type == 8)
+ {
+ l_input_type_e = RD_DQ;
+ l_max_limit = 127;
+ }
+ else if(iv_shmoo_type == 4)
+ {
+ l_input_type_e = WR_DQS;
+ }
+
+ for (l_p = 0; l_p < 2; l_p++)
+ {
+ for(uint8_t i = 0; i < iv_MAX_RANKS[l_p]; i++)
+ {
+
+ rank = valid_rank1[l_p][i];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ }
+ }
+ }
+
+ if(bound == RIGHT)
+ {
+ for (l_delay = 1; ((pass == 0)); l_delay = l_delay + 1)
+ {
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 1,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+
+ }
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq));
+
+
+ if(l_p == 0)
+ {
+
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+
+ if(l_CDarray0[l_i] == l_dq)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+
+ if(l_CDarray1[l_i] == l_dq)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] > l_max_limit)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+
+
+ l_dq = l_dq + 4;
+
+ } //end of nibble
+ } //end of rank
+ } //end of port loop
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 35)
+ {
+ break;
+ }
+ } //end of Delay loop;
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 1,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+
+
+ }
+
+ if(bound == LEFT)
+ {
+ for (l_delay = 1; (pass == 0); l_delay += 1)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+
+
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ }
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq));
+
+ if(l_p == 0)
+ {
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+ if(l_CDarray0[l_i] == l_dq)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+ if(l_CDarray1[l_i] == l_dq)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] == 0)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+
+ l_dq = l_dq + 4;
+
+ }
+ }
+
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 35)
+ {
+ break;
+ }
+ }
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+
+
+
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::knob_update_bin(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass)
+ {
+ fapi2::buffer<uint64_t> data_buffer_64;
+ fapi2::buffer<uint64_t> data_buffer_64_1;
+ input_type_t l_input_type_e = WR_DQ;
+ uint8_t l_dq = 0;
+ access_type_t l_access_type_e = WRITE;
+ uint8_t l_n = 0;
+ uint8_t l_i = 0;
+ uint8_t l_flag_p0 = 0;
+ uint8_t l_flag_p1 = 0;
+ FAPI_INF("Inside - Binary Schmoo FW - %d", scenario);
+ uint8_t l_p = 0;
+ uint8_t rank = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint8_t l_status = 1;
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+ int count_cycle = 0;
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ if(iv_shmoo_type == 2)
+ {
+ l_input_type_e = WR_DQ;
+ }
+ else if(iv_shmoo_type == 8)
+ {
+ l_input_type_e = RD_DQ;
+ }
+ else if(iv_shmoo_type == 4)
+ {
+ l_input_type_e = WR_DQS;
+ }
+ else if(iv_shmoo_type == 16)
+ {
+ l_input_type_e = RD_DQS;
+ }
+
+
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+
+
+ //Reset schmoo_error_map
+
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for(uint8_t i = 0; i < iv_MAX_RANKS[l_p]; i++)
+ {
+
+ rank = valid_rank1[l_p][i];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ binary_done_map[l_p][rank][l_n] = 0;
+ }
+ }
+ }
+
+ if(bound == RIGHT)
+ {
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ do
+ {
+ l_status = 0;
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq));
+
+
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ if(binary_done_map[l_p][rank][l_n] == 0)
+ {
+ l_status = 1;
+ }
+
+ l_flag_p0 = 0;
+ l_flag_p1 = 0;
+
+ if(l_p == 0)
+ {
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+ if(l_CDarray0[l_i] == l_dq)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p0 = 1;
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+
+ if(l_CDarray1[l_i] == l_dq)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p1 = 1;
+
+ }
+ }
+ }
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq] = (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] > SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq];
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+ }
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq] = (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] > SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq];
+ }
+
+ if(l_p == 0)
+ {
+ if(l_flag_p0 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = 1;
+ }
+ }
+ else
+ {
+ if(l_flag_p1 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = 1;
+ }
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+
+ }
+ }
+
+ l_dq = l_dq + 4;
+ }
+ }
+
+
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(check_error_map(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+ count_cycle++;
+ }
+ while(l_status == 1);
+ }
+
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+ //////
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+
+
+
+
+ }
+
+ count_cycle = 0;
+
+ if(bound == LEFT)
+ {
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ l_status = 1;
+
+ while(l_status == 1)
+ {
+ l_status = 0;
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq));
+
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+ //////
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+
+ if(binary_done_map[l_p][rank][l_n] == 0)
+ {
+ l_status = 1;
+ }
+
+ l_flag_p0 = 0;
+ l_flag_p1 = 0;
+
+ if(l_p == 0)
+ {
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+ if(l_CDarray0[l_i] == l_dq)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p0 = 1;
+
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+
+ if(l_CDarray1[l_i] == l_dq)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p1 = 1;
+
+ }
+ }
+ }
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq] = (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] > SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq];
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+
+ }
+ }
+ else
+ {
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq] = (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] > SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq];
+ }
+
+
+ if(l_p == 0)
+ {
+ if(l_flag_p0 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = 1;
+ }
+ }
+ else
+ {
+ if(l_flag_p1 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] = 1;
+ }
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq];
+
+ }
+ }
+
+ l_dq = l_dq + 4;
+ }
+ }
+
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(check_error_map(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+ count_cycle++;
+ }
+ }
+
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = bit;
+ //////
+ rank = valid_rank1[l_p][l_rank];
+ //printf("Valid rank of %d %d %d %d %d %d %d %d",valid_rank1[0],valid_rank1[1],valid_rank1[2],valid_rank1[3],valid_rank1[4],valid_rank1[5],valid_rank1[6],valid_rank1[7]);
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+
+ } // End of LEFT
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::knob_update_dqs_by4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass)
+ {
+ fapi2::buffer<uint64_t> data_buffer_64;
+ fapi2::buffer<uint64_t> data_buffer_64_1;
+
+ input_type_t l_input_type_e = WR_DQ;
+ input_type_t l_input_type_e_dqs = WR_DQS;
+ uint8_t l_dq = 0;
+ access_type_t l_access_type_e = WRITE;
+ uint8_t l_n = 0;
+ uint8_t l_dqs = 1;
+ uint8_t l_p = 0;
+ uint8_t l_i = 0;
+ uint16_t l_delay = 0;
+ uint16_t l_max_limit = 500;
+ uint8_t rank = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+ FAPI_INF("\nWRT_DQS --- > CDIMM X4 - Scenario = %d", scenario);
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: ecb_error_map failed!!");
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for(uint8_t i = 0; i < iv_MAX_RANKS[l_p]; i++)
+ {
+
+ rank = valid_rank1[l_p][i];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ }
+ }
+ }
+
+ if(bound == RIGHT)
+ {
+
+ for (l_delay = 1; ((pass == 0)); l_delay++)
+ {
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+
+ if(l_p == 0)
+ {
+
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+
+ if(l_CDarray0[l_i] == l_dq)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+
+ if(l_CDarray1[l_i] == l_dq)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_n] = SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n] + l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_n]));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ }
+
+ if(SHMOO[l_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_dq] > l_max_limit)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ } // for nibble
+ } // for rank
+ } // for port
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+ } //end of delay
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+
+ }
+ }
+ }
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+
+ } // end bound == right
+
+ if(bound == LEFT)
+ {
+
+
+ for (l_delay = 1; (pass == 0); l_delay++)
+ {
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+
+ if(l_p == 0)
+ {
+
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+
+ if(l_CDarray0[l_i] == l_dq)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+
+ if(l_CDarray1[l_i] == l_dq)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_n] = SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n] - l_delay;
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_n]));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ }
+
+ if(SHMOO[l_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_n] == 0)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+ }
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+ }
+ }
+ }
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::knob_update_dqs_by4_isdimm(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass)
+ {
+ fapi2::buffer<uint64_t> data_buffer_64;
+ fapi2::buffer<uint64_t> data_buffer_64_1;
+ input_type_t l_input_type_e = WR_DQ;
+ input_type_t l_input_type_e_dqs = WR_DQS;
+ uint8_t l_dq = 0;
+ access_type_t l_access_type_e = WRITE;
+ uint8_t l_n = 0;
+ uint8_t l_dqs = 1;
+ uint8_t l_my_dqs = 0;
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+ uint8_t l_p = 0;
+ uint16_t l_delay = 0;
+ uint16_t l_max_limit = 500;
+ uint8_t rank = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint8_t l_dqs_arr[18] = {0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 17};
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for(uint8_t i = 0; i < iv_MAX_RANKS[l_p]; i++)
+ {
+ rank = valid_rank1[l_p][i];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ }
+ }
+ }
+
+ if(bound == RIGHT)
+ {
+ for (l_delay = 1; ((pass == 0)); l_delay++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+ l_my_dqs = 0;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+ l_my_dqs = l_dqs_arr[l_n];
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_my_dqs] = SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_my_dqs] + l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_my_dqs, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_my_dqs]));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ }
+
+ if(SHMOO[l_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_dq] > l_max_limit)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ } //end of nibble loop
+ } //end of rank
+ } //end of port
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+ } //end of delay loop
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+ }
+ }
+ }
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ } //end of rank
+ } //end of port
+ } //end of bit
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+ }
+
+ if(bound == LEFT)
+ {
+ for (l_delay = 1; (pass == 0); l_delay++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+ l_my_dqs = 0;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+ l_my_dqs = l_dqs_arr[l_n];
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_my_dqs] = SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_my_dqs] - l_delay;
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_my_dqs, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_my_dqs]));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ }
+
+ if(SHMOO[l_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_dq] == 0)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+ } //end of delay loop
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+ }
+ }
+ }
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ } //end of nibble
+ } //end of rank
+ } //port loop
+ } //bit loop
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+ } //end of Left
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::knob_update_dqs_by8(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass)
+ {
+ fapi2::buffer<uint64_t> data_buffer_64(64);
+ fapi2::buffer<uint64_t> data_buffer_64_1(64);
+ //uint8_t l_rp=0;
+ input_type_t l_input_type_e = WR_DQ;
+ input_type_t l_input_type_e_dqs = WR_DQS;
+ uint8_t l_dq = 0;
+ uint8_t l_dqs = 0;
+ access_type_t l_access_type_e = WRITE;
+ uint8_t l_n = 0;
+ uint8_t l_scen_dqs = 1;
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+ uint8_t l_p = 0;
+ uint16_t l_delay = 0;
+ uint16_t l_max_limit = 500;
+ uint8_t rank = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+
+ FAPI_INF("\nWRT_DQS --- > CDIMM X8 - Scenario = %d", scenario);
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for(uint8_t i = 0; i < iv_MAX_RANKS[l_p]; i++)
+ {
+
+ rank = valid_rank1[l_p][i];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ } //end of nib
+ } //end of rank
+ } //end of port loop
+
+ if(bound == RIGHT)
+ {
+ for (l_delay = 1; ((pass == 0)); l_delay++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+ l_dqs = 0;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+
+ if((schmoo_error_map[l_p][rank][l_n] == 0) && (schmoo_error_map[l_p][rank][l_n + 1] == 0))
+ {
+ //Increase delay of DQS
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_n] = SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n] + l_delay;
+ //Write it to register DQS delay
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_n]));
+
+ //Increase Delay of DQ
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+
+ l_dq = l_dq + 1;
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] > l_max_limit)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ if((schmoo_error_map[l_p][rank][l_n] == 1) || (schmoo_error_map[l_p][rank][l_n + 1] == 1))
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ l_n = l_n + 1;
+ l_dqs = l_dqs + 1;
+
+ } //end of nibble loop
+ } //end of rank loop
+ } //end of port loop
+
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+ } //end of delay loop
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+
+ } //end of nib
+ } //end of rank
+ } //end of port loop
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ } //end of nib
+ } //end of rank
+ } //end of port loop
+ } //end of bit loop
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+ }
+
+ if(bound == LEFT)
+ {
+ for (l_delay = 1; (pass == 0); l_delay++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+ l_dqs = 0;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+
+
+
+ if((schmoo_error_map[l_p][rank][l_n] == 0) && (schmoo_error_map[l_p][rank][l_n + 1] == 0))
+ {
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_n] = SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n] - l_delay;
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_n]));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] == 0)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ if((schmoo_error_map[l_p][rank][l_n] == 1) || (schmoo_error_map[l_p][rank][l_n + 1] == 1))
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ l_n = l_n + 1;
+ l_dqs = l_dq + 1;
+
+ } //nibble loop
+ } //rank loop
+ } //port loop
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+
+ } //end of l delay loop
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+
+ }
+ }
+ }
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+ } //end of bound Left
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::knob_update_dqs_by8_isdimm(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass)
+ {
+ fapi2::buffer<uint64_t> data_buffer_64;
+ fapi2::buffer<uint64_t> data_buffer_64_1;
+ //uint8_t l_rp=0;
+ input_type_t l_input_type_e = WR_DQ;
+ input_type_t l_input_type_e_dqs = WR_DQS;
+ uint8_t l_dq = 0;
+ uint8_t l_dqs = 0;
+ access_type_t l_access_type_e = WRITE;
+ uint8_t l_n = 0;
+ uint8_t l_scen_dqs = 1;
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+ uint8_t l_p = 0;
+ uint16_t l_delay = 0;
+ uint16_t l_max_limit = 500;
+ uint8_t rank = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ //uint8_t i_rp=0;
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+
+ if(iv_dmm_type == 1)
+ {
+
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for(uint8_t i = 0; i < iv_MAX_RANKS[l_p]; i++)
+ {
+
+ rank = valid_rank1[l_p][i];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ }
+ }
+ }
+
+ if(bound == RIGHT)
+ {
+
+ for (l_delay = 1; ((pass == 0)); l_delay++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+ l_dqs = 0;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+ l_dqs = l_n / 2;
+
+ if((schmoo_error_map[l_p][rank][l_n] == 0) && (schmoo_error_map[l_p][rank][l_n + 1] == 0))
+ {
+
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_dqs] = SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_dqs] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_dqs, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_dqs]));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] +
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq]));
+
+ }
+
+ if(SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.rb_regval[l_dqs] > l_max_limit)
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ if((schmoo_error_map[l_p][rank][l_n] == 1) || (schmoo_error_map[l_p][rank][l_n + 1] == 1))
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ l_n = l_n + 1;
+
+ }
+
+
+ }
+
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+ }
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+ }
+ }
+ }
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+ }
+
+ if(bound == LEFT)
+ {
+
+ for (l_delay = 1; (pass == 0); l_delay++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = 0;
+ l_dqs = 0;
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ l_dq = 4 * l_n;
+
+ l_dqs = l_n / 2;
+
+ if((schmoo_error_map[l_p][rank][l_n] == 0) && (schmoo_error_map[l_p][rank][l_n + 1] == 0))
+ {
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_dqs] = SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_dqs] -
+ l_delay;
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_dqs, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_dqs]));
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ l_dq = l_dq + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq] -
+ l_delay;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq]));
+ }
+
+ if(SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.lb_regval[l_dqs] == 0)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ if((schmoo_error_map[l_p][rank][l_n] == 1) || (schmoo_error_map[l_p][rank][l_n + 1] == 1))
+ {
+
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ schmoo_error_map[l_p][rank][l_n + 1] = 1;
+ }
+
+ l_n = l_n + 1;
+
+ } //nibble loop
+ } //rank loop
+ } //port loop
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(check_error_map2(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ if (l_delay > 70)
+ {
+ break;
+ }
+
+ }
+
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank[l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e_dqs, l_n, 0,
+ SHMOO[l_scen_dqs].MBA.P[l_p].S[rank].K.nom_val[l_n]));
+
+ }
+ }
+ }
+
+ for(uint8_t l_bit = 0; l_bit < 4; l_bit++)
+ {
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ l_dq = l_bit;
+
+ rank = valid_rank1[l_p][l_rank];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq]));
+ l_dq = l_dq + 4;
+ }
+ } //rank loop
+ } //port loop
+ } //bit loop
+
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq),
+ "generic_shmoo::do_mcbist_test: mcb_error_map failed!!");
+
+ } //end of LEFT
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function calls the knob_update for each DQ which is used to find bound that is left/right according to schmoo type
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::find_bound(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound)
+ {
+ uint8_t l_bit = 0;
+ uint8_t l_comp = 0;
+ uint8_t pass = 0;
+ uint8_t l_dram_width = 0;
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, l_dram_width));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_SCHMOO_MODE, i_target, l_comp));
+
+ FAPI_INF("%s:\n SCHMOO IS IN PROGRESS ...... \n", mss::c_str(i_target));
+
+ //WRT_DQS Portion
+ if(iv_DQS_ON == 1)
+ {
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+ pass = 0;
+
+ if(l_dram_width == 4)
+ {
+ if(iv_dmm_type == 1)
+ {
+ FAPI_TRY(knob_update_dqs_by4_isdimm(i_target, bound, iv_shmoo_type, l_bit, pass));
+ }
+ else
+ {
+ FAPI_TRY(knob_update_dqs_by4(i_target, bound, iv_shmoo_type, l_bit, pass));
+ }
+ } //end of if dram_width 4
+ else
+ {
+ if(iv_dmm_type == 1)
+ {
+ FAPI_TRY(knob_update_dqs_by8_isdimm(i_target, bound, iv_shmoo_type, l_bit, pass));
+ }
+ else
+ {
+ FAPI_TRY(knob_update_dqs_by8(i_target, bound, iv_shmoo_type, l_bit, pass));
+ }
+ }
+ } //end of if iv_DQS_ON 1 or WRT_DQS
+
+ else if(l_comp == 6)
+ {
+ pass = 0;
+ FAPI_TRY(knob_update_bin_composite(i_target, bound, iv_shmoo_type, l_bit, pass));
+ }
+ else
+ {
+ //Bit loop
+ for (l_bit = 0; l_bit < MAX_BITS; l_bit++)
+ {
+ // preetham function here
+ pass = 0;
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ if (l_comp == 4)
+ {
+ FAPI_INF("Calling Binary - %d", iv_shmoo_type);
+ FAPI_TRY(knob_update_bin(i_target, bound, iv_shmoo_type, l_bit, pass));
+ }
+ else
+ {
+ FAPI_TRY(knob_update(i_target, bound, iv_shmoo_type, l_bit, pass));
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::print_report(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk, l_byte, l_nibble, l_bit = 0;
+ uint8_t l_dq = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint8_t l_mbapos = 0;
+ uint32_t l_attr_mss_freq_u32 = 0;
+ uint32_t l_attr_mss_volt_u32 = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t l_attr_eff_num_drops_per_port_u8 = 0;
+ uint8_t l_attr_eff_dram_width_u8 = 0;
+
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT, l_target_centaur, l_attr_mss_volt_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT, i_target, l_attr_eff_num_drops_per_port_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, l_attr_eff_dram_width_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target, l_mbapos));
+
+ FAPI_INF("%s:freq = %d on %s.", mss::c_str(i_target), l_attr_mss_freq_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s: volt = %d on %s.", mss::c_str(i_target), l_attr_mss_volt_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s: dimm_type = %d on %s.", mss::c_str(i_target), l_attr_eff_dimm_type_u8, mss::c_str(i_target));
+
+ if ( l_attr_eff_dimm_type_u8 == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES )
+ {
+ FAPI_INF("%s: It is a CDIMM", mss::c_str(i_target));
+ }
+ else
+ {
+ FAPI_INF("%s: It is an ISDIMM", mss::c_str(i_target));
+ }
+
+ FAPI_INF("%s: \n Number of ranks on port = 0 is %d ", mss::c_str(i_target), iv_MAX_RANKS[0]);
+ FAPI_INF("%s: \n Number of ranks on port = 1 is %d \n \n", mss::c_str(i_target), iv_MAX_RANKS[1]);
+ FAPI_INF("%s:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", mss::c_str(i_target));
+
+ //// Based on schmoo param the print will change eventually
+ if(iv_shmoo_type == 2)
+ {
+ FAPI_INF("%s:Schmoo POS\tPort\tRank\tByte\tnibble\tbit\tNominal\t\tSetup_Limit\tHold_Limit\tWrD_Setup(ps)\tWrD_Hold(ps)\tEye_Width(ps)\tBitRate\tVref_Multiplier ",
+ mss::c_str(i_target));
+ }
+ else
+ {
+ FAPI_INF("%s:Schmoo POS\tPort\tRank\tByte\tnibble\tbit\tNominal\t\tSetup_Limit\tHold_Limit\tRdD_Setup(ps)\tRdD_Hold(ps)\tEye_Width(ps)\tBitRate\tVref_Multiplier ",
+ mss::c_str(i_target));
+ }
+
+ for (l_p = 0; l_p < 2; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ for(l_byte = 0; l_byte < 10; l_byte++)
+ {
+ //Nibble loop
+ for(l_nibble = 0; l_nibble < 2; l_nibble++)
+ {
+ for(l_bit = 0; l_bit < 4; l_bit++)
+ {
+ l_dq = 8 * l_byte + 4 * l_nibble + l_bit;
+
+ if(iv_shmoo_type == 2)
+ {
+ FAPI_INF("%s:WR_EYE %d\t%d\t%d\t%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n ", mss::c_str(i_target),
+ l_mbapos, l_p, i_rank, l_byte, l_nibble, l_bit, SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq], SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.total_margin[l_dq], l_attr_mss_freq_u32, iv_vref_mul);
+ }
+
+ if(iv_shmoo_type == 8)
+ {
+ FAPI_INF("%s:RD_EYE %d\t%d\t%d\t%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n ", mss::c_str(i_target),
+ l_mbapos, l_p, i_rank, l_byte, l_nibble, l_bit, SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq], SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.total_margin[l_dq], l_attr_mss_freq_u32, iv_vref_mul);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::print_report_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk, l_nibble = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint8_t l_mbapos = 0;
+ uint16_t l_total_margin = 0;
+ uint32_t l_attr_mss_freq_u32 = 0;
+ uint32_t l_attr_mss_volt_u32 = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t l_attr_eff_num_drops_per_port_u8 = 0;
+ uint8_t l_attr_eff_dram_width_u8 = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint8_t l_by8_dqs = 0;
+ char* l_pMike = new char[128];
+ char* l_str = new char[128];
+
+ uint8_t l_i = 0;
+ uint8_t l_dq = 0;
+ uint8_t l_flag = 0;
+ uint8_t l_CDarray0[80] = { 0 };
+ uint8_t l_CDarray1[80] = { 0 };
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1,
+ count_bad_dq), "generic_shmoo::print report: mcb_error_map failed!!");
+
+ if (iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT, l_target_centaur, l_attr_mss_volt_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT, i_target, l_attr_eff_num_drops_per_port_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, l_attr_eff_dram_width_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target, l_mbapos));
+
+ if (l_attr_eff_dram_width_u8 == 8)
+ {
+ l_SCHMOO_NIBBLES = 10;
+
+ if (iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 9;
+ }
+ }
+
+ FAPI_INF("%s: freq = %d on %s.", mss::c_str(i_target),
+ l_attr_mss_freq_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s:volt = %d on %s.", mss::c_str(i_target),
+ l_attr_mss_volt_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s:dimm_type = %d on %s.", mss::c_str(i_target),
+ l_attr_eff_dimm_type_u8, mss::c_str(i_target));
+ FAPI_INF("%s:\n Number of ranks on port=0 is %d ", mss::c_str(i_target),
+ iv_MAX_RANKS[0]);
+ FAPI_INF("%s:\n Number of ranks on port=1 is %d ", mss::c_str(i_target),
+ iv_MAX_RANKS[1]);
+
+ if (l_attr_eff_dimm_type_u8 == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ FAPI_INF("%s:It is a CDIMM", mss::c_str(i_target));
+ }
+ else
+ {
+ FAPI_INF("%s:It is an ISDIMM", mss::c_str(i_target));
+ }
+
+ FAPI_INF("%s:\n Number of ranks on port=0 is %d ", mss::c_str(i_target),
+ iv_MAX_RANKS[0]);
+ FAPI_INF("%s:\n Number of ranks on port=1 is %d \n \n",
+ mss::c_str(i_target), iv_MAX_RANKS[1]);
+
+ FAPI_INF(
+ "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ sprintf(l_pMike,
+ "Schmoo POS\tPort\tRank\tDQS\tNominal\t\ttDQSSmin_PR_limit\ttDQSSmax_PR_limit\ttDQSSmin(ps)\ttDQSSmax(ps)\ttDQSS_Window(ps)\tBitRate ");
+ FAPI_INF("%s", l_pMike);
+ delete[] l_pMike;
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ ////
+
+ i_rank = valid_rank1[l_p][l_rnk];
+ //
+
+ for (l_nibble = 0; l_nibble < l_SCHMOO_NIBBLES; l_nibble++)
+ {
+ l_by8_dqs = l_nibble;
+
+ if (iv_dmm_type == 0)
+ {
+ if (l_attr_eff_dram_width_u8 == 8)
+ {
+ l_nibble = l_nibble * 2;
+ }
+ }
+
+ l_dq = 4 * l_nibble;
+ l_flag = 0;
+
+ if (l_p == 0)
+ {
+ for (l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+ if (l_CDarray0[l_i] == l_dq)
+ {
+ l_flag = 1;
+
+ }
+ }
+ }
+ else
+ {
+ for (l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+ if (l_CDarray1[l_i] == l_dq)
+ {
+ l_flag = 1;
+
+ }
+ }
+ }
+
+ if(l_flag == 1)
+ {
+ continue;
+ }
+
+ l_total_margin
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble]
+ + SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble];
+ sprintf(l_str, "%d\t%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d",
+ l_mbapos, l_p, i_rank, l_nibble,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.curr_val[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble],
+ l_total_margin, l_attr_mss_freq_u32);
+
+ FAPI_INF("WR_DQS %s", l_str);
+
+ if (iv_dmm_type == 0)
+ {
+ if (l_attr_eff_dram_width_u8 == 8)
+ {
+ l_nibble = l_by8_dqs;
+ }
+ }
+ }
+ }
+ }
+
+ delete[] l_str;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::print_report_dqs2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk, l_nibble = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint8_t l_mbapos = 0;
+ uint32_t l_attr_mss_freq_u32 = 0;
+ uint32_t l_attr_mss_volt_u32 = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t l_attr_eff_num_drops_per_port_u8 = 0;
+ uint8_t l_attr_eff_dram_width_u8 = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint8_t l_by8_dqs = 0;
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT, l_target_centaur, l_attr_mss_volt_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT, i_target, l_attr_eff_num_drops_per_port_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, l_attr_eff_dram_width_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target, l_mbapos));
+
+ if(l_attr_eff_dram_width_u8 == 8)
+ {
+ l_SCHMOO_NIBBLES = 10;
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 9;
+ }
+ }
+
+ FAPI_INF("%s:freq = %d on %s.", mss::c_str(i_target), l_attr_mss_freq_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s:volt = %d on %s.", mss::c_str(i_target), l_attr_mss_volt_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s:dimm_type = %d on %s.", mss::c_str(i_target), l_attr_eff_dimm_type_u8, mss::c_str(i_target));
+ FAPI_INF("%s:\n Number of ranks on port=0 is %d ", mss::c_str(i_target), iv_MAX_RANKS[0]);
+ FAPI_INF("%s:\n Number of ranks on port=1 is %d ", mss::c_str(i_target), iv_MAX_RANKS[1]);
+
+ if ( l_attr_eff_dimm_type_u8 == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES )
+ {
+ FAPI_INF("%s:It is a CDIMM", mss::c_str(i_target));
+ }
+ else
+ {
+ FAPI_INF("%s:It is an ISDIMM", mss::c_str(i_target));
+ }
+
+ FAPI_INF("%s:\n Number of ranks on port=0 is %d ", mss::c_str(i_target), iv_MAX_RANKS[0]);
+ FAPI_INF("%s:\n Number of ranks on port=1 is %d \n \n", mss::c_str(i_target), iv_MAX_RANKS[1]);
+
+ FAPI_INF("%s:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++", mss::c_str(i_target));
+ FAPI_INF("%s:Schmoo POS\tPort\tRank\tDQS\tNominal\t\ttDQSSmin_PR_limit\ttDQSSmax_PR_limit\ttDQSSmin(ps)\ttDQSSmax(ps)\ttDQSS_Window(ps)\tBitRate ",
+ mss::c_str(i_target));
+
+ iv_shmoo_type = 4;
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ for(l_nibble = 0; l_nibble < l_SCHMOO_NIBBLES; l_nibble++)
+ {
+ l_by8_dqs = l_nibble;
+
+ if(iv_dmm_type == 0)
+ {
+ if(l_attr_eff_dram_width_u8 == 8)
+ {
+ l_nibble = l_nibble * 2;
+ }
+ }
+
+ FAPI_INF("%s:WR_DQS %d\t%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\n ", mss::c_str(i_target), l_mbapos, l_p,
+ i_rank, l_nibble, SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.total_margin[l_nibble], l_attr_mss_freq_u32);
+
+ if(iv_dmm_type == 0)
+ {
+ if(l_attr_eff_dram_width_u8 == 8)
+ {
+ l_nibble = l_by8_dqs;
+ }
+ }
+
+
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::get_margin(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk, l_byte, l_nibble, l_bit;
+ uint32_t l_attr_mss_freq_margin_u32 = 0;
+ uint32_t l_freq = 0;
+ uint64_t l_cyc = 1000000000000000ULL;
+ uint8_t l_dq = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint64_t l_factor = 0;
+ uint64_t l_factor_ps = 1000000000;
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur,
+ l_attr_mss_freq_margin_u32));
+ l_freq = l_attr_mss_freq_margin_u32 / 2;
+ l_cyc = l_cyc / l_freq;// converting to zepto to get more accurate data
+ l_factor = l_cyc / 128;
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ ////
+
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ //
+ for (l_byte = 0; l_byte < iv_MAX_BYTES; l_byte++)
+ {
+ //Nibble loop
+ for (l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ for (l_bit = 0; l_bit < MAX_BITS; l_bit++)
+ {
+ l_dq = 8 * l_byte + 4 * l_nibble + l_bit;
+
+ if (iv_shmoo_type == 1)
+ {
+ if (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] == 0)
+ {
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] = 0;
+
+
+ }
+ }
+
+ if (iv_shmoo_param == 4)
+ {
+ if (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq]
+ > SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq]
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] - 1;
+ }
+
+ if (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq]
+ < SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq]
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] + 1;
+ }
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq]
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] - 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq]
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] + 1;
+ }
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq]
+ = ((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq]
+ - SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq])
+ * l_factor) / l_factor_ps;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq]
+ = ((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq]
+ - SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq])
+ * l_factor) / l_factor_ps;
+ }
+ }
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::get_margin2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk, l_byte, l_nibble, l_bit = 0;
+ uint32_t l_attr_mss_freq_margin_u32 = 0;
+ uint32_t l_freq = 0;
+ uint64_t l_cyc = 1000000000000000ULL;
+ uint8_t l_dq = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint64_t l_factor = 0;
+ uint64_t l_factor_ps = 1000000000;
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_margin_u32));
+ l_freq = l_attr_mss_freq_margin_u32 / 2;
+ l_cyc = l_cyc / l_freq; // converting to zepto to get more accurate data
+ l_factor = l_cyc / 128;
+
+ //FAPI_INF("Get Margin2 - Preet");
+
+ for (l_p = 0; l_p < MAX_PORTS_PER_MBA; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ for(l_byte = 0; l_byte < 10; l_byte++)
+ {
+ for(l_nibble = 0; l_nibble < 2; l_nibble++)
+ {
+ for(l_bit = 0; l_bit < 4; l_bit++)
+ {
+ l_dq = 8 * l_byte + 4 * l_nibble + l_bit;
+
+ if((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq]) <= 0 && (iv_shmoo_type == 8))
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] = 0;
+ }
+
+ if((iv_shmoo_param == 4) || (iv_shmoo_param == 6))
+ {
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] > SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] -
+ 1;
+ }
+
+ if((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] < SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq])
+ && (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] != 0))
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] +
+ 1;
+ }
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] -
+ 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq] +
+ 1;
+ }
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq] = ((
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq] - SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq]) *
+ l_factor) / l_factor_ps;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq] = ((
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq] - SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq]) *
+ l_factor) / l_factor_ps; //((1/uint32_t_freq*1000000)/128);
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.total_margin[l_dq] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq];
+ } // for bit
+ } // for nibble
+ } //for byte
+ } //for rank
+ } // for port
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::print_report2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk, l_byte, l_nibble, l_bit = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint8_t l_mbapos = 0;
+ uint32_t l_attr_mss_freq_u32 = 0;
+ uint32_t l_attr_mss_volt_u32 = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t l_attr_eff_num_drops_per_port_u8 = 0;
+ uint8_t l_attr_eff_dram_width_u8 = 0;
+ uint16_t l_total_margin = 0;
+ uint8_t l_dq = 0;
+ uint8_t vrefdq_train_value[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ char* l_pMike = new char[160];
+ char* l_str = new char[128];
+ uint8_t l_dram_gen = 1;
+ uint8_t l_param_valid = 0;
+ uint32_t base_percent = 60000;
+ uint32_t index_mul_print = 650;
+ uint32_t vref_val_print = 0;
+ uint8_t vrefdq_train_range[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM] = {0};
+ uint32_t l_attr_rd_vred_vpd_value[2] = {0};
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_RANGE, i_target, vrefdq_train_range));
+ FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target, l_dram_gen));
+ FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CEN_EFF_VREF_DQ_TRAIN_VALUE, i_target, vrefdq_train_value));
+ FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CEN_EFF_SCHMOO_PARAM_VALID, i_target, l_param_valid));
+
+ if(vrefdq_train_range[0][0][0] == 1)
+ {
+ base_percent = 45000;
+ }
+
+ if (iv_shmoo_type == 2)
+ {
+ vref_val_print = base_percent + (vrefdq_train_value[0][0][0] * index_mul_print);
+ }
+
+ else if((iv_shmoo_type == 8) && (l_param_valid != fapi2::ENUM_ATTR_CEN_EFF_SCHMOO_PARAM_VALID_RD_VREF))
+ {
+ FAPI_TRY(FAPI_ATTR_GET( fapi2::ATTR_CEN_VPD_RD_VREF, i_target, l_attr_rd_vred_vpd_value));
+ //FAPI_INF("Rd_From VPD = %d",l_attr_rd_vred_vpd_value[0]);
+ vref_val_print = l_attr_rd_vred_vpd_value[0];
+ }
+ else if((iv_shmoo_type == 8) && (l_param_valid == fapi2::ENUM_ATTR_CEN_EFF_SCHMOO_PARAM_VALID_RD_VREF))
+ {
+ FAPI_INF("Rd_From iv_vref_mul = %d", iv_vref_mul);
+ vref_val_print = iv_vref_mul;
+ }
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_VOLT, l_target_centaur, l_attr_mss_volt_u32));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_DROPS_PER_PORT, i_target,
+ l_attr_eff_num_drops_per_port_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target,
+ l_attr_eff_dram_width_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target, l_mbapos));
+
+ FAPI_INF("%s: freq = %d on %s.", mss::c_str(i_target),
+ l_attr_mss_freq_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s: volt = %d on %s.", mss::c_str(i_target),
+ l_attr_mss_volt_u32, mss::c_str(l_target_centaur));
+ FAPI_INF("%s: dimm_type = %d on %s.", mss::c_str(i_target),
+ l_attr_eff_dimm_type_u8, mss::c_str(i_target));
+ //FAPI_INF("%s: +++ Preet1 %d +++ ", mss::c_str(i_target),vref_val_print);
+
+ if (l_attr_eff_dimm_type_u8 == fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ FAPI_INF("%s: It is a CDIMM", mss::c_str(i_target));
+ }
+ else
+ {
+ FAPI_INF("%s: It is an ISDIMM", mss::c_str(i_target));
+ }
+
+ FAPI_INF("%s: \n Number of ranks on port = 0 is %d ",
+ mss::c_str(i_target), iv_MAX_RANKS[0]);
+ FAPI_INF("%s: \n Number of ranks on port = 1 is %d \n \n",
+ mss::c_str(i_target), iv_MAX_RANKS[1]);
+
+ FAPI_INF("dram_width = %d \n\n", l_attr_eff_dram_width_u8);
+ FAPI_INF("%s:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++",
+ mss::c_str(i_target));
+ //// Based on schmoo param the print will change eventually
+
+ if (iv_shmoo_type == 0)
+ {
+ sprintf(l_pMike,
+ "Schmoo POS\tPort\tRank\tByte\tnibble\t\tNominal\tSetup_Limit\tHold_Limit\tWrD_Setup(ps)\tWrD_Hold(ps)\tEye_Width(ps)\tBitRate\tVref_Multiplier ");
+ }
+ else
+ {
+ sprintf(l_pMike,
+ "Schmoo POS\tPort\tRank\tByte\tnibble\t\tNominal\tSetup_Limit\tHold_Limit\tRdD_Setup(ps)\tRdD_Hold(ps)\tEye_Width(ps)\tBitRate\tVref_Multiplier ");
+ }
+
+ //FAPI_INF("Schmoo POS\tPort\tRank\tByte\tnibble\tbit\tNominal\t\tSetup_Limit\tHold_Limit \n");
+ FAPI_INF("%s", l_pMike);
+ delete[] l_pMike;
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ for (l_byte = 0; l_byte < iv_MAX_BYTES; l_byte++)
+ {
+ //Nibble loop
+ for (l_nibble = 0; l_nibble < MAX_NIBBLES; l_nibble++)
+ {
+ for (l_bit = 0; l_bit < MAX_BITS; l_bit++)
+ {
+ l_dq = (BITS_PER_BYTE * l_byte) + (BITS_PER_NIBBLE * l_nibble) + l_bit;
+ l_total_margin
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq]
+ + SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq];
+
+ if(l_dram_gen == 2)
+ {
+ sprintf(l_str, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d",
+ l_mbapos, l_p, i_rank, l_byte, l_nibble, l_bit,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq],
+ l_total_margin, l_attr_mss_freq_u32, vref_val_print);
+ }
+ else
+ {
+ sprintf(l_str, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d\t\t%d",
+ l_mbapos, l_p, i_rank, l_byte, l_nibble, l_bit,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq],
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq],
+ l_total_margin, l_attr_mss_freq_u32, iv_vref_mul);
+ }
+
+ if (iv_shmoo_type == 2)
+ {
+ FAPI_IMP("WR_EYE %s ", l_str);
+
+ }
+
+ if (iv_shmoo_type == 8)
+ {
+ FAPI_IMP("RD_EYE %s ", l_str);
+
+ }
+ } // end for bit
+ } // end for nibble
+ } // end for byte
+ } // end for rank
+ } // end for port
+
+ delete[] l_str;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ fapi2::ReturnCode generic_shmoo::get_margin_dqs_by4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk = 0;
+ uint32_t l_attr_mss_freq_margin_u32 = 0;
+ uint32_t l_freq = 0;
+ uint64_t l_cyc = 1000000000000000ULL;
+ uint8_t l_nibble = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint64_t l_factor = 0;
+ uint64_t l_factor_ps = 1000000000;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_margin_u32));
+ l_freq = l_attr_mss_freq_margin_u32 / 2;
+ l_cyc = l_cyc / l_freq; // converting to zepto to get more accurate data
+ l_factor = l_cyc / 128;
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ i_rank = valid_rank1[l_p][l_rnk];
+ //Nibble loop
+
+ for(l_nibble = 0; l_nibble < l_SCHMOO_NIBBLES; l_nibble++)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble] - 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble] + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble] = ((
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_nibble]) * l_factor) / l_factor_ps;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble] = ((
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_nibble] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble]) * l_factor) /
+ l_factor_ps; //((1/uint32_t_freq*1000000)/128);
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.total_margin[l_nibble] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble];
+
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::get_margin_dqs_by8(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+ uint8_t l_rnk = 0;
+ uint32_t l_attr_mss_freq_margin_u32 = 0;
+ uint32_t l_freq = 0;
+ uint64_t l_cyc = 1000000000000000ULL;
+ uint8_t l_nibble = 0;
+ uint8_t l_p = 0;
+ uint8_t i_rank = 0;
+ uint64_t l_factor = 0;
+ uint64_t l_factor_ps = 1000000000;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 9;
+ }
+
+ const auto l_target_centaur = i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, l_attr_mss_freq_margin_u32));
+ l_freq = l_attr_mss_freq_margin_u32 / 2;
+ l_cyc = l_cyc / l_freq; // converting to zepto to get more accurate data
+ l_factor = l_cyc / 128;
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ for(l_nibble = 0; l_nibble < l_SCHMOO_NIBBLES; l_nibble++)
+ {
+ if(iv_dmm_type == 0)
+ {
+ if((l_nibble % 2))
+ {
+ continue ;
+ }
+ }
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble] - 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble] + 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble] = ((
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.rb_regval[l_nibble] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_nibble]) * l_factor) / l_factor_ps;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble] = ((
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.nom_val[l_nibble] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.lb_regval[l_nibble]) * l_factor) /
+ l_factor_ps; //((1/uint32_t_freq*1000000)/128);
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.total_margin[l_nibble] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble];
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::knob_update_bin_composite(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ bound_t bound, uint8_t scenario, uint8_t bit, uint8_t pass)
+ {
+ fapi2::buffer<uint64_t> data_buffer_64(64);
+ fapi2::buffer<uint64_t> data_buffer_64_1(64);
+ input_type_t l_input_type_e = WR_DQ;
+ uint8_t l_n = 0;
+ access_type_t l_access_type_e = WRITE;
+ uint8_t l_dq = 0;
+ uint8_t l_i = 0;
+ uint8_t l_flag_p0 = 0;
+ uint8_t l_flag_p1 = 0;
+ FAPI_INF("SHMOOING VIA COMPOSITE EYE FW !!!!");
+ uint8_t l_p = 0;
+ uint8_t rank = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint8_t l_status = 1;
+ uint8_t l_CDarray0[80] = {0};
+ uint8_t l_CDarray1[80] = {0};
+ int count_cycle = 0;
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ if(iv_shmoo_type == 2)
+ {
+ l_input_type_e = WR_DQ;
+ }
+ else if(iv_shmoo_type == 8)
+ {
+ l_input_type_e = RD_DQ;
+ }
+ else if(iv_shmoo_type == 4)
+ {
+ l_input_type_e = WR_DQS;
+ }
+ else if(iv_shmoo_type == 16)
+ {
+ l_input_type_e = RD_DQS;
+ }
+
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+
+ //Reset schmoo_error_map
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for(uint8_t i = 0; i < iv_MAX_RANKS[l_p]; i++)
+ {
+
+ rank = valid_rank1[l_p][i];
+
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 0;
+ binary_done_map[l_p][rank][l_n] = 0;
+ }
+ }
+ }
+
+ if(bound == RIGHT)
+ {
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ do
+ {
+ l_status = 0;
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq));
+
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for(l_dq = 0; l_dq < 4; l_dq++)
+ {
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ if(binary_done_map[l_p][rank][l_n] == 0)
+ {
+ l_status = 1;
+ }
+
+ l_flag_p0 = 0;
+ l_flag_p1 = 0;
+
+ if(l_p == 0)
+ {
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+ if(l_CDarray0[l_i] == l_dq + l_n * 4)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p0 = 1;
+
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+
+ if(l_CDarray1[l_i] == l_dq + l_n * 4)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p1 = 1;
+
+ }
+ }
+ }
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4] =
+ (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq + l_n * 4, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] >
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4];
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+ // printf("\n the right bound for port=%d rank=%d dq=%d is %d \n",l_p,rank,l_dq+l_n*4,FAPI_INF.MBA.P[l_p].S[rank].K.curr_val[l_dq+l_n*4]);
+ }
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4] =
+ (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq + l_n * 4, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] >
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4];
+ }
+
+ if(l_p == 0)
+ {
+ if(l_flag_p0 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] = 1;
+ }
+ }
+ else
+ {
+ if(l_flag_p1 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] = 1;
+ }
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.rb_regval[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+
+ }
+ } // end else (schmoo_error_map[l_p][rank][l_n] != 0)
+ } // end for nibble
+ } // end for dq
+ } // end for rank
+
+
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(check_error_map(i_target, l_p, pass));
+ //FAPI_INF("\n the status =%d \n",l_status);
+ count_cycle++;
+ } // end do
+
+ while(l_status == 1);
+ } // end for port
+
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for(l_dq = 0; l_dq < 4; l_dq++)
+ {
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq + l_n * 4, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq + l_n * 4]));
+ }
+ }
+ }
+ }
+ }
+
+ count_cycle = 0;
+
+ if(bound == LEFT)
+ {
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ l_status = 1;
+
+ while(l_status == 1)
+ {
+ l_status = 0;
+
+ FAPI_TRY(mcb_error_map(i_target, mcbist_error_map, l_CDarray0, l_CDarray1, count_bad_dq));
+
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for(l_dq = 0; l_dq < 4; l_dq++)
+ {
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ if(binary_done_map[l_p][rank][l_n] == 0)
+ {
+ l_status = 1;
+ }
+
+ l_flag_p0 = 0;
+ l_flag_p1 = 0;
+
+ if(l_p == 0)
+ {
+ for(l_i = 0; l_i < count_bad_dq[0]; l_i++)
+ {
+ if(l_CDarray0[l_i] == l_dq + l_n * 4)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p0 = 1;
+
+ }
+ }
+ }
+ else
+ {
+ for(l_i = 0; l_i < count_bad_dq[1]; l_i++)
+ {
+
+ if(l_CDarray1[l_i] == l_dq + l_n * 4)
+ {
+ schmoo_error_map[l_p][rank][l_n] = 1;
+ l_flag_p1 = 1;
+
+ }
+ }
+ }
+
+ if(schmoo_error_map[l_p][rank][l_n] == 0)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4] =
+ (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq + l_n * 4, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] >
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4];
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+
+ }
+ }
+ else
+ {
+
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4];
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4] =
+ (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] +
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4]) / 2;
+
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq + l_n * 4, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_val[l_dq + l_n * 4]));
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] >
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4])
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+ }
+ else
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4] -
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_pass[l_dq + l_n * 4];
+ }
+
+
+ if(l_p == 0)
+ {
+ if(l_flag_p0 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] = 1;
+ }
+ }
+ else
+ {
+ if(l_flag_p1 == 1)
+ {
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] = 1;
+ }
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.curr_diff[l_dq + l_n * 4] <= 1)
+ {
+ binary_done_map[l_p][rank][l_n] = 1;
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.lb_regval[l_dq + l_n * 4] =
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.last_fail[l_dq + l_n * 4];
+
+ }
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(do_mcbist_reset(i_target), "generic_shmoo::find_bound do_mcbist_reset failed");
+ FAPI_TRY(do_mcbist_test(i_target), "generic_shmoo::find_bound do_mcbist_test failed");
+ FAPI_TRY(check_error_map(i_target, l_p, pass), "generic_shmoo::find_bound do_mcbist_test failed");
+ count_cycle++;
+ }
+ }
+
+ for(l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rank = 0; l_rank < iv_MAX_RANKS[l_p]; l_rank++)
+ {
+ rank = valid_rank1[l_p][l_rank];
+
+ for(l_dq = 0; l_dq < 4; l_dq++)
+ {
+ for (l_n = 0; l_n < l_SCHMOO_NIBBLES; l_n++)
+ {
+ FAPI_TRY(mss_access_delay_reg_schmoo(i_target, l_access_type_e, l_p, rank, l_input_type_e, l_dq + l_n * 4, 0,
+ SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[rank].K.nom_val[l_dq + l_n * 4]));
+ }
+ }
+ }
+ }
+ } // End of LEFT
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+
+ ///
+ /// @brief Sets the PDA nibble table with shmoo values
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] pda_nibble_table Per nibble vref + margins
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::get_nibble_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t pda_nibble_table[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT][MAX_RANKS_PER_DIMM][16][2])
+ {
+ uint8_t l_dimm = 0;
+ uint8_t num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, num_ranks_per_dimm));
+
+ for(uint8_t l_p = 0; l_p < MAX_PORTS_PER_MBA; l_p++)
+ {
+ for (l_dimm = 0; l_dimm < MAX_DIMM_PER_PORT; l_dimm++)
+ {
+ for(uint8_t l_rnk = 0; l_rnk < num_ranks_per_dimm[l_p][l_dimm]; l_rnk++)
+ {
+ for(uint8_t l_dq = 0; l_dq < 4; l_dq++)
+ {
+ for(uint8_t l_n = 0; l_n < 16; l_n++)
+ {
+ pda_nibble_table[l_p][l_dimm][l_rnk][l_n][0] = iv_vref_mul;
+
+ if(l_dimm == 0)
+ {
+ pda_nibble_table[l_p][l_dimm][l_rnk][l_n][1] = SHMOO[iv_DQS_ON].MBA.P[l_p].S[l_rnk].K.total_margin[l_dq + l_n * 4];
+ }
+ else
+ {
+ pda_nibble_table[l_p][l_dimm][l_rnk][l_n][1] = SHMOO[iv_DQS_ON].MBA.P[l_p].S[l_rnk + 4].K.total_margin[l_dq + l_n * 4];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief This function is used to get the minimum margin of all the schmoo margins
+ /// @param[in] i_target Centaur input MBA
+ /// @param[out] o_right_min_margin Minimum hold margin
+ /// @param[out] o_left_min_margin Minimum setup margin
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ void generic_shmoo::get_min_margin2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target, uint32_t* o_right_min_margin,
+ uint32_t* o_left_min_margin)
+ {
+ uint8_t l_rnk, l_byte, l_nibble, l_bit, i_rank = 0;
+ uint16_t l_temp_right = 4800;
+ uint16_t l_temp_left = 4800;
+ uint8_t l_dq = 0;
+ uint8_t l_p = 0;
+ FAPI_INF("In GET_MIN_MARGIN - iv_shmoo_type = %d", iv_shmoo_type);
+
+ for (l_p = 0; l_p < 2; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ ////
+ for (l_byte = 0; l_byte < 10; l_byte++)
+ {
+ //Nibble loop
+ for (l_nibble = 0; l_nibble < 2; l_nibble++)
+ {
+ for (l_bit = 0; l_bit < 4; l_bit++)
+ {
+ l_dq = 8 * l_byte + 4 * l_nibble + l_bit;
+
+ if ((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq]
+ < l_temp_right) && (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq] != 0 ))
+ {
+ l_temp_right
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_dq];
+ }
+
+ if ((SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq]
+ < l_temp_left) && (SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq] != 0))
+ {
+ l_temp_left
+ = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_dq];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(iv_shmoo_type == 8)
+ {
+ *o_right_min_margin = l_temp_left;
+ *o_left_min_margin = l_temp_right;
+ }
+ else
+ {
+ *o_right_min_margin = l_temp_right;
+ *o_left_min_margin = l_temp_left;
+ }
+ }
+
+ ///
+ /// @brief This function is used to get the minimum margin of all the schmoo margins
+ /// @param[in] i_target Centaur input MBA
+ /// @param[out] o_right_min_margin Minimum hold margin
+ /// @param[out] o_left_min_margin Minimum setup margin
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::get_min_margin_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t* o_right_min_margin, uint32_t* o_left_min_margin)
+ {
+ uint8_t l_rnk, l_nibble, i_rank = 0;
+ uint16_t l_temp_right = 4800;
+ uint16_t l_temp_left = 4800;
+ uint8_t l_p = 0;
+ uint8_t l_attr_eff_dram_width_u8 = 0;
+ uint8_t l_SCHMOO_NIBBLES = 20;
+ uint8_t l_by8_dqs = 0;
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_WIDTH, i_target, l_attr_eff_dram_width_u8));
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 18;
+ }
+
+ if(l_attr_eff_dram_width_u8 == 8)
+ {
+ l_SCHMOO_NIBBLES = 10;
+
+ if(iv_dmm_type == 1)
+ {
+ l_SCHMOO_NIBBLES = 9;
+ }
+ }
+
+ iv_shmoo_type = 4;
+
+ for (l_p = 0; l_p < MAX_PORT; l_p++)
+ {
+ for (l_rnk = 0; l_rnk < iv_MAX_RANKS[l_p]; l_rnk++)
+ {
+ i_rank = valid_rank1[l_p][l_rnk];
+
+ for(l_nibble = 0; l_nibble < l_SCHMOO_NIBBLES; l_nibble++)
+ {
+ l_by8_dqs = l_nibble;
+
+ if(iv_dmm_type == 0)
+ {
+ if(l_attr_eff_dram_width_u8 == 8)
+ {
+ l_nibble = l_nibble * 2;
+ }
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble] < l_temp_right)
+ {
+ l_temp_right = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.right_margin_val[l_nibble];
+ }
+
+ if(SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble] < l_temp_left)
+ {
+ l_temp_left = SHMOO[iv_SHMOO_ON].MBA.P[l_p].S[i_rank].K.left_margin_val[l_nibble];
+ }
+
+ if(iv_dmm_type == 0)
+ {
+ if(l_attr_eff_dram_width_u8 == 8)
+ {
+ l_nibble = l_by8_dqs;
+ }
+ }
+ } // for nibble
+ } // for rank
+ } // for port
+
+
+ // hacked for now till schmoo is running
+ if(iv_shmoo_type == 8)
+ {
+ *o_right_min_margin = l_temp_left;
+ *o_left_min_margin = l_temp_right;
+ }
+ else
+ {
+ *o_right_min_margin = l_temp_right;
+ *o_left_min_margin = l_temp_left;
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief call setup_mcbist
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode generic_shmoo::schmoo_setup_mcb(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
+ {
+
+ struct subtest_info l_sub_info[30] = {0};
+ uint32_t l_pattern = 0;
+ uint32_t l_testtype = 0;
+ mcbist_byte_mask i_mcbbytemask1;
+ char l_str_cust_addr[] =
+ "ba0,ba1,mr3,mr2,mr1,mr0,ba2,ba3,cl2,cl3,cl4,cl5,cl6,cl7,cl8,cl9,cl11,cl13,r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r13,r14,r15,r16,sl2,sl1,sl0";
+
+ i_mcbbytemask1 = UNMASK_ALL;
+ l_pattern = iv_pattern;
+ l_testtype = iv_test_type;
+
+ if (iv_shmoo_type == 16)
+ {
+ FAPI_INF("%s:\n Read DQS is running \n", mss::c_str(i_target));
+
+ if (iv_SHMOO_ON == 1)
+ {
+ l_testtype = 3;
+ }
+
+ if (iv_SHMOO_ON == 2)
+ {
+ l_testtype = 4;
+ }
+ }
+
+ //send shmoo mode to vary the address range
+ if (iv_shmoo_type == 16)
+ {
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_PATTERN, i_target, l_pattern));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_TEST_TYPE, i_target, l_testtype));
+ }
+
+ FAPI_TRY(setup_mcbist(i_target, i_mcbbytemask1, 0, 0x0ull , l_sub_info, l_str_cust_addr));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+}//Extern C
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.H
new file mode 100755
index 000000000..5a40fa7c8
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.H
@@ -0,0 +1,414 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_generic_shmoo.H
+/// @brief Memory Subsystem Generic Shmoo -- abstraction for HB
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#include <fapi2.H>
+
+#ifndef generic_shmoo_H
+#define generic_shmoo_H
+
+//! Globals
+#define SHMOO_DEBUG 0
+#define SHMOO_DEBUG2 0
+#include <p9c_mss_shmoo_common.H>
+#include <p9c_mss_mcbist.H>
+
+///
+/// @brief MSS Generic Shmoo Class.. Inherits from PHY access class and the knob abstraction
+///
+class generic_shmoo
+{
+ private:
+
+ //! MBS Config : Port + Socket + Knobs
+ struct SHMOO_SCENARIO
+ {
+ struct MBS_CONFIG
+ {
+ struct PORT
+ {
+ struct RANK
+ {
+ shmoo_knob_data_t K; // Set of knobs used by this shmoo
+ } S[MAX_RANK]; //Max Rank are 8
+ } P[MAX_PORT]; // Max Port 2
+ } MBA;
+ shmoo_knob_config_t static_knob; // Static info regarding the knob
+ } SHMOO[MAX_SHMOO]; // Denote max shmoo scenarios we have; Have 2; so that one for WR/RD and other Clock.
+
+ //! Result Data
+ uint8_t convergence_gap;
+ shmoo_algorithm_t algorithm;
+ shmoo_mode mcbist_mode;
+ uint8_t mcbist_error_map[MAX_PORT][MAX_RANK][MAX_BYTE][MAX_NIBBLES]; //MAX byte is 10; Max Nibble are 2;
+ uint8_t count_bad_dq[MAX_PORT];
+ uint8_t schmoo_error_map[MAX_PORT][MAX_RANK][MAX_BYTE * MAX_NIBBLES]; // 10 * 2 = 20 Nibbles
+ uint8_t binary_done_map[MAX_PORT][MAX_RANK][MAX_BYTE * MAX_NIBBLES]; // 10 * 2 = 20 Nibbles
+ shmoo_type_t shmoo_mask;
+ uint8_t iv_addr;
+ uint8_t iv_MAX_RANKS[MAX_PORT];
+ uint8_t iv_MAX_BYTES;
+ uint32_t iv_pattern;
+ uint32_t iv_test_type;
+ uint8_t iv_dmm_type;
+ uint8_t iv_SHMOO_ON;
+ uint8_t iv_DQS_ON;
+ uint8_t iv_shmoo_type;
+ uint16_t iv_shmoo_param;
+ uint16_t iv_binary_diff;
+ uint32_t iv_vref_mul;
+ uint8_t valid_rank[MAX_RANK];
+ uint8_t valid_rank1[MAX_PORT][MAX_RANK];
+
+ public:
+
+ enum bound_t {LEFT, RIGHT};
+ ///
+ /// @brief generic shmoo constructor
+ ///
+ generic_shmoo(uint8_t iv_addr, shmoo_type_t shmoo_mask, shmoo_algorithm_t shmoo_algorithm); // Constructor
+ ///
+ /// @brief generic generic shmoo constructor
+ ///
+ generic_shmoo() {};
+ ~generic_shmoo() {};
+
+ //initialize multi dim arrays to known value
+ void init_multi_array(uint16_t (&array)[MAX_DQ],
+ const uint16_t init_val);
+
+ ///
+ /// @brief This function gets the nominal values for each DQ of relevant knobs
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_all_noms(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief set all bits
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode set_all_binary(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound);
+
+ ///
+ /// @brief Read in all nominal values of relevant knobs
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_all_noms_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function calls the knob_update for each DQ which is used to find bound that is left/right according to schmoo type
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode find_bound(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t);
+
+ ///
+ /// @brief This is a key function is used to find right and left bound using new algorithm -- there is an option u can chose not to use it by setting a flag
+ /// @param[in] i_target Centaur input MBA Parameters: Target:MBA,bound:RIGHT/LEFT,scenario:type of schmoo,iv_port:0/1,rank:0-7,byte:0-7,nibble:0/1,bit:0-3,pass,
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode knob_update(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass);
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode knob_update_bin(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass);
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode knob_update_dqs_by8(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass);
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode knob_update_dqs_by4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass);
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode print_report(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode print_report_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode print_report_dqs2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_margin(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_margin2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_margin_dqs_by8(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_margin_dqs_by4(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_min_margin(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t* o_right_min_margin,
+ uint32_t* o_left_min_margin);
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ void get_min_margin2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t* o_right_min_margin,
+ uint32_t* o_left_min_margin);
+
+ ///
+ /// @brief This function is used to get margin for setup,hold and total eye width in Ps by using frequency
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_min_margin_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t* o_right_min_margin,
+ uint32_t* o_left_min_margin);
+
+ ///
+ /// @brief do mcbist check for error on particular nibble
+ /// @param[in] i_target: centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode do_mcbist_test(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief do mcbist reset
+ /// @param[in] i_target Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode do_mcbist_reset(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief used by do_mcbist_test to check the error map for particular nibble
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] l_p Centaur input port
+ /// @param[out] pass 1 = error found in mcb_error_map
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode check_error_map(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint8_t port,
+ uint8_t& pass);
+
+ ///
+ /// @brief used by do_mcbist_test to check the error map for particular nibble
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] l_p Centaur input port
+ /// @param[out] pass 1 = error found in mcb_error_map
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode check_error_map2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint8_t port,
+ uint8_t& pass);
+
+ ///
+ /// @brief do intial mcbist check in nominal and report spd if any bad bit found
+ /// @param[in] i_target Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff succesful
+ ///
+ fapi2::ReturnCode sanity_check(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief call setup_mcbist
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode schmoo_setup_mcb(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode knob_update_dqs_by8_isdimm(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass);
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode knob_update_dqs_by4_isdimm(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass);
+
+ ///
+ /// @brief Delegator function that runs shmoo using other functions
+ /// @param[in] i_target Centaur input mba
+ /// @param[out] o_right_min_margin Minimum hold time
+ /// @param[out] o_left_min_margin Minimum setup time
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode run(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t* right_min_margin,
+ uint32_t* left_min_margin,
+ uint32_t i_vref_mul);
+ ///
+ /// @brief save and restore registers before and after shmoo
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] i_content_array register contents to save/restore
+ /// @param[in] i_mode 0 = save; 1 = restore
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode shmoo_save_rest(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint64_t i_content_array[],
+ const uint8_t i_mode);
+
+ ///
+ /// @brief Sets the PDA nibble table with shmoo values
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] pda_nibble_table Per nibble vref + margins
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode get_nibble_pda(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ uint32_t pda_nibble_table[2][2][4][16][2]);
+
+ ///
+ /// @brief used to find right and left bound
+ /// @param[in] i_target Centaur input MBA
+ /// @param[in] bound RIGHT/LEFT
+ /// @param[in] scenario type of shmoo
+ /// @param[in] bit 0-3
+ /// @param[in] pass
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode knob_update_bin_composite(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target,
+ const bound_t bound,
+ const uint8_t scenario,
+ const uint8_t bit,
+ uint8_t pass);
+
+ ///
+ /// @brief This function is used to print the information needed such as freq,voltage etc, and also the right,left and total margin
+ /// @param[in] i_target Centaur input MBA
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode print_report2(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target);
+
+};
+#endif
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.mk
new file mode 100755
index 000000000..88a99a897
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_generic_shmoo.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_generic_shmoo
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.C
new file mode 100755
index 000000000..f992af05c
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.C
@@ -0,0 +1,845 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_mcbist.C
+/// @brief MCBIST execution procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#include <generic/memory/lib/utils/c_str.H>
+#include <p9c_mss_mcbist.H>
+#include <fapi2.H>
+extern "C"
+{
+ constexpr uint8_t MAX_BYTE = 10;
+ ///
+ /// @brief This function executes different MCBIST subtests
+ /// @param[in] i_target_mba Centaur.mba
+ /// @param[in] i_test_type Subtest Type
+ /// @param[in] i_sub_info
+ /// @retun FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode cfg_mcb_test_mem(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const mcbist_test_mem i_test_type,
+ struct subtest_info l_sub_info[30])
+ {
+ uint8_t l_print = 0;
+ uint32_t l_mcbtest = 0;
+ uint8_t l_index, l_data_flag, l_random_flag, l_count, l_data_attr;
+ l_index = 0;
+ l_data_flag = 0;
+ l_random_flag = 0;
+ l_data_attr = 0;
+ uint8_t l_done_bit = 0;
+ uint8_t test_array_count[44] = { 0, 2, 2, 1, 1, 1, 6, 6, 30, 30,
+ 2, 7, 4, 2, 1, 5, 4, 2, 1, 1,
+ 3, 1, 1, 4, 2, 1, 1, 1, 1, 10,
+ 0, 5, 3, 3, 3, 3, 9, 4, 30, 1,
+ 2, 2, 3, 3
+ };
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_PRINTING_DISABLE, i_target_mba, l_print));
+
+ if (l_print == 0)
+ {
+ FAPI_DBG("Function Name: cfg_mcb_test_mem");
+ FAPI_DBG("Start Time");
+ }
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_TEST_TYPE, i_target_mba, l_mcbtest));
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+ if (i_test_type == CENSHMOO)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : CENSHMOO ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, SF, FIX, 0, DEFAULT, FIX_ADDR, 0, 0, 1, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, FIX, 1, DEFAULT, FIX_ADDR, 1, 1, 1, l_sub_info));
+
+ }
+ else if (i_test_type == MEMWRITE)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : MEMWRITE ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, SF, FIX, 1, DEFAULT, FIX_ADDR, 0, 0, 0, l_sub_info));
+
+ }
+ else if (i_test_type == MEMREAD)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : MEMREAD ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, FIX, 1, DEFAULT, FIX_ADDR, 0, 0, 0, l_sub_info));
+ }
+ else if (i_test_type == SIMPLE_FIX)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : SIMPLE_FIX ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, SF, FIX, 0, DEFAULT, FIX_ADDR, 0, 0, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, FIX, 1, DEFAULT, FIX_ADDR, 1, 1, 4, l_sub_info));
+
+ l_done_bit = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, FIX, 1, DEFAULT, FIX_ADDR, 2, 2, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ OPER_RAND, 0, RF, FIX, 1, DEFAULT, FIX_ADDR, 3, 3, 4, l_sub_info));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR1Q,
+ RW, 4, RF, DATA_RF, 0, DEFAULT, FIX_ADDR, 0, 4, 4, l_sub_info));
+ }
+ else if (i_test_type == SIMPLE_RAND)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : SIMPLE_RAND ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ WR, 0, SF, DATA_RF, 1, DEFAULT, FIX_ADDR, 0, 0, 4, l_sub_info));
+
+
+ l_done_bit = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 1, SF, DATA_RF, 0, DEFAULT, FIX_ADDR, 1, 1, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, RF, DATA_RF, 0, DEFAULT, FIX_ADDR, 2, 2, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, RF, DATA_RF, 1, DEFAULT, FIX_ADDR, 3, 3, 4, l_sub_info));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR1Q,
+ RW, 4, RF, DATA_RF, 0, DEFAULT, FIX_ADDR, 0, 4, 4, l_sub_info));
+
+ }
+ else if (i_test_type == WR_ONLY)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : WR_ONLY ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, SF, DATA_RF, 0, DEFAULT, FIX_ADDR, 0, 0, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, DATA_RF, 1, DEFAULT, FIX_ADDR, 1, 1, 4, l_sub_info));
+
+
+ l_done_bit = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, RF, FIX, 0, DEFAULT, FIX_ADDR, 2, 2, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ OPER_RAND, 0, RF, FIX, 1, DEFAULT, FIX_ADDR, 3, 3, 4, l_sub_info));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR1Q,
+ RW, 4, RF, DATA_RF, 0, DEFAULT, FIX_ADDR, 0, 4, 4, l_sub_info));
+
+ }
+ else if (i_test_type == W_ONLY)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : W_ONLY ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, SF, DATA_RF, 1, DEFAULT, FIX_ADDR, 0, 0, 4, l_sub_info));
+
+
+ l_done_bit = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, FIX, 1, DEFAULT, FIX_ADDR, 1, 1, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, RF, FIX, 0, DEFAULT, FIX_ADDR, 2, 2, 4,
+ l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ OPER_RAND, 0, RF, FIX, 1, DEFAULT, FIX_ADDR, 3, 3, 4, l_sub_info));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR1Q,
+ RW, 4, RF, DATA_RF, 0, DEFAULT, FIX_ADDR, 0, 4, 4, l_sub_info));
+
+ }
+ else if (i_test_type == R_ONLY)
+ {
+ if (l_print == 0)
+ {
+ FAPI_DBG("Current MCBIST TESTTYPE : R_ONLY ");
+ }
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, DATA_RF, 1, DEFAULT, FIX_ADDR, 0, 0, 4, l_sub_info));
+
+
+ l_done_bit = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ GOTO, 0, SF, FIX, 0, DEFAULT, FIX_ADDR, 1, 1, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, RF, FIX, 0, DEFAULT, FIX_ADDR, 2, 2, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ OPER_RAND, 0, RF, FIX, 1, DEFAULT, FIX_ADDR, 3, 3, 4, l_sub_info));
+
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR1Q,
+ RW, 4, RF, DATA_RF, 0, DEFAULT, FIX_ADDR, 0, 4, 4, l_sub_info));
+
+ }
+ else if (i_test_type == SIMPLE_FIX_RF)
+ {
+ FAPI_DBG("%s:Current MCBIST TESTTYPE : SIMPLE_FIX_RF ",
+ mss::c_str(i_target_mba));
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ W, 0, SF, DATA_RF, 0, DEFAULT, FIX_ADDR, 0, 0, 4, l_sub_info));
+
+ FAPI_TRY(mcb_write_test_mem(i_target_mba, CEN_MBA_MCBMR0Q,
+ R, 0, SF, DATA_RF, 1, DEFAULT, FIX_ADDR, 1, 1, 4, l_sub_info));
+
+ l_done_bit = 1;
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_CFG_MCB_TEST_MEM_INVALID_INPUT().
+ set_TEST_TYPE_PARAM(i_test_type),
+ "Invalid MCBIST test type (%d)! cfg_mcb_test_mem Function",
+ i_test_type);
+ }
+
+ if (l_print == 0)
+ {
+ FAPI_DBG("Function Name: cfg_mcb_test_mem");
+ FAPI_DBG("Stop Time");
+ }
+
+ l_count = test_array_count[l_mcbtest];
+
+ for (l_index = 0; l_index < l_count; l_index++)
+ {
+ if (l_sub_info[l_index].l_fixed_data_enable == 1)
+ {
+ l_data_flag = 1;
+ }
+
+ if (l_sub_info[l_index].l_random_data_enable == 1)
+ {
+ l_random_flag = 1;
+ }
+ }
+
+ if ((l_data_flag == 0) && (l_random_flag == 1))
+ {
+ l_data_attr = 1;
+ }
+ else if ((l_data_flag == 1) && (l_random_flag == 0))
+ {
+ l_data_attr = 2;
+ }
+ else if ((l_data_flag == 1) && (l_random_flag == 1))
+ {
+ l_data_attr = 3;
+ }
+ else
+ {
+ l_data_attr = 3;
+ }
+
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MCBIST_DATA_ENABLE, i_target_mba, l_data_attr));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+
+ ///
+ /// @brief This function writes data patterns based on i_datamode passed
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_datamode MCBIST Data mode
+ /// @param[in] i_mcbrotate Provides the number of bit to shift per burst
+ /// @param[in] i_mcbrotdata Provides the data seed to shift per burst
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode cfg_mcb_dgen(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const mcbist_data_gen i_datamode,
+ const uint8_t i_mcbrotate,
+ const uint64_t i_mcbrotdata)
+ {
+ uint8_t l_print = 0;
+ uint8_t l_data_attr, l_random_flag, l_data_flag = 0;
+ l_data_flag = 1;
+ l_random_flag = 1;
+ l_data_attr = 3;
+ uint8_t l_seed_choice = 0;
+ uint32_t i_seed = 0;
+ i_seed = 0x20;
+ l_seed_choice = 1;
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ fapi2::buffer<uint64_t> l_var_data_buffer_64;
+ fapi2::buffer<uint64_t> l_var1_data_buffer_64;
+ fapi2::buffer<uint64_t> l_spare_data_buffer_64;
+ fapi2::buffer<uint32_t> l_data_buffer_32;
+ fapi2::buffer<uint16_t> l_data_buffer_16;
+ fapi2::variable_buffer l_data_buffer_4(4);
+ fapi2::variable_buffer l_data_buffer1_4(4);
+ uint64_t l_var = 0x0000000000000000ull;
+ uint64_t l_var1 = 0x0000000000000000ull;
+ uint64_t l_spare = 0x0000000000000000ull;
+ uint8_t l_rotnum = 0;
+ uint64_t l_data_buffer_64_value = 0;
+ uint32_t l_mba01_mcb_pseudo_random[MAX_BYTE] =
+ {
+ CEN_MBA_MCBFD0Q, CEN_MBA_MCBFD1Q,
+ CEN_MBA_MCBFD2Q, CEN_MBA_MCBFD3Q,
+ CEN_MBA_MCBFD4Q, CEN_MBA_MCBFD5Q,
+ CEN_MBA_MCBFD6Q, CEN_MBA_MCBFD7Q,
+ CEN_MBA_MCBFDQ, CEN_MBA_MCBFDSPQ
+ };
+ constexpr uint32_t l_mba01_mcb_random[MAX_BYTE] = { CEN_MBA_MCBRDS0Q,
+ CEN_MBA_MCBRDS1Q,
+ CEN_MBA_MCBRDS2Q,
+ CEN_MBA_MCBRDS3Q,
+ CEN_MBA_MCBRDS4Q,
+ CEN_MBA_MCBRDS5Q,
+ CEN_MBA_MCBRDS6Q,
+ CEN_MBA_MCBRDS7Q,
+ CEN_MBA_MCBRDS8Q,
+ CEN_MBA_MCBRDSSPQ
+ };
+ constexpr uint32_t l_mbs01_mcb_random[MAX_BYTE] = { CEN_MCBISTS01_MBS_MCBRDS0Q,
+ CEN_MCBISTS01_MBS_MCBRDS1Q,
+ CEN_MCBISTS01_MBS_MCBRDS2Q,
+ CEN_MCBISTS01_MBS_MCBRDS3Q,
+ CEN_MCBISTS01_MBS_MCBRDS4Q,
+ CEN_MCBISTS01_MBS_MCBRDS5Q,
+ CEN_MCBISTS01_MBS_MCBRDS6Q,
+ CEN_MCBISTS01_MBS_MCBRDS7Q,
+ CEN_MCBISTS01_MBS_MCBRDS8Q,
+ CEN_MCBISTS01_MBS_MCBRDSSPQ
+ };
+ constexpr uint32_t l_mbs23_mcb_random[MAX_BYTE] = { CEN_MCBISTS23_MBS_MCBRDS0Q,
+ CEN_MCBISTS23_MBS_MCBRDS1Q,
+ CEN_MCBISTS23_MBS_MCBRDS2Q,
+ CEN_MCBISTS23_MBS_MCBRDS3Q,
+ CEN_MCBISTS23_MBS_MCBRDS4Q,
+ CEN_MCBISTS23_MBS_MCBRDS5Q,
+ CEN_MCBISTS23_MBS_MCBRDS6Q,
+ CEN_MCBISTS23_MBS_MCBRDS7Q,
+ CEN_MCBISTS23_MBS_MCBRDS8Q,
+ CEN_MCBISTS23_MBS_MCBRDSSPQ
+ };
+
+ uint8_t l_index, l_index1 = 0;
+ uint32_t l_rand_32 = 0;
+ uint32_t l_rand_8 = 0;
+ uint8_t l_mbaPosition = 0;
+
+
+ if (l_print == 0)
+ {
+ FAPI_DBG("Function Name: cfg_mcb_dgen");
+ FAPI_DBG(" Data mode is %d ", i_datamode);
+ }
+
+ const auto i_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+
+ if (l_print == 0)
+ {
+ FAPI_DBG("Error in getting parent chip!");
+ }
+
+ if (l_print == 0)
+ {
+ FAPI_DBG("Function cfg_mcb_dgen");
+ }
+
+ //Read MBA position attribute 0 - MBA01 1 - MBA23
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target_mba, l_mbaPosition));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_PRINTING_DISABLE, i_target_mba, l_print));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_DATA_ENABLE, i_target_mba, l_data_attr));
+
+ if (l_data_attr == 1)
+ {
+ l_data_flag = 0;
+ l_random_flag = 1;
+ }
+ else if (l_data_attr == 2)
+ {
+ l_data_flag = 1;
+ l_random_flag = 0;
+ }
+ else if (l_data_attr == 3)
+ {
+ l_data_flag = 1;
+ l_random_flag = 1;
+ }
+ else
+ {
+ l_data_flag = 1;
+ l_random_flag = 1;
+ }
+
+ if (l_data_flag == 1)
+ {
+ if (i_datamode == MCBIST_2D_CUP_PAT5)
+ {
+ l_var = 0xFFFF0000FFFF0000ull;
+ l_var1 = 0x0000FFFF0000FFFFull;
+ l_spare = 0xFF00FF00FF00FF00ull;
+
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+ l_spare_data_buffer_64 = l_spare;
+
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if (i_datamode == MCBIST_2D_CUP_PAT8)
+ {
+ l_var = 0xFFFFFFFFFFFFFFFFull;
+ l_var1 = 0x0000000000000000ull;
+ l_spare = 0xFFFF0000FFFF0000ull;
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+ l_spare_data_buffer_64 = l_spare;
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD1Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD2Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD5Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD6Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if (i_datamode == ABLE_FIVE)
+ {
+ l_var = 0xA5A5A5A5A5A5A5A5ull;
+ l_var1 = 0x5A5A5A5A5A5A5A5Aull;
+ l_spare = 0xA55AA55AA55AA55Aull;
+
+ l_spare_data_buffer_64 = l_spare;
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if(i_datamode == MPR)
+ {
+ l_var = 0x0000000000000000ull;
+ l_var1 = 0xFFFFFFFFFFFFFFFFull;
+ l_spare = 0x00FF00FF00FF00FFull;
+
+ l_spare_data_buffer_64 = l_spare;
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDQ , l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDSPQ , l_spare_data_buffer_64));
+ }
+ else if ((i_datamode == DATA_GEN_DELTA_I) ||
+ (i_datamode == MCBIST_2D_CUP_PAT0))
+ {
+ l_var = 0xFFFFFFFFFFFFFFFFull;
+ l_var1 = 0x0000000000000000ull;
+ l_spare = 0xFF00FF00FF00FF00ull;
+ l_spare_data_buffer_64 = l_spare;
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if (i_datamode == PSEUDORANDOM)
+ {
+ l_rand_32 = 0xFFFFFFFF;//Hard Coded Temporary Fix till random function is fixed
+
+ // srand(2);
+ if (l_seed_choice == 1)
+ {
+ if (i_seed == 0)
+ {
+ i_seed = 0xFFFFFFFF;
+ }
+
+ l_rand_32 = i_seed;
+ }
+
+ for (l_index = 0; l_index < (MAX_BYTE); l_index++)
+ {
+ FAPI_TRY(l_data_buffer_32.insertFromRight(l_rand_32, 0, 32));
+ FAPI_TRY(l_data_buffer_64.insert(uint32_t(l_data_buffer_32), 0, 32, 0));
+ FAPI_TRY(l_data_buffer_32.insertFromRight(l_rand_32, 0, 32));
+ FAPI_TRY(l_data_buffer_64.insert(uint32_t(l_data_buffer_32), 32, 32, 0));
+ FAPI_TRY(fapi2::putScom(i_target_mba, l_mba01_mcb_pseudo_random[l_index],
+ l_data_buffer_64));
+ }
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_CFG_MCB_DGEN_INVALID_INPUT().
+ set_DATA_MODE_PARAM(i_datamode),
+ "cfg_mcb_dgen: Invalid data mode (%d)",
+ i_datamode);
+ }
+
+ if (i_datamode == MCBIST_2D_CUP_PAT5)
+ {
+ l_var = 0xFFFF0000FFFF0000ull;
+ l_var1 = 0x0000FFFF0000FFFFull;
+ l_spare = 0xFF00FF00FF00FF00ull;
+
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+ l_spare_data_buffer_64 = l_spare;
+
+ if (l_mbaPosition == 0)
+ {
+ //Writing MBS 01 pattern registers for comparison mode
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if (l_mbaPosition == 1)
+ {
+ //Writing MBS 23 pattern registers for comparison mode
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ }
+ else if (i_datamode == MCBIST_2D_CUP_PAT8)
+ {
+ l_var = 0xFFFFFFFFFFFFFFFFull;
+ l_var1 = 0x0000000000000000ull;
+ l_spare = 0xFFFF0000FFFF0000ull;
+
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+ l_spare_data_buffer_64 = l_spare;
+
+ if (l_mbaPosition == 0)
+ {
+ //Writing MBS 01 pattern registers for comparison mod
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD1Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD2Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD5Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD6Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if (l_mbaPosition == 1)
+ {
+ //Writing MBS 23 pattern registers for comparison mod
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD1Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD2Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD5Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD6Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ }
+ else if (i_datamode == ABLE_FIVE)
+ {
+ l_var = 0xA5A5A5A5A5A5A5A5ull;
+ l_var1 = 0x5A5A5A5A5A5A5A5Aull;
+ l_spare = 0xA55AA55AA55AA55Aull;
+
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+ l_spare_data_buffer_64 = l_spare;
+
+ if (l_mbaPosition == 0)
+ {
+ //Writing MBS 01 pattern registers for comparison mod
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if (l_mbaPosition == 1)
+ {
+ //Writing MBS 23 pattern registers for comparison mod
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ }
+ else if ((i_datamode == DATA_GEN_DELTA_I) || (i_datamode
+ == MCBIST_2D_CUP_PAT0))
+ {
+ l_var = 0xFFFFFFFFFFFFFFFFull;
+ l_var1 = 0x0000000000000000ull;
+ l_spare = 0xFF00FF00FF00FF00ull;
+
+ l_var_data_buffer_64 = l_var;
+ l_var1_data_buffer_64 = l_var1;
+ l_spare_data_buffer_64 = l_spare;
+
+ if (l_mbaPosition == 0)
+ {
+ //Writing MBS 01 pattern registers for comparison mod
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ else if (l_mbaPosition == 1)
+ {
+ //Writing MBS 23 pattern registers for comparison mod
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD0Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD1Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD2Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD3Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD4Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD5Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD6Q, l_var_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFD7Q, l_var1_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDQ, l_spare_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MBS_MCBFDSPQ, l_spare_data_buffer_64));
+ }
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_CFG_MCB_DGEN_INVALID_INPUT().
+ set_DATA_MODE_PARAM(i_datamode),
+ "cfg_mcb_dgen: Invalid data mode (%d)",
+ i_datamode);
+ }
+ }
+
+ if (l_random_flag == 1)
+ {
+ for (l_index = 0; l_index < MAX_BYTE; l_index++)
+ {
+ for (l_index1 = 0; l_index1 < 8; l_index1++)
+ {
+ l_rand_8 = 0xFF;
+ FAPI_TRY(l_data_buffer_64.insert(l_rand_8, 8 * l_index1, 8, 24));
+ }
+
+ FAPI_TRY(fapi2::putScom(i_target_mba, l_mba01_mcb_random[l_index], l_data_buffer_64));
+
+ if (l_mbaPosition == 0)
+ {
+ FAPI_TRY(fapi2::putScom(i_target_centaur, l_mbs01_mcb_random[l_index], l_data_buffer_64));
+ }
+ else
+ {
+ FAPI_TRY(fapi2::putScom(i_target_centaur, l_mbs23_mcb_random[l_index], l_data_buffer_64));
+ }
+ }
+ }
+
+
+ // get the rotate value loaded into reg, if rotate value 0 / not defined the default to rotate =13
+ if(i_mcbrotate == 0)
+ {
+ FAPI_DBG("%s:i_mcbrotate == 0 , the l_rotnum is set to 13", mss::c_str(i_target_mba));
+ l_rotnum = 13; // for random data generation - basic setup
+ }
+ else
+ {
+ l_rotnum = i_mcbrotate;
+ }
+
+ l_data_buffer_64.flush<0>();
+
+ // get the rotate data seed loaded into reg, if rotate data value = 0 / not defined the default rotate pttern is randomlly generated.
+ if(i_mcbrotdata == 0)
+ {
+ // generate the random number
+ l_data_buffer_64 = 0x863A822CDF2924C4ull;
+ }
+ else
+ {
+ l_data_buffer_64 = i_mcbrotdata;
+ }
+
+ // load the mcbist and mba with rotnum and rotdata.
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBDRSRQ , l_data_buffer_64)); //added
+
+ if(l_mbaPosition == 0)
+ {
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201167F , l_data_buffer_64));
+ l_data_buffer_64_value = l_data_buffer_64;
+ FAPI_INF("%s:Value of Rotate data seed %016llX for reg %08X", mss::c_str(i_target_mba), l_data_buffer_64_value,
+ 0x0201167F );
+
+ FAPI_TRY(l_data_buffer_16.insert(l_data_buffer_64, 0, 16));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, 0x02011680 , l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.insert(l_rotnum, 0, 4, 4));
+ FAPI_TRY(l_data_buffer_64.insert(l_data_buffer_16, 4, 16));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x02011680 , l_data_buffer_64));
+ }
+ else
+ {
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x0201177F , l_data_buffer_64)); //added
+ l_data_buffer_64_value = l_data_buffer_64;
+ FAPI_INF("%s:Value of Rotate data seed %016llX for reg %08X", mss::c_str(i_target_mba), l_data_buffer_64_value,
+ 0x0201177F );
+
+ FAPI_TRY(l_data_buffer_16.insert(l_data_buffer_64, 0, 16));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, 0x02011780 , l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.insert(l_rotnum, 0, 4, 4));
+ FAPI_TRY(l_data_buffer_64.insert(l_data_buffer_16, 4, 16));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, 0x02011780 , l_data_buffer_64));
+ }
+
+ FAPI_DBG("%s: Preet Clearing bit 20 of CEN_MBA_MCBDRCRQ to avoid inversion of data to the write data flow",
+ mss::c_str(i_target_mba));
+ l_data_buffer_64.clearBit<20, 2>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBDRCRQ, l_data_buffer_64));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.H
new file mode 100755
index 000000000..1f2746d75
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.H
@@ -0,0 +1,443 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_mcbist.H
+/// @brief MCBIST execution procedures header
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#ifndef MSS_MCBIST_H
+#define MSS_MCBIST_H
+#include <fapi2.H>
+#include <cen_gen_scom_addresses.H>
+#include <p9c_mss_access_delay_reg.H>
+#include <dimmConsts.H>
+
+extern "C"
+{
+
+ //############### Global variables ################
+ ///
+ /// @brief mcbist test enums
+ ///
+ enum mcbist_test_mem
+ {
+ USER_MODE,
+ CENSHMOO,
+ SUREFAIL,
+ MEMWRITE,
+ MEMREAD,
+ CBR_REFRESH,
+ MCBIST_SHORT,
+ SHORT_SEQ,
+ DELTA_I,
+ DELTA_I_LOOP,
+ SHORT_RAND,
+ LONG1,
+ BUS_TAT,
+ SIMPLE_FIX,
+ SIMPLE_RAND,
+ SIMPLE_RAND_2W,
+ SIMPLE_RAND_FIXD,
+ SIMPLE_RA_RD_WR,
+ SIMPLE_RA_RD_R,
+ SIMPLE_RA_FD_R,
+ SIMPLE_RA_FD_R_INF,
+ SIMPLE_SA_FD_R,
+ SIMPLE_RA_FD_W,
+ INFINITE,
+ WR_ONLY,
+ W_ONLY,
+ R_ONLY,
+ W_ONLY_RAND,
+ R_ONLY_RAND,
+ R_ONLY_MULTI,
+ SHORT,
+ SIMPLE_RAND_BARI,
+ W_R_INFINITE,
+ W_R_RAND_INFINITE,
+ R_INFINITE1,
+ R_INFINITE_RF,
+ MARCH,
+ SIMPLE_FIX_RF,
+ SHMOO_STRESS,
+ SIMPLE_RAND_RA,
+ SIMPLE_FIX_RA,
+ SIMPLE_FIX_RF_RA,
+ TEST_RR,
+ TEST_RF,
+ W_ONLY_INFINITE_RAND,
+ MCB_2D_CUP_SEQ,
+ MCB_2D_CUP_RAND,
+ SHMOO_STRESS_INFINITE,
+ HYNIX_1_COL,
+ RMWFIX,
+ RMWFIX_I,
+ W_INFINITE,
+ R_INFINITE
+ };
+ ///
+ /// @brief mcbist data enums
+ ///
+ enum mcbist_data_gen
+ {
+ ABLE_FIVE,
+ USR_MODE,
+ ONEHOT,
+ DQ0_00011111_RESTALLONE,
+ DQ0_11100000_RESTALLZERO,
+ ALLZERO,
+ ALLONE,
+ BYTE_BURST_SIGNATURE,
+ BYTE_BURST_SIGNATURE_V1,
+ BYTE_BURST_SIGNATURE_V2,
+ BYTE_BURST_SIGNATURE_V3,
+ DATA_GEN_DELTA_I,
+ MCBIST_2D_CUP_PAT0,
+ MPR,
+ MPR03,
+ MPR25,
+ MPR47,
+ DELTA_I1,
+ MCBIST_2D_CUP_PAT1,
+ MHC_55,
+ MHC_DQ_SIM,
+ MCBIST_2D_CUP_PAT2,
+ MCBIST_2D_CUP_PAT3,
+ MCBIST_2D_CUP_PAT4,
+ MCBIST_2D_CUP_PAT5,
+ MCBIST_2D_CUP_PAT6,
+ MCBIST_2D_CUP_PAT7,
+ MCBIST_2D_CUP_PAT8,
+ MCBIST_2D_CUP_PAT9,
+ CWLPATTERN,
+ GREY1,
+ DC_ONECHANGE,
+ DC_ONECHANGEDIAG,
+ GREY2,
+ FIRST_XFER,
+ MCBIST_222_XFER,
+ MCBIST_333_XFER,
+ MCBIST_444_XFER,
+ MCBIST_555_XFER,
+ MCBIST_666_XFER,
+ MCBIST_777_XFER,
+ MCBIST_888_XFER,
+ FIRST_XFER_X4MODE,
+ MCBIST_LONG,
+ PSEUDORANDOM,
+ CASTLE
+ };
+
+ ///
+ /// @brief mcbist operation enums
+ ///
+ enum mcbist_oper_type
+ {
+ W,
+ R,
+ RW,
+ WR,
+ RWR,
+ RWW,
+ OPER_RAND,
+ GOTO
+ };
+
+ ///
+ /// @brief mcbist data mode enums
+ ///
+ enum mcbist_data_mode
+ {
+ FIX,
+ DATA_RF,
+ DATA_RR,
+ RECCF,
+ RECCB,
+ DEA,
+ DRL,
+ DRR
+
+ };
+
+ ///
+ /// @brief mcbist address mode enums
+ ///
+ enum mcbist_addr_mode
+ {
+ SF,
+ SR,
+ RF,
+ RR
+ };
+
+ ///
+ /// @brief mcbist select mode enums
+ ///
+ enum mcbist_add_select_mode
+ {
+ FIX_ADDR,
+ PORTA0_RANDOM,
+ PORTA1_RANDOM,
+ PORTA0_SEQ
+ };
+
+ ///
+ /// @brief mcbist data select enums
+ ///
+ enum mcbist_data_select_mode
+ {
+ DEFAULT,
+ BURST0,
+ BURST1,
+ BURST2
+ };
+
+ ///
+ /// @brief byte mask enums
+ ///
+ enum mcbist_byte_mask
+ {
+ BYTE0,
+ BYTE1,
+ BYTE2,
+ BYTE3,
+ BYTE4,
+ BYTE5,
+ BYTE6,
+ BYTE7,
+ BYTE8,
+ BYTE9,
+ UNMASK_ALL,
+ NONE
+ };
+
+ ///
+ /// @brief shmoo mode enums
+ ///
+ enum shmoo_mode
+ {
+ FAST = 0,
+ ONE_SLOW = 1,
+ QUARTER_SLOW = 2,
+ HALF_SLOW = 3,
+ FULL_SLOW = 4,
+ ONE_CHAR = 5,
+ QUARTER_CHAR = 6,
+ HALF_CHAR = 7,
+ FULL_CHAR = 8
+ };
+
+ ///
+ /// @brief shmoo address mode enums
+ ///
+ enum shmoo_addr_mode
+ {
+ FEW_ADDR = 0,
+ QUARTER_ADDR = 1,
+ HALF_ADDR = 2,
+ FULL_ADDR = 3
+ };
+
+ ///
+ /// @brief subtest enums
+ ///
+ struct subtest_info
+ {
+ uint8_t l_operation_type;
+ uint8_t l_data_mode;
+ uint8_t l_addr_mode;
+ uint8_t l_random_data_enable;
+ uint8_t l_fixed_data_enable;
+ uint8_t l_random_addr_enable;
+ uint8_t l_fixed_addr_enable;
+ };
+
+ ///
+ /// @brief check the MCBIST Configuration Register for mcb fail, in progress, done
+ /// @param[in] i_target_mba Centaur.mba
+ /// @param[out] o_mcb_status MCB status
+ /// @param[in] i_sub_info MCB subtest information array
+ /// @param[in] i_flag verbose flag
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode poll_mcb(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ uint8_t* o_mcb_status,
+ struct subtest_info l_sub_info[30],
+ const uint8_t i_flag);
+
+ ///
+ /// @brief Reads the nibblewise Error map registers into o_error_map
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[out] o_error_map[][8][10][2] Contains the error map
+ /// @param[in] i_CDarray0[80]
+ /// @param[in] i_CDarray1[80]
+ /// @param[in] count_bad_dq[2]
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_error_map(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ uint8_t o_error_map[MAX_PORTS_PER_MBA][MAX_RANKS_PER_PORT][MAX_BYTES_PER_RANK][MAX_NIBBLES_PER_BYTE],
+ uint8_t i_CDarray0[DIMM_DQ_SPD_DATA_SIZE],
+ uint8_t i_CDarray1[DIMM_DQ_SPD_DATA_SIZE],
+ uint8_t count_bad_dq[2]);
+
+ ///
+ /// @brief Based on parameters passed we write data into Register being passed
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_reg_addr Register address
+ /// @param[in] i_operation_type Operation Type
+ /// @param[in] i_cfg_test_123_cmd Integer value
+ /// @param[in] i_addr_mode Sequential or Random address modes
+ /// @param[in] i_data_mode Data Mode
+ /// @param[in] i_done Done Bit
+ /// @param[in] i_data_select_mode Different BURST modes or DEFAULT
+ /// @param[in] i_addr_select_mode Address Select mode
+ /// @param[in] i_testnumber Subtest number
+ /// @param[in] i_testnumber1 Subtest number
+ /// @param[in] i_total_subtest_no
+ /// @param[in] i_sub_info Subtest info array
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_write_test_mem(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint64_t i_reg_addr,
+ const mcbist_oper_type i_operation_type,
+ const uint8_t i_cfg_test_123_cmd,
+ const mcbist_addr_mode i_addr_mode,
+ const mcbist_data_mode i_data_mode,
+ const uint8_t i_done,
+ const mcbist_data_select_mode i_data_select_mode,
+ const mcbist_add_select_mode i_addr_select_mode,
+ const uint8_t i_testnumber,
+ const uint8_t i_testnumber1,
+ const uint8_t i_total_no,
+ struct subtest_info l_sub_info[30]);
+
+ ///
+ /// @brief This function executes different MCBIST subtests
+ /// @param[in] i_target_mba Centaur.mba
+ /// @param[in] i_test_type Subtest Type
+ /// @param[in] i_sub_info
+ /// @retun FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode cfg_mcb_test_mem(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const mcbist_test_mem i_test_type,
+ struct subtest_info l_sub_info[30]);
+
+ ///
+ /// @brief Clears all the trap registers in MCBIST engine
+ /// @param[in] i_target_mba Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_reset_trap(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief This function writes data patterns based on i_datamode passed
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_datamode MCBIST Data mode
+ /// @param[in] i_mcbrotate Provides the number of bit to shift per burst
+ /// @param[in] i_mcbrotdata Provides the data seed to shift per burst
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode cfg_mcb_dgen(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const mcbist_data_gen i_datamode,
+ const uint8_t i_mcbrotate,
+ const uint64_t i_mcbrotdata);
+
+ ///
+ /// @brief It is used to mask bad bits read from SPD
+ /// @param[in] i_target_mba Centaur.mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode cfg_byte_mask(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief Checks for dimms drop in the particular port & starts MCBIST
+ /// @param[in] i_target_mna Centaur.mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode start_mcb(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+ ///
+ /// @brief Will setup the required MCBIST configuration register
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_mcbbytemask It is used to mask bad bits read from SPD
+ /// @param[in] i_mcbrotate Provides the number of bit to shift per burst
+ /// @param[in] i_mcbrotdata Provides the rotate data to shift per burst
+ /// @param[in] i_sub_info
+ /// @param[in] i_str_cust_addr
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode setup_mcbist(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const mcbist_byte_mask i_mcbbytemask,
+ const uint8_t i_mcbrotate,
+ const uint64_t i_mcbrotdata,
+ struct subtest_info l_sub_info[30],
+ const char* l_str_cust_addr);
+
+ ///
+ /// @brief print the mcbist error map
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @param[in] i_mcb_fail_160
+ /// @param[in] i_port Centaur input port
+ /// @param[in] i_array error array
+ /// @param[in] i_number Highest index in array w error
+ /// @param[in] i_data_buf_port MCB data mask
+ /// @param[in] i_data_buf_spare MCB data mask
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_error_map_print(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const fapi2::variable_buffer& l_mcb_fail_160,
+ const uint8_t i_port,
+ const uint8_t l_array[DIMM_DQ_SPD_DATA_SIZE],
+ const uint8_t l_number,
+ const fapi2::buffer<uint64_t> l_data_buf_port,
+ const fapi2::buffer<uint64_t> l_data_buf_spare);
+ ///
+ /// @brief Convert Testype num to mcbist_test_mem type
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_pattern MCBIST testtype
+ /// @param[out] o_mcbtest MCBIST testtype
+ ///
+ void mss_conversion_testtype(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t l_pattern,
+ mcbist_test_mem& o_mcbtest);
+
+ ///
+ /// @brief convert number pattern to mcbist_data_gen type
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_pattern input pattern
+ /// @param[out] o_mcbpatt mcbist_data_gen type pattern
+ ///
+ void mss_conversion_data(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t l_pattern,
+ mcbist_data_gen& o_mcbpatt);
+}
+#endif
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.mk
new file mode 100755
index 000000000..51eddabff
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_mcbist
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.C
new file mode 100644
index 000000000..79fb0dc86
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.C
@@ -0,0 +1,934 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_mcbist_address.C
+/// @brief MCBIST address generation procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+
+#include <p9c_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/c_str.H>
+extern "C"
+{
+#define DELIMITERS ","
+ constexpr uint8_t MAX_ADDR_BITS = 37;
+
+ ///
+ /// @brief Setup MCBIST address string
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @param[in] l_str_cust_addr Optional custom address string
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode address_generation(const fapi2:: Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const char* l_str_cust_addr)
+ {
+ uint8_t l_num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_num_master_ranks[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_dram_rows = 0;
+ uint8_t l_dram_cols = 0;
+ uint8_t l_addr_inter = 0;
+ uint8_t l_num_ranks_p0_dim0, l_num_ranks_p0_dim1, l_num_ranks_p1_dim0, l_num_ranks_p1_dim1 = 0;
+ uint8_t l_master_ranks_p0_dim0, l_master_ranks_p0_dim1, l_master_ranks_p1_dim0 = 0;
+ uint8_t mr3_valid, mr2_valid, mr1_valid, sl0_valid, sl1_valid, sl2_valid = 0;
+
+ char S0[] = "b";
+ //Choose a default buffer for the below
+ //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
+ //MR0(MSB) MR1 MR2 MR3 BA0 BA1 BA2 BA3 C3 C4 C5 C6 C7 C8 C9 C10 C11 R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 SL0(MSB) SL1 SL2
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, l_num_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target_mba, l_num_master_ranks));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_ROWS, i_target_mba, l_dram_rows));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_COLS, i_target_mba, l_dram_cols));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_ADDR_INTER, i_target_mba, l_addr_inter));
+
+ l_num_ranks_p0_dim0 = l_num_ranks_per_dimm[0][0];
+ l_num_ranks_p0_dim1 = l_num_ranks_per_dimm[0][1];
+ l_num_ranks_p1_dim0 = l_num_ranks_per_dimm[1][0];
+ l_num_ranks_p1_dim1 = l_num_ranks_per_dimm[1][1];
+ l_master_ranks_p0_dim0 = l_num_master_ranks[0][0];
+ l_master_ranks_p0_dim1 = l_num_master_ranks[0][1];
+ l_master_ranks_p1_dim0 = l_num_master_ranks[1][0];
+
+ //Initial all ranks are invalid
+ mr3_valid = 0;
+ mr2_valid = 0;
+ mr1_valid = 0;
+ sl2_valid = 0;
+ sl1_valid = 0;
+ sl0_valid = 0;
+
+ if( (l_num_ranks_p0_dim0 == 1 && l_num_ranks_p0_dim1 == 0) || (l_num_ranks_p1_dim0 == 1
+ && l_num_ranks_p1_dim1 == 0) ) //Single Rank case -- default0
+ {
+ //do rank-only stuff for this
+ FAPI_DBG("%s:--- INSIDE 1R", mss::c_str(i_target_mba));
+ l_addr_inter = 3;
+ }
+
+ else if ( (l_num_ranks_p0_dim0 == 1 && l_num_ranks_p0_dim1 == 1) || (l_num_ranks_p1_dim0 == 1
+ && l_num_ranks_p1_dim1 == 1) )
+ {
+ FAPI_DBG("%s:--- INSIDE p0d0 valid and p0d1 valid --- 0 4---- 2R", mss::c_str(i_target_mba));
+ mr1_valid = 1;
+ }
+
+ else if ( (l_num_ranks_p0_dim0 == 2 && l_num_ranks_p0_dim1 == 0) || (l_num_ranks_p1_dim0 == 2
+ && l_num_ranks_p1_dim1 == 0) )
+ {
+ FAPI_DBG("%s:--- INSIDE p0d0 valid and p0d1 valid --- 0 1---- 2R", mss::c_str(i_target_mba));
+ mr3_valid = 1;
+ }
+ else if (((l_num_ranks_p0_dim0 == 2 && l_num_ranks_p0_dim1 == 2) || (l_num_ranks_p1_dim0 == 2
+ && l_num_ranks_p1_dim1 == 2)) && (l_master_ranks_p0_dim0 != 1 && l_master_ranks_p0_dim1 != 1)) //Rank 01 and 45 case
+ {
+ FAPI_DBG("%s:--- INSIDE --- 2R 0145", mss::c_str(i_target_mba));
+ mr3_valid = 1;
+ mr1_valid = 1;
+ }
+
+ else if((l_num_ranks_p0_dim0 == 4 && l_num_ranks_p0_dim1 == 0 ) || (l_num_ranks_p1_dim0 == 4
+ && l_num_ranks_p1_dim1 == 0 )) //Rank 0123 on single dimm case
+ {
+ mr3_valid = 1;
+ mr2_valid = 1;
+ }
+ else if (((l_num_ranks_p0_dim0 == 4 && l_num_ranks_p0_dim1 == 4) || (l_num_ranks_p1_dim0 == 4
+ && l_num_ranks_p1_dim1 == 4)) && l_master_ranks_p0_dim0 == 1) //1r 4h stack
+ {
+ mr1_valid = 0; //DDC
+ sl1_valid = 1;
+ sl2_valid = 1;
+ }
+
+ else if (((l_num_ranks_p0_dim0 == 8 && l_num_ranks_p0_dim1 == 0) || (l_num_ranks_p1_dim0 == 8
+ && l_num_ranks_p1_dim1 == 0)) && ((l_master_ranks_p0_dim0 == 2) || (l_master_ranks_p0_dim1 == 0
+ && l_master_ranks_p1_dim0 == 2))) //2rx4 4h ddr4 3ds
+ {
+ l_addr_inter = 4;
+ mr3_valid = 1; //DDC
+ sl1_valid = 1;
+ sl2_valid = 1;
+ }
+ else if ((l_num_ranks_p0_dim0 == 4 && l_num_ranks_p0_dim1 == 4) || (l_num_ranks_p1_dim0 == 4
+ && l_num_ranks_p1_dim1 == 4)) //Rank 0123 and 4567 case
+ {
+ mr3_valid = 1;
+ mr2_valid = 1;
+ mr1_valid = 1;
+ }
+ else if (((l_num_ranks_p0_dim0 == 2 && l_num_ranks_p0_dim1 == 2) ||
+ (l_num_ranks_p1_dim0 == 2 && l_num_ranks_p1_dim1 == 2)) &&
+ (l_master_ranks_p0_dim0 == 1 && l_master_ranks_p0_dim1 == 1)) //1rx4 2h ddr4 3ds 2 dimm, CDIMM
+ {
+ sl1_valid = 0;
+ sl2_valid = 1;
+ mr1_valid = 1;
+ }
+ else
+ {
+ FAPI_INF("-- Error ---- mcbist_addr_Check dimm_Config ----- ");
+ }
+
+ //custom addressing string is not to be used
+ if(l_addr_inter != 4)
+ {
+ FAPI_TRY(parse_addr(i_target_mba, S0, mr3_valid, mr2_valid, mr1_valid,
+ l_dram_rows, l_dram_cols, l_addr_inter, sl2_valid, sl1_valid, sl0_valid));
+ }
+ else
+ {
+ FAPI_DBG("Custom addressing flag was selected");
+ FAPI_TRY(parse_addr(i_target_mba, l_str_cust_addr, mr3_valid, mr2_valid, mr1_valid,
+ l_dram_rows, l_dram_cols, l_addr_inter, sl2_valid, sl1_valid, sl0_valid));
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Parse MCBIST address string and set corresponding registers
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @param[in] addr_string MCBIST address string
+ /// @param[in] mr3_valid Master rank 3 valid bit
+ /// @param[in] mr2_valid Master rank 2 valid bit
+ /// @param[in] mr1_valid Master rank 1 valid bit
+ /// @param[in] l_dram_rows Num dram rows
+ /// @param[in] l_dram_cols Num dram columns
+ /// @param[in] l_addr_inter Address interleave bit
+ /// @param[in] sl2_valid Slave rank 2 valid bit
+ /// @param[in] sl1_valid Slave rank 1 valid bit
+ /// @param[in] sl0_valid Slave rank 0 valid bit
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode parse_addr(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const char addr_string[],
+ const uint8_t mr3_valid,
+ const uint8_t mr2_valid,
+ const uint8_t mr1_valid,
+ const uint8_t l_dram_rows,
+ const uint8_t l_dram_cols,
+ const uint8_t l_addr_inter,
+ const uint8_t sl2_valid,
+ const uint8_t sl1_valid,
+ const uint8_t sl0_valid)
+ {
+ uint8_t i = MAX_ADDR_BITS;
+ uint8_t l_value = 0;
+ uint32_t l_value32 = 0;
+ uint32_t l_sbit = 0;
+ uint32_t l_start = 0;
+ uint32_t l_len = 0;
+ uint64_t l_readscom_value = 0;
+ uint64_t l_end = 0;
+ uint64_t l_start_addr = 0;
+ uint8_t l_value_zero = 0;
+ uint8_t l_user_end_addr = 0;
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ fapi2::buffer<uint64_t> l_data_buffer_rd64;
+ uint8_t l_attr_addr_mode = 0;
+ uint8_t l_num_cols = 0;
+ uint8_t l_num_rows = 0;
+ uint8_t l_dram_gen = 0;
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_MODE, i_target_mba, l_attr_addr_mode));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_ADDR_NUM_COLS, i_target_mba, l_num_cols));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_ADDR_NUM_ROWS, i_target_mba, l_num_rows));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, l_dram_gen));
+
+ if (l_num_cols == 0)
+ {
+ l_num_cols = l_dram_cols;
+ }
+
+ if (l_num_rows == 0)
+ {
+ l_num_rows = l_dram_rows;
+ }
+
+ //Set all the addr reg to 0
+ //Define Custom String
+ //Set all Params based on the string.
+ l_data_buffer_64.flush<0>();
+ l_sbit = 0;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+
+ l_sbit = 54;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+
+ l_sbit = 18;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ if (mr3_valid == 1)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 12;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ if (mr2_valid == 1)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 6;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ if (mr1_valid == 1)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 48;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+
+ l_sbit = 42;
+ l_value = i;
+ //------- Enable these for DDR4 --- for now constant map to zero
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ if (l_dram_gen == 2)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 0;
+ l_value = i;
+ //------- Enable these for DDR4 --- for now constant map to zero
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ l_sbit = 42;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ l_sbit = 36;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 1)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 30;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 2)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 24;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 3)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 18;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 4)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 12;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 5)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 6;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 6)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 0;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 7)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+ i--;
+ }
+
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR3A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 54;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 11)
+ {
+ if (l_dram_cols >= 11)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ FAPI_DBG("%s:Col 11 -- Invalid", mss::c_str(i_target_mba));
+
+ }
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 48;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_cols >= 12)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 42;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 0)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 36;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 1)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 30;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 2)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 24;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 3)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 18;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 4)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 12;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 5)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 6;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 6)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 0;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 7)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR2A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 54;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 8)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 48;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 9)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 42;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 10)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 36;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 11)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 30;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 12)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 24;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 13)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 18;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 14)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 12;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_num_rows > 15)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ }
+
+ l_sbit = 6;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+
+ if (l_dram_rows >= 17)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit, 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR1A0Q, l_data_buffer_64));
+ }
+
+ l_sbit = 36;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ if(sl2_valid == 1)
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit , 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit , 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ FAPI_DBG("%s:sl2 Invalid", mss::c_str(i_target_mba));
+
+ }
+
+ l_sbit = 30;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ //------- Enable these for later --- for now constant map to zero
+ if(sl1_valid == 1)
+ {
+
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit , 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit , 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ FAPI_DBG("%s:sl1 Invalid", mss::c_str(i_target_mba));
+
+ }
+
+ FAPI_INF("Inside strcmp sl0");
+ l_sbit = 24;
+ l_value = i;
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+
+ //------- Enable these for later --- for now constant map to zero
+ if(sl0_valid == 1)
+ {
+
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value, l_sbit , 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ i--;
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_value_zero, l_sbit , 6));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAMR0A0Q, l_data_buffer_64));
+ FAPI_DBG("%s:sl0 Invalid", mss::c_str(i_target_mba));
+
+ }
+
+ //------ Setting Start and end addr counters
+ FAPI_INF("Debug - --------------- Setting Start and End Counters -----------\n");
+ l_data_buffer_rd64.flush<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSSARA0Q, l_data_buffer_rd64));
+ l_value = i + 1;
+ FAPI_INF("Setting end_addr Value of i = %d", i);
+ l_data_buffer_rd64.flush<0>();
+
+ //Calculate and set Valid bits for end_addr
+ for (i = l_value; i <= 37; i++)
+ {
+ FAPI_TRY(l_data_buffer_rd64.clearBit(i));
+ FAPI_TRY(l_data_buffer_rd64.setBit(i));
+ }
+
+ l_readscom_value = uint64_t(l_data_buffer_rd64);
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_SCHMOO_ADDR_MODE, i_target_mba, l_attr_addr_mode));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_START_ADDR, i_target_mba, l_start_addr));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_END_ADDR, i_target_mba, l_end));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_RANK, i_target_mba, l_user_end_addr));
+
+ if (l_user_end_addr == 1)
+ {
+ //Setting start and end Temp
+ l_data_buffer_rd64 = l_start_addr;
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSSARA0Q, l_data_buffer_rd64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSSARA1Q, l_data_buffer_rd64));
+ l_data_buffer_rd64 = l_end;
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA0Q, l_data_buffer_rd64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA1Q, l_data_buffer_rd64));
+ }
+
+ else
+ {
+ if (l_attr_addr_mode == 0)
+ {
+ FAPI_INF("ATTR_EFF_SCHMOO_ADDR_MODE - %d ---- Few Address Mode --------", l_attr_addr_mode);
+ l_sbit = 32;
+ l_data_buffer_rd64.flush<0>();
+ l_start = 24;
+ l_len = 8;
+ l_value32 = 28;
+ FAPI_TRY(l_data_buffer_rd64.insert(l_value32, l_sbit, l_len, l_start));
+ l_readscom_value = 0x000003FFF8000000ull;
+ l_data_buffer_rd64 = l_readscom_value;
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA0Q, l_data_buffer_rd64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA1Q, l_data_buffer_rd64));
+ l_readscom_value = uint64_t(l_data_buffer_rd64);
+ }
+ else if (l_attr_addr_mode == 1)
+ {
+ FAPI_INF("ATTR_EFF_SCHMOO_ADDR_MODE - %d ---- QUARTER ADDRESSING Mode --------", l_attr_addr_mode);
+ l_readscom_value = l_readscom_value >> 2;
+ FAPI_INF("Debug - Final End addr for CEN_MBA_MCBSEARA0Q = %016llX", l_readscom_value);
+ l_data_buffer_rd64 = l_readscom_value;
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA0Q, l_data_buffer_rd64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA1Q, l_data_buffer_rd64));
+
+ }
+ else if (l_attr_addr_mode == 2)
+ {
+ FAPI_INF("ATTR_EFF_SCHMOO_ADDR_MODE - %d ---- HALF ADDRESSING Mode --------", l_attr_addr_mode);
+ l_readscom_value = l_readscom_value >> 1;
+ FAPI_INF("Debug - Final End addr for CEN_MBA_MCBSEARA0Q = %016llX", l_readscom_value);
+ l_data_buffer_rd64 = l_readscom_value;
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA0Q, l_data_buffer_rd64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA1Q, l_data_buffer_rd64));
+
+ }
+ else
+ {
+ FAPI_INF("ATTR_EFF_SCHMOO_ADDR_MODE - %d ---- FULL Address Mode --------", l_attr_addr_mode);
+ FAPI_INF("Debug - Final End addr for CEN_MBA_MCBSEARA0Q = %016llX", l_readscom_value);
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA0Q, l_data_buffer_rd64));
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBSEARA1Q, l_data_buffer_rd64));
+
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.H
new file mode 100644
index 000000000..734951fbc
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.H
@@ -0,0 +1,98 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_mcbist_address.H
+/// @brief MCBIST address procedures header
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#ifndef MSS_MCBIST_ADDRESS_H
+#define MSS_MCBIST_ADDRESS_H
+
+#include <fapi2.H>
+#include <cen_gen_scom_addresses.H>
+#include <p9c_mss_access_delay_reg.H>
+#include <p9c_mss_mcbist.H>
+#include <string.h>
+#include <dimmConsts.H>
+extern "C"
+{
+ ///
+ /// @brief interleave type enum
+ ///
+ enum interleave_type
+ {
+ BANK_RANK,
+ RANK_BANK,
+ BANK_ONLY,
+ RANK_ONLY,
+ RANKS_DIMM0,
+ RANKS_DIMM1,
+ USER_PATTERN
+ };
+
+ ///
+ /// @brief Setup MCBIST address string
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @param[in] l_str_cust_addr Optional custom address string
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode address_generation(const fapi2:: Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const char* l_str_cust_addr);
+ ///
+ /// @brief Parse MCBIST address string and set corresponding registers
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @param[in] addr_string MCBIST address string
+ /// @param[in] mr3_valid Master rank 3 valid bit
+ /// @param[in] mr2_valid Master rank 2 valid bit
+ /// @param[in] mr1_valid Master rank 1 valid bit
+ /// @param[in] l_dram_rows Num dram rows
+ /// @param[in] l_dram_cols Num dram columns
+ /// @param[in] l_addr_inter Address interleave bit
+ /// @param[in] sl2_valid Slave rank 2 valid bit
+ /// @param[in] sl1_valid Slave rank 1 valid bit
+ /// @param[in] sl0_valid Slave rank 0 valid bit
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode parse_addr(const fapi2:: Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const char addr_string[],
+ const uint8_t mr3_valid,
+ const uint8_t mr2_valid,
+ const uint8_t mr1_valid,
+ const uint8_t l_dram_rows,
+ const uint8_t l_dram_cols,
+ const uint8_t l_addr_inter,
+ const uint8_t sl2_valid,
+ const uint8_t sl1_valid,
+ const uint8_t sl0_valid);
+
+}
+#endif
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.mk
new file mode 100755
index 000000000..dd9b3a2c0
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_address.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_mcbist_address
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.C
new file mode 100644
index 000000000..75f9ed6c3
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.C
@@ -0,0 +1,2583 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_mcbist_common.C
+/// @brief mcbist procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+///
+
+#include <fapi2.H>
+#include <p9c_mss_mcbist.H>
+#include <p9c_mss_mcbist_address.H>
+#include <p9c_mss_access_delay_reg.H>
+#include <fapiTestHwpDq.H>
+#include <p9c_dimmBadDqBitmapFuncs.H>
+#include <generic/memory/lib/utils/c_str.H>
+
+extern "C"
+{
+ constexpr uint8_t MCB_TEST_NUM = 16;
+ constexpr uint64_t MCB_MAX_TIMEOUT = 0000000600000000ull;
+
+ ///
+ /// @brief Will setup the required MCBIST configuration register
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_mcbbytemask It is used to mask bad bits read from SPD
+ /// @param[in] i_mcbrotate Provides the number of bit to shift per burst
+ /// @param[in] i_mcbrotdata Provides the rotate data to shift per burst
+ /// @param[in] i_sub_info
+ /// @param[in] i_str_cust_addr
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode setup_mcbist(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const mcbist_byte_mask i_mcbbytemask,
+ const uint8_t i_mcbrotate,
+ const uint64_t i_mcbrotdata,
+ struct subtest_info i_sub_info[30],
+ const char* i_str_cust_addr)
+ {
+ FAPI_DBG("%s:Function Setup_MCBIST", mss::c_str(i_target_mba));
+ FAPI_DBG("Custom Addr Mode %s", i_str_cust_addr);
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ fapi2::buffer<uint64_t> l_data_buffer_mask1a_64;
+ fapi2::buffer<uint64_t> l_data_buffer_mask1b_64;
+ fapi2::buffer<uint64_t> l_data_buffer_mask0_64;
+ uint8_t l_bit32 = 0;
+ uint8_t l_new_addr = 1;
+ uint32_t i_mcbpatt = 0;
+ uint32_t i_mcbtest = 0;
+ uint8_t i_zmode_port = 0;
+ uint8_t i_zmode = 0;
+ uint8_t l_mba_position = 0;
+ mcbist_test_mem i_mcbtest1;
+ mcbist_data_gen i_mcbpatt1;
+ i_mcbtest1 = CENSHMOO;
+ i_mcbpatt1 = ABLE_FIVE;
+ uint8_t l_index = 0;
+ uint8_t l_flag = 0;
+ constexpr uint64_t scom_array[8] =
+ {
+ CEN_MBA_MBABS0, CEN_MBA_MBABS1,
+ CEN_MBA_MBABS2, CEN_MBA_MBABS3,
+ CEN_MBA_MBABS4, CEN_MBA_MBABS5,
+ CEN_MBA_MBABS6, CEN_MBA_MBABS7
+ };
+
+ constexpr uint64_t l_scom_array_MBS[16] =
+ {
+ CEN_ECC01_MBSBS2, CEN_ECC01_MBSBS3,
+ CEN_ECC01_MBSBS4, CEN_ECC01_MBSBS5,
+ CEN_ECC01_MBSBS6, CEN_ECC01_MBSBS7,
+ CEN_ECC23_MBSBS0, CEN_ECC23_MBSBS1,
+ CEN_ECC23_MBSBS2, CEN_ECC23_MBSBS3,
+ CEN_ECC23_MBSBS4, CEN_ECC23_MBSBS5,
+ CEN_ECC23_MBSBS6, CEN_ECC23_MBSBS7,
+ CEN_ECC01_MBSBS0, CEN_ECC01_MBSBS1
+ };
+
+ const auto l_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_PATTERN, i_target_mba, i_mcbpatt));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_TEST_TYPE, i_target_mba, i_mcbtest));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_ZMODE, i_target_mba, i_zmode));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_ZMODE_PORT, i_target_mba, i_zmode_port));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target_mba, l_mba_position));
+
+ mss_conversion_testtype(i_target_mba, i_mcbtest, i_mcbtest1);
+ mss_conversion_data(i_target_mba, i_mcbpatt, i_mcbpatt1);
+
+ FAPI_TRY(mcb_reset_trap(i_target_mba));
+
+ //should set attr for this 1st 8 or last 8
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_ERROR_CAPTURE, i_target_mba, l_bit32));
+
+ if (l_bit32 == 1)
+ {
+ FAPI_DBG("%s: error capture set to last 8 Bits", mss::c_str(i_target_mba));
+ FAPI_TRY(fapi2::getScom(l_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer_64));
+ l_data_buffer_64.setBit<32>();
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer_64));
+
+ FAPI_TRY(fapi2::getScom(l_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer_64));
+ l_data_buffer_64.setBit<32>();
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer_64));
+
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBA_WRQ0Q, l_data_buffer_64));
+ l_data_buffer_64.clearBit<5>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBA_WRQ0Q, l_data_buffer_64));
+
+ //#RRQ FIFO Mode OFF
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBA_RRQ0Q, l_data_buffer_64));
+ l_data_buffer_64.setBit<6>();
+ l_data_buffer_64.setBit<7>();
+ l_data_buffer_64.setBit<8>();
+ l_data_buffer_64.setBit<9>();
+ l_data_buffer_64.setBit<10>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBA_RRQ0Q, l_data_buffer_64));
+
+ //power bus ECC setting for random data
+ //# MBA01_MBA_WRD_MODE - disbale powerbus ECC checking and correction
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBA_WRD_MODE, l_data_buffer_64));
+ l_data_buffer_64.setBit<0>();
+ l_data_buffer_64.setBit<1>();
+ l_data_buffer_64.setBit<5>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBA_WRD_MODE, l_data_buffer_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_data_buffer_64));
+ l_data_buffer_64.clearBit<29>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_CCS_MODEQ, l_data_buffer_64));
+
+
+ for (l_index = 0; l_index < 8; l_index++)
+ {
+ FAPI_TRY(fapi2::getScom(i_target_mba, scom_array[l_index], l_data_buffer_64));
+
+ l_flag = (uint64_t(l_data_buffer_64)) ? 1 : 0;
+
+ if (l_flag == 1)
+ {
+ break;
+ }
+ }
+
+ for (l_index = 0; l_index < 16; l_index++)
+ {
+ FAPI_TRY(fapi2::getScom(l_target_centaur, l_scom_array_MBS[l_index], l_data_buffer_64));
+
+ l_flag = (uint64_t(l_data_buffer_64)) ? 1 : 0;
+
+ if (l_flag == 1)
+ {
+ break;
+ }
+ }
+
+ if (l_flag == 1)
+ {
+ FAPI_DBG("%s:WARNING: Bit Steering is enabled !!!", mss::c_str(i_target_mba));
+ }
+ else
+ {
+ FAPI_DBG("%s:steer mode is not enabled", mss::c_str(i_target_mba));
+ }
+
+ FAPI_TRY(cfg_mcb_test_mem(i_target_mba, i_mcbtest1, i_sub_info));
+
+ FAPI_TRY(cfg_mcb_dgen(i_target_mba, i_mcbpatt1, i_mcbrotate, i_mcbrotdata));
+
+
+ FAPI_DBG("%s:DEBUG-----Print----Address Gen ", mss::c_str(i_target_mba));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_ADDR_MODES, i_target_mba, l_new_addr));
+
+ FAPI_DBG("DEBUG----- l_new_addr = %d ", l_new_addr);
+
+ if (l_new_addr != 0)
+ {
+ FAPI_TRY(address_generation(i_target_mba, i_str_cust_addr));
+ }
+
+ FAPI_INF( "+++ Enabling Refresh +++");
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+ //Bit 0 is enable
+ l_data_buffer_64.setBit<0>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MBAREF0Q, l_data_buffer_64));
+
+
+ if (i_mcbbytemask != NONE)
+ {
+ FAPI_TRY(cfg_byte_mask(i_target_mba));
+
+ }
+
+ if(i_zmode) //zMode must mask opposite port
+ {
+ l_data_buffer_mask0_64.insert<0, 64, 0>(0xFFFFFFFFFFFFFFFF);
+
+ if(l_mba_position == 0)
+ {
+ FAPI_TRY(fapi2::getScom(l_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer_mask1a_64));
+ FAPI_TRY(fapi2::getScom(l_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer_mask1b_64));
+ l_data_buffer_mask1a_64.insert<0, 16>(0xFFFFFFFFFFFFFFFF);
+ l_data_buffer_mask1b_64.insert<16, 16>(0xFFFFFFFFFFFFFFFF);
+
+ if(i_zmode_port == 0) //EVEN port under test : 0, mask port 1
+ {
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS01_MCBCMB1Q, l_data_buffer_mask0_64));
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer_mask1b_64));
+ }
+ else // ODD port under test : 1, mask port 0
+ {
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS01_MCBCMA1Q, l_data_buffer_mask0_64));
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer_mask1a_64));
+ }
+ }
+ else
+ {
+ FAPI_TRY(fapi2::getScom(l_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer_mask1a_64));
+ FAPI_TRY(fapi2::getScom(l_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer_mask1b_64));
+ l_data_buffer_mask1a_64.insert<0, 16>(0xFFFFFFFFFFFFFFFF);
+ l_data_buffer_mask1b_64.insert<16, 16>(0xFFFFFFFFFFFFFFFF);
+
+ if(i_zmode_port == 0) //EVEN port under test : 2, mask port 3
+ {
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS23_MCBCMB1Q, l_data_buffer_mask0_64));
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer_mask1b_64));
+ }
+ else //ODD port under test: 3, mask port 2
+ {
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS23_MCBCMA1Q, l_data_buffer_mask0_64));
+ FAPI_TRY(fapi2::putScom(l_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer_mask1a_64));
+ }
+ }
+ } // if zmode
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+
+ ///
+ /// @brief Clears all the trap registers in MCBIST engine
+ /// @param[in] i_target_mba Centaur input mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_reset_trap(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ uint8_t l_mba_position = 0;
+ const auto i_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target_mba, l_mba_position));
+
+ FAPI_DBG("%s:Function - mcb_reset_trap", mss::c_str(i_target_mba));
+ //Reset the MCBIST runtime counter
+ FAPI_DBG("%s:Clearing the MCBIST Runtime Counter ", mss::c_str(i_target_mba));
+ l_data_buffer_64.flush<0>();
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_RUNTIMECTRQ, l_data_buffer_64));
+ l_data_buffer_64.clearBit<0, 37>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_RUNTIMECTRQ, l_data_buffer_64));
+
+ l_data_buffer_64.flush<0>();
+
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMA1Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMB1Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMA1Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMB1Q, l_data_buffer_64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer_64));
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Checks for dimms drop in the particular port & starts MCBIST
+ /// @param[in] i_target_mna Centaur.mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode start_mcb(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ uint8_t l_num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint64_t l_time = 0;
+ FAPI_DBG("%s:Function - start_mcb", mss::c_str(i_target_mba));
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBAGRAQ, l_data_buffer_64));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, l_num_ranks_per_dimm));
+
+ if ((l_num_ranks_per_dimm[0][0] > 0) && (l_num_ranks_per_dimm[0][1] > 0))
+ {
+ FAPI_DBG("%s: Socket 0, 1 Configured", mss::c_str(i_target_mba));
+ l_data_buffer_64.setBit<24>();
+ l_data_buffer_64.setBit<25>();
+ }
+ else if (l_num_ranks_per_dimm[0][0] > 0)
+ {
+ FAPI_DBG("%s: Socket 0 Configured", mss::c_str(i_target_mba));
+ l_data_buffer_64.setBit<24>();
+ l_data_buffer_64.clearBit<25>();
+ }
+ else if (l_num_ranks_per_dimm[0][1] > 0)
+ {
+ FAPI_DBG("%s: Socket 1 Configured", mss::c_str(i_target_mba));
+ l_data_buffer_64.clearBit<24>();
+ l_data_buffer_64.setBit<25>();
+ }
+ else
+ {
+ FAPI_DBG("%s:No Socket found", mss::c_str(i_target_mba));
+ }
+
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBAGRAQ, l_data_buffer_64));
+
+ FAPI_DBG("%s:STARTING MCBIST for Centaur Target", mss::c_str(i_target_mba));
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCB_CNTLSTATQ, l_data_buffer_64));
+
+ if (l_data_buffer_64.getBit<0>())
+ {
+ FAPI_DBG("%s:MCBIST already in progess, wait till MCBIST completes",
+ mss::c_str(i_target_mba));
+ return fapi2::current_err;
+ }
+
+ l_data_buffer_64.flush<0>();
+ l_data_buffer_64.setBit<0>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_MAX_TIMEOUT, i_target_mba, l_time));
+
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCB_CNTLQ, l_data_buffer_64));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief check the MCBIST Configuration Register for mcb fail, in progress, done
+ /// @param[in] i_target_mba Centaur.mba
+ /// @param[out] o_mcb_status MCB status
+ /// @param[in] i_sub_info MCB subtest information array
+ /// @param[in] i_flag verbose flag
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode poll_mcb(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ uint8_t* o_mcb_status,
+ struct subtest_info i_sub_info[30],
+ const uint8_t i_flag)
+ {
+ // return value after each SCOM access/buffer modification
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ fapi2::buffer<uint64_t> l_data_buffer_trap_64;
+ fapi2::buffer<uint64_t> l_stop_on_fail_buffer_64;
+ //Current status of the MCB (done, fail, in progress)
+ uint8_t l_mcb_done = 0;
+ uint8_t l_mcb_fail = 0;
+ uint8_t l_mcb_ip = 0;
+ //Time out variables
+ uint64_t l_mcb_timeout = 0;
+ uint32_t l_count = 0;
+ uint64_t l_time = 0;
+ uint32_t l_time_count = 0;
+ uint8_t l_index = 0;
+ uint8_t l_Subtest_no = 0;
+ uint64_t l_counter = 0x0ll;
+ uint32_t i_mcbtest = 0;
+ uint32_t l_st_ln = 0;
+ uint32_t l_len = 0;
+ uint32_t l_dts_0 = 0;
+ uint32_t l_dts_1 = 0;
+ uint8_t l_mcb_stop_on_fail = 0;
+ mcbist_test_mem i_mcbtest1;
+ const auto i_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+
+ //Should get the attributes l_time
+ uint8_t test_array_count[44] = { 0, 2, 2, 1, 1, 1, 6, 6, 30, 30,
+ 2, 7, 4, 2, 1, 5, 4, 2, 1, 1,
+ 3, 1, 1, 4, 2, 1, 1, 1, 1, 10,
+ 0, 5, 3, 3, 3, 3, 9, 4, 30, 1,
+ 2, 2, 3, 3
+ };
+
+ FAPI_DBG("%s:Function Poll_MCBIST", mss::c_str(i_target_mba));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_MAX_TIMEOUT, i_target_mba, l_time));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_STOP_ON_ERROR, i_target_mba, l_mcb_stop_on_fail));
+
+ if (l_time == 0x0000000000000000)
+ {
+ l_time = MCB_MAX_TIMEOUT;
+ }
+
+ FAPI_DBG("%s:Value of max time %016llX", mss::c_str(i_target_mba), l_time);
+
+ while ((l_mcb_done == 0) && (l_mcb_timeout <= l_time))
+ {
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCB_CNTLSTATQ, l_data_buffer_64));
+
+ if (l_data_buffer_64.getBit<0>())
+ {
+ l_time_count++;
+
+ if (l_time_count == 500)
+ {
+ l_time_count = 0;
+ FAPI_DBG("%s:POLLING STATUS:POLLING IN PROGRESS...........",
+ mss::c_str(i_target_mba));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, 0x02050000, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.extractToRight(l_dts_0, 0, 12));
+ FAPI_TRY(l_data_buffer_64.extractToRight(l_dts_1, 16, 12));
+
+ FAPI_DBG("%s:DTS Thermal Sensor 0 Results %d", mss::c_str(i_target_centaur), l_dts_0);
+ FAPI_DBG("%s:DTS Thermal Sensor 1 Results %d", mss::c_str(i_target_centaur), l_dts_1);
+
+ if (i_flag == 0)
+ {
+ // Read Counter Reg
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_RUNTIMECTRQ, l_data_buffer_64));
+ FAPI_TRY(l_data_buffer_64.extract(l_counter, 0, 64));
+ FAPI_DBG("%s:MCBCounter %016llX ", mss::c_str(i_target_mba), l_counter);
+
+ //Read Sub-Test number
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBSTATAQ_ROX, l_data_buffer_64));
+ l_st_ln = 3;
+ l_len = 5;
+
+ FAPI_TRY(l_data_buffer_64.extract(l_Subtest_no, l_st_ln, l_len));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_TEST_TYPE, i_target_mba, i_mcbtest));
+ mss_conversion_testtype(i_target_mba, i_mcbtest, i_mcbtest1);
+
+ l_index = test_array_count[i_mcbtest] = {0};
+
+ if (l_Subtest_no < l_index)
+ {
+ switch (i_sub_info[l_Subtest_no].l_operation_type)
+ {
+ case 0:
+ FAPI_DBG("%s:SUBTEST :WRITE", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ FAPI_DBG("%s:SUBTEST :READ", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ FAPI_DBG("%s:SUBTEST :READ - WRITE", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ FAPI_DBG("%s:SUBTEST :WRITE - READ", mss::c_str(i_target_mba));
+ break;
+
+ case 4:
+ FAPI_DBG("%s:SUBTEST :READ - WRITE - READ", mss::c_str(i_target_mba));
+ break;
+
+ case 5:
+ FAPI_DBG("%s:SUBTEST :READ - WRITE - WRITE", mss::c_str(i_target_mba));
+ break;
+
+ case 6:
+ FAPI_DBG("%s:SUBTEST :RANDOM COMMAND SEQUENCE", mss::c_str(i_target_mba));
+ break;
+
+ case 7:
+ FAPI_DBG("%s:SUBTEST :GOTO SUBTEST N OR REFRESH ONLY", mss::c_str(i_target_mba));
+ break;
+
+ default:
+ FAPI_DBG("%s:Wrong Operation selected for Subtest", mss::c_str(i_target_mba));
+ }
+
+ switch (i_sub_info[l_Subtest_no].l_data_mode)
+ {
+ case 0:
+ FAPI_DBG("%s:DATA MODE :FIXED DATA", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ FAPI_DBG("%s:DATA MODE :DATA_RANDOM_FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ FAPI_DBG("%s:DATA MODE :DATA_RANDOM_REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ FAPI_DBG("%s:DATA MODE :RANDOM w/ECC FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 4:
+ FAPI_DBG("%s:DATA MODE :RANDOM w/ECC REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ case 5:
+ FAPI_DBG("%s:DATA MODE :DATA EQUAL ADDRESS", mss::c_str(i_target_mba));
+ break;
+
+ case 6:
+ FAPI_DBG("%s:DATA MODE :DATA ROTATE LEFT", mss::c_str(i_target_mba));
+ break;
+
+ case 7:
+ FAPI_DBG("%s:DATA MODE :DATA ROTATE RIGHT", mss::c_str(i_target_mba));
+ break;
+
+ default:
+ FAPI_DBG("%s:Wrong Data Mode selected for Subtest", mss::c_str(i_target_mba));
+ }
+
+ switch (i_sub_info[l_Subtest_no].l_addr_mode)
+ {
+ case 0:
+ FAPI_DBG("%s:ADDRESS MODE :SEQUENTIAL FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ FAPI_DBG("%s:ADDRESS MODE :SEQUENTIAL REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ FAPI_DBG("%s:ADDRESS MODE :RANDOM FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ FAPI_DBG("%s:ADDRESS MODE :RANDOM REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ default:
+ FAPI_DBG("%s:Wrong Address Mode selected for Subtest", mss::c_str(i_target_mba));
+ }
+ } // if subtest no < index
+ } // if i_flag == 0
+ } // if time count == 500
+
+ l_mcb_ip = 1;
+ } // if getBit<0>
+
+ if (l_data_buffer_64.getBit<1>())
+ {
+ FAPI_DBG("%s:POLLING STATUS:MCBIST POLLING DONE",
+ mss::c_str(i_target_mba));
+ FAPI_DBG("%s:MCBIST is done", mss::c_str(i_target_mba));
+ l_mcb_ip = 0;
+ l_mcb_done = 1;
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBCFGQ, l_data_buffer_trap_64));
+ l_data_buffer_64.clearBit<60>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBCFGQ, l_data_buffer_trap_64));
+ }
+
+ if (l_data_buffer_64.getBit<2>())
+ {
+ l_mcb_fail = 1;
+ FAPI_DBG("%s:POLLING STATUS:MCBIST FAILED", mss::c_str(i_target_mba));
+
+ if (l_mcb_stop_on_fail == 1) //if stop on error is 1, break after the current subtest completes
+ {
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBCFGQ, l_stop_on_fail_buffer_64));
+ l_stop_on_fail_buffer_64.setBit<62>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBCFGQ, l_stop_on_fail_buffer_64));
+
+ FAPI_DBG("%s:MCBIST will break after Current Subtest",
+ mss::c_str(i_target_mba));
+
+ while (l_mcb_done == 0) // Poll till MCBIST is done
+ {
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCB_CNTLSTATQ, l_data_buffer_64));
+
+ if (l_data_buffer_64.getBit<1>())
+ {
+ l_mcb_ip = 0;
+ l_mcb_done = 1;
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_MCBCFGQ, l_data_buffer_trap_64));
+ l_data_buffer_64.clearBit<60>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBCFGQ, l_data_buffer_trap_64));
+
+ FAPI_DBG("%s:MCBIST Done", mss::c_str(i_target_mba));
+ l_stop_on_fail_buffer_64.clearBit<62>();
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_MCBCFGQ, l_stop_on_fail_buffer_64));
+
+ }
+ }
+ }
+ }
+
+ l_mcb_timeout++;
+
+ FAPI_ASSERT(l_mcb_timeout < l_time,
+ fapi2::CEN_MSS_MCBIST_TIMEOUT_ERROR().
+ set_MBA_CHIPLET(i_target_mba),
+ "poll_mcb:Maximum time out");
+
+ l_count++;
+ }
+
+ FAPI_DBG("%s:*************************************************", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:MCB done bit : %d", mss::c_str(i_target_mba), l_mcb_done);
+ FAPI_DBG("%s:MCB fail bit : %d", mss::c_str(i_target_mba), l_mcb_fail);
+ FAPI_DBG("%s:MCB IP bit : %d", mss::c_str(i_target_mba), l_mcb_ip);
+ FAPI_DBG("%s:*************************************************", mss::c_str(i_target_mba));
+
+ if ((l_mcb_done == 1) && (l_mcb_fail == 1) && (l_mcb_stop_on_fail == true))
+ {
+ *o_mcb_status = 1; /// MCB fail
+ }
+ else if ((l_mcb_done == 1) && (l_mcb_fail == 0))
+ {
+ *o_mcb_status = 0;//pass;
+ }
+ else if ((l_mcb_done == 0) && (l_mcb_ip == 1) && (l_mcb_timeout == l_time))
+ {
+ *o_mcb_status = 1;//fail;
+ }
+
+ if (*o_mcb_status == 1)
+ {
+ FAPI_DBG("poll_mcb: MCBIST failed");
+ return fapi2::FAPI2_RC_FALSE;
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief print the mcbist cdimm error map
+ /// @param[in] i_target_mba Centaur input MBA
+ /// @param[in] i_mcb_fail_160
+ /// @param[in] i_port Centaur input port
+ /// @param[in] i_array error array
+ /// @param[in] i_number Highest index in array w error
+ /// @param[in] i_data_buf_port MCB data mask
+ /// @param[in] i_data_buf_spare MCB data mask
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_error_map_print(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const fapi2::variable_buffer& i_mcb_fail_160,
+ const uint8_t i_port,
+ const uint8_t i_array[DIMM_DQ_SPD_DATA_SIZE],
+ const uint8_t i_number,
+ const fapi2::buffer<uint64_t> i_data_buf_port,
+ const fapi2::buffer<uint64_t> i_data_buf_spare)
+ {
+ uint8_t l_num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_rankpair_table[MAX_RANKS_PER_PORT] = {0};
+ uint8_t l_cur_rank = 0;
+ uint16_t l_index0, l_index1, l_byte, l_nibble = 0;
+ uint8_t l_max_rank = 0;
+ uint8_t l_rank_pair = 0;
+ char l_str1[200] = "";
+ uint8_t l_rank = 0;
+ uint8_t l_mba_position = 0;
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint64_t l_generic_buffer = 0;
+ uint32_t l_sbit, l_len;
+ uint16_t l_output = 0;
+ uint8_t l_index, l_value, l_value1;
+ uint8_t l_marray0[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_num, io_num, l_inter, l_num2, l_index2;
+ fapi2::variable_buffer l_data_buffer1_64(64), l_data_buffer3_64(64);
+ FAPI_INF("Function MCB_ERROR_MAP_PRINT");
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target_mba, l_mba_position));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, dram_stack));
+
+ if (dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target_mba, l_num_ranks_per_dimm));
+ }
+ else
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, l_num_ranks_per_dimm));
+ }
+
+ l_max_rank = l_num_ranks_per_dimm[i_port][0] + l_num_ranks_per_dimm[i_port][1];
+
+ FAPI_TRY(mss_getrankpair(i_target_mba, i_port, 0, &l_rank_pair, l_rankpair_table));
+
+ FAPI_ASSERT(l_max_rank != 0,
+ fapi2::CEN_MSS_PLACE_HOLDER_ERROR(),
+ "%s: NO RANK FOUND ON PORT %d ", mss::c_str(i_target_mba), i_port);
+
+ if (i_port == 0)
+ {
+ l_sbit = 0;
+ l_len = 16;
+ FAPI_TRY(i_data_buf_port.extract(l_generic_buffer, 0, 64));
+ FAPI_TRY(i_data_buf_spare.extractToRight(l_output, l_sbit, l_len));
+
+ if (l_mba_position == 0)
+ {
+ FAPI_DBG("%s:################# MBA01 ###########################\n", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:################# PORT0 ERROR MAP #################\n", mss::c_str(i_target_mba));
+ }
+ else
+ {
+ FAPI_DBG("%s:################# MBA23 ###########################\n", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:################# PORT0 ERROR MAP #################\n", mss::c_str(i_target_mba));
+ }
+
+ FAPI_DBG("%s:Byte 00112233445566778899", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:Nibble 01010101010101010101", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:MASK %016llX%04X\n", mss::c_str(i_target_mba), l_generic_buffer, l_output);
+ }
+ else
+ {
+ l_sbit = 16;
+ l_len = 16;
+ FAPI_TRY(i_data_buf_port.extract(l_generic_buffer, 0, 64));
+ FAPI_TRY(i_data_buf_spare.extractToRight(l_output, l_sbit, l_len));
+
+ if (l_mba_position == 0)
+ {
+ FAPI_DBG("%s:################# MBA01 ###########################\n", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:################# PORT1 ERROR MAP #################\n", mss::c_str(i_target_mba));
+ }
+ else
+ {
+ FAPI_DBG("%s:################# MBA23 ###########################\n", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:################# PORT1 ERROR MAP #################\n", mss::c_str(i_target_mba));
+ }
+
+ FAPI_DBG("%s:Byte 00112233445566778899", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:Nibble 01010101010101010101", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:MASK %016llX%04X\n", mss::c_str(i_target_mba), l_generic_buffer, l_output);
+ }
+
+ l_data_buffer1_64.flush<0>();
+
+ l_num = 0;
+
+ for (l_index = 0; l_index < i_number; l_index++)
+ {
+ l_value = i_array[l_index];
+ l_inter = (l_value / 4);
+ l_num2 = l_num - 1;
+
+ if (l_inter == l_marray0[l_num2] && (l_num != 0))
+ {
+ continue;
+ }
+
+ l_value1 = l_inter;
+ l_marray0[l_num] = l_value1;
+ l_num++;
+ }
+
+ io_num = l_num;
+
+ l_cur_rank = 0;
+ l_rank = 0;
+ l_num = 0;
+ l_value = 0;
+
+ FAPI_TRY(mss_getrankpair(i_target_mba, i_port, 0, &l_rank_pair, l_rankpair_table));
+
+ for (l_cur_rank = 0; l_cur_rank < l_max_rank; l_cur_rank++)
+ {
+ l_index2 = 0;
+ l_num = 0;
+ l_rank = l_rankpair_table[l_cur_rank];
+ sprintf(l_str1, "%s:%-4s%d%5s", mss::c_str(i_target_mba), "RANK", l_rank, "");
+
+ for (l_byte = 0; l_byte < MAX_BYTES_PER_RANK; l_byte++)
+ {
+ for (l_nibble = 0; l_nibble < MAX_NIBBLES_PER_BYTE; l_nibble++)
+ {
+ l_value = l_marray0[l_num];
+ FAPI_DBG("%s:l_value %d l_num %d", mss::c_str(i_target_mba), l_value, l_num);
+ l_index0 = (l_rank * 20) + (l_byte * 2) + l_nibble;
+ l_index2 = (l_byte * 2) + l_nibble;
+ l_index1 = l_index0;
+ FAPI_DBG("l_rank %x l_index0 %x l_index2 %x", l_rank, l_index0, l_index2);
+
+ if ((l_value == l_index2) && (l_num < io_num))
+ {
+ strcat(l_str1, "M");
+ FAPI_DBG("%s:l_value %d l_num %d", mss::c_str(i_target_mba), l_value, l_num);
+ l_num++;
+ }
+ else
+ {
+ if (i_mcb_fail_160.isBitSet(l_index1))
+ {
+ strcat(l_str1, "X");
+ }
+ else
+ {
+ strcat(l_str1, ".");
+ }
+ }
+ }
+ }
+
+ FAPI_DBG("%s", l_str1);
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Reads the nibblewise Error map registers into o_error_map
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[out] o_error_map[][8][10][2] Contains the error map
+ /// @param[in] i_CDarray0[80]
+ /// @param[in] i_CDarray1[80]
+ /// @param[in] count_bad_dq[2]
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_error_map(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ uint8_t o_error_map[MAX_PORTS_PER_MBA][MAX_RANKS_PER_PORT][MAX_BYTES_PER_RANK][MAX_NIBBLES_PER_BYTE],
+ uint8_t i_CDarray0[DIMM_DQ_SPD_DATA_SIZE],
+ uint8_t i_CDarray1[DIMM_DQ_SPD_DATA_SIZE],
+ uint8_t count_bad_dq[2])
+ {
+ fapi2::buffer<uint64_t> l_mcbem1ab;
+ fapi2::buffer<uint64_t> l_mcbem2ab;
+ fapi2::buffer<uint64_t> l_mcbem3ab;
+ fapi2::variable_buffer l_mcb_fail_160(160);
+ fapi2::variable_buffer l_mcb_fail1_160(160);
+ fapi2::variable_buffer l_ISDIMM_BUF1(64), l_ISDIMM_BUF0(64);
+ fapi2::variable_buffer l_ISDIMM_spare1(8), l_ISDIMM_spare0(8);
+ uint8_t l_max_rank0, l_max_rank1;
+ fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> i_target_centaur;
+ uint16_t l_index0 = 0;
+ uint32_t l_index1 = 0;
+ uint8_t l_port = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_byte = 0;
+ uint8_t l_nibble = 0;
+ uint8_t l_num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_PORTS_PER_MBA] = {0};
+ uint8_t l_mba_position = 0;
+ uint8_t rank_pair = 0;
+ uint8_t i_byte = 0;
+ uint8_t i_nibble = 0;
+ uint8_t i_input_index_u8 = 0;
+ uint8_t o_val = 0;
+ uint8_t i_byte1 = 0;
+ uint8_t i_nibble1 = 0;
+ uint8_t l_zmode_port = 0;
+ uint8_t l_zmode = 0;
+ uint8_t l_index = 0;
+ uint8_t l_i = 0;
+ uint8_t l_number = 0;
+ uint8_t l_value = 0;
+ uint8_t l_value1 = 0;
+ uint8_t l_number1 = 0;//l_cur_rank,
+ uint8_t l_array[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_marray11[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_array0[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_marray0[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_array1[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_marray1[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_marray[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t cdimm_dq0[ISDIMM_MAX_DQ_72] = { 0 };
+ uint8_t cdimm_dq1[ISDIMM_MAX_DQ_72] = { 0 };
+ uint8_t cdimm_dq[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_isarray1[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_isarray0[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_isarray[DIMM_DQ_SPD_DATA_SIZE] = { 0 };
+ uint8_t l_rankpair_table[MAX_RANKS_PER_PORT] = {0};
+ fapi2::buffer<uint64_t> l_data_buffer1_64, l_data_buffer3_64,
+ l_data_buf_port0, l_data_buf_port1, l_data_buf_spare;
+ uint64_t l_generic_buffer0 = 0;
+ uint64_t l_generic_buffer1 = 0;
+ uint64_t l_generic_buffer = 0;
+ uint32_t l_sbit = 0;
+ uint32_t l_len = 0;
+ uint8_t l_output0 = 0;
+ uint8_t l_output1 = 0;
+ uint8_t l_output = 0;
+ uint8_t l_j = 0;
+ input_type l_input_type_e = ISDIMM_DQ;
+ uint8_t valid_rank[MAX_RANKS_PER_PORT] = {0};
+ char l_str[200] = "";
+ uint8_t l_max_bytes = 9;
+ uint8_t l_max_rank = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t dram_stack[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t l_port_index = 0;
+ FAPI_DBG("%s:Function MCB_ERROR_MAP", mss::c_str(i_target_mba));
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target_mba, l_mba_position));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_ZMODE, i_target_mba, l_zmode));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_ZMODE_PORT, i_target_mba, l_zmode_port));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_STACK_TYPE, i_target_mba, dram_stack));
+
+ if (dram_stack[0][0] == fapi2::ENUM_ATTR_CEN_EFF_STACK_TYPE_STACK_3DS)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target_mba, l_num_ranks_per_dimm));
+ }
+ else
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, l_num_ranks_per_dimm));
+ }
+
+ l_max_rank0 = l_num_ranks_per_dimm[0][0] + l_num_ranks_per_dimm[0][1];
+ l_max_rank1 = l_num_ranks_per_dimm[1][0] + l_num_ranks_per_dimm[1][1];
+ i_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+
+ if (l_mba_position == 0)
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBEMA1Q, l_mcbem1ab));
+
+ FAPI_TRY(l_mcb_fail_160.insert(uint64_t(l_mcbem1ab), 0, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBEMA2Q, l_mcbem2ab));
+
+ FAPI_TRY(l_mcb_fail_160.insert(uint64_t(l_mcbem2ab), 60, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBEMA3Q, l_mcbem3ab));
+
+ FAPI_TRY(l_mcb_fail_160.insert(uint64_t(l_mcbem3ab), 120, 40, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBEMB1Q, l_mcbem1ab));
+
+ FAPI_TRY(l_mcb_fail1_160.insert(uint64_t(l_mcbem1ab), 0, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBEMB2Q, l_mcbem2ab));
+
+ FAPI_TRY(l_mcb_fail1_160.insert(uint64_t(l_mcbem2ab), 60, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBEMB3Q, l_mcbem3ab));
+
+ FAPI_TRY(l_mcb_fail1_160.insert(uint64_t(l_mcbem3ab), 120, 40, 0));
+ }
+ else if (l_mba_position == 1)
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBEMA1Q, l_mcbem1ab));
+
+ FAPI_TRY(l_mcb_fail_160.insert(uint64_t(l_mcbem1ab), 0, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBEMA2Q, l_mcbem2ab));
+
+ FAPI_TRY(l_mcb_fail_160.insert(uint64_t(l_mcbem2ab), 60, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBEMA3Q, l_mcbem3ab));
+
+ FAPI_TRY(l_mcb_fail_160.insert(uint64_t(l_mcbem3ab), 120, 40, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBEMB1Q, l_mcbem1ab));
+
+ FAPI_TRY(l_mcb_fail1_160.insert(uint64_t(l_mcbem1ab), 0, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBEMB2Q, l_mcbem2ab));
+
+ FAPI_TRY(l_mcb_fail1_160.insert(uint64_t(l_mcbem2ab), 60, 60, 0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBEMB3Q, l_mcbem3ab));
+
+ FAPI_TRY(l_mcb_fail1_160.insert(uint64_t(l_mcbem3ab), 120, 40, 0));
+ }
+
+ for (l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ FAPI_TRY(mss_getrankpair(i_target_mba, l_port, 0, &rank_pair, valid_rank));
+
+ if (l_port == 0)
+ {
+ l_max_rank = l_max_rank0;
+ }
+ else
+ {
+ l_max_rank = l_max_rank1;
+ }
+
+ for (uint8_t l_rank_index = 0; l_rank_index < l_max_rank; l_rank_index++)
+ {
+ l_rank = valid_rank[l_rank_index];
+
+ for (l_byte = 0; l_byte < MAX_BYTES_PER_RANK; l_byte++)
+ {
+ for (l_nibble = 0; l_nibble < MAX_NIBBLES_PER_BYTE; l_nibble++)
+ {
+ if (l_port == 0 && l_zmode == 1 && l_zmode_port == 1)
+ {
+ continue;
+ }
+ else if (l_port == 1 && l_zmode == 1 && l_zmode_port == 0)
+ {
+ continue;
+ }
+ else if (l_port == 0)
+ {
+ l_index0 = (l_rank * 20) + (l_byte * 2) + l_nibble;
+ l_index1 = l_index0;
+
+ if ((l_mcb_fail_160.isBitSet(l_index1)))
+ {
+ o_error_map[l_port][l_rank][l_byte][l_nibble] = 1;
+ }
+ else
+ {
+ o_error_map[l_port][l_rank][l_byte][l_nibble] = 0;
+ }
+ }
+ else if (l_port == 1)
+ {
+ l_index0 = (l_rank * 20) + (l_byte * 2) + l_nibble;
+ l_index1 = l_index0;
+
+ if ((l_mcb_fail1_160.isBitSet(l_index1)))
+ {
+ o_error_map[l_port][l_rank][l_byte][l_nibble] = 1;
+ }
+ else
+ {
+ o_error_map[l_port][l_rank][l_byte][l_nibble] = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_attr_eff_dimm_type_u8));
+
+ l_i = 0;
+ l_data_buffer1_64.flush<0>();
+ l_port_index = 0;
+
+ while (l_port_index < MAX_PORTS_PER_MBA)
+ {
+ l_data_buffer1_64.flush<0>();
+ l_data_buffer3_64.flush<0>();
+
+ if (l_mba_position == 0)
+ {
+ if (l_port_index == 0)
+ {
+ l_i = 0;
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMA1Q, l_data_buf_port0));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buf_spare));
+
+ for (l_index = 0; l_index < 64; l_index++)
+ {
+ if (l_data_buf_port0.getBit(l_index))
+ {
+ l_array0[l_i] = l_index;
+ l_i++;
+ }
+ }
+
+ for (l_index = 0; l_index < 16; l_index++)
+ {
+ if (l_data_buf_spare.getBit(l_index))
+ {
+ l_array0[l_i] = l_index + 64;
+ l_i++;
+ }
+ }
+
+ l_number1 = l_i;
+ }
+
+ else
+ {
+ l_i = 0;
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMB1Q, l_data_buf_port1));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buf_spare));
+
+ for (l_index = 0; l_index < 64; l_index++)
+ {
+ if (l_data_buf_port1.getBit(l_index))
+ {
+ l_array1[l_i] = l_index;
+ l_i++;
+ }
+ }
+
+ for (l_index = 16; l_index < 32; l_index++)
+ {
+ if (l_data_buf_spare.getBit(l_index))
+ {
+ l_array1[l_i] = l_index + 64 - 16;
+ l_i++;
+ }
+ }
+
+ l_number = l_i;
+ }
+ }
+ else
+ {
+ if (l_port_index == 0)
+ {
+ l_i = 0;
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buf_spare));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMA1Q, l_data_buf_port0));
+
+ for (l_index = 0; l_index < 64; l_index++)
+ {
+ if (l_data_buf_port0.getBit(l_index))
+ {
+ l_array0[l_i] = l_index;
+ l_i++;
+ }
+ }
+
+ for (l_index = 0; l_index < 16; l_index++)
+ {
+ if (l_data_buf_spare.getBit(l_index))
+ {
+ l_array0[l_i] = l_index + 64;
+ l_i++;
+ }
+ }
+
+ l_number1 = l_i;
+ }
+ else
+ {
+ l_i = 0;
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buf_spare));
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMB1Q, l_data_buf_port1));
+
+ for (l_index = 0; l_index < 64; l_index++)
+ {
+ if (l_data_buf_port1.getBit(l_index))
+ {
+ l_array1[l_i] = l_index;
+ l_i++;
+ }
+ }
+
+ for (l_index = 16; l_index < 32; l_index++)
+ {
+ if (l_data_buf_spare.getBit(l_index))
+ {
+ l_array1[l_i] = l_index + 64 - 16;
+ l_i++;
+ }
+ }
+
+ l_number = l_i;
+ }
+ }
+
+ ++l_port_index;
+ }
+
+ //Conversion from CDIMM larray to ISDIMM larray
+ //port 0
+ for (l_i = 0; l_i < ISDIMM_MAX_DQ_72; l_i++)
+ {
+ FAPI_TRY(rosetta_map(i_target_mba, 0, l_input_type_e, l_i, 0, o_val));
+ cdimm_dq0[o_val] = l_i;
+ }
+
+ //port 1
+ for (l_i = 0; l_i < ISDIMM_MAX_DQ_72; l_i++)
+ {
+ FAPI_TRY(rosetta_map(i_target_mba, 1, l_input_type_e, l_i, 0, o_val));
+ cdimm_dq1[o_val] = l_i;
+ }
+
+ uint8_t l_num, io_num, io_num0, io_num1, l_inter, l_flag, l_n;
+ l_n = 0;
+ io_num0 = 0;
+ io_num1 = 0;
+ l_port = 0;
+
+ while (l_port < MAX_PORTS_PER_MBA)
+ {
+ l_num = 0;
+
+ if (l_port == 0)
+ {
+ for (l_index = 0; l_index < l_number1; l_index++)
+ {
+ l_array[l_index] = l_array0[l_index];
+ }
+
+ l_n = l_number1;
+ FAPI_TRY(mss_getrankpair(i_target_mba, l_port, 0, &rank_pair, l_rankpair_table));
+
+ for (l_i = 0; l_i < ISDIMM_MAX_DQ_72; l_i++)
+ {
+ cdimm_dq[l_i] = cdimm_dq0[l_i];
+ }
+ }
+ else
+ {
+ for (l_index = 0; l_index < l_number; l_index++)
+ {
+ l_array[l_index] = l_array1[l_index];
+ l_n = l_number;
+ }
+
+ FAPI_TRY(mss_getrankpair(i_target_mba, l_port, 0, &rank_pair, l_rankpair_table));
+
+ for (l_i = 0; l_i < ISDIMM_MAX_DQ_72; l_i++)
+ {
+ cdimm_dq[l_i] = cdimm_dq1[l_i];
+ }
+ }
+
+ //Getting array for converting CDIMM values as index and ISDIMM values as value of array for that index
+ for (l_index = 0; l_index < l_n; l_index++)
+ {
+ l_value = l_array[l_index];
+ l_value1 = cdimm_dq[l_value];
+
+ if (l_value >= 72)
+ {
+ l_value1 = 255;
+ }
+
+ l_isarray[l_index] = l_value1;
+ }
+
+ if (l_attr_eff_dimm_type_u8 != fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ //For ISDIMM marray
+ for (l_index = 0; l_index < l_n; l_index++)
+ {
+ l_value = l_isarray[l_index];
+ l_inter = (l_value / 4);
+ l_value1 = l_num - 1;
+ l_marray[l_num] = l_inter * 4;
+ l_num++;
+ }
+ }
+ else
+ {
+ //For CDIMM marray
+ for (l_index = 0; l_index < l_n; l_index++)
+ {
+ l_value = l_array[l_index];
+ l_inter = (l_value / 4);
+ l_value1 = l_num - 1;
+ l_marray[l_num] = l_inter * 4;
+ l_num++;
+ }
+ }
+
+ //Loop to sort Masked ISDIMM array
+ for (l_i = 0; l_i < l_num - 1; l_i++)
+ {
+ for (l_j = l_i + 1; l_j < l_num; l_j++)
+ {
+ if (l_marray[l_i] > l_marray[l_j])
+ {
+ l_value = l_marray[l_j];
+ l_marray[l_j] = l_marray[l_i];
+ l_marray[l_i] = l_value;
+ }
+ }
+ }
+
+ //loop to remove repetition elements
+ l_j = 0;
+
+ for (l_i = 0; l_i < l_num; l_i++)
+ {
+ l_flag = 0;
+
+ if ((l_marray[l_i] == l_marray[l_i + 1]) && (l_num != 0))
+ {
+ l_flag = 1;
+ }
+
+ if (l_flag == 0)
+ {
+ l_marray11[l_j] = l_marray[l_i];
+ l_j++;
+ }
+ }
+
+ l_num = l_j;
+
+ if (l_port == 0)
+ {
+ io_num0 = l_num;
+
+ if (io_num0 >= 21)
+ {
+ io_num0 = 21;
+ }
+
+ for (l_index = 0; l_index < io_num0; l_index++)
+ {
+ l_marray0[l_index] = l_marray11[l_index];
+ }
+
+ for (l_index = 0; l_index < l_number1; l_index++)
+ {
+
+ l_isarray0[l_index] = l_isarray[l_index];
+ }
+ }
+ else
+ {
+ io_num1 = l_num;
+
+ if (io_num1 >= 21)
+ {
+ io_num1 = 21;
+ }
+
+ for (l_index = 0; l_index < io_num1; l_index++)
+ {
+ l_marray1[l_index] = l_marray11[l_index];
+ }
+
+ for (l_index = 0; l_index < l_number; l_index++)
+ {
+
+ l_isarray1[l_index] = l_isarray[l_index];
+ }
+ }
+
+ l_port++;
+ }
+
+ count_bad_dq[0] = l_number1;
+ count_bad_dq[1] = l_number;
+
+ for (l_i = 0; l_i < l_number1; l_i++)
+ {
+ i_CDarray0[l_i] = l_array0[l_i];
+ }
+
+ for (l_i = 0; l_i < l_number; l_i++)
+ {
+ i_CDarray1[l_i] = l_array1[l_i];
+ }
+
+ if(l_attr_eff_dimm_type_u8 != fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES) //Calling ISDIMM error mAP and LRDIMM
+ {
+ FAPI_DBG("%s:################# Error MAP for ISDIMM #################",
+ mss::c_str(i_target_mba));
+
+ for (l_port = 0; l_port < 2; l_port++)
+ {
+ if (l_port == 0)
+ {
+ l_max_rank = l_max_rank0;
+
+ io_num = io_num0;
+
+ for (l_index = 0; l_index < io_num; l_index++)
+ {
+ l_marray[l_index] = l_marray0[l_index];
+ }
+ }
+ else
+ {
+ l_max_rank = l_max_rank1;
+
+ io_num = io_num1;
+
+ for (l_index = 0; l_index < io_num; l_index++)
+ {
+ l_marray[l_index] = l_marray1[l_index];
+ }
+ }
+
+ if (l_max_rank == 0)
+ {
+ FAPI_DBG("%s: NO RANKS FOUND ON PORT %d", mss::c_str(i_target_mba), l_port);
+ }
+ else
+ {
+ //To set the mask print in error map
+ l_value = 0;
+
+ if (l_port == 0)
+ {
+ //For Port 0
+ for (l_index = 0; l_index < l_number1; l_index++)
+ {
+ l_flag = 0;
+ l_value = l_isarray0[l_index];
+
+ if (l_value >= 72)
+ {
+ l_flag = 1;
+ }
+
+ if ((l_value >= 64) && (l_value < 72))
+ {
+ l_value1 = l_value - 64;
+ l_flag = 2;
+ FAPI_TRY(l_ISDIMM_spare0.setBit(l_value1));
+ }
+
+ if (l_flag == 0)
+ {
+ FAPI_TRY(l_ISDIMM_BUF0.setBit(l_value));
+ }
+ }
+
+ l_generic_buffer0 = 0;
+ l_output0 = 0;
+ FAPI_TRY(l_ISDIMM_BUF0.extract(l_generic_buffer0, 0, 64));
+ l_sbit = 0;
+ l_len = 8;
+ FAPI_TRY(l_ISDIMM_spare0.extractToRight(l_output0, l_sbit, l_len));
+ l_generic_buffer = l_generic_buffer0;
+ l_output = l_output0;
+ }
+ else
+ {
+ for (l_index = 0; l_index < l_number; l_index++)
+ {
+ l_flag = 0;
+ l_value = l_isarray1[l_index];
+
+ if (l_value >= 72)
+ {
+ l_flag = 1;
+ }
+
+ if ((l_value >= 64) && (l_value < 72))
+ {
+ l_value1 = l_value - 64;
+ l_flag = 2;
+ FAPI_TRY(l_ISDIMM_spare1.setBit(l_value1));
+ }
+
+ if (l_flag == 0)
+ {
+ FAPI_TRY(l_ISDIMM_BUF1.setBit(l_value));
+ }
+ }
+
+ l_generic_buffer1 = 0;
+ l_output1 = 0;
+ FAPI_TRY(l_ISDIMM_BUF1.extract(l_generic_buffer1, 0, 64));
+ l_sbit = 0;
+ l_len = 8;
+ FAPI_TRY(l_ISDIMM_spare1.extractToRight(l_output1, l_sbit, l_len));
+ l_generic_buffer = l_generic_buffer1;
+ l_output = l_output1;
+ }
+
+ //Mask calculation Ends
+ if (l_mba_position == 0)
+ {
+ //FAPI_DBG("%s:MASK %016llX%02X\n",mss::c_str(i_target_mba),l_generic_buffer0,l_output0);
+ FAPI_DBG("%s:################# MBA01 ###########################\n", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:################# PORT%d ERROR MAP #################\n", mss::c_str(i_target_mba), l_port);
+ FAPI_DBG("%s:Byte 001122334455667788", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:Nibble 010101010101010101", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:MASK %016llX%02X\n", mss::c_str(i_target_mba), l_generic_buffer, l_output);
+ }
+ else
+ {
+ FAPI_DBG("%s:################# MBA23 ###########################\n", mss::c_str(i_target_mba));
+ FAPI_DBG(
+ "%s:################# PORT%d ERROR MAP #################\n", mss::c_str(i_target_mba), l_port);
+ FAPI_DBG("%s:Byte 001122334455667788", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:Nibble 010101010101010101", mss::c_str(i_target_mba));
+ FAPI_DBG("%s:MASK %016llX%02X\n", mss::c_str(i_target_mba), l_generic_buffer, l_output);
+ }
+
+ for (uint8_t i = 0; i < l_max_rank; i++)
+ {
+ l_num = 0;
+ FAPI_TRY(mss_getrankpair(i_target_mba, l_port, 0, &rank_pair, valid_rank));
+
+ l_rank = valid_rank[i];
+ sprintf(l_str, "%s:%-4s%d%5s", mss::c_str(i_target_mba), "RANK", l_rank, "");
+ l_flag = 0;
+
+ for (i_byte = 0; i_byte < l_max_bytes; i_byte++)
+ {
+ for (i_nibble = 0; i_nibble < 2; i_nibble++)
+ {
+ l_flag = 0;
+ l_inter = l_marray[l_num];
+
+ i_input_index_u8 = (8 * i_byte) + (4 * i_nibble);
+
+ if ((l_inter == i_input_index_u8) && (l_num < io_num))
+ {
+ l_num++;
+ l_flag = 1;
+ }
+
+ FAPI_TRY(rosetta_map(i_target_mba, l_port,
+ l_input_type_e, i_input_index_u8,
+ 0, o_val));
+
+ i_byte1 = o_val / 8;
+ i_nibble1 = o_val % 8;
+
+ if (i_nibble1 > 3)
+ {
+ i_nibble1 = 1;
+ }
+ else
+ {
+ i_nibble1 = 0;
+ }
+
+ if (l_flag == 1)
+ {
+ strcat(l_str, "M");
+ }
+ else
+ {
+ if (o_error_map[l_port][l_rank][i_byte1][i_nibble1] == 1)
+ {
+ strcat(l_str, "X");
+ }
+ else
+ {
+ strcat(l_str, ".");
+ }
+ }
+ } // for nibble
+ } // for byte
+ } // for rank
+ } // ranks found
+ } // for each port
+ } //custom dimm yes
+
+ else //Calling CDIMM error Map print
+ {
+ FAPI_DBG("%s:################# CDIMM ERROR MAP ###########################\n", mss::c_str(i_target_mba));
+ l_port = 0;
+ mcb_error_map_print(i_target_mba, l_mcb_fail_160, l_port, l_array0,
+ l_number1, l_data_buf_port0, l_data_buf_spare);
+
+ l_port = 1;
+ mcb_error_map_print(i_target_mba, l_mcb_fail1_160, l_port, l_array1,
+ l_number, l_data_buf_port1, l_data_buf_spare);
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Based on parameters passed we write data into Register being passed
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_reg_addr Register address
+ /// @param[in] i_operation_type Operation Type
+ /// @param[in] i_cfg_test_123_cmd Integer value
+ /// @param[in] i_addr_mode Sequential or Random address modes
+ /// @param[in] i_data_mode Data Mode
+ /// @param[in] i_done Done Bit
+ /// @param[in] i_data_select_mode Different BURST modes or DEFAULT
+ /// @param[in] i_addr_select_mode Address Select mode
+ /// @param[in] i_testnumber Subtest number
+ /// @param[in] i_testnumber1 Subtest number
+ /// @param[in] i_total_subtest_no
+ /// @param[in] i_sub_info Subtest info array
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode mcb_write_test_mem(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint64_t i_reg_addr,
+ const mcbist_oper_type i_operation_type,
+ const uint8_t i_cfg_test_123_cmd,
+ const mcbist_addr_mode i_addr_mode,
+ const mcbist_data_mode i_data_mode,
+ const uint8_t i_done,
+ const mcbist_data_select_mode i_data_select_mode,
+ const mcbist_add_select_mode i_addr_select_mode,
+ const uint8_t i_testnumber,
+ const uint8_t i_testnumber1,
+ const uint8_t i_total_subtest_no,
+ struct subtest_info i_sub_info[30])
+ {
+ uint8_t l_index = 0;
+ uint8_t l_operation_type = i_operation_type;
+ uint8_t l_cfg_test_123_cmd = i_cfg_test_123_cmd;
+ uint8_t l_addr_mode = i_addr_mode;
+ uint8_t l_data_mode = i_data_mode;
+ uint8_t l_data_select_mode = i_data_select_mode;
+ uint8_t l_addr_select_mode = i_addr_select_mode;
+ fapi2::buffer<uint64_t> l_data_buffer_64;
+ uint8_t l_done_bit = 0;
+
+ FAPI_DBG("%s:Function mcb_write_test_mem", mss::c_str(i_target_mba));
+ FAPI_TRY(fapi2::getScom(i_target_mba, i_reg_addr, l_data_buffer_64));
+
+ l_index = i_testnumber * (MCB_TEST_NUM);
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MCBIST_ADDR_BANK, i_target_mba, l_done_bit));
+
+ if (l_done_bit == 1)
+ {
+ return fapi2::FAPI2_RC_FALSE;
+ }
+
+ i_sub_info[i_testnumber1].l_operation_type = l_operation_type;
+ i_sub_info[i_testnumber1].l_data_mode = l_data_mode;
+ i_sub_info[i_testnumber1].l_addr_mode = l_addr_mode;
+
+ // Operation type
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_operation_type, l_index, 3));
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_cfg_test_123_cmd, l_index + 3, 3));
+ // ADDR MODE
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_addr_mode, l_index + 6, 2));
+ // DATA MODE
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_data_mode, l_index + 8, 3));
+ // Done bit
+ FAPI_TRY(l_data_buffer_64.insertFromRight(i_done, l_index + 11, 1));
+ // Data Select Mode
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_data_select_mode, l_index + 12, 2));
+
+ // Address Select mode
+ FAPI_TRY(l_data_buffer_64.insertFromRight(l_addr_select_mode, l_index + 14, 2));
+
+ FAPI_TRY(fapi2::putScom(i_target_mba, i_reg_addr, l_data_buffer_64));
+ FAPI_TRY(fapi2::getScom(i_target_mba, i_reg_addr, l_data_buffer_64));
+
+ FAPI_DBG("%s:SUBTEST %d of %d in Progress.................... ",
+ mss::c_str(i_target_mba), i_testnumber1, i_total_subtest_no);
+ //FAPI_DBG("%s:SUBTEST %d in Progress.................... ",i_testnumber);
+ FAPI_DBG("%s:SUBTEST DETAILS", mss::c_str(i_target_mba));
+
+ switch (l_operation_type)
+ {
+ case 0:
+ FAPI_DBG("%s:SUBTEST :WRITE", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ FAPI_DBG("%s:SUBTEST :READ", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ FAPI_DBG("%s:SUBTEST :READ - WRITE", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ FAPI_DBG("%s:SUBTEST :WRITE - READ", mss::c_str(i_target_mba));
+ break;
+
+ case 4:
+ FAPI_DBG("%s:SUBTEST :READ - WRITE - READ", mss::c_str(i_target_mba));
+ break;
+
+ case 5:
+ FAPI_DBG("%s:SUBTEST :READ - WRITE - WRITE", mss::c_str(i_target_mba));
+ break;
+
+ case 6:
+ FAPI_DBG("%s:SUBTEST :RANDOM COMMAND SEQUENCE", mss::c_str(i_target_mba));
+ break;
+
+ case 7:
+ FAPI_DBG("%s:SUBTEST :GOTO SUBTEST N OR REFRESH ONLY", mss::c_str(i_target_mba));
+ break;
+
+ default:
+ FAPI_DBG("%s:Wrong Operation selected for Subtest", mss::c_str(i_target_mba));
+ }
+
+ switch (l_data_mode)
+ {
+ case 0:
+ FAPI_DBG("%s:DATA MODE :FIXED DATA", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ FAPI_DBG("%s:DATA MODE :DATA_RANDOM_FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ FAPI_DBG("%s:DATA MODE :DATA_RANDOM_REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ FAPI_DBG("%s:DATA MODE :RANDOM w/ECC FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 4:
+ FAPI_DBG("%s:DATA MODE :RANDOM w/ECC REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ case 5:
+ FAPI_DBG("%s:DATA MODE :DATA EQUAL ADDRESS", mss::c_str(i_target_mba));
+ break;
+
+ case 6:
+ FAPI_DBG("%s:DATA MODE :DATA ROTATE LEFT", mss::c_str(i_target_mba));
+ break;
+
+ case 7:
+ FAPI_DBG("%s:DATA MODE :DATA ROTATE RIGHT", mss::c_str(i_target_mba));
+ break;
+
+ default:
+ FAPI_DBG("%s:Wrong Data Mode selected for Subtest", mss::c_str(i_target_mba));
+ }
+
+ switch (l_addr_mode)
+ {
+ case 0:
+ FAPI_DBG("%s:ADDRESS MODE :SEQUENTIAL FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ FAPI_DBG("%s:ADDRESS MODE :SEQUENTIAL REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ FAPI_DBG("%s:ADDRESS MODE :RANDOM FORWARD", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ FAPI_DBG("%s:ADDRESS MODE :RANDOM REVERSE", mss::c_str(i_target_mba));
+ break;
+
+ default:
+ FAPI_DBG("%s:Wrong Address Mode selected for Subtest", mss::c_str(i_target_mba));
+ }
+
+ FAPI_DBG("%s:SUBTEST %d of %d done ", mss::c_str(i_target_mba),
+ i_testnumber1, i_total_subtest_no);
+
+ if (i_done == 1)
+ {
+ FAPI_DBG("%s:DONE BIT IS SET FOR CURRENT SUBTEST %d",
+ mss::c_str(i_target_mba), i_testnumber1);
+ //FAPI_DBG("%s:DONE BIT IS SET FOR CURRENT SUBTEST %d",i_testnumber);
+ }
+
+ if ((l_data_mode == 0) || (l_data_mode == 6) || (l_data_mode == 7) || (l_data_mode == 5))
+ {
+ //FAPI_DBG("%s:fixed set and value of datamode is %d",l_data_mode);
+ i_sub_info[i_testnumber1].l_fixed_data_enable = 1;
+ }
+ else if ((l_data_mode == 1) || (l_data_mode == 2) || (l_data_mode == 3) || (l_data_mode == 4))
+ {
+ i_sub_info[i_testnumber1].l_random_data_enable = 1;
+ //FAPI_DBG("%s:random set and value of datamode is %d",l_data_mode);
+ }
+
+ if ((l_addr_mode == 0) || (l_addr_mode == 1))
+ {
+ //FAPI_DBG("fixed addr and value of addrmode is %d",l_addr_mode);
+ i_sub_info[i_testnumber1].l_fixed_addr_enable = 1;
+ }
+ else if ((l_addr_mode == 2) || (l_addr_mode == 3))
+ {
+ i_sub_info[i_testnumber1].l_random_addr_enable = 1;
+ //FAPI_DBG("random addr and value of addrmode is %d",l_addr_mode);
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief It is used to mask bad bits read from SPD
+ /// @param[in] i_target_mba Centaur.mba
+ /// @return FAPI2_RC_SUCCESS iff successful
+ ///
+ fapi2::ReturnCode cfg_byte_mask(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+ {
+ uint8_t l_port = 0;
+ uint8_t l_dimm = 0;
+ uint8_t l_rank = 0;
+ uint8_t l_max_0 = 0;
+ uint8_t l_max_1 = 0;
+ uint8_t l_num_ranks = 0;
+ uint8_t l_rnk = 0;
+ uint8_t num_ranks_per_dimm[MAX_PORTS_PER_MBA][MAX_DIMM_PER_PORT] = {0};
+ uint8_t rank_pair = 0;
+ uint64_t l_var = 0xFFFFFFFFFFFFFFFFull;
+ uint16_t l_spare = 0xFFFF;
+ fapi2::buffer<uint64_t> l_data_buffer1_64;
+ fapi2::buffer<uint64_t> l_data_buffer2_64;
+ fapi2::buffer<uint64_t> l_data_buffer3_64;
+ fapi2::buffer<uint64_t> l_data_buffer4_64;
+ fapi2::buffer<uint64_t> l_data_buffer5_64;
+ const auto i_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ uint8_t l_mba_position = 0;
+ uint8_t l_attr_eff_dimm_type_u8 = 0;
+ uint8_t l_dqBitmap[DIMM_DQ_RANK_BITMAP_SIZE] = {0};
+ uint8_t l_dq[8] = { 0 };
+ uint8_t l_sp[2] = { 0 };
+ uint16_t l_index0 = 0;
+ uint8_t l_index_sp = 0;
+ uint16_t l_sp_isdimm = 0xff;
+ uint8_t valid_rank[MAX_RANKS_PER_PORT] = {0};
+
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_NUM_RANKS_PER_DIMM, i_target_mba, num_ranks_per_dimm));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CUSTOM_DIMM, i_target_mba, l_attr_eff_dimm_type_u8));
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, i_target_mba, l_mba_position));
+
+ for (l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ l_num_ranks = num_ranks_per_dimm[l_port][0] + num_ranks_per_dimm[l_port][1];
+ FAPI_TRY(mss_getrankpair(i_target_mba, l_port, 0, &rank_pair, valid_rank));
+
+ for (l_rank = 0; l_rank < l_num_ranks; l_rank++)
+ {
+ l_rnk = valid_rank[l_rank];
+
+ if (l_rnk == 255)
+ {
+ continue;
+ }
+
+ l_max_0 = num_ranks_per_dimm[0][0] + num_ranks_per_dimm[0][1];
+ l_max_1 = num_ranks_per_dimm[1][0] + num_ranks_per_dimm[1][1];
+
+ l_data_buffer3_64.flush<0>();
+
+ FAPI_DBG("%s:Function cfg_byte_mask", mss::c_str(i_target_mba));
+
+ if (l_rnk > 3)
+ {
+ l_dimm = 1;
+ l_rnk = l_rnk - 4;
+ }
+ else
+ {
+ l_dimm = 0;
+ }
+
+ FAPI_TRY(dimmGetBadDqBitmap(i_target_mba, l_port, l_dimm, l_rnk, l_dqBitmap));
+
+ for (l_index0 = 0; l_index0 < DIMM_DQ_RANK_BITMAP_SIZE; l_index0++)
+ {
+ if (l_index0 < 8)
+ {
+ l_dq[l_index0] = l_dqBitmap[l_index0];
+
+ if (l_dqBitmap[l_index0])
+ {
+ FAPI_DBG("%s:\n the port=%d bad dq=%x on dq=%d",
+ mss::c_str(i_target_mba), l_port,
+ l_dqBitmap[l_index0], l_index0);
+ }
+ }
+ else
+ {
+ if (l_dqBitmap[l_index0])
+ {
+ FAPI_DBG("%s:\n the port=%d bad dq=%x on dq=%d",
+ mss::c_str(i_target_mba), l_port,
+ l_dqBitmap[l_index0], l_index0);
+ }
+
+ l_sp[l_index_sp] = l_dqBitmap[l_index0];
+ l_index_sp++;
+ }
+ }
+
+ for(l_index0 = 0; l_index0 < 8; l_index0++)
+ {
+ FAPI_TRY(l_data_buffer1_64.insertFromRight(l_dq[l_index0], l_index0 * 8, 8));
+ }
+
+ if (l_mba_position == 0)
+ {
+ if (l_port == 0)
+ {
+ if(l_attr_eff_dimm_type_u8 != fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp_isdimm, 8, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 0, 8));
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 0, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[1], 8, 8));
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMA1Q, l_data_buffer4_64));
+
+ l_data_buffer1_64 |= l_data_buffer4_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMA1Q, l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer5_64));
+
+ l_data_buffer2_64 |= l_data_buffer5_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer2_64));
+
+ }
+ else
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer2_64));
+
+ if(l_attr_eff_dimm_type_u8 != fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp_isdimm, 24, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 16, 8));
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 16, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[1], 24, 8));
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMB1Q, l_data_buffer4_64));
+
+ l_data_buffer1_64 |= l_data_buffer4_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMB1Q, l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer5_64));
+
+ l_data_buffer2_64 |= l_data_buffer5_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer2_64));
+
+ }
+ }
+ else
+ {
+ if (l_port == 0)
+ {
+ if(l_attr_eff_dimm_type_u8 != fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp_isdimm, 8, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 0, 8));
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 0, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[1], 8, 8));
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMA1Q, l_data_buffer4_64));
+
+ l_data_buffer1_64 |= l_data_buffer4_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMA1Q, l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer5_64));
+
+ l_data_buffer2_64 |= l_data_buffer5_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer2_64));
+
+ }
+ else
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer2_64));
+
+ if(l_attr_eff_dimm_type_u8 != fapi2::ENUM_ATTR_CEN_EFF_CUSTOM_DIMM_YES)
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp_isdimm, 24, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 16, 8));
+ }
+ else
+ {
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[0], 16, 8));
+ FAPI_TRY(l_data_buffer2_64.insertFromRight(l_sp[1], 24, 8));
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMB1Q, l_data_buffer4_64));
+
+ l_data_buffer1_64 |= l_data_buffer4_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMB1Q,
+ l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer5_64));
+
+ l_data_buffer2_64 |= l_data_buffer5_64;
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer2_64));
+
+ }
+ }
+ }
+ }
+
+ if (l_max_0 == 0)
+ {
+ if (l_mba_position == 0)
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMA1Q, l_data_buffer1_64));
+
+ FAPI_TRY(l_data_buffer1_64.insert(l_var, 0, 64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMA1Q, l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer1_64));
+
+ FAPI_TRY(l_data_buffer1_64.insertFromRight(l_spare, 0, 16));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer1_64));
+
+ }
+ else
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMA1Q, l_data_buffer1_64));
+
+ FAPI_TRY(l_data_buffer1_64.insert(l_var, 0, 64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMA1Q, l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer1_64));
+
+ FAPI_TRY(l_data_buffer1_64.insertFromRight(l_spare, 0, 16));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer1_64));
+
+ }
+ }
+
+ if (l_max_1 == 0)
+ {
+ if (l_mba_position == 0)
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMB1Q, l_data_buffer1_64));
+ FAPI_TRY(l_data_buffer1_64.insert(l_var, 0, 64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMB1Q, l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer1_64));
+ FAPI_TRY(l_data_buffer1_64.insertFromRight(l_spare, 16, 16));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS01_MCBCMABQ, l_data_buffer1_64));
+
+ }
+ else
+ {
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMB1Q, l_data_buffer1_64));
+ FAPI_TRY(l_data_buffer1_64.insert(l_var, 0, 64));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMB1Q, l_data_buffer1_64));
+
+ FAPI_TRY(fapi2::getScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer1_64));
+ FAPI_TRY(l_data_buffer1_64.insertFromRight(l_spare, 16, 16));
+ FAPI_TRY(fapi2::putScom(i_target_centaur, CEN_MCBISTS23_MCBCMABQ, l_data_buffer1_64));
+
+ }
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Convert Testype num to mcbist_test_mem type
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_pattern MCBIST testtype
+ /// @param[out] o_mcbtest MCBIST testtype
+ ///
+ void mss_conversion_testtype(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_pattern,
+ mcbist_test_mem& o_mcbtest)
+ {
+
+ FAPI_INF("%s:value of testtype is %d", mss::c_str(i_target_mba), i_pattern);
+
+ switch (i_pattern)
+ {
+ case 0:
+ o_mcbtest = USER_MODE;
+ FAPI_INF("%s:TESTTYPE :USER_MODE", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ o_mcbtest = CENSHMOO;
+ FAPI_INF("%s:TESTTYPE :CENSHMOO", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ o_mcbtest = SUREFAIL;
+ FAPI_INF("%s:TESTTYPE :SUREFAIL", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ o_mcbtest = MEMWRITE;
+ FAPI_INF("%s:TESTTYPE :MEMWRITE", mss::c_str(i_target_mba));
+ break;
+
+ case 4:
+ o_mcbtest = MEMREAD;
+ FAPI_INF("%s:TESTTYPE :MEMREAD", mss::c_str(i_target_mba));
+ break;
+
+ case 5:
+ o_mcbtest = CBR_REFRESH;
+ FAPI_INF("%s:TESTTYPE :CBR_REFRESH", mss::c_str(i_target_mba));
+ break;
+
+ case 6:
+ o_mcbtest = MCBIST_SHORT;
+ FAPI_INF("%s:TESTTYPE :MCBIST_SHORT", mss::c_str(i_target_mba));
+ break;
+
+ case 7:
+ o_mcbtest = SHORT_SEQ;
+ FAPI_INF("%s:TESTTYPE :SHORT_SEQ", mss::c_str(i_target_mba));
+ break;
+
+ case 8:
+ o_mcbtest = DELTA_I;
+ FAPI_INF("%s:TESTTYPE :DELTA_I", mss::c_str(i_target_mba));
+ break;
+
+ case 9:
+ o_mcbtest = DELTA_I_LOOP;
+ FAPI_INF("%s:TESTTYPE :DELTA_I_LOOP", mss::c_str(i_target_mba));
+ break;
+
+ case 10:
+ o_mcbtest = SHORT_RAND;
+ FAPI_INF("%s:TESTTYPE :SHORT_RAND", mss::c_str(i_target_mba));
+ break;
+
+ case 11:
+ o_mcbtest = LONG1;
+ FAPI_INF("%s:TESTTYPE :LONG1", mss::c_str(i_target_mba));
+ break;
+
+ case 12:
+ o_mcbtest = BUS_TAT;
+ FAPI_INF("%s:TESTTYPE :BUS_TAT", mss::c_str(i_target_mba));
+ break;
+
+ case 13:
+ o_mcbtest = SIMPLE_FIX;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_FIX", mss::c_str(i_target_mba));
+ break;
+
+ case 14:
+ o_mcbtest = SIMPLE_RAND;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RAND", mss::c_str(i_target_mba));
+ break;
+
+ case 15:
+ o_mcbtest = SIMPLE_RAND_2W;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RAND_2W", mss::c_str(i_target_mba));
+ break;
+
+ case 16:
+ o_mcbtest = SIMPLE_RAND_FIXD;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RAND_FIXD", mss::c_str(i_target_mba));
+ break;
+
+ case 17:
+ o_mcbtest = SIMPLE_RA_RD_WR;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RA_RD_WR", mss::c_str(i_target_mba));
+ break;
+
+ case 18:
+ o_mcbtest = SIMPLE_RA_RD_R;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RA_RD_R", mss::c_str(i_target_mba));
+ break;
+
+ case 19:
+ o_mcbtest = SIMPLE_RA_FD_R;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RA_FD_R", mss::c_str(i_target_mba));
+ break;
+
+ case 20:
+ o_mcbtest = SIMPLE_RA_FD_R_INF;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RA_FD_R_INF", mss::c_str(i_target_mba));
+ break;
+
+ case 21:
+ o_mcbtest = SIMPLE_SA_FD_R;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_SA_FD_R", mss::c_str(i_target_mba));
+ break;
+
+ case 22:
+ o_mcbtest = SIMPLE_RA_FD_W;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RA_FD_W", mss::c_str(i_target_mba));
+ break;
+
+ case 23:
+ o_mcbtest = INFINITE;
+ FAPI_INF("%s:TESTTYPE :INFINITE", mss::c_str(i_target_mba));
+ break;
+
+ case 24:
+ o_mcbtest = WR_ONLY;
+ FAPI_INF("%s:TESTTYPE :WR_ONLY", mss::c_str(i_target_mba));
+ break;
+
+ case 25:
+ o_mcbtest = W_ONLY;
+ FAPI_INF("%s:TESTTYPE :W_ONLY", mss::c_str(i_target_mba));
+ break;
+
+ case 26:
+ o_mcbtest = R_ONLY;
+ FAPI_INF("%s:TESTTYPE :R_ONLY", mss::c_str(i_target_mba));
+ break;
+
+ case 27:
+ o_mcbtest = W_ONLY_RAND;
+ FAPI_INF("%s:TESTTYPE :W_ONLY_RAND", mss::c_str(i_target_mba));
+ break;
+
+ case 28:
+ o_mcbtest = R_ONLY_RAND;
+ FAPI_INF("%s:TESTTYPE :R_ONLY_RAND", mss::c_str(i_target_mba));
+ break;
+
+ case 29:
+ o_mcbtest = R_ONLY_MULTI;
+ FAPI_INF("%s:TESTTYPE :R_ONLY_MULTI", mss::c_str(i_target_mba));
+ break;
+
+ case 30:
+ o_mcbtest = SHORT;
+ FAPI_INF("%s:TESTTYPE :SHORT", mss::c_str(i_target_mba));
+ break;
+
+ case 31:
+ o_mcbtest = SIMPLE_RAND_BARI;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RAND_BARI", mss::c_str(i_target_mba));
+ break;
+
+ case 32:
+ o_mcbtest = W_R_INFINITE;
+ FAPI_INF("%s:TESTTYPE :W_R_INFINITE", mss::c_str(i_target_mba));
+ break;
+
+ case 33:
+ o_mcbtest = W_R_RAND_INFINITE;
+ FAPI_INF("%s:TESTTYPE :W_R_RAND_INFINITE", mss::c_str(i_target_mba));
+ break;
+
+ case 34:
+ o_mcbtest = R_INFINITE1;
+ FAPI_INF("%s:TESTTYPE :R_INFINITE1", mss::c_str(i_target_mba));
+ break;
+
+ case 35:
+ o_mcbtest = R_INFINITE_RF;
+ FAPI_INF("%s:TESTTYPE :R_INFINITE_RF", mss::c_str(i_target_mba));
+ break;
+
+ case 36:
+ o_mcbtest = MARCH;
+ FAPI_INF("%s:TESTTYPE :MARCH", mss::c_str(i_target_mba));
+ break;
+
+ case 37:
+ o_mcbtest = SIMPLE_FIX_RF;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_FIX_RF", mss::c_str(i_target_mba));
+ break;
+
+ case 38:
+ o_mcbtest = SHMOO_STRESS;
+ FAPI_INF("%s:TESTTYPE :SHMOO_STRESS", mss::c_str(i_target_mba));
+ break;
+
+ case 39:
+ o_mcbtest = SIMPLE_RAND_RA;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_RAND_RA", mss::c_str(i_target_mba));
+ break;
+
+ case 40:
+ o_mcbtest = SIMPLE_FIX_RA;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_FIX_RA", mss::c_str(i_target_mba));
+ break;
+
+ case 41:
+ o_mcbtest = SIMPLE_FIX_RF_RA;
+ FAPI_INF("%s:TESTTYPE :SIMPLE_FIX_RF_RA", mss::c_str(i_target_mba));
+ break;
+
+ case 42:
+ o_mcbtest = TEST_RR;
+ FAPI_INF("%s:TESTTYPE :TEST_RR", mss::c_str(i_target_mba));
+ break;
+
+ case 43:
+ o_mcbtest = TEST_RF;
+ FAPI_INF("%s:TESTTYPE :TEST_RF", mss::c_str(i_target_mba));
+ break;
+
+ case 44:
+ o_mcbtest = W_ONLY_INFINITE_RAND;
+ FAPI_INF("%s:TESTTYPE :W_ONLY_INFINITE_RAND", mss::c_str(i_target_mba));
+ break;
+
+ case 45:
+ o_mcbtest = MCB_2D_CUP_SEQ;
+ FAPI_INF("%s:TESTTYPE :MCB_2D_CUP_SEQ", mss::c_str(i_target_mba));
+ break;
+
+ case 46:
+ o_mcbtest = MCB_2D_CUP_RAND;
+ FAPI_INF("%s:TESTTYPE :MCB_2D_CUP_RAND", mss::c_str(i_target_mba));
+ break;
+
+ case 47:
+ o_mcbtest = SHMOO_STRESS_INFINITE;
+ FAPI_INF("%s:TESTTYPE :SHMOO_STRESS_INFINITE", mss::c_str(i_target_mba));
+ break;
+
+ case 48:
+ o_mcbtest = HYNIX_1_COL;
+ FAPI_INF("%s:TESTTYPE :HYNIX_1_COL", mss::c_str(i_target_mba));
+ break;
+
+ case 49:
+ o_mcbtest = RMWFIX;
+ FAPI_INF("%s:TESTTYPE :RMWFIX", mss::c_str(i_target_mba));
+ break;
+
+ case 50:
+ o_mcbtest = RMWFIX_I;
+ FAPI_INF("%s:TESTTYPE :RMWFIX_I", mss::c_str(i_target_mba));
+ break;
+
+ case 51:
+ o_mcbtest = W_INFINITE;
+ FAPI_INF("%s:TESTTYPE :W_INFINITE", mss::c_str(i_target_mba));
+ break;
+
+ case 52:
+ o_mcbtest = R_INFINITE;
+ FAPI_INF("%s:TESTTYPE :R_INFINITE", mss::c_str(i_target_mba));
+ break;
+
+
+ default:
+ FAPI_INF("%s:Wrong Test_type,so using default test_type",
+ mss::c_str(i_target_mba));
+ }
+
+ }
+
+ ///
+ /// @brief convert number pattern to mcbist_data_gen type
+ /// @param[in] i_target_mba Centaur input mba
+ /// @param[in] i_pattern input pattern
+ /// @param[out] o_mcbpatt mcbist_data_gen type pattern
+ ///
+ void mss_conversion_data(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_pattern,
+ mcbist_data_gen& o_mcbpatt)
+ {
+ FAPI_INF("%s:value of pattern is %d", mss::c_str(i_target_mba), i_pattern);
+
+ switch (i_pattern)
+ {
+ case 0:
+ o_mcbpatt = ABLE_FIVE;
+ FAPI_INF("%s:PATTERN :ABLE_FIVE", mss::c_str(i_target_mba));
+ break;
+
+ case 1:
+ o_mcbpatt = USR_MODE;
+ FAPI_INF("%s:PATTERN :USER_MODE", mss::c_str(i_target_mba));
+ break;
+
+ case 2:
+ o_mcbpatt = ONEHOT;
+ FAPI_INF("%s:PATTERN :ONEHOT", mss::c_str(i_target_mba));
+ break;
+
+ case 3:
+ o_mcbpatt = DQ0_00011111_RESTALLONE;
+ FAPI_INF("%s:PATTERN :DQ0_00011111_RESTALLONE", mss::c_str(i_target_mba));
+ break;
+
+ case 4:
+ o_mcbpatt = DQ0_11100000_RESTALLZERO;
+ FAPI_INF("%s:PATTERN :DQ0_11100000_RESTALLZERO", mss::c_str(i_target_mba));
+ break;
+
+ case 5:
+ o_mcbpatt = ALLZERO;
+ FAPI_INF("%s:PATTERN :ALLZERO", mss::c_str(i_target_mba));
+ break;
+
+ case 6:
+ o_mcbpatt = ALLONE;
+ FAPI_INF("%s:PATTERN :ALLONE", mss::c_str(i_target_mba));
+ break;
+
+ case 7:
+ o_mcbpatt = BYTE_BURST_SIGNATURE;
+ FAPI_INF("%s:PATTERN :BYTE_BURST_SIGNATURE", mss::c_str(i_target_mba));
+ break;
+
+ case 8:
+ o_mcbpatt = BYTE_BURST_SIGNATURE_V1;
+ FAPI_INF("%s:PATTERN :BYTE_BURST_SIGNATURE_V1", mss::c_str(i_target_mba));
+ break;
+
+ case 9:
+ o_mcbpatt = BYTE_BURST_SIGNATURE_V2;
+ FAPI_INF("%s:PATTERN :BYTE_BURST_SIGNATURE_V2", mss::c_str(i_target_mba));
+ break;
+
+ case 10:
+ o_mcbpatt = BYTE_BURST_SIGNATURE_V3;
+ FAPI_INF("%s:PATTERN :BYTE_BURST_SIGNATURE_V3", mss::c_str(i_target_mba));
+ break;
+
+ case 11:
+ o_mcbpatt = DATA_GEN_DELTA_I;
+ FAPI_INF("%s:PATTERN :DATA_GEN_DELTA_I", mss::c_str(i_target_mba));
+ break;
+
+ case 12:
+ o_mcbpatt = MCBIST_2D_CUP_PAT0;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT0", mss::c_str(i_target_mba));
+ break;
+
+ case 13:
+ o_mcbpatt = MPR;
+ FAPI_INF("%s:PATTERN :MPR", mss::c_str(i_target_mba));
+ break;
+
+ case 14:
+ o_mcbpatt = MPR03;
+ FAPI_INF("%s:PATTERN :MPR03", mss::c_str(i_target_mba));
+ break;
+
+ case 15:
+ o_mcbpatt = MPR25;
+ FAPI_INF("%s:PATTERN :MPR25", mss::c_str(i_target_mba));
+ break;
+
+ case 16:
+ o_mcbpatt = MPR47;
+ FAPI_INF("%s:PATTERN :MPR47", mss::c_str(i_target_mba));
+ break;
+
+ case 17:
+ o_mcbpatt = DELTA_I1;
+ FAPI_INF("%s:PATTERN :DELTA_I1", mss::c_str(i_target_mba));
+ break;
+
+ case 18:
+ o_mcbpatt = MCBIST_2D_CUP_PAT1;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT1", mss::c_str(i_target_mba));
+ break;
+
+ case 19:
+ o_mcbpatt = MHC_55;
+ FAPI_INF("%s:PATTERN :MHC_55", mss::c_str(i_target_mba));
+ break;
+
+ case 20:
+ o_mcbpatt = MHC_DQ_SIM;
+ FAPI_INF("%s:PATTERN :MHC_DQ_SIM", mss::c_str(i_target_mba));
+ break;
+
+ case 21:
+ o_mcbpatt = MCBIST_2D_CUP_PAT2;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT2", mss::c_str(i_target_mba));
+ break;
+
+ case 22:
+ o_mcbpatt = MCBIST_2D_CUP_PAT3;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT3", mss::c_str(i_target_mba));
+ break;
+
+ case 23:
+ o_mcbpatt = MCBIST_2D_CUP_PAT4;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT4", mss::c_str(i_target_mba));
+ break;
+
+ case 24:
+ o_mcbpatt = MCBIST_2D_CUP_PAT5;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT5", mss::c_str(i_target_mba));
+ break;
+
+ case 25:
+ o_mcbpatt = MCBIST_2D_CUP_PAT6;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT6", mss::c_str(i_target_mba));
+ break;
+
+ case 26:
+ o_mcbpatt = MCBIST_2D_CUP_PAT7;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT7", mss::c_str(i_target_mba));
+ break;
+
+ case 27:
+ o_mcbpatt = MCBIST_2D_CUP_PAT8;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT8", mss::c_str(i_target_mba));
+ break;
+
+ case 28:
+ o_mcbpatt = MCBIST_2D_CUP_PAT9;
+ FAPI_INF("%s:PATTERN :MCBIST_2D_CUP_PAT9", mss::c_str(i_target_mba));
+ break;
+
+ case 29:
+ o_mcbpatt = CWLPATTERN;
+ FAPI_INF("%s:PATTERN :CWLPATTERN", mss::c_str(i_target_mba));
+ break;
+
+ case 30:
+ o_mcbpatt = GREY1;
+ FAPI_INF("%s:PATTERN :GREY1", mss::c_str(i_target_mba));
+ break;
+
+ case 31:
+ o_mcbpatt = DC_ONECHANGE;
+ FAPI_INF("%s:PATTERN :DC_ONECHANGE", mss::c_str(i_target_mba));
+ break;
+
+ case 32:
+ o_mcbpatt = DC_ONECHANGEDIAG;
+ FAPI_INF("%s:PATTERN :DC_ONECHANGEDIAG", mss::c_str(i_target_mba));
+ break;
+
+ case 33:
+ o_mcbpatt = GREY2;
+ FAPI_INF("%s:PATTERN :GREY2", mss::c_str(i_target_mba));
+ break;
+
+ case 34:
+ o_mcbpatt = FIRST_XFER;
+ FAPI_INF("%s:PATTERN :FIRST_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 35:
+ o_mcbpatt = MCBIST_222_XFER;
+ FAPI_INF("%s:PATTERN :MCBIST_222_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 36:
+ o_mcbpatt = MCBIST_333_XFER;
+ FAPI_INF("%s:PATTERN :MCBIST_333_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 37:
+ o_mcbpatt = MCBIST_444_XFER;
+ FAPI_INF("%s:PATTERN :MCBIST_444_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 38:
+ o_mcbpatt = MCBIST_555_XFER;
+ FAPI_INF("%s:PATTERN :MCBIST_555_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 39:
+ o_mcbpatt = MCBIST_666_XFER;
+ FAPI_INF("%s:PATTERN :MCBIST_666_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 40:
+ o_mcbpatt = MCBIST_777_XFER;
+ FAPI_INF("%s:PATTERN :MCBIST_777_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 41:
+ o_mcbpatt = MCBIST_888_XFER;
+ FAPI_INF("%s:PATTERN :MCBIST_888_XFER", mss::c_str(i_target_mba));
+ break;
+
+ case 42:
+ o_mcbpatt = FIRST_XFER_X4MODE;
+ FAPI_INF("%s:PATTERN :FIRST_XFER_X4MODE", mss::c_str(i_target_mba));
+ break;
+
+ case 43:
+ o_mcbpatt = MCBIST_LONG;
+ FAPI_INF("%s:PATTERN :MCBIST_LONG", mss::c_str(i_target_mba));
+ break;
+
+ case 44:
+ o_mcbpatt = PSEUDORANDOM;
+ FAPI_INF("%s:PATTERN :PSEUDORANDOM", mss::c_str(i_target_mba));
+ break;
+
+ case 45:
+ o_mcbpatt = CASTLE;
+ FAPI_INF("%s:PATTERN :CASTLE", mss::c_str(i_target_mba));
+ break;
+
+ default:
+ FAPI_INF("%s:Wrong Data Pattern,so using default pattern",
+ mss::c_str(i_target_mba));
+ }
+ }
+}
+
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.mk
new file mode 100755
index 000000000..6c06a370a
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mcbist_common.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_mcbist_common
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.C
index 5b7b9243d..7ce1ada44 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.C
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.C
@@ -31,7 +31,7 @@
/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
/// *HWP Team: Memory
/// *HWP Level: 2
-/// *HWP Consumed by: Memtools
+/// *HWP Consumed by: HB:CI
///
//----------------------------------------------------------------------
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.H
index cbc90fbed..be2167ada 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.H
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_mrs6_DDR4.H
@@ -31,7 +31,7 @@
/// *HWP HWP Backup: Steve Glancy <sglancy@us.ibm.com>
/// *HWP Team: Memory
/// *HWP Level: 2
-/// *HWP Consumed by: Memtools
+/// *HWP Consumed by: HB:CI
///
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_shmoo_common.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_shmoo_common.H
new file mode 100755
index 000000000..0cf8393a0
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_shmoo_common.H
@@ -0,0 +1,107 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_shmoo_common.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_shmoo_common.H
+/// @brief Tools for DDR4 DIMMs centaur procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: steve glancy <sglancy@us.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+//
+//
+
+
+
+#ifndef MSS_SHMOO_COMMON_H
+#define MSS_SHMOO_COMMON_H
+
+///
+/// @brief shmoo type enums
+///
+enum shmoo_type_t
+{
+ TEST_NONE = 0,
+ MCBIST = 1,
+ WR_EYE = 2,
+ WRT_DQS = 8,
+ RD_EYE = 4,
+ RD_GATE = 16,
+ BOX = 32
+};
+
+///
+/// @brief shmoo algorithm enums
+///
+enum shmoo_algorithm_t
+{
+ SEQ_LIN // Parallel bytes/ranks here .. no parallel targets in HB
+};
+
+const uint8_t NINE = 9;
+const uint8_t MAX_SHMOO = 2;
+const uint8_t MAX_RANK_DIMM = 4;
+const uint8_t MAX_NIBBLES = 2;
+const uint8_t MAX_BITS = 4;
+const uint8_t MAX_DQ = 80;
+const uint8_t MAX_DQS = 20;
+const uint8_t SCHMOO_NIBBLES = 20;
+const uint8_t MAX_PORT = 2;
+const uint8_t MAX_BYTE = 10;
+const uint8_t MAX_RANK = 8;
+
+///
+/// @brief Defines the structure of a knob ..Holds static info regarding a knob
+///
+struct shmoo_knob_config_t
+{
+ //! These are const values that define a knob , will not change during
+ //! shmoo runtime
+ uint16_t min_val; //Minimum value that can be taken by the knob
+ uint16_t max_val; //Maximum value that can be taken by the knob
+};
+
+///
+/// @brief Defines the structure of a knob ..Holds dynamic runtime info of a knob
+///
+struct shmoo_knob_data_t
+{
+ // placeholder for the datastructure that will hold all the shmoo
+ // config data and results
+ bool done;
+ uint16_t lb_regval[MAX_DQ]; // Left Bound register/Hex value
+ uint16_t rb_regval[MAX_DQ];// Right Bound register/Hex value
+ uint16_t nom_val[MAX_DQ]; // nominal value of this instance of the knob
+ uint16_t last_pass[MAX_DQ];
+ uint16_t total_margin[MAX_DQ];
+ uint16_t curr_diff[MAX_DQ];
+ uint16_t last_fail[MAX_DQ];
+ uint16_t curr_val[MAX_DQ];
+ uint16_t right_margin_val[MAX_DQ];
+ uint16_t left_margin_val[MAX_DQ];
+};
+#endif
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.C b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.C
new file mode 100755
index 000000000..95f63ec36
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.C
@@ -0,0 +1,1430 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file p9c_mss_termination_control.C
+/// @brief Tools for DDR4 DIMMs centaur procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: SARAVANAN SETHURAMAN <saravanans@in.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+//
+
+
+// Saravanan - Yet to update DRV_IMP new attribute enum change
+
+// Not supported
+// DDR4, DIMM Types
+//----------------------------------------------------------------------
+// Includes - FAPI
+//----------------------------------------------------------------------
+
+#include <fapi2.H>
+#include <dimmConsts.H>
+#include <generic/memory/lib/utils/c_str.H>
+
+//----------------------------------------------------------------------
+//Centaur functions
+//----------------------------------------------------------------------
+#include <p9c_mss_termination_control.H>
+#include <cen_gen_scom_addresses.H>
+#include <p9c_mss_draminit_training_advanced.H>
+
+///
+/// @brief This function will configure the Driver impedance values to the registers
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @param[in] i_drv_imp_dq_dqs driver impedance (DQ/DQS) (OHM24,OHM30,OHM34,OHM40)
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode config_drv_imp(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port,
+ const uint8_t i_drv_imp_dq_dqs)
+{
+ fapi2::buffer<uint64_t> data_buffer;
+ uint8_t enslice_drv = 0xFF;
+ uint8_t enslice_ffedrv = 0xF;
+ uint8_t i = 0;
+
+ FAPI_ASSERT(i_port < MAX_PORTS_PER_MBA,
+ fapi2::CEN_CONFIG_DRV_IMP_INVALID_INPUT().
+ set_PORT_PARAM(i_port),
+ "Driver impedance port input(%u) out of bounds",
+ i_port);
+
+ for(i = 0; i < MAX_DRV_IMP; i++)
+ {
+ if (drv_imp_array[i] == i_drv_imp_dq_dqs)
+ {
+ switch (i)
+ {
+ case 0: //40 ohms
+ enslice_drv = 0x3C;
+ enslice_ffedrv = 0xF;
+ break;
+
+ case 1: //34 ohms
+ enslice_drv = 0x7C;
+ enslice_ffedrv = 0xF;
+ break;
+
+ case 2: //30 ohms
+ enslice_drv = 0x7E;
+ enslice_ffedrv = 0xF;
+ break;
+
+ case 3: //24 ohms
+ enslice_drv = 0xFF;
+ enslice_ffedrv = 0xF;
+ break;
+ }
+
+ break;
+ }
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P0_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(enslice_drv, 48, 8), "config_drv_imp: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(enslice_ffedrv, 56, 4), "config_drv_imp: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P0_4,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P0_4,
+ data_buffer));
+
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P1_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(enslice_drv, 48, 8), "config_drv_imp: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(enslice_ffedrv, 56, 4), "config_drv_imp: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_SLICE_P1_4,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_SLICE_P1_4,
+ data_buffer));
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief This function will configure the Receiver impedance values to the registers
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @param[in] i_rcv_imp_dq_dqs : reciever impedance (OHM15,OHM20,OHM30,OHM40,OHM48,OHM60,OHM80,OHM120,OHM160,OHM240)
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+
+fapi2::ReturnCode config_rcv_imp(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port,
+ const uint8_t i_rcv_imp_dq_dqs)
+{
+ fapi2::buffer<uint64_t> data_buffer;
+ uint8_t enslicepterm = 0xFF;
+ uint8_t enslicepffeterm = 0;
+ uint8_t i = 0;
+
+ FAPI_ASSERT(i_port < MAX_PORTS_PER_MBA,
+ fapi2::CEN_CONFIG_RCV_IMP_INVALID_INPUT().
+ set_PORT_PARAM(i_port),
+ "Receiver impedance port input(%u) out of bounds",
+ i_port);
+
+ for(i = 0; i < MAX_RCV_IMP; i++)
+ {
+ if (rcv_imp_array[i] == i_rcv_imp_dq_dqs)
+ {
+ switch (i)
+ {
+ case 0: //120 OHMS
+ enslicepterm = 0x10;
+ enslicepffeterm = 0x0;
+ break;
+
+ case 1: //80 OHMS
+ enslicepterm = 0x10;
+ enslicepffeterm = 0x2;
+ break;
+
+ case 2: //60 OHMS
+ enslicepterm = 0x18;
+ enslicepffeterm = 0x0;
+ break;
+
+ case 3: //48 OHMS
+ enslicepterm = 0x18;
+ enslicepffeterm = 0x2;
+ break;
+
+ case 4: //40 OHMS
+ enslicepterm = 0x18;
+ enslicepffeterm = 0x6;
+ break;
+
+ case 5: //34 OHMS
+ enslicepterm = 0x38;
+ enslicepffeterm = 0x2;
+ break;
+
+ case 6: //30 OHMS
+ enslicepterm = 0x3C;
+ enslicepffeterm = 0x0;
+ break;
+
+ case 7: //20 OHMS
+ enslicepterm = 0x7E;
+ enslicepffeterm = 0x0;
+ break;
+
+ case 8: //15 OHMS
+ enslicepterm = 0xFF;
+ enslicepffeterm = 0x0;
+ break;
+ }
+
+ break;
+ }
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P0_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(enslicepterm, 48, 8), "config_rcv_imp: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(enslicepffeterm, 56, 4), "config_rcv_imp: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P0_4,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P0_4,
+ data_buffer));
+
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P1_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(enslicepterm, 48, 8), "config_rcv_imp: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(enslicepffeterm, 56, 4), "config_rcv_imp: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_NFET_TERM_P1_4,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_PFET_TERM_P1_4,
+ data_buffer));
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief This function will configure the Slew rate values to the registers
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @param[in] i_slew_type SLEW_TYPE_DATA=0, SLEW_TYPE_ADR_ADDR=1, SLEW_TYPE_ADR_CNTL=2
+/// @param[in] i_slew_imp OHM15=15, OHM20=20, OHM24=24, OHM30=30, OHM34=34, OHM40=40
+/// @note: 15, 20, 30, 40 valid for ADR; 24, 30, 34, 40 valid for DATA
+/// @param[in] i_slew_rate SLEW_3V_NS=3, SLEW_4V_NS=4, SLEW_5V_NS=5, SLEW_6V_NS=6, SLEW_MAXV_NS=7
+/// @note SLEW_MAXV_NS bypasses slew calibration
+/// @return FAPI2_RC_SUCCESS iff success
+///
+fapi2::ReturnCode config_slew_rate(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port, const uint8_t i_slew_type, const uint8_t i_slew_imp,
+ const uint8_t i_slew_rate)
+{
+ fapi2::buffer<uint64_t> data_buffer;
+ uint8_t slew_cal_value = 0;
+ uint8_t imp_idx = 255;
+ uint8_t slew_idx = 255;
+ // array for ATTR_CEN_MSS_SLEW_RATE_DATA/ADR [2][4][4]
+ // port,imp,slew_rat cal'd slew settings
+ uint8_t calibrated_slew_rate_table
+ [MAX_PORTS_PER_MBA][MAX_NUM_IMP][MAX_NUM_CAL_SLEW_RATES] = {{{0}}};
+
+ // FFDC for bad parameters
+ FAPI_ASSERT(i_port < MAX_PORTS_PER_MBA,
+ fapi2::CEN_CONFIG_SLEW_RATE_INVALID_INPUT().
+ set_PORT_PARAM(i_port).
+ set_SLEW_TYPE_PARAM(i_slew_type).
+ set_SLEW_IMP_PARAM(i_slew_imp).
+ set_SLEW_RATE_PARAM(i_slew_rate),
+ "Slew port input(%u) out of bounds", i_port);
+
+ FAPI_ASSERT(i_slew_type < MAX_NUM_SLEW_TYPES,
+ fapi2::CEN_CONFIG_SLEW_RATE_INVALID_INPUT().
+ set_PORT_PARAM(i_port).
+ set_SLEW_TYPE_PARAM(i_slew_type).
+ set_SLEW_IMP_PARAM(i_slew_imp).
+ set_SLEW_RATE_PARAM(i_slew_rate),
+ "Slew type input(%u) out of bounds, (>= %u)",
+ i_slew_type, MAX_NUM_SLEW_TYPES);
+
+ switch (i_slew_rate) // get slew index
+ {
+ case SLEW_MAXV_NS: // max slew
+ FAPI_INF("Slew rate is set to MAX, using bypass mode");
+ slew_cal_value = 0; // slew cal value for bypass mode
+ break;
+
+ case SLEW_6V_NS:
+ slew_idx = 3;
+ break;
+
+ case SLEW_5V_NS:
+ slew_idx = 2;
+ break;
+
+ case SLEW_4V_NS:
+ slew_idx = 1;
+ break;
+
+ case SLEW_3V_NS:
+ slew_idx = 0;
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::CEN_CONFIG_SLEW_RATE_INVALID_INPUT(),
+ "Slew rate input(%u) out of bounds",
+ i_slew_rate);
+ }
+
+ if (i_slew_type == SLEW_TYPE_DATA)
+ {
+ switch (i_slew_imp) // get impedance index for data
+ {
+ case OHM40:
+ imp_idx = 3;
+ break;
+
+ case OHM34:
+ imp_idx = 2;
+ break;
+
+ case OHM30:
+ imp_idx = 1;
+ break;
+
+ case OHM24:
+ imp_idx = 0;
+ break;
+
+ default: // OHM15 || OHM20 not valid for data
+ FAPI_ASSERT(false,
+ fapi2::CEN_CONFIG_SLEW_RATE_INVALID_INPUT(),
+ "Slew impedance input(%u) invalid "
+ "or out of bounds, index=%u",
+ i_slew_imp, imp_idx);
+ }
+
+ if (i_slew_rate != SLEW_MAXV_NS)
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_SLEW_RATE_DATA, i_target_mba,
+ calibrated_slew_rate_table));
+
+ slew_cal_value =
+ calibrated_slew_rate_table[i_port][imp_idx][slew_idx];
+ }
+
+ if (slew_cal_value > MAX_SLEW_VALUE)
+ {
+ FAPI_INF("WARNING: Slew rate(0x%02x) unsupported, "
+ "but continuing... !!", slew_cal_value);
+ slew_cal_value = slew_cal_value & 0x0F;
+ }
+
+ FAPI_INF("Setting DATA (dq/dqs) slew register, imped=%i, slewrate=%i, "
+ "reg_val=0x%X", i_slew_imp, i_slew_rate, slew_cal_value);
+
+ FAPI_DBG("port%u type=%u imp_idx=%u slew_idx=%u cal_slew=%u",
+ i_port, i_slew_type, imp_idx, slew_idx, slew_cal_value);
+
+ if (i_port == 0) // port 0 dq/dqs slew
+ {
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P0_0,
+ data_buffer));
+
+ FAPI_TRY(data_buffer.insertFromRight(slew_cal_value, 56, 4), "Error in setting up DATA slew buffer");
+ // switch this later to use broadcast address, 0x80003C750301143F P0_[0:4]
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P0_4,
+ data_buffer));
+ }
+ else // port 1 dq/dqs slew
+ {
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P1_0,
+ data_buffer));
+
+ FAPI_TRY(data_buffer.insertFromRight(slew_cal_value, 56, 4), "Error in setting up DATA slew buffer");
+ // switch this later to use broadcast address, 0x80013C750301143F P1_[0:4]
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_IO_TX_CONFIG0_P1_4,
+ data_buffer));
+ }
+ } // end DATA
+ else // Slew type = ADR
+ {
+ uint8_t adr_pos = 48; // SLEW_CTL0(48:51) of reg for ADR command slew
+
+ for(uint8_t i = 0; i < MAX_NUM_IMP; i++) // find ADR imp index
+ {
+ if (adr_imp_array[i] == i_slew_imp)
+ {
+ imp_idx = i;
+ break;
+ }
+ }
+
+ if ((i_slew_imp == OHM24) || (i_slew_imp == OHM34) ||
+ (imp_idx >= MAX_NUM_IMP))
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_CONFIG_SLEW_RATE_INVALID_INPUT(),
+ "Slew impedance input(%u) out of bounds",
+ i_slew_imp);
+ }
+
+ if (i_slew_rate == SLEW_MAXV_NS)
+ {
+ slew_cal_value = 0;
+ }
+ else
+ {
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_SLEW_RATE_ADR, i_target_mba,
+ calibrated_slew_rate_table));
+
+ slew_cal_value =
+ calibrated_slew_rate_table[i_port][imp_idx][slew_idx];
+ }
+
+ if (slew_cal_value > MAX_SLEW_VALUE)
+ {
+ FAPI_INF("!! Slew rate(0x%02x) unsupported, but continuing... !!",
+ slew_cal_value);
+ slew_cal_value = slew_cal_value & 0x0F;
+ }
+
+ switch (i_slew_type) // get impedance index for data
+ {
+ case SLEW_TYPE_ADR_ADDR:
+ // CTL0 for command slew (A0:15, BA0:3, ACT, PAR, CAS, RAS, WE)
+ FAPI_INF("Setting ADR command/address slew in CTL0 register "
+ "imped=%i, slewrate=%i, reg_val=0x%X", i_slew_imp,
+ i_slew_rate, slew_cal_value);
+ adr_pos = 48;
+ break;
+
+ case SLEW_TYPE_ADR_CNTL:
+ // CTL1 for control slew (CKE0:1, CKE4:5, ODT0:3, CSN0:3)
+ FAPI_INF("Setting ADR control slew in CTL1 register "
+ "imped=%i, slewrate=%i, reg_val=0x%X", i_slew_imp,
+ i_slew_rate, slew_cal_value);
+ adr_pos = 52;
+ break;
+
+ case SLEW_TYPE_ADR_CLK:
+ // CTL2 for clock slew (CLK0:3)
+ FAPI_INF("Setting ADR clock slew in CTL2 register "
+ "imped=%i, slewrate=%i, reg_val=0x%X", i_slew_imp,
+ i_slew_rate, slew_cal_value);
+ adr_pos = 56;
+ break;
+
+ case SLEW_TYPE_ADR_SPCKE:
+ // CTL3 for spare clock slew (CKE2:3)
+ FAPI_INF("Setting ADR Spare clock in CTL3 register "
+ "imped=%i, slewrate=%i, reg_val=0x%X", i_slew_imp,
+ i_slew_rate, slew_cal_value);
+ adr_pos = 60;
+ break;
+ }
+
+ FAPI_DBG("port%u type=%u slew_idx=%u imp_idx=%u cal_slew=%u",
+ i_port, i_slew_type, slew_idx, imp_idx, slew_cal_value);
+
+ if (i_port == 0) // port 0 adr slew
+ {
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P0_ADR0,
+ data_buffer));
+
+ FAPI_TRY(data_buffer.insertFromRight(slew_cal_value, adr_pos, 4), "Error in setting up ADR slew buffer");
+ // switch this later to use broadcast address, 0x80007C1A0301143f ADR[0:3]
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P0_ADR0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P0_ADR1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P0_ADR2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P0_ADR3,
+ data_buffer));
+ }
+ else // port 1 adr slew
+ {
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P1_ADR0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(slew_cal_value, adr_pos, 4), "Error in setting up ADR slew buffer");
+ // switch this later to use broadcast address, 0x80017C1A0301143f ADR[0:3]
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P1_ADR0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P1_ADR1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P1_ADR2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_ADR_IO_SLEW_CTL_VALUE_P1_ADR3,
+ data_buffer));
+ }
+ } // end ADR
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief This function configures PC_VREF_DRV_CONTROL registers to vary the DIMM VREF
+/// @param[in] i_target_mba Centaur input mba
+/// @param[in] i_port Centaur input port
+/// @param[in] i_wr_dram_vref dram write reference voltage
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode config_wr_dram_vref(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port,
+ const uint32_t i_wr_dram_vref)
+{
+
+ fapi2::buffer<uint64_t> data_buffer;
+ uint32_t pcvref = 0;
+ uint32_t sign = 0;
+
+ // For DDR3 vary from VDD*0.42 to VDD*575
+ // For DDR4 internal voltage is there this function is not required
+ FAPI_ASSERT(i_port < MAX_PORTS_PER_MBA,
+ fapi2::CEN_CONFIG_WR_DRAM_VREF_INVALID_INPUT().
+ set_PORT_PARAM(i_port),
+ "Write Vref port input(%u) out of bounds",
+ i_port);
+
+ if(i_wr_dram_vref < 500)
+ {
+ sign = 1;
+ }
+ else
+ {
+ sign = 0;
+ }
+
+ if((i_wr_dram_vref == 420) || (i_wr_dram_vref == 575))
+ {
+ pcvref = 0xF;
+ }
+ else if((i_wr_dram_vref == 425) || (i_wr_dram_vref == 570))
+ {
+ pcvref = 0x7;
+ }
+ else if((i_wr_dram_vref == 430) || (i_wr_dram_vref == 565))
+ {
+ pcvref = 0xB;
+ }
+ else if((i_wr_dram_vref == 435) || (i_wr_dram_vref == 560))
+ {
+ pcvref = 0x3;
+ }
+ else if((i_wr_dram_vref == 440) || (i_wr_dram_vref == 555))
+ {
+ pcvref = 0xD;
+ }
+ else if((i_wr_dram_vref == 445) || (i_wr_dram_vref == 550))
+ {
+ pcvref = 0x5;
+ }
+ else if((i_wr_dram_vref == 450) || (i_wr_dram_vref == 545))
+ {
+ pcvref = 0x9;
+ }
+ else if((i_wr_dram_vref == 455) || (i_wr_dram_vref == 540))
+ {
+ pcvref = 0x1;
+ }
+ else if((i_wr_dram_vref == 460) || (i_wr_dram_vref == 535))
+ {
+ pcvref = 0xE;
+ }
+ else if((i_wr_dram_vref == 465) || (i_wr_dram_vref == 530))
+ {
+ pcvref = 0x6;
+ }
+ else if((i_wr_dram_vref == 470) || (i_wr_dram_vref == 525))
+ {
+ pcvref = 0xA;
+ }
+ else if((i_wr_dram_vref == 475) || (i_wr_dram_vref == 520))
+ {
+ pcvref = 0x2;
+ }
+ else if((i_wr_dram_vref == 480) || (i_wr_dram_vref == 515))
+ {
+ pcvref = 0xC;
+ }
+ else if((i_wr_dram_vref == 485) || (i_wr_dram_vref == 510))
+ {
+ pcvref = 0x4;
+ }
+ else if((i_wr_dram_vref == 490) || (i_wr_dram_vref == 505))
+ {
+ pcvref = 0x8;
+ }
+ else if((i_wr_dram_vref == 495) || (i_wr_dram_vref == 500))
+ {
+ pcvref = 0x0;
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_mba, CEN_MBA_DDRPHY_PC_VREF_DRV_CONTROL_P0, data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(sign, 48, 1), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(sign, 53, 1), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(pcvref, 49, 4), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(pcvref, 54, 4), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_DDRPHY_PC_VREF_DRV_CONTROL_P0, data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(sign, 48, 1), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(sign, 53, 1), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(pcvref, 49, 4), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(data_buffer.insertFromRight(pcvref, 54, 4), "config_wr_vref: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba, CEN_MBA_DDRPHY_PC_VREF_DRV_CONTROL_P1, data_buffer));
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief This function configures read vref registers to vary the CEN VREF
+/// @param[in] i_target_mba centaur input mba
+/// @param[in] i_rd_cen_vref Read vref (centaur side)
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+fapi2::ReturnCode config_rd_cen_vref (const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba, const uint8_t i_port,
+ const uint32_t i_rd_cen_vref)
+{
+// VDD40375 = 40375, VDD41750 = 41750, VDD43125 = 43125, VDD44500 = 44500,
+// VDD45875 = 45875, VDD47250 = 47250, VDD48625 = 48625, VDD50000 = 50000, VDD51375 = 51375,
+// VDD52750 = 52750, VDD54125 = 54125, VDD55500 = 55500, VDD56875 = 56875, VDD58250 = 58250,
+// VDD59625 = 59625, VDD61000 = 61000, VDD60375 = 60375, VDD61750 = 61750, VDD63125 = 63125,
+// VDD64500 = 64500, VDD65875 = 65875, VDD67250 = 67250, VDD68625 = 68625, VDD70000 = 70000,
+// VDD71375 = 71375, VDD72750 = 72750, VDD74125 = 74125, VDD75500 = 75500, VDD76875 = 76875,
+// VDD78250 = 78250, VDD79625 = 79625, VDD81000 = 81000
+// DDR3 supports upto 61000, DDR4 - full range
+
+ fapi2::buffer<uint64_t> data_buffer;
+ uint32_t rd_vref = 0;
+
+ FAPI_ASSERT(i_port < MAX_PORTS_PER_MBA,
+ fapi2::CEN_CONFIG_RD_CEN_VREF_INVALID_INPUT().
+ set_PORT_PARAM(i_port),
+ "Read vref port input(%u) out of bounds",
+ i_port);
+
+ //if (rd_cen_vref == DDR3 rd_vref ) || (rd_cen_vref == DDR4)
+
+ if((i_rd_cen_vref == 61000) || (i_rd_cen_vref == 81000))
+ {
+ rd_vref = 0xF;
+ }
+ else if((i_rd_cen_vref == 59625) || (i_rd_cen_vref == 79625))
+ {
+ rd_vref = 0xE;
+ }
+ else if((i_rd_cen_vref == 58250) || (i_rd_cen_vref == 78250))
+ {
+ rd_vref = 0xD;
+ }
+ else if((i_rd_cen_vref == 56875) || (i_rd_cen_vref == 76875))
+ {
+ rd_vref = 0xC;
+ }
+ else if((i_rd_cen_vref == 55500) || (i_rd_cen_vref == 75500))
+ {
+ rd_vref = 0xB;
+ }
+ else if((i_rd_cen_vref == 54125) || (i_rd_cen_vref == 74125))
+ {
+ rd_vref = 0xA;
+ }
+ else if((i_rd_cen_vref == 52750) || (i_rd_cen_vref == 72750))
+ {
+ rd_vref = 0x9;
+ }
+ else if((i_rd_cen_vref == 51375) || (i_rd_cen_vref == 71375))
+ {
+ rd_vref = 0x8;
+ }
+ else if((i_rd_cen_vref == 50000) || (i_rd_cen_vref == 70000))
+ {
+ rd_vref = 0x0;
+ }
+ else if((i_rd_cen_vref == 48625) || (i_rd_cen_vref == 68625))
+ {
+ rd_vref = 0x1;
+ }
+ else if((i_rd_cen_vref == 47250) || (i_rd_cen_vref == 67250))
+ {
+ rd_vref = 0x2;
+ }
+ else if((i_rd_cen_vref == 45875) || (i_rd_cen_vref == 65875))
+ {
+ rd_vref = 0x3;
+ }
+ else if((i_rd_cen_vref == 44500) || (i_rd_cen_vref == 64500))
+ {
+ rd_vref = 0x4;
+ }
+ else if((i_rd_cen_vref == 43125) || (i_rd_cen_vref == 63125))
+ {
+ rd_vref = 0x5;
+ }
+ else if((i_rd_cen_vref == 41750) || (i_rd_cen_vref == 61750))
+ {
+ rd_vref = 0x6;
+ }
+ else if((i_rd_cen_vref == 40375) || (i_rd_cen_vref == 60375))
+ {
+ rd_vref = 0x7;
+ }
+ else
+ {
+ rd_vref = 0x0;
+ }
+
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(rd_vref, 56, 4), "config_rd_vref: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P0_4,
+ data_buffer));
+ FAPI_TRY(fapi2::getScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_0,
+ data_buffer));
+ FAPI_TRY(data_buffer.insertFromRight(rd_vref, 56, 4), "config_rd_vref: Error in setting up buffer ");
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_0,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_1,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_2,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_3,
+ data_buffer));
+ FAPI_TRY(fapi2::putScom(i_target_mba,
+ CEN_MBA_DDRPHY_DP18_RX_PEAK_AMP_P1_4,
+ data_buffer));
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// Function: mss_slew_cal()
+/// @brief Runs the slew calibration engine to configure MSS_SLEW_DATA/ADR attrs and calls config_slew_rate to set the slew rate
+/// @param[in] i_target_mba centaur mba
+///
+fapi2::ReturnCode mss_slew_cal(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba)
+{
+ fapi2::ReturnCode array_rcs[MAX_PORTS_PER_MBA]; // capture rc per port loop
+ uint32_t poll_count = 0;
+ uint8_t ports_valid = 0;
+ uint8_t is_sim = 0;
+ fapi2::ReturnCode rc;
+ uint8_t freq_idx = 0; // freq index into lookup table
+ uint32_t ddr_freq = 0; // current ddr freq
+ uint8_t ddr_idx = 0; // ddr type index into lookup table
+ uint8_t ddr_type = 0; // ATTR_CEN_EFF_DRAM_GEN{0=invalid, 1=ddr3, 2=ddr4}
+
+ uint8_t cal_status = 0;
+ // bypass slew (MAX slew rate) not included since it is not calibrated.
+ // for output ATTR_CEN_MSS_SLEW_RATE_DATA(0),
+ // ATTR_CEN_MSS_SLEW_RATE_ADR(1), [port=2][imp=4][slew=4]
+ uint8_t calibrated_slew[2][MAX_PORTS_PER_MBA][MAX_NUM_IMP]
+ [MAX_NUM_CAL_SLEW_RATES] = {{{{ 0 }}}};
+
+ fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP> l_target_centaur; // temporary target for parent
+
+ fapi2::buffer<uint64_t> ctl_reg;
+ fapi2::buffer<uint64_t> stat_reg;
+
+ // DD level 1.0-1.1, Version 1.0
+ // [ddr3/4][dq/adr][speed][impedance][slew_rate]
+ // note: Assumes standard voltage for DDR3(1.35V), DDR4(1.2V),
+ // little endian, if >=128, lab only debug.
+ //
+ // ddr_type(2) ddr3=0, ddr4=1
+ // data/adr(2) data(dq/dqs)=0, adr(cmd/cntl)=1
+ // speed(4) 1066=0, 1333=1, 1600=2, 1866=3
+ // imped(4) 24ohms=0, 30ohms=1, 34ohms=2, 40ohms=3 for DQ/DQS
+ // imped(4) 15ohms=0, 20ohms=1, 30ohms=2, 40ohms=3 for ADR driver
+ // slew(3) 3V/ns=0, 4V/ns=1, 5V/ns=2, 6V/ns=3
+ const uint8_t slew_table[2][2][4][4][4] =
+ {
+// NOTE: bit 7 = unsupported slew, and actual value is in bits 4:0
+
+ /* DDR3(0) */
+ { {
+ // dq/dqs(0)
+ /* Imp. ________24ohms______..________30ohms______..________34ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+ /*1066*/{{ 12, 9, 7, 134}, { 13, 9, 7, 133}, { 13, 10, 7, 134}, { 14, 10, 7, 132}},
+ /*1333*/{{ 15, 11, 8, 135}, { 16, 12, 9, 135}, { 17, 12, 9, 135}, { 17, 12, 8, 133}},
+ /*1600*/{{ 18, 13, 10, 136}, { 19, 14, 10, 136}, { 20, 15, 11, 136}, { 21, 14, 10, 134}},
+ /*1866*/{{149, 143, 140, 138}, {151, 144, 140, 137}, {151, 145, 141, 138}, {152, 145, 139, 135}}
+ }, {
+ // adr(1),
+ /* Imp. ________15ohms______..________20ohms______..________30ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+// 1066 {{ 17, 13, 10, 8}, { 13, 11, 7, 6}, { 12, 8, 5, 131}, { 7, 4, 131, 131}}, // old before May 2013
+ /*1066*/{{ 17, 13, 10, 8}, { 13, 10, 7, 6}, { 12, 8, 5, 131}, { 7, 4, 131, 131}},
+ /*1333*/{{ 21, 16, 12, 10}, { 17, 12, 9, 7}, { 15, 10, 6, 132}, { 6, 5, 132, 132}},
+ /*1600*/{{ 25, 19, 15, 12}, { 20, 14, 13, 8}, { 19, 12, 7, 133}, { 7, 6, 133, 133}},
+ /*1866*/{{157, 150, 145, 142}, {151, 145, 141, 138}, {150, 142, 136, 134}, {141, 134, 134, 134}}
+ }
+ },
+ /* DDR4(1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+ { {
+ // dq/dqs(0)
+ /* Imp. ________24ohms______..________30ohms______..________34ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+ /*1066*/{{138, 135, 134, 133}, {139, 136, 134, 132}, {140, 136, 134, 132}, {140, 136, 132, 132}},
+ /*1333*/{{139, 137, 135, 134}, {142, 138, 135, 133}, {143, 138, 135, 133}, {143, 138, 133, 132}},
+ /*1600*/{{ 15, 11, 9, 135}, { 17, 11, 9, 135}, { 18, 13, 9, 134}, { 18, 11, 6, 133}},
+ /*1866*/{{ 18, 13, 10, 137}, { 19, 13, 10, 136}, { 21, 15, 10, 135}, { 21, 13, 8, 134}}
+ }, {
+ // adr(1)
+ /* Imp. ________15ohms______..________20ohms______..________30ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+ /*1066*/{{142, 139, 136, 134}, {140, 136, 134, 133}, {138, 134, 131, 131}, {133, 131, 131, 131}},
+ /*1333*/{{145, 142, 139, 136}, {143, 138, 135, 134}, {140, 135, 132, 132}, {134, 132, 132, 132}},
+ /*1600*/{{ 21, 16, 13, 10}, { 18, 12, 9, 135}, { 15, 8, 133, 133}, { 7, 133, 133, 133}},
+ /*1866*/{{ 24, 19, 15, 11}, { 21, 14, 10, 136}, { 17, 10, 134, 134}, { 9, 134, 134, 134}}
+ }
+ }
+ };
+
+ // slew calibration control register
+ const uint64_t slew_cal_cntl[] =
+ {
+ CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0, // port 0
+ CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P1_ADR32S0 // port 1
+ };
+ // slew calibration status registers
+ const uint64_t slew_cal_stat[] =
+ {
+ CEN_MBA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0_RO,
+ CEN_MBA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P1_ADR32S0_RO
+ };
+ const uint8_t ENABLE_BIT = 48;
+ const uint8_t START_BIT = 49;
+ const uint8_t BB_LOCK_BIT = 56;
+ // general purpose 100 ns delay for HW mode (2000 sim cycles if simclk = 20ghz)
+ const uint16_t DELAY_100NS = 100;
+ const uint16_t DELAY_2000NCLKS = 4000; // roughly 2000 nclks if DDR freq >= 1066
+ // normally 2000, but since cal doesn't work in SIM, setting to 1
+ const uint16_t DELAY_SIMCYCLES = 1;
+ const uint8_t MAX_POLL_LOOPS = 20;
+
+ uint8_t cal_slew;
+ uint8_t slew_imp_val [MAX_NUM_SLEW_TYPES][2][MAX_PORTS_PER_MBA] = {{{0}}};
+ enum
+ {
+ SLEW = 0,
+ IMP = 1,
+ };
+ // verify which ports are functional
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR,
+ i_target_mba, ports_valid), "Failed to get attribute:ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR");
+
+ // Check if in SIM
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), is_sim),
+ "Failed to get attribute: ATTR_IS_SIMULATION");
+ // Get DDR type (DDR3 or DDR4)
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_DRAM_GEN, i_target_mba, ddr_type),
+ "Failed to get attribute: ATTR_CEN_EFF_DRAM_GEN");
+
+ // ddr_type(2) ddr3=0, ddr4=1
+ if (ddr_type == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR4) //type=2
+ {
+ ddr_idx = 1;
+ }
+ else if (ddr_type == fapi2::ENUM_ATTR_CEN_EFF_DRAM_GEN_DDR3) //type=1
+ {
+ ddr_idx = 0;
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_SLEW_CAL_INVALID_DRAM_GEN().
+ set_DRAM_GEN(ddr_type),
+ "Invalid ATTR_CEN_DRAM_DRAM_GEN = %d, %s!",
+ ddr_type,
+ mss::c_str(i_target_mba));
+ }
+
+ // get freq from parent
+ l_target_centaur = i_target_mba.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>();
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_MSS_FREQ, l_target_centaur, ddr_freq));
+
+ if (ddr_freq == 0)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_SLEW_CAL_INVALID_FREQ(),
+ "Invalid ATTR_CEN_MSS_FREQ = %d on %s!",
+ ddr_freq,
+ mss::c_str(i_target_mba));
+ }
+
+ // speed(4) 1066=0, 1333=1, 1600=2, 1866=3
+ if (ddr_freq > 1732)
+ {
+ freq_idx = 3; // for 1866+
+ }
+ else if ((ddr_freq > 1460) && (ddr_freq <= 1732))
+ {
+ freq_idx = 2; // for 1600
+ }
+ else if ((ddr_freq > 1200) && (ddr_freq <= 1460))
+ {
+ freq_idx = 1; // for 1333
+ }
+ else // (ddr_freq <= 1200)
+ {
+ freq_idx = 0; // for 1066-
+ }
+
+ for (uint8_t l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ uint8_t port_val = (ports_valid & (0xF0 >> (4 * l_port)));
+
+ if (port_val == 0)
+ {
+ FAPI_INF("WARNING: port %u is invalid from "
+ "ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR (0x%02x), skipping.",
+ l_port, ports_valid);
+ continue;
+ }
+
+ // Step A: Configure ADR registers and MCLK detect (done in ddr_phy_reset)
+ // CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0 + port
+ FAPI_TRY(fapi2::getScom(i_target_mba, slew_cal_cntl[l_port], ctl_reg),
+ "Error reading DDRPHY_ADR_SLEW_CAL_CNTL register.");
+ ctl_reg.flush<0>();
+ FAPI_TRY(ctl_reg.setBit(ENABLE_BIT), "Error setting enable bit in ADR Slew calibration "
+ "control register."); // set enable (bit49) to 1
+
+ FAPI_INF("Enabling slew calibration engine on port %i: DDR%i(%u) "
+ "%u(%u) in %s", l_port, (ddr_type + 2), ddr_idx, ddr_freq,
+ freq_idx, mss::c_str(i_target_mba));
+
+ // CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0 + port
+ FAPI_TRY(fapi2::putScom(i_target_mba, slew_cal_cntl[l_port], ctl_reg), "Error enabling slew calibration engine in "
+ "DDRPHY_ADR_SLEW_CAL_CNTL register.");
+ // Note: must be 2000 nclks+ after setting enable bit
+ FAPI_TRY(fapi2::delay(DELAY_2000NCLKS, 1), "Error executing fapi2::delay of 2000 nclks or 1 simcycle");
+
+ //---------------------------------------------------------------------/
+ // Step 1. Check for BB lock.
+ FAPI_DBG("Wait for BB lock in status register, bit %u", BB_LOCK_BIT);
+
+ for (poll_count = 0; poll_count < MAX_POLL_LOOPS; poll_count++)
+ {
+ FAPI_TRY(fapi2::delay(DELAY_100NS, DELAY_SIMCYCLES), "Error executing fapi2::delay of 100ns or 2000simcycles");
+ // CEN_MBA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0_RO + port
+ FAPI_TRY(fapi2::getScom(i_target_mba, slew_cal_stat[l_port], stat_reg),
+ "Error reading DDRPHY_ADR_SYSCLK_PR_VALUE_RO register "
+ "for BB_Lock.");
+// FAPI_DBG("stat_reg = 0x%04x, count=%i",stat_reg.getHalfWord(3),
+// poll_count);
+
+ if (stat_reg.getBit(BB_LOCK_BIT))
+ {
+ break;
+ }
+ }
+
+ if (poll_count == MAX_POLL_LOOPS)
+ {
+ FAPI_INF("WARNING: Timeout on polling BB_Lock, continuing...");
+ }
+ else
+ {
+ FAPI_DBG("polling finished in %i loops (%u ns)\n",
+ poll_count, (100 * poll_count));
+ }
+
+ //---------------------------------------------------------------------/
+ // Create calibrated slew settings
+ // dq/adr(2) dq/dqs=0, adr=1
+ // slew(4) 3V/ns=0, 4V/ns=1, 5V/ns=2, 6V/ns=3
+ for (uint8_t data_adr = 0; data_adr < 2; data_adr++)
+ {
+ FAPI_INF("Starting %s(%i) slew calibration...",
+ (data_adr ? "ADR" : "DATA"), data_adr);
+
+ for (uint8_t imp = 0; imp < MAX_NUM_IMP; imp++)
+ {
+
+ for (uint8_t slew = 0; slew < MAX_NUM_CAL_SLEW_RATES; slew++)
+ {
+ cal_slew =
+ slew_table[ddr_idx][data_adr][freq_idx][imp][slew];
+
+ // set slew phase rotator from slew_table
+ // slew_table[ddr3/4][dq/adr][freq][impedance][slew_rate]
+ FAPI_TRY(ctl_reg.insertFromRight(cal_slew, 59, 5), "Error setting start bit or cal input value.");
+
+ FAPI_TRY(ctl_reg.setBit(START_BIT), "Error setting start bit or cal input value."); // set start bit(48)
+
+ /* FAPI_DBG("Slew data_adr=%i, imp_idx=%i, slewrate=%i, "
+ "i_slew=%i,0x%02X (59:63) cntl_reg(48:63)=0x%04X",
+ data_adr, imp, (slew+3), cal_slew, cal_slew,
+ ctl_reg.getHalfWord(3)); */
+
+ // CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0 + port
+ FAPI_TRY(fapi2::putScom(i_target_mba, slew_cal_cntl[l_port], ctl_reg), "Error starting slew calibration.");
+
+ // poll for calibration status done or timeout...
+ for (poll_count = 0; poll_count < MAX_POLL_LOOPS;
+ poll_count++)
+ {
+ // CEN_MBA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0_RO + port
+ FAPI_TRY(fapi2::getScom(i_target_mba, slew_cal_stat[l_port],
+ stat_reg), "Error reading "
+ "DDRPHY_ADR_SYSCLK_PR_VALUE_RO "
+ "register for calibration status.");
+ FAPI_TRY(stat_reg.extractToRight(cal_status, 58, 2), "Error getting calibration status bits");
+
+ if (cal_status != 0)
+ {
+ break;
+ }
+
+ // wait (1020 mclks / MAX_POLL_LOOPS)
+ FAPI_TRY(fapi2::delay(DELAY_100NS, DELAY_SIMCYCLES));
+ }
+
+ if (cal_status > 1)
+ {
+ if (cal_status == 3)
+ {
+ FAPI_DBG("slew calibration completed successfully,"
+ " loop=%i input=0x%02x", poll_count,
+ (cal_slew & 0x1F));
+ }
+ else if (cal_status == 2)
+ {
+ /* FAPI_INF("WARNING: occurred during slew calibration"
+ ", imped=%i, slewrate=%i %s ddr_idx[%i]",
+ data_adr ? adr_imp_array[imp] :
+ drv_imp_array[(4-imp)], (slew+3),
+ i_target_mba.toEcmdString(), ddr_idx);
+ FAPI_INF("data_adr[%i], freq_idx[%i], imp[%i], slew[%i]",
+ data_adr, freq_idx, imp, slew);
+ FAPI_INF("input=0x%02X, ctrl=0x%04X, status=0x%04X",
+ (cal_slew & 0x1F), ctl_reg.getHalfWord(3),
+ stat_reg.getHalfWord(3)); */
+ }
+
+ cal_slew = cal_slew & 0x80; // clear bits 6:0
+ stat_reg.extract<60, 4, 4>(cal_slew);
+ FAPI_DBG("MSS_SLEW_RATE_%s port[%i]imp[%i]slew[%i] = "
+ "0x%02x\n", (data_adr ? "ADR" : "DATA"), l_port,
+ imp, slew, (cal_slew & 0xF));
+ calibrated_slew[data_adr][l_port][imp][slew] = cal_slew;
+ }
+ else
+ {
+ if (is_sim)
+ {
+ // Calibration fails in sim since bb_lock not
+ // possible in cycle simulator, putting initial
+ // to be cal'd value in output table
+ FAPI_INF("In SIM setting input slew value in array"
+ ", status(%i) NOT clean.", cal_status);
+ calibrated_slew[data_adr][l_port][imp][slew] =
+ cal_slew;
+ }
+ else
+ {
+ FAPI_ERR("Slew calibration failed on %s slew: "
+ "imp_idx=%d(%i ohms)",
+ (data_adr ? "ADR" : "DATA"), imp,
+ (data_adr ? adr_imp_array[imp] :
+ drv_imp_array[(4 - imp)]));
+ // FAPI_ERR("slew_idx=%d(%i V/ns), slew_table=0x%02X",
+ // slew, (slew+3), cal_slew);
+ //FAPI_ERR("ctl_reg=0x%04X, status=0x%04X on %s!",
+ // stat_reg.getHalfWord(3),
+ // ctl_reg.getHalfWord(3),
+ // i_target_mba.toEcmdString());
+
+ if (cal_status == 1)
+ {
+ if (l_port == 0)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_SLEW_CAL_ERROR_PORT0().
+ set_DATA_ADR(data_adr).
+ set_IMP(imp).
+ set_SLEW(slew).
+ set_MBA_IN_ERROR(i_target_mba).
+ set_STAT_REG(stat_reg),
+ "Error occurred during slew calibration on port 0");
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_SLEW_CAL_ERROR_PORT1().
+ set_DATA_ADR(data_adr).
+ set_IMP(imp).
+ set_SLEW(slew).
+ set_MBA_IN_ERROR(i_target_mba).
+ set_STAT_REG(stat_reg),
+ "Error occurred during slew calibration on port 1");
+ }
+ }
+ else
+ {
+ if (l_port == 0)
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_SLEW_CAL_TIMEOUT_PORT0().
+ set_DATA_ADR(data_adr).
+ set_IMP(imp).
+ set_SLEW(slew).
+ set_MBA_IN_ERROR(i_target_mba).
+ set_STAT_REG(stat_reg),
+ "Slew calibration timed out on port 0, loop=%i", poll_count);
+ }
+ else
+ {
+ FAPI_ASSERT(false,
+ fapi2::CEN_MSS_SLEW_CAL_TIMEOUT_PORT1().
+ set_DATA_ADR(data_adr).
+ set_IMP(imp).
+ set_SLEW(slew).
+ set_MBA_IN_ERROR(i_target_mba).
+ set_STAT_REG(stat_reg),
+ "Slew calibration timed out on port 1, loop=%i",
+ poll_count);
+ }
+ }
+
+ array_rcs[l_port] = rc;
+ continue;
+ }
+ } // end error check
+ } // end slew
+ } // end imp
+ } // end data_adr
+
+ // disable calibration engine for port
+ ctl_reg.clearBit(ENABLE_BIT);
+ FAPI_TRY(fapi2::putScom(i_target_mba, slew_cal_cntl[l_port], ctl_reg), "Error disabling slew calibration engine in "
+ "DDRPHY_ADR_SLEW_CAL_CNTL register.");
+ FAPI_INF("Finished slew calibration on port %i: "
+ "disabling cal engine\n", l_port);
+ } // end port loop
+
+ for (uint8_t rn = 0; rn < MAX_PORTS_PER_MBA; rn++)
+ {
+ if (array_rcs[rn] != fapi2::FAPI2_RC_SUCCESS)
+ {
+ FAPI_ERR("Returning ERROR RC for port %u", rn);
+ return array_rcs[rn];
+ }
+ }
+
+ FAPI_INF("Setting output slew tables ATTR_CEN_MSS_SLEW_RATE_DATA/ADR\n");
+ // ATTR_CEN_MSS_SLEW_RATE_DATA [2][4][4] port, imped, slew_rate
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_SLEW_RATE_DATA, i_target_mba, calibrated_slew[0]),
+ "Failed to set attribute: ATTR_CEN_MSS_SLEW_RATE_DATA");
+ // ATTR_CEN_MSS_SLEW_RATE_ADR [2][4][4] port, imped, slew_rate
+ FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_CEN_MSS_SLEW_RATE_ADR, i_target_mba, calibrated_slew[1]),
+ "Failed to set attribute: ATTR_CEN_MSS_SLEW_RATE_ADR");
+
+ /******************************************************************************/
+
+ // Get desired dq/dqs slew rate & impedance from attribute
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS, i_target_mba,
+ slew_imp_val[SLEW_TYPE_DATA][SLEW]), "Failed to get attribute: ATTR_CEN_EFF_CEN_SLEW_RATE_DQ_DQS");
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS, i_target_mba,
+ slew_imp_val[SLEW_TYPE_DATA][IMP]), "Failed to get attribute: ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS");
+
+ // convert enum value to actual ohms.
+ for (uint8_t j = 0; j < MAX_PORTS_PER_MBA; j++)
+ {
+// FAPI_INF("DQ_DQS IMP Attribute[%i] = %u", j,
+// slew_imp_val[SLEW_TYPE_DATA][IMP][j]);
+
+ switch (slew_imp_val[SLEW_TYPE_DATA][IMP][j])
+ {
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM24_FFE0:
+ slew_imp_val[SLEW_TYPE_DATA][IMP][j] = 24;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE0:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE480:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE240:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE160:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE120:
+ slew_imp_val[SLEW_TYPE_DATA][IMP][j] = 30;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE0:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE480:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE240:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE160:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE120:
+ slew_imp_val[SLEW_TYPE_DATA][IMP][j] = 34;
+ break;
+
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE0:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE480:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE240:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE160:
+ case fapi2::ENUM_ATTR_CEN_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE120:
+ slew_imp_val[SLEW_TYPE_DATA][IMP][j] = 40;
+ break;
+
+ default:
+ FAPI_INF("WARNING: EFF_CEN_DRV_IMP_DQ_DQS attribute "
+ "invalid, using value of 0");
+ }
+
+// FAPI_DBG("switched imp to value of %u",
+// slew_imp_val[SLEW_TYPE_DATA][IMP][j]);
+ }
+
+ // Get desired ADR control slew rate & impedance from attribute
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_SLEW_RATE_CNTL, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_CNTL][SLEW]), "Failed to get attribute: ATTR_CEN_VPD_SLEW_RATE_CNTL");
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRV_IMP_CNTL, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_CNTL][IMP]), "Failed to get attribute: ATTR_CEN_VPD_DRV_IMP_CNTL");
+ // Get desired ADR command slew rate & impedance from attribute
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_SLEW_RATE_ADDR, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_ADDR][SLEW]), "Failed to get attribute: ATTR_CEN_VPD_SLEW_RATE_ADDR");
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRV_IMP_ADDR, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_ADDR][IMP]), "Failed to get attribute: ATTR_CEN_VPD_DRV_IMP_ADDR");
+ // Get desired ADR clock slew rate & impedance from attribute
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_SLEW_RATE_CLK, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_CLK][SLEW]), "Failed to get attribute: ATTR_CEN_VPD_SLEW_RATE_CLK");
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRV_IMP_CLK, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_CLK][IMP]), "Failed to get attribute: ATTR_CEN_VPD_DRV_IMP_CLK");
+ // Get desired ADR Spare clock slew rate & impedance from attribute
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_SLEW_RATE_SPCKE, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_SPCKE][SLEW]), "Failed to get attribute: ATTR_CEN_VPD_SLEW_RATE_SPCKE");
+ FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_VPD_DRV_IMP_SPCKE, i_target_mba,
+ slew_imp_val[SLEW_TYPE_ADR_SPCKE][IMP]), "Failed to get attribute: ATTR_CEN_VPD_DRV_IMP_SPCKE");
+
+ for (uint8_t l_port = 0; l_port < MAX_PORTS_PER_MBA; l_port++)
+ {
+ //uint8_t ports_mask = 0xF0; // bits 0:3 = port0, bits 4:7 = port1
+ uint8_t port_val = (ports_valid & (0xF0 >> (4 * l_port)));
+
+ if (port_val == 0)
+ {
+ FAPI_INF("WARNING: port %u is invalid from "
+ "ATTR_CEN_MSS_EFF_DIMM_FUNCTIONAL_VECTOR, 0x%02x "
+ "skipping configuration of slew rate on this port",
+ l_port, ports_valid);
+ continue;
+ }
+
+ FAPI_INF("Setting slew registers for port %i", l_port);
+
+ for (uint8_t slew_type = 0; slew_type < MAX_NUM_SLEW_TYPES; slew_type++)
+ {
+ fapi2::ReturnCode config_rc =
+ config_slew_rate(i_target_mba, l_port, slew_type,
+ slew_imp_val[slew_type][IMP][l_port],
+ slew_imp_val[slew_type][SLEW][l_port]);
+
+ if (config_rc)
+ {
+ array_rcs[l_port] = config_rc;
+ }
+ }
+ }
+
+ for (uint8_t rn = 0; rn < MAX_PORTS_PER_MBA; rn++)
+ {
+ if (array_rcs[rn] != fapi2::FAPI2_RC_SUCCESS)
+ {
+ FAPI_ERR("Returning ERROR RC for port %u", rn);
+ return array_rcs[rn];
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.H
new file mode 100755
index 000000000..ccebbf44f
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.H
@@ -0,0 +1,402 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file mss_draminit_training_advanced.H
+/// @brief Tools for DDR4 DIMMs centaur procedures
+///
+/// *HWP HWP Owner: Luke Mulkey <lwmulkey@us.ibm.com>
+/// *HWP HWP Backup: SARAVANAN SETHURAMAN <saravanans@in.ibm.com>
+/// *HWP Team: Memory
+/// *HWP Level: 2
+/// *HWP Consumed by: HB:CI
+//
+//
+
+
+#ifndef MSS_TERMINATION_CONTROL_H
+#define MSS_TERMINATION_CONTROL_H
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include <fapi2.H>
+#include <cen_gen_scom_addresses_fld.H>
+#include <cen_gen_scom_addresses.H>
+
+///
+/// @brief termination constants
+///
+enum term_consts : size_t
+{
+ SLEW = 0,
+ IMP = 1,
+ MAX_NUM_IMP = 4, // number of impedances valid per slew type
+ // bypass slew (MAX slew rate) not included since it is not calibrated.
+ MAX_NUM_CAL_SLEW_RATES = 4, // 3V/ns, 4V/ns, 5V/ns, 6V/n
+ MAX_NUM_SLEW_RATES = 4, // 3V/ns, 4V/ns, 5V/ns, 6V/n, MAX?
+ MAX_SLEW_VALUE = 15, // 4 bit value
+ MAX_WR_VREF = 32,
+ MAX_DRV_IMP = 4,
+ MAX_RCV_IMP = 9,
+};
+
+///
+/// @brief Address shmoo is not done as a part of Training advanced, so the order matches attribute enum
+///
+const uint8_t adr_imp_array[] =
+{
+ 15,
+ 20,
+ 30,
+ 40,
+};
+
+///
+/// @brief slew rate values
+///
+const uint8_t slew_rate_array[] =
+{
+ 6,
+ 5,
+ 4,
+ 3,
+};
+
+///
+/// @brief Wr vref values
+///
+const uint32_t wr_vref_array[] =
+{
+ 420,
+ 425,
+ 430,
+ 435,
+ 440,
+ 445,
+ 450,
+ 455,
+ 460,
+ 465,
+ 470,
+ 475,
+ 480,
+ 485,
+ 490,
+ 495,
+ 500,
+ 505,
+ 510,
+ 515,
+ 520,
+ 525,
+ 530,
+ 535,
+ 540,
+ 545,
+ 550,
+ 555,
+ 560,
+ 565,
+ 570,
+ 575
+};
+
+
+//The Array is re-arranged inorder to find the best Eye margin based on the
+//Fitness level - 500 is the best value
+const uint32_t wr_vref_array_fitness[] =
+{
+ 420,
+ 425,
+ 575,
+ 430,
+ 570,
+ 435,
+ 565,
+ 440,
+ 560,
+ 445,
+ 555,
+ 450,
+ 550,
+ 455,
+ 545,
+ 460,
+ 540,
+ 465,
+ 535,
+ 470,
+ 530,
+ 475,
+ 525,
+ 480,
+ 520,
+ 485,
+ 515,
+ 490,
+ 510,
+ 495,
+ 505,
+ 500
+};
+
+const uint8_t MAX_RD_VREF = 16;
+
+///
+/// @brief rd vref values
+///
+const uint32_t rd_cen_vref_array[] =
+{
+ 40375,
+ 41750,
+ 43125,
+ 44500,
+ 45875,
+ 47250,
+ 48625,
+ 50000,
+ 51375,
+ 52750,
+ 54125,
+ 55500,
+ 56875,
+ 58250,
+ 59625,
+ 61000
+};
+
+///
+/// @brief The Array is re-arranged inorder to find the best Eye margin based on the
+/// Fitness level - 50000 is the best value
+///
+const uint32_t rd_cen_vref_array_fitness[] =
+{
+ 61000,
+ 59625,
+ 40375,
+ 58250,
+ 41750,
+ 56875,
+ 43125,
+ 55500,
+ 44500,
+ 54125,
+ 45875,
+ 52750,
+ 47250,
+ 51375,
+ 48625,
+ 50000
+};
+
+///
+/// @brief The Array is re-arranged inorder to find the best Eye margin based on the
+/// Fitness level - 24 is the best value
+///
+const uint8_t drv_imp_array[] =
+{
+ 40,
+ 34,
+ 30,
+ 24
+};
+
+///
+/// @brief The Array is re-arranged inorder to find the best Eye margin based on the
+/// Fitness level - 15 is the best value
+///
+const uint8_t rcv_imp_array[] =
+{
+ 120,
+ 80,
+ 60,
+ 48,
+ 40,
+ 34,
+ 30,
+ 20,
+ 15
+};
+
+///
+/// @brief slew calibration control register
+///
+constexpr uint64_t SLEW_CAL_CNTL[] =
+{
+ CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0, // port 0
+ CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P1_ADR32S0 // port 1
+};
+
+///
+/// @brief slew calibration status registers
+///
+constexpr uint64_t SLEW_CAL_STAT[] =
+{
+ CEN_MBA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0_RO,
+ CEN_MBA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P1_ADR32S0_RO
+};
+
+///
+/// @brief adr enums
+///
+enum adr
+{
+ ADR_SLEW_CAL_CNTL_ADR32S0_ENABLE = CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0_ADR0_ENABLE,
+ ADR_SLEW_CAL_CNTL_ADR32S0_START = CEN_MBA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0_ADR0_START,
+ ADR_SYSCLK_PR_VALUE_RO_BB_LOCK = CEN_MBA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0_ADR0_BB_LOCK,
+};
+
+constexpr uint8_t NUM_DRAM_GENS = 2;
+constexpr uint8_t NUM_PIN_TYPES = 2;
+constexpr uint8_t NUM_SPEEDS = 4;
+constexpr uint8_t NUM_IMPS = 4;
+constexpr uint8_t NUM_SLEWS = 4;
+// DD level 1.0-1.1, Version 1.0
+// [ddr3/4][dq/adr][speed][impedance][slew_rate]
+// note: Assumes standard voltage for DDR3(1.35V), DDR4(1.2V),
+// little endian, if >=128, lab only debug.
+//
+// ddr_type(2) ddr3=0, ddr4=1
+// data/adr(2) data(dq/dqs)=0, adr(cmd/cntl)=1
+// speed(4) 1066=0, 1333=1, 1600=2, 1866=3
+// imped(4) 24ohms=0, 30ohms=1, 34ohms=2, 40ohms=3 for DQ/DQS
+// imped(4) 15ohms=0, 20ohms=1, 30ohms=2, 40ohms=3 for ADR driver
+// slew(3) 3V/ns=0, 4V/ns=1, 5V/ns=2, 6V/ns=3
+constexpr uint8_t SLEW_TABLE[NUM_DRAM_GENS][NUM_PIN_TYPES][NUM_SPEEDS][NUM_IMPS][NUM_SLEWS] =
+{
+ // NOTE: bit 7 = unsupported slew, and actual value is in bits 4:0
+
+ /* DDR3(0) */
+ { {
+ // dq/dqs(0)
+ /* Imp. ________24ohms______..________30ohms______..________34ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+ /*1066*/{{ 12, 9, 7, 134}, { 13, 9, 7, 133}, { 13, 10, 7, 134}, { 14, 10, 7, 132}},
+ /*1333*/{{ 15, 11, 8, 135}, { 16, 12, 9, 135}, { 17, 12, 9, 135}, { 17, 12, 8, 133}},
+ /*1600*/{{ 18, 13, 10, 136}, { 19, 14, 10, 136}, { 20, 15, 11, 136}, { 21, 14, 10, 134}},
+ /*1866*/{{149, 143, 140, 138}, {151, 144, 140, 137}, {151, 145, 141, 138}, {152, 145, 139, 135}}
+ }, {
+ // adr(1),
+ /* Imp. ________15ohms______..________20ohms______..________30ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+ /*1066*/{{ 17, 13, 10, 8}, { 13, 10, 7, 6}, { 12, 8, 5, 131}, { 7, 4, 131, 131}},
+ /*1333*/{{ 21, 16, 12, 10}, { 17, 12, 9, 7}, { 15, 10, 6, 132}, { 6, 5, 132, 132}},
+ /*1600*/{{ 25, 19, 15, 12}, { 20, 14, 13, 8}, { 19, 12, 7, 133}, { 7, 6, 133, 133}},
+ /*1866*/{{157, 150, 145, 142}, {151, 145, 141, 138}, {150, 142, 136, 134}, {141, 134, 134, 134}}
+ }
+ },
+ /* DDR4(1) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
+ { {
+ // dq/dqs(0)
+ /* Imp. ________24ohms______..________30ohms______..________34ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+ /*1066*/{{138, 135, 134, 133}, {139, 136, 134, 132}, {140, 136, 134, 132}, {140, 136, 132, 132}},
+ /*1333*/{{139, 137, 135, 134}, {142, 138, 135, 133}, {143, 138, 135, 133}, {143, 138, 133, 132}},
+ /*1600*/{{ 15, 11, 9, 135}, { 17, 11, 9, 135}, { 18, 13, 9, 134}, { 18, 11, 6, 133}},
+ /*1866*/{{ 18, 13, 10, 137}, { 19, 13, 10, 136}, { 21, 15, 10, 135}, { 21, 13, 8, 134}}
+ }, {
+ // adr(1)
+ /* Imp. ________15ohms______..________20ohms______..________30ohms______..________40ohms______
+ Slew 3 4 5 6 3 4 5 6 3 4 5 6 3 4 5 6 (V/ns) */
+ /*1066*/{{142, 139, 136, 134}, {140, 136, 134, 133}, {138, 134, 131, 131}, {133, 131, 131, 131}},
+ /*1333*/{{145, 142, 139, 136}, {143, 138, 135, 134}, {140, 135, 132, 132}, {134, 132, 132, 132}},
+ /*1600*/{{ 21, 16, 13, 10}, { 18, 12, 9, 135}, { 15, 8, 133, 133}, { 7, 133, 133, 133}},
+ /*1866*/{{ 24, 19, 15, 11}, { 21, 14, 10, 136}, { 17, 10, 134, 134}, { 9, 134, 134, 134}}
+ }
+ }
+};
+
+
+extern "C"
+{
+ ///
+ /// @brief configures PC_VREF_DRV_CONTROL registers to vary the DRAM VREF
+ /// @param[in] i_target_mba Reference to centaur.mba target
+ /// @param[in] i_port MBA Port
+ /// @param[in] i_wr_dram_vref DRAM VREF to set
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode config_wr_dram_vref(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port,
+ const uint32_t i_wr_dram_vref);
+
+ ///
+ /// @brief configures read vref registers to vary the CEN VREF
+ /// @param[in] i_target_mba Reference to centaur.mba target
+ /// @param[in] i_port MBA Port
+ /// @param[in] i_rd_cen_vref CEN VREF to set
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode config_rd_cen_vref(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port,
+ const uint32_t i_rd_cen_vref);
+
+ ///
+ /// @brief configures the Driver impedance values to the registers
+ /// @param[in] i_target_mba Reference to centaur.mba target
+ /// @param[in] i_port MBA Port
+ /// @param[in] i_drv_imp_dq_dqs Driver impedance values
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode config_drv_imp(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port,
+ const uint8_t i_drv_imp_dq_dqs);
+
+ ///
+ /// @brief configures the Receiver impedance values to the registers
+ /// @param[in] i_target_mba Reference to centaur.mba target
+ /// @param[in] i_port MBA Port
+ /// @param[in] i_rcv_imp_dq_dqs Receiver impedance values
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode config_rcv_imp(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port,
+ const uint8_t i_rcv_imp_dq_dqs);
+
+ ///
+ /// @brief configures the Slew rate values to the registers
+ /// @param[in] i_target_mba Reference to centaur.mba target
+ /// @param[in] i_port MBA Port
+ /// @param[in] i_slew_type Slew Type
+ /// @param[in] i_slew_imp Slew Impedance
+ /// @param[in] i_slew_rate Slew Rate
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode config_slew_rate(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba,
+ const uint8_t i_port,
+ const uint8_t i_slew_type,
+ const uint8_t i_slew_imp,
+ const uint8_t i_slew_rate);
+
+ ///
+ /// @brief runs the slew calibration engine
+ /// Configures MSS_SLEW_DATA/ADR attributes and calls config_slew_rate to set
+ /// the slew rate in the registers.
+ /// @param[in] i_target_mba Reference to centaur.mba target
+ /// @return ReturnCode
+ ///
+ fapi2::ReturnCode mss_slew_cal(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target_mba);
+
+} // extern C
+#endif
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.mk b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.mk
new file mode 100755
index 000000000..c696b734d
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.mk
@@ -0,0 +1,31 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/p9c_mss_termination_control.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2016,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+
+# Include the macros and things for MSS procedures
+-include 01common.mk
+
+PROCEDURE=p9c_mss_termination_control
+$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H
index 002c86d1f..bfcb6681a 100755
--- a/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H
+++ b/src/import/chips/centaur/procedures/hwp/memory/p9c_mss_unmask_errors.H
@@ -29,7 +29,7 @@
/// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
/// *HWP Team: Memory
/// *HWP Level: 2
-/// *HWP Consumed by: Memtools
+/// *HWP Consumed by: HB:CI
//
//
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.C b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.C
new file mode 100755
index 000000000..fac099adb
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.C
@@ -0,0 +1,262 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#include <prcdUtils.H>
+#include <croClientCapi.H>
+#include <ecmdClientCapi.H>
+#include <ecmdUtils.H>
+#include <ecmdSharedUtils.H>
+#include <fapi2.H>
+#include <fapi2ClientCapi.H>
+#include <fapi2SharedUtils.H>
+#include <string>
+#include <sstream>
+
+#include <p9c_mss_draminit_training_advanced.H>
+
+// ----------------------------------------------------------------------
+// Function definitions
+// ----------------------------------------------------------------------
+
+// display help message
+void help()
+{
+ // procedure constants
+ const std::string PROCEDURE = "mss_draminit_training_advanced_wrap";
+ const std::string REVISION = "$Revision: 1.1 $";
+ // build help message
+ char outstr[200];
+ snprintf(outstr, sizeof(outstr),
+ "\nThis is the help text for the procedure %s (%s)\n", PROCEDURE.c_str(),
+ REVISION.c_str());
+ ecmdOutput(outstr);
+ snprintf(outstr, sizeof(outstr), "Syntax: %s\n", PROCEDURE.c_str());
+ ecmdOutput(outstr);
+ ecmdOutput(" [-h] [-k#] [-n#] [-s#] [-p#] [-verif]\n");
+ ecmdOutput("\n");
+ ecmdOutput("Additional options:\n");
+ ecmdOutput(" -h This help\n");
+ ecmdOutput("\n");
+}
+
+
+// main function
+int main(int argc, char* argv[])
+{
+ // procedure constants
+ const std::string PROCEDURE = "mss_draminit_training_advanced_wrap";
+ const std::string REVISION = "$Revision: 1.1 $";
+
+ // from prcdUtils
+ extern bool GLOBAL_SIM_MODE;
+ extern bool GLOBAL_VERIF_MODE;
+
+ // flow/control variables
+ uint32_t rc = ECMD_SUCCESS;
+ ecmdDllInfo DLLINFO;
+ ecmdLooperData looper;
+ ecmdChipTarget target;
+ bool valid_pos_found = false;
+ char outstr[200];
+
+ fapi2::ReturnCode rc_fapi(fapi2::FAPI2_RC_SUCCESS);
+
+
+ //-----------------------------------------------------------------------------------------
+ // load and initialize the eCMD Dll
+ // if left NULL, which DLL to load is determined by the ECMD_DLL_FILE environment variable
+ // if set to a specific value, the specified DLL will be loaded
+ //-----------------------------------------------------------------------------------------
+ rc = ecmdLoadDll("");
+
+ if (rc)
+ {
+ return rc;
+ }
+
+ //-----------------------------------------------------------------------------------------
+ // This is needed if you're running a FAPI procedure from this eCMD procedure
+ //-----------------------------------------------------------------------------------------
+
+ // initalize FAPI2 extension
+ rc = fapi2InitExtension();
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing FAPI2 extension!\n");
+ return rc;
+ }
+
+
+
+ // establish if this is a simulation run or not
+ rc = ecmdQueryDllInfo(DLLINFO);
+
+ if (rc)
+ {
+ ecmdUnloadDll();
+ return rc;
+ }
+
+ if (DLLINFO.dllEnv == ECMD_DLL_ENV_SIM)
+ {
+ GLOBAL_SIM_MODE = true;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // Parse out user options (excluding -pX, -cX, -coe, -debug, etc
+ // E.G., ecmdRunHwp.x86 -testmode
+ //-------------------------------------------------------------------------------------------------
+ if (ecmdParseOption(&argc, &argv, "-h"))
+ {
+ help();
+ ecmdUnloadDll();
+ return rc;
+ }
+
+
+ // run procedure in sim verification mode
+ if (ecmdParseOption(&argc, &argv, "-verif"))
+ {
+ GLOBAL_VERIF_MODE = true;
+ }
+
+
+ //-------------------------------------------------------------------------------------------------
+ // Parse out common eCMD args like -p0, -c0, -coe, etc..
+ // Any found args will be removed from arg list upon return
+ //-------------------------------------------------------------------------------------------------
+ rc = ecmdCommandArgs(&argc, &argv);
+
+ if (rc)
+ {
+ ecmdUnloadDll();
+ return rc;
+ }
+
+ // unsupported arguments left over?
+ if (argc != 1)
+ {
+ ecmdOutputError("Unknown/unsupported arguments specified!\n");
+ help();
+ ecmdUnloadDll();
+ return ECMD_INVALID_ARGS;
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // Let's always print the dll info to the screen, unless in quiet mode
+ //-------------------------------------------------------------------------------------------------
+
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ // print informational message
+ snprintf(outstr, sizeof(outstr), "Procedure %s: %s\n", PROCEDURE.c_str(),
+ REVISION.c_str());
+ ecmdOutput(outstr);
+
+ // always print the DLL info to the screen, unless in quiet mode
+ rc = ecmdDisplayDllInfo();
+
+ if (rc)
+ {
+ return rc;
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+ // Loop over all all pu chips
+ //-------------------------------------------------------------------------------------------------
+ target.chipType = "centaur"; // "p9n"; // "pu";
+ target.chipTypeState = ECMD_TARGET_FIELD_VALID;
+ target.chipUnitType = "mba"; // mca; // "mcs"; // "mba"; // "mcbist";
+ target.chipUnitTypeState = ECMD_TARGET_FIELD_VALID;
+ target.cageState = ECMD_TARGET_FIELD_WILDCARD;
+ target.nodeState = ECMD_TARGET_FIELD_WILDCARD;
+ target.slotState = ECMD_TARGET_FIELD_WILDCARD;
+ target.posState = ECMD_TARGET_FIELD_WILDCARD;
+ target.threadState = ECMD_TARGET_FIELD_UNUSED;
+ target.chipUnitNumState = ECMD_TARGET_FIELD_WILDCARD;
+
+ rc = ecmdConfigLooperInit(target, ECMD_SELECTED_TARGETS_LOOP_DEFALL, looper);
+
+ if (rc)
+ {
+ ecmdOutputError("Error initializing proc chip looper!\n");
+ ecmdUnloadDll();
+ return rc;
+ }
+
+ while (ecmdConfigLooperNext(target, looper))
+ {
+ if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE))
+ {
+ snprintf(outstr, sizeof(outstr),
+ "Going to call %s on proc k%d:n%d:s%d:p%02d chip type = %s %s\n",
+ PROCEDURE.c_str(), target.cage, target.node, target.slot, target.pos,
+ target.chipType.c_str(),
+ target.chipUnitType.c_str() );
+ ecmdOutput(outstr);
+ }
+
+ // EXAMPLE setting up a fapi2::Target from an ecmdChipTarget
+ fapi2::Target<fapi2::TARGET_TYPE_MBA> fapi_target(&target);
+
+ // invoke FAPI procedure core
+ FAPI_EXEC_HWP(rc_fapi, p9c_mss_draminit_training_advanced, fapi_target);
+ rc = (uint64_t) rc_fapi;
+
+ if (rc)
+ {
+ snprintf(outstr, sizeof(outstr),
+ "ERROR: %s FAPI call exited with return code = %s 0x%08x \n",
+ PROCEDURE.c_str(), ecmdParseReturnCode(rc).c_str(), rc);
+ ecmdOutputError(outstr);
+ ecmdUnloadDll();
+ return rc;
+ }
+
+ // mark that valid position has been found
+ valid_pos_found = true;
+ }
+
+ // check that a valid target was found
+ if (rc == ECMD_SUCCESS && !valid_pos_found)
+ {
+ ecmdOutputError("No valid targets found!\n");
+ ecmdUnloadDll();
+ return ECMD_TARGET_NOT_CONFIGURED;
+ }
+
+ prcdInfoMessage("----------------------------------------\n");
+ prcdInfoMessage(" mss_draminit_training_advanced is done\n");
+ prcdInfoMessage("----------------------------------------\n");
+
+ //-----------------------------------------------------------------------------------------------
+ // Unload the eCMD Dll, this should always be the last thing you do
+ //-----------------------------------------------------------------------------------------------
+
+ ecmdUnloadDll();
+ return rc;
+}
diff --git a/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.mk b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.mk
new file mode 100755
index 000000000..6eba109ce
--- /dev/null
+++ b/src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.mk
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/import/chips/centaur/procedures/hwp/memory/wrapper/p9c_mss_draminit_training_advanced_wrap.mk $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2017
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+-include 01common.mk
+WRAPPER=p9c_mss_draminit_training_advanced_wrap
+$(WRAPPER)_USELIBS+=p9c_mss_draminit_training_advanced
+$(WRAPPER)_DEPLIBS+=cen
+$(call BUILD_WRAPPER)
OpenPOWER on IntegriCloud