summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/spd
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2017-08-18 10:53:44 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-08-29 11:39:24 -0400
commit2b881ebf90218af1ce41918b214498c2574940e1 (patch)
tree5acce76de62c874ae32eff6c12d3ffa1094fc44f /src/import/chips/p9/procedures/hwp/memory/lib/spd
parent598111fc4b49f16495b41b8461fc01d49239eb42 (diff)
downloadtalos-hostboot-2b881ebf90218af1ce41918b214498c2574940e1.tar.gz
talos-hostboot-2b881ebf90218af1ce41918b214498c2574940e1.zip
Adds DDR4 hybrid NV-RDIMM support
Change-Id: Ie5cc0ed4dc6337c35df2e222cc4e220e5720f0bd Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/44974 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/45182 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/spd')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C195
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H30
2 files changed, 224 insertions, 1 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C
index fd032e167..87effa9d6 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C
@@ -73,6 +73,10 @@ enum factory_byte_extract
ADDITIONS_LEVEL_LEN = 4, ///< SPD additions level bit length
// Byte 3
+ HYBRID_START = 0, ///< SPD hybrid start bit
+ HYBRID_LEN = 1, ///< SPD hybrid bit length
+ HYBRID_TYPE_START = 1, ///< SPD hybrid type start bit
+ HYBRID_TYPE_LEN = 3, ///< SPD hybrid type bit length
BASE_MODULE_START = 4, ///< SPD base module start bit
BASE_MODULE_LEN = 4, ///< SPD base module bit length
};
@@ -163,6 +167,114 @@ fapi_try_exit:
}
///
+/// @brief Decodes hybrid type (whether or not the DIMM is a hybrid) from SPD
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data
+/// @param[out] o_value hybrid
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 3 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode hybrid(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 3 maps
+ // Item JC-45-2220.01x
+ // Page 17
+ // DDR4 SPD Document Release 3
+ // 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_EFF_HYBRID_NOT_HYBRID},
+ {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID},
+ // All others reserved or not supported
+ };
+
+ constexpr size_t BYTE_INDEX = 3;
+ constexpr field_t HYBRID{BYTE_INDEX, HYBRID_START, HYBRID_LEN};
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field(i_target, HYBRID, i_spd_data);
+ FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits);
+
+ // Check that value is valid
+ const bool l_is_val_found = find_value_from_key(HYBRID_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target,
+ l_is_val_found,
+ HYBRID.iv_byte,
+ l_field_bits,
+ "Failed check on Hybrid") );
+
+ FAPI_INF("%s. Hybrid Media: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes hybrid type (hybrid DIMM type) from SPD
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data
+/// @param[out] o_value hybrid module type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 3 (bits 6~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode hybrid_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 3 maps
+ // Item JC-45-2220.01x
+ // Page 17
+ // DDR4 SPD Document Release 3
+ // Byte 3 (0x003): Key Byte / Module Type - Hybrid
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_TYPE_MAP =
+ {
+ //{key byte, dimm type}
+ {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE},
+ {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM},
+ // All others reserved or not supported
+ };
+
+ constexpr size_t BYTE_INDEX = 3;
+ constexpr field_t HYBRID_TYPE{BYTE_INDEX, HYBRID_TYPE_START, HYBRID_TYPE_LEN};
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field(i_target, HYBRID_TYPE, i_spd_data);
+ FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits);
+
+ // Check that value is valid
+ const bool l_is_val_found = find_value_from_key(HYBRID_TYPE_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target,
+ l_is_val_found,
+ HYBRID_TYPE.iv_byte,
+ l_field_bits,
+ "Failed check on Hybrid Memory Type") );
+
+ FAPI_INF("%s. Hybrid Memory Type: %d",
+ mss::c_str(i_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
/// @brief Decodes base module type (DIMM type) from SPD
/// @param[in] i_target dimm target
/// @param[in] i_spd_data SPD data
@@ -189,7 +301,7 @@ fapi2::ReturnCode base_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_targ
//{key byte, dimm type}
{1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM},
{2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM},
- {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM}
+ {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM},
// All others reserved or not supported
};
@@ -340,6 +452,68 @@ fapi_try_exit:
}
///
+/// @brief Helper function to set hybrid attribute
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data
+/// @param[out] o_hybrid dimm type encoding needed by factory
+/// @return FAPI2_RC_SUCCESS if okay
+///
+static fapi2::ReturnCode hybrid_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ uint8_t& o_hybrid)
+{
+ const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) );
+ const auto l_dimm_num = index(i_target);
+ const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target);
+
+ // Get dimm type & set attribute (needed by c_str)
+ uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {};
+
+ FAPI_TRY( hybrid(i_target, i_spd_data, o_hybrid),
+ "%s. Failed to find hybrid", mss::c_str(i_target) );
+ FAPI_TRY( eff_hybrid(l_mcs, &l_dimm_types_mcs[0][0]),
+ "%s. Failed to invoke hybrid accessor", mss::c_str(i_target));
+
+ l_dimm_types_mcs[l_port_num][l_dimm_num] = o_hybrid;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID, l_mcs, l_dimm_types_mcs),
+ "%s. Failed to set ATTR_EFF_HYBRID", mss::c_str(i_target));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to set hybrid_type attribute
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data
+/// @param[out] o_hybrid_type dimm type encoding needed by factory
+/// @return FAPI2_RC_SUCCESS if okay
+///
+static fapi2::ReturnCode hybrid_type_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ uint8_t& o_hybrid_type)
+{
+ const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) );
+ const auto l_dimm_num = index(i_target);
+ const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target);
+
+ // Get dimm type & set attribute (needed by c_str)
+ uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {};
+
+ FAPI_TRY( hybrid_type(i_target, i_spd_data, o_hybrid_type),
+ "%s. Failed to find hybrid_memory_type", mss::c_str(i_target) );
+ FAPI_TRY( eff_hybrid_memory_type(l_mcs, &l_dimm_types_mcs[0][0]),
+ "%s. Failed to invoke hybrid_memory_type accessor", mss::c_str(i_target));
+
+ l_dimm_types_mcs[l_port_num][l_dimm_num] = o_hybrid_type;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, l_mcs, l_dimm_types_mcs),
+ "%s. Failed to set ATTR_EFF_HYBRID_MEMORY", mss::c_str(i_target));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
/// @brief Helper function to set dram gen attribute
/// @param[in] i_target dimm target
/// @param[in] i_spd_data SPD data
@@ -618,11 +792,15 @@ fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_targ
rcw_settings& o_raw_card)
{
uint8_t l_dimm_type = 0;
+ uint8_t l_hybrid = 0;
+ uint8_t l_hybrid_type = 0;
uint8_t l_ref_raw_card_rev = 0;
// Lets find out what raw card we are and grab the right
// raw card settings
FAPI_TRY( mss::eff_dimm_type(i_target, l_dimm_type) );
+ FAPI_TRY( mss::eff_hybrid(i_target, l_hybrid) );
+ FAPI_TRY( mss::eff_hybrid_memory_type(i_target, l_hybrid_type) );
FAPI_TRY( reference_raw_card(i_target, i_spd_data, l_ref_raw_card_rev) );
FAPI_INF( "Retrieved dimm_type: %d, raw card reference: 0x%lx from SPD",
@@ -632,6 +810,15 @@ fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_targ
{
case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM:
+ // TODO:RTC178807 - Update how NVDIMMs are handled once more are up and running in the lab
+ // NVDIMM is currently considered differently than all other rdimm raw cards, due to settings differences
+ if((l_hybrid == fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID) &&
+ (l_hybrid_type == fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM))
+ {
+ l_ref_raw_card_rev = mss::rdimm::raw_card_rev::NVDIMM;
+ FAPI_INF("%s is an NVDIMM, overwrote l_ref_raw_card_rev to be 0x%02x", mss::c_str(i_target), l_ref_raw_card_rev);
+ }
+
FAPI_ASSERT( find_value_from_key( mss::rdimm::RAW_CARDS, l_ref_raw_card_rev, o_raw_card),
fapi2::MSS_INVALID_RAW_CARD()
.set_DIMM_TYPE(l_dimm_type)
@@ -688,6 +875,8 @@ fapi2::ReturnCode factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
}
uint8_t l_dimm_type = 0;
+ uint8_t l_hybrid = 0;
+ uint8_t l_hybrid_type = 0;
uint8_t l_encoding_rev = 0;
uint8_t l_additions_rev = 0;
rcw_settings l_raw_card;
@@ -696,6 +885,10 @@ fapi2::ReturnCode factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
// the SPD decoder for debugging help
FAPI_TRY( dimm_type_setter(i_target, i_spd_data, l_dimm_type),
"%s. Failed to set DIMM type", mss::c_str(i_target) );
+ FAPI_TRY( hybrid_setter(i_target, i_spd_data, l_hybrid),
+ "%s. Failed to set hybrid", mss::c_str(i_target) );
+ FAPI_TRY( hybrid_type_setter(i_target, i_spd_data, l_hybrid_type),
+ "%s. Failed to set hybrid_type", mss::c_str(i_target) );
FAPI_TRY( dram_gen_setter(i_target, i_spd_data),
"%s. Failed to set DRAM generation", mss::c_str(i_target) );
FAPI_TRY( raw_card_factory(i_target, i_spd_data, l_raw_card),
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H
index 4087bf464..bb19eaf34 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H
@@ -83,6 +83,36 @@ fapi2::ReturnCode rev_additions_level(const fapi2::Target<fapi2::TARGET_TYPE_DIM
uint8_t& o_value);
///
+/// @brief Decodes hybrid type (whether or not the DIMM is a hybrid) from SPD
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data
+/// @param[out] o_value hybrid
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 3 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode hybrid(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ uint8_t& o_value);
+
+///
+/// @brief Decodes hybrid type (hybrid DIMM type) from SPD
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data
+/// @param[out] o_value hybrid module type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 3 (bits 6~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode hybrid_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ uint8_t& o_value);
+
+///
/// @brief Decodes base module type (DIMM type) from SPD
/// @param[in] i_target dimm target
/// @param[in] i_spd_data SPD data
OpenPOWER on IntegriCloud