summaryrefslogtreecommitdiffstats
path: root/src/import/generic
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/generic')
-rw-r--r--src/import/generic/memory/lib/ccs/ccs.H1327
-rw-r--r--src/import/generic/memory/lib/ccs/ccs_traits.H (renamed from src/import/generic/memory/lib/utils/mcbist/address.H)28
-rw-r--r--src/import/generic/memory/lib/data_engine/attr_engine_traits.H2805
-rw-r--r--src/import/generic/memory/lib/data_engine/data_engine.H249
-rw-r--r--src/import/generic/memory/lib/data_engine/data_engine_traits_def.H143
-rw-r--r--src/import/generic/memory/lib/data_engine/data_engine_utils.H485
-rw-r--r--src/import/generic/memory/lib/data_engine/p9a/p9a_data_init_traits.H573
-rw-r--r--src/import/generic/memory/lib/data_engine/p9n/p9n_data_init_traits.H488
-rw-r--r--src/import/generic/memory/lib/data_engine/pre_data_init.H324
-rw-r--r--src/import/generic/memory/lib/ecc/ecc.H758
-rw-r--r--src/import/generic/memory/lib/ecc/ecc_traits.H30
-rw-r--r--src/import/generic/memory/lib/ecc/fw_mark_store.H596
-rw-r--r--src/import/generic/memory/lib/ecc/galois.H166
-rw-r--r--src/import/generic/memory/lib/ecc/hw_mark_store.H482
-rw-r--r--src/import/generic/memory/lib/ecc/mainline_aue_trap.H107
-rw-r--r--src/import/generic/memory/lib/ecc/mainline_mpe_trap.H139
-rw-r--r--src/import/generic/memory/lib/ecc/mainline_nce_trap.H172
-rw-r--r--src/import/generic/memory/lib/ecc/mainline_rce_trap.H107
-rw-r--r--src/import/generic/memory/lib/ecc/mainline_ue_trap.H107
-rw-r--r--src/import/generic/memory/lib/ecc/maint_current_trap.H170
-rw-r--r--src/import/generic/memory/lib/ecc/mark_shadow_reg.H126
-rw-r--r--src/import/generic/memory/lib/ecc/mbs_error_vector_trap.H179
-rw-r--r--src/import/generic/memory/lib/ecc/modal_symbol_count.H549
-rw-r--r--src/import/generic/memory/lib/ecc/read_error_count_regs.H625
-rw-r--r--src/import/generic/memory/lib/mss_generic_attribute_getters.H470
-rw-r--r--src/import/generic/memory/lib/prd/hwp_wrappers.H246
-rw-r--r--src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H18
-rw-r--r--src/import/generic/memory/lib/spd/common/dimm_module_decoder.H200
-rw-r--r--src/import/generic/memory/lib/spd/common/spd_decoder_base.H62
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H288
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/ddr4/efd_ddr4_custom_microchip_decoder.H398
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/ddr4/efd_fields_ddr4.H356
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/ddr4/efd_traits_ddr4.H508
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/efd_decoder.H289
-rw-r--r--src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C24
-rw-r--r--src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H10
-rw-r--r--src/import/generic/memory/lib/spd/spd_checker.H5
-rw-r--r--src/import/generic/memory/lib/spd/spd_facade.H289
-rw-r--r--src/import/generic/memory/lib/spd/spd_factory_pattern.H13
-rw-r--r--src/import/generic/memory/lib/spd/spd_fields_ddr4.H183
-rw-r--r--src/import/generic/memory/lib/spd/spd_traits_ddr4.H295
-rw-r--r--src/import/generic/memory/lib/spd/spd_utils.C8
-rw-r--r--src/import/generic/memory/lib/utils/buffer_ops.H28
-rw-r--r--src/import/generic/memory/lib/utils/conversions.H2
-rw-r--r--src/import/generic/memory/lib/utils/count_dimm.H22
-rw-r--r--src/import/generic/memory/lib/utils/dimm/kind.H249
-rw-r--r--src/import/generic/memory/lib/utils/dimm/mss_timing.H912
-rw-r--r--src/import/generic/memory/lib/utils/dump_regs.H31
-rw-r--r--src/import/generic/memory/lib/utils/endian_utils.H36
-rw-r--r--src/import/generic/memory/lib/utils/find.H186
-rw-r--r--src/import/generic/memory/lib/utils/find_magic.H164
-rw-r--r--src/import/generic/memory/lib/utils/fir/gen_mss_unmask.H39
-rw-r--r--src/import/generic/memory/lib/utils/freq/cas_latency.H16
-rw-r--r--src/import/generic/memory/lib/utils/freq/gen_mss_freq.H59
-rw-r--r--src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H52
-rw-r--r--src/import/generic/memory/lib/utils/index.H19
-rw-r--r--src/import/generic/memory/lib/utils/mc/gen_mss_port.H960
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_address.H24
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H3829
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H441
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_ecc_trap_address.H176
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_fwms_address.H175
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.C146
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H103
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H815
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H41
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_memdiags.H1287
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_patterns.C24
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_patterns.H24
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_settings.H24
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/settings.H24
-rw-r--r--src/import/generic/memory/lib/utils/mss_bad_bits.H28
-rw-r--r--src/import/generic/memory/lib/utils/mss_field.H49
-rw-r--r--src/import/generic/memory/lib/utils/mss_generic_check.H25
-rw-r--r--src/import/generic/memory/lib/utils/mss_math.H29
-rw-r--r--src/import/generic/memory/lib/utils/mss_rank.H326
-rw-r--r--src/import/generic/memory/lib/utils/num.H31
-rw-r--r--src/import/generic/memory/lib/utils/power_thermal/gen_decoder.H584
-rw-r--r--src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H1308
-rw-r--r--src/import/generic/memory/lib/utils/power_thermal/gen_throttle_traits.H33
-rw-r--r--src/import/generic/memory/lib/utils/shared/mss_generic_consts.H626
-rw-r--r--src/import/generic/memory/lib/utils/voltage/gen_mss_volt.H4
-rw-r--r--src/import/generic/memory/mss_git_data_helper.H34
-rw-r--r--src/import/generic/procedures/xml/attribute_info/generic_memory_attributes.xml39
-rw-r--r--src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml111
-rw-r--r--src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml157
-rw-r--r--src/import/generic/procedures/xml/attribute_info/generic_memory_si_attributes.xml57
-rw-r--r--src/import/generic/procedures/xml/error_info/generic_error.xml917
88 files changed, 25278 insertions, 3385 deletions
diff --git a/src/import/generic/memory/lib/ccs/ccs.H b/src/import/generic/memory/lib/ccs/ccs.H
new file mode 100644
index 000000000..f97c1f885
--- /dev/null
+++ b/src/import/generic/memory/lib/ccs/ccs.H
@@ -0,0 +1,1327 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/ccs/ccs.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 ccs.H
+/// @brief Run and manage the CCS engine
+///
+// *HWP HWP Owner: Matthew Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_CCS_H_
+#define _MSS_CCS_H_
+
+#include <fapi2.H>
+
+#include <generic/memory/lib/utils/poll.H>
+#include <generic/memory/lib/utils/buffer_ops.H>
+#include <generic/memory/lib/utils/index.H>
+#include <generic/memory/lib/utils/pos.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ccs/ccs_traits.H>
+
+namespace mss
+{
+
+static constexpr uint64_t CKE_HIGH = 0b1111;
+static constexpr uint64_t CKE_LOW = 0b0000;
+
+// CKE setup for rank 0-7 to support
+// Currently only support 0, 1, 4, 5
+// Not supported ranks will always get 0
+// For self_refresh_entry_command()
+static constexpr uint64_t CKE_ARY_SRE[] =
+{
+ // 0, 1, 2, 3,
+ 0b0111, 0b1011, 0, 0,
+ // 4, 5, 6, 7
+ 0b0111, 0b1011, 0, 0
+};
+
+// For self_refresh_exit_command()
+static constexpr uint64_t CKE_ARY_SRX[] =
+{
+ // 0, 1, 2, 3,
+ 0b1000, 0b0100, 0, 0,
+ // 4, 5, 6, 7
+ 0b1000, 0b0100, 0, 0
+};
+
+namespace ccs
+{
+
+enum rank_configuration
+{
+ DUAL_DIRECT = 0,
+ QUAD_ENCODED = 1,
+ // Note: we don't include QUAD_DIRECT in here
+ // That's because it uses 4 CS and is board wiring dependent
+ // Not sure if it would use CS23 or CID01 for CS2/3
+};
+
+///
+/// @class instruction_t
+/// @brief Class for ccs instructions
+/// @tparam T fapi2::TargetType representing the target of the CCS instructions
+/// @note A ccs instruction is data (array 0) and some control information (array 1)cc
+///
+class instruction_t
+{
+ private:
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ public:
+ fapi2::buffer<uint64_t> arr0;
+ fapi2::buffer<uint64_t> arr1;
+ // The MCA indexed rank on which to operate. If this is invalid, all ranks will be disabled
+ uint64_t iv_rank;
+ // We want to have a switch to update rank or not. A user might want to setup CS in some weird way
+ // In that case, they don't want us "fixing" their CS values
+ // We'll default the rank to be updated - we want to send out CS properly
+ bool iv_update_rank;
+
+ ///
+ /// @brief intstruction_t ctor
+ /// @param[in] i_rank the rank this instruction is headed for
+ /// @param[in] i_arr0 the initial value for arr0, defaults to 0
+ /// @param[in] i_arr1 the initial value for arr1, defaults to 0
+ /// @param[in] i_update_rank true if the rank should be updated before being sent, defaults to true
+ ///
+ instruction_t( const uint64_t i_rank = NO_CHIP_SELECT_ACTIVE,
+ const fapi2::buffer<uint64_t> i_arr0 = 0,
+ const fapi2::buffer<uint64_t> i_arr1 = 0,
+ const bool i_update_rank = true):
+ arr0(i_arr0),
+ arr1(i_arr1),
+ iv_rank(i_rank),
+ iv_update_rank(i_update_rank)
+ {
+ // Skip setting up the rank if the user doesn't want us to
+ if(iv_update_rank)
+ {
+ // Set the chip selects to be 1's (not active)
+ // We'll fix these up before executing the instructions
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1,
+ TT::ARR0_DDR_CSN_0_1_LEN>(0b11);
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3,
+ TT::ARR0_DDR_CSN_2_3_LEN>(0b11);
+ }
+ }
+
+ ///
+ /// @brief Updates the rank based upon the passed in rank configuration encoding
+ /// @param[in] i_target the port target for this instruction - for error logging
+ /// @param[in] i_rank_config the rank configuration
+ /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS if ok
+ ///
+ fapi2::ReturnCode configure_rank(const fapi2::Target<TT::PORT_TARGET_TYPE>& i_target,
+ const rank_configuration i_rank_config )
+ {
+ // If this instrunction is set to not update the rank, then don't update the rank
+ if(!iv_update_rank)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // Regardless of rank configurations, if we have NO_CHIP_SELECT_ACTIVE, deactivate all CS
+ if(iv_rank == NO_CHIP_SELECT_ACTIVE)
+ {
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1, TT::ARR0_DDR_CSN_0_1_LEN>(0b11);
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3, TT::ARR0_DDR_CSN_2_3_LEN>(0b11);
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // First, check rank - we need to make sure that we have a valid rank
+ FAPI_ASSERT(iv_rank < TT::CCS_MAX_MRANK_PER_PORT,
+ fapi2::MSS_INVALID_RANK()
+ .set_PORT_TARGET(i_target)
+ .set_RANK(iv_rank)
+ .set_FUNCTION(generic_ffdc_codes::CCS_INST_CONFIGURE_RANK),
+ "%s rank out of bounds rank%u", mss::c_str(i_target), iv_rank);
+
+ // Now the fun happens and we can deal with the actual encoding
+
+ // If we're quad mode, setup the encoding accordingly
+ if(i_rank_config == rank_configuration::QUAD_ENCODED)
+ {
+ // CS 0/1 are first, while CID0/1 are second
+ // In quad enabled mode, CID acts as a "package select"
+ // It selects R0/2 vs R1/3
+ // CS0 vs CS1 selects the low vs high rank in the package
+ // CS0 will select rank 0/1
+ // CS1 will select rank 2/3
+
+ const auto l_dimm_rank = mss::index(iv_rank);
+ const bool l_is_dimm0 = iv_rank < TT::CCS_MAX_RANK_PER_DIMM;
+ constexpr uint64_t NON_DIMM_CS = 0b11;
+
+ // Assigns the CS based upon which DIMM we're at
+ const auto CS01 = l_is_dimm0 ? TT::CS_N[l_dimm_rank].first : NON_DIMM_CS;
+ const auto CS23 = l_is_dimm0 ? NON_DIMM_CS : TT::CS_N[l_dimm_rank].first;
+
+ // Setup that rank
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1,
+ TT::ARR0_DDR_CSN_0_1_LEN>(CS01);
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3,
+ TT::ARR0_DDR_CSN_2_3_LEN>(CS23);
+ arr0.insertFromRight<TT::ARR0_DDR_CID_0_1,
+ TT::ARR0_DDR_CID_0_1_LEN>(TT::CS_N[l_dimm_rank].second);
+ }
+
+ // Otherwise, setup for dual-direct mode (our only other supported mode at the moment)
+ else
+ {
+ const auto l_dimm_rank = mss::index(iv_rank);
+ const bool l_is_dimm0 = iv_rank < TT::CCS_MAX_RANK_PER_DIMM;
+
+ // Assigns the CS based upon which DIMM we're at
+ const auto CS01 = l_is_dimm0 ? TT::CS_ND[l_dimm_rank].first : TT::CS_ND[l_dimm_rank].second;
+ const auto CS23 = l_is_dimm0 ? TT::CS_ND[l_dimm_rank].second : TT::CS_ND[l_dimm_rank].first;
+
+ // Setup that rank
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_0_1,
+ TT::ARR0_DDR_CSN_0_1_LEN>(CS01);
+ arr0.insertFromRight<TT::ARR0_DDR_CSN_2_3,
+ TT::ARR0_DDR_CSN_2_3_LEN>(CS23);
+
+ // Check that we don't have a rank out of bounds case here
+ // We can only have that if
+ // 1) we are DIMM1
+ // 2) our DIMM rank is greater than the maximum allowed number of ranks on DIMM1
+ // So, we pass always if we're DIMM0, or if our DIMM rank is less than the maximum number of DIMM's on rank 1
+ FAPI_ASSERT(l_dimm_rank < TT::CCS_MAX_RANKS_DIMM1 || l_is_dimm0,
+ fapi2::MSS_INVALID_RANK()
+ .set_PORT_TARGET(i_target)
+ .set_RANK(iv_rank)
+ .set_FUNCTION(generic_ffdc_codes::CCS_INST_CONFIGURE_RANK),
+ "%s rank out of bounds rank%u", mss::c_str(i_target), iv_rank);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Equals comparison operator
+ /// @param[in] i_rhs - the instruction to compare to
+ /// @return True if both instructions are equal
+ ///
+ inline bool operator==( const instruction_t& i_rhs ) const
+ {
+ return arr0 == i_rhs.arr0 &&
+ arr1 == i_rhs.arr1 &&
+ iv_rank == i_rhs.iv_rank &&
+ iv_update_rank == i_rhs.iv_update_rank;
+ }
+};
+
+///
+/// @brief Determines our rank configuration type
+/// @param[in] i_target the MCA target on which to operate
+/// @param[out] o_rank_config the rank configuration
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS if ok
+///
+inline fapi2::ReturnCode get_rank_config(const fapi2::Target<DEFAULT_MEM_PORT_TARGET>& i_target,
+ rank_configuration& o_rank_config)
+{
+ typedef ccsTraits<DEFAULT_MC_TYPE> TT;
+ constexpr uint8_t QUAD_RANK_ENABLE = 4;
+ o_rank_config = rank_configuration::DUAL_DIRECT;
+
+ uint8_t l_num_master_ranks[TT::CCS_MAX_DIMM_PER_PORT] = {};
+ FAPI_TRY(TT::get_rank_config_attr(i_target, l_num_master_ranks));
+
+ // We only need to check DIMM0
+ // Our number of ranks should be the same between DIMM's 0/1
+ // Check if we have the right number for encoded mode
+ o_rank_config = l_num_master_ranks[0] == QUAD_RANK_ENABLE ?
+ rank_configuration::QUAD_ENCODED :
+ rank_configuration::DUAL_DIRECT;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Determines our rank configuration type across all ports
+/// @param[in] i_target the MCA target on which to operate
+/// @param[out] o_rank_config the rank configuration
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS if ok
+///
+inline fapi2::ReturnCode get_rank_config(const fapi2::Target<DEFAULT_MC_TARGET>& i_target,
+ std::vector<rank_configuration>& o_rank_config)
+{
+ typedef ccsTraits<DEFAULT_MC_TYPE> TT;
+
+ o_rank_config.clear();
+ // Create one per port, we then use relative indexing to get us the number we need
+ o_rank_config = std::vector<rank_configuration>(TT::PORTS_PER_MC_TARGET);
+
+ for(const auto& l_port : mss::find_targets<DEFAULT_MEM_PORT_TARGET>(i_target))
+ {
+ rank_configuration l_config;
+ FAPI_TRY(get_rank_config(l_port, l_config));
+ o_rank_config[mss::relative_pos<DEFAULT_MC_TARGET>(l_port)] = l_config;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief A class representing a series of CCS instructions, and the
+/// CCS engine parameters associated with running the instructions
+/// @tparam T fapi2::TargetType representing the fapi2 target which
+/// @tparam P fapi2::TargetType representing the port
+/// contains the CCS engine
+class program
+{
+ private:
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ public:
+ // Setup our poll parameters so the CCS executer can see
+ // whether to use the delays in the instruction stream or not
+ program(): iv_poll(0, 0)
+ {}
+
+ // Vector of instructions
+ std::vector< instruction_t > iv_instructions;
+ poll_parameters iv_poll;
+
+ // Vector of polling probes
+ std::vector< poll_probe<TT::PORT_TARGET_TYPE> > iv_probes;
+};
+
+///
+/// @brief Common setup for all MRS/RCD instructions
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in,out] i_arr0 fapi2::buffer<uint64_t> representing the ARR0 of the instruction
+///
+static void mrs_rcd_helper( fapi2::buffer<uint64_t>& i_arr0 )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ //
+ // Generic DDR4 MRS setup (RCD is an MRS)
+ //
+ // CKE is high Note: P8 set all 4 of these high - not sure if that's correct. BRS
+ i_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+
+ // ACT is high
+ i_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS, CAS, WE low
+ i_arr0.clearBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_14>();
+}
+
+///
+/// @brief Setup activate command instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the DIMM this instruction is headed for
+/// @param[in] i_rank the rank on this dimm
+///
+inline instruction_t act_command( const uint64_t i_rank )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ // Set all CKE to high
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+
+ // ACT is high
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS low, CAS low, WE low
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_14>();
+
+ // Just leaving the row addresses to all 0 for now
+ // row, bg, ba set to 0
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_ADDRESS_17>();
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_ADDRESS_0_13, TT::ARR0_DDR_ADDRESS_0_13_LEN>();
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_GROUP_1>();
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_GROUP_0>();
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_0_1, TT::ARR0_DDR_BANK_0_1_LEN>();
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_2>();
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Create, initialize an RCD (RCW - JEDEC) CCS command
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the DIMM this instruction is headed for
+/// @param[in] i_turn_on_cke flag that states whether we want CKE on for this RCW (defaulted to true)
+/// @return the RCD CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t rcd_command( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const bool i_sim,
+ const bool i_turn_on_cke = true)
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
+
+ //
+ // Generic DDR4 MRS setup (RCD is an MRS)
+ //
+ mrs_rcd_helper(rcd_boilerplate_arr0);
+
+ // Not adding i_turn_on_cke in the mrs_rcd helper because we only need this
+ // for RCWs and there is no need to complicate/change the MRS cmd API with
+ // uneeded functionality. Little duplication, but this isolates the change.
+ if( !i_sim )
+ {
+ const uint64_t l_cke = i_turn_on_cke ? CKE_HIGH : CKE_LOW;
+ rcd_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(l_cke);
+ }
+
+ //
+ // RCD setup
+ //
+ // DDR4: Set BG1 to 0 during an MRS.
+ // BG0, BA1:BA0 to 0b111 selects RCW (aka MR7).
+ rcd_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_GROUP_1>()
+ .template insertFromRight<TT::ARR0_DDR_BANK_0_1, TT::ARR0_DDR_BANK_0_1_LEN>(0b11)
+ .template setBit<TT::ARR0_DDR_BANK_GROUP_0>();
+
+ // RCD always goes to the 0th rank on the DIMM; either 0 or 4.
+ return instruction_t((mss::index(i_target) == 0) ? 0 : 4, rcd_boilerplate_arr0, rcd_boilerplate_arr1);
+}
+
+///
+/// @brief Create, initialize an MRS CCS command
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the DIMM this instruction is headed for
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_mrs the specific MRS
+/// @return the MRS CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t mrs_command ( const uint64_t i_rank,
+ const uint64_t i_mrs )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
+ fapi2::buffer<uint8_t> mrs(i_mrs);
+
+ //
+ // Generic DDR4 MRS setup (RCD is an MRS)
+ //
+ mrs_rcd_helper(rcd_boilerplate_arr0);
+
+ //
+ // MRS setup
+ //
+ // DDR4: Set BG1 to 0. BG0, BA1:BA0 to i_mrs
+ rcd_boilerplate_arr0.clearBit<TT::ARR0_DDR_BANK_GROUP_1>();
+ mss::swizzle<TT::ARR0_DDR_BANK_0_1, 3, 7>(mrs, rcd_boilerplate_arr0);
+ FAPI_DBG("mrs rcd boiler 0x%016lx 0x%llx", uint8_t(mrs), uint64_t(rcd_boilerplate_arr0));
+ return instruction_t(i_rank, rcd_boilerplate_arr0, rcd_boilerplate_arr1);
+}
+
+///
+/// @brief Create, initialize a JEDEC Device Deselect CCS command
+/// @param[in] i_idle the idle time to the next command (default to 0)
+/// @return the Device Deselect CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t des_command(const uint16_t i_idle = 0)
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
+
+ // ACT is high. It's a no-care in the spec but it seems to raise questions when
+ // people look at the trace, so lets set it high.
+ rcd_boilerplate_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // CKE is high Note: P8 set all 4 of these high - not sure if that's correct. BRS
+ rcd_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+
+ // Insert idle
+ rcd_boilerplate_arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>( i_idle );
+
+ // ACT is high no-care
+ // RAS, CAS, WE no-care
+
+ // Device Deslect wants CS_n always high (select nothing using rank NO_CHIP_SELECT_ACTIVE)
+ return instruction_t( NO_CHIP_SELECT_ACTIVE,
+ rcd_boilerplate_arr0,
+ rcd_boilerplate_arr1);
+}
+
+///
+/// @brief Converts an ODT attribute to CCS array input
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_attr_value ODT attribute value
+/// @return CCS value for the ODT's
+///
+inline uint8_t convert_odt_attr_to_ccs(const fapi2::buffer<uint8_t>& i_attr_value)
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ // ODT value buffer
+ fapi2::buffer<uint8_t> l_ccs_value;
+ l_ccs_value.template writeBit<TT::CCS_ODT_DIMM0_R0>(i_attr_value.template getBit<TT::ATTR_ODT_DIMM0_R0>())
+ .template writeBit<TT::CCS_ODT_DIMM0_R1>(i_attr_value.template getBit<TT::ATTR_ODT_DIMM0_R1>())
+ .template writeBit<TT::CCS_ODT_DIMM0_R0>(i_attr_value.template getBit<TT::ATTR_ODT_DIMM0_R0>())
+ .template writeBit<TT::CCS_ODT_DIMM1_R0>(i_attr_value.template getBit<TT::ATTR_ODT_DIMM1_R0>())
+ .template writeBit<TT::CCS_ODT_DIMM1_R1>(i_attr_value.template getBit<TT::ATTR_ODT_DIMM1_R1>());
+
+ return uint8_t(l_ccs_value);
+}
+
+///
+/// @brief Create, initialize an ODT CCS command
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_odt_values CCS defined ODT values
+/// @param[in] i_cycles the number of cycles to hold the ODT for - defaults to DEFAULT_ODT_CYCLE_LEN
+/// @return the Device Deselect CCS instruction
+/// @note This technically is not a JEDEC command, but is needed for CCS to hold the ODT cycles
+/// CCS by design does not repeat or latch ODT's appropriately
+/// As such, it's up to the programmers to hold the ODT's appropriately
+/// This "command" will greatly help us do that
+///
+template< typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline instruction_t odt_command(const uint8_t i_odt_values, const uint64_t i_cycles = TT::DEFAULT_ODT_CYCLE_LEN)
+{
+ auto l_odt_cmd = des_command();
+ l_odt_cmd.arr0.template insertFromRight<TT::ARR0_DDR_ODT, TT::ARR0_DDR_ODT_LEN>(i_odt_values);
+ l_odt_cmd.arr1.template insertFromRight<TT::ARR1_REPEAT_CMD_CNT, TT::ARR1_REPEAT_CMD_CNT_LEN>(i_cycles);
+
+ return l_odt_cmd;
+}
+
+
+///
+/// @brief Create, initialize a NTTM read CCS command
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @return the Device Deselect CCS instruction
+/// @note need to setup 4 cycles delay
+///
+inline instruction_t nttm_read_command()
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ // get the des_command
+ auto l_command = des_command();
+ // set to CCS_INST_ARR1 register
+ l_command.arr1.template setBit<TT::NTTM_MODE_FORCE_READ>();
+ l_command.arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>(TT::NTTM_READ_DELAY);
+
+ return l_command;
+}
+
+///
+/// @brief Create, initialize a JEDEC Device Power Down Entry CCS command
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @return the Device Deselect CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t pde_command()
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr0;
+ fapi2::buffer<uint64_t> rcd_boilerplate_arr1;
+
+ // Power Down Entry just like a DES, but we set CKE low
+ instruction_t l_inst = des_command();
+
+ // CKE is low. Note: P8 set all 4 of these low - not sure if that's correct.
+ l_inst.arr0.template insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_LOW);
+
+ l_inst.arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>( TT::TIMING_TCPDED );
+
+ return l_inst;
+}
+
+///
+/// @brief Setup ZQ Long instruction
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_idle the idle time to the next command (default to 0)
+/// @return the MRS CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t zqcl_command( const uint64_t i_rank,
+ const uint16_t i_idle = 0 )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ // CKE is high Note: P8 set all 4 of these high - not sure if that's correct. BRS
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+
+ // ACT is high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS/CAS high, WE low
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template setBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_14>();
+
+ // ADDR10/AP is high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ADDRESS_10>();
+
+ // Insert idle
+ l_boilerplate_arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>( i_idle );
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Setup read command helper function
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_bank_addr bank address bits [BG0:BG1] = [62:63] (right aligned)
+/// @param[in] i_bank_group_addr bank group address bits [BA0:BA1] = [62:63] (right aligned)
+/// @param[in] i_column_addr column address bits [A0:A9] = [54:63] (right aligned)
+/// @return the read command CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+static fapi2::buffer<uint64_t> read_cmd_boilerplate( const uint64_t i_rank,
+ const fapi2::buffer<uint64_t>& i_bank_addr = 0,
+ const fapi2::buffer<uint64_t>& i_bank_group_addr = 0,
+ const fapi2::buffer<uint64_t>& i_column_addr = 0)
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ // TODO - RTC 166175 Encapsulate command truth table in a subclass for ccs.H
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+
+ // CKE is high Note: P8 set all 4 of these high - not sure if that's correct. AAM
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE,
+ TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+
+ // ACT is high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS high, CAS low, WE high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template setBit<TT::ARR0_DDR_ADDRESS_14>();
+
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_BANK_0_1,
+ TT::ARR0_DDR_BANK_0_1_LEN>(i_bank_addr);
+
+ // Bank Group takes a little effort - the bits aren't contiguous
+ constexpr uint64_t BG0_BIT = 62;
+ constexpr uint64_t BG1_BIT = 63;
+
+ l_boilerplate_arr0.writeBit<TT::ARR0_DDR_BANK_GROUP_0>(i_bank_group_addr.getBit<BG0_BIT>())
+ .template writeBit<TT::ARR0_DDR_BANK_GROUP_1>(i_bank_group_addr.getBit<BG1_BIT>());
+
+ // CA is A[0:9]
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_ADDRESS_0_9,
+ TT::ARR0_DDR_ADDRESS_0_9_LEN>(i_column_addr);
+
+ return l_boilerplate_arr0;
+}
+
+///
+/// @brief Setup write command (Fixed BL8 or BC4) instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_bank_addr bank address bits [BA0:BA1] = [62:63] (right aligned)
+/// @param[in] i_bank_group_addr bank group address bits [BG0:BG1] = [62:63] (right aligned)
+/// @param[in] i_column_addr column address bits [A0:A9] = [54:63] (right aligned)
+/// @return the write command CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t wr_command( const uint64_t i_rank,
+ const fapi2::buffer<uint64_t>& i_bank_addr = 0,
+ const fapi2::buffer<uint64_t>& i_bank_group_addr = 0,
+ const fapi2::buffer<uint64_t>& i_column_addr = 0)
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ // WR's and RD's are very similar, so we just use the RD command boiler plate and modify the command to a WR
+ fapi2::buffer<uint64_t> l_boilerplate_arr0 = read_cmd_boilerplate(i_rank,
+ i_bank_addr,
+ i_bank_group_addr,
+ i_column_addr);
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ // RAS high, CAS low, WE low
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_14>();
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Setup read command (Fixed BL8 or BC4) instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_bank_addr bank address bits [BA0:BA1] = [62:63] (right aligned)
+/// @param[in] i_bank_group_addr bank group address bits [BG0:BG1] = [62:63] (right aligned)
+/// @param[in] i_column_addr column address bits [A0:A9] = [54:63] (right aligned)
+/// @return the read command CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t rd_command( const uint64_t i_rank,
+ const fapi2::buffer<uint64_t>& i_bank_addr = 0,
+ const fapi2::buffer<uint64_t>& i_bank_group_addr = 0,
+ const fapi2::buffer<uint64_t>& i_column_addr = 0)
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ l_boilerplate_arr0 = read_cmd_boilerplate(i_rank,
+ i_bank_addr,
+ i_bank_group_addr,
+ i_column_addr);
+
+ // Setup ADDR10/AP based on read type
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_ADDRESS_10>();
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Setup read w/auto precharge command (Fixed BL8 or BC4) instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_bank_addr bank address bits [BG0:BG1] = [62:63] (right aligned)
+/// @param[in] i_bank_group_addr bank group address bits [BA0:BA1] = [62:63] (right aligned)
+/// @param[in] i_column_addr column address bits [A0:A9] = [54:63] (right aligned)
+/// @return the read command CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t rda_command( const uint64_t i_rank,
+ const fapi2::buffer<uint64_t>& i_bank_addr = 0,
+ const fapi2::buffer<uint64_t>& i_bank_group_addr = 0,
+ const fapi2::buffer<uint64_t>& i_column_addr = 0)
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ l_boilerplate_arr0 = read_cmd_boilerplate(i_rank,
+ i_bank_addr,
+ i_bank_group_addr,
+ i_column_addr);
+
+ // Setup ADDR10/AP based on read type
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ADDRESS_10>();
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Setup precharge all banks command instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_idle the idle time to the next command (default to 0)
+/// @return the precharge all banks command CCS instruction
+/// @note THIS IS DDR4 ONLY RIGHT NOW. We can (and possibly should) specialize this
+/// for the controller (Nimbus v Centaur) and then correct for DRAM generation (not included
+/// in this template definition)
+///
+inline instruction_t precharge_all_command( const uint64_t i_rank,
+ const uint16_t i_idle = 0 )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ // CKE is high Note: P8 set all 4 of these high - not sure if that's correct. AAM
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+
+ // ACT is high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS low, CAS high, WE low
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template setBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_14>();
+
+ // Setup ADDR10/AP high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ADDRESS_10>();
+
+ // Insert idle
+ l_boilerplate_arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>( i_idle );
+
+ // From DDR4 Spec table 17:
+ // All other bits from the command truth table or 'V', for valid (1 or 0)
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Setup self-refresh entry command instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_idle the idle time to the next command (default to 0)
+/// @return the self-refresh entry command CCS instruction
+/// @note THIS IS FOR DDR4 NON-LRDIMM ONLY RIGHT NOW
+///
+inline instruction_t self_refresh_entry_command( const uint64_t i_rank, const uint16_t i_idle = 0 )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ // Set all CKE to high except the rank passed in
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_ARY_SRE[i_rank]);
+
+ // ACT is high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS low, CAS low, WE high
+ l_boilerplate_arr0.clearBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template clearBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template setBit<TT::ARR0_DDR_ADDRESS_14>();
+
+ // Insert idle
+ l_boilerplate_arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>( i_idle );
+
+ // From DDR4 Spec table 17:
+ // All other bits from the command truth table are 'V', for valid (1 or 0)
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Setup self-refresh exit using NOP command instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_idle the idle time to the next command (default to 0)
+/// @return the self-refresh exit command CCS instruction
+/// @note Using NOP in case SDRAM is in gear down mode and max power saving mode exit
+/// @note THIS IS FOR DDR4 NON-LRDIMM ONLY RIGHT NOW
+///
+inline instruction_t self_refresh_exit_command( const uint64_t i_rank, const uint16_t i_idle = 0 )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ fapi2::buffer<uint64_t> l_boilerplate_arr0;
+ fapi2::buffer<uint64_t> l_boilerplate_arr1;
+
+ // Set all CKE to low except the rank passed in
+ l_boilerplate_arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_ARY_SRX[i_rank]);
+
+ // ACT is high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ACTN>();
+
+ // RAS high, CAS high, WE high
+ l_boilerplate_arr0.setBit<TT::ARR0_DDR_ADDRESS_16>()
+ .template setBit<TT::ARR0_DDR_ADDRESS_15>()
+ .template setBit<TT::ARR0_DDR_ADDRESS_14>();
+
+ // Insert idle
+ l_boilerplate_arr1.template insertFromRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>( i_idle );
+
+ // From DDR4 Spec table 17:
+ // All other bits from the command truth table are 'V', for valid (1 or 0)
+
+ return instruction_t(i_rank, l_boilerplate_arr0, l_boilerplate_arr1);
+}
+
+///
+/// @brief Setup refresh command instruction
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the DIMM this instruction is headed for
+/// @param[in] i_rank the rank on this dimm
+/// @param[in] i_idle the idle time to the next command (default to 0)
+/// @return the self-refresh entry command CCS instruction
+/// @note THIS IS FOR DDR4 NON-LRDIMM ONLY RIGHT NOW
+///
+inline instruction_t refresh_command( const uint64_t i_rank, const uint16_t i_idle = 0 )
+{
+ using TT = ccsTraits<DEFAULT_MC_TYPE>;
+
+ // Refresh is self-refresh entry with CKE high
+ auto l_refresh_template = self_refresh_entry_command(i_rank, i_idle);
+
+ // CKE is high
+ l_refresh_template.arr0.template insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(CKE_HIGH);
+
+ return l_refresh_template;
+}
+
+//
+// These functions are a little sugar to keep callers from doing the traits-dance to get the
+// appropriate bit field
+//
+
+///
+/// @brief Select the port(s) to be used by the CCS
+/// @tparam MC the memory controller type which executes the CCS instruction
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the target to effect
+/// @param[in] i_ports the buffer representing the ports
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT = ccsTraits<MC> >
+fapi2::ReturnCode select_ports( const fapi2::Target<T>& i_target, uint64_t i_ports);
+
+///
+/// @brief User sets to a '1'b to tell the Hdw to stop CCS whenever failure occurs. When a
+/// '0'b, Hdw will continue CCS even if a failure occurs.
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] the target to effect
+/// @param[in,out] io_buffer the buffer representing the mode register
+/// @param[in] i_value true iff stop whenever failure occurs.
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline void stop_on_err( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& io_buffer, const states i_value)
+{
+ io_buffer.writeBit<TT::STOP_ON_ERR>(i_value);
+}
+
+///
+/// @brief Disable ECC checking on the CCS arrays
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] the target to effect
+/// @param[in,out] io_buffer the buffer representing the mode register
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline void disable_ecc( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& io_buffer)
+{
+ io_buffer.setBit<TT::DISABLE_ECC_ARRAY_CHK>()
+ .template setBit<TT::DISABLE_ECC_ARRAY_CORRECTION>();
+}
+
+///
+/// @brief User sets to a '1'b to force the Hdw to ignore any array ue or sue errors
+/// during CCS command fetching.
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] the target to effect
+/// @param[in,out] io_buffer the buffer representing the mode register
+/// @param[in] i_value true iff ignore any array ue or sue errors.
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline void ue_disable( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& io_buffer, const states i_value)
+{
+ io_buffer.writeBit<TT::UE_DISABLE>(i_value);
+}
+
+///
+/// @brief User sets to a '1'b to force the Hdw to delay parity a cycle
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] the target to effect
+/// @param[in,out] io_buffer the buffer representing the mode register
+/// @param[in] i_value mss::ON iff delay parity a cycle
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline void parity_after_cmd( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& io_buffer, const states i_value)
+{
+ io_buffer.writeBit<TT::CFG_PARITY_AFTER_CMD>(i_value);
+}
+
+///
+/// @brief DDr calibration counter
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] the target to effect
+/// @param[in,out] io_buffer the buffer representing the mode register
+/// @param[in] i_count the count to wait for DDR cal to complete.
+/// @param[in] i_mult the DDR calibration time multiplaction factor
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline void cal_count( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& io_buffer,
+ const uint64_t i_count, const uint64_t i_mult)
+{
+ io_buffer.insertFromRight<TT::DDR_CAL_TIMEOUT_CNT, TT::DDR_CAL_TIMEOUT_CNT_LEN>(i_count);
+ io_buffer.insertFromRight<TT::DDR_CAL_TIMEOUT_CNT_MULT, TT::DDR_CAL_TIMEOUT_CNT_MULT_LEN>(i_mult);
+}
+
+///
+/// @brief Copy CKE signals to CKE Spare on both ports NOTE: DOESN'T APPLY FOR NIMBUS. NO
+/// SPARE CHIPS TO COPY TO. 0 - Spare CKEs not copied with values from CKE(0:1) and
+/// CKE(4:5) 1 - Port A CKE(0:1) copied to Port A CKE(2:3), Port A CKE(4:5) copied
+/// to Port A CKE(6:7), Port B CKE(0:1) copied to Port B CKE(2:3) and Port B CKE(4:5)
+/// copied to Port B CKE(6:7)
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the ccsTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in,out] io_buffer the buffer representing the mode register
+/// @param[in] i_value mss::ON iff Copy CKE signals to CKE Spare on both ports
+/// @note no-op for p9n
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+void copy_cke_to_spare_cke( const fapi2::Target<T>&, fapi2::buffer<uint64_t>& io_buffer, const states i_value);
+
+///
+/// @brief Read the modeq register appropriate for this target
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the target to effect
+/// @param[in,out] io_buffer the buffer representing the mode register
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline fapi2::ReturnCode read_mode( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& io_buffer)
+{
+ return mss::getScom(i_target, TT::MODEQ_REG, io_buffer);
+}
+
+///
+/// @brief Write the modeq register appropriate for this target
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the target to effect
+/// @param[in] i_buffer the buffer representing the mode register
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline fapi2::ReturnCode write_mode( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_buffer)
+{
+ return mss::putScom(i_target, TT::MODEQ_REG, i_buffer);
+}
+
+///
+/// @brief config the NTTM
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_mcbist the target to operate
+/// @param[in] i_nttm_mode NTTM we need to turn on or off (i.e. ON, OFF)
+/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+inline fapi2::ReturnCode configure_nttm( const fapi2::Target<T>& i_target,
+ const mss::states i_nttm_mode)
+{
+ fapi2::buffer<uint64_t> l_data;
+
+ FAPI_TRY(read_mode(i_target, l_data));
+
+ l_data.writeBit<TT::NTTM_MODE>(i_nttm_mode);
+
+ FAPI_TRY(write_mode(i_target, l_data));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Execute a set of CCS instructions - multiple ports
+/// @tparam P the port type for this CCS engine
+/// @tparam MC the MC type on which to operate
+/// @param[in] i_program the vector of instructions
+/// @param[in] i_ports the vector of ports
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType P, mss::mc_type MC>
+fapi2::ReturnCode cleanup_from_execute(const ccs::program& i_program,
+ const std::vector< fapi2::Target<P> >& i_ports);
+
+///
+/// @brief Start or stop the CCS engine
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target The MCBIST containing the CCS engine
+/// @param[in] i_start_stop bool MSS_CCS_START for starting MSS_CCS_STOP otherwise
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+fapi2::ReturnCode start_stop( const fapi2::Target<T>& i_target, const bool i_start_stop )
+{
+ fapi2::buffer<uint64_t> l_buf;
+
+ // Do we need to read this? We are setting the only bit defined in the scomdef? BRS
+ FAPI_TRY(mss::getScom(i_target, TT::CNTLQ_REG, l_buf));
+
+ FAPI_TRY( mss::putScom(i_target, TT::CNTLQ_REG,
+ i_start_stop ? l_buf.setBit<TT::CCS_START>() : l_buf.setBit<TT::CCS_STOP>()) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Determine the CCS failure type
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam P the target of the CCS instruction (the port)
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target MC target
+/// @param[in] i_type the failure type
+/// @param[in] i_port The port the CCS instruction is training
+/// @return ReturnCode associated with the fail.
+/// @note FFDC is handled here, caller doesn't need to do it
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, fapi2::TargetType P = DEFAULT_MEM_PORT_TARGET, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+fapi2::ReturnCode fail_type( const fapi2::Target<T>& i_target,
+ const uint64_t i_type,
+ const fapi2::Target<P>& i_port );
+
+///
+/// @brief Execute a CCS array already loaded in to the engine
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam P the target of the CCS instruction (the port)
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the MCBIST ccs program - to get the polling parameters
+/// @param[in] i_port the port associated with the MCBIST array
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, fapi2::TargetType P, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+fapi2::ReturnCode execute_inst_array(const fapi2::Target<T>& i_target,
+ ccs::program& i_program,
+ const fapi2::Target<P>& i_port)
+{
+ fapi2::buffer<uint64_t> status;
+
+ FAPI_TRY(start_stop(i_target, mss::START), "%s Error in execute_inst_array", mss::c_str(i_port) );
+
+ mss::poll(i_target, TT::STATQ_REG, i_program.iv_poll,
+ [&status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_DBG("ccs statq 0x%016lx, remaining: %d", stat_reg, poll_remaining);
+ status = stat_reg;
+ return status.getBit<TT::CCS_IN_PROGRESS>() != 1;
+ },
+ i_program.iv_probes);
+
+ // Check for done and success. DONE being the only bit set.
+ if (status == TT::STAT_QUERY_SUCCESS)
+ {
+ FAPI_INF("%s CCS Executed Successfully.", mss::c_str(i_port) );
+ goto fapi_try_exit;
+ }
+
+ // So we failed or we're still in progress. Mask off the fail bits
+ // and run this through the FFDC generator.
+ FAPI_TRY(fail_type(i_target, status & TT::STAT_ERR_MASK, i_port), "Error in execute_inst_array" );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Updates the initial delays based upon the total delays passed in
+/// @tparam fapi2::TargetType T the type of the target running CCS
+/// @tparam MC the memory controller type running CCS
+/// @param[in] i_target the target type on which to operate
+/// @param[in] i_delay the calculated delays from CCS
+/// @param[in,out] io_program the program for which to update the delays
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, mss::mc_type MC = DEFAULT_MC_TYPE >
+fapi2::ReturnCode update_initial_delays( const fapi2::Target<T>& i_target,
+ const uint64_t i_delay,
+ ccs::program& io_program);
+
+///
+/// @brief Execute a set of CCS instructions - multiple ports
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam P the port type for this CCS engine
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the vector of instructions
+/// @param[in] i_ports the vector of ports
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, fapi2::TargetType P, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+fapi2::ReturnCode execute( const fapi2::Target<T>& i_target,
+ ccs::program& i_program,
+ const std::vector< fapi2::Target<P> >& i_ports)
+{
+ // Subtract one for the idle we insert at the end
+ constexpr size_t CCS_INSTRUCTION_DEPTH = TT::CCS_ARRAY_LEN - 1;
+ constexpr uint64_t CCS_ARR0_ZERO = TT::CCS_ARR0_START;
+ constexpr uint64_t CCS_ARR1_ZERO = TT::CCS_ARR1_START;
+
+ ccs::instruction_t l_des = ccs::des_command();
+
+ FAPI_INF("loading ccs instructions (%d) for %s", i_program.iv_instructions.size(), mss::c_str(i_target));
+
+ auto l_inst_iter = i_program.iv_instructions.begin();
+
+ std::vector<rank_configuration> l_rank_configs;
+ FAPI_TRY(get_rank_config(i_target, l_rank_configs));
+
+ // Stop the CCS engine just for giggles - it might be running ...
+ FAPI_TRY( start_stop(i_target, mss::states::STOP), "Error in ccs::execute" );
+
+ FAPI_ASSERT( mss::poll(i_target, TT::STATQ_REG, poll_parameters(),
+ [](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_INF("ccs statq (stop) 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ return stat_reg.getBit<TT::CCS_IN_PROGRESS>() != 1;
+ }),
+ TT::setup_trying_to_stop_err(i_target) );
+
+ while (l_inst_iter != i_program.iv_instructions.end())
+ {
+ // Kick off the CCS engine - per port. No broadcast mode for CCS (per Shelton 9/23/15)
+ for (const auto& p : i_ports)
+ {
+ const auto l_port_index = mss::relative_pos<T>(p);
+ size_t l_inst_count = 0;
+
+ uint64_t l_total_delay = 0;
+ uint64_t l_delay = 0;
+ uint64_t l_repeat = 0;
+ uint8_t l_current_cke = 0;
+
+ // Shove the instructions into the CCS engine, in 32 instruction chunks, and execute them
+ for (; l_inst_iter != i_program.iv_instructions.end()
+ && l_inst_count < CCS_INSTRUCTION_DEPTH; ++l_inst_count, ++l_inst_iter)
+ {
+ // First, update the current instruction's chip selects for the current port
+ FAPI_TRY(l_inst_iter->configure_rank(p, l_rank_configs[l_port_index]), "Error in rank config");
+
+ l_inst_iter->arr0.extractToRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(l_current_cke);
+
+ // Make sure this instruction leads to the next. Notice this limits this mechanism to pretty
+ // simple (straight line) CCS programs. Anything with a loop or such will need another mechanism.
+ l_inst_iter->arr1.insertFromRight<TT::ARR1_GOTO_CMD, TT::ARR1_GOTO_CMD_LEN>(l_inst_count + 1);
+ FAPI_TRY( mss::putScom(i_target, CCS_ARR0_ZERO + l_inst_count, l_inst_iter->arr0), "Error in ccs::execute" );
+ FAPI_TRY( mss::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_inst_iter->arr1), "Error in ccs::execute" );
+
+ // arr1 contains a specification of the delay and repeat after this instruction, as well
+ // as a repeat. Total up the delays as we go so we know how long to wait before polling
+ // the CCS engine for completion
+ l_inst_iter->arr1.extractToRight<TT::ARR1_IDLES, TT::ARR1_IDLES_LEN>(l_delay);
+ l_inst_iter->arr1.extractToRight<TT::ARR1_REPEAT_CMD_CNT, TT::ARR1_REPEAT_CMD_CNT_LEN>(l_repeat);
+
+ l_total_delay += l_delay * (l_repeat + 1);
+
+ FAPI_INF("css inst %d: 0x%016lX 0x%016lX (0x%lx, 0x%lx) delay: 0x%x (0x%x) %s",
+ l_inst_count, l_inst_iter->arr0, l_inst_iter->arr1,
+ CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count,
+ l_delay, l_total_delay, mss::c_str(i_target));
+ }
+
+ // Updates the initial delays
+ FAPI_TRY(update_initial_delays(i_target, l_total_delay, i_program), "Error in ccs::execute");
+
+ FAPI_INF("executing ccs instructions (%d:%d, %d) for %s",
+ i_program.iv_instructions.size(), l_inst_count, i_program.iv_poll.iv_initial_delay, mss::c_str(i_target));
+
+ // Deselect
+ l_des.arr0.insertFromRight<TT::ARR0_DDR_CKE, TT::ARR0_DDR_CKE_LEN>(l_current_cke);
+
+ // Insert a DES as our last instruction. DES is idle state anyway and having this
+ // here as an instruction forces the CCS engine to wait the delay specified in
+ // the last instruction in this array (which it otherwise doesn't do.)
+ l_des.arr1.setBit<TT::ARR1_END>();
+ FAPI_TRY( mss::putScom(i_target, CCS_ARR0_ZERO + l_inst_count, l_des.arr0), "Error in ccs::execute" );
+ FAPI_TRY( mss::putScom(i_target, CCS_ARR1_ZERO + l_inst_count, l_des.arr1), "Error in ccs::execute" );
+
+ FAPI_INF("css inst %d fixup: 0x%016lX 0x%016lX (0x%lx, 0x%lx) %s",
+ l_inst_count, l_des.arr0, l_des.arr1,
+ CCS_ARR0_ZERO + l_inst_count, CCS_ARR1_ZERO + l_inst_count, mss::c_str(i_target));
+
+
+ FAPI_INF("executing CCS array for port %d (%s)", l_port_index, mss::c_str(p));
+ FAPI_TRY( select_ports<DEFAULT_MC_TYPE>( i_target, l_port_index), "Error in ccs execute" );
+ FAPI_TRY( execute_inst_array(i_target, i_program, p), "Error in ccs execute" );
+ }
+ }
+
+ // Cleans up after executing the CCS program (runs workarounds if needed)
+ FAPI_TRY((cleanup_from_execute<P, DEFAULT_MC_TYPE>(i_program, i_ports)));
+
+fapi_try_exit:
+ i_program.iv_instructions.clear();
+ return fapi2::current_err;
+}
+
+///
+/// @brief Execute a set of CCS instructions - single port
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam P the target of the CCS instruction (the port)
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the vector of instructions
+/// @param[in] i_port The target that's being programmed by the array
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< fapi2::TargetType T, fapi2::TargetType P, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+fapi2::ReturnCode execute( const fapi2::Target<T>& i_target,
+ ccs::program& i_program,
+ const fapi2::Target<P>& i_port)
+{
+ // Mmm. Might want to find a better way to do this - seems expensive. BRS
+ std::vector< fapi2::Target<P> > l_ports{ i_port };
+ return execute(i_target, i_program, l_ports);
+}
+
+///
+/// @brief Query the status of the CCS engine
+/// @tparam T the target type of the chiplet which executes the CCS instruction
+/// @tparam TT the CCS traits of the chiplet which executes the CCS instruction
+/// @param[in] i_target The MCBIST containing the CCS engine
+/// @param[out] io_status The query result first being the result, second the type
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template< fapi2::TargetType T, typename TT = ccsTraits<DEFAULT_MC_TYPE> >
+fapi2::ReturnCode status_query( const fapi2::Target<T>& i_target, std::pair<uint64_t, uint64_t>& io_status );
+
+} // ends namespace ccs
+} // ends namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/address.H b/src/import/generic/memory/lib/ccs/ccs_traits.H
index af12f7144..5bfcbd064 100644
--- a/src/import/generic/memory/lib/utils/mcbist/address.H
+++ b/src/import/generic/memory/lib/ccs/ccs_traits.H
@@ -1,7 +1,7 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
-/* $Source: src/import/generic/memory/lib/utils/mcbist/address.H $ */
+/* $Source: src/import/generic/memory/lib/ccs/ccs_traits.H $ */
/* */
/* OpenPOWER HostBoot Project */
/* */
@@ -22,3 +22,29 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file ccs_traits.H
+/// @brief Run and manage the CCS engine
+///
+// *HWP HWP Owner: Matthew Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_CCS_TRAITS_H_
+#define _MSS_CCS_TRAITS_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+///
+/// @class ccsTraits
+/// @brief CCS Engine traits and addresses
+/// @tparam MC The memory controller type of the traits
+///
+template< mss::mc_type MC >
+class ccsTraits;
+
+#endif
diff --git a/src/import/generic/memory/lib/data_engine/attr_engine_traits.H b/src/import/generic/memory/lib/data_engine/attr_engine_traits.H
index 1d7388f65..ebcd02c8c 100644
--- a/src/import/generic/memory/lib/data_engine/attr_engine_traits.H
+++ b/src/import/generic/memory/lib/data_engine/attr_engine_traits.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
+/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -37,24 +37,449 @@
#define _MSS_ATTR_ENGINE_TRAITS_H_
#include <fapi2.H>
+#include <generic/memory/lib/spd/spd_facade.H>
#include <generic/memory/lib/data_engine/data_engine_traits_def.H>
+#include <generic/memory/lib/data_engine/data_engine.H>
#include <generic/memory/lib/data_engine/data_engine_utils.H>
#include <generic/memory/lib/mss_generic_attribute_getters.H>
#include <generic/memory/lib/mss_generic_attribute_setters.H>
+#include <generic/memory/lib/mss_generic_system_attribute_getters.H>
#include <generic/memory/lib/spd/ddimm/efd_decoder.H>
-#include <generic/memory/lib/spd/spd_facade.H>
-#include <generic/memory/lib/utils/buffer_ops.H>
+#include <generic/memory/lib/utils/dimm/mss_timing.H>
+#include <generic/memory/lib/spd/spd_utils.H>
namespace mss
{
///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TCCD_L
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TCCD_L >
+{
+ static constexpr const char* TIMING_NAME = "TCCD_L";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_tccd_l;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_tccd_l;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TWTR_L
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWTR_L >
+{
+ static constexpr const char* TIMING_NAME = "tWTR_L";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_twtr_l;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_twtr_l;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TWTR_S
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWTR_S >
+{
+ static constexpr const char* TIMING_NAME = "tWTR_S";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_twtr_s;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_twtr_s;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TFAW
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TFAW >
+{
+ static constexpr const char* TIMING_NAME = "tFAW";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_tfaw;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_tfaw;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TRCD
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRCD >
+{
+ static constexpr const char* TIMING_NAME = "trcd";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trcd;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trcd;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TRP
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRP >
+{
+ static constexpr const char* TIMING_NAME = "tRP";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trp;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trp;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TRAS
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRAS >
+{
+ static constexpr const char* TIMING_NAME = "tRAS";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_tras;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_tras;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TWR
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWR >
+{
+ static constexpr const char* TIMING_NAME = "tWR";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_twr;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_twr;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TRRD_S
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRRD_S >
+{
+ static constexpr const char* TIMING_NAME = "tRRD_S";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trrd_s;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trrd_s;
+};
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @note attr_eff_engine_fields, DRAM_TRRD_L
+///
+template< >
+struct setTimingTraits< attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRRD_L >
+{
+ static constexpr const char* TIMING_NAME = "tRRD_L";
+
+ static constexpr spd_facade_fptr get_timing_in_mtb = &spd::facade::min_trrd_l;
+ static constexpr spd_facade_fptr get_timing_in_ftb = &spd::facade::fine_offset_min_trrd_l;
+};
+
+///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_eff_engine_fields, PRIM_STACK_TYPE specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::PRIM_STACK_TYPE>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_PRIM_STACK_TYPE_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_PRIM_STACK_TYPE_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_PRIM_STACK_TYPE;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_prim_stack_type(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_prim_stack_type(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return i_spd_data.prim_sdram_signal_loading(o_setting);
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_eff_engine_fields, PRIM_DIE_COUNT specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::PRIMARY_DIE_COUNT>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_PRIM_DIE_COUNT_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_PRIM_DIE_COUNT_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_PRIM_DIE_COUNT;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_prim_die_count(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_prim_die_count(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ // =========================================================
+ // Byte 6 maps
+ // Item JC-45-2220.01x
+ // Page 19
+ // DDR4 SPD Document Release 3
+ // Byte 6 (0x006): Primary SDRAM Package Type
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_DIE_COUNT_MAP =
+ {
+ // {key byte, number of die}
+ {0, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D1},
+ {1, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D2},
+ {2, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D3},
+ {3, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D4},
+ {4, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D5},
+ {5, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D6},
+ {6, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D7},
+ {7, fapi2::ENUM_ATTR_MEM_EFF_PRIM_DIE_COUNT_D8}
+ };
+
+ const auto l_dimm = i_spd_data.get_dimm_target();
+
+ attr_integral_type l_decoder_val = 0;
+ FAPI_TRY( i_spd_data.prim_sdram_die_count(l_decoder_val) );
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_dimm, PRIM_DIE_COUNT_MAP, FFDC_CODE, l_decoder_val, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for pre_data_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_eff_engine_fields, DRAM_DENSITY specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_DENSITY>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_DENSITY_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_DENSITY_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_DENSITY;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_density(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_density(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[in] i_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ // =========================================================
+ // DDR4 SPD Document Release 4
+ // Byte 2 (0x002): Key Byte / DRAM Device Type
+ // =========================================================
+ static const std::vector< std::pair<uint8_t, uint8_t> > DRAM_DENSITY_MAP =
+ {
+ // {key byte, capacity in GBs}
+ {4, fapi2::ENUM_ATTR_MEM_EFF_DRAM_DENSITY_4G},
+ {5, fapi2::ENUM_ATTR_MEM_EFF_DRAM_DENSITY_8G},
+ {6, fapi2::ENUM_ATTR_MEM_EFF_DRAM_DENSITY_16G},
+ };
+
+ const auto l_dimm = i_spd_data.get_dimm_target();
+
+ attr_integral_type l_sdram_density = 0;
+ FAPI_TRY( i_spd_data.sdram_density(l_sdram_density),
+ "%s failed to get device type from SPD", spd::c_str(l_dimm) );
+
+ FAPI_TRY( lookup_table_check(l_dimm, DRAM_DENSITY_MAP, FFDC_CODE, l_sdram_density, o_setting),
+ "%s failed DRAM_DENSITY lookup check", spd::c_str(l_dimm) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_engine_derived_fields, BUS_WIDTH specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::PRIM_BUS_WIDTH>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_PRIM_BUS_WIDTH_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_PRIM_BUS_WIDTH_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_PRIM_BUS_WIDTH;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_prim_bus_width(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_prim_bus_width(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ // =========================================================
+ // Byte 13 maps
+ // Item JC-45-2220.01x
+ // Page 27
+ // DDR4 SPD Document Release 3
+ // Byte 13 (0x00D): Module Memory Bus Width
+ // =========================================================
+ const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP =
+ {
+ // {key byte, bus width (in bits)
+ {0, fapi2::ENUM_ATTR_MEM_EFF_PRIM_BUS_WIDTH_8_BITS},
+ {1, fapi2::ENUM_ATTR_MEM_EFF_PRIM_BUS_WIDTH_16_BITS},
+ {2, fapi2::ENUM_ATTR_MEM_EFF_PRIM_BUS_WIDTH_32_BITS},
+ {3, fapi2::ENUM_ATTR_MEM_EFF_PRIM_BUS_WIDTH_64_BITS}
+ // All others reserved
+ };
+
+ const auto l_dimm = i_spd_data.get_dimm_target();
+
+ attr_integral_type l_spd_bus_width = 0;
+ FAPI_TRY( i_spd_data.prim_bus_width(l_spd_bus_width) );
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_dimm, BUS_WIDTH_MAP, FFDC_CODE, l_spd_bus_width, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_eff_engine_fields, DRAM_WIDTH specialization
///
-template<>
-struct attrEngineTraits<attr_eff_engine_fields, DRAM_WIDTH>
+template< proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_WIDTH>
{
using attr_type = fapi2::ATTR_MEM_EFF_DRAM_WIDTH_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -67,8 +492,8 @@ struct attrEngineTraits<attr_eff_engine_fields, DRAM_WIDTH>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_dram_width(i_target, o_setting);
}
@@ -79,8 +504,8 @@ struct attrEngineTraits<attr_eff_engine_fields, DRAM_WIDTH>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_dram_width(i_target, i_setting);
}
@@ -88,13 +513,12 @@ struct attrEngineTraits<attr_eff_engine_fields, DRAM_WIDTH>
///
/// @brief Computes setting for attribute
/// @param[in] i_efd_data EFD data
- /// @param[in] i_setting value we want to set attr with
+ /// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
attr_integral_type& o_setting)
{
-
// =========================================================
// Byte 12 maps
// Item JC-45-2220.01x
@@ -113,11 +537,147 @@ struct attrEngineTraits<attr_eff_engine_fields, DRAM_WIDTH>
};
// Read SPD value
+ const auto l_dimm = i_spd_data.get_dimm_target();
+
attr_integral_type l_value = 0;
FAPI_TRY( i_spd_data.device_width(l_value) );
// Map SPD value to desired setting
- FAPI_TRY(lookup_table_check(i_spd_data.get_dimm_target(), DRAM_WIDTH_MAP, SET_DRAM_WIDTH, l_value, o_setting));
+ FAPI_TRY(lookup_table_check(l_dimm, DRAM_WIDTH_MAP, SET_DRAM_WIDTH, l_value, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_si_engine_fields, COLUMN_ADDR_BITS specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::COLUMN_ADDR_BITS>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_COLUMN_BITS_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_COLUMN_BITS_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_COL_ADDR_BITS;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_column_bits(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_column_bits(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ static const std::vector< std::pair<uint8_t, uint8_t> > DRAM_ADDR_COL_MAP =
+ {
+ {0b001, fapi2::ENUM_ATTR_MEM_EFF_DRAM_COLUMN_BITS_NUM10},
+ };
+
+ const auto l_dimm = i_spd_data.get_dimm_target();
+
+ attr_integral_type l_value = 0;
+ FAPI_TRY(i_spd_data.column_address_bits(l_value))
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_dimm, DRAM_ADDR_COL_MAP, SET_COL_ADDR_BITS, l_value, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_si_engine_fields, ROW_ADDR_BITS specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::ROW_ADDR_BITS>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_ROW_BITS_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_ROW_BITS_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_ROW_ADDR_BITS;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_row_bits(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_row_bits(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ static const std::vector< std::pair<uint8_t, uint8_t> > DRAM_ADDR_ROW_MAP =
+ {
+ {0b010, fapi2::ENUM_ATTR_MEM_EFF_DRAM_ROW_BITS_NUM14},
+ {0b011, fapi2::ENUM_ATTR_MEM_EFF_DRAM_ROW_BITS_NUM15},
+ {0b100, fapi2::ENUM_ATTR_MEM_EFF_DRAM_ROW_BITS_NUM16},
+ {0b101, fapi2::ENUM_ATTR_MEM_EFF_DRAM_ROW_BITS_NUM17},
+ {0b110, fapi2::ENUM_ATTR_MEM_EFF_DRAM_ROW_BITS_NUM18},
+ };
+
+ const auto l_dimm = i_spd_data.get_dimm_target();
+
+ attr_integral_type l_value = 0;
+ FAPI_TRY(i_spd_data.row_address_bits(l_value))
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_dimm, DRAM_ADDR_ROW_MAP, SET_ROW_ADDR_BITS, l_value, o_setting));
fapi_try_exit:
return fapi2::current_err;
@@ -130,19 +690,21 @@ struct attrEngineTraits<attr_eff_engine_fields, DRAM_WIDTH>
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, ATTR_SI_BASE_CASE specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, ATTR_SI_BASE_CASE> {};
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::ATTR_SI_BASE_CASE> {};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_RCV_IMP_DQ_DQS specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_DQ_DQS>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_RCV_IMP_DQ_DQS>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_RCV_IMP_DQ_DQS_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -155,8 +717,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_DQ_DQS>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_rcv_imp_dq_dqs(i_target, o_setting);
}
@@ -167,8 +729,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_DQ_DQS>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_rcv_imp_dq_dqs(i_target, i_setting);
}
@@ -176,23 +738,45 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_DQ_DQS>
///
/// @brief Computes setting for attribute
/// @param[in] i_efd_data EFD data
- /// @param[in] i_setting value we want to set attr with
+ /// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->phy_odt_impedance(o_setting);
+ uint8_t l_odt_impedance = 0;
+
+ static const std::vector< std::pair<uint8_t, uint8_t> > ODT_IMP_MAP =
+ {
+ // {key byte, PHY ODT IMP (ohms)}
+ {0b00000, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_DQ_DQS_DISABLE},
+ {0b00001, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_DQ_DQS_OHM_40},
+ {0b00010, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_DQ_DQS_OHM_60},
+ {0b00011, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_DQ_DQS_OHM_80},
+ {0b00100, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_DQ_DQS_OHM_120},
+ {0b00101, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_DQ_DQS_OHM_240},
+
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ FAPI_TRY(i_efd_data->phy_odt_impedance(l_odt_impedance));
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, ODT_IMP_MAP, mss::SET_SI_MC_RCV_IMP_DQ_DQS, l_odt_impedance, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_UP specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_UP>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_IMP_DQ_DQS_PULL_UP>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -205,8 +789,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_UP>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_imp_dq_dqs_pull_up(i_target, o_setting);
}
@@ -217,8 +801,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_UP>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_imp_dq_dqs_pull_up(i_target, i_setting);
}
@@ -226,23 +810,58 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_UP>
///
/// @brief Computes setting for attribute
/// @param[in] i_efd_data EFD data
- /// @param[in] i_setting value we want to set attr with
+ /// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->phy_drive_impedance_pull_up(o_setting);
+ uint8_t l_phy_drv_imp_pu;
+
+ static const std::vector< std::pair<uint16_t, uint16_t> > PHY_DRV_IMP_PU_MAP =
+ {
+ // {key byte, DRV IMP PU (ohms)}
+ {0b000000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_DISABLE},
+ {0b000001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_28},
+ {0b000010, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_30},
+ {0b000011, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_32},
+ {0b000100, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_34},
+ {0b000101, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_36},
+ {0b000110, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_40},
+ {0b000111, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_43},
+ {0b001000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_48},
+ {0b001001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_53},
+ {0b001010, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_60},
+ {0b001011, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_68},
+ {0b001100, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_80},
+ {0b001101, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_96},
+ {0b001110, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_120},
+ {0b001111, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_160},
+ {0b010000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_240},
+ {0b010001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP_OHM_480},
+
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ FAPI_TRY(i_efd_data->phy_drive_impedance_pull_up(l_phy_drv_imp_pu));
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, PHY_DRV_IMP_PU_MAP, mss::SET_SI_MC_DRV_IMP_DQ_DQS_PULL_UP,
+ static_cast<uint16_t>(l_phy_drv_imp_pu), o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -255,8 +874,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_imp_dq_dqs_pull_down(i_target, o_setting);
}
@@ -267,8 +886,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_imp_dq_dqs_pull_down(i_target, i_setting);
}
@@ -276,24 +895,59 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN>
///
/// @brief Computes setting for attribute
/// @param[in] i_efd_data EFD data
- /// @param[in] i_setting value we want to set attr with
+ /// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->phy_drive_impedance_pull_down(o_setting);
+ uint8_t l_phy_drv_imp_pd = 0;
+
+ static const std::vector< std::pair<uint16_t, uint16_t> > PHY_DRV_IMP_PD_MAP =
+ {
+ // {key byte, DRV IMP PD (ohms)}
+ {0b000000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_DISABLE},
+ {0b000001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_28},
+ {0b000010, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_30},
+ {0b000011, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_32},
+ {0b000100, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_34},
+ {0b000101, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_36},
+ {0b000110, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_40},
+ {0b000111, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_43},
+ {0b001000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_48},
+ {0b001001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_53},
+ {0b001010, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_60},
+ {0b001011, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_68},
+ {0b001100, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_80},
+ {0b001101, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_96},
+ {0b001110, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_120},
+ {0b001111, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_160},
+ {0b010000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_240},
+ {0b010001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN_OHM_480},
+
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ FAPI_TRY(i_efd_data->phy_drive_impedance_pull_down(l_phy_drv_imp_pd));
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, PHY_DRV_IMP_PD_MAP, mss::SET_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN,
+ static_cast<uint16_t>(l_phy_drv_imp_pd), o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_DQ_DQS specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_DQ_DQS>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_SLEW_RATE_DQ_DQS>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_SLEW_RATE_DQ_DQS_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -306,8 +960,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_DQ_DQS>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_slew_rate_dq_dqs(i_target, o_setting);
}
@@ -318,8 +972,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_DQ_DQS>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_slew_rate_dq_dqs(i_target, i_setting);
}
@@ -327,10 +981,10 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_DQ_DQS>
///
/// @brief Computes setting for attribute
/// @param[in] i_efd_data EFD data
- /// @param[in] i_setting value we want to set attr with
+ /// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
return i_efd_data->phy_slew_rate_dq_dqs(o_setting);
@@ -339,11 +993,12 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_DQ_DQS>
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_IMP_CMD_ADDR specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CMD_ADDR>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_IMP_CMD_ADDR>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -356,8 +1011,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CMD_ADDR>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_imp_cmd_addr(i_target, o_setting);
}
@@ -368,8 +1023,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CMD_ADDR>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_imp_cmd_addr(i_target, i_setting);
}
@@ -377,23 +1032,46 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CMD_ADDR>
///
/// @brief Computes setting for attribute
/// @param[in] i_efd_data EFD data
- /// @param[in] i_setting value we want to set attr with
+ /// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->atx_impedance(o_setting);
+ uint8_t l_atx_impedance = 0;
+
+ static const std::vector< std::pair<uint8_t, uint8_t> > ATX_IMP_MAP =
+ {
+ // {key byte, ATX IMP (ohm)}
+ {0b0000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_DISABLE},
+ {0b0001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_OHM_20},
+ {0b0010, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_OHM_24},
+ {0b0011, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_OHM_30},
+ {0b0100, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_OHM_40},
+ {0b0101, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_OHM_60},
+ {0b0110, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CMD_ADDR_OHM_120},
+
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ FAPI_TRY(i_efd_data->atx_impedance(l_atx_impedance));
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, ATX_IMP_MAP, mss::SET_SI_MC_DRV_IMP_CMD_ADDR, l_atx_impedance, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CMD_ADDR specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CMD_ADDR>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_SLEW_RATE_CMD_ADDR>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_SLEW_RATE_CMD_ADDR_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -406,8 +1084,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CMD_ADDR>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_slew_rate_cmd_addr(i_target, o_setting);
}
@@ -418,8 +1096,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CMD_ADDR>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_slew_rate_cmd_addr(i_target, i_setting);
}
@@ -427,10 +1105,10 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CMD_ADDR>
///
/// @brief Computes setting for attribute
/// @param[in] i_efd_data EFD data
- /// @param[in] i_setting value we want to set attr with
+ /// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
return i_efd_data->atx_slew_rate(o_setting);
@@ -439,11 +1117,12 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CMD_ADDR>
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_IMP_CLK specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CLK>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_IMP_CLK>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_IMP_CLK_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -456,8 +1135,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CLK>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_imp_clk(i_target, o_setting);
}
@@ -468,8 +1147,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CLK>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_imp_clk(i_target, i_setting);
}
@@ -480,20 +1159,43 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_IMP_CLK>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->ck_impedance(o_setting);
+ uint8_t l_ck_impedance = 0;
+
+ static const std::vector< std::pair<uint8_t, uint8_t> > CK_IMP_MAP =
+ {
+ // {key byte, CK IMP (ohm)}
+ {0b0000, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CLK_DISABLE},
+ {0b0001, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CLK_OHM_20},
+ {0b0010, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CLK_OHM_24},
+ {0b0011, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CLK_OHM_30},
+ {0b0100, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CLK_OHM_40},
+ {0b0101, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CLK_OHM_60},
+ {0b0110, fapi2::ENUM_ATTR_MEM_SI_MC_DRV_IMP_CLK_OHM_120},
+
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ FAPI_TRY(i_efd_data->ck_impedance(l_ck_impedance));
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, CK_IMP_MAP, mss::SET_SI_MC_DRV_IMP_CLK, l_ck_impedance, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CLK specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CLK>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_SLEW_RATE_CLK>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_SLEW_RATE_CLK_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -506,8 +1208,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CLK>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_slew_rate_clk(i_target, o_setting);
}
@@ -518,8 +1220,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CLK>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_slew_rate_clk(i_target, i_setting);
}
@@ -530,7 +1232,7 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CLK>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
return i_efd_data->ck_slew_rate(o_setting);
@@ -539,11 +1241,12 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_SLEW_RATE_CLK>
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_RCV_IMP_ALERT_N specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_ALERT_N>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_RCV_IMP_ALERT_N>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -556,8 +1259,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_ALERT_N>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_rcv_imp_alert_n(i_target, o_setting);
}
@@ -568,8 +1271,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_ALERT_N>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_rcv_imp_alert_n(i_target, i_setting);
}
@@ -580,20 +1283,43 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_RCV_IMP_ALERT_N>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->alert_odt_impedance(o_setting);
+ uint8_t l_alert_odt_imp = 0;
+
+ static const std::vector< std::pair<uint8_t, uint8_t> > ALERT_ODT_IMP_MAP =
+ {
+ // {key byte, ALERT ODT IMP (ohms)}
+ {0b0000, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_DISABLE},
+ {0b0001, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_OHM_40},
+ {0b0010, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_OHM_48},
+ {0b0011, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_OHM_60},
+ {0b0100, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_OHM_80},
+ {0b0101, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_OHM_120},
+ {0b0110, fapi2::ENUM_ATTR_MEM_SI_MC_RCV_IMP_ALERT_N_OHM_240},
+
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ FAPI_TRY(i_efd_data->alert_odt_impedance(l_alert_odt_imp));
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, ALERT_ODT_IMP_MAP, mss::SET_SI_MC_RCV_IMP_ALERT_N, l_alert_odt_imp, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_DRAM_RTT_NOM specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_NOM>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_DRAM_RTT_NOM>
{
using attr_type = fapi2::ATTR_MEM_SI_DRAM_RTT_NOM_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -606,8 +1332,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_NOM>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_dram_rtt_nom(i_target, o_setting);
}
@@ -618,8 +1344,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_NOM>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_dram_rtt_nom(i_target, i_setting);
}
@@ -630,20 +1356,70 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_NOM>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->dram_rtt_nom(o_setting);
+ uint8_t l_rtt_nom = 0;
+
+ static const std::vector< std::pair<uint8_t, uint8_t> > RTT_NOM_MAP =
+ {
+ {0b0000, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_NOM_DISABLE},
+ {0b0001, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_NOM_OHM34},
+ {0b0010, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_NOM_OHM40},
+ {0b0011, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_NOM_OHM60},
+ {0b0100, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_NOM_OHM80},
+ {0b0101, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_NOM_OHM120},
+ {0b0110, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_NOM_OHM240},
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ switch(i_efd_data->get_rank())
+ {
+ case 0:
+ FAPI_TRY( i_efd_data->dram_rtt_nom_rank0(l_rtt_nom) );
+ break;
+
+ case 1:
+ FAPI_TRY( i_efd_data->dram_rtt_nom_rank1(l_rtt_nom) );
+ break;
+
+ case 2:
+ FAPI_TRY( i_efd_data->dram_rtt_nom_rank2(l_rtt_nom) );
+ break;
+
+ case 3:
+ FAPI_TRY( i_efd_data->dram_rtt_nom_rank3(l_rtt_nom) );
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_SPD_RANK().
+ set_FUNCTION(SET_SI_DRAM_RTT_NOM).
+ set_RANK( i_efd_data->get_rank() ).
+ set_TARGET(l_ocmb),
+ "%s SPD decoder returned invalid rank: %d",
+ spd::c_str(l_ocmb),
+ i_efd_data->get_rank());
+ break;
+ };
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, RTT_NOM_MAP, mss::SET_SI_DRAM_RTT_NOM, l_rtt_nom, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_DRAM_RTT_WR specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_WR>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_DRAM_RTT_WR>
{
using attr_type = fapi2::ATTR_MEM_SI_DRAM_RTT_WR_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -656,8 +1432,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_WR>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_dram_rtt_wr(i_target, o_setting);
}
@@ -668,8 +1444,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_WR>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_dram_rtt_wr(i_target, i_setting);
}
@@ -680,20 +1456,67 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_WR>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->dram_rtt_wr(o_setting);
+ uint8_t l_rtt_wr = 0;
+
+ static const std::vector< std::pair<uint8_t, uint8_t> > RTT_WR_MAP =
+ {
+ {0b0000, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_WR_DISABLE},
+ {0b0001, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_WR_OHM80},
+ {0b0010, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_WR_OHM120},
+ {0b0011, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_WR_OHM240},
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ switch(i_efd_data->get_rank())
+ {
+ case 0:
+ FAPI_TRY( i_efd_data->dram_rtt_wr_rank0(l_rtt_wr) );
+ break;
+
+ case 1:
+ FAPI_TRY( i_efd_data->dram_rtt_wr_rank1(l_rtt_wr) );
+ break;
+
+ case 2:
+ FAPI_TRY( i_efd_data->dram_rtt_wr_rank2(l_rtt_wr) );
+ break;
+
+ case 3:
+ FAPI_TRY( i_efd_data->dram_rtt_wr_rank3(l_rtt_wr) );
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_SPD_RANK().
+ set_FUNCTION(SET_SI_DRAM_RTT_WR).
+ set_RANK( i_efd_data->get_rank() ).
+ set_TARGET(l_ocmb),
+ "%s SPD decoder returned invalid rank: %d",
+ spd::c_str(l_ocmb),
+ i_efd_data->get_rank());
+ break;
+ };
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, RTT_WR_MAP, mss::SET_SI_DRAM_RTT_WR, l_rtt_wr, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_DRAM_RTT_PARK specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_PARK>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_DRAM_RTT_PARK>
{
using attr_type = fapi2::ATTR_MEM_SI_DRAM_RTT_PARK_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -706,8 +1529,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_PARK>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_dram_rtt_park(i_target, o_setting);
}
@@ -718,8 +1541,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_PARK>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_dram_rtt_park(i_target, i_setting);
}
@@ -730,20 +1553,72 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_RTT_PARK>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->dram_rtt_park(o_setting);
+ uint8_t l_rtt_park = 0;
+
+ static const std::vector< std::pair<uint8_t, uint8_t> > RTT_PARK_MAP =
+ {
+ // {key byte, RTT PARK (ohms)}
+ {0b0000, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_DISABLE},
+ {0b0001, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_OHM34},
+ {0b0010, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_OHM40},
+ {0b0011, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_OHM48},
+ {0b0100, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_OHM60},
+ {0b0101, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_OHM80},
+ {0b0110, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_OHM120},
+ {0b0111, fapi2::ENUM_ATTR_MEM_SI_DRAM_RTT_PARK_OHM240},
+ // All others reserved
+ };
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ switch(i_efd_data->get_rank())
+ {
+ case 0:
+ FAPI_TRY( i_efd_data->dram_rtt_park_rank0(l_rtt_park) );
+ break;
+
+ case 1:
+ FAPI_TRY( i_efd_data->dram_rtt_park_rank1(l_rtt_park) );
+ break;
+
+ case 2:
+ FAPI_TRY( i_efd_data->dram_rtt_park_rank2(l_rtt_park) );
+ break;
+
+ case 3:
+ FAPI_TRY( i_efd_data->dram_rtt_park_rank3(l_rtt_park) );
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_SPD_RANK().
+ set_FUNCTION(SET_SI_DRAM_RTT_PARK).
+ set_RANK( i_efd_data->get_rank() ).
+ set_TARGET(l_ocmb),
+ "%s SPD decoder returned invalid rank: %d",
+ spd::c_str(l_ocmb),
+ i_efd_data->get_rank());
+ break;
+ };
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, RTT_PARK_MAP, mss::SET_SI_DRAM_RTT_PARK, l_rtt_park, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_DRAM_PREAMBLE specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_PREAMBLE>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_DRAM_PREAMBLE>
{
using attr_type = fapi2::ATTR_MEM_SI_DRAM_PREAMBLE_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -756,8 +1631,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_PREAMBLE>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_dram_preamble(i_target, o_setting);
}
@@ -768,8 +1643,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_PREAMBLE>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_dram_preamble(i_target, i_setting);
}
@@ -780,7 +1655,7 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_PREAMBLE>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
i_efd_data->write_preamble(o_setting);
@@ -790,11 +1665,12 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_PREAMBLE>
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_MC_DRV_EQ_DQ_DQS specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_EQ_DQ_DQS>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_MC_DRV_EQ_DQ_DQS>
{
using attr_type = fapi2::ATTR_MEM_SI_MC_DRV_EQ_DQ_DQS_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -807,8 +1683,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_EQ_DQ_DQS>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_mc_drv_eq_dq_dqs(i_target, o_setting);
}
@@ -819,8 +1695,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_EQ_DQ_DQS>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_mc_drv_eq_dq_dqs(i_target, i_setting);
}
@@ -831,7 +1707,7 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_EQ_DQ_DQS>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
return i_efd_data->phy_equalization(o_setting);
@@ -840,11 +1716,12 @@ struct attrEngineTraits<attr_si_engine_fields, SI_MC_DRV_EQ_DQ_DQS>
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
/// @note attr_si_engine_fields, SI_DRAM_DRV_IMP_DQ_DQS specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_DRV_IMP_DQ_DQS>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_DRAM_DRV_IMP_DQ_DQS>
{
using attr_type = fapi2::ATTR_MEM_SI_DRAM_DRV_IMP_DQ_DQS_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
@@ -857,8 +1734,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_DRV_IMP_DQ_DQS>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
return mss::attr::get_si_dram_drv_imp_dq_dqs(i_target, o_setting);
}
@@ -869,8 +1746,8 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_DRV_IMP_DQ_DQS>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
return mss::attr::set_si_dram_drv_imp_dq_dqs(i_target, i_setting);
}
@@ -881,25 +1758,134 @@ struct attrEngineTraits<attr_si_engine_fields, SI_DRAM_DRV_IMP_DQ_DQS>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ attr_integral_type& o_setting)
+ {
+ static const std::vector< std::pair<uint8_t, uint8_t> > DRAM_DIC_MAP =
+ {
+ // {key byte, DRAM DIC (ohms)}
+ {0, fapi2::ENUM_ATTR_MEM_SI_DRAM_DRV_IMP_DQ_DQS_DISABLE},
+ {1, fapi2::ENUM_ATTR_MEM_SI_DRAM_DRV_IMP_DQ_DQS_OHM34},
+ {2, fapi2::ENUM_ATTR_MEM_SI_DRAM_DRV_IMP_DQ_DQS_OHM48},
+ };
+
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ attr_integral_type l_dram_dic = 0;
+ FAPI_TRY(i_efd_data->dram_dic(l_dram_dic))
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(l_ocmb, DRAM_DIC_MAP, SET_SI_DRAM_DRV_IMP_DQ_DQS, l_dram_dic, o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_si_engine_fields, SI_ODT_WR specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_ODT_WR>
+{
+ using attr_type = fapi2::ATTR_MEM_SI_ODT_WR_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_ODT_WR_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_ODT_WR;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_si_odt_wr(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_si_odt_wr(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->dram_dic(o_setting);
+ uint8_t l_value = 0;
+
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ switch(i_efd_data->get_rank())
+ {
+ case 0:
+ FAPI_TRY( i_efd_data->odt_wr_map_rank0(l_value) );
+ break;
+
+ case 1:
+ FAPI_TRY( i_efd_data->odt_wr_map_rank1(l_value) );
+ break;
+
+ case 2:
+ FAPI_TRY( i_efd_data->odt_wr_map_rank2(l_value) );
+ break;
+
+ case 3:
+ FAPI_TRY( i_efd_data->odt_wr_map_rank3(l_value) );
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_SPD_RANK().
+ set_FUNCTION(SET_SI_ODT_WR).
+ set_RANK( i_efd_data->get_rank() ).
+ set_TARGET(l_ocmb),
+ "%s SPD decoder returned invalid rank: %d",
+ spd::c_str(l_ocmb),
+ i_efd_data->get_rank());
+ break;
+ };
+
+ // Map to attribute bitmap
+ l_value = mss::gen::align_odt_field_to_attr(l_value);
+
+ o_setting = l_value;
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
-/// @note attr_si_engine_fields, SI_VREF_DQ_TRAIN_RANGE specialization
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_si_engine_fields, SI_ODT_RD specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_VREF_DQ_TRAIN_RANGE>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_ODT_RD>
{
- using attr_type = fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE_Type;
+ using attr_type = fapi2::ATTR_MEM_SI_ODT_RD_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_VREF_DQ_TRAIN_RANGE;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_ODT_RD_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_ODT_RD;
///
/// @brief attribute getter
@@ -907,10 +1893,10 @@ struct attrEngineTraits<attr_si_engine_fields, SI_VREF_DQ_TRAIN_RANGE>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
{
- return mss::attr::get_si_vref_dq_train_range(i_target, o_setting);
+ return mss::attr::get_si_odt_rd(i_target, o_setting);
}
///
@@ -919,10 +1905,10 @@ struct attrEngineTraits<attr_si_engine_fields, SI_VREF_DQ_TRAIN_RANGE>
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
{
- return mss::attr::set_si_vref_dq_train_range(i_target, i_setting);
+ return mss::attr::set_si_odt_rd(i_target, i_setting);
}
///
@@ -934,22 +1920,63 @@ struct attrEngineTraits<attr_si_engine_fields, SI_VREF_DQ_TRAIN_RANGE>
static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->wr_vref_dq_range(o_setting);
+ uint8_t l_value = 0;
+
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ switch(i_efd_data->get_rank())
+ {
+ case 0:
+ FAPI_TRY( i_efd_data->odt_rd_map_rank0(l_value) );
+ break;
+
+ case 1:
+ FAPI_TRY( i_efd_data->odt_rd_map_rank1(l_value) );
+ break;
+
+ case 2:
+ FAPI_TRY( i_efd_data->odt_rd_map_rank2(l_value) );
+ break;
+
+ case 3:
+ FAPI_TRY( i_efd_data->odt_rd_map_rank3(l_value) );
+ break;
+
+ default:
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_SPD_RANK().
+ set_FUNCTION(SET_SI_ODT_RD).
+ set_RANK( i_efd_data->get_rank() ).
+ set_TARGET(l_ocmb),
+ "%s SPD decoder returned invalid rank: %d",
+ spd::c_str(l_ocmb),
+ i_efd_data->get_rank());
+ break;
+ };
+
+ // Map to attribute bitmap
+ l_value = mss::gen::align_odt_field_to_attr(l_value);
+
+ o_setting = l_value;
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
-/// @class attrEngineTraits
-/// @note attr_si_engine_fields, SI_VREF_DQ_TRAIN_VALUE specialization
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_si_engine_fields, SI_GEARDOWN_MODE specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_VREF_DQ_TRAIN_VALUE>
+template< proc_type P >
+struct attrEngineTraits<P, attr_si_engine_fields, attr_si_engine_fields::SI_GEARDOWN_MODE>
{
- using attr_type = fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE_Type;
+ using attr_type = fapi2::ATTR_MEM_SI_GEARDOWN_MODE_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_VREF_DQ_TRAIN_VALUE;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_GEARDOWN_MODE_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_GEARDOWN_MODE;
///
/// @brief attribute getter
@@ -957,49 +1984,364 @@ struct attrEngineTraits<attr_si_engine_fields, SI_VREF_DQ_TRAIN_VALUE>
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_si_geardown_mode(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_si_geardown_mode(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ attr_integral_type& o_setting)
+ {
+ return i_efd_data->geardown_during_training(o_setting);
+ }
+};
+
+//
+// Derived attributes
+//
+///
+
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, MRANKS specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_engine_derived_fields, attr_engine_derived_fields::LOGICAL_RANKS>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_LOGICAL_RANKS;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& o_setting)
{
- return mss::attr::get_si_vref_dq_train_value(i_target, o_setting);
+ return mss::attr::get_logical_ranks_per_dimm(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_logical_ranks_per_dimm(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ attr_integral_type& o_setting)
+ {
+ uint8_t l_prim_stack_type = 0;
+ uint8_t l_master_ranks = 0;
+ uint8_t l_die_count = 0;
+
+ FAPI_TRY( mss::attr::get_num_master_ranks_per_dimm(i_target, l_master_ranks) );
+ FAPI_TRY( mss::attr::get_prim_die_count(i_target, l_die_count) );
+ FAPI_TRY( mss::attr::get_prim_stack_type(i_target, l_prim_stack_type) );
+
+ {
+ // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count.
+ // For MONOLITHIC & MULTI_LOAD_STACK
+ // The die count isn't guaranteed to be 1 (e.g. SDP - 1 die package, DDP - 2 die package).
+ // Value of 1 has no meaning and is used for calculation purposes as defined by the SPD spec.
+ const auto l_multiplier = (l_prim_stack_type == fapi2::ENUM_ATTR_MEM_EFF_PRIM_STACK_TYPE_3DS) ? l_die_count : 1;
+ o_setting = (l_master_ranks * l_multiplier);
+ FAPI_DBG("%s Num Logical Ranks %d", spd::c_str(i_target), o_setting);
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_engine_derived_fields, MEM_DIMM_SIZE specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_engine_derived_fields, attr_engine_derived_fields::MEM_DIMM_SIZE>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DIMM_SIZE_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DIMM_SIZE_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DIMM_SIZE;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dimm_size(i_target, o_setting);
}
///
/// @brief attribute setter
/// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dimm_size(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+
+ static inline fapi2::ReturnCode get_value_to_set(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ attr_integral_type& o_setting)
+ {
+ uint8_t l_dram_width = 0;
+ uint8_t l_dram_density = 0;
+ uint8_t l_logical_rank_per_dimm = 0;
+ uint8_t l_bus_width = 0;
+
+ FAPI_TRY( mss::attr::get_dram_width(i_target, l_dram_width) );
+ FAPI_TRY( mss::attr::get_dram_density(i_target, l_dram_density) );
+ FAPI_TRY( mss::attr::get_logical_ranks_per_dimm(i_target, l_logical_rank_per_dimm) );
+ FAPI_TRY( mss::attr::get_prim_bus_width(i_target, l_bus_width) );
+
+ // Calculate dimm size
+ // Formula from SPD Spec (seriously, they don't have parenthesis in the spec)
+ // Total = SDRAM Capacity / 8 * Primary Bus Width / SDRAM Width * Logical Ranks per DIMM
+ o_setting = (l_dram_density * l_bus_width * l_logical_rank_per_dimm) / (8 * l_dram_width);
+
+ FAPI_DBG("%s DIMM size = %d => (%d * %d * %d) / (8 * %d)",
+ spd::c_str(i_target), o_setting, l_dram_density, l_bus_width, l_logical_rank_per_dimm, l_dram_width);
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attr_engine_derived_fields, HEIGHT_3DS specialization
+///
+template< proc_type P >
+struct attrEngineTraits<P, attr_engine_derived_fields, attr_engine_derived_fields::HEIGHT_3DS>
+{
+ using attr_type = fapi2::ATTR_MEM_3DS_HEIGHT_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_3DS_HEIGHT_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_3DS_HEIGHT;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_3ds_height(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_3ds_height(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ attr_integral_type& o_setting)
+ {
+ uint8_t l_master_ranks_per_dimm = 0;
+ uint8_t l_logical_ranks_per_dimm = 0;
+
+ FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_target, l_master_ranks_per_dimm));
+ FAPI_TRY(mss::attr::get_logical_ranks_per_dimm(i_target, l_logical_ranks_per_dimm));
+ {
+ const uint16_t l_result = l_logical_ranks_per_dimm / l_master_ranks_per_dimm;
+
+ static const std::vector< std::pair<uint16_t, uint16_t> > HEIGHT_3DS_MAP =
+ {
+ // {key byte, 3DS HEIGHT}
+ {1, fapi2::ENUM_ATTR_MEM_3DS_HEIGHT_PLANAR},
+ {2, fapi2::ENUM_ATTR_MEM_3DS_HEIGHT_H2},
+ {4, fapi2::ENUM_ATTR_MEM_3DS_HEIGHT_H4},
+ {8, fapi2::ENUM_ATTR_MEM_3DS_HEIGHT_H8},
+ // All others reserved
+ };
+
+ // Map SPD value to desired setting
+ FAPI_TRY(lookup_table_check(i_target, HEIGHT_3DS_MAP, mss::SET_3DS_HEIGHT, l_result, o_setting));
+ }
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_CWL specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_CWL>
+{
+ using attr_type = fapi2::ATTR_MEM_DRAM_CWL_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_DRAM_CWL_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_CWL;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& o_setting)
{
- return mss::attr::set_si_vref_dq_train_value(i_target, o_setting);
+ return mss::attr::get_dram_cwl(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the fapi2 target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_cwl(i_target, i_setting);
}
///
/// @brief Computes setting for attribute
- /// @param[in] i_efd_data EFD data
+ /// @param[in] i_spd_data SPD data
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->wr_vref_dq_value(o_setting);
+ // Taken from DDR4 JEDEC spec 1716.78C
+ // Proposed DDR4 Full spec update(79-4A)
+ // Page 26, Table 7
+ static const std::vector<std::pair<uint64_t, uint8_t> > CWL_TABLE_1 =
+ {
+ {1866, 10},
+ {2133, 11},
+ {2400, 12},
+ {2666, 14},
+ {2933, 16},
+ {3200, 16},
+ };
+
+ static const std::vector<std::pair<uint64_t, uint8_t> > CWL_TABLE_2 =
+ {
+ // Note that 2tCK write preamble is not valid for 1866 or 2133 speed grades
+ {2400, 14},
+ {2666, 16},
+ {2933, 18},
+ {3200, 18},
+ };
+
+ const auto& l_dimm = i_spd_data.get_dimm_target();
+ // TK This could change but not sure where to get this from
+ constexpr size_t MAX_RANKS_PER_DIMM = 4;
+ uint64_t l_freq = 0;
+ uint8_t l_preambles[MAX_RANKS_PER_DIMM] = {0};
+ fapi2::buffer<uint8_t> l_preamble;
+
+ FAPI_TRY( mss::attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( mss::attr::get_si_dram_preamble(l_dimm, l_preambles) );
+
+ // TK Using the preamble for rank0 for now
+ l_preamble = l_preambles[0];
+
+ if (!l_preamble.getBit<fapi2::ENUM_ATTR_MEM_SI_DRAM_PREAMBLE_WRITE_PREAMBLE_BIT>())
+ {
+ FAPI_TRY(lookup_table_check(l_dimm, CWL_TABLE_1, FFDC_CODE, l_freq, o_setting));
+ }
+ else
+ {
+ FAPI_TRY(lookup_table_check(l_dimm, CWL_TABLE_2, FFDC_CODE, l_freq, o_setting));
+ }
+
+ FAPI_DBG("%s DRAM CWL %d", spd::c_str(l_dimm), o_setting);
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
/// @brief Traits for attr_engine
/// @class attrEngineTraits
-/// @note attr_si_engine_fields, SI_ODT_WR specialization
+/// @note attr_engine_derived_fields, DRAM_MFG_ID specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_ODT_WR>
+template < proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_MFG_ID>
{
- using attr_type = fapi2::ATTR_MEM_SI_ODT_WR_Type;
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_MFG_ID_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_ODT_WR_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_ODT_WR;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_MFG_ID_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_MFG_ID;
///
/// @brief attribute getter
@@ -1010,19 +2352,19 @@ struct attrEngineTraits<attr_si_engine_fields, SI_ODT_WR>
static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& o_setting)
{
- return mss::attr::get_si_odt_wr(i_target, o_setting);
+ return mss::attr::get_dram_mfg_id(i_target, o_setting);
}
///
/// @brief attribute setter
- /// @param[in] i_target the fapi2 target
+ /// @param[in] i_target the attr target
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& i_setting)
{
- return mss::attr::set_si_odt_wr(i_target, i_setting);
+ return mss::attr::set_dram_mfg_id(i_target, i_setting);
}
///
@@ -1031,41 +2373,149 @@ struct attrEngineTraits<attr_si_engine_fields, SI_ODT_WR>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
attr_integral_type& o_setting)
{
- fapi2::buffer<uint8_t> l_buffer;
- uint8_t l_value = 0;
+ fapi2::buffer<attr_integral_type> l_temp;
+ FAPI_TRY(i_spd_data.dram_manufacturer_id_code(l_temp));
+ fapi2::endian_swap(l_temp);
+ o_setting = l_temp;
- switch(i_efd_data->get_rank())
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TREFI specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TREFI>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TREFI_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TREFI_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TREFI;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trefi(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trefi(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ const auto& l_dimm = i_spd_data.get_dimm_target();
+ uint8_t l_refresh_mode = 0;
+ uint8_t l_refresh_rate = 0;
+ uint64_t l_trefi_in_ps = 0;
+ int64_t l_tck_in_ps = 0;
+ uint64_t l_freq = 0;
+
+ FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps),
+ "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) );
+
+ FAPI_TRY( mss::attr::get_mrw_fine_refresh_mode(l_refresh_mode) );
+ FAPI_TRY( mss::attr::get_mrw_refresh_rate_request(l_refresh_rate) );
+
+ switch(l_refresh_mode)
{
- case 0:
- FAPI_TRY( i_efd_data->odt_wr_map_rank0(l_value) );
- break;
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL:
- case 1:
- FAPI_TRY( i_efd_data->odt_wr_map_rank1(l_value) );
+ FAPI_TRY( calc_trefi( mss::refresh_rate::REF1X,
+ l_refresh_rate,
+ l_trefi_in_ps),
+ "%s Failed to calculate tREF1", spd::c_str(l_dimm) );
break;
- case 2:
- FAPI_TRY( i_efd_data->odt_wr_map_rank2(l_value) );
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X:
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X:
+
+ FAPI_TRY( calc_trefi( mss::refresh_rate::REF2X,
+ l_refresh_rate,
+ l_trefi_in_ps),
+ "%s Failed to calculate tREF2", spd::c_str(l_dimm) );
break;
- case 3:
- FAPI_TRY( i_efd_data->odt_wr_map_rank3(l_value) );
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_4X:
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_4X:
+
+ FAPI_TRY( calc_trefi( mss::refresh_rate::REF4X,
+ l_refresh_rate,
+ l_trefi_in_ps),
+ "%s Failed to calculate tREF4", spd::c_str(l_dimm) );
break;
default:
- // TODO Add FFDC
- fapi2::Assert(false);
+ // Fine Refresh Mode will be a platform attribute set by the MRW,
+ // which they "shouldn't" mess up as long as use "attribute" enums.
+ // if openpower messes this up we can at least catch it
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_FINE_REFRESH_MODE().
+ set_FINE_REF_MODE(l_refresh_mode),
+ "%s Incorrect Fine Refresh Mode received: %d ",
+ spd::c_str(l_dimm),
+ l_refresh_mode);
break;
};
- // TK update to handle differentiating 2 DIMMs, defaulted to DIMM0 case for explorer
{
- // Map to attribute bitmap
- reverse(l_value);
- o_setting = l_value;
+ // Calculate refresh cycle time in nCK & set attribute
+ constexpr double PERCENT_ADJUST = 0.99;
+
+ // Calculate nck
+ uint64_t l_trefi_in_nck = 0;
+ FAPI_TRY( spd::calc_nck( l_trefi_in_ps,
+ static_cast<uint64_t>(l_tck_in_ps),
+ spd::INVERSE_DDR4_CORRECTION_FACTOR,
+ l_trefi_in_nck),
+ "%s Error in calculating tREFI, with value of l_trefi_in_ps: %d", spd::c_str(l_dimm), l_trefi_in_ps);
+
+ // Lab requested 99% of tREFI calculation to avoid any latency impact and violation of any
+ // refresh specification (across all number of ranks and frequencies) observed
+ // during lab power/thermal tests.
+
+ FAPI_INF("%s adjusting tREFI calculation by 99%, calculated tREFI (nck): %lu, adjusted tREFI (nck): %lu,",
+ spd::c_str(l_dimm), l_trefi_in_nck, l_trefi_in_nck * PERCENT_ADJUST);
+
+ // The compiler does this under the covers but just to be explicit on intent:
+ // Floating point arithmetic and truncation of result saved to an unsigned integer
+ l_trefi_in_nck = static_cast<double>(l_trefi_in_nck * PERCENT_ADJUST);
+
+ FAPI_INF("%s tCK (ps): %d, tREFI (ps): %d, tREFI (nck): %d",
+ spd::c_str(l_dimm), l_tck_in_ps, l_trefi_in_ps, l_trefi_in_nck);
+
+ o_setting = l_trefi_in_nck;
+ FAPI_DBG("%s DRAM TREFI %d", spd::c_str(l_dimm), o_setting);
}
fapi_try_exit:
@@ -1074,82 +2524,760 @@ struct attrEngineTraits<attr_si_engine_fields, SI_ODT_WR>
};
///
-/// @brief Traits for attr_engine
-/// @class attrEngineTraits
-/// @note attr_si_engine_fields, SI_ODT_RD specialization
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TCCD_L specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_ODT_RD>
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TCCD_L>
{
- using attr_type = fapi2::ATTR_MEM_SI_ODT_RD_Type;
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TCCD_L_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_ODT_RD_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_ODT_RD;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TCCD_L_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TCCD_L;
///
/// @brief attribute getter
- /// @param[in] i_target the fapi2 target
+ /// @param[in] i_target the attr target
/// @param[out] o_setting array to populate
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& o_setting)
{
- return mss::attr::get_si_odt_rd(i_target, o_setting);
+ return mss::attr::get_dram_tccd_l(i_target, o_setting);
}
///
/// @brief attribute setter
- /// @param[in] i_target the fapi2 target
+ /// @param[in] i_target the attr target
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& i_setting)
{
- return mss::attr::set_si_odt_rd(i_target, i_setting);
+ return mss::attr::set_dram_tccd_l(i_target, i_setting);
}
///
/// @brief Computes setting for attribute
- /// @param[in] i_efd_data EFD data
+ /// @param[in] i_spd_data SPD data
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
attr_integral_type& o_setting)
{
- uint8_t l_value = 0;
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TCCD_L>(i_spd_data, o_setting);
+ }
+};
- switch(i_efd_data->get_rank())
- {
- case 0:
- FAPI_TRY( i_efd_data->odt_rd_map_rank0(l_value) );
- break;
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TWTR_L specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWTR_L>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TWTR_L_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TWTR_L_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TWTR_L;
- case 1:
- FAPI_TRY( i_efd_data->odt_rd_map_rank1(l_value) );
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_twtr_l(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_twtr_l(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TWTR_L>(i_spd_data, o_setting);
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TWTR_S specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWTR_S>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TWTR_S_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TWTR_S_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TWTR_S;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_twtr_s(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_twtr_s(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TWTR_S>(i_spd_data, o_setting);
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TFAW specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TFAW>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TFAW_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TFAW_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TFAW;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_tfaw(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_tfaw(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TFAW>(i_spd_data, o_setting);
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRCD specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRCD>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRCD_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRCD_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRCD;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trcd(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trcd(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TRCD>(i_spd_data, o_setting);
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRP specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRP>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRP_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRP_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRP;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trp(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trp(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TRP>(i_spd_data, o_setting);
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRAS specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRAS>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRAS_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRAS_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRAS;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_tras(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_tras(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TRAS>(i_spd_data, o_setting);
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TWR specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TWR>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TWR_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TWR_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TWR;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_twr(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_twr(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return mss::calc_spd_time_in_nck<attr_eff_engine_fields,
+ attr_eff_engine_fields::DRAM_TWR>(i_spd_data, o_setting);
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRTP specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRTP>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRTP_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRTP_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRTP;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trtp(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trtp(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ const auto& l_dimm = i_spd_data.get_dimm_target();
+ int64_t l_tck_in_ps = 0;
+ uint64_t l_freq = 0;
+
+ // Values from proposed DDR4 Full spec update(79-4A)
+ // Item No. 1716.78C
+ // Page 241 & 246
+ constexpr int64_t l_max_trtp_in_ps = trtp();
+ uint8_t l_calc_trtp_in_nck = 0;
+
+ FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps),
+ "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) );
+
+ // Calculate nck
+ FAPI_TRY( spd::calc_nck(l_max_trtp_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_calc_trtp_in_nck),
+ "%s Error in calculating trtp, with value of l_twtr_in_ps: %d",
+ spd::c_str(l_dimm), l_max_trtp_in_ps);
+
+ FAPI_INF("%s tCK (ps): %d, tRTP (ps): %d, tRTP (nck): %d",
+ spd::c_str(l_dimm), l_tck_in_ps, l_max_trtp_in_ps, l_calc_trtp_in_nck);
+
+ o_setting = l_calc_trtp_in_nck;
+ FAPI_DBG("%s DRAM TRTP %d", spd::c_str(l_dimm), o_setting);
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRRD_S specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRRD_S>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRRD_S_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRRD_S_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRRD_S;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trrd_s(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trrd_s(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ const auto& l_dimm = i_spd_data.get_dimm_target();
+
+ // Taking the worst case required minimum JEDEC value
+ // instead of calculating proposed value from SPD -- which selects optimistic values
+ // leading to errors in expected timing values
+ uint64_t l_trrd_s_in_nck = 0;
+ uint64_t l_freq = 0;
+ uint8_t l_dram_width = 0;
+ FAPI_TRY( attr::get_dram_width(l_dimm, l_dram_width) );
+ FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( trrd_s( l_dimm, l_dram_width, l_freq, l_trrd_s_in_nck) );
+
+ FAPI_INF("%s SDRAM width: %d, tRRD_S (nck): %d",
+ spd::c_str(l_dimm), l_dram_width, l_trrd_s_in_nck);
+
+ o_setting = l_trrd_s_in_nck;
+ FAPI_DBG("%s DRAM TRRD_S %d", spd::c_str(l_dimm), o_setting);
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRRD_L specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRRD_L>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRRD_L_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRRD_L_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRRD_L;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trrd_l(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trrd_l(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ const auto& l_dimm = i_spd_data.get_dimm_target();
+
+ // Taking the worst case required minimum JEDEC value
+ // instead of calculating proposed value from SPD -- which selects optimistic values
+ // leading to errors in expected timing values
+ uint8_t l_dram_width = 0;
+ uint64_t l_trrd_l_in_nck = 0;
+ uint64_t l_freq = 0;
+
+ FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( attr::get_dram_width(l_dimm, l_dram_width) );
+ FAPI_TRY( trrd_l( l_dimm, l_dram_width, l_freq, l_trrd_l_in_nck) );
+
+ FAPI_INF("%s SDRAM width: %d, tRRD_L (nck): %d",
+ spd::c_str(l_dimm), l_dram_width, l_trrd_l_in_nck);
+
+ o_setting = l_trrd_l_in_nck;
+ FAPI_DBG("%s DRAM TRRD_L %d", spd::c_str(l_dimm), o_setting);
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRFC specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRFC>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRFC_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRFC_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRFC;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trfc(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trfc(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ const auto& l_dimm = i_spd_data.get_dimm_target();
+ int64_t l_tck_in_ps = 0;
+ uint64_t l_freq = 0;
+ uint8_t l_refresh_mode = 0;
+ int64_t l_trfc_mtb = 0;
+ int64_t l_trfc_in_ps = 0;
+
+ FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps),
+ "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) );
+
+ FAPI_TRY( mss::attr::get_mrw_fine_refresh_mode(l_refresh_mode) );
+
+ // Selects appropriate tRFC based on fine refresh mode
+ switch(l_refresh_mode)
+ {
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL:
+ FAPI_TRY( i_spd_data.min_trfc1(l_trfc_mtb),
+ "%s Failed to decode SPD for tRFC1", spd::c_str(l_dimm) );
break;
- case 2:
- FAPI_TRY( i_efd_data->odt_rd_map_rank2(l_value) );
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X:
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X:
+ FAPI_TRY( i_spd_data.min_trfc2(l_trfc_mtb),
+ "%s Failed to decode SPD for tRFC2", spd::c_str(l_dimm) );
break;
- case 3:
- FAPI_TRY( i_efd_data->odt_rd_map_rank3(l_value) );
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_4X:
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_4X:
+ FAPI_TRY( i_spd_data.min_trfc4(l_trfc_mtb),
+ "%s Failed to decode SPD for tRFC4", spd::c_str(l_dimm) );
break;
default:
- // TODO Add FFDC
- fapi2::Assert(false);
+ // Fine Refresh Mode will be a platform attribute set by the MRW,
+ // which they "shouldn't" mess up as long as use "attribute" enums.
+ // if openpower messes this up we can at least catch it
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_FINE_REFRESH_MODE().
+ set_FINE_REF_MODE(l_refresh_mode),
+ "%s Incorrect Fine Refresh Mode received: %d ",
+ spd::c_str(l_dimm),
+ l_refresh_mode);
break;
- };
+ }// switch
+
+ // Calculate trfc (in ps)
+ {
+ int64_t l_trfc_ftb = 0;
+ int64_t l_ftb = 0;
+ int64_t l_mtb = 0;
+
+ FAPI_TRY( spd::get_timebases(i_spd_data, l_mtb, l_ftb) );
+
+ FAPI_INF( "%s medium timebase (ps): %ld, fine timebase (ps): %ld, tRFC (MTB): %ld, tRFC(FTB): %ld",
+ spd::c_str(l_dimm), l_mtb, l_ftb, l_trfc_mtb, l_trfc_ftb );
+
+ l_trfc_in_ps = spd::calc_timing_from_timebase(l_trfc_mtb, l_mtb, l_trfc_ftb, l_ftb);
+ }
- // TK update to handle differentiating 2 DIMMs, defaulted to DIMM0 case for explorer
{
- // Map to attribute bitmap
- reverse(l_value);
- o_setting = l_value;
+ // Calculate refresh cycle time in nCK & set attribute
+
+ uint16_t l_trfc_in_nck = 0;
+
+ // Calculate nck
+ FAPI_TRY( spd::calc_nck(l_trfc_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_in_nck),
+ "%s Error in calculating l_tRFC, with value of l_trfc_in_ps: %d", spd::c_str(l_dimm), l_trfc_in_ps);
+
+ FAPI_INF("%s tCK (ps): %d, tRFC (ps): %d, tRFC (nck): %d",
+ spd::c_str(l_dimm), l_tck_in_ps, l_trfc_in_ps, l_trfc_in_nck);
+
+ o_setting = l_trfc_in_nck;
+ FAPI_DBG("%s DRAM TRFC %d", spd::c_str(l_dimm), o_setting);
}
fapi_try_exit:
@@ -1158,17 +3286,98 @@ struct attrEngineTraits<attr_si_engine_fields, SI_ODT_RD>
};
///
+/// @brief Traits for attrEngineTraits
+/// @class attrEngineTraits - partial specialization
+/// @tparam P processor type
+/// @note attrEngineTraits, DRAM_TRFC_DLR specialization
+///
+template<proc_type P>
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_TRFC_DLR>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_TRFC_DLR_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_TRFC_DLR_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_TRFC_DLR;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the attr target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_trfc_dlr(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_trfc_dlr(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_spd_data SPD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ const auto& l_dimm = i_spd_data.get_dimm_target();
+ int64_t l_tck_in_ps = 0;
+ uint64_t l_freq = 0;
+ uint8_t l_refresh_mode = 0;
+ uint8_t l_dram_density = 0;
+ uint64_t l_trfc_dlr_in_ps = 0;
+ uint8_t l_trfc_dlr_in_nck = 0;
+
+ FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps),
+ "%s Failed to calculate clock period (tCK)", spd::c_str(l_dimm) );
+
+ FAPI_TRY( mss::attr::get_mrw_fine_refresh_mode(l_refresh_mode) );
+ FAPI_TRY( mss::attr::get_dram_density(l_dimm, l_dram_density) );
+
+ // Calculate refresh cycle time in ps
+ FAPI_TRY( calc_trfc_dlr(l_dimm, l_refresh_mode, l_dram_density, l_trfc_dlr_in_ps),
+ "%s Failed calc_trfc_dlr()", spd::c_str(l_dimm) );
+
+ // Calculate refresh cycle time in nck
+ FAPI_TRY( spd::calc_nck(l_trfc_dlr_in_ps, static_cast<uint64_t>(l_tck_in_ps), spd::INVERSE_DDR4_CORRECTION_FACTOR,
+ l_trfc_dlr_in_nck));
+
+ FAPI_INF("%s tCK (ps): %d, tRFC_DLR (ps): %d, tRFC_DLR (nck): %d",
+ spd::c_str(l_dimm), l_tck_in_ps, l_trfc_dlr_in_ps, l_trfc_dlr_in_nck);
+
+ o_setting = l_trfc_dlr_in_nck;
+ FAPI_DBG("%s DRAM TRFC_DLR %d", spd::c_str(l_dimm), o_setting);
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
/// @brief Traits for attr_engine
/// @class attrEngineTraits
-/// @note attr_si_engine_fields, SI_GEARDOWN_MODE specialization
+/// @note attr_engine_derived_fields, RCD_MFG_ID specialization
///
-template<>
-struct attrEngineTraits<attr_si_engine_fields, SI_GEARDOWN_MODE>
+template < proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::RCD_MFG_ID>
{
- using attr_type = fapi2::ATTR_MEM_SI_GEARDOWN_MODE_Type;
+ using attr_type = fapi2::ATTR_MEM_EFF_RCD_MFG_ID_Type;
using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_SI_GEARDOWN_MODE_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_SI_GEARDOWN_MODE;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_RCD_MFG_ID_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_RCD_MFG_ID;
///
/// @brief attribute getter
@@ -1179,19 +3388,119 @@ struct attrEngineTraits<attr_si_engine_fields, SI_GEARDOWN_MODE>
static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& o_setting)
{
- return mss::attr::get_si_geardown_mode(i_target, o_setting);
+ return mss::attr::get_rcd_mfg_id(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_rcd_mfg_id(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return i_spd_data.reg_manufacturer_id_code(o_setting);
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits
+/// @note attr_engine_derived_fields, DRAM_MODULE_HEIGHT specialization
+///
+template < proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::DRAM_MODULE_HEIGHT>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_MODULE_HEIGHT;
+
+ ///
+ /// @brief attribute getter
+ /// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_dram_module_height(i_target, o_setting);
}
///
/// @brief attribute setter
+ /// @param[in] i_target the attr target
+ /// @param[in] i_setting array to set
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& i_setting)
+ {
+ return mss::attr::set_dram_module_height(i_target, i_setting);
+ }
+
+ ///
+ /// @brief Computes setting for attribute
+ /// @param[in] i_efd_data EFD data
+ /// @param[out] o_setting value we want to set attr with
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
+ attr_integral_type& o_setting)
+ {
+ return i_spd_data.module_base_height(o_setting);
+ }
+};
+
+///
+/// @brief Traits for attr_engine
+/// @class attrEngineTraits
+/// @note attr_engine_derived_fields, SPD_REVISION specialization
+///
+template < proc_type P >
+struct attrEngineTraits<P, attr_eff_engine_fields, attr_eff_engine_fields::SPD_REVISION>
+{
+ using attr_type = fapi2::ATTR_MEM_EFF_SPD_REVISION_Type;
+ using attr_integral_type = std::remove_all_extents<attr_type>::type;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_SPD_REVISION_TargetType;
+ static constexpr generic_ffdc_codes FFDC_CODE = SET_SPD_REVISION;
+
+ ///
+ /// @brief attribute getter
/// @param[in] i_target the fapi2 target
+ /// @param[out] o_setting array to populate
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
+ attr_type& o_setting)
+ {
+ return mss::attr::get_spd_revision(i_target, o_setting);
+ }
+
+ ///
+ /// @brief attribute setter
+ /// @param[in] i_target the attr target
/// @param[in] i_setting array to set
/// @return FAPI2_RC_SUCCESS iff okay
///
static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
attr_type& i_setting)
{
- return mss::attr::set_si_geardown_mode(i_target, i_setting);
+ return mss::attr::set_spd_revision(i_target, i_setting);
}
///
@@ -1200,10 +3509,10 @@ struct attrEngineTraits<attr_si_engine_fields, SI_GEARDOWN_MODE>
/// @param[out] o_setting value we want to set attr with
/// @return FAPI2_RC_SUCCESS iff okay
///
- static fapi2::ReturnCode get_value_to_set(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ static inline fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
attr_integral_type& o_setting)
{
- return i_efd_data->geardown_during_training(o_setting);
+ return i_spd_data.revision(o_setting);
}
};
diff --git a/src/import/generic/memory/lib/data_engine/data_engine.H b/src/import/generic/memory/lib/data_engine/data_engine.H
index aa0fb5f0a..6e206292b 100644
--- a/src/import/generic/memory/lib/data_engine/data_engine.H
+++ b/src/import/generic/memory/lib/data_engine/data_engine.H
@@ -38,225 +38,100 @@
#include <cstring>
#include <fapi2.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
-#include <generic/memory/lib/data_engine/attr_engine_traits.H>
#include <generic/memory/lib/data_engine/data_engine_utils.H>
-#include <generic/memory/lib/spd/spd_utils.H>
-#include <generic/memory/lib/utils/conversions.H>
-#include <generic/memory/lib/mss_generic_attribute_getters.H>
namespace mss
{
-
-///
-/// @brief Alias for function pointer to spd_facade timing methods
-///
-using spd_facade_fptr = fapi2::ReturnCode (spd::facade::*)(int64_t& o_timing_in_mtb) const;
-
-///
-/// @brief Algorithm to calculate SPD timings in nCK
-/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields)
-/// @tparam F SPD field
-/// @tparam OT output type
-/// @tparam TT defaulted to setTimingTraits<ET, F>
-/// @param[in] i_spd the SPD data
-/// @param[out] o_timing_in_ps SPD timing value in picoseconds
-/// @return FAPI2_RC_SUCCESS iff okay
-///
-template < typename ET,
- ET F,
- typename OT,
- typename TT = setTimingTraits<ET, F> >
-inline fapi2::ReturnCode calc_spd_time_in_ps(const spd::facade& i_spd,
- OT& o_timing_in_ps)
-{
- const auto l_dimm = i_spd.get_dimm_target();
- int64_t l_timing_mtb = 0;
- int64_t l_timing_ftb = 0;
- int64_t l_mtb = 0;
- int64_t l_ftb = 0;
-
- FAPI_TRY( spd::get_timebases(i_spd, l_mtb, l_ftb) );
-
- FAPI_TRY( (i_spd.*TT::get_timing_in_mtb)(l_timing_mtb),
- "Failed to get % (in MTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) );
- FAPI_TRY( (i_spd.*TT::get_timing_in_ftb)(l_timing_ftb),
- "Failed to get %s (in FTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) );
-
- FAPI_DBG("%s medium timebase (ps): %ld, fine timebase (ps): %ld, %s (MTB): %ld, (FTB): %ld",
- spd::c_str(l_dimm), l_mtb, l_ftb, TT::TIMING_NAME, l_timing_mtb, l_timing_ftb );
-
- o_timing_in_ps = spd::calc_timing_from_timebase(l_timing_mtb, l_mtb, l_timing_ftb, l_ftb);
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Algorithm to calculate SPD timings in nCK
-/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields)
-/// @tparam F SPD field
-/// @tparam OT output type
-/// @tparam TT defaulted to setTimingTraits<ET, F>
-/// @param[in] i_spd the SPD data
-/// @param[out] o_timing_in_ps SPD timing value in number of clocks (nCK)
-/// @return FAPI2_RC_SUCCESS iff okay
-///
-template < typename ET,
- ET F,
- typename OT,
- typename TT = setTimingTraits<ET, F> >
-inline fapi2::ReturnCode calc_spd_time_in_nck(const spd::facade& i_spd,
- OT& o_timing_in_nck)
-{
- const auto l_dimm = i_spd.get_dimm_target();
-
- // Calculate the DIMM speed in picoseconds (a.k.a tCK == clock period)
- int64_t l_tck_in_ps = 0;
- uint64_t l_freq = 0;
- FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
- FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps),
- "Failed to calculate clock period (tCK) for %s", spd::c_str(l_dimm) );
-
- {
- // Calculate the desired timing in ps
- int64_t l_timing_in_ps = 0;
- FAPI_TRY( (calc_spd_time_in_ps<ET, F>(i_spd, l_tck_in_ps)) );
-
- // Calculate nck
- FAPI_TRY( spd::calc_nck(l_timing_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, o_timing_in_nck),
- "Error in calculating %s (nCK) for target %s, with value of %d",
- TT::TIMING_NAME, spd::c_str(l_dimm), l_timing_in_ps );
-
- FAPI_INF("tCK (ps): %d, %s (ps): %d, %s (nck): %d",
- l_tck_in_ps, TT::TIMING_NAME, l_timing_in_ps, TT::TIMING_NAME, o_timing_in_nck);
- }
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Sets preliminary data fields
-/// @tparam F pre_data_init_fields
-/// @tparam T FAPI2 target type
-/// @tparam IT Input data type
-/// @tparam TT defaulted to preDataInitTraits<T>
-/// @param[in] i_setting value we want to set attr with
-/// @return FAPI2_RC_SUCCESS iff okay
-///
-template< attr_eff_engine_fields F,
- fapi2::TargetType T,
- typename IT,
- typename TT = mss::attrEngineTraits<decltype(F), F>
- >
-inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
- const IT i_setting)
+namespace gen
{
- FAPI_TRY( (gen::set_field<TT>(i_target, i_setting)),
- "Failed set_field() for %s", spd::c_str(i_target) );
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Value traits for attrEnumTraits
-/// @class attrEnumTraits - attr_si_engine_fields specialization
-///
-template < >
-struct attrEnumTraits<attr_si_engine_fields>
-{
- static constexpr size_t DISPATCHER = ATTR_SI_DISPATCHER;
-};
-
-///
-/// @brief Value traits for attrEnumTraits
-/// @class attrEnumTraits - attr_eff_engine_fields specialization
-///
-template < >
-struct attrEnumTraits<attr_eff_engine_fields>
-{
- static constexpr size_t DISPATCHER = ATTR_EFF_DISPATCHER;
-};
-
-///
-/// @brief Value traits for attrEnumTraits
-/// @class attrEnumTraits - attr_eff_engine_fields specialization
-///
-template < >
-struct attrEnumTraits<pre_data_init_fields>
-{
- static constexpr size_t DISPATCHER = ATTR_PRE_DATA_ENG_DISPATCHER;
-};
///
-/// @brief attribute signal integrity engine
-/// @class attr_si_engine
-/// @tparam ET field enumeration type
-/// @tparam TT defaulted to attrEnumTraits<ET>
+/// @brief Template recursive algorithm for setting attrs
+/// @class attr_engine - partial specialization when F != 0
+/// @tparam P processor type
+/// @tparam ET enum type - conceptually a list of attrs to set
+/// @tparam F enum value - the specific attr value from ET to set
+/// @tparam TT associated traits for attr_engine
///
-template < typename ET, typename TT = attrEnumTraits<ET> >
-struct attr_si_engine
+template < proc_type P, typename ET, ET F, typename TT >
+struct attr_engine<P, ET, F, TT, false>
{
- using attr_eng_t = gen::attr_engine<ET, static_cast<ET>(TT::DISPATCHER)>;
-
///
- /// @brief Sets attr_si_engine_fields
- /// @tparam[in] IT rank input type
- /// @param[in] i_target the DIMM target
- /// @param[in] i_efd_data EFD data
- /// @param[in] i_rank current rank
+ /// @brief Sets attributes fields F in ET
+ /// @tparam IT the input type
+ /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target)
/// @return FAPI2_RC_SUCCESS iff ok
///
- static fapi2::ReturnCode set(const std::shared_ptr<efd::base_decoder>& i_efd_data)
+ template < typename IT >
+ static fapi2::ReturnCode single_set(const IT& i_input)
{
- return attr_eng_t::set(i_efd_data);
- }
-};
+ typename TT::attr_integral_type l_value = 0;
-///
-/// @brief Data structure to set effective config EFF data
-/// @class pre_attr_eff_engine
-/// @tparam F attr_eff_engine_fields enum
-///
-template < typename ET, typename TT = attrEnumTraits<ET> >
-struct attr_eff_engine
-{
- using attr_eng_t = gen::attr_engine<ET, static_cast<ET>(TT::DISPATCHER)>;
+ FAPI_TRY( TT::get_value_to_set(i_input, l_value),
+ "Failed get_value_to_set() for proc_type: %d and enum val: %d", P, F);
+
+ FAPI_TRY( set_field<TT>(i_input, l_value),
+ "Failed set_field() for proc_type: %d and enum val: %d", P, F);
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
///
- /// @brief Sets attr_si_engine_fields
- /// @param[in] i_target the DIMM target
- /// @param[in] i_spd_data EFD data
+ /// @brief Sets attributes fields F in ET
+ /// @tparam IT the input type
+ /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target)
/// @return FAPI2_RC_SUCCESS iff ok
///
- static fapi2::ReturnCode set(const mss::spd::facade& i_spd_data)
+ template < typename IT >
+ static fapi2::ReturnCode set(const IT& i_input)
{
- return attr_eng_t::set(i_spd_data);
+ FAPI_TRY( (attr_engine<P, ET, F, TT, static_cast<size_t>(F) == 0u>::single_set(i_input)),
+ "Failed attr_engine<P, ET, F>::single_set() for proc_type: %d and enum val: %d", P, F);
+
+ // Compiler isn't smart enough to deduce F - 1u (decrementing the enum values by 1)
+ // Cast needed to help the compiler deduce this value is an ET type
+ // This does the recursive call to unroll a compile-time looping of a enum list of attrs to set
+ // The recursion stops at the base case where NEXT_FLD == 0u
+ {
+ constexpr ET NEXT_FLD = static_cast<ET>( static_cast<size_t>(F) - 1u );
+ using T = mss::attrEngineTraits<P, ET, NEXT_FLD>;
+
+ FAPI_TRY( (attr_engine <P, ET, NEXT_FLD, T, 0u == static_cast<size_t>(NEXT_FLD)>::set(i_input)),
+ "Failed (attr_engine <P, ET, NEXT_FLD>::set() for proc_type: %d and enum val: %d", P, F);
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
}
};
///
-/// @brief Data structure to set effective config EFF data
-/// @class attr_derived_engine
-/// @tparam ET attr fields enum type
+/// @brief Template recursive algorithm for setting attrs
+/// @class attr_engine - partial specialization where F == 0u
+/// @tparam P processor type
+/// @tparam ET attr fields enum type (conceptually a list of attrs to set)
+/// @tparam F enum value - the specific attr value from ET to set
+/// @tparam TT associated traits for attr_engine
///
-template < typename ET, typename TT = attrEnumTraits<ET> >
-struct attr_derived_engine
+template < proc_type P, typename ET, ET F, typename TT >
+struct attr_engine< P, ET, F, TT, true >
{
- using attr_eng_t = gen::attr_engine<ET, static_cast<ET>(TT::DISPATCHER)>;
-
///
- /// @brief Sets attr fields denoted by an eum list
- /// @param[in] i_target the DIMM target
+ /// @brief Sets attributes fields F in ET
+ /// @tparam IT the input type
+ /// @param[in] i_input input (efd_decoder, spd_facade, fapi2 target)
/// @return FAPI2_RC_SUCCESS iff ok
///
- static fapi2::ReturnCode set(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target)
+ template < typename IT >
+ static fapi2::ReturnCode set(const IT& i_input)
{
- return attr_eng_t::set(i_target);
+ FAPI_DBG("NO-OP: Reached base case (0) of recursive template for proc_type: %d and enum value: %d", P, F);
+ return fapi2::FAPI2_RC_SUCCESS;
}
};
+}// gen
}// mss
#endif
diff --git a/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H b/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H
index be55890ea..4852da6b1 100644
--- a/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H
+++ b/src/import/generic/memory/lib/data_engine/data_engine_traits_def.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -43,62 +43,91 @@ namespace mss
{
///
-/// @brief enum list of preliminary data fields
+/// @brief enum list of preliminary data fields needed before eff_config
///
-enum generic_metadata_fields
+enum class pre_data_init_fields
{
// Template recursive base case
- ATTR_METADATA_BASE_CASE = 0,
+ ATTR_PRE_DATA_ENGINE_CASE = 0,
// Attrs to set
- DIMM_TYPE_METADATA = 1,
- DRAM_GEN_METADATA = 2,
- DIMM_POS_METADATA = 3,
+ DIMM_TYPE = 1,
+ DRAM_GEN = 2,
+ HYBRID = 3,
+ HYBRID_MEDIA = 4,
+ MRANKS = 5,
+ HOST_TO_DDR_SPEED_RATIO = 6,
+ DIMM_RANKS_CNFG = 7,
// Dispatcher set to last enum value
- ATTR_METADATA_DISPATCHER = DIMM_POS_METADATA,
+ DISPATCHER = DIMM_RANKS_CNFG,
};
///
/// @brief enum list of preliminary data fields
+/// @note Separating these fields into their own special case
+/// since this is needed for reuse in incompatible code bases
+/// (e.g. Nimbus vs Axone)
+/// @warning these depend on pre_data_init_fields fields being set
///
-enum pre_data_init_fields
+enum class generic_metadata_fields
{
// Template recursive base case
- ATTR_PRE_DATA_ENGINE_CASE = 0,
+ ATTR_METADATA_BASE_CASE = 0,
// Attrs to set
- DIMM_TYPE = 1,
- DRAM_GEN = 2,
- HYBRID = 3,
- HYBRID_MEDIA = 4,
- MRANKS = 5,
- DIMM_RANKS_CNFG = 6,
- HOST_TO_DDR_SPEED_RATIO = 7,
+ DIMM_TYPE_METADATA = 1,
+ DRAM_GEN_METADATA = 2,
+ DIMM_POS_METADATA = 3,
// Dispatcher set to last enum value
- ATTR_PRE_DATA_ENG_DISPATCHER = HOST_TO_DDR_SPEED_RATIO,
+ DISPATCHER = DIMM_POS_METADATA,
};
///
/// @brief enum list of SPD based attr fields to set
///
-enum attr_eff_engine_fields
+enum class attr_eff_engine_fields
{
// Template recursive base case
ATTR_EFF_BASE_CASE = 0,
// Attrs to set
- DRAM_WIDTH = 1,
+ DRAM_CWL = 1,
+ DRAM_TREFI = 2,
+ DRAM_TCCD_L = 3,
+ DRAM_TWTR_L = 4,
+ DRAM_TWTR_S = 5,
+ DRAM_TFAW = 6,
+ DRAM_TRCD = 7,
+ DRAM_TRP = 8,
+ DRAM_TRAS = 9,
+ DRAM_TWR = 10,
+ DRAM_TRTP = 11,
+ DRAM_TRRD_S = 12,
+ DRAM_TRRD_L = 13,
+ DRAM_TRFC = 14,
+ DRAM_TRFC_DLR = 15,
+ DRAM_WIDTH = 16,
+ PRIM_BUS_WIDTH = 17,
+ DRAM_DENSITY = 18,
+ PRIMARY_DIE_COUNT = 19,
+ PRIM_STACK_TYPE = 20,
+ COLUMN_ADDR_BITS = 21,
+ ROW_ADDR_BITS = 22,
+ DRAM_MFG_ID = 23,
+ RCD_MFG_ID = 24,
+ DRAM_MODULE_HEIGHT = 25,
+ SPD_REVISION = 26,
// Dispatcher set to last enum value
- ATTR_EFF_DISPATCHER = DRAM_WIDTH,
+ DISPATCHER = SPD_REVISION,
};
///
-/// @brief enum list of SI attr fields to set
+/// @brief enum list of SI attr fields to set from EFD
///
-enum attr_si_engine_fields
+enum class attr_si_engine_fields
{
// Template recursive base case
ATTR_SI_BASE_CASE = 0,
@@ -119,29 +148,51 @@ enum attr_si_engine_fields
SI_DRAM_PREAMBLE = 13,
SI_MC_DRV_EQ_DQ_DQS = 14,
SI_DRAM_DRV_IMP_DQ_DQS = 15,
- SI_VREF_DQ_TRAIN_RANGE = 16,
- SI_VREF_DQ_TRAIN_VALUE = 17,
- SI_ODT_WR = 18,
- SI_ODT_RD = 19,
- SI_GEARDOWN_MODE = 20,
+ SI_ODT_WR = 16,
+ SI_ODT_RD = 17,
+ SI_GEARDOWN_MODE = 18,
+
+ // Dispatcher set to last enum value
+ DISPATCHER = SI_GEARDOWN_MODE,
+};
+
+///
+/// @brief enum list of derived attributes
+/// @note these are attributes that are derived from other
+/// attributes or other APIs.
+///
+enum class attr_engine_derived_fields
+{
+ // Attributes are set recursively from the bottom up.
+ // When adding attrs that depend on other attrs
+ // being set first, they should be placed earlier in the enum list
+ // so that base level attrs are set first.
+
+ // Template recursive base case
+ ATTR_DERIVED_BASE_CASE = 0,
+
+ // Attrs to set
+ MEM_DIMM_SIZE = 1,
+ HEIGHT_3DS = 2, // HEIGHT_3DS must be calculated after LOGICAL_RANKS
+ LOGICAL_RANKS = 3,
// Dispatcher set to last enum value
- ATTR_SI_DISPATCHER = SI_GEARDOWN_MODE,
+ DISPATCHER = LOGICAL_RANKS,
};
///
/// @brief Forward declartion of traits for pre_data_engine
/// @class preDataInitTraits
-/// @tparam T proc_type (e.g. Nimbus, Axone, etc.)
+/// @tparam P processor type (e.g. Nimbus, Axone, etc.)
/// @tparam TT pre_data_init_fields (e.g. DIMM_TYPE, MRANK, etc.)
///
-template< proc_type T, pre_data_init_fields TT >
+template< proc_type P, pre_data_init_fields TT >
class preDataInitTraits;
///
/// @brief Traits associated with DIMM positioning
/// @class dimmPosTraits
-/// @tparam MC the MC type
+/// @tparam MC the memory controller type
///
template< mss::mc_type MC >
class dimmPosTraits;
@@ -149,10 +200,11 @@ class dimmPosTraits;
///
/// @brief Forward declartion of traits for attrEngineTraits
/// @class attrEngineTraits
+/// @tparam P processor type (e.g. Nimbus, Axone, etc.)
/// @tparam ET enum type
/// @tparam T enum value
///
-template < typename ET, ET T>
+template < proc_type P, typename ET, ET T = ET::DISPATCHER>
struct attrEngineTraits;
///
@@ -164,14 +216,25 @@ struct attrEngineTraits;
template < typename ET, ET T >
struct setTimingTraits;
+namespace gen
+{
///
-/// @brief Forward declartion of traits for attrEnumTraits
-/// @class attrEnumTraits
-/// @tparam ET enum type
-///
-template < typename ET >
-struct attrEnumTraits;
-
+/// @brief Template recursive algorithm for setting attrs
+/// @class attr_engine
+/// @tparam P processor type (e.g. Nimbus, Axone, etc.)
+/// @tparam ET enum type - conceptually a list of attrs to set
+/// @tparam F enum value - the specific attr value from ET to set
+/// @tparam TT associated traits for attr_engine
+/// @tparam B dispatch tag - defaulted to false
+///
+template < proc_type P,
+ typename ET,
+ ET F = ET::DISPATCHER,
+ typename TT = attrEngineTraits<P, ET, F>,
+ bool B = false>
+struct attr_engine;
+
+}// gen
}// mss
#endif
diff --git a/src/import/generic/memory/lib/data_engine/data_engine_utils.H b/src/import/generic/memory/lib/data_engine/data_engine_utils.H
index aaf9a0485..a4a8d9946 100644
--- a/src/import/generic/memory/lib/data_engine/data_engine_utils.H
+++ b/src/import/generic/memory/lib/data_engine/data_engine_utils.H
@@ -37,154 +37,104 @@
#define _MSS_DATA_ENGINE_UTILS_H_
#include <fapi2.H>
+#include <generic/memory/lib/data_engine/data_engine_traits_def.H>
#include <generic/memory/lib/utils/index.H>
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/utils/pos.H>
#include <generic/memory/lib/spd/ddimm/efd_decoder.H>
+#include <generic/memory/lib/spd/spd_utils.H>
#include <generic/memory/lib/spd/spd_facade.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+#include <generic/memory/lib/utils/conversions.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/buffer_ops.H>
namespace mss
{
///
-/// @class DataSetterTraits2D
-/// @brief Traits for setting eff_config data
-/// @tparam P proc_type
-/// @tparam X size of 1st array index
-/// @tparam Y size of 2nd array index
+/// @brief Alias for function pointer to spd_facade timing methods
///
-template < proc_type, size_t X, size_t Y >
-struct DataSetterTraits2D;
+using spd_facade_fptr = fapi2::ReturnCode (spd::facade::*)(int64_t& o_timing_in_mtb) const;
///
-/// @class DataSetterTraits - Nimbus, [PORT][DIMM] array specialization
-/// @brief Traits for setting eff_config data
+/// @brief Algorithm to calculate SPD timings in nCK
+/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields)
+/// @tparam F SPD field
+/// @tparam OT output type
+/// @tparam TT defaulted to setTimingTraits<ET, F>
+/// @param[in] i_spd the SPD data
+/// @param[out] o_timing_in_ps SPD timing value in picoseconds
+/// @return FAPI2_RC_SUCCESS iff okay
///
-template < >
-struct DataSetterTraits2D < proc_type::NIMBUS,
- mcTypeTraits<mc_type::NIMBUS>::PORTS_PER_MCS,
- mcTypeTraits<mc_type::NIMBUS>::DIMMS_PER_PORT
- >
+template < typename ET,
+ ET F,
+ typename OT,
+ typename TT = setTimingTraits<ET, F> >
+inline fapi2::ReturnCode calc_spd_time_in_ps(const spd::facade& i_spd,
+ OT& o_timing_in_ps)
{
- static constexpr fapi2::TargetType TARGET = fapi2::TARGET_TYPE_MCA;
-};
+ const auto l_dimm = i_spd.get_dimm_target();
+ int64_t l_timing_mtb = 0;
+ int64_t l_timing_ftb = 0;
+ int64_t l_mtb = 0;
+ int64_t l_ftb = 0;
-///
-/// @brief Helper function to update a 2D array output
-/// @tparam P proc_type
-/// @tparam X size of 1st array index
-/// @tparam Y size of 2nd array index
-/// @tparam T Input/output data type
-/// @tparam TT defaulted to DataSetterTraits2D<P, X, Y>
-/// @param[in] i_target the DIMM target
-/// @param[in] i_setting array to set
-/// @param[in] i_ffdc_code FFDC function code
-/// @param[out] o_data attribute data structure to set
-/// @warning This is Nimbus specific until MCA alias to MEM_PORT
-///
-template < proc_type P,
- size_t X,
- size_t Y,
- typename T,
- typename TT = DataSetterTraits2D<P, X, Y>
- >
-fapi2::ReturnCode update_data(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const T i_setting,
- const generic_ffdc_codes i_ffdc_code,
- T (&o_data)[X][Y])
-{
- // Currenlty only valid for a DIMM target, for Nimbus, traits enforces this at compile time
- // Use case is currently for pre_eff_config which is supported in both Axone and Nimbus
- const auto l_port_index = mss::index( find_target<TT::TARGET>(i_target) );
- const auto l_dimm_index = mss::index(i_target);
+ FAPI_TRY( spd::get_timebases(i_spd, l_mtb, l_ftb) );
- FAPI_ASSERT( l_port_index < X,
- fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
- .set_INDEX(l_port_index)
- .set_LIST_SIZE(X)
- .set_FUNCTION(i_ffdc_code)
- .set_TARGET(i_target),
- "Port index (%d) was larger than max (%d) on %s",
- l_port_index,
- X,
- mss::spd::c_str(i_target) );
+ FAPI_TRY( (i_spd.*TT::get_timing_in_mtb)(l_timing_mtb),
+ "Failed to get % (in MTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) );
+ FAPI_TRY( (i_spd.*TT::get_timing_in_ftb)(l_timing_ftb),
+ "Failed to get %s (in FTB) for %s", TT::TIMING_NAME, spd::c_str(l_dimm) );
- FAPI_ASSERT( l_dimm_index < Y,
- fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
- .set_INDEX(l_dimm_index)
- .set_LIST_SIZE(Y)
- .set_FUNCTION(i_ffdc_code)
- .set_TARGET(i_target),
- "DIMM index (%d) was larger than max (%d) on %s",
- l_dimm_index,
- Y,
- mss::spd::c_str(i_target) );
-
- o_data[l_port_index][l_dimm_index] = i_setting;
+ FAPI_DBG("%s medium timebase (ps): %ld, fine timebase (ps): %ld, %s (MTB): %ld, (FTB): %ld",
+ spd::c_str(l_dimm), l_mtb, l_ftb, TT::TIMING_NAME, l_timing_mtb, l_timing_ftb );
- return fapi2::FAPI2_RC_SUCCESS;
+ o_timing_in_ps = spd::calc_timing_from_timebase(l_timing_mtb, l_mtb, l_timing_ftb, l_ftb);
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Mapping boilerplate check
-/// @tparam T FAPI2 target type
-/// @tparam IT map key type
-/// @tparam OT map value type
-/// @param[in] i_target the FAPI target
-/// @param[in] i_map SPD to attribute data mapping
-/// @param[in] i_ffdc_code FFDC function code
-/// @param[in] i_key Key to query map
-/// @param[out] o_output value from key
+/// @brief Algorithm to calculate SPD timings in nCK
+/// @tparam ET SPD fields enumeration (e.g. attr_eff_engine_fields)
+/// @tparam F SPD field
+/// @tparam OT output type
+/// @tparam TT defaulted to setTimingTraits<ET, F>
+/// @param[in] i_spd the SPD data
+/// @param[out] o_timing_in_ps SPD timing value in number of clocks (nCK)
/// @return FAPI2_RC_SUCCESS iff okay
///
-template< fapi2::TargetType T, typename IT, typename OT >
-inline fapi2::ReturnCode lookup_table_check(const fapi2::Target<T>& i_target,
- const std::vector<std::pair<IT, OT>>& i_map,
- const generic_ffdc_codes i_ffdc_code,
- const IT i_key,
- OT& o_output)
+template < typename ET,
+ ET F,
+ typename OT,
+ typename TT = setTimingTraits<ET, F> >
+inline fapi2::ReturnCode calc_spd_time_in_nck(const spd::facade& i_spd,
+ OT& o_timing_in_nck)
{
- const bool l_is_val_found = mss::find_value_from_key(i_map, i_key, o_output);
+ const auto l_dimm = i_spd.get_dimm_target();
- FAPI_ASSERT( l_is_val_found,
- fapi2::MSS_LOOKUP_FAILED()
- .set_KEY(i_key)
- .set_DATA(o_output)
- .set_FUNCTION(i_ffdc_code)
- .set_TARGET(i_target),
- "Failed to find a mapped value for %d on %s",
- i_key,
- mss::spd::c_str(i_target) );
-fapi_try_exit:
- return fapi2::current_err;
-}
+ // Calculate the DIMM speed in picoseconds (a.k.a tCK == clock period)
+ int64_t l_tck_in_ps = 0;
+ uint64_t l_freq = 0;
+ FAPI_TRY( attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(l_dimm), l_freq) );
+ FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps),
+ "Failed to calculate clock period (tCK) for %s", spd::c_str(l_dimm) );
-///
-/// @brief Sets attr data fields
-/// @tparam P proc_type
-/// @tparam TT data engine class traits (e.g. preDataInitTraits, etc.)
-/// @tparam T FAPI2 target type
-/// @tparam IT Input data type
-/// @param[in] i_target the FAPI target
-/// @param[in] i_setting value we want to set attr with
-/// @return FAPI2_RC_SUCCESS iff okay
-///
-template< proc_type P,
- typename TT,
- fapi2::TargetType T,
- typename IT >
-inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
- const IT i_setting)
-{
- const auto l_attr_target = mss::find_target<TT::TARGET_TYPE>(i_target);
- typename TT::attr_type l_attr_list = {};
- FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list) );
+ {
+ // Calculate the desired timing in ps
+ int64_t l_timing_in_ps = 0;
+ FAPI_TRY( (calc_spd_time_in_ps<ET, F>(i_spd, l_timing_in_ps)) );
+
+ // Calculate nck
+ FAPI_TRY( spd::calc_nck(l_timing_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, o_timing_in_nck),
+ "Error in calculating %s (nCK) for target %s, with value of %d",
+ TT::TIMING_NAME, spd::c_str(l_dimm), l_timing_in_ps );
- FAPI_TRY( update_data<P>(i_target, i_setting, TT::FFDC_CODE, l_attr_list) );
- FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list) );
+ FAPI_INF("tCK (ps): %d, %s (ps): %d, %s (nck): %d",
+ l_tck_in_ps, TT::TIMING_NAME, l_timing_in_ps, TT::TIMING_NAME, o_timing_in_nck);
+ }
fapi_try_exit:
return fapi2::current_err;
@@ -196,7 +146,7 @@ namespace gen
{
///
-/// @brief Get the target associated with the SPD facade
+/// @brief Helper to get the target associated with the SPD facade
/// @param[in] i_data the SPD data
/// return a fapi2 DIMM target
///
@@ -206,7 +156,7 @@ static inline fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_target(const spd::facad
}
///
-/// @brief Get the target associated with the EFD decoder
+/// @brief Helper to get the target associated with the EFD decoder
/// @param[in] i_data the EFD data
/// return a fapi2 DIMM target
///
@@ -216,6 +166,32 @@ static inline fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> get_target(const std::
}
///
+/// @brief Helper function to get the target associated with generic attribute setting
+/// @param[in] i_target
+/// return a fapi2 MEM_PORT target
+///
+static inline fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> get_attr_target(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
+ i_target)
+{
+ return mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(i_target);
+}
+
+///
+/// @brief Helper function to get the target associated with generic attribute setting
+/// @param[in] i_target
+/// return a fapi2 MEM_PORT target
+///
+inline fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> get_attr_target(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
+ i_target)
+{
+ // Explorer has only one MEM_PORT per OCMB, so we are looking for the 0th pos relative to the OCMB
+ // Will need to update to take into account a mem_channel index in VPDinfo if we ever support this.
+ // Per FW, for the DDIMM case we can't support unique settings per channel because the SPD
+ // doesn't know about anything outside of the DDIMM itself.
+ return mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target)[0];
+}
+
+///
/// @brief Helper function to update the structure that holds attr data
/// @tparam X size of 1st array index
/// @tparam Y size of 2nd array index
@@ -238,10 +214,9 @@ inline fapi2::ReturnCode update_data(const std::shared_ptr<efd::base_decoder>& i
{
const auto l_ocmb = i_efd_data->get_ocmb_target();
- // TK, remove hard-code when VPDinfo struct adds an iv_dimm index
- // For explorer we can only have 1 DDIMM (index 0), or up to 2 DIMMs
- constexpr size_t l_dimm_index = 0;
- const auto l_rank = i_efd_data->get_rank();
+ // mss::index of rank number will % 4 (RANKS_PER_DIMM) to get us the corresponding dimm
+ const auto l_dimm_index = i_efd_data->get_rank() / mss::MAX_RANK_PER_DIMM;
+ const auto l_dimm_rank = i_efd_data->get_rank() % mss::MAX_RANK_PER_DIMM;
FAPI_ASSERT( l_dimm_index < X,
fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
@@ -254,19 +229,19 @@ inline fapi2::ReturnCode update_data(const std::shared_ptr<efd::base_decoder>& i
X,
mss::spd::c_str(l_ocmb) );
- FAPI_ASSERT( l_rank < Y,
+ FAPI_ASSERT( l_dimm_rank < Y,
fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
- .set_INDEX(l_rank)
+ .set_INDEX(l_dimm_rank)
.set_LIST_SIZE(X)
.set_FUNCTION(i_ffdc_code)
.set_TARGET(l_ocmb),
"Rank index (%d) was larger than max (%d) on %s",
- l_rank,
+ l_dimm_rank,
Y,
mss::spd::c_str(l_ocmb) );
- FAPI_DBG("Updating data[%d][%d] with %d for %s", l_dimm_index, l_rank, i_setting, spd::c_str(l_ocmb));
- o_data[l_dimm_index][l_rank] = i_setting;
+ FAPI_DBG("Updating data[%d][%d] with %d for %s", l_dimm_index, l_dimm_rank, i_setting, spd::c_str(l_ocmb));
+ o_data[l_dimm_index][l_dimm_rank] = i_setting;
return fapi2::FAPI2_RC_SUCCESS;
@@ -294,9 +269,8 @@ inline fapi2::ReturnCode update_data( const spd::facade& i_spd_data,
const FFDC i_ffdc_code,
T (&o_data)[X])
{
- // TK remove hard-code to DIMM0, use REL_POS attr
const auto l_dimm = i_spd_data.get_dimm_target();
- const size_t l_dimm_index = 0;
+ const size_t l_dimm_index = mss::index(l_dimm);
FAPI_ASSERT( l_dimm_index < X,
fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
@@ -321,6 +295,49 @@ fapi_try_exit:
///
/// @brief Helper function to update the structure that holds attr data
/// @tparam T the FAPI2 TargetType
+/// @tparam IT Input/Output data type
+/// @tparam FFDC the FFDC type
+/// @tparam X size of 1st array index
+/// @param[in] i_target the FAPI2 target
+/// @param[in] i_setting array to set
+/// @param[in] i_ffdc_code FFDC function code
+/// @param[out] o_data attribute data structure to set
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < fapi2::TargetType T,
+ typename IT,
+ typename FFDC,
+ size_t X >
+inline fapi2::ReturnCode update_data( const fapi2::Target<T>& i_target,
+ const IT i_setting,
+ const FFDC i_ffdc_code,
+ IT (&o_data)[X])
+{
+ const size_t l_dimm_index = mss::index(i_target);
+
+ FAPI_ASSERT( l_dimm_index < X,
+ fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
+ .set_INDEX(l_dimm_index)
+ .set_LIST_SIZE(X)
+ .set_FUNCTION(i_ffdc_code)
+ .set_TARGET(i_target),
+ "Dimm index (%d) was larger than max (%d) on %s",
+ l_dimm_index,
+ X,
+ mss::spd::c_str(i_target) );
+
+ FAPI_DBG("Updating data[%d] with %d for %s", l_dimm_index, i_setting, spd::c_str(i_target));
+ o_data[l_dimm_index] = i_setting;
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to update the structure that holds attr data
+/// @tparam T the FAPI2 TargetType
/// @tparam IT Input data type
/// @tparam FFDC type
/// @tparam OT Output data type
@@ -386,39 +403,18 @@ inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
{
const auto l_attr_target = mss::find_target<TT::TARGET_TYPE>(i_target);
typename TT::attr_type l_attr_list = {};
- FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list) );
- FAPI_TRY( update_data(i_target, i_setting, TT::FFDC_CODE, l_attr_list) );
- FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list) );
+ FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list),
+ "Failed get_attr() for %s", spd::c_str(i_target) );
-fapi_try_exit:
- return fapi2::current_err;
-}
+ FAPI_TRY( update_data(i_target, i_setting, TT::FFDC_CODE, l_attr_list),
+ "Failed update_data for %s", spd::c_str(i_target) );
-///
-/// @brief Helper function to get the target associated with generic attribute setting
-/// @param[in] i_target
-/// return a fapi2 MEM_PORT target
-///
-static inline fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> get_attr_target(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target)
-{
- return mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(i_target);
-}
+ FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list),
+ "Failed set_attr() for %s", spd::c_str(i_target) );
-///
-/// @brief Helper function to get the target associated with generic attribute setting
-/// @param[in] i_target
-/// return a fapi2 MEM_PORT target
-///
-inline fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> get_attr_target(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
- i_target)
-{
- // Explorer has only one MEM_PORT per OCMB, so we are looking for the 0th pos relative to the OCMB
- // Will need to update to take into account a mem_channel index in VPDinfo if we ever support this.
- // Per FW, for the DDIMM case we can't support unique settings per channel because the SPD
- // doesn't know about anything outside of the DDIMM itself.
- return mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target)[0];
+fapi_try_exit:
+ return fapi2::current_err;
}
///
@@ -444,148 +440,22 @@ inline fapi2::ReturnCode set_field(const DT& i_data,
// Get the attribute data in its entirety
typename TT::attr_type l_attr_list = {};
- FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list) );
+ FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list),
+ "Failed get_attr()");
// Update the portion of interest (can vary per dimm and/or rank)
- FAPI_TRY( update_data(i_data, i_setting, TT::FFDC_CODE, l_attr_list) );
+ FAPI_TRY( update_data(i_data, i_setting, TT::FFDC_CODE, l_attr_list),
+ "Failed update_data()");
// Set the contents back to the attribute
- FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list) );
+ FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list),
+ "Failed set_attr()");
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Template recursive algorithm for setting attrs
-/// @class attr_engine
-/// @tparam ET enum type - conceptually a list of attrs to set
-/// @tparam F enum value - the specific attr value from ET to set
-/// @tparam TT defaulted to attrEngineTraits<ET, F>
-/// @tparam V defaulted to void (dispatch tag)
-///
-template < typename ET,
- ET F,
- typename TT = mss::attrEngineTraits<ET, F>,
- typename V = void >
-struct attr_engine
-{
- ///
- /// @brief Sets attributes fields F in ET
- /// @tparam T the fapi2 target type
- /// @param[in] i_target the fapi2 target
- /// @return FAPI2_RC_SUCCESS iff oka
- ///
- template < fapi2::TargetType T >
- static fapi2::ReturnCode single_set(const fapi2::Target<T>& i_target)
- {
- typename TT::attr_integral_type l_value = 0;
- FAPI_TRY( TT::get_value_to_set(i_target, l_value) );
-
- FAPI_TRY( set_field<TT>(i_target, l_value) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Sets attributes fields F in ET
- /// @tparam DT the data type
- /// @param[in] i_data the data (efd_decoder, spd_facade, etc.)
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- template < typename DT >
- static fapi2::ReturnCode single_set(const DT& i_data)
- {
- typename TT::attr_integral_type l_value = 0;
- FAPI_TRY( TT::get_value_to_set(i_data, l_value) );
-
- FAPI_TRY( set_field<TT>(i_data, l_value) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Sets attributes fields F in ET
- /// @tparam DT the data type
- /// @param[in] i_data the data (efd_decoder, spd_facade, etc.)
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- template < typename DT >
- static fapi2::ReturnCode set(const DT& i_data)
- {
- FAPI_TRY( (attr_engine<ET, F>::single_set(i_data)) );
-
- // Compiler isn't smart enough to deduce F - 1u (decrementing the enum values by 1)
- // Cast needed to help the compiler deduce this value is an ET type
- // This does the recursive call to unroll a compile-time looping of a enum list of attrs to set
- FAPI_TRY( (attr_engine < ET, static_cast<ET>(F - 1u) >::set(i_data)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Sets attributes fields F in ET
- /// @tparam T the fapi2 target type
- /// @param[in] i_target the fapi2 target
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- template < fapi2::TargetType T >
- static fapi2::ReturnCode set(const fapi2::Target<T>& i_target)
- {
- FAPI_TRY( (attr_engine<ET, F>::single_set(i_target)) );
-
- // Compiler isn't smart enough to deduce F - 1u (decrementing the enum values by 1)
- // Cast needed to help the compiler deduce this value is an ET type
- // This does the recursive call to unroll a compile-time looping of a enum list of attrs to set
- FAPI_TRY( (attr_engine < ET, static_cast<ET>(F - 1u) >::set(i_target)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-};
-
-///
-/// @brief Algorithm for setting SI attrs
-/// @class attr_engine
-/// @tparam ET enum type
-/// @tparam F enum value
-/// @note partial specialization when F == 0 (base case). Which is a NOP.
-///
-template < typename ET, ET F>
-struct attr_engine< ET,
- F,
- mss::attrEngineTraits<ET, F>,
- typename std::enable_if<0u == F>::type >
-{
- ///
- /// @brief Sets attributes fields F in ET
- /// @tparam T the fapi2 target type
- /// @param[in] i_target the fapi2 target
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- template < fapi2::TargetType T >
- static fapi2::ReturnCode set(const fapi2::Target<T>& i_target)
- {
- return fapi2::FAPI2_RC_SUCCESS;
- }
-
- ///
- /// @brief Sets attributes fields F in ET
- /// @tparam DT the data type
- /// @param[in] i_data the data (efd_decoder, spd_facade, etc.)
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- template < typename DT >
- static fapi2::ReturnCode set(const DT& i_data)
- {
- return fapi2::FAPI2_RC_SUCCESS;
- }
-};
-
-///
/// @brief Return a DIMM's position from a fapi2 target
/// @tparam TT Traits associated with DIMM position (e.g. dimmPosTraits)
/// @tparam OT the output type
@@ -609,6 +479,39 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Shift the bits of the SPD field to match the attribute format
+/// @param[in] i_value ODT field value from SPD
+/// @return ATTR formatted uint8_t
+///
+static inline uint8_t align_odt_field_to_attr(const uint8_t i_value)
+{
+ static constexpr uint8_t ODT2_OLD = 2;
+ static constexpr uint8_t ODT3_OLD = 3;
+ static constexpr uint8_t ODT2 = 4;
+ static constexpr uint8_t ODT3 = 5;
+
+ fapi2::buffer<uint8_t> l_value(i_value);
+ // Map to attribute bitmap
+ reverse(l_value);
+
+ // l_value currently looks like:
+ // XXYY0000
+ // ODT
+ // 0123----
+ //
+ // We need it to look like:
+ // XX00YY00
+ // 01--23--
+ l_value.writeBit<ODT2>(l_value.getBit<ODT2_OLD>());
+ l_value.writeBit<ODT3>(l_value.getBit<ODT3_OLD>());
+
+ l_value.clearBit<ODT2_OLD>();
+ l_value.clearBit<ODT3_OLD>();
+
+ return l_value();
+}
+
}// gen
}//mss
diff --git a/src/import/generic/memory/lib/data_engine/p9a/p9a_data_init_traits.H b/src/import/generic/memory/lib/data_engine/p9a/p9a_data_init_traits.H
deleted file mode 100644
index d0f00d6f0..000000000
--- a/src/import/generic/memory/lib/data_engine/p9a/p9a_data_init_traits.H
+++ /dev/null
@@ -1,573 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/data_engine/p9a/p9a_data_init_traits.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
-/* [+] 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 p9a_data_init_traits.H
-/// @brief Trait class definitions for Axone pre_data_init
-///
-// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
-// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com>
-// *HWP Team: Memory
-// *HWP Level: 2
-// *HWP Consumed by: HB:CI
-
-#ifndef _MSS_P9A_PRE_DATA_INIT_TRAITS_H_
-#define _MSS_P9A_PRE_DATA_INIT_TRAITS_H_
-
-#include <fapi2.H>
-#include <generic/memory/lib/data_engine/data_engine_traits_def.H>
-#include <generic/memory/lib/data_engine/data_engine_utils.H>
-#include <generic/memory/lib/spd/spd_facade.H>
-#include <generic/memory/lib/mss_generic_attribute_getters.H>
-#include <generic/memory/lib/mss_generic_attribute_setters.H>
-
-namespace mss
-{
-
-///
-/// @brief Helper function to get dimm_type from SPD
-/// @param[in] i_spd_data SPD data
-/// @param[in] i_setting value we want to set attr with
-/// @return FAPI2_RC_SUCCESS iff okay
-///
-static fapi2::ReturnCode get_dimm_type(const spd::facade& i_spd_data,
- uint8_t& o_setting)
-{
- // =========================================================
- // DDR4 SPD Document Release 4
- // Byte 3 (0x003): Key Byte / Module Type
- // =========================================================
- static const std::vector< std::pair<uint8_t, uint8_t> > BASE_MODULE_TYPE_MAP =
- {
- //{key byte, dimm type}
- {1, fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_RDIMM},
- {2, fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_UDIMM},
- {10, fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM},
- // All others reserved or not supported
- };
-
- const auto l_dimm = i_spd_data.get_dimm_target();
- uint8_t l_base_module_type = 0;
- FAPI_TRY(i_spd_data.base_module(l_base_module_type));
- FAPI_TRY(lookup_table_check(l_dimm, BASE_MODULE_TYPE_MAP, SET_ATTR_DIMM_TYPE, l_base_module_type, o_setting));
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Helper function to get dram_gen from SPD
-/// @param[in] i_spd_data SPD data
-/// @param[in] i_setting value we want to set attr with
-/// @return FAPI2_RC_SUCCESS iff okay
-///
-static fapi2::ReturnCode get_dram_gen(const spd::facade& i_spd_data,
- uint8_t& o_setting)
-{
- // =========================================================
- // DDR4 SPD Document Release 4
- // Byte 2 (0x002): Key Byte / DRAM Device Type
- // =========================================================
- static const std::vector< std::pair<uint8_t, uint8_t> > DRAM_GEN_MAP =
- {
- //{key value, dram gen}
- {0x0C, fapi2::ENUM_ATTR_MEM_EFF_DRAM_GEN_DDR4}
- // Other key bytes reserved or not supported
- };
-
- const auto l_dimm = i_spd_data.get_dimm_target();
- uint8_t l_device_type = 0;
- FAPI_TRY(i_spd_data.device_type(l_device_type));
- FAPI_TRY(lookup_table_check(l_dimm, DRAM_GEN_MAP, SET_ATTR_DRAM_GEN, l_device_type, o_setting));
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note pre_data_init_fields, DIMM_TYPE specialization
-///
-template<>
-struct attrEngineTraits<pre_data_init_fields, DIMM_TYPE>
-{
- using attr_type = fapi2::ATTR_MEM_EFF_DIMM_TYPE_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DIMM_TYPE_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DIMM_TYPE;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the attr target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return mss::attr::get_dimm_type(i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the attr target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return mss::attr::set_dimm_type(i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
- attr_integral_type& o_setting)
- {
- return get_dimm_type(i_spd_data, o_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note pre_data_init_fields, DRAM_GEN specialization
-///
-template<>
-struct attrEngineTraits<pre_data_init_fields, DRAM_GEN>
-{
- using attr_type = fapi2::ATTR_MEM_EFF_DRAM_GEN_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DRAM_GEN_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_GEN;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the attr target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return mss::attr::get_dram_gen(i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the attr target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return mss::attr::set_dram_gen(i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
- attr_integral_type& o_setting)
- {
- return get_dram_gen(i_spd_data, o_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note pre_data_init_fields, HOST_TO_DDR_SPEED_RATIO specialization
-///
-template<>
-struct attrEngineTraits<pre_data_init_fields, HOST_TO_DDR_SPEED_RATIO>
-{
- using attr_type = fapi2::ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_HOST_TO_DDR_SPEED_RATIO;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the attr target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return mss::attr::get_host_to_ddr_speed_ratio(i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the attr target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return mss::attr::set_host_to_ddr_speed_ratio(i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
- attr_integral_type& o_setting)
- {
- // =========================================================
- // DDR4 SPD Document Release 4
- // Byte 220 (0x0DC): Host Interface Speed to DDR Interface Speed Ratio
- // =========================================================
- static const std::vector< std::pair<uint8_t, uint8_t> > HOST_TO_DDR_SPEED_RATIO_MAP =
- {
- // {key byte, speed ratio}
- {0, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_1_TO_1},
- {1, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_2_TO_1},
- {2, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_4_TO_1},
- {3, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_8_TO_1},
- {4, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_16_TO_1},
- {5, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_32_TO_1},
- {6, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_64_TO_1},
- {7, fapi2::ENUM_ATTR_MEM_EFF_HOST_TO_DDR_SPEED_RATIO_128_TO_1},
- // All others reserved or not supported
- };
-
- const auto l_dimm = i_spd_data.get_dimm_target();
-
- attr_integral_type l_value = 0;
- FAPI_TRY( i_spd_data.host_to_ddr_speed_ratio(l_value),
- "%s failed to get host to DDR speed ratio from SPD", spd::c_str(l_dimm) );
-
- FAPI_TRY( lookup_table_check(l_dimm, HOST_TO_DDR_SPEED_RATIO_MAP, FFDC_CODE, l_value, o_setting),
- "%s failed HOST_TO_DDR_SPEED_RATIO lookup check", spd::c_str(l_dimm) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note pre_data_init_fields, HYBRID specialization
-///
-template<>
-struct attrEngineTraits<pre_data_init_fields, HYBRID>
-{
- using attr_type = fapi2::ATTR_MEM_EFF_HYBRID_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_HYBRID_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_HYBRID;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the attr target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return mss::attr::get_hybrid(i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the attr target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return mss::attr::set_hybrid(i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
- attr_integral_type& o_setting)
- {
- // =========================================================
- // DDR4 SPD Document Release 4
- // Byte 3 (0x003): Key Byte / Module Type - Hybrid
- // =========================================================
- static const std::vector< std::pair<uint8_t, uint8_t> > HYBRID_MAP =
- {
- //{key byte, dimm type}
- {0, fapi2::ENUM_ATTR_MEM_EFF_HYBRID_NOT_HYBRID},
- {1, fapi2::ENUM_ATTR_MEM_EFF_HYBRID_IS_HYBRID},
- // All others reserved or not supported
- };
-
- uint8_t l_spd_hybrid_type = 0;
- FAPI_TRY(i_spd_data.hybrid(l_spd_hybrid_type));
- FAPI_TRY(lookup_table_check(i_spd_data.get_dimm_target(), HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_type, o_setting));
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note pre_data_init_fields, HYBRID_MEDIA specialization
-///
-template<>
-struct attrEngineTraits<pre_data_init_fields, HYBRID_MEDIA>
-{
- using attr_type = fapi2::ATTR_MEM_EFF_HYBRID_MEMORY_TYPE_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_HYBRID_MEMORY_TYPE_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_HYBRID_MEDIA;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the attr target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return mss::attr::get_hybrid_memory_type(i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the attr target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return mss::attr::set_hybrid_memory_type(i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
- attr_integral_type& o_setting)
- {
- // =========================================================
- // DDR4 SPD Document Release 4
- // Byte 3 (0x003): Key Byte / Module Type - Hybrid
- // =========================================================
- static const std::vector< std::pair<uint8_t, uint8_t> > HYBRID_MEMORY_TYPE_MAP =
- {
-
- //{key byte, dimm type}
- {0, fapi2::ENUM_ATTR_MEM_EFF_HYBRID_MEMORY_TYPE_NONE},
- {1, fapi2::ENUM_ATTR_MEM_EFF_HYBRID_MEMORY_TYPE_NVDIMM},
- // All others reserved or not supported
- };
-
- uint8_t l_spd_hybrid_media = 0;
- FAPI_TRY(i_spd_data.hybrid_media(l_spd_hybrid_media));
- FAPI_TRY(lookup_table_check(i_spd_data.get_dimm_target(), HYBRID_MEMORY_TYPE_MAP, SET_ATTR_HYBRID_MEDIA,
- l_spd_hybrid_media, o_setting));
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-};
-
-///
-/// @brief Gets master ranks from SPD
-/// @param[out] o_output num package ranks per DIMM
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-static fapi2::ReturnCode get_master_ranks(const spd::facade& i_spd_data,
- const generic_ffdc_codes i_ffdc,
- uint8_t& o_output)
-{
- // =========================================================
- // DDR4 SPD Document Release 4
- // Byte 12 (0x00C): Module Organization
- // =========================================================
- static const std::vector< std::pair<uint8_t, uint8_t> > NUM_PACKAGE_RANKS_MAP =
- {
- // {key byte, num of package ranks per DIMM (package ranks)}
- {0, fapi2::ENUM_ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM_1R},
- {1, fapi2::ENUM_ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM_2R},
- {3, fapi2::ENUM_ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM_4R},
- };
-
- const auto l_dimm = i_spd_data.get_dimm_target();
- uint8_t l_master_ranks_spd = 0;
- FAPI_TRY(i_spd_data.num_package_ranks_per_dimm(l_master_ranks_spd),
- "%s failed to get number of package ranks from SPD", spd::c_str(l_dimm));
-
- FAPI_TRY(lookup_table_check(l_dimm, NUM_PACKAGE_RANKS_MAP, i_ffdc, l_master_ranks_spd,
- o_output), "%s failed MASTER_RANKS lookup check", spd::c_str(l_dimm));
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note pre_data_init_fields, MRANKS specialization
-///
-template<>
-struct attrEngineTraits<pre_data_init_fields, MRANKS>
-{
- using attr_type = fapi2::ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_MRANKS;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the attr target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return mss::attr::get_num_master_ranks_per_dimm(i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the attr target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return mss::attr::set_num_master_ranks_per_dimm(i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
- attr_integral_type& o_setting)
- {
- FAPI_TRY( get_master_ranks(i_spd_data, SET_ATTR_MASTER_RANKS, o_setting) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note pre_data_init_fields, DIMM_RANKS_CNFG specialization
-///
-template<>
-struct attrEngineTraits<pre_data_init_fields, DIMM_RANKS_CNFG>
-{
- using attr_type = fapi2::ATTR_MEM_EFF_DIMM_RANKS_CONFIGED_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_EFF_DIMM_RANKS_CONFIGED_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DIMM_RANKS_CNFG;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the attr target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return mss::attr::get_dimm_ranks_configed(i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the attr target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return mss::attr::set_dimm_ranks_configed(i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const spd::facade& i_spd_data,
- attr_integral_type& o_setting)
- {
- // Set configed ranks. Set the bit representing the master rank configured (0 being left most.) So,
- // a 4R DIMM would be 0b11110000 (0xF0). This is used by PRD.
- fapi2::buffer<uint8_t> l_ranks_configed;
-
- uint8_t l_master_ranks = 0;
- FAPI_TRY( get_master_ranks(i_spd_data, SET_ATTR_RANKS_CONFIGED, l_master_ranks) );
-
- FAPI_TRY( l_ranks_configed.setBit(0, l_master_ranks),
- "%s. Failed to setBit", spd::c_str(i_spd_data.get_dimm_target()) );
-
- o_setting = l_ranks_configed;
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-};
-
-}//mss
-
-#endif
diff --git a/src/import/generic/memory/lib/data_engine/p9n/p9n_data_init_traits.H b/src/import/generic/memory/lib/data_engine/p9n/p9n_data_init_traits.H
deleted file mode 100644
index 5f0207b14..000000000
--- a/src/import/generic/memory/lib/data_engine/p9n/p9n_data_init_traits.H
+++ /dev/null
@@ -1,488 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/data_engine/p9n/p9n_data_init_traits.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
-/* [+] 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 p9n_data_init_traits.H
-/// @brief Trait class definitions for Nimbus pre_data_init
-///
-// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
-// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com>
-// *HWP Team: Memory
-// *HWP Level: 2
-// *HWP Consumed by: CI
-
-#ifndef _MSS_P9N_PRE_DATA_INIT_TRAITS_H_
-#define _MSS_P9N_PRE_DATA_INIT_TRAITS_H_
-
-#include <fapi2.H>
-#include <generic/memory/lib/data_engine/data_engine_traits_def.H>
-#include <generic/memory/lib/data_engine/data_engine.H>
-#include <lib/mss_attribute_accessors.H>
-
-namespace mss
-{
-
-///
-/// @brief Traits for pre_data_engine
-/// @class preDataInitTraits
-/// @note NIMBUS, DIMM_TYPE specialization
-///
-template<>
-class preDataInitTraits<mss::proc_type::NIMBUS, DIMM_TYPE>
-{
- public:
- using attr_type = fapi2::ATTR_EFF_DIMM_TYPE_Type;
- static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_DIMM_TYPE_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DIMM_TYPE;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_TYPE, i_target, o_setting) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, i_target, i_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class preDataInitTraits
-/// @note NIMBUS, DRAM_GEN specialization
-///
-template<>
-class preDataInitTraits<mss::proc_type::NIMBUS, DRAM_GEN>
-{
- public:
- using attr_type = fapi2::ATTR_EFF_DRAM_GEN_Type;
- static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_DRAM_GEN_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_GEN;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_GEN, i_target, o_setting) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, i_target, i_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class preDataInitTraits
-/// @note NIMBUS, HYBRID specialization
-///
-template<>
-class preDataInitTraits<mss::proc_type::NIMBUS, HYBRID>
-{
- public:
- using attr_type = fapi2::ATTR_EFF_HYBRID_Type;
- static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_HYBRID_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_HYBRID;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_HYBRID, i_target, o_setting) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID, i_target, i_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class preDataInitTraits
-/// @note NIMBUS, HYBRID_MEDIA specialization
-///
-template<>
-class preDataInitTraits<mss::proc_type::NIMBUS, HYBRID_MEDIA>
-{
- public:
- using attr_type = fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE_Type;
- static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_HYBRID_MEDIA;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, i_target, o_setting) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, i_target, i_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class preDataInitTraits
-/// @note NIMBUS, MRANKS specialization
-///
-template<>
-class preDataInitTraits<mss::proc_type::NIMBUS, MRANKS>
-{
- public:
- using attr_type = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_Type;
- static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_MRANKS;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, o_setting) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, i_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class preDataInitTraits
-/// @note NIMBUS, DIMM_RANKS_CNFG specialization
-///
-template<>
-class preDataInitTraits<mss::proc_type::NIMBUS, DIMM_RANKS_CNFG>
-{
- public:
- using attr_type = fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED_Type;
- static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DIMM_RANKS_CNFG;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, i_target, o_setting) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, i_target, i_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note AXONE, DIMM_TYPE_METADATA specialization
-///
-template<>
-struct attrEngineTraits<generic_metadata_fields, DIMM_TYPE_METADATA>
-{
- using attr_type = fapi2::ATTR_MEM_DIMM_TYPE_METADATA_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_DIMM_TYPE_METADATA_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DIMM_TYPE_METADATA;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return FAPI_ATTR_GET(fapi2::ATTR_MEM_DIMM_TYPE_METADATA, i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_MEM_DIMM_TYPE_METADATA, i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- attr_integral_type& o_setting)
- {
- return mss::eff_dimm_type(i_target, o_setting);
- }
-};
-
-///
-/// @brief Traits associated with DIMM positioning
-/// @class dimmPosTraits - NIMBUS specializattion
-///
-template<>
-class dimmPosTraits<mss::mc_type::NIMBUS>
-{
- private:
- using PT = posTraits<fapi2::TARGET_TYPE_DIMM>;
- using MT = mss::mcTypeTraits<mc_type::NIMBUS>;
-
- public:
- // Public interface syntatic sugar
- using pos_type = PT::pos_type;
-
- // Proc 0 is DIMM 0-15, proc 2 is 64-79. 64 is the stride between processors
- static constexpr auto DIMM_STRIDE_PER_PROC = 64;
- static constexpr auto TOTAL_DIMM = MT::MC_PER_MODULE * MT::MCS_PER_MC * MT::PORTS_PER_MCS * MT::DIMMS_PER_PORT;
-
- ///
- /// @brief Return the PROC_CHIP parent of a DIMM
- /// @param[in] i_target the dimm target
- /// @return the fapi2 proc target
- ///
- static fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> get_proc(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target)
- {
- // Using fapi2 rather than mss::find as this is pretty low level stuff.
- return i_target.getParent<fapi2::TARGET_TYPE_MCA>().getParent<fapi2::TARGET_TYPE_PROC_CHIP>();
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note generic_metadata_fields, DRAM_GEN_METADATA specialization
-///
-template<>
-struct attrEngineTraits<generic_metadata_fields, DRAM_GEN_METADATA>
-{
- using attr_type = fapi2::ATTR_MEM_DRAM_GEN_METADATA_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_DRAM_GEN_METADATA_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DRAM_GEN_METADATA;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return FAPI_ATTR_GET(fapi2::ATTR_MEM_DRAM_GEN_METADATA, i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_MEM_DRAM_GEN_METADATA, i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- attr_integral_type& o_setting)
- {
- return mss::eff_dram_gen(i_target, o_setting);
- }
-};
-
-///
-/// @brief Traits for pre_data_engine
-/// @class attrEngineTraits
-/// @note generic_metadata_fields, DIMM_POS_METADATA specialization
-///
-template<>
-struct attrEngineTraits<generic_metadata_fields, DIMM_POS_METADATA>
-{
- using attr_type = fapi2::ATTR_MEM_DIMM_POS_METADATA_Type;
- using attr_integral_type = std::remove_all_extents<attr_type>::type;
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::ATTR_MEM_DIMM_POS_METADATA_TargetType;
- static constexpr generic_ffdc_codes FFDC_CODE = SET_DIMM_POS_METADATA;
-
- ///
- /// @brief attribute getter
- /// @param[in] i_target the MCS target
- /// @param[out] o_setting array to populate
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& o_setting)
- {
- return FAPI_ATTR_GET(fapi2::ATTR_MEM_DIMM_POS_METADATA, i_target, o_setting);
- }
-
- ///
- /// @brief attribute setter
- /// @param[in] i_target the MCS target
- /// @param[in] i_setting array to set
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target,
- attr_type& i_setting)
- {
- return FAPI_ATTR_SET(fapi2::ATTR_MEM_DIMM_POS_METADATA, i_target, i_setting);
- }
-
- ///
- /// @brief Computes setting for attribute
- /// @param[in] i_spd_data SPD data
- /// @param[in] i_setting value we want to set attr with
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- static fapi2::ReturnCode get_value_to_set(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- attr_integral_type& o_setting)
- {
- using TT = mss::dimmPosTraits<mss::mc_type::NIMBUS>;
- return gen::dimm_pos<TT>(i_target, o_setting);
- }
-};
-
-///
-/// @brief Value traits for attr_eff_engine_fields
-/// @class attrEngineTraits
-/// @note attr_eff_engine_fields
-///
-template < >
-struct attrEnumTraits<generic_metadata_fields>
-{
- static constexpr size_t DISPATCHER = ATTR_METADATA_DISPATCHER;
-};
-
-}// mss
-
-#endif
diff --git a/src/import/generic/memory/lib/data_engine/pre_data_init.H b/src/import/generic/memory/lib/data_engine/pre_data_init.H
deleted file mode 100644
index df19a86ef..000000000
--- a/src/import/generic/memory/lib/data_engine/pre_data_init.H
+++ /dev/null
@@ -1,324 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/data_engine/pre_data_init.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
-/* [+] 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 pre_data_init.H
-/// @brief Class to set preliminary eff_config attributes
-///
-// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
-// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com>
-// *HWP Team: Memory
-// *HWP Level: 2
-// *HWP Consumed by: CI
-
-#ifndef _MSS_PRE_DATA_INIT_H_
-#define _MSS_PRE_DATA_INIT_H_
-
-#include <cstring>
-#include <fapi2.H>
-#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
-#include <generic/memory/lib/spd/spd_facade.H>
-#include <generic/memory/lib/utils/find.H>
-#include <generic/memory/lib/data_engine/p9n/p9n_data_init_traits.H>
-#include <generic/memory/lib/data_engine/data_engine_utils.H>
-
-namespace mss
-{
-
-///
-/// @brief Sets preliminary data fields
-/// @tparam P processor type (e.g. NIMBUS, AXONE, etc.)
-/// @tparam F pre_data_init_fields
-/// @tparam T FAPI2 target type
-/// @tparam IT Input data type
-/// @tparam TT defaulted to preDataInitTraits<T>
-/// @param[in] i_setting value we want to set attr with
-/// @return FAPI2_RC_SUCCESS iff okay
-///
-template< proc_type P,
- pre_data_init_fields F,
- fapi2::TargetType T,
- typename IT,
- typename TT = preDataInitTraits<P, F>
- >
-inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
- const IT i_setting)
-{
- FAPI_TRY( (set_field<P, TT>(i_target, i_setting)),
- "Failed set_field() for %s", spd::c_str(i_target) );
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Data structure to set pre-effective config data
-/// @class pre_data_engine
-/// @tparam P supported processor type (e.g. Nimbus, Axone, etc.)
-///
-template< proc_type P >
-class pre_data_engine
-{
- private:
-
- fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_dimm;
- spd::facade iv_spd_data;
-
- public:
-
- static const std::vector<std::pair<uint8_t, uint8_t> > NUM_PACKAGE_RANKS_MAP;
- static const std::vector<std::pair<uint8_t, uint8_t> > BASE_MODULE_TYPE_MAP;
- static const std::vector<std::pair<uint8_t, uint8_t> > DRAM_GEN_MAP;
- static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MAP;
- static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MEMORY_TYPE_MAP;
-
- ///
- /// @brief ctor
- /// @param[in] i_target the DIMM target
- /// @param[in] i_spd_data SPD decoder
- ///
- pre_data_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const spd::facade& i_spd_data):
- iv_dimm(i_target),
- iv_spd_data(i_spd_data)
- {}
-
- ///
- /// @brief default dtor
- ///
- ~pre_data_engine() = default;
-
- ///
- /// @brief Set ATTR_EFF_DIMM_TYPE
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- fapi2::ReturnCode set_dimm_type()
- {
- uint8_t l_base_module_type = 0;
- uint8_t l_dimm_type = 0;
-
- FAPI_TRY(iv_spd_data.base_module(l_base_module_type));
- FAPI_TRY(lookup_table_check(iv_dimm, BASE_MODULE_TYPE_MAP, SET_ATTR_DIMM_TYPE, l_base_module_type, l_dimm_type));
- FAPI_TRY( (set_field<P, DIMM_TYPE>(iv_dimm, l_dimm_type)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Set ATTR_EFF_DRAM_GEN
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- fapi2::ReturnCode set_dram_gen()
- {
- uint8_t l_device_type = 0;
- uint8_t l_dram_gen = 0;
-
- FAPI_TRY(iv_spd_data.device_type(l_device_type));
- FAPI_TRY(lookup_table_check(iv_dimm, DRAM_GEN_MAP, SET_ATTR_DRAM_GEN, l_device_type, l_dram_gen));
-
- FAPI_TRY( (set_field<P, DRAM_GEN>(iv_dimm, l_dram_gen)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Set ATTR_EFF_HYBRID
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- fapi2::ReturnCode set_hybrid()
- {
- uint8_t l_spd_hybrid_type = 0;
- uint8_t l_hybrid = 0;
-
- FAPI_TRY(iv_spd_data.hybrid(l_spd_hybrid_type));
- FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_type, l_hybrid));
-
- FAPI_TRY( (set_field<P, HYBRID>(iv_dimm, l_hybrid)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Set ATTR_EFF_HYBRID_MEMORY_TYPE
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- fapi2::ReturnCode set_hybrid_media()
- {
- uint8_t l_hybrid_media = 0;
- uint8_t l_spd_hybrid_media = 0;
-
- FAPI_TRY(iv_spd_data.hybrid_media(l_spd_hybrid_media));
- FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_media, l_hybrid_media));
-
- FAPI_TRY( (set_field<P, HYBRID_MEDIA>(iv_dimm, l_hybrid_media)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Set ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- fapi2::ReturnCode set_master_ranks()
- {
- uint8_t l_master_ranks = 0;
- FAPI_TRY( get_master_ranks(l_master_ranks) );
-
- FAPI_TRY( (set_field<P, MRANKS>(iv_dimm, l_master_ranks)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
- /// @brief Sets ATTR_EFF_DIMM_RANKS_CONFIGED
- /// @return FAPI2_RC_SUCCESS iff okay
- ///
- fapi2::ReturnCode set_dimm_ranks_configured()
- {
- // Set configed ranks. Set the bit representing the master rank configured (0 being left most.) So,
- // a 4R DIMM would be 0b11110000 (0xF0). This is used by PRD.
- fapi2::buffer<uint8_t> l_ranks_configed;
-
- // Make sure the number of master ranks is setup
- uint8_t l_master_ranks = 0;
- FAPI_TRY( get_master_ranks(l_master_ranks) );
-
- FAPI_TRY( l_ranks_configed.setBit(0, l_master_ranks),
- "%s. Failed to setBit", spd::c_str(iv_dimm) );
-
- FAPI_TRY( (set_field<P, DIMM_RANKS_CNFG>(iv_dimm, uint8_t(l_ranks_configed))) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- private:
-
- ///
- /// @brief Gets master ranks from SPD
- /// @param[out] o_output num package ranks per DIMM
- /// @return FAPI2_RC_SUCCESS iff ok
- ///
- fapi2::ReturnCode get_master_ranks(uint8_t& o_output)
- {
- // Sets up commonly used member variables
- uint8_t l_master_ranks_spd = 0;
- FAPI_TRY(iv_spd_data.num_package_ranks_per_dimm(l_master_ranks_spd),
- "%s failed to get number of package ranks from SPD", spd::c_str(iv_dimm));
-
- FAPI_TRY(lookup_table_check(iv_dimm, NUM_PACKAGE_RANKS_MAP, PRE_DATA_ENGINE_CTOR, l_master_ranks_spd,
- o_output), "%s failed MASTER_RANKS lookup check", spd::c_str(iv_dimm));
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-};
-
-///
-/// @brief Sets pre_eff_config attributes
-/// @tparam P processor type
-/// @param[in] i_target the DIMM target
-/// @param[in] i_spd_decoder SPD decoder
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-template <mss::proc_type P>
-inline fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const spd::facade& i_spd_decoder );
-
-///
-/// @brief Sets pre_eff_config attributes - NIMBUS specialization
-/// @param[in] i_target the DIMM target
-/// @param[in] i_spd_decoder SPD decoder
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-template <>
-inline fapi2::ReturnCode set_pre_init_attrs<mss::proc_type::NIMBUS>( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
- i_target,
- const spd::facade& i_spd_decoder )
-{
- // TK explicitly forcing this API to only run in Nimbus, need to move pre_data_engine to Nimbus chip path,
- // using template recursive algorithm moving forward
- mss::pre_data_engine<mss::proc_type::NIMBUS> l_data_engine(i_target, i_spd_decoder);
-
- // Set attributes needed before eff_config
- // DIMM type and DRAM gen are needed for c_str to aid debugging
- FAPI_TRY(l_data_engine.set_dimm_type(), "Failed to set DIMM type %s", mss::spd::c_str(i_target) );
- FAPI_TRY(l_data_engine.set_dram_gen(), "Failed to set DRAM gen %s", mss::spd::c_str(i_target) );
-
- // Hybrid and hybrid media help detect hybrid modules, specifically NVDIMMs for Nimbus
- FAPI_TRY(l_data_engine.set_hybrid(), "Failed to set Hybrid %s", mss::spd::c_str(i_target) );
- FAPI_TRY(l_data_engine.set_hybrid_media(), "Failed to set Hybrid Media %s", mss::spd::c_str(i_target) );
-
- // Number of master ranks needed for VPD decoding
- // and dimm_ranks_configured is a PRD attr...
- FAPI_TRY(l_data_engine.set_master_ranks(), "Failed to set Master ranks %s", mss::spd::c_str(i_target) );
- FAPI_TRY(l_data_engine.set_dimm_ranks_configured(), "Failed to set DIMM ranks configured %s",
- mss::spd::c_str(i_target) );
-
- FAPI_TRY( mss::attr_derived_engine<mss::generic_metadata_fields>::set(i_target) );
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Sets pre_eff_config attributes
-/// @tparam P processor type
-/// @tparam T fapi2::TargetType
-/// @param[in] i_target the target on which to operate
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-template <mss::proc_type P, fapi2::TargetType T>
-fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<T>& i_target )
-{
- for( const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
- {
- std::vector<uint8_t> l_raw_spd;
- FAPI_TRY(mss::spd::get_raw_data(d, l_raw_spd));
- {
- // Gets the SPD facade
- fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS);
- mss::spd::facade l_spd_decoder(d, l_raw_spd, l_rc);
-
- // Checks that the facade was setup correctly
- FAPI_TRY(l_rc, "Failed to initialize SPD facade for %s", mss::spd::c_str(d));
-
- // Sets pre-init attributes
- FAPI_TRY(mss::set_pre_init_attrs<P>(d, l_spd_decoder), "%s failed to set pre init attrs", mss::spd::c_str(d) );
- }
- }
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-}//mss
-
-#endif
diff --git a/src/import/generic/memory/lib/ecc/ecc.H b/src/import/generic/memory/lib/ecc/ecc.H
index 37a3fc067..610d20489 100644
--- a/src/import/generic/memory/lib/ecc/ecc.H
+++ b/src/import/generic/memory/lib/ecc/ecc.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
+/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,3 +22,759 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file ecc.H
+/// @brief Top level API for MSS ECC
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_ECC_H_
+#define _MSS_ECC_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+#include <generic/memory/lib/ecc/galois.H>
+#include <generic/memory/lib/ecc/hw_mark_store.H>
+#include <generic/memory/lib/ecc/fw_mark_store.H>
+#include <generic/memory/lib/ecc/mainline_nce_trap.H>
+#include <generic/memory/lib/ecc/mainline_rce_trap.H>
+#include <generic/memory/lib/ecc/mainline_mpe_trap.H>
+#include <generic/memory/lib/ecc/mainline_ue_trap.H>
+#include <generic/memory/lib/ecc/mainline_aue_trap.H>
+#include <generic/memory/lib/ecc/mbs_error_vector_trap.H>
+#include <generic/memory/lib/ecc/maint_current_trap.H>
+#include <generic/memory/lib/ecc/read_error_count_regs.H>
+#include <generic/memory/lib/ecc/modal_symbol_count.H>
+#include <generic/memory/lib/ecc/mark_shadow_reg.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+///
+/// @brief Get Hardware Mark Store
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_rank the desired rank
+/// @param[out] o_galois the Galois code of the mark
+/// @param[out] o_confirmed true if the mark is a chipmark
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_hwms( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ uint64_t& o_galois,
+ mss::states& o_confirmed )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::hwms::read(i_target, i_rank, l_buffer) );
+ mss::ecc::hwms::get_chipmark(l_buffer, o_galois);
+ mss::ecc::hwms::get_confirmed(l_buffer, o_confirmed);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Set Hardware Mark Store
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_rank the desired rank
+/// @param[in] i_galois the Galois code of the mark, or set to 0 to clear mark
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode set_hwms( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_galois )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+ uint8_t l_symbol = 0;
+
+ // galois value of 0 means to clear the mark so only fill in fields if non-zero
+ if (i_galois != 0)
+ {
+ // check for valid Galois code
+ FAPI_TRY( mss::ecc::galois_to_symbol( (uint8_t)i_galois, l_symbol) );
+
+ mss::ecc::hwms::set_chipmark(l_buffer, i_galois);
+ mss::ecc::hwms::set_confirmed(l_buffer, mss::YES);
+ mss::ecc::hwms::set_exit_1(l_buffer, mss::YES);
+ }
+
+ FAPI_TRY( mss::ecc::hwms::write(i_target, i_rank, l_buffer) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Firmware Mark Store
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_rank the desired rank
+/// @param[out] o_galois the Galois code of the mark
+/// @param[out] o_type the type code of the mark
+/// @param[out] o_region the region code of the mark
+/// @param[out] o_address the starting address of the mark
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_fwms( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ uint64_t& o_galois,
+ mss::ecc::fwms::mark_type& o_type,
+ mss::ecc::fwms::mark_region& o_region,
+ mss::mcbist::address& o_address )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::fwms::read(i_target, i_rank, l_buffer) );
+ mss::ecc::fwms::get_mark(l_buffer, o_galois);
+ mss::ecc::fwms::get_type(l_buffer, o_type);
+ mss::ecc::fwms::get_region(l_buffer, o_region);
+ mss::ecc::fwms::get_address(l_buffer, o_address);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Set Firmware Mark Store
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_rank the desired rank
+/// @param[in] i_galois the Galois code of the mark, or set to 0 to clear mark
+/// @param[in] i_type the type code of the mark
+/// @param[in] i_region the region code of the mark
+/// @param[in] i_address the starting address of the mark
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode set_fwms( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_galois,
+ const mss::ecc::fwms::mark_type i_type,
+ const mss::ecc::fwms::mark_region i_region,
+ const mss::mcbist::address i_address )
+{
+ fapi2::buffer<uint64_t> l_buffer = 0;
+ uint8_t l_symbol = 0;
+
+ // galois value of 0 means to clear the mark so only fill in fields if non-zero
+ if (i_galois != 0)
+ {
+ // check for valid Galois code
+ FAPI_TRY( mss::ecc::galois_to_symbol( (uint8_t)i_galois, l_symbol) );
+
+ mss::ecc::fwms::set_mark(l_buffer, i_galois);
+ mss::ecc::fwms::set_type(l_buffer, i_type);
+ mss::ecc::fwms::set_region(l_buffer, i_region);
+ mss::ecc::fwms::set_address(l_buffer, i_address);
+ mss::ecc::fwms::set_exit_1(l_buffer, mss::YES);
+ }
+
+ FAPI_TRY( mss::ecc::fwms::write(i_target, i_rank, l_buffer) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Query Hardware Marks
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_marks vector of Galois codes of any marks set
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+/// @note no rank information is returned
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode get_hw_marks( const fapi2::Target<T>& i_target,
+ std::vector<uint64_t>& o_marks )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+ uint64_t l_galois = 0;
+ auto l_confirmed = mss::states::NO;
+
+ o_marks.clear();
+
+ for (uint64_t l_rank = 0; l_rank < TT::ECC_MAX_MRANK_PER_PORT; ++l_rank)
+ {
+ FAPI_TRY( get_hwms(i_target, l_rank, l_galois, l_confirmed) );
+
+ if (l_confirmed == mss::states::YES)
+ {
+ o_marks.push_back(l_galois);
+ }
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Query Firmware Marks
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_marks vector of Galois codes of any marks set
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+/// @note no rank information is returned
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode get_fw_marks( const fapi2::Target<T>& i_target,
+ std::vector<uint64_t>& o_marks )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+ uint64_t l_galois = 0;
+ auto l_type = mss::ecc::fwms::mark_type::CHIP;
+ auto l_region = mss::ecc::fwms::mark_region::UNIVERSAL;
+ mss::mcbist::address l_address;
+
+ o_marks.clear();
+
+ for (uint64_t l_rank = 0; l_rank < TT::ECC_MAX_MRANK_PER_PORT; ++l_rank)
+ {
+ FAPI_TRY( get_fwms(i_target, l_rank, l_galois, l_type, l_region, l_address) );
+
+ if (l_region != mss::ecc::fwms::mark_region::DISABLED)
+ {
+ o_marks.push_back(l_galois);
+ }
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline NCE address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_address the trap address of the last mainline nce
+/// @param[out] o_on_rce mss::YES if nce is part of an rce
+/// @param[out] o_is_tce mss::YES if nce is a tce
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_nce_addr_trap( const fapi2::Target<T>& i_target,
+ mss::mcbist::address& o_address,
+ mss::states& o_on_rce,
+ mss::states& o_is_tce )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mainline_nce_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_nce_trap::get_address(l_buffer, o_address);
+ mss::ecc::mainline_nce_trap::get_nce_on_rce(l_buffer, o_on_rce);
+ mss::ecc::mainline_nce_trap::get_nce_is_tce(l_buffer, o_is_tce);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline NCE error vector traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_galois the Galois code
+/// @param[out] o_magnitude the magnitude of the error
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_nce_error_vector_trap( const fapi2::Target<T>& i_target,
+ uint64_t& o_galois,
+ uint64_t& o_magnitude )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mbs_error_vector_trap::read(i_target, l_buffer) );
+ mss::ecc::mbs_error_vector_trap::get_nce_galois(i_target, l_buffer, o_galois);
+ mss::ecc::mbs_error_vector_trap::get_nce_magnitude(i_target, l_buffer, o_magnitude);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline TCE address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_address the trap address of the last mainline nce
+/// @param[out] o_on_rce mss::YES if nce is part of an rce
+/// @param[out] o_is_tce mss::YES if nce is a tce
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_tce_addr_trap( const fapi2::Target<T>& i_target,
+ mss::mcbist::address& o_address,
+ mss::states& o_on_rce,
+ mss::states& o_is_tce )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mainline_nce_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_nce_trap::get_address(l_buffer, o_address);
+ mss::ecc::mainline_nce_trap::get_nce_on_rce(l_buffer, o_on_rce);
+ mss::ecc::mainline_nce_trap::get_nce_is_tce(l_buffer, o_is_tce);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline TCE error vector traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_nce_galois the Galois code
+/// @param[out] o_nce_magnitude the magnitude of the error
+/// @param[out] o_tce_galois the Galois code
+/// @param[out] o_tce_magnitude the magnitude of the error
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_tce_error_vector_trap( const fapi2::Target<T>& i_target,
+ uint64_t& o_nce_galois,
+ uint64_t& o_nce_magnitude,
+ uint64_t& o_tce_galois,
+ uint64_t& o_tce_magnitude )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mbs_error_vector_trap::read(i_target, l_buffer) );
+ mss::ecc::mbs_error_vector_trap::get_nce_galois(i_target, l_buffer, o_nce_galois);
+ mss::ecc::mbs_error_vector_trap::get_nce_magnitude(i_target, l_buffer, o_nce_magnitude);
+ mss::ecc::mbs_error_vector_trap::get_tce_galois(i_target, l_buffer, o_tce_galois);
+ mss::ecc::mbs_error_vector_trap::get_tce_magnitude(i_target, l_buffer, o_tce_magnitude);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline MPE address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_address the trap address of the last mainline mpe
+/// @param[out] o_on_rce mss::YES if mpe is part of an rce
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_mpe_addr_trap( const fapi2::Target<T>& i_target,
+ mss::mcbist::address& o_address,
+ mss::states& o_on_rce )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mainline_mpe_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_mpe_trap::get_address(l_buffer, o_address);
+ mss::ecc::mainline_mpe_trap::get_mpe_on_rce(l_buffer, o_on_rce);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline RCE address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_address the trap address of the last mainline rce
+/// @param[out] o_nce_on_rce mss::YES if nce is part of an rce
+/// @param[out] o_tce_on_rce mss::YES if tce is part of an rce
+/// @param[out] o_mpe_on_rce mss::YES if mpe is part of an rce
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_rce_addr_trap( const fapi2::Target<T>& i_target,
+ mss::mcbist::address& o_address,
+ mss::states& o_nce_on_rce,
+ mss::states& o_tce_on_rce,
+ mss::states& o_mpe_on_rce )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mainline_rce_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_rce_trap::get_address(l_buffer, o_address);
+
+ FAPI_TRY( mss::ecc::mainline_nce_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_nce_trap::get_nce_on_rce(l_buffer, o_nce_on_rce);
+ mss::ecc::mainline_nce_trap::get_nce_is_tce(l_buffer, o_tce_on_rce);
+
+ FAPI_TRY( mss::ecc::mainline_mpe_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_mpe_trap::get_mpe_on_rce(l_buffer, o_mpe_on_rce);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline UE address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_address the trap address of the last mainline ue
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_ue_addr_trap( const fapi2::Target<T>& i_target,
+ mss::mcbist::address& o_address )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mainline_ue_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_ue_trap::get_address(l_buffer, o_address);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Mainline AUE address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_address the trap address of the last mainline aue
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_aue_addr_trap( const fapi2::Target<T>& i_target,
+ mss::mcbist::address& o_address )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mainline_aue_trap::read(i_target, l_buffer) );
+ mss::ecc::mainline_aue_trap::get_address(l_buffer, o_address);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get IMPE address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_chipmark the mark location (Galois code) of the last mark placed
+/// @param[out] o_rank the rank of the last mark placed
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_impe_addr_trap( const fapi2::Target<T>& i_target,
+ uint64_t& o_chipmark,
+ uint64_t& o_rank )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mark_shadow_reg::read(i_target, l_buffer) );
+ mss::ecc::mark_shadow_reg::get_chipmark(l_buffer, o_chipmark);
+ mss::ecc::mark_shadow_reg::get_rank(l_buffer, o_rank);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Maint Current address traps
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_address the last address executed
+/// @param[out] o_port_trap port value if MCBCFGQ_cfg_current_addr_trap_update_dis == 0
+/// @param[out] o_dimm_trap dimm value if MCBCFGQ_cfg_current_addr_trap_update_dis == 0
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_maint_current_addr_trap( const fapi2::Target<T>& i_target,
+ mss::mcbist::address& o_address,
+ uint64_t& o_port_trap,
+ uint64_t& o_dimm_trap )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::maint_current_trap::read(i_target, l_buffer) );
+ mss::ecc::maint_current_trap::get_address(l_buffer, o_address);
+ mss::ecc::maint_current_trap::get_port(l_buffer, o_port_trap);
+ mss::ecc::maint_current_trap::get_dimm(l_buffer, o_dimm_trap);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Per Symbol Error Counts
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_error_counts vector of symbol error counts
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode get_per_symbol_error_counts( const fapi2::Target<T>& i_target,
+ std::vector<uint64_t>& o_error_counts )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+ uint64_t l_count = 0;
+ o_error_counts.clear();
+
+ for (uint64_t l_index = 0; l_index < TT::NUM_MBSSYM_REGS; ++l_index)
+ {
+ FAPI_TRY( mss::ecc::modal_symbol_count::read(i_target, l_index, l_buffer) );
+
+ for (uint64_t l_symbol = 0; l_symbol < TT::MODAL_SYMBOL_COUNTERS_PER_REG; ++l_symbol)
+ {
+ l_count = 0;
+ mss::ecc::modal_symbol_count::get_count(l_buffer, l_symbol, l_count);
+ o_error_counts.push_back(l_count);
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Intermittent NCE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of intermittent NCE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_intermittent_nce_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg0::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg0::get_intermittent_ce_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Soft NCE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of soft NCE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_soft_nce_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg0::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg0::get_soft_ce_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Hard NCE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of hard NCE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_hard_nce_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg0::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg0::get_hard_ce_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Intermittent MCE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of intermittent MCE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_intermittent_mce_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg0::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg0::get_intermittent_mce_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Soft MCE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of soft MCE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_soft_mce_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg0::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg0::get_soft_mce_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get Hard MCE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of hard MCE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_hard_mce_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg1::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg1::get_hard_mce_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get ICE (IMPE) error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of ICE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_ice_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg1::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg1::get_ice_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get UE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of UE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_ue_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg1::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg1::get_ue_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get AUE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of AUE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_aue_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg1::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg1::get_aue_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get RCE error count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_count count of RCE events
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_rce_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::read_error_count_reg1::read(i_target, l_buffer) );
+ mss::ecc::read_error_count_reg1::get_rce_count(l_buffer, o_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get MCE symbol count
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_symbol0_count count of symbol 0 errors
+/// @param[out] o_symbol1_count count of symbol 1 errors
+/// @param[out] o_symbol2_count count of symbol 2 errors
+/// @param[out] o_symbol3_count count of symbol 3 errors
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode get_mce_symbol_count( const fapi2::Target<T>& i_target,
+ uint64_t& o_symbol0_count,
+ uint64_t& o_symbol1_count,
+ uint64_t& o_symbol2_count,
+ uint64_t& o_symbol3_count )
+{
+ fapi2::buffer<uint64_t> l_buffer;
+
+ FAPI_TRY( mss::ecc::mark_symbol_count_reg::read(i_target, l_buffer) );
+ mss::ecc::mark_symbol_count_reg::get_symbol0_count(l_buffer, o_symbol0_count);
+ mss::ecc::mark_symbol_count_reg::get_symbol1_count(l_buffer, o_symbol1_count);
+ mss::ecc::mark_symbol_count_reg::get_symbol2_count(l_buffer, o_symbol2_count);
+ mss::ecc::mark_symbol_count_reg::get_symbol3_count(l_buffer, o_symbol3_count);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/ecc_traits.H b/src/import/generic/memory/lib/ecc/ecc_traits.H
index 81d264ff7..8018c42ae 100644
--- a/src/import/generic/memory/lib/ecc/ecc_traits.H
+++ b/src/import/generic/memory/lib/ecc/ecc_traits.H
@@ -22,3 +22,33 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file ecc_traits.H
+/// @brief Traits class for the MC ECC syndrome registers
+///
+// *HWP HWP Owner: Matthew Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_ECC_TRAITS_H_
+#define _MSS_ECC_TRAITS_H_
+
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+namespace mss
+{
+
+///
+/// @class eccTraits
+/// @brief a collection of traits associated with the MC ECC interface
+/// @tparam T fapi2::TargetType representing the memory controller
+///
+template< mss::mc_type MC, fapi2::TargetType T >
+class eccTraits;
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/fw_mark_store.H b/src/import/generic/memory/lib/ecc/fw_mark_store.H
index e1fb56927..28e8668fb 100644
--- a/src/import/generic/memory/lib/ecc/fw_mark_store.H
+++ b/src/import/generic/memory/lib/ecc/fw_mark_store.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
+/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,3 +22,597 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file fw_mark_store.H
+/// @brief Subroutines for the MC firmware mark store registers
+///
+// *HWP HWP Owner: Matthew Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_FW_MARK_STORE_H_
+#define _MSS_FW_MARK_STORE_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_fwms_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace fwms
+{
+
+///
+/// @brief chip mark type enums
+///
+enum mark_type
+{
+ SYMBOL = 1,
+ CHIP = 0
+};
+
+///
+/// @brief Chip Mark Region. Used for region field values in the FWMS regs
+///
+enum mark_region
+{
+ DISABLED = 0b000,
+ RESERVED = 0b001,
+ BANK = 0b010,
+ BANKGROUP = 0b011,
+ SRANK = 0b100,
+ MRANK = 0b101,
+ DIMM = 0b110,
+ UNIVERSAL = 0b111
+};
+
+///
+/// @brief Read Firmware Mark Store (FWMS) register
+/// @tparam R master rank number
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t R, fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read_rank( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ static_assert((R < TT::ECC_MAX_MRANK_PER_PORT), "Master rank index failed range check");
+ FAPI_TRY( mss::getScom(i_target, (TT::FIRMWARE_MS0_REG + R), o_data) );
+ FAPI_INF("read_rank<%d>: 0x%016lx", R, o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 0 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank0( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<0>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 1 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank1( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<1>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 2 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank2( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<2>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 3 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank3( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<3>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 4 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank4( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<4>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 5 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank5( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<5>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 6 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank6( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<6>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) rank 7 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank7( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<7>(i_target, o_data) );
+}
+
+///
+/// @brief Read Firmware Mark Store (FWMS) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_rank the master rank index
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ fapi2::buffer<uint64_t>& o_data )
+{
+ switch (i_rank)
+ {
+ case(0):
+ return ( read_rank0(i_target, o_data) );
+
+ case(1):
+ return ( read_rank1(i_target, o_data) );
+
+ case(2):
+ return ( read_rank2(i_target, o_data) );
+
+ case(3):
+ return ( read_rank3(i_target, o_data) );
+
+ case(4):
+ return ( read_rank4(i_target, o_data) );
+
+ case(5):
+ return ( read_rank5(i_target, o_data) );
+
+ case(6):
+ return ( read_rank6(i_target, o_data) );
+
+ case(7):
+ return ( read_rank7(i_target, o_data) );
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_RANK_PASSED()
+ .set_RANK(i_rank)
+ .set_TARGET(i_target)
+ .set_FUNCTION(FWMS_READ),
+ "%s Invalid rank passed to fwms::ecc::read (%d)",
+ mss::c_str(i_target),
+ i_rank);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) register
+/// @tparam R master rank number
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t R, fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write_rank( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ static_assert((R < TT::ECC_MAX_MRANK_PER_PORT), "Master rank index failed range check");
+ FAPI_TRY( mss::putScom(i_target, (TT::FIRMWARE_MS0_REG + R), i_data) );
+ FAPI_DBG("write_rank<%d>: 0x%016lx", R, i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 0 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank0( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<0>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 1 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank1( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<1>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 2 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank2( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<2>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 3 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank3( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<3>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 4 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank4( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<4>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 5 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank5( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<5>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 6 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank6( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<6>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) rank 7 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank7( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<7>(i_target, i_data) );
+}
+
+///
+/// @brief Write Firmware Mark Store (FWMS) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_rank the master rank index
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ switch (i_rank)
+ {
+ case(0):
+ return ( write_rank0(i_target, i_data) );
+
+ case(1):
+ return ( write_rank1(i_target, i_data) );
+
+ case(2):
+ return ( write_rank2(i_target, i_data) );
+
+ case(3):
+ return ( write_rank3(i_target, i_data) );
+
+ case(4):
+ return ( write_rank4(i_target, i_data) );
+
+ case(5):
+ return ( write_rank5(i_target, i_data) );
+
+ case(6):
+ return ( write_rank6(i_target, i_data) );
+
+ case(7):
+ return ( write_rank7(i_target, i_data) );
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_RANK_PASSED()
+ .set_RANK(i_rank)
+ .set_TARGET(i_target)
+ .set_FUNCTION(FWMS_WRITE),
+ "%s Invalid rank passed to fwms::ecc::write (%d)",
+ mss::c_str(i_target),
+ i_rank);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_mark
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note FWMS0_MARK: mark (Galois field code)
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_mark( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::FIRMWARE_MS_MARK, TT::FIRMWARE_MS_MARK_LEN>(i_value);
+ FAPI_DBG("set_mark: 0x%02lx", i_value);
+}
+
+///
+/// @brief get_mark
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note FWMS0_MARK: mark (Galois field code)
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_mark( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::FIRMWARE_MS_MARK, TT::FIRMWARE_MS_MARK_LEN>(o_value);
+ FAPI_INF("get_mark: 0x%02lx", o_value);
+}
+
+///
+/// @brief set_type
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note FWMS0_TYPE: mark type
+/// @note Dial enums:
+/// @note SYMBOL=>0b1
+/// @note CHIP=>0b0
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_type( fapi2::buffer<uint64_t>& io_data, const mark_type i_value )
+{
+ io_data.writeBit<TT::FIRMWARE_MS_TYPE>(i_value);
+ FAPI_INF("set_type: 0x%01lx", i_value);
+}
+
+///
+/// @brief get_type
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note FWMS0_TYPE: mark type
+/// @note Dial enums:
+/// @note SYMBOL=>0b1
+/// @note CHIP=>0b0
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_type( const fapi2::buffer<uint64_t>& i_data, mark_type& o_value )
+{
+ o_value = mark_type(i_data.getBit<TT::FIRMWARE_MS_TYPE>());
+ FAPI_INF("get_type: 0x%01lx", o_value);
+}
+
+///
+/// @brief set_region
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note FWMS0_REGION: Selects mark region (address range to which mark applies)
+/// @note Dial enums:
+/// @note DISABLED=>0b000
+/// @note RESERVED=>0b001
+/// @note BANK=>0b010
+/// @note BANKGROUP=>0b011
+/// @note SRANK=>0b100
+/// @note MRANK=>0b101
+/// @note DIMM=>0b110
+/// @note UNIVERSAL=>0b111
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_region( fapi2::buffer<uint64_t>& io_data, const mark_region i_value )
+{
+ io_data.insertFromRight<TT::FIRMWARE_MS_REGION, TT::FIRMWARE_MS_REGION_LEN>(i_value);
+ FAPI_INF("set_region: 0x%02lx", i_value);
+}
+
+///
+/// @brief get_region
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note FWMS0_REGION: Selects mark region (address range to which mark applies)
+/// @note Dial enums:
+/// @note DISABLED=>0b000
+/// @note RESERVED=>0b001
+/// @note BANK=>0b010
+/// @note BANKGROUP=>0b011
+/// @note SRANK=>0b100
+/// @note MRANK=>0b101
+/// @note DIMM=>0b110
+/// @note UNIVERSAL=>0b111
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_region( const fapi2::buffer<uint64_t>& i_data, mark_region& o_value )
+{
+ uint64_t l_temp = 0;
+ i_data.extractToRight<TT::FIRMWARE_MS_REGION, TT::FIRMWARE_MS_REGION_LEN>(l_temp);
+ o_value = mark_region(l_temp);
+ FAPI_INF("get_region: 0x%02lx", o_value);
+}
+
+///
+/// @brief set_address
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_address mcbist::address form of address field
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_address( fapi2::buffer<uint64_t>& io_data, const mcbist::address& i_address)
+{
+ // construct fwms::address from mcbist::address
+ const auto l_addr = address<MC, T, TT>(i_address);
+ io_data.insert<TT::FIRMWARE_MS_ADDRESS, TT::FIRMWARE_MS_ADDRESS_LEN, TT::FIRMWARE_MS_ADDRESS>(l_addr);
+ FAPI_INF("set_address: 0x%016lx", uint64_t(l_addr));
+}
+
+///
+/// @brief get_address
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_address mcbist::address form of address field
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_address( const fapi2::buffer<uint64_t>& i_data, mcbist::address& o_address )
+{
+ // construct fwms::address from i_data
+ const auto l_addr = mss::ecc::fwms::address<MC, T, TT>(uint64_t(i_data));
+ // construct mcbist::address from fwms::address
+ o_address = l_addr.operator mss::mcbist::address();
+ FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr));
+}
+
+///
+/// @brief set_exit_1
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_state mss::YES or mss::NO - desired state
+/// @note FWMS0_EXIT_1: When set, bypass-enabled reads using this mark will use exit 1
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_exit_1( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::FIRMWARE_MS_EXIT1>(i_state);
+ FAPI_INF("set_exit_1: 0x%01lx", i_state);
+}
+
+///
+/// @brief get_exit_1
+/// @tparam T fapi2 Target Type defaults to defaulted port in mc const
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_state mss::YES or mss::NO - representing the state of the field
+/// @note FWMS0_EXIT_1: When set, bypass-enabled reads using this mark will use exit 1
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_exit_1( const fapi2::buffer<uint64_t>& i_data, mss::states& o_state )
+{
+ o_state = (i_data.getBit<TT::FIRMWARE_MS_EXIT1>() == false) ? mss::NO : mss::YES;
+ FAPI_INF("get_exit_1: 0x%01lx", o_state);
+}
+
+} // close namespace fwms
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/galois.H b/src/import/generic/memory/lib/ecc/galois.H
index 951839c7a..b795e9897 100644
--- a/src/import/generic/memory/lib/ecc/galois.H
+++ b/src/import/generic/memory/lib/ecc/galois.H
@@ -22,3 +22,169 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file galois.H
+/// @brief Translate ECC mark Galois codes to symbol and DQ
+///
+// *HWP HWP Owner: Matthew Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_ECC_GALOIS_H_
+#define _MSS_ECC_GALOIS_H_
+
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+///
+/// @brief Return symbol value from a given Galois code
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<T>
+/// @param[in] i_galois the Galois code
+/// @param[out] o_symbol symbol value represented by given Galois code
+/// @return FAPI2_RC_SUCCESS iff all is ok
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+fapi2::ReturnCode galois_to_symbol( const uint8_t i_galois, uint8_t& o_symbol )
+{
+ const auto& l_p = std::find(TT::symbol2galois, (TT::symbol2galois + TT::ECC_MAX_SYMBOLS), i_galois);
+
+ FAPI_ASSERT( l_p != (TT::symbol2galois + TT::ECC_MAX_SYMBOLS),
+ fapi2::MSS_INVALID_GALOIS_TO_SYMBOL()
+ .set_GALOIS(i_galois),
+ "Invalid Galois code: 0x%02x",
+ i_galois);
+
+ o_symbol = (l_p - TT::symbol2galois);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return Galois code from a given symbol value
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<T>
+/// @param[in] i_symbol the symbol value
+/// @param[out] o_galois Galois code represented by given symbol
+/// @return FAPI2_RC_SUCCESS iff all is ok
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+fapi2::ReturnCode symbol_to_galois( const uint8_t i_symbol, uint8_t& o_galois )
+{
+ FAPI_ASSERT( i_symbol < TT::ECC_MAX_SYMBOLS,
+ fapi2::MSS_INVALID_SYMBOL_FOR_GALOIS()
+ .set_SYMBOL(i_symbol),
+ "Invalid symbol: %d",
+ i_symbol);
+
+ o_galois = TT::symbol2galois[i_symbol];
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return symbol value from a given DQ index
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<T>
+/// @param[in] i_dq the DQ index
+/// @param[out] o_symbol symbol value represented by given DQ index
+/// @return FAPI2_RC_SUCCESS iff all is ok
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+fapi2::ReturnCode dq_to_symbol( const uint8_t i_dq, uint8_t& o_symbol )
+{
+ const auto& l_p = std::find(TT::symbol2dq, (TT::symbol2dq + TT::ECC_MAX_DQ_BITS), i_dq);
+
+ FAPI_ASSERT( l_p != (TT::symbol2dq + TT::ECC_MAX_DQ_BITS),
+ fapi2::MSS_INVALID_DQ_TO_SYMBOL()
+ .set_DQ(i_dq),
+ "Invalid DQ index: %d",
+ i_dq);
+
+ o_symbol = (l_p - TT::symbol2dq);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return DQ index from a given symbol value
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<T>
+/// @param[in] i_symbol the symbol value
+/// @param[out] o_dq DQ index represented by given symbol value
+/// @return FAPI2_RC_SUCCESS iff all is ok
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+fapi2::ReturnCode symbol_to_dq( const uint8_t i_symbol, uint8_t& o_dq )
+{
+ FAPI_ASSERT( i_symbol < TT::ECC_MAX_SYMBOLS,
+ fapi2::MSS_INVALID_SYMBOL_TO_DQ()
+ .set_SYMBOL(i_symbol),
+ "symbol_to_dq: invalid symbol: %d",
+ i_symbol);
+
+ o_dq = TT::symbol2dq[i_symbol];
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return DQ index from a given Galois code
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<T>
+/// @param[in] i_galois the Galois code
+/// @param[out] o_dq DQ index represented by given Galois code
+/// @return FAPI2_RC_SUCCESS iff all is ok
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+fapi2::ReturnCode galois_to_dq( const uint8_t i_galois, uint8_t& o_dq )
+{
+ uint8_t l_symbol = 0;
+
+ FAPI_TRY( galois_to_symbol<T>(i_galois, l_symbol), "Failed galois_to_symbol");
+ FAPI_TRY( symbol_to_dq<T>(l_symbol, o_dq), "Failed symbol_to_dq" );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return Galois code from a given DQ index
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<T>
+/// @param[in] i_dq the DQ index
+/// @param[out] o_galois Galois code represented by given symbol
+/// @return FAPI2_RC_SUCCESS iff all is ok
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+fapi2::ReturnCode dq_to_galois( const uint8_t i_dq, uint8_t& o_galois )
+{
+ uint8_t l_symbol = 0;
+
+ FAPI_TRY( mss::ecc::dq_to_symbol<T>(i_dq, l_symbol), "Failed dq_to_symbol");
+ FAPI_TRY( mss::ecc::symbol_to_galois<T>(l_symbol, o_galois) , "Failed symbol_to_galois" );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // close namespace ecc
+
+} // close namespace mss
+#endif
diff --git a/src/import/generic/memory/lib/ecc/hw_mark_store.H b/src/import/generic/memory/lib/ecc/hw_mark_store.H
index 2200e9aee..bc0ccccb8 100644
--- a/src/import/generic/memory/lib/ecc/hw_mark_store.H
+++ b/src/import/generic/memory/lib/ecc/hw_mark_store.H
@@ -22,3 +22,485 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file hw_mark_store.H
+/// @brief Subroutines for the MC hardware mark store registers
+///
+// *HWP HWP Owner: Matthew Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_HW_MARK_STORE_H_
+#define _MSS_HW_MARK_STORE_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+#include <generic/memory/lib/utils/scom.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace hwms
+{
+
+///
+/// @brief Read Hardware Mark Store (HWMS) register
+/// @tparam R master rank number
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t R, fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read_rank( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ static_assert((R < TT::ECC_MAX_MRANK_PER_PORT), "Master rank index failed range check");
+ FAPI_TRY( mss::getScom(i_target, (TT::HARDWARE_MS0_REG + R), o_data) );
+ FAPI_INF("read_rank<%d>: 0x%016lx", R, o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 0 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank0( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<0>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 1 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank1( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<1>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 2 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank2( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<2>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 3 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank3( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<3>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 4 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank4( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<4>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 5 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank5( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<5>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 6 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank6( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<6>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) rank 7 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_rank7( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_rank<7>(i_target, o_data) );
+}
+
+///
+/// @brief Read Hardware Mark Store (HWMS) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_rank the master rank index
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ fapi2::buffer<uint64_t>& o_data )
+{
+ switch (i_rank)
+ {
+ case(0):
+ return ( read_rank0(i_target, o_data) );
+
+ case(1):
+ return ( read_rank1(i_target, o_data) );
+
+ case(2):
+ return ( read_rank2(i_target, o_data) );
+
+ case(3):
+ return ( read_rank3(i_target, o_data) );
+
+ case(4):
+ return ( read_rank4(i_target, o_data) );
+
+ case(5):
+ return ( read_rank5(i_target, o_data) );
+
+ case(6):
+ return ( read_rank6(i_target, o_data) );
+
+ case(7):
+ return ( read_rank7(i_target, o_data) );
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_RANK_PASSED()
+ .set_RANK(i_rank)
+ .set_TARGET(i_target)
+ .set_FUNCTION(HWMS_READ),
+ "%s Invalid rank passed to fwms::ecc::hwms::read (%d)",
+ mss::c_str(i_target),
+ i_rank);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) register
+/// @tparam R master rank number
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t R, fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write_rank( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ static_assert((R < TT::ECC_MAX_MRANK_PER_PORT), "Master rank index failed range check");
+ FAPI_TRY( mss::putScom(i_target, (TT::HARDWARE_MS0_REG + R), i_data) );
+ FAPI_INF("write_rank<%d>: 0x%016lx", R, i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 0 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank0( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<0>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 1 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank1( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<1>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 2 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank2( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<2>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 3 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank3( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<3>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 4 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank4( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<4>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 5 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank5( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<5>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 6 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank6( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<6>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) rank 7 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_rank7( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_rank<7>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_rank the master rank index
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ switch (i_rank)
+ {
+ case(0):
+ return ( write_rank0(i_target, i_data) );
+
+ case(1):
+ return ( write_rank1(i_target, i_data) );
+
+ case(2):
+ return ( write_rank2(i_target, i_data) );
+
+ case(3):
+ return ( write_rank3(i_target, i_data) );
+
+ case(4):
+ return ( write_rank4(i_target, i_data) );
+
+ case(5):
+ return ( write_rank5(i_target, i_data) );
+
+ case(6):
+ return ( write_rank6(i_target, i_data) );
+
+ case(7):
+ return ( write_rank7(i_target, i_data) );
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_RANK_PASSED()
+ .set_RANK(i_rank)
+ .set_TARGET(i_target)
+ .set_FUNCTION(HWMS_WRITE),
+ "%s Invalid rank passed to fwms::ecc::hwms::write(%d)",
+ mss::c_str(i_target),
+ i_rank);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_chipmark
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note HWMS0_CHIPMARK: Hardware chipmark (Galois field code)
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_chipmark( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::HARDWARE_MS_CHIPMARK, TT::HARDWARE_MS_CHIPMARK_LEN>(i_value);
+ FAPI_INF("set_chipmark: 0x%02lx", i_value);
+}
+
+///
+/// @brief get_chipmark
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note HWMS0_CHIPMARK: Hardware chipmark (Galois field code)
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_chipmark( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::HARDWARE_MS_CHIPMARK, TT::HARDWARE_MS_CHIPMARK_LEN>(o_value);
+ FAPI_INF("get_chipmark: 0x%02lx", o_value);
+}
+
+///
+/// @brief set_confirmed
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_state mss::YES or mss::NO - desired state
+/// @note HWMS0_CONFIRMED: chipmark confirmed
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_confirmed( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::HARDWARE_MS_CONFIRMED>(i_state);
+ FAPI_INF("set_confirmed: 0x%01lx", i_state);
+}
+
+///
+/// @brief get_confirmed
+/// @tparam T fapi2 Target Type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_state mss::YES or mss::NO - representing the state of the field
+/// @note HWMS0_CONFIRMED: chipmark confirmed
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_confirmed( const fapi2::buffer<uint64_t>& i_data, mss::states& o_state )
+{
+ o_state = (i_data.getBit<TT::HARDWARE_MS_CONFIRMED>() == false) ? mss::NO : mss::YES;
+ FAPI_INF("get_confirmed: 0x%01lx", o_state);
+}
+
+///
+/// @brief set_exit_1
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_state mss::YES or mss::NO - desired state
+/// @note HWMS0_EXIT_1: When set, bypass-enabled reads using this mark will
+/// @note use exit 1; otherwise exit 0
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_exit_1( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::HARDWARE_MS_EXIT1>(i_state);
+ FAPI_INF("set_exit_1: 0x%01lx", i_state);
+}
+
+///
+/// @brief get_exit_1
+/// @tparam T fapi2 Target Type defaults to the default set in mc const file
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_state mss::YES or mss::NO - representing the state of the field
+/// @note HWMS0_EXIT_1: When set, bypass-enabled reads using this mark will
+/// @note use exit 1; otherwise exit 0
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_exit_1( const fapi2::buffer<uint64_t>& i_data, mss::states& o_state )
+{
+ o_state = (i_data.getBit<TT::HARDWARE_MS_EXIT1>() == false) ? mss::NO : mss::YES;
+ FAPI_INF("get_exit_1: 0x%01lx", o_state);
+}
+
+} // close namespace hwms
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/mainline_aue_trap.H b/src/import/generic/memory/lib/ecc/mainline_aue_trap.H
index 49a28287f..a69098d7e 100644
--- a/src/import/generic/memory/lib/ecc/mainline_aue_trap.H
+++ b/src/import/generic/memory/lib/ecc/mainline_aue_trap.H
@@ -22,3 +22,110 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mainline_aue_trap.H
+/// @brief Subroutines for the MC mainline aue address trap registers (MBAUER*Q)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MAINLINE_AUE_TRAP_H_
+#define _MSS_MAINLINE_AUE_TRAP_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace mainline_aue_trap
+{
+
+///
+/// @brief Read MBS Mainline AUE Address Trap (MBAUER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::getScom(l_mcbist_target, (TT::MAINLINE_AUE_REGS[l_port]), o_data) );
+ FAPI_INF("%s read: 0x%016lx", mss::c_str(i_target), o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Mainline AUE Address Trap (MBAUER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::putScom(l_mcbist_target, (TT::MAINLINE_AUE_REGS[l_port]), i_data) );
+ FAPI_INF("%s write: 0x%016lx", mss::c_str(i_target), i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_address( fapi2::buffer<uint64_t>& io_data, const mcbist::address& i_address)
+{
+ io_data.insertFromRight<TT::AUE_ADDR_TRAP, TT::AUE_ADDR_TRAP_LEN>(uint64_t(i_address));
+ FAPI_INF("set_address: 0x%016lx", uint64_t(i_address));
+}
+
+///
+/// @brief get_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_address( const fapi2::buffer<uint64_t>& i_data, mcbist::address& o_address )
+{
+ uint64_t l_addr = 0;
+ i_data.extractToRight<TT::AUE_ADDR_TRAP, TT::AUE_ADDR_TRAP_LEN>(l_addr);
+ o_address = mcbist::address(l_addr);
+ FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr));
+}
+
+} // close namespace mainline_aue_trap
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/mainline_mpe_trap.H b/src/import/generic/memory/lib/ecc/mainline_mpe_trap.H
index c07639036..68fa26001 100644
--- a/src/import/generic/memory/lib/ecc/mainline_mpe_trap.H
+++ b/src/import/generic/memory/lib/ecc/mainline_mpe_trap.H
@@ -22,3 +22,142 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mainline_mpe_trap.H
+/// @brief Subroutines for the MC mainline mpe address trap registers (MBNCER*Q)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MAINLINE_MPE_TRAP_H_
+#define _MSS_MAINLINE_MPE_TRAP_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace mainline_mpe_trap
+{
+
+///
+/// @brief Read MBS Mainline MPE Address Trap (MBMPER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::getScom(l_mcbist_target, (TT::MAINLINE_MPE_REGS[l_port]), o_data) );
+ FAPI_INF("%s read: 0x%016lx", mss::c_str(i_target), o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Mainline MPE Address Trap (MBMPER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::putScom(l_mcbist_target, (TT::MAINLINE_MPE_REGS[l_port]), i_data) );
+ FAPI_INF("%s write: 0x%016lx", mss::c_str(i_target), i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_address( fapi2::buffer<uint64_t>& io_data, const mcbist::address& i_address)
+{
+ io_data.insertFromRight<TT::MPE_ADDR_TRAP, TT::MPE_ADDR_TRAP_LEN>(uint64_t(i_address));
+ FAPI_INF("set_address: 0x%016lx", uint64_t(i_address));
+}
+
+///
+/// @brief get_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_address( const fapi2::buffer<uint64_t>& i_data, mcbist::address& o_address )
+{
+ uint64_t l_addr = 0;
+ i_data.extractToRight<TT::MPE_ADDR_TRAP, TT::MPE_ADDR_TRAP_LEN>(l_addr);
+ o_address = mcbist::address(l_addr);
+ FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr));
+}
+
+///
+/// @brief set_mpe_on_rce
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_state mss::YES or mss::NO - desired state
+/// @note MBMPER0Q_PORT_0_MAINLINE_MPE_ON_RCE: Indicates whether if this error
+/// @note came on the retry of a UE, RCD, or AUE as part of an RCE
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_mpe_on_rce( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::MPE_ON_RCE>(i_state);
+ FAPI_INF("set_mpe_on_rce: 0x%01lx", i_state);
+}
+
+///
+/// @brief get_mpe_on_rce
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_state mss::YES or mss::NO - representing the state of the field
+/// @note MBMPER0Q_PORT_0_MAINLINE_MPE_ON_RCE: Indicates whether if this error
+/// @note came on the retry of a UE, RCD, or AUE as part of an RCE
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_mpe_on_rce( const fapi2::buffer<uint64_t>& i_data, mss::states& o_state )
+{
+ o_state = (i_data.getBit<TT::MPE_ON_RCE>() == false) ? mss::NO : mss::YES;
+ FAPI_INF("get_mpe_on_rce: 0x%01lx", o_state);
+}
+
+} // close namespace mainline_mpe_trap
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/mainline_nce_trap.H b/src/import/generic/memory/lib/ecc/mainline_nce_trap.H
index cbffeb8e6..b99d4716a 100644
--- a/src/import/generic/memory/lib/ecc/mainline_nce_trap.H
+++ b/src/import/generic/memory/lib/ecc/mainline_nce_trap.H
@@ -22,3 +22,175 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mainline_nce_trap.H
+/// @brief Subroutines for the MC mainline nce address trap registers (MBNCER*Q)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MAINLINE_NCE_TRAP_H_
+#define _MSS_MAINLINE_NCE_TRAP_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/pos.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace mainline_nce_trap
+{
+
+///
+/// @brief Read MBS Mainline NCE Address Trap (MBNCER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::getScom(l_mcbist_target, (TT::MAINLINE_NCE_REGS[l_port]), o_data) );
+ FAPI_INF("%s read: 0x%016lx", mss::c_str(i_target), o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Mainline NCE Address Trap (MBNCER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::putScom(l_mcbist_target, (TT::MAINLINE_NCE_REGS[l_port]), i_data) );
+ FAPI_INF("%s write: 0x%016lx", mss::c_str(i_target), i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_address( fapi2::buffer<uint64_t>& io_data, const mcbist::address& i_address)
+{
+ io_data.insertFromRight<TT::NCE_ADDR_TRAP, TT::NCE_ADDR_TRAP_LEN>(uint64_t(i_address));
+ FAPI_INF("set_address: 0x%016lx", uint64_t(i_address));
+}
+
+///
+/// @brief get_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_address( const fapi2::buffer<uint64_t>& i_data, mcbist::address& o_address )
+{
+ uint64_t l_addr = 0;
+ i_data.extractToRight<TT::NCE_ADDR_TRAP, TT::NCE_ADDR_TRAP_LEN>(l_addr);
+ o_address = mcbist::address(l_addr);
+ FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr));
+}
+
+///
+/// @brief set_nce_on_rce
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_state mss::YES or mss::NO - desired state
+/// @note MBNCER0Q_PORT_0_MAINLINE_NCE_ON_RCE: Indicates whether if this NCE came on the
+/// @note retry of a UE, RCD, or AUE as part of an RCE
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_nce_on_rce( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::NCE_ON_RCE>(i_state);
+ FAPI_INF("set_nce_on_rce: 0x%01lx", i_state);
+}
+
+///
+/// @brief get_nce_on_rce
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_state mss::YES or mss::NO - representing the state of the field
+/// @note MBNCER0Q_PORT_0_MAINLINE_NCE_ON_RCE: Indicates whether if this NCE came on the
+/// @note retry of a UE, RCD, or AUE as part of an RCE
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_nce_on_rce( const fapi2::buffer<uint64_t>& i_data, mss::states& o_state )
+{
+ o_state = (i_data.getBit<TT::NCE_ON_RCE>() == false) ? mss::NO : mss::YES;
+ FAPI_INF("get_nce_on_rce: 0x%01lx", o_state);
+}
+
+///
+/// @brief set_nce_is_tce
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_state mss::YES or mss::NO - desired state
+/// @note MBNCER0Q_PORT_0_MAINLINE_NCE_IS_TCE: Indicates if this NCE is actually
+/// @note a two symbol error (TCE)
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_nce_is_tce( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::NCE_IS_TCE>(i_state);
+ FAPI_INF("set_nce_is_tce: 0x%01lx", i_state);
+}
+
+///
+/// @brief get_nce_is_tce
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_state mss::YES or mss::NO - representing the state of the field
+/// @note MBNCER0Q_PORT_0_MAINLINE_NCE_IS_TCE: Indicates if this NCE is actually
+/// @note a two symbol error (TCE)
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_nce_is_tce( const fapi2::buffer<uint64_t>& i_data, mss::states& o_state )
+{
+ o_state = (i_data.getBit<TT::NCE_IS_TCE>() == false) ? mss::NO : mss::YES;
+ FAPI_INF("get_nce_is_tce: 0x%01lx", o_state);
+}
+
+} // close namespace mainline_nce_trap
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/mainline_rce_trap.H b/src/import/generic/memory/lib/ecc/mainline_rce_trap.H
index 02afe5b63..747192479 100644
--- a/src/import/generic/memory/lib/ecc/mainline_rce_trap.H
+++ b/src/import/generic/memory/lib/ecc/mainline_rce_trap.H
@@ -22,3 +22,110 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mainline_rce_trap.H
+/// @brief Subroutines for the MC mainline rce address trap registers (MBRCER*Q)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MAINLINE_RCE_TRAP_H_
+#define _MSS_MAINLINE_RCE_TRAP_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace mainline_rce_trap
+{
+
+///
+/// @brief Read MBS Mainline RCE Address Trap (MBRCER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::getScom(l_mcbist_target, (TT::MAINLINE_RCE_REGS[l_port]), o_data) );
+ FAPI_INF("read: 0x%016lx", o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Mainline RCE Address Trap (MBRCER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::putScom(l_mcbist_target, (TT::MAINLINE_RCE_REGS[l_port]), i_data) );
+ FAPI_INF("write: 0x%016lx", i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_address( fapi2::buffer<uint64_t>& io_data, const mcbist::address& i_address)
+{
+ io_data.insertFromRight<TT::RCE_ADDR_TRAP, TT::RCE_ADDR_TRAP_LEN>(uint64_t(i_address));
+ FAPI_INF("set_address: 0x%016lx", uint64_t(i_address));
+}
+
+///
+/// @brief get_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_address( const fapi2::buffer<uint64_t>& i_data, mcbist::address& o_address )
+{
+ uint64_t l_addr = 0;
+ i_data.extractToRight<TT::RCE_ADDR_TRAP, TT::RCE_ADDR_TRAP_LEN>(l_addr);
+ o_address = mcbist::address(l_addr);
+ FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr));
+}
+
+} // close namespace mainline_rce_trap
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/mainline_ue_trap.H b/src/import/generic/memory/lib/ecc/mainline_ue_trap.H
index 10da89c18..ed5e46820 100644
--- a/src/import/generic/memory/lib/ecc/mainline_ue_trap.H
+++ b/src/import/generic/memory/lib/ecc/mainline_ue_trap.H
@@ -22,3 +22,110 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mainline_ue_trap.H
+/// @brief Subroutines for the MC mainline ue address trap registers (MBUER*Q)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MAINLINE_UE_TRAP_H_
+#define _MSS_MAINLINE_UE_TRAP_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace mainline_ue_trap
+{
+
+///
+/// @brief Read MBS Mainline UE Address Trap (MBUER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::getScom(l_mcbist_target, (TT::MAINLINE_UE_REGS[l_port]), o_data) );
+ FAPI_INF("read: 0x%016lx", o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Mainline UE Address Trap (MBUER*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::putScom(l_mcbist_target, (TT::MAINLINE_UE_REGS[l_port]), i_data) );
+ FAPI_INF("write: 0x%016lx", i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_address( fapi2::buffer<uint64_t>& io_data, const mcbist::address& i_address)
+{
+ io_data.insertFromRight<TT::UE_ADDR_TRAP, TT::UE_ADDR_TRAP_LEN>(uint64_t(i_address));
+ FAPI_INF("set_address: 0x%016lx", uint64_t(i_address));
+}
+
+///
+/// @brief get_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_address( const fapi2::buffer<uint64_t>& i_data, mcbist::address& o_address )
+{
+ uint64_t l_addr = 0;
+ i_data.extractToRight<TT::UE_ADDR_TRAP, TT::UE_ADDR_TRAP_LEN>(l_addr);
+ o_address = mcbist::address(l_addr);
+ FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr));
+}
+
+} // close namespace mainline_ue_trap
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/maint_current_trap.H b/src/import/generic/memory/lib/ecc/maint_current_trap.H
index fd3b7de8e..a5e25297f 100644
--- a/src/import/generic/memory/lib/ecc/maint_current_trap.H
+++ b/src/import/generic/memory/lib/ecc/maint_current_trap.H
@@ -22,3 +22,173 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file maint_current_trap.H
+/// @brief Subroutines for the MC maint current address trap register (MCBMCATQ)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MAINT_CURRENT_TRAP_H_
+#define _MSS_MAINT_CURRENT_TRAP_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace maint_current_trap
+{
+
+///
+/// @brief Read MBS Mainline MPE Address Trap (MCBMCATQ) register
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mem port
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<DEFAULT_MEM_PORT_TARGET>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ const auto& l_mcbist_target = mss::find_target<T>(i_target);
+
+ FAPI_TRY( mss::getScom(l_mcbist_target, TT::MPE_ADDR_TRAP_REG, o_data) );
+ FAPI_INF("read: 0x%016lx", o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Mainline MPE Address Trap (MCBMCATQ) register
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mem port
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<DEFAULT_MEM_PORT_TARGET>& i_target,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ const auto& l_mcbist_target = mss::find_target<T>(i_target);
+
+ FAPI_TRY( mss::putScom(l_mcbist_target, TT::MPE_ADDR_TRAP_REG, i_data) );
+ FAPI_INF("write: 0x%016lx", i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_address( fapi2::buffer<uint64_t>& io_data, const mcbist::address& i_address)
+{
+ io_data.insertFromRight<TT::CURRENT_ADDR_TRAP, TT::CURRENT_ADDR_TRAP_LEN>(uint64_t(i_address));
+ FAPI_INF("set_address: 0x%016lx", uint64_t(i_address));
+}
+
+///
+/// @brief get_address
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_address mcbist::address form of address field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_address( const fapi2::buffer<uint64_t>& i_data, mcbist::address& o_address )
+{
+ uint64_t l_addr = 0;
+ i_data.extractToRight<TT::CURRENT_ADDR_TRAP, TT::CURRENT_ADDR_TRAP_LEN>(l_addr);
+ o_address = mcbist::address(l_addr);
+ FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr));
+}
+
+///
+/// @brief set_port
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value - desired value
+/// @note MCBMCATQ_CFG_CURRENT_PORT_TRAP: If MCBCFGQ_cfg_current_addr_trap_update_dis = 0, then this
+/// @note field will store port. This field is ONLY valid in maint_addr_mode. Garabage otherwise.
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_port( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::CURRENT_PORT, TT::CURRENT_PORT_LEN>(i_value);
+ FAPI_INF("set_port: 0x%01lx", i_value);
+}
+
+///
+/// @brief get_port
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value - representing the field value
+/// @note MCBMCATQ_CFG_CURRENT_PORT_TRAP: If MCBCFGQ_cfg_current_addr_trap_update_dis = 0, then this
+/// @note field will store port. This field is ONLY valid in maint_addr_mode. Garabage otherwise.
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_port( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::CURRENT_PORT, TT::CURRENT_PORT_LEN>(o_value);
+ FAPI_INF("get_port: 0x%01lx", o_value);
+}
+
+///
+/// @brief set_dimm
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value - desired value
+/// @note MCBMCATQ_CFG_CURRENT_DIMM_TRAP: If MCBCFGQ_cfg_current_addr_trap_update_dis = 0, then this
+/// @note field will store dimm select.
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_dimm( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.writeBit<TT::CURRENT_DIMM>(i_value);
+ FAPI_INF("set_dimm: 0x%01lx", i_value);
+}
+
+///
+/// @brief get_dimm
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value - representing the field value
+/// @note MCBMCATQ_CFG_CURRENT_DIMM_TRAP: If MCBCFGQ_cfg_current_addr_trap_update_dis = 0, then this
+/// @note field will store dimm select.
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_dimm( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ o_value = i_data.getBit<TT::CURRENT_DIMM>();
+ FAPI_INF("get_dimm: 0x%01lx", o_value);
+}
+
+} // close namespace maint_current_trap
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/mark_shadow_reg.H b/src/import/generic/memory/lib/ecc/mark_shadow_reg.H
index d2e0d92c3..65bd7dca2 100644
--- a/src/import/generic/memory/lib/ecc/mark_shadow_reg.H
+++ b/src/import/generic/memory/lib/ecc/mark_shadow_reg.H
@@ -22,3 +22,129 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mark_shadow_reg.H
+/// @brief Subroutines for the MC mark shadow registers (MSR)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MARK_SHADOW_REG_H_
+#define _MSS_MARK_SHADOW_REG_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace mark_shadow_reg
+{
+
+///
+/// @brief Read Mark Shadow register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ FAPI_TRY( mss::getScom(i_target, TT::MARK_SHADOW_REG, o_data) );
+ FAPI_INF("%s read: 0x%016lx", mss::c_str(i_target), o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write Mark Shadow register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( mss::putScom(i_target, TT::MARK_SHADOW_REG, i_data) );
+ FAPI_INF("%s write: 0x%016lx", mss::c_str(i_target), i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_chipmark
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_chipmark( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SHADOW_CHIPMARK, TT::SHADOW_CHIPMARK_LEN>(i_value);
+ FAPI_INF("set_chipmark: 0x%016lx", i_value);
+}
+
+///
+/// @brief get_chipmark
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_chipmark( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SHADOW_CHIPMARK, TT::SHADOW_CHIPMARK_LEN>(o_value);
+ FAPI_INF("get_chipmark: 0x%016lx", o_value);
+}
+
+///
+/// @brief set_rank
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_rank( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SHADOW_RANK, TT::SHADOW_RANK_LEN>(i_value);
+ FAPI_INF("set_rank: 0x%016lx", i_value);
+}
+
+///
+/// @brief get_rank
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MEM_PORT_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+///
+template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_rank( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SHADOW_RANK, TT::SHADOW_RANK_LEN>(o_value);
+ FAPI_INF("get_rank: 0x%016lx", o_value);
+}
+
+} // close namespace mark_shadow_reg
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/mbs_error_vector_trap.H b/src/import/generic/memory/lib/ecc/mbs_error_vector_trap.H
index 529491723..302ab3fbf 100644
--- a/src/import/generic/memory/lib/ecc/mbs_error_vector_trap.H
+++ b/src/import/generic/memory/lib/ecc/mbs_error_vector_trap.H
@@ -22,3 +22,182 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mbs_error_vector_trap.H
+/// @brief Subroutines for the MC MBS error vector trap registers (MBSEVR*Q)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MBS_ERROR_VECTOR_TRAP_H_
+#define _MSS_MBS_ERROR_VECTOR_TRAP_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace mbs_error_vector_trap
+{
+
+///
+/// @brief Read MBS Error Vector Trap (MBSEVR*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::getScom(l_mcbist_target, (TT::ERROR_VECTOR_REGS[l_port]), o_data) );
+ FAPI_INF("%s read: 0x%016lx", mss::c_str(i_target), o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Error Vector Trap (MBSEVR*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ const auto& l_mcbist_target = mss::find_target<DEFAULT_MC_TARGET>(i_target);
+ const auto& l_port = mss::relative_pos<DEFAULT_MC_TARGET>(i_target);
+
+ FAPI_TRY( mss::putScom(l_mcbist_target, (TT::ERROR_VECTOR_REGS[l_port]), i_data) );
+ FAPI_INF("%s write: 0x%016lx", mss::c_str(i_target), i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_nce_galois
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void set_nce_galois( const fapi2::Target<T>& i_target,
+ fapi2::buffer<uint64_t>& io_data,
+ const uint64_t i_value);
+///
+/// @brief get_nce_galois
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the register value
+/// @param[out] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void get_nce_galois( const fapi2::Target<T>& i_target,
+ const fapi2::buffer<uint64_t>& i_data,
+ uint64_t& o_value);
+
+///
+/// @brief set_nce_magnitude
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void set_nce_magnitude( const fapi2::Target<T>& i_target,
+ fapi2::buffer<uint64_t>& io_data,
+ const uint64_t i_value);
+
+///
+/// @brief get_nce_magnitude
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the register value
+/// @param[out] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void get_nce_magnitude( const fapi2::Target<T>& i_target,
+ const fapi2::buffer<uint64_t>& i_data,
+ uint64_t& o_value);
+
+///
+/// @brief set_tce_galois
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void set_tce_galois( const fapi2::Target<T>& i_target,
+ fapi2::buffer<uint64_t>& io_data,
+ const uint64_t i_value);
+
+///
+/// @brief get_tce_galois
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the register value
+/// @param[out] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void get_tce_galois( const fapi2::Target<T>& i_target,
+ const fapi2::buffer<uint64_t>& i_data,
+ uint64_t& o_value);
+
+///
+/// @brief set_tce_magnitude
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void set_tce_magnitude( const fapi2::Target<T>& i_target,
+ fapi2::buffer<uint64_t>& io_data,
+ const uint64_t i_value);
+
+///
+/// @brief get_tce_magnitude
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the register value
+/// @param[out] i_value the value of the field
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+void get_tce_magnitude( const fapi2::Target<T>& i_target,
+ const fapi2::buffer<uint64_t>& i_data,
+ uint64_t& o_value);
+
+} // close namespace mbs_error_vector_trap
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/modal_symbol_count.H b/src/import/generic/memory/lib/ecc/modal_symbol_count.H
index 1cca236c2..8a4c7a921 100644
--- a/src/import/generic/memory/lib/ecc/modal_symbol_count.H
+++ b/src/import/generic/memory/lib/ecc/modal_symbol_count.H
@@ -22,3 +22,552 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file modal_symbol_count.H
+/// @brief Subroutines for the MC modal symbol count (MBSSYMEC*Q) registers
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_MODAL_SYMBOL_COUNT_H_
+#define _MSS_MODAL_SYMBOL_COUNT_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace modal_symbol_count
+{
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) register
+/// @tparam N the register index (0-8)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t N, fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read_index( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ static_assert((N < TT::NUM_MBSSYM_REGS), "Modal symbol count reg index failed range check");
+ FAPI_TRY( mss::getScom(i_target, (TT::MODAL_SYM_COUNT0_REG + N), o_data) );
+ FAPI_INF("read_index<%d>: 0x%016lx", N, o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 0 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index0( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<0>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 1 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index1( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<1>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 2 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index2( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<2>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 3 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index3( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<3>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 4 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index4( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<4>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 5 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index5( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<5>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 6 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index6( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<6>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 7 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index7( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<7>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) 8 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read_index8( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ return ( read_index<8>(i_target, o_data) );
+}
+
+///
+/// @brief Read modal symbol count (MBSSYMEC*Q) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_index the register index
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target,
+ const uint64_t i_index,
+ fapi2::buffer<uint64_t>& o_data )
+{
+ switch (i_index)
+ {
+ case(0):
+ return ( read_index0(i_target, o_data) );
+
+ case(1):
+ return ( read_index1(i_target, o_data) );
+
+ case(2):
+ return ( read_index2(i_target, o_data) );
+
+ case(3):
+ return ( read_index3(i_target, o_data) );
+
+ case(4):
+ return ( read_index4(i_target, o_data) );
+
+ case(5):
+ return ( read_index5(i_target, o_data) );
+
+ case(6):
+ return ( read_index6(i_target, o_data) );
+
+ case(7):
+ return ( read_index7(i_target, o_data) );
+
+ case(8):
+ return ( read_index8(i_target, o_data) );
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_INDEX_PASSED()
+ .set_INDEX(i_index)
+ .set_FUNCTION(SYMBOL_COUNT_READ),
+ "%s Invalid index passed to fwms::ecc::modal_symbol_count::read (%d)",
+ mss::c_str(i_target),
+ i_index);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) register
+/// @tparam N the register index (0-8)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t N, fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write_index( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ static_assert((N < TT::NUM_MBSSYM_REGS), "Modal symbol count reg index failed range check");
+ FAPI_TRY( mss::putScom(i_target, (TT::MODAL_SYM_COUNT0_REG + N), i_data) );
+ FAPI_INF("write_index<%d>: 0x%016lx", N, i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 0 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index0( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<0>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 1 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index1( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<1>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 2 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index2( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<2>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 3 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index3( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<3>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 4 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index4( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<4>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 5 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index5( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<5>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 6 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index6( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<6>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 7 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index7( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<7>(i_target, i_data) );
+}
+
+///
+/// @brief Write modal symbol count (MBSSYMEC*Q) 8 register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write_index8( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ return ( write_index<8>(i_target, i_data) );
+}
+
+///
+/// @brief Write Hardware Mark Store (HWMS) register
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @param[in] i_target the fapi2 target of the mc
+/// @param[in] i_index the register index
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target,
+ const uint64_t i_index,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ switch (i_index)
+ {
+ case(0):
+ return ( write_index0(i_target, i_data) );
+
+ case(1):
+ return ( write_index1(i_target, i_data) );
+
+ case(2):
+ return ( write_index2(i_target, i_data) );
+
+ case(3):
+ return ( write_index3(i_target, i_data) );
+
+ case(4):
+ return ( write_index4(i_target, i_data) );
+
+ case(5):
+ return ( write_index5(i_target, i_data) );
+
+ case(6):
+ return ( write_index6(i_target, i_data) );
+
+ case(7):
+ return ( write_index7(i_target, i_data) );
+
+ case(8):
+ return ( write_index8(i_target, i_data) );
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_INDEX_PASSED()
+ .set_INDEX(i_index)
+ .set_FUNCTION(SYMBOL_COUNT_WRITE),
+ "%s Invalid index passed to fwms::ecc::modal_symbol_count::write (%d)",
+ mss::c_str(i_target),
+ i_index);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_count
+/// @tparam T fapi2 Target Type defaults to TARGET_TYPE_MCBIST
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_index the counter index
+/// @param[in] i_value the value of the field
+/// @note MBSSYMEC*Q_MODAL_SYMBOL_COUNTER_XX: Functional mode determined by MBSTRQ_Symbol_counter_mode:
+/// @note if 00, 0:7 = Maint NCE counter for Symbol XX if 01, 0:3 = MCBIST error counter for nibble (XX/4)
+/// @note and rank (XX%4)*2 4:7 = MCBIST error counter for nibble (XX/4) and rank ((XX%4)*2)+1 if 10,
+/// @note 0:3 = MCBIST error counter for port XX/18 and nibble XX%18 4:7 = MCBIST error rank map for
+/// @note port XX/18 and nibble XX%18
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_index, const uint64_t i_value )
+{
+ static_assert ( TT::MODAL_SYMBOL_COUNTERS_PER_REG <= 8,
+ "mss::ecc_count::modal_symbol_count: Modal symbol count field index failed range check" );
+ const uint64_t l_field = i_index % TT::MODAL_SYMBOL_COUNTERS_PER_REG;
+
+ switch (l_field)
+ {
+ case 0:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_00, TT::MODAL_SYMBOL_COUNTER_00_LEN>(i_value);
+ break;
+
+ case 1:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_01, TT::MODAL_SYMBOL_COUNTER_01_LEN>(i_value);
+ break;
+
+ case 2:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_02, TT::MODAL_SYMBOL_COUNTER_02_LEN>(i_value);
+ break;
+
+ case 3:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_03, TT::MODAL_SYMBOL_COUNTER_03_LEN>(i_value);
+ break;
+
+ case 4:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_04, TT::MODAL_SYMBOL_COUNTER_04_LEN>(i_value);
+ break;
+
+ case 5:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_05, TT::MODAL_SYMBOL_COUNTER_05_LEN>(i_value);
+ break;
+
+ case 6:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_06, TT::MODAL_SYMBOL_COUNTER_06_LEN>(i_value);
+ break;
+
+ case 7:
+ io_data.insertFromRight<TT::MODAL_SYMBOL_COUNTER_07, TT::MODAL_SYMBOL_COUNTER_07_LEN>(i_value);
+ break;
+
+ default:
+ // Shouldn't happen due to modulo above, but here just in case - JLH
+ FAPI_ERR("Modal symbol count field index failed range check");
+ fapi2::Assert(false);
+ break;
+ }
+
+ FAPI_INF("set_count(%d): 0x%02lx", l_field, i_value);
+}
+
+///
+/// @brief get_count
+/// @tparam T fapi2 Target Type defaults to TARGET_TYPE_MCBIST
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[in] i_index the counter index
+/// @param[out] o_value the value of the field
+/// @note MBSSYMEC*Q_MODAL_SYMBOL_COUNTER_XX: Functional mode determined by MBSTRQ_Symbol_counter_mode:
+/// @note if 00, 0:7 = Maint NCE counter for Symbol XX if 01, 0:3 = MCBIST error counter for nibble (XX/4)
+/// @note and rank (XX%4)*2 4:7 = MCBIST error counter for nibble (XX/4) and rank ((XX%4)*2)+1 if 10,
+/// @note 0:3 = MCBIST error counter for port XX/18 and nibble XX%18 4:7 = MCBIST error rank map for
+/// @note port XX/18 and nibble XX%18
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_count( const fapi2::buffer<uint64_t>& i_data, const uint64_t i_index, uint64_t& o_value )
+{
+ const uint64_t l_field = i_index % TT::MODAL_SYMBOL_COUNTERS_PER_REG;
+ static_assert ( TT::MODAL_SYMBOL_COUNTERS_PER_REG <= 8,
+ "mss::ecc_count::get_count: Modal symbol count field index failed range check" );
+
+ switch (l_field)
+ {
+ case 0:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_00, TT::MODAL_SYMBOL_COUNTER_00_LEN>(o_value);
+ break;
+
+ case 1:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_01, TT::MODAL_SYMBOL_COUNTER_01_LEN>(o_value);
+ break;
+
+ case 2:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_02, TT::MODAL_SYMBOL_COUNTER_02_LEN>(o_value);
+ break;
+
+ case 3:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_03, TT::MODAL_SYMBOL_COUNTER_03_LEN>(o_value);
+ break;
+
+ case 4:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_04, TT::MODAL_SYMBOL_COUNTER_04_LEN>(o_value);
+ break;
+
+ case 5:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_05, TT::MODAL_SYMBOL_COUNTER_05_LEN>(o_value);
+ break;
+
+ case 6:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_06, TT::MODAL_SYMBOL_COUNTER_06_LEN>(o_value);
+ break;
+
+ case 7:
+ i_data.extractToRight<TT::MODAL_SYMBOL_COUNTER_07, TT::MODAL_SYMBOL_COUNTER_07_LEN>(o_value);
+ break;
+
+ default:
+ // shouldn't happen due to modulo above, but here just in case
+ FAPI_ERR("Modal symbol count field index failed range check");
+ fapi2::Assert(false);
+ break;
+ }
+
+ FAPI_INF("get_count(%d): 0x%02lx", l_field, o_value);
+}
+
+} // close namespace modal_symbol_count
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/ecc/read_error_count_regs.H b/src/import/generic/memory/lib/ecc/read_error_count_regs.H
index 78b0d7b31..352f28795 100644
--- a/src/import/generic/memory/lib/ecc/read_error_count_regs.H
+++ b/src/import/generic/memory/lib/ecc/read_error_count_regs.H
@@ -22,3 +22,628 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mainline_ue_trap.H
+/// @brief Subroutines for the MBS Memory Scrub/Read Error Count registers (MBSEC*Q)
+///
+// *HWP HWP Owner: Matt Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_READ_ERROR_COUNT_REGS_H_
+#define _MSS_READ_ERROR_COUNT_REGS_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/scom.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace read_error_count_reg0
+{
+
+///
+/// @brief Read MBS Memory Scrub/Read Error Count Register 0 (MBSEC0Q)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ FAPI_TRY( mss::getScom(i_target, TT::READ_ERROR_COUNT_REG0, o_data) );
+ FAPI_INF("%s read: 0x%016lx", mss::c_str(i_target), o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Memory Scrub/Read Error Count Register 0 (MBSEC0Q)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( mss::putScom(i_target, TT::READ_ERROR_COUNT_REG0, i_data) );
+ FAPI_INF("%s write: 0x%016lx", mss::c_str(i_target), i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_intermittent_ce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_INTERMITTENT_CE_COUNT: Intermittent CE Count This is a 12-bit count of
+/// @note intermittent CE events. Will freeze its value upon incrementing to the max
+/// @note value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_intermittent_ce_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::INTERMITTENT_CE_COUNT, TT::INTERMITTENT_CE_COUNT_LEN>(i_value);
+ FAPI_INF("set_intermittent_ce_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_intermittent_ce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_INTERMITTENT_CE_COUNT: Intermittent CE Count This is a 12-bit count of
+/// @note intermittent CE events. Will freeze its value upon incrementing to the max
+/// @note value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_intermittent_ce_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::INTERMITTENT_CE_COUNT, TT::INTERMITTENT_CE_COUNT_LEN>(o_value);
+ FAPI_INF("get_intermittent_ce_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_soft_ce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_SOFT_CE_COUNT: Soft CE Count This is a 12-bit count of
+/// @note soft CE events. Will freeze its value upon incrementing to the max
+/// @note value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_soft_ce_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SOFT_CE_COUNT, TT::SOFT_CE_COUNT_LEN>(i_value);
+ FAPI_INF("set_soft_ce_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_soft_ce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_SOFT_CE_COUNT: Soft CE Count This is a 12-bit count of
+/// @note soft CE events. Will freeze its value upon incrementing to the max
+/// @note value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_soft_ce_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SOFT_CE_COUNT, TT::SOFT_CE_COUNT_LEN>(o_value);
+ FAPI_INF("get_soft_ce_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_hard_ce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_HARD_CE_COUNT: Hard CE Count This is a 12-bit count of
+/// @note hard CE events. Will freeze its value upon incrementing to the max
+/// @note value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_hard_ce_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::HARD_CE_COUNT, TT::HARD_CE_COUNT_LEN>(i_value);
+ FAPI_INF("set_hard_ce_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_hard_ce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_HARD_CE_COUNT: Hard CE Count This is a 12-bit count of
+/// @note hard CE events. Will freeze its value upon incrementing to the max
+/// @note value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_hard_ce_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::HARD_CE_COUNT, TT::HARD_CE_COUNT_LEN>(o_value);
+ FAPI_INF("get_hard_ce_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_intermittent_mce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_INTERMITTENT_MCE_COUNT: Intermittent MCE Count This is a 12-bit count of
+/// @note intermittent Marked Chip Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_intermittent_mce_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::INTERMITTENT_MCE_COUNT, TT::INTERMITTENT_MCE_COUNT_LEN>(i_value);
+ FAPI_INF("set_intermittent_mce_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_intermittent_mce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_INTERMITTENT_MCE_COUNT: Intermittent MCE Count This is a 12-bit count of
+/// @note intermittent Marked Chip Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_intermittent_mce_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::INTERMITTENT_MCE_COUNT, TT::INTERMITTENT_MCE_COUNT_LEN>(o_value);
+ FAPI_INF("get_intermittent_mce_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_soft_mce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_SOFT_MCE_COUNT: Soft MCE Count This is a 12-bit count of
+/// @note soft Marked Chip Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_soft_mce_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SOFT_MCE_COUNT, TT::SOFT_MCE_COUNT_LEN>(i_value);
+ FAPI_INF("set_soft_mce_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_soft_mce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_SOFT_MCE_COUNT: Soft MCE Count This is a 12-bit count of
+/// @note soft Marked Chip Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_soft_mce_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SOFT_MCE_COUNT, TT::SOFT_MCE_COUNT_LEN>(o_value);
+ FAPI_INF("get_soft_mce_count: 0x%03lx", o_value);
+}
+
+} // close namespace read_error_count_reg0
+
+namespace read_error_count_reg1
+{
+
+///
+/// @brief Read MBS Memory Scrub/Read Error Count Register 1 (MBSEC1Q)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ FAPI_TRY( mss::getScom(i_target, TT::READ_ERROR_COUNT_REG1, o_data) );
+ FAPI_INF("%s read: 0x%016lx", mss::c_str(i_target), o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Memory Scrub/Read Error Count Register 1 (MBSEC1Q)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( mss::putScom(i_target, TT::READ_ERROR_COUNT_REG1, i_data) );
+ FAPI_INF("%s write: 0x%016lx", mss::c_str(i_target), i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_hard_mce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_HARD_MCE_COUNT: Hard MCE Count This is a 12-bit count of
+/// @note hard Marked Chip Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_hard_mce_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::HARD_MCE_COUNT, TT::HARD_MCE_COUNT_LEN>(i_value);
+ FAPI_INF("set_hard_mce_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_hard_mce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_HARD_MCE_COUNT: Hard MCE Count This is a 12-bit count of
+/// @note hard Marked Chip Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_hard_mce_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::HARD_MCE_COUNT, TT::HARD_MCE_COUNT_LEN>(o_value);
+ FAPI_INF("get_hard_mce_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_ice_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_ICE_COUNT: ICE (IMPE) Count This is a 12-bit count of
+/// @note Intermittent Marked-Placed Chip Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_ice_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::ICE_COUNT, TT::ICE_COUNT_LEN>(i_value);
+ FAPI_INF("set_ice_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_ice_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_ICE_COUNT: ICE (IMPE) Count This is a 12-bit count of
+/// @note Intermittent Marked-Placed Chip Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_ice_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::ICE_COUNT, TT::ICE_COUNT_LEN>(o_value);
+ FAPI_INF("get_ice_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_ue_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_UE_COUNT: UE Count This is a 12-bit count of
+/// @note Uncorrectable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_ue_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::UE_COUNT, TT::UE_COUNT_LEN>(i_value);
+ FAPI_INF("set_ue_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_ue_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_UE_COUNT: UE Count This is a 12-bit count of
+/// @note Uncorrectable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_ue_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::UE_COUNT, TT::UE_COUNT_LEN>(o_value);
+ FAPI_INF("get_ue_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_aue_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_AUE_COUNT: AUE Count This is a 12-bit count of
+/// @note AUE Parity Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_aue_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::AUE_COUNT, TT::AUE_COUNT_LEN>(i_value);
+ FAPI_INF("set_aue_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_aue_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_AUE_COUNT: AUE Count This is a 12-bit count of
+/// @note AUE Parity Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_aue_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::AUE_COUNT, TT::AUE_COUNT_LEN>(o_value);
+ FAPI_INF("get_aue_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_rce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSEC0Q_RCE_COUNT: RCE Count This is a 12-bit count of
+/// @note Retried Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_rce_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::RCE_COUNT, TT::RCE_COUNT_LEN>(i_value);
+ FAPI_INF("set_rce_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_rce_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSEC0Q_RCE_COUNT: RCE Count This is a 12-bit count of
+/// @note Retried Correctable Error events. Will freeze its value upon
+/// @note incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_rce_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::RCE_COUNT, TT::RCE_COUNT_LEN>(o_value);
+ FAPI_INF("get_rce_count: 0x%03lx", o_value);
+}
+
+} // close namespace read_error_count_reg1
+
+namespace mark_symbol_count_reg
+{
+
+///
+/// @brief Read MBS Mark Symbol Error Count Register (MBSMSECQ)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode read( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ FAPI_TRY( mss::getScom(i_target, TT::MARK_SYMBOL_COUNT_REG, o_data) );
+ FAPI_INF("read: 0x%016lx", o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write MBS Mark Symbol Error Count Register (MBSMSECQ)
+/// @tparam T fapi2 Target Type - derived from i_target's type
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_target the fapi2 target of the mcbist
+/// @param[in] i_data the value to write to the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline fapi2::ReturnCode write( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( mss::putScom(i_target, TT::MARK_SYMBOL_COUNT_REG, i_data) );
+ FAPI_INF("write: 0x%016lx", i_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set_symbol0_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL0_COUNT: MCE Symbol 0 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 0 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_symbol0_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SYMBOL0_COUNT, TT::SYMBOL0_COUNT_LEN>(i_value);
+ FAPI_INF("set_symbol0_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_symbol0_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL0_COUNT: MCE Symbol 0 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 0 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_symbol0_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SYMBOL0_COUNT, TT::SYMBOL0_COUNT_LEN>(o_value);
+ FAPI_INF("get_symbol0_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_symbol1_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL1_COUNT: MCE Symbol 1 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 1 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_symbol1_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SYMBOL1_COUNT, TT::SYMBOL1_COUNT_LEN>(i_value);
+ FAPI_INF("set_symbol1_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_symbol1_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL1_COUNT: MCE Symbol 1 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 1 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_symbol1_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SYMBOL1_COUNT, TT::SYMBOL1_COUNT_LEN>(o_value);
+ FAPI_INF("get_symbol1_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_symbol2_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL2_COUNT: MCE Symbol 2 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 2 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_symbol2_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SYMBOL2_COUNT, TT::SYMBOL2_COUNT_LEN>(i_value);
+ FAPI_INF("set_symbol2_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_symbol2_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL2_COUNT: MCE Symbol 2 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 2 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_symbol2_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SYMBOL2_COUNT, TT::SYMBOL2_COUNT_LEN>(o_value);
+ FAPI_INF("get_symbol2_count: 0x%03lx", o_value);
+}
+
+///
+/// @brief set_symbol3_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in, out] io_data the register value
+/// @param[in] i_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL3_COUNT: MCE Symbol 3 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 3 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void set_symbol3_count( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value )
+{
+ io_data.insertFromRight<TT::SYMBOL3_COUNT, TT::SYMBOL3_COUNT_LEN>(i_value);
+ FAPI_INF("set_symbol3_count: 0x%03lx", i_value);
+}
+
+///
+/// @brief get_symbol3_count
+/// @tparam T fapi2 Target Type defaults to DEFAULT_MC_TARGET
+/// @tparam TT traits type defaults to eccTraits<DEFAULT_MC_TYPE, T>
+/// @param[in] i_data the register value
+/// @param[out] o_value the value of the field
+/// @note MBSMSECQ_MCE_SYMBOL3_COUNT: MCE Symbol 3 Error Count This is a 8-bit count
+/// @note that increments on MCE when Symbol 3 under chip mark takes error. Will freeze
+/// @note its value upon incrementing to the max value until reset.
+///
+template< fapi2::TargetType T = DEFAULT_MC_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
+inline void get_symbol3_count( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value )
+{
+ i_data.extractToRight<TT::SYMBOL3_COUNT, TT::SYMBOL3_COUNT_LEN>(o_value);
+ FAPI_INF("get_symbol3_count: 0x%03lx", o_value);
+}
+
+} // close namespace mark_symbol_count_reg
+
+} // close namespace ecc
+
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/mss_generic_attribute_getters.H b/src/import/generic/memory/lib/mss_generic_attribute_getters.H
index f16829f3b..f18b799ea 100644
--- a/src/import/generic/memory/lib/mss_generic_attribute_getters.H
+++ b/src/import/generic/memory/lib/mss_generic_attribute_getters.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -37,6 +37,33 @@ namespace mss
namespace attr
{
///
+/// @brief ATTR_BAD_DQ_BITMAP getter
+/// @param[in] const ref to the TARGET_TYPE_DIMM
+/// @param[out] uint8_t&[] array reference to store the value
+/// @note Generated by gen_accessors.pl generate_other_attr_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Bad DQ bitmap from a controller point of view. The data is a 10 byte bitmap for
+/// each of 4 possible ranks. The bad DQ data is stored in NVRAM, and it is stored in
+/// a special format translated to a DIMM Connector point of view. All of these details
+/// are hidden from the user of this attribute.
+///
+inline fapi2::ReturnCode get_bad_dq_bitmap(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint8_t (&o_array)[4][10])
+{
+ uint8_t l_value[4][10] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_BAD_DQ_BITMAP, i_target, l_value) );
+ memcpy(o_array, &l_value, 40);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_BAD_DQ_BITMAP: 0x%lx",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
+
+///
/// @brief ATTR_MEM_DIMM_POS_METADATA getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
/// @param[out] uint32_t& reference to store the value
@@ -960,27 +987,45 @@ fapi_try_exit:
///
-/// @brief ATTR_BAD_DQ_BITMAP getter
-/// @param[in] const ref to the TARGET_TYPE_DIMM
-/// @param[out] uint8_t&[] array reference to store the value
+/// @brief ATTR_OMI_DL_PREIPL_PRBS_TIME getter
+/// @param[in] const ref to the TARGET_TYPE_OMI
+/// @param[out] uint32_t& reference to store the value
/// @note Generated by gen_accessors.pl generate_other_attr_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Bad DQ bitmap from a controller point of view. The data is a 10 byte bitmap for
-/// each of 4 possible ranks. The bad DQ data is stored in NVRAM, and it is stored in
-/// a special format translated to a DIMM Connector point of view. All of these details
-/// are hidden from the user of this attribute.
+/// @note The time to send pre-ipl PRBS in ms.
///
-inline fapi2::ReturnCode get_bad_dq_bitmap(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- uint8_t (&o_array)[4][10])
+inline fapi2::ReturnCode get_omi_dl_preipl_prbs_time(const fapi2::Target<fapi2::TARGET_TYPE_OMI>& i_target,
+ uint32_t& o_value)
{
- uint8_t l_value[4][10] = {};
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_BAD_DQ_BITMAP, i_target, l_value) );
- memcpy(o_array, &l_value, 40);
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_OMI_DL_PREIPL_PRBS_TIME, i_target, o_value) );
return fapi2::current_err;
fapi_try_exit:
- FAPI_ERR("failed getting ATTR_BAD_DQ_BITMAP: 0x%lx",
+ FAPI_ERR("failed getting ATTR_OMI_DL_PREIPL_PRBS_TIME: 0x%lx",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief ATTR_MSS_OMI_EDPL_DISABLE getter
+/// @param[out] uint8_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_other_attr_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note EDPL (Error Detection Per Lane) is a feature in the DL that adds some additional
+/// checks to the traffic going across the OpenCAPI link in order to better track which
+/// lanes are having issues. Note: EDPL must be set the same on both sides of the link.
+/// This attribute affects both the proc/mc side and the OCMB side.
+///
+inline fapi2::ReturnCode get_mss_omi_edpl_disable(uint8_t& o_value)
+{
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_OMI_EDPL_DISABLE, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), o_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MSS_OMI_EDPL_DISABLE: 0x%lx",
uint64_t(fapi2::current_err));
return fapi2::current_err;
}
@@ -1464,14 +1509,60 @@ fapi_try_exit:
}
///
+/// @brief ATTR_MEM_EFF_PRIM_DIE_COUNT getter
+/// @param[in] const ref to the TARGET_TYPE_DIMM
+/// @param[out] uint8_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note ARRAY[DIMM] Primary SDRAM Die Count. Decodes Byte 6 (bits 6~4).
+///
+inline fapi2::ReturnCode get_prim_die_count(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_value)
+{
+ uint8_t l_value[2] = {};
+ const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_PRIM_DIE_COUNT, l_port, l_value) );
+ o_value = l_value[mss::index(i_target)];
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_PRIM_DIE_COUNT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MEM_EFF_PRIM_DIE_COUNT getter
+/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
+/// @param[out] uint8_t&[] array reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note ARRAY[DIMM] Primary SDRAM Die Count. Decodes Byte 6 (bits 6~4).
+///
+inline fapi2::ReturnCode get_prim_die_count(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
+ uint8_t (&o_array)[2])
+{
+ uint8_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_PRIM_DIE_COUNT, i_target, l_value) );
+ memcpy(o_array, &l_value, 2);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_PRIM_DIE_COUNT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
/// @brief ATTR_MEM_EFF_PRIM_STACK_TYPE getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
/// @param[out] uint8_t& reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM] Primary SDRAM Package Type. Decodes Byte 6. This byte defines the primary
-/// set of SDRAMs. Monolithic = SPD, Multi-load stack = DDP/QDP, Single-load stack =
-/// 3DS
+/// @note ARRAY[DIMM] Primary SDRAM Package Type (bits 1~0). Decodes Byte 6. This byte defines
+/// the primary set of SDRAMs. Monolithic = SPD, Multi-load stack = DDP/QDP, Single-load
+/// stack = 3DS
///
inline fapi2::ReturnCode get_prim_stack_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_value)
{
@@ -1494,9 +1585,9 @@ fapi_try_exit:
/// @param[out] uint8_t&[] array reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM] Primary SDRAM Package Type. Decodes Byte 6. This byte defines the primary
-/// set of SDRAMs. Monolithic = SPD, Multi-load stack = DDP/QDP, Single-load stack =
-/// 3DS
+/// @note ARRAY[DIMM] Primary SDRAM Package Type (bits 1~0). Decodes Byte 6. This byte defines
+/// the primary set of SDRAMs. Monolithic = SPD, Multi-load stack = DDP/QDP, Single-load
+/// stack = 3DS
///
inline fapi2::ReturnCode get_prim_stack_type(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
uint8_t (&o_array)[2])
@@ -1514,6 +1605,52 @@ fapi_try_exit:
}
///
+/// @brief ATTR_MEM_EFF_PRIM_BUS_WIDTH getter
+/// @param[in] const ref to the TARGET_TYPE_DIMM
+/// @param[out] uint8_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note ARRAY[DIMM] Primary bus with (bits 1~0). Decodes Byte 13.
+///
+inline fapi2::ReturnCode get_prim_bus_width(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_value)
+{
+ uint8_t l_value[2] = {};
+ const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_PRIM_BUS_WIDTH, l_port, l_value) );
+ o_value = l_value[mss::index(i_target)];
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_PRIM_BUS_WIDTH: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MEM_EFF_PRIM_BUS_WIDTH getter
+/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
+/// @param[out] uint8_t&[] array reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note ARRAY[DIMM] Primary bus with (bits 1~0). Decodes Byte 13.
+///
+inline fapi2::ReturnCode get_prim_bus_width(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
+ uint8_t (&o_array)[2])
+{
+ uint8_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_PRIM_BUS_WIDTH, i_target, l_value) );
+ memcpy(o_array, &l_value, 2);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_PRIM_BUS_WIDTH: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
/// @brief ATTR_MEM_EFF_DRAM_PPR getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
/// @param[out] uint8_t& reference to store the value
@@ -1968,7 +2105,7 @@ fapi_try_exit:
}
///
-/// @brief ATTR_MEM_EFF_NUM_RANKS_PER_DIMM getter
+/// @brief ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
/// @param[out] uint8_t& reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
@@ -1979,24 +2116,24 @@ fapi_try_exit:
/// number of logical ranks per DIMM. Logical rank refers the individually addressable
/// die in a 3DS stack and has no meaning for monolithic or multi-load stacked SDRAMs.
///
-inline fapi2::ReturnCode get_num_ranks_per_dimm(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+inline fapi2::ReturnCode get_logical_ranks_per_dimm(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
uint8_t& o_value)
{
uint8_t l_value[2] = {};
const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_NUM_RANKS_PER_DIMM, l_port, l_value) );
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM, l_port, l_value) );
o_value = l_value[mss::index(i_target)];
return fapi2::current_err;
fapi_try_exit:
- FAPI_ERR("failed getting ATTR_MEM_EFF_NUM_RANKS_PER_DIMM: 0x%lx (target: %s)",
+ FAPI_ERR("failed getting ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM: 0x%lx (target: %s)",
uint64_t(fapi2::current_err), mss::c_str(i_target));
return fapi2::current_err;
}
///
-/// @brief ATTR_MEM_EFF_NUM_RANKS_PER_DIMM getter
+/// @brief ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM getter
/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
/// @param[out] uint8_t&[] array reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
@@ -2007,17 +2144,63 @@ fapi_try_exit:
/// number of logical ranks per DIMM. Logical rank refers the individually addressable
/// die in a 3DS stack and has no meaning for monolithic or multi-load stacked SDRAMs.
///
-inline fapi2::ReturnCode get_num_ranks_per_dimm(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
+inline fapi2::ReturnCode get_logical_ranks_per_dimm(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
uint8_t (&o_array)[2])
{
uint8_t l_value[2] = {};
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_NUM_RANKS_PER_DIMM, i_target, l_value) );
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM, i_target, l_value) );
memcpy(o_array, &l_value, 2);
return fapi2::current_err;
fapi_try_exit:
- FAPI_ERR("failed getting ATTR_MEM_EFF_NUM_RANKS_PER_DIMM: 0x%lx (target: %s)",
+ FAPI_ERR("failed getting ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MEM_3DS_HEIGHT getter
+/// @param[in] const ref to the TARGET_TYPE_DIMM
+/// @param[out] uint16_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Setting for 3DS stack. Calculated from logical_ranks / master_ranks
+///
+inline fapi2::ReturnCode get_3ds_height(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint16_t& o_value)
+{
+ uint16_t l_value[2] = {};
+ const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_3DS_HEIGHT, l_port, l_value) );
+ o_value = l_value[mss::index(i_target)];
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_3DS_HEIGHT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MEM_3DS_HEIGHT getter
+/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
+/// @param[out] uint16_t&[] array reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Setting for 3DS stack. Calculated from logical_ranks / master_ranks
+///
+inline fapi2::ReturnCode get_3ds_height(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
+ uint16_t (&o_array)[2])
+{
+ uint16_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_3DS_HEIGHT, i_target, l_value) );
+ memcpy(o_array, &l_value, 4);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_3DS_HEIGHT: 0x%lx (target: %s)",
uint64_t(fapi2::current_err), mss::c_str(i_target));
return fapi2::current_err;
}
@@ -2074,7 +2257,8 @@ fapi_try_exit:
/// @param[out] uint16_t& reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351
+/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351 for ISDIMMs Decodes
+/// SPD Byte 552 and 553 for DDIMMs
///
inline fapi2::ReturnCode get_dram_mfg_id(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint16_t& o_value)
{
@@ -2097,7 +2281,8 @@ fapi_try_exit:
/// @param[out] uint16_t&[] array reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351
+/// @note ARRAY[DIMM] DRAM Manufacturer ID Code Decodes SPD Byte 350 and 351 for ISDIMMs Decodes
+/// SPD Byte 552 and 553 for DDIMMs
///
inline fapi2::ReturnCode get_dram_mfg_id(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
uint16_t (&o_array)[2])
@@ -2115,6 +2300,53 @@ fapi_try_exit:
}
///
+/// @brief ATTR_MEM_EFF_DRAM_MODULE_HEIGHT getter
+/// @param[in] const ref to the TARGET_TYPE_DIMM
+/// @param[out] uint8_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note ARRAY[DIMM] DRAM Modlue Height Decodes SPD Byte 193
+///
+inline fapi2::ReturnCode get_dram_module_height(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint8_t& o_value)
+{
+ uint8_t l_value[2] = {};
+ const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_DRAM_MODULE_HEIGHT, l_port, l_value) );
+ o_value = l_value[mss::index(i_target)];
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_DRAM_MODULE_HEIGHT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MEM_EFF_DRAM_MODULE_HEIGHT getter
+/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
+/// @param[out] uint8_t&[] array reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note ARRAY[DIMM] DRAM Modlue Height Decodes SPD Byte 193
+///
+inline fapi2::ReturnCode get_dram_module_height(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
+ uint8_t (&o_array)[2])
+{
+ uint8_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_DRAM_MODULE_HEIGHT, i_target, l_value) );
+ memcpy(o_array, &l_value, 2);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_DRAM_MODULE_HEIGHT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
/// @brief ATTR_MEM_EFF_RCD_MFG_ID getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
/// @param[out] uint16_t& reference to store the value
@@ -2414,6 +2646,26 @@ fapi_try_exit:
}
///
+/// @brief ATTR_MEM_EFF_DRAM_MDS getter
+/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
+/// @param[out] uint8_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Controls if the given target has an MDS (managed DRAM solution)
+///
+inline fapi2::ReturnCode get_dram_mds(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target, uint8_t& o_value)
+{
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_DRAM_MDS, i_target, o_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_DRAM_MDS: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
/// @brief ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
/// @param[out] uint8_t& reference to store the value
@@ -2602,6 +2854,26 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief ATTR_MEM_EFF_SPD_REVISION getter
+/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
+/// @param[out] uint8_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note SPD Revision (SPD Byte 1)
+///
+inline fapi2::ReturnCode get_spd_revision(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target, uint8_t& o_value)
+{
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_EFF_SPD_REVISION, i_target, o_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_SPD_REVISION: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
///
/// @brief ATTR_MEM_EFF_VOLT_VDDR getter
@@ -3106,100 +3378,6 @@ fapi_try_exit:
}
///
-/// @brief ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE getter
-/// @param[in] const ref to the TARGET_TYPE_DIMM
-/// @param[out] uint8_t&[] array reference to store the value
-/// @note Generated by gen_accessors.pl generate_mc_port_params
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM][RANK] vrefdq_train value. This is for DDR4 MRS6.
-///
-inline fapi2::ReturnCode get_si_vref_dq_train_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- uint8_t (&o_array)[4])
-{
- uint8_t l_value[2][4] = {};
- const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
-
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE, l_port, l_value) );
- memcpy(o_array, &(l_value[mss::index(i_target)][0]), 4);
- return fapi2::current_err;
-
-fapi_try_exit:
- FAPI_ERR("failed getting ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE: 0x%lx (target: %s)",
- uint64_t(fapi2::current_err), mss::c_str(i_target));
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE getter
-/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
-/// @param[out] uint8_t&[] array reference to store the value
-/// @note Generated by gen_accessors.pl generate_mc_port_params
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM][RANK] vrefdq_train value. This is for DDR4 MRS6.
-///
-inline fapi2::ReturnCode get_si_vref_dq_train_value(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
- uint8_t (&o_array)[2][4])
-{
- uint8_t l_value[2][4] = {};
-
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE, i_target, l_value) );
- memcpy(o_array, &l_value, 8);
- return fapi2::current_err;
-
-fapi_try_exit:
- FAPI_ERR("failed getting ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE: 0x%lx (target: %s)",
- uint64_t(fapi2::current_err), mss::c_str(i_target));
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE getter
-/// @param[in] const ref to the TARGET_TYPE_DIMM
-/// @param[out] uint8_t&[] array reference to store the value
-/// @note Generated by gen_accessors.pl generate_mc_port_params
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM][RANK] vrefdq_train range. This is for DDR4 MRS6.
-///
-inline fapi2::ReturnCode get_si_vref_dq_train_range(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- uint8_t (&o_array)[4])
-{
- uint8_t l_value[2][4] = {};
- const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
-
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE, l_port, l_value) );
- memcpy(o_array, &(l_value[mss::index(i_target)][0]), 4);
- return fapi2::current_err;
-
-fapi_try_exit:
- FAPI_ERR("failed getting ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE: 0x%lx (target: %s)",
- uint64_t(fapi2::current_err), mss::c_str(i_target));
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE getter
-/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
-/// @param[out] uint8_t&[] array reference to store the value
-/// @note Generated by gen_accessors.pl generate_mc_port_params
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note ARRAY[DIMM][RANK] vrefdq_train range. This is for DDR4 MRS6.
-///
-inline fapi2::ReturnCode get_si_vref_dq_train_range(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
- uint8_t (&o_array)[2][4])
-{
- uint8_t l_value[2][4] = {};
-
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE, i_target, l_value) );
- memcpy(o_array, &l_value, 8);
- return fapi2::current_err;
-
-fapi_try_exit:
- FAPI_ERR("failed getting ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE: 0x%lx (target: %s)",
- uint64_t(fapi2::current_err), mss::c_str(i_target));
- return fapi2::current_err;
-}
-
-///
/// @brief ATTR_MEM_SI_GEARDOWN_MODE getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
/// @param[out] uint8_t&[] array reference to store the value
@@ -3590,20 +3768,20 @@ fapi_try_exit:
///
/// @brief ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
-/// @param[out] uint8_t&[] array reference to store the value
+/// @param[out] uint16_t&[] array reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] Memory Controller side Drive Impedance Pull Down for Data and
/// Data Strobe Lines in Ohms.
///
inline fapi2::ReturnCode get_si_mc_drv_imp_dq_dqs_pull_down(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- uint8_t (&o_array)[4])
+ uint16_t (&o_array)[4])
{
- uint8_t l_value[2][4] = {};
+ uint16_t l_value[2][4] = {};
const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN, l_port, l_value) );
- memcpy(o_array, &(l_value[mss::index(i_target)][0]), 4);
+ memcpy(o_array, &(l_value[mss::index(i_target)][0]), 8);
return fapi2::current_err;
fapi_try_exit:
@@ -3615,19 +3793,19 @@ fapi_try_exit:
///
/// @brief ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN getter
/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
-/// @param[out] uint8_t&[] array reference to store the value
+/// @param[out] uint16_t&[] array reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] Memory Controller side Drive Impedance Pull Down for Data and
/// Data Strobe Lines in Ohms.
///
inline fapi2::ReturnCode get_si_mc_drv_imp_dq_dqs_pull_down(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
- uint8_t (&o_array)[2][4])
+ uint16_t (&o_array)[2][4])
{
- uint8_t l_value[2][4] = {};
+ uint16_t l_value[2][4] = {};
FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN, i_target, l_value) );
- memcpy(o_array, &l_value, 8);
+ memcpy(o_array, &l_value, 16);
return fapi2::current_err;
fapi_try_exit:
@@ -3639,20 +3817,20 @@ fapi_try_exit:
///
/// @brief ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP getter
/// @param[in] const ref to the TARGET_TYPE_DIMM
-/// @param[out] uint8_t&[] array reference to store the value
+/// @param[out] uint16_t&[] array reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] Memory Controller side Drive Impedance Pull Up for Data and Data
/// Strobe Lines in Ohms.
///
inline fapi2::ReturnCode get_si_mc_drv_imp_dq_dqs_pull_up(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- uint8_t (&o_array)[4])
+ uint16_t (&o_array)[4])
{
- uint8_t l_value[2][4] = {};
+ uint16_t l_value[2][4] = {};
const auto l_port = i_target.getParent<fapi2::TARGET_TYPE_MEM_PORT>();
FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP, l_port, l_value) );
- memcpy(o_array, &(l_value[mss::index(i_target)][0]), 4);
+ memcpy(o_array, &(l_value[mss::index(i_target)][0]), 8);
return fapi2::current_err;
fapi_try_exit:
@@ -3664,19 +3842,19 @@ fapi_try_exit:
///
/// @brief ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP getter
/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
-/// @param[out] uint8_t&[] array reference to store the value
+/// @param[out] uint16_t&[] array reference to store the value
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] Memory Controller side Drive Impedance Pull Up for Data and Data
/// Strobe Lines in Ohms.
///
inline fapi2::ReturnCode get_si_mc_drv_imp_dq_dqs_pull_up(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
- uint8_t (&o_array)[2][4])
+ uint16_t (&o_array)[2][4])
{
- uint8_t l_value[2][4] = {};
+ uint16_t l_value[2][4] = {};
FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MEM_SI_MC_DRV_IMP_DQ_DQS_PULL_UP, i_target, l_value) );
- memcpy(o_array, &l_value, 8);
+ memcpy(o_array, &l_value, 16);
return fapi2::current_err;
fapi_try_exit:
@@ -4032,7 +4210,8 @@ fapi_try_exit:
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] READ, On Die Termination triggering bitmap. Use bitmap to determine
/// which ODT to fire for the designated rank. The bits in 8 bit field are [DIMM0 ODT0][DIMM0
-/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
+/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3] For
+/// Explorer: Only bits 0,1,4,5 are used. They correspond to A0 A1 -- -- B0 B1 -- --
///
inline fapi2::ReturnCode get_si_odt_rd(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t (&o_array)[4])
{
@@ -4057,7 +4236,8 @@ fapi_try_exit:
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] READ, On Die Termination triggering bitmap. Use bitmap to determine
/// which ODT to fire for the designated rank. The bits in 8 bit field are [DIMM0 ODT0][DIMM0
-/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
+/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3] For
+/// Explorer: Only bits 0,1,4,5 are used. They correspond to A0 A1 -- -- B0 B1 -- --
///
inline fapi2::ReturnCode get_si_odt_rd(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
uint8_t (&o_array)[2][4])
@@ -4082,7 +4262,8 @@ fapi_try_exit:
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] WRITE, On Die Termination triggering bitmap. Use bitmap to determine
/// which ODT to fire for the designated rank. The bits in 8 bit field are [DIMM0 ODT0][DIMM0
-/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
+/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3] For
+/// Explorer: Only bits 0,1,4,5 are used. They correspond to A0 A1 -- -- B0 B1 -- --
///
inline fapi2::ReturnCode get_si_odt_wr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t (&o_array)[4])
{
@@ -4107,7 +4288,8 @@ fapi_try_exit:
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
/// @note Array[DIMM][RANK] WRITE, On Die Termination triggering bitmap. Use bitmap to determine
/// which ODT to fire for the designated rank. The bits in 8 bit field are [DIMM0 ODT0][DIMM0
-/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
+/// ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3] For
+/// Explorer: Only bits 0,1,4,5 are used. They correspond to A0 A1 -- -- B0 B1 -- --
///
inline fapi2::ReturnCode get_si_odt_wr(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
uint8_t (&o_array)[2][4])
diff --git a/src/import/generic/memory/lib/prd/hwp_wrappers.H b/src/import/generic/memory/lib/prd/hwp_wrappers.H
new file mode 100644
index 000000000..afbb34a81
--- /dev/null
+++ b/src/import/generic/memory/lib/prd/hwp_wrappers.H
@@ -0,0 +1,246 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/prd/hwp_wrappers.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 hwp_wrappers.H
+/// @brief Main wrapper file for PRD calling memory procedure code
+///
+// *HWP HWP Owner: Matthew Hickman <Matthew.Hickman@ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _HWP_WRAPPERS_H_
+#define _HWP_WRAPPERS_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_memdiags.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H>
+#include <chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist_traits.H>
+
+///
+/// @brief Memdiags stop command wrapper for Nimbus
+/// @param[in] i_target the target
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+fapi2::ReturnCode nim_stop( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target );
+
+///
+/// @brief Memdiags stop command wrapper for Explorer
+/// @param[in] i_target the target
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+fapi2::ReturnCode exp_stop( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target );
+
+///
+/// @brief Memdiags Super Fast Init command wrapper for Nimbus
+/// @param[in] i_target the target behind which all memory should be initialized
+/// @param[in] i_pattern an index representing a pattern to use to init memory (defaults to 0)
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode nim_sf_init( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ const uint64_t i_pattern );
+
+///
+/// @brief Memdiags Super Fast Init command wrapper for Nimbus
+/// @param[in] i_target the target behind which all memory should be initialized
+/// @param[in] i_pattern an index representing a pattern to use to init memory (defaults to 0)
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode exp_sf_init( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const uint64_t i_pattern );
+
+///
+/// @brief Memdiags Super Fast Read command wrapper for Nimbus
+/// @param[in] i_target the target behind which all memory should be read
+/// @param[in] i_stop stop conditions
+/// @param[in] i_address mcbist::address representing the address from which to start.
+// Defaults to the first address behind the target
+/// @param[in] i_end whether to end, and where
+/// Defaults to stop after slave rank
+/// @param[in] i_end_address mcbist::address representing the address to end.
+// Defaults to TT::LARGEST_ADDRESS
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode nim_sf_read( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ const mss::mcbist::stop_conditions<mss::mc_type::NIMBUS>& i_stop,
+ const mss::mcbist::address& i_address = mss::mcbist::address(),
+ const mss::mcbist::end_boundary i_end = mss::mcbist::end_boundary::STOP_AFTER_SLAVE_RANK,
+ const mss::mcbist::address& i_end_address = mss::mcbist::address(
+ mss::mcbistTraits<mss::mc_type::NIMBUS, fapi2::TARGET_TYPE_MCBIST>::LARGEST_ADDRESS) );
+
+///
+/// @brief Memdiags Super Fast Read command wrapper for Explorer
+/// @param[in] i_target the target behind which all memory should be read
+/// @param[in] i_stop stop conditions
+/// @param[in] i_address mcbist::address representing the address from which to start.
+// Defaults to the first address behind the target
+/// @param[in] i_end whether to end, and where
+/// Defaults to stop after slave rank
+/// @param[in] i_end_address mcbist::address representing the address to end.
+// Defaults to TT::LARGEST_ADDRESS
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode exp_sf_read( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const mss::mcbist::stop_conditions<mss::mc_type::EXPLORER>& i_stop,
+ const mss::mcbist::address& i_address = mss::mcbist::address(),
+ const mss::mcbist::end_boundary i_end = mss::mcbist::end_boundary::STOP_AFTER_SLAVE_RANK,
+ const mss::mcbist::address& i_end_address = mss::mcbist::address(
+ mss::mcbistTraits<mss::mc_type::EXPLORER, fapi2::TARGET_TYPE_OCMB_CHIP>::LARGEST_ADDRESS) );
+
+///
+/// @brief Continuous background scrub command wrapper for Nimbus
+/// @param[in] i_target the target behind which all memory should be scrubbed
+/// @param[in] i_stop stop conditions
+/// @param[in] i_speed the speed to scrub
+/// @param[in] i_address mcbist::address representing the address from which to start.
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode nim_background_scrub( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ const mss::mcbist::stop_conditions<mss::mc_type::NIMBUS>& i_stop,
+ const mss::mcbist::speed i_speed,
+ const mss::mcbist::address& i_address );
+
+///
+/// @brief Continuous background scrub command wrapper for Explorer
+/// @param[in] i_target the target behind which all memory should be scrubbed
+/// @param[in] i_stop stop conditions
+/// @param[in] i_speed the speed to scrub
+/// @param[in] i_address mcbist::address representing the address from which to start.
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode exp_background_scrub( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const mss::mcbist::stop_conditions<mss::mc_type::EXPLORER>& i_stop,
+ const mss::mcbist::speed i_speed,
+ const mss::mcbist::address& i_address );
+
+///
+/// @brief Targeted scrub command wrapper for Nimbus
+/// @param[in] i_target the target behind which all memory should be scrubbed
+/// @param[in] i_stop stop conditions
+/// @param[in] i_speed the speed to scrub
+/// @param[in] i_start_address mcbist::address representing the address from which to start.
+/// @param[in] i_end_address mcbist::address representing the address at which to end.
+/// @param[in] i_end whether to end, and where
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode nim_targeted_scrub( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ const mss::mcbist::stop_conditions<mss::mc_type::NIMBUS>& i_stop,
+ const mss::mcbist::address& i_start_address,
+ const mss::mcbist::address& i_end_address,
+ const mss::mcbist::end_boundary i_end );
+
+///
+/// @brief Targeted scrub command wrapper for Explorer
+/// @param[in] i_target the target behind which all memory should be scrubbed
+/// @param[in] i_stop stop conditions
+/// @param[in] i_speed the speed to scrub
+/// @param[in] i_start_address mcbist::address representing the address from which to start.
+/// @param[in] i_end_address mcbist::address representing the address at which to end.
+/// @param[in] i_end whether to end, and where
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+fapi2::ReturnCode exp_targeted_scrub( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const mss::mcbist::stop_conditions<mss::mc_type::EXPLORER>& i_stop,
+ const mss::mcbist::address& i_start_address,
+ const mss::mcbist::address& i_end_address,
+ const mss::mcbist::end_boundary i_end );
+
+///
+/// @brief Continue current command wrapper for Nimbus
+/// @param[in] i_target the target
+/// @param[in] i_end whether to end, and where (default - don't stop at end of rank)
+/// @param[in] i_stop stop conditions (default - 0 meaning 'don't change conditions')
+/// @param[in] i_speed the speed to scrub (default - SAME_SPEED meaning leave speed untouched)
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+fapi2::ReturnCode nim_continue_cmd( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ const mss::mcbist::end_boundary i_end = mss::mcbist::end_boundary::DONT_CHANGE,
+ const mss::mcbist::stop_conditions<mss::mc_type::NIMBUS>& i_stop = mss::mcbist::stop_conditions<mss::mc_type::NIMBUS>
+ (mss::mcbist::stop_conditions<mss::mc_type::NIMBUS>::DONT_CHANGE),
+ const mss::mcbist::speed i_speed = mss::mcbist::speed::SAME_SPEED );
+
+///
+/// @brief Continue current command wrapper for Explorer
+/// @param[in] i_target the target
+/// @param[in] i_end whether to end, and where (default - don't stop at end of rank)
+/// @param[in] i_stop stop conditions (default - 0 meaning 'don't change conditions')
+/// @param[in] i_speed the speed to scrub (default - SAME_SPEED meaning leave speed untouched)
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+fapi2::ReturnCode exp_continue_cmd( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const mss::mcbist::end_boundary i_end = mss::mcbist::end_boundary::DONT_CHANGE,
+ const mss::mcbist::stop_conditions<mss::mc_type::EXPLORER>& i_stop =
+ mss::mcbist::stop_conditions<mss::mc_type::EXPLORER>
+ (mss::mcbist::stop_conditions<mss::mc_type::EXPLORER>::DONT_CHANGE),
+ const mss::mcbist::speed i_speed = mss::mcbist::speed::SAME_SPEED );
+
+///
+/// @brief Broadcast mode check wrapper for Nimbus
+/// @param[in] i_target the target to effect
+/// @return o_capable - yes iff these vector of targets are broadcast capable
+///
+const mss::states nim_is_broadcast_capable(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target);
+
+
+///
+/// @brief Broadcast mode check wrapper for Nimbus
+/// @param[in] i_targets the vector of targets to analyze
+/// @return o_capable - yes iff these vector of targets are broadcast capable
+///
+const mss::states nim_is_broadcast_capable(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_MCBIST>>& i_targets);
+
+///
+/// @brief Broadcast mode check wrapper for Nimbus
+/// @param[in] i_kinds the dimms to effect
+/// @return o_capable - yes iff these vector of targets are broadcast capable
+///
+const mss::states nim_is_broadcast_capable(const std::vector<mss::dimm::kind<>>& i_kinds);
+
+///
+/// @brief Broadcast mode check wrapper for Explorer
+/// @param[in] i_target the target to effect
+/// @return o_capable - yes iff these vector of targets are broadcast capable
+///
+const mss::states exp_is_broadcast_capable(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target);
+
+
+///
+/// @brief Broadcast mode check wrapper for Explorer
+/// @param[in] i_targets the vector of targets to analyze
+/// @return o_capable - yes iff these vector of targets are broadcast capable
+///
+const mss::states exp_is_broadcast_capable(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>>& i_targets);
+
+///
+/// @brief Broadcast mode check wrapper for Explorer
+/// @param[in] i_kinds the dimms to effect
+/// @return o_capable - yes iff these vector of targets are broadcast capable
+///
+const mss::states exp_is_broadcast_capable(const std::vector<mss::dimm::kind<>>& i_kinds);
+
+#endif
diff --git a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H
index 12821c76f..1ebd48115 100644
--- a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H
+++ b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H
@@ -493,7 +493,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_twrmin_msn, l_twrmin_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, TWRMIN));
+ FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, U, TWRMIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Write Recovery Time (tWRmin) in MTB units: %d",
@@ -526,7 +526,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_twtr_lmin_msn, l_twtr_lmin_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, TWTR_L_MIN));
+ FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, U, TWTR_L_MIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Write to Read Time - Different Bank Group (tWTR_Lmin) in MTB units: %d",
@@ -560,7 +560,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_twtr_smin_msn, l_twtr_smin_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, TWTR_S_MIN));
+ FAPI_TRY( check::max_timing_range<BITS12>(i_target, l_buffer, U, TWTR_S_MIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Write to Read Time - Different Bank Group (tWTR_Smin) in MTB units: %d",
@@ -1275,7 +1275,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_tRASmin_msn, l_tRASmin_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, TRASMIN));
+ FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, R, TRASMIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Active to Precharge Delay Time (tRASmin) in MTB units: %d",
@@ -1305,7 +1305,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_trcmin_msn, l_trcmin_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, TRCMIN));
+ FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, R, TRCMIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB units: %d",
@@ -1336,7 +1336,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_trfc1min_msb, l_trfc1min_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, TRFC1MIN));
+ FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, R, TRFC1MIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB units: %d",
@@ -1366,7 +1366,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_trfc2min_msb, l_trfc2min_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, TRFC2MIN));
+ FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, R, TRFC2MIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB units: %d",
@@ -1396,7 +1396,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_trfc4min_msb, l_trfc4min_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, TRFC4MIN));
+ FAPI_TRY( check::max_timing_range<BITS16>(iv_target, l_buffer, R, TRFC4MIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB units: %d",
@@ -1426,7 +1426,7 @@ class decoder<DDR4, BASE_CNFG, R> : public base_cnfg_decoder
right_aligned_insert(l_buffer, l_tfawmin_msn, l_tfawmin_lsb);
// Update output only after check passes
- FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, TFAWMIN));
+ FAPI_TRY( check::max_timing_range<BITS12>(iv_target, l_buffer, R, TFAWMIN));
o_value = l_buffer;
FAPI_INF("%s. Minimum Four Activate Window Delay Time (tFAWmin) in MTB units: %d",
diff --git a/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H b/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H
index 11e5f3a6e..7ccd72116 100644
--- a/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H
+++ b/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2019 */
+/* Contributors Listed Below - COPYRIGHT 2016,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -107,6 +107,17 @@ class dimm_module_decoder
}
///
+ /// @brief Decodes SPD Revision -> SPD_REVISION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode revision(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
/// @brief Decodes module nominal height max
/// @param[out] o_output height range encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
@@ -559,11 +570,11 @@ class dimm_module_decoder
// DDIMM information from here on out
//////////////////////////////////////////
///
- /// @brief Decodes SPD Revision for bytes 192->447 -> SPD_REVISION
+ /// @brief Decodes SPD Revision for bytes 192->447 -> SPD_REV_DDIMM_MODULE
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode ddimm_spd_revision(uint8_t& o_output) const
+ virtual fapi2::ReturnCode ddimm_module_spd_revision(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
@@ -953,7 +964,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWA Voltage Setting -> PMIC0_SWA_RANGE
+ /// @brief Decodes PMIC0 SWA Voltage Setting -> PMIC0_SWA_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -975,11 +986,22 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWA Voltage Offset -> PMIC0_SWA_OFF_RANGE
+ /// @brief Decodes PMIC0 SWA Voltage Offset -> PMIC0_SWA_OFF_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swa_pmic0(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_offset_direction_swa_pmic0(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWA Delay -> PMIC0_SWA_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_delay_swa_pmic0(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
@@ -1008,7 +1030,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWB Voltage Setting -> PMIC0_SWB_RANGE
+ /// @brief Decodes PMIC0 SWB Voltage Setting -> PMIC0_SWB_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1030,18 +1052,29 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWB Voltage Offset -> PMIC0_SWB_OFF_RANGE
+ /// @brief Decodes PMIC0 SWB Voltage Offset -> PMIC0_SWB_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swb_pmic0(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWB Delay -> PMIC0_SWB_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swb_pmic0(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_delay_swb_pmic0(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWB Delay Sequence Order -> PMIC0_SWB_ORDER
+ /// @brief Decodes PMIC0 SWB Sequence Order -> PMIC0_SWB_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1063,7 +1096,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWC Voltage Setting -> PMIC0_SWC_RANGE
+ /// @brief Decodes PMIC0 SWC Voltage Setting -> PMIC0_SWC_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1085,18 +1118,29 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWC Voltage Offset -> PMIC0_SWC_OFF_RANGE
+ /// @brief Decodes PMIC0 SWC Voltage Offset -> PMIC0_SWC_OFF_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swc_pmic0(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_offset_direction_swc_pmic0(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWC Delay Sequence Order -> PMIC0_SWC_ORDER
+ /// @brief Decodes PMIC0 SWC Delay -> PMIC0_SWC_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_delay_swc_pmic0(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWC Sequence Order -> PMIC0_SWC_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1118,7 +1162,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWD Voltage Setting -> PMIC0_SWD_RANGE
+ /// @brief Decodes PMIC0 SWD Voltage Setting -> PMIC0_SWD_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1140,18 +1184,29 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWD Voltage Offset -> PMIC0_SWD_OFF_RANGE
+ /// @brief Decodes PMIC0 SWD Voltage Offset -> PMIC0_SWD_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swd_pmic0(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWD Delay -> PMIC0_SWD_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swd_pmic0(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_delay_swd_pmic0(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWD Delay Sequence Order -> PMIC0_SWD_ORDER
+ /// @brief Decodes PMIC0 SWD Sequence Order -> PMIC0_SWD_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1184,7 +1239,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWA Voltage Setting -> PMIC1_SWA_RANGE
+ /// @brief Decodes PMIC1 SWA Voltage Setting -> PMIC1_SWA_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1206,18 +1261,29 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWA Voltage Offset -> PMIC1_SWA_OFF_RANGE
+ /// @brief Decodes PMIC1 SWA Voltage Offset -> PMIC1_SWA_OFF_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swa_pmic1(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_offset_direction_swa_pmic1(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWA Delay Sequence Order -> PMIC1_SWA_ORDER
+ /// @brief Decodes PMIC1 SWA Delay -> PMIC1_SWA_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_delay_swa_pmic1(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWA Sequence Order -> PMIC1_SWA_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1239,7 +1305,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWB Voltage Setting -> PMIC1_SWB_RANGE
+ /// @brief Decodes PMIC1 SWB Voltage Setting -> PMIC1_SWB_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1261,18 +1327,29 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWB Voltage Offset -> PMIC1_SWB_OFF_RANGE
+ /// @brief Decodes PMIC1 SWB Voltage Offset -> PMIC1_SWB_OFF_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swb_pmic1(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_offset_direction_swb_pmic1(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWB Delay Sequence Order -> PMIC1_SWB_ORDER
+ /// @brief Decodes PMIC1 SWB Delay -> PMIC1_SWB_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_delay_swb_pmic1(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWB Sequence Order -> PMIC1_SWB_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1294,7 +1371,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWC Voltage Setting -> PMIC1_SWC_RANGE
+ /// @brief Decodes PMIC1 SWC Voltage Setting -> PMIC1_SWC_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1316,18 +1393,29 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWC Voltage Offset -> PMIC1_SWC_OFF_RANGE
+ /// @brief Decodes PMIC1 SWC Voltage Offset -> PMIC1_SWC_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swc_pmic1(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWC Delay -> PMIC1_SWC_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swc_pmic1(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_delay_swc_pmic1(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWC Delay Sequence Order -> PMIC1_SWC_ORDER
+ /// @brief Decodes PMIC1 SWC Sequence Order -> PMIC1_SWC_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1349,7 +1437,7 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWD Voltage Setting -> PMIC1_SWD_RANGE
+ /// @brief Decodes PMIC1 SWD Voltage Setting -> PMIC1_SWD_RANGE_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1371,18 +1459,29 @@ class dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWD Voltage Offset -> PMIC1_SWD_OFF_RANGE
+ /// @brief Decodes PMIC1 SWD Voltage Offset -> PMIC1_SWD_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swd_pmic1(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWD Delay -> PMIC1_SWD_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swd_pmic1(uint8_t& o_output) const
+ virtual fapi2::ReturnCode volt_delay_swd_pmic1(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWD Delay Sequence Order -> PMIC1_SWD_ORDER
+ /// @brief Decodes PMIC1 SWD Sequence Order -> PMIC1_SWD_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1402,6 +1501,39 @@ class dimm_module_decoder
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
+
+ ///
+ /// @brief Decodes PMIC0 Sequence Order
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sequence_pmic0(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 Sequence Order
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sequence_pmic1(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM Manufacturer ID code
+ /// @param[out] o_value dram manufacturing id code
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ virtual fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value ) const
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
};
}// spd
diff --git a/src/import/generic/memory/lib/spd/common/spd_decoder_base.H b/src/import/generic/memory/lib/spd/common/spd_decoder_base.H
index 878d2f27e..d69d216b5 100644
--- a/src/import/generic/memory/lib/spd/common/spd_decoder_base.H
+++ b/src/import/generic/memory/lib/spd/common/spd_decoder_base.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017,2018 */
+/* Contributors Listed Below - COPYRIGHT 2017,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -788,6 +788,66 @@ class base_cnfg_decoder
}
///
+ /// @brief Decodes Fine Offset for tWTR_L
+ /// @param[out] o_value tWTR_L offset in FTB units
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_twtr_l( int64_t& o_value ) const
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for twtr_s
+ /// @param[out] o_value twtr_s offset in FTB units
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_twtr_s( int64_t& o_value ) const
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for tfaw
+ /// @param[out] o_value tfaw offset in FTB units
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_tfaw( int64_t& o_value ) const
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for tras
+ /// @param[out] o_value tras offset in FTB units
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_tras( int64_t& o_value ) const
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for twr
+ /// @param[out] o_value twr offset in FTB units
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_twr( int64_t& o_value ) const
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
/// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section
/// @param[out] o_value crc value from SPD
/// @return FAPI2_RC_SUCCESS iff okay
diff --git a/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H b/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H
index 2d1816ab3..fb93691d2 100644
--- a/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H
+++ b/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -54,7 +54,7 @@ namespace spd
/// @brief DDIMM module SPD DRAM decoder
///
template < rev R >
-class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
+class decoder< DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
{
private:
@@ -114,13 +114,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes SPD Revision for bytes 192->447 -> SPD_REVISION
+ /// @brief Decodes SPD Revision for bytes 192->447 -> SPD_REV_DDIMM_MODULE
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode ddimm_spd_revision(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode ddimm_module_spd_revision(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::SPD_REVISION, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::SPD_REV_DDIMM_MODULE, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -642,19 +642,6 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes VDD_Core PMIC0 -> VDD_CORE_PMIC0
- /// @param[out] o_output encoding from SPD
- /// @return FAPI2_RC_SUCCESS if okay
- ///
- virtual fapi2::ReturnCode vdd_core_pmic0(uint8_t& o_output) const override
- {
- FAPI_TRY( (mss::spd::reader<fields_t::VDD_CORE_PMIC0, R>(iv_target, iv_data, o_output)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
/// @brief Decodes PMIC0 Manfacture ID code 2nd byte
/// @param[out] o_output encoding from SPD - multiple fields used
/// @return FAPI2_RC_SUCCESS if okay
@@ -696,19 +683,6 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes VDD_Core PMIC1 -> VDD_CORE_PMIC1
- /// @param[out] o_output encoding from SPD
- /// @return FAPI2_RC_SUCCESS if okay
- ///
- virtual fapi2::ReturnCode vdd_core_pmic1(uint8_t& o_output) const override
- {
- FAPI_TRY( (mss::spd::reader<fields_t::VDD_CORE_PMIC1, R>(iv_target, iv_data, o_output)) );
-
- fapi_try_exit:
- return fapi2::current_err;
- }
-
- ///
/// @brief Decodes PMIC1 Manfacture ID code 2nd byte
/// @param[out] o_output encoding from SPD - multiple fields used
/// @return FAPI2_RC_SUCCESS if okay
@@ -763,13 +737,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWA Voltage Setting -> PMIC0_SWA_RANGE
+ /// @brief Decodes PMIC0 SWA Voltage Setting -> PMIC0_SWA_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swa_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWA_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWA_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -789,20 +763,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWA Voltage Offset -> PMIC0_SWA_OFF_RANGE
+ /// @brief Decodes PMIC0 SWA Voltage Offset -> PMIC0_SWA_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swa_pmic0(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWA_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWA Sequence Delay -> PMIC0_SWA_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swa_pmic0(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_delay_swa_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWA_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWA_DELAY, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWA Delay Sequence Order -> PMIC0_SWA_ORDER
+ /// @brief Decodes PMIC0 SWA Sequence Order -> PMIC0_SWA_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -828,13 +815,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWB Voltage Setting -> PMIC0_SWB_RANGE
+ /// @brief Decodes PMIC0 SWB Voltage Setting -> PMIC0_SWB_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swb_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWB_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWB_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -854,20 +841,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWB Voltage Offset -> PMIC0_SWB_OFF_RANGE
+ /// @brief Decodes PMIC0 SWB Voltage Offset -> PMIC0_SWB_OFF_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swb_pmic0(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_offset_direction_swb_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWB_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWB_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWB Delay Sequence Order -> PMIC0_SWB_ORDER
+ /// @brief Decodes PMIC0 SWB Sequence Delay -> PMIC0_SWB_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_delay_swb_pmic0(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWB_DELAY, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWB Sequence Order -> PMIC0_SWB_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -893,13 +893,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWC Voltage Setting -> PMIC0_SWC_RANGE
+ /// @brief Decodes PMIC0 SWC Voltage Setting -> PMIC0_SWC_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swc_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWC_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWC_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -919,20 +919,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWC Voltage Offset -> PMIC0_SWC_OFF_RANGE
+ /// @brief Decodes PMIC0 SWC Voltage Offset -> PMIC0_SWC_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swc_pmic0(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWC_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWC Sequence Delay -> PMIC0_SWC_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swc_pmic0(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_delay_swc_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWC_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWC_DELAY, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWC Delay Sequence Order -> PMIC0_SWC_ORDER
+ /// @brief Decodes PMIC0 SWC Sequence Order -> PMIC0_SWC_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -958,13 +971,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWD Voltage Setting -> PMIC0_SWD_RANGE
+ /// @brief Decodes PMIC0 SWD Voltage Setting -> PMIC0_SWD_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swd_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWD_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWD_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -984,20 +997,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC0 SWD Voltage Offset -> PMIC0_SWD_OFF_RANGE
+ /// @brief Decodes PMIC0 SWD Voltage Offset -> PMIC0_SWD_OFF_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swd_pmic0(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_offset_direction_swd_pmic0(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWD_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWD_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWD Delay Sequence Order -> PMIC0_SWD_ORDER
+ /// @brief Decodes PMIC0 SWD Sequence Delay -> PMIC0_SWD_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_delay_swd_pmic0(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC0_SWD_DELAY, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWD Sequence Order -> PMIC0_SWD_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1036,13 +1062,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWA Voltage Setting -> PMIC1_SWA_RANGE
+ /// @brief Decodes PMIC1 SWA Voltage Setting -> PMIC1_SWA_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swa_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWA_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWA_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -1062,20 +1088,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWA Voltage Offset -> PMIC1_SWA_OFF_RANGE
+ /// @brief Decodes PMIC1 SWA Voltage Offset -> PMIC1_SWA_OFF_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swa_pmic1(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_offset_direction_swa_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWA_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWA_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWA Delay Sequence Order -> PMIC1_SWA_ORDER
+ /// @brief Decodes PMIC1 SWA Sequence Delay -> PMIC1_SWA_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_delay_swa_pmic1(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWA_DELAY, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWA Sequence Order -> PMIC1_SWA_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1101,13 +1140,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWB Voltage Setting -> PMIC1_SWB_RANGE
+ /// @brief Decodes PMIC1 SWB Voltage Setting -> PMIC1_SWB_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swb_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWB_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWB_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -1127,20 +1166,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWB Voltage Offset -> PMIC1_SWB_OFF_RANGE
+ /// @brief Decodes PMIC1 SWB Voltage Offset -> PMIC1_SWB_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swb_pmic1(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWB_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWB Sequence Delay -> PMIC1_SWB_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swb_pmic1(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_delay_swb_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWB_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWB_DELAY, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWB Delay Sequence Order -> PMIC1_SWB_ORDER
+ /// @brief Decodes PMIC1 SWB Sequence Order -> PMIC1_SWB_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1166,13 +1218,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWC Voltage Setting -> PMIC1_SWC_RANGE
+ /// @brief Decodes PMIC1 SWC Voltage Setting -> PMIC1_SWC_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swc_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWC_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWC_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -1192,20 +1244,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWC Voltage Offset -> PMIC1_SWC_OFF_RANGE
+ /// @brief Decodes PMIC1 SWC Voltage Offset -> PMIC1_SWC_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swc_pmic1(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWC_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWC Sequence Delay -> PMIC1_SWC_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swc_pmic1(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_delay_swc_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWC_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWC_DELAY, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWC Delay Sequence Order -> PMIC1_SWC_ORDER
+ /// @brief Decodes PMIC1 SWC Sequence Order -> PMIC1_SWC_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1231,13 +1296,13 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWD Voltage Setting -> PMIC1_SWD_RANGE
+ /// @brief Decodes PMIC1 SWD Voltage Setting -> PMIC1_SWD_RANGE_SELECT
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
virtual fapi2::ReturnCode volt_setpoint_range_swd_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWD_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWD_RANGE_SELECT, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
@@ -1257,20 +1322,33 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
}
///
- /// @brief Decodes PMIC1 SWD Voltage Offset -> PMIC1_SWD_OFF_RANGE
+ /// @brief Decodes PMIC1 SWD Voltage Offset -> PMIC1_SWD_OFF_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode volt_offset_direction_swd_pmic1(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWD_OFF_DIRECTION, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWD Sequence Delay -> PMIC1_SWD_DELAY
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode volt_offset_range_swd_pmic1(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode volt_delay_swd_pmic1(uint8_t& o_output) const override
{
- FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWD_OFF_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::PMIC1_SWD_DELAY, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWD Delay Sequence Order -> PMIC1_SWD_ORDER
+ /// @brief Decodes PMIC1 SWD Sequence Order -> PMIC1_SWD_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -1295,6 +1373,58 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
return fapi2::current_err;
}
+ ///
+ /// @brief Decodes PMIC1 Sequence -> PMIC0_SEQUENCE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sequence_pmic0(uint8_t& o_output) const override
+ {
+ FAPI_TRY((mss::spd::reader<fields_t::PMIC0_SEQUENCE, R>(iv_target, iv_data, o_output)));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 Sequence -> PMIC1_SEQUENCE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sequence_pmic1(uint8_t& o_output) const override
+ {
+ FAPI_TRY((mss::spd::reader<fields_t::PMIC1_SEQUENCE, R>(iv_target, iv_data, o_output)));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes DRAM manufacturing ID Code
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_manufacturer_id_code(uint16_t& o_output) const override
+ {
+ uint8_t l_byte0 = 0;
+ uint8_t l_byte1 = 0;
+
+ FAPI_TRY( (mss::spd::reader<fields_t::DRAM_MFR_ID_CODE_LSB, R>(iv_target, iv_data, l_byte0)) );
+ FAPI_TRY( (mss::spd::reader<fields_t::DRAM_MFR_ID_CODE_MSB, R>(iv_target, iv_data, l_byte1)) );
+
+ {
+ fapi2::buffer<uint16_t> l_buffer;
+ right_aligned_insert(l_buffer, l_byte1, l_byte0);
+ o_output = l_buffer;
+ FAPI_INF("%s. Register Manufacturer ID Code: 0x%04x",
+ spd::c_str(iv_target),
+ o_output);
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
};// decoder
}// spd
diff --git a/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_ddr4_custom_microchip_decoder.H b/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_ddr4_custom_microchip_decoder.H
index 12acc87ef..213293fdd 100644
--- a/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_ddr4_custom_microchip_decoder.H
+++ b/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_ddr4_custom_microchip_decoder.H
@@ -40,6 +40,7 @@
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <generic/memory/lib/spd/ddimm/efd_decoder.H>
#include <generic/memory/lib/utils/mss_buffer_utils.H>
+#include <generic/memory/lib/utils/find.H>
namespace mss
{
@@ -488,6 +489,19 @@ class decoder<mss::spd::device_type::DDR4, DDR4_CUSTOM_MICROCHIP, R > : public b
}
///
+ /// @brief Decodes Host RD VREF DQ -> INIT_PHY_VREF
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode init_phy_vref(uint8_t& o_output) const override
+ {
+ FAPI_TRY( (reader<fields_t::INIT_PHY_VREF, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
/// @brief Decodes Initial WR VREF DQ setting -> WR_VREF_DQ_RANGE
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
@@ -631,208 +645,498 @@ class decoder<mss::spd::device_type::DDR4, DDR4_CUSTOM_MICROCHIP, R > : public b
}
///
+ /// @brief Decodes BIST CAL Mode -> BIST_CA_LATENCY_MODE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bist_ca_latency_mode(uint8_t& o_output) const
+ {
+ // Note: using a one-to-one mapping to allow us to re-use the API
+ // We really just need to check that the value exists in the list
+ const std::vector<std::pair<uint8_t, uint8_t>> ALLOWED_VALUES =
+ {
+ {0b0000, 0b0000},
+ {0b0011, 0b0011},
+ {0b0100, 0b0100},
+ {0b0101, 0b0101},
+ {0b0110, 0b0110},
+ {0b1000, 0b1000},
+ };
+
+ FAPI_TRY( (reader<fields_t::BIST_CA_LATENCY_MODE, R>(iv_target, iv_data, o_output)) );
+
+ {
+ // Map EFD value to desired setting
+ // Value and key should be the same thing, just creating a helper variable to avoid confusion
+ const auto l_key = o_output;
+ uint8_t l_value = 0;
+ o_output = 0;
+ FAPI_TRY(lookup_table_check(iv_target, ALLOWED_VALUES, EFD_CA_LATENCY_MODE, l_key, o_output));
+ o_output = l_value;
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes BIST CA Parity Latency Mode -> BIST_CA_PL_MODE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bist_ca_pl_mode(uint8_t& o_output) const
+ {
+ // Note: using a one-to-one mapping to allow us to re-use the API
+ // We really just need to check that the value exists in the list
+ const std::vector<std::pair<uint8_t, uint8_t>> ALLOWED_VALUES =
+ {
+ {0b0000, 0b0000},
+ {0b0100, 0b0100},
+ {0b0101, 0b0101},
+ {0b0110, 0b0110},
+ {0b1000, 0b1000},
+ };
+
+ FAPI_TRY( (reader<fields_t::BIST_CA_PL_MODE, R>(iv_target, iv_data, o_output)) );
+
+ {
+ // Map EFD value to desired setting
+ // Value and key should be the same thing, just creating a helper variable to avoid confusion if we return with a bad value and an RC
+ const auto l_key = o_output;
+ uint8_t l_value = 0;
+ o_output = 0;
+ FAPI_TRY(lookup_table_check(iv_target, ALLOWED_VALUES, EFD_CA_PL_MODE, l_key, l_value));
+ o_output = l_value;
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes DFI Max RD Latency -> DFIMRL_DDRCLK
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dfimrl_ddrclk(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::DFIMRL_DDRCLK, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 0 -> CAC_DLY_A_0
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_0(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_0, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 1 -> CAC_DLY_A_1
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_1(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_1, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 2 -> CAC_DLY_A_2
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_2(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_2, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 3 -> CAC_DLY_A_3
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_3(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_3, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 4 -> CAC_DLY_A_4
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_4(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_4, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 5 -> CAC_DLY_A_5
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_5(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_5, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 6 -> CAC_DLY_A_6
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_6(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_6, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 7 -> CAC_DLY_A_7
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_7(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_A_7, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 0 -> CAC_DLY_B_0
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_0(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_0, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 1 -> CAC_DLY_B_1
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_1(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_1, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 2 -> CAC_DLY_B_2
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_2(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_2, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 3 -> CAC_DLY_B_3
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_3(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_3, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 4 -> CAC_DLY_B_4
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_4(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_4, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 5 -> CAC_DLY_B_5
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_5(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_5, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 6 -> CAC_DLY_B_6
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_6(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_6, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 7 -> CAC_DLY_B_7
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_7(uint8_t& o_output) const
+ {
+ FAPI_TRY( (reader<fields_t::CAC_DLY_B_7, R>(iv_target, iv_data, o_output)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
/// @brief Decodes PMIC0 SWA Volt -> PMIC0_SWA_SETTING
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swa_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swa_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWA_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWA_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWA Volt -> PMIC0_SWA_RANGE
+ /// @brief Decodes PMIC0 SWA Volt -> PMIC0_SWA_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swa_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swa_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWA_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWA_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_SETTING
+ /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swb_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swb_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWB_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWB_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_RANGE
+ /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swb_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swb_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWB_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWB_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_SETTING
+ /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swc_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swc_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWC_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWC_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_RANGE
+ /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swc_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swc_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWC_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWC_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_SETTING
+ /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swd_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swd_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWD_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWD_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_RANGE
+ /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swd_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic0_swd_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC0_SWD_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC0_SWD_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_SETTING
+ /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swa_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swa_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWA_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWA_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_RANGE
+ /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swa_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swa_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWA_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWA_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_SETTING
+ /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swb_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swb_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWB_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWB_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_RANGE
+ /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swb_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swb_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWB_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWB_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_SETTING
+ /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swc_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swc_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWC_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWC_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_RANGE
+ /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swc_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swc_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWC_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWC_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_SETTING
+ /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swd_setting(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swd_offset(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWD_SETTING, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWD_OFFSET, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_RANGE
+ /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swd_range(uint8_t& o_output) const override
+ virtual fapi2::ReturnCode pmic1_swd_offset_direction(uint8_t& o_output) const override
{
- FAPI_TRY(( reader<fields_t::PMIC1_SWD_RANGE, R>(iv_target, iv_data, o_output)) );
+ FAPI_TRY(( reader<fields_t::PMIC1_SWD_OFFSET_DIRECTION, R>(iv_target, iv_data, o_output)) );
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_fields_ddr4.H b/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_fields_ddr4.H
index 4cebb9acb..9a1415a75 100644
--- a/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_fields_ddr4.H
+++ b/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_fields_ddr4.H
@@ -244,100 +244,200 @@ class fields<mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>
PHY_EQUALIZATION_LEN = 2,
// Byte 44: Initial WR VREF DQ setting
- WR_VREF_DQ_BYTE = 44,
+ INIT_VREF_DQ_BYTE = 44,
WR_VREF_DQ_RANGE_START = 1,
WR_VREF_DQ_RANGE_LEN = 1,
WR_VREF_DQ_VALUE_START = 2,
WR_VREF_DQ_VALUE_LEN = 6,
- // Byte 45: ODT WR Map CS Byte1
- ODT_WR_MAP1_BYTE = 45,
+ // Byte 45: Host RD VREF DQ
+ INIT_PHY_VREF_BYTE = 45,
+ INIT_PHY_VREF_START = 1,
+ INIT_PHY_VREF_LEN = 7,
+
+ // Byte 46: ODT WR Map CS Byte1
+ ODT_WR_MAP1_BYTE = 46,
ODT_WR_MAP_RANK3_START = 0,
ODT_WR_MAP_RANK3_LEN = 4,
ODT_WR_MAP_RANK2_START = 4,
ODT_WR_MAP_RANK2_LEN = 4,
- // Byte 46: ODT WR Map CS Byte0
- ODT_WR_MAP0_BYTE = 46,
+ // Byte 47: ODT WR Map CS Byte0
+ ODT_WR_MAP0_BYTE = 47,
ODT_WR_MAP_RANK1_START = 0,
ODT_WR_MAP_RANK1_LEN = 4,
ODT_WR_MAP_RANK0_START = 4,
ODT_WR_MAP_RANK0_LEN = 4,
- // Byte 47: ODT RD Map CS Byte1
- ODT_RD_MAP1_BYTE = 47,
+ // Byte 48: ODT RD Map CS Byte1
+ ODT_RD_MAP1_BYTE = 48,
ODT_RD_MAP_RANK3_START = 0,
ODT_RD_MAP_RANK3_LEN = 4,
ODT_RD_MAP_RANK2_START = 4,
ODT_RD_MAP_RANK2_LEN = 4,
- // Byte 48: ODT RD Map CS Byte0
- ODT_RD_MAP0_BYTE = 48,
+ // Byte 49: ODT RD Map CS Byte0
+ ODT_RD_MAP0_BYTE = 49,
ODT_RD_MAP_RANK1_START = 0,
ODT_RD_MAP_RANK1_LEN = 4,
ODT_RD_MAP_RANK0_START = 4,
ODT_RD_MAP_RANK0_LEN = 4,
- // Byte 49: Geardown during training
- GEARDOWN_DURING_TRAINING_BYTE = 49,
+ // Byte 50: Geardown during training
+ GEARDOWN_DURING_TRAINING_BYTE = 50,
GEARDOWN_DURING_TRAINING_START = 7,
GEARDOWN_DURING_TRAINING_LEN = 1,
- // Byte 50: PMIC0 SWA Volt
- PMIC0_SWA_BYTE = 50,
- PMIC0_SWA_SETTING_START = 0,
- PMIC0_SWA_SETTING_LEN = 7,
- PMIC0_SWA_RANGE_START = 7,
- PMIC0_SWA_RANGE_LEN = 1,
-
- // Byte 51: PMIC0 SWB Volt
- PMIC0_SWB_BYTE = 51,
- PMIC0_SWB_SETTING_START = 0,
- PMIC0_SWB_SETTING_LEN = 7,
- PMIC0_SWB_RANGE_START = 7,
- PMIC0_SWB_RANGE_LEN = 1,
-
- // Byte 52: PMIC0 SWC Volt
- PMIC0_SWC_BYTE = 52,
- PMIC0_SWC_SETTING_START = 0,
- PMIC0_SWC_SETTING_LEN = 7,
- PMIC0_SWC_RANGE_START = 7,
- PMIC0_SWC_RANGE_LEN = 1,
-
- // Byte 53: PMIC0 SWD Volt
- PMIC0_SWD_BYTE = 53,
- PMIC0_SWD_SETTING_START = 0,
- PMIC0_SWD_SETTING_LEN = 7,
- PMIC0_SWD_RANGE_START = 7,
- PMIC0_SWD_RANGE_LEN = 1,
-
- // Byte 54: PMIC1 SWA Volt
- PMIC1_SWA_BYTE = 54,
- PMIC1_SWA_SETTING_START = 0,
- PMIC1_SWA_SETTING_LEN = 7,
- PMIC1_SWA_RANGE_START = 7,
- PMIC1_SWA_RANGE_LEN = 1,
-
- // Byte 55: PMIC1 SWB Volt
- PMIC1_SWB_BYTE = 55,
- PMIC1_SWB_SETTING_START = 0,
- PMIC1_SWB_SETTING_LEN = 7,
- PMIC1_SWB_RANGE_START = 7,
- PMIC1_SWB_RANGE_LEN = 1,
-
- // Byte 56: PMIC1 SWC Volt
- PMIC1_SWC_BYTE = 56,
- PMIC1_SWC_SETTING_START = 0,
- PMIC1_SWC_SETTING_LEN = 7,
- PMIC1_SWC_RANGE_START = 7,
- PMIC1_SWC_RANGE_LEN = 1,
-
- // Byte 57: PMIC1 SWD Volt
- PMIC1_SWD_BYTE = 57,
- PMIC1_SWD_SETTING_START = 0,
- PMIC1_SWD_SETTING_LEN = 7,
- PMIC1_SWD_RANGE_START = 7,
- PMIC1_SWD_RANGE_LEN = 1,
+ // Byte 51: BIST CAL Mode
+ BIST_CA_LATENCY_MODE_BYTE = 51,
+ BIST_CA_LATENCY_MODE_START = 4,
+ BIST_CA_LATENCY_MODE_LEN = 4,
+
+ // Byte 52: BIST CA Parity Latency Mode
+ BIST_CA_PL_MODE_BYTE = 52,
+ BIST_CA_PL_MODE_START = 4,
+ BIST_CA_PL_MODE_LEN = 4,
+
+ // Byte 53: DFI Max RD Latency
+ DFI_MAX_RD_LATENCY_BYTE = 53,
+ DFIMRL_DDRCLK_START = 3,
+ DFIMRL_DDRCLK_LEN = 5,
+
+ // Byte 54: CAC Delay A side Group 0
+ CAC_DELAY_A_SIDE_GROUP_0_BYTE = 54,
+ CAC_DLY_A_0_START = 3,
+ CAC_DLY_A_0_LEN = 5,
+
+ // Byte 55: CAC Delay A side Group 1
+ CAC_DELAY_A_SIDE_GROUP_1_BYTE = 55,
+ CAC_DLY_A_1_START = 3,
+ CAC_DLY_A_1_LEN = 5,
+
+ // Byte 56: CAC Delay A side Group 2
+ CAC_DELAY_A_SIDE_GROUP_2_BYTE = 56,
+ CAC_DLY_A_2_START = 3,
+ CAC_DLY_A_2_LEN = 5,
+
+ // Byte 57: CAC Delay A side Group 3
+ CAC_DELAY_A_SIDE_GROUP_3_BYTE = 57,
+ CAC_DLY_A_3_START = 3,
+ CAC_DLY_A_3_LEN = 5,
+
+ // Byte 58: CAC Delay A side Group 4
+ CAC_DELAY_A_SIDE_GROUP_4_BYTE = 58,
+ CAC_DLY_A_4_START = 3,
+ CAC_DLY_A_4_LEN = 5,
+
+ // Byte 59: CAC Delay A side Group 5
+ CAC_DELAY_A_SIDE_GROUP_5_BYTE = 59,
+ CAC_DLY_A_5_START = 3,
+ CAC_DLY_A_5_LEN = 5,
+
+ // Byte 60: CAC Delay A side Group 6
+ CAC_DELAY_A_SIDE_GROUP_6_BYTE = 60,
+ CAC_DLY_A_6_START = 3,
+ CAC_DLY_A_6_LEN = 5,
+
+ // Byte 61: CAC Delay A side Group 7
+ CAC_DELAY_A_SIDE_GROUP_7_BYTE = 61,
+ CAC_DLY_A_7_START = 3,
+ CAC_DLY_A_7_LEN = 5,
+
+ // Byte 62: CAC Delay B side Group 0
+ CAC_DELAY_B_SIDE_GROUP_0_BYTE = 62,
+ CAC_DLY_B_0_START = 3,
+ CAC_DLY_B_0_LEN = 5,
+
+ // Byte 63: CAC Delay B side Group 1
+ CAC_DELAY_B_SIDE_GROUP_1_BYTE = 63,
+ CAC_DLY_B_1_START = 3,
+ CAC_DLY_B_1_LEN = 5,
+
+ // Byte 64: CAC Delay B side Group 2
+ CAC_DELAY_B_SIDE_GROUP_2_BYTE = 64,
+ CAC_DLY_B_2_START = 3,
+ CAC_DLY_B_2_LEN = 5,
+
+ // Byte 65: CAC Delay B side Group 3
+ CAC_DELAY_B_SIDE_GROUP_3_BYTE = 65,
+ CAC_DLY_B_3_START = 3,
+ CAC_DLY_B_3_LEN = 5,
+
+ // Byte 66: CAC Delay B side Group 4
+ CAC_DELAY_B_SIDE_GROUP_4_BYTE = 66,
+ CAC_DLY_B_4_START = 3,
+ CAC_DLY_B_4_LEN = 5,
+
+ // Byte 67: CAC Delay B side Group 5
+ CAC_DELAY_B_SIDE_GROUP_5_BYTE = 67,
+ CAC_DLY_B_5_START = 3,
+ CAC_DLY_B_5_LEN = 5,
+
+ // Byte 68: CAC Delay B side Group 6
+ CAC_DELAY_B_SIDE_GROUP_6_BYTE = 68,
+ CAC_DLY_B_6_START = 3,
+ CAC_DLY_B_6_LEN = 5,
+
+ // Byte 69: CAC Delay B side Group 7
+ CAC_DELAY_B_SIDE_GROUP_7_BYTE = 69,
+ CAC_DLY_B_7_START = 3,
+ CAC_DLY_B_7_LEN = 5,
+
+ // Byte 70: PMIC0 SWA Volt
+ PMIC0_SWA_BYTE = 70,
+ PMIC0_SWA_OFFSET_START = 0,
+ PMIC0_SWA_OFFSET_LEN = 7,
+ PMIC0_SWA_OFFSET_DIRECTION_START = 7,
+ PMIC0_SWA_OFFSET_DIRECTION_LEN = 1,
+
+ // Byte 71: PMIC0 SWB Volt
+ PMIC0_SWB_BYTE = 71,
+ PMIC0_SWB_OFFSET_START = 0,
+ PMIC0_SWB_OFFSET_LEN = 7,
+ PMIC0_SWB_OFFSET_DIRECTION_START = 7,
+ PMIC0_SWB_OFFSET_DIRECTION_LEN = 1,
+
+ // Byte 72: PMIC0 SWC Volt
+ PMIC0_SWC_BYTE = 72,
+ PMIC0_SWC_OFFSET_START = 0,
+ PMIC0_SWC_OFFSET_LEN = 7,
+ PMIC0_SWC_OFFSET_DIRECTION_START = 7,
+ PMIC0_SWC_OFFSET_DIRECTION_LEN = 1,
+
+ // Byte 73: PMIC0 SWD Volt
+ PMIC0_SWD_BYTE = 73,
+ PMIC0_SWD_OFFSET_START = 0,
+ PMIC0_SWD_OFFSET_LEN = 7,
+ PMIC0_SWD_OFFSET_DIRECTION_START = 7,
+ PMIC0_SWD_OFFSET_DIRECTION_LEN = 1,
+
+ // Byte 74: PMIC1 SWA Volt
+ PMIC1_SWA_BYTE = 74,
+ PMIC1_SWA_OFFSET_START = 0,
+ PMIC1_SWA_OFFSET_LEN = 7,
+ PMIC1_SWA_OFFSET_DIRECTION_START = 7,
+ PMIC1_SWA_OFFSET_DIRECTION_LEN = 1,
+
+ // Byte 75: PMIC1 SWB Volt
+ PMIC1_SWB_BYTE = 75,
+ PMIC1_SWB_OFFSET_START = 0,
+ PMIC1_SWB_OFFSET_LEN = 7,
+ PMIC1_SWB_OFFSET_DIRECTION_START = 7,
+ PMIC1_SWB_OFFSET_DIRECTION_LEN = 1,
+
+ // Byte 76: PMIC1 SWC Volt
+ PMIC1_SWC_BYTE = 76,
+ PMIC1_SWC_OFFSET_START = 0,
+ PMIC1_SWC_OFFSET_LEN = 7,
+ PMIC1_SWC_OFFSET_DIRECTION_START = 7,
+ PMIC1_SWC_OFFSET_DIRECTION_LEN = 1,
+
+ // Byte 77: PMIC1 SWD Volt
+ PMIC1_SWD_BYTE = 77,
+ PMIC1_SWD_OFFSET_START = 0,
+ PMIC1_SWD_OFFSET_LEN = 7,
+ PMIC1_SWD_OFFSET_DIRECTION_START = 7,
+ PMIC1_SWD_OFFSET_DIRECTION_LEN = 1,
};
public:
@@ -454,60 +554,120 @@ class fields<mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>
// Byte 43: PHY Equalization
static constexpr field_t PHY_EQUALIZATION{PHY_EQUALIZATION_BYTE, PHY_EQUALIZATION_START, PHY_EQUALIZATION_LEN};
- // Byte 44: Initial WR VREF DQ setting
- static constexpr field_t WR_VREF_DQ_RANGE{WR_VREF_DQ_BYTE, WR_VREF_DQ_RANGE_START, WR_VREF_DQ_RANGE_LEN};
- static constexpr field_t WR_VREF_DQ_VALUE{WR_VREF_DQ_BYTE, WR_VREF_DQ_VALUE_START, WR_VREF_DQ_VALUE_LEN};
+ // Byte 44: Initial VREF DQ setting
+ static constexpr field_t WR_VREF_DQ_RANGE{INIT_VREF_DQ_BYTE, WR_VREF_DQ_RANGE_START, WR_VREF_DQ_RANGE_LEN};
+ static constexpr field_t WR_VREF_DQ_VALUE{INIT_VREF_DQ_BYTE, WR_VREF_DQ_VALUE_START, WR_VREF_DQ_VALUE_LEN};
+
+ // Byte 45: Initial PHY VREF setting
+ static constexpr field_t INIT_PHY_VREF{INIT_PHY_VREF_BYTE, INIT_PHY_VREF_START, INIT_PHY_VREF_LEN};
- // Byte 45: ODT WR Map CS Byte1
+ // Byte 46: ODT WR Map CS Byte1
static constexpr field_t ODT_WR_MAP_RANK3{ODT_WR_MAP1_BYTE, ODT_WR_MAP_RANK3_START, ODT_WR_MAP_RANK3_LEN};
static constexpr field_t ODT_WR_MAP_RANK2{ODT_WR_MAP1_BYTE, ODT_WR_MAP_RANK2_START, ODT_WR_MAP_RANK2_LEN};
- // Byte 46: ODT WR Map CS Byte0
+ // Byte 47: ODT WR Map CS Byte0
static constexpr field_t ODT_WR_MAP_RANK1{ODT_WR_MAP0_BYTE, ODT_WR_MAP_RANK1_START, ODT_WR_MAP_RANK1_LEN};
static constexpr field_t ODT_WR_MAP_RANK0{ODT_WR_MAP0_BYTE, ODT_WR_MAP_RANK0_START, ODT_WR_MAP_RANK0_LEN};
- // Byte 47: ODT RD Map CS Byte1
+ // Byte 48: ODT RD Map CS Byte1
static constexpr field_t ODT_RD_MAP_RANK3{ODT_RD_MAP1_BYTE, ODT_RD_MAP_RANK3_START, ODT_RD_MAP_RANK3_LEN};
static constexpr field_t ODT_RD_MAP_RANK2{ODT_RD_MAP1_BYTE, ODT_RD_MAP_RANK2_START, ODT_RD_MAP_RANK2_LEN};
- // Byte 48: ODT RD Map CS Byte0
+ // Byte 49: ODT RD Map CS Byte0
static constexpr field_t ODT_RD_MAP_RANK1{ODT_RD_MAP0_BYTE, ODT_RD_MAP_RANK1_START, ODT_RD_MAP_RANK1_LEN};
static constexpr field_t ODT_RD_MAP_RANK0{ODT_RD_MAP0_BYTE, ODT_RD_MAP_RANK0_START, ODT_RD_MAP_RANK0_LEN};
- // Byte 49: Geardown during training
+ // Byte 50: Geardown during training
static constexpr field_t GEARDOWN_DURING_TRAINING{GEARDOWN_DURING_TRAINING_BYTE, GEARDOWN_DURING_TRAINING_START, GEARDOWN_DURING_TRAINING_LEN};
- // Byte 50: PMIC0 SWA Volt
- static constexpr field_t PMIC0_SWA_SETTING{PMIC0_SWA_BYTE, PMIC0_SWA_SETTING_START, PMIC0_SWA_SETTING_LEN};
- static constexpr field_t PMIC0_SWA_RANGE{PMIC0_SWA_BYTE, PMIC0_SWA_RANGE_START, PMIC0_SWA_RANGE_LEN};
+ // Byte 51: BIST CAL Mode
+ static constexpr field_t BIST_CA_LATENCY_MODE{BIST_CA_LATENCY_MODE_BYTE, BIST_CA_LATENCY_MODE_START, BIST_CA_LATENCY_MODE_LEN};
+
+ // Byte 52: BIST CA Parity Latency Mode
+ static constexpr field_t BIST_CA_PL_MODE{BIST_CA_PL_MODE_BYTE, BIST_CA_PL_MODE_START, BIST_CA_PL_MODE_LEN};
+
+ // Byte 53: DFI Max RD Latency
+ static constexpr field_t DFIMRL_DDRCLK{DFI_MAX_RD_LATENCY_BYTE, DFIMRL_DDRCLK_START, DFIMRL_DDRCLK_LEN};
+
+ // Byte 54: CAC Delay A side Group 0
+ static constexpr field_t CAC_DLY_A_0{CAC_DELAY_A_SIDE_GROUP_0_BYTE, CAC_DLY_A_0_START, CAC_DLY_A_0_LEN};
+
+ // Byte 55: CAC Delay A side Group 1
+ static constexpr field_t CAC_DLY_A_1{CAC_DELAY_A_SIDE_GROUP_1_BYTE, CAC_DLY_A_1_START, CAC_DLY_A_1_LEN};
+
+ // Byte 56: CAC Delay A side Group 2
+ static constexpr field_t CAC_DLY_A_2{CAC_DELAY_A_SIDE_GROUP_2_BYTE, CAC_DLY_A_2_START, CAC_DLY_A_2_LEN};
+
+ // Byte 57: CAC Delay A side Group 3
+ static constexpr field_t CAC_DLY_A_3{CAC_DELAY_A_SIDE_GROUP_3_BYTE, CAC_DLY_A_3_START, CAC_DLY_A_3_LEN};
+
+ // Byte 58: CAC Delay A side Group 4
+ static constexpr field_t CAC_DLY_A_4{CAC_DELAY_A_SIDE_GROUP_4_BYTE, CAC_DLY_A_4_START, CAC_DLY_A_4_LEN};
+
+ // Byte 59: CAC Delay A side Group 5
+ static constexpr field_t CAC_DLY_A_5{CAC_DELAY_A_SIDE_GROUP_5_BYTE, CAC_DLY_A_5_START, CAC_DLY_A_5_LEN};
+
+ // Byte 60: CAC Delay A side Group 6
+ static constexpr field_t CAC_DLY_A_6{CAC_DELAY_A_SIDE_GROUP_6_BYTE, CAC_DLY_A_6_START, CAC_DLY_A_6_LEN};
+
+ // Byte 61: CAC Delay A side Group 7
+ static constexpr field_t CAC_DLY_A_7{CAC_DELAY_A_SIDE_GROUP_7_BYTE, CAC_DLY_A_7_START, CAC_DLY_A_7_LEN};
+
+ // Byte 62: CAC Delay B side Group 0
+ static constexpr field_t CAC_DLY_B_0{CAC_DELAY_B_SIDE_GROUP_0_BYTE, CAC_DLY_B_0_START, CAC_DLY_B_0_LEN};
+
+ // Byte 63: CAC Delay B side Group 1
+ static constexpr field_t CAC_DLY_B_1{CAC_DELAY_B_SIDE_GROUP_1_BYTE, CAC_DLY_B_1_START, CAC_DLY_B_1_LEN};
+
+ // Byte 64: CAC Delay B side Group 2
+ static constexpr field_t CAC_DLY_B_2{CAC_DELAY_B_SIDE_GROUP_2_BYTE, CAC_DLY_B_2_START, CAC_DLY_B_2_LEN};
+
+ // Byte 65: CAC Delay B side Group 3
+ static constexpr field_t CAC_DLY_B_3{CAC_DELAY_B_SIDE_GROUP_3_BYTE, CAC_DLY_B_3_START, CAC_DLY_B_3_LEN};
+
+ // Byte 66: CAC Delay B side Group 4
+ static constexpr field_t CAC_DLY_B_4{CAC_DELAY_B_SIDE_GROUP_4_BYTE, CAC_DLY_B_4_START, CAC_DLY_B_4_LEN};
+
+ // Byte 67: CAC Delay B side Group 5
+ static constexpr field_t CAC_DLY_B_5{CAC_DELAY_B_SIDE_GROUP_5_BYTE, CAC_DLY_B_5_START, CAC_DLY_B_5_LEN};
+
+ // Byte 68: CAC Delay B side Group 6
+ static constexpr field_t CAC_DLY_B_6{CAC_DELAY_B_SIDE_GROUP_6_BYTE, CAC_DLY_B_6_START, CAC_DLY_B_6_LEN};
+
+ // Byte 69: CAC Delay B side Group 7
+ static constexpr field_t CAC_DLY_B_7{CAC_DELAY_B_SIDE_GROUP_7_BYTE, CAC_DLY_B_7_START, CAC_DLY_B_7_LEN};
+
+ // Byte 70: PMIC0 SWA Volt
+ static constexpr field_t PMIC0_SWA_OFFSET{PMIC0_SWA_BYTE, PMIC0_SWA_OFFSET_START, PMIC0_SWA_OFFSET_LEN};
+ static constexpr field_t PMIC0_SWA_OFFSET_DIRECTION{PMIC0_SWA_BYTE, PMIC0_SWA_OFFSET_DIRECTION_START, PMIC0_SWA_OFFSET_DIRECTION_LEN};
- // Byte 51: PMIC0 SWB Volt
- static constexpr field_t PMIC0_SWB_SETTING{PMIC0_SWB_BYTE, PMIC0_SWB_SETTING_START, PMIC0_SWB_SETTING_LEN};
- static constexpr field_t PMIC0_SWB_RANGE{PMIC0_SWB_BYTE, PMIC0_SWB_RANGE_START, PMIC0_SWB_RANGE_LEN};
+ // Byte 71: PMIC0 SWB Volt
+ static constexpr field_t PMIC0_SWB_OFFSET{PMIC0_SWB_BYTE, PMIC0_SWB_OFFSET_START, PMIC0_SWB_OFFSET_LEN};
+ static constexpr field_t PMIC0_SWB_OFFSET_DIRECTION{PMIC0_SWB_BYTE, PMIC0_SWB_OFFSET_DIRECTION_START, PMIC0_SWB_OFFSET_DIRECTION_LEN};
- // Byte 52: PMIC0 SWC Volt
- static constexpr field_t PMIC0_SWC_SETTING{PMIC0_SWC_BYTE, PMIC0_SWC_SETTING_START, PMIC0_SWC_SETTING_LEN};
- static constexpr field_t PMIC0_SWC_RANGE{PMIC0_SWC_BYTE, PMIC0_SWC_RANGE_START, PMIC0_SWC_RANGE_LEN};
+ // Byte 72: PMIC0 SWC Volt
+ static constexpr field_t PMIC0_SWC_OFFSET{PMIC0_SWC_BYTE, PMIC0_SWC_OFFSET_START, PMIC0_SWC_OFFSET_LEN};
+ static constexpr field_t PMIC0_SWC_OFFSET_DIRECTION{PMIC0_SWC_BYTE, PMIC0_SWC_OFFSET_DIRECTION_START, PMIC0_SWC_OFFSET_DIRECTION_LEN};
- // Byte 53: PMIC0 SWD Volt
- static constexpr field_t PMIC0_SWD_SETTING{PMIC0_SWD_BYTE, PMIC0_SWD_SETTING_START, PMIC0_SWD_SETTING_LEN};
- static constexpr field_t PMIC0_SWD_RANGE{PMIC0_SWD_BYTE, PMIC0_SWD_RANGE_START, PMIC0_SWD_RANGE_LEN};
+ // Byte 73: PMIC0 SWD Volt
+ static constexpr field_t PMIC0_SWD_OFFSET{PMIC0_SWD_BYTE, PMIC0_SWD_OFFSET_START, PMIC0_SWD_OFFSET_LEN};
+ static constexpr field_t PMIC0_SWD_OFFSET_DIRECTION{PMIC0_SWD_BYTE, PMIC0_SWD_OFFSET_DIRECTION_START, PMIC0_SWD_OFFSET_DIRECTION_LEN};
- // Byte 54: PMIC1 SWA Volt
- static constexpr field_t PMIC1_SWA_SETTING{PMIC1_SWA_BYTE, PMIC1_SWA_SETTING_START, PMIC1_SWA_SETTING_LEN};
- static constexpr field_t PMIC1_SWA_RANGE{PMIC1_SWA_BYTE, PMIC1_SWA_RANGE_START, PMIC1_SWA_RANGE_LEN};
+ // Byte 74: PMIC1 SWA Volt
+ static constexpr field_t PMIC1_SWA_OFFSET{PMIC1_SWA_BYTE, PMIC1_SWA_OFFSET_START, PMIC1_SWA_OFFSET_LEN};
+ static constexpr field_t PMIC1_SWA_OFFSET_DIRECTION{PMIC1_SWA_BYTE, PMIC1_SWA_OFFSET_DIRECTION_START, PMIC1_SWA_OFFSET_DIRECTION_LEN};
- // Byte 55: PMIC1 SWB Volt
- static constexpr field_t PMIC1_SWB_SETTING{PMIC1_SWB_BYTE, PMIC1_SWB_SETTING_START, PMIC1_SWB_SETTING_LEN};
- static constexpr field_t PMIC1_SWB_RANGE{PMIC1_SWB_BYTE, PMIC1_SWB_RANGE_START, PMIC1_SWB_RANGE_LEN};
+ // Byte 75: PMIC1 SWB Volt
+ static constexpr field_t PMIC1_SWB_OFFSET{PMIC1_SWB_BYTE, PMIC1_SWB_OFFSET_START, PMIC1_SWB_OFFSET_LEN};
+ static constexpr field_t PMIC1_SWB_OFFSET_DIRECTION{PMIC1_SWB_BYTE, PMIC1_SWB_OFFSET_DIRECTION_START, PMIC1_SWB_OFFSET_DIRECTION_LEN};
- // Byte 56: PMIC1 SWC Volt
- static constexpr field_t PMIC1_SWC_SETTING{PMIC1_SWC_BYTE, PMIC1_SWC_SETTING_START, PMIC1_SWC_SETTING_LEN};
- static constexpr field_t PMIC1_SWC_RANGE{PMIC1_SWC_BYTE, PMIC1_SWC_RANGE_START, PMIC1_SWC_RANGE_LEN};
+ // Byte 76: PMIC1 SWC Volt
+ static constexpr field_t PMIC1_SWC_OFFSET{PMIC1_SWC_BYTE, PMIC1_SWC_OFFSET_START, PMIC1_SWC_OFFSET_LEN};
+ static constexpr field_t PMIC1_SWC_OFFSET_DIRECTION{PMIC1_SWC_BYTE, PMIC1_SWC_OFFSET_DIRECTION_START, PMIC1_SWC_OFFSET_DIRECTION_LEN};
- // Byte 57: PMIC1 SWD Volt
- static constexpr field_t PMIC1_SWD_SETTING{PMIC1_SWD_BYTE, PMIC1_SWD_SETTING_START, PMIC1_SWD_SETTING_LEN};
- static constexpr field_t PMIC1_SWD_RANGE{PMIC1_SWD_BYTE, PMIC1_SWD_RANGE_START, PMIC1_SWD_RANGE_LEN};
+ // Byte 77: PMIC1 SWD Volt
+ static constexpr field_t PMIC1_SWD_OFFSET{PMIC1_SWD_BYTE, PMIC1_SWD_OFFSET_START, PMIC1_SWD_OFFSET_LEN};
+ static constexpr field_t PMIC1_SWD_OFFSET_DIRECTION{PMIC1_SWD_BYTE, PMIC1_SWD_OFFSET_DIRECTION_START, PMIC1_SWD_OFFSET_DIRECTION_LEN};
};
} // ns efd
diff --git a/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_traits_ddr4.H b/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_traits_ddr4.H
index b292d4180..447e661dc 100644
--- a/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_traits_ddr4.H
+++ b/src/import/generic/memory/lib/spd/ddimm/ddr4/efd_traits_ddr4.H
@@ -294,11 +294,11 @@ class readerTraits
{
public:
- static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr size_t COMPARISON_VAL = 0x0F;
static constexpr const char* FIELD_STR = "PHY Slew Rate DQ_DQS";
template <typename T>
- using COMPARISON_OP = std::equal_to<T>;
+ using COMPARISON_OP = std::less_equal<T>;
};
///
@@ -332,11 +332,11 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
{
public:
- static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr size_t COMPARISON_VAL = 0x0E;
static constexpr const char* FIELD_STR = "ATX Slew rate";
template <typename T>
- using COMPARISON_OP = std::equal_to<T>;
+ using COMPARISON_OP = std::less_equal<T>;
};
///
@@ -370,11 +370,11 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
{
public:
- static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr size_t COMPARISON_VAL = 0x0E;
static constexpr const char* FIELD_STR = "CK Slew rate";
template <typename T>
- using COMPARISON_OP = std::equal_to<T>;
+ using COMPARISON_OP = std::less_equal<T>;
};
///
@@ -408,11 +408,11 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
{
public:
- static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr size_t COMPARISON_VAL = 0x07;
static constexpr const char* FIELD_STR = "DRAM RTT Nom";
template <typename T>
- using COMPARISON_OP = std::equal_to<T>;
+ using COMPARISON_OP = std::less_equal<T>;
};
///
@@ -503,11 +503,11 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
{
public:
- static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr size_t COMPARISON_VAL = 0x04;
static constexpr const char* FIELD_STR = "DRAM RTT WR";
template <typename T>
- using COMPARISON_OP = std::equal_to<T>;
+ using COMPARISON_OP = std::less_equal<T>;
};
///
@@ -598,11 +598,11 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
{
public:
- static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr size_t COMPARISON_VAL = 0x07;
static constexpr const char* FIELD_STR = "DRAM RTT Park";
template <typename T>
- using COMPARISON_OP = std::equal_to<T>;
+ using COMPARISON_OP = std::less_equal<T>;
};
///
@@ -780,6 +780,25 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
+/// @note PHY_VREF_PERCENT field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::INIT_PHY_VREF, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x7f;
+ static constexpr const char* FIELD_STR = "Host RD VREF DQ";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
/// @note WR_VREF_DQ_VALUE field specialization
/// @note valid for all revs
///
@@ -966,21 +985,382 @@ class readerTraits
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
};
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BIST_CA_LATENCY_MODE field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::BIST_CA_LATENCY_MODE, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x08;
+ static constexpr const char* FIELD_STR = "BIST Command address Latency Mode";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note BIST_CA_PL_MODE field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::BIST_CA_PL_MODE, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x08;
+ static constexpr const char* FIELD_STR = "BIST CA Parity Latency Mode";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DFIMRL_DDRCLK field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::DFIMRL_DDRCLK, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x0f;
+ static constexpr const char* FIELD_STR = "DFI Max RD Latency";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
///
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWA_SETTING field specialization
+/// @note CAC_DLY_A_0 field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWA_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_0, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group 0";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_A_1 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_1, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group 1";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_A_2 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_2, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group 2";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_A_3 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_3, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group .";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_A_4 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_4, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group 4";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_A_5 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_5, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group 5";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_A_6 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_6, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group 6";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_A_7 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_A_7, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay A side Group 7";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_0 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_0, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 0";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_1 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_1, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 1";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_2 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_2, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 2";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_3 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_3, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 3";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_4 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_4, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 4";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_5 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_5, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 5";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_6 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_6, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 6";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note CAC_DLY_B_7 field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::CAC_DLY_B_7, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x1f;
+ static constexpr const char* FIELD_STR = "CAC Delay B side Group 7";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PMIC0_SWA_OFFSET field specialization
+/// @note valid for all revs
+///
+template< mss::spd::rev R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWA_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC0 SWA Setting";
+ static constexpr const char* FIELD_STR = "PMIC0 SWA Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -990,16 +1370,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWA_RANGE field specialization
+/// @note PMIC0_SWA_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWA_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWA_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWA Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWA Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1009,16 +1390,16 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWB_SETTING field specialization
+/// @note PMIC0_SWB_OFFSET field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWB_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWB_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC0 SWB Setting";
+ static constexpr const char* FIELD_STR = "PMIC0 SWB Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1028,16 +1409,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWB_RANGE field specialization
+/// @note PMIC0_SWB_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWB_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWB_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWB Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWB Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1047,16 +1429,16 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWC_SETTING field specialization
+/// @note PMIC0_SWC_OFFSET field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWC_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWC_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC0 SWC Setting";
+ static constexpr const char* FIELD_STR = "PMIC0 SWC Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1066,16 +1448,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWC_RANGE field specialization
+/// @note PMIC0_SWC_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWC_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWC_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWC Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWC Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1085,16 +1468,16 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWD_SETTING field specialization
+/// @note PMIC0_SWD_OFFSET field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWD_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWD_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC0 SWD Setting";
+ static constexpr const char* FIELD_STR = "PMIC0 SWD Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1104,16 +1487,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWD_RANGE field specialization
+/// @note PMIC0_SWD_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWD_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC0_SWD_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWD Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWD Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1123,16 +1507,16 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWA_SETTING field specialization
+/// @note PMIC1_SWA_OFFSET field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWA_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWA_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC1 SWA Setting";
+ static constexpr const char* FIELD_STR = "PMIC1 SWA Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1142,16 +1526,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWA_RANGE field specialization
+/// @note PMIC1_SWA_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWA_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWA_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWA Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWA Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1161,16 +1546,16 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWB_SETTING field specialization
+/// @note PMIC1_SWB_OFFSET field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWB_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWB_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC1 SWB Setting";
+ static constexpr const char* FIELD_STR = "PMIC1 SWB Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1180,16 +1565,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWB_RANGE field specialization
+/// @note PMIC1_SWB_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWB_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWB_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWB Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWB Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1199,16 +1585,16 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWC_SETTING field specialization
+/// @note PMIC1_SWC_OFFSET field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWC_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWC_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC1 SWC Setting";
+ static constexpr const char* FIELD_STR = "PMIC1 SWC Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1218,16 +1604,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWC_RANGE field specialization
+/// @note PMIC1_SWC_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWC_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWC_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWC Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWC Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1237,16 +1624,16 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWD_SETTING field specialization
+/// @note PMIC1_SWD_OFFSET field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWD_SETTING, R >
+class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWD_OFFSET, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x3f;
- static constexpr const char* FIELD_STR = "PMIC1 SWD Setting";
+ static constexpr const char* FIELD_STR = "PMIC1 SWD Offset";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -1256,16 +1643,17 @@ class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUS
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWD_RANGE field specialization
+/// @note PMIC1_SWD_OFFSET_DIRECTION field specialization
/// @note valid for all revs
///
template< mss::spd::rev R >
-class readerTraits < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWD_RANGE, R >
+class readerTraits
+ < fields< mss::spd::device_type::DDR4, mss::efd::id::DDR4_CUSTOM_MICROCHIP>::PMIC1_SWD_OFFSET_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWD Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWD Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
diff --git a/src/import/generic/memory/lib/spd/ddimm/efd_decoder.H b/src/import/generic/memory/lib/spd/ddimm/efd_decoder.H
index 6ac30ab0f..df0dbed5e 100644
--- a/src/import/generic/memory/lib/spd/ddimm/efd_decoder.H
+++ b/src/import/generic/memory/lib/spd/ddimm/efd_decoder.H
@@ -67,7 +67,6 @@ inline fapi2::ReturnCode reader( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHI
const std::vector<IT>& i_spd_data,
OT& o_value)
{
-
FAPI_TRY( (mss::get_field<endian::LITTLE, F, TT>(i_target, i_spd_data, mss::READ_SPD_FIELD, o_value)),
"Failed efd::read_field() for %s", spd::c_str(i_target) );
@@ -493,7 +492,7 @@ class base_decoder
}
///
- /// @brief Decodes Initial WR VREF DQ setting -> WR_VREF_DQ_RANGE
+ /// @brief Decodes Initial VREF DQ setting -> WR_VREF_DQ_RANGE
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -504,7 +503,7 @@ class base_decoder
}
///
- /// @brief Decodes Initial WR VREF DQ setting -> WR_VREF_DQ_VALUE
+ /// @brief Decodes Initial VREF DQ setting -> WR_VREF_DQ_VALUE
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -515,6 +514,17 @@ class base_decoder
}
///
+ /// @brief Decodes Initial PHY VREF -> INIT_PHY_VREF
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode init_phy_vref(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
/// @brief Decodes ODT WR Map CS Byte0 -> ODT_WR_MAP_RANK3
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
@@ -614,176 +624,385 @@ class base_decoder
}
///
- /// @brief Decodes PMIC0 SWA Volt -> PMIC0_SWA_SETTING
+ /// @brief Decodes BIST CAL Mode -> BIST_CA_LATENCY_MODE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bist_ca_latency_mode(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes BIST CA Parity Latency Mode -> BIST_CA_PL_MODE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bist_ca_pl_mode(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DFI Max RD Latency -> DFIMRL_DDRCLK
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dfimrl_ddrclk(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 0 -> CAC_DLY_A_0
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_0(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 1 -> CAC_DLY_A_1
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_1(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 2 -> CAC_DLY_A_2
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_2(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 3 -> CAC_DLY_A_3
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_3(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 4 -> CAC_DLY_A_4
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_4(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 5 -> CAC_DLY_A_5
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_5(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 6 -> CAC_DLY_A_6
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_6(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay A side Group 7 -> CAC_DLY_A_7
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_a_side_group_7(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 0 -> CAC_DLY_B_0
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_0(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 1 -> CAC_DLY_B_1
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_1(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 2 -> CAC_DLY_B_2
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_2(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 3 -> CAC_DLY_B_3
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cac_delay_b_side_group_3(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes CAC Delay B side Group 4 -> CAC_DLY_B_4
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swa_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode cac_delay_b_side_group_4(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWA Volt -> PMIC0_SWA_RANGE
+ /// @brief Decodes CAC Delay B side Group 5 -> CAC_DLY_B_5
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swa_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode cac_delay_b_side_group_5(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_SETTING
+ /// @brief Decodes CAC Delay B side Group 6 -> CAC_DLY_B_6
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swb_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode cac_delay_b_side_group_6(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_RANGE
+ /// @brief Decodes CAC Delay B side Group 7 -> CAC_DLY_B_7
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swb_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode cac_delay_b_side_group_7(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_SETTING
+ /// @brief Decodes PMIC0 SWA Volt -> PMIC0_SWA_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swc_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swa_offset(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_RANGE
+ /// @brief Decodes PMIC0 SWA Volt -> PMIC0_SWA_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swc_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swa_offset_direction(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_SETTING
+ /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swd_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swb_offset(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_RANGE
+ /// @brief Decodes PMIC0 SWB Volt -> PMIC0_SWB_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic0_swd_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swb_offset_direction(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_SETTING
+ /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swa_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swc_offset(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_RANGE
+ /// @brief Decodes PMIC0 SWC Volt -> PMIC0_SWC_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swa_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swc_offset_direction(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_SETTING
+ /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swb_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swd_offset(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_RANGE
+ /// @brief Decodes PMIC0 SWD Volt -> PMIC0_SWD_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swb_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic0_swd_offset_direction(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_SETTING
+ /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swc_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic1_swa_offset(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_RANGE
+ /// @brief Decodes PMIC1 SWA Volt -> PMIC1_SWA_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swc_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic1_swa_offset_direction(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_OFFSET
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode pmic1_swb_offset(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWB Volt -> PMIC1_SWB_OFFSET_DIRECTION
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode pmic1_swb_offset_direction(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_OFFSET
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode pmic1_swc_offset(uint8_t& o_output) const
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWC Volt -> PMIC1_SWC_OFFSET_DIRECTION
+ /// @param[out] o_output ncoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode pmic1_swc_offset_direction(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_SETTING
+ /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_OFFSET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swd_setting(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic1_swd_offset(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
}
///
- /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_RANGE
+ /// @brief Decodes PMIC1 SWD Volt -> PMIC1_SWD_OFFSET_DIRECTION
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- virtual fapi2::ReturnCode pmic1_swd_range(uint8_t& o_output) const
+ virtual fapi2::ReturnCode pmic1_swd_offset_direction(uint8_t& o_output) const
{
o_output = 0;
return fapi2::FAPI2_RC_SUCCESS;
diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C
index 19a839e17..ac30f2cd0 100644
--- a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C
+++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -53,6 +53,12 @@ rcw_settings rdimm_rc_a1( 0x02, // RC00 Enable weak drive
0x00); // RC01 Enables all clocks
///
+/// @brief raw card A2 settings
+///
+rcw_settings rdimm_rc_a2( 0x02, // RC00 Enable weak drive
+ 0x00); // RC01 Enables all clocks
+
+///
/// @brief raw card B1 settings
/// @note need to verify, copy from b2, need to verify with b1 annex
///
@@ -66,6 +72,12 @@ rcw_settings rdimm_rc_b2( 0x02, // RC00
0x00 ); // RC01
///
+/// @brief raw card B3 settings
+///
+rcw_settings rdimm_rc_b3( 0x02, // RC00
+ 0x00 ); // RC01
+
+///
/// @brief raw card C1 settings
///
rcw_settings rdimm_rc_c1( 0x02, // RC00
@@ -79,6 +91,13 @@ rcw_settings rdimm_rc_c2( 0x02, // RC00
0x0C ); // RC01
///
+/// @brief raw card C3 settings
+/// @note same settings as C1
+///
+rcw_settings rdimm_rc_c3( 0x02, // RC00
+ 0x0C ); // RC01
+
+///
/// @brief raw card for custom dimms
///
rcw_settings rdimm_rc_custom( 0x02, // RC00
@@ -117,8 +136,11 @@ const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
{raw_card_rev::B1, rdimm_rc_b1},
{raw_card_rev::C1, rdimm_rc_c1},
{raw_card_rev::VBU, rdimm_rc_vbu},
+ {raw_card_rev::A2, rdimm_rc_a2},
{raw_card_rev::B2, rdimm_rc_b2},
{raw_card_rev::C2, rdimm_rc_c2},
+ {raw_card_rev::B3, rdimm_rc_b3},
+ {raw_card_rev::C3, rdimm_rc_c3},
{raw_card_rev::CUSTOM, rdimm_rc_custom},
};
diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H
index fedcbe356..e624861a0 100644
--- a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H
+++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -59,16 +59,19 @@ enum raw_card_rev : uint8_t
A1 = 0x20,
B1 = 0x21,
-
// RDIMM power-on
C1 = 0x22,
// TK - Change VBU value to a no-op value or a value that will never be reached -JLH
VBU = 0x23,
+ A2 = 0x40,
B2 = 0x41,
C2 = 0x42,
+ B3 = 0x61,
+ C3 = 0x62,
+
// Default settings used for DIMMs that do not use a JEDEC raw card reference
CUSTOM = 0xFF,
};
@@ -83,10 +86,13 @@ extern const std::vector< std::pair< uint8_t, rcw_settings> > RAW_CARDS;
// Exposed so we can test them.
// Alphabetized list below
extern rcw_settings rdimm_rc_a1;
+extern rcw_settings rdimm_rc_a2;
extern rcw_settings rdimm_rc_b1;
extern rcw_settings rdimm_rc_b2;
+extern rcw_settings rdimm_rc_b3;
extern rcw_settings rdimm_rc_c1;
extern rcw_settings rdimm_rc_c2;
+extern rcw_settings rdimm_rc_c3;
extern rcw_settings rdimm_rc_custom;
extern rcw_settings rdimm_rc_nvdimm;
extern rcw_settings rdimm_rc_vbu;
diff --git a/src/import/generic/memory/lib/spd/spd_checker.H b/src/import/generic/memory/lib/spd/spd_checker.H
index 0b2a33076..50e6ef347 100644
--- a/src/import/generic/memory/lib/spd/spd_checker.H
+++ b/src/import/generic/memory/lib/spd/spd_checker.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017 */
+/* Contributors Listed Below - COPYRIGHT 2017,2019 */
/* [+] Evan Lojewski */
/* [+] International Business Machines Corp. */
/* */
@@ -103,17 +103,20 @@ namespace check
/// @tparam TT defaulted to bitRangeTraits<TB>
/// @param[in] i_target fapi2 target
/// @param[in] i_timing the timing value
+/// @param[in] i_rev the SPD revision that needs to be checked
/// @param[in] i_ffdc ffdc function code
/// @return FAPI2_RC_SUCCESS iff okay
///
template < bit_len BL, fapi2::TargetType T, typename TT = bitRangeTraits<BL> >
fapi2::ReturnCode max_timing_range(const fapi2::Target<T>& i_target,
const int64_t i_timing,
+ const rev i_rev,
const generic_ffdc_codes i_ffdc)
{
FAPI_ASSERT( (i_timing <= TT::UPPER_BOUND) &&
(i_timing >= TT::LOWER_BOUND),
fapi2::MSS_SPD_TIMING_FAIL()
+ .set_FAILED_REVISION(i_rev)
.set_FUNCTION_CODE(i_ffdc)
.set_TARGET(i_target),
"Failed timing parameter check for %s",
diff --git a/src/import/generic/memory/lib/spd/spd_facade.H b/src/import/generic/memory/lib/spd/spd_facade.H
index ed2fd357f..53fe2a675 100644
--- a/src/import/generic/memory/lib/spd/spd_facade.H
+++ b/src/import/generic/memory/lib/spd/spd_facade.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -48,6 +48,8 @@ inline fapi2::ReturnCode get_raw_data(const fapi2::Target<fapi2::TARGET_TYPE_DIM
FAPI_TRY( fapi2::getSPD(i_target, nullptr, l_size),
"%s. Failed to retrieve SPD blob size", spd::c_str(i_target) );
+ FAPI_DBG( "SPD size %d for %s", l_size, spd::c_str(i_target) );
+
// Reassign container size with the retrieved size
// Arbitrarily set the data to zero since it will be overwritten
o_spd.assign(l_size, 0);
@@ -74,6 +76,7 @@ class facade final
std::vector<uint8_t> iv_data;
std::shared_ptr<dimm_module_decoder> iv_dimm_module_decoder;
std::shared_ptr<base_cnfg_decoder> iv_base_cnfg_decoder;
+ uint8_t iv_dimm_type;
public:
@@ -95,6 +98,11 @@ class facade final
FAPI_TRY(l_factories.create_decoder(iv_dimm_module_decoder));
FAPI_TRY(l_factories.create_decoder(iv_base_cnfg_decoder));
+ // Variable to deal with dimm modules (e.g. DDIMM) that has
+ // fields that are not disjoint between the
+ // general and dimm module section of the SPD (i.e. a hack variable)
+ FAPI_TRY( iv_base_cnfg_decoder->base_module(iv_dimm_type) );
+
o_rc = fapi2::FAPI2_RC_SUCCESS;
return;
@@ -854,6 +862,75 @@ class facade final
}
///
+ /// @brief Decodes Fine Offset for Minimum Write to Read Time - Same Bank Group
+ /// @param[out] o_value SPD encoded value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ fapi2::ReturnCode fine_offset_min_twtr_l( int64_t& o_value ) const
+ {
+ FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_twtr_l(o_value) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Write to Read Time - Different Bank Group
+ /// @param[out] o_value SPD encoded value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ fapi2::ReturnCode fine_offset_min_twtr_s( int64_t& o_value ) const
+ {
+ FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_twtr_s(o_value) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum Four Activate Window Delay Time
+ /// @param[out] o_value SPD encoded value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ fapi2::ReturnCode fine_offset_min_tfaw( int64_t& o_value ) const
+ {
+ FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_tfaw(o_value) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum Active to Precharge Delay Time in MTB
+ /// @param[out] o_value SPD encoded value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @warning not an actual SPD field, defaulted to zero to simplify calculations
+ ///
+ fapi2::ReturnCode fine_offset_min_tras( int64_t& o_value ) const
+ {
+ FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_tras(o_value) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Write Recovery Time
+ /// @param[out] o_value SPD encoded value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ fapi2::ReturnCode fine_offset_min_twr( int64_t& o_value ) const
+ {
+ FAPI_TRY( iv_base_cnfg_decoder->fine_offset_min_twr(o_value) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group
/// @param[out] o_value SPD encoded value
/// @return FAPI2_RC_SUCCESS iff okay
@@ -1041,7 +1118,17 @@ class facade final
///
fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value ) const
{
- FAPI_TRY( iv_base_cnfg_decoder->dram_manufacturer_id_code(o_value) );
+ // Some module fields are duplicated in the general section and
+ // dimm module sections of the SPD. For DDIMMs, we want get it
+ // from the dimm module section instead of the general section.
+ if( iv_dimm_type == spd::DDIMM )
+ {
+ FAPI_TRY( iv_dimm_module_decoder->dram_manufacturer_id_code(o_value) );
+ }
+ else
+ {
+ FAPI_TRY( iv_base_cnfg_decoder->dram_manufacturer_id_code(o_value) );
+ }
fapi_try_exit:
return fapi2::current_err;
@@ -1059,6 +1146,20 @@ class facade final
fapi_try_exit:
return fapi2::current_err;
}
+
+ ///
+ /// @brief Decodes module base height
+ /// @param[out] o_value SPD encoded value
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode module_base_height(uint8_t& o_value) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->module_base_height(o_value) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
///
/// @brief Decodes module nominal height max
/// @param[out] o_value SPD encoded value
@@ -1581,13 +1682,13 @@ class facade final
}
///
- /// @brief Decodes SPD Revision for bytes 192->447 -> SPD_REVISION
+ /// @brief Decodes SPD Revision for bytes 192->447 -> SPD_REV_DDIMM_MODULE
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode ddimm_spd_revision(uint8_t& o_output) const
+ fapi2::ReturnCode ddimm_module_spd_revision(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->ddimm_spd_revision(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->ddimm_module_spd_revision(o_output) );
fapi_try_exit:
return fapi2::current_err;
@@ -2035,16 +2136,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swa_pmic0(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swa_pmic0(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swa_pmic0(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWA Delay -> PMIC0_SWA_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swa_pmic0(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swa_pmic0(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swa_pmic0(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWA Delay Sequence Order -> PMIC0_SWA_ORDER
+ /// @brief Decodes PMIC0 SWA Sequence Order -> PMIC0_SWA_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2100,16 +2214,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swb_pmic0(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swb_pmic0(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swb_pmic0(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swb_pmic0(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWB Delay Sequence Order -> PMIC0_SWB_ORDER
+ /// @brief Decodes PMIC0 SWB Delay -> PMIC0_SWB_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swb_pmic0(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swb_pmic0(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWB Sequence Order -> PMIC0_SWB_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2165,16 +2292,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swc_pmic0(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swc_pmic0(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swc_pmic0(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWC Delay -> PMIC0_SWC_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swc_pmic0(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swc_pmic0(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swc_pmic0(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWC Delay Sequence Order -> PMIC0_SWC_ORDER
+ /// @brief Decodes PMIC0 SWC Sequence Order -> PMIC0_SWC_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2230,16 +2370,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swd_pmic0(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swd_pmic0(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swd_pmic0(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC0 SWD Delay -> PMIC0_SWD_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swd_pmic0(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swd_pmic0(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swd_pmic0(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC0 SWD Delay Sequence Order -> PMIC0_SWD_ORDER
+ /// @brief Decodes PMIC0 SWD Sequence Order -> PMIC0_SWD_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2265,6 +2418,19 @@ class facade final
}
///
+ /// @brief Decodes PMIC0 Sequence -> PMIC0_SEQUENCE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode sequence_pmic0(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->sequence_pmic0(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
/// @brief Decodes PMIC1 SWA Voltage Setting -> PMIC1_SWA_VOLT_SET
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
@@ -2308,16 +2474,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swa_pmic1(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swa_pmic1(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swa_pmic1(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWA Delay -> PMIC1_SWA_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swa_pmic1(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swa_pmic1(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swa_pmic1(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWA Delay Sequence Order -> PMIC1_SWA_ORDER
+ /// @brief Decodes PMIC1 SWA Sequence Order -> PMIC1_SWA_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2373,16 +2552,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swb_pmic1(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swb_pmic1(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swb_pmic1(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swb_pmic1(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWB Delay Sequence Order -> PMIC1_SWB_ORDER
+ /// @brief Decodes PMIC1 SWB Delay -> PMIC1_SWB_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swb_pmic1(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swb_pmic1(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWB Sequence Order -> PMIC1_SWB_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2438,16 +2630,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swc_pmic1(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swc_pmic1(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swc_pmic1(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWC Delay -> PMIC1_SWC_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swc_pmic1(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swc_pmic1(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swc_pmic1(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWC Delay Sequence Order -> PMIC1_SWC_ORDER
+ /// @brief Decodes PMIC1 SWC Sequence Order -> PMIC1_SWC_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2503,16 +2708,29 @@ class facade final
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode volt_offset_range_swd_pmic1(uint8_t& o_output) const
+ fapi2::ReturnCode volt_offset_direction_swd_pmic1(uint8_t& o_output) const
{
- FAPI_TRY( iv_dimm_module_decoder->volt_offset_range_swd_pmic1(o_output) );
+ FAPI_TRY( iv_dimm_module_decoder->volt_offset_direction_swd_pmic1(o_output) );
fapi_try_exit:
return fapi2::current_err;
}
///
- /// @brief Decodes PMIC1 SWD Delay Sequence Order -> PMIC1_SWD_ORDER
+ /// @brief Decodes PMIC1 SWD Delay -> PMIC1_SWD_DELAY
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode volt_delay_swd_pmic1(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->volt_delay_swd_pmic1(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Decodes PMIC1 SWD Sequence Order -> PMIC1_SWD_ORDER
/// @param[out] o_output encoding from SPD
/// @return FAPI2_RC_SUCCESS if okay
///
@@ -2536,6 +2754,19 @@ class facade final
fapi_try_exit:
return fapi2::current_err;
}
+
+ ///
+ /// @brief Decodes PMIC0 Sequence -> PMIC0_SEQUENCE
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode sequence_pmic1(uint8_t& o_output) const
+ {
+ FAPI_TRY( iv_dimm_module_decoder->sequence_pmic1(o_output) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
};
///
diff --git a/src/import/generic/memory/lib/spd/spd_factory_pattern.H b/src/import/generic/memory/lib/spd/spd_factory_pattern.H
index 567ce2d82..278fdf09d 100644
--- a/src/import/generic/memory/lib/spd/spd_factory_pattern.H
+++ b/src/import/generic/memory/lib/spd/spd_factory_pattern.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -219,7 +219,8 @@ class module_factory
RDIMM_DDR4_REV_1_1 { DDR4, RDIMM_MODULE, rev::V1_1},
NVDIMM_DDR4_REV_1_0{ DDR4, NVDIMM_MODULE, rev::V1_0},
NVDIMM_DDR4_REV_1_1{ DDR4, NVDIMM_MODULE, rev::V1_1},
- DDIMM_DDR4_REV_0_0 { DDR4, DDIMM_MODULE, rev::V0_0}
+ DDIMM_DDR4_REV_0_0 { DDR4, DDIMM_MODULE, rev::V0_0},
+ DDIMM_DDR4_REV_0_3 { DDR4, DDIMM_MODULE, rev::V0_3}
{
// Setup pre-defined maps available to search through
init_map_vars(i_spd_data, iv_decoder_map);
@@ -270,6 +271,7 @@ class module_factory
const module_key NVDIMM_DDR4_REV_1_0;
const module_key NVDIMM_DDR4_REV_1_1;
const module_key DDIMM_DDR4_REV_0_0;
+ const module_key DDIMM_DDR4_REV_0_3;
std::map< module_key, std::shared_ptr<T> > iv_decoder_map;
@@ -329,6 +331,10 @@ class module_factory
// Rev 0.0
// DDIMMs start out life w/the updated general section
o_map[DDIMM_DDR4_REV_0_0] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V0_0> >(iv_target, i_spd_data);
+
+ // Remains mostly the same. New thermal sensor fields and pmic redundancy fields
+ o_map[DDIMM_DDR4_REV_0_3] = std::make_shared< decoder<DDR4, BASE_CNFG, rev::V0_3> >(iv_target, i_spd_data);
+
}
///
@@ -375,6 +381,9 @@ class module_factory
// Rev 0.0
// Life starts out at base revision level
o_map[DDIMM_DDR4_REV_0_0] = std::make_shared< decoder<DDR4, DDIMM_MODULE, rev::V0_0> >(iv_target, i_spd_data);
+
+ // Remains mostly the same. New thermal sensor fields and pmic redundancy fields
+ o_map[DDIMM_DDR4_REV_0_3] = std::make_shared< decoder<DDR4, DDIMM_MODULE, rev::V0_3> >(iv_target, i_spd_data);
}
///
diff --git a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H
index ac110cb9d..c05527045 100644
--- a/src/import/generic/memory/lib/spd/spd_fields_ddr4.H
+++ b/src/import/generic/memory/lib/spd/spd_fields_ddr4.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -795,10 +795,10 @@ class fields<DDR4, DDIMM_MODULE>
enum
{
- // Byte 192: SPD Revision for bytes 192->447
- SPD_REV_BYTE = 192,
- SPD_REVISION_START = 0,
- SPD_REVISION_LEN = 8,
+ // Byte 192: SPD Revision DDIMM Module Type (bytes 192->447)
+ SPD_REV_DDIMM_MODULE_BYTE = 192,
+ SPD_REV_DDIMM_MODULE_START = 0,
+ SPD_REV_DDIMM_MODULE_LEN = 8,
// Byte 193: Module Height
MODULE_HEIGHT_BYTE = 193,
@@ -959,10 +959,10 @@ class fields<DDR4, DDIMM_MODULE>
VIN_BULK_ENDURANT_START = 6,
VIN_BULK_ENDURANT_LEN = 2,
- // Byte 226: VDD_Core PMIC0
- VDD_CORE_PMIC0_BYTE = 226,
- VDD_CORE_PMIC0_START = 0,
- VDD_CORE_PMIC0_LEN = 8,
+ // Byte 226: PMIC0 Sequence
+ PMIC0_SEQUENCE_BYTE = 226,
+ PMIC0_SEQUENCE_START = 0,
+ PMIC0_SEQUENCE_LEN = 8,
// Byte 227: PMIC0 Manfacture ID code 1st byte
PMIC0_MFG_CODE1_BYTE = 227,
@@ -979,10 +979,10 @@ class fields<DDR4, DDIMM_MODULE>
PMIC0_REV_START = 0,
PMIC0_REV_LEN = 8,
- // Byte 230: VDD_Core PMIC1
- VDD_CORE_PMIC1_BYTE = 230,
- VDD_CORE_PMIC1_START = 0,
- VDD_CORE_PMIC1_LEN = 8,
+ // Byte 230: PMIC1 Sequence
+ PMIC1_SEQUENCE_BYTE = 230,
+ PMIC1_SEQUENCE_START = 0,
+ PMIC1_SEQUENCE_LEN = 8,
// Byte 231: PMIC1 Manfacture ID code 1st byte
PMIC1_MFG_CODE1_BYTE = 231,
@@ -1003,76 +1003,84 @@ class fields<DDR4, DDIMM_MODULE>
PMIC0_SWA_VOLT_SET_BYTE = 234,
PMIC0_SWA_VOLT_SET_START = 0,
PMIC0_SWA_VOLT_SET_LEN = 7,
- PMIC0_SWA_RANGE_START = 7,
- PMIC0_SWA_RANGE_LEN = 1,
+ PMIC0_SWA_RANGE_SELECT_START = 7,
+ PMIC0_SWA_RANGE_SELECT_LEN = 1,
// Byte 235: PMIC0 SWA Voltage Offset
PMIC0_SWA_VOLT_OFF_BYTE = 235,
PMIC0_SWA_VOLT_OFF_START = 0,
PMIC0_SWA_VOLT_OFF_LEN = 7,
- PMIC0_SWA_OFF_RANGE_START = 7,
- PMIC0_SWA_OFF_RANGE_LEN = 1,
+ PMIC0_SWA_OFF_DIRECTION_START = 7,
+ PMIC0_SWA_OFF_DIRECTION_LEN = 1,
// Byte 236: PMIC0 SWA Delay Sequence Order
PMIC0_SWA_DELAY_BYTE = 236,
- PMIC0_SWA_ORDER_START = 0,
+ PMIC0_SWA_DELAY_START = 0,
+ PMIC0_SWA_DELAY_LEN = 4,
+ PMIC0_SWA_ORDER_START = 4,
PMIC0_SWA_ORDER_LEN = 4,
// Byte 237: PMIC0 SWB Voltage Setting
PMIC0_SWB_VOLT_SET_BYTE = 237,
PMIC0_SWB_VOLT_SET_START = 0,
PMIC0_SWB_VOLT_SET_LEN = 7,
- PMIC0_SWB_RANGE_START = 7,
- PMIC0_SWB_RANGE_LEN = 1,
+ PMIC0_SWB_RANGE_SELECT_START = 7,
+ PMIC0_SWB_RANGE_SELECT_LEN = 1,
// Byte 238: PMIC0 SWB Voltage Offset
PMIC0_SWB_VOLT_OFF_BYTE = 238,
PMIC0_SWB_VOLT_OFF_START = 0,
PMIC0_SWB_VOLT_OFF_LEN = 7,
- PMIC0_SWB_OFF_RANGE_START = 7,
- PMIC0_SWB_OFF_RANGE_LEN = 1,
+ PMIC0_SWB_OFF_DIRECTION_START = 7,
+ PMIC0_SWB_OFF_DIRECTION_LEN = 1,
// Byte 239: PMIC0 SWB Delay Sequence Order
PMIC0_SWB_DELAY_BYTE = 239,
- PMIC0_SWB_ORDER_START = 0,
+ PMIC0_SWB_DELAY_START = 0,
+ PMIC0_SWB_DELAY_LEN = 4,
+ PMIC0_SWB_ORDER_START = 4,
PMIC0_SWB_ORDER_LEN = 4,
// Byte 240: PMIC0 SWC Voltage Setting
PMIC0_SWC_VOLT_SET_BYTE = 240,
PMIC0_SWC_VOLT_SET_START = 0,
PMIC0_SWC_VOLT_SET_LEN = 7,
- PMIC0_SWC_RANGE_START = 7,
- PMIC0_SWC_RANGE_LEN = 1,
+ PMIC0_SWC_RANGE_SELECT_START = 7,
+ PMIC0_SWC_RANGE_SELECT_LEN = 1,
// Byte 241: PMIC0 SWC Voltage Offset
PMIC0_SWC_VOLT_OFF_BYTE = 241,
PMIC0_SWC_VOLT_OFF_START = 0,
PMIC0_SWC_VOLT_OFF_LEN = 7,
- PMIC0_SWC_OFF_RANGE_START = 7,
- PMIC0_SWC_OFF_RANGE_LEN = 1,
+ PMIC0_SWC_OFF_DIRECTION_START = 7,
+ PMIC0_SWC_OFF_DIRECTION_LEN = 1,
// Byte 242: PMIC0 SWC Delay Sequence Order
PMIC0_SWC_DELAY_BYTE = 242,
- PMIC0_SWC_ORDER_START = 0,
+ PMIC0_SWC_DELAY_START = 0,
+ PMIC0_SWC_DELAY_LEN = 4,
+ PMIC0_SWC_ORDER_START = 4,
PMIC0_SWC_ORDER_LEN = 4,
// Byte 243: PMIC0 SWD Voltage Setting
PMIC0_SWD_VOLT_SET_BYTE = 243,
PMIC0_SWD_VOLT_SET_START = 0,
PMIC0_SWD_VOLT_SET_LEN = 7,
- PMIC0_SWD_RANGE_START = 7,
- PMIC0_SWD_RANGE_LEN = 1,
+ PMIC0_SWD_RANGE_SELECT_START = 7,
+ PMIC0_SWD_RANGE_SELECT_LEN = 1,
// Byte 244: PMIC0 SWD Voltage Offset
PMIC0_SWD_VOLT_OFF_BYTE = 244,
PMIC0_SWD_VOLT_OFF_START = 0,
PMIC0_SWD_VOLT_OFF_LEN = 7,
- PMIC0_SWD_OFF_RANGE_START = 7,
- PMIC0_SWD_OFF_RANGE_LEN = 1,
+ PMIC0_SWD_OFF_DIRECTION_START = 7,
+ PMIC0_SWD_OFF_DIRECTION_LEN = 1,
// Byte 245: PMIC0 SWD Delay Sequence Order
PMIC0_SWD_DELAY_BYTE = 245,
- PMIC0_SWD_ORDER_START = 0,
+ PMIC0_SWD_DELAY_START = 0,
+ PMIC0_SWD_DELAY_LEN = 4,
+ PMIC0_SWD_ORDER_START = 4,
PMIC0_SWD_ORDER_LEN = 4,
// Byte 246: PMIC0 Phase Combination
@@ -1084,82 +1092,96 @@ class fields<DDR4, DDIMM_MODULE>
PMIC1_SWA_VOLT_SET_BYTE = 247,
PMIC1_SWA_VOLT_SET_START = 0,
PMIC1_SWA_VOLT_SET_LEN = 7,
- PMIC1_SWA_RANGE_START = 7,
- PMIC1_SWA_RANGE_LEN = 1,
+ PMIC1_SWA_RANGE_SELECT_START = 7,
+ PMIC1_SWA_RANGE_SELECT_LEN = 1,
// Byte 248: PMIC1 SWA Voltage Offset
PMIC1_SWA_VOLT_OFF_BYTE = 248,
PMIC1_SWA_VOLT_OFF_START = 0,
PMIC1_SWA_VOLT_OFF_LEN = 7,
- PMIC1_SWA_OFF_RANGE_START = 7,
- PMIC1_SWA_OFF_RANGE_LEN = 1,
+ PMIC1_SWA_OFF_DIRECTION_START = 7,
+ PMIC1_SWA_OFF_DIRECTION_LEN = 1,
// Byte 249: PMIC1 SWA Delay Sequence Order
PMIC1_SWA_DELAY_BYTE = 249,
- PMIC1_SWA_ORDER_START = 0,
+ PMIC1_SWA_DELAY_START = 0,
+ PMIC1_SWA_DELAY_LEN = 4,
+ PMIC1_SWA_ORDER_START = 4,
PMIC1_SWA_ORDER_LEN = 4,
// Byte 250: PMIC1 SWB Voltage Setting
PMIC1_SWB_VOLT_SET_BYTE = 250,
PMIC1_SWB_VOLT_SET_START = 0,
PMIC1_SWB_VOLT_SET_LEN = 7,
- PMIC1_SWB_RANGE_START = 7,
- PMIC1_SWB_RANGE_LEN = 1,
+ PMIC1_SWB_RANGE_SELECT_START = 7,
+ PMIC1_SWB_RANGE_SELECT_LEN = 1,
// Byte 251: PMIC1 SWB Voltage Offset
PMIC1_SWB_VOLT_OFF_BYTE = 251,
PMIC1_SWB_VOLT_OFF_START = 0,
PMIC1_SWB_VOLT_OFF_LEN = 7,
- PMIC1_SWB_OFF_RANGE_START = 7,
- PMIC1_SWB_OFF_RANGE_LEN = 1,
+ PMIC1_SWB_OFF_DIRECTION_START = 7,
+ PMIC1_SWB_OFF_DIRECTION_LEN = 1,
// Byte 252: PMIC1 SWB Delay Sequence Order
PMIC1_SWB_DELAY_BYTE = 252,
- PMIC1_SWB_ORDER_START = 0,
+ PMIC1_SWB_DELAY_START = 0,
+ PMIC1_SWB_DELAY_LEN = 4,
+ PMIC1_SWB_ORDER_START = 4,
PMIC1_SWB_ORDER_LEN = 4,
// Byte 253: PMIC1 SWC Voltage Setting
PMIC1_SWC_VOLT_SET_BYTE = 253,
PMIC1_SWC_VOLT_SET_START = 0,
PMIC1_SWC_VOLT_SET_LEN = 7,
- PMIC1_SWC_RANGE_START = 7,
- PMIC1_SWC_RANGE_LEN = 1,
+ PMIC1_SWC_RANGE_SELECT_START = 7,
+ PMIC1_SWC_RANGE_SELECT_LEN = 1,
// Byte 254: PMIC1 SWC Voltage Offset
PMIC1_SWC_VOLT_OFF_BYTE = 254,
PMIC1_SWC_VOLT_OFF_START = 0,
PMIC1_SWC_VOLT_OFF_LEN = 7,
- PMIC1_SWC_OFF_RANGE_START = 7,
- PMIC1_SWC_OFF_RANGE_LEN = 1,
+ PMIC1_SWC_OFF_DIRECTION_START = 7,
+ PMIC1_SWC_OFF_DIRECTION_LEN = 1,
// Byte 255: PMIC1 SWC Delay Sequence Order
PMIC1_SWC_DELAY_BYTE = 255,
- PMIC1_SWC_ORDER_START = 0,
+ PMIC1_SWC_DELAY_START = 0,
+ PMIC1_SWC_DELAY_LEN = 4,
+ PMIC1_SWC_ORDER_START = 4,
PMIC1_SWC_ORDER_LEN = 4,
// Byte 256: PMIC1 SWD Voltage Setting
PMIC1_SWD_VOLT_SET_BYTE = 256,
PMIC1_SWD_VOLT_SET_START = 0,
PMIC1_SWD_VOLT_SET_LEN = 7,
- PMIC1_SWD_RANGE_START = 7,
- PMIC1_SWD_RANGE_LEN = 1,
+ PMIC1_SWD_RANGE_SELECT_START = 7,
+ PMIC1_SWD_RANGE_SELECT_LEN = 1,
// Byte 257: PMIC1 SWD Voltage Offset
PMIC1_SWD_VOLT_OFF_BYTE = 257,
PMIC1_SWD_VOLT_OFF_START = 0,
PMIC1_SWD_VOLT_OFF_LEN = 7,
- PMIC1_SWD_OFF_RANGE_START = 7,
- PMIC1_SWD_OFF_RANGE_LEN = 1,
+ PMIC1_SWD_OFF_DIRECTION_START = 7,
+ PMIC1_SWD_OFF_DIRECTION_LEN = 1,
// Byte 258: PMIC1 SWD Delay Sequence Order
PMIC1_SWD_DELAY_BYTE = 258,
- PMIC1_SWD_ORDER_START = 0,
+ PMIC1_SWD_DELAY_START = 0,
+ PMIC1_SWD_DELAY_LEN = 4,
+ PMIC1_SWD_ORDER_START = 4,
PMIC1_SWD_ORDER_LEN = 4,
// Byte 259: PMIC1 Phase Combination
PMIC1_PHASE_COMBIN_BYTE = 259,
PMIC1_PHASE_COMBIN_START = 4,
PMIC1_PHASE_COMBIN_LEN = 4,
+
+ // Byte 552-553
+ DRAM_MFR_ID_CODE_LSB_BYTE = 552,
+ DRAM_MFR_ID_CODE_MSB_BYTE = 553,
+ DRAM_MFR_ID_CODE_START = 0,
+ DRAM_MFR_ID_CODE_LEN = 8,
};
public:
@@ -1170,8 +1192,8 @@ class fields<DDR4, DDIMM_MODULE>
// Second field - start bit
// Third field - bit length
- // Byte 192: SPD Revision for bytes 192->447
- static constexpr field_t SPD_REVISION{SPD_REV_BYTE, SPD_REVISION_START, SPD_REVISION_LEN};
+ // Byte 192: SPD Revision DDIMM Module Bytes (192->447)
+ static constexpr field_t SPD_REV_DDIMM_MODULE{SPD_REV_DDIMM_MODULE_BYTE, SPD_REV_DDIMM_MODULE_START, SPD_REV_DDIMM_MODULE_LEN};
// Byte 193: Module Height
static constexpr field_t MODULE_BASE_HEIGHT{MODULE_HEIGHT_BYTE, MODULE_BASE_HEIGHT_START, MODULE_BASE_HEIGHT_LEN};
@@ -1266,8 +1288,8 @@ class fields<DDR4, DDIMM_MODULE>
static constexpr field_t VIN_BULK_OPERABLE{VIN_BULK_BYTE, VIN_BULK_OPERABLE_START, VIN_BULK_OPERABLE_LEN};
static constexpr field_t VIN_BULK_ENDURANT{VIN_BULK_BYTE, VIN_BULK_ENDURANT_START, VIN_BULK_ENDURANT_LEN};
- // Byte 226: VDD_Core PMIC0
- static constexpr field_t VDD_CORE_PMIC0{VDD_CORE_PMIC0_BYTE, VDD_CORE_PMIC0_START, VDD_CORE_PMIC0_LEN};
+ // Byte 226: PMIC0 Sequence
+ static constexpr field_t PMIC0_SEQUENCE{PMIC0_SEQUENCE_BYTE, PMIC0_SEQUENCE_START, PMIC0_SEQUENCE_LEN};
// Byte 227: PMIC0 Manfacture ID code 1st byte
static constexpr field_t PMIC0_CONT_CODE{PMIC0_MFG_CODE1_BYTE, PMIC0_CONT_CODE_START, PMIC0_CONT_CODE_LEN};
@@ -1278,8 +1300,8 @@ class fields<DDR4, DDIMM_MODULE>
// Byte 229: PMIC0 Revision Number
static constexpr field_t PMIC0_REV{PMIC0_REV_BYTE, PMIC0_REV_START, PMIC0_REV_LEN};
- // Byte 230: VDD_Core PMIC1
- static constexpr field_t VDD_CORE_PMIC1{VDD_CORE_PMIC1_BYTE, VDD_CORE_PMIC1_START, VDD_CORE_PMIC1_LEN};
+ // Byte 230: PMIC1 Sequence
+ static constexpr field_t PMIC1_SEQUENCE{PMIC1_SEQUENCE_BYTE, PMIC1_SEQUENCE_START, PMIC1_SEQUENCE_LEN};
// Byte 231: PMIC1 Manfacture ID code 1st byte
static constexpr field_t PMIC1_CONT_CODE{PMIC1_MFG_CODE1_BYTE, PMIC1_CONT_CODE_START, PMIC1_CONT_CODE_LEN};
@@ -1292,46 +1314,50 @@ class fields<DDR4, DDIMM_MODULE>
// Byte 234: PMIC0 SWA Voltage Setting
static constexpr field_t PMIC0_SWA_VOLT_SET{PMIC0_SWA_VOLT_SET_BYTE, PMIC0_SWA_VOLT_SET_START, PMIC0_SWA_VOLT_SET_LEN};
- static constexpr field_t PMIC0_SWA_RANGE{PMIC0_SWA_VOLT_SET_BYTE, PMIC0_SWA_RANGE_START, PMIC0_SWA_RANGE_LEN};
+ static constexpr field_t PMIC0_SWA_RANGE_SELECT{PMIC0_SWA_VOLT_SET_BYTE, PMIC0_SWA_RANGE_SELECT_START, PMIC0_SWA_RANGE_SELECT_LEN};
// Byte 235: PMIC0 SWA Voltage Offset
static constexpr field_t PMIC0_SWA_VOLT_OFF{PMIC0_SWA_VOLT_OFF_BYTE, PMIC0_SWA_VOLT_OFF_START, PMIC0_SWA_VOLT_OFF_LEN};
- static constexpr field_t PMIC0_SWA_OFF_RANGE{PMIC0_SWA_VOLT_OFF_BYTE, PMIC0_SWA_OFF_RANGE_START, PMIC0_SWA_OFF_RANGE_LEN};
+ static constexpr field_t PMIC0_SWA_OFF_DIRECTION{PMIC0_SWA_VOLT_OFF_BYTE, PMIC0_SWA_OFF_DIRECTION_START, PMIC0_SWA_OFF_DIRECTION_LEN};
// Byte 236: PMIC0 SWA Delay Sequence Order
+ static constexpr field_t PMIC0_SWA_DELAY{PMIC0_SWA_DELAY_BYTE, PMIC0_SWA_DELAY_START, PMIC0_SWA_DELAY_LEN};
static constexpr field_t PMIC0_SWA_ORDER{PMIC0_SWA_DELAY_BYTE, PMIC0_SWA_ORDER_START, PMIC0_SWA_ORDER_LEN};
// Byte 237: PMIC0 SWB Voltage Setting
static constexpr field_t PMIC0_SWB_VOLT_SET{PMIC0_SWB_VOLT_SET_BYTE, PMIC0_SWB_VOLT_SET_START, PMIC0_SWB_VOLT_SET_LEN};
- static constexpr field_t PMIC0_SWB_RANGE{PMIC0_SWB_VOLT_SET_BYTE, PMIC0_SWB_RANGE_START, PMIC0_SWB_RANGE_LEN};
+ static constexpr field_t PMIC0_SWB_RANGE_SELECT{PMIC0_SWB_VOLT_SET_BYTE, PMIC0_SWB_RANGE_SELECT_START, PMIC0_SWB_RANGE_SELECT_LEN};
// Byte 238: PMIC0 SWB Voltage Offset
static constexpr field_t PMIC0_SWB_VOLT_OFF{PMIC0_SWB_VOLT_OFF_BYTE, PMIC0_SWB_VOLT_OFF_START, PMIC0_SWB_VOLT_OFF_LEN};
- static constexpr field_t PMIC0_SWB_OFF_RANGE{PMIC0_SWB_VOLT_OFF_BYTE, PMIC0_SWB_OFF_RANGE_START, PMIC0_SWB_OFF_RANGE_LEN};
+ static constexpr field_t PMIC0_SWB_OFF_DIRECTION{PMIC0_SWB_VOLT_OFF_BYTE, PMIC0_SWB_OFF_DIRECTION_START, PMIC0_SWB_OFF_DIRECTION_LEN};
// Byte 239: PMIC0 SWB Delay Sequence Order
+ static constexpr field_t PMIC0_SWB_DELAY{PMIC0_SWB_DELAY_BYTE, PMIC0_SWB_DELAY_START, PMIC0_SWB_DELAY_LEN};
static constexpr field_t PMIC0_SWB_ORDER{PMIC0_SWB_DELAY_BYTE, PMIC0_SWB_ORDER_START, PMIC0_SWB_ORDER_LEN};
// Byte 240: PMIC0 SWC Voltage Setting
static constexpr field_t PMIC0_SWC_VOLT_SET{PMIC0_SWC_VOLT_SET_BYTE, PMIC0_SWC_VOLT_SET_START, PMIC0_SWC_VOLT_SET_LEN};
- static constexpr field_t PMIC0_SWC_RANGE{PMIC0_SWC_VOLT_SET_BYTE, PMIC0_SWC_RANGE_START, PMIC0_SWC_RANGE_LEN};
+ static constexpr field_t PMIC0_SWC_RANGE_SELECT{PMIC0_SWC_VOLT_SET_BYTE, PMIC0_SWC_RANGE_SELECT_START, PMIC0_SWC_RANGE_SELECT_LEN};
// Byte 241: PMIC0 SWC Voltage Offset
static constexpr field_t PMIC0_SWC_VOLT_OFF{PMIC0_SWC_VOLT_OFF_BYTE, PMIC0_SWC_VOLT_OFF_START, PMIC0_SWC_VOLT_OFF_LEN};
- static constexpr field_t PMIC0_SWC_OFF_RANGE{PMIC0_SWC_VOLT_OFF_BYTE, PMIC0_SWC_OFF_RANGE_START, PMIC0_SWC_OFF_RANGE_LEN};
+ static constexpr field_t PMIC0_SWC_OFF_DIRECTION{PMIC0_SWC_VOLT_OFF_BYTE, PMIC0_SWC_OFF_DIRECTION_START, PMIC0_SWC_OFF_DIRECTION_LEN};
// Byte 242: PMIC0 SWC Delay Sequence Order
+ static constexpr field_t PMIC0_SWC_DELAY{PMIC0_SWC_DELAY_BYTE, PMIC0_SWC_DELAY_START, PMIC0_SWC_DELAY_LEN};
static constexpr field_t PMIC0_SWC_ORDER{PMIC0_SWC_DELAY_BYTE, PMIC0_SWC_ORDER_START, PMIC0_SWC_ORDER_LEN};
// Byte 243: PMIC0 SWD Voltage Setting
static constexpr field_t PMIC0_SWD_VOLT_SET{PMIC0_SWD_VOLT_SET_BYTE, PMIC0_SWD_VOLT_SET_START, PMIC0_SWD_VOLT_SET_LEN};
- static constexpr field_t PMIC0_SWD_RANGE{PMIC0_SWD_VOLT_SET_BYTE, PMIC0_SWD_RANGE_START, PMIC0_SWD_RANGE_LEN};
+ static constexpr field_t PMIC0_SWD_RANGE_SELECT{PMIC0_SWD_VOLT_SET_BYTE, PMIC0_SWD_RANGE_SELECT_START, PMIC0_SWD_RANGE_SELECT_LEN};
// Byte 244: PMIC0 SWD Voltage Offset
static constexpr field_t PMIC0_SWD_VOLT_OFF{PMIC0_SWD_VOLT_OFF_BYTE, PMIC0_SWD_VOLT_OFF_START, PMIC0_SWD_VOLT_OFF_LEN};
- static constexpr field_t PMIC0_SWD_OFF_RANGE{PMIC0_SWD_VOLT_OFF_BYTE, PMIC0_SWD_OFF_RANGE_START, PMIC0_SWD_OFF_RANGE_LEN};
+ static constexpr field_t PMIC0_SWD_OFF_DIRECTION{PMIC0_SWD_VOLT_OFF_BYTE, PMIC0_SWD_OFF_DIRECTION_START, PMIC0_SWD_OFF_DIRECTION_LEN};
// Byte 245: PMIC0 SWD Delay Sequence Order
+ static constexpr field_t PMIC0_SWD_DELAY{PMIC0_SWD_DELAY_BYTE, PMIC0_SWD_DELAY_START, PMIC0_SWD_DELAY_LEN};
static constexpr field_t PMIC0_SWD_ORDER{PMIC0_SWD_DELAY_BYTE, PMIC0_SWD_ORDER_START, PMIC0_SWD_ORDER_LEN};
// Byte 246: PMIC0 Phase Combination
@@ -1339,51 +1365,58 @@ class fields<DDR4, DDIMM_MODULE>
// Byte 247: PMIC1 SWA Voltage Setting
static constexpr field_t PMIC1_SWA_VOLT_SET{PMIC1_SWA_VOLT_SET_BYTE, PMIC1_SWA_VOLT_SET_START, PMIC1_SWA_VOLT_SET_LEN};
- static constexpr field_t PMIC1_SWA_RANGE{PMIC1_SWA_VOLT_SET_BYTE, PMIC1_SWA_RANGE_START, PMIC1_SWA_RANGE_LEN};
+ static constexpr field_t PMIC1_SWA_RANGE_SELECT{PMIC1_SWA_VOLT_SET_BYTE, PMIC1_SWA_RANGE_SELECT_START, PMIC1_SWA_RANGE_SELECT_LEN};
// Byte 248: PMIC1 SWA Voltage Offset
static constexpr field_t PMIC1_SWA_VOLT_OFF{PMIC1_SWA_VOLT_OFF_BYTE, PMIC1_SWA_VOLT_OFF_START, PMIC1_SWA_VOLT_OFF_LEN};
- static constexpr field_t PMIC1_SWA_OFF_RANGE{PMIC1_SWA_VOLT_OFF_BYTE, PMIC1_SWA_OFF_RANGE_START, PMIC1_SWA_OFF_RANGE_LEN};
+ static constexpr field_t PMIC1_SWA_OFF_DIRECTION{PMIC1_SWA_VOLT_OFF_BYTE, PMIC1_SWA_OFF_DIRECTION_START, PMIC1_SWA_OFF_DIRECTION_LEN};
// Byte 249: PMIC1 SWA Delay Sequence Order
+ static constexpr field_t PMIC1_SWA_DELAY{PMIC1_SWA_DELAY_BYTE, PMIC1_SWA_DELAY_START, PMIC1_SWA_DELAY_LEN};
static constexpr field_t PMIC1_SWA_ORDER{PMIC1_SWA_DELAY_BYTE, PMIC1_SWA_ORDER_START, PMIC1_SWA_ORDER_LEN};
// Byte 250: PMIC1 SWB Voltage Setting
static constexpr field_t PMIC1_SWB_VOLT_SET{PMIC1_SWB_VOLT_SET_BYTE, PMIC1_SWB_VOLT_SET_START, PMIC1_SWB_VOLT_SET_LEN};
- static constexpr field_t PMIC1_SWB_RANGE{PMIC1_SWB_VOLT_SET_BYTE, PMIC1_SWB_RANGE_START, PMIC1_SWB_RANGE_LEN};
+ static constexpr field_t PMIC1_SWB_RANGE_SELECT{PMIC1_SWB_VOLT_SET_BYTE, PMIC1_SWB_RANGE_SELECT_START, PMIC1_SWB_RANGE_SELECT_LEN};
// Byte 251: PMIC1 SWB Voltage Offset
static constexpr field_t PMIC1_SWB_VOLT_OFF{PMIC1_SWB_VOLT_OFF_BYTE, PMIC1_SWB_VOLT_OFF_START, PMIC1_SWB_VOLT_OFF_LEN};
- static constexpr field_t PMIC1_SWB_OFF_RANGE{PMIC1_SWB_VOLT_OFF_BYTE, PMIC1_SWB_OFF_RANGE_START, PMIC1_SWB_OFF_RANGE_LEN};
+ static constexpr field_t PMIC1_SWB_OFF_DIRECTION{PMIC1_SWB_VOLT_OFF_BYTE, PMIC1_SWB_OFF_DIRECTION_START, PMIC1_SWB_OFF_DIRECTION_LEN};
// Byte 252: PMIC1 SWB Delay Sequence Order
+ static constexpr field_t PMIC1_SWB_DELAY{PMIC1_SWB_DELAY_BYTE, PMIC1_SWB_DELAY_START, PMIC1_SWB_DELAY_LEN};
static constexpr field_t PMIC1_SWB_ORDER{PMIC1_SWB_DELAY_BYTE, PMIC1_SWB_ORDER_START, PMIC1_SWB_ORDER_LEN};
// Byte 253: PMIC1 SWC Voltage Setting
static constexpr field_t PMIC1_SWC_VOLT_SET{PMIC1_SWC_VOLT_SET_BYTE, PMIC1_SWC_VOLT_SET_START, PMIC1_SWC_VOLT_SET_LEN};
- static constexpr field_t PMIC1_SWC_RANGE{PMIC1_SWC_VOLT_SET_BYTE, PMIC1_SWC_RANGE_START, PMIC1_SWC_RANGE_LEN};
+ static constexpr field_t PMIC1_SWC_RANGE_SELECT{PMIC1_SWC_VOLT_SET_BYTE, PMIC1_SWC_RANGE_SELECT_START, PMIC1_SWC_RANGE_SELECT_LEN};
// Byte 254: PMIC1 SWC Voltage Offset
static constexpr field_t PMIC1_SWC_VOLT_OFF{PMIC1_SWC_VOLT_OFF_BYTE, PMIC1_SWC_VOLT_OFF_START, PMIC1_SWC_VOLT_OFF_LEN};
- static constexpr field_t PMIC1_SWC_OFF_RANGE{PMIC1_SWC_VOLT_OFF_BYTE, PMIC1_SWC_OFF_RANGE_START, PMIC1_SWC_OFF_RANGE_LEN};
+ static constexpr field_t PMIC1_SWC_OFF_DIRECTION{PMIC1_SWC_VOLT_OFF_BYTE, PMIC1_SWC_OFF_DIRECTION_START, PMIC1_SWC_OFF_DIRECTION_LEN};
// Byte 255: PMIC1 SWC Delay Sequence Order
+ static constexpr field_t PMIC1_SWC_DELAY{PMIC1_SWC_DELAY_BYTE, PMIC1_SWC_DELAY_START, PMIC1_SWC_DELAY_LEN};
static constexpr field_t PMIC1_SWC_ORDER{PMIC1_SWC_DELAY_BYTE, PMIC1_SWC_ORDER_START, PMIC1_SWC_ORDER_LEN};
// Byte 256: PMIC1 SWD Voltage Setting
static constexpr field_t PMIC1_SWD_VOLT_SET{PMIC1_SWD_VOLT_SET_BYTE, PMIC1_SWD_VOLT_SET_START, PMIC1_SWD_VOLT_SET_LEN};
- static constexpr field_t PMIC1_SWD_RANGE{PMIC1_SWD_VOLT_SET_BYTE, PMIC1_SWD_RANGE_START, PMIC1_SWD_RANGE_LEN};
+ static constexpr field_t PMIC1_SWD_RANGE_SELECT{PMIC1_SWD_VOLT_SET_BYTE, PMIC1_SWD_RANGE_SELECT_START, PMIC1_SWD_RANGE_SELECT_LEN};
// Byte 257: PMIC1 SWD Voltage Offset
static constexpr field_t PMIC1_SWD_VOLT_OFF{PMIC1_SWD_VOLT_OFF_BYTE, PMIC1_SWD_VOLT_OFF_START, PMIC1_SWD_VOLT_OFF_LEN};
- static constexpr field_t PMIC1_SWD_OFF_RANGE{PMIC1_SWD_VOLT_OFF_BYTE, PMIC1_SWD_OFF_RANGE_START, PMIC1_SWD_OFF_RANGE_LEN};
+ static constexpr field_t PMIC1_SWD_OFF_DIRECTION{PMIC1_SWD_VOLT_OFF_BYTE, PMIC1_SWD_OFF_DIRECTION_START, PMIC1_SWD_OFF_DIRECTION_LEN};
// Byte 258: PMIC1 SWD Delay Sequence Order
+ static constexpr field_t PMIC1_SWD_DELAY{PMIC1_SWD_DELAY_BYTE, PMIC1_SWD_DELAY_START, PMIC1_SWD_DELAY_LEN};
static constexpr field_t PMIC1_SWD_ORDER{PMIC1_SWD_DELAY_BYTE, PMIC1_SWD_ORDER_START, PMIC1_SWD_ORDER_LEN};
// Byte 259: PMIC1 Phase Combination
static constexpr field_t PMIC1_PHASE_COMBIN{PMIC1_PHASE_COMBIN_BYTE, PMIC1_PHASE_COMBIN_START, PMIC1_PHASE_COMBIN_LEN};
+ // Byte 552 and 553: DRAM manufacturing ID for DDIMMs
+ static constexpr field_t DRAM_MFR_ID_CODE_LSB{DRAM_MFR_ID_CODE_LSB_BYTE, DRAM_MFR_ID_CODE_START, DRAM_MFR_ID_CODE_LEN};
+ static constexpr field_t DRAM_MFR_ID_CODE_MSB{DRAM_MFR_ID_CODE_MSB_BYTE, DRAM_MFR_ID_CODE_START, DRAM_MFR_ID_CODE_LEN};
};
}// spd
diff --git a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H
index c26ca2082..fd60ba00f 100644
--- a/src/import/generic/memory/lib/spd/spd_traits_ddr4.H
+++ b/src/import/generic/memory/lib/spd/spd_traits_ddr4.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -3690,11 +3690,11 @@ class readerTraits< fields<DDR4, LRDIMM_MODULE>::DATA_BUFFER_GAIN_ADJUST, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note SPD_REVISION field specialization
+/// @note SPD_REV_DDIMM_MODULE field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::SPD_REVISION, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::SPD_REV_DDIMM_MODULE, R >
{
public:
@@ -4450,16 +4450,16 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::VIN_BULK_ENDURANT, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note VDD_CORE_PMIC0 field specialization
+/// @note PMIC0_SEQUENCE field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::VDD_CORE_PMIC0, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SEQUENCE, R >
{
public:
- static constexpr size_t COMPARISON_VAL = 0xff;
- static constexpr const char* FIELD_STR = "VDD_Core PMIC0";
+ static constexpr size_t COMPARISON_VAL = 0x4;
+ static constexpr const char* FIELD_STR = "PMIC0 Sequence";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -4526,16 +4526,16 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_REV, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note VDD_CORE_PMIC1 field specialization
+/// @note PMIC1_SEQUENCE field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::VDD_CORE_PMIC1, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SEQUENCE, R >
{
public:
- static constexpr size_t COMPARISON_VAL = 0xff;
- static constexpr const char* FIELD_STR = "VDD_Core PMIC1";
+ static constexpr size_t COMPARISON_VAL = 0x04;
+ static constexpr const char* FIELD_STR = "PMIC1 Sequence";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -4621,11 +4621,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWA_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWA_RANGE field specialization
+/// @note PMIC0_SWA_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWA_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWA_RANGE_SELECT, R >
{
public:
@@ -4659,16 +4659,35 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWA_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWA_OFF_RANGE field specialization
+/// @note PMIC0_SWA_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWA_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWA_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWA Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWA Voltage Offset Direction";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PMIC0_SWA_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWA_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC0 SWA Delay";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -4716,11 +4735,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWB_RANGE field specialization
+/// @note PMIC0_SWB_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_RANGE_SELECT, R >
{
public:
@@ -4754,16 +4773,16 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWB_OFF_RANGE field specialization
+/// @note PMIC0_SWB_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWB Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWB Voltage Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -4773,6 +4792,26 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_OFF_RANGE, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
+/// @note PMIC0_SWB_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWB_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC0 SWB Delay";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
/// @note PMIC0_SWB_ORDER field specialization
/// @note valid for all revs
///
@@ -4811,11 +4850,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWC_RANGE field specialization
+/// @note PMIC0_SWC_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_RANGE_SELECT, R >
{
public:
@@ -4849,16 +4888,16 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWC_OFF_RANGE field specialization
+/// @note PMIC0_SWC_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWC Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWC Voltage Offset Direction";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -4868,6 +4907,26 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_OFF_RANGE, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
+/// @note PMIC0_SWC_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWC_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC0 SWC Delay";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
/// @note PMIC0_SWC_ORDER field specialization
/// @note valid for all revs
///
@@ -4906,11 +4965,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWD_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWD_RANGE field specialization
+/// @note PMIC0_SWD_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWD_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWD_RANGE_SELECT, R >
{
public:
@@ -4944,21 +5003,41 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWD_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC0_SWD_OFF_RANGE field specialization
+/// @note PMIC0_SWD_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWD_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWD_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC0 SWD Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC0 SWD Voltage Offset Direction";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PMIC0_SWD_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC0_SWD_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC0 SWD Delay";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
};
+
///
/// @class readerTraits
/// @brief trait structure to hold static SPD information
@@ -5020,11 +5099,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWA_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWA_RANGE field specialization
+/// @note PMIC1_SWA_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWA_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWA_RANGE_SELECT, R >
{
public:
@@ -5058,16 +5137,35 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWA_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWA_OFF_RANGE field specialization
+/// @note PMIC1_SWA_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWA_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWA_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWA Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWA Voltage Offset Direction";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PMIC1_SWA_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWA_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC1 SWA Delay";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -5115,11 +5213,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWB_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWB_RANGE field specialization
+/// @note PMIC1_SWB_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWB_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWB_RANGE_SELECT, R >
{
public:
@@ -5153,16 +5251,35 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWB_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWB_OFF_RANGE field specialization
+/// @note PMIC1_SWB_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWB_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWB_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWB Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWB Voltage Offset Direction";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PMIC1_SWB_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWB_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC1 SWB Delay";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -5210,11 +5327,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWC_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWC_RANGE field specialization
+/// @note PMIC1_SWC_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWC_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWC_RANGE_SELECT, R >
{
public:
@@ -5248,16 +5365,35 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWC_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWC_OFF_RANGE field specialization
+/// @note PMIC1_SWC_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWC_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWC_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWC Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWC Voltage Offset Direction";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PMIC1_SWC_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWC_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC1 SWC Delay";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -5305,11 +5441,11 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWD_VOLT_SET, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWD_RANGE field specialization
+/// @note PMIC1_SWD_RANGE_SELECT field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWD_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWD_RANGE_SELECT, R >
{
public:
@@ -5343,16 +5479,35 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWD_VOLT_OFF, R >
/// @class readerTraits
/// @brief trait structure to hold static SPD information
/// @tparam R the revision of the SPD field
-/// @note PMIC1_SWD_OFF_RANGE field specialization
+/// @note PMIC1_SWD_OFF_DIRECTION field specialization
/// @note valid for all revs
///
template< rev R >
-class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWD_OFF_RANGE, R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWD_OFF_DIRECTION, R >
{
public:
static constexpr size_t COMPARISON_VAL = 0x01;
- static constexpr const char* FIELD_STR = "PMIC1 SWD Voltage Offset Range";
+ static constexpr const char* FIELD_STR = "PMIC1 SWD Voltage Offset Direction";
+
+ template <typename T>
+ using COMPARISON_OP = std::less_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note PMIC1_SWD_DELAY field specialization
+/// @note valid for all revs
+///
+template< rev R >
+class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_SWD_DELAY, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x07;
+ static constexpr const char* FIELD_STR = "PMIC1 SWD Delay";
template <typename T>
using COMPARISON_OP = std::less_equal<T>;
@@ -5396,6 +5551,44 @@ class readerTraits < fields< DDR4, DDIMM_MODULE>::PMIC1_PHASE_COMBIN, R >
using COMPARISON_OP = std::less_equal<T>;
};
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_MFR_ID_CODE_LSB field specialization
+/// @note valid for all revisions
+///
+template< rev R >
+class readerTraits < fields<DDR4, DDIMM_MODULE>::DRAM_MFR_ID_CODE_LSB, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "DRAM manufacturer ID code, LSB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
+///
+/// @class readerTraits
+/// @brief trait structure to hold static SPD information
+/// @tparam R the revision of the SPD field
+/// @note DRAM_MFR_ID_CODE_MSB field specialization
+/// @note valid for all revisions
+///
+template< rev R >
+class readerTraits < fields<DDR4, DDIMM_MODULE>::DRAM_MFR_ID_CODE_MSB, R >
+{
+ public:
+
+ static constexpr size_t COMPARISON_VAL = 0x00;
+ static constexpr const char* FIELD_STR = "DRAM manufacturer ID code, MSB";
+
+ template <typename T>
+ using COMPARISON_OP = std::greater_equal<T>;
+};
+
}// spd
}// mss
diff --git a/src/import/generic/memory/lib/spd/spd_utils.C b/src/import/generic/memory/lib/spd/spd_utils.C
index bfe380dc5..38bf99577 100644
--- a/src/import/generic/memory/lib/spd/spd_utils.C
+++ b/src/import/generic/memory/lib/spd/spd_utils.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -113,7 +113,7 @@ fapi2::ReturnCode get_timebases( const mss::spd::facade& i_spd_decoder,
"Could not find a mapped value that matched the key (%d) for %s",
l_spd_ftb, spd::c_str(l_target) );
- FAPI_INF("MTB: %d, FTB: %d for %s", o_mtb, o_ftb, spd::c_str(l_target));
+ FAPI_DBG("MTB: %d, FTB: %d for %s", o_mtb, o_ftb, spd::c_str(l_target));
fapi_try_exit:
return fapi2::current_err;
@@ -162,7 +162,7 @@ fapi2::ReturnCode get_tckmin( const mss::spd::facade& i_spd_decoder,
o_value = l_temp;
- FAPI_INF("%s. tCKmin (ps): %d",
+ FAPI_DBG("%s. tCKmin (ps): %d",
spd::c_str(l_target),
o_value );
@@ -213,7 +213,7 @@ fapi2::ReturnCode get_tckmax( const mss::spd::facade& i_spd_decoder,
o_value = l_temp;
- FAPI_INF( "%s. tCKmax (ps): %d",
+ FAPI_DBG( "%s. tCKmax (ps): %d",
spd::c_str(l_target),
o_value);
diff --git a/src/import/generic/memory/lib/utils/buffer_ops.H b/src/import/generic/memory/lib/utils/buffer_ops.H
index 31e7f11a2..42b02b5d1 100644
--- a/src/import/generic/memory/lib/utils/buffer_ops.H
+++ b/src/import/generic/memory/lib/utils/buffer_ops.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -103,6 +103,32 @@ static inline void reverse( T& io_buffer )
}
///
+/// @brief Reverse a given bit range of a buffer
+/// @tparam S start bit
+/// @tparam L length of bits to reverse
+/// @tparam T buffer type
+/// @param[in] io_buffer
+///
+template<uint64_t S, uint64_t L, typename T>
+static inline void reverse_range(fapi2::buffer<T>& io_buffer)
+{
+ const auto target_length = fapi2::parameterTraits<T>::bit_length();
+
+ static_assert(S < target_length,
+ "reverse_range(): Start is out of bounds");
+
+ static_assert((S + L) <= target_length,
+ "reverse_range(): (Start + Len) is out of bounds");
+
+ fapi2::buffer<T> l_tmp;
+
+ io_buffer.template extractToRight<S, L>(l_tmp);
+
+ l_tmp.reverse();
+ io_buffer.template insert<S, L>(l_tmp);
+}
+
+///
/// @brief Swizzle bits between two fapi2 buffers, and insert from source to destination
/// @tparam DS the start bit in the destination buffer - swizzle will count up from here
/// @tparam L how many bits to swizzle
diff --git a/src/import/generic/memory/lib/utils/conversions.H b/src/import/generic/memory/lib/utils/conversions.H
index 5981fe7b5..dc4290ea5 100644
--- a/src/import/generic/memory/lib/utils/conversions.H
+++ b/src/import/generic/memory/lib/utils/conversions.H
@@ -101,7 +101,7 @@ static const std::vector<std::pair<uint64_t, uint64_t>> FREQ_TO_CLOCK_PERIOD =
{DIMM_SPEED_4400, 454}, // DDR5
{DIMM_SPEED_4800, 416}, // DDR5
};
-}
+} // ns dram_freq
///
/// @brief Return the number of picoseconds
diff --git a/src/import/generic/memory/lib/utils/count_dimm.H b/src/import/generic/memory/lib/utils/count_dimm.H
index 87f54fb40..3ceea2fab 100644
--- a/src/import/generic/memory/lib/utils/count_dimm.H
+++ b/src/import/generic/memory/lib/utils/count_dimm.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -55,7 +55,6 @@ inline size_t count_dimm(const fapi2::Target<T>& i_target)
// in the case of an over-ride and there are no DIMM in the config, we want to let
// people know. Which is how we found we needed to add this code ...
size_t l_dimm_count = find_targets<fapi2::TARGET_TYPE_DIMM>(i_target).size();
- FAPI_INF("%d DIMM on %s", l_dimm_count, mss::c_str(i_target));
return l_dimm_count;
}
@@ -71,5 +70,24 @@ inline size_t count_dimm(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target)
return 1;
}
+///
+/// @brief Return the count of the number of DIMM attached to a vector of targets
+/// @tparam T the fapi2::TargetType
+/// @param[in] i_target a vector of targets
+/// @return size_t the count of DIMM attached
+///
+template< fapi2::TargetType T >
+inline size_t count_dimm(const std::vector<fapi2::Target<T>>& i_targets)
+{
+ size_t l_dimm_count = 0;
+
+ for (const auto& l_target : i_targets)
+ {
+ l_dimm_count += count_dimm(l_target);
+ }
+
+ return l_dimm_count;
+}
+
}
#endif
diff --git a/src/import/generic/memory/lib/utils/dimm/kind.H b/src/import/generic/memory/lib/utils/dimm/kind.H
index bcb29264d..cdabc493e 100644
--- a/src/import/generic/memory/lib/utils/dimm/kind.H
+++ b/src/import/generic/memory/lib/utils/dimm/kind.H
@@ -22,3 +22,252 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file kind.H
+/// @brief Encapsulation for dimms of all types
+///
+// *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_KIND_H_
+#define _GEN_MSS_KIND_H_
+
+#include <fapi2.H>
+
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+namespace mss
+{
+
+namespace dimm
+{
+
+///
+/// @class mss::dimm::kind
+/// @tparam MC the MC type
+/// @brief A class containing information about a dimm like ranks, density, configuration - what kind of dimm is it?
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE>
+class kind
+{
+ public:
+
+ ///
+ /// @brief Generate a vector of DIMM kind from a vector of DIMM
+ /// @param[in] i_dimm a vector of DIMM
+ /// @return std::vector of dimm::kind relating to the DIMM passed in
+ ///
+ static std::vector<kind> vector(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>>& i_dimm)
+ {
+ std::vector<kind> l_kinds;
+
+ for (const auto& d : i_dimm)
+ {
+ l_kinds.push_back( kind(d) );
+ }
+
+ return l_kinds;
+ }
+
+ ///
+ /// @brief operator=() - assign kinds (needed to sort vectors of kinds)
+ /// @param[in] i_rhs the right hand side of the assignment statement
+ /// @return reference to this
+ ///
+ inline kind& operator=(const kind& i_rhs)
+ {
+ iv_target = i_rhs.iv_target;
+ iv_master_ranks = i_rhs.iv_master_ranks;
+ iv_total_ranks = i_rhs.iv_total_ranks;
+ iv_dram_density = i_rhs.iv_dram_density;
+ iv_dram_width = i_rhs.iv_dram_width;
+ iv_dram_generation = i_rhs.iv_dram_generation;
+ iv_dimm_type = i_rhs.iv_dimm_type;
+ iv_rows = i_rhs.iv_rows;
+ iv_size = i_rhs.iv_size;
+ iv_mfgid = i_rhs.iv_mfgid;
+ iv_stack_type = i_rhs.iv_stack_type;
+ iv_hybrid = i_rhs.iv_hybrid;
+ iv_hybrid_memory_type = i_rhs.iv_hybrid_memory_type;
+ iv_rcd_mfgid = i_rhs.iv_rcd_mfgid;
+ iv_module_height = i_rhs.iv_module_height;
+ return *this;
+ }
+
+ ///
+ /// @brief operator==() - are two kinds the same?
+ /// @param[in] i_rhs the right hand side of the comparison statement
+ /// @return bool true iff the two kind are of the same kind
+ /// @warning this does not compare the targets (iv_target,) just the values
+ /// Also does not compare the mfgid as that's not really part of the DIMM kind but is additional information
+ ///
+ inline bool operator==(const kind& i_rhs) const
+ {
+ return ((iv_master_ranks == i_rhs.iv_master_ranks) &&
+ (iv_total_ranks == i_rhs.iv_total_ranks) &&
+ (iv_dram_density == i_rhs.iv_dram_density) &&
+ (iv_dram_width == i_rhs.iv_dram_width) &&
+ (iv_dram_generation == i_rhs.iv_dram_generation) &&
+ (iv_dimm_type == i_rhs.iv_dimm_type) &&
+ (iv_rows == i_rhs.iv_rows) &&
+ (iv_size == i_rhs.iv_size) &&
+ (iv_stack_type == i_rhs.iv_stack_type) &&
+ (iv_hybrid == i_rhs.iv_hybrid) &&
+ (iv_hybrid_memory_type == i_rhs.iv_hybrid_memory_type) &&
+ (iv_rcd_mfgid == i_rhs.iv_rcd_mfgid) &&
+ (iv_module_height == i_rhs.iv_module_height));
+ }
+
+ ///
+ /// @brief operator!=() - are two kinds different?
+ /// @param[in] i_rhs the right hand side of the comparison statement
+ /// @return bool true iff the two kind are of different
+ /// @warning this does not compare the targets (iv_target,) just the values
+ ///
+ inline bool operator!=(const kind& i_rhs) const
+ {
+ return !(this->operator==(i_rhs));
+ }
+
+ ///
+ /// @brief Construct a dimm::kind data structure - information about the kind of DIMM this is
+ /// @param[in] i_target a DIMM target
+ ///
+ kind(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target):
+ iv_target(i_target)
+ {
+ FAPI_TRY( mss::attr::get_dram_gen(i_target, iv_dram_generation) );
+ FAPI_TRY( mss::attr::get_dimm_type(i_target, iv_dimm_type) );
+ FAPI_TRY( mss::attr::get_dram_density(i_target, iv_dram_density) );
+ FAPI_TRY( mss::attr::get_dram_width(i_target, iv_dram_width) );
+ FAPI_TRY( mss::attr::get_num_master_ranks_per_dimm(i_target, iv_master_ranks) );
+ FAPI_TRY( mss::attr::get_logical_ranks_per_dimm(i_target, iv_total_ranks) );
+ FAPI_TRY( mss::attr::get_dram_row_bits(i_target, iv_rows) );
+ FAPI_TRY( mss::attr::get_dimm_size(i_target, iv_size) );
+ FAPI_TRY( mss::attr::get_dram_mfg_id(i_target, iv_mfgid) );
+ FAPI_TRY( mss::attr::get_prim_stack_type( i_target, iv_stack_type) );
+ FAPI_TRY( mss::attr::get_hybrid( i_target, iv_hybrid ));
+ FAPI_TRY( mss::attr::get_hybrid_memory_type( i_target, iv_hybrid_memory_type ));
+ FAPI_TRY( mss::attr::get_rcd_mfg_id(i_target, iv_rcd_mfgid) );
+ FAPI_TRY( mss::attr::get_dram_module_height(i_target, iv_module_height) );
+ return;
+
+ fapi_try_exit:
+ // Not 100% sure what to do here ...
+ FAPI_ERR("error initializing DIMM structure: %s 0x%016lx", mss::c_str(i_target), uint64_t(fapi2::current_err));
+ fapi2::Assert(false);
+ }
+
+ ///
+ /// @brief Construct a DIMM kind used to identify this DIMM for tables.
+ /// @param[in] i_master_ranks number of master ranks on the DIMM
+ /// @param[in] i_total_ranks total number of ranks on the DIMM
+ /// @param[in] i_dram_density density of the DRAM
+ /// @param[in] i_dram_width width of the DRAM
+ /// @param[in] i_dram_generation DRAM generation
+ /// @param[in] i_dimm_type DIMM type (e.g. RDIMM)
+ /// @param[in] i_rows number of rows in the DRAM
+ /// @param[in] i_size the overal size of the DIMM in GB
+ /// @param[in] i_mfgid the dram manufacturer id of the dimm, defaulted to 0
+ /// @param[in] i_stack_type dram die type, single die package or 3DS
+ /// @param[in] i_hybrid, default not hybrid
+ /// @param[in] i_hybrid_memory_type, defult none
+ /// @param[in] i_rcd_mfgid dimm register and data buffer manufacturer id, default 0
+ /// @note can't be constexpr as fapi2::Target doesn't have a constexpr ctor.
+ ///
+ kind( const uint8_t i_master_ranks,
+ const uint8_t i_total_ranks,
+ const uint8_t i_dram_density,
+ const uint8_t i_dram_width,
+ const uint8_t i_dram_generation,
+ const uint8_t i_dimm_type,
+ const uint8_t i_rows,
+ const uint32_t i_size,
+ const uint16_t i_mfgid = 0,
+ const uint8_t i_stack_type = fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_SDP,
+ const uint8_t i_hybrid = fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID,
+ const uint8_t i_hybrid_memory_type = fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE,
+ const uint16_t i_rcd_mfgid = 0,
+ const uint8_t i_module_height = 0
+ ):
+ iv_target(0),
+ iv_master_ranks(i_master_ranks),
+ iv_total_ranks(i_total_ranks),
+ iv_dram_density(i_dram_density),
+ iv_dram_width(i_dram_width),
+ iv_dram_generation(i_dram_generation),
+ iv_dimm_type(i_dimm_type),
+ iv_rows(i_rows),
+ // TK consider calculating size rather than requiring it be set.
+ iv_size(i_size),
+ iv_mfgid(i_mfgid),
+ iv_stack_type(i_stack_type),
+ iv_hybrid(i_hybrid),
+ iv_hybrid_memory_type(i_hybrid_memory_type),
+ iv_rcd_mfgid(i_rcd_mfgid),
+ iv_module_height(i_module_height)
+ {
+ // Bit of an idiot-check to be sure a hand-crafted dimm::kind make sense wrt slaves, masters, packages, etc.
+ // Both of these are checked in eff_config. If they are messed up, they should be caught there
+ if (iv_master_ranks > iv_total_ranks)
+ {
+ FAPI_ERR("Not enough total ranks? master: %d total: %d",
+ iv_master_ranks,
+ iv_total_ranks);
+ fapi2::Assert(false);
+ }
+
+ if ((iv_total_ranks % iv_master_ranks) != 0)
+ {
+ FAPI_ERR("total or master ranks seems incorrect. master: %d total: %d",
+ iv_master_ranks,
+ iv_total_ranks);
+ fapi2::Assert(false);
+ }
+ }
+
+ fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target;
+ uint8_t iv_master_ranks;
+ uint8_t iv_total_ranks;
+ uint8_t iv_dram_density;
+ uint8_t iv_dram_width;
+ uint8_t iv_dram_generation;
+ uint8_t iv_dimm_type;
+ uint8_t iv_rows;
+ uint32_t iv_size;
+ uint16_t iv_mfgid;
+ uint8_t iv_stack_type;
+ uint8_t iv_hybrid;
+ uint8_t iv_hybrid_memory_type;
+ uint16_t iv_rcd_mfgid;
+ uint8_t iv_module_height;
+
+ ///
+ /// @brief equal_config
+ /// @param[in] i_input_compare the i_kind to compare against
+ /// @return bool true iff the two kind are of the same kind for xlate purposes
+ /// @warning this does not compare the targets (iv_target,), mfgid, prim_stack_type nor hybrid type
+ ///
+ inline bool equal_config(const kind& i_input_compare) const
+ {
+ return ((iv_master_ranks == i_input_compare.iv_master_ranks) &&
+ (iv_total_ranks == i_input_compare.iv_total_ranks) &&
+ (iv_dram_density == i_input_compare.iv_dram_density) &&
+ (iv_dram_width == i_input_compare.iv_dram_width) &&
+ (iv_dram_generation == i_input_compare.iv_dram_generation) &&
+ (iv_dimm_type == i_input_compare.iv_dimm_type) &&
+ (iv_rows == i_input_compare.iv_rows) &&
+ (iv_size == i_input_compare.iv_size));
+ }
+};
+
+}
+
+}
+#endif
diff --git a/src/import/generic/memory/lib/utils/dimm/mss_timing.H b/src/import/generic/memory/lib/utils/dimm/mss_timing.H
new file mode 100644
index 000000000..2bc9805de
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/dimm/mss_timing.H
@@ -0,0 +1,912 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/dimm/mss_timing.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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_timing.H
+/// @brief Determine effective config for mss settings
+///
+// *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com>
+// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_GEN_TIMING_H_
+#define _MSS_GEN_TIMING_H_
+
+#include <cstdint>
+#include <fapi2.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/conversions.H>
+#include <generic/memory/lib/spd/spd_utils.H>
+
+namespace mss
+{
+
+///
+/// @brief Enums for ffdc error callout so we know which function had the error
+///
+enum timing_ffdc_codes
+{
+ TRAS = 0,
+ TFAW_HALF_KB_PAGE_HELPER = 1,
+ TFAW_ONE_KB_PAGE_HELPER = 2,
+ TFAW_TW_KB_PAGE_HELPER = 3,
+ TFAW_SLR_X4_HELPER = 4,
+ TFAW_SLR_X8_HELPER = 5,
+ TRRD_S_SLR = 6,
+ TRRD_L_SLR = 7,
+ TRRD_L_HALF_AND_1KB_PAGE_HELPER = 8,
+ TRRD_S_HALF_AND_1KB_PAGE_HELPER = 9,
+ TRRD_S_2KB_PAGE_HELPER = 10,
+ TRRD_S = 11,
+ TRRD_L = 12,
+ TFAW = 13,
+ TDLLK = 14,
+};
+
+enum refresh_rate : uint8_t
+{
+ REF1X = 1, ///< Refresh rate 1X
+ REF2X = 2, ///< Refresh rate 2X
+ REF4X = 4, ///< Refresh rate 4X
+};
+
+namespace spd
+{
+
+///
+/// @brief Returns clock cycles form picoseconds based on speed bin
+/// Uses SPD rounding algorithm for DDR4
+/// @tparam OT the output type, derrived from the parameters
+/// @param[in] i_freq frequency of the DIMM
+/// @param[in] timing_in_ps timing parameter in ps
+/// @return the clock cycles of timing parameter (provided in ps)
+/// @note Uses DDR4 SPD Contents Rounding Algorithm
+/// @note Item 2220.46
+///
+template<typename OT>
+inline OT ps_to_nck( const uint64_t i_freq, const OT& i_timing_in_ps)
+{
+ OT l_tck_in_ps = 0;
+ OT l_temp_nck = 0;
+
+ // No time if MT/s is 0 (well, infinite really but shut up)
+ if (i_freq == 0)
+ {
+ return 0;
+ }
+
+ FAPI_TRY( freq_to_ps(i_freq, l_tck_in_ps),
+ "Failed freq() accessor" );
+ FAPI_TRY( calc_nck(i_timing_in_ps, l_tck_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_temp_nck),
+ "Failed calc_nck()" );
+
+ return l_temp_nck;
+
+fapi_try_exit:
+ // We simply can't work if we get an unsupported value that can't be converted to a valid tCK (clock period)
+ // ...so this should be ok
+ FAPI_ERR("Obtained an invalid MSS_FREQ (%d), or overflow occurred - stopping", i_freq);
+ fapi2::Assert(false);
+
+ // Keeps compiler happy
+ return 0;
+}
+
+///
+/// @brief Returns clock cycles from nanoseconds
+/// Uses SPD rounding algorithm for DDR4
+/// @tparam OT the output type, derrived from the parameters
+/// @param[in] i_freq frequency of the DIMM
+/// @param[out] o_value_nck the end calculation in nck
+/// @return the clock cycles of timing parameter (provided in ps)
+/// @note Uses DDR4 SPD Contents Rounding Algorithm
+/// @note Item 2220.46
+///
+template<typename OT>
+inline OT ns_to_nck( const uint64_t i_freq, const OT& i_timing_in_ns)
+{
+ return ps_to_nck(i_freq, i_timing_in_ns * CONVERT_PS_IN_A_NS);
+}
+
+}// spd
+
+///
+/// @brief Calculates refresh interval time
+/// @param[in] i_mode fine refresh rate mode
+/// @param[in] i_refresh_request_rate refresh rate
+/// @param[out] o_value timing val in ps
+/// @return fapi2::ReturnCode
+///
+inline fapi2::ReturnCode calc_trefi( const refresh_rate i_mode,
+ const uint8_t i_refresh_request_rate,
+ uint64_t& o_timing )
+{
+ // Proposed DDR4 Full spec update(79-4B)
+ // Item No. 1716.78C
+ // pg.46
+ // Table 24 - tREFI and tRFC parameters (in ps)
+ constexpr uint64_t TREFI_BASE = 7800000;
+
+ uint64_t l_refresh_request = 0;
+ constexpr double TEN_PERCENT_FASTER = 0.90;
+
+ switch(i_refresh_request_rate)
+ {
+ case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_SINGLE:
+ l_refresh_request = TREFI_BASE;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_DOUBLE:
+ // We are truncating but there is no remainder with TREFI_BASE, so we are okay
+ l_refresh_request = TREFI_BASE / 2;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_SINGLE_10_PERCENT_FASTER:
+ // We are truncating but there is no remainder with TREFI_BASE, so we are okay
+ // 10% faster so 100% - 10% = 90%
+ l_refresh_request = TREFI_BASE * TEN_PERCENT_FASTER;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_DOUBLE_10_PERCENT_FASTER:
+ // We are truncating but there is no remainder with TREFI_BASE, so we are okay
+ // 10% faster so 100% - 10% = 90%
+ l_refresh_request = (TREFI_BASE / 2) * TEN_PERCENT_FASTER;
+ break;
+
+ default:
+ // Will catch incorrect MRW value set
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_REFRESH_RATE_REQUEST().set_REFRESH_RATE_REQUEST(i_refresh_request_rate),
+ "Incorrect refresh request rate received: %d ", i_refresh_request_rate);
+ break;
+ }
+
+ o_timing = (l_refresh_request / i_mode);
+
+ FAPI_INF( "tREFI (ps): %d, refresh request (ps): %d, tREFI_base (ps): %d, REF%dX",
+ o_timing, l_refresh_request, TREFI_BASE, i_mode );
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+/// @brief Calculates Minimum Refresh Recovery Delay Time (different logical rank)
+/// @param[in] i_mode fine refresh rate mode
+/// @param[in] i_density SDRAM density
+/// @param[out] o_trfc_in_ps timing val in ps
+/// @return fapi2::FAPI2_RC_SUCCESS iff okay
+///
+inline fapi2::ReturnCode calc_trfc_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_refresh_mode,
+ const uint8_t i_density,
+ uint64_t& o_trfc_in_ps)
+{
+ // Proposed DDR4 3DS Addendum
+ // Item No. 1727.58A
+ // pg. 69 - 71
+ // Table 42 - Refresh parameters by logical rank density
+ const std::vector<std::pair<uint8_t, uint64_t> > TRFC_DLR1 =
+ {
+ // { density in GBs, tRFC4(min) in picoseconds }
+ {4, 90000},
+ {8, 120000},
+ {16, 185000},
+ };
+
+ // Proposed DDR4 3DS Addendum
+ // Item No. 1727.58A
+ // pg. 69 - 71
+ // Table 42 - Refresh parameters by logical rank density
+ const std::vector<std::pair<uint8_t, uint64_t> > TRFC_DLR2 =
+ {
+ // { density in GBs, tRFC4(min) in picoseconds }
+ {4, 55000},
+ {8, 90000},
+ {16, 120000},
+ };
+
+ // Proposed DDR4 3DS Addendum
+ // Item No. 1727.58A
+ // pg. 69 - 71
+ // Table 42 - Refresh parameters by logical rank density
+ const std::vector<std::pair<uint8_t, uint64_t> > TRFC_DLR4 =
+ {
+ // { density in GBs, tRFC4(min) in picoseconds }
+ {4, 40000},
+ {8, 55000},
+ {16, 90000},
+ };
+
+ bool l_is_val_found = 0;
+
+ // Selects appropriate tRFC based on fine refresh mode
+ switch(i_refresh_mode)
+ {
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL:
+ l_is_val_found = find_value_from_key(TRFC_DLR1, i_density, o_trfc_in_ps);
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X:
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X:
+ l_is_val_found = find_value_from_key(TRFC_DLR2, i_density, o_trfc_in_ps);
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_4X:
+ case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_4X:
+ l_is_val_found = find_value_from_key(TRFC_DLR4, i_density, o_trfc_in_ps);
+ break;
+
+ default:
+ // Fine Refresh Mode will be a platform attribute set by the MRW,
+ // which they "shouldn't" mess up as long as use "attribute" enums.
+ // if openpower messes this up we can at least catch it
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FINE_REFRESH_MODE()
+ .set_FINE_REF_MODE(i_refresh_mode),
+ "Incorrect Fine Refresh Mode received: %d ",
+ i_refresh_mode);
+ break;
+ }// switch
+
+ FAPI_ASSERT( l_is_val_found,
+ fapi2::MSS_FAILED_TO_FIND_TRFC()
+ .set_SDRAM_DENSITY(i_density)
+ .set_REFRESH_MODE(i_refresh_mode)
+ .set_DIMM_TARGET(i_target),
+ "%s: Unable to find tRFC (ps) from map with SDRAM density key %d with %d refresh mode",
+ mss::c_str(i_target),
+ i_density,
+ i_refresh_mode);
+
+ // Again, FAPI_ASSERT doesn't set current_err to good, only to bad
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief tRTP *in ps*
+/// @return constexpr value of RTP = 7500 ps
+///
+constexpr uint64_t trtp()
+{
+ // Per JEDEC spec, defaults to 7500 ps for all frequencies.
+ // (technically max of 7.5 ns or 4 nclk, which is always 7.5ns for DDR4)
+ return 7500;
+}
+
+///
+/// @brief Return the minimum allowable tRAS in picoseconds
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq freq for the DIMM
+/// @return value in picoseconds
+///
+inline uint64_t tras(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint64_t i_freq)
+{
+ uint64_t l_tras = 0;
+
+ switch(i_freq)
+ {
+ case 1866:
+ l_tras = 34000;
+ break;
+
+ case 2133:
+ l_tras = 33000;
+ break;
+
+ case 2400:
+ case 2666:
+ case 2933:
+ case 3200:
+ l_tras = 32000;
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FREQ_PASSED_IN()
+ .set_FREQ(i_freq)
+ .set_FUNCTION(TRAS)
+ .set_DIMM_TARGET(i_target),
+ "%s Invalid frequency %lu",
+ mss::c_str(i_target),
+ i_freq);
+ }
+
+ return l_tras;
+
+fapi_try_exit:
+
+ // We simply can't work if we can't get the frequency or
+ // if we get an unsupported value that can't be converted to a valid tCK (clock period)
+ // ...so this should be ok
+ FAPI_ERR("Obtained an invalid MSS_FREQ (%d) - stopping", i_freq);
+ fapi2::Assert(false);
+
+ // Keeps compiler happy
+ return 0;
+}
+
+///
+/// @brief Helper function to find tFAW based speed (MT/s) for 1/2 KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_half_kb_page_helper(const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(i_freq)
+ {
+ // static_cast is needed for template deduction of std::max API
+ case 1866:
+ o_output = std::max( 16, spd::ps_to_nck(i_freq, 17000) );
+ break;
+
+ case 2133:
+ o_output = std::max( 16, spd::ps_to_nck(i_freq, 15000) );
+ break;
+
+ case 2400:
+ o_output = std::max( 16, spd::ps_to_nck(i_freq, 13000) );
+ break;
+
+ case 2666:
+ o_output = std::max( 16, spd::ps_to_nck(i_freq, 12000) );
+ break;
+
+ case 2933:
+ o_output = std::max( 16, spd::ps_to_nck(i_freq, 10875) );
+ break;
+
+ case 3200:
+ o_output = std::max( 16, spd::ps_to_nck(i_freq, 10000) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FREQ_PASSED_IN()
+ .set_FREQ(i_freq)
+ .set_FUNCTION(TFAW_HALF_KB_PAGE_HELPER)
+ .set_DIMM_TARGET(i_target),
+ "%s Invalid frequency %lu",
+ mss::c_str(i_target),
+ i_freq);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tFAW based speed (MT/s) for 1KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_1kb_page_helper(const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(i_freq)
+ {
+ case 1866:
+ o_output = std::max( 20, spd::ns_to_nck(i_freq, 23) );
+ break;
+
+ case 2133:
+ case 2400:
+ case 2666:
+ case 2933:
+ case 3200:
+ o_output = std::max( 20, spd::ns_to_nck(i_freq, 21) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FREQ_PASSED_IN()
+ .set_FREQ(i_freq)
+ .set_FUNCTION(TFAW_ONE_KB_PAGE_HELPER)
+ .set_DIMM_TARGET(i_target),
+ "%s Invalid frequency %lu",
+ mss::c_str(i_target),
+ i_freq);
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tFAW based speed (MT/s) for 2KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_2kb_page_helper(const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ uint64_t& o_output)
+{
+
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(i_freq)
+ {
+ case 1866:
+ case 2133:
+ case 2400:
+ case 2666:
+ case 2933:
+ case 3200:
+ o_output = std::max( 28, spd::ns_to_nck(i_freq, 30) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FREQ_PASSED_IN()
+ .set_FREQ(i_freq)
+ .set_FUNCTION(TFAW_TW_KB_PAGE_HELPER)
+ .set_DIMM_TARGET(i_target),
+ "%s Invalid frequency %lu",
+ mss::c_str(i_target),
+ i_freq);
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return the minimum allowable tFAW in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_dram_width the page size
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_tFAW timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+//
+template< fapi2::TargetType T >
+fapi2::ReturnCode tfaw( const fapi2::Target<T>& i_target,
+ const uint8_t i_dram_width,
+ const uint64_t i_freq,
+ uint64_t& o_tFAW )
+{
+ switch(i_dram_width)
+ {
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4:
+ FAPI_TRY( tfaw_half_kb_page_helper(i_target, i_freq, o_tFAW) );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8:
+ FAPI_TRY( tfaw_1kb_page_helper(i_target, i_freq, o_tFAW) );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
+ FAPI_TRY( tfaw_2kb_page_helper(i_target, i_freq, o_tFAW) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_DRAM_WIDTH()
+ .set_DRAM_WIDTH(i_dram_width)
+ .set_DIMM_TARGET(i_target),
+ "Invalid DRAM width with %d for target %s",
+ i_dram_width,
+ mss::c_str(i_target));
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief tFAW_dlr *in nck*
+/// @return 16nck
+/// @note From DDR4 3DS Spec
+/// 12.2 Timing Parameters by Speed Grade
+///
+constexpr uint64_t tfaw_dlr()
+{
+ return 16;
+}
+
+///
+/// @brief tRRD_dlr *in nck*
+/// @return 4nck
+/// @note From DDR4 3DS Spec
+/// 12.2 Timing Parameters by Speed Grade
+///
+constexpr uint64_t trrd_dlr()
+{
+ return 4;
+}
+
+///
+/// @brief Helper function to find tRRD_L based speed (MT/s) for 1KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_l_half_and_1kb_page_helper(const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(i_freq)
+ {
+ case 1866:
+ case 2133:
+ // From the spec: Max(4nCK,5.3ns)
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 5300) );
+ break;
+
+ case 2400:
+ case 2666:
+ case 2933:
+ case 3200:
+ // Max(4nCK,4.9ns)
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 4900) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FREQ_PASSED_IN()
+ .set_FREQ(i_freq)
+ .set_FUNCTION(TRRD_L_HALF_AND_1KB_PAGE_HELPER)
+ .set_DIMM_TARGET(i_target),
+ "%s Invalid frequency %lu",
+ mss::c_str(i_target),
+ i_freq);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tRRD_L based speed (MT/s) for 2KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_l_2kb_page_helper(const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ uint64_t& o_output)
+{
+
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(i_freq)
+ {
+ case 1866:
+ case 2133:
+ case 2400:
+ case 2666:
+ case 2933:
+ case 3200:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 6400) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), i_freq);
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return the minimum allowable tRRD_L in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_dram_width the page size
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode trrd_l( const fapi2::Target<T>& i_target,
+ const uint8_t i_dram_width,
+ const uint64_t i_freq,
+ uint64_t& o_tRRD_L )
+{
+ switch(i_dram_width)
+ {
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4:
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8:
+ FAPI_TRY( trrd_l_half_and_1kb_page_helper(i_target, i_freq, o_tRRD_L),
+ "Error calculating trrd l for half and 1kb page" );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
+ FAPI_TRY( trrd_l_2kb_page_helper(i_target, i_freq, o_tRRD_L) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_PAGE_SIZE()
+ .set_DRAM_WIDTH(i_dram_width)
+ .set_DIMM_TARGET(i_target),
+ "%s Recieved an invalid page size: %lu",
+ mss::c_str(i_target),
+ i_dram_width);
+ break;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tRRD_S based speed (MT/s) for 1KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_s_half_and_1kb_page_helper(const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(i_freq)
+ {
+ case 1866:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 4200) );
+ break;
+
+ case 2133:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 3700) );
+ break;
+
+ case 2400:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 3300) );
+ break;
+
+ case 2666:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 3000) );
+ break;
+
+ case 2933:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 2700) );
+ break;
+
+ case 3200:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 2500) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FREQ_PASSED_IN()
+ .set_FREQ(i_freq)
+ .set_FUNCTION(TRRD_S_HALF_AND_1KB_PAGE_HELPER)
+ .set_DIMM_TARGET(i_target),
+ "%s Invalid frequency %lu",
+ mss::c_str(i_target),
+ i_freq);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tRRD_S based speed (MT/s) for 2KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_s_2kb_page_helper(const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(i_freq)
+ {
+ case 1866:
+ case 2133:
+ case 2400:
+ case 2666:
+ case 2933:
+ case 3200:
+ o_output = std::max( 4, spd::ps_to_nck(i_freq, 5300) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_FREQ_PASSED_IN()
+ .set_FREQ(i_freq)
+ .set_FUNCTION(TRRD_S_2KB_PAGE_HELPER)
+ .set_DIMM_TARGET(i_target),
+ "%s Invalid frequency %lu",
+ mss::c_str(i_target),
+ i_freq);
+ break;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return the minimum allowable tRRD_S in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_dram_width the page size
+/// @param[in] i_freq the DRAM frequency
+/// @param[out] o_tRRD_S timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode trrd_s( const fapi2::Target<T>& i_target,
+ const uint8_t i_dram_width,
+ const uint64_t i_freq,
+ uint64_t& o_tRRD_S )
+{
+ switch(i_dram_width)
+ {
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4:
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8:
+ FAPI_TRY( trrd_s_half_and_1kb_page_helper(i_target, i_freq, o_tRRD_S),
+ "Error calculating trrd_s for half and 1kb page" );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
+ FAPI_TRY( trrd_s_2kb_page_helper(i_target, i_freq, o_tRRD_S) );
+ break;
+
+ default:
+ FAPI_ASSERT( false,
+ fapi2::MSS_INVALID_PAGE_SIZE()
+ .set_DRAM_WIDTH(i_dram_width)
+ .set_DIMM_TARGET(i_target),
+ "%s Recieved an invalid page size: %lu",
+ mss::c_str(i_target),
+ i_dram_width);
+ break;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/dump_regs.H b/src/import/generic/memory/lib/utils/dump_regs.H
index 91241cd70..f8d7e5b12 100644
--- a/src/import/generic/memory/lib/utils/dump_regs.H
+++ b/src/import/generic/memory/lib/utils/dump_regs.H
@@ -22,3 +22,34 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+
+///
+/// @file dump_regs.H
+/// @brief Dump registers
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_DUMP_REGS_H_
+#define _MSS_DUMP_REGS_H_
+
+#include <fapi2.H>
+
+namespace mss
+{
+
+///
+/// @brief Dump the registers of a target
+/// @tparam T, the fapi2::TargetType
+/// @param[in] i_target the target in question
+/// @return fapi2::FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode dump_regs( const fapi2::Target<T>& i_target );
+
+}
+#endif
diff --git a/src/import/generic/memory/lib/utils/endian_utils.H b/src/import/generic/memory/lib/utils/endian_utils.H
index 20bfd7caa..94b9dbc0d 100644
--- a/src/import/generic/memory/lib/utils/endian_utils.H
+++ b/src/import/generic/memory/lib/utils/endian_utils.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -37,9 +37,14 @@
#ifndef _ENDIAN_UTILS_H_
#define _ENDIAN_UTILS_H_
-#include <cstdint>
#include <vector>
-#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+#ifdef __PPE__
+ #include <mss_generic_consts.H>
+#else
+ #include <cstdint>
+ #include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#endif
namespace mss
{
@@ -67,6 +72,7 @@ void forceLE(const T& i_input, std::vector<uint8_t>& io_data)
}
}
+#ifndef __PPE__
///
/// @brief Forces native data into LE order for an array
/// @tparam T the data type to process
@@ -82,7 +88,7 @@ inline void forceLEArray(const T* i_input, const uint64_t i_size, std::vector<ui
forceLE(i_input[i], io_data);
}
}
-
+#endif
///
/// @brief Forces native data into BE order
/// @tparam T the data type to process
@@ -98,20 +104,31 @@ void forceBE(const T& i_input, std::vector<uint8_t>& io_data)
std::vector<uint8_t> l_tempBuffer;
// This loop will put i_input into l_tempBuffer in BE order
- for(size_t i = 0; i < sizeof(i_input); i++)
+
+ for(size_t i = sizeof(i_input); i > 0; i--)
{
// Grab the lowest order byte and add it to the front of the vector
const uint8_t l_byte = l_temp & 0xFF;
- l_tempBuffer.insert(l_tempBuffer.begin(), l_byte);
+ l_tempBuffer.push_back(l_byte);
// Shift higher byte value into lowest no matter existing endianness
l_temp >>= BITS_PER_BYTE;
}
// Put the new BE formatted data at the end of the input buffer
- io_data.insert(io_data.end(), l_tempBuffer.begin(), l_tempBuffer.end());
+
+ std::vector<uint8_t>::iterator it = l_tempBuffer.end();
+ --it; //Move iterator to the last element.
+
+ for(uint8_t i = l_tempBuffer.size(); i > 0; --i)
+ {
+ io_data.push_back(*it);
+ --it;
+ }
+
}
+#ifndef __PPE__
///
/// @brief Forces native data into BE order for an array
/// @tparam T the data type to process
@@ -127,6 +144,7 @@ inline void forceBEArray(const T* i_input, const uint64_t i_size, std::vector<ui
forceBE(i_input[i], io_data);
}
}
+#endif
///
/// @brief Converts LE data into native order
@@ -165,6 +183,7 @@ bool readLE(const std::vector<uint8_t>& i_input, uint32_t& io_idx, T& o_data)
return true;
}
+#ifndef __PPE__
///
/// @brief Converts LE data into native order
/// @tparam T the data type to output to
@@ -188,6 +207,7 @@ bool readLEArray(const std::vector<uint8_t>& i_input, const uint32_t i_size, uin
return l_passing;
}
+#endif
///
/// @brief Converts BE data into native order
@@ -225,6 +245,7 @@ bool readBE(const std::vector<uint8_t>& i_input, uint32_t& io_idx, T& o_data)
return true;
}
+#ifndef __PPE__
///
/// @brief Converts BE data into native order
/// @tparam T the data type to output to
@@ -248,6 +269,7 @@ bool readBEArray(const std::vector<uint8_t>& i_input, const uint32_t i_size, uin
return l_passing;
}
+#endif
}
diff --git a/src/import/generic/memory/lib/utils/find.H b/src/import/generic/memory/lib/utils/find.H
index c22199b6d..297334ae7 100644
--- a/src/import/generic/memory/lib/utils/find.H
+++ b/src/import/generic/memory/lib/utils/find.H
@@ -38,9 +38,13 @@
#include <fapi2.H>
#include <vector>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/index.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
namespace mss
{
+
///
/// @brief Helper to find a set of elements based on a fapi2 target
/// @tparam M the target type to be returned
@@ -117,6 +121,7 @@ static inline fapi2::Target<M> find_target_impl( const fapi2::Target<T>& i_targe
/// @tparam M the target type to be returned
/// @tparam T the fapi2 target type of the argument
/// @param[in] i_target the fapi2 target T
+/// @param[in] std::true_type tag dispatch if T == M
/// @return an M target.
/// @note Only works for valid parent-child relationships
///
@@ -145,30 +150,6 @@ inline fapi2::Target<M> find_target( const fapi2::Target<T>& i_target)
}
///
-/// @brief find the McBIST given a DIMM
-/// @param[in] i_target the fapi2 target DIMM
-/// @return a McBIST target.
-///
-template<>
-inline fapi2::Target<fapi2::TARGET_TYPE_MCBIST> find_target(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target)
-{
- return i_target.getParent<fapi2::TARGET_TYPE_MCA>().getParent<fapi2::TARGET_TYPE_MCBIST>();
-}
-
-///
-/// @brief find the PROC_CHIP given a MBA
-/// @param[in] i_target the fapi2 target MBA
-/// @return a DMI target.
-///
-template<>
-inline fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> find_target(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
-{
- return i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>()
- .getParent<fapi2::TARGET_TYPE_DMI>()
- .getParent<fapi2::TARGET_TYPE_PROC_CHIP>();
-}
-
-///
/// @brief find the PROC_CHIP given a OCMB_CHIP
/// @param[in] i_target the fapi2 target OCMB_CHIP
/// @return a PROC_CHIP target.
@@ -183,26 +164,16 @@ inline fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> find_target(const fapi2::Targ
}
///
-/// @brief find the DMI given an MBA
-/// @param[in] i_target the fapi2 target MBA
-/// @return a DMI target.
-///
-template<>
-inline fapi2::Target<fapi2::TARGET_TYPE_DMI> find_target(const fapi2::Target<fapi2::TARGET_TYPE_MBA>& i_target)
-{
- return i_target.getParent<fapi2::TARGET_TYPE_MEMBUF_CHIP>().getParent<fapi2::TARGET_TYPE_DMI>();
-}
-
-///
-/// @brief find the PROC given a MEMBUF
-/// @param[in] i_target the fapi2 target MEMBUF
-/// @return a PROC target.
+/// @brief find the MCC given a OCMB_CHIP
+/// @param[in] i_target the fapi2 target OCMB_CHIP
+/// @return a MCC target.
///
template<>
-inline fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> find_target(const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>&
+inline fapi2::Target<fapi2::TARGET_TYPE_MCC> find_target(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
i_target)
{
- return i_target.getParent<fapi2::TARGET_TYPE_DMI>().getParent<fapi2::TARGET_TYPE_PROC_CHIP>();
+ return i_target.getParent<fapi2::TARGET_TYPE_OMI>()
+ .getParent<fapi2::TARGET_TYPE_MCC>();
}
///
@@ -230,98 +201,93 @@ find_targets( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
}
///
-/// @brief find all the MBA connected to an DMI
-/// @param[in] i_target a fapi2::Target DMI
-/// @return a vector of fapi2::TARGET_TYPE_MBA
-///
-template<>
-inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_MBA> >
-find_targets( const fapi2::Target<fapi2::TARGET_TYPE_DMI>& i_target,
- fapi2::TargetState i_state )
-{
- std::vector< fapi2::Target<fapi2::TARGET_TYPE_MBA> > l_mbas;
-
- for (const auto& membuf_chip : i_target.getChildren<fapi2::TARGET_TYPE_MEMBUF_CHIP>(i_state))
- {
- auto l_these_mbas( membuf_chip.getChildren<fapi2::TARGET_TYPE_MBA>(i_state) );
- l_mbas.insert(l_mbas.end(), l_these_mbas.begin(), l_these_mbas.end());
- }
-
- return l_mbas;
-}
-
-///
-/// @brief find all the DIMM connected to a centaur
-/// @param[in] i_target a fapi2::Target TARGET_TYPE_MEMBUF_CHIP
+/// @brief find all the DIMMS connected to an MI
+/// @param[in] i_target a fapi2::Target MI
/// @return a vector of fapi2::TARGET_TYPE_DIMM
///
template<>
inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_DIMM> >
-find_targets( const fapi2::Target<fapi2::TARGET_TYPE_MEMBUF_CHIP>& i_target,
+find_targets( const fapi2::Target<fapi2::TARGET_TYPE_MI>& i_target,
fapi2::TargetState i_state )
{
std::vector< fapi2::Target<fapi2::TARGET_TYPE_DIMM> > l_dimms;
- for (const auto& l_mba : i_target.getChildren<fapi2::TARGET_TYPE_MBA>(i_state))
+ for (const auto& l_omi : i_target.getChildren<fapi2::TARGET_TYPE_OMI>(i_state))
{
- auto l_these_dimms( l_mba.getChildren<fapi2::TARGET_TYPE_DIMM>(i_state) );
- l_dimms.insert(l_dimms.end(), l_these_dimms.begin(), l_these_dimms.end());
+ for (const auto& l_ocmb : l_omi.getChildren<fapi2::TARGET_TYPE_OCMB_CHIP>(i_state))
+ {
+ auto l_these_dimms( l_ocmb.getChildren<fapi2::TARGET_TYPE_DIMM>(i_state) );
+ l_dimms.insert(l_dimms.end(), l_these_dimms.begin(), l_these_dimms.end());
+ }
}
return l_dimms;
}
///
-/// @brief find all the dimm connected to an MCS
-/// @param[in] i_target a fapi2::Target MCS
-/// @return a vector of fapi2::TARGET_TYPE_DIMM
+/// @brief find all the OCMB_CHIPs connected to an MI
+/// @param[in] i_target a fapi2::Target MI
+/// @return a vector of fapi2::TARGET_TYPE_OCMB_CHIP
///
template<>
-inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_DIMM> >
-find_targets( const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >
+find_targets( const fapi2::Target<fapi2::TARGET_TYPE_MI>& i_target,
fapi2::TargetState i_state )
{
- std::vector< fapi2::Target<fapi2::TARGET_TYPE_DIMM> > l_dimms;
+ std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> > l_ocmbs;
- for (const auto& p : i_target.getChildren<fapi2::TARGET_TYPE_MCA>(i_state))
+ for (const auto& l_omi : i_target.getChildren<fapi2::TARGET_TYPE_OMI>(i_state))
{
- auto l_these_dimms( p.getChildren<fapi2::TARGET_TYPE_DIMM>(i_state) );
- l_dimms.insert(l_dimms.end(), l_these_dimms.begin(), l_these_dimms.end());
+ auto l_these_ocmbs( l_omi.getChildren<fapi2::TARGET_TYPE_OCMB_CHIP>(i_state) );
+ l_ocmbs.insert(l_ocmbs.end(), l_these_ocmbs.begin(), l_these_ocmbs.end());
}
- return l_dimms;
+ return l_ocmbs;
}
///
-/// @brief find all the dimms connected to an MCBIST
-/// @param[in] i_target a fapi2::Target MCBIST
-/// @return a vector of fapi2::TARGET_TYPE_DIMM
+/// @brief find all the MEM_PORTs connected to a PROC_CHIP
+/// @param[in] i_target a fapi2::Target PROC_CHIP
+/// @return a vector of fapi2::TARGET_TYPE_MEM_PORT
///
template<>
-inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_DIMM> >
-find_targets( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> >
+find_targets( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
fapi2::TargetState i_state )
{
- std::vector< fapi2::Target<fapi2::TARGET_TYPE_DIMM> > l_dimms;
+ std::vector< fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> > l_ports;
- for (const auto& p : i_target.getChildren<fapi2::TARGET_TYPE_MCA>(i_state))
+ for (const auto& l_mc : i_target.getChildren<fapi2::TARGET_TYPE_MC>(i_state))
{
- auto l_these_dimms( p.getChildren<fapi2::TARGET_TYPE_DIMM>(i_state) );
- l_dimms.insert(l_dimms.end(), l_these_dimms.begin(), l_these_dimms.end());
+ for (const auto& l_omi : l_mc.getChildren<fapi2::TARGET_TYPE_OMI>(i_state))
+ {
+ for (const auto& l_ocmb : l_omi.getChildren<fapi2::TARGET_TYPE_OCMB_CHIP>(i_state))
+ {
+ auto l_these_ports( l_ocmb.getChildren<fapi2::TARGET_TYPE_MEM_PORT>(i_state) );
+ l_ports.insert(l_ports.end(), l_these_ports.begin(), l_these_ports.end());
+ }
+ }
}
- return l_dimms;
+ return l_ports;
}
///
-/// @brief find the MCS given a DIMM
-/// @param[in] i_target the fapi2 target DIMM
-/// @return a MCS target.
+/// @brief Helper to find a set of elements based on a fapi2 target, then sort them
+/// @tparam M the target type to be returned
+/// @tparam T the fapi2 target type of the argument
+/// @param[in] i_target the fapi2 target T
+/// @param[in] i_state [optional] fapi2 target state (defaults to TARGET_STATE_FUNCTIONAL)
+/// @return a vector of M targets sorted by mss::index.
+/// @note this uses mss::index so the targets will be sorted via ATTR_REL_POS of their immediate parent
///
-template<>
-inline fapi2::Target<fapi2::TARGET_TYPE_MCS> find_target( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target)
+template< fapi2::TargetType M, fapi2::TargetType T >
+static inline std::vector< fapi2::Target<M> > find_targets_sorted_by_index( const fapi2::Target<T>& i_target,
+ fapi2::TargetState i_state = fapi2::TARGET_STATE_FUNCTIONAL )
{
- return i_target.getParent<fapi2::TARGET_TYPE_MCA>().getParent<fapi2::TARGET_TYPE_MCS>();
+ std::vector<fapi2::Target<M>> l_targets = find_targets<M, T>(i_target, i_state);
+ sort_targets_by_index(l_targets);
+ return l_targets;
}
///
@@ -432,6 +398,40 @@ bool find_value_from_key( const std::pair<T, OT> (&i_array)[N],
return false;
}
+///
+/// @brief Mapping boilerplate check
+/// @tparam T FAPI2 target type
+/// @tparam IT map key type
+/// @tparam OT map value type
+/// @param[in] i_target the FAPI target
+/// @param[in] i_map SPD to attribute data mapping
+/// @param[in] i_ffdc_code FFDC function code
+/// @param[in] i_key Key to query map
+/// @param[out] o_output value from key
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template< fapi2::TargetType T, typename IT, typename OT >
+inline fapi2::ReturnCode lookup_table_check(const fapi2::Target<T>& i_target,
+ const std::vector<std::pair<IT, OT>>& i_map,
+ const generic_ffdc_codes i_ffdc_code,
+ const IT i_key,
+ OT& o_output)
+{
+ const bool l_is_val_found = mss::find_value_from_key(i_map, i_key, o_output);
+
+ FAPI_ASSERT( l_is_val_found,
+ fapi2::MSS_LOOKUP_FAILED()
+ .set_KEY(i_key)
+ .set_DATA(o_output)
+ .set_FUNCTION(i_ffdc_code)
+ .set_TARGET(i_target),
+ "Failed to find a mapped value for %d on %s",
+ i_key,
+ mss::spd::c_str(i_target) );
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
}// mss
#endif
diff --git a/src/import/generic/memory/lib/utils/find_magic.H b/src/import/generic/memory/lib/utils/find_magic.H
deleted file mode 100644
index a67d4f2e8..000000000
--- a/src/import/generic/memory/lib/utils/find_magic.H
+++ /dev/null
@@ -1,164 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/utils/find_magic.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
-/* [+] 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 */
-
-#ifndef _MSS_FIND_WITH_MAGIC_H
-#define _MSS_FIND_WITH_MAGIC_H
-
-#include <fapi2.H>
-#include <vector>
-#include <generic/memory/lib/utils/pos.H>
-#include <generic/memory/lib/utils/c_str.H>
-#include <generic/memory/lib/utils/find.H>
-
-namespace mss
-{
-
-///
-/// @brief find the union of functionl targets and any magic targets
-/// @note The PHY has a logic block which is only contained in the 0th PHY in the controller.
-/// This makes the 0th PHY 'magic' in that it needs to always be present if not functional.
-/// This function returns all functional targets and includes the magic target whether or not
-/// it is truly functional.
-/// @tparam M the target type to be returned
-/// @tparam T the fapi2 target type of the argument
-/// @param[in] i_target the fapi2 target T
-/// @return a vector of M targets.
-///
-template< fapi2::TargetType M, fapi2::TargetType T >
-inline std::vector< fapi2::Target<M> > find_targets_with_magic( const fapi2::Target<T>& i_target);
-
-///
-/// @brief find a set of magic elements based on a fapi2 target
-/// @note The PHY has a logic block which is only contained in the 0th PHY in the controller.
-/// This makes the 0th PHY 'magic' in that it needs to always be present if not functional.
-/// This function returns all magic targets whether or not it is truly functional.
-/// It does not include other functional or present targets.
-/// @tparam M the target type to be returned
-/// @tparam T the fapi2 target type of the argument
-/// @param[in] i_target the fapi2 target T
-/// @return a vector of M targets.
-///
-template< fapi2::TargetType M, fapi2::TargetType T >
-inline std::vector< fapi2::Target<M> > find_magic_targets( const fapi2::Target<T>& i_target);
-
-///
-/// @brief find the magic MCA connected to an MCBIST
-/// @param[in] i_target the fapi2::Target MCBIST
-/// @return a vector of fapi2::TARGET_TYPE_MCA
-///
-template<>
-inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> >
-find_magic_targets(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target)
-{
- // The magic port is in position 0, relative to the MCBIST
- constexpr uint64_t RELATIVE_MAGIC_POS = 0;
-
- // This is only one magic MCA on every MCBIST, so we only return a vector of one
- std::vector<fapi2::Target<fapi2::TARGET_TYPE_MCA>> l_magic_ports;
-
- // Get all the present MCA children and find the target with the relative position of 0
- for (const auto& p : i_target.getChildren<fapi2::TARGET_TYPE_MCA>(fapi2::TARGET_STATE_PRESENT))
- {
- if (mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(p) == RELATIVE_MAGIC_POS)
- {
- l_magic_ports.push_back(p);
- }
- }
-
- // We don't care if the vector is empty. We don't know what the caller will do with this
- // and they might not care if there is no magic port either ...
- return l_magic_ports;
-}
-
-///
-/// @brief find the union of functionl targets and any magic targets
-/// @param[in] i_target the fapi2::Target MCBIST
-/// @return a vector of i2::Target<fapi2::TARGET_TYPE_MCA>
-///
-template<>
-inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> >
-find_targets_with_magic( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target)
-{
- // We need the union of the functional target list and the magic target list. We can
- // get a little tricky with the MCA's - we know there's only one magic port.
- // So if the one magic port isn't in the list of functional ports, add it
- auto l_magic_ports = find_magic_targets<fapi2::TARGET_TYPE_MCA>(i_target);
-
- if (l_magic_ports.size() != 1)
- {
- FAPI_ERR("Found wrong number of magic ports on %s (%d)", mss::c_str(i_target), l_magic_ports.size());
- fapi2::Assert(false);
- }
-
- auto l_ports = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
- const auto l_magic_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(l_magic_ports[0]);
- const auto l_magic_port = std::find_if(l_ports.begin(), l_ports.end(),
- [&l_magic_pos](const fapi2::Target<fapi2::TARGET_TYPE_MCA>& t)
- {
- // Check ports by relative position.
- const auto l_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(t);
- FAPI_DBG("checking for magic port at %d candidate is %d", l_magic_pos, l_pos);
- return l_magic_pos == l_pos;
- });
-
- if (l_magic_port == l_ports.end())
- {
- // Add the magic port to the front of the port vector.
- FAPI_DBG("inserting magic port %d", l_magic_pos);
- l_ports.insert(l_ports.begin(), l_magic_ports[0]);
- }
-
- // In either case, l_ports is the proper thing to return. Either the magic port was in
- // l_ports or it is now because we inserted it.
- return l_ports;
-}
-
-///
-/// @brief Determine if a thing is functional
-/// @tparam I, the type of the item we want to check for
-/// @tparam P, the type of the parent which holds the things of interest
-/// @param[in] i_target the parent containing the thing we're looking for
-/// @param[in] i_rel_pos the relative position of the item of interest.
-/// @return bool true iff the thing at i_rel_pos is noted as functional
-///
-template< fapi2::TargetType I, fapi2::TargetType P >
-bool is_functional( const fapi2::Target<P>& i_target, const uint64_t i_rel_pos )
-{
- // Not sure of a good way to do this ... we get all the functional
- // children of the parent and look for our relative position ...
- for (const auto& i : i_target.template getChildren<I>(fapi2::TARGET_STATE_FUNCTIONAL))
- {
- if (mss::template relative_pos<P>(i) == i_rel_pos)
- {
- return true;
- }
- }
-
- return false;
-}
-
-}// mss
-
-#endif
diff --git a/src/import/generic/memory/lib/utils/fir/gen_mss_unmask.H b/src/import/generic/memory/lib/utils/fir/gen_mss_unmask.H
index fa14534e5..a45b48202 100644
--- a/src/import/generic/memory/lib/utils/fir/gen_mss_unmask.H
+++ b/src/import/generic/memory/lib/utils/fir/gen_mss_unmask.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -38,6 +38,8 @@
#include <fapi2.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
namespace mss
{
@@ -46,40 +48,63 @@ namespace unmask
///
/// @brief Unmask and setup actions performed after draminit_mc
+/// @tparam MC the memory controller type
/// @tparam T the fapi2::TargetType which hold the FIR bits
/// @param[in] i_target the fapi2::Target
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
-template< mss::mc_type MC, fapi2::TargetType T >
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
fapi2::ReturnCode after_draminit_mc( const fapi2::Target<T>& i_target );
///
/// @brief Unmask and setup actions performed after draminit_training
+/// @tparam MC the memory controller type
/// @tparam T the fapi2::TargetType which hold the FIR bits
/// @param[in] i_target the fapi2::Target
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
-template< mss::mc_type MC, fapi2::TargetType T >
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
fapi2::ReturnCode after_draminit_training( const fapi2::Target<T>& i_target );
///
/// @brief Unmask and setup actions performed after mss_scominit
+/// @tparam MC the memory controller type
/// @tparam T the fapi2::TargetType which hold the FIR bits
-/// @param[in] i_target the fapi2::Target of the MCBIST
+/// @param[in] i_target the fapi2::Target
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
-template< mss::mc_type MC, fapi2::TargetType T >
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
fapi2::ReturnCode after_scominit( const fapi2::Target<T>& i_target );
///
/// @brief Unmask and setup actions performed after mss_ddr_phy_reset
+/// @tparam MC the memory controller type
/// @tparam T the fapi2::TargetType which hold the FIR bits
-/// @param[in] i_target the fapi2::Target of the MCBIST
+/// @param[in] i_target the fapi2::Target
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
///
-template< mss::mc_type MC, fapi2::TargetType T >
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
fapi2::ReturnCode after_phy_reset( const fapi2::Target<T>& i_target );
+///
+/// @brief Unmask and setup actions for memdiags related FIR
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2::TargetType which hold the FIR bits
+/// @param[in] i_target the fapi2::Target
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+fapi2::ReturnCode after_memdiags( const fapi2::Target<T>& i_target );
+
+///
+/// @brief Unmask and setup actions for scrub related FIR
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2::TargetType which hold the FIR bits
+/// @param[in] i_target the fapi2::Target
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+fapi2::ReturnCode after_background_scrub( const fapi2::Target<T>& i_target );
}
}
diff --git a/src/import/generic/memory/lib/utils/freq/cas_latency.H b/src/import/generic/memory/lib/utils/freq/cas_latency.H
index 1b71481e2..0605189c2 100644
--- a/src/import/generic/memory/lib/utils/freq/cas_latency.H
+++ b/src/import/generic/memory/lib/utils/freq/cas_latency.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2019 */
+/* Contributors Listed Below - COPYRIGHT 2016,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -571,7 +571,7 @@ class cas_latency
l_temp);
o_value = l_temp;
- FAPI_INF( "%s. tAAmin (ps): %d",
+ FAPI_DBG( "%s. tAAmin (ps): %d",
mss::spd::c_str(l_target),
o_value);
@@ -628,7 +628,7 @@ class cas_latency
{
FAPI_TRY( spd::calc_nck(i_taa, i_tck, spd::INVERSE_DDR4_CORRECTION_FACTOR, o_cas_latency) );
- FAPI_INF("%s. tAA (ps): %d, tCK (ps): %d, CL (nck): %d",
+ FAPI_DBG("%s. tAA (ps): %d, tCK (ps): %d, CL (nck): %d",
mss::spd::c_str(iv_target),
i_taa,
i_tck,
@@ -651,8 +651,8 @@ class cas_latency
const uint64_t l_min_cl = get_min_cl(l_cl_mask);
const uint64_t l_max_cl = get_max_cl(l_cl_mask);
- FAPI_INF("%s. min CL %lu", mss::spd::c_str(iv_target), l_min_cl);
- FAPI_INF("%s. max CL %lu", mss::spd::c_str(iv_target), l_max_cl);
+ FAPI_DBG("%s. min CL %lu", mss::spd::c_str(iv_target), l_min_cl);
+ FAPI_DBG("%s. max CL %lu", mss::spd::c_str(iv_target), l_max_cl);
for(uint64_t l_cas_latency = l_min_cl; l_cas_latency <= l_max_cl; ++l_cas_latency)
{
@@ -688,7 +688,7 @@ class cas_latency
{
const bool l_found = std::binary_search(i_common_cls.begin(), i_common_cls.end(), i_cas_latency);
- FAPI_INF("Found CL: %d in common CL mask: 0x%llX ? %s for %s",
+ FAPI_DBG("Found CL: %d in common CL mask: 0x%llX ? %s for %s",
i_cas_latency, iv_common_cl_bitmap, l_found ? "yes" : "no", mss::spd::c_str(iv_target));
return l_found;
@@ -709,7 +709,7 @@ class cas_latency
const size_t l_taa_max = (iv_is_3ds == loading::NOT_3DS) ? TAA_MAX_DDR4 : TAA_MAX_DDR4_3DS;
const bool l_is_cl_exceeding_taa = l_cas_latency_time > l_taa_max;
- FAPI_INF("%s. CL (%d) * tCK (%d) = %d > %d ? %s",
+ FAPI_DBG("%s. CL (%d) * tCK (%d) = %d > %d ? %s",
mss::spd::c_str(iv_target),
i_cas_latency,
i_tck,
@@ -758,7 +758,7 @@ class cas_latency
FAPI_TRY( freq_to_ps(l_proposed_freq, io_tck),
"%s. Failed freq_to_ps()", mss::spd::c_str(iv_target) );
- FAPI_INF("%s Supported dimm speed override %d MT/s (Clock period %d in ps)",
+ FAPI_DBG("%s Supported dimm speed override %d MT/s (Clock period %d in ps)",
mss::spd::c_str(iv_target), l_proposed_freq, io_tck);
// Sanity check
diff --git a/src/import/generic/memory/lib/utils/freq/gen_mss_freq.H b/src/import/generic/memory/lib/utils/freq/gen_mss_freq.H
index 4df0eeb06..c681f2e59 100644
--- a/src/import/generic/memory/lib/utils/freq/gen_mss_freq.H
+++ b/src/import/generic/memory/lib/utils/freq/gen_mss_freq.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -105,7 +105,7 @@ fapi2::ReturnCode get_dimm_type(const fapi2::Target<T>& i_target,
/// @return FAPI2_RC_SUCCESS iff ok
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-fapi2::ReturnCode callout_bad_freq_calculated(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+fapi2::ReturnCode callout_bad_freq_calculated(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const uint64_t i_final_freq);
///
@@ -164,7 +164,7 @@ fapi2::ReturnCode is_vpd_config_supported( const fapi2::Target<TT::VPD_TARGET_TY
set_MAX(VPD_KW_MAX).
set_ACTUAL(io_vpd_info.iv_size).
set_KEYWORD(VPD_BLOB).
- set_MCS_TARGET(i_target),
+ set_VPD_TARGET(i_target),
"VPD MR keyword size retrieved: %d, is larger than max: %d for %s",
io_vpd_info.iv_size, TT::VPD_KEYWORD_MAX, mss::c_str(i_target));
}
@@ -208,7 +208,7 @@ fapi2::ReturnCode check_freq_support_vpd( const fapi2::Target<TT::PORT_TARGET_TY
/// @return FAPI2_RC_SUCCESS iff ok
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-inline fapi2::ReturnCode set_freq_attrs(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+inline fapi2::ReturnCode set_freq_attrs(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<uint64_t>& i_dimm_freq)
{
// Find the minimum (but non-0) freq in the vector. If we see all 0's we'll write a 0. However,
@@ -245,7 +245,7 @@ fapi_try_exit:
/// @return FAPI2_RC_SUCCESS iff okay
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-inline fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+inline fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
std::vector<uint32_t>& o_supported_freqs)
{
uint64_t l_largest_tck = 0;
@@ -255,7 +255,17 @@ inline fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TT::FREQ_TARGET_
// Get cached decoder
std::vector< mss::spd::facade > l_spd_facades;
- FAPI_TRY( get_spd_decoder_list(i_target, l_spd_facades), "%s get decoder - spd", mss::c_str(i_target) );
+
+ for (const auto& l_port : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target))
+ {
+ std::vector< mss::spd::facade > l_these_spd_facades;
+ FAPI_TRY( get_spd_decoder_list(l_port, l_these_spd_facades), "%s get decoder - spd", mss::c_str(l_port) );
+
+ for (const auto& l_spd_facade : l_these_spd_facades)
+ {
+ l_spd_facades.push_back(l_spd_facade);
+ }
+ }
// Looking for the biggest application period on an MC.
// This will further reduce supported frequencies the system can run on.
@@ -263,7 +273,7 @@ inline fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TT::FREQ_TARGET_
{
const auto l_dimm = l_cache.get_dimm_target();
const auto l_port = mss::find_target<TT::PORT_TARGET_TYPE>(l_dimm);
- const auto l_port_pos = mss::relative_pos<TT::FREQ_TARGET_TYPE>(l_port);
+ const auto l_port_pos = mss::relative_pos<TT::FREQ_DOMAIN_TARGET_TYPE>(l_port);
uint64_t l_tckmax_in_ps = 0;
uint64_t l_tck_min_in_ps = 0;
uint32_t l_dimm_freq = 0;
@@ -279,7 +289,7 @@ inline fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TT::FREQ_TARGET_
l_largest_tck = std::min(l_largest_tck, l_tckmax_in_ps);
FAPI_TRY( mss::ps_to_freq(l_largest_tck, l_dimm_freq), "%s ps to freq %lu", mss::c_str(i_target), l_largest_tck );
- FAPI_INF("Biggest freq supported from SPD %d MT/s for %s",
+ FAPI_DBG("Biggest freq supported from SPD %d MT/s for %s",
l_dimm_freq, mss::c_str(l_dimm));
o_supported_freqs[l_port_pos] = std::min(l_dimm_freq, o_supported_freqs[l_port_pos]);
@@ -299,12 +309,12 @@ fapi_try_exit:
///
// Pass in the syncronous target
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
std::vector<std::vector<uint32_t>>& o_vpd_supported_freqs)
{
// This bitmap will keep track of the ports we visit.
// Any we don't are not configured, so will support all frequencies in the scoreboard
- fapi2::buffer<uint8_t> configured_ports;
+ fapi2::buffer<uint64_t> configured_ports;
// Clearing output Just.In.Case
o_vpd_supported_freqs.clear();
@@ -317,7 +327,8 @@ fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<TT::FREQ_TARGET_TYPE>
// Just go to find target for the port level
for( const auto& p : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target) )
{
- const auto l_port_pos = mss::relative_pos<TT::FREQ_TARGET_TYPE>(p);
+ const auto l_port_pos = mss::relative_pos<TT::FREQ_DOMAIN_TARGET_TYPE>(p);
+
FAPI_TRY( configured_ports.setBit(l_port_pos) );
if( mss::count_dimm(p) == 0 )
@@ -342,7 +353,7 @@ fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<TT::FREQ_TARGET_TYPE>
// Add supported freqs to our output
if (l_supported)
{
- FAPI_INF("VPD supported freq added: %d for %s", freq, mss::c_str(p) );
+ FAPI_DBG("VPD supported freq added: %d for %s", freq, mss::c_str(p) );
o_vpd_supported_freqs[l_port_pos].push_back(freq);
}
}
@@ -381,7 +392,7 @@ fapi_try_exit:
/// @return FAPI2_RC_SUCCESS iff okay
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-inline fapi2::ReturnCode find_min_dimm_freq(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+inline fapi2::ReturnCode find_min_dimm_freq(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<uint32_t>& i_supported_freqs,
std::vector<uint64_t>& o_min_dimm_freq)
{
@@ -420,14 +431,14 @@ inline fapi2::ReturnCode find_min_dimm_freq(const fapi2::Target<TT::FREQ_TARGET_
// Find CAS latency using JEDEC algorithm
FAPI_TRY( l_cas_latency.find_cl(l_desired_cl, l_tCKmin), "%s failed to find a cas latency", mss::c_str(i_target) );
- FAPI_INF("%s. Result from CL algorithm, CL (nck): %d, tCK (ps): %d",
+ FAPI_DBG("%s. Result from CL algorithm, CL (nck): %d, tCK (ps): %d",
mss::c_str(l_port), l_desired_cl, l_tCKmin);
// Find dimm transfer speed from selected tCK
FAPI_TRY( mss::ps_to_freq(l_tCKmin, l_desired_freq),
"%s. Failed ps_to_freq()", mss::c_str(l_port) );
- FAPI_INF("DIMM speed %d from selected tCK (ps): %d for %s",
+ FAPI_DBG("DIMM speed %d from selected tCK (ps): %d for %s",
l_desired_freq,
l_tCKmin,
mss::c_str(l_port));
@@ -437,7 +448,7 @@ inline fapi2::ReturnCode find_min_dimm_freq(const fapi2::Target<TT::FREQ_TARGET_
}// end else
FAPI_TRY(set_CL_attr<P>(l_port, l_desired_cl), "%s. Failed set_CL_attr()", mss::c_str(l_port) );
- } // mca
+ } // port
fapi_try_exit:
return fapi2::current_err;
@@ -452,7 +463,7 @@ fapi_try_exit:
/// @return FAPI2_RC_SUCCESS iff okay
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-inline fapi2::ReturnCode supported_freqs(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+inline fapi2::ReturnCode supported_freqs(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
std::vector<uint32_t>& o_freqs)
{
o_freqs.clear();
@@ -462,15 +473,18 @@ inline fapi2::ReturnCode supported_freqs(const fapi2::Target<TT::FREQ_TARGET_TYP
std::vector<std::vector<uint32_t>> l_vpd_supported_freqs;
std::vector<uint32_t> l_spd_supported_freq;
std::vector<uint8_t> l_deconfigured = {0};
+ std::vector<fapi2::Target<TT::PORT_TARGET_TYPE>> l_deconfigured_targets;
// Retrieve system MRW, SPD, and VPD constraints
FAPI_TRY( max_allowed_dimm_freq<P>(l_max_mrw_freqs.data()), "%s max_allowed_dimm_freq", mss::c_str(i_target) );
+
FAPI_TRY( spd_supported_freq<P>(i_target, l_spd_supported_freq),
"%s spd supported freqs", mss::c_str(i_target) );
+
FAPI_TRY( vpd_supported_freqs<P>(i_target, l_vpd_supported_freqs),
"%s vpd supported freqs", mss::c_str(i_target) );
- // Limits the frequency by the Nimbus processor constraints (sync mode)
+ // Limits the frequency by the processor constraints (sync mode)
FAPI_TRY( limit_freq_by_processor<P>(i_target, l_scoreboard) );
// Limit frequency scoreboard according to MRW constraints
@@ -486,6 +500,7 @@ inline fapi2::ReturnCode supported_freqs(const fapi2::Target<TT::FREQ_TARGET_TYP
FAPI_TRY( l_scoreboard.template resolve<P>(i_target,
l_vpd_supported_freqs,
l_deconfigured,
+ l_deconfigured_targets,
o_freqs) );
FAPI_INF("%s supported freqs:", mss::c_str(i_target));
@@ -510,7 +525,7 @@ namespace check
/// @return FAPI2_RC_SUCCESS iff okay
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-fapi2::ReturnCode final_freq(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target);
+fapi2::ReturnCode final_freq(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target);
} // check nameespace
@@ -522,16 +537,16 @@ fapi2::ReturnCode final_freq(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target
/// @return FAPI2_RC_SUCCESS iff okay
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-fapi2::ReturnCode generate_freq(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target)
+fapi2::ReturnCode generate_freq(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target)
{
std::vector<uint64_t> l_min_dimm_freq;
std::vector<uint32_t> l_supported_freqs;
- // Get supported freqs for this MCBIST
+ // Get supported freqs for this domain
FAPI_TRY( mss::supported_freqs<P>(i_target, l_supported_freqs), "%s failed to get supported frequencies",
mss::c_str(i_target) );
- // Finds the minimum supported DIMM frequencies for this MCBIST
+ // Finds the minimum supported DIMM frequencies for this domain
FAPI_TRY(mss::find_min_dimm_freq<P>(i_target, l_supported_freqs, l_min_dimm_freq),
"%s. Failed find_min_dimm_freq()", mss::c_str(i_target) );
diff --git a/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H b/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H
index 3b2f7ded9..94bdcc980 100644
--- a/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H
+++ b/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -161,7 +161,6 @@ class freq_scoreboard
if ( l_scoreboard_freq > i_freq_limit )
{
- FAPI_INF("Removing freq %d on port %d since it's above the limit %d", l_scoreboard_freq, i_port_pos, i_freq_limit);
l_port_supported_freqs[l_index] = false;
}
}
@@ -229,7 +228,6 @@ class freq_scoreboard
if (l_it == i_freq_list.end())
{
- FAPI_INF("Removing freq %d on port %d since it's not supported", iv_freq_values[l_index], i_port_pos);
iv_supported_port_freqs[i_port_pos][l_index] = false;
}
}
@@ -308,13 +306,15 @@ class freq_scoreboard
/// @param[in] i_target MCBIST target
/// @param[in] i_vpd_supported_freqs vector of hardware supported freqs -- from VPD
/// @param[out] o_deconfigured vector of port positions that were deconfigured by this function
+ /// @param[out] o_deconfigured_targets vector of port targets that were deconfigured by this function
/// @param[out] o_freqs vector of frequencies supported by all ports
/// @return FAPI2_RC_SUCCESS if successful
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
- fapi2::ReturnCode resolve(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+ fapi2::ReturnCode resolve(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<std::vector<uint32_t>>& i_vpd_supported_freqs,
std::vector<uint8_t>& o_deconfigured,
+ std::vector<fapi2::Target<TT::PORT_TARGET_TYPE>>& o_deconfigured_targets,
std::vector<uint32_t>& o_freqs)
{
const auto l_ports = mss::find_targets<TT::PORT_TARGET_TYPE>(i_target);
@@ -358,10 +358,10 @@ class freq_scoreboard
FAPI_TRY(callout_no_common_freq<P>(i_target, l_common_ports > l_empty_port_count, l_port_count));
// Now find and deconfigure all ports that don't support our selected frequency
- FAPI_TRY(deconfigure_ports<P>(i_target, l_ports, l_best_freq_index, o_deconfigured));
+ FAPI_TRY(deconfigure_ports<P>(i_target, l_ports, l_best_freq_index, o_deconfigured, o_deconfigured_targets));
// Now find all the frequencies supported by the ports that are left over
- FAPI_TRY(this->template resolve<P>(i_target, i_vpd_supported_freqs, o_deconfigured, o_freqs));
+ FAPI_TRY(this->template resolve<P>(i_target, i_vpd_supported_freqs, o_deconfigured, o_deconfigured_targets, o_freqs));
#ifndef __HOSTBOOT_MODULE
@@ -417,7 +417,7 @@ class freq_scoreboard
/// @returh l_supported_vector return the fector of supported frequencies
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
- std::vector<uint64_t> count_supported_frequencies(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+ std::vector<uint64_t> count_supported_frequencies(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<fapi2::Target<TT::PORT_TARGET_TYPE>>& i_ports,
std::vector<uint32_t>& o_freqs)
{
@@ -434,7 +434,7 @@ class freq_scoreboard
{
if (l_supported[l_index])
{
- FAPI_INF("%s Frequency %d is supported by port%d", mss::c_str(i_target), TT::SUPPORTED_FREQS[l_index], l_pos);
+ FAPI_DBG("%s Frequency %d is supported by port%d", mss::c_str(i_target), TT::SUPPORTED_FREQS[l_index], l_pos);
++l_support_counts[l_index];
}
@@ -442,7 +442,7 @@ class freq_scoreboard
// Note that deconfigured ports will support all frequencies due to the way the scoreboard is built
if (l_support_counts[l_index] == iv_num_ports)
{
- FAPI_INF("%s Frequency %d is supported by all ports", mss::c_str(i_target), TT::SUPPORTED_FREQS[l_index]);
+ FAPI_DBG("%s Frequency %d is supported by all ports", mss::c_str(i_target), TT::SUPPORTED_FREQS[l_index]);
o_freqs.push_back(TT::SUPPORTED_FREQS[l_index]);
}
@@ -461,15 +461,18 @@ class freq_scoreboard
/// @param[in] i_ports vector of ports
/// @param[in] i_best_freq_index index corresponding to the best case frequency
/// @param[out] o_deconfigured vector of deconfigured port positions
+ /// @param[out] o_deconfigured_targets vector of deconfigured targets
/// @return FAPI2_RC_SUCCESS iff ok
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
- fapi2::ReturnCode deconfigure_ports(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+ fapi2::ReturnCode deconfigure_ports(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<fapi2::Target<TT::PORT_TARGET_TYPE>>& i_ports,
const uint64_t i_best_freq_index,
- std::vector<uint8_t>& o_deconfigured)
+ std::vector<uint8_t>& o_deconfigured,
+ std::vector<fapi2::Target<TT::PORT_TARGET_TYPE>>& o_deconfigured_targets)
{
o_deconfigured.clear();
+ o_deconfigured_targets.clear();
for ( size_t l_pos = 0; l_pos < iv_num_ports; ++l_pos )
{
@@ -478,7 +481,7 @@ class freq_scoreboard
i_ports.end(),
[l_pos]( const fapi2::Target<TT::PORT_TARGET_TYPE>& i_rhs) -> bool
{
- return (mss::relative_pos<TT::FREQ_TARGET_TYPE>(i_rhs) != l_pos);
+ return (mss::relative_pos<TT::FREQ_DOMAIN_TARGET_TYPE>(i_rhs) == l_pos);
});
// If we didn't find an port for a given position, there wasn't one configured there
@@ -489,7 +492,7 @@ class freq_scoreboard
// and call it out if it doesn't support the selected freq
const auto& p = *l_it_port;
- FAPI_INF("Checking if port %d (%s) supports common frequency", l_pos, mss::c_str(p));
+ FAPI_DBG("Checking if port %d (%s) supports common frequency", l_pos, mss::c_str(p));
if (!iv_supported_port_freqs[l_pos][i_best_freq_index])
{
@@ -497,6 +500,7 @@ class freq_scoreboard
auto& l_port_supported_freqs = iv_supported_port_freqs[l_pos];
o_deconfigured.push_back(l_pos);
+ o_deconfigured_targets.push_back(p);
FAPI_ASSERT_NOEXIT( false,
fapi2::MSS_PORT_DOES_NOT_SUPPORT_MAJORITY_FREQ()
.set_FREQ_TARGET(i_target)
@@ -526,7 +530,7 @@ class freq_scoreboard
/// @return FAPI2_RC_SUCCESS iff ok
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-fapi2::ReturnCode limit_freq_by_processor(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+fapi2::ReturnCode limit_freq_by_processor(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
freq_scoreboard& io_scoreboard);
///
@@ -541,7 +545,7 @@ fapi2::ReturnCode limit_freq_by_processor(const fapi2::Target<TT::FREQ_TARGET_TY
/// have a path for testing
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-inline fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+inline fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<uint32_t>& i_max_mrw_freqs,
freq_scoreboard& io_scoreboard)
{
@@ -563,18 +567,18 @@ inline fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<TT::FREQ_TARGET_T
fapi2::MSS_MAX_FREQ_ATTR_SIZE_CHANGED()
.set_ACTUAL_SIZE(i_max_mrw_freqs.size())
.set_SUPPOSED_SIZE(NUM_MAX_FREQS)
- .set_MCA_TARGET(i_target),
+ .set_PORT_TARGET(i_target),
"%s Incorrect number of max frequencies in attribute for (%d)",
mss::c_str(i_target),
i_max_mrw_freqs.size());
- FAPI_INF("attribute supported max allowed dimm freqs %d %d %d %d %d for %s",
+ FAPI_DBG("attribute supported max allowed dimm freqs %d %d %d %d %d for %s",
i_max_mrw_freqs[0], i_max_mrw_freqs[1], i_max_mrw_freqs[2], i_max_mrw_freqs[3], i_max_mrw_freqs[4],
mss::c_str(i_target));
for( const auto& p : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target) )
{
- const auto l_port_pos = mss::relative_pos<TT::FREQ_TARGET_TYPE>(p);
+ const auto l_port_pos = mss::relative_pos<TT::FREQ_DOMAIN_TARGET_TYPE>(p);
const auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(p);
const uint64_t l_dimms_on_port = l_dimms.size();
@@ -612,7 +616,7 @@ inline fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<TT::FREQ_TARGET_T
// If we have an LRDIMM, it's treated as a one rank DIMM from the memory controller's perspective
l_rank_index = l_dimm_type == TT::LRDIMM_TYPE ? 0 : l_num_master_ranks - 1;
l_index = l_indexes[l_dimms_on_port - 1][l_rank_index];
- FAPI_INF("%s is %s. rank_index%u index:%u", spd::c_str(d), l_dimm_type == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM",
+ FAPI_DBG("%s is %s. rank_index%u index:%u", spd::c_str(d), l_dimm_type == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM",
l_rank_index, l_index);
FAPI_ASSERT( (l_index < NUM_MAX_FREQS),
@@ -625,7 +629,7 @@ inline fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<TT::FREQ_TARGET_T
l_num_master_ranks,
mss::c_str(d));
- FAPI_INF("%s rank config %d drop %d yields max freq attribute index of %d (%d)",
+ FAPI_DBG("%s rank config %d drop %d yields max freq attribute index of %d (%d)",
mss::c_str(d), l_num_master_ranks, l_dimms_on_port,
l_indexes[l_dimms_on_port - 1][l_rank_index],
i_max_mrw_freqs[l_index] );
@@ -655,7 +659,7 @@ fapi_try_exit:
/// have a path for testing
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-fapi2::ReturnCode limit_freq_by_vpd(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+fapi2::ReturnCode limit_freq_by_vpd(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<std::vector<uint32_t>>& i_hw_freqs,
freq_scoreboard& io_scoreboard)
{
@@ -669,7 +673,7 @@ fapi2::ReturnCode limit_freq_by_vpd(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i
for( const auto& p : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target) )
{
- const auto l_port_pos = mss::relative_pos<TT::FREQ_TARGET_TYPE>(p);
+ const auto l_port_pos = mss::relative_pos<TT::FREQ_DOMAIN_TARGET_TYPE>(p);
const auto& l_port_freqs = i_hw_freqs[l_port_pos];
// This is the list of supported frequencies for VPD
@@ -709,13 +713,13 @@ fapi_try_exit:
/// have a path for testing
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
-fapi2::ReturnCode limit_freq_by_spd(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+fapi2::ReturnCode limit_freq_by_spd(const fapi2::Target<TT::FREQ_DOMAIN_TARGET_TYPE>& i_target,
const std::vector<uint32_t>& i_hw_freqs,
freq_scoreboard& io_scoreboard)
{
for( const auto& p : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target) )
{
- const auto l_port_pos = mss::relative_pos<TT::FREQ_TARGET_TYPE>(p);
+ const auto l_port_pos = mss::relative_pos<TT::FREQ_DOMAIN_TARGET_TYPE>(p);
// Remove any frequencies that aren't in this port's list from the scoreboard
io_scoreboard.remove_freqs_above_limit(l_port_pos, i_hw_freqs);
diff --git a/src/import/generic/memory/lib/utils/index.H b/src/import/generic/memory/lib/utils/index.H
index fde43f711..59b67c187 100644
--- a/src/import/generic/memory/lib/utils/index.H
+++ b/src/import/generic/memory/lib/utils/index.H
@@ -74,7 +74,24 @@ fapi_try_exit:
}
///
-/// @brief Return an attribute array index from a rank number
+/// @brief Sort the provided target vector in order of index (low to high)
+///
+/// @tparam T TargetType
+/// @param[in,out] io_targets vector of targets to sort
+///
+template <fapi2::TargetType T>
+inline void sort_targets_by_index(std::vector<fapi2::Target<T>>& io_targets)
+{
+ std::sort(io_targets.begin(), io_targets.end(), [] (
+ const fapi2::Target<T>& l_first_target,
+ const fapi2::Target<T>& l_second_target) -> bool
+ {
+ return mss::index(l_first_target) < mss::index(l_first_target);
+ });
+}
+
+///
+/// @brief Return a dimm rank / attribute array index from a port rank number
/// @param[in] i_rank uint64_t a rank number DIMM0 {0, 1, 2, 3} DIMM1 {0, 1, 2, 3}
/// @return size_t the attribute array index.
///
diff --git a/src/import/generic/memory/lib/utils/mc/gen_mss_port.H b/src/import/generic/memory/lib/utils/mc/gen_mss_port.H
index e44601ac2..6c4b4d4b1 100644
--- a/src/import/generic/memory/lib/utils/mc/gen_mss_port.H
+++ b/src/import/generic/memory/lib/utils/mc/gen_mss_port.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -38,26 +38,138 @@
#define _GEN_MSS_PORT_H_
#include <fapi2.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <generic/memory/lib/utils/mc/gen_mss_port_traits.H>
#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/ecc/ecc.H>
+#include <generic/memory/lib/utils/mss_bad_bits.H>
+#include <generic/memory/lib/utils/mss_rank.H>
namespace mss
{
///
+/// @brief Reads the farb0q register
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the target
+/// @param[out] o_data data read from the register
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note Disable Port Fail after recurring RCD errors.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode read_farb0q( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ FAPI_TRY( mss::getScom(i_target, TT::FARB0Q_REG, o_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Writes the farb0q register
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the target
+/// @param[in] i_data data read from the register
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note Disable Port Fail after recurring RCD errors.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode write_farb0q( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( mss::putScom(i_target, TT::FARB0Q_REG, i_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Reads the farb6q register
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the target
+/// @param[out] o_data data read from the register
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note Disable Port Fail after recurring RCD errors.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode read_farb6q( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ FAPI_TRY( mss::getScom(i_target, TT::FARB6Q_REG, o_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Writes the farb6q register
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the target
+/// @param[in] i_data data read from the register
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note Disable Port Fail after recurring RCD errors.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode write_farb6q( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( mss::putScom(i_target, TT::FARB6Q_REG, i_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Gets the bandwidth window data
+/// @tparam MC the memory controller type
+/// @tparam TT the class traits for the port
+/// @param[in] i_data data read from the register
+/// @param[out] o_bw_window
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note Disable Port Fail after recurring RCD errors.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = portTraits<MC> >
+void get_bw_window( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_bw_window )
+{
+ o_bw_window = 0;
+ i_data.extractToRight<TT::BW_WINDOW_SIZE, TT::BW_WINDOW_SIZE_LEN>(o_bw_window);
+}
+
+///
+/// @brief Gets the bandwidth snapshot
+/// @tparam MC the memory controller type
+/// @tparam TT the class traits for the port
+/// @param[in] i_data data read from the register
+/// @param[out] o_bw_snapshot
+/// @return FAPI2_RC_SUCCESS if and only if ok
+/// @note Disable Port Fail after recurring RCD errors.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = portTraits<MC> >
+void get_bw_snapshot( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_bw_snapshot )
+{
+ o_bw_snapshot = 0;
+ i_data.extractToRight<TT::BW_SNAPSHOT, TT::BW_SNAPSHOT_LEN>(o_bw_snapshot);
+}
+
+
+///
/// @brief ATTR_MSS_MVPD_FWMS getter declare
/// @tparam MC the memory controller type
/// @tparam T the fapi2 target type of the target
/// @param[in] const ref to the fapi2::Target<fapi2::TargetType>
/// @param[out] uint32_t* memory to store the value
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Mark store records from MPVD Lx
-/// keyword
+/// @note Mark store records from MPVD Lx keyword
///
template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T>
-inline fapi2::ReturnCode mvpd_fwms(const fapi2::Target< T>& i_target, uint32_t (&o_array)[MARK_STORE_COUNT]);
+fapi2::ReturnCode mvpd_fwms(const fapi2::Target< T>& i_target, uint32_t (&o_array)[MARK_STORE_COUNT]);
///
/// @brief Enable power management
@@ -111,9 +223,9 @@ fapi2::ReturnCode change_iml_complete( const fapi2::Target<T>& i_target, states
FAPI_DBG("Change the IML init complete bit to high for %s %s", (i_state == HIGH ? "high" : "low"),
mss::c_str(i_target));
- FAPI_TRY( mss::getScom(i_target, TT::FARB6Q_REG, l_data) );
+ FAPI_TRY( mss::getScom(i_target, TT::PMU8Q_REG, l_data) );
l_data.writeBit<TT::CFG_INIT_COMPLETE>(i_state);
- FAPI_TRY( mss::putScom(i_target, TT::FARB6Q_REG, l_data) );
+ FAPI_TRY( mss::putScom(i_target, TT::PMU8Q_REG, l_data) );
fapi_try_exit:
return fapi2::current_err;
@@ -293,6 +405,19 @@ fapi_try_exit:
///
+/// @brief Change the state of the force_str bit
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the target
+/// @param[in] i_state the state
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode change_force_str( const fapi2::Target<T>& i_target, const states i_state );
+
+
+///
/// @brief Change the state of the MC Refresh enable bit
/// @tparam MC the memory controller type
/// @tparam T the fapi2 target type of the target
@@ -339,6 +464,19 @@ fapi_try_exit:
}
///
+/// @brief Set up memory controller specific settings for ECC registers (at the end of draminit_mc)
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the target
+/// @param[in,out] io_data contents of RECR register
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode ecc_reg_settings_draminit_mc( const fapi2::Target<T>& i_target,
+ fapi2::buffer<uint64_t>& io_data );
+
+///
/// @brief Enable Read ECC checking
/// @tparam MC the memory controller type
/// @tparam T the fapi2 target type of the target
@@ -346,9 +484,11 @@ fapi_try_exit:
/// @param[in] i_target the target
/// @return FAPI2_RC_SUCCESS if and only if ok
///
-template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+template< mss::mc_type MC, fapi2::TargetType T, typename TT = portTraits<MC> >
fapi2::ReturnCode enable_read_ecc( const fapi2::Target<T>& i_target )
{
+ constexpr uint8_t RECR_MBSECCQ_DATA_INVERSION_NO_INVERSION = 0b00;
+ constexpr uint8_t RECR_MBSECCQ_DATA_INVERSION_INVERT_DATA_TOGGLE_CHECKS = 0b11;
fapi2::buffer<uint64_t> l_data;
uint8_t l_sim = 0;
@@ -362,13 +502,17 @@ fapi2::ReturnCode enable_read_ecc( const fapi2::Target<T>& i_target )
// VBU tests assume good ECC and we don't have good ECC (since we're not writing everything)
// so we can't run with address checking. Disable address checking in sim.
- l_data.writeBit<TT::ECC_USE_ADDR_HASH>(l_sim ? 0 : 1);
+ l_data.writeBit<TT::ECC_USE_ADDR_HASH>(l_sim ? mss::states::LOW : mss::states::HIGH);
- // The preferred operating mode is 11 (INVERT_DATA_TOGGLE_CHECKS) which stores data complemented
- // (because most bits are '0', and the dram bus pulls up, so transmitting 1s is least power) but
+ // The preferred operating mode is 11 (INVERT_DATA_TOGGLE_CHECKS) which stores data complemented
+ // (because most bits are '0', and the dram bus pulls up, so transmitting 1s is least power) but
// still flips the inversion of check bits to aid RAS. Per Brad Michael 12/15
// Leave un-inverted for sim. This allows the DIMM loader to write 0's and effect good ECC
- l_data.insertFromRight<TT::RECR_MBSECCQ_DATA_INVERSION, TT::RECR_MBSECCQ_DATA_INVERSION_LEN>(l_sim ? 0b00 : 0b11);
+ l_data.insertFromRight<TT::RECR_MBSECCQ_DATA_INVERSION, TT::RECR_MBSECCQ_DATA_INVERSION_LEN>(l_sim ?
+ RECR_MBSECCQ_DATA_INVERSION_NO_INVERSION :
+ RECR_MBSECCQ_DATA_INVERSION_INVERT_DATA_TOGGLE_CHECKS);
+
+ FAPI_TRY( ecc_reg_settings_draminit_mc<MC>(i_target, l_data) );
// bits: 60 MBSTRQ_CFG_MAINT_RCE_WITH_CE
// cfg_maint_rce_with_ce - not implemented. Need to investigate if needed for nimbus.
@@ -412,6 +556,800 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Configures the write reorder queue bit
+/// @tparam MC the memory controller type
+/// @tparam T, the mc
+/// @tparam TT, the class traits for the port
+/// @param[in] i_target the target to effect
+/// @param[in] i_state to set the bit too
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+inline fapi2::ReturnCode configure_wrq(const fapi2::Target<T>& i_target,
+ const mss::states i_state)
+{
+ // Loops through all port targets, hitting all the registers
+ for( const auto& l_port : mss::find_targets<TT::PORT_TYPE>(i_target) )
+ {
+ fapi2::buffer<uint64_t> l_data;
+
+ // Gets the reg
+ FAPI_TRY(mss::getScom(l_port, TT::WRQ_REG, l_data), "%s failed to getScom from WRQ0Q", mss::c_str(l_port));
+
+ // Sets the bit
+ l_data.writeBit<TT::WRQ_FIFO_MODE>(i_state == mss::states::ON);
+
+ // Sets the regs
+ FAPI_TRY(mss::putScom(l_port, TT::WRQ_REG, l_data), "%s failed to putScom to WRQ0Q", mss::c_str(l_port));
+ }
+
+ // In case we don't have any port's
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Configures the read reorder queue bit
+/// @tparam MC the memory controller type
+/// @tparam T, the mc
+/// @tparam TT, the class traits for the port
+/// @param[in] i_target the target to effect
+/// @param[in] i_state to set the bit too
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+inline fapi2::ReturnCode configure_rrq(const fapi2::Target<T>& i_target, const mss::states i_state)
+{
+ // Loops through all port targets, hitting all the registers
+ for( const auto& l_port : mss::find_targets<TT::PORT_TYPE>(i_target) )
+ {
+ fapi2::buffer<uint64_t> l_data;
+
+ // Gets the reg
+ FAPI_TRY(mss::getScom(l_port, TT::RRQ_REG, l_data), "%s failed to getScom from RRQ0Q", mss::c_str(l_port));
+
+ // Sets the bit
+ l_data.writeBit<TT::RRQ_FIFO_MODE>(i_state == mss::states::ON);
+
+ // Sets the regs
+ FAPI_TRY(mss::putScom(l_port, TT::RRQ_REG, l_data), "%s failed to putScom to RRQ0Q", mss::c_str(l_port));
+ }
+
+ // In case we don't have any port's
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Place a symbol mark in a Firmware Mark Store register
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the DIMM target
+/// @param[in] i_rank the rank
+/// @param[in] i_dq the bad DQ bit
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+inline fapi2::ReturnCode place_symbol_mark(const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq)
+{
+ const auto& l_port = mss::find_target<TT::PORT_TYPE>(i_target);
+ const auto l_dimm_idx = mss::index(i_target);
+ const auto l_rank_idx = mss::index(i_rank);
+
+ uint8_t l_galois = 0;
+ mss::mcbist::address l_addr;
+
+ // For symbol marks, we set the appropriate Firmware Mark Store reg, with the symbol's
+ // Galois code, mark_type=SYMBOL, mark_region=MRANK, and the address of the DIMM+MRANK
+ // TODO RTC:165133 Remove static_cast once Galois API is updated to accept uint64_t input
+ FAPI_TRY( mss::ecc::dq_to_galois(static_cast<uint8_t>(i_dq), l_galois) );
+
+ l_addr.set_dimm(l_dimm_idx).set_master_rank(l_rank_idx);
+
+ FAPI_INF("%s Setting firmware symbol mark on rank:%d dq:%d galois:0x%02x",
+ mss::c_str(i_target), i_rank, i_dq, l_galois);
+ FAPI_TRY( mss::ecc::set_fwms(l_port, i_rank, l_galois,
+ mss::ecc::fwms::mark_type::SYMBOL,
+ mss::ecc::fwms::mark_region::MRANK,
+ l_addr) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Place a chip mark in a Hardware Mark Store register
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT the class traits for the port
+/// @param[in] i_target the DIMM target
+/// @param[in] i_rank the rank
+/// @param[in] i_dq one of the bad DQ bits in the bad nibble
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+inline fapi2::ReturnCode place_chip_mark(const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq)
+{
+ const auto& l_port = mss::find_target<TT::PORT_TYPE>(i_target);
+
+ uint8_t l_galois = 0;
+ uint8_t l_symbol = 0;
+
+ // For chip marks, we set the appropriate Hardware Mark Store reg, with the Galois code
+ // of the first (smallest) symbol in the bad nibble, and both confirmed and exit1 bits set
+ FAPI_TRY( mss::ecc::dq_to_symbol(static_cast<uint8_t>(i_dq), l_symbol) );
+
+ // Round down to the nearest "nibble" to get the correct symbol, then get the Galois code for it
+ l_symbol = (l_symbol / BITS_PER_NIBBLE) * BITS_PER_NIBBLE;
+ FAPI_TRY( mss::ecc::symbol_to_galois(l_symbol, l_galois) );
+
+ FAPI_INF("%s Setting hardware (chip) mark on rank:%d galois:0x%02x", mss::c_str(i_target), i_rank, l_galois);
+ FAPI_TRY( mss::ecc::set_hwms(l_port, i_rank, l_galois) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+// Forward declaration for use in repair_state classes
+template< fapi2::TargetType T >
+class repair_state_machine;
+
+///
+/// @class mss::repair_state
+/// @brief A class for keeping track of bad bit repair states in a repair_state_machine
+/// @tparam T, the fapi2 target type of the DIMM
+/// @note this is a base class
+///
+template< fapi2::TargetType T >
+class repair_state
+{
+ public:
+ /// @brief default contructor
+ repair_state() = default;
+ /// @brief default destructor
+ virtual ~repair_state() = default;
+
+ ///
+ /// @brief Perform a repair for a single bad DQ bit in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq the DQ bit index
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ virtual fapi2::ReturnCode one_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded) = 0;
+
+ ///
+ /// @brief Perform a repair for multiple bad DQ bits in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq one of the bad DQ bit indexes
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ virtual fapi2::ReturnCode multiple_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded) = 0;
+
+ protected:
+ ///
+ /// @brief Set a new state in the repair state machine
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_state pointer to the new state to set
+ ///
+ inline void set_state(repair_state_machine<T>& io_machine, std::shared_ptr<repair_state<T>> i_state)
+ {
+ io_machine.update_state(i_state);
+ }
+};
+
+///
+/// @class mss::chip_and_symbol_mark
+/// @brief repair_state class for when both a chip mark and a symbol mark have been used
+/// @tparam T, the fapi2 target type of the DIMM
+///
+template< fapi2::TargetType T >
+class chip_and_symbol_mark : public repair_state<T>
+{
+ public:
+ /// @brief default contructor
+ chip_and_symbol_mark() = default;
+ /// @brief default destructor
+ ~chip_and_symbol_mark() = default;
+
+ ///
+ /// @brief Perform a repair for a single bad DQ bit in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq the DQ bit index
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode one_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // repairs exceeded
+ FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) );
+ FAPI_INF("%s Repairs exceeded (chip mark and symbol mark exist, plus one bad DQ) on rank:%d DQ:%d",
+ mss::c_str(i_target), i_rank, i_dq);
+ return fapi2::FAPI2_RC_SUCCESS;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Perform a repair for multiple bad DQ bits in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq one of the bad DQ bit indexes
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode multiple_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // repairs exceeded
+ FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) );
+ FAPI_INF("%s Repairs exceeded (chip mark and symbol mark exist, plus one bad nibble) on rank:%d DQ:%d",
+ mss::c_str(i_target), i_rank, i_dq);
+ return fapi2::FAPI2_RC_SUCCESS;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @class mss::symbol_mark_plus_unrepaired_dq
+/// @brief repair_state class for when only a symbol mark has been used, and one DQ bit remains unrepaired
+/// @tparam T, the fapi2 target type of the DIMM
+///
+template< fapi2::TargetType T >
+class symbol_mark_plus_unrepaired_dq : public repair_state<T>
+{
+ public:
+ /// @brief default contructor
+ symbol_mark_plus_unrepaired_dq() = default;
+ /// @brief default destructor
+ ~symbol_mark_plus_unrepaired_dq() = default;
+
+ ///
+ /// @brief Perform a repair for a single bad DQ bit in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq the DQ bit index
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode one_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // repairs exceeded
+ FAPI_INF("%s Repairs exceeded (symbol mark and unrepaired DQ exist, plus bad DQ) on rank:%d DQ:%d",
+ mss::c_str(i_target), i_rank, i_dq);
+ FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) );
+ return fapi2::FAPI2_RC_SUCCESS;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Perform a repair for multiple bad DQ bits in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq one of the bad DQ bit indexes
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode multiple_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // place a chip mark, but also repairs exceeded
+ FAPI_TRY( place_chip_mark(i_target, i_rank, i_dq) );
+ FAPI_TRY( io_repairs_applied.setBit(i_rank) );
+ FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) );
+ FAPI_INF("%s Repairs exceeded (symbol mark and unrepaired DQ exist, plus bad nibble) on rank:%d DQ:%d",
+ mss::c_str(i_target), i_rank, i_dq);
+ {
+ const auto new_state = std::make_shared<chip_and_symbol_mark<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::set_state(io_machine, new_state);
+ }
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+};
+
+///
+/// @class mss::symbol_mark_only
+/// @brief repair_state class for when only a symbol mark has been used
+/// @tparam T, the fapi2 target type of the DIMM
+///
+template< fapi2::TargetType T >
+class symbol_mark_only : public repair_state<T>
+{
+ public:
+ /// @brief default contructor
+ symbol_mark_only() = default;
+ /// @brief default destructor
+ ~symbol_mark_only() = default;
+
+ ///
+ /// @brief Perform a repair for a single bad DQ bit in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq the DQ bit index
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode one_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // leave an unrepaired DQ
+ const auto new_state = std::make_shared< symbol_mark_plus_unrepaired_dq<T> >();
+ mss::repair_state<T>::set_state(io_machine, new_state);
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Perform a repair for multiple bad DQ bits in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq one of the bad DQ bit indexes
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode multiple_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // place a chip mark
+ FAPI_TRY( place_chip_mark(i_target, i_rank, i_dq) );
+ FAPI_TRY( io_repairs_applied.setBit(i_rank) );
+ {
+ const auto new_state = std::make_shared< chip_and_symbol_mark<T> >();
+ mss::repair_state<T>::set_state(io_machine, new_state);
+ }
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @class mss::chip_mark_only
+/// @brief repair_state class for when only a chip mark has been used
+/// @tparam T, the fapi2 target type of the DIMM
+///
+template< fapi2::TargetType T >
+class chip_mark_only : public repair_state<T>
+{
+ public:
+ /// @brief default contructor
+ chip_mark_only() = default;
+ /// @brief default destructor
+ ~chip_mark_only() = default;
+
+ ///
+ /// @brief Perform a repair for a single bad DQ bit in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq the DQ bit index
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode one_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // place a symbol mark
+ FAPI_TRY( place_symbol_mark(i_target, i_rank, i_dq) );
+ FAPI_TRY( io_repairs_applied.setBit(i_rank) );
+ {
+ const auto new_state = std::make_shared<chip_and_symbol_mark<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::set_state(io_machine, new_state);
+ }
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Perform a repair for multiple bad DQ bits in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq one of the bad DQ bit indexes
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode multiple_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // repairs exceeded
+ FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) );
+ FAPI_INF("%s Repairs exceeded (chip mark exists, plus bad nibble) on rank:%d DQ:%d",
+ mss::c_str(i_target), i_rank, i_dq);
+ return fapi2::FAPI2_RC_SUCCESS;
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @class mss::no_fails
+/// @brief repair_state class for no fails (no marks applied)
+/// @tparam T, the fapi2 target type of the DIMM
+///
+template< fapi2::TargetType T >
+class no_fails : public repair_state<T>
+{
+ public:
+ /// @brief default contructor
+ no_fails() = default;
+ /// @brief default destructor
+ ~no_fails() = default;
+
+ ///
+ /// @brief Perform a repair for a single bad DQ bit in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq the DQ bit index
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode one_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // place a symbol mark
+ FAPI_TRY( place_symbol_mark(i_target, i_rank, i_dq) );
+ FAPI_TRY( io_repairs_applied.setBit(i_rank) );
+ {
+ const auto new_state = std::make_shared<symbol_mark_only<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::set_state(io_machine, new_state);
+ }
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Perform a repair for multiple bad DQ bits in a nibble
+ /// @param[in,out] io_machine the repair state machine
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq one of the bad DQ bit indexes
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode multiple_bad_dq(repair_state_machine<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // place a chip mark
+ FAPI_TRY( place_chip_mark(i_target, i_rank, i_dq) );
+ FAPI_TRY( io_repairs_applied.setBit(i_rank) );
+ {
+ const auto new_state = std::make_shared<chip_mark_only<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::set_state(io_machine, new_state);
+ }
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @class mss::repair_state_machine
+/// @brief state machine class used in restore_repairs_helper
+/// @tparam T, the fapi2 target type of the DIMM
+///
+template< fapi2::TargetType T >
+class repair_state_machine
+{
+ public:
+ /// @brief constructor
+ repair_state_machine()
+ : iv_repair_state(std::make_shared<no_fails<T>>()) {}
+
+ /// @brief default destructor
+ ~repair_state_machine() = default;
+
+ ///
+ /// @brief Perform a repair for a single bad DQ bit in a nibble
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq the DQ bit index
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repai:rs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode one_bad_dq(const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ FAPI_TRY( iv_repair_state->one_bad_dq(*this, i_target, i_rank, i_dq, io_repairs_applied, io_repairs_exceeded) );
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Perform a repair for multiple bad DQ bits in a nibble
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_rank the rank
+ /// @param[in] i_dq one of the bad DQ bit indexes
+ /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+ /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+ /// @return FAPI2_RC_SUCCESS if and only if ok
+ ///
+ fapi2::ReturnCode multiple_bad_dq(const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ FAPI_TRY( iv_repair_state->multiple_bad_dq(*this, i_target, i_rank, i_dq, io_repairs_applied, io_repairs_exceeded) );
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Update the state of the state machine
+ /// @param[in] i_state shared pointer to the new state
+ ///
+ void update_state(std::shared_ptr<repair_state<T>> i_state)
+ {
+ iv_repair_state = i_state;
+ }
+
+ private:
+ std::shared_ptr<repair_state<T>> iv_repair_state;
+};
+
+/// @brief Get the attributes for the reorder queue setting
+/// @tparam MC the memory controller type
+/// @tparam T, the fapi2 target type of the target
+/// @param[in] const ref to the mc target
+/// @param[out] uint8_t& reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Contains the settings for write/read reorder queue
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+fapi2::ReturnCode reorder_queue_setting(const fapi2::Target<T>& i_target, uint8_t& o_value);
+
+///
+/// @brief Resets the write/read reorder queue values - needs to be called after MCBIST execution
+/// @tparam MC the memory controller type
+/// @tparam T, the mc
+/// @tparam TT, the class traits for the port
+/// @param[in] i_target the target to effect
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits<MC> >
+inline fapi2::ReturnCode reset_reorder_queue_settings(const fapi2::Target<T>& i_target)
+{
+ uint8_t l_reorder_queue = 0;
+ FAPI_TRY(reorder_queue_setting<MC>(i_target, l_reorder_queue));
+
+ // Changes the reorder queue settings
+ {
+ // Two settings are FIFO and REORDER. FIFO is a 1 in the registers, while reorder is a 0 state
+ const mss::states l_state = ((l_reorder_queue == fapi2::ENUM_ATTR_MEM_REORDER_QUEUE_SETTING_FIFO) ?
+ mss::states::ON : mss::states::OFF);
+ FAPI_TRY(configure_rrq(i_target, l_state), "%s failed to reset read reorder queue settings", mss::c_str(i_target));
+ FAPI_TRY(configure_wrq(i_target, l_state), "%s failed to reset read reorder queue settings", mss::c_str(i_target));
+ }
+
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Convert a bitmap from the BAD_DQ_BITMAP attribute to a vector of bad DQ indexes
+/// @param[in] i_bad_bits an 8-bit bitmap of bad bits
+/// @param[in] i_nibble which nibble of the bitmap to convert
+/// @return std::vector of DQ bits marked as bad in the bitmap
+///
+inline std::vector<uint64_t> bad_bit_helper(const uint8_t i_bad_bits, const size_t i_nibble)
+{
+ std::vector<uint64_t> l_output;
+ fapi2::buffer<uint8_t> l_bit_buffer(i_bad_bits);
+
+ const size_t l_start = (i_nibble == 0) ? 0 : mss::conversions::BITS_PER_NIBBLE;
+
+ for (size_t l_offset = 0; l_offset < mss::conversions::BITS_PER_NIBBLE; ++l_offset)
+ {
+ const size_t l_position_tmp = l_start + l_offset;
+
+ if (l_bit_buffer.getBit(l_position_tmp))
+ {
+ l_output.push_back(l_position_tmp);
+ }
+ }
+
+ return l_output;
+}
+
+// TODO: RTC: 157753 tparam R can be pulled from an PORT trait once we have it
+//
+/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute, helper function for unit testing
+/// @tparam MC the memory controller type
+/// @tparam T, the fapi2 target type of the DIMM (derived)
+/// @tparam R the maximum rank per DIMM
+/// @tparam B the number of bytes per rank in the bad_dq_bitmap attribute
+/// @param[in] i_target A target representing a DIMM
+/// @param[in] i_bad_bits the bad bits values from the VPD, for the specified DIMM
+/// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied
+/// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, uint64_t R, uint64_t B >
+inline fapi2::ReturnCode restore_repairs_helper( const fapi2::Target<T>& i_target,
+ const uint8_t i_bad_bits[R][B],
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+{
+ FAPI_INF("%s Restore repair marks from bad DQ data", mss::c_str(i_target));
+
+ using MCT = mss::mcbistMCTraits<MC>;
+ using MT = mss::mcbistTraits<MC, MCT::MC_TARGET_TYPE>;
+
+ std::vector<uint64_t> l_ranks;
+ const auto l_dimm_idx = index(i_target);
+
+ // gets all of the ranks to loop over
+ FAPI_TRY( mss::rank::ranks_on_dimm_helper<MC>(i_target, l_ranks) );
+
+ // loop through ranks
+ for (const auto l_rank : l_ranks)
+ {
+ const auto l_rank_idx = index(l_rank);
+
+ repair_state_machine<fapi2::TARGET_TYPE_DIMM> l_machine;
+
+ for (uint64_t l_byte = 0; l_byte < (MT::MAX_DQ_NIBBLES / mss::conversions::NIBBLES_PER_BYTE); ++l_byte)
+ {
+ for (size_t l_nibble = 0; l_nibble < mss::conversions::NIBBLES_PER_BYTE; ++l_nibble)
+ {
+ const auto l_bad_dq_vector = bad_bit_helper(i_bad_bits[l_rank_idx][l_byte], l_nibble);
+ FAPI_DBG("Total bad bits on DIMM:%d rank:%d nibble%d: %d",
+ l_dimm_idx, l_rank, (l_byte * NIBBLES_PER_BYTE) + l_nibble, l_bad_dq_vector.size());
+
+ // apply repairs and update repair machine state
+ // if there are no bad bits (l_bad_dq_vector.size() == 0) no action is necessary
+ if (l_bad_dq_vector.size() == 1)
+ {
+ // l_bad_dq_vector is per byte, so multiply up to get the bad dq's index
+ const uint64_t l_dq = l_bad_dq_vector[0] + (l_byte * BITS_PER_BYTE);
+ FAPI_TRY( l_machine.one_bad_dq(i_target, l_rank, l_dq, io_repairs_applied, io_repairs_exceeded) );
+ }
+ else if (l_bad_dq_vector.size() > 1)
+ {
+ // l_bad_dq_vector is per byte, so multiply up to get the bad dq's index
+ const uint64_t l_dq = l_bad_dq_vector[0] + (l_byte * BITS_PER_BYTE);
+ FAPI_TRY( l_machine.multiple_bad_dq(i_target, l_rank, l_dq, io_repairs_applied, io_repairs_exceeded) );
+ }
+
+ // if repairs have been exceeded, we're done
+ if (io_repairs_exceeded.getBit(l_dimm_idx))
+ {
+ FAPI_INF("Repairs exceeded on DIMM %s", c_str(i_target));
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+ } // end loop through nibbles
+ } // end loop through bytes
+ } // end loop through ranks
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute
+/// @tparam MC, the memory controller type
+/// @tparam T, the fapi2 target type of the port (derived)
+/// @param[in] i_target A target representing a port
+/// @param[in,out] io_repairs_applied bit mask, where a bit set means a rank had repairs applied (bit0 = rank0, etc)
+/// @param[in,out] io_repairs_exceeded bit mask, where a bit set means a DIMM had more bad bits than could be repaired (bit0 = DIMM0 etc)
+/// @return FAPI2_RC_SUCCESS if and only if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+inline fapi2::ReturnCode restore_repairs( const fapi2::Target<T>& i_target,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+{
+ uint8_t l_bad_bits[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] = {};
+
+ io_repairs_applied = 0;
+ io_repairs_exceeded = 0;
+
+ for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
+ {
+ FAPI_TRY( mss::get_bad_dq_bitmap<MC>(l_dimm, l_bad_bits) );
+
+ FAPI_TRY( (restore_repairs_helper<MC, fapi2::TARGET_TYPE_DIMM, BAD_BITS_RANKS, BAD_DQ_BYTE_COUNT>(
+ l_dimm, l_bad_bits, io_repairs_applied, io_repairs_exceeded)) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
}// ns mss
#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_address.H b/src/import/generic/memory/lib/utils/mcbist/gen_address.H
deleted file mode 100644
index 45c4a4767..000000000
--- a/src/import/generic/memory/lib/utils/mcbist/gen_address.H
+++ /dev/null
@@ -1,24 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_address.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
-/* [+] 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 */
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H
index 0c5543750..667be0598 100644
--- a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
+/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,3 +22,3830 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file gen_mss_mcbist.H
+/// @brief Run and manage the MCBIST engine
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_MCBIST_H_
+#define _GEN_MSS_MCBIST_H_
+
+#include <fapi2.H>
+
+#include <generic/memory/lib/utils/poll.H>
+#include <generic/memory/lib/utils/memory_size.H>
+#include <generic/memory/lib/utils/mc/gen_mss_port.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H>
+#include <generic/memory/lib/utils/conversions.H>
+#include <generic/memory/lib/utils/num.H>
+
+namespace mss
+{
+
+///
+/// @brief Gets the attribute for freq
+/// @tparam MC the memory controller type
+/// @tparam T the fapi2 target type of the target
+/// @param[in] const ref to the target
+/// @param[out] uint64_t& reference to store the value
+/// @note Generated by gen_accessors.pl generate_mc_port_params
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Frequency of this memory channel in MT/s (Mega Transfers per second)
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T>
+fapi2::ReturnCode freq(const fapi2::Target<T>& i_target, uint64_t& o_value);
+
+///
+/// @brief Return the estimated time an MCBIST subtest will take to complete
+/// Useful for initial polling delays, probably isn't accurate for much else
+/// as it doesn't take refresh in to account (which will necessarily slow down
+/// the program.)
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType
+/// @param[in] i_target the target from which to gather memory frequency
+/// @param[in] i_bytes number of *bytes* in the address range
+/// @param[in] i_64B_per mss::YES if the command is 64B, mss::NO if it's 128B. Defaults to mss::YES
+/// @return the initial polling delay for this program in ns
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+inline uint64_t calculate_initial_delay(const fapi2::Target<T>& i_target,
+ const uint64_t i_bytes,
+ const bool i_64B_per = mss::YES)
+{
+ // TODO RTC: 164104 Update MCBIST delay calculator. As we learn more about what
+ // the lab really needs, we can probably make this function better.
+ const uint64_t l_bytes_per_cmd = (i_64B_per == mss::YES) ? 64 : 128;
+
+ // Best case is a command takes 4 cycles. Given the number of commands and address space size
+ // we can get some idea of how long to wait before we start polling.
+ return cycles_to_ns(i_target, (i_bytes / l_bytes_per_cmd) * mss::CYCLES_PER_CMD);
+}
+
+
+///
+/// @brief Reads the contents of the MCBISTFIRMASK
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to mcbistTraits<MC, T>
+/// @param[in] i_target the target on which to operate
+/// @param[out] o_data the register data
+/// @return fapi2::fapi2_rc_success if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode read_mcbfirmask( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ o_data = 0;
+
+ FAPI_TRY( fapi2::getScom(i_target, TT::MCBFIRMASK_REG, o_data ), "%s failed to read MCBISTFIRMASK regiser",
+ mss::c_str(i_target));
+ FAPI_DBG("%s MCBISTFIRMASK has data 0x%016lx", mss::c_str(i_target), o_data);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Writes the contents of the MCBISTFIRMASK
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to mcbistTraits<MC, T>
+/// @param[in] i_target the target on which to operate
+/// @param[in] i_data the register data
+/// @return fapi2::fapi2_rc_success if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode write_mcbfirmask( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCBFIRMASK_REG, i_data ), "%s failed to write MCBISTFIRMASK regiser",
+ mss::c_str(i_target));
+ FAPI_DBG("%s MCBISTFIRMASK has data 0x%016lx", mss::c_str(i_target), i_data);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Reads the contents of the MCBISTFIRQ
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to mcbistTraits<MC, T>
+/// @param[in] i_target the target on which to operate
+/// @param[out] o_data the register data
+/// @return fapi2::fapi2_rc_success if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode read_mcbfirq( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ o_data = 0;
+
+ FAPI_TRY( fapi2::getScom(i_target, TT::MCBFIRQ_REG, o_data ), "%s failed to read MCBISTFIRQ regiser",
+ mss::c_str(i_target));
+ FAPI_DBG("%s MCBISTFIRQ has data 0x%016lx", mss::c_str(i_target), o_data);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Writes the contents of the MCBISTFIRQ
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to mcbistTraits<MC, T>
+/// @param[in] i_target the target on which to operate
+/// @param[in] i_data the register data
+/// @return fapi2::fapi2_rc_success if ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode write_mcbfirq( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCBFIRQ_REG, i_data ), "%s failed to write MCBISTFIRQ regiser",
+ mss::c_str(i_target));
+ FAPI_DBG("%s MCBISTFIRQ has data 0x%016lx", mss::c_str(i_target), i_data);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Sets the mask for program complete
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCBIST
+/// @tparam TT traits type defaults to mcbistTraits<MC, T>
+/// @param[in,out] io_data the value of the register
+/// @param[in] i_state the state to write into the enable
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = fapi2::TARGET_TYPE_MCBIST, typename TT = mcbistTraits<MC, T> >
+inline void set_mcbist_program_complete_mask( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::MCB_PROGRAM_COMPLETE_MASK>(i_state == mss::states::ON);
+ FAPI_DBG("set_mcbist_program_complete_mask to %d 0x%016lx", i_state, io_data);
+}
+
+///
+/// @brief Sets the mask for WAT debug ATTN
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCBIST
+/// @tparam TT traits type defaults to mcbistTraits<MC, T>
+/// @param[in,out] io_data the value of the register
+/// @param[in] i_state the state to write into the enable
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = fapi2::TARGET_TYPE_MCBIST, typename TT = mcbistTraits<MC, T> >
+inline void set_mcbist_wat_debug_attn_mask( fapi2::buffer<uint64_t>& io_data, const mss::states i_state )
+{
+ io_data.writeBit<TT::MCB_WAT_DEBUG_ATTN_MASK>(i_state == mss::states::ON);
+ FAPI_DBG("set_mcbist_wat_debug_attn_mask to %d 0x%016lx", i_state, io_data);
+}
+
+///
+/// @brief Clears the program complete and WAT debug ATTN
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCBIST
+/// @tparam TT traits type defaults to mcbistTraits<MC, T>
+/// @param[in,out] io_data the value of the register
+/// @param[in] i_state the state to write into the enable
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = fapi2::TARGET_TYPE_MCBIST, typename TT = mcbistTraits<MC, T> >
+inline void clear_mcbist_program_complete( fapi2::buffer<uint64_t>& io_data )
+{
+ io_data.writeBit<TT::MCB_PROGRAM_COMPLETE>(mss::states::OFF);
+ io_data.writeBit<TT::MCB_WAT_DEBUG_ATTN>(mss::states::OFF);
+ FAPI_DBG("clear_mcbist_program_complete to %d 0x%016lx", mss::states::OFF, io_data);
+}
+
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = fapi2::TARGET_TYPE_MCBIST, typename TT = mcbistTraits<MC, T> >
+inline void get_mcbist_program_complete_mask( const fapi2::buffer<uint64_t> i_data, mss::states& o_state )
+{
+ o_state = i_data.getBit<TT::MCB_PROGRAM_COMPLETE>() ? mss::states::HIGH : mss::states::LOW;
+ FAPI_DBG("get_mcbist_program_complete_mask %d", o_state);
+}
+
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = fapi2::TARGET_TYPE_MCBIST, typename TT = mcbistTraits<MC, T> >
+inline void get_mcbist_wat_debug_attn_mask( const fapi2::buffer<uint64_t> i_data, mss::states& o_state )
+{
+ o_state = i_data.getBit<TT::MCB_WAT_DEBUG_ATTN>() ? mss::states::HIGH : mss::states::LOW;
+ FAPI_DBG("mcbist_wat_debug_attn_mask %d", o_state);
+}
+
+
+namespace mcbist
+{
+
+///
+/// @class subtest_t
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType
+/// @tparam TT the mcbistTraits associated with T
+/// @brief encapsulation of an MCBIST subtest.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+class subtest_t
+{
+ public:
+
+ ///
+ /// @brief Constructor
+ ///
+ subtest_t( const uint16_t i_data = 0 ):
+ iv_mcbmr(i_data)
+ {}
+
+ ///
+ /// @brief Checks if the op type requires FIFO mode to be on
+ /// @return bool fifo_mode_requried - true if FIFO mode is required to be forced on
+ ///
+ inline bool fifo_mode_required() const
+ {
+ // Gets the op type for this subtest
+ uint64_t l_value_to_find = 0;
+ iv_mcbmr.extractToRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(l_value_to_find);
+
+ // Finds if this op type is in the vector that stores the OP types that require FIFO mode to be run
+ const auto l_op_type_it = std::find(TT::FIFO_MODE_REQUIRED_OP_TYPES.begin(), TT::FIFO_MODE_REQUIRED_OP_TYPES.end(),
+ l_value_to_find);
+
+ // If the op type is required (aka was found), it will be less than end
+ // std::find returns the ending iterator if it was not found, so this will return false in that case
+ return l_op_type_it != TT::FIFO_MODE_REQUIRED_OP_TYPES.end();
+ }
+
+ ///
+ /// @brief Convert to a 16 bit int
+ /// @return the subtest as a 16 bit integer, useful for testing
+ ///
+ inline operator uint16_t()
+ {
+ return uint16_t(iv_mcbmr);
+ }
+
+ ///
+ /// @brief Complement the data for the first subcommand
+ /// @param[in] i_state the desired state (mss::ON or mss::OFF)
+ ///
+ inline void change_compliment_1st_cmd( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_1ST_CMD>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Complement the data for the second subcommand
+ /// @param[in] i_state the desired state (mss::ON or mss::OFF)
+ /// @return void
+ ///
+ inline void change_compliment_2nd_cmd( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_2ND_CMD>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Complement the data for the third subcommand
+ /// @param[in] i_state the desired state (mss::ON or mss::OFF)
+ /// @return void
+ ///
+ inline void change_compliment_3rd_cmd( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_3RD_CMD>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Enable a specific port for this test - maint address mode
+ /// @param[in] i_port the port desired to be enabled - int 0, 1, 2, 3
+ /// @note The port number is relative to the MCBIST
+ /// @return void
+ ///
+ inline void enable_port( const uint64_t i_port )
+ {
+ if (TT::MULTI_PORTS == mss::states::YES)
+ {
+ constexpr uint64_t l_len = (TT::COMPL_2ND_CMD - TT::COMPL_1ST_CMD) + 1;
+ iv_mcbmr.template insertFromRight<TT::COMPL_1ST_CMD, l_len>(i_port);
+ }
+
+ return;
+ }
+
+ ///
+ /// @brief Enable a specific dimm for this test - maint address mode
+ /// @param[in] i_dimm the dimm desired to be enabled - int 0, 1
+ /// @return void
+ ///
+ inline void enable_dimm( const uint64_t i_dimm )
+ {
+ iv_mcbmr.template writeBit<TT::COMPL_3RD_CMD>(i_dimm);
+ return;
+ }
+
+ ///
+ /// @brief Get the port from this subtest
+ /// @note The port number is relative to the MCBIST
+ /// @return the port of the subtest
+ ///
+ inline uint64_t get_port() const
+ {
+ uint64_t l_port = 0;
+
+ if (TT::MULTI_PORTS == mss::states::YES)
+ {
+ constexpr uint64_t l_len = (TT::COMPL_2ND_CMD - TT::COMPL_1ST_CMD) + 1;
+ iv_mcbmr.template extractToRight<TT::COMPL_1ST_CMD, l_len>(l_port);
+ }
+
+ return l_port;
+ }
+
+ ///
+ /// @brief Get the DIMM from this subtest
+ /// @return the DIMM this subtest has been configured for
+ ///
+ inline uint64_t get_dimm() const
+ {
+
+ return iv_mcbmr.template getBit<TT::COMPL_3RD_CMD>() ? 1 : 0;
+
+ return 0;
+ }
+
+ ///
+ /// @brief Add the subtest to go to
+ /// @param[in] the subtest to jump to
+ /// @return void
+ ///
+ inline void change_goto_subtest( const uint64_t i_jmp_to )
+ {
+ iv_mcbmr.template insertFromRight<TT::GOTO_SUBTEST, TT::GOTO_SUBTEST_LEN>(i_jmp_to);
+ FAPI_INF("changing subtest to jump to %d (0x%02x)", i_jmp_to, iv_mcbmr);
+ return;
+ }
+
+ ///
+ /// @brief Generate addresses in reverse order
+ /// @param[in] i_state the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_addr_rev_mode( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::ADDR_REV_MODE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Generate addresses in random order
+ /// @param[in] i_state the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_addr_rand_mode( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::ADDR_RAND_MODE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Generate and check data with ECC
+ /// @param[in] i_state the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_ecc_mode( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::ECC_MODE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Set the 'done after this test' bit
+ /// @param[in] i_state the desired state of the function; mss:ON, mss::OFF
+ /// @return void
+ ///
+ inline void change_done( const mss::states i_state )
+ {
+ iv_mcbmr.template writeBit<TT::DONE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Set the data mode for this subtest
+ /// @param[in] i_mode the desired mcbist::data_mode
+ /// @return void
+ ///
+ inline void change_data_mode( const data_mode i_mode )
+ {
+ iv_mcbmr.template insertFromRight<TT::DATA_MODE, TT::DATA_MODE_LEN>(i_mode);
+ return;
+ }
+
+ ///
+ /// @brief Set the operation type for this subtest
+ /// @param[in] i_mode the desired mcbist::op_type
+ /// @return void
+ ///
+ inline void change_op_type( const op_type i_type )
+ {
+ iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(i_type);
+ return;
+ }
+
+ ///
+ /// @brief Configure which address registers to use for this subtest
+ /// @param[in] i_index 0 = MCBSA0Q, 1 = MCBSA1Q, ...
+ /// @note wraps to 0-3 no matter what value you pass in.
+ /// @return void
+ ///
+ inline void change_addr_sel( const uint16_t i_index )
+ {
+ // Roll the index around - tidy support for an index which is out of range.
+ iv_mcbmr.template insertFromRight<TT::ADDR_SEL, TT::ADDR_SEL_LEN>(i_index % TT::MAX_ADDRESS_START_END_REGISTERS);
+ FAPI_INF("changed address select to index %d (0x%x)", i_index, iv_mcbmr);
+ return;
+ }
+
+ //
+ // @brief operator== for mcbist subtests
+ // @param[in] i_rhs the right hand side of the compare
+ // @return bool, true iff i_rhs == this
+ inline bool operator==(const subtest_t& i_rhs) const
+ {
+ return i_rhs.iv_mcbmr == iv_mcbmr;
+ }
+
+ /// The mcbist 'memory register' for this subtest.
+ // Note that it is only 16 bits.
+ // Each 64b memory register contains multiple 16 bit subtest definitions.
+ // As we create a vector of subtests, we'll drop them in to their appropriate
+ // MCBMR register before executing.
+ fapi2::buffer<uint16_t> iv_mcbmr;
+};
+
+///
+/// @brief Return a write subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> write_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0000 - we want subtest type to be a Write (W)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::WRITE);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 12 = 1 - ecc
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ // 14:15 = 0 address select config registers 0
+
+ return l_subtest;
+}
+
+
+///
+/// @brief Return an alter subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> alter_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 1011 - we want subtest type to be a Alter
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::ALTER);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return an display subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> display_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 1100 - we want subtest type to be a Display
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::DISPLAY);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return an scrub subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> scrub_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 1001 - we want subtest type to be a Scrub
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::SCRUB_RRWR);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a steer subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> steer_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 1010 - we want subtest type to be a Steer
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::STEER_RW);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a read subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> read_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0001 - we want subtest type to be a Read (R)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::READ);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a read write subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> read_write_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0010 - we want subtest type to be a Read Write (RW)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::READ_WRITE);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+
+///
+/// @brief Return a write read subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> write_read_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0011 - we want subtest type to be a Write Read (WR)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::WRITE_READ);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a read write read subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> read_write_read_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0100 - we want subtest type to be a Read Write Read (RWR)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::READ_WRITE_READ);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a read read write subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> read_read_write_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 1000 - we want subtest type to be a Read Read Write (RRW)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::READ_READ_WRITE);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a read write write subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> read_write_write_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0101 - we want subtest type to be a Read Write Write (RWW)
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::READ_WRITE_WRITE);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a random subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> random_subtest()
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0110 - we want subtest type to be a Random Seq, a randomly chosen read or write
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::RAND_SEQ);
+
+ // - Not a special subtest, so no other configs associated
+ // 4 = 0 - we don't want to complement data for our Writes
+ // 5:6 = 00 - don't know whether we complement 2nd and 3rd subcommand, caller to fix
+ // 7 = 0 - forward address generation
+ // 8 = 0 - non random address generation
+ // - Don't need to set up anything for LFSRs
+ // 9:11 = 000 - Fixed data mode
+
+ // 14:15 = 0 address select config registers 0
+
+ // By default we want to turn on ECC. Caller can turn it off.
+ l_subtest.change_ecc_mode(mss::ON);
+
+ return l_subtest;
+}
+
+///
+/// @brief Return a goto subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] the subtest we should go to
+/// @return mss::mcbist::subtest_t
+/// @note Turns on ECC mode for the returned subtest - caller can turn it off
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> goto_subtest( const uint64_t i_jump_to )
+{
+ // Starts life full of 0's
+ subtest_t<MC, T, TT> l_subtest;
+
+ // 0:3 = 0111 - we want subtest type to be a Goto
+ l_subtest.iv_mcbmr.template insertFromRight<TT::OP_TYPE, TT::OP_TYPE_LEN>(op_type::GOTO_SUBTEST_N);
+
+ // Plug in the subtest the user passed in
+ l_subtest.change_goto_subtest(i_jump_to);
+ return l_subtest;
+}
+
+///
+/// @brief Return an init subtest - configured simply
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @return mss::mcbist::subtest_t
+/// @note Configures for start/end address select bit as address config register 0
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE, typename TT = mcbistTraits<MC, T> >
+inline subtest_t<MC, T, TT> init_subtest()
+{
+ return write_subtest<MC, T, TT>();
+}
+
+///
+/// @brief A class representing a series of MCBIST subtests, and the
+/// MCBIST engine parameters associated with running the subtests
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType representing the fapi2 target which
+/// @tparam TT the mcbistTraits associated with T - derived
+/// contains the MCBIST engine (e.g., fapi2::TARGET_TYPE_MCBIST)
+/// @tparam TT, the mssTraits associtated with T
+/// @note MCBIST Memory Parameter Register defaults to
+/// - issue commands as fast as possible
+/// - even weighting of read/write if random addressing
+/// - disable clock monitoring
+/// - random command gap is disabled
+/// - BC4 disabled
+/// - no selected ports
+/// @note Address Generation Config Register defaults to
+/// - 0 fixed slots
+/// - All address counter modes on (so addr configs are start + len)
+/// - maint address mode enabled
+/// - maint broadcast mode disabled
+/// - maint slave rank boundary detect disabled
+/// @note Config register defaults to
+/// - BROADCAST_SYNC_EN disabled
+/// - BROADCAST_SYNC_WAIT 0
+/// - TIMEOUT_MODE - wait 524288 cycles until timeout is called
+/// - RESET_KEEPER - 0
+/// - CURRENT_ADDR_TRAP_UPDATE_DIS - 0
+/// - CCS_RETRY_DIS - 0
+/// - RESET_CNTS_START_OF_RANK - 0
+/// - LOG_COUNTS_IN_TRACE - 0
+/// - SKIP_INVALID_ADDR_DIMM_DIS - 0
+/// - REFRESH_ONLY_SUBTEST_EN - 0
+/// - REFRESH_ONLY_SUBTEST_TIMEBASE_SEL(0:1) - 0
+/// - RAND_ADDR_ALL_ADDR_MODE_EN - 0
+/// - REF_WAIT_TIME(0:13) - 0
+/// - MCB_LEN64 - 1
+/// - PAUSE_ON_ERROR_MODE(0:1) - don't pause on error
+/// - PAUSE_AFTER_CCS_SUBTEST - don't puase after CCS subtest
+/// - FORCE_PAUSE_AFTER_ADDR - don't pause after current address
+/// - FORCE_PAUSE_AFTER_SUBTEST - no pause after subtest
+/// - ENABLE_SPEC_ATTN - disabled
+/// - ENABLE_HOST_ATTN - enabled
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+class program
+{
+ private:
+
+ ///
+ /// @class broadcast_helper
+ /// @brief Nested class to help specialize broadcast mode functionality
+ /// @tparam mss::states BC - YES if broadcast mode capable
+ /// @tparam B = true - here for a little compiler magic to allow some partial specializations
+ ///
+ template< mss::states BC, bool B = true >
+ struct broadcast_helper;
+
+ ///
+ /// @class broadcast_helper - BC mode capable specialization
+ /// @tparam B = true - here for a little compiler magic to allow some partial specializations
+ ///
+ template<bool B >
+ struct broadcast_helper<mss::states::YES, B>
+ {
+
+ ///
+ /// @brief Change the broadcast sync enable bit - broadcast capable specialization
+ /// @param[in] i_state mss::ON to enable the sync pulse, mss::OFF to disable
+ /// @param[in,out] io_config configuration register
+ ///
+ static inline void broadcast_sync_enable( const mss::states i_state, fapi2::buffer<uint64_t>& io_config )
+ {
+ io_config.writeBit<TT::SYNC_EN>(i_state);
+ }
+
+ ///
+ /// @brief Change the broadcast mode sync timbase count - broadcast capable specialization
+ /// @param[in] i_broadcast_timebase
+ /// @param[in,out] io_config configuration register
+ ///
+ static inline void change_broadcast_timebase( const mss::mcbist::broadcast_timebase i_broadcast_timebase,
+ fapi2::buffer<uint64_t>& io_config )
+ {
+ io_config.insertFromRight<TT::SYNC_WAIT, TT::SYNC_WAIT_LEN>(i_broadcast_timebase);
+ }
+
+ ///
+ /// @brief Enable or disable broadcast mode - broadcast capable specialization
+ /// @param[in] i_mode true if broadcast should be enabled
+ /// @param[in,out] io_addr_gen address generation register
+ /// @warn Maint address mode must be enabled for this to work
+ /// @return void
+ ///
+ static inline void change_maint_broadcast_mode( const bool i_mode, fapi2::buffer<uint64_t>& io_addr_gen )
+ {
+ io_addr_gen.writeBit<TT::MAINT_BROADCAST_MODE_EN>(i_mode);
+ }
+ };
+
+
+ ///
+ /// @class broadcast_helper - BC mode incapable specialization
+ /// @tparam B = true - here for a little compiler magic to allow some partial specializations
+ /// @note all functions here should be empty - if we don't have broadcast mode, we don't want to do anything for it
+ ///
+ template<bool B >
+ struct broadcast_helper<mss::states::NO, B>
+ {
+
+ ///
+ /// @brief Change the broadcast sync enable bit - broadcast incapable specialization
+ /// @param[in] i_state mss::ON to enable the sync pulse, mss::OFF to disable
+ /// @param[in,out] io_config configuration register
+ ///
+ static inline void broadcast_sync_enable( const mss::states i_state, fapi2::buffer<uint64_t>& io_config )
+ {}
+
+ ///
+ /// @brief Change the broadcast mode sync timbase count - broadcast incapable specialization
+ /// @param[in] i_broadcast_timebase
+ /// @param[in,out] io_config configuration register
+ ///
+ static inline void change_broadcast_timebase( const mss::mcbist::broadcast_timebase i_broadcast_timebase,
+ fapi2::buffer<uint64_t>& io_config )
+ {}
+
+ ///
+ /// @brief Enable or disable broadcast mode - broadcast incapable specialization
+ /// @param[in] i_mode true if broadcast should be enabled
+ /// @param[in,out] io_addr_gen address generation register
+ /// @warn Maint address mode must be enabled for this to work
+ /// @return void
+ ///
+ static inline void change_maint_broadcast_mode( const bool i_mode, fapi2::buffer<uint64_t>& io_addr_gen )
+ {}
+ };
+
+ public:
+ // Setup our poll parameters so the MCBIST executer can see
+ // whether to use the delays in the instruction stream or not
+ program():
+ iv_parameters(0),
+ iv_addr_gen(0),
+ iv_test_type(CENSHMOO), // Used as default
+ iv_addr_map0(0),
+ iv_addr_map1(0),
+ iv_addr_map2(0),
+ iv_addr_map3(0),
+ iv_data_rotate_cnfg(0),
+ iv_data_rotate_seed(0),
+ iv_config(0),
+ iv_control(0),
+ iv_async(false),
+ iv_pattern(PATTERN_0),
+ iv_random24_data_seed(RANDOM24_SEEDS_0),
+ iv_random24_seed_map(RANDOM24_SEED_MAP_0),
+ iv_compare_mask(0)
+ {
+ // Enable the maintenance mode addressing
+ change_maint_address_mode(mss::ON);
+
+ // Enable 64B lengths by default. Commands which need 128B (scrub, steer, alter, display)
+ // can change this to 128B (mss::OFF).
+ change_len64(mss::ON);
+
+ // Turn off counting mode for all address configs
+ iv_addr_gen.insertFromRight<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(0b0000);
+
+ // By default if there's an error, we stop after the errored address
+ iv_config.insertFromRight<TT::CFG_PAUSE_ON_ERROR_MODE,
+ TT::CFG_PAUSE_ON_ERROR_MODE_LEN>(end_boundary::STOP_AFTER_ADDRESS);
+
+ // All mcbist attentions are host attentions, special attention bit is already clear
+ if(TT::CFG_ENABLE_ATTN_SUPPORT == mss::states::YES)
+ {
+ iv_config.setBit<TT::CFG_ENABLE_HOST_ATTN>();
+ }
+
+ }
+
+ ///
+ /// @brief Change the DIMM select in the address mapping
+ /// @param[in] i_bitmap DIMM select bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_dimm_select_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_DIMM_SELECT, TT::CFG_AMAP_DIMM_SELECT_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the MRANK0 address mapping when not in 5D mode
+ /// @param[in] i_bitmap MRANK0 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_mrank0_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_MRANK0, TT::CFG_AMAP_MRANK0_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the MRANK0 address mapping when in 5D mode
+ /// @param[in] i_bitmap MRANK0 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_mrank0_bit_5d( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_SRANK0, TT::CFG_AMAP_SRANK0_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the MRANK1 address mapping when not in 5D mode
+ /// @param[in] i_bitmap MRANK1 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_mrank1_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_MRANK1, TT::CFG_AMAP_MRANK1_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the MRANK1 address mapping when in 5D mode
+ /// @param[in] i_bitmap MRANK1 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_mrank1_bit_5d( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_SRANK1, TT::CFG_AMAP_SRANK1_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the MRANK2 address mapping when in 5D mode
+ /// @param[in] i_bitmap MRANK2 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_mrank2_bit_5d( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_SRANK2, TT::CFG_AMAP_SRANK2_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the SRANK0 address mapping when in 5D mode
+ /// @param[in] i_bitmap SRANK0 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_srank0_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_SRANK0, TT::CFG_AMAP_SRANK0_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the SRANK1 address mapping
+ /// @param[in] i_bitmap SRANK1 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_srank1_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_SRANK1, TT::CFG_AMAP_SRANK1_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the SRANK2 address mapping
+ /// @param[in] i_bitmap SRANK2 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_srank2_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_SRANK2, TT::CFG_AMAP_SRANK2_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the BANK2 address mapping
+ /// @param[in] i_bitmap BANK2 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_bank2_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_BANK2, TT::CFG_AMAP_BANK2_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the BANK1 address mapping
+ /// @param[in] i_bitmap BANK1 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_bank1_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_BANK1, TT::CFG_AMAP_BANK1_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the BANK0 address mapping
+ /// @param[in] i_bitmap BANK0 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_bank0_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map0.insertFromRight<TT::CFG_AMAP_BANK0, TT::CFG_AMAP_BANK0_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the BANK_GROUP1 address mapping
+ /// @param[in] i_bitmap BANK_GROUP1 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_bank_group1_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_BANK_GROUP1, TT::CFG_AMAP_BANK_GROUP1_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the BANK_GROUP0 address mapping
+ /// @param[in] i_bitmap BANK_GROUP0 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_bank_group0_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_BANK_GROUP0, TT::CFG_AMAP_BANK_GROUP0_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW17 address mapping
+ /// @param[in] i_bitmap ROW17 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row17_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW17, TT::CFG_AMAP_ROW17_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW16 address mapping
+ /// @param[in] i_bitmap ROW16 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row16_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW16, TT::CFG_AMAP_ROW16_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW15 address mapping
+ /// @param[in] i_bitmap ROW15 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row15_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW15, TT::CFG_AMAP_ROW15_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW14 address mapping
+ /// @param[in] i_bitmap ROW14 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row14_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW14, TT::CFG_AMAP_ROW14_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW13 address mapping
+ /// @param[in] i_bitmap ROW13 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_row13_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW13, TT::CFG_AMAP_ROW13_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW12 address mapping
+ /// @param[in] i_bitmap ROW12 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row12_bit( const uint64_t i_bitmap )
+ {
+ // CFG_AMAP_ROW12 = MCBIST_MCBAMR1A0Q_CFG_AMAP_ROW12 ,
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW12, TT::CFG_AMAP_ROW12_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW11 address mapping
+ /// @param[in] i_bitmap ROW11 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row11_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW11, TT::CFG_AMAP_ROW11_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW10 address mapping
+ /// @param[in] i_bitmap ROW10 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row10_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map1.insertFromRight<TT::CFG_AMAP_ROW10, TT::CFG_AMAP_ROW10_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW9 address mapping
+ /// @param[in] i_bitmap ROW9 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row9_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW9, TT::CFG_AMAP_ROW9_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW8 address mapping
+ /// @param[in] i_bitmap ROW8 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row8_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW8, TT::CFG_AMAP_ROW8_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW7 address mapping
+ /// @param[in] i_bitmap ROW7 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row7_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW7, TT::CFG_AMAP_ROW7_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW6 address mapping
+ /// @param[in] i_bitmap ROW6 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row6_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW6, TT::CFG_AMAP_ROW6_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW5 address mapping
+ /// @param[in] i_bitmap ROW5 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row5_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW5, TT::CFG_AMAP_ROW5_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW4 address mapping
+ /// @param[in] i_bitmap ROW4 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row4_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW4, TT::CFG_AMAP_ROW4_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW3 address mapping
+ /// @param[in] i_bitmap ROW3 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row3_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW3, TT::CFG_AMAP_ROW3_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW2 address mapping
+ /// @param[in] i_bitmap ROW2 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row2_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW2, TT::CFG_AMAP_ROW2_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW1 address mapping
+ /// @param[in] i_bitmap ROW1 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row1_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW1, TT::CFG_AMAP_ROW1_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the ROW0 address mapping
+ /// @param[in] i_bitmap ROW0 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_row0_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map2.insertFromRight<TT::CFG_AMAP_ROW0, TT::CFG_AMAP_ROW0_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the COL9 address mapping
+ /// @param[in] i_bitmap COL9 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col9_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL9, TT::CFG_AMAP_COL9_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the COL8 address mapping
+ /// @param[in] i_bitmap COL8 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col8_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL8, TT::CFG_AMAP_COL8_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the COL7 address mapping
+ /// @param[in] i_bitmap COL7 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col7_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL7, TT::CFG_AMAP_COL7_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the COL6 address mapping
+ /// @param[in] i_bitmap COL6 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col6_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL6, TT::CFG_AMAP_COL6_LEN>(i_bitmap);
+ return;
+ }
+
+ /// @brief Change the COL5 address mapping
+ /// @param[in] i_bitmap COL5 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col5_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL5, TT::CFG_AMAP_COL5_LEN>(i_bitmap);
+ return;
+ }
+
+ /// @brief Change the COL4 address mapping
+ /// @param[in] i_bitmap COL4 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col4_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL4, TT::CFG_AMAP_COL4_LEN>(i_bitmap);
+ return;
+ }
+
+ /// @brief Change the COL3 address mapping
+ /// @param[in] i_bitmap COL3 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col3_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL3, TT::CFG_AMAP_COL3_LEN>(i_bitmap);
+ return;
+ }
+
+ /// @brief Change the COL2 address mapping
+ /// @param[in] i_bitmap COL2 bit map in the address counter
+ /// @note Assumes data is right-aligned
+ ///
+ inline void change_col2_bit( const uint64_t i_bitmap )
+ {
+ iv_addr_map3.insertFromRight<TT::CFG_AMAP_COL2, TT::CFG_AMAP_COL2_LEN>(i_bitmap);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist 64/128 byte control
+ /// @param[in] i_state mss::ON if you want 64B, mss::OFF if you want 128B
+ /// @return void
+ ///
+ inline void change_len64( const mss::states i_state )
+ {
+ iv_config.writeBit<TT::CFG_MCB_LEN64>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Change the random address all address mode
+ /// @param[in] i_state mss::ON if you random addressing all addresses, mss::OFF if you don't
+ /// @return void
+ ///
+ inline void random_address_all( const mss::states i_state )
+ {
+ iv_config.writeBit<TT::RAND_ADDR_ALL_ADDR_MODE_EN>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Change the broadcast sync enable bit
+ /// @param[in] i_state mss::ON to enable the sync pulse, mss::OFF to disable
+ /// @return void
+ ///
+ inline void broadcast_sync_enable( const mss::states i_state )
+ {
+ broadcast_helper<TT::BROADCAST_CAPABLE>::broadcast_sync_enable(i_state, iv_config);
+ }
+
+ ///
+ /// @brief Change the broadcast mode sync timbase count
+ /// @param[in] i_broadcast_timebase
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_broadcast_timebase( const mss::mcbist::broadcast_timebase i_broadcast_timebase )
+ {
+ broadcast_helper<TT::BROADCAST_CAPABLE>::change_broadcast_timebase(i_broadcast_timebase, iv_config);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist thresholds
+ /// @param[in] i_thresholds the new thresholds/stop conditions
+ /// @return void
+ ///
+ inline void change_thresholds( const stop_conditions<MC>& i_thresholds )
+ {
+ iv_thresholds = i_thresholds;
+ return;
+ }
+
+ ///
+ /// @brief Change the data rotate value
+ /// @param[in] i_data_rotate
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_data_rotate( mss::mcbist::data_rotate_mode i_data_rotate )
+ {
+ iv_data_rotate_cnfg.insertFromRight<TT::CFG_DATA_ROT, TT::CFG_DATA_ROT_LEN>(i_data_rotate);
+ return;
+ }
+
+ ///
+ /// @brief Get the data rotate value
+ /// @note Assumes data is right aligned
+ /// @return the data rotate value config
+ ///
+ inline uint64_t get_data_rotate()
+ {
+ uint64_t l_data_rotate = 0;
+ iv_data_rotate_cnfg.extractToRight<TT::CFG_DATA_ROT, TT::CFG_DATA_ROT_LEN>(l_data_rotate);
+ return l_data_rotate;
+ }
+
+ ///
+ /// @brief Change the data seed mode value
+ /// @param[in] i_data_seed_mode
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_data_seed_mode( const mss::mcbist::data_seed_mode i_data_seed_mode )
+ {
+ iv_data_rotate_cnfg.insertFromRight<TT::CFG_DATA_SEED_MODE, TT::CFG_DATA_SEED_MODE_LEN>(i_data_seed_mode);
+ return;
+ }
+
+ ///
+ /// @brief Get the data seed mode value
+ /// @note Assumes data is right aligned
+ /// @return the data seed mode value
+ ///
+ inline uint64_t get_data_seed_mode()
+ {
+ uint64_t l_data_seed_mode = 0;
+ iv_data_rotate_cnfg.extractToRight<TT::CFG_DATA_SEED_MODE, TT::CFG_DATA_SEED_MODE_LEN>(l_data_seed_mode);
+ return l_data_seed_mode;
+ }
+
+ ///
+ /// @brief Change the data rotate seed for data bits 0:63
+ /// @param[in] i_width
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_data_rotate_seed1( const uint64_t i_data_rotate_seed1 )
+ {
+ iv_data_rotate_seed.insertFromRight<TT::CFG_DATA_ROT_SEED1, TT::CFG_DATA_ROT_SEED1_LEN>(i_data_rotate_seed1);
+ return;
+ }
+
+ ///
+ /// @brief Get the data rotate seed for data bits 0:63
+ /// @note Assumes data is right aligned
+ /// @return the data rotate seed for data bits 0:63
+ ///
+ inline uint64_t get_data_rotate_seed1()
+ {
+ uint64_t l_data_rotate_seed1 = 0;
+ iv_data_rotate_seed.extractToRight<TT::CFG_DATA_ROT_SEED1, TT::CFG_DATA_ROT_SEED1_LEN>(l_data_rotate_seed1);
+ return l_data_rotate_seed1;
+ }
+
+ ///
+ /// @brief Change the data rotate seed for data bits 64:79
+ /// @param[in] i_width
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_data_rotate_seed2( const uint64_t i_data_rotate_seed2 )
+ {
+ iv_data_rotate_cnfg.insertFromRight<TT::CFG_DATA_ROT_SEED2, TT::CFG_DATA_ROT_SEED2_LEN>(i_data_rotate_seed2);
+ return;
+ }
+
+ ///
+ /// @brief Get the data rotate seed for data bits 64:79
+ /// @note Assumes data is right aligned
+ /// @return the data rotate seed for data bits 64:79
+ ///
+ inline uint64_t get_data_rotate_seed2()
+ {
+ uint64_t l_data_rotate_seed2 = 0;
+ iv_data_rotate_cnfg.extractToRight<TT::CFG_DATA_ROT_SEED2, TT::CFG_DATA_ROT_SEED2_LEN>(l_data_rotate_seed2);
+ return l_data_rotate_seed2;
+ }
+
+ ///
+ /// @brief Change the compare mask CE trap enable
+ /// @param[in] i_state mss::ON to enable the trap, mss::OFF to disable the trap
+ /// @return void
+ ///
+ inline void change_ce_trap_enable( const mss::states i_state )
+ {
+ iv_compare_mask.writeBit<TT::CFG_TRAP_CE_ENABLE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Change the compare mask UE trap enable
+ /// @param[in] i_state mss::ON to enable the trap, mss::OFF to disable the trap
+ /// @return void
+ ///
+ inline void change_ue_trap_enable( const mss::states i_state )
+ {
+ iv_compare_mask.writeBit<TT::CFG_TRAP_UE_ENABLE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Change the compare mask MPE trap enable
+ /// @param[in] i_state mss::ON to enable the trap, mss::OFF to disable the trap
+ /// @return void
+ ///
+ inline void change_mpe_trap_enable( const mss::states i_state )
+ {
+ iv_compare_mask.writeBit<TT::CFG_TRAP_MPE_ENABLE>(i_state);
+ return;
+ }
+
+ ///
+ /// @brief Change the forced pause state
+ /// @param[in] i_end the end_boundary to pause at
+ /// @return void
+ ///
+ inline void change_forced_pause( const end_boundary& i_end )
+ {
+ if (i_end == end_boundary::DONT_CHANGE)
+ {
+ return;
+ }
+
+ // Clear all the forced pause bits so we don't stack pauses
+ iv_config.clearBit<TT::MCBIST_CFG_FORCE_PAUSE_AFTER_ADDR>();
+ iv_config.clearBit<TT::MCBIST_CFG_PAUSE_AFTER_RANK>();
+ iv_config.clearBit<TT::MCBIST_CFG_FORCE_PAUSE_AFTER_SUBTEST>();
+ iv_addr_gen.clearBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>();
+
+ switch (i_end)
+ {
+ case end_boundary::STOP_AFTER_ADDRESS:
+ iv_config.setBit<TT::MCBIST_CFG_FORCE_PAUSE_AFTER_ADDR>();
+ break;
+
+ case end_boundary::STOP_AFTER_SLAVE_RANK:
+ iv_config.setBit<TT::MCBIST_CFG_PAUSE_AFTER_RANK>();
+ iv_addr_gen.setBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>();
+ break;
+
+ case end_boundary::STOP_AFTER_MASTER_RANK:
+ iv_config.setBit<TT::MCBIST_CFG_PAUSE_AFTER_RANK>();
+ iv_addr_gen.clearBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>();
+ break;
+
+ case end_boundary::STOP_AFTER_SUBTEST:
+ iv_config.setBit<TT::MCBIST_CFG_FORCE_PAUSE_AFTER_SUBTEST>();
+ break;
+
+ // None is all set, we cleared the bits above
+ case end_boundary::NONE:
+ break;
+
+ // Default is a no forced pause (as we cleared all the bits)
+ default:
+ FAPI_INF("no forced pause state - end state %d unknown", i_end);
+ break;
+ };
+
+ return;
+ }
+
+ ///
+ /// @brief Calculate minimum command gap for BG_SCRUB
+ /// @param[in] i_target the target behind which the memory sits
+ /// @param[in] i_freq the DRAM frequency
+ /// @param[in] i_size the sum of all DIMM sizes
+ /// @param[out] o_min_cmd_gap the setting for MCBPARMQ_CFG_MIN_CMD_GAP
+ /// @param[out] o_timebase the setting for MCBPARMQ_CFG_MIN_GAP_TIMEBASE
+ /// @return FAPI2_RC_SUCCSS iff ok
+ ///
+ inline fapi2::ReturnCode calculate_min_cmd_gap( const fapi2::Target<T>& i_target,
+ const uint64_t i_freq,
+ const uint64_t i_size,
+ uint64_t& o_min_cmd_gap,
+ mss::states& o_timebase )
+ {
+ constexpr uint64_t l_seconds = SEC_IN_HOUR * BG_SCRUB_IN_HOURS;
+ constexpr uint64_t MIN_CMD_GAP = 0x001;
+ uint64_t l_mem_cycles_per_sec;
+ uint64_t l_total_cycles;
+ uint64_t l_total_addresses;
+ uint64_t l_min_cmd_gap;
+
+ // Sanity check our inputs, just assert if bad since they come directly from eff_config
+ // this will prevent us from any divide by zero problems
+ FAPI_ASSERT( (i_freq != 0) && (i_size != 0),
+ fapi2::MSS_ZERO_FREQ_OR_SIZE().
+ set_FREQ(i_freq).
+ set_SIZE(i_size),
+ "%s received zero memory freq or size in calculate_min_cmd_gap", mss::c_str(i_target));
+
+ // MIN CMD GAP = TOTAL CYCLES / TOTAL ADDRESSES
+ // TOTAL CYCLES = 12 hours x 60 min/hr x 60 sec/min x [DRAM freq] cycles/sec x
+ // 1/2 (MEM logic runs half DRAM freq)
+ l_mem_cycles_per_sec = (i_freq * T_PER_MT) / 2;
+ l_total_cycles = l_seconds * l_mem_cycles_per_sec;
+
+ // TOTAL ADDRESSES = sum over all dimms of ( [DIMM CAPACITY]/128B )
+ l_total_addresses = i_size * BYTES_PER_GB / 128;
+
+ l_min_cmd_gap = l_total_cycles / l_total_addresses;
+
+ // If we're greater than the timebase, set the multiplier and divide down to get the gap setting
+ if (CMD_TIMEBASE < l_min_cmd_gap)
+ {
+ o_min_cmd_gap = l_min_cmd_gap / CMD_TIMEBASE;
+ o_timebase = mss::ON;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // If we're greater than the max gap setting, get as close to 12 hours as we can instead of just truncating
+ if (l_min_cmd_gap > MAX_CMD_GAP)
+ {
+ // work backwards to calculate what the total scrub time would be with the highest cmd gap with no multiplier...
+ const uint64_t l_scrub_time_fff = (l_total_addresses * MAX_CMD_GAP) / l_mem_cycles_per_sec;
+ // and with the lowest cmd gap with the multiplier
+ const uint64_t l_scrub_time_001 = (l_total_addresses * CMD_TIMEBASE) / l_mem_cycles_per_sec;
+
+ if ((l_seconds - l_scrub_time_fff) > (l_scrub_time_001 - l_seconds))
+ {
+ FAPI_INF("%s gap is greater than the field will allow. Setting to: 0x%03x", mss::c_str(i_target), MIN_CMD_GAP);
+ o_min_cmd_gap = MIN_CMD_GAP;
+ o_timebase = mss::ON;
+ }
+ else
+ {
+ FAPI_INF("%s gap is greater than the field will allow. Setting to: 0x%03x", mss::c_str(i_target), MAX_CMD_GAP);
+ o_min_cmd_gap = MAX_CMD_GAP;
+ o_timebase = mss::OFF;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // Else, we're good to just set the calculated gap value directly
+ o_min_cmd_gap = l_min_cmd_gap;
+ o_timebase = mss::OFF;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Change MCBIST Speed
+ /// @param[in] i_target the target behind which the memory sits
+ /// @param[in] i_speed the speed eunmeration
+ /// @return FAPI2_RC_SUCCSS iff ok
+ ///
+ inline fapi2::ReturnCode change_speed( const fapi2::Target<T>& i_target, const speed i_speed )
+ {
+ switch (i_speed)
+ {
+ case speed::LUDICROUS:
+ change_min_cmd_gap(0);
+ change_min_gap_timebase(mss::OFF);
+ return fapi2::FAPI2_RC_SUCCESS;
+ break;
+
+ case speed::BG_SCRUB:
+ {
+ uint64_t l_freq = 0;
+ uint64_t l_size = 0;
+ uint64_t l_min_cmd_gap = 0;
+ mss::states l_timebase = mss::OFF;
+
+ constexpr uint64_t l_seconds = SEC_IN_HOUR * BG_SCRUB_IN_HOURS;
+
+ FAPI_TRY( mss::freq(i_target, l_freq) );
+ FAPI_TRY( mss::eff_memory_size<MC>(i_target, l_size) );
+
+ FAPI_TRY( calculate_min_cmd_gap(i_target, l_freq, l_size, l_min_cmd_gap, l_timebase) );
+
+ FAPI_INF("%s setting bg scrub speed: %dMT/s, memory: %dGB, duration: %ds, gap: %d",
+ mss::c_str(i_target), l_freq, l_size, l_seconds, l_min_cmd_gap);
+
+ change_min_cmd_gap(l_min_cmd_gap);
+ change_min_gap_timebase(l_timebase);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+ break;
+
+ // Otherwise it's SAME_SPEED or something else in which case we do nothing
+ default:
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ break;
+ };
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Get a list of ports involved in the program
+ /// @param[in] i_target the target for this program
+ /// @return vector of port targets
+ ///
+ std::vector<fapi2::Target<TT::PORT_TYPE>> get_port_list( const fapi2::Target<T>& i_target ) const;
+
+ ///
+ /// @brief Change MCBIST Stop-on-error conditions (end boundaries)
+ /// @param[in] i_end the end boundary
+ /// @note By default the MCBIST is programmed to always stop after an errored address. This API
+ /// allows the caller to force a stop at a boundary or to force no stopping on errors
+ ///
+ inline void change_end_boundary( const end_boundary i_end )
+ {
+ // If there's no change, just get outta here
+ if (i_end == DONT_CHANGE)
+ {
+ return;
+ }
+
+ // The values of the enum were crafted so that we can simply insertFromRight into the register.
+ // We take note of whether to set the slave or master rank indicator and set that as well.
+ // The hardware has to have a 1 or a 0 - so there is no choice for the rank detection. So it
+ // doesn't matter that we're processing other end boundaries here - they'll just look like we
+ // asked for a master rank detect.
+ iv_config.insertFromRight<TT::CFG_PAUSE_ON_ERROR_MODE, TT::CFG_PAUSE_ON_ERROR_MODE_LEN>(i_end);
+
+ const uint64_t l_detect_slave = fapi2::buffer<uint64_t>(i_end).getBit<TT::SLAVE_RANK_INDICATED_BIT>();
+ iv_addr_gen.writeBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>( l_detect_slave );
+ FAPI_INF("load MCBIST end boundaries 0x%016lx detect slave? %s",
+ i_end, (l_detect_slave == 1 ? "yes" : "no") );
+ }
+
+ ///
+ /// @brief Change the mcbist min command gap
+ /// @param[in] i_gap minimum number of cycles between commands when cfg_en_randcmd_gap is a 0 (disabled)
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_cmd_gap( const uint64_t i_gap )
+ {
+ iv_parameters.insertFromRight<TT::MIN_CMD_GAP, TT::MIN_CMD_GAP_LEN>(i_gap);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist gap timebase
+ /// @param[in] i_tb When set to mss::ON and cfg_en_randcmd_gap is a 0, then the number of minimum
+ /// cycles between commands will be cfg_min_cmd_gap multiplied by 2^13.
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_gap_timebase( const bool i_tb )
+ {
+ iv_parameters.writeBit<TT::MIN_GAP_TIMEBASE>(i_tb);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist min command gap blind steer
+ /// @param[in] i_gap min gap between commands when doing steering
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_cmd_gap_blind_steer( const uint64_t i_gap )
+ {
+ iv_parameters.insertFromRight<TT::MIN_CMD_GAP_BLIND_STEER, TT::MIN_CMD_GAP_BLIND_STEER_LEN>(i_gap);
+ return;
+ }
+
+ ///
+ /// @brief Change the mcbist gap timebase for blind steer
+ /// @param[in] i_tb When set to mss::ON and cfg_en_randcmd_gap is a 0, then the number of minimum
+ /// cycles between commands will be cfg_min_cmd_gap multiplied by 2^13.
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_min_gap_timebase_blind_steer( const bool i_tb )
+ {
+ iv_parameters.writeBit<TT::MIN_GAP_TIMEBASE_BLIND_STEER>(i_tb);
+ return;
+ }
+
+ ///
+ /// @brief Change the weights for random mcbist reads, writes
+ /// @param[in] i_weight
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_randcmd_wgt( const uint64_t i_weight )
+ {
+ iv_parameters.insertFromRight<TT::RANDCMD_WGT, TT::RANDCMD_WGT_LEN>(i_weight);
+ return;
+ }
+
+ ///
+ /// @brief Change the weights for random mcbist command gaps
+ /// @param[in] i_weight
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_randgap_wgt( const uint64_t i_weight )
+ {
+ iv_parameters.insertFromRight<TT::RANDGAP_WGT, TT::RANDGAP_WGT_LEN>(i_weight);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable mcbist clock monitoring
+ /// @param[in] i_monitor mss::ON to monitor
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_clock_monitor_en( const bool i_monitor )
+ {
+ iv_parameters.writeBit<TT::CLOCK_MONITOR_EN>(i_monitor);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable mcbist random command gaps
+ /// @param[in] i_rndgap mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_en_randcmd_gap( const bool i_rndgap )
+ {
+ iv_parameters.writeBit<TT::EN_RANDCMD_GAP>(i_rndgap);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable mcbist BC4 support
+ /// @param[in] i_bc4 mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_bc4_en( const bool i_bc4 )
+ {
+ iv_parameters.writeBit<TT::BC4_EN>(i_bc4);
+ return;
+ }
+
+ ///
+ /// @brief Change fixed width address generator config
+ /// @param[in] i_width
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_fixed_width( const uint64_t i_width )
+ {
+ iv_addr_gen.insertFromRight<TT::FIXED_WIDTH, TT::FIXED_WIDTH_LEN>(i_width);
+ return;
+ }
+
+ ///
+ /// @brief Get the fixed width address config
+ /// @note Assumes data is right aligned
+ /// @return the fixed width address config
+ ///
+ inline uint64_t get_fixed_width() const
+ {
+ uint64_t l_fixed_width = 0;
+ iv_addr_gen.extractToRight<TT::FIXED_WIDTH, TT::FIXED_WIDTH_LEN>(l_fixed_width);
+ return l_fixed_width;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 0
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode0( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ // Bit 0 enables counter mode for start/end address field 0
+ l_value.writeBit<0>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 1
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode1( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ // Bit 1 enables counter mode for start/end address field 1
+ l_value.writeBit<1>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 2
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode2( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ // Bit 2 enables counter mode for start/end address field 2
+ l_value.writeBit<2>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable address counting mode for address config 3
+ /// @param[in] i_program, the program in question
+ /// @param[in] i_mode mss::ON to enable
+ /// @note Assumes data is right-aligned
+ /// @return void
+ ///
+ inline void change_address_counter_mode3( const bool i_mode )
+ {
+ fapi2::buffer<uint64_t> l_value;
+ iv_addr_gen.extract<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ // Bit 3 enables counter mode for start/end address field 3
+ l_value.writeBit<3>(i_mode);
+ iv_addr_gen.insert<TT::ADDR_COUNTER_MODE, TT::ADDR_COUNTER_MODE_LEN>(l_value);
+ return;
+ }
+
+
+ ///
+ /// @brief Enable or disable maint address mode
+ /// @param[in] i_mode mss::ON to enable
+ /// @warn Address counter modes must be 0 for this to work.
+ /// @note When enabled subtest complement bits become 3-bit port-dimm selector field
+ /// (Note: when turning this off, make sure you clear or reprogram complement bits)
+ /// @return void
+ ///
+ inline void change_maint_address_mode( const bool i_mode )
+ {
+ iv_addr_gen.writeBit<TT::MAINT_ADDR_MODE_EN>(i_mode);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable broadcast mode
+ /// @param[in] i_program the program in question
+ /// @param[in] i_mode mss::ON to enable
+ /// @warn Maint address mode must be enabled for this to work
+ /// @return void
+ ///
+ inline void change_maint_broadcast_mode( const bool i_mode )
+ {
+ broadcast_helper<TT::BROADCAST_CAPABLE>::change_maint_broadcast_mode(i_mode, iv_addr_gen);
+ return;
+ }
+
+
+ ///
+ /// @brief Enable or disable slave rank boundary detect
+ /// @param[in] i_program the program in question
+ /// @param[in] i_mode mss::ON to enable
+ /// @return void
+ ///
+ inline void change_srank_boundaries( const bool i_mode )
+ {
+ iv_addr_gen.writeBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>(i_mode);
+ return;
+ }
+
+ ///
+ /// @brief Enable or disable async mode
+ /// @param[in] i_program the program in question
+ /// @param[in] i_mode mss::ON to enable, programs will run async
+ /// @return void
+ ///
+ inline void change_async( const bool i_mode )
+ {
+ iv_async = i_mode;
+ return;
+ }
+
+ ///
+ /// @brief Select the port(s) to be used by the MCBIST
+ /// @param[in] i_ports uint64_t representing the ports. Multiple bits set imply broadcast
+ /// i_ports is a right-aligned uint64_t, of which only the right-most 4 bits are used. The register
+ /// field is defined such that the left-most bit in the field represents port 0, the right most
+ /// bit in the field represents port 3. So, to run on port 0, i_ports should be 0b1000. 0b0001
+ /// (or 0x1) is port 3 - not port 0
+ /// @return void
+ ///
+ inline void select_ports( const uint64_t i_ports )
+ {
+ if (TT::MULTI_PORTS == mss::states::YES)
+ {
+ iv_control.insertFromRight<TT::PORT_SEL, TT::PORT_SEL_LEN>(i_ports);
+ FAPI_INF("mcbist select ports: iv_control 0x%016lx (ports: 0x%x)", iv_control, i_ports);
+ }
+
+ return;
+ }
+
+ ///
+ /// @brief Process mcbist errors
+ /// @param[in] i_target the target for this program
+ /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
+ /// This shouldn't be called in firmware? Check with PRD
+ ///
+ inline fapi2::ReturnCode process_errors( const fapi2::Target<T> i_target ) const
+ {
+ // MCBIST error traits
+ using ET = mcbistMCTraits<MC>;
+
+ // Until reading the error array is documented, comparison errors 'just' result in
+ // a flag indicating there was a problem on port.
+ {
+ fapi2::buffer<uint64_t> l_data;
+ uint64_t l_port = 0;
+ uint64_t l_subtest = 0;
+ FAPI_TRY( fapi2::getScom(i_target, TT::MCBSTATQ_REG, l_data), "%s Failed getScom", mss::c_str(i_target) );
+
+ if (TT::MULTI_PORTS == mss::states::YES)
+ {
+ l_data.extractToRight<TT::LOGGED_ERROR_ON_PORT_INDICATOR, TT::LOGGED_ERROR_ON_PORT_INDICATOR_LEN>(l_port);
+ }
+
+ l_data.extractToRight<TT::SUBTEST_NUM_INDICATOR, TT::SUBTEST_NUM_INDICATOR_LEN>(l_subtest);
+
+ FAPI_ASSERT( l_port == 0,
+ ET::memdiags_compare_error_in_last_pattern()
+ .set_MC_TARGET(i_target)
+ .set_PORT(mss::first_bit_set(l_port))
+ .set_SUBTEST(l_subtest),
+ "%s MCBIST error on port %d subtest %d", mss::c_str(i_target), mss::first_bit_set(l_port), l_subtest );
+ }
+
+ // Check for UE errors
+ {
+ fapi2::buffer<uint64_t> l_read0;
+ fapi2::buffer<uint64_t> l_read1;
+
+ FAPI_TRY( fapi2::getScom(i_target, TT::SRERR0_REG, l_read0), "%s Failed getScom", mss::c_str(i_target) );
+ FAPI_TRY( fapi2::getScom(i_target, TT::SRERR1_REG, l_read1), "%s Failed getScom", mss::c_str(i_target) );
+
+ FAPI_ASSERT( ((l_read0 == 0) && (l_read1 == 0)),
+ ET::memdiags_error_in_last_pattern()
+ .set_MC_TARGET(i_target)
+ .set_STATUS0(l_read0)
+ .set_STATUS1(l_read1),
+ "%s MCBIST scrub/read error reg0: 0x%016lx reg1: 0x%016lx", mss::c_str(i_target), l_read0, l_read1 );
+ }
+
+ FAPI_INF("%s Execution success - no errors seen from MCBIST program", mss::c_str(i_target));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Store off the pattern index. We'll use this to write the patterns when we load the program
+ /// @param[in] i_index an index such as mss::mcbist::PATTERN_0
+ /// @return fapi2::ReturnCode checks for bad pattern index
+ /// @warning if you give a pattern index which does not exist your pattern will not change.
+ /// @note patterns default to PATTERN_0
+ ///
+ inline fapi2::ReturnCode change_pattern( const uint64_t i_pattern )
+ {
+ FAPI_INF("change MCBIST pattern index %d", i_pattern);
+
+ // Sanity check the pattern since they're just numbers.
+ FAPI_ASSERT( i_pattern <= mcbist::NO_PATTERN,
+ fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().
+ set_INDEX(i_pattern).
+ set_MC_TYPE(MC),
+ "Attempting to change a pattern which does not exist %d", i_pattern );
+
+ iv_pattern = i_pattern;
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Store off the random 24b data seed index. We'll use this to write the 24b random data seeds when we load the program
+ /// @param[in] i_index an index such as mss::mcbist::RANDOM24_SEEDS_0
+ /// @return fapi2::ReturnCode checks for bad pattern index
+ /// @warning if you give a pattern index which does not exist your pattern will not change.
+ /// @note patterns default to PATTERN_0
+ ///
+ inline fapi2::ReturnCode change_random_24b_seeds( const uint64_t i_random24_seed )
+ {
+ FAPI_INF("change MCBIST 24b random data seeds index %d", i_random24_seed );
+
+ // TK Want a new RC for random 24
+ // Sanity check the pattern since they're just numbers.
+ FAPI_ASSERT( i_random24_seed <= mcbist::NO_RANDOM24_SEEDS,
+ fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().
+ set_INDEX(i_random24_seed).
+ set_MC_TYPE(MC),
+ "Attempting to change to a 24b random data seed which does not exist %d", i_random24_seed );
+
+ iv_random24_data_seed = i_random24_seed;
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Store off the random 24b data seed mapping index. We'll use this to write the 24b random data seed mappings when we load the program
+ /// @param[in] i_index an index such as mss::mcbist::RANDOM24_SEEDS_0
+ /// @return fapi2::ReturnCode checks for bad pattern index
+ /// @warning if you give a pattern index which does not exist your pattern will not change.
+ /// @note patterns default to PATTERN_0
+ ///
+ inline fapi2::ReturnCode change_random_24b_maps( const uint64_t i_random24_map )
+ {
+ FAPI_INF("change MCBIST 24b random data seed mappings index %d", i_random24_map );
+
+ // TK Want a new RC for random 24
+ // Sanity check the pattern since they're just numbers.
+ FAPI_ASSERT( i_random24_map <= mcbist::NO_RANDOM24_SEED_MAP,
+ fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().
+ set_INDEX(i_random24_map).
+ set_MC_TYPE(MC),
+ "Attempting to change to a random seed map which does not exist %d", i_random24_map );
+
+ iv_random24_seed_map = i_random24_map;
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief checks if two programs are equal
+ /// @param[in] i_rhs program to compare
+ /// @return bool true if equal
+ ///
+ inline bool operator==( const program<MC>& i_rhs ) const
+ {
+ //checks the vector first, to save time if they're not equal (no sense in checking everything else)
+ if(iv_subtests != i_rhs.iv_subtests)
+ {
+ return false;
+ }
+
+ //checks everything else
+ bool l_equal = iv_parameters == i_rhs.iv_parameters;
+ l_equal &= iv_addr_gen == i_rhs.iv_addr_gen;
+ l_equal &= iv_test_type == i_rhs.iv_test_type;
+ l_equal &= iv_poll == i_rhs.iv_poll;
+ l_equal &= iv_addr_map0 == i_rhs.iv_addr_map0;
+ l_equal &= iv_addr_map1 == i_rhs.iv_addr_map1;
+ l_equal &= iv_addr_map2 == i_rhs.iv_addr_map2;
+ l_equal &= iv_addr_map3 == i_rhs.iv_addr_map3;
+ l_equal &= iv_config == i_rhs.iv_config;
+ l_equal &= iv_control == i_rhs.iv_control;
+ l_equal &= iv_async == i_rhs.iv_async;
+ l_equal &= iv_pattern == i_rhs.iv_pattern;
+ l_equal &= iv_thresholds == i_rhs.iv_thresholds;
+ l_equal &= iv_data_rotate_cnfg == i_rhs.iv_data_rotate_cnfg;
+ l_equal &= iv_data_rotate_seed == i_rhs.iv_data_rotate_seed;
+ l_equal &= iv_random24_data_seed == i_rhs.iv_random24_data_seed;
+ l_equal &= iv_random24_seed_map == i_rhs.iv_random24_seed_map;
+ l_equal &= iv_data_rotate_cnfg == i_rhs.iv_data_rotate_cnfg;
+ l_equal &= iv_data_rotate_seed == i_rhs.iv_data_rotate_seed;
+ l_equal &= iv_compare_mask == i_rhs.iv_compare_mask;
+
+ //returns result
+ return l_equal;
+ }
+
+ // Vector of subtests. Note the MCBIST subtests are spread across
+ // 8 registers - 4 subtests fit in one 64b register
+ // (16 bits/test, 4 x 16 == 64, 4x8 = 32 subtests)
+ // We keep a vector of 16 bit subtests here, and we program the
+ // MCBIST engine (i.e., spread the subtests over the 8 registers)
+ // when we're told to execute the program.
+ std::vector< subtest_t<MC, T, TT> >iv_subtests;
+
+ // Place to hold the value of the MCBIST Memory Parameter Register. We'll scom
+ // it when we execute the program.
+ fapi2::buffer<uint64_t> iv_parameters;
+
+ // Place to hold the value of the MCBIST Address Generation Config. We'll scom
+ // it when we execute the program.
+ fapi2::buffer<uint64_t> iv_addr_gen;
+
+ test_type iv_test_type;
+
+ poll_parameters iv_poll;
+
+ // Address Map Registers
+ // We might want to refactor to a vector ... BRS
+ // uint64_t iv_addr_map0;
+ // uint64_t iv_addr_map1;
+ // uint64_t iv_addr_map2;
+ // uint64_t iv_addr_map3;
+ //Perhaps this isn't the right approach, we can discuss and change if needed, leaving the above comments for now
+ fapi2::buffer<uint64_t> iv_addr_map0;
+ fapi2::buffer<uint64_t> iv_addr_map1;
+ fapi2::buffer<uint64_t> iv_addr_map2;
+ fapi2::buffer<uint64_t> iv_addr_map3;
+
+ // Data Rotate Seed and Config Registers
+ fapi2::buffer<uint64_t> iv_data_rotate_cnfg;
+ fapi2::buffer<uint64_t> iv_data_rotate_seed;
+
+ // Config register
+ fapi2::buffer<uint64_t> iv_config;
+
+ // Control register
+ fapi2::buffer<uint64_t> iv_control;
+
+ // True iff we want to run in asynchronous mode
+ bool iv_async;
+
+ // The pattern for the pattern generator
+ uint64_t iv_pattern;
+
+ // The pattern for the random 24b seeds
+ uint64_t iv_random24_data_seed;
+
+ // The pattern for the random 24b data seed mapping
+ uint64_t iv_random24_seed_map;
+
+ // The pattern for the pattern generator
+ fapi2::buffer<uint64_t> iv_compare_mask;
+
+ // The error stop conditions, thresholds for the program
+ stop_conditions<MC> iv_thresholds;
+};
+
+///
+/// @brief Load the mcbist config register
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mssTraits associtated with T
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_config( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ FAPI_INF("%s loading MCBIST Config 0x%016lx", mss::c_str(i_target), i_program.iv_config);
+
+ // Copy the program's config settings - we want to modify them if we're in sim.
+ fapi2::buffer<uint64_t> l_config = i_program.iv_config;
+
+ // If we're running in Cronus, there is no interrupt so any attention bits will
+ // hang something somewhere. Make sure there's nothing in this config which can
+ // turn on attention bits unless we're running in hostboot
+#ifndef __HOSTBOOT_MODULE
+
+ if(TT::CFG_ENABLE_ATTN_SUPPORT == mss::states::YES)
+ {
+ l_config.template clearBit<TT::CFG_ENABLE_HOST_ATTN>();
+ l_config.template clearBit<TT::CFG_ENABLE_SPEC_ATTN>();
+ }
+
+#endif
+
+ FAPI_TRY( fapi2::putScom(i_target, TT::CFGQ_REG, l_config) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Load the mcbist control register
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_control( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ FAPI_INF("loading MCBIST Control 0x%016lx for %s", i_program.iv_control, mss::c_str(i_target));
+ return fapi2::putScom(i_target, TT::CNTLQ_REG, i_program.iv_control);
+}
+
+
+///
+/// @brief Load the address generator config
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_addr_gen( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ FAPI_INF("loading MCBIST Address Generation 0x%016lx for %s", i_program.iv_addr_gen, mss::c_str(i_target));
+ return fapi2::putScom(i_target, TT::MCBAGRAQ_REG, i_program.iv_addr_gen);
+}
+
+///
+/// @brief Configure address range based on index
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @param[in] i_index which start/end pair to effect
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+/// @warn if address counting mode is enabled in the MCBIST program, these bits are start, len
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode config_address_range( const fapi2::Target<T>& i_target,
+ const uint64_t i_start,
+ const uint64_t i_end,
+ const uint64_t i_index )
+{
+ FAPI_INF("config MCBIST address range %d start: 0x%016lx (0x%016lx), end/len 0x%016lx (0x%016lx)",
+ i_index,
+ i_start, (i_start << mss::mcbist::address::MAGIC_PAD),
+ i_end, (i_end << mss::mcbist::address::MAGIC_PAD),
+ mss::c_str(i_target));
+ FAPI_ASSERT( i_index < TT::ADDRESS_PAIRS,
+ fapi2::MSS_MCBIST_INVALID_ADDRESS_PAIR_INDEX().
+ set_INDEX(i_index).
+ set_MC_TYPE(MC).
+ set_TARGET(i_target),
+ "An invalid address pair index %d for %s", i_index, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::address_pairs[i_index].first, i_start << mss::mcbist::address::MAGIC_PAD) );
+ FAPI_TRY( fapi2::putScom(i_target, TT::address_pairs[i_index].second, i_end << mss::mcbist::address::MAGIC_PAD) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Configure address range 0
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+/// @warn if address counting mode is enabled in the MCBIST program, these bits are start, len
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode config_address_range0( const fapi2::Target<T>& i_target,
+ const uint64_t i_start,
+ const uint64_t i_end )
+{
+ return config_address_range<MC>(i_target, i_start, i_end, 0);
+}
+
+
+///
+/// @brief Configure address range 1
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+/// @warn if address counting mode is enabled in the MCBIST program, these bits are start, len
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode config_address_range1( const fapi2::Target<T>& i_target,
+ const uint64_t i_start,
+ const uint64_t i_end )
+{
+ return config_address_range<MC>(i_target, i_start, i_end, 1);
+}
+
+
+///
+/// @brief Configure address range 2
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+/// @warn if address counting mode is enabled in the MCBIST program, these bits are start, len
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode config_address_range2( const fapi2::Target<T>& i_target,
+ const uint64_t i_start,
+ const uint64_t i_end )
+{
+ return config_address_range<MC>(i_target, i_start, i_end, 2);
+}
+
+
+///
+/// @brief Configure address range 3
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start 64b right-aligned address
+/// @param[in] i_end 64b right-aligned address
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note Only the right-most 37 bits of the start/end are used.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode config_address_range3( const fapi2::Target<T>& i_target,
+ const uint64_t i_start,
+ const uint64_t i_end )
+{
+ return config_address_range<MC>(i_target, i_start, i_end, 3);
+}
+
+///
+/// @brief Start or stop the MCBIST engine
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start_stop bool START for starting, STOP otherwise
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode start_stop( const fapi2::Target<T>& i_target, const bool i_start_stop )
+{
+ // This is the same as the CCS start_stop ... perhaps we need one template for all
+ // 'engine' control functions? BRS
+ fapi2::buffer<uint64_t> l_buf;
+ FAPI_TRY(fapi2::getScom(i_target, TT::CNTLQ_REG, l_buf));
+
+ FAPI_TRY( fapi2::putScom(i_target, TT::CNTLQ_REG,
+ i_start_stop ? l_buf.setBit<TT::MCBIST_START>() : l_buf.setBit<TT::MCBIST_STOP>()) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Resume the MCBIST engine
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode resume( const fapi2::Target<T>& i_target )
+{
+ fapi2::buffer<uint64_t> l_buf;
+
+ FAPI_TRY( fapi2::getScom(i_target, TT::CNTLQ_REG, l_buf) );
+ FAPI_TRY( fapi2::putScom(i_target, TT::CNTLQ_REG, l_buf.setBit<TT::MCBIST_RESUME>()) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Reset the MCBIST error logs
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode reset_errors( const fapi2::Target<T>& i_target )
+{
+ fapi2::buffer<uint64_t> l_buf;
+
+ FAPI_TRY( fapi2::getScom(i_target, TT::CNTLQ_REG, l_buf) );
+ FAPI_TRY( fapi2::putScom(i_target, TT::CNTLQ_REG, l_buf.setBit<TT::MCBIST_RESET_ERRORS>()) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return whether or not the MCBIST engine has an operation in progress
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[out] o_in_progress - false if no operation is in progress
+/// @return FAPI2_RC_SUCCESS if getScom succeeded
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode in_progress( const fapi2::Target<T>& i_target, bool& o_in_progress )
+{
+ fapi2::buffer<uint64_t> l_buf;
+
+ FAPI_TRY(fapi2::getScom(i_target, TT::STATQ_REG, l_buf));
+ o_in_progress = l_buf.getBit<TT::MCBIST_IN_PROGRESS>();
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Load a set of MCBIST subtests in to the MCBIST registers
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode load_mcbmr( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // Leave if there are no subtests.
+ if (0 == i_program.iv_subtests.size())
+ {
+ FAPI_INF("no subtests, nothing to do for %s", mss::c_str(i_target));
+ return fapi2::current_err;
+ }
+
+ // List of the 8 MCBIST registers - each holds 4 subtests.
+ const std::vector< uint64_t > l_memory_registers =
+ {
+ TT::MCBMR0_REG, TT::MCBMR1_REG, TT::MCBMR2_REG, TT::MCBMR3_REG,
+ TT::MCBMR4_REG, TT::MCBMR5_REG, TT::MCBMR6_REG, TT::MCBMR7_REG,
+ };
+
+ std::vector< uint64_t > l_memory_register_buffers =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ };
+
+ ssize_t l_bin = -1;
+ size_t l_register_shift = 0;
+
+ // We'll shift this in to position to indicate which subtest is the last
+ const uint64_t l_done_bit( 0x8000000000000000 >> TT::DONE );
+
+ // For now limit MCBIST programs to 32 subtests.
+ const auto l_program_size = i_program.iv_subtests.size();
+ FAPI_ASSERT( l_program_size <= TT::SUBTEST_PER_PROGRAM,
+ fapi2::MSS_MCBIST_PROGRAM_TOO_BIG().
+ set_PROGRAM_LENGTH(l_program_size).
+ set_TARGET(i_target).
+ set_MC_TYPE(MC),
+ "mcbist program of length %d exceeds arbitrary maximum of %d", l_program_size, TT::SUBTEST_PER_PROGRAM );
+
+ // Distribute the program over the 8 MCBIST subtest registers
+ // We need the index, so increment thru i_program.iv_subtests.size()
+ for (size_t l_index = 0; l_index < l_program_size; ++l_index)
+ {
+ l_bin = (l_index % TT::SUBTEST_PER_REG) == 0 ? l_bin + 1 : l_bin;
+ l_register_shift = (l_index % TT::SUBTEST_PER_REG) * TT::BITS_IN_SUBTEST;
+
+ l_memory_register_buffers[l_bin] |=
+ (uint64_t(i_program.iv_subtests[l_index].iv_mcbmr) << TT::LEFT_SHIFT) >> l_register_shift;
+
+ FAPI_DBG("putting subtest %d (0x%x) in MCBMR%dQ shifted %d 0x%016llx",
+ l_index, i_program.iv_subtests[l_index].iv_mcbmr, l_bin,
+ l_register_shift, l_memory_register_buffers[l_bin]);
+ }
+
+ // l_bin and l_register_shift are the values for the last subtest we'll tell the MCBIST about.
+ // We need to set that subtest's done-bit so the MCBIST knows it's the end of the line
+ l_memory_register_buffers[l_bin] |= l_done_bit >> l_register_shift;
+ FAPI_DBG("setting MCBMR%dQ subtest %llu as the last subtest 0x%016llx",
+ l_bin, l_register_shift, l_memory_register_buffers[l_bin]);
+
+ // ... and slam the values in to the registers.
+ // Could just decrement l_bin, but that scoms the subtests in backwards and is confusing
+ for (auto l_index = 0; l_index <= l_bin; ++l_index)
+ {
+ FAPI_TRY( fapi2::putScom(i_target, l_memory_registers[l_index], l_memory_register_buffers[l_index]) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Load a set of MCBIST address map registers
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode load_mcbamr( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ // Vector? Can decide when we fully understand the methods to twiddle the maps themselves. BRS
+ FAPI_INF("load MCBIST address map register 0: 0x%016lx for %s", i_program.iv_addr_map0, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCBAMR0A0Q_REG, i_program.iv_addr_map0) );
+
+ FAPI_INF("load MCBIST address map register 1: 0x%016lx for %s", i_program.iv_addr_map1, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCBAMR1A0Q_REG, i_program.iv_addr_map1) );
+
+ FAPI_INF("load MCBIST address map register 2: 0x%016lx for %s", i_program.iv_addr_map2, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCBAMR2A0Q_REG, i_program.iv_addr_map2) );
+
+ FAPI_INF("load MCBIST address map register 3: 0x%016lx for %s", i_program.iv_addr_map3, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCBAMR3A0Q_REG, i_program.iv_addr_map3) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Load MCBIST Memory Parameter Register
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] the target to effect
+/// @param[in] the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_mcbparm( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ FAPI_INF("load MCBIST parameter register: 0x%016lx for %s", i_program.iv_parameters, mss::c_str(i_target));
+ return fapi2::putScom(i_target, TT::MCBPARMQ_REG, i_program.iv_parameters);
+}
+
+///
+/// @brief Clear mcbist errors
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target fapi2::Target<T> of the MCBIST
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode clear_errors( const fapi2::Target<T> i_target )
+{
+ // TK: Clear the more detailed errors checked above
+ FAPI_INF("Clear MCBIST error state for %s", mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::MCBSTATQ_REG, 0) );
+ FAPI_TRY( fapi2::putScom(i_target, TT::SRERR0_REG, 0) );
+ FAPI_TRY( fapi2::putScom(i_target, TT::SRERR1_REG, 0) );
+ FAPI_TRY( fapi2::putScom(i_target, TT::FIRQ_REG, 0) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper for assembling the ecc/spare pattern
+/// @param[in] i_data the data pattern for a single beat
+/// @param[in] i_invert true if the data should be inverted
+/// @return The data pattern for this beat (a single byte of dataa)
+///
+inline uint8_t generate_eccspare_pattern_helper(const uint64_t& i_data, const bool i_invert )
+{
+ fapi2::buffer<uint64_t> l_data(i_invert ? ~i_data : i_data);
+ uint8_t l_byte = 0;
+ l_data.extractToRight<0, BITS_PER_BYTE>(l_byte);
+ return l_byte;
+}
+
+///
+/// @brief Generates the pattern for the ECC and/or spare data
+/// @param[in] i_pattern the pattern on which to operate
+/// @param[in] i_invert true if the pattern should be inverted
+/// @return ECC/spare pattern as needing to be put into the ECC/spare registers
+///
+inline fapi2::buffer<uint64_t> generate_eccspare_pattern(const pattern& i_pattern, const bool i_invert )
+{
+ constexpr uint64_t BYTE0 = BITS_PER_BYTE * 0;
+ constexpr uint64_t BYTE1 = BITS_PER_BYTE * 1;
+ constexpr uint64_t BYTE2 = BITS_PER_BYTE * 2;
+ constexpr uint64_t BYTE3 = BITS_PER_BYTE * 3;
+ constexpr uint64_t BYTE4 = BITS_PER_BYTE * 4;
+ constexpr uint64_t BYTE5 = BITS_PER_BYTE * 5;
+ constexpr uint64_t BYTE6 = BITS_PER_BYTE * 6;
+ constexpr uint64_t BYTE7 = BITS_PER_BYTE * 7;
+
+ fapi2::buffer<uint64_t> l_pattern;
+
+ // Pattern assembly is a tad weird for ECC/spare
+ // The pattern is stored in the same register by byte
+ // So we want to keep the same data as the rest of the data
+ // As such, we want to grab each piece of data on a byte by byte basis, flip as needed, and append it to the pattern
+
+ // Beat 0/1
+ l_pattern.insertFromRight<BYTE0, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[0].first, i_invert));
+ l_pattern.insertFromRight<BYTE1, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[0].second, i_invert));
+
+ // Beat 2/3
+ l_pattern.insertFromRight<BYTE2, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[1].first, i_invert));
+ l_pattern.insertFromRight<BYTE3, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[1].second, i_invert));
+
+ // Beat 4/5
+ l_pattern.insertFromRight<BYTE4, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[2].first, i_invert));
+ l_pattern.insertFromRight<BYTE5, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[2].second, i_invert));
+
+ // Beat 6/7
+ l_pattern.insertFromRight<BYTE6, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[3].first, i_invert));
+ l_pattern.insertFromRight<BYTE7, BITS_PER_BYTE>(generate_eccspare_pattern_helper(i_pattern[3].second, i_invert));
+
+ return l_pattern;
+}
+
+///
+/// @brief Load MCBIST ECC (and?) spare data pattern given a pattern
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_pattern an mcbist::patterns
+/// @param[in] i_invert whether to invert the pattern or not
+/// @note this overload disappears when we have real patterns.
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode load_eccspare_pattern( const fapi2::Target<T>& i_target, const pattern& i_pattern,
+ const bool i_invert );
+
+///
+/// @brief Load MCBIST pattern given a pattern
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_pattern an mcbist::patterns
+/// @param[in] i_invert whether to invert the pattern or not
+/// @note this overload disappears when we have real patterns.
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_pattern( const fapi2::Target<T>& i_target, const pattern& i_pattern, const bool i_invert )
+{
+ uint64_t l_address = TT::PATTERN0_REG;
+
+ // Checks that the pattern is of the expected length, if not, error out
+ // Creates helpers for FAPI_ASSERT
+ const auto EXPECTED_SIZE = TT::EXPECTED_PATTERN_SIZE;
+ const auto ACTUAL_SIZE = i_pattern.size();
+ FAPI_ASSERT(EXPECTED_SIZE == ACTUAL_SIZE,
+ fapi2::MSS_MCBIST_INCORRECT_PATTERN_LENGTH()
+ .set_TARGET(i_target)
+ .set_EXPECTED(EXPECTED_SIZE)
+ .set_ACTUAL(ACTUAL_SIZE),
+ "%s pattern expected size %u != actual size %u",
+ mss::c_str(i_target), EXPECTED_SIZE, ACTUAL_SIZE);
+
+ // TK: algorithm for patterns which include ECC bits in them
+ // Loop over the cache lines in the pattern. We write one half of the cache line
+ // to the even register and half to the odd.
+ for (const auto& l_cache_line : i_pattern)
+ {
+ const fapi2::buffer<uint64_t> l_value_first = i_invert ? ~l_cache_line.first : l_cache_line.first;
+ const fapi2::buffer<uint64_t> l_value_second = i_invert ? ~l_cache_line.second : l_cache_line.second;
+ FAPI_INF("Loading cache line pattern 0x%016lx 0x%016lx for %s", l_value_first, l_value_second, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, l_address, l_value_first) );
+ FAPI_TRY( fapi2::putScom(i_target, ++l_address, l_value_second) );
+ ++l_address;
+ }
+
+ FAPI_TRY(load_eccspare_pattern<MC>( i_target, i_pattern, i_invert ));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Check if patter is valid and get the index/invert
+/// @param[in] i_pattern the pattern
+/// @param[out] o_index the pattern index
+/// @param[out] o_invert if pattern is inverted
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+inline fapi2::ReturnCode get_pattern( uint64_t i_pattern, uint64_t& o_pattern_index, bool& o_invert)
+{
+ if (NO_PATTERN != i_pattern)
+ {
+ o_invert = false;
+
+ // Sanity check the pattern since they're just numbers.
+ // Belt-and-suspenders FAPI_ASSERT as the sim-only uses this API directly.
+ FAPI_ASSERT( i_pattern <= mcbist::LAST_PATTERN,
+ fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().
+ set_INDEX(i_pattern),
+ "Attempting to load a pattern which does not exist %d", i_pattern );
+
+ // The indexes are split in to even and odd where the odd indexes don't really exist.
+ // They're just indicating that we want to grab the even index and invert it. So calculate
+ // the proper vector index and acknowledge the inversion if necessary.
+ if (mss::is_odd(i_pattern))
+ {
+ o_invert = true;
+ i_pattern = i_pattern - 1;
+ }
+
+ o_pattern_index = i_pattern / 2;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Load MCBIST pattern given an index
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_index the pattern index
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_pattern( const fapi2::Target<T>& i_target, const uint64_t i_pattern )
+{
+ if (NO_PATTERN != i_pattern)
+ {
+ bool l_invert = false;
+ uint64_t l_pattern_index = 0;
+
+ FAPI_TRY(get_pattern(i_pattern, l_pattern_index, l_invert));
+ return load_pattern(i_target, patterns[l_pattern_index], l_invert);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Load MCBIST pattern given an index
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_pattern( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ return load_pattern(i_target, i_program.iv_pattern);
+}
+
+///
+/// @brief Load MCBIST maint pattern given a pattern
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @tparam MC the mc type of the T
+/// @param[in] i_target the target to effect
+/// @param[in] i_pattern an mcbist::patterns
+/// @param[in] i_invert whether to invert the pattern or not
+/// @note this overload disappears when we have real patterns.
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode load_maint_pattern( const fapi2::Target<T>& i_target, const pattern& i_pattern, const bool i_invert )
+{
+ // The scom registers are in the port target. PT: port traits
+ using PT = mcbistTraits<MC, TT::PORT_TYPE>;
+
+ // Init the fapi2 return code
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // Array access control
+ fapi2::buffer<uint64_t> l_aacr;
+ // Array access data
+ fapi2::buffer<uint64_t> l_aadr;
+
+ // first we must setup the access control register
+ // Setup the array address
+ // enable the auto increment bit
+ // set ecc mode bit on
+ l_aacr
+ .template writeBit<PT::RMW_WRT_BUFFER_SEL>(mss::states::OFF)
+ .template insertFromRight<PT::RMW_WRT_ADDRESS, PT::RMW_WRT_ADDRESS_LEN>(PT::MAINT_DATA_INDEX_START)
+ .template writeBit<PT::RMW_WRT_AUTOINC>(mss::states::ON)
+ .template writeBit<PT::RMW_WRT_ECCGEN>(mss::states::ON);
+
+ // This loop will be run twice to write the pattern twice. Once per 64B write.
+ // When MCBIST maint mode is in 64B mode it will only use the first 64B when in 128B mode
+ // MCBIST maint will use all 128B (it will perform two consecutive writes)
+ const auto l_ports = mss::find_targets<TT::PORT_TYPE>(i_target);
+ // Init the port map
+
+ for (const auto& p : l_ports)
+ {
+ l_aacr.template insertFromRight<PT::RMW_WRT_ADDRESS, PT::RMW_WRT_ADDRESS_LEN>(PT::MAINT_DATA_INDEX_START);
+
+ for (auto l_num_writes = 0; l_num_writes < 2; ++l_num_writes)
+ {
+ FAPI_INF("Setting the array access control register for %s.", mss::c_str(p));
+ FAPI_TRY( fapi2::putScom(p, PT::RMW_WRT_BUF_CTL_REG, l_aacr) );
+
+ for (const auto& l_cache_line : i_pattern)
+ {
+ fapi2::buffer<uint64_t> l_value_first = i_invert ? ~l_cache_line.first : l_cache_line.first;
+ fapi2::buffer<uint64_t> l_value_second = i_invert ? ~l_cache_line.second : l_cache_line.second;
+ FAPI_INF("Loading cache line pattern 0x%016lx 0x%016lx for %s", l_value_first, l_value_second, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(p, PT::RMW_WRT_BUF_DATA_REG, l_value_first));
+
+ // In order for the data to actually be written into the RMW buffer, we must issue a putscom to the MCA_AAER register
+ // This register is used for the ECC, we will just write all zero to this register. The ECC will be auto generated
+ // when the aacr MCA_WREITE_AACR_ECCGEN bit is set
+ FAPI_TRY( fapi2::putScom(p, PT::RMW_WRT_BUF_ECC_REG, 0) );
+
+ // No need to increment the address because the logic does it automatically when MCA_WREITE_AACR_AUTOINC is set
+ FAPI_TRY( fapi2::putScom(p, PT::RMW_WRT_BUF_DATA_REG, l_value_second) );
+
+ // In order for the data to actually be written into the RMW buffer, we must issue a putscom to the MCA_AAER register
+ // This register is used for the ECC, we will just write all zero to this register. The ECC will be auto generated
+ // when the aacr MCA_WREITE_AACR_ECCGEN bit is set
+ FAPI_TRY( fapi2::putScom(p, PT::RMW_WRT_BUF_ECC_REG, 0) );
+ }
+
+ l_aacr.template insertFromRight<PT::RMW_WRT_ADDRESS, PT::RMW_WRT_ADDRESS_LEN>(PT::MAINT_DATA_INDEX_END);
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+///
+/// @brief Load MCBIST maint pattern given an index
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_index the pattern index
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_maint_pattern( const fapi2::Target<T>& i_target, uint64_t i_pattern )
+{
+ if (NO_PATTERN != i_pattern)
+ {
+ bool l_invert = false;
+ uint64_t l_pattern_index = 0;
+
+ FAPI_TRY(get_pattern(i_pattern, l_pattern_index, l_invert));
+ return load_maint_pattern(i_target, patterns[l_pattern_index], l_invert);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Load MCBIST Maint mode pattern given an index
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_maint_pattern( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ return load_maint_pattern(i_target, i_program.iv_pattern);
+}
+
+
+///
+/// @brief Load MCBIST 24b random data seeds given a pattern index
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_random24_data_seed mcbist::random24_data_seed
+/// @param[in] i_random24_map mcbist::random24_seed_map
+/// @param[in] i_invert whether to invert the pattern or not
+/// @note this overload disappears when we have real patterns.
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode load_random24b_seeds( const fapi2::Target<T>& i_target,
+ const random24_data_seed& i_random24_data_seed,
+ const random24_seed_map& i_random24_map,
+ const bool i_invert )
+{
+ // Init the fapi2 return code
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ const uint64_t l_random_addr0 = TT::RANDOM_DATA_SEED0;
+ const uint64_t l_random_addr1 = TT::RANDOM_DATA_SEED1;
+ uint64_t l_index = 0;
+ uint64_t l_map_index = 0;
+ uint64_t l_map_offset = 0;
+
+ fapi2::buffer<uint64_t> l_mcbrsd0q;
+ fapi2::buffer<uint64_t> l_mcbrsd1q;
+
+
+ // We are going to loop through the random seeds and load them into the random seed registers
+ // Because the 24b random data seeds share the same registers as the 24b random data byte LFSR maps
+ // we will load those as well
+
+ for (const auto& l_seed : i_random24_data_seed)
+ {
+ FAPI_INF("Loading 24b random seed index %ld for %s", l_index, mss::c_str(i_target));
+ fapi2::buffer<uint64_t> l_value = i_invert ? ~l_seed : l_seed;
+
+ // Print an informational message to indicate if a random seed is 0
+ // TK Do we want an error here? 0 may be used on purpose to hold a byte at all 0 on purpose
+ if ( l_value == 0 )
+ {
+ FAPI_INF("Warning: Random 24b data seed is set to 0 for seed index %d for %s", l_index, mss::c_str(i_target));
+ }
+
+ // If we are processing the first 24b random data seed we will add it to the fapi buffer
+ // we won't load it yet because the second 24b seed will be loaded into the same register
+ if ( l_index == 0 )
+ {
+ l_mcbrsd0q.insertFromRight<TT::CFG_DGEN_RNDD_SEED0, TT::CFG_DGEN_RNDD_SEED0_LEN>(l_value);
+ }
+ // The second 24b random data seed is loaded into the same register as the first seed
+ // therefore we will add the second seed to the fapi buffer and then issue the putscom
+ else if (l_index == 1 )
+ {
+ l_mcbrsd0q.insertFromRight<TT::CFG_DGEN_RNDD_SEED1, TT::CFG_DGEN_RNDD_SEED1_LEN>(l_value);
+ FAPI_INF("Loading 24b random seeds 0 and 1 0x%016lx for %s", l_mcbrsd0q, mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, l_random_addr0, l_mcbrsd0q) );
+ }
+ // The third 24b random data seed occupies the same register as the random data byte maps. Therefore we first
+ // add the third random 24b data seed to the register and then loop through all of the byte mappings a total of
+ // 9. ach of the byte mappings associates a byte of the random data to a byte in the 24b random data LFSRs
+ // Each byte map is offset by 4 bits in the register.
+ else
+ {
+ l_mcbrsd1q.insertFromRight<TT::CFG_DGEN_RNDD_SEED2, TT::CFG_DGEN_RNDD_SEED2_LEN>(l_value);
+
+ for (const auto& l_map : i_random24_map)
+ {
+ l_map_offset = TT::CFG_DGEN_RNDD_DATA_MAPPING + (l_map_index * RANDOM24_SEED_MAP_FIELD_LEN);
+ FAPI_TRY(l_mcbrsd1q.insertFromRight(l_map, l_map_offset, RANDOM24_SEED_MAP_FIELD_LEN));
+ FAPI_INF("Loading 24b random seed map index %ld for %s", l_map_index, mss::c_str(i_target));
+ FAPI_ASSERT( l_map_index < mss::mcbist::MAX_NUM_RANDOM24_MAPS,
+ fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().
+ set_INDEX(l_map_index).
+ set_MC_TYPE(MC),
+ "Attempting to load a 24b random data seed map which does not exist %d", l_map_index );
+ ++l_map_index;
+ }
+
+ FAPI_TRY( fapi2::putScom(i_target, l_random_addr1, l_mcbrsd1q) );
+ }
+
+ FAPI_ASSERT( l_index < MAX_NUM_RANDOM24_SEEDS,
+ fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().
+ set_INDEX(l_index).
+ set_MC_TYPE(MC),
+ "Attempting to load a 24b random data seed which does not exist %d", l_index );
+ ++l_index;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+
+
+///
+/// @brief Load MCBIST 24b Random data seeds given a pattern index
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_data_seed the 24b random data seed index
+/// @param[in] i_seed_map the 24b random data map index
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_random24b_seeds( const fapi2::Target<T>& i_target, uint64_t i_data_seed,
+ uint64_t i_seed_map )
+{
+ if ((NO_RANDOM24_SEEDS != i_data_seed) && (NO_RANDOM24_SEED_MAP != i_seed_map))
+ {
+ bool l_invert = false;
+
+ // TK Want a new RC for random 24
+ // Sanity check the pattern since they're just numbers.
+ // Belt-and-suspenders FAPI_ASSERT as the sim-only uses this API directly.
+ FAPI_ASSERT( i_data_seed <= mcbist::LAST_RANDOM24_SEEDS,
+ fapi2::MSS_MEMDIAGS_INVALID_PATTERN_INDEX().
+ set_INDEX(i_data_seed).
+ set_MC_TYPE(MC),
+ "Attempting to load a 24b random data seed set which does not exist %d", i_data_seed );
+
+ // The indexes are split in to even and odd where the odd indexes don't really exist.
+ // They're just indicating that we want to grab the even index and invert it. So calculate
+ // the proper vector index and acknowledge the inversion if necessary.
+ if ((i_data_seed % 2) != 0)
+ {
+ l_invert = true;
+ i_data_seed -= 1;
+ }
+
+ return load_random24b_seeds(i_target, random24_data_seeds[i_data_seed / 2], random24_seed_maps[i_seed_map], l_invert);
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Load MCBIST 24b Random data seeds given a program conatining a pattern index
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_random24b_seeds( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ return load_random24b_seeds(i_target, i_program.iv_random24_data_seed, i_program.iv_random24_seed_map);
+}
+
+///
+/// @brief Loads the FIFO value if needed
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_fifo_mode( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ // Checks if FIFO mode is required by checking all subtests
+ const auto l_subtest_it = std::find_if(i_program.iv_subtests.begin(),
+ i_program.iv_subtests.end(), []( const mss::mcbist::subtest_t<MC, T, TT>& i_rhs) -> bool
+ {
+ return i_rhs.fifo_mode_required();
+ });
+
+ // if the FIFO load is not needed (no subtest requiring it was found), just exit out
+ if(l_subtest_it == i_program.iv_subtests.end())
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // Turns on FIFO mode
+ constexpr mss::states FIFO_ON = mss::states::ON;
+
+ FAPI_TRY( configure_wrq(i_target, FIFO_ON) );
+ FAPI_TRY( configure_rrq(i_target, FIFO_ON) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Load MCBIST data patterns and configuration
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_data_config( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ // First load the data pattern registers
+ FAPI_INF("Loading the data pattern seeds for %s!", mss::c_str(i_target));
+ FAPI_TRY( mss::mcbist::load_pattern(i_target, i_program.iv_pattern) );
+
+ // Load the 24b random data pattern seeds registers
+ FAPI_INF("Loading the 24b Random data pattern seeds for %s!", mss::c_str(i_target));
+ FAPI_TRY( mss::mcbist::load_random24b_seeds(i_target, i_program.iv_random24_data_seed,
+ i_program.iv_random24_seed_map) );
+
+ // Load the maint data pattern into the Maint entry in the RMW buffer
+ // TK Might want to only load the RMW buffer if maint commands are present in the program
+ // The load takes 33 Putscoms to load 16 64B registers, might slow down mcbist programs that
+ // don't need the RMW buffer maint entry loaded
+ FAPI_INF("Loading the maint data pattern into the RMW buffer for %s!", mss::c_str(i_target));
+ FAPI_TRY( mss::mcbist::load_maint_pattern(i_target, i_program.iv_pattern) );
+
+ FAPI_INF("Loading the data rotate config and seeds for %s!", mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::DATA_ROTATE_CNFG_REG, i_program.iv_data_rotate_cnfg) );
+ FAPI_TRY( fapi2::putScom(i_target, TT::DATA_ROTATE_SEED_REG, i_program.iv_data_rotate_seed) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Load MCBIST data compare mask registers
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode load_data_compare_mask( const fapi2::Target<T>& i_target,
+ const mcbist::program<MC>& i_program )
+{
+ // Init the fapi2 return code
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // Load the MCBCM Data compare masks
+ const auto l_ports = mss::find_targets<TT::PORT_TYPE>(i_target);
+ FAPI_INF("Loading the MCBIST data compare mask registers!");
+
+ for (const auto& p : l_ports)
+ {
+ FAPI_TRY( fapi2::putScom(p, TT::COMPARE_MASK, i_program.iv_compare_mask) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Load MCBIST Thresholds
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_thresholds the thresholds
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_thresholds( const fapi2::Target<T>& i_target, const uint64_t i_thresholds )
+{
+ FAPI_INF("load MCBIST threshold register: 0x%016lx for %s", i_thresholds, mss::c_str(i_target) );
+ return fapi2::putScom(i_target, TT::THRESHOLD_REG, i_thresholds);
+}
+
+///
+/// @brief Load MCBIST Threshold Register
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType - derived
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the program containing the thresholds
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode load_thresholds( const fapi2::Target<T>& i_target, const mcbist::program<MC>& i_program )
+{
+ return load_thresholds(i_target, i_program.iv_thresholds);
+}
+
+///
+/// @brief Read entries from MCBIST Read Modify Write (RMW) array
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start_addr the array address to read first
+/// @param[in] i_num_entries the number of array entries to read
+/// @param[in] i_roll_over_for_compare_mode set to true if only using first
+/// NUM_COMPARE_INFO_ENTRIES of array, so array address rolls over at correct value
+/// @param[out] o_data vector of output data
+/// @param[out] o_ecc_data vector of ecc data
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note The number of entries in the array depends on i_roll_over_for_compare_mode parameter:
+/// (NUM_COMPARE_LOG_ENTRIES for false, NUM_COMPARE_INFO_ENTRIES for true) but user may read more than
+/// that since reads work in a circular buffer fashion
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode read_rmw_array(const fapi2::Target<T>& i_target,
+ const uint64_t i_start_addr,
+ const uint64_t i_num_entries,
+ const bool i_roll_over_for_compare_mode,
+ std::vector< fapi2::buffer<uint64_t> >& o_data,
+ std::vector< fapi2::buffer<uint64_t> >& o_ecc_data)
+{
+ fapi2::buffer<uint64_t> l_control_value;
+ fapi2::buffer<uint64_t> l_data;
+ uint64_t l_array_addr = i_start_addr;
+
+ // Clear out any stale values from output vectors
+ o_data.clear();
+ o_ecc_data.clear();
+
+ // Set the control register for the RMW array
+ l_control_value.template writeBit<TT::RMW_WRT_BUFFER_SEL>(TT::SELECT_RMW_BUFFER)
+ // set start address
+ .template insertFromRight<TT::RMW_WRT_ADDRESS, TT::RMW_WRT_ADDRESS_LEN>(l_array_addr)
+ // enable the auto increment bit
+ .template setBit<TT::RMW_WRT_AUTOINC>()
+ // set ecc mode bit off
+ .template clearBit<TT::RMW_WRT_ECCGEN>();
+
+ FAPI_INF("Setting the RMW array access control register for %s.", mss::c_str(i_target));
+ FAPI_TRY( fapi2::putScom(i_target, TT::RMW_WRT_BUF_CTL_REG, l_control_value) );
+
+ for (uint8_t l_index = 0; l_index < i_num_entries; ++l_index)
+ {
+ // Read info out of RMW array and put into output vector
+ // Note that since we enabled AUTOINC above, reading ECC_REG will increment
+ // the array pointer so the next DATA_REG read will read the next array entry
+ FAPI_TRY( fapi2::getScom(i_target, TT::RMW_WRT_BUF_DATA_REG, l_data) );
+
+ FAPI_INF("RMW data index %d is: %016lx for %s", l_array_addr, l_data, mss::c_str(i_target));
+ o_data.push_back(l_data);
+
+ // Need to read ecc register to increment array index
+ FAPI_TRY( fapi2::getScom(i_target, TT::RMW_WRT_BUF_ECC_REG, l_data) );
+ o_ecc_data.push_back(l_data);
+ ++l_array_addr;
+
+ // Need to manually roll over address if we go beyond NUM_COMPARE_INFO_ENTRIES
+ // Since actual array is bigger than what is used for compare mode
+ if (i_roll_over_for_compare_mode &&
+ (l_array_addr >= TT::NUM_COMPARE_INFO_ENTRIES))
+ {
+ FAPI_INF("Rolling over the RMW array access control register address from %d to %d for %s.", (i_start_addr + l_index),
+ 0, mss::c_str(i_target));
+ l_control_value.clearBit<TT::RMW_WRT_ADDRESS, TT::RMW_WRT_ADDRESS_LEN>();
+ FAPI_TRY( fapi2::putScom(i_target, TT::RMW_WRT_BUF_CTL_REG, l_control_value) );
+ l_array_addr = 0;
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Read entries from MCBIST Read Modify Write (RMW) array
+/// Overload for the case where o_ecc_data is not needed
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start_addr the array address to read first
+/// @param[in] i_num_entries the number of array entries to read
+/// @param[in] i_roll_over_for_compare_mode set to true if only using first
+/// NUM_COMPARE_INFO_ENTRIES of array, so array address rolls over at correct value
+/// @param[out] o_data vector of output data
+/// @return FAPI2_RC_SUCCSS iff ok
+/// @note The number of entries in the array depends on i_roll_over_for_compare_mode parameter:
+/// (NUM_COMPARE_LOG_ENTRIES for false, NUM_COMPARE_INFO_ENTRIES for true) but user may read more than
+/// that since reads work in a circular buffer fashion
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+inline fapi2::ReturnCode read_rmw_array(const fapi2::Target<T>& i_target,
+ const uint64_t i_start_addr,
+ const uint64_t i_num_entries,
+ const bool i_roll_over_for_compare_mode,
+ std::vector< fapi2::buffer<uint64_t> >& o_data)
+{
+ std::vector< fapi2::buffer<uint64_t> > l_temp;
+ return read_rmw_array(i_target, i_start_addr, i_num_entries, i_roll_over_for_compare_mode, o_data, l_temp);
+}
+
+///
+/// @brief Configures broadcast mode, if it is needed
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType
+/// @param[in] i_target the target to effect
+/// @param[in,out] io_program the mcbist::program
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+fapi2::ReturnCode configure_broadcast_mode(const fapi2::Target<T>& i_target, mcbist::program<MC>& io_program);
+
+///
+/// @brief Read entries from MCBIST Read Buffer (RB) array
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start_addr the array address to read first
+/// @param[in] i_num_entries the number of array entries to read
+/// @param[out] o_data vector of output data
+/// @param[out] o_ecc_data vector of ecc data
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode read_rb_array(const fapi2::Target<T>& i_target,
+ const uint64_t i_start_addr,
+ const uint64_t i_num_entries,
+ std::vector< fapi2::buffer<uint64_t> >& o_data,
+ std::vector< fapi2::buffer<uint64_t> >& o_ecc_data);
+
+///
+/// @brief Read entries from MCBIST Read Buffer (RB) array
+/// Overload for the case where o_ecc_data is not needed
+/// @tparam MC the mc type of the T
+/// @tparam T, the fapi2::TargetType
+/// @tparam TT, the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_start_addr the array address to read first
+/// @param[in] i_num_entries the number of array entries to read
+/// @param[out] o_data vector of output data
+/// @return FAPI2_RC_SUCCSS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode read_rb_array(const fapi2::Target<T>& i_target,
+ const uint64_t i_start_addr,
+ const uint64_t i_num_entries,
+ std::vector< fapi2::buffer<uint64_t> >& o_data)
+{
+ std::vector< fapi2::buffer<uint64_t> > l_temp;
+ return read_rb_array<MC>(i_target, i_start_addr, i_num_entries, o_data, l_temp);
+}
+
+///
+/// @brief Poll the mcbist engine and check for errors
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program, the mcbist program which is executing
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode poll( const fapi2::Target<T>& i_target, const program<MC>& i_program )
+{
+ using ET = mss::mcbistMCTraits<MC>;
+ fapi2::buffer<uint64_t> l_status;
+
+ const uint64_t l_done = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_DONE>();
+ const uint64_t l_fail = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_FAIL>();
+ const uint64_t l_in_progress = fapi2::buffer<uint64_t>().setBit<TT::MCBIST_IN_PROGRESS>();
+
+ // A small vector of addresses to poll during the polling loop
+ const std::vector<mss::poll_probe<T>> l_probes =
+ {
+ {i_target, "mcbist current address", TT::LAST_ADDR_REG},
+ };
+
+ mss::poll(i_target, TT::STATQ_REG, i_program.iv_poll,
+ [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_DBG("mcbist statq 0x%016lx, remaining: %d", stat_reg, poll_remaining);
+ l_status = stat_reg;
+ return l_status.getBit<TT::MCBIST_IN_PROGRESS>() != 1;
+ },
+ l_probes);
+
+ // Check to see if we're still in progress - meaning we timed out.
+ FAPI_ASSERT((l_status & l_in_progress) != l_in_progress,
+ ET::mcbist_timeout().set_MC_TARGET(i_target),
+ "MCBIST timed out %s", mss::c_str(i_target));
+
+ // The control register has a bit for done-and-happy and a bit for done-and-unhappy
+ if ( ((l_status & l_done) == l_done) || ((l_status & l_fail) == l_fail) )
+ {
+ FAPI_INF("MCBIST completed, processing errors for %s", mss::c_str(i_target));
+
+ // We're done. It doesn't mean that there were no errors.
+ FAPI_TRY( i_program.process_errors(i_target) );
+
+ // If we're here there were no errors, but lets report if the fail bit was set anyway.
+ FAPI_ASSERT( (l_status & l_fail) != l_fail,
+ ET::mcbist_unknown_failure()
+ .set_MC_TARGET(i_target)
+ .set_STATUS_REGISTER(l_status),
+ "%s MCBIST reported a fail, but process_errors didn't find it 0x%016llx",
+ mss::c_str(i_target), l_status );
+
+ // And if we're here all is good with the world.
+ return fapi2::current_err;
+ }
+
+ FAPI_ASSERT(false,
+ ET::mcbist_data_fail()
+ .set_MC_TARGET(i_target)
+ .set_STATUS_REGISTER(l_status),
+ "%s MCBIST executed but we got corrupted data in the control register 0x%016llx",
+ mss::c_str(i_target), l_status );
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Clear the errors helper. Chip can specialise this
+/// function to put any necessary workaround in it.
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist program to execute
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode clear_error_helper( const fapi2::Target<T>& i_target, const program<MC>& i_program )
+{
+ FAPI_TRY( clear_errors(i_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Execute the mcbist program
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target to effect
+/// @param[in] i_program the mcbist program to execute
+/// @return fapi2::ReturnCode, FAPI2_RC_SUCCESS iff OK
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T>, typename ET = mcbistMCTraits<MC> >
+fapi2::ReturnCode execute( const fapi2::Target<T>& i_target, const program<MC>& i_program )
+{
+ fapi2::buffer<uint64_t> l_status;
+ bool l_poll_result = false;
+ poll_parameters l_poll_parameters;
+
+ // Init the fapi2 return code
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // Before we go off into the bushes, lets see if there are any instructions in the
+ // program. If not, we can save everyone the hassle
+ FAPI_ASSERT(0 != i_program.iv_subtests.size(),
+ fapi2::MSS_MEMDIAGS_NO_MCBIST_SUBTESTS().set_MC_TARGET(i_target),
+ "Attempt to run an MCBIST program with no subtests on %s", mss::c_str(i_target));
+
+ FAPI_TRY( clear_error_helper<MC>(i_target, const_cast<program<MC>&>(i_program)) );
+
+ // Configures the write/read FIFO bit
+ FAPI_TRY( load_fifo_mode<MC>( i_target, i_program) );
+
+ // Slam the address generator config
+ FAPI_TRY( load_addr_gen<MC>(i_target, i_program) );
+
+ // Slam the parameters in to the mcbist parameter register
+ FAPI_TRY( load_mcbparm<MC>(i_target, i_program) );
+
+ // Slam the configured address maps down
+ FAPI_TRY( load_mcbamr( i_target, i_program) );
+
+ // Slam the config register down
+ FAPI_TRY( load_config<MC>( i_target, i_program) );
+
+ // Slam the control register down
+ FAPI_TRY( load_control<MC>( i_target, i_program) );
+
+ // Load the patterns and any associated bits for random, etc
+ FAPI_TRY( load_data_config<MC>( i_target, i_program) );
+
+ // Load the thresholds
+ FAPI_TRY( load_thresholds<MC>( i_target, i_program) );
+
+ // Slam the subtests in to the mcbist registers
+ // Always do this last so the action file triggers see the other bits set
+ FAPI_TRY( load_mcbmr<MC>(i_target, i_program) );
+
+ // Start the engine, and then poll for completion
+ FAPI_TRY(start_stop<MC>(i_target, mss::START));
+
+ // Verify that the in-progress bit has been set, so we know we started
+ // Don't use the program's poll as it could be a very long time. Use the default poll.
+ l_poll_result = mss::poll(i_target, TT::STATQ_REG, l_poll_parameters,
+ [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_DBG("looking for mcbist start, mcbist statq 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ l_status = stat_reg;
+ // We're done polling when either we see we're in progress or we see we're done.
+ return (l_status.getBit<TT::MCBIST_IN_PROGRESS>() == true) || (l_status.getBit<TT::MCBIST_DONE>() == true);
+ });
+
+ // So we've either run/are running or we timed out waiting for the start.
+ FAPI_ASSERT( l_poll_result == true,
+ ET::memdiags_failed_to_start().set_MC_TARGET(i_target),
+ "The MCBIST engine failed to start its program" );
+
+ // If the user asked for async mode, we can leave. Otherwise, poll and check for errors
+ if (!i_program.iv_async)
+ {
+ return mcbist::poll(i_target, i_program);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // namespace mcbist
+
+namespace ecc
+{
+
+///
+/// @brief Clear all MAINT.ECC counters
+/// @tparam T the fapi2::TargetType - derived
+/// @param[in] i_target the fapi2 target
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T >
+inline fapi2::ReturnCode clear_all_counters( const fapi2::Target<T>& i_target )
+{
+ return ( mss::mcbist::reset_errors(i_target) );
+}
+
+} // namespace ecc
+
+} // namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H
new file mode 100644
index 000000000..37e35c48d
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H
@@ -0,0 +1,441 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 gen_mss_mcbist_address.H
+/// @brief Class for mcbist related addresses (addresses below the hash translation)
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_MCBIST_ADDRESS_H_
+#define _GEN_MSS_MCBIST_ADDRESS_H_
+
+#include <fapi2.H>
+#include <utility>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+
+namespace mss
+{
+
+namespace mcbist
+{
+
+///
+/// @class address
+/// @brief Represents a physical address in memory
+/// @note
+/// 0:1 port select
+/// 2 dimm select
+/// 3:4 mrank(0 to 1)
+/// 5:7 srank(0 to 2)
+/// 8:25 row(0 to 17)
+/// 26:32 col(3 to 9)
+/// 33:35 bank(0 to 2)
+/// 36:37 bank_group(0 to 1)
+///
+class address
+{
+ public:
+
+ // How far over we shift to align the address in either the register or a buffer
+ static constexpr uint64_t MAGIC_PAD = 26;
+
+ // first is the start bit of the field, second is the length
+ using field = std::pair<uint64_t, uint64_t>;
+
+ constexpr static field PORT = {0, 2};
+ constexpr static field DIMM = {2, 1};
+ constexpr static field MRANK = {3, 2};
+ constexpr static field SRANK = {5, 3};
+ constexpr static field ROW = {8, 18};
+ constexpr static field COL = {26, 7};
+ constexpr static field BANK = {33, 3};
+ constexpr static field BANK_GROUP = {36, 2};
+ constexpr static field LAST_VALID = BANK_GROUP;
+
+ ///
+ /// @brief default ctor
+ ///
+ address() = default;
+
+ // Used when accessing an integral value containing a port and DIMM combination
+ static constexpr uint64_t DIMM_BIT = 63;
+ static constexpr uint64_t PORT_START = 61;
+ static constexpr uint64_t PORT_LEN = 2;
+
+ ///
+ /// @brief Construct an address from a uint64_t
+ /// @param[in] i_value representing an address
+ ///
+ address( const uint64_t i_value ):
+ iv_address(i_value << MAGIC_PAD)
+ {
+ }
+
+ ///
+ /// @brief Construct an address from the provided buffer
+ /// @param[in] i_address fapi2::buffer address
+ ///
+ address(const fapi2::buffer<uint64_t>& i_address):
+ iv_address(i_address)
+ {
+ }
+
+ ///
+ /// @brief Conversion operator to uint64_t
+ /// @warn Right-aligns the address
+ ///
+ inline operator uint64_t() const
+ {
+ return iv_address >> MAGIC_PAD;
+ }
+
+ ///
+ /// @brief Set a field for an address
+ /// @tparam F the field to set
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ ///
+ template< const field& F >
+ inline address& set_field( const uint64_t i_value )
+ {
+ iv_address.insertFromRight<F.first, F.second>(i_value);
+ return *this;
+ }
+
+ ///
+ /// @brief Get a field from an address
+ /// @tparam F the field to get
+ /// @return right-aligned uint64_t representing the value
+ ///
+ template< const field& F >
+ inline uint64_t get_field() const
+ {
+ uint64_t l_value = 0;
+ iv_address.extractToRight<F.first, F.second>(l_value);
+ return l_value;
+ }
+
+ ///
+ /// @brief Get a range of addresses.
+ /// @tparam[in] F the left-most valid field. So, if the address was for master rank,
+ /// the left-most valid field would be MRANK
+ /// @param[out] o_end representing an address to end at
+ /// @note this pointer is the start address
+ ///
+ template< const field& F >
+ inline void get_range( address& o_end ) const
+ {
+ constexpr uint64_t START = F.first + F.second;
+ constexpr uint64_t LEN = (LAST_VALID.first + LAST_VALID.second) - START;
+
+ // All we need to do is fill in the bits to the right of the last valid field
+ o_end.iv_address = iv_address;
+ o_end.iv_address.setBit<START, LEN>();
+ }
+
+
+ ///
+ /// @brief Get an end address for sim mode
+ /// @param[out] o_end representing an address to end at
+ /// @note this pointer is the start address
+ ///
+ inline void get_sim_end_address( address& o_end ) const
+ {
+ // This magic number represents a range of addresses which cover all
+ // cache lines the training algorithms touch. By effecting 0 - this end
+ // address you'll effect everything which has bad ECC in the sim.
+ // TODO: this will have to change for explorer. it's algorithm dependent.
+ // we'll need to talk to the microchip about this
+ constexpr uint64_t l_magic_sim_number = 0b1000000;
+
+ get_range<COL>(o_end);
+ o_end.set_column(l_magic_sim_number);
+ return;
+ }
+
+ ///
+ /// @brief Get a range of addresses given a master rank
+ /// @param[in] i_start representing an address to start from
+ /// @param[out] o_end representing an address to end at
+ ///
+ inline static void get_mrank_range( const address& i_start, address& o_end )
+ {
+ i_start.get_range<MRANK>(o_end);
+ }
+
+ ///
+ /// @brief Get a range of addresses given a master rank
+ /// @param[in] i_port representing the port for the starting address
+ /// @param[in] i_dimm representing the dimm for the starting address
+ /// @param[in] i_mrank representing the master rank for the starting address
+ /// @param[out] o_start representing an address to start from
+ /// @param[out] o_end representing an address to end at
+ ///
+ inline static void get_mrank_range( const uint64_t i_port,
+ const uint64_t i_dimm,
+ const uint64_t i_mrank,
+ address& o_start,
+ address& o_end )
+ {
+ o_start.set_port(i_port).set_dimm(i_dimm).set_master_rank(i_mrank);
+ get_mrank_range(o_start, o_end);
+ }
+
+ ///
+ /// @brief Get a range of addresses given a slave rank
+ /// @param[in] i_start representing an address to start from
+ /// @param[out] o_end representing an address to end at
+ ///
+ inline static void get_srank_range( const address& i_start, address& o_end )
+ {
+ i_start.get_range<SRANK>(o_end);
+ }
+
+ ///
+ /// @brief Get a range of addresses given a slave rank
+ /// @param[in] i_port representing the port for the starting address
+ /// @param[in] i_dimm representing the dimm for the starting address
+ /// @param[in] i_mrank representing the master rank for the starting address
+ /// @param[in] i_srank representing the slave rank for the starting address
+ /// @param[out] o_start representing an address to start from
+ /// @param[out] o_end representing an address to end at
+ ///
+ inline static void get_srank_range( const uint64_t i_port, const uint64_t i_dimm,
+ const uint64_t i_mrank, const uint64_t i_srank,
+ address& o_start,
+ address& o_end )
+ {
+ o_start.set_port(i_port).set_dimm(i_dimm).set_master_rank(i_mrank).set_slave_rank(i_srank);
+ get_srank_range(o_start, o_end);
+ }
+
+ ///
+ /// @brief Set the port value for an address
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ ///
+ inline address& set_port( const uint64_t i_value )
+ {
+ return set_field<PORT>(i_value);
+ }
+
+ ///
+ /// @brief Get the port value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_port() const
+ {
+ return get_field<PORT>();
+ }
+
+ ///
+ /// @brief Set the DIMM value for an address
+ /// @param[in] i_value the value to set
+ /// @note 0 is the DIMM[0] != 0 is DIMM[1]
+ /// @return address& for method chaining
+ ///
+ inline address& set_dimm( const uint64_t i_value )
+ {
+ return set_field<DIMM>(i_value);
+ }
+
+ ///
+ /// @brief Get the DIMM value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_dimm() const
+ {
+ return get_field<DIMM>();
+ }
+
+ ///
+ /// @brief Set the port and DIMM value for an address
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ /// @note Useful for indexing all ports/DIMM on a controller
+ ///
+ inline address& set_port_dimm( const fapi2::buffer<uint64_t> i_value )
+ {
+ uint64_t l_read_port = 0;
+
+ i_value.extractToRight<PORT_START, PORT_LEN>(l_read_port);
+ return set_dimm(i_value.getBit<DIMM_BIT>()).set_port(l_read_port);
+ }
+
+ ///
+ /// @brief Get the port and DIMM value for an address
+ /// @return right-aligned uint64_t representing the value
+ /// @note Useful for indexing all ports/DIMM on a controller
+ ///
+ inline uint64_t get_port_dimm() const
+ {
+ fapi2::buffer<uint64_t> l_value;
+
+ l_value.insertFromRight<PORT_START, PORT_LEN>(get_port());
+ l_value.writeBit<DIMM_BIT>(get_dimm());
+
+ return l_value;
+ }
+
+ ///
+ /// @brief Set the master rank value for an address
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ ///
+ inline address& set_master_rank( const uint64_t i_value )
+ {
+ return set_field<MRANK>(i_value);
+ }
+
+ ///
+ /// @brief Get the master rank value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_master_rank() const
+ {
+ return get_field<MRANK>();
+ }
+
+
+ ///
+ /// @brief Set the slave rank value for an address
+ /// @param[in] i_value the value to set
+ ///
+ inline void set_slave_rank( const uint64_t i_value )
+ {
+ set_field<SRANK>(i_value);
+ }
+
+ ///
+ /// @brief Get the slave rank value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_slave_rank() const
+ {
+ return get_field<SRANK>();
+ }
+
+
+ ///
+ /// @brief Set the row value for an address
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ ///
+ inline address& set_row( const uint64_t i_value )
+ {
+ return set_field<ROW>(i_value);
+ }
+
+ ///
+ /// @brief Get the row value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_row() const
+ {
+ return get_field<ROW>();
+ }
+
+
+ ///
+ /// @brief Set the column value for an address
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ ///
+ inline address& set_column( const uint64_t i_value )
+ {
+ return set_field<COL>(i_value);
+ }
+
+ ///
+ /// @brief Get the column value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_column() const
+ {
+ return get_field<COL>();
+ }
+
+
+ ///
+ /// @brief Set the bank value for an address
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ ///
+ inline address& set_bank( const uint64_t i_value )
+ {
+ return set_field<BANK>(i_value);
+ }
+
+ ///
+ /// @brief Get the bank value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_bank() const
+ {
+ return get_field<BANK>();
+ }
+
+ ///
+ /// @brief Set the bank group value for an address
+ /// @param[in] i_value the value to set
+ /// @return address& for method chaining
+ ///
+ inline address& set_bank_group( const uint64_t i_value )
+ {
+ return set_field<BANK_GROUP>(i_value);
+ }
+
+ ///
+ /// @brief Get the bank group value for an address
+ /// @return right-aligned uint64_t representing the value
+ ///
+ inline uint64_t get_bank_group() const
+ {
+ return get_field<BANK_GROUP>();
+ }
+
+ ///
+ /// @brief Get the buffer object for bit operations
+ /// @return fapi2::buffer<uint64_t>&
+ ///
+ inline fapi2::buffer<uint64_t> get_address_buffer() const
+ {
+ return iv_address;
+ }
+
+ private:
+ // We use a fapi2 buffer as it has static compile-time support
+ fapi2::buffer<uint64_t> iv_address;
+};
+
+} // close namespace mcbist
+} // close namespace mss
+
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_ecc_trap_address.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_ecc_trap_address.H
new file mode 100644
index 000000000..ba8b1f47b
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_ecc_trap_address.H
@@ -0,0 +1,176 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_ecc_trap_address.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 gen_mss_mcbist_ecc_trap_address.H
+/// @brief Class for ECC trap addresses (addresses below the hash translation)
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_MCBIST_ECC_TRAP_ADDRESS_H_
+#define _GEN_MSS_MCBIST_ECC_TRAP_ADDRESS_H_
+
+#include <fapi2.H>
+#include <utility>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+///
+/// @class trap_address
+/// @brief Converts trap address into mcbist::address
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type defaults to fapi2::TARGET_TYPE_MCA or TARGET_TYPE_MEM_PORT
+/// @tparam TT traits type defaults to eccTraits<T>
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::FWMS_ADDR_TARGET_TYPE, typename TT = mss::eccTraits<MC, T> >
+class trap_address
+{
+ public:
+ // first is the start bit of the field, second is the length
+ using field = std::pair<uint64_t, uint64_t>;
+
+ constexpr static field PORT = {TT::TRAP_ADDRESS_PORT, TT::TRAP_ADDRESS_PORT_LEN};
+ constexpr static field DIMM = {TT::TRAP_ADDRESS_DIMM, TT::TRAP_ADDRESS_DIMM_LEN};
+ constexpr static field MRANK = {TT::TRAP_ADDRESS_MRANK, TT::TRAP_ADDRESS_MRANK_LEN};
+ constexpr static field SRANK = {TT::TRAP_ADDRESS_SRANK, TT::TRAP_ADDRESS_SRANK_LEN};
+ constexpr static field ROW = {TT::TRAP_ADDRESS_ROW, TT::TRAP_ADDRESS_ROW_LEN};
+ constexpr static field COL = {TT::TRAP_ADDRESS_COL, TT::TRAP_ADDRESS_COL_LEN};
+ constexpr static field BANK = {TT::TRAP_ADDRESS_BANK, TT::TRAP_ADDRESS_BANK_LEN};
+ constexpr static field BANK_GROUP = {TT::TRAP_ADDRESS_BANK_GROUP, TT::TRAP_ADDRESS_BANK_GROUP_LEN};
+
+ trap_address() = default;
+
+ ///
+ /// @brief Construct an address from a uint64_t (scom'ed value)
+ /// @param[in] i_value representing raw value from FWMS register
+ ///
+ trap_address( const uint64_t& i_value ):
+ iv_value(i_value)
+ {
+ }
+
+ ///
+ /// @brief Construct an address from an mcbist::address
+ /// @param[in] i_mcbist_address mcbist formatted address
+ /// @note Construction of mcbist::address from trap_address
+ /// @note located in mcbist::address class
+ ///
+ trap_address( const mcbist::address& i_mcbist_address )
+ {
+ iv_value.insertFromRight<PORT.first, PORT.second>(i_mcbist_address.get_field<mcbist::address::PORT>());
+ iv_value.insertFromRight<DIMM.first, DIMM.second>(i_mcbist_address.get_field<mcbist::address::DIMM>());
+ iv_value.insertFromRight<MRANK.first, MRANK.second>(i_mcbist_address.get_field<mcbist::address::MRANK>());
+ iv_value.insertFromRight<SRANK.first, SRANK.second>(i_mcbist_address.get_field<mcbist::address::SRANK>());
+ iv_value.insertFromRight<ROW.first, ROW.second>(i_mcbist_address.get_field<mcbist::address::ROW>());
+ iv_value.insertFromRight<COL.first, COL.second>(i_mcbist_address.get_field<mcbist::address::COL>());
+ iv_value.insertFromRight<BANK.first, BANK.second>(i_mcbist_address.get_field<mcbist::address::BANK>());
+ iv_value.insertFromRight<BANK_GROUP.first, BANK_GROUP.second>
+ (i_mcbist_address.get_field<mcbist::address::BANK_GROUP>());
+ }
+
+ ///
+ /// @brief Construct an mcbist::address from an ecc::trap_address
+ /// @return the mcbist::address
+ ///
+ inline operator mss::mcbist::address() const
+ {
+ mss::mcbist::address l_mcbist_address;
+ l_mcbist_address.set_port (this->get_field<PORT>());
+ l_mcbist_address.set_dimm (this->get_field<DIMM>());
+ l_mcbist_address.set_master_rank(this->get_field<MRANK>());
+ l_mcbist_address.set_slave_rank (this->get_field<SRANK>());
+ l_mcbist_address.set_row (this->get_field<ROW>());
+ l_mcbist_address.set_column (this->get_field<COL>());
+ l_mcbist_address.set_bank (this->get_field<BANK>());
+ l_mcbist_address.set_bank_group (this->get_field<BANK_GROUP>());
+ return l_mcbist_address;
+ }
+
+ ///
+ /// @brief Conversion operator to uint64_t
+ ///
+ inline operator uint64_t() const
+ {
+ uint64_t l_temp = 0;
+ iv_value.extract<TT::TRAP_ADDRESS, TT::TRAP_ADDRESS_LEN, TT::TRAP_ADDRESS>(l_temp);
+ return l_temp;
+ }
+
+ ///
+ /// @brief Get a field from an address
+ /// @tparam F the field to get
+ /// @return right-aligned uint64_t representing the value
+ ///
+ template< const field& F >
+ inline uint64_t get_field() const
+ {
+ uint64_t l_value = 0;
+ iv_value.extractToRight<F.first, F.second>(l_value);
+ return l_value;
+ }
+
+ private:
+ fapi2::buffer<uint64_t> iv_value;
+};
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::PORT;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::DIMM;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::MRANK;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::SRANK;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::ROW;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::COL;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::BANK;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename trap_address<MC, T, TT>::field trap_address<MC, T, TT>::BANK_GROUP;
+
+
+} // close namespace ecc
+} // close namespace mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_fwms_address.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_fwms_address.H
new file mode 100644
index 000000000..2b1bda8fe
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_fwms_address.H
@@ -0,0 +1,175 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_fwms_address.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 gen_mss_mcbist_fwms_address.H
+/// @brief Class for FWMS trap addresses (addresses below the hash translation)
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_MCBIST_FWMS_ADDRESS_H_
+#define _GEN_MSS_MCBIST_FWMS_ADDRESS_H_
+
+#include <fapi2.H>
+#include <utility>
+#include <generic/memory/lib/ecc/ecc_traits.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H>
+
+namespace mss
+{
+
+namespace ecc
+{
+
+namespace fwms
+{
+
+///
+/// @class address
+/// @brief Converts Firmware Mark Store ADDRESS field into mcbist::address
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2 Target Type defaults to fapi2::TARGET_TYPE_MCA or TARGET_TYPE_MEM_PORT
+/// @tparam TT traits type defaults to eccTraits<MC, T>
+/// @note template argument defaults are in forward declaration in lib/mcbist/address.H
+/// @note 12 = dimm
+/// @note 13:14 = mrank
+/// @note 15:17 = srank
+/// @note 18:19 = bank group
+/// @note 20:22 = bank
+///
+// See declaration below
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::FWMS_ADDR_TARGET_TYPE, typename TT = mss::eccTraits<MC, T> >
+class address
+{
+ public:
+ // first is the start bit of the field, second is the length
+ using field = std::pair<uint64_t, uint64_t>;
+
+ constexpr static field DIMM = {TT::FIRMWARE_MS_ADDRESS, 1};
+ constexpr static field MRANK = {TT::FIRMWARE_MS_ADDRESS + 1, 2};
+ constexpr static field SRANK = {TT::FIRMWARE_MS_ADDRESS + 3, 3};
+ constexpr static field BANK_GROUP = {TT::FIRMWARE_MS_ADDRESS + 6, 2};
+ constexpr static field BANK = {TT::FIRMWARE_MS_ADDRESS + 8, 3};
+
+ address() = default;
+
+ ///
+ /// @brief Construct an address from a uint64_t (scom'ed value)
+ /// @param[in] i_value representing raw value from FWMS register
+ ///
+ address( const uint64_t& i_value ):
+ iv_value(i_value)
+ {
+ }
+
+ ///
+ /// @brief Construct an address from an mcbist::address
+ /// @param[in] i_mcbist_address mcbist formatted address
+ /// @note Construction of mcbist::address from address
+ /// @note located in mcbist::address class
+ ///
+ address( const mss::mcbist::address& i_mcbist_address )
+ {
+ iv_value.insertFromRight<DIMM.first, DIMM.second>(i_mcbist_address.get_dimm());
+ iv_value.insertFromRight<MRANK.first, MRANK.second>(i_mcbist_address.get_master_rank());
+ iv_value.insertFromRight<SRANK.first, SRANK.second>(i_mcbist_address.get_slave_rank());
+ iv_value.insertFromRight<BANK_GROUP.first, BANK_GROUP.second>(i_mcbist_address.get_bank_group());
+ iv_value.insertFromRight<BANK.first, BANK.second>(i_mcbist_address.get_bank());
+ }
+
+ ///
+ /// @brief Construct an address from an ecc::fwms::address
+ /// @tparam MC the mc type
+ /// @param[in] i_address representing an address field from a firmware mark store register
+ ///
+
+ ///
+ /// @brief Construct an mcbist::address from an ecc::fwms::address
+ /// @return the mcbist::address
+ ///
+ inline operator mss::mcbist::address() const
+ {
+ mss::mcbist::address l_mcbist_address;
+ l_mcbist_address.set_dimm (this->get_field<DIMM>());
+ l_mcbist_address.set_master_rank(this->get_field<MRANK>());
+ l_mcbist_address.set_slave_rank (this->get_field<SRANK>());
+ l_mcbist_address.set_bank_group (this->get_field<BANK_GROUP>());
+ l_mcbist_address.set_bank (this->get_field<BANK>());
+ return l_mcbist_address;
+ }
+
+ ///
+ /// @brief Conversion operator to uint64_t
+ ///
+ inline operator uint64_t() const
+ {
+ uint64_t l_temp = 0;
+ iv_value.extract<TT::FIRMWARE_MS_ADDRESS, TT::FIRMWARE_MS_ADDRESS_LEN, TT::FIRMWARE_MS_ADDRESS>(l_temp);
+ return l_temp;
+ }
+
+ ///
+ /// @brief Get a field from an address
+ /// @tparam F the field to get
+ /// @return right-aligned uint64_t representing the value
+ ///
+ template< const field& F >
+ inline uint64_t get_field() const
+ {
+ uint64_t l_value = 0;
+ iv_value.extractToRight<F.first, F.second>(l_value);
+ return l_value;
+ }
+
+ private:
+ fapi2::buffer<uint64_t> iv_value;
+
+};
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename address<MC, T, TT>::field address<MC, T, TT>::DIMM;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename address<MC, T, TT>::field address<MC, T, TT>::MRANK;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename address<MC, T, TT>::field address<MC, T, TT>::SRANK;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename address<MC, T, TT>::field address<MC, T, TT>::BANK_GROUP;
+
+template< mss::mc_type MC, fapi2::TargetType T , typename TT >
+constexpr typename address<MC, T, TT>::field address<MC, T, TT>::BANK;
+
+
+} // close namespace fwms
+} // close namespace ecc
+} // close namespace mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.C b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.C
new file mode 100644
index 000000000..81988c3d9
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.C
@@ -0,0 +1,146 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 gen_mss_mcbist_patterns.C
+/// @brief Static definition of MCBIST patterns
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#include <fapi2.H>
+#include <vector>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H>
+
+namespace mss
+{
+
+namespace mcbist
+{
+
+/// Vector of cache lines, seaprated in to two 64B chunks
+// TK Real patterns from Marc representing the proper bits for ECC checking
+const std::vector< pattern > patterns =
+{
+ // Pattern index 0 (Pattern 1 is this inverted)
+ { {0x0000000000000000, 0x0000000000000000},
+ {0x0000000000000000, 0x0000000000000000},
+ {0x0000000000000000, 0x0000000000000000},
+ {0x0000000000000000, 0x0000000000000000},
+ },
+
+ // Pattern index 2 (Pattern 3 is this inverted)
+ { {0x5555555555555555, 0x5555555555555555},
+ {0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA},
+ {0x5555555555555555, 0x5555555555555555},
+ {0xAAAAAAAAAAAAAAAA, 0xAAAAAAAAAAAAAAAA},
+ },
+
+ // Pattern index 4 (Pattern 5 is this inverted)
+ { {0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
+ {0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
+ {0x0000000000000000, 0x0000000000000000},
+ {0x0000000000000000, 0x0000000000000000},
+ },
+
+ // Pattern index 6 (Pattern 7 is this inverted)
+ { {0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
+ {0x0000000000000000, 0x0000000000000000},
+ {0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF},
+ {0x0000000000000000, 0x0000000000000000},
+ },
+
+ // Pattern index 8 Random Seed
+ { {0x1234567887654321, 0x8765432112345678},
+ {0x1234567887654321, 0x8765432112345678},
+ {0x1234567887654321, 0x8765432112345678},
+ {0x1234567887654321, 0x8765432112345678},
+ },
+
+ // Pattern index 10 (Pattern 11 is this inverted), MPR pattern
+ { {0x0000000000000000, 0xFFFFFFFFFFFFFFFF},
+ {0x0000000000000000, 0xFFFFFFFFFFFFFFFF},
+ {0x0000000000000000, 0xFFFFFFFFFFFFFFFF},
+ {0x0000000000000000, 0xFFFFFFFFFFFFFFFF},
+ },
+};
+
+// TK Want a new RC for random 24
+/// Vector of 24b random data seeds
+const std::vector< random24_data_seed > random24_data_seeds =
+{
+ // 24 Bit Pattern index 0 (Pattern 1 is this inverted)
+ { {0x010203},
+ {0x040506},
+ {0x070809},
+ },
+
+ // 24 Bit Pattern index 2 (Pattern 3 is this inverted)
+ { {0x112233},
+ {0x445566},
+ {0x778899},
+ },
+
+};
+
+/// Vector of 24b random data seed mappings
+// Not sure how many mapping we will want, for now it should be sufficient to
+// have all bytes point to a different LFSR or all bytes point to the same LFSR
+const std::vector< random24_seed_map > random24_seed_maps =
+{
+ // 8 Bit Pattern index 0
+ // This selection maps every data byte to a different random LFSR
+ { {0x0},
+ {0x1},
+ {0x2},
+ {0x3},
+ {0x4},
+ {0x5},
+ {0x6},
+ {0x7},
+ {0x8},
+ },
+
+ // 8 Bit Pattern index 1
+ // This selection maps every data byte to random LFSR 0
+ { {0x0},
+ {0x0},
+ {0x0},
+ {0x0},
+ {0x0},
+ {0x0},
+ {0x0},
+ {0x0},
+ {0x0},
+ },
+
+};
+
+} //namespace mcbist
+} //namespace mss
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H
new file mode 100644
index 000000000..cfb4a532d
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H
@@ -0,0 +1,103 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 gen_mss_mcbist_patterns.H
+/// @brief Static definition of MCBIST patterns
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_GEN_MCBIST_PATTERNS_
+#define _MSS_GEN_MCBIST_PATTERNS_
+
+#include <vector>
+
+namespace mss
+{
+namespace mcbist
+{
+
+/// Memory diagnostic Pattern indexes.
+// Why not an enum? I want to do math on them to generate a proper index in to a vector of
+// patterns and enums really don't like that.
+// Couple of extra symbols in here to keep things easy if desired
+constexpr uint64_t PATTERN_ZEROS = 0;
+constexpr uint64_t PATTERN_0 = PATTERN_ZEROS;
+constexpr uint64_t PATTERN_ONES = 1;
+constexpr uint64_t PATTERN_1 = PATTERN_ONES;
+constexpr uint64_t PATTERN_2 = 2;
+constexpr uint64_t PATTERN_3 = 3;
+constexpr uint64_t PATTERN_4 = 4;
+constexpr uint64_t PATTERN_5 = 5;
+constexpr uint64_t PATTERN_6 = 6;
+constexpr uint64_t PATTERN_7 = 7;
+constexpr uint64_t PATTERN_8 = 8;
+constexpr uint64_t PATTERN_9 = 9;
+constexpr uint64_t PATTERN_10 = 10;
+constexpr uint64_t PATTERN_RANDOM = PATTERN_8;
+constexpr uint64_t LAST_PATTERN = PATTERN_10;
+
+// Don't mess with the patterns
+constexpr uint64_t NO_PATTERN = LAST_PATTERN + 1;
+
+//Pattern references for the 24b random data pattern seeds
+constexpr uint64_t MAX_NUM_RANDOM24_SEEDS = 3;
+constexpr uint64_t RANDOM24_SEEDS_0 = 0;
+constexpr uint64_t RANDOM24_SEEDS_1 = 1;
+constexpr uint64_t RANDOM24_SEEDS_2 = 2;
+constexpr uint64_t RANDOM24_SEEDS_3 = 3;
+constexpr uint64_t LAST_RANDOM24_SEEDS = RANDOM24_SEEDS_3;
+constexpr uint64_t NO_RANDOM24_SEEDS = LAST_RANDOM24_SEEDS + 1;
+
+//Pattern references for the 24b random data pattern seeds
+constexpr uint64_t MAX_NUM_RANDOM24_MAPS = 9;
+constexpr uint64_t RANDOM24_SEED_MAP_0 = 0;
+constexpr uint64_t RANDOM24_SEED_MAP_1 = 1;
+constexpr uint64_t LAST_RANDOM24_SEED_MAP = RANDOM24_SEED_MAP_1;
+constexpr uint64_t NO_RANDOM24_SEED_MAP = LAST_RANDOM24_SEED_MAP + 1;
+constexpr uint64_t RANDOM24_SEED_MAP_FIELD_LEN = 4;
+
+
+/// Vector of cache lines, separated in to two 64B chunks
+using cache_line = std::pair<uint64_t, uint64_t> ;
+using pattern = std::vector< cache_line > ;
+extern const std::vector< pattern > patterns;
+
+// Vector of 24b random data seeds
+using random24_data_seed = std::vector< uint64_t > ;
+extern const std::vector< random24_data_seed > random24_data_seeds;
+
+// Vector of 24b random data seed maps
+using random24_seed_map = std::vector< uint64_t >;
+extern const std::vector< random24_seed_map > random24_seed_maps;
+
+}// mcbist
+
+}// mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H
new file mode 100644
index 000000000..6f570fbad
--- /dev/null
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H
@@ -0,0 +1,815 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 gen_mss_mcbist_settings.H
+/// @brief MCBIST settings, like stop conditions, thresholds, etc
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_MCBIST_SETTINGS_H_
+#define _GEN_MSS_MCBIST_SETTINGS_H_
+
+#include <fapi2.H>
+
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/bit_count.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H>
+
+namespace mss
+{
+
+namespace mcbist
+{
+///
+/// @brief End boundaries for MCBIST programs - where to stop when stopping or pausing
+///
+enum end_boundary : uint64_t
+{
+ // We're gonna get a little hacky here. The pause on error mode field
+ // is two bits, with another bit representing slave/master. So we craft
+ // the enum so that we can insertFromRight and get the proper vaules, and
+ // leave one bit out of that two-bit range to represent master or slave
+ NONE = 0b000,
+ STOP_AFTER_ADDRESS = 0b001,
+ STOP_AFTER_MASTER_RANK = 0b010,
+ STOP_AFTER_SLAVE_RANK = 0b110,
+ STOP_AFTER_SUBTEST = 0b011,
+
+ DONT_CHANGE = 0xFF,
+};
+
+///
+/// @brief Speeds for performing MCBIST operations
+///
+enum speed
+{
+ /// As fast as possible, often the default
+ LUDICROUS = 0,
+
+ /// Background scrubbing speed.
+ BG_SCRUB = 1,
+
+ /// Used to indicate to the continue current command to not change the speed of the commands
+ SAME_SPEED = 4,
+};
+
+///
+/// @class Memory diagnostic subsystem stop-on-error settings and thresholds
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @note Matches Nimbus MBSTRQ, but might be changed later for Centaur, or mapped.
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mss::mcbistTraits<MC, T> >
+class stop_conditions
+{
+ public:
+
+ // Many of the config fields share a disable bit pattern, so we define it here
+ static constexpr uint64_t DISABLE = 0b1111;
+ static constexpr uint64_t MAX_THRESHOLD = 0b1110;
+ static constexpr uint64_t DONT_CHANGE = 0;
+
+ private:
+
+ ///
+ /// @brief Little helper to convert threshold inputs to exponents
+ /// @param[in] i_value, the value of the threshold (presumably)
+ /// @return a value n such that 2^n <= i_value && n < 15
+ ///
+ uint64_t make_threshold_setting( const uint64_t i_value )
+ {
+ // If the user passes in DISABLE, let it past. This prevents callers from having to
+ // do the conditional. Zero is none which is disable
+ if ((i_value == DISABLE) || (i_value == 0))
+ {
+ return DISABLE;
+ }
+
+ // Find the first bit set. This represents the largest power of 2 this input can represent
+ // The subtraction from 63 switches from a left-count to a right-count (e.g., 0 (left most
+ // bit) is really bit 63 if you start on the right.)
+ const uint64_t l_largest = 63 - first_bit_set(i_value);
+
+ // If the first bit set is off in space and greater than 2^14, we just return 0b1110
+ // Otherwise, l_largest is the droid we're looking for
+ return l_largest >= MAX_THRESHOLD ? MAX_THRESHOLD : l_largest;
+ }
+
+ ///
+ /// @brief Generic pause on threshold
+ /// @tparam F, the bit field to manipulate
+ /// @tparam L, the length of F
+ /// @param[in] the state of the error - mss::ON or mss::OFF
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ template< uint64_t F, uint64_t L >
+ inline stop_conditions<MC, T, TT>& set_pause_on_threshold( const states i_on_or_off )
+ {
+ if (i_on_or_off == mss::OFF)
+ {
+ iv_value.insertFromRight<F, L>(DISABLE);
+ return *this;
+ }
+
+ uint64_t l_thresh = 0;
+ iv_value.extractToRight<F, L>(l_thresh);
+
+ if (l_thresh == DISABLE)
+ {
+ // Note the threshold field is an exponent, so this is 2^0, or 1 count
+ iv_value.insertFromRight<F, L>(0);
+ }
+
+ return *this;
+ }
+
+ public:
+ ///
+ /// @brief Stop/Thresholds class ctor
+ ///
+ stop_conditions():
+ iv_value(0)
+ {
+ // By default we want to start everything in 'don't stop' mode. This means disabling
+ // the errors which contain thresholds
+ set_thresh_nce_int(DISABLE)
+ .set_thresh_nce_soft(DISABLE)
+ .set_thresh_nce_hard(DISABLE)
+ .set_thresh_rce(DISABLE)
+ .set_thresh_ice(DISABLE)
+ .set_thresh_mce_int(DISABLE)
+ .set_thresh_mce_soft(DISABLE)
+ .set_thresh_mce_hard(DISABLE);
+ }
+
+ ///
+ /// @brief Stop/Thresholds class ctor
+ /// @param[in] uint64_t representing the threshold register contents
+ ///
+ stop_conditions(const uint64_t i_value):
+ iv_value(i_value)
+ {
+ }
+
+ ///
+ /// @brief Stop/Thresholds class dtor
+ ///
+ ~stop_conditions() = default;
+
+ ///
+ /// @brief uint64_t conversion
+ ///
+ inline operator uint64_t() const
+ {
+ return uint64_t(iv_value);
+ }
+
+ ///
+ /// @brief set_thresh_nce_int
+ /// @param[in] i_value the value of the field
+ /// NCE intermittent error threshold magnitude to trigger for triggering pause. If
+ /// 1111, then pause will never be triggered (disabled). Else, then MCBIST will
+ /// pause if it takes sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_nce_int( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_NCE_INT,
+ TT::MBSTRQ_CFG_THRESH_MAG_NCE_INT_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_nce_int - enable NCE intermittent error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_nce_int( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_NCE_INT,
+ TT::MBSTRQ_CFG_THRESH_MAG_NCE_INT_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_thresh_nce_soft
+ /// @param[in] i_value the value of the field
+ /// NCE soft error threshold magnitude to trigger for triggering pause. If 1111,
+ /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it
+ /// takes sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_nce_soft( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_NCE_SOFT,
+ TT::MBSTRQ_CFG_THRESH_MAG_NCE_SOFT_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_nce_int - enable NCE soft error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_nce_soft( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_NCE_SOFT,
+ TT::MBSTRQ_CFG_THRESH_MAG_NCE_SOFT_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_thresh_nce_hard
+ /// @param[in] i_value the value of the field
+ /// NCE hard error threshold magnitude to trigger for triggering pause. If 1111,
+ /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it
+ /// takes sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_nce_hard( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_NCE_HARD,
+ TT::MBSTRQ_CFG_THRESH_MAG_NCE_HARD_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_nce_hard - enable NCE hard error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_nce_hard( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_NCE_HARD,
+ TT::MBSTRQ_CFG_THRESH_MAG_NCE_HARD_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_thresh_rce
+ /// @param[in] i_value the value of the field
+ /// RCE error threshold magnitude to trigger for triggering pause. If 1111, then
+ /// pause will never be triggered (disabled). Else, then MCBIST will pause if it takes
+ /// sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_rce( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_RCE,
+ TT::MBSTRQ_CFG_THRESH_MAG_RCE_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_rce - enable RCE error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_rce( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_RCE,
+ TT::MBSTRQ_CFG_THRESH_MAG_RCE_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_thresh_ice
+ /// @param[in] i_value the value of the field
+ /// ICE (IMPE) error threshold magnitude to trigger for triggering pause. If 1111,
+ /// then pause will never be triggered (disabled). Else, then MCBIST will pause if
+ /// it takes sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_ice( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_ICE,
+ TT::MBSTRQ_CFG_THRESH_MAG_ICE_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_ice - enable ICE (IMPE) error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_ice( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_ICE,
+ TT::MBSTRQ_CFG_THRESH_MAG_ICE_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_thresh_mce_int
+ /// @param[in] i_value the value of the field
+ /// MCE intermittent error threshold magnitude to trigger for triggering pause. If
+ /// 1111, then pause will never be triggered (disabled). Else, then MCBIST will
+ /// pause if it takes sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_mce_int( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_MCE_INT,
+ TT::MBSTRQ_CFG_THRESH_MAG_MCE_INT_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_mce_int - enable MCE intermittent error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_mce_int( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_MCE_INT,
+ TT::MBSTRQ_CFG_THRESH_MAG_MCE_INT_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_thresh_mce_soft
+ /// @param[in] i_value the value of the field
+ /// MCE soft error threshold magnitude to trigger for triggering pause. If 1111,
+ /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it
+ /// takes sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_mce_soft( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_MCE_SOFT,
+ TT::MBSTRQ_CFG_THRESH_MAG_MCE_SOFT_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_mce_soft - enable MCE soft error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_mce_soft( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_MCE_SOFT,
+ TT::MBSTRQ_CFG_THRESH_MAG_MCE_SOFT_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_thresh_mce_hard
+ /// @param[in] i_value the value of the field
+ /// MCE hard error threshold magnitude to trigger for triggering pause. If 1111,
+ /// then pause will never be triggered (disabled). Else, then MCBIST will pause if it
+ /// takes sees 2^[this value] number of errors of this type.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note The register field is actually an exponent. The hardware will count 2^n for the
+ /// threshold. However, the input represents a count - how many. Thus we need to convert
+ /// the input to a power of 2 to get a proper exponent. Your input will be rounded down
+ /// to the nearest power of 2 which is less than 2^15 before being set in the register.
+ ///
+ inline stop_conditions<MC, T, TT>& set_thresh_mce_hard( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_THRESH_MAG_MCE_HARD,
+ TT::MBSTRQ_CFG_THRESH_MAG_MCE_HARD_LEN>(make_threshold_setting(i_value));
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_mce_hard - enable MCE hard error
+ /// @param[in] i_on_or_off - the desired state.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ /// @note If the input is mss::ON, this method enables the error, it's corresponding
+ /// threshold defines the threshold at which the engine will stop. If no threshold is
+ /// defined (the error is disabled) this method will set the threshold to 1. A previously
+ /// defined threshold (i.e., not disabled) will be left intact. If the input
+ /// is mss::OFF, this method will disable the error by setting the threshold to disabled.
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_mce_hard( const states i_on_or_off )
+ {
+ return set_pause_on_threshold<TT::MBSTRQ_CFG_THRESH_MAG_MCE_HARD,
+ TT::MBSTRQ_CFG_THRESH_MAG_MCE_HARD_LEN>(i_on_or_off);
+ }
+
+ ///
+ /// @brief set_pause_on_sce
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause on SCE error. When enabled, MCBIST will pause at the boundary
+ /// configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_sce( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_ON_SCE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_mce
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause on MCE error. When enabled, MCBIST will pause at the boundary
+ /// configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_mce( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_ON_MCE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_mpe
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause on MPE error. When enabled, MCBIST will pause at the boundary
+ /// configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_mpe( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_ON_MPE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_ue
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause on UE error. When enabled, MCBIST will pause at the boundary
+ /// configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_ue( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_ON_UE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_sue
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause on SUE error. When enabled, MCBIST will pause at the boundary
+ /// configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_sue( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_ON_SUE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_aue
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause on AUE error. When enabled, MCBIST will pause at the boundary
+ /// configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_aue( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_ON_AUE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_on_rcd
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause on RCD error. When enabled, MCBIST will pause at the boundary
+ /// configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_on_rcd( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_ON_RCD>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_symbol_counter_mode
+ /// @param[in] i_value the value of the field
+ /// Selects which mode to use symbol counter latches: Mode 0) MAINT 8-bit error
+ /// counters for of 72 symbols Mode 1) MCBIST 4-bit error counters for 18 nibbles x 8
+ /// ranks (port agnostic) Mode 2) MCBIST 4-bit error counters for 18 nibbles x 4
+ /// ports (rank agnostic) and 1-bit error rank map for 18 nibbles x 4 ports
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_symbol_counter_mode( const uint64_t i_value )
+ {
+ iv_value.insertFromRight<TT::MBSTRQ_CFG_SYMBOL_COUNTER_MODE,
+ TT::MBSTRQ_CFG_SYMBOL_COUNTER_MODE_LEN>(i_value);
+ return *this;
+ }
+
+ ///
+ /// @brief set_nce_soft_symbol_count_enable
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enables soft NCEs to trigger per symbol NCE error counting Only applies to
+ /// scrub where we have different types of NCE. Non scrub counts all NCE.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_nce_soft_symbol_count_enable( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_NCE_SOFT_SYMBOL_COUNT_ENABLE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_nce_inter_symbol_count_enable
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enables intermittent NCEs to trigger per symbol NCE error counting Only applies
+ /// to scrub where we have different types of NCE. Non scrub counts all NCE.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_nce_inter_symbol_count_enable( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_NCE_INTER_SYMBOL_COUNT_ENABLE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_nce_hard_symbol_count_enable
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enables hard NCEs to trigger per symbol NCE error counting Only applies to
+ /// scrub where we have different types of NCE. Non scrub counts all NCE.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_nce_hard_symbol_count_enable( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_NCE_HARD_SYMBOL_COUNT_ENABLE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_mcb_error
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause when MCBIST error is logged. When enabled, MCBIST will pause at
+ /// the boundary configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_mcb_error( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_MCB_ERROR>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_pause_mcb_log_full
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enable pause when MCBIST log is full. When enabled, MCBIST will pause at the
+ /// boundary configured if this error is seen.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_pause_mcb_log_full( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_PAUSE_MCB_LOG_FULL>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_maint_rce_with_ce
+ /// @param[in] i_on_or_off - the desired state.
+ /// cfg_maint_rce_with_ce - not implemented. Need to investigate if needed for nimbus.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_maint_rce_with_ce( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_MAINT_RCE_WITH_CE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_mce_soft_symbol_count_enable
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enables soft MCEs to trigger per symbol MCE error counting Only applies to
+ /// scrub where we have different types of MCE. Non scrub counts all MCE.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_mce_soft_symbol_count_enable( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_MCE_SOFT_SYMBOL_COUNT_ENABLE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_mce_inter_symbol_count_enable
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enables intermittent MCEs to trigger per symbol MCE error counting Only applies
+ /// to scrub where we have different types of MCE. Non scrub counts all MCE.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_mce_inter_symbol_count_enable( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_MCE_INTER_SYMBOL_COUNT_ENABLE>(i_on_or_off);
+ return *this;
+ }
+
+ ///
+ /// @brief set_mce_hard_symbol_count_enable
+ /// @param[in] i_on_or_off - the desired state.
+ /// Enables hard MCEs to trigger per symbol MCE error counting Only applies to
+ /// scrub where we have different types of MCE. Non scrub counts all MCE.
+ /// @return fapi2::buffer<uint64_t>& this->iv_value useful for method chaining
+ ///
+ inline stop_conditions<MC, T, TT>& set_mce_hard_symbol_count_enable( const states i_on_or_off )
+ {
+ iv_value.writeBit<TT::MBSTRQ_CFG_MCE_HARD_SYMBOL_COUNT_ENABLE>(i_on_or_off);
+ return *this;
+ }
+
+ private:
+
+ fapi2::buffer<uint64_t> iv_value;
+};
+
+template< mss::mc_type MC, fapi2::TargetType T, typename TT>
+constexpr uint64_t stop_conditions<MC, T, TT>::DISABLE;
+
+template< mss::mc_type MC, fapi2::TargetType T, typename TT>
+constexpr uint64_t stop_conditions<MC, T, TT>::MAX_THRESHOLD;
+
+template< mss::mc_type MC, fapi2::TargetType T, typename TT>
+constexpr uint64_t stop_conditions<MC, T, TT>::DONT_CHANGE;
+
+///
+/// @class memdiags operational constraints
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T - derived
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+struct constraints
+{
+ ///
+ /// @brief constraints default constructor
+ ///
+ constraints():
+ iv_stop(),
+ iv_pattern(NO_PATTERN),
+ iv_end_boundary(NONE),
+ iv_speed(LUDICROUS),
+ iv_start_address(0),
+ iv_end_address(TT::LARGEST_ADDRESS)
+ {
+ }
+
+ ///
+ /// @brief constraints constructor
+ /// @param[in] i_pattern a pattern to set
+ ///
+ constraints( const uint64_t i_pattern ):
+ constraints()
+ {
+ iv_pattern = i_pattern;
+ FAPI_INF("setting up constraints with pattern %d", i_pattern);
+ }
+
+ ///
+ /// @brief constraints constructor
+ /// @param[in] i_stop stop conditions
+ ///
+ constraints( const stop_conditions<MC, T, TT>& i_stop ):
+ constraints()
+ {
+ iv_stop = i_stop;
+ FAPI_INF("setting up constraints with stop 0x%016lx", uint64_t(i_stop));
+ }
+
+ ///
+ /// @brief constraints constructor
+ /// @param[in] i_stop stop conditions
+ /// @param[in] i_start_address address to start from
+ ///
+ constraints( const stop_conditions<MC, T, TT>& i_stop,
+ const address& i_start_address ):
+ constraints(i_stop)
+ {
+ iv_start_address = i_start_address;
+ FAPI_INF("setting up constraints with start address 0x%016lx", uint64_t(i_start_address));
+ }
+
+ ///
+ /// @brief constraints constructor
+ /// @param[in] i_stop stop conditions
+ /// @param[in] i_speed the speed at which to run
+ /// @param[in] i_end_boundary the place to stop on error
+ /// @param[in] i_start_address address to start from
+ /// @param[in] i_end_address address to end at (optional, run to end)
+ ///
+ constraints( const stop_conditions<MC, T, TT>& i_stop,
+ const speed i_speed,
+ const end_boundary i_end_boundary,
+ const address& i_start_address,
+ const address& i_end_address = mcbist::address(TT::LARGEST_ADDRESS) ):
+ constraints(i_stop, i_start_address)
+ {
+ iv_end_boundary = i_end_boundary;
+ iv_speed = i_speed;
+ iv_end_address = i_end_address;
+
+ FAPI_INF("setting up constraints with end boundary %d and speed 0x%x", i_end_boundary, i_speed);
+
+ // If our end address is 'before' our start address, make the end address the same as the start.
+ if (iv_start_address > iv_end_address)
+ {
+ iv_end_address = iv_start_address;
+ }
+ }
+
+ // Member variable declaration
+ stop_conditions<MC, T, TT> iv_stop;
+ uint64_t iv_pattern;
+ end_boundary iv_end_boundary;
+ speed iv_speed;
+ mcbist::address iv_start_address;
+ mcbist::address iv_end_address;
+};
+
+
+} // namespace
+} // namespace
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H
index 54583ebd0..cd0bc5163 100644
--- a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H
@@ -22,3 +22,44 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file gen_mss_mcbist_traits.H
+/// @brief Run and manage the MCBIST engine
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_MCBIST_TRAITS_H_
+#define _GEN_MSS_MCBIST_TRAITS_H_
+
+#include <fapi2.H>
+
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+
+namespace mss
+{
+
+///
+/// @class mcbistMCTraits
+/// @tparam MC the mc type
+/// @brief A MC to MC_TARGET_TYPE mapping
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE >
+class mcbistMCTraits;
+
+///
+/// @class mcbistTraits
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @brief a collection of traits associated with the MCBIST engine or hardware
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE>
+class mcbistTraits;
+
+}// mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_memdiags.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_memdiags.H
index 62af113ca..c67b51595 100644
--- a/src/import/generic/memory/lib/utils/mcbist/gen_mss_memdiags.H
+++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_memdiags.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
+/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,3 +22,1288 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file gen_mss_memdiags.H
+/// @brief API for memory diagnostics
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+//
+
+#ifndef _GEN_MSS_MEMDIAGS_H_
+#define _GEN_MSS_MEMDIAGS_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/mss_generic_system_attribute_getters.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H>
+#include <generic/memory/lib/utils/fir/gen_mss_unmask.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+#include <generic/memory/lib/utils/conversions.H>
+#include <generic/memory/lib/utils/pos.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+#include <generic/memory/lib/utils/poll.H>
+
+
+namespace mss
+{
+
+///
+/// @brief Determine if a thing is functional
+/// @tparam I, the type of the item we want to check for
+/// @tparam P, the type of the parent which holds the things of interest
+/// @param[in] i_target the parent containing the thing we're looking for
+/// @param[in] i_rel_pos the relative position of the item of interest.
+/// @return bool true iff the thing at i_rel_pos is noted as functional
+///
+template< fapi2::TargetType I, fapi2::TargetType P >
+inline bool is_functional( const fapi2::Target<P>& i_target, const uint64_t i_rel_pos )
+{
+ // Not sure of a good way to do this ... we get all the functional
+ // children of the parent and look for our relative position ...
+ for (const auto& i : i_target.template getChildren<I>(fapi2::TARGET_STATE_FUNCTIONAL))
+ {
+ if (mss::template relative_pos<P>(i) == i_rel_pos)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+namespace mcbist
+{
+namespace sim
+{
+
+/// @brief Perform a sim version of initializing memory
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T
+/// @param T a fapi2::TargetType
+/// @param[in] i_target
+/// @param[in] i_pattern an index representing a pattern to use to initize memory (defaults to 0)
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode sf_init( const fapi2::Target<T>& i_target, const uint64_t i_pattern )
+{
+ FAPI_INF("Start sim init for %s", mss::c_str(i_target));
+
+ // If we're running in the simulator, we want to only touch the addresses which training touched
+
+ for (const auto& p : i_target.template getChildren<TT::PORT_TYPE>())
+ {
+ std::vector<uint64_t> l_pr;
+ mss::mcbist::program<MC> l_program;
+
+ mss::mcbist::address l_start;
+ mss::mcbist::address l_end;
+
+ size_t l_rank_address_pair = 0;
+
+ // No point in bothering if we don't have any DIMM
+ if (mss::count_dimm(p) == 0)
+ {
+ FAPI_INF("No DIMM on %s, not running sf_init", mss::c_str(p));
+ continue;
+ }
+
+ // In sim we know a few things ...
+ // Get the primary ranks for this port. We know there can only be 4, and we know we only trained the primary
+ // ranks. Therefore, we only need to clean up the primary ranks. And because there's 4 max, we can do it
+ // all using the 4 address range registers of tne MCBIST (broadcast currently not considered.)
+ // So we can write 0's to those to get their ECC fixed up.
+ FAPI_TRY( mss::rank::primary_ranks(p, l_pr) );
+ fapi2::Assert( l_pr.size() <= mss::MAX_RANK_PER_DIMM );
+
+ for (auto r = l_pr.begin(); r != l_pr.end(); ++l_rank_address_pair, ++r)
+ {
+ FAPI_INF("sim init %s, rank %d", mss::c_str(p), *r);
+
+ // Setup l_start to represent this rank, and then make the end address from that.
+ l_start.set_master_rank(*r);
+
+ // Set C3 bit to get an entire cache line
+ l_start.get_sim_end_address(l_end);
+
+ // By default we're in maint address mode, not address counting mode. So we give it a start and end, and ignore
+ // anything invalid - that's what maint address mode is all about
+ mss::mcbist::config_address_range<MC>(i_target, l_start, l_end, l_rank_address_pair);
+
+ // Write
+ {
+ // Run in ECC mode, 64B writes (superfast mode)
+
+ mss::mcbist::subtest_t<MC> l_fw_subtest =
+ mss::mcbist::write_subtest<MC>();
+
+ l_fw_subtest.enable_port(mss::relative_pos<T>(p));
+ l_fw_subtest.change_addr_sel(l_rank_address_pair);
+ l_fw_subtest.enable_dimm(mss::rank::get_dimm_from_rank(*r));
+ l_program.iv_subtests.push_back(l_fw_subtest);
+ FAPI_DBG("adding superfast write for %s rank %d (dimm %d)", mss::c_str(p), *r, mss::rank::get_dimm_from_rank(*r));
+ }
+
+ // Read - we do a read here as verification can use this as a tool as we do the write and then the read.
+ // If we failed to write properly the read would thow ECC errors. Just a write (which the real hardware would
+ // do) doesn't catch that. This takes longer, but it's not terribly long in any event.
+ {
+ // Run in ECC mode, 64B writes (superfast mode)
+ mss::mcbist::subtest_t<MC> l_fr_subtest =
+ mss::mcbist::read_subtest<MC>();
+
+ l_fr_subtest.enable_port(mss::relative_pos<T>(p));
+ l_fr_subtest.change_addr_sel(l_rank_address_pair);
+ l_fr_subtest.enable_dimm(mss::rank::get_dimm_from_rank(*r));
+ l_program.iv_subtests.push_back(l_fr_subtest);
+ FAPI_DBG("adding superfast read for %s rank %d (dimm %d)", mss::c_str(p), *r, mss::rank::get_dimm_from_rank(*r));
+ }
+ }
+
+ // Write pattern
+ FAPI_TRY( mss::mcbist::load_pattern<MC>(i_target, i_pattern) );
+
+ // Setup the sim polling based on a heuristic <cough>guess</cough>
+ // Looks like ~400ck per address for a write/read program on the sim-dimm, and add a long number of polls
+ // On real hardware wait 100ms and then start polling for another 5s
+ l_program.iv_poll.iv_initial_sim_delay = mss::cycles_to_simcycles(((l_end - l_start) * l_pr.size()) * 800);
+ l_program.iv_poll.iv_initial_delay = 100 * mss::DELAY_1MS;
+ l_program.iv_poll.iv_sim_delay = 100000;
+ l_program.iv_poll.iv_delay = 10 * mss::DELAY_1MS;
+ l_program.iv_poll.iv_poll_count = 500;
+
+ // Just one port for now. Per Shelton we need to set this in maint address mode
+ // even tho we specify the port/dimm in the subtest.
+ fapi2::buffer<uint8_t> l_port;
+ l_port.setBit(mss::relative_pos<T>(p));
+ l_program.select_ports(l_port >> 4);
+
+ // Kick it off, wait for a result
+ FAPI_TRY( mss::mcbist::execute(i_target, l_program) );
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_INF("End sim init for %s", mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+} // namespace sim
+} // namespace mcbist
+
+
+namespace memdiags
+{
+
+// Map some of the mcbist namespace here to make it easier for users of memdiags
+// This is an intentional using statement in a header which is typically
+// disallowed - I am intentionally pulling these into this namespace for all callers.
+using mss::mcbist::constraints;
+using mss::mcbist::speed;
+using mss::mcbist::end_boundary;
+using mss::mcbist::stop_conditions;
+using mss::mcbist::cache_line;
+using mss::mcbist::pattern;
+using mss::mcbist::patterns;
+
+// Why not mss::mcbist::address? Because the fields can't be pulled in via using,
+// and it seems even more confusing to have a memdiags address but have to use
+// mcbist fields. So, we all use mcbist address until such time that its promoted
+// to some other general namespace.
+
+using mss::mcbist::PATTERN_ZEROS;
+using mss::mcbist::PATTERN_0;
+using mss::mcbist::PATTERN_ONES;
+using mss::mcbist::PATTERN_1;
+using mss::mcbist::PATTERN_2;
+using mss::mcbist::PATTERN_3;
+using mss::mcbist::PATTERN_4;
+using mss::mcbist::PATTERN_5;
+using mss::mcbist::PATTERN_6;
+using mss::mcbist::PATTERN_7;
+using mss::mcbist::PATTERN_8;
+using mss::mcbist::PATTERN_RANDOM;
+using mss::mcbist::LAST_PATTERN;
+using mss::mcbist::NO_PATTERN;
+
+///
+/// @brief Set up memory controller specific settings for pre-maint mode read
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the portTraits associated with the port
+/// @param[in] i_target the memory controller target
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode pre_maint_read_settings( const fapi2::Target<T>& i_target );
+
+///
+/// @brief Set up memory controller specific settings for pre-scrub
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the portTraits associated with the port
+/// @param[in] i_target the memory controller target
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT = portTraits<MC> >
+fapi2::ReturnCode pre_scrub_settings( const fapi2::Target<T>& i_target );
+
+///
+/// @brief Stop the current command
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType of the target
+/// @param[in] i_target the target
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T>
+fapi2::ReturnCode stop( const fapi2::Target<T>& i_target )
+{
+ // Too long, make shorter
+ using TT = mss::mcbistTraits<MC, T>;
+ using ET = mss::mcbistMCTraits<MC>;
+
+ // Poll parameters are defined as TK so that we wait a nice time for operations
+ // For now use the defaults
+ mss::poll_parameters l_poll_parameters;
+ fapi2::buffer<uint64_t> l_status;
+ fapi2::buffer<uint64_t> l_last_address;
+ bool l_poll_result = false;
+
+ FAPI_INF("Stopping any mcbist operations which are in progress for %s", mss::c_str(i_target));
+
+ // TODO RTC:153951 Add masking of FIR when stopping
+ FAPI_TRY( mss::mcbist::start_stop<MC>(i_target, mss::STOP) );
+
+ // Poll waiting for the engine to stop
+ l_poll_result = mss::poll(i_target, TT::STATQ_REG, l_poll_parameters,
+ [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_DBG("looking for mcbist not in-progress, mcbist statq 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ l_status = stat_reg;
+ // We're done polling when either we see we're in progress or we see we're done.
+ return l_status.getBit<TT::MCBIST_IN_PROGRESS>() == false;
+ });
+
+ // Pass or fail output the current address. This is useful for debugging when we can get it.
+ // It's in the register FFDC for memdiags so we don't need it below
+ FAPI_TRY( mss::getScom(i_target, TT::LAST_ADDR_REG, l_last_address) );
+ FAPI_INF("MCBIST last address (during stop): 0x%016lx for %s",
+ l_last_address, mss::c_str(i_target));
+
+ // So we've either stopped or we timed out
+ FAPI_ASSERT( l_poll_result == true,
+ ET::memdiags_failed_to_stop()
+ .set_MC_TARGET(i_target)
+ .set_POLL_COUNT(l_poll_parameters.iv_poll_count),
+ "%s The MCBIST engine failed to stop its program",
+ mss::c_str(i_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+
+///
+/// @class Base class for memdiags operations
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+class operation
+{
+ public:
+ ///
+ /// @brief memdiags::operation constructor
+ /// @param[in] i_target the target of the mcbist engine
+ /// @param[in] i_subtest the proper subtest for this operation
+ /// @param[in] i_const mss::constraint structure
+ ///
+ operation( const fapi2::Target<T>& i_target,
+ const mss::mcbist::subtest_t<MC> i_subtest,
+ const constraints<MC> i_const ):
+ iv_target(i_target),
+ iv_subtest(i_subtest),
+ iv_const(i_const)
+ {
+ FAPI_TRY( mss::attr::get_is_simulation (iv_sim) );
+ return;
+
+ fapi_try_exit:
+ // Seems like a safe risk to take ...
+ FAPI_ERR("Unable to get the attribute ATTR_IS_SIMULATION");
+ return;
+ }
+
+ operation() = delete;
+
+ ///
+ /// @brief Execute the memdiags operation
+ /// @return FAPI2_RC_SUCCESS iff ok
+ ///
+ inline fapi2::ReturnCode execute()
+ {
+ return mss::mcbist::execute(iv_target, iv_program);
+ }
+
+ ///
+ /// @brief memdiags::operation destructor
+ ///
+ virtual ~operation() = default;
+
+ ///
+ /// @brief memdiags init helper
+ /// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
+ /// in subclassed constructores more easily.
+ /// @return FAPI2_RC_SUCCESS iff everything ok
+ ///
+ fapi2::ReturnCode base_init();
+
+ ///
+ /// @brief Configures all subtests for a multiport init
+ /// @param[in] i_dimms a vector of DIMM targets
+ ///
+ void configure_multiport_subtests(const std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>>& i_dimms);
+
+ ///
+ /// @brief memdiags multi-port init helper
+ /// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
+ /// in subclassed constructores more easily.
+ /// @return FAPI2_RC_SUCCESS iff everything ok
+ ///
+ fapi2::ReturnCode multi_port_init();
+
+ ///
+ /// @brief memdiags multi-port init for specific chip
+ /// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
+ /// in subclassed constructores more easily.
+ /// @return FAPI2_RC_SUCCESS iff everything ok
+ ///
+ fapi2::ReturnCode multi_port_init_internal();
+
+
+ ///
+ /// @brief memdiags multi-port address config helper
+ /// Initializes the address configs needed for a multi port operation
+ /// @return FAPI2_RC_SUCCESS iff everything ok
+ ///
+ fapi2::ReturnCode multi_port_addr();
+
+ ///
+ /// @brief Single port initializer
+ /// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
+ /// in subclassed constructores more easily.
+ /// @return FAPI2_RC_SUCCESS iff everything ok
+ ///
+ fapi2::ReturnCode single_port_init();
+
+ ///
+ /// @brief get the protected mcbist program - useful for testing
+ /// @return a reference to the iv_program member
+ /// @note Intentionally not const ref; allows getter to set.
+ ///
+ mss::mcbist::program<MC>& get_program()
+ {
+ return iv_program;
+ }
+
+ ///
+ /// @brief get the protected mcbist subtest_t - useful for testing
+ /// @return a reference to the iv_subtest member
+ ///
+ const mss::mcbist::subtest_t<MC>& get_subtest() const
+ {
+ return iv_subtest;
+ }
+
+ protected:
+ fapi2::Target<T> iv_target;
+ mss::mcbist::subtest_t<MC> iv_subtest;
+ constraints<MC> iv_const;
+ mss::mcbist::program<MC> iv_program;
+ uint8_t iv_sim;
+};
+
+
+
+///
+/// @brief memdiags init helper
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T
+/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
+/// in subclassed constructors more easily.
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT >
+inline fapi2::ReturnCode operation<MC, T, TT>::base_init()
+{
+ FAPI_INF("memdiags base init for %s", mss::c_str(iv_target));
+
+ // Check the state of the MCBIST engine to make sure its OK that we proceed.
+ // Force stop the engine (per spec, as opposed to waiting our turn)
+ FAPI_TRY( memdiags::stop<MC>(iv_target) );
+
+ // Zero out cmd timebase - mcbist::program constructor does that for us.
+ // Load pattern
+ FAPI_TRY( iv_program.change_pattern(iv_const.iv_pattern) );
+
+ // Load end boundaries
+ iv_program.change_end_boundary(iv_const.iv_end_boundary);
+
+ // Load thresholds
+ iv_program.change_thresholds(iv_const.iv_stop);
+
+ // Setup the requested speed
+ FAPI_TRY( iv_program.change_speed(iv_target, iv_const.iv_speed) );
+
+ // Enable maint addressing mode - enabled by default in the mcbist::program ctor
+
+ // Apparently the MCBIST engine needs the ports selected even though the ports are specified
+ // in the subtest. We can just select them all, and it adjusts when it executes the subtest
+ iv_program.select_ports(0b1111);
+
+ // Kick it off, don't wait for a result
+ iv_program.change_async(mss::ON);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Single port initializer
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T
+/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
+/// in subclassed constructors more easily.
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT >
+inline fapi2::ReturnCode operation<MC, T, TT>::single_port_init()
+{
+ using ET = mcbistMCTraits<MC>;
+ FAPI_INF("single port init for %s", mss::c_str(iv_target));
+
+ const uint64_t l_relative_port_number = iv_const.iv_start_address.get_port();
+ const uint64_t l_dimm_number = iv_const.iv_start_address.get_dimm();
+
+ // Make sure the specificed port is functional
+ FAPI_ASSERT( mss::is_functional<TT::PORT_TYPE>(iv_target, l_relative_port_number),
+ ET::memdiags_port_not_functional()
+ .set_RELATIVE_PORT_POSITION(l_relative_port_number)
+ .set_ADDRESS( uint64_t(iv_const.iv_start_address) )
+ .set_MC_TARGET(iv_target),
+ "Port with relative postion %d is not functional for %s",
+ l_relative_port_number, mss::c_str(iv_target));
+
+ // No broadcast mode for this one
+ // Push on a read subtest
+ {
+ mss::mcbist::subtest_t<MC> l_subtest = iv_subtest;
+
+ l_subtest.enable_port(l_relative_port_number);
+ l_subtest.enable_dimm(l_dimm_number);
+ iv_program.iv_subtests.push_back(l_subtest);
+ FAPI_INF("%s adding subtest 0x%04x for port %d, DIMM %d",
+ mss::c_str(iv_target), l_subtest, l_relative_port_number, l_dimm_number);
+ }
+
+ // The address should have the port and DIMM noted in it. All we need to do is calculate the
+ // remainder of the address
+ if (iv_sim)
+ {
+ iv_const.iv_start_address.get_sim_end_address(iv_const.iv_end_address);
+ }
+ else if (iv_const.iv_end_address == TT::LARGEST_ADDRESS)
+ {
+ // Only the DIMM range as we don't want to cross ports.
+ iv_const.iv_start_address.template get_range<mss::mcbist::address::DIMM>(iv_const.iv_end_address);
+ }
+
+ // Configure the address range
+ FAPI_TRY( mss::mcbist::config_address_range0<MC>(iv_target, iv_const.iv_start_address, iv_const.iv_end_address) );
+
+ // Initialize the common sections
+ FAPI_TRY( base_init() );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+
+///
+/// @brief memdiags multi-port init helper
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType - derived
+/// @tparam TT the mcbistTraits associated with T
+/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes
+/// in subclassed constructors more easily.
+/// @return FAPI2_RC_SUCCESS iff everything ok
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT >
+inline fapi2::ReturnCode operation<MC, T, TT>::multi_port_init()
+{
+ FAPI_INF("multi-port init for %s", mss::c_str(iv_target));
+
+ const auto l_port = mss::find_targets<TT::PORT_TYPE>(iv_target);
+
+ // Make sure we have ports, if we don't then exit out
+ if(l_port.size() == 0)
+ {
+ // Cronus can have no ports under an MCBIST, FW deconfigures by association
+ FAPI_INF("%s has no attached ports skipping setup", mss::c_str(iv_target));
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // Let's assume we are going to send out all subtest unless we are in broadcast mode,
+ // where we only send up to 2 subtests under an port ( 1 for each DIMM) which is why no const
+ auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target);
+
+ if( l_dimms.size() == 0)
+ {
+ // Cronus can have no DIMMS under an MCBIST, FW deconfigures by association
+ FAPI_INF("%s has no attached DIMMs skipping setup", mss::c_str(iv_target));
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ return multi_port_init_internal();
+}
+
+
+///
+/// @class Class for memdiags' super-fast init
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+struct sf_init_operation : public operation<MC>
+{
+
+ ///
+ /// @brief memdiags::sf_init_operation constructor
+ /// @param[in] i_target the target of the mcbist engine
+ /// @param[in] i_const mss::constraint structure
+ /// @param[out] o_rc the fapi2::ReturnCode of the intialization process
+ ///
+ sf_init_operation( const fapi2::Target<T>& i_target,
+ const constraints<MC> i_const,
+ fapi2::ReturnCode& o_rc):
+ operation<MC>(i_target, mss::mcbist::init_subtest<MC>(), i_const)
+ {
+ // If sf_init was passed the random data pattern, then modify the subtest to use the true random data
+ if(i_const.iv_pattern == PATTERN_RANDOM)
+ {
+ this->iv_subtest.change_data_mode(mss::mcbist::data_mode::RAND_FWD_MAINT);
+ }
+
+ // We're a multi-port operation
+ o_rc = this->multi_port_init();
+ }
+
+ sf_init_operation() = delete;
+};
+
+
+
+///
+/// @class Class for memdiags' super-fast read
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+struct sf_read_operation : public operation<MC>
+{
+
+ ///
+ /// @brief memdiags::sf_read_operation constructor
+ /// @param[in] i_target the target of the mcbist engine
+ /// @param[in] i_const mss::constraint structure
+ /// @param[out] o_rc the fapi2::ReturnCode of the intialization process
+ ///
+ sf_read_operation( const fapi2::Target<T>& i_target,
+ const constraints<MC> i_const,
+ fapi2::ReturnCode& o_rc):
+ operation<MC>(i_target, mss::mcbist::read_subtest<MC>(), i_const)
+ {
+ // We're a multi-port operation
+ o_rc = this->multi_port_init();
+ }
+
+ sf_read_operation() = delete;
+};
+
+
+///
+/// @class Class for memdiags' super-fast read to end of port
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+struct sf_read_eop_operation : public operation<MC>
+{
+ ///
+ /// @brief memdiags::sf_read_operation constructor
+ /// @param[in] i_target the target of the mcbist engine
+ /// @param[in] i_const mss::constraint structure
+ /// @param[out] o_rc the fapi2::ReturnCode of the intialization process
+ ///
+ sf_read_eop_operation( const fapi2::Target<T>& i_target,
+ const constraints<MC> i_const,
+ fapi2::ReturnCode& o_rc ):
+ operation<MC>(i_target, mss::mcbist::read_subtest<MC>(), i_const)
+ {
+ // We're a single-port operation
+ o_rc = this->single_port_init();
+ }
+
+ sf_read_eop_operation() = delete;
+};
+
+///
+/// @class Class for memdiags' continuous scrub
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+struct continuous_scrub_operation : public operation<MC>
+{
+
+ ///
+ /// @brief memdiags::continuous_scrub_operation constructor
+ /// @param[in] i_target the target of the mcbist engine
+ /// @param[in] i_const the contraints of the operation
+ /// @param[out] o_rc the fapi2::ReturnCode of the intialization process
+ ///
+ continuous_scrub_operation( const fapi2::Target<T>& i_target,
+ const constraints<MC> i_const,
+ fapi2::ReturnCode& o_rc );
+
+ continuous_scrub_operation() = delete;
+};
+
+///
+/// @brief memdiags::continuous_scrub_operation constructor
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+/// @param[in] i_target the target of the mcbist engine
+/// @param[in] i_const the contraints of the operation
+/// @param[out] o_rc the fapi2::ReturnCode of the intialization process
+///
+template< mss::mc_type MC, fapi2::TargetType T, typename TT>
+continuous_scrub_operation<MC, T, TT>::continuous_scrub_operation(
+ const fapi2::Target<T>& i_target,
+ const constraints<MC> i_const,
+ fapi2::ReturnCode& o_rc ):
+ operation<MC>(i_target, mss::mcbist::scrub_subtest<MC>(), i_const)
+{
+ mss::mcbist::address l_generic_start_address;
+ mss::mcbist::address l_generic_end_address;
+
+ FAPI_INF("setting up for continuous scrub for %s", mss::c_str(i_target));
+
+ // Scrub operations run 128B
+ operation<MC>::iv_program.change_len64(mss::OFF);
+
+ // We build a little program here which allows us to restart the loop in the event of a pause.
+ // So we need to craft some of the address ranges and some of the subtests by hand.
+
+ // Setup address config 0 to cover all the addresses for a port/dimm.
+ // We leverage the MCBIST's ability to skip invalid addresses, and just setup
+ // If we're running in the simulator, we want to only touch the addresses which training touched
+ // *INDENT-OFF*
+ operation<MC>::iv_sim ?
+ l_generic_start_address.get_sim_end_address(l_generic_end_address) :
+ l_generic_start_address.get_range<mss::mcbist::address::DIMM>(l_generic_end_address);
+ // *INDENT-ON*
+
+ FAPI_TRY( mss::mcbist::config_address_range0<MC>(i_target, l_generic_start_address, l_generic_end_address) );
+
+ // We push on a fake subtest 0 and subtest 1. We fix them up after we fill in the
+ // rest of the subtests.
+ operation<MC>::iv_program.iv_subtests.push_back(operation<MC>::iv_subtest);
+ operation<MC>::iv_program.iv_subtests.push_back(operation<MC>::iv_subtest);
+
+ // a generic 0 - DIMM address range.
+ //
+ // Subtests 2-9: One subtest per port/dimm each covering the whole range of that
+ // port/dimm. scrub_subtests by default are using address config 0, so each of
+ // these get their full address complement.
+ for (const auto& p : operation<MC>::iv_target.template getChildren<TT::PORT_TYPE>())
+ {
+ for (const auto& d : p.template getChildren<fapi2::TARGET_TYPE_DIMM>())
+ {
+ // Don't destroy the subtest passed in, copy it
+ auto l_subtest = operation<MC>::iv_subtest;
+
+ l_subtest.enable_port(mss::relative_pos<T>(p));
+ l_subtest.enable_dimm(mss::index(d));
+ operation<MC>::iv_program.iv_subtests.push_back(l_subtest);
+ FAPI_INF("adding scrub subtest for %s (dimm %d) ( 0x%04x)", mss::c_str(d), mss::index(d), l_subtest);
+ }
+ }
+
+ //
+ // Subtest 10: goto subtest 2. This causes us to loop back to the first port/dimm and go thru them all
+ // This subtest will be marked the last when the MCBMR registers are filled in.
+ //
+ operation<MC>::iv_program.iv_subtests.push_back(mss::mcbist::goto_subtest<MC>(2));
+ FAPI_INF("last goto subtest (10) is going to subtest 2 ( 0x%04x) for %s", operation<MC>::iv_program.iv_subtests[2],
+ mss::c_str(operation<MC>::iv_target));
+
+ // Ok, now we can go back in to fill in the first two subtests.
+
+ {
+ auto l_subtest = operation<MC>::iv_subtest;
+ auto l_port = operation<MC>::iv_const.iv_start_address.get_port();
+ auto l_dimm = operation<MC>::iv_const.iv_start_address.get_dimm();
+ size_t l_index = 2;
+
+ // By default if we don't find our port/dimm in the subtests, we just go back to the beginning.
+ uint64_t l_goto_subtest = 2;
+
+ //
+ // subtest 0
+ //
+
+ // load the start address given and calculate the end address. Stick this into address config 1
+ // We don't need to account for the simulator here as the caller can do that when they setup the
+ // start address.
+ // *INDENT-OFF*
+ operation<MC>::iv_sim ?
+ operation<MC>::iv_const.iv_start_address.get_sim_end_address(operation<MC>::iv_const.iv_end_address) :
+ operation<MC>::iv_const.iv_start_address.template get_range<mss::mcbist::address::DIMM>(operation<MC>::iv_const.iv_end_address);
+ // *INDENT-ON*
+
+ FAPI_TRY( mss::mcbist::config_address_range1(i_target, operation<MC>::iv_const.iv_start_address,
+ operation<MC>::iv_const.iv_end_address) );
+
+ // We need to use this address range. We know it's ok to write to element 0 as we pushed it on above
+ l_subtest.change_addr_sel(1);
+ l_subtest.enable_port(l_port);
+ l_subtest.enable_dimm(l_dimm);
+
+ operation<MC>::iv_program.iv_subtests[0] = l_subtest;
+ FAPI_INF("adding scrub subtest 0 for port %d dimm %d (0x%04x) for %s", l_port, l_dimm, l_subtest, mss::c_str(i_target));
+
+ //
+ // subtest 1
+ //
+
+ // From the port/dimm specified in the start address, we know what subtest should execute next. The idea
+ // being that this 0'th subtest is a mechanism to allow the caller to start a scrub 'in the middle' and
+ // jump to the next port/dimm which would have been scrubbed. The hard part is that we don't know where
+ // in the subtest vector the 'next' port/dimm are placed. So we look for our port/dimm (skipping subtest 0
+ // since we know that's us and skipping subtest 1 since it isn't there yet.)
+ for (; l_index < operation<MC>::iv_program.iv_subtests.size(); ++l_index)
+ {
+ auto l_my_dimm = operation<MC>::iv_program.iv_subtests[l_index].get_dimm();
+ auto l_my_port = operation<MC>::iv_program.iv_subtests[l_index].get_port();
+
+ if ((l_dimm == l_my_dimm) && (l_port == l_my_port))
+ {
+ l_goto_subtest = l_index + 1;
+ break;
+ }
+ }
+
+ // Since we set l_goto_subtest up with a meaningful default, we can just make a subtest with the
+ // l_goto_subtest subtest specified and pop that in to index 1.
+ FAPI_INF("adding scrub subtest 1 to goto subtest %d (port %d, dimm %d, test 0x%04x) for %s", l_goto_subtest,
+ operation<MC>::iv_program.iv_subtests[l_goto_subtest].get_port(),
+ operation<MC>::iv_program.iv_subtests[l_goto_subtest].get_dimm(),
+ operation<MC>::iv_program.iv_subtests[l_goto_subtest], mss::c_str(i_target) );
+
+ operation<MC>::iv_program.iv_subtests[1] = mss::mcbist::goto_subtest<MC>(l_goto_subtest);
+ }
+
+ // Initialize the common sections
+ FAPI_TRY( operation<MC>::base_init() );
+
+fapi_try_exit:
+ o_rc = fapi2::current_err;
+ return;
+}
+
+
+
+///
+/// @class Class for memdiags' targeted scrub
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+struct targeted_scrub_operation : public operation<MC>
+{
+
+ ///
+ /// @brief memdiags::targeted_scrub_operation constructor
+ /// @param[in] i_target the target of the mcbist engine
+ /// @param[in] i_const the contraints of the operation
+ /// @param[out] o_rc the fapi2::ReturnCode of the intialization process
+ ///
+ targeted_scrub_operation( const fapi2::Target<T>& i_target,
+ const constraints<MC> i_const,
+ fapi2::ReturnCode& o_rc ):
+ operation<MC>(i_target, mss::mcbist::scrub_subtest<MC>(), i_const)
+ {
+ // Scrub operations run 128B
+ this->iv_program.change_len64(mss::OFF);
+
+ // We're a single-port operation
+ o_rc = this->single_port_init();
+
+ // Targeted scrub needs to force a pause and the end boundary. So we make sure that happens here.
+ this->iv_program.change_forced_pause( i_const.iv_end_boundary );
+ }
+
+ targeted_scrub_operation() = delete;
+};
+
+///
+/// @brief Super Fast Init - used to init all memory behind a target with a given pattern
+/// @note Uses broadcast mode if possible
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType of the target
+/// @param[in] i_target the target behind which all memory should be initialized
+/// @param[in] i_pattern an index representing a pattern to use to init memory (defaults to 0)
+/// @return FAPI2_RC_SUCCESS iff everything ok
+/// @note The function is asynchronous, and the caller should be looking for a done attention
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+fapi2::ReturnCode sf_init( const fapi2::Target<T>& i_target,
+ const uint64_t i_pattern = PATTERN_0 )
+{
+ using ET = mss::mcbistMCTraits<MC>;
+ FAPI_INF("superfast init start for %s", mss::c_str(i_target));
+
+ uint8_t l_sim = false;
+ FAPI_TRY( mss::attr::get_is_simulation( l_sim) );
+
+ if (l_sim)
+ {
+ // Use some sort of pattern in sim in case the verification folks need to look for something
+ // TK. Need a verification pattern. This is a not-good pattern for verification ... We don't really
+ // have a good pattern for verification defined.
+ FAPI_INF("running mss sim init in place of sf_init for %s", mss::c_str(i_target));
+ return mss::mcbist::sim::sf_init<MC>(i_target, i_pattern);
+ }
+ else
+ {
+ fapi2::ReturnCode l_rc;
+ constraints<MC> l_const(i_pattern);
+ sf_init_operation<MC> l_init_op(i_target, l_const, l_rc);
+
+ FAPI_ASSERT( l_rc == fapi2::FAPI2_RC_SUCCESS,
+ ET::memdiags_sf_init_failed_init().set_MC_TARGET(i_target),
+ "Unable to initialize the MCBIST engine for a sf read %s", mss::c_str(i_target) );
+
+ return l_init_op.execute();
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Super Fast Read - used to run superfast read on all memory behind the target
+/// Determines ability to braodcast to all ports behind a target, does so if possible.
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType of the target
+/// @tparam TT the mcbistTraits associated with T - derived
+/// @param[in] i_target the target behind which all memory should be read
+/// @param[in] i_stop stop conditions
+/// @param[in] i_address mcbist::address representing the address from which to start.
+// Defaults to the first address behind the target
+/// @param[in] i_end whether to end, and where
+/// Defaults to stop after slave rank
+/// @param[in] i_end_address mcbist::address representing the address to end.
+// Defaults to TT::LARGEST_ADDRESS
+/// @return FAPI2_RC_SUCCESS iff everything ok
+/// @note The function is asynchronous, and the caller should be looking for a done attention
+/// @note The address is often the port, dimm, rank but this is not enforced in the API.
+///
+template< mss::mc_type MC, fapi2::TargetType T = mss::mcbistMCTraits<MC>::MC_TARGET_TYPE , typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode sf_read( const fapi2::Target<T>& i_target,
+ const stop_conditions<MC>& i_stop,
+ const mss::mcbist::address& i_address = mss::mcbist::address(),
+ const end_boundary i_end = end_boundary::STOP_AFTER_SLAVE_RANK,
+ const mss::mcbist::address& i_end_address = mss::mcbist::address(TT::LARGEST_ADDRESS) )
+{
+ using ET = mss::mcbistMCTraits<MC>;
+ FAPI_INF("superfast read - start for %s", mss::c_str(i_target));
+
+ FAPI_TRY( pre_maint_read_settings<MC>(i_target) );
+
+ {
+ fapi2::ReturnCode l_rc;
+ constraints<MC> l_const(i_stop, speed::LUDICROUS, i_end, i_address, i_end_address);
+ sf_read_operation<MC> l_read_op(i_target, l_const, l_rc);
+
+ FAPI_ASSERT( l_rc == fapi2::FAPI2_RC_SUCCESS,
+ ET::memdiags_sf_init_failed_init().set_MC_TARGET(i_target),
+ "Unable to initialize the MCBIST engine for a sf read %s", mss::c_str(i_target) );
+
+ return l_read_op.execute();
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Scrub - continuous scrub all memory behind the target
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType of the target
+/// @param[in] i_target the target behind which all memory should be scrubbed
+/// @param[in] i_stop stop conditions
+/// @param[in] i_speed the speed to scrub
+/// @param[in] i_address mcbist::address representing the address from which to start.
+/// @return FAPI2_RC_SUCCESS iff everything ok
+/// @note The function is asynchronous, and the caller should be looking for a done attention
+/// @note The address is often the port, dimm, rank but this is not enforced in the API.
+///
+template< mss::mc_type MC, fapi2::TargetType T >
+fapi2::ReturnCode background_scrub( const fapi2::Target<T>& i_target,
+ const stop_conditions<MC>& i_stop,
+ const speed i_speed,
+ const mss::mcbist::address& i_address )
+{
+ using ET = mss::mcbistMCTraits<MC>;
+ FAPI_INF("continuous (background) scrub for %s", mss::c_str(i_target));
+
+ FAPI_TRY( pre_scrub_settings<MC>(i_target) );
+
+ {
+ fapi2::ReturnCode l_rc;
+ constraints<MC> l_const(i_stop, i_speed, end_boundary::STOP_AFTER_ADDRESS, i_address);
+ continuous_scrub_operation<MC> l_op(i_target, l_const, l_rc);
+
+ FAPI_ASSERT( l_rc == fapi2::FAPI2_RC_SUCCESS,
+ ET::memdiags_continuous_scrub_failed_init().set_MC_TARGET(i_target),
+ "Unable to initialize the MCBIST engine for a continuous scrub %s", mss::c_str(i_target) );
+
+ return l_op.execute();
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Scrub - targeted scrub all memory described by the input address (rank, slave, etc.)
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType of the target
+/// @param[in] i_target the target behind which all memory should be scrubbed
+/// @param[in] i_stop stop conditions
+/// @param[in] i_speed the speed to scrub
+/// @param[in] i_start_address mcbist::address representing the address from which to start.
+/// @param[in] i_end_address mcbist::address representing the address at which to end.
+/// @param[in] i_end whether to end, and where
+/// @return FAPI2_RC_SUCCESS iff everything ok
+/// @note The function is asynchronous, and the caller should be looking for a done attention
+/// @note The address is often the port, dimm, rank but this is not enforced in the API.
+///
+template< mss::mc_type MC, fapi2::TargetType T >
+fapi2::ReturnCode targeted_scrub( const fapi2::Target<T>& i_target,
+ const stop_conditions<MC>& i_stop,
+ const mss::mcbist::address& i_start_address,
+ const mss::mcbist::address& i_end_address,
+ const end_boundary i_end )
+{
+ using ET = mss::mcbistMCTraits<MC>;
+ FAPI_INF("targeted scrub for %s", mss::c_str(i_target));
+
+ FAPI_TRY( pre_scrub_settings<MC>(i_target) );
+
+ {
+ fapi2::ReturnCode l_rc;
+ constraints<MC> l_const(i_stop, speed::LUDICROUS, i_end, i_start_address, i_end_address);
+ targeted_scrub_operation<MC> l_op(i_target, l_const, l_rc);
+
+ FAPI_ASSERT( l_rc == fapi2::FAPI2_RC_SUCCESS,
+ ET::memdiags_targeted_scrub_failed_init().set_MC_TARGET(i_target),
+ "Unable to initialize the MCBIST engine for a targeted scrub %s", mss::c_str(i_target) );
+
+ return l_op.execute();
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Continue current command on next address
+/// The current commaand has paused on an error, so we can record the address of the error
+/// and finish the current master or slave rank.
+/// @tparam MC the mc type of the T
+/// @tparam T the fapi2::TargetType of the target
+/// @param[in] i_target the target
+/// @param[in] i_end whether to end, and where (default - don't stop at end of rank)
+/// @param[in] i_stop stop conditions (default - 0 meaning 'don't change conditions')
+/// @param[in] i_speed the speed to scrub (default - SAME_SPEED meaning leave speed untouched)
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T >
+fapi2::ReturnCode continue_cmd( const fapi2::Target<T>& i_target,
+ const end_boundary i_end = end_boundary::DONT_CHANGE,
+ const stop_conditions<MC>& i_stop = stop_conditions<MC>(stop_conditions<MC>::DONT_CHANGE),
+ const speed i_speed = speed::SAME_SPEED )
+{
+ // Too long, make shorter
+ using TT = mss::mcbistTraits<MC, T>;
+ using ET = mss::mcbistMCTraits<MC>;
+
+ // We can use a local mcbist::program to help with the bit processing, and then write just the registers we touch.
+ mss::mcbist::program<MC> l_program;
+ fapi2::buffer<uint64_t> l_status;
+
+ FAPI_INF("continue_cmd for %s", mss::c_str(i_target));
+
+ // TODO RTC:155518 Check for stop or in progress before allowing continue. Not critical
+ // as the caller should know and can check the in-progress bit in the event they don't
+
+ if (i_end != end_boundary::DONT_CHANGE)
+ {
+ // Before we go too far, check to see if we're already stopped at the boundary we are asking to stop at
+ bool l_stopped_at_boundary = false;
+ uint64_t l_error_mode = 0;
+ bool l_detect_slave = false;
+
+ FAPI_TRY( mss::getScom(i_target, TT::CFGQ_REG, l_program.iv_config) );
+ FAPI_TRY( mss::getScom(i_target, TT::MCBAGRAQ_REG, l_program.iv_addr_gen) );
+ l_program.iv_config.template extractToRight<TT::CFG_PAUSE_ON_ERROR_MODE, TT::CFG_PAUSE_ON_ERROR_MODE_LEN>(l_error_mode);
+ l_detect_slave = l_program.iv_addr_gen.template getBit<TT::MAINT_DETECT_SRANK_BOUNDARIES>();
+
+
+ switch (i_end)
+ {
+ case end_boundary::STOP_AFTER_ADDRESS:
+ l_stopped_at_boundary =
+ l_program.iv_config.template getBit< TT::MCBIST_CFG_FORCE_PAUSE_AFTER_ADDR>() ||
+ l_error_mode == end_boundary::STOP_AFTER_ADDRESS;
+ break;
+
+ case end_boundary::STOP_AFTER_SLAVE_RANK:
+ // Note: we really want STOP_AFTER_MASTER_RANK here even though we're in the slave
+ // case because MASTER_RANK has the a 0 so that l_error_mode will check correctly
+ l_stopped_at_boundary =
+ l_program.iv_config.template getBit< TT::MCBIST_CFG_PAUSE_AFTER_RANK>() ||
+ ((l_error_mode == end_boundary::STOP_AFTER_MASTER_RANK) && (l_detect_slave == false));
+ break;
+
+ case end_boundary::STOP_AFTER_MASTER_RANK:
+ l_stopped_at_boundary =
+ l_program.iv_config.template getBit< TT::MCBIST_CFG_PAUSE_AFTER_RANK>() ||
+ ((l_error_mode == end_boundary::STOP_AFTER_MASTER_RANK) && (l_detect_slave == true));
+ break;
+
+ case end_boundary::STOP_AFTER_SUBTEST:
+ l_stopped_at_boundary =
+ l_program.iv_config.template getBit< TT::MCBIST_CFG_FORCE_PAUSE_AFTER_SUBTEST>() ||
+ l_error_mode == end_boundary::STOP_AFTER_SUBTEST;
+ break;
+
+ // By default we're not stopped at a boundary we're going to continue from
+ default:
+ break;
+ };
+
+ FAPI_ASSERT( l_stopped_at_boundary == false,
+ ET::memdiags_already_at_boundary().set_MC_TARGET(i_target).set_BOUNDARY(i_stop),
+ "Asked to stop at a boundary, but we're already there" );
+
+ // Ok, if we're here either we need to change the stop and boundary conditions.
+ // Read-modify-write the fields in the program.
+ FAPI_TRY( mss::getScom(i_target, TT::MCBAGRAQ_REG, l_program.iv_addr_gen) );
+
+ // Note: we are specifically not configuring broadcast mode here
+ // The continue command is called by PRD exclusively at mainline
+ // If we're at mainline, we can't run in broadcast mode
+ // If we ever need to call continue elsewhere, we'll need to do the following
+ // 1) add the function to configure broadcast mode
+ // 2) add in a switch to disable broadcast mode if we're at runtime
+
+ l_program.change_end_boundary(i_end);
+
+ FAPI_TRY( mss::mcbist::load_addr_gen(i_target, l_program) );
+
+ FAPI_TRY( mss::mcbist::load_config(i_target, l_program) );
+ }
+
+ // Thresholds
+ // According to API definition, 0 means don't change conditions
+ if( i_stop != stop_conditions<MC>::DONT_CHANGE)
+ {
+ FAPI_TRY( mss::mcbist::load_thresholds(i_target, i_stop) );
+ }
+
+ // Setup speed
+ FAPI_TRY( l_program.change_speed(i_target, i_speed) );
+
+ // Load new speed unless we aren't changing it
+ if( i_speed != speed::SAME_SPEED )
+ {
+ FAPI_TRY( load_mcbparm(i_target, l_program) );
+ }
+
+ // Tickle the resume from pause
+ FAPI_TRY( mss::mcbist::resume(i_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Begin initialize memory
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MC engine
+/// @tparam TT the mcbistTraits associated with T
+/// @param[in] i_target MC
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode mss_initialize_memory(const fapi2::Target<T>& i_target )
+{
+ using ET = mss::mcbistMCTraits<MC>;
+ FAPI_INF("Start mss_initialize_memory for %s", mss::c_str(i_target));
+
+ // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
+ // attributes for the PHY, etc.
+ if (mss::count_dimm(i_target) == 0)
+ {
+ FAPI_INF("... skipping scrub for %s - no DIMM ...", mss::c_str(i_target));
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // If we're running in the simulator, we want to only touch the addresses which training touched
+ uint8_t l_sim = 0;
+ bool l_poll_results = false;
+ fapi2::buffer<uint64_t> l_status;
+
+ // A small vector of addresses to poll during the polling loop
+ const std::vector<mss::poll_probe<T>> l_probes =
+ {
+ {i_target, "mcbist current address", TT::LAST_ADDR_REG},
+ };
+
+ // We'll fill in the initial delay below
+ mss::poll_parameters l_poll_parameters(0, 200, 100 * mss::DELAY_1MS, 200, 10000);
+ uint64_t l_memory_size = 0;
+
+ FAPI_TRY( mss::eff_memory_size<MC>(i_target, l_memory_size) );
+ l_poll_parameters.iv_initial_delay = mss::calculate_initial_delay<MC>(i_target, (l_memory_size * mss::BYTES_PER_GB));
+
+ FAPI_TRY( mss::attr::get_is_simulation( l_sim) );
+
+ if (l_sim)
+ {
+ FAPI_INF("running mss sim init in place of scrub for %s", mss::c_str(i_target));
+
+ // Use some sort of pattern in sim in case the verification folks need to look for something
+ // TK. Need a verification pattern. This is a not-good pattern for verification ... We don't really
+ // have a good pattern for verification defined.
+ auto l_rc = mss::mcbist::sim::sf_init<MC>(i_target, mss::mcbist::PATTERN_0);
+
+ // Unmask firs and turn off FIFO mode before returning
+ FAPI_TRY ( mss::unmask::after_memdiags<MC>( i_target ) );
+ FAPI_TRY ( mss::reset_reorder_queue_settings<MC>(i_target) );
+
+ return l_rc;
+ }
+
+ // In Cronus on hardware (which is how we got here - f/w doesn't call this) we want
+ // to call sf_init (0's)
+ // TK we need to check FIR given the way this is right now, we should adjust with better stop
+ // conditions when we learn more about what we want to find in the lab
+ FAPI_TRY( mss::memdiags::sf_init<MC>(i_target, mss::mcbist::PATTERN_0) );
+
+ // Poll for completion.
+ l_poll_results = mss::poll(i_target, TT::FIRQ_REG, l_poll_parameters,
+ [&l_status](const size_t poll_remaining,
+ const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_DBG("mcbist firq 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ l_status = stat_reg;
+ return l_status.getBit<TT::MCB_PROGRAM_COMPLETE>() == true;
+ },
+ l_probes);
+
+ FAPI_ASSERT( l_poll_results == true,
+ ET::memdiags_sf_init_failed_init().set_MC_TARGET(i_target),
+ "sf init for scrub/memdiags timedout %s", mss::c_str(i_target) );
+
+ // Unmask firs after memdiags and turn off FIFO mode
+ FAPI_TRY ( mss::unmask::after_memdiags<MC>( i_target ) );
+ FAPI_TRY ( mss::reset_reorder_queue_settings<MC>(i_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Begin background scrub helper
+/// @tparam MC the mc type of the T
+/// @tparam T fapi2::TargetType of the MCBIST engine
+/// @tparam TT the mcbistTraits associated with T
+/// @param[in] i_target MC
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = mcbistTraits<MC, T> >
+fapi2::ReturnCode mss_background_scrub_helper( const fapi2::Target<T>& i_target )
+{
+ FAPI_INF("Start mss_background_scrub_helper b on: %s", mss::c_str( i_target ));
+
+ // If there are no DIMM we don't need to bother. In fact, we can't as we didn't setup
+ // attributes for the PHY, etc.
+ if (mss::count_dimm(i_target) == 0)
+ {
+ FAPI_INF("... skipping background scrub for %s - no DIMM ...", mss::c_str(i_target));
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // If we're running in the simulator, we want to only touch the addresses which training touched
+ uint8_t l_sim = 0;
+ FAPI_TRY( mss::attr::get_is_simulation(l_sim) );
+
+ // Kick off background scrub if we are not running in sim
+ if (!(l_sim))
+ {
+ // Start background scrub
+ FAPI_TRY ( mss::memdiags::background_scrub<MC>( i_target,
+ mss::mcbist::stop_conditions<MC>(),
+ mss::mcbist::speed::BG_SCRUB,
+ mss::mcbist::address() ) );
+ }
+
+ // Unmask firs after background scrub is started
+ FAPI_TRY ( mss::unmask::after_background_scrub<MC>( i_target ) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // namespace memdiags
+
+} // namespace mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_patterns.C b/src/import/generic/memory/lib/utils/mcbist/gen_patterns.C
deleted file mode 100644
index 03053fc0f..000000000
--- a/src/import/generic/memory/lib/utils/mcbist/gen_patterns.C
+++ /dev/null
@@ -1,24 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_patterns.C $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
-/* [+] 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 */
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_patterns.H b/src/import/generic/memory/lib/utils/mcbist/gen_patterns.H
deleted file mode 100644
index f99518b7e..000000000
--- a/src/import/generic/memory/lib/utils/mcbist/gen_patterns.H
+++ /dev/null
@@ -1,24 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_patterns.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
-/* [+] 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 */
diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_settings.H b/src/import/generic/memory/lib/utils/mcbist/gen_settings.H
deleted file mode 100644
index 1d437f39c..000000000
--- a/src/import/generic/memory/lib/utils/mcbist/gen_settings.H
+++ /dev/null
@@ -1,24 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/utils/mcbist/gen_settings.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
-/* [+] 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 */
diff --git a/src/import/generic/memory/lib/utils/mcbist/settings.H b/src/import/generic/memory/lib/utils/mcbist/settings.H
deleted file mode 100644
index 0d0b10883..000000000
--- a/src/import/generic/memory/lib/utils/mcbist/settings.H
+++ /dev/null
@@ -1,24 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/generic/memory/lib/utils/mcbist/settings.H $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
-/* [+] 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 */
diff --git a/src/import/generic/memory/lib/utils/mss_bad_bits.H b/src/import/generic/memory/lib/utils/mss_bad_bits.H
index e6d2cdfa5..b39d84859 100644
--- a/src/import/generic/memory/lib/utils/mss_bad_bits.H
+++ b/src/import/generic/memory/lib/utils/mss_bad_bits.H
@@ -46,6 +46,17 @@ namespace mss
{
///
+/// @brief A generic bad bits getter
+/// @tparam MC type memory controller type
+/// @param[in] i_target the fapi2 target oon which training was conducted
+/// @param[out] o_array the bad bits array
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code
+///
+template <mss::mc_type MC>
+fapi2::ReturnCode get_bad_dq_bitmap(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint8_t (&o_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]);
+
+///
/// @brief A generic bad bits setter
/// @tparam MC type memory controller type
/// @param[in] i_target the fapi2 target oon which training was conducted
@@ -57,6 +68,23 @@ fapi2::ReturnCode set_bad_dq_bitmap(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>
uint8_t (&i_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]);
///
+/// @brief combine the two bad bits arrays into the io_bad_bits array
+/// @param[in] i_new_bad_bits bad bits to append
+/// @param[in,out] io_bad_bits will contain the bitwise or of the original io_bad_bits and i_new_bad_bits
+///
+inline void combine_bad_bits(const uint8_t (&i_new_bad_bits)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT],
+ uint8_t (&io_bad_bits)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT])
+{
+ for (uint8_t l_rank = 0; l_rank < BAD_BITS_RANKS; ++ l_rank)
+ {
+ for (uint8_t l_bad_dq_byte = 0; l_bad_dq_byte < BAD_DQ_BYTE_COUNT; ++l_bad_dq_byte)
+ {
+ io_bad_bits[l_rank][l_bad_dq_byte] |= i_new_bad_bits[l_rank][l_bad_dq_byte];
+ }
+ }
+}
+
+///
/// @brief Records bad bits into the bad bits attribute
/// @tparam MC MC type on which training was run
/// @tparam T fapi2::TargetType on which training was conducted
diff --git a/src/import/generic/memory/lib/utils/mss_field.H b/src/import/generic/memory/lib/utils/mss_field.H
index e22b2fa47..c69bde04f 100644
--- a/src/import/generic/memory/lib/utils/mss_field.H
+++ b/src/import/generic/memory/lib/utils/mss_field.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -37,8 +37,21 @@
#ifndef _MSS_FIELD_H_
#define _MSS_FIELD_H_
-#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
-#include <generic/memory/lib/utils/mss_generic_check.H>
+#ifdef __PPE__
+ #include <mss_generic_check.H>
+#else
+ #include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+ #include <generic/memory/lib/utils/mss_generic_check.H>
+#endif
+
+//Macro
+#ifdef __PPE__
+ #define TARGIDFORMAT "0x%08X"
+ #define TARGTID i_target.get()
+#else
+ #define TARGIDFORMAT "%s"
+ #define TARGTID spd::c_str(i_target)
+#endif
namespace mss
{
@@ -190,18 +203,18 @@ inline fapi2::ReturnCode get_field(const fapi2::Target<T>& i_target,
.set_LIST_SIZE(i_data.size())
.set_FUNCTION(i_ffdc_codes)
.set_TARGET(i_target),
- "Out of bounds indexing (with %d) on a list of size %d for %s",
+ "Out of bounds indexing (with %d) on a list of size %d for " TARGIDFORMAT,
BYTE,
i_data.size(),
- spd::c_str(i_target));
+ TARGTID);
{
// Extracting desired bits
const fapi2::buffer<OT> l_buffer(i_data[BYTE]);
l_buffer.template extractToRight<F.get_start(), F.get_length()>(o_value);
- FAPI_DBG("%s data[%d] = 0x%02x. Field with start bit %d, bit len %d, has data 0x%02x.",
- spd::c_str(i_target),
+ FAPI_DBG(TARGIDFORMAT " data[%d] = 0x%02x. Field with start bit %d, bit len %d, has data 0x%02x.",
+ TARGTID,
BYTE,
i_data[BYTE],
F.get_start(),
@@ -214,6 +227,7 @@ inline fapi2::ReturnCode get_field(const fapi2::Target<T>& i_target,
fapi_try_exit:
return fapi2::current_err;
}
+#ifndef __PPE__
///
/// @brief Helper function to set byte field information
@@ -274,6 +288,7 @@ inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
fapi_try_exit:
return fapi2::current_err;
}
+#endif
///
/// @brief byte field reader
@@ -303,7 +318,7 @@ inline fapi2::ReturnCode get_field( const fapi2::Target<T>& i_target,
{
IT l_temp = 0;
FAPI_TRY( (get_field<E, F>(i_target, i_data, i_ffdc_codes, l_temp)),
- "Failed get_field() for %s", spd::c_str(i_target) );
+ "Failed get_field() for " TARGIDFORMAT, TARGTID );
// Test if retrieved data seems valid
FAPI_TRY( check::invalid_value(i_target,
@@ -312,30 +327,33 @@ inline fapi2::ReturnCode get_field( const fapi2::Target<T>& i_target,
typename TT::template COMPARISON_OP<IT>() ),
F.get_byte(i_data),
l_temp,
- i_ffdc_codes),
- "Failed fail_for_invalid_value() for %s", spd::c_str(i_target) );
+ i_ffdc_codes,
+ TT::FIELD_STR),
+ "%s failed check::invalid_value() for %s",
+ TT::FIELD_STR, spd::c_str(i_target) );
// Output should only change if data check passes
o_value = static_cast<OT>(l_temp);
-
FAPI_ASSERT( o_value == l_temp,
fapi2::MSS_CONVERSION_ERROR()
.set_ORIGINAL_VAL(l_temp)
.set_CONVERTED_VAL(o_value)
.set_TARGET(i_target)
.set_FUNCTION(i_ffdc_codes),
- "Conversion error between original %d to converted %d value for %s",
- l_temp, o_value, spd::c_str(i_target) );
+ "Conversion error between original %d to converted %d value for " TARGIDFORMAT,
+ l_temp, o_value, TARGTID);
- FAPI_INF("%s: 0x%02x for %s",
+ FAPI_DBG("%s: 0x%02x for %s",
TT::FIELD_STR,
o_value,
spd::c_str(i_target));
+
fapi_try_exit:
return fapi2::current_err;
}
+#ifndef __PPE__
///
/// @brief byte field writer
/// @tparam E endian type
@@ -378,7 +396,7 @@ inline fapi2::ReturnCode set_field( const fapi2::Target<T>& i_target,
FAPI_TRY( (set_field<E, F>(i_target, i_setting, i_ffdc_codes, io_data)),
"Failed set_field() for %s", spd::c_str(i_target) );
- FAPI_INF("%s: Set value of 0x%02x. Data for buffer at byte %d, is now 0x%02x for %s",
+ FAPI_DBG("%s: Set value of 0x%02x. Data for buffer at byte %d, is now 0x%02x for %s",
TT::FIELD_STR,
i_setting,
BYTE,
@@ -388,6 +406,7 @@ inline fapi2::ReturnCode set_field( const fapi2::Target<T>& i_target,
fapi_try_exit:
return fapi2::current_err;
}
+#endif
}// mss
diff --git a/src/import/generic/memory/lib/utils/mss_generic_check.H b/src/import/generic/memory/lib/utils/mss_generic_check.H
index f31440e14..45428b8c3 100644
--- a/src/import/generic/memory/lib/utils/mss_generic_check.H
+++ b/src/import/generic/memory/lib/utils/mss_generic_check.H
@@ -37,15 +37,18 @@
#define _MSS_GENERIC_CHECK_H_
#include <fapi2.H>
-#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
-#include <generic/memory/lib/utils/scom.H>
-#include <generic/memory/lib/utils/c_str.H>
+
+#ifndef __PPE__
+ #include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+ #include <generic/memory/lib/utils/scom.H>
+ #include <generic/memory/lib/utils/c_str.H>
+#endif
namespace mss
{
namespace check
{
-
+#ifndef __PPE__
///
/// @brief Checks whether any FIRs have lit up on a target
/// @tparam MC MC type for which to check FIR's
@@ -175,6 +178,7 @@ fapi2::ReturnCode fir_or_pll_fail( const fapi2::Target<T>& i_target,
#endif
}
+#endif
///
/// @brief Checks conditional passes and implements traces & exits if it fails
/// @tparam T fapi2 target type
@@ -196,6 +200,18 @@ inline fapi2::ReturnCode invalid_value(const fapi2::Target<T>& i_target,
const FFDC i_ffdc_codes,
const char* i_err_str = "")
{
+#ifdef __PPE__
+ FAPI_ASSERT(i_conditional,
+ fapi2::MSS_FAILED_DATA_INTEGRITY_CHECK().
+ set_VALUE(i_data).
+ set_BYTE(i_byte_index).
+ set_TARGET(i_target).
+ set_FFDC_CODE(i_ffdc_codes),
+ "%s Byte %d, Data returned: %d.",
+ i_err_str,
+ i_byte_index,
+ i_data);
+#else
FAPI_ASSERT(i_conditional,
fapi2::MSS_FAILED_DATA_INTEGRITY_CHECK().
set_VALUE(i_data).
@@ -208,6 +224,7 @@ inline fapi2::ReturnCode invalid_value(const fapi2::Target<T>& i_target,
i_byte_index,
i_data);
+#endif
return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
diff --git a/src/import/generic/memory/lib/utils/mss_math.H b/src/import/generic/memory/lib/utils/mss_math.H
index ebb3da8e3..b3ff26fde 100644
--- a/src/import/generic/memory/lib/utils/mss_math.H
+++ b/src/import/generic/memory/lib/utils/mss_math.H
@@ -107,6 +107,35 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Round value to a multiple of another number
+///
+/// @param[in] i_value value to round
+/// @param[in] i_multiple multiple to round to
+/// @return uint64_t rounded value
+///
+inline uint32_t round_to_nearest_multiple(const uint32_t i_value, const uint32_t i_multiple)
+{
+ return ((i_value + i_multiple / 2) / i_multiple) * i_multiple;
+}
+
+///
+/// @brief Determines if the double has decimal digits and adds 1 and rounds if true
+/// @param[in] i_val the double to be rounded up if trialing digits
+/// @return the input value rounded up to the next whole digit
+/// @note Called in p9_mss_bulk_pwr_throttles
+///
+inline uint32_t round_up(const double i_val)
+{
+ //convert to uint to truncate decimals and convert back to double for comparison
+ uint32_t temp = uint32_t (i_val);
+
+ //if not equal, lost something from truncating, so add 1
+ temp += (temp == i_val) ? 0 : 1;
+
+ //Truncate final value
+ return temp;
+}
}// mss
diff --git a/src/import/generic/memory/lib/utils/mss_rank.H b/src/import/generic/memory/lib/utils/mss_rank.H
index b43e7e6ff..f4731df46 100644
--- a/src/import/generic/memory/lib/utils/mss_rank.H
+++ b/src/import/generic/memory/lib/utils/mss_rank.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
+/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,3 +22,327 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file mss_rank.H
+/// @brief Tools to obtain rank info from DIMM or PORT target
+///
+// *HWP HWP Owner: Mark Pizzutillo <Mark.Pizzutillo@ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_GENERIC_RANK_H_
+#define _MSS_GENERIC_RANK_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/index.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+namespace mss
+{
+namespace rank
+{
+
+///
+/// @brief Rank traits class for variations depending on MC
+/// @tparam MC the memory controller type
+///
+template <mss::mc_type MC = DEFAULT_MC_TYPE>
+class rankTraits;
+
+///
+/// @brief Rank info class
+/// @tparam MC the memory controller type
+/// @tparam TT the class traits for the port
+///
+template <mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = rankTraits<MC>>
+class info
+{
+
+ public:
+ // Delete default constructor
+ info() = delete;
+
+ ///
+ /// @brief Constructor for info object
+ /// @param[in] i_target DIMM target
+ /// @param[in] i_index dimm rank index 0-3
+ /// @param[out] o_rc return code, FAPI2_RC_SUCCESS if no error
+ ///
+ info(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm_target, const uint8_t i_index, fapi2::ReturnCode& o_rc)
+ {
+ o_rc = fapi2::FAPI2_RC_SUCCESS;
+
+ uint8_t l_master_ranks_per_dimm = 0;
+ FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_dimm_target, l_master_ranks_per_dimm));
+
+ FAPI_ASSERT((i_index < l_master_ranks_per_dimm),
+ fapi2::MSS_RANK_OUT_OF_RANGE()
+ .set_TARGET(i_dimm_target)
+ .set_RANK(i_index),
+ "Rank %u provided to info constructor for DIMM %s exceeded the number of master ranks per DIMM",
+ i_index, mss::c_str(i_dimm_target));
+ // Targets
+ iv_dimm_target = i_dimm_target;
+ iv_port_target = mss::find_target<DEFAULT_MEM_PORT_TARGET>(i_dimm_target);
+
+ // Ranks
+ iv_dimm_rank = i_index;
+ iv_port_rank = iv_dimm_rank + ((mss::index(i_dimm_target) * TT::RANK_INDEX_STEP));
+ iv_phy_rank = iv_dimm_rank + ((mss::index(i_dimm_target) * TT::PHY_RANK_INDEX_STEP));
+ fapi_try_exit:
+ o_rc = fapi2::current_err;
+ }
+
+ ///
+ /// @brief Constructor for info object
+ /// @param[in] i_target PORT target
+ /// @param[in] i_index port rank index 0-7
+ /// @param[out] o_rc return code, FAPI2_RC_SUCCESS if no error
+ ///
+ info(const fapi2::Target<DEFAULT_MEM_PORT_TARGET>& i_port_target, const uint8_t i_index, fapi2::ReturnCode& o_rc)
+ {
+ o_rc = fapi2::FAPI2_RC_SUCCESS;
+
+ // Dimm Target
+ const uint8_t l_target_index = i_index / TT::RANK_INDEX_STEP;
+ const auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_port_target);
+
+ // This assumes that the mc_type max # of dimms per port is correct
+ FAPI_ASSERT( !l_dimms.empty(),
+ fapi2::MSS_EMPTY_VECTOR().
+ set_FUNCTION(INIT_RANK_INFO).
+ set_TARGET(i_port_target),
+ "Empty dimm vector received on port %s",
+ mss::spd::c_str(i_port_target));
+
+ {
+ // This will remain false in two cases:
+ // Either:
+ // 1. The corresponding DIMM index is out of range (caused by port index out of range)
+ // 2. The corresponding DIMMs master_ranks_per_dimm is less than the desired rank
+ bool l_valid_rank = false;
+
+ for (const auto& l_dimm : l_dimms)
+ {
+ // Since we can't guarantee the order of the returned dimms, we iterate through until we (might) find
+ // the right one. There's a chance it may not exist for example given info(port, rank13) would give us
+ // a dimm index above 2, which may be out of range, so we could never find a matching dimm, so we will
+ // throw that error.
+ // If we do find the right dimm, we need to then make sure that the master_ranks_per_dimm attribute
+ // is greater than the expected dimm rank.
+ if (mss::index(l_dimm) == l_target_index)
+ {
+ uint8_t l_master_ranks_per_dimm = 0;
+ FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(l_dimm, l_master_ranks_per_dimm));
+
+ // The rank passed in matches one of a valid DIMM
+ l_valid_rank = (i_index % TT::RANK_INDEX_STEP) < l_master_ranks_per_dimm;
+
+ iv_dimm_target = l_dimm;
+ }
+ }
+
+ FAPI_ASSERT(l_valid_rank,
+ fapi2::MSS_RANK_OUT_OF_RANGE()
+ .set_TARGET(i_port_target)
+ .set_RANK(i_index),
+ "Rank %u provided to rank_info constructor for PORT %s was out of range",
+ i_index, mss::c_str(i_port_target));
+
+ // Port Target
+ iv_port_target = i_port_target;
+
+ // Ranks
+ iv_dimm_rank = i_index % TT::RANK_INDEX_STEP;
+ iv_phy_rank = get_phy_rank_from_port_rank(i_index);
+ iv_port_rank = i_index;
+ }
+
+ fapi_try_exit:
+ o_rc = fapi2::current_err;
+ }
+
+ ///
+ /// @brief Accessor for port rank
+ /// @return the number (0-7) of the rank within its port
+ ///
+ inline const uint8_t get_port_rank() const
+ {
+ return iv_port_rank;
+ }
+
+ ///
+ /// @brief Accessor for rank number of DIMM
+ /// @return the number (0-3) of the DIMM
+ ///
+ inline const uint8_t get_dimm_rank() const
+ {
+ return iv_dimm_rank;
+ }
+
+ ///
+ /// @brief Accessor for phy rank
+ /// @return the phy rank value
+ /// @note in a hypothetical 2 4-rank dimm configuration (not possible), this value is not valid
+ ///
+ inline const uint8_t get_phy_rank() const
+ {
+ return iv_phy_rank;
+ }
+
+ ///
+ /// @brief Accessor for DIMM target
+ /// @return the dimm target associated with the rank
+ ///
+ inline const fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const
+ {
+ return iv_dimm_target;
+ }
+
+ ///
+ /// @brief Accessor for PORT target
+ /// @return the port target associated with the rank
+ ///
+ inline const fapi2::Target<DEFAULT_MEM_PORT_TARGET> get_port_target() const
+ {
+ return iv_port_target;
+ }
+
+ ///
+ /// @brief Calculate phy rank given port rank (unit testable)
+ ///
+ /// @param[in] l_port_rank port rank
+ /// @return phy rank
+ ///
+ inline static uint8_t get_phy_rank_from_port_rank(const uint8_t i_port_rank)
+ {
+ const uint8_t l_dimm_rank = i_port_rank % TT::RANK_INDEX_STEP;
+ const uint8_t l_dimm_index = i_port_rank / TT::RANK_INDEX_STEP;
+
+ // Dimm index * 2 sets the center point at 2
+ // Add on the dimm rank
+ // Note that this logic does NOT apply in a hypothetical/impossible 2 4-rank dimm configuration
+ return ((l_dimm_index * TT::PHY_RANK_INDEX_STEP) + (l_dimm_rank));
+ }
+
+ private:
+ fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_dimm_target;
+ fapi2::Target<DEFAULT_MEM_PORT_TARGET> iv_port_target;
+ uint8_t iv_dimm_rank;
+ uint8_t iv_port_rank;
+
+ // Note! a configuration of 2 4-rank dimms is not possible.
+ // In this hypothetical scenario, the value for phy-rank would not
+ // be valid / does not apply, as there will be some rollover.
+ // 1 rank-per-dimm: 0 dimm0 2 dimm1
+ // 2 rank-per-dimm: 0/1 dimm0 2/3 dimm1.
+ // 2 rank single dimm 0/1
+ // 4 rank (quad encoded) 0-3.
+ uint8_t iv_phy_rank;
+};
+
+///
+/// @brief Obtains all DIMM ranks on a given port target
+/// @tparam MC the memory controller type
+/// @tparam TT the class traits for the port
+/// @param[in] i_port_target port target
+/// @param[out] o_vect vector of ranks
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template <mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = rankTraits<MC>>
+fapi2::ReturnCode ranks_on_port(const fapi2::Target<DEFAULT_MEM_PORT_TARGET>& i_port_target,
+ std::vector<info<MC>>& o_vect)
+{
+ o_vect.clear();
+
+ uint8_t l_master_ranks_per_dimm[TT::MAX_DIMMS_PER_PORT] = {0};
+ FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_port_target, l_master_ranks_per_dimm));
+
+ FAPI_ASSERT(((l_master_ranks_per_dimm[0] <= TT::MAX_RANKS_PER_DIMM) &&
+ (l_master_ranks_per_dimm[1] <= TT::MAX_RANKS_PER_DIMM)),
+ fapi2::MSS_TOO_MANY_PRIMARY_RANKS_ON_PORT()
+ .set_PORT_TARGET(i_port_target),
+ "Primary ranks on PORT %s exceeded %u",
+ mss::c_str(i_port_target),
+ TT::MAX_RANKS_PER_DIMM);
+
+ for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_port_target))
+ {
+ const uint8_t l_dimm_index = mss::index(l_dimm);
+ const uint8_t l_port_index_start = l_dimm_index * TT::RANK_INDEX_STEP;
+
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
+
+ // For each rank index of the dimm from the port's perspective
+ for (uint8_t l_index = l_port_index_start; l_index < (l_port_index_start + l_master_ranks_per_dimm[l_dimm_index]);
+ ++l_index)
+ {
+ o_vect.push_back(mss::rank::info<>(i_port_target, l_index, l_rc));
+ FAPI_TRY(l_rc);
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Obtains all ranks on a given DIMM target
+/// @tparam MC the memory controller type
+/// @tparam TT the class traits for the port
+/// @param[in] i_target DIMM target
+/// @param[out] o_vect vector of ranks
+/// @return FAPI2_RC_SUCCESS iff success
+///
+template <mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = rankTraits<MC>>
+fapi2::ReturnCode ranks_on_dimm(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm_target,
+ std::vector<info<MC>>& o_vect)
+{
+ o_vect.clear();
+ uint8_t l_master_ranks_per_dimm = 0;
+ FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_dimm_target, l_master_ranks_per_dimm));
+
+ FAPI_ASSERT(l_master_ranks_per_dimm <= TT::MAX_RANKS_PER_DIMM,
+ fapi2::MSS_TOO_MANY_PRIMARY_RANKS_ON_DIMM()
+ .set_RANK_COUNT(l_master_ranks_per_dimm)
+ .set_DIMM_TARGET(i_dimm_target),
+ "Seeing %d primary ranks on DIMM %s",
+ l_master_ranks_per_dimm,
+ mss::c_str(i_dimm_target));
+ {
+ // Return code for constructor call
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
+
+ // For each rank index from the dimm's perspective
+ for (uint8_t l_index = 0; l_index < l_master_ranks_per_dimm; l_index++)
+ {
+ o_vect.push_back(mss::rank::info<>(i_dimm_target, l_index, l_rc));
+ FAPI_TRY(l_rc, "ranks_on_dimm(): Error in rank::info constructor call for DIMM %s and rank %u",
+ mss::c_str(i_dimm_target), l_index);
+ }
+ }
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return a vector of rank numbers which represent the ranks for this dimm
+/// @tparam MC the memory controller type
+/// @param[in] i_dimm_target TARGET_TYPE_DIMM
+/// @param[out] o_ranks a vector of ranks for dimm (numbers)
+/// @return FAPI2_RC_SUCCESS iff all is ok
+///
+template<mss::mc_type MC>
+fapi2::ReturnCode ranks_on_dimm_helper(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm_target,
+ std::vector<uint64_t>& o_ranks);
+
+} // rank
+} // mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/num.H b/src/import/generic/memory/lib/utils/num.H
index 62332bb65..327aca84f 100644
--- a/src/import/generic/memory/lib/utils/num.H
+++ b/src/import/generic/memory/lib/utils/num.H
@@ -22,3 +22,34 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file num.H
+/// @brief Miscellaneous number checking functions
+///
+// *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _GEN_MSS_NUM_H_
+#define _GEN_MSS_NUM_H_
+
+namespace mss
+{
+
+///
+/// @brief Return whether or not a number is odd
+/// @param[in] i_number the number to check
+/// @return true if i_number is odd
+///
+template< typename T >
+constexpr bool is_odd(const T i_number)
+{
+ return (i_number & 0x1);
+}
+
+
+}
+#endif
diff --git a/src/import/generic/memory/lib/utils/power_thermal/gen_decoder.H b/src/import/generic/memory/lib/utils/power_thermal/gen_decoder.H
index 7e2c47406..f2d6370be 100644
--- a/src/import/generic/memory/lib/utils/power_thermal/gen_decoder.H
+++ b/src/import/generic/memory/lib/utils/power_thermal/gen_decoder.H
@@ -22,3 +22,587 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file gen_decoder.H
+/// @brief Decoder for ATTR_MSS_MRW_PWR_CURVE_SLOPE and _INTERCEPT and THERMAL_POWER_LIMIT
+///
+// *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_GEN_POWER_DECODER__
+#define _MSS_GEN_POWER_DECODER__
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+#include <generic/memory/lib/utils/power_thermal/gen_throttle_traits.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+
+namespace mss
+{
+
+namespace power_thermal
+{
+
+constexpr uint32_t ANY_SIZE = 0xFFFFFFFF;
+constexpr uint8_t ANY_TYPE = 0xFF;
+constexpr uint8_t ANY_GEN = 0xFF;
+constexpr uint8_t ANY_WIDTH = 0xFF;
+constexpr uint8_t ANY_DENSITY = 0xFF;
+constexpr uint8_t ANY_STACK_TYPE = 0xFF;
+constexpr uint16_t ANY_MFGID = 0xFFFF;
+constexpr uint8_t ANY_HEIGHT = 0xFF;
+constexpr uint8_t ANY_PORT = 0xFF;
+
+//Currently needs to be in sorted order for lookup to work
+static const std::vector< std::pair<uint32_t , uint8_t> > DIMM_SIZE_MAP =
+{
+ {4, 0b0000},
+ {8, 0b0001},
+ {16, 0b0010},
+ {32, 0b0011},
+ {64, 0b0100},
+ {128, 0b0101},
+ {256, 0b0110},
+ {512, 0b0111},
+ {ANY_SIZE, 0b1111}
+};
+
+
+
+static const std::vector< std::pair<uint8_t , uint8_t> > DRAM_GEN_MAP =
+{
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_GEN_EMPTY, 0b00},
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_GEN_DDR3, 0b01},
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_GEN_DDR4, 0b10},
+ {ANY_GEN, 0b11}
+};
+
+static const std::vector <std::pair<uint8_t, uint8_t> > DRAM_WIDTH_MAP =
+{
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4, 0b000},
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X8, 0b001},
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X16, 0b010},
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X32, 0b011},
+ {ANY_WIDTH, 0b111}
+};
+
+static const std::vector< std::pair<uint8_t , uint8_t> > DRAM_DENSITY_MAP =
+{
+ {4, 0b000},
+ {8, 0b001},
+ {16, 0b010},
+ {32, 0b011},
+ {64, 0b100},
+ {ANY_DENSITY, 0b111}
+};
+
+static const std::vector <std::pair<uint8_t, uint8_t> > DRAM_STACK_TYPE_MAP =
+{
+ {fapi2::ENUM_ATTR_MEM_EFF_PRIM_STACK_TYPE_SDP, 0b00},
+ {fapi2::ENUM_ATTR_MEM_EFF_PRIM_STACK_TYPE_DDP_QDP, 0b01},
+ {fapi2::ENUM_ATTR_MEM_EFF_PRIM_STACK_TYPE_3DS, 0b10},
+ {ANY_STACK_TYPE, 0b11}
+};
+
+//Note, the first entries of the pairs need to be in sorted order!!
+static const std::vector <std::pair<uint16_t, uint8_t> > DRAM_MFGID_MAP =
+{
+ //Kingston
+ {0x0198, 0b011},
+ //A-data
+ {0x04CB, 0b101},
+ //Micron
+ {0x802C, 0b000},
+ //HYNIX
+ {0x80AD, 0b001},
+ //SAMSUNG
+ {0x80CE, 0b010},
+ //Innodisk
+ {0x86F1, 0b100},
+ // ANY
+ {ANY_MFGID, 0b111}
+};
+
+static const std::vector< std::pair<uint8_t , uint8_t> > DIMM_MODULE_HEIGHT_MAP =
+{
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_1U, 0b00},
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_2U, 0b01},
+ {fapi2::ENUM_ATTR_MEM_EFF_DRAM_MODULE_HEIGHT_4U, 0b10},
+ {ANY_HEIGHT, 0b11}
+};
+
+static const std::vector < std::pair< uint8_t, uint8_t> > DIMMS_PORT_MAP =
+{
+ //Num dimms per MCA, only 1 or 2 possible options. 0 is no-op
+ {1, 0b00},
+ {2, 0b01},
+ {ANY_PORT, 0b11}
+};
+
+// Forward declaration
+template<mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = throttle_traits<MC>>
+fapi2::ReturnCode generate_wildcard_mask(const uint32_t i_hash, uint32_t& o_mask);
+
+
+///
+///@brief a compare functor for the decoder::find_attr functions below
+/// @tparam MC mss::mc_type
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE>
+struct is_match
+{
+ ///
+ ///@brief functor constructor
+ ///@param[in] i_gen_key the class object's constructed hash for the installed dimm, to be compared with the attr array
+ ///
+ is_match(const uint32_t i_gen_key) : iv_gen_key(i_gen_key) {}
+ const fapi2::buffer<uint32_t> iv_gen_key;
+
+ ///
+ ///@brief Boolean compare used for find_if function
+ ///
+ bool operator()(const uint64_t i_hash)
+ {
+ // l_this_hash is the first half of the i_hash's bits
+ const uint32_t l_this_hash = i_hash >> 32;
+ uint32_t l_wildcard_mask = 0;
+
+ // Get wildcard mask. If the decoding fails(value to key), we should continue
+ generate_wildcard_mask<MC>(l_this_hash, l_wildcard_mask);
+
+ // Mask the wildcard bits
+ return ((l_this_hash | l_wildcard_mask) == (iv_gen_key | l_wildcard_mask));
+ }
+};
+
+///
+/// @brief Encode the attribute into a bit encoding
+/// @tparam S *ATTR*_SIZE enum used for fapi2::buffer position
+/// @tparam L *ATTR*_LEN enum used for fapi2::buffer position
+/// @tparam T integral type of key
+/// @tparam OT fapi2::buffer of some integral type
+/// @param[in] i_target the DIMM the encoding is for
+/// @param[in] i_attr the attribute key being used for the encoding
+/// @param[in] i_map a vector of pairs of the ATTR values and encodings for each value, sorted
+/// @param[out] o_buf the fapi2::buffer where the encoding is going into
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff attribute is found in map lookup
+///
+template<size_t S, size_t L, typename T, typename OT>
+inline fapi2::ReturnCode encode ( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const T& i_attr,
+ const std::vector<std::pair<T, OT> >& i_map,
+ fapi2::buffer<uint32_t>& o_buf)
+{
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ //used to hold result from vector pair lookup
+ OT l_encoding = 0;
+
+ //Failing out if we don't find an encoding. All suported types should be encoded above
+ FAPI_ASSERT( mss::find_value_from_key (i_map, i_attr, l_encoding),
+ fapi2::MSS_POWER_THERMAL_ENCODE_ERROR()
+ .set_ATTR(i_attr)
+ .set_DIMM_TARGET(i_target),
+ "Couldn't find encoding for power thermal encode for value: %x target: %s", i_attr, mss::c_str(i_target));
+ o_buf.insertFromRight<S, L>(l_encoding);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode the attribute into a bit encoding
+/// @tparam S DRAM_GEN_SIZE enum used for fapi2::buffer position
+/// @tparam L DRAM_GEN_LEN enum used for fapi2::buffer position
+/// @tparam T integral type of key
+/// @tparam OT fapi2::buffer of some integral type
+/// @param[in] i_map a vector of pairs of the ATTR values and encodings for each value
+/// @param[in] i_buf the fapi2::buffer that has the encoding to parse
+/// @param[out] o_attr the attribute value from the encoding is going
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff attribute is found in map lookup
+///
+template<size_t S, size_t L, typename T, typename OT>
+inline fapi2::ReturnCode decode (const std::vector<std::pair<T, OT> >& i_map,
+ fapi2::buffer<uint32_t>& i_buf,
+ T& o_attr )
+{
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ //used to hold result from vector pair lookup
+ OT l_encoding = 0;
+ i_buf.extractToRight<S, L>(l_encoding);
+
+ //Failing out if we don't find an decoding. All suported types should be encoded above
+ FAPI_ASSERT( mss::find_key_from_value (i_map, l_encoding, o_attr),
+ fapi2::MSS_POWER_THERMAL_DECODE_ERROR()
+ .set_ATTR(l_encoding),
+ "Couldn't find encoding for power thermal decode");
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief generates wildcard mask for the hash value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+/// @tparam MC mss::mc_type
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+/// @param[in] i_hash The encoded value
+/// @param[out] o_mask The wildcard mask
+///
+
+template<mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = throttle_traits<MC>>
+fapi2::ReturnCode generate_wildcard_mask(const uint32_t i_hash, uint32_t& o_mask)
+{
+
+ fapi2::buffer<uint32_t> l_mask;
+ fapi2::buffer<uint32_t> l_hash = i_hash;
+ uint8_t l_uint8_buf = 0;
+ uint16_t l_uint16_buf = 0;
+ uint32_t l_uint32_buf = 0;
+
+ //DIMM_SIZE wildcard
+ FAPI_TRY(( decode<TT::DIMM_SIZE_START, TT::DIMM_SIZE_LEN>
+ (DIMM_SIZE_MAP, l_hash, l_uint32_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DIMM_SIZE", l_hash );
+
+ if(ANY_SIZE == l_uint32_buf)
+ {
+ l_mask.setBit<TT::DIMM_SIZE_START, TT::DIMM_SIZE_LEN>();
+ }
+
+ //DRAM_GEN wildcard
+ FAPI_TRY(( decode<TT::DRAM_GEN_START, TT::DRAM_GEN_LEN>
+ (DRAM_GEN_MAP, l_hash, l_uint8_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DRAM_GEN", l_hash);
+
+ if(ANY_GEN == l_uint8_buf)
+ {
+ l_mask.setBit<TT::DRAM_GEN_START, TT::DRAM_GEN_LEN>();
+ }
+
+ //DIMM_TYPE wildcard
+ FAPI_TRY(( decode<TT::DIMM_TYPE_START, TT::DIMM_TYPE_LEN>
+ (TT::DIMM_TYPE_MAP, l_hash, l_uint8_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DIMM_TYPE", l_hash);
+
+ if(ANY_TYPE == l_uint8_buf)
+ {
+ l_mask.setBit<TT::DIMM_TYPE_START, TT::DIMM_TYPE_LEN>();
+ }
+
+ //DRAM_WIDTH wildcard
+ FAPI_TRY(( decode<TT::DRAM_WIDTH_START, TT::DRAM_WIDTH_LEN>
+ (DRAM_WIDTH_MAP, l_hash, l_uint8_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DRAM_WIDTH", l_hash);
+
+ if(ANY_WIDTH == l_uint8_buf)
+ {
+ l_mask.setBit<TT::DRAM_WIDTH_START, TT::DRAM_WIDTH_LEN>();
+ }
+
+ //DRAM_DENSITY wildcard
+ FAPI_TRY(( decode<TT::DRAM_DENSITY_START, TT::DRAM_DENSITY_LEN>
+ (DRAM_DENSITY_MAP, l_hash, l_uint8_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DRAM_DENSITY", l_hash);
+
+ if(ANY_DENSITY == l_uint8_buf)
+ {
+ l_mask.setBit<TT::DRAM_DENSITY_START, TT::DRAM_DENSITY_LEN>();
+ }
+
+ //DRAM_STACK_TYPE wildcard
+ FAPI_TRY(( decode<TT::DRAM_STACK_TYPE_START, TT::DRAM_STACK_TYPE_LEN>
+ (DRAM_STACK_TYPE_MAP, l_hash, l_uint8_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DRAM_STACK_TYPE", l_hash);
+
+ if(ANY_STACK_TYPE == l_uint8_buf)
+ {
+ l_mask.setBit<TT::DRAM_STACK_TYPE_START, TT::DRAM_STACK_TYPE_LEN>();
+ }
+
+ //DRAM_MFGID wildcard
+ FAPI_TRY(( decode<TT::DRAM_MFGID_START, TT::DRAM_MFGID_LEN>
+ (DRAM_MFGID_MAP, l_hash, l_uint16_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DRAM_MFG_ID", l_hash);
+
+ if(ANY_MFGID == l_uint16_buf)
+ {
+ l_mask.setBit<TT::DRAM_MFGID_START, TT::DRAM_MFGID_LEN>();
+ }
+
+
+ if (TT::MC_TARGET_TYPE == fapi2::TARGET_TYPE_MCS)
+ {
+ //NUM DROPS PER PORT wildcard
+ FAPI_TRY(( decode<TT::DIMMS_PER_PORT_START, TT::DIMMS_PER_PORT_LEN>
+ (DIMMS_PORT_MAP, l_hash, l_uint8_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DIMMS_PER_PORT", l_hash);
+
+ if(ANY_PORT == l_uint8_buf)
+ {
+ l_mask.setBit<TT::DIMMS_PER_PORT_START, TT::DIMMS_PER_PORT_LEN>();
+ }
+ }
+
+ if (TT::MC_TARGET_TYPE == fapi2::TARGET_TYPE_OCMB_CHIP)
+ {
+ //MODUEL HEIGHT wildcard
+ FAPI_TRY(( decode<TT::DIMM_MODULE_HEIGHT_START, TT::DIMM_MODULE_HEIGHT_LEN>
+ (DIMM_MODULE_HEIGHT_MAP, l_hash, l_uint8_buf)),
+ "Failed to generate power thermal decoding for %s val %d",
+ "DIMMS_MODULE_HEIGHT", l_hash);
+
+ if(ANY_HEIGHT == l_uint8_buf)
+ {
+ l_mask.setBit<TT::DIMM_MODULE_HEIGHT_START, TT::DIMM_MODULE_HEIGHT_LEN>();
+ }
+ }
+
+ o_mask = l_mask;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @class decoder
+/// @brief Decodes the power curve and thermal power limit attributes for eff_config_thermal
+/// @tparam MC mss::mc_type
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = throttle_traits<MC>>
+class decoder
+{
+ public:
+
+ //IVs for all of the attributes per MCS
+ const mss::dimm::kind<MC> iv_kind;
+
+ //Left in here rather than calculating during encode for testing
+ uint8_t iv_dimms_per_port;
+
+ //Power thermal attributes, both total and vddr versions will be used in eff_config_thermal
+ uint16_t iv_vddr_slope = 0;
+ uint16_t iv_vddr_intercept = 0;
+ uint16_t iv_total_slope = 0;
+ uint16_t iv_total_intercept = 0;
+
+ // Valid for OCMB only
+ uint32_t iv_power_limit = 0 ;
+
+ uint32_t iv_thermal_power_limit = 0;
+
+ //Generated key, used to decode all three power curve attributes
+ fapi2::buffer<uint32_t> iv_gen_key;
+
+ ///
+ /// @brief Constructor
+ /// @param[in] dimm::kind to call power thermal stuff on
+ ///
+ decoder( const mss::dimm::kind<MC>& i_kind):
+ iv_kind(i_kind)
+ {
+ iv_dimms_per_port = mss::count_dimm (find_target<TT::PORT_TARGET_TYPE>(iv_kind.iv_target));
+ };
+
+ //
+ // @brief Default destructor
+ //
+ ~decoder() = default;
+
+ ///
+ /// @brief generates the 32 bit encoding for the power curve attributes
+ /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+ /// @note populates iv_gen_key
+ ///
+ fapi2::ReturnCode generate_encoding ();
+
+ ///
+ /// @brief Finds a value for the power curve slope attributes by matching the generated hashes
+ /// @param[in] i_array is a vector of the attribute values
+ /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+ /// @note populates iv_vddr_slope, iv_total_slope
+ ///
+ fapi2::ReturnCode find_slope (const std::vector< const std::vector<uint64_t>* >& i_slope);
+
+ ///
+ /// @brief Finds a value for power curve intercept attributes by matching the generated hashes
+ /// @param[in] i_array is a vector of the attribute values
+ /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+ /// @note populates iv_vddr_intercept, iv_total_intercept
+ ///
+ fapi2::ReturnCode find_intercept (const std::vector< const std::vector<uint64_t>* >& i_intercept);
+
+ ///
+ /// @brief Finds a value from ATTR_MSS_MRW_THERMAL_MEMORY_POWER_LIMIT and stores in iv variable
+ /// @param[in] i_array is a vector of the attribute values
+ /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+ /// @note populates iv_thermal_power_limit
+ ///
+ fapi2::ReturnCode find_thermal_power_limit (const std::vector< const std::vector<uint64_t>* >& i_thermal_limits);
+
+ ///
+ /// @brief Helper function to find the value from attribute
+ /// @tparam FIELD_START the field start offset inside attribute
+ /// @tparam FIELD_LEN the field length to extract
+ /// @tparam FUNCTION the function of the field
+ /// @tparam OT output type
+ /// @param[in] i_array is a vector of the attribute values
+ /// @param[in] i_attr_description the attribute description
+ /// @param[out] o_value the output value
+ /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+ /// @note populates iv_thermal_power_limit
+ ///
+ template<size_t FIELD_START, size_t FIELD_LEN, generic_ffdc_codes FUNCTION, typename OT>
+ fapi2::ReturnCode get_power_thermal_value(const std::vector<uint64_t>& i_array,
+ const char* const i_attr_description,
+ OT& o_value);
+};
+
+///
+/// @brief generates the 32 bit encoding for the power curve attributes
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+/// @note populates iv_gen_keys
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode decoder<MC, TT>::generate_encoding()
+{
+ //DIMM_SIZE
+ FAPI_TRY(( encode<TT::DIMM_SIZE_START, TT::DIMM_SIZE_LEN>
+ (iv_kind.iv_target, iv_kind.iv_size, DIMM_SIZE_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DIMM_SIZE", iv_kind.iv_size, mss::c_str(iv_kind.iv_target) );
+
+ //DRAM_GEN
+ FAPI_TRY(( encode<TT::DRAM_GEN_START, TT::DRAM_GEN_LEN>
+ (iv_kind.iv_target, iv_kind.iv_dram_generation, DRAM_GEN_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DRAM_GEN", iv_kind.iv_dram_generation, mss::c_str(iv_kind.iv_target) );
+
+ //DIMM_TYPE
+ FAPI_TRY(( encode<TT::DIMM_TYPE_START, TT::DIMM_TYPE_LEN>
+ (iv_kind.iv_target, iv_kind.iv_dimm_type, TT::DIMM_TYPE_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DIMM_TYPE", iv_kind.iv_dimm_type, mss::c_str(iv_kind.iv_target) );
+
+ //DRAM WIDTH
+ FAPI_TRY(( encode<TT::DRAM_WIDTH_START, TT::DRAM_WIDTH_LEN>
+ (iv_kind.iv_target, iv_kind.iv_dram_width, DRAM_WIDTH_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DRAM_WIDTH", iv_kind.iv_dram_width, mss::c_str(iv_kind.iv_target) );
+
+ //DRAM DENSITY
+ FAPI_TRY(( encode<TT::DRAM_DENSITY_START, TT::DRAM_DENSITY_LEN>
+ (iv_kind.iv_target, iv_kind.iv_dram_density, DRAM_DENSITY_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DRAM_DENSITY", iv_kind.iv_dram_density, mss::c_str(iv_kind.iv_target) );
+
+ //DRAM STACK TYPE
+ FAPI_TRY(( encode<TT::DRAM_STACK_TYPE_START, TT::DRAM_STACK_TYPE_LEN>
+ (iv_kind.iv_target, iv_kind.iv_stack_type, DRAM_STACK_TYPE_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DRAM_STACK_TYPE", iv_kind.iv_stack_type, mss::c_str(iv_kind.iv_target) );
+
+ //DRAM MFG ID
+ FAPI_TRY(( encode<TT::DRAM_MFGID_START, TT::DRAM_MFGID_LEN>
+ (iv_kind.iv_target, iv_kind.iv_mfgid, DRAM_MFGID_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DRAM_MFG_ID", iv_kind.iv_mfgid, mss::c_str(iv_kind.iv_target) );
+
+ if (TT::MC_TARGET_TYPE == fapi2::TARGET_TYPE_MCS)
+ {
+ //NUM DROPS PER PORT
+ FAPI_TRY(( encode<TT::DIMMS_PER_PORT_START, TT::DIMMS_PER_PORT_LEN>
+ (iv_kind.iv_target, iv_dimms_per_port, DIMMS_PORT_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DIMMS_PER_PORT", iv_dimms_per_port, mss::c_str(iv_kind.iv_target) );
+ }
+
+ if (TT::MC_TARGET_TYPE == fapi2::TARGET_TYPE_OCMB_CHIP)
+ {
+ //DIMM_MODULE_HEIGHT
+ FAPI_TRY(( encode<TT::DIMM_MODULE_HEIGHT_START, TT::DIMM_MODULE_HEIGHT_LEN>
+ (iv_kind.iv_target, iv_kind.iv_module_height, DIMM_MODULE_HEIGHT_MAP, iv_gen_key)),
+ "Failed to generate power thermal encoding for %s val %d on target: %s",
+ "DIMM_MODULE_HEIGHT", iv_kind.iv_module_height, mss::c_str(iv_kind.iv_target) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find the value from attribute
+/// @param[in] i_array is a vector of the attribute values
+/// @param[in] i_attr_description the attribute description
+/// @param[out] o_value the output value
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+/// @note populates iv_thermal_power_limit
+///
+template<mss::mc_type MC, typename TT>
+template<size_t FIELD_START, size_t FIELD_LEN, generic_ffdc_codes FUNCTION, typename OT>
+fapi2::ReturnCode decoder<MC, TT>::get_power_thermal_value(const std::vector<uint64_t>& i_array,
+ const char* const i_attr_description,
+ OT& o_value)
+{
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // Find iterator to matching key (if it exists)
+ auto l_value_iterator = std::find_if(i_array.begin(),
+ i_array.end(),
+ is_match<>(iv_gen_key));
+
+ FAPI_ASSERT(l_value_iterator != i_array.end(),
+ fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND()
+ .set_GENERATED_KEY(iv_gen_key)
+ .set_FUNCTION(FUNCTION)
+ .set_DIMM_TARGET(iv_kind.iv_target)
+ .set_SIZE(iv_kind.iv_size)
+ .set_DRAM_GEN(iv_kind.iv_dram_generation)
+ .set_DIMM_TYPE(iv_kind.iv_dimm_type)
+ .set_DRAM_WIDTH( iv_kind.iv_dram_width)
+ .set_DRAM_DENSITY(iv_kind.iv_dram_density)
+ .set_STACK_TYPE(iv_kind.iv_stack_type)
+ .set_MFGID(iv_kind.iv_mfgid)
+ .set_MODULE_HEIGHT(iv_kind.iv_module_height),
+ "Couldn't find %s value for generated key:0x%08lx, for target %s. "
+ "DIMM values for generated key are "
+ "size is %d, gen is %d, type is %d, width is %d, density %d, stack %d, mfgid %d, dimms %d, height %d",
+ i_attr_description,
+ iv_gen_key,
+ mss::c_str(iv_kind.iv_target),
+ iv_kind.iv_size,
+ iv_kind.iv_dram_generation,
+ iv_kind.iv_dimm_type,
+ iv_kind.iv_dram_width,
+ iv_kind.iv_dram_density,
+ iv_kind.iv_stack_type,
+ iv_kind.iv_mfgid,
+ iv_dimms_per_port,
+ iv_kind.iv_module_height
+ );
+ {
+ const fapi2::buffer<uint64_t> l_temp(*l_value_iterator);
+ l_temp.extractToRight<FIELD_START, FIELD_LEN>(o_value);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} // power_thermal
+} // mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H b/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H
index 4d99317bf..0b15b6ab2 100644
--- a/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H
+++ b/src/import/generic/memory/lib/utils/power_thermal/gen_throttle.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2019 */
+/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -22,3 +22,1309 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+///
+/// @file gen_throttle.H
+/// @brief throttle API
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_GEN_POWER_THROTTLE_
+#define _MSS_GEN_POWER_THROTTLE_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/power_thermal/gen_throttle_traits.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+#include <generic/memory/lib/mss_generic_system_attribute_getters.H>
+#include <generic/memory/lib/mss_generic_system_attribute_setters.H>
+#include <generic/memory/lib/mss_generic_attribute_setters.H>
+#include <generic/memory/lib/utils/mss_math.H>
+#include <generic/memory/lib/utils/pos.H>
+
+namespace mss
+{
+
+namespace power_thermal
+{
+
+///
+/// @brief throttle constants used in the power_thermal functions
+///
+enum throttle_const : size_t
+{
+ /// Dram data bus utilization is bus utilization / 4
+ DRAM_BUS_UTILS = 4,
+
+ /// 10000 to convert to and from c%
+ UTIL_CONVERSION = 10000,
+
+ /// Conversion to percentage
+ PERCENT_CONVERSION = 100,
+
+};
+
+///
+/// @brief Calculate the N throttle for a given dram data bus utilization value
+///
+/// @tparam T1 template parameter, type of input to be processed
+/// @tparam T2 template parameter, type of input to be processed
+/// @param[in] i_dram_util dram data bus utilization value
+/// @param[in] i_throttle_m M throttle value in N/M throttling
+///
+/// @return int32_t calculated N throttle value
+///
+template<typename T1, typename T2>
+inline uint32_t calc_n_from_dram_util(const T1 i_dram_util, const T2 i_throttle_m)
+{
+ constexpr uint64_t CONVERT_ADDR_UTIL_TO_DATA_UTIL = 4;
+
+ return (static_cast<int>(static_cast<double>(i_dram_util)
+ * (i_throttle_m)
+ / (CONVERT_ADDR_UTIL_TO_DATA_UTIL)
+ / (PERCENT_CONVERSION)
+ )
+ );
+}
+
+///
+/// @brief Calculate N (address operations) allowed within a window of M DRAM clocks
+/// @param[in] i_databus_util databus utilization percentage (e.g. 5% = 5)
+/// @param[in] i_num_dram_clocks window of M DRAM clocks
+/// @return number of throttled commands allowed
+/// @note Uses N/M Throttling.
+/// Equation: N = (DRAM data bus utilization * M) / (4 * 10000)
+///
+inline uint32_t throttled_cmds(const uint32_t i_databus_util, const uint32_t i_num_dram_clocks)
+{
+ constexpr uint64_t l_divisor = DRAM_BUS_UTILS * UTIL_CONVERSION;
+ const uint64_t l_dividend = i_databus_util * i_num_dram_clocks;
+ const uint64_t l_result = l_dividend / l_divisor;
+
+ //Make sure N is not equal to 0, or we brick the dram until reboot
+ return ((l_result == 0) ? 1 : l_result);
+}
+
+///
+/// @brief Calculate the port databus utilization based off of N throttles and M dram clocks
+/// @tparam MC mss::mc_type
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+/// @tparam T output type
+/// @param[in] i_n_throttles N (address operations) allowed within a window of M DRAM clocks
+/// @param[in] i_num_dram_clocks window of M DRAM clocks
+/// @param[out] o_calc_util
+/// @return FAPI2_RC_SUCCESS iff method was a success
+/// @note Uses N/M Throttling.
+/// @note DRAM databus utilization = N * 4 * 10000 / M
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = throttle_traits<MC>, typename T>
+fapi2::ReturnCode calc_util_from_throttles(const uint16_t i_n_throttles,
+ const uint32_t i_num_dram_clocks,
+ T& o_calc_util)
+{
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ constexpr uint32_t l_multiplier = DRAM_BUS_UTILS * UTIL_CONVERSION;
+ const uint64_t l_calc_util_uint64 = static_cast<uint64_t>((static_cast<double>(i_n_throttles) * l_multiplier) /
+ i_num_dram_clocks);
+ FAPI_ASSERT( (i_num_dram_clocks != 0),
+ fapi2::MSS_M_DRAM_CLOCKS_EQUALS_ZERO(),
+ "ATTR_MSS_MRW_MEM_M_DRAM_CLOCKS was not set and equals zero");
+
+ o_calc_util = (static_cast<double>(i_n_throttles) * l_multiplier) / i_num_dram_clocks;
+
+ // Best way to check for overflow if o_calc_util can be a double?
+ // If o_calc_util overflows, the value inside will be below the expected outcome
+ // So compare o_calc_util with the calculated value, but store calculated value in largest storage
+ // Compare ">=" because o_calc_util can be a double, and so we can't compare just equality due to truncation
+ FAPI_ASSERT( o_calc_util >= l_calc_util_uint64,
+ fapi2::MSS_OUTPUT_OVERFLOW_CALC_UTIL()
+ .set_RESULT(o_calc_util),
+ "Overflow of output variable in calc_util_from_throttles throttles: %d, multiplier %d, dram_clocks %d",
+ i_n_throttles,
+ l_multiplier,
+ i_num_dram_clocks);
+
+ // Check for the minimum
+ if(o_calc_util < TT::MIN_UTIL)
+ {
+ FAPI_INF("Calculated utilization (%f) is less than the minimum utilization: %lu. Setting to minimum value",
+ o_calc_util, TT::MIN_UTIL);
+ o_calc_util = TT::MIN_UTIL;
+ }
+
+ FAPI_INF("In calc_util_from_throttles, calculated %f for output utilization from throttles:%d, dram_clocks %d",
+ o_calc_util, i_n_throttles, i_num_dram_clocks);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Perform thermal calculations as part of the effective configuration
+/// @tparam MC mss::mc_type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+/// @param[in] i_target the MCS target in which the runtime throttles will be reset
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = throttle_traits<MC>>
+fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target<T>& i_target )
+{
+
+ uint32_t l_max_databus = 0;
+ uint32_t l_throttle_m_clocks = 0;
+
+ FAPI_TRY( mss::attr::get_mrw_mem_m_dram_clocks(l_throttle_m_clocks) );
+ FAPI_TRY( mss::attr::get_mrw_max_dram_databus_util(l_max_databus) );
+
+ //Set runtime throttles to unthrottled value, using max dram utilization and M throttle
+ //Do I need to check to see if any DIMMS configured on the port?
+ for (const auto& l_port : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target))
+ {
+ uint16_t l_run_throttle = 0;
+
+ if (mss::count_dimm (l_port) != 0)
+ {
+ l_run_throttle = mss::power_thermal::throttled_cmds (l_max_databus, l_throttle_m_clocks);
+ }
+
+ FAPI_TRY( mss::attr::set_runtime_mem_throttled_n_commands_per_port( l_port, l_run_throttle) );
+ FAPI_TRY( mss::attr::set_runtime_mem_throttled_n_commands_per_slot( l_port, l_run_throttle) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Update the runtime throttles to the worst case of the general throttle values and the runtime values
+/// @tparam MC mss::mc_type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+/// @param[in] i_target the MCS target in which the runtime throttles will be set
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = throttle_traits<MC>>
+fapi2::ReturnCode update_runtime_throttle(const fapi2::Target<T>& i_target)
+
+{
+
+ if (mss::count_dimm(i_target) == 0)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ for (const auto& l_port : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target))
+ {
+
+ uint16_t l_run_slot = 0;
+ uint16_t l_run_port = 0;
+ uint16_t l_calc_slot = 0;
+ uint16_t l_calc_port = 0;
+
+ FAPI_TRY(mss::attr::get_runtime_mem_throttled_n_commands_per_slot(l_port, l_run_slot));
+ FAPI_TRY(mss::attr::get_runtime_mem_throttled_n_commands_per_port(l_port, l_run_port));
+ FAPI_TRY(mss::attr::get_mem_throttled_n_commands_per_slot(l_port, l_calc_slot));
+ FAPI_TRY(mss::attr::get_mem_throttled_n_commands_per_port(l_port, l_calc_port));
+
+ //Choose the worst case between runtime and calculated throttles
+ //Have to make sure the calc_slot isn't equal to 0 though
+ l_run_slot = (l_calc_slot != 0) ?
+ std::min(l_run_slot, l_calc_slot) : l_run_slot;
+ l_run_port = (l_calc_port != 0) ?
+ std::min(l_run_port, l_calc_port) : l_run_port;
+
+ FAPI_INF("New runtime throttles for %s for slot are %d, port are %d",
+ mss::c_str(l_port),
+ l_run_slot,
+ l_run_port);
+
+ FAPI_TRY( mss::attr::set_runtime_mem_throttled_n_commands_per_port(l_port, l_run_port) );
+ FAPI_TRY( mss::attr::set_runtime_mem_throttled_n_commands_per_slot(l_port, l_run_slot) );
+ }
+
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+
+///
+/// @brief Update the runtime throttles to the worst case of the general throttle values and the runtime values
+/// @tparam MC mss::mc_type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+/// @param[in] i_target the MCS target in which the runtime throttles will be set
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = throttle_traits<MC>>
+fapi2::ReturnCode update_runtime_throttles(const std::vector< fapi2::Target<T> >& i_targets)
+
+{
+ for (const auto& l_mc : i_targets)
+ {
+ FAPI_TRY(update_runtime_throttle(l_mc));
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @class throttle
+/// @brief Determine power_thermal throttles for memory
+/// @tparam MC mss::mc_type
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = throttle_traits<MC>>
+class throttle
+{
+ private:
+ ///
+ /// @brief Calculate the power (cW) of inputs and the power curve
+ /// @tparam T the type of i_util and return value
+ /// @param[in] i_util the databus utilization that the power will be based on
+ /// @param[in] l_pos the dimm position for the power value being calculated.
+ /// @return Integral type T
+ ///
+ template<typename T>
+ inline T calc_power (const T i_util, const size_t i_pos, fapi2::ReturnCode& o_rc ) const
+ {
+ o_rc = fapi2::FAPI2_RC_SUCCESS;
+ FAPI_ASSERT( (i_pos < TT::DIMMS_PER_PORT),
+ fapi2::MSS_POWER_THERMAL_DIMM_INDEX_OUT_OF_BOUND()
+ .set_INPUT_SIZE(i_pos)
+ .set_MAX_SIZE(TT::DIMMS_PER_PORT),
+ "The dimm is index is out of bound for the port index: %d, max: %d for port %s",
+ i_pos, TT::DIMMS_PER_PORT, mss::c_str(iv_target) );
+
+ return ((i_util / UTIL_CONVERSION) * iv_pwr_slope[i_pos]) + iv_pwr_int[i_pos];
+
+ fapi_try_exit:
+ o_rc = fapi2::current_err;
+ return 0;
+ }
+
+ ///
+ /// @brief Raise the o_value by the percent passed in
+ /// @param[in] i_uplift the percent the o_Value should be raised by
+ /// @param[out] o_value the value that will be modified
+ ///
+ inline void calc_power_uplift (const uint8_t i_uplift, double& o_value) const
+ {
+ o_value *= (1 + (static_cast<double>(i_uplift) / PERCENT_CONVERSION));
+ }
+
+ public:
+ const fapi2::Target<TT::PORT_TARGET_TYPE>& iv_target;
+
+ uint32_t iv_databus_port_max;
+
+ uint8_t iv_power_uplift_idle;
+ uint8_t iv_power_uplift;
+
+ uint16_t iv_runtime_n_slot;
+ uint16_t iv_runtime_n_port;
+ uint32_t iv_m_clocks;
+ uint32_t iv_dimm_thermal_limit[TT::DIMMS_PER_PORT] = {};
+ uint16_t iv_pwr_slope[TT::DIMMS_PER_PORT] = {};
+ uint16_t iv_pwr_int[TT::DIMMS_PER_PORT] = {};
+ uint16_t iv_n_slot;
+ uint16_t iv_n_port;
+ uint32_t iv_port_power_limit;
+ uint32_t iv_calc_port_maxpower;
+
+ //default ctor deleted
+ throttle() = delete;
+
+ ///
+ /// @brief Constructor
+ /// @param[in] i_target port target to call power thermal stuff on
+ /// @param[out] o_rc fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ctor was successful
+ ///
+ throttle( const fapi2::Target<TT::PORT_TARGET_TYPE>& i_port, fapi2::ReturnCode& o_rc);
+
+ //
+ // @brief Destructor
+ //
+ ~throttle() = default;
+
+ ///
+ /// @brief Calculates the min and max power usage for a port
+ /// @param[in] i_idle_util the utilization of the databus in idle mode
+ /// @param[in] i_max_util the utilization of the port at maximum possible (mrw or calculated)
+ /// @param[out] o_port_power_idle max value of port power in cW
+ /// @param[out] o_port_power_max max value of port power in cW
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+ /// @note Called twice in p9_mss_bulk_pwr_throttles
+ ///
+ fapi2::ReturnCode calc_port_power( const double i_idle_util [TT::DIMMS_PER_PORT],
+ const double i_max_util [TT::DIMMS_PER_PORT],
+ double& o_port_power_idle,
+ double& o_port_power_max) const;
+ ///
+ /// @brief Calculates max and min power usages based off of DIMM power curves
+ /// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw)
+ /// @param[in] i_port_power_calc_idle double of the port's power consumption at idle
+ /// @param[out] o_dimm_power_idle array of dimm power in cW
+ /// @param[out] o_dimm_power_max array of dimm power in cW
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+ /// @note Called in p9_mss_bulk_pwr_throttles
+ /// @note used for the thermal throttles
+ ///
+ fapi2::ReturnCode calc_dimm_power(const double i_databus_idle,
+ const double i_databus_max,
+ double o_dimm_power_idle [TT::DIMMS_PER_PORT],
+ double o_dimm_power_max [TT::DIMMS_PER_PORT]) const;
+
+ ///
+ /// @brief Calculate the power curve in order to calculate databus utilization
+ /// @param[in] i_power_idle double of the port's power consumption at idle
+ /// @param[in] i_power_max double of the port's power consumption at max utilization
+ /// @param[out] o_power_slope
+ /// @param[out] o_power_int
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+ /// @note Called in p9_mss_bulk_pwr_throttles
+ /// @note Power curve needed to calculate the utilization
+ ///
+ fapi2::ReturnCode calc_power_curve(const double i_power_idle,
+ const double i_power_max,
+ uint32_t& o_power_slope,
+ uint32_t& o_power_int) const;
+ ///
+ /// @brief Calculate the databus utilization given the power curve
+ /// @param[in] i_slope the slope of power curve
+ /// @param[in] i_int the intercept of power curve
+ /// @param[in] i_power_limit either iv_port_power_limit or thermal_power_limit depending on throttle type
+ /// @param[out] o_port_util the port's databus utilization
+ /// @note Called in p9_mss_bulk_pwr_throttles
+ /// @note Chooses worst case between the maximum allowed databus utilization and the calculated value
+ ///
+ void calc_util_usage(const uint32_t i_slope,
+ const uint32_t i_int,
+ const uint32_t i_power_limit,
+ double& o_util) const;
+ ///
+ /// @brief set iv_n_port, iv_n_slot, iv_calc_port_maxpower
+ /// @param[in] i_util_port pass in the calculated port databus utilization
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+ ///
+ fapi2::ReturnCode calc_slots_and_power (const double i_util_port);
+
+ ///
+ /// @brief calculated the output power estimate from the calculated N throttle
+ /// @param[in] i_n_slot the N throttle per slot
+ /// @param[in] i_n_port the N throttle per port
+ /// @param[out] o_power the calculated power
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+ ///
+ fapi2::ReturnCode calc_power_from_n (const uint16_t i_n_slot, const uint16_t i_n_port, uint32_t& o_power) const;
+
+ ///
+ /// @brief Converts the port maximum databus util to a dimm level based on powerslopes and dimms installed
+ /// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw)
+ /// @param[out] o_databus_dimm_max array of dimm utilization values
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+ /// @note Called in p9_mss_bulk_pwr_throttles
+ /// @used to calculate the port power based off of DIMM power curves
+ ///
+ fapi2::ReturnCode calc_databus( const double i_databus_port_max,
+ double o_databus_dimm_max [TT::DIMMS_PER_PORT]);
+ ///
+ /// @brief Converts the port and slot util to a dimm level based on powerslopes and number of dimms installed
+ /// @param[in] i_util_slot databus utilization for the slot
+ /// @param[in] i_util_port databus utilization for the port
+ /// @param[out] o_util_dimm_max array of dimm utilization values
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+ /// @note determines worst case utilization per dimms, takes into account port and combine slot throttles
+ ///
+ fapi2::ReturnCode calc_split_util(
+ const double i_util_slot,
+ const double i_util_port,
+ double o_util_dimm_max [TT::DIMMS_PER_PORT]) const;
+
+
+ ///
+ /// @brief Calculate ATTR_MSS_CHANNEL_PAIR_MAXPOWER and ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+ /// @note Called in p9_mss_bulk_pwr_throttles
+ /// @note determines the throttle levels based off of the port's power curve, max databus utilization,
+ /// and memwat target.
+ /// @note currently sets the slot and port throttles to the same value
+ ///
+ fapi2::ReturnCode power_regulator_throttles ();
+
+ ///
+ /// @brief Set ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+ /// @note Called in p9_mss_bulk_pwr_throttles
+ /// @note Sets the throttle levels based off of the dimm's thermal limits
+ /// @note both DIMM's on a port are set to the same throttle level
+ ///
+ fapi2::ReturnCode thermal_throttles ();
+};
+
+
+///
+/// @brief Constructor
+/// @tparam MC mss::mc_type
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+/// @param[in] i_target MCS target to call power thermal stuff on
+/// @param[out] o_rc, a return code which determines the success of the constructor
+///
+template<mss::mc_type MC, typename TT>
+throttle<MC, TT>::throttle( const fapi2::Target<TT::PORT_TARGET_TYPE>& i_port, fapi2::ReturnCode& o_rc) :
+ iv_target(i_port),
+ iv_databus_port_max(0),
+ iv_runtime_n_slot(0),
+ iv_runtime_n_port(0),
+ iv_n_slot(0),
+ iv_n_port(0),
+ iv_port_power_limit(0),
+ iv_calc_port_maxpower(0)
+{
+ FAPI_TRY( mss::attr::get_mrw_max_dram_databus_util(iv_databus_port_max), "%s Error in throttle ctor",
+ mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_mrw_dimm_power_curve_percent_uplift(iv_power_uplift), "%s Error in throttle ctor",
+ mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_mrw_dimm_power_curve_percent_uplift_idle(iv_power_uplift_idle), "%s Error in throttle ctor",
+ mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_dimm_thermal_limit( iv_target, iv_dimm_thermal_limit), "%s Error in throttle ctor",
+ mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_total_pwr_intercept( iv_target, iv_pwr_int), "%s Error in throttle ctor", mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_total_pwr_slope( iv_target, iv_pwr_slope), "%s Error in throttle ctor", mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_runtime_mem_throttled_n_commands_per_slot(iv_target, iv_runtime_n_slot ),
+ "%s Error in throttle ctor",
+ mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_runtime_mem_throttled_n_commands_per_port(iv_target, iv_runtime_n_port ),
+ "%s Error in throttle ctor",
+ mss::c_str(i_port) );
+ FAPI_TRY( mss::attr::get_mrw_mem_m_dram_clocks(iv_m_clocks), "%s Error in throttle ctor", mss::c_str(i_port) );
+
+ //Port power limit = sum of dimm power limits
+ for ( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target) )
+ {
+ uint32_t l_dimm_limit = 0;
+ FAPI_TRY( mss::attr::get_mem_watt_target( l_dimm, l_dimm_limit) );
+ iv_port_power_limit += l_dimm_limit;
+ }
+
+ FAPI_INF("Setting up throttle for target %s, Values are: max databus is %d, uplifts are %d %d, runtime throttles are %d %d",
+ mss::c_str(iv_target),
+ iv_databus_port_max,
+ iv_power_uplift,
+ iv_power_uplift_idle,
+ iv_runtime_n_slot,
+ iv_runtime_n_port);
+
+ FAPI_INF("The dimm power limit is %d, dram clocks are %d, dimm power curve slopes are %d %d for %s",
+ iv_port_power_limit,
+ iv_m_clocks,
+ iv_pwr_slope[0],
+ iv_pwr_slope[1],
+ mss::c_str(iv_target));
+
+ FAPI_INF("DIMM power curve intercepts are %d %d, DIMM power thermal limits are %d %d for %s",
+ iv_pwr_int[0],
+ iv_pwr_int[1],
+ iv_dimm_thermal_limit[0],
+ iv_dimm_thermal_limit[1],
+ mss::c_str(iv_target));
+
+ FAPI_ASSERT( (iv_databus_port_max != 0),
+ fapi2::MSS_NO_DATABUS_UTILIZATION()
+ .set_PORT_DATABUS_UTIL(iv_databus_port_max)
+ .set_DIMM_COUNT(mss::count_dimm(iv_target)),
+ "Failed to get max databus utilization for target %s",
+ mss::c_str(iv_target));
+
+ FAPI_ASSERT( (iv_port_power_limit != 0),
+ fapi2::MSS_NO_PORT_POWER_LIMIT()
+ .set_COUNT_DIMMS( mss::count_dimm(iv_target))
+ .set_PORT_POWER_LIMIT( iv_port_power_limit),
+ "Error calculating port_power_limit on target %s with %d DIMMs installed",
+ mss::c_str(iv_target),
+ iv_port_power_limit);
+
+ //Checking to make sure all of the attributes are valid
+ for ( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target) )
+ {
+ const auto l_pos = mss::index(l_dimm);
+ FAPI_ASSERT( (iv_pwr_int[l_pos] != 0),
+ fapi2::MSS_POWER_INTERCEPT_NOT_SET(),
+ "The attribute ATTR_MSS_TOTAL_PWR_INTERCEPT equals 0 for %s",
+ mss::c_str(l_dimm));
+
+ FAPI_ASSERT( (iv_pwr_slope[l_pos] != 0),
+ fapi2::MSS_POWER_SLOPE_NOT_SET(),
+ "The attribute ATTR_MSS_TOTAL_PWR_SLOPE equals 0 for %s",
+ mss::c_str(l_dimm));
+ }
+
+fapi_try_exit:
+ o_rc = fapi2::current_err;
+ return;
+}
+
+///
+/// @brief Set ATTR_MSS_CHANNEL_PAIR_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and _PER_PORT
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @note determines the throttle levels based off of the port's power curve,
+/// @note the _per_slot throttles are set to the _per_port values
+/// @note throttles are all equalized and set to the worst case value
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::power_regulator_throttles ()
+{
+ double l_port_power_calc_idle = 0;
+ double l_port_power_calc_max = 0;
+ uint32_t l_port_power_slope = 0;
+ uint32_t l_port_power_int = 0;
+ double l_calc_util_port = 0;
+ double l_databus_dimm_max[TT::DIMMS_PER_PORT] = {};
+ double l_calc_databus_port_idle[TT::DIMMS_PER_PORT] = {TT::IDLE_UTIL, TT::IDLE_UTIL};
+
+ //Decide utilization for each dimm based off of dimm count and power slopes
+ FAPI_TRY( calc_databus(iv_databus_port_max, l_databus_dimm_max),
+ "Failed to calculate each DIMMs' percentage of dram databus utilization for target %s, max port databus is %d",
+ mss::c_str(iv_target),
+ iv_databus_port_max);
+
+ //Use the dimm utilizations and dimm power slopes to calculate port min and max power
+ FAPI_TRY( calc_port_power(l_calc_databus_port_idle,
+ l_databus_dimm_max,
+ l_port_power_calc_idle,
+ l_port_power_calc_max),
+ "Failed to calculate the max and idle power for port %s",
+ mss::c_str(iv_target));
+
+ FAPI_INF("POWER throttles: %s max port power is %f", mss::c_str(iv_target), l_port_power_calc_max);
+
+ //Calculate the power curve slope and intercept using the port's min and max power values
+ FAPI_TRY(calc_power_curve(l_port_power_calc_idle,
+ l_port_power_calc_max,
+ l_port_power_slope,
+ l_port_power_int),
+ "Failed to calculate the power curve for port %s, calculated port power max is %f, idle is %f",
+ mss::c_str(iv_target),
+ l_port_power_calc_max,
+ l_port_power_calc_idle);
+
+ FAPI_INF("%s POWER Port power limit is %d", mss::c_str(iv_target), iv_port_power_limit);
+ //Calculate the port's utilization to get under watt target using the port's calculated slopes
+ calc_util_usage(l_port_power_slope,
+ l_port_power_int,
+ iv_port_power_limit,
+ l_calc_util_port);
+
+ FAPI_INF("%s POWER calc util port is %f", mss::c_str(iv_target), l_calc_util_port);
+
+ //Calculate the new slot values and the max power value for the port
+ FAPI_TRY( calc_slots_and_power( l_calc_util_port),
+ "%s Error calculating the final throttles and power values for target with passed in port utilization %f",
+ mss::c_str(iv_target),
+ l_calc_util_port);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief set iv_n_port, iv_n_slot, iv_calc_port_maxpower
+/// @param[in] i_util_port pass in the calculated port databus utilization
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::calc_slots_and_power (const double i_util_port)
+{
+ //Calculate the Port N throttles
+ iv_n_port = power_thermal::throttled_cmds(i_util_port, iv_m_clocks);
+
+ //Set iv_n_slot to the lower value between the slot runtime and iv_n_port
+ iv_n_slot = (iv_runtime_n_slot != 0) ? std::min (iv_n_port, iv_runtime_n_slot) : iv_n_port;
+
+ //Choose the lowest value of the runtime and the calculated
+ iv_n_port = (iv_runtime_n_port != 0) ? std::min (iv_n_port, iv_runtime_n_port) : iv_n_port;
+
+ //Use the throttle value to calculate the power that gets to exactly that value
+ FAPI_TRY( calc_power_from_n(iv_n_slot, iv_n_port, iv_calc_port_maxpower));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Set ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and PER_PORT
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @note Sets the throttle levels based off of the dimm's thermal limits
+/// @note both DIMM's on a port are set to the same throttle level
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::thermal_throttles ()
+{
+ double l_dimm_power_idle [TT::DIMMS_PER_PORT] = {};
+ double l_dimm_power_max [TT::DIMMS_PER_PORT] = {};
+ uint32_t l_dimm_power_slope [TT::DIMMS_PER_PORT] = {};
+ uint32_t l_dimm_power_int [TT::DIMMS_PER_PORT] = {};
+ double l_calc_util [TT::DIMMS_PER_PORT] = {};
+ const auto l_count = count_dimm (iv_target);
+ uint8_t l_found_ddimm = 0;
+
+ //Calculate the dimm power range for each dimm at max utilization for each
+ FAPI_TRY( calc_dimm_power(TT::IDLE_UTIL,
+ iv_databus_port_max,
+ l_dimm_power_idle,
+ l_dimm_power_max));
+
+ //Let's calculate the N throttle for each DIMM
+ for ( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target) )
+ {
+ uint16_t l_temp_n_slot = 0;
+ const uint8_t l_pos = mss::index(l_dimm);
+ mss::dimm::kind<MC> l_kind (l_dimm);
+ l_found_ddimm = (l_kind.iv_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM) ? 1 : l_found_ddimm;
+ //Calculate the power curve taking the thermal limit into account
+ FAPI_TRY( calc_power_curve(l_dimm_power_idle[l_pos],
+ l_dimm_power_max[l_pos],
+ l_dimm_power_slope[l_pos],
+ l_dimm_power_int[l_pos]),
+ "Failed to calculate the power curve for dimm %s, calculated dimm power curve slope is %d, intercept %d",
+ mss::c_str(l_dimm),
+ l_dimm_power_slope[l_pos],
+ l_dimm_power_int[l_pos]);
+
+ //Calculate the databus utilization at the calculated power curve
+ calc_util_usage(l_dimm_power_slope[l_pos],
+ l_dimm_power_int[l_pos],
+ iv_dimm_thermal_limit[l_pos],
+ l_calc_util[l_pos]);
+
+ FAPI_INF("THERMAL throttles: %s dram databus utilization is %f", mss::c_str(l_dimm), l_calc_util[l_pos]);
+
+ l_temp_n_slot = power_thermal::throttled_cmds (l_calc_util[l_pos], iv_m_clocks);
+
+ //Set to the min between the two value
+ //If iv_n_slot == 0 (so uninitialized), set it to the calculated slot value
+ //The l_n_slot value can't be equal to 0 because there's a dimm installed
+ if ((l_temp_n_slot < iv_n_slot) || (iv_n_slot == 0))
+ {
+ iv_n_slot = l_temp_n_slot;
+ }
+ }
+
+ //Set to lowest value between calculated and runtime
+ FAPI_INF("THERMAL throttles: runtime slot is %d, calc n slot is %d for %s", iv_runtime_n_slot, iv_n_slot,
+ mss::c_str(iv_target));
+ //DDDIMMs: Taking the min of the SLOT and the iv_runtime_port throttle value
+ //ISDIMMs: Taking the min of the SLOT * (# of dimms on the port) and the iv_runtime_port throttle value
+ //Thermal throttling happens after the POWER calculations. the iv_runtime_n_port value shouldn't be set to 0
+ iv_n_port = (l_found_ddimm) ?
+ std::min(iv_runtime_n_port, static_cast<uint16_t>(iv_n_slot)) :
+ std::min(iv_runtime_n_port, static_cast<uint16_t>(iv_n_slot * l_count));
+ iv_n_port = (iv_n_port == 0) ? TT::MIN_THROTTLE : iv_n_port;
+
+ iv_n_slot = std::min(iv_n_slot, iv_runtime_n_slot);
+ iv_n_slot = (iv_n_slot == 0) ? TT::MIN_THROTTLE : iv_n_slot;
+
+ //Now time to get and set iv_calc_port_max from the calculated N throttle
+ FAPI_TRY( calc_power_from_n(iv_n_slot, iv_n_port, iv_calc_port_maxpower),
+ "Failed to calculate the final max port maxpower. Slot throttle value is %d, port value is %d for %s",
+ iv_n_slot,
+ iv_n_port,
+ mss::c_str(iv_target));
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ FAPI_ERR("Error calculating mss::power_thermal::thermal_throttles() for %s", mss::c_str(iv_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief Calculates the min and max power usage for a port based off of power curves and utilizations
+/// @param[in] i_idle_util the utilization of the databus in idle mode (0% most likely)
+/// @param[in] i_max_util the utilization of the dimm at maximum possible percentage (mrw or calculated)
+/// @param[out] o_port_power_idle max value of port power in cW
+/// @param[out] o_port_power_max max value of port power in cW
+/// @return fapi2::FAPI2_RC_SUCCESS iff the method was a success
+/// @note Called twice in p9_mss_bulk_pwr_throttles
+/// @note uses dimm power curves from class variables
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::calc_port_power(const double i_idle_util [TT::DIMMS_PER_PORT],
+ const double i_max_util [TT::DIMMS_PER_PORT],
+ double& o_port_power_idle,
+ double& o_port_power_max) const
+{
+ //Playing it safe
+ o_port_power_idle = 0;
+ o_port_power_max = 0;
+ fapi2::ReturnCode l_rc;
+
+ //Calculate the port power curve info by summing the dimms on the port
+ for ( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target) )
+ {
+ const auto l_pos = mss::index(l_dimm);
+ //Printing as decimals because HB messes up floats
+ FAPI_INF("%s max dram databus for DIMM in pos %d is %d, databus for idle is %d",
+ mss::c_str(iv_target),
+ l_pos,
+ static_cast<uint64_t>( i_max_util[l_pos]),
+ static_cast<uint64_t>( i_idle_util[l_pos]) );
+ //Sum up the dimm's power to calculate the port power curve
+ o_port_power_idle += calc_power(i_idle_util[l_pos], l_pos, l_rc);
+ FAPI_TRY(l_rc, "calc_power failed");
+ o_port_power_max += calc_power(i_max_util[l_pos], l_pos, l_rc);
+ FAPI_TRY(l_rc, "calc_power failed");
+ }
+
+ //Raise the powers by the uplift percent
+ calc_power_uplift(iv_power_uplift_idle, o_port_power_idle);
+ calc_power_uplift(iv_power_uplift, o_port_power_max);
+
+ FAPI_ASSERT( (o_port_power_max > 0),
+ fapi2::MSS_NO_PORT_POWER()
+ .set_COUNT_DIMMS(mss::count_dimm(iv_target))
+ .set_MAX_UTILIZATION_DIMM_0(i_max_util[0])
+ .set_MAX_UTILIZATION_DIMM_1(i_max_util[1]),
+ "No Port Power limit was calculated for %s, %d DIMMs installed, utilizations: DIMM 0 %d, DIMM 1 %d",
+ mss::c_str(iv_target),
+ mss::count_dimm(iv_target),
+ i_max_util[0],
+ i_max_util[1]);
+
+ //FAPI_ASSERTs don't set the current err to good
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Calculates max and min power usages based off of DIMM power curves
+/// @param[in] i_databus_idle idle databus utilization (either calculated or mrw)
+/// @param[in] i_databus_max max databus utilization (either calculated or mrw)
+/// @param[out] o_dimm_power_idle array of dimm power in cW
+/// @param[out] o_dimm_power_max array of dimm power in cW
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @note used for the thermal throttles
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::calc_dimm_power(const double i_databus_idle,
+ const double i_databus_max,
+ double o_dimm_power_idle [TT::DIMMS_PER_PORT],
+ double o_dimm_power_max [TT::DIMMS_PER_PORT]) const
+{
+ for ( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target) )
+ {
+ fapi2::ReturnCode l_rc;
+ const uint8_t l_pos = mss::index(l_dimm);
+ o_dimm_power_idle[l_pos] = calc_power(i_databus_idle, l_pos, l_rc);
+ FAPI_TRY(l_rc, "calc_power failed");
+ o_dimm_power_max[l_pos] = calc_power(i_databus_max, l_pos, l_rc);
+ FAPI_TRY(l_rc, "calc_power failed");
+
+ //Raise the powers by the uplift percent
+ calc_power_uplift(iv_power_uplift_idle, o_dimm_power_idle[l_pos]);
+ calc_power_uplift(iv_power_uplift, o_dimm_power_max[l_pos]);
+
+ FAPI_INF("Calc_dimm_power: dimm (%d) power max is %f, dimm slope %d, intercept %d for %s",
+ l_pos,
+ o_dimm_power_max[l_pos],
+ iv_pwr_slope[l_pos],
+ iv_pwr_int[l_pos],
+ mss::c_str(l_dimm));
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_INF("Error calculating mss::power_thermal::calc_dimm_power for %s", mss::c_str(iv_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief Calculate the port power curve in order to calculate the port utilization
+/// @param[in] i_power_idle double of the port's power consumption at idle
+/// @param[in] i_power_max double of the port's power consumption at max utilization
+/// @param[out] o_slope
+/// @param[out] o_int
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @note Port power curve needed to calculate the port utilization
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::calc_power_curve(const double i_power_idle,
+ const double i_power_max,
+ uint32_t& o_slope,
+ uint32_t& o_int) const
+{
+ auto l_min_util = TT::MIN_UTIL;
+ const double l_divisor = ((static_cast<double>(iv_databus_port_max) / UTIL_CONVERSION) - TT::IDLE_UTIL);
+ FAPI_ASSERT ((l_divisor > 0),
+ fapi2::MSS_CALC_POWER_CURVE_DIVIDE_BY_ZERO()
+ .set_PORT_DATABUS_UTIL(iv_databus_port_max)
+ .set_UTIL_CONVERSION(UTIL_CONVERSION)
+ .set_IDLE_UTIL(l_min_util)
+ .set_RESULT(l_divisor),
+ "Calculated zero for the divisor in calc_power_curve on target %s",
+ mss::c_str(iv_target) );
+
+ o_slope = (i_power_max - i_power_idle) / l_divisor;
+ o_int = i_power_idle - (o_slope * TT::IDLE_UTIL);
+ FAPI_INF("Calc_power_curve: power idle is %f, max is %f, slope is %d, int is %d for %s",
+ i_power_idle,
+ i_power_max,
+ o_slope,
+ o_int,
+ mss::c_str(iv_target));
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_INF("Error calculating mss::power_thermal::calc_power_curve for %s", mss::c_str(iv_target));
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Calculate the databus utilization given the power curve
+/// @param[in] i_slope
+/// @param[in] i_int
+/// @param[in] i_power_limit either the port_power_limit or the dimm thermal power limit
+/// @param[out] o_port_util the port's databus utilization
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @note Chooses worst case between the maximum allowed databus utilization and the calculated value
+///
+template<mss::mc_type MC, typename TT>
+void throttle<MC, TT>::calc_util_usage(const uint32_t i_slope,
+ const uint32_t i_int,
+ const uint32_t i_power_limit,
+ double& o_util) const
+{
+ // Return 0 utilization if our intercept is above the power limit
+ o_util = (i_power_limit > i_int) ? (((static_cast<double>(i_power_limit) - i_int) / i_slope ) * UTIL_CONVERSION) : 0;
+
+ // Cast to uint32 for edge case where it has decimals
+ o_util = (static_cast<uint32_t>(o_util) < iv_databus_port_max) ? static_cast<uint32_t>(o_util) : iv_databus_port_max;
+
+ // Check for the minimum threshnold and update if need be
+ if(o_util < TT::MIN_UTIL)
+ {
+ FAPI_INF("Calculated utilization (%f) is less than the minimum utilization: %lu. Setting to minimum value for %s",
+ o_util,
+ TT::MIN_UTIL, mss::c_str(iv_target));
+ o_util = TT::MIN_UTIL;
+ }
+}
+
+///
+/// @brief calculated the output power estimate from the calculated N throttle
+/// @param[in] i_n_slot the throttle per slot in terms of N commands
+/// @param[in] i_n_port the throttle per port in terms of N commands
+/// @param[out] o_power the calculated power
+/// @return fapi2::ReturnCode iff it was a success
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::calc_power_from_n (const uint16_t i_n_slot,
+ const uint16_t i_n_port,
+ uint32_t& o_power) const
+{
+ double l_calc_util_port = 0;
+ double l_calc_util_slot = 0;
+ double l_calc_databus_port_max[TT::DIMMS_PER_PORT] = {};
+ double l_calc_databus_port_idle[TT::DIMMS_PER_PORT] = {};
+ double l_port_power_max = 0;
+ double l_port_power_idle = 0;
+
+ FAPI_TRY( calc_util_from_throttles(i_n_slot, iv_m_clocks, l_calc_util_slot),
+ "%s Error calculating utilization from slot throttle %d and mem clocks %d",
+ mss::c_str(iv_target),
+ i_n_slot,
+ iv_m_clocks);
+ FAPI_TRY( calc_util_from_throttles(i_n_port, iv_m_clocks, l_calc_util_port),
+ "%s Error calculating utilization from port throttle %d and mem clocks %d",
+ mss::c_str(iv_target),
+ i_n_port,
+ iv_m_clocks);
+
+ //Determine the utilization for each DIMM that will maximize the port power
+ FAPI_TRY( calc_split_util(l_calc_util_slot, l_calc_util_port, l_calc_databus_port_max),
+ "Error splitting the utilization for target %s with slot utilizatio %f and port util %f",
+ mss::c_str(iv_target),
+ l_calc_util_slot,
+ l_calc_util_port);
+
+ FAPI_TRY( calc_port_power(l_calc_databus_port_idle,
+ l_calc_databus_port_max,
+ l_port_power_idle,
+ l_port_power_max),
+ "Error calculating the port power value for %s. Slot value is %d, port value is %d",
+ mss::c_str(iv_target),
+ i_n_slot,
+ i_n_port);
+
+ o_power = mss::round_up (l_port_power_max);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Converts the port maximum databus to a dimm level based on powerslopes and dimms installed
+/// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw)
+/// @param[out] o_databus_dimm_max array of dimm utilization values
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @used to calculate the port power based off of DIMM power curves
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::calc_databus (const double i_databus_port_max,
+ double o_databus_dimm_max [TT::DIMMS_PER_PORT])
+{
+ const uint8_t l_count_dimms = count_dimm(iv_target);
+
+ //No work for no dimms
+ if (l_count_dimms == 0)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target))
+ {
+ //Left early if count_dimms == 0
+ // For DDIMM, set each virtual DIMM to the same utilization value since mrw slope/intercept/limit attributes
+ // are equally divided by number of virtual dimms (ie. mrw values are for whole DDIMM, not individual virtual DIMMs)
+ // For ISDIMM, divide utilization by number of DIMMs on the port
+ mss::dimm::kind<MC> l_kind (l_dimm);
+ o_databus_dimm_max[mss::index(l_dimm)] = (l_kind.iv_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM) ?
+ i_databus_port_max :
+ i_databus_port_max / l_count_dimms;
+ }
+
+ //If the power slopes aren't equal, set the dimm with the highest power slope
+ //Should be correct even if only one DIMM is installed
+ if (iv_pwr_slope[0] != iv_pwr_slope[1])
+ {
+ o_databus_dimm_max[0] = (iv_pwr_slope[0] > iv_pwr_slope[1]) ? i_databus_port_max : 0;
+ o_databus_dimm_max[1] = (iv_pwr_slope[1] > iv_pwr_slope[0]) ? i_databus_port_max : 0;
+ }
+
+ //Make sure both are not 0
+ FAPI_ASSERT ( (o_databus_dimm_max[0] != 0) || (o_databus_dimm_max[1] != 0),
+ fapi2::MSS_NO_DATABUS_UTILIZATION()
+ .set_PORT_DATABUS_UTIL(i_databus_port_max)
+ .set_DIMM_COUNT(l_count_dimms),
+ "Failed to calculated databus utilization for target %s",
+ mss::c_str(iv_target));
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Converts the port and slot util to a dimm level based on powerslopes and number of dimms installed
+/// @param[in] i_util_slot databus utilization for the slot
+/// @param[in] i_util_port databus utilization for the port
+/// @param[out] o_util_dimm_max array of dimm utilization values
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
+/// @note determines worst case utilization per dimms, takes into account port and combine slot throttles
+/// @note used in calculating the port power, not for calculating the slot and port utilization
+///
+template<mss::mc_type MC, typename TT>
+fapi2::ReturnCode throttle<MC, TT>::calc_split_util(
+ const double i_util_slot,
+ const double i_util_port,
+ double o_util_dimm_max [TT::DIMMS_PER_PORT]) const
+{
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ uint8_t l_found_ddimm = 0;
+ const uint8_t l_count_dimms = count_dimm (iv_target);
+ //The total utilization to be used is limited by either what the port can allow or what the dimms can use
+ FAPI_ASSERT( (i_util_slot <= i_util_port),
+ fapi2::MSS_SLOT_UTIL_EXCEEDS_PORT()
+ .set_SLOT_UTIL(i_util_slot)
+ .set_PORT_UTIL(i_util_port),
+ "The slot utilization (%f) exceeds the port's utilization (%f) for %s",
+ i_util_slot,
+ i_util_port,
+ mss::c_str(iv_target));
+
+ if (l_count_dimms == 0)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ for ( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target) )
+ {
+ mss::dimm::kind<MC> l_kind (l_dimm);
+ l_found_ddimm = (l_kind.iv_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM) ? 1 : l_found_ddimm;
+ }
+
+ //assumptions slot <= port, l_count_dimms <=2
+ if (i_util_slot * l_count_dimms > i_util_port)
+ {
+ FAPI_INF("i_util_slot is %f, i_util_port is %f, l_count_dimms is %d for %s",
+ i_util_slot,
+ i_util_port,
+ l_count_dimms,
+ mss::c_str(iv_target));
+ const uint8_t l_high_pos = (iv_pwr_slope[0] >= iv_pwr_slope[1]) ? 0 : 1;
+
+ //Highest power_slope gets the higher utilization
+ o_util_dimm_max[l_high_pos] = std::min(i_util_slot, i_util_port);
+ //Set the other dimm to the left over utilization (i_util_port - i_util_slot) if not a DDIMM, otherwise set to same value as above
+ o_util_dimm_max[(!l_high_pos)] = (l_found_ddimm) ?
+ o_util_dimm_max[l_high_pos] :
+ ((l_count_dimms == TT::DIMMS_PER_PORT) ?
+ (i_util_port - o_util_dimm_max[l_high_pos]) :
+ 0
+ );
+
+ FAPI_INF("Split utilization for target %s, DIMM in %d gets %f, DIMM in %d gets %f",
+ mss::c_str(iv_target),
+ l_high_pos,
+ o_util_dimm_max[l_high_pos],
+ !l_high_pos,
+ o_util_dimm_max[!l_high_pos]);
+ }
+ else
+ {
+ //If only 1 dimm, i_util_port == i_util_slot
+ //If 2 dimms, 2*i_util_slot <= i_util_pot
+ //Either way, limit utilization by the slot value
+ for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target))
+ {
+ const size_t l_pos = mss::index(l_dimm);
+ o_util_dimm_max[l_pos] = i_util_slot;
+ }
+ }
+
+ //make sure both are not 0
+ FAPI_ASSERT ( (o_util_dimm_max[0] != 0) || (o_util_dimm_max[1] != 0),
+ fapi2::MSS_NO_DATABUS_UTILIZATION()
+ .set_PORT_DATABUS_UTIL(i_util_port)
+ .set_DIMM_COUNT(mss::count_dimm(iv_target)),
+ "Failed to calculated util utilization for target %s",
+ mss::c_str(iv_target));
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief set the safemode throttle register
+/// @tparam MC mss::mc_type
+/// @tparam T the fapi2 target type of the target
+/// @tparam TT portTraits port traits for the given MC target type
+/// @param[in] i_target the port target
+/// @return fapi2::FAPI2_RC_SUCCESS if ok
+/// @note sets FARB4Q
+/// @note used to set throttle window (N throttles / M clocks)
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = throttle_traits<MC>>
+fapi2::ReturnCode calc_utilization(const fapi2::Target<T>& i_target,
+ const uint32_t i_input_databus_util,
+ const uint32_t i_dram_clocks,
+ const uint16_t i_safemode_throttle_per_port,
+ const uint32_t i_max_databus_util,
+ uint32_t& o_util,
+ bool& o_util_error,
+ bool& o_safemode)
+{
+ constexpr uint64_t l_min_util = TT::MIN_UTIL;
+
+ o_util = i_input_databus_util;
+ o_safemode = false;
+
+ // Use MRW safemode throttle values if input utilization is zero
+ if (i_input_databus_util == 0)
+ {
+ FAPI_TRY(calc_util_from_throttles<MC>(i_safemode_throttle_per_port,
+ i_dram_clocks,
+ o_util),
+ "%s Error calculating utilization from safemode throttle %d and mem clocks %d",
+ mss::c_str(i_target),
+ i_safemode_throttle_per_port,
+ i_dram_clocks);
+ FAPI_INF("%s Safemode throttles being used since input util is zero: Using N=%d, Utilization %f",
+ mss::c_str(i_target),
+ i_safemode_throttle_per_port,
+ o_util);
+ o_safemode = true;
+ }
+ else if (i_input_databus_util < l_min_util)
+ {
+ o_util_error = true;
+ }
+
+ // Make sure MIN_UTIL <= input_utilization <= max_utilization
+ o_util = (o_util >= l_min_util) ? std::min(o_util, i_max_databus_util) : l_min_util;
+
+ FAPI_INF("%s MRW dram clock window: %d, databus utilization: %d",
+ mss::c_str(i_target),
+ i_dram_clocks,
+ o_util);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Equalize the throttles and estimated power at those throttle levels
+/// @tparam MC mss::mc_type
+/// @tparam T the fapi2 MC target type of the target
+/// @tparam TT throttle_traits throttle traits for the given mc_type
+/// @param[in] i_targets vector of MCS targets all on the same VDDR domain
+/// @param[in] i_throttle_type denotes if this was done for POWER (VMEM) or THERMAL (VMEM+VPP) throttles
+/// @param[out] o_exceeded_power vector of MCA targets where the estimated power exceeded the maximum allowed
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note sets the throttles and power to the worst case
+/// Called by p9_mss_bulk_pwr_throttles and by p9_mss_utils_to_throttle (so by IPL or by OCC)
+///
+template<mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = throttle_traits<MC>>
+fapi2::ReturnCode equalize_throttles (const std::vector< fapi2::Target<T> >& i_targets,
+ const throttle_type i_throttle_type,
+ std::vector< fapi2::Target<TT::PORT_TARGET_TYPE> >& o_exceeded_power)
+
+{
+ o_exceeded_power.clear();
+
+ //Set to max values so every compare will change to min value
+ uint16_t l_min_slot = ~(0);
+ uint16_t l_min_port = ~(0);
+
+ //Loop through all of the MC targets to find the worst case throttle value (lowest) for the slot and port
+ for (const auto& l_mc : i_targets)
+ {
+ for (const auto& l_port : mss::find_targets<TT::PORT_TARGET_TYPE>(l_mc))
+ {
+ uint16_t l_calc_slot = 0;
+ uint16_t l_calc_port = 0;
+ uint16_t l_run_slot = 0;
+ uint16_t l_run_port = 0;
+
+ if (mss::count_dimm(l_port) == 0)
+ {
+ FAPI_INF("Seeing no DIMMs on %s -- skipping", mss::c_str(l_port));
+ continue;
+ }
+
+ FAPI_TRY(mss::attr::get_mem_throttled_n_commands_per_slot(l_port, l_calc_slot));
+ FAPI_TRY(mss::attr::get_mem_throttled_n_commands_per_port(l_port, l_calc_port));
+ FAPI_TRY(mss::attr::get_runtime_mem_throttled_n_commands_per_slot(l_port, l_run_slot));
+ FAPI_TRY(mss::attr::get_runtime_mem_throttled_n_commands_per_port(l_port, l_run_port));
+
+ //Find the smaller of the three values (calculated slot, runtime slot, and min slot)
+ l_min_slot = (l_calc_slot != 0) ? std::min( std::min (l_calc_slot, l_run_slot),
+ l_min_slot) : l_min_slot;
+ l_min_port = (l_calc_port != 0) ? std::min( std::min( l_calc_port, l_run_port),
+ l_min_port) : l_min_port;
+ }
+ }
+
+ FAPI_INF("Calculated min slot is %d, min port is %d for the system", l_min_slot, l_min_port);
+
+ //Now set every port to have those values
+ {
+ for (const auto& l_mc : i_targets)
+ {
+ for (const auto& l_port : mss::find_targets<TT::PORT_TARGET_TYPE>(l_mc))
+ {
+ uint16_t l_fin_slot = 0;
+ uint16_t l_fin_port = 0;
+ uint32_t l_fin_power = 0;;
+
+ if (mss::count_dimm(l_port) == 0)
+ {
+ FAPI_INF("Seeing no DIMMs on %s -- skipping", mss::c_str(l_port));
+ continue;
+ }
+
+ // Declaring above to avoid fapi2 jump
+ uint64_t l_power_limit = 0;
+
+ l_fin_slot = l_min_slot;
+ l_fin_port = l_min_port;
+
+ //Need to create throttle object for each port in order to get dimm configuration and power curves
+ //To calculate the slot/port utilization and total port power consumption
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
+
+ const auto l_dummy = mss::power_thermal::throttle<MC>(l_port, l_rc);
+ FAPI_TRY(l_rc, "Failed creating a throttle object in equalize_throttles for %s", mss::c_str(l_port));
+
+ FAPI_TRY( l_dummy.calc_power_from_n(l_fin_slot, l_fin_port, l_fin_power),
+ "Failed calculating the power value for throttles: slot %d, port %d for target %s",
+ l_fin_slot,
+ l_fin_port,
+ mss::c_str(l_port));
+
+ // You may ask why this is not a variable within the throttle struct
+ // It's because POWER throttling is on a per port basis while the THERMAL throttle is per dimm
+ // Didn't feel like adding a variable just for this check
+ l_power_limit = (i_throttle_type == throttle_type::POWER) ?
+ l_dummy.iv_port_power_limit : (l_dummy.iv_dimm_thermal_limit[0] + l_dummy.iv_dimm_thermal_limit[1]);
+
+ FAPI_INF("%s Calculated power is %d, limit is %ld", mss::c_str(l_port), l_fin_power, l_power_limit);
+
+ //If there's an error with calculating port power, the wrong watt target was passed in
+ //Returns an error but doesn't deconfigure anything. Calling function can log if it wants to
+ //Called by OCC and by p9_mss_eff_config_thermal, thus different ways for error handling
+ //Continue setting throttles to prevent a possible throttle == 0
+ //The error will be the last bad port found
+ if (l_fin_power > l_power_limit)
+ {
+ //Need this because of pos traits and templating stuff
+ uint64_t l_fail = mss::fapi_pos(l_port);
+
+ //Set the failing port. OCC just needs one failing port, doesn't need all of them
+ FAPI_TRY( mss::attr::set_port_pos_of_fail_throttle(l_fail) );
+
+ FAPI_ASSERT_NOEXIT( false,
+ fapi2::MSS_CALC_PORT_POWER_EXCEEDS_MAX()
+ .set_CALCULATED_PORT_POWER(l_fin_power)
+ .set_MAX_POWER_ALLOWED(l_power_limit)
+ .set_PORT_POS(mss::pos(l_port))
+ .set_PORT_TARGET(l_port),
+ "Error calculating the final port power value for target %s, calculated power is %d, max value can be %d",
+ mss::c_str(l_port),
+ l_fin_power,
+ l_power_limit);
+
+ o_exceeded_power.push_back(l_port);
+ }
+
+ FAPI_INF("%s Final throttles values for slot %d, for port %d, power value %d",
+ mss::c_str(l_port),
+ l_fin_slot,
+ l_fin_port,
+ l_fin_power);
+
+ //Even if there's an error, still calculate and set the throttles.
+ //OCC will set to safemode if there's an error
+ //Better to set the throttles than leave them 0, and potentially brick the memory
+ FAPI_TRY( mss::attr::set_mem_throttled_n_commands_per_port( l_port, l_fin_port) );
+ FAPI_TRY( mss::attr::set_mem_throttled_n_commands_per_slot( l_port, l_fin_slot) );
+ FAPI_TRY( mss::attr::set_port_maxpower( l_port, l_fin_power) );
+ }
+ }
+ }
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ FAPI_ERR("Error equalizing memory throttles");
+ return fapi2::current_err;
+}
+
+} //ns power_thermal
+}// mss
+
+#endif
diff --git a/src/import/generic/memory/lib/utils/power_thermal/gen_throttle_traits.H b/src/import/generic/memory/lib/utils/power_thermal/gen_throttle_traits.H
index 17758adf1..d6d30fa66 100644
--- a/src/import/generic/memory/lib/utils/power_thermal/gen_throttle_traits.H
+++ b/src/import/generic/memory/lib/utils/power_thermal/gen_throttle_traits.H
@@ -22,3 +22,36 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file gen_throttle_traits.H
+/// @brief Contains throttle traits information
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP FW Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: CI
+
+#ifndef _GEN_THROTTLE_TRAITS_H_
+#define _GEN_THROTTLE_TRAITS_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+namespace mss
+{
+
+namespace power_thermal
+{
+
+///
+/// @class Traits for throttle
+/// @tparam MC mss::mc_type memory controller type
+///
+template< mss::mc_type MC = DEFAULT_MC_TYPE >
+class throttle_traits;
+
+} //ns power_thermal
+} // ns mss
+#endif
diff --git a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H
index bcf4f1207..77f177c40 100644
--- a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H
+++ b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018,2019 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] Evan Lojewski */
/* [+] International Business Machines Corp. */
/* */
@@ -38,7 +38,9 @@
#ifndef _MSS_GENERIC_CONSTS_H_
#define _MSS_GENERIC_CONSTS_H_
-#include <cstdint>
+#ifndef __PPE__
+ #include <cstdint>
+#endif
namespace mss
{
@@ -52,6 +54,39 @@ enum common_consts
MEMCMP_EQUAL = 0, ///< Equal comparison value for memcmp
BAD_BITS_RANKS = 4, ///< Bad bit attribute's number of ranks
BAD_DQ_BYTE_COUNT = 10, ///< Bad bit attribute's number of byte
+ ATTR_RANK0 = 0, ///< Attribute index for rank0
+ ATTR_RANK1 = 1, ///< Attribute index for rank1
+ ATTR_RANK2 = 2, ///< Attribute index for rank2
+ ATTR_RANK3 = 3, ///< Attribute index for rank3
+};
+
+///
+/// @brief Common mcbist constants
+///
+enum mcbist_common_consts
+{
+ CYCLES_PER_CMD = 4, ///< Best case cycles per MCBIST command
+ MAX_RANK_PER_DIMM = 4,
+
+ BYTES_PER_GB = 1000000000, ///< Multiplier to go from GB to B
+ T_PER_MT = 1000000, ///< Multiplier to go from MT/s to T/s
+
+ // Number of double words in...
+ NUM_DW_IN_128B = 16,
+ NUM_DW_IN_64B = 8,
+
+ BG_SCRUB_IN_HOURS = 12,
+ CMD_TIMEBASE = 8192, ///< Represents the timebase multiplier for the MCBIST inter cmd gap
+ MAX_CMD_GAP = 4095, ///< Represents the maximum (non-multplied) time for MCBIST inter cmd gap
+
+
+ // MCBIST polling constant for actual HW
+ // The specific value here is not important, only that it is very large to avoid polling timeouts,
+ // but not to avoid any actual hardware timeouts
+ // Note: ~0 is not used as that would cause MCBIST to never timeout even if the hardware is in an infinite loop
+ // You can't get greater than ~0, so you'd never timeout
+ // TODO RTC:166340 - Clean up MCBIST polling
+ OVERLY_LARGE_NUMBER_OF_POLLS = 5000000000000,
};
///
@@ -60,12 +95,13 @@ enum common_consts
enum common_timings
{
DELAY_1NS = 1,
- DELAY_10NS = 10 , ///< general purpose 10 ns delay for HW mode
- DELAY_100NS = 100, ///< general purpose 100 ns delay for HW mode
- DELAY_1US = 1000, ///< general purpose 1 usec delay for HW mode
- DELAY_10US = 10000, ///< general purpose 1 usec delay for HW mode
- DELAY_100US = 100000, ///< general purpose 100 usec delay for HW mode
- DELAY_1MS = 1000000, ///< general purpose 1 ms delay for HW mode
+ DELAY_10NS = 10 , ///< general purpose 10 ns delay for HW mode
+ DELAY_100NS = 100, ///< general purpose 100 ns delay for HW mode
+ DELAY_1US = 1000, ///< general purpose 1 usec delay for HW mode
+ DELAY_10US = 10000, ///< general purpose 1 usec delay for HW mode
+ DELAY_100US = 100000, ///< general purpose 100 usec delay for HW mode
+ DELAY_1MS = 1000000, ///< general purpose 1 ms delay for HW mode
+ DELAY_1S = 1000000000, ///< general purpose 1 sec delay for HW mode
};
///
@@ -80,6 +116,17 @@ enum conversions
NIBBLES_PER_BYTE = 2,
BITS_PER_NIBBLE = 4,
BITS_PER_BYTE = 8,
+ BIT_POS_FOR_BYTE0 = BITS_PER_BYTE * 0,
+ BIT_POS_FOR_BYTE1 = BITS_PER_BYTE * 1,
+ BIT_POS_FOR_BYTE2 = BITS_PER_BYTE * 2,
+ BIT_POS_FOR_BYTE3 = BITS_PER_BYTE * 3,
+ BIT_POS_FOR_BYTE4 = BITS_PER_BYTE * 4,
+ BIT_POS_FOR_BYTE5 = BITS_PER_BYTE * 5,
+ BIT_POS_FOR_BYTE6 = BITS_PER_BYTE * 6,
+ BIT_POS_FOR_BYTE7 = BITS_PER_BYTE * 7,
+
+ // Used by exp_decoder.C for dA to cA
+ DECI_TO_CENTI = 10,
};
enum generic_sizes
@@ -141,8 +188,11 @@ enum generic_ffdc_codes
SET_MRANKS = 0x102A,
SET_HOST_TO_DDR_SPEED_RATIO = 0x102B,
SET_ATTR_HOST_TO_DDR_SPEED_RATIO = 0x102C,
+ CCS_INST_CONFIGURE_RANK = 0x102D,
SET_DIMM_RANKS_CNFG = 0x1039,
DDIMM_RAWCARD_DECODE = 0x103a,
+ INIT_RANK_INFO = 0x103B,
+ BIAS_PMIC_FROM_SPD = 0x103C,
SET_DRAM_WIDTH = 0x1040,
SET_SI_VREF_DRAM_WR = 0x1041,
@@ -170,6 +220,58 @@ enum generic_ffdc_codes
SET_DRAM_GEN_METADATA = 0x1063,
SET_DIMM_TYPE_METADATA = 0x1064,
SET_DIMM_POS_METADATA = 0x1065,
+ SET_LOGICAL_RANKS = 0x1066,
+ SET_PRIM_STACK_TYPE = 0x1067,
+ SET_DIMM_SIZE = 0x1068,
+ SET_PRIM_BUS_WIDTH = 0x1069,
+ SET_PRIM_DIE_COUNT = 0x1070,
+ SET_DRAM_DENSITY = 0x1071,
+
+ // Power thermal functions
+ POWER_LIMIT = 0x1072,
+ SLOPE = 0x1073,
+ INTERCEPT = 0x1074,
+
+ SET_SI_RD_VREF_DQ = 0x1075,
+ SET_CAC_DELAY_A = 0x1076,
+ SET_CAC_DELAY_B = 0x1077,
+ EFD_CA_LATENCY_MODE = 0x1080,
+ EFD_CA_PL_MODE = 0x1081,
+ SET_COL_ADDR_BITS = 0x1082,
+ SET_ROW_ADDR_BITS = 0x1083,
+ SET_3DS_HEIGHT = 0x1084,
+ SET_DRAM_CWL = 0x1085,
+ SET_DRAM_TREFI = 0x1086,
+ SET_DRAM_TCCD_L = 0x1087,
+ SET_DRAM_TWTR_L = 0x1088,
+ SET_DRAM_TWTR_S = 0x1089,
+ SET_DRAM_TFAW = 0x108A,
+ SET_DRAM_TRCD = 0x108B,
+ SET_DRAM_TRP = 0x108C,
+ SET_DRAM_TRAS = 0x108D,
+ SET_DRAM_TWR = 0x108E,
+ SET_DRAM_TRTP = 0x108F,
+ SET_DRAM_TRRD_S = 0x1090,
+ SET_DRAM_TRRD_L = 0x1091,
+ SET_DRAM_TRFC = 0x1092,
+ SET_DRAM_TRFC_DLR = 0x1093,
+ SET_DRAM_MFG_ID = 0x1094,
+
+ // Used in fw_mark_store.H for MSS_INVALID_RANK_PASSED
+ FWMS_READ = 0x1095,
+ FWMS_WRITE = 0x1096,
+
+ // Used in hw_mark_store.H for MSS_INVALID_RANK_PASSED
+ HWMS_READ = 0x1097,
+ HWMS_WRITE = 0x1098,
+
+ // MSS_INVALID_INDEX_PASSED
+ SYMBOL_COUNT_READ = 0x1099,
+ SYMBOL_COUNT_WRITE = 0x109A,
+
+ SET_RCD_MFG_ID = 0x109B,
+ SET_DRAM_MODULE_HEIGHT = 0x109C,
+ SET_SPD_REVISION = 0x109D,
};
///
@@ -242,6 +344,510 @@ enum states
NO_CHIP_SELECT_ACTIVE = 0xFF,
};
+
+enum port_select
+{
+ // Port selects for MCBIST and CCS
+ // Select for 1 port
+ PORT0 = 0b1000,
+ PORT1 = 0b0100,
+ PORT2 = 0b0010,
+ PORT3 = 0b0001,
+ // Selects for 2 port combinations
+ PORT01 = PORT0 | PORT1,
+ PORT02 = PORT0 | PORT2,
+ PORT03 = PORT0 | PORT3,
+ PORT12 = PORT1 | PORT2,
+ PORT13 = PORT1 | PORT3,
+ PORT23 = PORT2 | PORT3,
+ // Selects for 3 port combinations
+ PORT012 = PORT0 | PORT1 | PORT2,
+ PORT013 = PORT0 | PORT1 | PORT3,
+ PORT023 = PORT0 | PORT2 | PORT3,
+ PORT123 = PORT1 | PORT2 | PORT3,
+ // Select all
+ PORT0123 = PORT0 | PORT1 | PORT2 | PORT3,
+ // Maybe a better name for disabling all
+ PORT_NONE = 0b0000,
+};
+
+enum dimm_select
+{
+ // Dimm selects for MCBIST and CCS
+ // Select for 1 dimm
+ DIMM0 = 0b10,
+ DIMM1 = 0b01,
+ // Selects for 2 dimm combinations
+ DIMM01 = DIMM0 | DIMM1,
+ // Maybe a better name for disabling all
+ DIMM_NONE = 0b00,
+};
+
+namespace mcbist
+{
+
+enum broadcast_timebase
+{
+ // Number of 1024 2:1 cycle timebases to wait starting MCBIST
+ // for SRQs to get synced for broadcast mode
+ TB_COUNT_2 = 0b0000001,
+ TB_COUNT_4 = 0b0000011,
+ TB_COUNT_8 = 0b0000111,
+ TB_COUNT_16 = 0b0001111,
+ TB_COUNT_32 = 0b0011111,
+ TB_COUNT_64 = 0b0111111,
+ TB_COUNT_128 = 0b1111111,
+};
+
+enum data_rotate_mode
+{
+ // MCBIST data rotate modes refer to register MCBDRCR bits 0:3
+ ROTATE_0_BITS = 0b0000,
+ ROTATE_1_BITS = 0b0001,
+ ROTATE_2_BITS = 0b0010,
+ ROTATE_3_BITS = 0b0011,
+ ROTATE_4_BITS = 0b0100,
+ ROTATE_5_BITS = 0b0101,
+ ROTATE_6_BITS = 0b0110,
+ ROTATE_7_BITS = 0b0111,
+ ROTATE_8_BITS = 0b1000,
+ ROTATE_9_BITS = 0b1001,
+ ROTATE_10_BITS = 0b1010,
+ ROTATE_11_BITS = 0b1011,
+ ROTATE_12_BITS = 0b1100,
+ ROTATE_13_BITS = 0b1101,
+ ROTATE_14_BITS = 0b1110,
+ ROTATE_15_BITS = 0b1111,
+};
+
+enum data_seed_mode
+{
+ // MCBIST data seed modes refer to register MCBDRCR bits 21:22
+ ALL_UNIQUE = 0b00,
+ REPEAT_SEED_0 = 0b01,
+ REPEAT_SEED_1 = 0b10,
+ REPEAT_SEED_2 = 0b11,
+};
+
+enum data_mode
+{
+ // MCBIST test data modes
+ FIXED_DATA_MODE = 0b000,
+ RAND_FWD_MODE = 0b001,
+ RAND_REV_MODE = 0b010,
+ RAND_FWD_MAINT = 0b011,
+ RAND_REV_MAINT = 0b100,
+ DATA_EQ_ADDR = 0b101,
+ ROTATE_LEFT_MODE = 0b110,
+ ROTATE_RIGHT_MODE = 0b111,
+};
+
+// 0:3 Operation Type
+enum op_type
+{
+ WRITE = 0b0000, // fast, with no concurrent traffic
+ READ = 0b0001, // fast, with no concurrent traffic
+ READ_WRITE = 0b0010,
+ WRITE_READ = 0b0011,
+ READ_WRITE_READ = 0b0100,
+ READ_WRITE_WRITE = 0b0101,
+ RAND_SEQ = 0b0110,
+ READ_READ_WRITE = 0b1000,
+ SCRUB_RRWR = 0b1001,
+ STEER_RW = 0b1010,
+ ALTER = 0b1011, // (W)
+ DISPLAY = 0b1100, // (R, slow)
+ CCS_EXECUTE = 0b1111,
+
+ // if bits 9:11 (Data Mode bits) = 000 (bits 4:8 used to specify which subtest to go to)
+ // Refresh only cmd if bits 9:11 (Data Mode bits) /= 000
+ GOTO_SUBTEST_N = 0b0111,
+};
+
+
+enum test_type
+{
+ USER_MODE = 0,
+ CENSHMOO = 1,
+ SUREFAIL = 2,
+ MEMWRITE = 3,
+ MEMREAD = 4,
+ CBR_REFRESH = 5,
+ MCBIST_SHORT = 6,
+ SHORT_SEQ = 7,
+ DELTA_I = 8,
+ DELTA_I_LOOP = 9,
+ SHORT_RAND = 10,
+ LONG1 = 11,
+ BUS_TAT = 12,
+ SIMPLE_FIX = 13,
+ SIMPLE_RAND = 14,
+ SIMPLE_RAND_2W = 15,
+ SIMPLE_RAND_FIXD = 16,
+ SIMPLE_RA_RD_WR = 17,
+ SIMPLE_RA_RD_R = 18,
+ SIMPLE_RA_FD_R = 19,
+ SIMPLE_RA_FD_R_INF = 20,
+ SIMPLE_SA_FD_R = 21,
+ SIMPLE_RA_FD_W = 22,
+ INFINITE = 23,
+ WR_ONLY = 24,
+ W_ONLY = 25,
+ R_ONLY = 26,
+ W_ONLY_RAND = 27,
+ R_ONLY_RAND = 28,
+ R_ONLY_MULTI = 29,
+ SHORT = 30,
+ SIMPLE_RAND_BARI = 31,
+ W_R_INFINITE = 32,
+ W_R_RAND_INFINITE = 33,
+ R_INFINITE1 = 34,
+ R_INFINITE_RF = 35,
+ MARCH = 36,
+ SIMPLE_FIX_RF = 37,
+ SHMOO_STRESS = 38,
+ SIMPLE_RAND_RA = 39,
+ SIMPLE_FIX_RA = 40,
+ SIMPLE_FIX_RF_RA = 41,
+ TEST_RR = 42,
+ TEST_RF = 43,
+ W_ONLY_INFINITE_RAND = 44,
+ MCB_2D_CUP_SEQ = 45,
+ MCB_2D_CUP_RAND = 46,
+ SHMOO_STRESS_INFINITE = 47,
+ HYNIX_1_COL = 48,
+ RMWFIX = 49,
+ RMWFIX_I = 50,
+ W_INFINITE = 51,
+ R_INFINITE = 52,
+};
+
+
+} // namespace mcbist
+
+namespace omi
+{
+
+///
+/// @brief dl0 no forward progress timer
+///
+enum no_forward_progress_timer
+{
+ NO_FORWARD_TIMER_1US = 0b0000,
+ NO_FORWARD_TIMER_2US = 0b0001,
+ NO_FORWARD_TIMER_4US = 0b0010,
+ NO_FORWARD_TIMER_8US = 0b0011,
+ NO_FORWARD_TIMER_16US = 0b0100,
+ NO_FORWARD_TIMER_32US = 0b0101,
+ NO_FORWARD_TIMER_64US = 0b0110,
+ NO_FORWARD_TIMER_128US = 0b0111,
+ NO_FORWARD_TIMER_256US = 0b1000,
+ NO_FORWARD_TIMER_512US = 0b1001,
+ NO_FORWARD_TIMER_1MS = 0b1010,
+ NO_FORWARD_TIMER_2MS = 0b1011,
+ NO_FORWARD_TIMER_4MS = 0b1100,
+ NO_FORWARD_TIMER_8MS = 0b1101,
+ NO_FORWARD_TIMER_16MS = 0b1110,
+ NO_FORWARD_TIMER_DISABLED = 0b1111,
+};
+
+///
+/// @brief dl0 PHY control mode - determines the amount of time needed to receive pattern A or pattern B
+///
+enum phy_ctr_mode
+{
+ PHY_CTR_MODE_1US = 0b0000,
+ PHY_CTR_MODE_50US = 0b0001,
+ PHY_CTR_MODE_100US = 0b0010,
+ PHY_CTR_MODE_200US = 0b0011,
+ PHY_CTR_MODE_500US = 0b0100,
+ PHY_CTR_MODE_1MS = 0b0101,
+ PHY_CTR_MODE_2MS = 0b0110,
+ PHY_CTR_MODE_3MS = 0b0111,
+ PHY_CTR_MODE_4MS = 0b1000,
+ PHY_CTR_MODE_5MS = 0b1001,
+ PHY_CTR_MODE_6MS = 0b1010,
+ PHY_CTR_MODE_8MS = 0b1011,
+ PHY_CTR_MODE_10MS = 0b1100,
+ PHY_CTR_MODE_15MS = 0b1101,
+ PHY_CTR_MODE_30MS = 0b1110,
+ PHY_CTR_MODE_60MS = 0b1111,
+};
+
+///
+/// @brief dl0 supported link widths
+///
+enum link_widths
+{
+ LINK_WIDTHS_X4PLUS1 = 0b1000,
+ LINK_WIDTHS_X16 = 0b0100,
+ LINK_WIDTHS_X8 = 0b0010,
+ LINK_WIDTHS_X4 = 0b0001,
+};
+
+///
+/// @brief dl0 train mode
+///
+enum train_mode
+{
+ TX_ZEROS = 0b0000,
+ TX_PATTERN_A = 0b0001,
+ TX_PATTERN_B = 0b0010,
+ TX_SYNC_PATTERN = 0b0011,
+ TX_TRAINING_STATE1 = 0b0100,
+ TX_TRAINING_STATE2 = 0b0101,
+ TX_TRAINING_STATE3 = 0b0110,
+ TX_TRAINING_STATE0 = 0b0111,
+ ENABLE_AUTO_TRAINING = 0b1000,
+};
+
+
+///
+/// @brief These values are the number of clock cycles and the times specified assume a 625ps period.
+/// This timer value must be greater than the di/dt timer
+///
+enum rx_cdr_timer
+{
+ CDR_TIMER_DISABLED = 0b0001,
+ CDR_TIMER_60NS = 0b0001,
+ CDR_TIMER_125NS = 0b0010,
+ CDR_TIMER_185NS = 0b0011,
+ CDR_TIMER_250NS = 0b0100,
+ CDR_TIMER_375NS = 0b0101,
+ CDR_TIMER_500NS = 0b0110,
+ CDR_TIMER_750NS = 0b0111,
+ CDR_TIMER_1US = 0b1000,
+ CDR_TIMER_2US = 0b1001,
+ CDR_TIMER_4US = 0b1010,
+ CDR_TIMER_8US = 0b1011,
+ CDR_TIMER_16US = 0b1100,
+ CDR_TIMER_32US = 0b1101,
+ CDR_TIMER_64US = 0b1110,
+ CDR_TIMER_128US = 0b1111,
+};
+
+///
+/// @brief Amount of time to wait after lane is turned on/off before another lane can be turned on/off
+///
+enum didt_timer
+{
+ DIDT_TIMER_DISABLED = 0b0000,
+ DIDT_TIMER_5NS = 0b0001,
+ DIDT_TIMER_10NS = 0b0010,
+ DIDT_TIMER_15NS = 0b0011,
+ DIDT_TIMER_20NS = 0b0100,
+ DIDT_TIMER_30NS = 0b0101,
+ DIDT_TIMER_45NS = 0b0110,
+ DIDT_TIMER_60NS = 0b0111,
+ DIDT_TIMER_90NS = 0b1000,
+ DIDT_TIMER_125NS = 0b1001,
+ DIDT_TIMER_185NS = 0b1010,
+ DIDT_TIMER_250NS = 0b1011,
+ DIDT_TIMER_375NS = 0b1100,
+ DIDT_TIMER_500NS = 0b1101,
+ DIDT_TIMER_768NS = 0b1110,
+ DIDT_TIMER_1US = 0b1111,
+};
+
+///
+/// @brief Calibration timer - amount of time betweem re-calibration for a given lane
+///
+enum recal_timer
+{
+ RECAL_TIMER_DISABLED = 0b000,
+ RECAL_TIMER_25MS = 0b001,
+ RECAL_TIMER_50MS = 0b010,
+ RECAL_TIMER_100MS = 0b011,
+ RECAL_TIMER_200MS = 0b100,
+ RECAL_TIMER_400MS = 0b101,
+ RECAL_TIMER_800MS = 0b110,
+ RECAL_TIMER_1600MS = 0b111,
+};
+
+///
+/// @brief PMU prescalar value
+///
+enum pmu_prescalar
+{
+ PRESCALAR_16BIT = 0b000,
+ PRESCALAR_8BIT = 0b001,
+ PRESCALAR_20BIT = 0b100,
+};
+
+
+///
+/// @brief PMU cntrx pair selector
+///
+enum cntrl_pair_selector
+{
+ SEL_ODD = 0b00,
+ SEL_EVEN = 0b01,
+ SEL_BOTH_AND = 0b10,
+ SEL_BOTH_XOR = 0b11,
+};
+
+///
+/// @brief PMU cntrx event selector
+///
+enum cntrl_event_selector
+{
+ SIG_7_6 = 0b00,
+ SIG_5_4 = 0b01,
+ SIG_3_2 = 0b10,
+ SIG_1_0 = 0b11,
+};
+
+///
+/// @brief Configuration override to select lane width for dynamic lane power down modes.
+///
+enum lan_width_override
+{
+ TL_CTR_BY_SIDEBAND = 0b00,
+ DL_OVERRIDE_X2 = 0b01,
+ DL_OVERRIDE_X4 = 0b10,
+ DL_OVERRIDE_X8 = 0b11,
+};
+
+///
+/// @brief Number of consecutive pattern B seen before indicating received pattern B
+///
+enum b_hysteresis
+{
+ B_HYSTERESIS_16 = 0b0000,
+ B_HYSTERESIS_24 = 0b0001,
+ B_HYSTERESIS_32 = 0b0010,
+ B_HYSTERESIS_40 = 0b0011,
+ B_HYSTERESIS_48 = 0b0100,
+ B_HYSTERESIS_56 = 0b0101,
+ B_HYSTERESIS_64 = 0b0110,
+ B_HYSTERESIS_72 = 0b0111,
+ B_HYSTERESIS_80 = 0b1000,
+ B_HYSTERESIS_96 = 0b1001,
+ B_HYSTERESIS_128 = 0b1010,
+ B_HYSTERESIS_256 = 0b1011,
+ B_HYSTERESIS_512 = 0b1100,
+ B_HYSTERESIS_1K = 0b1101,
+ B_HYSTERESIS_2K = 0b1110,
+ B_HYSTERESIS_4K = 0b1111,
+};
+
+///
+/// @brief Number of consecutive pattern A seen before indicating received pattern A.
+///
+enum a_hysteresis
+{
+ A_HYSTERESIS_16 = 0b0000,
+ A_HYSTERESIS_24 = 0b0001,
+ A_HYSTERESIS_32 = 0b0010,
+ A_HYSTERESIS_48 = 0b0011,
+ A_HYSTERESIS_64 = 0b0100,
+ A_HYSTERESIS_96 = 0b0101,
+ A_HYSTERESIS_128 = 0b0110,
+ A_HYSTERESIS_256 = 0b0111,
+ A_HYSTERESIS_512 = 0b1000,
+ A_HYSTERESIS_1024 = 0b1001,
+ A_HYSTERESIS_2K = 0b1010,
+ A_HYSTERESIS_4K = 0b1011,
+ A_HYSTERESIS_8K = 0b1100,
+ A_HYSTERESIS_16K = 0b1101,
+ A_HYSTERESIS_32K = 0b1110,
+ A_HYSTERESIS_64K = 0b1111,
+};
+
+///
+/// @brief Lanes disabled
+///
+enum
+{
+ LANE_DISABLED_NONE = 0b00000000,
+ LANE_DISABLED_7 = 0b00000001,
+ LANE_DISABLED_6 = 0b00000010,
+ LANE_DISABLED_5 = 0b00000100,
+ LANE_DISABLED_4 = 0b00001000,
+ LANE_DISABLED_3 = 0b00010000,
+ LANE_DISABLED_2 = 0b00100000,
+ LANE_DISABLED_1 = 0b01000000,
+ LANE_DISABLED_0 = 0b10000000,
+};
+
+///
+/// @brief dl0 inject crc direction
+///
+enum crc_inject_dir
+{
+ CRC_DIR_RX = 0,
+ CRC_DIR_TX = 1,
+};
+
+///
+/// @brief dl0 crc injection rate
+///
+enum crc_inject_rate
+{
+ CRC_INJ_RATE_1US = 0b0000,
+ CRC_INJ_RATE_8US = 0b0001,
+ CRC_INJ_RATE_64US = 0b0010,
+ CRC_INJ_RATE_512US = 0b0011,
+ CRC_INJ_RATE_4MS = 0b0100,
+ CRC_INJ_RATE_32MS = 0b0101,
+ CRC_INJ_RATE_256MS = 0b0110,
+ CRC_INJ_RATE_2S = 0b0111,
+};
+
+///
+/// @brief CFG_DL0_EDPL_TIME: dl0 edpl time window
+///
+enum edpl_time_win
+{
+ EDPL_TIME_WIN_NO = 0b0000,
+ EDPL_TIME_WIN_4US = 0b0001,
+ EDPL_TIME_WIN_32US = 0b0010,
+ EDPL_TIME_WIN_256US = 0b0011,
+ EDPL_TIME_WIN_2MS = 0b0100,
+ EDPL_TIME_WIN_16MS = 0b0101,
+ EDPL_TIME_WIN_128MS = 0b0110,
+ EDPL_TIME_WIN_1S = 0b0111,
+ EDPL_TIME_WIN_8S = 0b1000,
+ EDPL_TIME_WIN_64S = 0b1001,
+ EDPL_TIME_WIN_512S = 0b1010,
+ EDPL_TIME_WIN_4KS = 0b1011,
+ EDPL_TIME_WIN_32KS = 0b1100,
+ EDPL_TIME_WIN_256KS = 0b1101,
+ EDPL_TIME_WIN_2MILLIONS = 0b1110,
+ EDPL_TIME_WIN_16MILLIONS = 0b1111,
+};
+
+///
+/// @brief CFG_DL0_EDPL_THRESHOLD: dl0 edpl threshold
+///
+enum edpl_err_thres
+{
+ EDPL_ERR_THRES_DISABLED = 0b000,
+ EDPL_ERR_THRES_2 = 0b001,
+ EDPL_ERR_THRES_4 = 0b010,
+ EDPL_ERR_THRES_8 = 0b011,
+ EDPL_ERR_THRES_16 = 0b100,
+ EDPL_ERR_THRES_32 = 0b101,
+ EDPL_ERR_THRES_64 = 0b110,
+ EDPL_ERR_THRES_128 = 0b111,
+};
+
+///
+/// @brief CONFIG1_CFG_PREIPL_PRBS_TIME: config1 pre-ipl prbs time
+///
+enum preipl_prbs_time
+{
+ PREIPL_PRBS_256US = 0b000,
+ PREIPL_PRBS_1US = 0b001,
+ PREIPL_PRBS_4MS = 0b010,
+ PREIPL_PRBS_16MS = 0b011,
+ PREIPL_PRBS_64MS = 0b100,
+ PREIPL_PRBS_256MS = 0b101,
+ PREIPL_PRBS_1S = 0b110,
+ PREIPL_PRBS_4S = 0b111,
+};
+
+}
///
/// @brief Supported DIMM speed equality deliberations
///
@@ -260,6 +866,7 @@ namespace spd
enum rev : uint8_t
{
V0_0 = 0x00, ///< represents Rev 0.0
+ V0_3 = 0x03, ///< represents Rev 0.3
V1_0 = 0x10, ///< represents Rev 1.0
V1_1 = 0x11, ///< represents Rev 1.1
V1_2 = 0x12, ///< represents Rev 1.2
@@ -269,7 +876,7 @@ enum rev : uint8_t
GEN_SEC_MAX = V1_1,
RDIMM_MAX = V1_1,
LRDIMM_MAX = V1_2,
- DDIMM_MAX = V0_0,
+ DDIMM_MAX = V0_3,
};
///
@@ -356,6 +963,7 @@ enum class throttle_type
};
+
///
/// @brief Trait classes for mc_type
/// @tparam MC the mc_type
diff --git a/src/import/generic/memory/lib/utils/voltage/gen_mss_volt.H b/src/import/generic/memory/lib/utils/voltage/gen_mss_volt.H
index d84c97dbe..9ff39109e 100644
--- a/src/import/generic/memory/lib/utils/voltage/gen_mss_volt.H
+++ b/src/import/generic/memory/lib/utils/voltage/gen_mss_volt.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -115,8 +115,6 @@ inline fapi2::ReturnCode setup_voltage_rail_values(const fapi2::Target<TT::SPD_T
FAPI_TRY( (mss::set_voltage_attributes<M, D>(l_voltage_target, l_dram_voltages)),
"Failed to set volt attributes for %s", mss::c_str(l_voltage_target) );
- FAPI_INF("%s End setup_voltage_rail_values", mss::c_str(i_target));
-
fapi_try_exit:
return fapi2::current_err;
}
diff --git a/src/import/generic/memory/mss_git_data_helper.H b/src/import/generic/memory/mss_git_data_helper.H
index c20a62ab0..ef09834fa 100644
--- a/src/import/generic/memory/mss_git_data_helper.H
+++ b/src/import/generic/memory/mss_git_data_helper.H
@@ -22,3 +22,37 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+///
+/// @file mss_git_data_helper.H
+/// @brief Helper file to print out the git data
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_GIT_DATA_HELPER_
+#define _MSS_GIT_DATA_HELPER_
+
+#ifndef __HOSTBOOT_MODULE
+ #include <generic/memory/mss_git_data.H>
+#endif
+
+namespace mss
+{
+
+///
+/// @brief Prints out the git commit data
+/// @pram[in] i_print additional print information to be added to the print statement
+///
+inline void display_git_commit_info(const char* i_print)
+{
+#ifndef __HOSTBOOT_MODULE
+ FAPI_INF("%s Git commit ID: %s", i_print, GIT_COMMIT_ID.c_str());
+#endif
+}
+
+} // ns mss
+
+#endif
diff --git a/src/import/generic/procedures/xml/attribute_info/generic_memory_attributes.xml b/src/import/generic/procedures/xml/attribute_info/generic_memory_attributes.xml
index 48c351b5f..ea15be54c 100644
--- a/src/import/generic/procedures/xml/attribute_info/generic_memory_attributes.xml
+++ b/src/import/generic/procedures/xml/attribute_info/generic_memory_attributes.xml
@@ -86,9 +86,15 @@
The map from the Dual Inline Memory Module
(DIMM) Data (DQ) Pin to the Module Package Data (DQ) Pinout
</description>
- <initToZero></initToZero>
+ <platInit/>
+ <mrwHide/>
+ <default>
+ <!-- Default to a 1:1 layout to match the DDIMM specification -->
+ 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,37,38,39,40,41,42,43,44,45,46,47,48,49,50,
+ 51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71
+ </default>
<valueType>uint8</valueType>
- <writeable/>
<mssUnits></mssUnits>
<mssBlobStart>0</mssBlobStart>
<mssBlobLength>72</mssBlobLength>
@@ -388,4 +394,33 @@
<mssAccessorName>dimm_type_metadata</mssAccessorName>
</attribute>
+ <attribute>
+ <id>ATTR_MSS_OMI_EDPL_DISABLE</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ EDPL (Error Detection Per Lane) is a feature in the DL that adds some additional checks to
+ the traffic going across the OpenCAPI link in order to better track which lanes are having issues.
+ Note: EDPL must be set the same on both sides of the link. This attribute affects both the proc/mc
+ side and the OCMB side.
+ </description>
+ <valueType>uint8</valueType>
+ <enum>FALSE = 0, TRUE = 1</enum>
+ <platInit/>
+ <initToZero/>
+ <mssAccessorName>mss_omi_edpl_disable</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_OMI_DL_PREIPL_PRBS_TIME</id>
+ <targetType>TARGET_TYPE_OMI</targetType>
+ <description>
+ The time to send pre-ipl PRBS in ms.
+ </description>
+ <valueType>uint32</valueType>
+ <default>0x400</default>
+ <platInit/>
+ <mrwHide/>
+ <mssAccessorName>omi_dl_preipl_prbs_time</mssAccessorName>
+ </attribute>
+
</attributes>
diff --git a/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml b/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml
index 8890a447b..50246bb19 100644
--- a/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml
+++ b/src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml
@@ -5,7 +5,7 @@
<!-- -->
<!-- OpenPOWER HostBoot Project -->
<!-- -->
-<!-- Contributors Listed Below - COPYRIGHT 2018,2019 -->
+<!-- Contributors Listed Below - COPYRIGHT 2018,2020 -->
<!-- [+] International Business Machines Corp. -->
<!-- -->
<!-- -->
@@ -64,7 +64,7 @@
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
- <enum> EMPTY = 0, RDIMM = 1, UDIMM = 2, LRDIMM = 3, DDIMM = 4</enum>
+ <enum> EMPTY = 0, RDIMM = 1, UDIMM = 2, LRDIMM = 3, DDIMM = 4, MDS_LRDIMM = 5, MDS = 6</enum>
<writeable/>
<array>2</array>
<mssAccessorName>dimm_type</mssAccessorName>
@@ -187,6 +187,7 @@
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
+ <enum> NUM10 = 10</enum>
<writeable/>
<array>2</array>
<mssAccessorName>dram_column_bits</mssAccessorName>
@@ -212,11 +213,36 @@
</attribute>
<attribute>
+ <id>ATTR_MEM_EFF_PRIM_DIE_COUNT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ ARRAY[DIMM]
+ Primary SDRAM Die Count.
+ Decodes Byte 6 (bits 6~4).
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint8</valueType>
+ <enum>
+ D1 = 1,
+ D2 = 2,
+ D3 = 3,
+ D4 = 4,
+ D5 = 5,
+ D6 = 6,
+ D7 = 7,
+ D8 = 8
+ </enum>
+ <writeable/>
+ <array>2</array>
+ <mssAccessorName>prim_die_count</mssAccessorName>
+ </attribute>
+
+ <attribute>
<id>ATTR_MEM_EFF_PRIM_STACK_TYPE</id>
<targetType>TARGET_TYPE_MEM_PORT</targetType>
<description>
ARRAY[DIMM]
- Primary SDRAM Package Type.
+ Primary SDRAM Package Type (bits 1~0).
Decodes Byte 6.
This byte defines the primary set of SDRAMs.
Monolithic = SPD, Multi-load stack = DDP/QDP, Single-load stack = 3DS
@@ -230,6 +256,24 @@
</attribute>
<attribute>
+ <id>ATTR_MEM_EFF_PRIM_BUS_WIDTH</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ ARRAY[DIMM]
+ Primary bus with (bits 1~0).
+ Decodes Byte 13.
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint8</valueType>
+ <enum>
+ 8_BITS = 8, 16_BITS = 16, 32_BITS = 32, 64_BITS = 64
+ </enum>
+ <writeable/>
+ <array>2</array>
+ <mssAccessorName>prim_bus_width</mssAccessorName>
+ </attribute>
+
+ <attribute>
<id>ATTR_MEM_EFF_DRAM_PPR</id>
<targetType>TARGET_TYPE_MEM_PORT</targetType>
<description>
@@ -522,7 +566,7 @@
</attribute>
<attribute>
- <id>ATTR_MEM_EFF_NUM_RANKS_PER_DIMM</id>
+ <id>ATTR_MEM_EFF_LOGICAL_RANKS_PER_DIMM</id>
<targetType>TARGET_TYPE_MEM_PORT</targetType>
<description>
ARRAY[DIMM]
@@ -542,7 +586,21 @@
</enum>
<writeable/>
<array>2</array>
- <mssAccessorName>num_ranks_per_dimm</mssAccessorName>
+ <mssAccessorName>logical_ranks_per_dimm</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_MEM_3DS_HEIGHT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ Setting for 3DS stack. Calculated from logical_ranks / master_ranks
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint16</valueType>
+ <enum>PLANAR = 0, H2 = 2, H4 = 4, H8 = 8</enum>
+ <array>2</array>
+ <writeable/>
+ <mssAccessorName>3ds_height</mssAccessorName>
</attribute>
<attribute>
@@ -567,7 +625,8 @@
<description>
ARRAY[DIMM]
DRAM Manufacturer ID Code
- Decodes SPD Byte 350 and 351
+ Decodes SPD Byte 350 and 351 for ISDIMMs
+ Decodes SPD Byte 552 and 553 for DDIMMs
</description>
<enum>MICRON = 0x802C, SAMSUNG = 0x80CE, HYNIX = 0x80AD </enum>
<initToZero></initToZero>
@@ -578,6 +637,22 @@
</attribute>
<attribute>
+ <id>ATTR_MEM_EFF_DRAM_MODULE_HEIGHT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ ARRAY[DIMM]
+ DRAM Modlue Height
+ Decodes SPD Byte 193
+ </description>
+ <enum>1U = 0, 2U = 1, 4U = 2 </enum>
+ <initToZero></initToZero>
+ <valueType>uint8</valueType>
+ <writeable/>
+ <array>2</array>
+ <mssAccessorName>dram_module_height</mssAccessorName>
+ </attribute>
+
+ <attribute>
<id>ATTR_MEM_EFF_RCD_MFG_ID</id>
<targetType>TARGET_TYPE_MEM_PORT</targetType>
<description>
@@ -693,6 +768,18 @@
</attribute>
<attribute>
+ <id>ATTR_MEM_EFF_DRAM_MDS</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ Controls if the given target has an MDS (managed DRAM solution)
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint8</valueType>
+ <writeable/>
+ <mssAccessorName>dram_mds</mssAccessorName>
+ </attribute>
+
+ <attribute>
<id>ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM</id>
<targetType>TARGET_TYPE_MEM_PORT</targetType>
<description>
@@ -818,4 +905,16 @@
<mssAccessorName>volt_vpp</mssAccessorName>
</attribute>
+ <attribute>
+ <id>ATTR_MEM_EFF_SPD_REVISION</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ SPD Revision (SPD Byte 1)
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint8</valueType>
+ <writeable/>
+ <mssAccessorName>spd_revision</mssAccessorName>
+ </attribute>
+
</attributes>
diff --git a/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml b/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml
index 31ac9b4c0..49d4a17ed 100644
--- a/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml
+++ b/src/import/generic/procedures/xml/attribute_info/generic_memory_mrw_attributes.xml
@@ -251,7 +251,7 @@
<valueType>uint32</valueType>
<platInit/>
<mssUnits>c%</mssUnits>
- <default>0x00002328</default>
+ <default>0x00002710</default>
<initToZero/>
<mssAccessorName>mrw_max_dram_databus_util</mssAccessorName>
</attribute>
@@ -606,4 +606,159 @@
<mssAccessorName>mrw_supported_dram_width</mssAccessorName>
</attribute>
+ <attribute>
+ <id>ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ Machine Readable Workbook Thermal Memory Power Limit
+ Used to calculate throttles to meet the thermal power per DIMM limit
+ Per DIMM basis, uses first matching KEY entry
+ KEY (0-21): In order
+ DIMM_SIZE = bits 0-3,
+ DIMM_GEN = 4-5,
+ DIMM_TYPE = 6-8,
+ DIMM_WIDTH = 9-11,
+ DIMM_DENSITY = 12-14,
+ DIMM_STACK_TYPE = 15-16,
+ DRAM_MFGID = 17-19,
+ DIMM_HEIGHT = 20-21,
+ Bits 22-32: Not used
+ VALUE (bits 32-47) in cW: thermal power limit
+ DDIMM: Total OCMB+DRAM power limit per DDIMM
+ non-DDIMM: VMEM+VPP power limit per DIMM
+ </description>
+ <valueType>uint64</valueType>
+ <mssUnits>cW</mssUnits>
+ <default>0xfffffc0009c40000</default>
+ <array>25</array>
+ <platInit/>
+ <mssAccessorName>mrw_ocmb_thermal_memory_power_limit</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_MSS_MRW_OCMB_PWR_SLOPE</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ Machine Readable Workbook Power Curve Slope for DIMM
+ Used to calculate thermal throttles and port power
+ Per DIMM basis, uses first matching KEY entry
+ KEY (0-21): In order
+ DIMM_SIZE = bits 0-3,
+ DIMM_GEN = 4-5,
+ DIMM_TYPE = 6-8,
+ DIMM_WIDTH = 9-11,
+ DIMM_DENSITY = 12-14,
+ DIMM_STACK_TYPE = 15-16,
+ DRAM_MFGID = 17-19,
+ DIMM_HEIGHT = 20-21,
+ Bits 22-32: Not used
+ VALUE (bits 32-47) in cW/utilization: DIMM power slope
+ DDIMM: Total OCMB+DRAM power slope per DDIMM
+ non-DDIMM: VMEM+VPP power slope per DIMM
+ </description>
+ <valueType>uint64</valueType>
+ <mssUnits>cW</mssUnits>
+ <default>0xfffffc0004620000</default>
+ <array>50</array>
+ <platInit/>
+ <mssAccessorName>mrw_ocmb_pwr_slope</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_MSS_MRW_OCMB_PWR_INTERCEPT</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ Machine Readable Workbook Power Curve Intercept for DIMM
+ Used to calculate thermal throttles and port power
+ Per DIMM basis, uses first matching KEY entry
+ KEY (0-21): In order
+ DIMM_SIZE = bits 0-3,
+ DIMM_GEN = 4-5,
+ DIMM_TYPE = 6-8,
+ DIMM_WIDTH = 9-11,
+ DIMM_DENSITY = 12-14,
+ DIMM_STACK_TYPE = 15-16,
+ DRAM_MFGID = 17-19,
+ DIMM_HEIGHT = 20-21,
+ Bits 22-32: Not used
+ VALUE (bits 32-47) in cW/utilization: DIMM power intercept
+ DDIMM: Total OCMB+DRAM power intercept per DDIMM
+ non-DDIMM: VMEM+VPP power intercept per DIMM
+ </description>
+ <valueType>uint64</valueType>
+ <mssUnits>cW/utilization</mssUnits>
+ <default>0xfffffc0005260000</default>
+ <array>50</array>
+ <platInit/>
+ <mssAccessorName>mrw_ocmb_pwr_intercept</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ Machine Readable Workbook Current Curve Intercept and limit for DIMM
+ Used to calculate throttles to meet regulator current per DIMM limit
+ Per DIMM basis, uses first matching KEY entry
+ For DDIMM, use PMIC SW output that provides worst case throttling
+ KEY (0-21): In order
+ DIMM_SIZE = bits 0-3,
+ DIMM_GEN = 4-5,
+ DIMM_TYPE = 6-8,
+ DIMM_WIDTH = 9-11,
+ DIMM_DENSITY = 12-14,
+ DIMM_STACK_TYPE = 15-16,
+ DRAM_MFGID = 17-19,
+ DIMM_HEIGHT = 20-21,
+ Bits 22-32: Not used
+ VALUE (bits 32-39): Current limit (dA)
+ DDIMM: PMIC output current limit per DDIMM
+ non-DDIMM: VMEM regulator current limit per DIMM
+ VALUE (bits 40-51): Current slope (cA/utilization)
+ DDIMM: PMIC output current slope per DDIMM
+ non-DDIMM: VMEM regulator current slope per DIMM
+ VALUE (bits 52-63): Current intercept (cA)
+ DDIMM: PMIC output current intercept per DDIMM
+ non-DDIMM: VMEM regulator current intercept per DIMM
+ </description>
+ <valueType>uint64</valueType>
+ <mssUnits>dA, cA/utilization, cA</mssUnits>
+ <default>0xFFFFFC0064152094</default>
+ <array>25</array>
+ <platInit/>
+ <mssAccessorName>mrw_ocmb_current_curve_with_limit</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_MSS_MRW_SAFEMODE_DRAM_DATABUS_UTIL</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ Machine Readable Workbook value for safe mode dram data bus utilization in centi percent (c%).
+ Set to below optimum value/ rate.
+ On a per port basis
+ Also used for emergency mode throttle
+ Used to thermally protect the system in all supported environmental conditions when OCC is not functional
+ Consumer: thermal_init, initfile
+ Default to 2500 c%%
+ </description>
+ <valueType>uint32</valueType>
+ <default>0x000009C4</default>
+ <platInit/>
+ <initToZero/>
+ <mssAccessorName>mrw_safemode_dram_databus_util</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_MEM_PORT_POS_OF_FAIL_THROTTLE</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ This is the fapi position of the port that failed to calculate
+ memory throttles given the passed in watt target and or utilization
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint64</valueType>
+ <mssAccessorName>port_pos_of_fail_throttle</mssAccessorName>
+ <writeable/>
+ </attribute>
+
</attributes>
diff --git a/src/import/generic/procedures/xml/attribute_info/generic_memory_si_attributes.xml b/src/import/generic/procedures/xml/attribute_info/generic_memory_si_attributes.xml
index 1ec910f04..9ff21bdd1 100644
--- a/src/import/generic/procedures/xml/attribute_info/generic_memory_si_attributes.xml
+++ b/src/import/generic/procedures/xml/attribute_info/generic_memory_si_attributes.xml
@@ -106,7 +106,7 @@
<initToZero></initToZero>
<valueType>uint8</valueType>
<writeable/>
- <enum>OHM34 = 34, OHM48 = 48</enum>
+ <enum>DISABLE = 0, OHM34 = 34, OHM48 = 48</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_dram_drv_imp_dq_dqs</mssAccessorName>
<array>2 4</array>
@@ -140,7 +140,7 @@
<initToZero></initToZero>
<valueType>uint8</valueType>
<writeable/>
- <enum>DISABLE = 0, OHM34 = 34, OHM40 = 40, OHM48 = 48, OHM60 = 60, OHM80 = 80, OHM120 = 120, OHM240 = 240</enum>
+ <enum>DISABLE = 0, OHM34 = 34, OHM40 = 40, OHM60 = 60, OHM80 = 80, OHM120 = 120, OHM240 = 240</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_dram_rtt_nom</mssAccessorName>
<array>2 4</array>
@@ -172,42 +172,13 @@
<initToZero></initToZero>
<valueType>uint8</valueType>
<writeable/>
- <enum>DISABLE = 0, HIGHZ = 1, OHM80 = 80, OHM120 = 120, OHM240 = 240</enum>
+ <enum>DISABLE = 0, OHM80 = 80, OHM120 = 120, OHM240 = 240</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_dram_rtt_wr</mssAccessorName>
<array>2 4</array>
</attribute>
<attribute>
- <id>ATTR_MEM_SI_VREF_DQ_TRAIN_VALUE</id>
- <targetType>TARGET_TYPE_MEM_PORT</targetType>
- <description>
- ARRAY[DIMM][RANK]
- vrefdq_train value. This is for DDR4 MRS6.
- </description>
- <initToZero></initToZero>
- <valueType>uint8</valueType>
- <writeable/>
- <array>2 4</array>
- <mssAccessorName>si_vref_dq_train_value</mssAccessorName>
- </attribute>
-
- <attribute>
- <id>ATTR_MEM_SI_VREF_DQ_TRAIN_RANGE</id>
- <targetType>TARGET_TYPE_MEM_PORT</targetType>
- <description>
- ARRAY[DIMM][RANK]
- vrefdq_train range. This is for DDR4 MRS6.
- </description>
- <initToZero></initToZero>
- <valueType>uint8</valueType>
- <enum>RANGE1 = 0, RANGE2 = 1</enum>
- <writeable/>
- <array>2 4</array>
- <mssAccessorName>si_vref_dq_train_range</mssAccessorName>
- </attribute>
-
- <attribute>
<id>ATTR_MEM_SI_GEARDOWN_MODE</id>
<targetType>TARGET_TYPE_MEM_PORT</targetType>
<description>
@@ -278,7 +249,7 @@
<initToZero></initToZero>
<valueType>uint8</valueType>
<writeable/>
- <enum>DISABLE = 0</enum>
+ <enum>DISABLE = 0, OHM_20 = 20, OHM_24 = 24, OHM_30 = 30, OHM_40 = 40, OHM_60 = 60, OHM_120 = 120</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_mc_drv_imp_clk</mssAccessorName>
<array>2 4</array>
@@ -294,7 +265,7 @@
<initToZero></initToZero>
<valueType>uint8</valueType>
<writeable/>
- <enum>DISABLE = 0</enum>
+ <enum>DISABLE = 0, OHM_20 = 20, OHM_24 = 24, OHM_30 = 30, OHM_40 = 40, OHM_60 = 60, OHM_120 = 120</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_mc_drv_imp_cmd_addr</mssAccessorName>
<array>2 4</array>
@@ -340,9 +311,11 @@
Memory Controller side Drive Impedance Pull Down for Data and Data Strobe Lines in Ohms.
</description>
<initToZero></initToZero>
- <valueType>uint8</valueType>
+ <valueType>uint16</valueType>
<writeable/>
- <enum>DISABLE = 0</enum>
+ <enum>DISABLE = 0, OHM_28 = 28, OHM_30 = 30, OHM_32 = 32, OHM_34 = 34, OHM_36 = 36, OHM_40 = 40, OHM_43 = 43,
+ OHM_48 = 48, OHM_53 = 53, OHM_60 = 60, OHM_68 = 68, OHM_80 = 80, OHM_96 = 96, OHM_120 = 120, OHM_160 = 160,
+ OHM_240 = 240, OHM_480 = 480</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_mc_drv_imp_dq_dqs_pull_down</mssAccessorName>
<array>2 4</array>
@@ -356,9 +329,11 @@
Memory Controller side Drive Impedance Pull Up for Data and Data Strobe Lines in Ohms.
</description>
<initToZero></initToZero>
- <valueType>uint8</valueType>
+ <valueType>uint16</valueType>
<writeable/>
- <enum>DISABLE = 0</enum>
+ <enum>DISABLE = 0, OHM_28 = 28, OHM_30 = 30, OHM_32 = 32, OHM_34 = 34, OHM_36 = 36, OHM_40 = 40, OHM_43 = 43,
+ OHM_48 = 48, OHM_53 = 53, OHM_60 = 60, OHM_68 = 68, OHM_80 = 80, OHM_96 = 96, OHM_120 = 120, OHM_160 = 160,
+ OHM_240 = 240, OHM_480 = 480</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_mc_drv_imp_dq_dqs_pull_up</mssAccessorName>
<array>2 4</array>
@@ -453,7 +428,7 @@
<initToZero></initToZero>
<valueType>uint8</valueType>
<writeable/>
- <enum>DISABLE = 0</enum>
+ <enum>DISABLE = 0, OHM_40 = 40, OHM_48 = 48, OHM_60 = 60, OHM_80 = 80, OHM_120 = 120, OHM_240 = 240</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_mc_rcv_imp_alert_n</mssAccessorName>
<array>2 4</array>
@@ -469,7 +444,7 @@
<initToZero></initToZero>
<valueType>uint8</valueType>
<writeable/>
- <enum>DISABLE = 0</enum>
+ <enum>DISABLE = 0, OHM_40 = 40, OHM_60 = 60, OHM_80 = 80, OHM_120 = 120, OHM_240 = 240</enum>
<mssUnits>ohm</mssUnits>
<mssAccessorName>si_mc_rcv_imp_dq_dqs</mssAccessorName>
<array>2 4</array>
@@ -483,6 +458,7 @@
READ, On Die Termination triggering bitmap. Use bitmap to determine which ODT to fire for the designated rank.
The bits in 8 bit field are
[DIMM0 ODT0][DIMM0 ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
+ For Explorer: Only bits 0,1,4,5 are used. They correspond to A0 A1 -- -- B0 B1 -- --
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
@@ -499,6 +475,7 @@
WRITE, On Die Termination triggering bitmap. Use bitmap to determine which ODT to fire for the designated rank.
The bits in 8 bit field are
[DIMM0 ODT0][DIMM0 ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
+ For Explorer: Only bits 0,1,4,5 are used. They correspond to A0 A1 -- -- B0 B1 -- --
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
diff --git a/src/import/generic/procedures/xml/error_info/generic_error.xml b/src/import/generic/procedures/xml/error_info/generic_error.xml
index 7b3f1e894..d25d1885b 100644
--- a/src/import/generic/procedures/xml/error_info/generic_error.xml
+++ b/src/import/generic/procedures/xml/error_info/generic_error.xml
@@ -68,6 +68,47 @@
</hwpError>
<hwpError>
+ <rc>RC_MSS_FAILED_SPD_REVISION_FALLBACK</rc>
+ <description>
+ Unable to fall back SPD decoder to the highest decoded
+ revision. Most likely a programming error.
+ </description>
+ <ffdc>FAILED_REVISION</ffdc>
+ <ffdc>FUNCTION_CODE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_FAILED_TO_FIND_TRFC</rc>
+ <description>
+ Unable to find tRFC (ps) from map with SDRAM density key
+ </description>
+ <ffdc>SDRAM_DENSITY</ffdc>
+ <ffdc>REFRESH_MODE</ffdc>
+ <callout>
+ <target>DIMM_TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>DIMM_TARGET</target>
+ </deconfigure>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
<rc>RC_MSS_FREQ_CL_EXCEEDS_TAA_MAX</rc>
<description>
Calculated Cas Latency exceeds JEDEC value for TAA Max
@@ -129,6 +170,17 @@
</hwpError>
<hwpError>
+ <rc>RC_MSS_FREQ_INDEX_TOO_LARGE</rc>
+ <description>Error calculating the index into max_freq array</description>
+ <ffdc>INDEX</ffdc>
+ <ffdc>NUM_MAX_FREQS</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
<rc>RC_MSS_FREQ_INVALID_CALCULATED_TCK</rc>
<description>
Invalid value clock period (less than equal 0).
@@ -204,6 +256,18 @@
</callout>
</hwpError>
+ <hwpError>
+ <rc>RC_MSS_INVALID_CAST_CALC_NCK</rc>
+ <description>Invalid cast or calculation for calc_nck</description>
+ <ffdc>TIMING_PS</ffdc>
+ <ffdc>NCK_NS</ffdc>
+ <ffdc>CORRECTION_FACTOR</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
<hwpError>
<rc>RC_MSS_INVALID_CLOCK_PERIOD</rc>
<description>
@@ -216,17 +280,170 @@
</callout>
</hwpError>
-<hwpError>
- <rc>RC_MSS_INVALID_FREQUENCY</rc>
- <description>
- An invalid frequency was passed to frequency to clock period
- </description>
- <ffdc>FREQ</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
-</hwpError>
+ <hwpError>
+ <rc>RC_MSS_INVALID_DB_MDQ_DRIVE_STRENGTH</rc>
+ <description>
+ Bad SPD data for bytes 145 - 147.
+ Reserved settings for data buffer MDQ drive strength received.
+ This could be code problem (decoding) or bad SPD.
+ </description>
+ <ffdc>DATA_RATE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_DIMM_SPEED</rc>
+ <description>
+ Invalid DIMM speed received. Possibly a programming error.
+ </description>
+ <ffdc>DIMM_SPEED</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_DIMM_TYPE</rc>
+ <description>
+ Received a DIMM type unsupported by the SPD decoder factory
+ </description>
+ <ffdc>DIMM_TYPE</ffdc>
+ <ffdc>FUNCTION</ffdc>
+ <callout>
+ <procedure>MEMORY_PLUGGING_ERROR</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <target>DIMM_TARGET</target>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>DIMM_TARGET</target>
+ </deconfigure>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_DRAM_GEN</rc>
+ <description>
+ Received a DRAM gen unsupported by the SPD decoder factory
+ </description>
+ <ffdc>DRAM_GEN</ffdc>
+ <ffdc>FUNCTION</ffdc>
+ <callout>
+ <procedure>MEMORY_PLUGGING_ERROR</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <target>DIMM_TARGET</target>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>DIMM_TARGET</target>
+ </deconfigure>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_FREQ_PASSED_IN</rc>
+ <description>
+ An invalid Freq value has been set
+ </description>
+ <ffdc>FREQ</ffdc>
+ <ffdc>FUNCTION</ffdc>
+ <ffdc>DIMM_TARGET</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_FREQUENCY</rc>
+ <description>
+ An invalid frequency was passed to frequency to clock period
+ </description>
+ <ffdc>FREQ</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_FREQ_LIST_PASSED</rc>
+ <description>
+ Wrong size vector passed into frequency scoreboard function
+ </description>
+ <ffdc>SIZE</ffdc>
+ <ffdc>EXPECTED</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_FINE_REFRESH_MODE</rc>
+ <description>
+ Invalid fine refresh mode received from the mrw
+ </description>
+ <ffdc>FINE_REF_MODE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_HYBRID_MODULE</rc>
+ <description>
+ Received an invalid or unsupported hybrid media (SPD byte 3, bits [6:4])
+ for a specified hybrid modue (SPD byte 3, bit [7])
+ </description>
+ <ffdc>HYBRID</ffdc>
+ <ffdc>HYBRID_MEDIA</ffdc>
+ <ffdc>FUNCTION</ffdc>
+ <callout>
+ <procedure>MEMORY_PLUGGING_ERROR</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>LOW</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
<hwpError>
<rc>RC_MSS_INVALID_PORT_INDEX_PASSED</rc>
@@ -240,6 +457,89 @@
</hwpError>
<hwpError>
+ <rc>RC_MSS_INVALID_RANK</rc>
+ <description>
+ Invalid rank passed into function
+ </description>
+ <ffdc>FUNCTION</ffdc>
+ <ffdc>RANK</ffdc>
+ <ffdc>PORT_TARGET</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_REFRESH_RATE_REQUEST</rc>
+ <description>
+ Invalid refresh request rate received.
+ Possibly due to bad MRW setting for ATTR_MSS_MRW_REFRESH_RATE_REQUEST.
+ </description>
+ <ffdc>REFRESH_RATE_REQUEST</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_SPD_PARAMETER_RECEIVED</rc>
+ <description>
+ Unable to fall back SPD decoder to the highest decoded
+ revision. Most likely a programming error.
+ </description>
+ <ffdc>SPD_PARAM</ffdc>
+ <ffdc>FUNCTION_CODE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_SPD_RANK</rc>
+ <description>
+ Invalid rank passed into attribute engine.
+ May be due to problem in SPD.
+ </description>
+ <ffdc>FUNCTION</ffdc>
+ <ffdc>RANK</ffdc>
+ <ffdc>TARGET</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_SPD_RESERVED_BITS</rc>
+ <description>
+ Invalid SPD reserved bits received.
+ This could be code problem (decoding) or bad SPD.
+ </description>
+ <ffdc>FUNCTION_CODE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
<rc>RC_MSS_INVALID_TIMING_VALUE</rc>
<description>Invalid value calculated for timing value based on MTB and FTB from SPD.</description>
<ffdc>VALUE</ffdc>
@@ -256,6 +556,36 @@
</gard>
</hwpError>
+ <hwpError>
+ <rc>RC_MSS_INVALID_VPD_FREQ_LIST_PASSED</rc>
+ <description>
+ Wrong size vector passed into limit_freq_by_vpd function
+ </description>
+ <ffdc>SIZE</ffdc>
+ <ffdc>EXPECTED</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_VPD_KEYWORD_MAX</rc>
+ <description>
+ VPD keyword is too big for space allocated for it.
+ </description>
+ <ffdc>MAX</ffdc>
+ <ffdc>ACTUAL</ffdc>
+ <ffdc>KEYWORD</ffdc>
+ <callout>
+ <hw>
+ <hwid>VPD_PART</hwid>
+ <refTarget>VPD_TARGET</refTarget>
+ </hw>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
<hwpError>
<rc>RC_MSS_LOOKUP_FAILED</rc>
<description>
@@ -274,6 +604,39 @@
</hwpError>
<hwpError>
+ <rc>RC_MSS_MEMDIAGS_NO_MCBIST_SUBTESTS</rc>
+ <description>Attempt to run an MCBIST program with no subtests</description>
+ <ffdc>MC_TARGET</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_MCBIST_EXCEEDED_MAX_SUBTESTS</rc>
+ <description>Attempt to run an MCBIST program exceeding the max number of subtests (32)</description>
+ <ffdc>MC_TARGET</ffdc>
+ <ffdc>NUMBER_OF_SUBTESTS</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_MCBIST_INCORRECT_PATTERN_LENGTH</rc>
+ <description>MCBIST pattern has an incorrect length</description>
+ <ffdc>TARGET</ffdc>
+ <ffdc>ACTUAL</ffdc>
+ <ffdc>EXPECTED</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
<rc>RC_MSS_VOLT_WRONG_NUMBER_OF_VOLTAGES</rc>
<description>Incorrect number of voltages supplied to set_voltage_attributes function</description>
<ffdc>VOLT_TARGET</ffdc>
@@ -310,18 +673,31 @@
<description>
When considering the frequencies in the MRW and the max supported
frequencies based on DIMM config, the indicated port's DIMM do not support
- the frequency of the majority of other ports' DIMM, so it will be deconfigured
+ the frequency of the majority of other ports' DIMM in the frequency domain.
+ DIMM on the offending port will be deconfigured so the IPL can continue.
+ All DIMM in the offending port's frequency domain will be marked as
+ Hardware Callout.
</description>
<ffdc>FREQ_TARGET</ffdc>
<ffdc>PORT_TARGET</ffdc>
<ffdc>FREQUENCY</ffdc>
- <callout>
+ <callout>
+ <procedure>MEMORY_PLUGGING_ERROR</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
<childTargets>
- <parent>PORT_TARGET</parent>
+ <parent>FREQ_TARGET</parent>
<childType>TARGET_TYPE_DIMM</childType>
</childTargets>
<priority>MEDIUM</priority>
</callout>
+ <deconfigure>
+ <childTargets>
+ <parent>PORT_TARGET</parent>
+ <childType>TARGET_TYPE_DIMM</childType>
+ </childTargets>
+ </deconfigure>
</hwpError>
<hwpError>
@@ -376,6 +752,7 @@
Settings are incorrect for received data.
This could be code problem (decoding) or bad data.
</description>
+ <ffdc>TARGET</ffdc>
<ffdc>VALUE</ffdc>
<ffdc>BYTE</ffdc>
<ffdc>FFDC_CODE</ffdc>
@@ -392,4 +769,516 @@
</deconfigure>
</hwpError>
+ <hwpError>
+ <rc>RC_MSS_ZERO_FREQ_OR_SIZE</rc>
+ <description>
+ An zero memory frequency was passed to calculate min cmd gap
+ </description>
+ <ffdc>FREQ</ffdc>
+ <ffdc>SIZE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_MEMDIAGS_INVALID_PATTERN_INDEX</rc>
+ <description>An invalid pattern index was passed to the pattern loader</description>
+ <ffdc>INDEX</ffdc>
+ <ffdc>MC_TYPE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_MCBIST_PROGRAM_TOO_BIG</rc>
+ <description>MCBIST program larger than currently supported size</description>
+ <ffdc>PROGRAM_LENGTH</ffdc>
+ <ffdc>TARGET</ffdc>
+ <ffdc>MC_TYPE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_MCBIST_INVALID_ADDRESS_PAIR_INDEX</rc>
+ <description>An invalid address pair index</description>
+ <ffdc>INDEX</ffdc>
+ <ffdc>MC_TYPE</ffdc>
+ <ffdc>TARGET</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_POWER_INTERCEPT_NOT_SET</rc>
+ <description>
+ The attribute ATTR_MSS_TOTAL_POWER_INTERCEPT was not set and equals 0
+ </description>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_POWER_SLOPE_NOT_SET</rc>
+ <description>
+ The attribute ATTR_MSS_TOTAL_POWER_INTERCEPT was not set and equals 0
+ </description>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_NO_DATABUS_UTILIZATION</rc>
+ <description>
+ There are 2 DIMMS on the port but both have 0 databus utilization
+ </description>
+ <ffdc>PORT_DATABUS_UTIL</ffdc>
+ <ffdc>DIMM_COUNT</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_CALC_POWER_CURVE_DIVIDE_BY_ZERO</rc>
+ <description>
+ Denominator equals 0
+ </description>
+ <ffdc>PORT_DATABUS_UTIL</ffdc>
+ <ffdc>UTIL_CONVERSION</ffdc>
+ <ffdc>IDLE_UTIL</ffdc>
+ <ffdc>RESULT</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_NO_PORT_POWER_LIMIT</rc>
+ <description>
+ Got 0 when calculating port power limit.
+ Either no dimms or attribute MEM_WATT_TARGET wasn't set
+ </description>
+ <ffdc>COUNT_DIMMS</ffdc>
+ <ffdc>PORT_POWER_LIMIT</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_NO_PORT_POWER</rc>
+ <description>
+ Got 0 when calculating port power limits using the DIMMs databus utilization
+ </description>
+ <ffdc>COUNT_DIMMS</ffdc>
+ <ffdc>MAX_UTILIZATION_DIMM_0</ffdc>
+ <ffdc>MAX_UTILIZATION_DIMM_1</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_M_DRAM_CLOCKS_EQUALS_ZERO</rc>
+ <description>
+ ATTR_MSS_MRW_MEM_M_DRAM_CLOCKS was not set and equals zero
+ </description>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_MAX_FREQ_ATTR_SIZE_CHANGED</rc>
+ <description>
+ Number of entries for MSS_MRW_MAX_FREQ attribute from VPD has changed without updating the code
+ Asserted because direct accesses to array
+ </description>
+ <ffdc>ACTUAL_SIZE</ffdc>
+ <ffdc>SUPPOSED_SIZE</ffdc>
+ <ffdc>PORT_TARGET</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_CALC_PORT_POWER_EXCEEDS_MAX</rc>
+ <description>
+ The calculated port power from equalizing throttles exceeds the maximum allowed power
+ </description>
+ <ffdc>CALCULATED_PORT_POWER</ffdc>
+ <ffdc>MAX_POWER_ALLOWED</ffdc>
+ <ffdc>PORT_POS</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <childTargets>
+ <parent>PORT_TARGET</parent>
+ <childType>TARGET_TYPE_DIMM</childType>
+ </childTargets>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <childTargets>
+ <parent>PORT_TARGET</parent>
+ <childType>TARGET_TYPE_DIMM</childType>
+ </childTargets>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_SPD_REV_ENCODING_LEVEL_NOT_SUPPORTED</rc>
+ <description>
+ SPD revision on byte 1 (bits 7~4) has a unsupported encoding level
+ that is greater than the largest decoded SPD decoder. There is
+ no backward compatible revision to fallback to. This could be
+ bad SPD or a programming error.
+ </description>
+ <ffdc>ENCODING_LEVEL</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_SPD_TIMING_FAIL</rc>
+ <description>
+ Timing SPD parameter failed to meet JEDEC SPD timing
+ bounds. FUNCTION_CODE ffdc field encodes which timing param.
+ </description>
+ <ffdc>FAILED_REVISION</ffdc>
+ <ffdc>FUNCTION_CODE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <callout>
+ <target>TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_TOO_MANY_DIMMS_ON_PORT</rc>
+ <description>There seem to be too many dimms on the port</description>
+ <ffdc>DIMM_COUNT</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <childTargets>
+ <parent>PORT_TARGET</parent>
+ <childType>TARGET_TYPE_DIMM</childType>
+ </childTargets>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_SLOT_UTIL_EXCEEDS_PORT</rc>
+ <description>
+ The memory throttle per slot (DIMM) exceeds the allowed throttle for the port
+ </description>
+ <ffdc>SLOT_UTIL</ffdc>
+ <ffdc>PORT_UTIL</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_OUTPUT_OVERFLOW_CALC_UTIL</rc>
+ <description>
+ Type of output variable is not large enough for the calculations
+ </description>
+ <ffdc>RESULT</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_POWER_THERMAL_DECODE_ERROR</rc>
+ <description>
+ There was no match or value found in decoding the power thermal attributes
+ </description>
+ <ffdc>DIMM_TARGET</ffdc>
+ <ffdc>ATTR</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_MRW_SAFEMODE_UTIL_THROTTLE_NOT_SUPPORTED</rc>
+ <description>
+ The MRW safemode utilization that is less than the minimum utilization supported. Check ATTR_MSS_MRW_SAFEMODE_DRAM_DATABUS_UTIL.
+ </description>
+ <ffdc>MRW_SAFEMODE_UTIL</ffdc>
+ <ffdc>MIN_UTIL_VALUE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_NO_POWER_THERMAL_ATTR_FOUND</rc>
+ <description>
+ There was no match or value found in decoding the power thermal attributes
+ </description>
+ <ffdc>GENERATED_KEY</ffdc>
+ <ffdc>FUNCTION</ffdc>
+ <ffdc>DIMM_TARGET</ffdc>
+ <ffdc>SIZE</ffdc>
+ <ffdc>DRAM_GEN</ffdc>
+ <ffdc>DIMM_TYPE</ffdc>
+ <ffdc>DRAM_WIDTH</ffdc>
+ <ffdc>DRAM_DENSITY</ffdc>
+ <ffdc>STACK_TYPE</ffdc>
+ <ffdc>MFGID</ffdc>
+ <ffdc>MODULE_HEIGHT</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_POWER_THERMAL_ENCODE_ERROR</rc>
+ <description>
+ There was no match or value found in encoding the power thermal attributes
+ </description>
+ <ffdc>DIMM_TARGET</ffdc>
+ <ffdc>ATTR</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_POWER_THERMAL_ATTR_VECTORS_INCORRECT</rc>
+ <description>
+ The attributes vectors size is incorrect for find_xxx functions
+ </description>
+ <ffdc>FUNCTION</ffdc>
+ <ffdc>INPUT_SIZE</ffdc>
+ <ffdc>EXPECTED_SIZE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_POWER_THERMAL_DIMM_INDEX_OUT_OF_BOUND</rc>
+ <description>
+ The dimm index is out of bound for the port
+ </description>
+ <ffdc>INPUT_SIZE</ffdc>
+ <ffdc>MAX_SIZE</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_TOO_MANY_PRIMARY_RANKS_ON_DIMM</rc>
+ <description>
+ Too many primary ranks were seen on the dimm according
+ to the call to master_ranks_per_dimm</description>
+ <ffdc>RANK_COUNT</ffdc>
+ <callout>
+ <target>DIMM_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>DIMM_TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_TOO_MANY_PRIMARY_RANKS_ON_PORT</rc>
+ <description>
+ Too many primary ranks were seen on the port according
+ to the call to master_ranks_per_dimm</description>
+ <callout>
+ <target>PORT_TARGET</target>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>PORT_TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_RANK_OUT_OF_RANGE</rc>
+ <description>
+ The rank provided to the rank::info constructor exceeded
+ the maximum rank for the MC
+ </description>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ <ffdc>TARGET</ffdc>
+ <ffdc>RANK</ffdc>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_GALOIS_TO_SYMBOL</rc>
+ <description> An invalid galois code was found</description>
+ <ffdc>GALOIS</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_SYMBOL_FOR_GALOIS</rc>
+ <description> An invalid symbol was passed to symbol_to_galois</description>
+ <ffdc>SYMBOL</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_DQ_TO_SYMBOL</rc>
+ <description> An invalid DQ bit index received to map to Galois symbol</description>
+ <ffdc>DQ</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_SYMBOL_TO_DQ</rc>
+ <description> An invalid symbol received to map to DQ bit index</description>
+ <ffdc>SYMBOL</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_RANK_PASSED</rc>
+ <description> An invalid rank was passed to ecc::read function</description>
+ <ffdc>RANK</ffdc>
+ <ffdc>FUNCTION</ffdc>
+ <ffdc>TARGET</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_INDEX_PASSED</rc>
+ <description> An invalid index was passed to MODAL_SYMBOL_COUNT function</description>
+ <ffdc>INDEX</ffdc>
+ <ffdc>FUNCTION</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_DRAM_WIDTH</rc>
+ <description>
+ Code only supports x4 and x8 drams at this time
+ </description>
+ <ffdc>DRAM_WIDTH</ffdc>
+ <callout>
+ <procedure>MEMORY_PLUGGING_ERROR</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <target>DIMM_TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>DIMM_TARGET</target>
+ </deconfigure>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_INVALID_PAGE_SIZE</rc>
+ <description>
+ Invalid page size
+ </description>
+ <ffdc>DRAM_WIDTH</ffdc>
+ <callout>
+ <procedure>MEMORY_PLUGGING_ERROR</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <target>DIMM_TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <target>DIMM_TARGET</target>
+ </deconfigure>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
+
</hwpErrors>
OpenPOWER on IntegriCloud