summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2019-02-27 13:58:49 -0600
committerChristian R. Geddes <crgeddes@us.ibm.com>2019-03-20 09:36:15 -0500
commite5a493e300da10cd6fe39ecb2e614d63dd11b9fb (patch)
treeb6a1b87872f58946999316a35dd70d604cb00a07
parent6d28e5b524f23fb473a6eff52b37f08fbafaf641 (diff)
downloadtalos-hostboot-e5a493e300da10cd6fe39ecb2e614d63dd11b9fb.tar.gz
talos-hostboot-e5a493e300da10cd6fe39ecb2e614d63dd11b9fb.zip
Add attribute engine algorithm for eff_config and pre_eff_config
Change-Id: I8498c143109fa1d1a2c9ad5492476e72f51ba509 Original-Change-Id: I2c89e6da17511462afbc661680d19df18a4708f4 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72962 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/74689 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H40
-rw-r--r--src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C68
-rw-r--r--src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.mk2
-rw-r--r--src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C29
-rw-r--r--src/import/generic/memory/lib/data_engine/data_engine.H217
-rw-r--r--src/import/generic/memory/lib/data_engine/data_engine_traits_def.H94
-rw-r--r--src/import/generic/memory/lib/data_engine/data_engine_utils.H334
-rw-r--r--src/import/generic/memory/lib/data_engine/p9a/p9a_data_init_traits.H444
-rw-r--r--src/import/generic/memory/lib/data_engine/pre_data_init.H1
-rw-r--r--src/import/generic/memory/lib/mss_generic_attribute_getters.H65
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H4
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/ddr4/efd_ddr4_custom_microchip_decoder.H6
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/efd_decoder.H19
-rw-r--r--src/import/generic/memory/lib/spd/ddimm/efd_factory.H8
-rw-r--r--src/import/generic/procedures/xml/attribute_info/generic_memory_eff_attributes.xml16
-rw-r--r--src/import/generic/procedures/xml/attribute_info/generic_memory_si_attributes.xml8
16 files changed, 1314 insertions, 41 deletions
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H
index 7b394b7aa..8d8944890 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/shared/exp_consts.H
@@ -33,8 +33,8 @@
// *HWP Level: 2
// *HWP Consumed by: CI
-#ifndef EXP_CONSTS_H
-#define EXP_CONSTS_H
+#ifndef MSS_EXP_CONSTS_H
+#define MSS_EXP_CONSTS_H
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
@@ -49,6 +49,30 @@ namespace exp
constexpr uint32_t OCMB_ADDR_SHIFT = 3;
///
+/// @brief enum list of explorer eff attributes to set
+///
+enum attr_eff_engine_fields
+{
+ // Template recursive base case
+ ATTR_EFF_BASE_CASE = 0,
+
+ // Attrs to set
+ BYTE_ENABLES = 1,
+ NIBBLE_ENABLES = 2,
+ SPD_TAA_MIN = 3,
+ FOUR_RANK_MODE = 4,
+ DDP_COMPATIBILITY = 5,
+ TSV_8H_SUPPORT = 6,
+ PSTATES = 7,
+ MRAM_SUPPORT = 8,
+ HEIGHT_3DS = 9,
+ SPD_CL_SUPPORTED = 10,
+
+ // Dispatcher set to last enum value
+ ATTR_EFF_DISPATCHER = SPD_CL_SUPPORTED,
+};
+
+///
/// @brief common explorer sizes
///
enum sizes
@@ -66,6 +90,18 @@ enum ffdc_codes
EXP_I2C_SET_FIELD = 0x0001,
READ_HOST_FW_RESPONSE_STRUCT = 0x0003,
READ_SENSOR_CACHE_STRUCT = 0x0004,
+
+ SET_BYTE_ENABLES = 0x1041,
+ SET_NIBBLE_ENABLES = 0x1042,
+ SET_TAA_MIN = 0x1043,
+ SET_FOUR_RANK_MODE = 0x1044,
+ SET_DDP_COMPATIBILITY = 0x1045,
+ SET_TSV_8H_SUPPORT = 0x1046,
+ SET_VREF_DQ_TRAIN_RANGE = 0x1047,
+ SET_PSTATES = 0x1048,
+ SET_MRAM_SUPPORT = 0x1049,
+ SET_3DS_HEIGHT = 0x1050,
+ SET_SPD_CL_SUPPORTED = 0x1051,
};
namespace i2c
diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C
index cfa7b80b3..8a1e0a877 100644
--- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C
+++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C
@@ -34,8 +34,14 @@
// *HWP Consumed by: FSP:HB
// fapi2
+#include <fapi2.H>
#include <p9a_mss_eff_config.H>
-
+#include <generic/memory/lib/data_engine/data_engine.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/spd/ddimm/efd_factory.H>
+#include <vpd_access.H>
+#include <mss_generic_attribute_getters.H>
+#include <lib/eff_config/explorer_attr_engine_traits.H>
///
/// @brief Configure the attributes for each controller
@@ -44,5 +50,63 @@
///
fapi2::ReturnCode p9a_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target )
{
- return fapi2::FAPI2_RC_SUCCESS;
+ // Workaround until DIMM level attrs work
+ uint8_t l_ranks[mss::exp::MAX_DIMM_PER_PORT] = {};
+
+ // Get EFD size - should only need to do it once
+ const auto l_ocmb = mss::find_target<fapi2::TARGET_TYPE_OCMB_CHIP>(i_target);
+ fapi2::MemVpdData_t l_vpd_type(fapi2::EFD);
+ fapi2::VPDInfo<fapi2::TARGET_TYPE_OCMB_CHIP> l_vpd_info(l_vpd_type);
+ FAPI_TRY( fapi2::getVPD(l_ocmb, l_vpd_info, nullptr) );
+
+ FAPI_TRY( mss::attr::get_num_master_ranks_per_dimm(i_target, l_ranks) );
+
+ for(const auto& dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
+ {
+ uint8_t l_dimm_index = 0;
+ uint64_t l_freq = 0;
+ FAPI_TRY( mss::attr::get_freq(mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(dimm), l_freq) );
+
+ // Quick hack to get the index until DIMM level attrs work
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_REL_POS, dimm, l_dimm_index) );
+
+ for( auto rank = 0; rank < l_ranks[l_dimm_index]; ++rank )
+ {
+ std::shared_ptr<mss::efd::base_decoder> l_efd_data;
+
+ // Get EFD data
+ l_vpd_info.iv_rank = rank;
+ l_vpd_info.iv_omi_freq_mhz = l_freq;
+ std::vector<uint8_t> l_vpd_raw (l_vpd_info.iv_size, 0);
+ FAPI_TRY( fapi2::getVPD(l_ocmb, l_vpd_info, l_vpd_raw.data()) );
+
+ // Instantiate EFD decoder
+ FAPI_TRY( mss::efd::factory(l_ocmb, l_vpd_raw, l_vpd_info.iv_rank, l_efd_data) );
+
+ // Set up SI ATTRS
+ FAPI_TRY( mss::attr_si_engine<mss::attr_si_engine_fields>::set(l_efd_data) );
+ }
+
+ {
+ std::vector<uint8_t> l_raw_spd;
+ FAPI_TRY(mss::spd::get_raw_data(dimm, l_raw_spd));
+ {
+ // Gets the SPD facade
+ fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS);
+ mss::spd::facade l_spd_decoder(dimm, 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(dimm) );
+
+ // Set up generic SPD ATTRS
+ FAPI_TRY( mss::attr_eff_engine<mss::attr_eff_engine_fields>::set(l_spd_decoder) );
+
+ // Set up explorer SPD ATTRS
+ FAPI_TRY( mss::attr_eff_engine<mss::exp::attr_eff_engine_fields>::set(l_spd_decoder) );
+ }
+ }
+ }// dimm
+
+fapi_try_exit:
+ return fapi2::current_err;
}
diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.mk b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.mk
index 94114e779..65e376f98 100644
--- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.mk
+++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.mk
@@ -27,5 +27,5 @@
-include 00p9a_common.mk
PROCEDURE=p9a_mss_eff_config
-$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE)))
+$(eval $(call ADD_P9A_MEMORY_INCDIRS,$(PROCEDURE)))
$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C
index f0a06de0b..7591689e2 100644
--- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C
+++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C
@@ -33,8 +33,11 @@
// *HWP Level: 1
// *HWP Consumed by: FSP:HB
-// fapi2
#include <p9a_mss_freq.H>
+#include <generic/memory/lib/data_engine/p9a/p9a_data_init_traits.H>
+#include <generic/memory/lib/data_engine/data_engine.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/spd/spd_facade.H>
///
/// @brief Calculate and save off DIMM frequencies
@@ -43,5 +46,27 @@
///
fapi2::ReturnCode p9a_mss_freq( const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target )
{
- return fapi2::FAPI2_RC_SUCCESS;
+ // We will first set pre-eff_config attribes
+ 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) );
+
+ FAPI_TRY( mss::attr_eff_engine<mss::pre_data_init_fields>::set(l_spd_decoder) );
+ }
+
+ // TK - Remove hard-code FREQ -- Should we have enums? Louis problem now
+ uint64_t HARDCODE_FREQ_LOUIS_REMOVE = 25600;
+ FAPI_TRY( mss::attr::set_freq(i_target, HARDCODE_FREQ_LOUIS_REMOVE) );
+ }// dimm
+
+fapi_try_exit:
+ return fapi2::current_err;
}
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 471390306..6a7cbb437 100644
--- a/src/import/generic/memory/lib/data_engine/data_engine.H
+++ b/src/import/generic/memory/lib/data_engine/data_engine.H
@@ -22,3 +22,220 @@
/* 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: HB:CI
+
+#ifndef _MSS_GEN_DATA_ENGINE_H_
+#define _MSS_GEN_DATA_ENGINE_H_
+
+#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)
+{
+ 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>
+///
+template < typename ET, typename TT = attrEnumTraits<ET> >
+struct attr_si_engine
+{
+ 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
+ /// @return FAPI2_RC_SUCCESS iff ok
+ ///
+ static fapi2::ReturnCode set(const std::shared_ptr<efd::base_decoder>& i_efd_data)
+ {
+ return attr_eng_t::set(i_efd_data);
+ }
+};
+
+///
+/// @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)>;
+
+ ///
+ /// @brief Sets attr_si_engine_fields
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_spd_data EFD data
+ /// @return FAPI2_RC_SUCCESS iff ok
+ ///
+ static fapi2::ReturnCode set(const mss::spd::facade& i_spd_data)
+ {
+ return attr_eng_t::set(i_spd_data);
+ }
+};
+
+}// 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 37fb596b4..4a802bd46 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
@@ -47,12 +47,67 @@ namespace mss
///
enum pre_data_init_fields
{
- DIMM_TYPE,
- DRAM_GEN,
- HYBRID,
- HYBRID_MEDIA,
- MRANKS,
- DIMM_RANKS_CNFG,
+ // Template recursive base case
+ ATTR_PRE_DATA_ENGINE_CASE = 0,
+
+ DIMM_TYPE = 1,
+ DRAM_GEN = 2,
+ HYBRID = 3,
+ HYBRID_MEDIA = 4,
+ MRANKS = 5,
+ DIMM_RANKS_CNFG = 6,
+
+ // Dispatcher set to last enum value
+ ATTR_PRE_DATA_ENG_DISPATCHER = DIMM_RANKS_CNFG,
+};
+
+///
+/// @brief enum list of SPD based attr fields to set
+///
+enum attr_eff_engine_fields
+{
+ // Template recursive base case
+ ATTR_EFF_BASE_CASE = 0,
+
+ // Attrs to set
+ DRAM_WIDTH = 1,
+
+ // Dispatcher set to last enum value
+ ATTR_EFF_DISPATCHER = DRAM_WIDTH,
+};
+
+///
+/// @brief enum list of SI attr fields to set
+///
+enum attr_si_engine_fields
+{
+ // Template recursive base case
+ ATTR_SI_BASE_CASE = 0,
+
+ // Attrs to set
+ SI_MC_RCV_IMP_DQ_DQS = 1,
+ SI_MC_DRV_IMP_DQ_DQS_PULL_UP = 2,
+ SI_MC_DRV_IMP_DQ_DQS_PULL_DOWN = 3,
+ SI_MC_DRV_SLEW_RATE_DQ_DQS = 4,
+ SI_MC_DRV_IMP_CMD_ADDR = 5,
+ SI_MC_DRV_SLEW_RATE_CMD_ADDR = 6,
+ SI_MC_DRV_IMP_CLK = 7,
+ SI_MC_DRV_SLEW_RATE_CLK = 8,
+ SI_MC_RCV_IMP_ALERT_N = 9,
+ SI_DRAM_RTT_NOM = 10,
+ SI_DRAM_RTT_WR = 11,
+ SI_DRAM_RTT_PARK = 12,
+ 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,
+
+ // Dispatcher set to last enum value
+ ATTR_SI_DISPATCHER = SI_GEARDOWN_MODE,
};
///
@@ -64,6 +119,33 @@ enum pre_data_init_fields
template< proc_type T, pre_data_init_fields TT >
class preDataInitTraits;
+
+///
+/// @brief Forward declartion of traits for attrEngineTraits
+/// @class attrEngineTraits
+/// @tparam ET enum type
+/// @tparam T enum value
+///
+template < typename ET, ET T>
+struct attrEngineTraits;
+
+///
+/// @brief Forward declartion of traits for setTimingTraits
+/// @class setTimingTraits
+/// @tparam ET enum type
+/// @tparam T enum value
+///
+template < typename ET, ET T >
+struct setTimingTraits;
+
+///
+/// @brief Forward declartion of traits for attr_engine
+/// @class attrEnumTraits
+/// @tparam ET enum type
+///
+template < typename ET >
+struct attrEnumTraits;
+
}// 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 e2d5652c0..5436fd5a3 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
@@ -39,6 +39,8 @@
#include <fapi2.H>
#include <generic/memory/lib/utils/index.H>
#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/spd/ddimm/efd_decoder.H>
+#include <generic/memory/lib/spd/spd_facade.H>
namespace mss
{
@@ -67,7 +69,7 @@ struct DataSetterTraits2D < proc_type::NIMBUS,
};
///
-/// @brief Helper function for attribute setting
+/// @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
@@ -85,11 +87,13 @@ template < proc_type P,
typename T,
typename TT = DataSetterTraits2D<P, X, Y>
>
-fapi2::ReturnCode data_setter(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+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);
@@ -170,8 +174,7 @@ fapi_try_exit:
template< proc_type P,
typename TT,
fapi2::TargetType T,
- typename IT
- >
+ typename IT >
inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
const IT i_setting)
{
@@ -179,13 +182,334 @@ inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
typename TT::attr_type l_attr_list = {};
FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list) );
- FAPI_TRY( data_setter<P>(i_target, i_setting, TT::FFDC_CODE, l_attr_list) );
+ 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_try_exit:
return fapi2::current_err;
}
+// Controller agnostic functions
+
+namespace gen
+{
+
+///
+/// @brief Get the target associated with the SPD facade
+/// @param[in] i_data the SPD data
+/// return a fapi2 DIMM target
+///
+static inline fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_target(const spd::facade& i_data)
+{
+ return i_data.get_dimm_target();
+}
+
+///
+/// @brief Get the target associated with the EFD decoder
+/// @param[in] i_data the EFD data
+/// return a fapi2 DIMM target
+///
+static inline fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> get_target(const std::shared_ptr<efd::base_decoder>& i_data)
+{
+ return i_data->get_ocmb_target();
+}
+
+///
+/// @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
+/// @tparam T Input/output data type
+/// @tparam FFDC the FFDC type
+/// @param[in] i_efd_data the EFD data
+/// @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 < size_t X,
+ size_t Y,
+ typename T,
+ typename FFDC >
+inline fapi2::ReturnCode update_data(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ const T i_setting,
+ const FFDC i_ffdc_code,
+ T (&o_data)[X][Y])
+{
+ 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();
+
+ 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(l_ocmb),
+ "Dimm index (%d) was larger than max (%d) on %s",
+ l_dimm_index,
+ X,
+ mss::spd::c_str(l_ocmb) );
+
+ FAPI_ASSERT( l_rank < Y,
+ fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
+ .set_INDEX(l_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,
+ 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;
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to update the structure that holds attr data
+/// @tparam X size of 1st array index
+/// @tparam T Input/output data type
+/// @tparam FFDC the FFDC type
+/// @param[in] i_data the SPD data
+/// @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
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < size_t X,
+ typename T,
+ typename FFDC >
+inline fapi2::ReturnCode update_data( const spd::facade& i_spd_data,
+ const T i_setting,
+ 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;
+
+ 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(l_dimm),
+ "Dimm index (%d) was larger than max (%d) on %s",
+ l_dimm_index,
+ X,
+ mss::spd::c_str(l_dimm) );
+
+ FAPI_DBG("Updating data[%d] with %d for %s", l_dimm_index, i_setting, spd::c_str(l_dimm));
+ 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 DT the data type
+/// @tparam IT Input data type
+/// @tparam FFDC type
+/// @tparam OT Output data type
+/// @param[in] i_data the data (e.g. EFD, SPD)
+/// @param[in] i_setting array to set
+/// @param[in] i_ffdc_code FFDC function code
+/// @param[out] o_data output to set
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < typename DT,
+ typename IT,
+ typename FFDC,
+ typename OT >
+inline fapi2::ReturnCode update_data( const DT& i_data,
+ const IT i_setting,
+ const FFDC i_ffdc_code,
+ OT& o_data )
+{
+ FAPI_DBG("Updating data with %d for %s", i_setting, spd::c_str(get_target(i_data)));
+ o_data = i_setting;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Sets attr data fields
+/// @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< 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>(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_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @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 Sets attr data fields
+/// @tparam TT data engine class traits (e.g. preDataInitTraits, etc.)
+/// @tparam DT the data 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< typename TT,
+ typename DT,
+ typename IT >
+inline fapi2::ReturnCode set_field(const DT& i_data,
+ const IT i_setting)
+{
+ // Grab the target associated w/the data (e.g. SPD or EFD)
+ const auto l_data_target = get_target(i_data);
+
+ // Grab the target associated w/the attribute to set
+ const auto l_attr_target = get_attr_target(l_data_target);
+
+ // 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) );
+
+ // 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) );
+
+ // Set the contents back to the attribute
+ FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list) );
+
+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 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 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 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;
+ }
+};
+
+}// gen
}//mss
#endif
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
index 66edc77d0..69234151e 100644
--- 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
@@ -22,3 +22,447 @@
/* 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>
+
+namespace mss
+{
+
+///
+/// @brief Traits for pre_data_engine
+/// @class attrEngineTraits
+/// @note AXONE, 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 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_EFF_DIMM_TYPE, 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_EFF_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)
+ {
+ // =========================================================
+ // 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
+ };
+
+ uint8_t l_base_module_type = 0;
+ FAPI_TRY(i_spd_data.base_module(l_base_module_type));
+ FAPI_TRY(lookup_table_check(i_spd_data.get_dimm_target(), BASE_MODULE_TYPE_MAP, SET_ATTR_DIMM_TYPE, l_base_module_type,
+ o_setting));
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Traits for pre_data_engine
+/// @class attrEngineTraits
+/// @note AXONE, 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 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_EFF_DRAM_GEN, 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_EFF_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)
+ {
+ // =========================================================
+ // 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
+ };
+
+ uint8_t l_device_type = 0;
+ FAPI_TRY(i_spd_data.device_type(l_device_type));
+ FAPI_TRY(lookup_table_check(i_spd_data.get_dimm_target(), 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 AXONE, 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 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_EFF_HYBRID, 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_EFF_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 AXONE, 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 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_EFF_HYBRID_MEMORY_TYPE, 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_EFF_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 AXONE, 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 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_EFF_NUM_MASTER_RANKS_PER_DIMM, 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_EFF_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 AXONE, 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 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_EFF_DIMM_RANKS_CONFIGED, 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_EFF_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/pre_data_init.H b/src/import/generic/memory/lib/data_engine/pre_data_init.H
index 068e4da4f..b3e4de8ad 100644
--- a/src/import/generic/memory/lib/data_engine/pre_data_init.H
+++ b/src/import/generic/memory/lib/data_engine/pre_data_init.H
@@ -42,7 +42,6 @@
#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/p9a/p9a_data_init_traits.H>
#include <generic/memory/lib/data_engine/data_engine_utils.H>
namespace mss
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 bce94f55f..3b01d0c4a 100644
--- a/src/import/generic/memory/lib/mss_generic_attribute_getters.H
+++ b/src/import/generic/memory/lib/mss_generic_attribute_getters.H
@@ -2349,6 +2349,55 @@ fapi_try_exit:
}
///
+/// @brief ATTR_MEM_EFF_DIMM_RANKS_CONFIGED 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 Bit wise representation of master ranks in each DIMM that are used for reads and
+/// writes. Used by PRD.
+///
+inline fapi2::ReturnCode get_dimm_ranks_configed(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_DIMM_RANKS_CONFIGED, 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_DIMM_RANKS_CONFIGED: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MEM_EFF_DIMM_RANKS_CONFIGED 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 Bit wise representation of master ranks in each DIMM that are used for reads and
+/// writes. Used by PRD.
+///
+inline fapi2::ReturnCode get_dimm_ranks_configed(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_DIMM_RANKS_CONFIGED, i_target, l_value) );
+ memcpy(o_array, &l_value, 2);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed getting ATTR_MEM_EFF_DIMM_RANKS_CONFIGED: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
/// @brief ATTR_MEM_EFF_DRAM_TREFI getter
/// @param[in] const ref to the TARGET_TYPE_MEM_PORT
/// @param[out] uint16_t& reference to store the value
@@ -3864,8 +3913,8 @@ fapi_try_exit:
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @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][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A]
+/// 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]
///
inline fapi2::ReturnCode get_si_odt_rd(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t (&o_array)[4])
{
@@ -3889,8 +3938,8 @@ fapi_try_exit:
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @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][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A]
+/// 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]
///
inline fapi2::ReturnCode get_si_odt_rd(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
uint8_t (&o_array)[2][4])
@@ -3914,8 +3963,8 @@ fapi_try_exit:
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @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][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A]
+/// 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]
///
inline fapi2::ReturnCode get_si_odt_wr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t (&o_array)[4])
{
@@ -3939,8 +3988,8 @@ fapi_try_exit:
/// @note Generated by gen_accessors.pl generate_mc_port_params
/// @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][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A]
+/// 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]
///
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/spd/ddimm/ddr4/ddimm_decoder_ddr4.H b/src/import/generic/memory/lib/spd/ddimm/ddr4/ddimm_decoder_ddr4.H
index 5e736cc76..2d1816ab3 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
@@ -452,7 +452,7 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
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",
+ FAPI_INF("%s. Byte enables: 0x%04x",
spd::c_str(iv_target),
o_output);
}
@@ -484,7 +484,7 @@ class decoder<DDR4, DDIMM_MODULE, R > : public dimm_module_decoder
fapi2::buffer<uint32_t> l_buffer;
right_aligned_insert(l_buffer, l_byte3, l_byte2, l_byte1, l_byte0);
o_output = l_buffer;
- FAPI_INF("%s. Register Manufacturer ID Code: 0x%04x",
+ FAPI_INF("%s. Nibble Enables: 0x%04x",
spd::c_str(iv_target),
o_output);
}
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 12a292b57..12acc87ef 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
@@ -68,10 +68,12 @@ class decoder<mss::spd::device_type::DDR4, DDR4_CUSTOM_MICROCHIP, R > : public b
/// @brief ctor
/// @param[in] i_target dimm target
/// @param[in] i_spd_data vector DIMM SPD data
+ /// @param[in] i_rank the current rank
///
decoder(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const std::vector<uint8_t>& i_spd_data):
- base_decoder(i_target, i_spd_data)
+ const std::vector<uint8_t>& i_spd_data,
+ const size_t i_rank):
+ base_decoder(i_target, i_spd_data, i_rank)
{
// Using the emulation value here
static_assert( R <= mss::spd::rev::DDIMM_MAX, " R > rev::DDIMM_MAX");
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 d3078c171..6ac30ab0f 100644
--- a/src/import/generic/memory/lib/spd/ddimm/efd_decoder.H
+++ b/src/import/generic/memory/lib/spd/ddimm/efd_decoder.H
@@ -86,6 +86,7 @@ class base_decoder
const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> iv_target;
std::vector<uint8_t> iv_data;
+ size_t iv_rank;
public:
@@ -98,11 +99,14 @@ class base_decoder
/// @brief ctor
/// @param[in] i_target DIMM target on which to operate
/// @param[in] i_target EFD data
+ /// @param[in] i_rank the current rank
///
base_decoder(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
- const std::vector<uint8_t>& i_data):
+ const std::vector<uint8_t>& i_data,
+ const size_t i_rank):
iv_target(i_target),
- iv_data(i_data)
+ iv_data(i_data),
+ iv_rank(i_rank)
{
}
@@ -115,12 +119,21 @@ class base_decoder
/// @brief Gets decoder target
/// @return fapi2::Target<fapi2::TARGET_TYPE_DIMM>
///
- virtual fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> get_dimm_target() const
+ virtual fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> get_ocmb_target() const
{
return iv_target;
}
///
+ /// @brief Gets rank tied to this decoder
+ /// @return size_t
+ ///
+ virtual size_t get_rank() const
+ {
+ return iv_rank;
+ }
+
+ ///
/// @brief Gets decoder SPD data
/// @return std::vector<uint8_t>
///
diff --git a/src/import/generic/memory/lib/spd/ddimm/efd_factory.H b/src/import/generic/memory/lib/spd/ddimm/efd_factory.H
index 6a85c86f8..540bb87b0 100644
--- a/src/import/generic/memory/lib/spd/ddimm/efd_factory.H
+++ b/src/import/generic/memory/lib/spd/ddimm/efd_factory.H
@@ -48,17 +48,19 @@ namespace efd
/// @brief Generates the EFD decoder based upon the EFD type
/// @param[in] i_target DIMM target
/// @param[in] i_data SPD data
+/// @param[in] i_rank the current rank
/// @param[out] o_decoder shared pointer to the decoder in question
/// @return fapi2::ReturnCode SUCCESS iff the procedure executes successfully
///
// TODO:update this for other types of EFD
inline fapi2::ReturnCode factory(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const std::vector<uint8_t>& i_data,
+ const size_t i_rank,
std::shared_ptr<base_decoder>& o_decoder_ptr)
{
- o_decoder_ptr =
- std::make_shared<mss::efd::decoder<mss::spd::device_type::DDR4, DDR4_CUSTOM_MICROCHIP, mss::spd::rev::V0_0>>(i_target,
- i_data);
+ o_decoder_ptr = std::make_shared<mss::efd::decoder<mss::spd::device_type::DDR4,
+ DDR4_CUSTOM_MICROCHIP,
+ mss::spd::rev::V0_0>>(i_target, i_data, i_rank);
return fapi2::FAPI2_RC_SUCCESS;
}
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 cec393f11..ae04f2e57 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
@@ -64,7 +64,7 @@
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
- <enum> EMPTY = 0, RDIMM = 1, UDIMM = 2, LRDIMM = 3</enum>
+ <enum> EMPTY = 0, RDIMM = 1, UDIMM = 2, LRDIMM = 3, DDIMM = 4</enum>
<writeable/>
<array>2</array>
<mssAccessorName>dimm_type</mssAccessorName>
@@ -698,6 +698,20 @@
</attribute>
<attribute>
+ <id>ATTR_MEM_EFF_DIMM_RANKS_CONFIGED</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ Bit wise representation of master ranks in each DIMM that are used for reads and writes.
+ Used by PRD.
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint8</valueType>
+ <writeable/>
+ <array> 2 </array>
+ <mssAccessorName>dimm_ranks_configed</mssAccessorName>
+ </attribute>
+
+ <attribute>
<id>ATTR_MEM_EFF_DRAM_TREFI</id>
<targetType>TARGET_TYPE_MEM_PORT</targetType>
<description>
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 819336678..1ec910f04 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
@@ -218,7 +218,7 @@
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
- <enum>HALF =0, QUARTER=1</enum>
+ <enum>HALF=0, QUARTER=1</enum>
<writeable/>
<array>2 4</array>
<mssAccessorName>si_geardown_mode</mssAccessorName>
@@ -481,7 +481,8 @@
<description>
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][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A]
+ The bits in 8 bit field are
+ [DIMM0 ODT0][DIMM0 ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
@@ -496,7 +497,8 @@
<description>
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][N/A][N/A][Dimm1 ODT0][Dimm1 ODT1][N/A][N/A]
+ The bits in 8 bit field are
+ [DIMM0 ODT0][DIMM0 ODT1][DIMM0 ODT2][DIMM0 ODT3][DIMM1 ODT0][DIMM1 ODT1][DIMM1 ODT2][DIMM1 ODT3]
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
OpenPOWER on IntegriCloud