summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/spd
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2017-09-20 05:17:48 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2017-09-20 17:05:40 -0400
commit4bedcbfa241d111dcc92f88389d33d9abe9d8bb5 (patch)
treee681939d02e9391438d3150cc37e5f656bb403d4 /src/import/generic/memory/lib/spd
parent5782a64d980963436b52960107b4ba150f1a3808 (diff)
downloadtalos-hostboot-4bedcbfa241d111dcc92f88389d33d9abe9d8bb5.tar.gz
talos-hostboot-4bedcbfa241d111dcc92f88389d33d9abe9d8bb5.zip
Split SPD Connector to SDRAM fields, add unit tests
Change-Id: Ifaa79b70368c41789a199db78de2fa4e40768922 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46217 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/46224 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: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/generic/memory/lib/spd')
-rw-r--r--src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H371
-rw-r--r--src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C53
-rw-r--r--src/import/generic/memory/lib/spd/common/spd_decoder_base.H19
3 files changed, 418 insertions, 25 deletions
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 c139b2a43..7ec95e040 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
@@ -51,10 +51,329 @@
#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H>
#include <generic/memory/lib/utils/c_str.H>
#include <generic/memory/lib/spd/common/spd_decoder_base.H>
-
+#include <generic/memory/lib/spd/spd_checker.H>
namespace mss
{
+
+///
+/// @brief Connector to SDRAM Bit Mapping field positions
+/// @note Bytes 60 - 77 . Mapping to Package rank map and
+/// nibble map starting and length positions for SPD field extraction.
+///
+enum connector_to_sdram
+{
+ PACKAGE_RANK_MAP_START = 0,
+ PACKAGE_RANK_MAP_LEN = 2,
+
+ NIBBLE_MAP_START = 2,
+ NIBBLE_MAP_LEN = 6,
+};
+
+///
+/// @brief Connector to SDRAM Bit Mapping fields
+/// @note template selector for traits and function API
+///
+enum connector_field
+{
+ NIBBLE_MAP,
+ PKG_RANK_MAP,
+};
+
+///
+/// @brief Connector to SDRAM Bit Mapping connector bits
+/// @note template selYYector for traits and function API.
+/// DQ0_31 represnts DQ nibbles for DQ bits 0 - 31.
+/// DQ32_63 represnts DQ nibbles for DQ bits 32 - 63.
+/// CB0_7 represents DQ nibbles for DQ bits 64 - 71.
+///
+enum connector_bits
+{
+ DQ0_31,
+ DQ32_63,
+ CB0_7,
+};
+
+///
+/// @brief Helper function threshold check for nibble map
+/// @param[in] i_target the DIMM target
+/// @param[in] i_byte the SPD byte
+/// @param[in] i_bit_order the nibble bit order from SPD
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+static fapi2::ReturnCode nibble_map_helper( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_bit_order )
+{
+ // SPD limits on what the value for the nibble map can be,
+ // taken from the SPD JEDEC spec.
+ constexpr uint64_t LOW_BIT_ORDER_MIN = 0x01;
+ constexpr uint64_t LOW_BIT_ORDER_MAX = 0x18;
+
+ constexpr uint64_t UP_BIT_ORDER_MIN = 0x21;
+ constexpr uint64_t UP_BIT_ORDER_MAX = 0x38;
+
+ // SPD JEDEC thresholds - protects against reserved values
+ const bool VALID_LOWER_NIBBLE = (i_bit_order >= LOW_BIT_ORDER_MIN) && (i_bit_order <= LOW_BIT_ORDER_MAX);
+ const bool VALID_UPPER_NIBBLE = (i_bit_order >= UP_BIT_ORDER_MIN) && (i_bit_order <= UP_BIT_ORDER_MAX);
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target,
+ (VALID_LOWER_NIBBLE || VALID_UPPER_NIBBLE),
+ i_byte,
+ i_bit_order,
+ "Failed check on the NIBBLE_MAP field") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function threshold check for package rank map
+/// @param[in] i_target the DIMM target
+/// @param[in] i_byte the SPD byte
+/// @param[in] i_pkg_rank_map pakcage rank map value
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+static fapi2::ReturnCode package_rank_map_helper( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_pkg_rank_map )
+{
+ // Taken from the SPD JEDEC spec, only valid encoding, the rest are reserved
+ constexpr uint64_t VALID_VALUE = 0;
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(i_target,
+ (i_pkg_rank_map == VALID_VALUE),
+ i_byte,
+ i_pkg_rank_map,
+ "Failed check on Package Rank Map") );
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @class connectorTraits
+/// @brief a collection of traits associated with the connector to SDRAM
+/// @tparam T the connector_bits representing the DQ bits
+/// @tparam OT the connector_field representing the SPD field
+///
+template< connector_bits T, connector_field OT >
+class connectorTraits;
+
+///
+/// @class connectorTraits
+/// @brief a collection of traits associated with the connector to SDRAM
+/// @note DQ0_31, NIBBLE_MAP specialization
+///
+template< >
+class connectorTraits<DQ0_31, NIBBLE_MAP>
+{
+ public:
+ enum
+ {
+ START = 60,
+ END = 67,
+ EXTRACT_START = NIBBLE_MAP_START,
+ EXTRACT_LEN = NIBBLE_MAP_LEN,
+
+ };
+
+ ///
+ /// @brief SPD byte field threshold check
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_byte the SPD byte
+ /// @param[in] i_bit_order the nibble bit order from SPD
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode fail_check( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_bit_order )
+ {
+ FAPI_TRY(nibble_map_helper(i_target, i_byte, i_bit_order) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+};
+
+///
+/// @class connectorTraits
+/// @brief a collection of traits associated with the connector to SDRAM
+/// @note DQ0_31, PKG_RANK_MAP specialization
+///
+template< >
+class connectorTraits<DQ0_31, PKG_RANK_MAP>
+{
+ public:
+ enum
+ {
+ START = 60,
+ END = 67,
+ EXTRACT_START = PACKAGE_RANK_MAP_START,
+ EXTRACT_LEN = PACKAGE_RANK_MAP_LEN,
+ };
+
+ ///
+ /// @brief SPD byte field threshold check
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_byte the SPD byte
+ /// @param[in] i_pkg_rank_map pakcage rank map value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode fail_check( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_pkg_rank_map )
+ {
+ FAPI_TRY( package_rank_map_helper(i_target, i_byte, i_pkg_rank_map) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+};
+
+///
+/// @class connectorTraits
+/// @brief a collection of traits associated with the connector to SDRAM
+/// @note DQ32_63, NIBBLE_MAP specialization
+///
+template< >
+class connectorTraits<DQ32_63, NIBBLE_MAP>
+{
+ public:
+ enum
+ {
+ START = 70,
+ END = 77,
+ EXTRACT_START = NIBBLE_MAP_START,
+ EXTRACT_LEN = NIBBLE_MAP_LEN,
+ };
+
+ ///
+ /// @brief SPD byte field threshold check
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_byte the SPD byte
+ /// @param[in] i_bit_order the nibble bit order from SPD
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode fail_check( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_bit_order )
+ {
+ FAPI_TRY(nibble_map_helper(i_target, i_byte, i_bit_order) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+};
+
+///
+/// @class connectorTraits
+/// @brief a collection of traits associated with the connector to SDRAM
+/// @note DQ32_63, PKG_RANK_MAP specialization
+///
+template< >
+class connectorTraits<DQ32_63, PKG_RANK_MAP>
+{
+ public:
+ enum
+ {
+ START = 70,
+ END = 77,
+ EXTRACT_START = PACKAGE_RANK_MAP_START,
+ EXTRACT_LEN = PACKAGE_RANK_MAP_LEN,
+ };
+
+ ///
+ /// @brief SPD byte field threshold check
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_byte the SPD byte
+ /// @param[in] i_pkg_rank_map pakcage rank map value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode fail_check( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_pkg_rank_map )
+ {
+ FAPI_TRY( package_rank_map_helper(i_target, i_byte, i_pkg_rank_map) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+};
+
+///
+/// @class connectorTraits
+/// @brief a collection of traits associated with the connector to SDRAM
+/// @note CB0_7, NIBBLE_MAP specialization
+///
+template< >
+class connectorTraits<CB0_7, NIBBLE_MAP>
+{
+ public:
+ enum
+ {
+ START = 68,
+ END = 69,
+ EXTRACT_START = NIBBLE_MAP_START,
+ EXTRACT_LEN = NIBBLE_MAP_LEN,
+ };
+
+ ///
+ /// @brief SPD byte field threshold check
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_byte the SPD byte
+ /// @param[in] i_bit_order the nibble bit order from SPD
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode fail_check( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_bit_order )
+ {
+ FAPI_TRY(nibble_map_helper(i_target, i_byte, i_bit_order) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+};
+
+///
+/// @class connectorTraits
+/// @brief a collection of traits associated with the connector to SDRAM
+/// @note CB0_7, PKG_RANK_MAP specialization
+///
+template< >
+class connectorTraits<CB0_7, PKG_RANK_MAP>
+{
+ public:
+ enum
+ {
+ START = 68,
+ END = 69,
+ EXTRACT_START = PACKAGE_RANK_MAP_START,
+ EXTRACT_LEN = PACKAGE_RANK_MAP_LEN,
+ };
+
+ ///
+ /// @brief SPD byte field threshold check
+ /// @param[in] i_target the DIMM target
+ /// @param[in] i_byte the SPD byte
+ /// @param[in] i_pkg_rank_map pakcage rank map value
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ static fapi2::ReturnCode fail_check( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_byte,
+ const uint8_t i_pkg_rank_map )
+ {
+ FAPI_TRY( package_rank_map_helper(i_target, i_byte, i_pkg_rank_map) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+
+ }
+};
+
namespace spd
{
@@ -303,8 +622,6 @@ class decoder_v1_0 : public decoder
// Bytes 46 - 59 - reserved
- // Bytes 60 - 77 - Connector to SDRAM Bit Mapping ??
-
// Bytes 78 - 116 - reserved
// Bytes 117 - 125 : Entire byte used
@@ -955,15 +1272,26 @@ class decoder_v1_0 : public decoder
virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value ) const override;
///
- /// @brief Decodes connector to SDRAM bit mapping
- /// @param[out] o_value vector of bit nibble maps for SPD bytes 60 - 77
+ /// @brief Decodes Package Rank Map
+ /// @param[out] o_value vector of package rank maps for SPD bytes 60 - 77
/// @return FAPI2_RC_SUCCESS iff okay
/// @note SPD Byte 60 - 77
/// @note JEDEC Standard No. 21-C
- /// @note Page 40
+ /// @note Page 45
/// @note DDR4 SPD Document Release 3
///
- virtual fapi2::ReturnCode connector_to_sdram( std::vector<uint8_t>& o_value ) const override;
+ virtual fapi2::ReturnCode package_rank_map( std::vector<uint8_t>& o_value ) const override;
+
+ ///
+ /// @brief Decodes Nibble Map
+ /// @param[out] o_value vector of nibble map encoding for SPD bytes 60 - 77
+ /// @return FAPI2_RC_SUCCESS iff okay
+ /// @note SPD Byte 60 - 77
+ /// @note JEDEC Standard No. 21-C
+ /// @note Page 45
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode nibble_map( std::vector<uint8_t>& o_value ) const override;
///
/// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group
@@ -1183,6 +1511,35 @@ class decoder_v1_0 : public decoder
///
virtual fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const override;
+ private:
+
+ ///
+ /// @brief SPD byte field threshold check
+ /// @param[out] o_value list of connector_field values from SPD
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ template< mss::connector_bits T, mss::connector_field OT, typename TT = mss::connectorTraits<T, OT> >
+ fapi2::ReturnCode sdram_connector_helper( std::vector<uint8_t>& o_value ) const
+ {
+ for( size_t byte = TT::START; byte <= TT::END; ++byte )
+ {
+ uint8_t l_field = 0;
+
+ fapi2::buffer<uint8_t> l_buffer(iv_spd_data[byte]);
+ l_buffer.extractToRight<TT::EXTRACT_START, TT::EXTRACT_LEN>(l_field);
+
+ FAPI_DBG("%s SPD byte %d, data: %d, field value: %d, starting bit: %d, bit length: %d",
+ mss::c_str(iv_target), byte, iv_spd_data[byte], l_field, TT::EXTRACT_START, TT::EXTRACT_LEN);
+
+ FAPI_TRY( TT::fail_check(iv_target, byte, l_field) );
+
+ o_value.push_back(l_field);
+ }
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
};// decoder
///
diff --git a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C
index 3615ee995..3c25e3530 100644
--- a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C
+++ b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C
@@ -43,7 +43,6 @@
#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H>
#include <generic/memory/lib/spd/common/rcw_settings.H>
-#include <generic/memory/lib/spd/spd_checker.H>
#include <generic/memory/lib/utils/c_str.H>
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/utils/mss_math.H>
@@ -2156,29 +2155,55 @@ fapi2::ReturnCode decoder_v1_0::min_twtr_l( int64_t& o_value) const
}
///
-/// @brief Decodes connector to SDRAM bit mapping
-/// @param[out] o_value vector of bit nibble maps for SPD bytes 60 - 77
+/// @brief Decodes Package Rank Map
+/// @param[out] o_value vector of package rank maps for SPD bytes 60 - 77
/// @return FAPI2_RC_SUCCESS iff okay
/// @note SPD Byte 60 - 77
/// @note JEDEC Standard No. 21-C
-/// @note Page 40
+/// @note Page 45
/// @note DDR4 SPD Document Release 3
///
-fapi2::ReturnCode decoder_v1_0::connector_to_sdram( std::vector<uint8_t>& o_value ) const
+fapi2::ReturnCode decoder_v1_0::package_rank_map( std::vector<uint8_t>& o_value ) const
{
- constexpr size_t BIT_MAPPING_START = 60;
- constexpr size_t BIT_MAPPING_END = 77;
+ o_value.clear();
+
+ FAPI_TRY( (sdram_connector_helper<DQ0_31, PKG_RANK_MAP>(o_value)),
+ "%s Failed to sdram_connector_helper for DQ0_31, PKG_RANK_MAP", mss::c_str(iv_target) );
+
+ FAPI_TRY( (sdram_connector_helper<DQ32_63, PKG_RANK_MAP>(o_value)),
+ "%s Failed to sdram_connector_helper for DQ32_63, PKG_RANK_MAP", mss::c_str(iv_target) );
+
+ FAPI_TRY( (sdram_connector_helper<CB0_7, PKG_RANK_MAP>(o_value)),
+ "%s Failed to sdram_connector_helper for CB0_7, PKG_RANK_MAP", mss::c_str(iv_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
- // Clear vector. Just.In.Case
+///
+/// @brief Decodes Nibble map
+/// @param[out] o_value vector of bit order encoding for SPD bytes 60 - 77
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note SPD Byte 60 - 77
+/// @note JEDEC Standard No. 21-C
+/// @note Page 45
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_0::nibble_map( std::vector<uint8_t>& o_value ) const
+{
o_value.clear();
- for( size_t byte = BIT_MAPPING_START; byte <= BIT_MAPPING_END; ++byte )
- {
- o_value.push_back(iv_spd_data[byte]);
- }
+ FAPI_TRY( (sdram_connector_helper<DQ0_31, NIBBLE_MAP>(o_value)),
+ "%s Failed to sdram_connector_helper for DQ0_31, NIBBLE_MAP", mss::c_str(iv_target) );
- // SPD doesn't provide a range of invalid values to test against
- return fapi2::FAPI2_RC_SUCCESS;
+ FAPI_TRY( (sdram_connector_helper<DQ32_63, NIBBLE_MAP>(o_value)),
+ "%s Failed to sdram_connector_helper for DQ32_63, NIBBLE_MAP", mss::c_str(iv_target) );
+
+ FAPI_TRY( (sdram_connector_helper<CB0_7, NIBBLE_MAP>(o_value)),
+ "%s Failed to sdram_connector_helper for CB0_7, NIBBLE_MAP", mss::c_str(iv_target) );
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
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 7efe06247..8ca317d28 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
@@ -674,11 +674,22 @@ class decoder
}
///
- /// @brief Decodes connector to SDRAM bit mapping
- /// @param[out] o_value vector of bit nibble maps for SPD bytes 60 - 77
- /// @return FAPI2_RC_SUCCESS if okay
+ /// @brief Decodes Package Rank Map
+ /// @param[out] o_value vector of package rank maps for SPD bytes 60 - 77
+ /// @return FAPI2_RC_SUCCESS iff okay
+ ///
+ virtual fapi2::ReturnCode package_rank_map( std::vector<uint8_t>& o_value ) const
+ {
+ o_value.clear();
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Nibble Map
+ /// @param[out] o_value vector of nibble map encoding for SPD bytes 60 - 77
+ /// @return FAPI2_RC_SUCCESS iff okay
///
- virtual fapi2::ReturnCode connector_to_sdram( std::vector<uint8_t>& o_value ) const
+ virtual fapi2::ReturnCode nibble_map( std::vector<uint8_t>& o_value ) const
{
o_value.clear();
return fapi2::FAPI2_RC_SUCCESS;
OpenPOWER on IntegriCloud