summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/spd
diff options
context:
space:
mode:
authorAndre Marin <aamarin@us.ibm.com>2017-03-22 23:04:12 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-03-27 12:29:28 -0400
commitaae922c1132fa71bd4ffb711296420755c7c0098 (patch)
treeea757503109d8918cb54105405a81438439797ff /src/import/generic/memory/lib/spd
parenta8edc5a1152e91170728d19ae5d0839223803bef (diff)
downloadblackbird-hostboot-aae922c1132fa71bd4ffb711296420755c7c0098.tar.gz
blackbird-hostboot-aae922c1132fa71bd4ffb711296420755c7c0098.zip
Add base spd decoder to share among controllers
Reorganized files and names to make room for DDR3 SPD decoder to be used for Cumulus. Change-Id: Id3e7a8f4bb60fd0ae0cdf36b8298a1d00257205a Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/36319 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/36326 Reviewed-by: Hostboot Team <hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@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.H1470
-rw-r--r--src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C2942
-rw-r--r--src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C850
-rw-r--r--src/import/generic/memory/lib/spd/common/dimm_module_decoder.H548
-rw-r--r--src/import/generic/memory/lib/spd/common/rcw_settings.H162
-rw-r--r--src/import/generic/memory/lib/spd/common/spd_decoder_base.H848
-rw-r--r--src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H670
-rw-r--r--src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C1367
-rw-r--r--src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C273
-rw-r--r--src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C306
-rw-r--r--src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C84
-rw-r--r--src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H68
-rw-r--r--src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H431
-rw-r--r--src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C672
-rw-r--r--src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C273
-rw-r--r--src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C216
-rw-r--r--src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H86
-rw-r--r--src/import/generic/memory/lib/spd/spd_checker.H112
18 files changed, 11378 insertions, 0 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
new file mode 100644
index 000000000..65198a856
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H
@@ -0,0 +1,1470 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file spd_decoder.H
+/// @brief SPD decoder declarations
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_SPD_DECODER_H_
+#define _MSS_SPD_DECODER_H_
+
+// std lib
+#include <cstdint>
+#include <map>
+#include <memory>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/common/dimm_module_decoder.H>
+#include <generic/memory/lib/spd/common/rcw_settings.H>
+#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H>
+#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>
+
+
+namespace mss
+{
+namespace spd
+{
+
+enum sdram_package_type : uint8_t
+{
+ // Signal loading
+ MONOLITHIC = 0,
+ NON_MONOLITHIC = 1,
+
+ // Package Type
+ UNSPECIFIED = MONOLITHIC,
+ MULTI_LOAD_STACK = 1,
+ SINGLE_LOAD_STACK = 2,
+};
+
+enum nominal_voltage : uint8_t
+{
+ NOT_OPERABLE = 0,
+ OPERABLE = 1,
+
+ NOT_ENDURANT = 0,
+ ENDURANT = 1
+};
+
+enum factory_byte_extract
+{
+ // Byte 1
+ ENCODING_LEVEL_START = 0,
+ ENCODING_LEVEL_LEN = 4,
+
+ ADDITIONS_LEVEL_START = 4,
+ ADDITIONS_LEVEL_LEN = 4,
+
+ // Byte 3
+ BASE_MODULE_START = 4,
+ BASE_MODULE_LEN = 4,
+};
+
+///
+/// @brief Helper function to extract byte information
+/// @tparam I Byte index
+/// @tparam S Start bit
+/// @tparam L Bit length
+/// @param[in] i_target the dimm target
+/// @param[in] i_spd_data the SPD data
+/// @return extracted byte (right aligned)
+///
+template<size_t I, uint8_t S, uint8_t L>
+inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data)
+{
+ //TODO - RTC:159477
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ I,
+ i_spd_data[I]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_spd_data[I]);
+
+ // Extracting desired bits
+ uint8_t l_field_bits = 0;
+ l_buffer.extractToRight<S, L>(l_field_bits);
+
+ return l_field_bits;
+}
+
+///
+/// @brief Helper function to extract byte information
+/// @tparam F the SPD field to extract
+/// @param[in] i_target the dimm target
+/// @param[in] i_spd_data the SPD data
+/// @return extracted byte (right aligned)
+///
+template< const field_t& F >
+inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data)
+{
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ F.iv_byte,
+ i_spd_data[F.iv_byte]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_spd_data[F.iv_byte]);
+
+ // Extracting desired bits
+ uint8_t l_field_bits = 0;
+ l_buffer.extractToRight<F.iv_start, F.iv_length>(l_field_bits);
+
+ return l_field_bits;
+}
+
+///
+/// @brief Helper function to extract byte information
+/// @param[in] i_target the dimm target
+/// @param[in] i_field the SPD field
+/// @param[in] i_spd_data the SPD data
+/// @return extracted byte (right aligned)
+///
+inline uint8_t extract_spd_field(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const field_t& i_field,
+ const std::vector<uint8_t>& i_spd_data)
+{
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(i_target),
+ i_field.iv_byte,
+ i_spd_data[i_field.iv_byte]);
+
+ fapi2::buffer<uint8_t> l_buffer(i_spd_data[i_field.iv_byte]);
+
+ // Extracting desired bits
+ uint8_t l_field_bits = 0;
+ l_buffer.extractToRight( l_field_bits, i_field.iv_start, i_field.iv_length );
+
+ return l_field_bits;
+}
+
+///
+/// @class decoder
+/// @brief Base SPD DRAM decoder
+///
+class decoder : public base_decoder
+{
+ protected:
+ enum
+ {
+ // Byte 0
+ BYTES_USED_START = 4,
+ BYTES_USED_LEN = 4,
+
+ BYTES_TOTAL_START = 1,
+ BYTES_TOTAL_LEN = 3,
+
+ // Byte 1 - see factory byte enum
+ // Byte 2 - Entire byte used
+
+ // Byte 3
+ HYBRID_MEDIA_START = 1,
+ HYBRID_MEDIA_LEN = 3,
+
+ HYBRID_START = 0,
+ HYBRID_LEN = 1,
+
+ // Byte 4
+ SDRAM_CAPACITY_START = 4,
+ SDRAM_CAPACITY_LEN = 4,
+
+ SDRAM_BANKS_START = 2,
+ SDRAM_BANKS_LEN = 2,
+
+ BANK_GROUP_START = 0,
+ BANK_GROUP_LEN = 2,
+
+ // Byte 5
+ COL_ADDRESS_START = 5,
+ COL_ADDRESS_LEN = 3,
+
+ ROW_ADDRESS_START = 2,
+ ROW_ADDRESS_LEN = 3,
+
+ // Byte 6
+ PRIM_SIGNAL_LOAD_START = 6,
+ PRIM_SIGNAL_LOAD_LEN = 2,
+
+ PRIM_DIE_COUNT_START = 1,
+ PRIM_DIE_COUNT_LEN = 3,
+
+ PRIM_PACKAGE_TYPE_START = 0,
+ PRIM_PACKAGE_TYPE_LEN = 1,
+
+ // Byte 7
+ MAC_START = 4,
+ MAC_LEN = 4,
+
+ TMAW_START = 2,
+ TMAW_LEN = 2,
+
+ // Byte 8 reserved
+
+ // Byte 9
+ SOFT_PPR_START = 2,
+ SOFT_PPR_LEN = 1,
+
+ PPR_START = 0,
+ PPR_LEN = 2,
+
+ // Byte 10
+ SEC_SIGNAL_LOAD_START = 5,
+ SEC_SIGNAL_LOAD_LEN = 2,
+
+ DENSITY_RATIO_START = 4,
+ DENSITY_RATIO_LEN = 2,
+
+ SEC_DIE_COUNT_START = 1,
+ SEC_DIE_COUNT_LEN = 3,
+
+ SEC_PACKAGE_TYPE_START = 0,
+ SEC_PACKAGE_TYPE_LEN = 1,
+
+ // Byte 11
+ OPERABLE_START = 7,
+ OPERABLE_LEN = 1,
+
+ ENDURANT_START = 6,
+ ENDURANT_LEN = 1,
+
+ NOM_VOLT_START = 0,
+ NOM_VOLT_LEN = 6,
+
+ // Byte 12
+ SDRAM_WIDTH_START = 5,
+ SDRAM_WIDTH_LEN = 3,
+
+ PACKAGE_RANKS_START = 2,
+ PACKAGE_RANKS_LEN = 3,
+
+ RANK_MIX_START = 1,
+ RANK_MIX_LEN = 1,
+
+ // Byte 13
+ BUS_WIDTH_START = 5,
+ BUS_WIDTH_LEN = 3,
+
+ BUS_EXT_WIDTH_START = 3,
+ BUS_EXT_WIDTH_LEN = 2,
+
+ // Byte 14
+ THERM_SENSOR_RESERV_START = 1,
+ THERM_SENSOR_RESERV_LEN = 7,
+
+ THERM_SENSOR_START = 0,
+ THERM_SENSOR_LEN = 1,
+
+ // Byte 15
+ EXT_MOD_TYPE_START = 5,
+ EXT_MOD_TYPE_LEN = 3,
+
+ // Byte 16 - reserved
+
+ // Byte 17
+ FINE_TIMEBASE_START = 6,
+ FINE_TIMEBASE_LEN = 2,
+
+ MED_TIMEBASE_START = 4,
+ MED_TIMEBASE_LEN = 2,
+
+ // Byte 18 - Entire byte used
+ // Byte 19 - Entire byte used
+
+ // Byte 20-23
+ CAS_BYTE_1_START = 56,
+ CAS_BYTE_1_LEN = 8,
+ CAS_BYTE_2_START = 48,
+ CAS_BYTE_2_LEN = 8,
+ CAS_BYTE_3_START = 40,
+ CAS_BYTE_3_LEN = 8,
+ CAS_BYTE_4_START = 32,
+ CAS_BYTE_4_LEN = 8,
+
+ // Byte 24 - Entire byte used
+ // Byte 25 - Entire byte used
+ // Byte 26 - Entire byte used
+
+ // Byte 27
+ TRASMIN_MSN_START = 4, // MSN = most significant nibble
+ TRASMIN_MSN_LEN = 4,
+
+ TRCMIN_MSN_START = 0, // MSN = most significant nibble
+ TRCMIN_MSN_LEN = 4,
+
+ // Byte 28
+ TRASMIN_LSB_START = 0, // LSB = least significant byte
+ TRASMIN_LSB_LEN = 8,
+
+ // Byte 29
+ TRCMIN_LSB_START = 0, // LSB = least significant byte
+ TRCMIN_LSB_LEN = 8,
+
+ // Byte 30
+ TRFC1MIN_LSB_START = 0,
+ TRFC1MIN_LSB_LEN = 8,
+
+ // Byte 31
+ TRFC1MIN_MSB_START = 0,
+ TRFC1MIN_MSB_LEN = 8,
+
+ // Byte 32
+ TRFC2MIN_LSB_START = 0,
+ TRFC2MIN_LSB_LEN = 8,
+
+ // Byte 33
+ TRFC2MIN_MSB_START = 0,
+ TRFC2MIN_MSB_LEN = 8,
+
+ // Byte 34 & Byte 35
+ TRFC4MIN_LSB_START = 0,
+ TRFC4MIN_LSB_LEN = 8,
+
+ TRFC4MIN_MSB_START = 0,
+ TRFC4MIN_MSB_LEN = 8,
+
+ // Byte 36
+ TFAWMIN_MSN_START = 4,
+ TFAWMIN_MSN_LEN = 4,
+
+ // Byte 37
+ TFAWMIN_LSB_START = 0,
+ TFAWMIN_LSB_LEN = 8,
+
+ // Byte 38 - Entire byte used
+ // Byte 39 - Entire byte used
+ // Byte 40 - Entire byte used
+
+ // Byte 41
+ TWRMIN_MSN_START = 4, // MSN = most significant nibble
+ TWRMIN_MSN_LEN = 4,
+
+ // Byte 42
+ TWRMIN_LSB_START = 0, // LSB = least significant nibble
+ TWRMIN_LSB_LEN = 8,
+
+ // Byte 43
+ TWTRMIN_L_MSN_START = 0, // MSN = most significant nibble
+ TWTRMIN_L_MSN_LEN = 4,
+
+ TWTRMIN_S_MSN_START = 4, // MSN = most significant nibble
+ TWTRMIN_S_MSN_LEN = 4,
+
+ // Byte 44
+ TWTRMIN_S_LSB_START = 0, // LSB = least significant byte
+ TWTRMIN_S_LSB_LEN = 8,
+
+ // Byte 45
+ TWTRMIN_L_LSB_START = 0,
+ TWTRMIN_L_LSB_LEN = 8,
+
+ // Bytes 46 - 59 - reserved
+
+ // Bytes 60 - 77 - Connector to SDRAM Bit Mapping ??
+
+ // Bytes 78 - 116 - reserved
+
+ // Bytes 117 - 125 : Entire byte used
+
+ // Byte 126
+ CRC_LSB_START = 0,
+ CRC_LSB_LEN = 8,
+
+ // Byte 127
+ CRC_MSB_START = 0,
+ CRC_MSB_LEN = 8,
+
+ // Byte 320
+ // Skip SPD most signigicant bit, so our 0
+ MOD_MFG_LSB_START = 0,
+ MOD_MFG_LSB_LEN = 8,
+
+ // Byte 321
+ MOD_MFG_MSB_START = 0,
+ MOD_MFG_MSB_LEN = 8,
+
+ };
+
+ // First field is byte index
+ // Second field is the decoding start bit
+ // Third field is the decoding bit length
+ static constexpr field_t BYTES_USED{0, BYTES_USED_START, BYTES_USED_LEN};
+ static constexpr field_t TOTAL_BYTES_USED{0, BYTES_TOTAL_START, BYTES_TOTAL_LEN};
+ static constexpr field_t HYBRID_MEDIA{3, HYBRID_MEDIA_START, HYBRID_MEDIA_LEN};
+ static constexpr field_t HYBRID{3, HYBRID_START, HYBRID_LEN};
+ static constexpr field_t SDRAM_CAPACITY{4, SDRAM_CAPACITY_START, SDRAM_CAPACITY_LEN};
+ static constexpr field_t SDRAM_BANKS{4, SDRAM_BANKS_START, SDRAM_BANKS_LEN};
+ static constexpr field_t BANK_GROUP{4, BANK_GROUP_START, BANK_GROUP_LEN};
+ static constexpr field_t COL_ADDRESS{5, COL_ADDRESS_START, COL_ADDRESS_LEN};
+ static constexpr field_t ROW_ADDRESS{5, ROW_ADDRESS_START, ROW_ADDRESS_LEN};
+ static constexpr field_t PRIM_SIGNAL_LOADING{6, PRIM_SIGNAL_LOAD_START, PRIM_SIGNAL_LOAD_LEN};
+ static constexpr field_t PRIM_DIE_COUNT{6, PRIM_DIE_COUNT_START, PRIM_DIE_COUNT_LEN};
+ static constexpr field_t PRIM_PACKAGE_TYPE{6, PRIM_PACKAGE_TYPE_START, PRIM_PACKAGE_TYPE_LEN};
+ static constexpr field_t MAC{7, MAC_START, MAC_LEN};
+ static constexpr field_t TMAW{7, TMAW_START, TMAW_LEN};
+ static constexpr field_t PPR{9, PPR_START, PPR_LEN};
+ static constexpr field_t SOFT_PPR{9, SOFT_PPR_START, SOFT_PPR_LEN};
+ static constexpr field_t SEC_SIGNAL_LOADING{10, SEC_SIGNAL_LOAD_START, SEC_SIGNAL_LOAD_LEN};
+ static constexpr field_t SEC_DENSITY_RATIO{10, DENSITY_RATIO_START, DENSITY_RATIO_LEN};
+ static constexpr field_t SEC_DIE_COUNT{10, SEC_DIE_COUNT_START, SEC_DIE_COUNT_LEN};
+ static constexpr field_t SEC_PACKAGE_TYPE{10, SEC_PACKAGE_TYPE_START, SEC_PACKAGE_TYPE_LEN};
+ static constexpr field_t OPERABLE_FLD{11, OPERABLE_START, OPERABLE_LEN};
+ static constexpr field_t ENDURANT_FLD{11, ENDURANT_START, ENDURANT_LEN};
+ static constexpr field_t SDRAM_WIDTH{12, SDRAM_WIDTH_START, SDRAM_WIDTH_LEN};
+ static constexpr field_t RANK_MIX{12, RANK_MIX_START, RANK_MIX_LEN};
+ static constexpr field_t PACKAGE_RANKS{12, PACKAGE_RANKS_START, PACKAGE_RANKS_LEN};
+ static constexpr field_t BUS_WIDTH{13, BUS_WIDTH_START, BUS_WIDTH_LEN};
+ static constexpr field_t BUS_EXT_WIDTH{13, BUS_EXT_WIDTH_START, BUS_EXT_WIDTH_LEN};
+ static constexpr field_t THERM_SENSOR{14, THERM_SENSOR_START, THERM_SENSOR_LEN};
+ static constexpr field_t EXTENDED_MODULE_TYPE{15, EXT_MOD_TYPE_START, EXT_MOD_TYPE_LEN};
+ static constexpr field_t FINE_TIMEBASE{17, FINE_TIMEBASE_START, FINE_TIMEBASE_LEN};
+ static constexpr field_t MEDIUM_TIMEBASE{17, MED_TIMEBASE_START, MED_TIMEBASE_LEN};
+ static constexpr field_t TRASMIN_MSN{27, TRASMIN_MSN_START, TRASMIN_MSN_LEN};
+ static constexpr field_t TRASMIN_LSB{28, TRASMIN_LSB_START, TRASMIN_LSB_LEN};
+ static constexpr field_t TRCMIN_MSN{27, TRCMIN_MSN_START, TRCMIN_MSN_LEN};
+ static constexpr field_t TRCMIN_LSB{29, TRCMIN_LSB_START, TRCMIN_LSB_LEN};
+ static constexpr field_t TRFC1MIN_MSB{31, TRFC1MIN_MSB_START, TRFC1MIN_MSB_LEN};
+ static constexpr field_t TRFC1MIN_LSB{30, TRFC1MIN_LSB_START, TRFC1MIN_LSB_LEN};
+ static constexpr field_t TRFC2MIN_MSB{33, TRFC2MIN_MSB_START, TRFC2MIN_MSB_LEN};
+ static constexpr field_t TRFC2MIN_LSB{32, TRFC2MIN_LSB_START, TRFC2MIN_LSB_LEN};
+ static constexpr field_t TRFC4MIN_MSB{35, TRFC4MIN_MSB_START, TRFC4MIN_MSB_LEN};
+ static constexpr field_t TRFC4MIN_LSB{34, TRFC4MIN_LSB_START, TRFC4MIN_LSB_LEN};
+ static constexpr field_t TFAWMIN_MSN{36, TFAWMIN_MSN_START, TFAWMIN_MSN_LEN};
+ static constexpr field_t TFAWMIN_LSB{37, TFAWMIN_LSB_START, TFAWMIN_LSB_LEN};
+ static constexpr field_t TWRMIN_MSN{41, TWRMIN_MSN_START, TWRMIN_MSN_LEN};
+ static constexpr field_t TWRMIN_LSB{42, TWRMIN_LSB_START, TWRMIN_LSB_LEN};
+ static constexpr field_t TWTRMIN_S_MSN{43, TWTRMIN_S_MSN_START, TWTRMIN_S_MSN_LEN};
+ static constexpr field_t TWTRMIN_S_LSB{44, TWTRMIN_S_LSB_START, TWTRMIN_S_LSB_LEN};
+ static constexpr field_t TWTRMIN_L_MSN{43, TWTRMIN_L_MSN_START, TWTRMIN_L_MSN_LEN};
+ static constexpr field_t TWTRMIN_L_LSB{45, TWTRMIN_L_LSB_START, TWTRMIN_L_LSB_LEN};
+ static constexpr field_t CRC_MSB{127, CRC_MSB_START, CRC_MSB_LEN};
+ static constexpr field_t CRC_LSB{126, CRC_LSB_START, CRC_LSB_LEN};
+
+ ///
+ /// @brief Helper function that turns Logical ranks in Primary SDRAM type
+ /// @param[out] o_logical_ranks number of logical ranks
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode prim_sdram_logical_ranks( uint8_t& o_logical_ranks );
+
+ public:
+
+ // Default constructor deleted
+ decoder() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data SPD data vector
+ /// @param[in] i_module_decoder shared_ptr to dimm module decoder
+ /// @param[in] i_raw_card raw pointer to rcd data
+ ///
+ decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& i_module_decoder,
+ const rcw_settings& i_raw_card);
+
+ ///
+ /// @brief Default dtor
+ ///
+ virtual ~decoder() = default;
+
+ /////////////////////////
+ // Member Methods
+ /////////////////////////
+
+ ///
+ /// @brief Decodes number of used SPD bytes
+ /// @param[out] o_value number of SPD bytes used
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note Decodes SPD Byte 0 (3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 14
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode number_of_used_bytes( uint16_t& o_value ) override;
+
+ ///
+ /// @brief Decodes total number of SPD bytes
+ /// @param[out] o_value number of total SPD bytes
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note Decodes SPD Byte 0 (bits 6~4)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 14
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode number_of_total_bytes( uint16_t& o_value ) override;
+
+ ///
+ /// @brief Decodes hybrid media field from SPD
+ /// @param[out] o_value
+ /// @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
+ ///
+ virtual fapi2::ReturnCode hybrid_media( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes hybrid field from SPD
+ /// @param[out] o_value
+ /// @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
+ ///
+ virtual fapi2::ReturnCode hybrid( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM density from SPD
+ /// @param[out] o_value SDRAM density in GBs
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 4 (bits 3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 18
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sdram_density( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes number of SDRAM banks bits from SPD
+ /// @param[out] o_value Number of SDRAM bank bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 4 (bits 5~4)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 18
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode bank_bits( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes number of SDRAM bank groups bits from SPD
+ /// @param[out] o_value Number of SDRAM bank groups bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 4 (bits 7~6)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 18
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode bank_group_bits( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes number of SDRAM column address bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 5 (bits 2~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 18
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode column_address_bits( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes number of SDRAM row address bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 5 (bits 5~3)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 18
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode row_address_bits( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Primary SDRAM signal loading
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 6 (bits 1~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 19
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode prim_sdram_signal_loading( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Primary SDRAM die count
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 6 (bits 6~4)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 19
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode prim_sdram_die_count( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Primary SDRAM package type
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 6 (bit 7)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 19
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode prim_sdram_package_type( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode SDRAM Maximum activate count
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 7 (bits 3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 20
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode maximum_activate_count( uint32_t& o_value ) override;
+
+ ///
+ /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 7 (bits 3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 20
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode maximum_activate_window_multiplier( uint32_t& o_value ) override;
+
+ ///
+ /// @brief Decode Post package repair (PPR)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 9 (bits 7~6)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 21
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode post_package_repair( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode Soft post package repair (soft PPR)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 9 (bit 5)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 21
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary SDRAM signal loading
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bits 1~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary DRAM Density Ratio
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bits 3~2)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary SDRAM die count
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bits 6~4)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary SDRAM package type
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bit 7)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode Module Nominal Voltage, VDD
+ /// @param[out] o_value enum representing if 1.2V is operable
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 11 (bit 0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 23
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode operable_nominal_voltage( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode Module Nominal Voltage, VDD
+ /// @param[out] o_value enum representing if 1.2V is endurant
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 11 (bit 1)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 23
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode endurant_nominal_voltage( uint8_t& o_value ) override;
+ ///
+ /// @brief Decodes SDRAM device width
+ /// @param[out] o_value device width in bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 12 (bits 2~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 23
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode device_width( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes number of package ranks per DIMM
+ /// @param[out] o_value number of package ranks per DIMM
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 12 (bits 5~3)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 23
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Rank Mix
+ /// @param[out] o_value rank mix value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 12 (bit 6)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 23
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode rank_mix( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes primary bus width
+ /// @param[out] o_value primary bus width in bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 13 (bits 2~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 27
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode prim_bus_width( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes bus width extension
+ /// @param[out] o_value bus width extension in bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 13 (bits 4~3)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 27
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode bus_width_extension( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode Module Thermal Sensor
+ /// @param[out] o_value thermal sensor value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 14 (bit 7)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 28
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode thermal_sensor( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode Extended Base Module Type
+ /// @param[out] o_value extended base module type value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 15 (bits 3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 28
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode extended_base_module_type( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode Fine Timebase
+ /// @param[out] o_value fine_timebase from SPD in picoseconds
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 17 (bits 1~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 29
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_timebase( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decode Medium Timebase
+ /// @param[out] o_value fine_timebase from SPD in picoseconds
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 17 (bits 3~2)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 29
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode medium_timebase( int64_t& o_value ) override;
+
+ ///
+ ///
+ /// @brief Decodes SDRAM Minimum Cycle Time in MTB
+ /// @param[out] o_value tCKmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 18
+ /// @note Item JC-45-2220.01x
+ /// @note Page 31-32
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tCKmin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tCKmin (SPD byte 125)
+ /// used for correction to get the actual value.
+ ///
+ virtual fapi2::ReturnCode min_tck( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Maximum Cycle Time in MTB
+ /// @param[out] o_value tCKmax in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 19
+ /// @note Item JC-45-2220.01x
+ /// @note Page 32
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tCKmax cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tCKmax (SPD byte 124)
+ /// used for correction to get the actual value.
+ ///
+ virtual fapi2::ReturnCode max_tck( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decode CAS Latencies Supported
+ /// @param[out] o_value bitmap of supported CAS latencies
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Bytes 20-23
+ /// @note Item JC-45-2220.01x
+ /// @note Page 33-34
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB
+ /// @param[out] o_value tAAmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 24
+ /// @note Item JC-45-2220.01x
+ /// @note Page 34
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tAAmin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tAAmin (SPD byte 123)
+ /// used for correction to get the actual value.
+ ///
+ virtual fapi2::ReturnCode min_taa( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB
+ /// @param[out] o_value tRCDmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 25
+ /// @note Item JC-45-2220.01x
+ /// @note Page 35
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tRCDmin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tRCDmin (SPD byte 122)
+ /// used for correction to get the actual value
+ ///
+ virtual fapi2::ReturnCode min_trcd( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB
+ /// @param[out] o_value tRPmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 26
+ /// @note Item JC-45-2220.01x
+ /// @note Page 36-37
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tRPmin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tRPmin (SPD byte 121)
+ /// used for correction to get the actual value
+ ///
+ virtual fapi2::ReturnCode min_trp( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB
+ /// @param[out] o_value tRASmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 28 (bits 7~4) & SPD Byte 27 (bits 3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 38
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_tras( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB
+ /// @param[out] o_value tRCmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 38
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tRCmin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tRCmin (SPD byte 120)
+ /// used for correction to get the actual value.
+ ///
+ virtual fapi2::ReturnCode min_trc( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1
+ /// @param[out] o_value tRFC1min in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 30 & Byte 31
+ /// @note Item JC-45-2220.01x
+ /// @note Page 39-40
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_trfc1( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2
+ /// @param[out] o_value tRFC2min in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 32 & Byte 33
+ /// @note Item JC-45-2220.01x
+ /// @note Page 40
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_trfc2( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4
+ /// @param[out] o_value tRFC4min in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 34 & Byte 35
+ /// @note Item JC-45-2220.01x
+ /// @note Page 40
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_trfc4( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time
+ /// @param[out] o_value tFAWmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 42
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_tfaw( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group
+ /// @param[out] o_value tRRD_Smin MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 38
+ /// @note Item JC-45-2220.01x
+ /// @note Page 43
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tRRD_Smin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tRRD_Smin (SPD byte 119)
+ /// used for correction to get the actual value.
+ ///
+ virtual fapi2::ReturnCode min_trrd_s( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group
+ /// @param[out] o_value tRRD_Lmin MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 39
+ /// @note Item JC-45-2220.01x
+ /// @note Page 43-44
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tRRD_Lmin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tRRD_Lmin (SPD byte 118)
+ /// used for correction to get the actual value.
+ ///
+ virtual fapi2::ReturnCode min_trrd_l( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group
+ /// @param[out] o_value tCCD_Lmin MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 40
+ /// @note Item JC-45-2220.01x
+ /// @note Page 44-45
+ /// @note DDR4 SPD Document Release 3
+ /// @warning If tCCD_Lmin cannot be divided evenly by the MTB,
+ /// this byte must be rounded up to the next larger
+ /// integer and the Fine Offset for tCCD_Lmin (SPD byte 117)
+ /// used for correction to get the actual value.
+ ///
+ virtual fapi2::ReturnCode min_tccd_l( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum Write Recovery Time
+ /// @param[out] o_value tWRmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 40
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_twr( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Different Bank Group
+ /// @param[out] o_value tWRT_Smin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 40
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_twtr_s( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Same Bank Group
+ /// @param[out] o_value tWRT_Lmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 46
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group
+ /// @param[out] o_value tCCD_Lmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 117
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_tccd_l( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group
+ /// @param[out] o_value tRRD_Lmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 118
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trrd_l( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+ /// @param[out] o_value tRRD_Smin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 119
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trrd_s( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time
+ /// @param[out] o_value tRCmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 120
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trc( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time
+ /// @param[out] o_value tRPmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 121
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trp( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+ /// @param[out] o_value tRCDmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 122
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trcd( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time
+ /// @param[out] o_value tAAmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 123
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_taa( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time
+ /// @param[out] o_value tCKmax offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 124
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_max_tck( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time
+ /// @param[out] o_value tCKmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 125
+ /// @note Item JC-45-2220.01x
+ /// @note Page 52
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_tck( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section
+ /// @param[out] o_value crc value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 127 & Byte 126
+ /// @note Item JC-45-2220.01x
+ /// @note Page 53
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode cyclical_redundancy_code( uint16_t& o_value ) override;
+
+ ///
+ /// @brief Decodes module manufacturer ID code
+ /// @param[out] o_output module manufacturing id code
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 320 (bit 7~0), 321 (6~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12 - 54
+ ///
+ virtual fapi2::ReturnCode module_manufacturer_id_code( uint16_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Module Manufacturing Location
+ /// @param[out] o_value uint8_t identifier for manufacturing location of memory module
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 322
+ /// @note Item JC-45-2220.01x
+ /// @note Page 55
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode module_manufacturing_location( uint8_t& o_value ) override;
+ ///
+ /// @brief Decodesmodule manufacturing date
+ /// @param[out] o_output the 2 byte date of manufacturing in BCD format
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 323 & 324
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 54
+ /// @note in Binary Coded Decimal (BCD)
+ /// @note MSB = year, LSB = week
+ ///
+ virtual fapi2::ReturnCode module_manufacturing_date( uint16_t& o_output ) override;
+
+ ///
+ /// @brief Decodes module's unique serial number
+ /// @param[out] o_output
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 325-328
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 54
+ ///
+ virtual fapi2::ReturnCode module_serial_number( uint32_t& o_output ) override;
+
+ ///
+ /// @brief Decodes Module Revision Code
+ /// @param[out] o_value uint8_t identifier for revision code
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 349
+ /// @note Item JC-45-2220.01x
+ /// @note Page 55
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode module_revision_code( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes DRAM Manufacturer ID code
+ /// @param[out] o_output dram manufacturing id code
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 350 - 351
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 54
+ ///
+ virtual fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_output ) override;
+ ///
+ /// @brief Decodes DRAM Stepping
+ /// @param[out] o_value uint8_t DRAM Stepping val
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 352
+ /// @note Item JC-45-2220.01x
+ /// @note Page 56
+ /// @note DDR4 SPD Document Release 3
+ /// @note also called die revision level
+ ///
+ virtual fapi2::ReturnCode dram_stepping( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Returns Logical ranks per DIMM
+ /// @param[out] o_logical_ranks number of logical ranks
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) override;
+
+};// decoder
+
+///
+/// @class decoder_v1_1
+/// @brief Base SPD DRAM decoder, 1st addition to general section
+///
+class decoder_v1_1 : public decoder
+{
+ protected:
+
+ ///
+ /// @brief Helper functions that returns Logical ranks in Secondary SDRAM type
+ /// @param[out] o_logical_ranks number of logical ranks
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sec_sdram_logical_ranks( uint8_t& o_logical_ranks );
+
+ public:
+ ///
+ /// @brief Default constructor
+ ///
+ decoder_v1_1() = default;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data SPD data vector
+ /// @param[in] i_module_decoder shared_ptr to dimm module decoder
+ /// @param[in] i_raw_card raw pointer to rcd data
+ ///
+ decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& i_module_decoder,
+ const rcw_settings& i_raw_card);
+
+ ///
+ /// @brief Default dtor
+ ///
+ virtual ~decoder_v1_1() = default;
+
+ /////////////////////////
+ // Member Methods
+ /////////////////////////
+
+ ///
+ /// @brief Decodes hybrid media field from SPD
+ /// @param[out] o_value
+ /// @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
+ ///
+ virtual fapi2::ReturnCode hybrid_media( uint8_t& o_value) override;
+
+ ///
+ /// @brief Decodes hybrid field from SPD
+ /// @param[out] o_value
+ /// @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
+ ///
+ virtual fapi2::ReturnCode hybrid( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes SDRAM density from SPD
+ /// @param[out] o_value SDRAM density in GBs
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 4 (bits 3~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 18
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sdram_density( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode Soft post package repair (soft PPR)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 9 (bit 5)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 21
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary SDRAM signal loading
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bits 1~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary DRAM Density Ratio
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bits 3~2)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary SDRAM die count
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bits 6~4)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Secondary SDRAM package type
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 10 (bit 7)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 22
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes number of package ranks per DIMM
+ /// @param[out] o_value number of package ranks per DIMM
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 12 (bits 5~3)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 23
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Rank Mix
+ /// @param[out] o_value rank mix value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 12 (bit 6)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 23
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode rank_mix( uint8_t& o_value ) override;
+
+ ///
+ /// @brief Decode CAS Latencies Supported
+ /// @param[out] o_value bitmap of supported CAS latencies
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Bytes 20-23
+ /// @note Item JC-45-2220.01x
+ /// @note Page 33-34
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value) override;
+
+ ///
+ /// @brief Decodes Minimum Write Recovery Time
+ /// @param[out] o_value tWRmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 40
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_twr( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Different Bank Group
+ /// @param[out] o_value tWRT_Smin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 40
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_twtr_s( int64_t& o_value ) override;
+
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Same Bank Group
+ /// @param[out] o_value tWRT_Lmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 46
+ /// @note DDR4 SPD Document Release 3
+ ///
+ virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value ) override;
+
+ ///
+ /// @brief Returns Logical ranks per DIMM
+ /// @param[out] o_logical_ranks number of logical ranks
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) override;
+
+};// spd_decoder_v1_1
+
+}// spd
+}// mss
+
+#endif //_MSSS_PD_DECODER_H_
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
new file mode 100644
index 000000000..ff265a585
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C
@@ -0,0 +1,2942 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_0.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file spd_decoder.C
+/// @brief SPD decoder definitions
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <map>
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#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>
+
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+namespace mss
+{
+namespace spd
+{
+
+/////////////////////////
+// Member Method implementation
+/////////////////////////
+
+///
+/// @brief ctor
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data vector
+/// @param[in] i_module_decoder shared_ptr to dimm module decoder
+/// @param[in] i_raw_card raw card data structure
+///
+decoder::decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& i_module_decoder,
+ const rcw_settings& i_raw_card)
+ : base_decoder(i_target, i_spd_data, i_module_decoder, i_raw_card)
+{}
+
+///
+/// @brief Decodes number of used SPD bytes
+/// @param[out] o_value number of SPD bytes used
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 0 bits(0~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 14
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::number_of_used_bytes( uint16_t& o_value )
+{
+ // =========================================================
+ // Byte 0 maps
+ // Item JC-45-2220.01x
+ // Page 14
+ // DDR4 SPD Document Release 3
+ // Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_USED_MAP =
+ {
+ //{key byte, number of used bytes}
+ {1, 128},
+ {2, 256},
+ {3, 384},
+ {4, 512}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< BYTES_USED >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(BYTES_USED_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ BYTES_USED.iv_byte,
+ l_field_bits,
+ "Failed check on SPD used bytes") );
+
+ FAPI_INF("%s. Bytes Used: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes total number of SPD bytes
+/// @param[out] o_value number of total SPD bytes
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 0 (bits 4~6)
+/// @note Item JC-45-2220.01x
+/// @note Page 14
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::number_of_total_bytes( uint16_t& o_value )
+{
+
+ // =========================================================
+ // Byte 0 maps
+ // Item JC-45-2220.01x
+ // Page 14
+ // DDR4 SPD Document Release 3
+ // Byte 0 (0x000): Number of Bytes Used / Number of Bytes in SPD Device
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint16_t> > BYTES_TOTAL_MAP =
+ {
+ //{key byte, number of total bytes}
+ {1, 256},
+ {2, 512}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< TOTAL_BYTES_USED >(iv_target, iv_spd_data);
+ FAPI_DBG("Field_Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(BYTES_TOTAL_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ TOTAL_BYTES_USED.iv_byte,
+ l_field_bits,
+ "Failed check on SPD total bytes") );
+
+ FAPI_INF("%s. Total Bytes: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes hybrid media field from SPD
+/// @param[out] o_value enum representing hybrid memory type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 3 (bits 4~6)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::hybrid_media( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // Decodes SPD Byte 3 (bits 4~6) were reserved
+ // and coded as zeros. There was no concept of hybrid media so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+}
+
+///
+/// @brief Decodes hybrid field from SPD
+/// @param[out] o_value enum representing if module is hybrid
+/// @return fapi2::ReturnCode
+/// @note Decodes SPD Byte 3 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::hybrid( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // Decodes SPD Byte 3 (bit 7) were reserved
+ // and coded as zeros. There was no concept of hybrid media so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes SDRAM density from SPD
+/// @param[out] o_value SDRAM density in GBs
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 4 (bits 0~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::sdram_density( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 4 maps
+ // Item JC-45-2220.01x
+ // Page 18
+ // DDR4 SPD Document Release 3
+ // Byte 4 (0x004): SDRAM Density and Banks
+ // =========================================================
+ static const std::vector< std::pair<uint8_t, uint8_t> > SDRAM_DENSITY_MAP =
+ {
+ // {key byte, capacity in GBs}
+ {2, 1},
+ {3, 2},
+ {4, 4},
+ {5, 8},
+ {6, 16},
+ {7, 32},
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SDRAM_CAPACITY >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ bool l_is_val_found = mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SDRAM_CAPACITY.iv_byte,
+ l_field_bits,
+ "Failed check for SPD DRAM capacity") );
+
+ FAPI_INF("%s. SDRAM density: %d Gb",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of SDRAM bank_bits from SPD
+/// @param[out] o_value Number of SDRAM bank bits
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 4 (bits 5~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::bank_bits( uint8_t& o_value)
+
+{
+ // =========================================================
+ // Byte 4 maps
+ // Item JC-45-2220.01x
+ // Page 18
+ // DDR4 SPD Document Release 3
+ // Byte 4 (0x004): SDRAM Density and Banks
+ // =========================================================
+ static const std::vector< std::pair<uint8_t, uint8_t> > BANK_ADDR_BITS_MAP =
+ {
+ // {key byte, number of bank address bits}
+ {0, 2},
+ {1, 3}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SDRAM_BANKS >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ bool l_is_val_found = mss::find_value_from_key(BANK_ADDR_BITS_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SDRAM_BANKS.iv_byte,
+ l_field_bits,
+ "Failed check for SPD DRAM banks") );
+
+ FAPI_INF("%s. Number of banks address bits: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of SDRAM bank group bits from SPD
+/// @param[out] o_value Number of SDRAM bank group bits
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 4 (bits 6~7)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::bank_group_bits( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 4 maps
+ // Item JC-45-2220.01x
+ // Page 18
+ // DDR4 SPD Document Release 3
+ // Byte 4 (0x004): SDRAM Density and Banks
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > BANK_GROUP_BITS_MAP =
+ {
+ // {key byte, number of bank groups bits}
+ {0, 0},
+ {1, 1},
+ {2, 2}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< BANK_GROUP >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ bool l_is_val_found = mss::find_value_from_key(BANK_GROUP_BITS_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ BANK_GROUP.iv_byte,
+ l_field_bits,
+ "Failed check for SPD DRAM bank groups") );
+
+ FAPI_INF("%s. Number of bank group bits: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of SDRAM column address bits
+/// @param[out] o_value number of column address bits
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 5 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::column_address_bits( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 5 maps
+ // Item JC-45-2220.01x
+ // Page 18
+ // DDR4 SPD Document Release 3
+ // Byte 5 (0x005): SDRAM Addressing
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > COLUMN_ADDRESS_BITS_MAP =
+ {
+ //{key byte,col address bits}
+ {0, 9},
+ {1, 10},
+ {2, 11},
+ {3, 12}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< COL_ADDRESS >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ bool l_is_val_found = mss::find_value_from_key(COLUMN_ADDRESS_BITS_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ COL_ADDRESS.iv_byte,
+ l_field_bits,
+ "Failed check for SDRAM Column Address Bits") );
+
+ FAPI_INF("%s. Number of Column Address Bits: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of SDRAM row address bits
+/// @param[out] o_value number of row address bits
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 5 (bits 5~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::row_address_bits( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 5 maps
+ // Item JC-45-2220.01x
+ // Page 18
+ // DDR4 SPD Document Release 3
+ // Byte 5 (0x005): SDRAM Addressing
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > ROW_ADDRESS_BITS_MAP =
+ {
+ //{key byte,row address bits}
+ {0, 12},
+ {1, 13},
+ {2, 14},
+ {3, 15},
+ {4, 16},
+ {5, 17},
+ {6, 18}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< ROW_ADDRESS >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ bool l_is_val_found = mss::find_value_from_key(ROW_ADDRESS_BITS_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ ROW_ADDRESS.iv_byte,
+ l_field_bits,
+ "Failed check for SDRAM Row Address Bits") );
+
+ FAPI_INF("%s. Number of Row Address Bits: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes Primary SDRAM signal loading
+/// @param[out] o_value enum representing signal loading type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 6 (bits 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 19
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::prim_sdram_signal_loading( uint8_t& o_value)
+{
+ // =========================================================
+ // 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_SIGNAL_LOADING_MAP =
+ {
+ // {key byte, signal loading}
+ {0, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_SDP},
+ {1, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_DDP_QDP},
+ {2, fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< PRIM_SIGNAL_LOADING >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(PRIM_SIGNAL_LOADING_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ PRIM_SIGNAL_LOADING.iv_byte,
+ l_field_bits,
+ "Failed check for Primary SDRAM Signal Loading") );
+
+ FAPI_INF("%s. Primary SDRAM Signal Loading: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Primary SDRAM die count
+/// @param[out] o_value die count
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 6 (bits 6~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 19
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::prim_sdram_die_count( uint8_t& o_value)
+{
+ // =========================================================
+ // 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, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< PRIM_DIE_COUNT >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ PRIM_DIE_COUNT.iv_byte,
+ l_field_bits,
+ "Failed check for SDRAM Row Address Bits") );
+
+ FAPI_INF("%s. Number of Row Address Bits: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Primary SDRAM package type
+/// @param[out] o_value enum representing package type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 6 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 19
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::prim_sdram_package_type( uint8_t& o_value)
+{
+ // =========================================================
+ // 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_PACKAGE_TYPE_MAP =
+ {
+ // {key byte, value}
+ {0, MONOLITHIC},
+ {1, NON_MONOLITHIC}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< PRIM_PACKAGE_TYPE >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(PRIM_PACKAGE_TYPE_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ PRIM_PACKAGE_TYPE.iv_byte,
+ l_field_bits,
+ "Failed check for Primary SDRAM package type") );
+
+ FAPI_INF("%s. Primary SDRAM package type: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decode SDRAM Maximum activate count
+/// @param[out] o_value enum representing max activate count
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 7 (bits 3~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 20
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::maximum_activate_count( uint32_t& o_value )
+{
+ // =========================================================
+ // Byte 7 maps
+ // Item JC-45-2220.01x
+ // Page 20
+ // DDR4 SPD Document Release 3
+ // Byte 7 (0x007): SDRAM Optional Features
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint32_t> > MAC_MAP =
+ {
+ // {key byte, maximum activate count}
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNTESTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_MAC_700K},
+ {2, fapi2::ENUM_ATTR_EFF_DRAM_MAC_600K},
+ {3, fapi2::ENUM_ATTR_EFF_DRAM_MAC_500K},
+ {4, fapi2::ENUM_ATTR_EFF_DRAM_MAC_400K},
+ {5, fapi2::ENUM_ATTR_EFF_DRAM_MAC_300K},
+ {6, fapi2::ENUM_ATTR_EFF_DRAM_MAC_200K},
+ {8, fapi2::ENUM_ATTR_EFF_DRAM_MAC_UNLIMITED}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< MAC >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(MAC_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ MAC.iv_byte,
+ l_field_bits,
+ "Failed check for SDRAM Maximum Active Count (MAC)") );
+
+ FAPI_INF("%s. Maximum Active Count (MAC): %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point
+/// @param[out] o_value max activate window multiplier
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 7 (bits 3~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 20
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::maximum_activate_window_multiplier( uint32_t& o_value )
+{
+ // =========================================================
+ // Byte 7 maps
+ // Item JC-45-2220.01x
+ // Page 20
+ // DDR4 SPD Document Release 3
+ // Byte 7 (0x007): SDRAM Optional Features
+ // =========================================================
+ // Multiplier with tREFI is not taken into account here
+ static const std::vector<std::pair<uint8_t, uint32_t> > TMAW_MAP =
+ {
+ // {key byte, tMAW multiplier}
+ {0, 8192},
+ {1, 4096},
+ {2, 2048}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< TMAW >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(TMAW_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ TMAW.iv_byte,
+ l_field_bits,
+ "Failed check for Maximum Active Window (tMAW)") );
+
+ FAPI_INF("%s. Maximum Active Window multiplier: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode Post package repair (PPR)
+/// @param[out] o_value enum representing if (hard) PPR is supported
+/// @return fapi2::ReturnCode
+/// @note SPD Byte 9 (bits 7~6)
+/// @note Item JC-45-2220.01x
+/// @note Page 21
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::post_package_repair( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 9 maps
+ // Item JC-45-2220.01x
+ // Page 21
+ // DDR4 SPD Document Release 3
+ // Byte 9 (0x009): Other SDRAM Optional Features
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > PPR_MAP =
+ {
+ // {key byte, value }
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_PPR_NOT_SUPPORTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_PPR_SUPPORTED}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< PPR >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(PPR_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ PPR.iv_byte,
+ l_field_bits,
+ "Failed check for PPR") );
+
+ FAPI_INF("%s. Post Package Repair (PPR): %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Secondary SDRAM signal loading
+/// @param[out] o_value enum representing signal loading type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bits 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::sec_sdram_signal_loading( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 10 (bits 1~0) were reserved
+ // and coded as zeros. There was no concept of
+ // secondary SDRAM signal loading so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decode Soft post package repair (soft PPR)
+/// @param[out] o_value enum representing if soft PPR is supported
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 9 (bit 5)
+/// @note Item JC-45-2220.01x
+/// @note Page 21
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::soft_post_package_repair( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 9 (bit 5) was reserved
+ // and coded as zeros. There was no concept of soft PPR so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes Secondary DRAM Density Ratio
+/// @param[out] o_value raw bits from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bits 3~2)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::sec_dram_density_ratio( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 10 (bits 3~2) were reserved
+ // and coded as zeros. There was no concept of
+ // secondary SDRAM density ratio so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes Secondary SDRAM die count
+/// @param[out] o_value die count
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bits 6~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::sec_sdram_die_count( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 10 (bits 6~4) were reserved
+ // and coded as zeros. There was no concept of
+ // secondary SDRAM hybrid media so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes Secondary SDRAM package type
+/// @param[out] o_value enum representing package type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::sec_sdram_package_type( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 10 (bit 7) was reserved
+ // and coded as zeros. There was no concept of
+ // secondary SDRAM package type so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decode Module Nominal Voltage, VDD
+/// @param[out] o_value enum representing if 1.2V is operable
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 11 (bit 0)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::operable_nominal_voltage( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 11 maps
+ // Item JC-45-2220.01x
+ // Page 22-23
+ // DDR4 SPD Document Release 3
+ // Byte 11 (0x00B): Modle Nominal Voltage
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > OPERABLE_MAP =
+ {
+ // {key byte, value }
+ {0, NOT_OPERABLE },
+ {1, OPERABLE}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< OPERABLE_FLD >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(OPERABLE_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ OPERABLE_FLD.iv_byte,
+ l_field_bits,
+ "Failed check for Operable nominal voltage") );
+
+ FAPI_INF("%s. Operable: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode Module Nominal Voltage, VDD
+/// @param[out] o_value enum representing if 1.2V is endurant
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 11 (bit 1)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::endurant_nominal_voltage( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 11 maps
+ // Item JC-45-2220.01x
+ // Page 22-23
+ // DDR4 SPD Document Release 3
+ // Byte 11 (0x00B): Modle Nominal Voltage
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > ENDURANT_MAP =
+ {
+ // {key byte, value }
+ {0, NOT_ENDURANT},
+ {1, ENDURANT}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< ENDURANT_FLD >(iv_target, iv_spd_data);
+
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(ENDURANT_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ ENDURANT_FLD.iv_byte,
+ l_field_bits,
+ "Failed check for Endurant nominal voltage") );
+
+ FAPI_INF("%s. Endurant: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes SDRAM device width
+/// @param[out] o_value device width in bits
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 12 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::device_width( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 12 maps
+ // Item JC-45-2220.01x
+ // Page 23
+ // DDR4 SPD Document Release 3
+ // Byte 12 (0x00C): Module Organization
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP =
+ {
+ // {key byte, device width (bits)}
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8},
+ {2, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16},
+ {3, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X32},
+ // All others reserved
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SDRAM_WIDTH >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(DEVICE_WIDTH_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SDRAM_WIDTH.iv_byte,
+ l_field_bits,
+ "Failed check for Device Width") );
+
+ FAPI_INF("%s. Device Width: %d bits",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes number of package ranks per DIMM
+/// @param[out] o_value number of package ranks per DIMM
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 12 (bits 5~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::num_package_ranks_per_dimm( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 12 maps
+ // Item JC-45-2220.01x
+ // Page 23
+ // DDR4 SPD Document Release 3
+ // 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, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< PACKAGE_RANKS >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ PACKAGE_RANKS.iv_byte,
+ l_field_bits,
+ "Failed check for Num Package Ranks Per DIMM") );
+
+ FAPI_INF("%s. Num Package Ranks per DIMM: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Rank Mix
+/// @param[out] o_value rank mix value from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 12 (bit 6)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::rank_mix( uint8_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // Decodes SPD Byte 3 (bits 4~6) were reserved
+ // and coded as zeros. There was no concept of rank_mix so this
+ // is thus hard-wired to zero.
+ o_value = 0x00;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+}
+
+///
+/// @brief Decodes primary bus width
+/// @param[out] o_value primary bus width in bits
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 13 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 27
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::prim_bus_width( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 13 maps
+ // Item JC-45-2220.01x
+ // Page 27
+ // DDR4 SPD Document Release 3
+ // Byte 13 (0x00D): Module Memory Bus Width
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP =
+ {
+ // {key byte, bus width (in bits)
+ {0, 8},
+ {1, 16},
+ {2, 32},
+ {3, 64}
+ // All others reserved
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< BUS_WIDTH >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ BUS_WIDTH.iv_byte,
+ l_field_bits,
+ "Failed check for Primary Bus Width") );
+
+ FAPI_INF("%s. Primary Bus Width: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes bus width extension
+/// @param[out] o_value bus width extension in bits
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 13 (bits 2~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 28
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::bus_width_extension( uint8_t& o_value)
+{
+ // =========================================================
+ // Byte 13 maps
+ // Item JC-45-2220.01x
+ // Page 27
+ // DDR4 SPD Document Release 3
+ // Byte 13 (0x00D): Module Memory Bus Width
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_EXT_MAP =
+ {
+ {0, 0},
+ {1, 8}
+ // All others reserved
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< BUS_EXT_WIDTH >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(BUS_WIDTH_EXT_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ BUS_EXT_WIDTH.iv_byte,
+ l_field_bits,
+ "Failed check for Bus Width Extension") );
+
+ FAPI_INF("%s. Bus Width Extension (bits): %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decode Module Thermal Sensor
+/// @param[out] o_value thermal sensor value from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 14 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 28
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::thermal_sensor( uint8_t& o_value)
+{
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< THERM_SENSOR >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check for valid value
+ constexpr size_t INVALID_VALUE = 2; // single bit value 0 or 1
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < INVALID_VALUE,
+ THERM_SENSOR.iv_byte,
+ l_field_bits,
+ "Failed check for Thermal Sensor") );
+
+ // Update output after check passes
+ o_value = l_field_bits;
+
+ FAPI_INF("%s. Thermal Sensor: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode Extended Base Module Type
+/// @param[out] o_value raw data from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 15 (bits 3~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 28
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::extended_base_module_type( uint8_t& o_value)
+{
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< EXTENDED_MODULE_TYPE >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check for valid value
+ // Currently reserved to 0b000
+ constexpr size_t RESERVED = 0;
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits == RESERVED,
+ EXTENDED_MODULE_TYPE.iv_byte,
+ l_field_bits,
+ "Failed check for Extended Base Module Type") );
+
+ // Update output for check passes
+ o_value = l_field_bits;
+
+ FAPI_INF("%s. Extended Base Module Type: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decode Fine Timebase
+/// @param[out] o_value fine_timebase from SPD in picoseconds
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 17 (bits 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 29
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_timebase( int64_t& o_value)
+{
+ // =========================================================
+ // Byte 17 maps
+ // Item JC-45-2220.01x
+ // Page 29
+ // DDR4 SPD Document Release 3
+ // Byte 17 (0x011): Timebases
+ // =========================================================
+ // Created a maps of a single value in case mapping expands to more values
+ static const std::vector<std::pair<uint8_t, int64_t> > FINE_TIMEBASE_MAP =
+ {
+ // {key byte, fine timebase (in picoseconds)
+ {0, 1}
+ // All others reserved
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< FINE_TIMEBASE >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(FINE_TIMEBASE_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ FINE_TIMEBASE.iv_byte,
+ l_field_bits,
+ "Failed check for Fine Timebase") );
+
+ FAPI_INF("%s. Fine Timebase: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode Medium Timebase
+/// @param[out] o_value medium timebase from SPD in picoseconds
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 17 (bits 3~2)
+/// @note Item JC-45-2220.01x
+/// @note Page 29
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::medium_timebase( int64_t& o_value)
+{
+ // =========================================================
+ // Byte 17 maps
+ // Item JC-45-2220.01x
+ // Page 29
+ // DDR4 SPD Document Release 3
+ // Byte 17 (0x011): Timebases
+ // =========================================================
+ // Created a maps of a single value in case mapping expands to more values
+ static const std::vector<std::pair<uint8_t, int64_t> > MEDIUM_TIMEBASE_MAP =
+ {
+ // {key byte, medium timebase (in picoseconds)
+ {0, 125}
+ // All others reserved
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< MEDIUM_TIMEBASE >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(MEDIUM_TIMEBASE_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ MEDIUM_TIMEBASE.iv_byte,
+ l_field_bits,
+ "Failed check for Medium Timebase") );
+
+ FAPI_INF("%s. Medium Timebase: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes SDRAM Minimum Cycle Time in MTB
+/// @param[out] o_value tCKmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 18
+/// @note Item JC-45-2220.01x
+/// @note Page 31-32
+/// @note DDR4 SPD Document Release 3
+/// @warning If tCKmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tCKmin (SPD byte 125)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::min_tck( int64_t& o_value )
+{
+ // Explicit conversion
+ constexpr size_t BYTE_INDEX = 18;
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: %d.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_timing_val);
+
+ // Check if value is valid
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the min cycle time (tckmin) in MTB") );
+
+ // Update output after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Cycle Time (tCKmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes SDRAM Maximum Cycle Time in MTB
+/// @param[out] o_value tCKmax in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 19
+/// @note Item JC-45-2220.01x
+/// @note Page 32
+/// @note DDR4 SPD Document Release 3
+/// @warning If tCKmax cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tCKmax (SPD byte 124)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::max_tck( int64_t& o_value )
+{
+ // Explicit conversion
+ constexpr size_t BYTE_INDEX = 19;
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: %d.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_timing_val);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the max cycle time (tckmax) in MTB") );
+
+ // Update output after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Maximum Cycle Time (tCKmax) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decode CAS Latencies Supported
+/// @param[out] o_value bitmap of supported CAS latencies
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Bytes 20-23
+/// @note Item JC-45-2220.01x
+/// @note Page 33-34
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::supported_cas_latencies( uint64_t& o_value )
+{
+ // Trace print in the front assists w/ debug
+ constexpr size_t FIRST_BYTE = 20;
+ uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ FIRST_BYTE,
+ first_raw_byte);
+
+ constexpr size_t SEC_BYTE = 21;
+ uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ SEC_BYTE,
+ sec_raw_byte);
+
+ constexpr size_t THIRD_BYTE = 22;
+ uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ THIRD_BYTE,
+ third_raw_byte);
+
+ constexpr size_t FOURTH_BYTE = 23;
+ uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ FOURTH_BYTE,
+ fourth_raw_byte);
+
+ // Buffers used for bit manipulation
+ // Combine Bytes to create bitmap - right aligned
+ fapi2::buffer<uint64_t> l_buffer;
+
+ l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(first_raw_byte)
+ .insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(sec_raw_byte)
+ .insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(third_raw_byte)
+ .insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(fourth_raw_byte);
+
+ // According to the JEDEC spec:
+ // Byte 22 (Bits 7~0) and Byte 23 are reserved and thus not supported
+ constexpr size_t MAX_VALID_VAL = 0x3FFFF;
+
+ // Check for a valid value
+ uint64_t l_supported_cl = l_buffer;
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_supported_cl <= MAX_VALID_VAL,
+ FOURTH_BYTE,
+ fourth_raw_byte,
+ "Failed check on CAS latencies supported") );
+
+ // Update output value only if range check passes
+ o_value = l_supported_cl;
+
+ FAPI_INF("%s. CAS latencies supported (bitmap): 0x%llX",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes SDRAM Minimum CAS Latency Time in MTB
+/// @param[out] o_value tAAmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 24
+/// @note Item JC-45-2220.01x
+/// @note Page 34
+/// @note DDR4 SPD Document Release 3
+/// @warning If tAAmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tAAmin (SPD byte 123)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::min_taa( int64_t& o_value )
+{
+ // Explicit conversion
+ constexpr size_t BYTE_INDEX = 24;
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_timing_val);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum CAS Latency Time (tAAmin) in MTB") );
+
+ // Only update output if it passes check
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum CAS Latency Time (tAAmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB
+/// @param[out] o_value tRCDmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 25
+/// @note Item JC-45-2220.01x
+/// @note Page 35
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRCDmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRCDmin (SPD byte 122)
+/// used for correction to get the actual value
+///
+fapi2::ReturnCode decoder::min_trcd( int64_t& o_value )
+{
+ // Explicit conversion
+ constexpr size_t BYTE_INDEX = 25;
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_timing_val);
+
+ // Find valid value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum RAS to CAS Delay Time (tRCDmin) in MTB") );
+
+ // Only update output if it passes check
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum RAS to CAS Delay Time (tRCDmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB
+/// @param[out] o_value tRPmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 26
+/// @note Item JC-45-2220.01x
+/// @note Page 36-37
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRPmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRPmin (SPD byte 121)
+/// used for correction to get the actual value
+///
+fapi2::ReturnCode decoder::min_trp( int64_t& o_value )
+{
+ // Explicit conversion
+ constexpr size_t BYTE_INDEX = 26;
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_timing_val);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Row Precharge Delay Time (tRPmin) in MTB") );
+
+ // Only update output if it passes check
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Row Precharge Delay Time (tRPmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB
+/// @param[out] o_value tRASmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 27 (bits 3~0) & Byte 28 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 38
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_tras( int64_t& o_value)
+{
+ uint8_t tRASmin_MSN = extract_spd_field< TRASMIN_MSN >(iv_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tRASmin_MSN);
+
+ uint8_t tRASmin_LSB = extract_spd_field< TRASMIN_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tRASmin_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRASmin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( tRASmin_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // But byte 28 of the JEDEC spec explains how to piece this together - AAM
+ constexpr size_t ERROR_BYTE_INDEX = 28;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Active to Precharge Delay Time (tRASmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Active to Precharge Delay Time (tRASmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB
+/// @param[out] o_value tRCmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 27 (bits 7~4) & SPD Byte 29 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 38
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRCmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRCmin (SPD byte 120)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::min_trc( int64_t& o_value)
+{
+ uint8_t tRCmin_MSN = extract_spd_field< TRCMIN_MSN >(iv_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tRCmin_MSN);
+
+ uint8_t tRCmin_LSB = extract_spd_field< TRCMIN_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tRCmin_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRCmin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( tRCmin_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // But byte 29 of the JEDEC spec explains how to piece this together - AAM
+ constexpr size_t ERROR_BYTE_INDEX = 29;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Active to Active/Refresh Delay Time (tRCmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1
+/// @param[out] o_value tRFC1min in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 30 & Byte 31
+/// @note Item JC-45-2220.01x
+/// @note Page 39-40
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_trfc1( int64_t& o_value)
+{
+ uint8_t tRFC1min_MSB = extract_spd_field< TRFC1MIN_MSB >(iv_target, iv_spd_data);
+ FAPI_INF("MSB Field Bits value: %lu", tRFC1min_MSB);
+
+ uint8_t tRFC1min_LSB = extract_spd_field< TRFC1MIN_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tRFC1min_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSB_START = 48;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC1min_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( tRFC1min_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 30) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 30;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Refresh Recovery Delay Time 1 (tRFC1min) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2
+/// @param[out] o_value tRFC2min in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 32 & Byte 33
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_trfc2( int64_t& o_value)
+{
+ uint8_t tRFC2min_MSB = extract_spd_field< TRFC2MIN_MSB >(iv_target, iv_spd_data);
+ FAPI_INF("MSB Field Bits value: %lu", tRFC2min_MSB);
+
+ uint8_t tRFC2min_LSB = extract_spd_field< TRFC2MIN_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tRFC2min_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSB_START = 48;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC2min_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( tRFC2min_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 33) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 33;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Refresh Recovery Delay Time 2 (tRFC2min) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4
+/// @param[out] o_value tRFC4min in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 34 & Byte 35
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_trfc4( int64_t& o_value)
+{
+ uint8_t tRFC4min_MSB = extract_spd_field< TRFC4MIN_MSB >(iv_target, iv_spd_data);
+ FAPI_INF("MSB Field Bits value: %lu", tRFC4min_MSB);
+
+ uint8_t tRFC4min_LSB = extract_spd_field< TRFC4MIN_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tRFC4min_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSB_START = 48;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( tRFC4min_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( tRFC4min_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 34) for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 34;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Refresh Recovery Delay Time 4 (tRFC4min) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes SDRAM Minimum Four Activate Window Delay Time
+/// @param[out] o_value tFAWmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 36 (bits 3~0) & Byte 37 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 42
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_tfaw( int64_t& o_value)
+{
+ uint8_t tFAWmin_MSN = extract_spd_field< TFAWMIN_MSN >(iv_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tFAWmin_MSN);
+
+ uint8_t tFAWmin_LSB = extract_spd_field< TFAWMIN_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tFAWmin_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tFAWmin_MSN ).
+ insertFromRight<LSB_START, LSB_LEN>( tFAWmin_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 65535; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 37) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 37;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Four Activate Window Delay Time (tFAWmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Four Activate Window Delay Time (tFAWmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group
+/// @param[out] o_value tRRD_Smin MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 38
+/// @note Item JC-45-2220.01x
+/// @note Page 43
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRRD_Smin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRRD_Smin (SPD byte 119)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::min_trrd_s( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 38;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Minimum Activate to Activate Delay Time - Different Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Find valid value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group
+/// @param[out] o_value tRRD_Lmin MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 39
+/// @note Item JC-45-2220.01x
+/// @note Page 43-44
+/// @note DDR4 SPD Document Release 3
+/// @warning If tRRD_Lmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tRRD_Lmin (SPD byte 118)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::min_trrd_l( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 39;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Minimum Activate to Activate Delay Time - Same Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Find valid value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Activate to Activate Delay Time - Same Bank Group (tRRD_Lmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group
+/// @param[out] o_value tCCD_Lmin MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 40
+/// @note Item JC-45-2220.01x
+/// @note Page 44-45
+/// @note DDR4 SPD Document Release 3
+/// @warning If tCCD_Lmin cannot be divided evenly by the MTB,
+/// this byte must be rounded up to the next larger
+/// integer and the Fine Offset for tCCD_Lmin (SPD byte 117)
+/// used for correction to get the actual value.
+///
+fapi2::ReturnCode decoder::min_tccd_l( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 40;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Minimum CAS to CAS Delay Time - Same Bank Group
+ // explicit conversion to int64_t
+ int64_t l_timing_val = int64_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 255; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum CAS to CAS Delay Time - Same Bank Group (tCCD_Lmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Minimum Write Recovery Time
+/// @param[out] o_value tWRmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_twr( int64_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0) were reserved
+ // and coded as zeros.
+ // Default as 0x78 for all DDR4 bins for rev 1.0
+ // No value given in 1.0 JEDEC spec and no value in SPD - JLH
+ // 1.1 Has valid values defined and in SPD, this is taken from there
+ o_value = 0x78;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+}
+
+///
+/// @brief Decodes Minimum Write to Read Time - Different Bank Group
+/// @param[out] o_value tWRT_Smin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_twtr_s( int64_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0) were reserved
+ // and coded as zeros.
+ // Default as 0x14 for all DDR4 bins for rev 1.0
+ // No value given in 1.0 JEDEC spec and no value in SPD - JLH
+ // 1.1 Has valid values defined and in SPD, this is taken from there
+ o_value = 0x14;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes Minimum Write to Read Time - Same Bank Group
+/// @param[out] o_value tWRT_Lmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 46
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::min_twtr_l( int64_t& o_value)
+{
+ // For General Section rev 1.0 of the SPD,
+ // SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0) were reserved
+ // and coded as zeros.
+ // Default as 0x3C for all DDR4 bins for rev 1.0
+ // No value given in 1.0 JEDEC spec and no value in SPD - JLH
+ // 1.1 Has valid values defined and in SPD, this is taken from there
+ o_value = 0x3C;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+}
+
+///
+/// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group
+/// @param[out] o_value tCCD_Lmin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 117
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_tccd_l( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 117;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for Minimum CAS to CAS Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for min RAS to CAS Delay Time (tCCD_Lmin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum RAS to CAS Delay Time (tCCD_Lmin) in FTB units: %d",
+ mss::c_str(iv_target),
+ 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 tRRD_Lmin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 118
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_trrd_l( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 118;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for Minimum Activate to Activate Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum Activate to Activate Delay Time (tRRD_Lmin) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+/// @param[out] o_value tRRD_Smin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 119
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_trrd_s( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 119;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum Activate to Activate Delay Time - Different Bank Group (tRRD_Smin) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time
+/// @param[out] o_value tRCmin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 120
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_trc( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 120;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for Minimum Active to Active/Refresh Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for vali value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum Active to Active/Refresh Delay Time (tRCmin) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time
+/// @param[out] o_value tRPmin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 121
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_trp( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 121;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for Minimum Row Precharge Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for Minimum Row Precharge Delay Time (tRPmin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum Row Precharge Delay Time (tRPmin) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+///
+/// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+/// @param[out] o_value tRCDmin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 122
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_trcd( int64_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 122;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for min RAS to CAS Delay Time (tRCDmin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum RAS to CAS Delay Time (tRCDmin) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time
+/// @param[out] o_value tAAmin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 123
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_taa( int64_t& o_value )
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 123;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for SDRAM Minimum CAS Latency Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Fine offset for Minimum CAS Latency Time (tAAmin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum CAS Latency Time (tAAmin) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time
+/// @param[out] o_value tCKmax offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 124
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_max_tck( int64_t& o_value )
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 124;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for SDRAM Maximum Cycle Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the fine offset for max cycle time (tckmax)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Maximum Cycle Time (tCKmax) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time
+/// @param[out] o_value tCKmin offset in FTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 125
+/// @note Item JC-45-2220.01x
+/// @note Page 52
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::fine_offset_min_tck( int64_t& o_value )
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 125;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ // Retrieve Fine Offset for SDRAM Minimum Cycle Time
+ // int8_t conversion - allows me to get a negative offset
+ // then implicit conversion to int64_t
+ int64_t l_timing_val = int8_t(iv_spd_data[BYTE_INDEX]);
+
+ // Check for valid value
+ constexpr int64_t TIMING_LOWER_BOUND = -128; // from JEDEC
+ constexpr int64_t TIMING_UPPER_BOUND = 127; // from JEDEC
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Fine offset for Minimum Cycle Time (tCKmin)") );
+
+ // Update output value only if range check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Fine offset for Minimum Cycle Time (tCKmin) in FTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes Cyclical Redundancy Code (CRC) for Base Configuration Section
+/// @param[out] o_value crc value from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 127 & Byte 126
+/// @note Item JC-45-2220.01x
+/// @note Page 53
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::cyclical_redundancy_code( uint16_t& o_value )
+{
+ uint8_t crc_MSB = extract_spd_field< CRC_MSB >(iv_target, iv_spd_data);
+ FAPI_INF("MSB Field Bits value: %lu", crc_MSB);
+
+ uint8_t crc_LSB = extract_spd_field< CRC_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", crc_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 0;
+ constexpr size_t MSN_LEN = 8;
+ constexpr size_t LSB_START = 8;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<uint16_t> l_buffer;
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( crc_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( crc_LSB );
+
+ // This value isn't bounded in the SPD document
+ o_value = l_buffer;
+
+ FAPI_INF("%s. Cyclical Redundancy Code (CRC): %d",
+ mss::c_str(iv_target),
+ o_value);
+
+ // Returns "happy" until we can figure out a way to test this - AAM
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes module manufacturer ID code
+/// @param[out] o_value module manufacturing id code
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 320 (bit 7~0), 321 (6~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12 - 54
+///
+fapi2::ReturnCode decoder::module_manufacturer_id_code( uint16_t& o_value )
+{
+
+ constexpr size_t BYTE_INDEX_MSB = 320;
+ uint8_t mfgid_MSB = iv_spd_data[BYTE_INDEX_MSB];
+
+ constexpr size_t BYTE_INDEX_LSB = 321;
+ uint8_t mfgid_LSB = iv_spd_data[BYTE_INDEX_LSB];
+
+ constexpr size_t MSB_START = 0;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 8;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<uint16_t> l_buffer;
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( mfgid_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( mfgid_LSB );
+
+ o_value = l_buffer;
+
+ FAPI_INF("%s.Module Manufacturer ID Code: %x",
+ mss::c_str(iv_target),
+ o_value);
+
+ // Returns "happy" until we can figure out a way to test this - AAM
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes Module Manufacturing Location
+/// @param[out] o_value uint8_t identifier for manufacturing location of memory module
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 322
+/// @note Item JC-45-2220.01x
+/// @note Page 55
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::module_manufacturing_location( uint8_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 322;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ o_value = iv_spd_data[BYTE_INDEX];
+
+ FAPI_INF("%s. Module Manufacturing Location: %x",
+ mss::c_str(iv_target),
+ o_value);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodesmodule manufacturing date
+/// @param[out] o_value the 2 byte date of manufacturing in BCD format
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 323-324
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 54
+/// @note in Binary Coded Decimal (BCD)
+/// @note MSB = year, LSB = week
+///
+fapi2::ReturnCode decoder::module_manufacturing_date( uint16_t& o_value )
+{
+
+ constexpr size_t BYTE_INDEX_MSB = 323;
+ uint8_t date_MSB = iv_spd_data[BYTE_INDEX_MSB];
+
+ constexpr size_t BYTE_INDEX_LSB = 324;
+ uint8_t date_LSB = iv_spd_data[BYTE_INDEX_LSB];
+
+ constexpr size_t MSB_START = 0;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 8;
+ constexpr size_t LSB_LEN = 8;
+
+ //Using insertFromRight because IBM is backwards
+ fapi2::buffer<uint16_t> l_buffer;
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( date_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( date_LSB );
+
+ o_value = l_buffer;
+
+ FAPI_INF("%s.Module Manufacturer ID date: %x",
+ mss::c_str(iv_target),
+ o_value);
+
+ // Returns "happy" until we can figure out a way to test this - AAM
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes module's unique serial number
+/// @param[out] o_value
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 325-328
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 54
+/// @note in Binary Coded Decimal (BCD)
+///
+fapi2::ReturnCode decoder::module_serial_number( uint32_t& o_value )
+{
+ constexpr size_t BYTE_INDEX_0 = 325;
+ uint8_t sn_byte_0 = iv_spd_data[BYTE_INDEX_0];
+
+ constexpr size_t BYTE_INDEX_1 = 326;
+ uint8_t sn_byte_1 = iv_spd_data[BYTE_INDEX_1];
+
+ constexpr size_t BYTE_INDEX_2 = 327;
+ uint8_t sn_byte_2 = iv_spd_data[BYTE_INDEX_2];
+
+ constexpr size_t BYTE_INDEX_3 = 328;
+ uint8_t sn_byte_3 = iv_spd_data[BYTE_INDEX_3];
+
+ constexpr size_t START_BYTE_0 = 0;
+ constexpr size_t LEN_BYTE_0 = 8;
+ constexpr size_t START_BYTE_1 = 8;
+ constexpr size_t LEN_BYTE_1 = 8;
+ constexpr size_t START_BYTE_2 = 16;
+ constexpr size_t LEN_BYTE_2 = 8;
+ constexpr size_t START_BYTE_3 = 24;
+ constexpr size_t LEN_BYTE_3 = 8;
+
+ //Goes down the batting order, Inserts from left side because IBM
+ fapi2::buffer<uint32_t> l_buffer;
+ l_buffer.insertFromRight<START_BYTE_0, LEN_BYTE_0>( sn_byte_0 )
+ .insertFromRight<START_BYTE_1, LEN_BYTE_1>( sn_byte_1 )
+ .insertFromRight<START_BYTE_2, LEN_BYTE_2>( sn_byte_2 )
+ .insertFromRight<START_BYTE_3, LEN_BYTE_3>( sn_byte_3 );
+
+ o_value = l_buffer;
+
+ FAPI_INF("%s.Module Serial Number : %x",
+ mss::c_str(iv_target),
+ o_value);
+
+ // Returns "happy" until we can figure out a way to test this - AAM
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes Module Revision Code
+/// @param[out] o_value uint8_t identifier for revision code
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 349
+/// @note Item JC-45-2220.01x
+/// @note Page 55
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder::module_revision_code( uint8_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 349;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ o_value = iv_spd_data[BYTE_INDEX];
+
+ FAPI_INF("%s. Module Revision Code: %x",
+ mss::c_str(iv_target),
+ o_value);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes DRAM Manufacturer ID code
+/// @param[out] o_value dram manufacturing id code
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 350 351
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 54
+///
+fapi2::ReturnCode decoder::dram_manufacturer_id_code( uint16_t& o_value )
+{
+ constexpr size_t BYTE_INDEX_MSB = 350;
+ uint8_t mfgid_MSB = iv_spd_data[BYTE_INDEX_MSB];
+
+ constexpr size_t BYTE_INDEX_LSB = 351;
+ uint8_t mfgid_LSB = iv_spd_data[BYTE_INDEX_LSB];
+
+ constexpr size_t MSB_START = 0;
+ constexpr size_t MSB_LEN = 8;
+ constexpr size_t LSB_START = 8;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<uint16_t> l_buffer;
+ l_buffer.insertFromRight<MSB_START, MSB_LEN>( mfgid_MSB )
+ .insertFromRight<LSB_START, LSB_LEN>( mfgid_LSB );
+
+ o_value = l_buffer;
+
+ FAPI_INF("%s.DRAM Manufacturer ID Code (dram_mfg_id): %x",
+ mss::c_str(iv_target),
+ o_value);
+
+ // Returns "happy" until we can figure out a way to test this - AAM
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes DRAM Stepping
+/// @param[out] o_value uint8_t DRAM Stepping val
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 353
+/// @note Item JC-45-2220.01x
+/// @note Page 56
+/// @note DDR4 SPD Document Release 3
+/// @note also called die revision level
+///
+fapi2::ReturnCode decoder::dram_stepping( uint8_t& o_value)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 352;
+
+ FAPI_INF("%s SPD data at Byte %d: 0x%01X.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ iv_spd_data[BYTE_INDEX]);
+
+ o_value = iv_spd_data[BYTE_INDEX];
+
+ FAPI_INF("%s. DRAM stepping: %x",
+ mss::c_str(iv_target),
+ o_value);
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Returns Logicalranks in Primary SDRAM type
+/// @param[out] o_logical_ranks number of logical ranks
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+///
+fapi2::ReturnCode decoder::prim_sdram_logical_ranks( uint8_t& o_logical_ranks )
+{
+ uint8_t l_signal_loading = 0;
+ uint8_t l_ranks_per_dimm = 0;
+
+ FAPI_TRY( prim_sdram_signal_loading(l_signal_loading) );
+ FAPI_TRY( num_package_ranks_per_dimm(l_ranks_per_dimm) );
+
+ if(l_signal_loading == spd::SINGLE_LOAD_STACK)
+ {
+ // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count.
+ uint8_t l_die_count = 0;
+ FAPI_TRY( prim_sdram_die_count(l_die_count) );
+
+ o_logical_ranks = l_ranks_per_dimm * l_die_count;
+ }
+ else
+ {
+ // Covers case 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 is used for calculation purposes as defined by the SPD spec.
+ o_logical_ranks = l_ranks_per_dimm;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Returns Logical ranks per DIMM
+/// @param[in] i_pDecoder shared pointer to the SPD decoder
+/// @param[out] o_logical_ranks number of logical ranks
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+///
+fapi2::ReturnCode decoder::logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm )
+{
+ FAPI_TRY( prim_sdram_logical_ranks(o_logical_rank_per_dimm) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}//spd
+}// mss
diff --git a/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C
new file mode 100644
index 000000000..ea72b7615
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C
@@ -0,0 +1,850 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file spd_decoder_v1_1.C
+/// @brief SPD decoder definitions
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
+#include <generic/memory/lib/spd/spd_checker.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/find.H>
+
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+namespace mss
+{
+namespace spd
+{
+
+/////////////////////////
+// Member method definitions
+/////////////////////////
+
+///
+/// @brief ctor
+/// @param[in] i_target dimm target
+/// @param[in] i_spd_data SPD data vector
+/// @param[in] i_module_decoder shared_ptr to dimm module decoder
+/// @param[in] i_raw_card raw card data structure
+///
+decoder_v1_1::decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& i_module_decoder,
+ const rcw_settings& i_raw_card)
+ : decoder(i_target, i_spd_data, i_module_decoder, i_raw_card)
+{}
+
+///
+/// @brief Decodes SDRAM density from SPD
+/// @param[out] o_value SDRAM density in GBs
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 4 (bits 0~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 18
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::sdram_density( uint8_t& o_value )
+{
+ // =========================================================
+ // Byte 4 maps
+ // Item JC-45-2220.01x
+ // Page 18
+ // DDR4 SPD Document Release 3
+ // Byte 4 (0x004): SDRAM Density and Banks
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > SDRAM_DENSITY_MAP =
+ {
+ // {key byte, capacity in GBs}
+ {2, 1},
+ {3, 2},
+ {4, 4},
+ {5, 8},
+ {6, 16},
+ {7, 32},
+ {8, 12},
+ {12, 24}
+ };
+
+ // Extracting desired biits
+ const uint8_t l_field_bits = extract_spd_field< SDRAM_CAPACITY >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Check to assure SPD DRAM capacity (map) wont be at invalid values
+ bool l_is_val_found = mss::find_value_from_key(SDRAM_DENSITY_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SDRAM_CAPACITY.iv_byte,
+ l_field_bits,
+ "Failed check for SPD DRAM capacity") );
+
+ FAPI_INF("%s. SDRAM density: %d Gb",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes hybrid media field from SPD
+/// @param[in] iv_target
+/// @param[out] o_value enum representing hybrid memory type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note Decodes SPD Byte 3 (bits 4~6)
+/// @note Item JC-45-2220.01x
+/// @note Page 17
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::hybrid_media( 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
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MEDIA_MAP =
+ {
+ //{key, value}
+ {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE},
+ {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< HYBRID_MEDIA >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(HYBRID_MEDIA_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ HYBRID_MEDIA.iv_byte,
+ l_field_bits,
+ "Failed check on Hybrid Media type") );
+
+ FAPI_INF("%s. Hybrid Media: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes hybrid field from SPD
+/// @param[out] o_value enum representing if module is hybrid
+/// @return fapi2::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 decoder_v1_1::hybrid( 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
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MAP =
+ {
+ //{key byte, value}
+ {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID},
+ {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< HYBRID >(iv_target, iv_spd_data);
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(HYBRID_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ HYBRID.iv_byte,
+ l_field_bits,
+ "Failed check on hybrid field") );
+
+ FAPI_INF("%s. Hybrid: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Secondary SDRAM signal loading
+/// @param[out] o_value enum representing signal loading type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bits 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::sec_sdram_signal_loading( uint8_t& o_value )
+{
+ // =========================================================
+ // Byte 10 maps
+ // Item JC-45-2220.01x
+ // Page 21-22
+ // DDR4 SPD Document Release 3
+ // Byte 10 (0x00A): Secondary SDRAM Package Type
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > SEC_SIGNAL_LOADING_MAP =
+ {
+ // {key byte, signal loading}
+ {0, UNSPECIFIED},
+ {1, MULTI_LOAD_STACK},
+ {2, SINGLE_LOAD_STACK}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SEC_SIGNAL_LOADING >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(SEC_SIGNAL_LOADING_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SEC_SIGNAL_LOADING.iv_byte,
+ l_field_bits,
+ "Failed check for Secondary SDRAM Signal Loading") );
+
+ FAPI_INF("%s. Secondary SDRAM Signal Loading: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode Soft post package repair (soft PPR)
+/// @param[out] o_value enum representing if soft PPR is supported
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 9 (bit 5)
+/// @note Item JC-45-2220.01x
+/// @note Page 21
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::soft_post_package_repair( uint8_t& o_value )
+{
+ // =========================================================
+ // Byte 9 maps
+ // Item JC-45-2220.01x
+ // Page 21
+ // DDR4 SPD Document Release 3
+ // Byte 9 (0x009): Other SDRAM Optional Features
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > SOFT_PPR_MAP =
+ {
+ // {key byte, value }
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SOFT_PPR >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(SOFT_PPR_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SOFT_PPR.iv_byte,
+ l_field_bits,
+ "Failed check for Soft PPR") );
+
+ FAPI_INF("%s. Soft Post Package Repair (Soft PPR): %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Secondary DRAM Density Ratio
+/// @param[out] o_value raw bits from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bits 3~2)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::sec_dram_density_ratio( uint8_t& o_value )
+{
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SEC_DENSITY_RATIO >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ constexpr size_t UNDEFINED = 3; // JEDEC map doesn't go beyond 3
+
+ FAPI_TRY( mss::check::spd:: fail_for_invalid_value(iv_target,
+ l_field_bits < UNDEFINED,
+ SEC_DENSITY_RATIO.iv_byte,
+ l_field_bits,
+ "Failed check for DRAM Density Ratio") );
+
+ FAPI_INF("%s. DRAM Density Ratio: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes Secondary SDRAM die count
+/// @param[out] o_value die count
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bits 6~4)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::sec_sdram_die_count( uint8_t& o_value )
+{
+ // =========================================================
+ // Byte 10 maps
+ // Item JC-45-2220.01x
+ // Page 21-22
+ // DDR4 SPD Document Release 3
+ // Byte 10 (0x00A): Secondary SDRAM Package Type
+ // =========================================================
+ static const std::vector<std::pair<uint8_t, uint8_t> > SEC_DIE_COUNT_MAP =
+ {
+ // {key byte, number of die}
+ {0, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8}
+
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SEC_DIE_COUNT >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SEC_DIE_COUNT.iv_byte,
+ l_field_bits,
+ "Failed check for Secondary Die Count") );
+
+ FAPI_INF("%s. Secondary Die Count: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Secondary SDRAM package type
+/// @param[out] o_value enum representing package type
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 10 (bit 7)
+/// @note Item JC-45-2220.01x
+/// @note Page 22
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::sec_sdram_package_type( uint8_t& o_value )
+{
+ // =========================================================
+ // Byte 10 maps
+ // Item JC-45-2220.01x
+ // Page 21-22
+ // DDR4 SPD Document Release 3
+ // Byte 10 (0x00A): Secondary SDRAM Package Type
+ // =========================================================
+
+ static const std::vector<std::pair<uint8_t, uint8_t> > SEC_PACKAGE_TYPE_MAP =
+ {
+ // {key byte, value }
+ {0, MONOLITHIC},
+ {1, NON_MONOLITHIC}
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< SEC_PACKAGE_TYPE >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(SEC_PACKAGE_TYPE_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ SEC_PACKAGE_TYPE.iv_byte,
+ l_field_bits,
+ "Failed check for Secondary Package Type") );
+
+ FAPI_INF("%s. Secondary Package Type: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of package ranks per DIMM
+/// @param[out] o_value number of package ranks per DIMM
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 12 (bits 5~3)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::num_package_ranks_per_dimm( uint8_t& o_value )
+{
+ // =========================================================
+ // Byte 12 maps
+ // Item JC-45-2220.01x
+ // Page 23
+ // DDR4 SPD Document Release 3
+ // 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, 1},
+ {1, 2},
+ {2, 3},
+ {3, 4},
+ {4, 5},
+ {5, 6},
+ {6, 7},
+ {7, 8},
+ };
+
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< PACKAGE_RANKS >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ bool l_is_val_found = mss::find_value_from_key(NUM_PACKAGE_RANKS_MAP, l_field_bits, o_value);
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_is_val_found,
+ PACKAGE_RANKS.iv_byte,
+ l_field_bits,
+ "Failed check for Num Package Ranks Per DIMM") );
+
+ FAPI_INF("%s. Num Package Ranks per DIMM: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Rank Mix
+/// @param[out] o_value rank mix value from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 12 (bit 6)
+/// @note Item JC-45-2220.01x
+/// @note Page 23
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::rank_mix( uint8_t& o_value )
+{
+ // Extracting desired bits
+ const uint8_t l_field_bits = extract_spd_field< RANK_MIX >(iv_target, iv_spd_data);
+ FAPI_DBG("Field Bits value: %d", l_field_bits);
+
+ // Find map value
+ constexpr size_t INVALID_VALUE = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits < INVALID_VALUE),
+ RANK_MIX.iv_byte,
+ l_field_bits,
+ "Failed check for Rank Mix") );
+
+ // Update output after check passes
+ o_value = l_field_bits;
+
+ FAPI_INF("%s. Rank Mix: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decode CAS Latencies Supported
+/// @param[out] o_value bitmap of supported CAS latencies
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Bytes 20-23
+/// @note Item JC-45-2220.01x
+/// @note Page 33-34
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::supported_cas_latencies( uint64_t& o_value )
+{
+ // Trace print in the front assists w/ debug
+ constexpr size_t FIRST_BYTE = 20;
+ uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ c_str(iv_target),
+ FIRST_BYTE,
+ first_raw_byte);
+
+ constexpr size_t SEC_BYTE = 21;
+ uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ c_str(iv_target),
+ SEC_BYTE,
+ sec_raw_byte);
+
+ constexpr size_t THIRD_BYTE = 22;
+ uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ c_str(iv_target),
+ THIRD_BYTE,
+ third_raw_byte);
+
+ constexpr size_t FOURTH_BYTE = 23;
+ uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE];
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ c_str(iv_target),
+ FOURTH_BYTE,
+ fourth_raw_byte);
+
+ // Buffers used for bit manipulation
+ // Combine Bytes to create bitmap - right aligned
+ fapi2::buffer<uint64_t> l_buffer;
+
+ l_buffer.insertFromRight<CAS_BYTE_1_START, CAS_BYTE_1_LEN>(first_raw_byte)
+ .insertFromRight<CAS_BYTE_2_START, CAS_BYTE_2_LEN>(sec_raw_byte)
+ .insertFromRight<CAS_BYTE_3_START, CAS_BYTE_3_LEN>(third_raw_byte)
+ .insertFromRight<CAS_BYTE_4_START, CAS_BYTE_4_LEN>(fourth_raw_byte);
+
+ // According to the JEDEC spec:
+ // Byte 23 bit 6 is reserved and must be coded as 0.
+ // Should we warn instead of fail because in last revision this was a reserved byte coded as 0x00
+ constexpr size_t BIT_START = 33; // relative position of bit 6 in byte 23 relative to uint64_t
+ constexpr size_t BIT_LEN = 1;
+
+ // Check for a valid value
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ !(l_buffer.getBit<BIT_START, BIT_LEN>()),
+ FOURTH_BYTE,
+ fourth_raw_byte,
+ "Failed check on CAS latencies supported") );
+
+ // Update output value only if range check passes
+ o_value = l_buffer;
+
+ FAPI_INF("%s. CAS latencies supported (bitmap): 0x%llX",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Minimum Write Recovery Time
+/// @param[out] o_value tWRmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 41 (bits 3~0) & Byte 42 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::min_twr( int64_t& o_value )
+{
+ uint8_t tWRmin_MSN = extract_spd_field< TWRMIN_MSN >(iv_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tWRmin_MSN);
+
+ uint8_t tWRmin_LSB = extract_spd_field< TWRMIN_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tWRmin_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWRmin_MSN ).
+ insertFromRight<LSB_START, LSB_LEN>( tWRmin_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ // This value used to be reserved to 0 - before spec update
+ // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+
+ constexpr int64_t TIMING_LOWER_BOUND = 0;
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 42) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 42;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Write Recovery Time (tWRmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Write Recovery Time (tWRmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes Minimum Write to Read Time - Different Bank Group
+/// @param[out] o_value tWTR_Smin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 43 (bits 3~0) & Byte 44 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 40
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::min_twtr_s( int64_t& o_value )
+{
+ uint8_t tWTR_Smin_MSN = extract_spd_field< TWTRMIN_S_MSN >(iv_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tWTR_Smin_MSN);
+
+ uint8_t tWTR_Smin_LSB = extract_spd_field< TWTRMIN_S_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tWTR_Smin_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWTR_Smin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( tWTR_Smin_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+
+ // This value used to be reserved to 0 - before spec update - AAM
+ // constexpr int64_t TIMING_LOWER_BOUND = 1; // from JEDEC
+ constexpr int64_t TIMING_LOWER_BOUND = 0;
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 44) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 44;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Write to Read Time - Different Bank Group (tWTR_Smin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Write to Read Time - Different Bank Group (tWTR_Smin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes Minimum Write to Read Time - Same Bank Group
+/// @param[out] o_value tWTR_Lmin in MTB units
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 43 (bits 7~4) & Byte 45 (bits 7~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 46
+/// @note DDR4 SPD Document Release 3
+///
+fapi2::ReturnCode decoder_v1_1::min_twtr_l( int64_t& o_value )
+{
+ // Extracting desired bits
+ uint8_t tWTR_Lmin_MSN = extract_spd_field< TWTRMIN_L_MSN >(iv_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tWTR_Lmin_MSN);
+
+ uint8_t tWTR_Lmin_LSB = extract_spd_field< TWTRMIN_L_LSB >(iv_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tWTR_Lmin_LSB);
+
+ // Combining bits to create timing value (in a buffer)
+ constexpr size_t MSN_START = 52;
+ constexpr size_t MSN_LEN = 4;
+ constexpr size_t LSB_START = 56;
+ constexpr size_t LSB_LEN = 8;
+
+ fapi2::buffer<int64_t> l_buffer;
+
+ l_buffer.insertFromRight<MSN_START, MSN_LEN>( tWTR_Lmin_MSN )
+ .insertFromRight<LSB_START, LSB_LEN>( tWTR_Lmin_LSB );
+
+ // Extract timing value from the buffer into an integral type
+ int64_t l_timing_val = l_buffer;
+
+ // JEDEC spec limits for this timing value
+ // This value used to be reserved to 0 - before spec update
+ //constexpr int64_t TIMING_LOWER_BOUND = 1 // from JEDEC
+ constexpr int64_t TIMING_LOWER_BOUND = 0;
+ constexpr int64_t TIMING_UPPER_BOUND = 4095; // from JEDEC
+
+ // best we can do?
+ // I had to combine parts from two different bytes.
+ // Chose one of them (byte 45) to for error printout of this decode
+ constexpr size_t ERROR_BYTE_INDEX = 45;
+
+ FAPI_TRY(mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_timing_val <= TIMING_UPPER_BOUND) &&
+ (l_timing_val >= TIMING_LOWER_BOUND),
+ ERROR_BYTE_INDEX,
+ l_timing_val,
+ "Failed check on the Minimum Write to Read Time - Same Bank Group (tWTR_Lmin) in MTB") );
+
+ // Update output only after check passes
+ o_value = l_timing_val;
+
+ FAPI_INF("%s. Minimum Write to Read Time - Same Bank Group (tWTR_Lmin) in MTB units: %d",
+ mss::c_str(iv_target),
+ o_value);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function that returns Logical ranks in SDRAM type
+/// @param[out] o_logical_ranks number of logical ranks
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+///
+fapi2::ReturnCode decoder_v1_1::sec_sdram_logical_ranks( uint8_t& o_logical_ranks )
+{
+ uint8_t l_signal_loading = 0;
+ uint8_t l_ranks_per_dimm = 0;
+
+ FAPI_TRY( sec_sdram_signal_loading(l_signal_loading) );
+ FAPI_TRY( num_package_ranks_per_dimm(l_ranks_per_dimm) );
+
+ if(l_signal_loading == spd::SINGLE_LOAD_STACK)
+ {
+ // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count.
+ uint8_t l_die_count = 0;
+ FAPI_TRY( sec_sdram_die_count(l_die_count) );
+
+ o_logical_ranks = l_ranks_per_dimm * l_die_count;
+ }
+ else
+ {
+ // Covers case 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 is used for calculation purposes as defined by the SPD spec.
+ o_logical_ranks = l_ranks_per_dimm;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Returns Logical ranks per DIMM
+/// @param[out] o_logical_ranks number of logical ranks
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+///
+fapi2::ReturnCode decoder_v1_1::logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm )
+{
+ uint8_t l_rank_mix = 0;
+
+ FAPI_TRY( rank_mix(l_rank_mix) );
+
+ if(l_rank_mix == fapi2::ENUM_ATTR_EFF_DRAM_RANK_MIX_SYMMETRICAL)
+ {
+ FAPI_TRY( prim_sdram_logical_ranks(o_logical_rank_per_dimm) );
+ }
+ else
+ {
+ // Rank mix is ASYMMETRICAL
+ uint8_t l_prim_logical_rank_per_dimm = 0;
+ uint8_t l_sec_logical_rank_per_dimm = 0;
+
+ FAPI_TRY( prim_sdram_logical_ranks(l_prim_logical_rank_per_dimm) );
+ FAPI_TRY( sec_sdram_logical_ranks(l_sec_logical_rank_per_dimm) );
+
+ o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm + l_sec_logical_rank_per_dimm;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}//spd
+}// mss
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
new file mode 100644
index 000000000..67faa47a0
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/common/dimm_module_decoder.H
@@ -0,0 +1,548 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/common/dimm_module_decoder.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file dimm_module_decoder.H
+/// @brief base dimm module SPD decoder declarations
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+
+#ifndef _MSS_DIMM_MODULE_DECODER_H_
+#define _MSS_DIMM_MODULE_DECODER_H_
+
+#include <fapi2.H>
+#include <cstdint>
+
+namespace mss
+{
+namespace spd
+{
+
+///
+/// @class dimm_module_decoder
+/// @brief Abstract class for DIMM module SPD DRAM decoders
+/// @note This would include for example, RDIMM and LRDIMM
+///
+class dimm_module_decoder
+{
+ public:
+
+ ///
+ /// @brief default ctor
+ ///
+ dimm_module_decoder() = default;
+
+ ///
+ /// @brief default dtor
+ ///
+ virtual ~dimm_module_decoder() = default;
+
+ ///
+ /// @brief Decodes module nominal height max
+ /// @param[out] o_output height range encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes raw card extension
+ /// @param[out] o_output height range encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes front module maximum thickness max
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes back module maximum thickness max
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of registers used on RDIMM
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of rows of DRAMs on RDIMM
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register and buffer type for LRDIMMs
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes heat spreader thermal characteristics
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCEawSS if okay
+ ///
+ virtual fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_output)
+ {
+ // Undefined must be coded as 0x00
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes heat spreader solution
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of continuation codes
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register manufacturer ID code
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode reg_manufacturer_id_code(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register revision number
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes address mapping from register to dram
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for CKE signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for ODT signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for command/address (CA) signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for control signal (CS) signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for clock (B side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for clock (A side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE)
+ /// @param[out] o_output encoded drive strength
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bcom_bcke_bodt_drive_strength(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+ }
+
+ ///
+ /// @brief Decodes register output drive strength for data buffer control (BCK)
+ /// @param[out] o_output encoded drive strength
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bck_output_drive_strength(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes RCD output slew rate control
+ /// @param[out] o_output encoded drive strength
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode slew_rate_control(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes data buffer revision number
+ /// @param[out] o_output revision number
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode data_buffer_rev(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 0
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank0(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 1
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank1(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 2
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank2(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 3
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank3(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes data buffer VrefDQ for DRAM interface
+ /// @param[out] o_output encoding of F5BC6x in DDR4DB01 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode data_buffer_vref_dq(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM interface MDQ Drive Strenth
+ /// of the data buffer component for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output encoding of F5BC6x in
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM interface MDQ read termination strength
+ /// of the data buffer component for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output encoding of F5BC6x in
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM drive strenth
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output DRAM drive strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_NOM
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_WR
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes VrefDQ range for DRAM interface range
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_range(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes data buffer VrefDQ range for DRAM interface range
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode data_buffer_vref_dq_range(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes data buffer gain adjustment
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode data_buffer_gain_adjustment(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes data buffer Decision Feedback Equalization (DFE)
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode data_buffer_dfe(uint8_t& o_output)
+ {
+ o_output = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+};
+
+///
+/// @brief data structure for byte fields
+/// @note holds byte index, start bit and length of decoded field
+///
+struct field_t
+{
+ const uint64_t iv_byte;
+ const uint64_t iv_start;
+ const uint64_t iv_length;
+
+ // default ctor deleted
+ constexpr field_t() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_byte_index
+ /// @param[in] i_start_bit
+ /// @param[in] i_bit_length
+ ///
+ constexpr field_t(const uint64_t i_byte_index,
+ const uint64_t i_start_bit,
+ const uint64_t i_bit_length)
+ : iv_byte(i_byte_index), iv_start(i_start_bit), iv_length(i_bit_length)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ ~field_t() = default;
+
+};// field_t
+
+}// spd
+}// mss
+
+#endif //_MSS_DIMM_MODULE_DECODER_H_
diff --git a/src/import/generic/memory/lib/spd/common/rcw_settings.H b/src/import/generic/memory/lib/spd/common/rcw_settings.H
new file mode 100644
index 000000000..57527dbe5
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/common/rcw_settings.H
@@ -0,0 +1,162 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/common/rcw_settings.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file raw_cards.H
+/// @brief Raw card data structure
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_RAW_CARDS_H_
+#define _MSS_RAW_CARDS_H_
+
+#include <fapi2.H>
+#include <cstdint>
+#include <vector>
+
+namespace mss
+{
+
+///
+/// @brief raw card VBU settings
+/// @note contains RCD settings for hard-coded values
+/// that are not application specific.
+/// Application specific settings are dervied in eff_config
+struct rcw_settings
+{
+ uint64_t iv_rc00;
+ uint64_t iv_rc01;
+ uint64_t iv_rc02;
+ uint64_t iv_rc06_07;
+ uint64_t iv_rc09;
+ uint64_t iv_rc0b;
+ uint64_t iv_rc0c;
+ uint64_t iv_rc0f;
+ uint64_t iv_rc1x;
+ uint64_t iv_rc2x;
+ uint64_t iv_rc4x;
+ uint64_t iv_rc5x;
+ uint64_t iv_rc6x;
+ uint64_t iv_rc8x;
+ uint64_t iv_rc9x;
+ uint64_t iv_rcax;
+ uint64_t iv_rcbx;
+
+ ///
+ /// @brief default ctor
+ ///
+ rcw_settings() = default;
+
+ ///
+ /// @brief Equality operator
+ /// @param[in] i_rhs the right-hand side of the == operation
+ /// @return true iff both raw_cards are equal
+ ///
+ inline bool operator==(const rcw_settings& i_rhs) const
+ {
+ // Betting this is faster than all the conditionals ...
+ return (memcmp(this, &i_rhs, sizeof(rcw_settings)) == 0);
+ }
+
+ ///
+ /// @brief Logical not operator
+ /// @param[in] i_rhs the right-hand side of the != operation
+ /// @return true iff both raw_cards are not equal
+ ///
+ inline bool operator!=(const rcw_settings& i_rhs) const
+ {
+ // Betting this is faster than all the conditionals ...
+ return !(*this == i_rhs);
+ }
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_rc00 setting for register control word (RC00)
+ /// @param[in] i_rc01 setting for register control word (RC01)
+ /// @param[in] i_rc02 setting for register control word (RC02)
+ /// @param[in] i_rc06_07 setting for register control word (RCO6 & RC07)
+ /// @param[in] i_rc09 setting for register control word (RC09)
+ /// @param[in] i_rc0b setting for register control word (RC0B)
+ /// @param[in] i_rc0c setting for register control word (RC0C)
+ /// @param[in] i_rc0f setting for register control word (RC0F)
+ /// @param[in] i_rc1x setting for register control word (RC1X)
+ /// @param[in] i_rc2x setting for register control word (RC2X)
+ /// @param[in] i_rc4x setting for register control word (RC4X)
+ /// @param[in] i_rc5x setting for register control word (RC5X)
+ /// @param[in] i_rc6x setting for register control word (RC6X)
+ /// @param[in] i_rc8x setting for register control word (RC8X)
+ /// @param[in] i_rc9x setting for register control word (RC9X)
+ /// @param[in] i_rcax setting for register control word (RCAX)
+ /// @param[in] i_rcbx setting for register control word (RCBX)
+ ///
+ constexpr rcw_settings( const uint64_t i_rc00,
+ const uint64_t i_rc01,
+ const uint64_t i_rc02,
+ const uint64_t i_rc06_07,
+ const uint64_t i_rc09,
+ const uint64_t i_rc0b,
+ const uint64_t i_rc0c,
+ const uint64_t i_rc0f,
+ const uint64_t i_rc1x,
+ const uint64_t i_rc2x,
+ const uint64_t i_rc4x,
+ const uint64_t i_rc5x,
+ const uint64_t i_rc6x,
+ const uint64_t i_rc8x,
+ const uint64_t i_rc9x,
+ const uint64_t i_rcax,
+ const uint64_t i_rcbx )
+ : iv_rc00(i_rc00),
+ iv_rc01(i_rc01),
+ iv_rc02(i_rc02),
+ iv_rc06_07(i_rc06_07),
+ iv_rc09(i_rc09),
+ iv_rc0b(i_rc0b),
+ iv_rc0c(i_rc0c),
+ iv_rc0f(i_rc0f),
+ iv_rc1x(i_rc1x),
+ iv_rc2x(i_rc2x),
+ iv_rc4x(i_rc4x),
+ iv_rc5x(i_rc5x),
+ iv_rc6x(i_rc6x),
+ iv_rc8x(i_rc8x),
+ iv_rc9x(i_rc9x),
+ iv_rcax(i_rcax),
+ iv_rcbx(i_rcbx)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ ~rcw_settings() = default;
+};
+
+}// mss
+
+#endif //_MSS_RAW_CARDS_H_
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
new file mode 100644
index 000000000..a1aee784e
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/common/spd_decoder_base.H
@@ -0,0 +1,848 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/common/spd_decoder_base.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file spd_decoder.H
+/// @brief SPD decoder declarations
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_BASE_SPD_DECODER_H_
+#define _MSS_BASE_SPD_DECODER_H_
+
+#include <cstdint>
+#include <memory>
+#include <fapi2.H>
+
+#include <generic/memory/lib/spd/common/dimm_module_decoder.H>
+#include <generic/memory/lib/spd/common/rcw_settings.H>
+
+namespace mss
+{
+namespace spd
+{
+
+///
+/// @class decoder
+/// @brief Base SPD DRAM decoder
+///
+class base_decoder
+{
+ protected:
+
+ ///
+ /// @brief Helper function that turns Logical ranks in Primary SDRAM type
+ /// @param[out] o_logical_ranks number of logical ranks
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode prim_sdram_logical_ranks( uint8_t& o_logical_ranks )
+ {
+ o_logical_ranks = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Helper functions that returns Logical ranks in Secondary SDRAM type
+ /// @param[out] o_logical_ranks number of logical ranks
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sec_sdram_logical_ranks( uint8_t& o_logical_ranks )
+ {
+ o_logical_ranks = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ public:
+ const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target;
+ std::shared_ptr<dimm_module_decoder> iv_module_decoder;
+ std::vector<uint8_t> iv_spd_data;
+ rcw_settings iv_raw_card;
+
+ // Default constructor deleted
+ base_decoder() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data SPD data vector
+ /// @param[in] i_module_decoder shared_ptr to dimm module decoder
+ /// @param[in] i_raw_card raw pointer to rcd data
+ ///
+ base_decoder(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data,
+ const std::shared_ptr<dimm_module_decoder>& i_module_decoder,
+ const rcw_settings& i_raw_card)
+ : iv_target(i_target),
+ iv_module_decoder(i_module_decoder),
+ iv_spd_data(i_spd_data),
+ iv_raw_card(i_raw_card)
+ {}
+
+ ///
+ /// @brief Default dtor
+ ///
+ virtual ~base_decoder() = default;
+
+ /////////////////////////
+ // Member Methods
+ /////////////////////////
+
+ ///
+ /// @brief Decodes number of used SPD bytes
+ /// @param[out] o_value number of SPD bytes used
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode number_of_used_bytes( uint16_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes total number of SPD bytes
+ /// @param[out] o_value number of total SPD bytes
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode number_of_total_bytes( uint16_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes hybrid media field from SPD
+ /// @param[out] o_value hybrid media decoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode hybrid_media( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes hybrid field from SPD
+ /// @param[out] o_value hybrid decoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode hybrid( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM density from SPD
+ /// @param[out] o_value SDRAM density in GBs
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sdram_density( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of SDRAM banks bits from SPD
+ /// @param[out] o_value Number of SDRAM bank bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bank_bits( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of SDRAM bank groups bits from SPD
+ /// @param[out] o_value Number of SDRAM bank groups bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bank_group_bits( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of SDRAM column address bits
+ /// @param[out] o_value Number of SDRAM bank bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode column_address_bits( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of SDRAM row address bits
+ /// @param[out] o_value Number of SDRAM bank bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode row_address_bits( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Primary SDRAM signal loading
+ /// @param[out] o_value Number of SDRAM bank bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode prim_sdram_signal_loading( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Primary SDRAM die count
+ /// @param[out] o_value Number of SDRAM bank bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode prim_sdram_die_count( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Primary SDRAM package type
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode prim_sdram_package_type( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode SDRAM Maximum activate count
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode maximum_activate_count( uint32_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode SDRAM Maximum activate window (multiplier), tREFI uknown at this point
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode maximum_activate_window_multiplier( uint32_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Post package repair (PPR)
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode post_package_repair( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Soft post package repair (soft PPR)
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode soft_post_package_repair( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Secondary SDRAM signal loading
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sec_sdram_signal_loading( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Secondary DRAM Density Ratio
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sec_dram_density_ratio( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Secondary SDRAM die count
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sec_sdram_die_count( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Secondary SDRAM package type
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode sec_sdram_package_type( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Module Nominal Voltage, VDD
+ /// @param[out] o_value enum representing if 1.2V is operable
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode operable_nominal_voltage( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Module Nominal Voltage, VDD
+ /// @param[out] o_value enum representing if 1.2V is endurant
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode endurant_nominal_voltage( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+ ///
+ /// @brief Decodes SDRAM device width
+ /// @param[out] o_value device width in bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode device_width( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes number of package ranks per DIMM
+ /// @param[out] o_value number of package ranks per DIMM
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode num_package_ranks_per_dimm( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Rank Mix
+ /// @param[out] o_value rank mix value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode rank_mix( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes primary bus width
+ /// @param[out] o_value primary bus width in bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode prim_bus_width( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes bus width extension
+ /// @param[out] o_value bus width extension in bits
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode bus_width_extension( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Module Thermal Sensor
+ /// @param[out] o_value thermal sensor value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode thermal_sensor( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Extended Base Module Type
+ /// @param[out] o_value extended base module type value from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode extended_base_module_type( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Fine Timebase
+ /// @param[out] o_value fine_timebase from SPD in picoseconds
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_timebase( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode Medium Timebase
+ /// @param[out] o_value fine_timebase from SPD in picoseconds
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode medium_timebase( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ ///
+ /// @brief Decodes SDRAM Minimum Cycle Time in MTB
+ /// @param[out] o_value tCKmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_tck( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Maximum Cycle Time in MTB
+ /// @param[out] o_value tCKmax in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode max_tck( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decode CAS Latencies Supported
+ /// @param[out] o_value bitmap of supported CAS latencies
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode supported_cas_latencies( uint64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum CAS Latency Time in MTB
+ /// @param[out] o_value tAAmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_taa( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum RAS to CAS Delay Time in MTB
+ /// @param[out] o_value tRCDmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trcd( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum Row Precharge Delay Time in MTB
+ /// @param[out] o_value tRPmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trp( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum Active to Precharge Delay Time in MTB
+ /// @param[out] o_value tRASmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_tras( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum Active to Active/Refresh Delay Time in MTB
+ /// @param[out] o_value tRCmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trc( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 1
+ /// @param[out] o_value tRFC1min in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trfc1( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 2
+ /// @param[out] o_value tRFC2min in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trfc2( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum Refresh Recovery Delay Time 4
+ /// @param[out] o_value tRFC4min in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trfc4( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes SDRAM Minimum Four Activate Window Delay Time
+ /// @param[out] o_value tFAWmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_tfaw( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Minimum Activate to Activate Delay Time - Different Bank Group
+ /// @param[out] o_value tRRD_Smin MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trrd_s( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Minimum Activate to Activate Delay Time - Same Bank Group
+ /// @param[out] o_value tRRD_Lmin MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_trrd_l( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Minimum CAS to CAS Delay Time - Same Bank Group
+ /// @param[out] o_value tCCD_Lmin MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_tccd_l( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Minimum Write Recovery Time
+ /// @param[out] o_value tWRmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_twr( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Different Bank Group
+ /// @param[out] o_value tWRT_Smin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_twtr_s( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Minimum Write to Read Time - Same Bank Group
+ /// @param[out] o_value tWRT_Lmin in MTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode min_twtr_l( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum CAS to CAS Delay Time - Same Bank Group
+ /// @param[out] o_value tCCD_Lmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_tccd_l( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Same Bank Group
+ /// @param[out] o_value tRRD_Lmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trrd_l( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Activate to Activate Delay Time - Different Bank Group
+ /// @param[out] o_value tRRD_Smin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trrd_s( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Active to Active/Refresh Delay Time
+ /// @param[out] o_value tRCmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trc( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for Minimum Row Precharge Delay Time
+ /// @param[out] o_value tRPmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trp( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum RAS to CAS Delay Time
+ /// @param[out] o_value tRCDmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_trcd( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum CAS Latency Time
+ /// @param[out] o_value tAAmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_taa( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Maximum Cycle Time
+ /// @param[out] o_value tCKmax offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_max_tck( int64_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Fine Offset for SDRAM Minimum Cycle Time
+ /// @param[out] o_value tCKmin offset in FTB units
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode fine_offset_min_tck( int64_t& o_value )
+ {
+ 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 if okay
+ ///
+ virtual fapi2::ReturnCode cyclical_redundancy_code( uint16_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes module manufacturer ID code
+ /// @param[out] o_output module manufacturing id code
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode module_manufacturer_id_code( uint16_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Module Manufacturing Location
+ /// @param[out] o_value uint8_t identifier for manufacturing location of memory module
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode module_manufacturing_location( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodesmodule manufacturing date
+ /// @param[out] o_value the 2 byte date of manufacturing in BCD format
+ /// @return FAPI2_RC_SUCCESS if okay
+ virtual fapi2::ReturnCode module_manufacturing_date( uint16_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes module's unique serial number
+ /// @param[out] o_value module's serial number
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode module_serial_number( uint32_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes Module Revision Code
+ /// @param[out] o_value uint8_t identifier for revision code
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode module_revision_code( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM Manufacturer ID code
+ /// @param[out] o_value dram manufacturing id code
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_manufacturer_id_code( uint16_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Decodes DRAM Stepping
+ /// @param[out] o_value uint8_t DRAM Stepping val
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode dram_stepping( uint8_t& o_value )
+ {
+ o_value = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ ///
+ /// @brief Returns Logical ranks per DIMM
+ /// @param[out] o_logical_ranks number of logical ranks
+ /// @return FAPI2_RC_SUCCESS if okay
+ ///
+ virtual fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm )
+ {
+ o_logical_rank_per_dimm = 0;
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+};// decoder
+
+}// spd
+}// mss
+
+#endif
diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H
new file mode 100644
index 000000000..32d4c6245
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H
@@ -0,0 +1,670 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file lrdimm_decoder.H
+/// @brief LRDIMM module SPD decoder declarations
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+
+#ifndef _MSS_LRDIMM_DECODER_H_
+#define _MSS_LRDIMM_DECODER_H_
+
+#include <fapi2.H>
+#include <vector>
+#include <generic/memory/lib/spd/common/dimm_module_decoder.H>
+
+namespace mss
+{
+namespace spd
+{
+namespace lrdimm
+{
+
+///
+/// @brief LRDIMM module decoder for revision 1.0
+///
+class decoder_v1_0 : public dimm_module_decoder
+{
+ protected:
+
+ const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target;
+
+ constexpr static field_t MODULE_NOMINAL_HEIGHT{128, 3, 5};
+ constexpr static field_t RAW_CARD_EXTENSION{128, 0, 3};
+
+ constexpr static field_t FRONT_MODULE_THICKNESS{129, 4, 4};
+ constexpr static field_t BACK_MODULE_THICKNESS{129, 0, 4};
+
+ constexpr static field_t NUM_REGISTERS_USED{131, 6, 2};
+ constexpr static field_t NUM_ROWS_OF_DRAMS{131, 4, 2};
+ constexpr static field_t REGISTER_TYPE{131, 0, 4};
+
+ constexpr static field_t HEAT_SPREADER_THERM_CHAR{132, 1, 7};
+ constexpr static field_t HEAT_SPREADER_SOLUTION{132, 0, 1};
+
+ constexpr static field_t CONTINUATION_CODES{133, 1, 7};
+ constexpr static field_t ADDR_MAPPING{136, 7, 1};
+
+ constexpr static field_t CKE_DRIVE_STRENGTH{137, 6, 2};
+ constexpr static field_t ODT_DRIVE_STRENGTH{137, 4, 2};
+ constexpr static field_t CA_DRIVE_STRENGTH{137, 2, 2};
+ constexpr static field_t CS_DRIVE_STRENGTH{137, 0, 2};
+
+ constexpr static field_t B_SIDE_DRIVE_STRENGTH{138, 6, 2};
+ constexpr static field_t A_SIDE_DRIVE_STRENGTH{138, 4, 2};
+ constexpr static field_t BCOM_BODT_BCKE_DRIVE_STRENGTH{138, 3, 1};
+ constexpr static field_t BCK_DRIVE_STRENGTH{138, 2, 1};
+ constexpr static field_t RCD_SLEW_CNTRL{138, 1, 1 };
+
+ constexpr static field_t VREF_DQ_RANK0{140, 2, 6};
+ constexpr static field_t VREF_DQ_RANK1{141, 2, 6};
+ constexpr static field_t VREF_DQ_RANK2{142, 2, 6};
+ constexpr static field_t VREF_DQ_RANK3{143, 2, 6};
+
+ constexpr static field_t DATA_BUFFER_MDQ{145, 1, 3};
+
+ constexpr static field_t DRAM_VREF_DQ_RANGE{155, 4, 4};
+ constexpr static field_t DATA_BUFFER_VREF_DQ{155, 3, 1};
+
+ constexpr static field_t DATA_BUFFER_GAIN_ADJUST{156, 7, 1};
+ constexpr static field_t DATA_BUFFER_DFE{156, 6, 1};
+
+ public:
+ // Allows injection of errors for testing
+ // TK - Consider API change to use setter/getters
+ // for this instance variable, RDIMM decoder
+ // uses this interface so they have to match - AAM
+ std::vector<uint8_t> iv_spd_data;
+
+ // deleted default ctor
+ decoder_v1_0() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data vector DIMM SPD data
+ ///
+ decoder_v1_0(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data)
+ : iv_target(i_target), iv_spd_data(i_spd_data)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ virtual ~decoder_v1_0() = default;
+
+ ///
+ /// @brief Decodes module nominal height max
+ /// @param[out] o_output height range encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 128 (Bits 4~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 55
+ ///
+ virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes raw card extension
+ /// @param[out] o_output raw card rev. encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 128 (Bits 7~5)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 55
+ ///
+ virtual fapi2::ReturnCode raw_card_extension(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes front module maximum thickness max
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 129 (Bits 3~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 55
+ ///
+ virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes back module maximum thickness max
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 129 (Bits 7~4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 55
+ ///
+ virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes number of registers used on LRDIMM
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 131 (Bits 1~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 57
+ ///
+ virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes number of rows of DRAMs on LRDIMM
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 131 (Bits 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 57
+ ///
+ virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes heat spreader solution
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 132 (Bit 7)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 58
+ ///
+ virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes number of continuation codes
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 133 (Bits 6~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 58
+ ///
+ virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register manufacturer ID code
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 134 (Bits 7~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 58
+ ///
+ virtual fapi2::ReturnCode reg_manufacturer_id_code(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register revision number
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 135 (Bits 7~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 58
+ ///
+ virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes address mapping from register to dram
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 136 (Bit 0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 59
+ ///
+ virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for CKE signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 60
+ ///
+ virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for ODT signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (Bits 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 60
+ ///
+ virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for command/address (CA) signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (Bits 5~4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 60
+ ///
+ virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for control signal (CS) signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (Bits 6~7)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 60
+ ///
+ virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (B side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (Bits 1~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 60
+ ///
+ virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (A side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (Bits 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 60
+ ///
+ virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes data buffer revision number
+ /// @param[out] o_output revision number
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 139 (Bits 7~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 60
+ ///
+ virtual fapi2::ReturnCode data_buffer_rev(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 0
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 140 (Bits 5~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 61
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank0(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 1
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 141 (Bits 5~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 61
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank1(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 2
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 142 (Bits 5~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 61
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank2(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM VrefDQ for Package Rank 3
+ /// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 143 (Bits 5~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 61
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_rank3(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes data buffer VrefDQ for DRAM interface
+ /// @param[out] o_output encoding of F5BC6x in DDR4DB01 spec
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 144 (Bits 5~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 61
+ ///
+ virtual fapi2::ReturnCode data_buffer_vref_dq(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM interface MDQ Drive Strenth
+ /// of the data buffer component for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output encoding of F5BC6x in
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 145 - 147 (Bits 6~4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 62
+ ///
+ virtual fapi2::ReturnCode data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed,
+ uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM interface MDQ read termination strength
+ /// of the data buffer component for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output encoding of F5BC6x in
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 145 - 147 (Bits 2~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 62
+ ///
+ virtual fapi2::ReturnCode data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM drive strenth
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output DRAM drive strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 148 (Bits 5~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 63
+ ///
+ virtual fapi2::ReturnCode dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_NOM
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 149 - 151 (Bits 2~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - (64 - 65)
+ ///
+ virtual fapi2::ReturnCode dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_WR
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 149 - 151 (Bits 5~3)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - (64 - 65)
+ ///
+ virtual fapi2::ReturnCode dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 152 - 154 (Bits 2~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 65
+ ///
+ virtual fapi2::ReturnCode dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3
+ /// for a particular dimm speed
+ /// @param[in] i_dimm_speed the dimm speed in MT/s
+ /// @param[out] o_output ODT termination strength (in ohms)
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 152 - 154 (Bits 5~3)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12.2 - 65
+ ///
+ virtual fapi2::ReturnCode dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output) override;
+
+};//decoder
+
+///
+/// @brief LRDIMM module decoder for revision 1.1
+///
+class decoder_v1_1 : public decoder_v1_0
+{
+ public:
+
+ // deleted default ctor
+ decoder_v1_1() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data vector DIMM SPD data
+ ///
+ decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data)
+ : decoder_v1_0(i_target, i_spd_data)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ virtual ~decoder_v1_1() = default;
+
+ ///
+ /// @brief Decodes register and data buffer types
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 131 (Bits 7~4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 63
+ ///
+ virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for CKE signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (Bits 1~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 65
+ ///
+ virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for ODT signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (Bits 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 65
+ ///
+ virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for control signal (CS) signal
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (Bits 6~7)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 65
+ ///
+ virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (B side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (Bits 1~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 66
+ ///
+ virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (A side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (Bits 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 66
+ ///
+ virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override;
+};
+
+///
+/// @brief LRDIMM module decoder for revision 1.2
+///
+class decoder_v1_2 : public decoder_v1_1
+{
+ public:
+
+ // deleted default ctor
+ decoder_v1_2() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data vector DIMM SPD data
+ ///
+ decoder_v1_2(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data)
+ : decoder_v1_1(i_target, i_spd_data)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ virtual ~decoder_v1_2() = default;
+
+ ///
+ /// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE)
+ /// @param[out] o_output encoded drive strength
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (Bit 4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 66
+ ///
+ virtual fapi2::ReturnCode bcom_bcke_bodt_drive_strength(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for data buffer control (BCK)
+ /// @param[out] o_output encoded drive strength
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (Bit 5)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 66
+ ///
+ virtual fapi2::ReturnCode bck_output_drive_strength(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes RCD output slew rate control
+ /// @param[out] o_output encoded drive strength
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (Bit 6)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 4
+ /// @note Page 4.1.2.L-4 - 70
+ ///
+ virtual fapi2::ReturnCode slew_rate_control(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes VrefDQ range for DRAM interface range
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 155 (Bits 3~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 4
+ /// @note Page 4.1.2.L-4 - 76
+ ///
+ virtual fapi2::ReturnCode dram_vref_dq_range(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes data buffer VrefDQ range for DRAM interface range
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 155 (Bit 4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 4
+ /// @note Page 4.1.2.L-4 - 76
+ ///
+ virtual fapi2::ReturnCode data_buffer_vref_dq_range(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes data buffer gain adjustment
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 156 (Bit 0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 4
+ /// @note Page 4.1.2.L-4 - 77
+ ///
+ virtual fapi2::ReturnCode data_buffer_gain_adjustment(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes data buffer Decision Feedback Equalization (DFE)
+ /// @param[out] o_output spd encoding
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 156 (Bit 1)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 4
+ /// @note Page 4.1.2.L-4 - 77
+ ///
+ virtual fapi2::ReturnCode data_buffer_dfe(uint8_t& o_output) override;
+};
+
+}// lrdimm
+}// spd
+}// mss
+
+#endif //_MSS_LRDIMM_DECODER_H_
diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C
new file mode 100644
index 000000000..00192a229
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C
@@ -0,0 +1,1367 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_0.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file lrdimm_decoder_v1_0.C
+/// @brief LRDIMM module SPD decoder definitions for revision 1.0
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H>
+#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
+#include <generic/memory/lib/spd/spd_checker.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/find.H>
+
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+
+namespace mss
+{
+namespace spd
+{
+namespace lrdimm
+{
+
+/////////////////////////
+// Non-member helper functions
+// For LRDIMM module rev 1.0
+/////////////////////////
+
+/// @brief Helper function to find SPD byte based on freq
+/// @param[in] i_dimm_speed DIMM speed in MT/s
+/// @param[out] o_byte byte to extract spd from
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400,
+/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values
+/// so we use a simple case statement to get our results.
+static fapi2::ReturnCode mdq_helper(const uint64_t i_dimm_speed, uint8_t& o_byte)
+{
+ switch(i_dimm_speed)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_byte = 145;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_byte = 146;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_byte = 147;
+ break;
+
+ default:
+ FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+};
+
+/// @brief Helper function to find start bit based on freq
+/// @param[in] i_dimm_speed DIMM speed in MT/s
+/// @param[out] o_start_bit start bit to extract SPD from
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400,
+/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values
+/// so we use a simple case statement to get our results.
+static fapi2::ReturnCode drive_strength_start_bit_finder(const uint64_t i_dimm_speed, size_t& o_start_bit)
+{
+ switch(i_dimm_speed)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_start_bit = 6;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_start_bit = 4;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_start_bit = 2;
+ break;
+
+ default:
+ FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+/// @brief Helper function to find SPD byte based on freq
+/// @param[in] i_dimm_speed DIMM speed in MT/s
+/// @param[out] o_byte byte to extract spd from
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400,
+/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values
+/// so we use a simple case statement to get our results.
+static fapi2::ReturnCode rtt_wr_and_nom_byte_finder(const uint64_t i_dimm_speed, size_t& o_byte)
+{
+ switch(i_dimm_speed)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_byte = 149;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_byte = 150;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_byte = 151;
+ break;
+
+ default:
+ FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+/// @brief Helper function to find SPD byte based on freq
+/// @param[in] i_dimm_speed DIMM speed in MT/s
+/// @param[out] o_byte byte to extract spd from
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD spec sets encoding based on freq ranges such as, 1866 < data rate <= 2400,
+/// But for Nimbus we can only be 1866, 2133, 2400, and 2666. No intermediate values
+/// so we use a simple case statement to get our results.
+static fapi2::ReturnCode rtt_park_byte_finder(const uint64_t i_dimm_speed, size_t& o_byte)
+{
+ switch(i_dimm_speed)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_byte = 152;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_byte = 153;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_byte = 154;
+ break;
+
+ default:
+ FAPI_ERR("Invalid dimm speed received: %d", i_dimm_speed);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+/////////////////////////
+// Member Method implementation
+// For LRDIMM module rev 1.0
+/////////////////////////
+
+///
+/// @brief Decodes module nominal height max
+/// @param[out] o_output height range encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 128 (Bits 4~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 55
+///
+fapi2::ReturnCode decoder_v1_0::max_module_nominal_height(uint8_t& o_output)
+{
+ uint8_t l_field_bits = extract_spd_field< MODULE_NOMINAL_HEIGHT >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b11111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ MODULE_NOMINAL_HEIGHT.iv_byte,
+ l_field_bits,
+ "Failed bound check for module nominal height max") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Max module nominal height: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes raw card extension
+/// @param[out] o_output raw card rev. encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 128 (Bits 7~5)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 55
+///
+fapi2::ReturnCode decoder_v1_0::raw_card_extension(uint8_t& o_output)
+{
+ uint8_t l_field_bits = extract_spd_field< RAW_CARD_EXTENSION >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ RAW_CARD_EXTENSION.iv_byte,
+ l_field_bits,
+ "Failed bound check for raw card extension") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Raw card extension: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes front module maximum thickness max
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 129 (Bits 3~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 55
+///
+fapi2::ReturnCode decoder_v1_0::front_module_max_thickness(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< FRONT_MODULE_THICKNESS >(iv_target, iv_spd_data);
+
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b1111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ FRONT_MODULE_THICKNESS.iv_byte,
+ l_field_bits,
+ "Failed bound check for front module max thickness") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Front module max thickness: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes back module maximum thickness max
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 129 (Bits 7~4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 55
+///
+fapi2::ReturnCode decoder_v1_0::back_module_max_thickness(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< BACK_MODULE_THICKNESS >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b1111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BACK_MODULE_THICKNESS.iv_byte,
+ l_field_bits,
+ "Failed bound check for back module max thickness") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Back module max thickness: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes number of registers used on LRDIMM
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 131 (Bits 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 57
+///
+fapi2::ReturnCode decoder_v1_0::num_registers_used(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< NUM_REGISTERS_USED >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 0b10;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ NUM_REGISTERS_USED.iv_byte,
+ l_field_bits,
+ "Failed bound check for number of registers used on RDIMM ") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Number of registers used on LRDIMM : %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of rows of DRAMs on LRDIMM
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 131 (Bits 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 57
+///
+fapi2::ReturnCode decoder_v1_0::num_rows_of_drams(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< NUM_ROWS_OF_DRAMS >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ NUM_REGISTERS_USED.iv_byte,
+ l_field_bits,
+ "Failed bound check for number of rows of DRAMs on LRDIMM ") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Number of rows of DRAMs on LRDIMM : %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes heat spreader solution
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 132 (Bit 7)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 58
+///
+fapi2::ReturnCode decoder_v1_0::heat_spreader_solution(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< HEAT_SPREADER_SOLUTION >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ HEAT_SPREADER_SOLUTION.iv_byte,
+ l_field_bits,
+ "Failed bound check for heat spreader solution") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Heat spreader solution: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes number of continuation codes
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 133 (bit 6~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 58
+///
+fapi2::ReturnCode decoder_v1_0::num_continuation_codes(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< CONTINUATION_CODES >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 10; // JEP106AS spec
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ CONTINUATION_CODES.iv_byte,
+ l_field_bits,
+ "Failed bound check for number of continuation codes") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Number of continuation codes: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register manufacturer ID code
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 134 (bit 7~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 58
+///
+fapi2::ReturnCode decoder_v1_0::reg_manufacturer_id_code(uint8_t& o_output)
+{
+ constexpr size_t BYTE_INDEX = 134;
+ uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX];
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // All bits used for encoding, no bounds to check
+ o_output = l_raw_byte;
+
+ FAPI_INF("%s. Register revision number: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes register revision number
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 135 (bit 7~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 58
+///
+fapi2::ReturnCode decoder_v1_0::register_rev_num(uint8_t& o_output)
+{
+ constexpr size_t BYTE_INDEX = 135;
+ uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX];
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // All bits used for encoding, no bounds to check
+ o_output = l_raw_byte;
+
+ FAPI_INF("%s. Register revision number: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes address mapping from register to dram
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 136 (bit 0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 59
+///
+fapi2::ReturnCode decoder_v1_0::register_to_dram_addr_mapping(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< ADDR_MAPPING >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ ADDR_MAPPING.iv_byte,
+ l_field_bits,
+ "Failed bound check for to register to dram addr mapping") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Address mapping from register to dram: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for CKE signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 60
+///
+fapi2::ReturnCode decoder_v1_0::cke_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< CKE_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ CKE_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CKE") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CKE: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for ODT signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 60
+///
+fapi2::ReturnCode decoder_v1_0::odt_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< ODT_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ ODT_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for ODT") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for ODT: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for command/address (CA) signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 5~4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 60
+///
+fapi2::ReturnCode decoder_v1_0::ca_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< CA_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t INVALID_VAL = 4;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < INVALID_VAL, // extract sanity check
+ CA_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CA") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CA: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for control signal (CS) signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 6~7)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 60
+///
+fapi2::ReturnCode decoder_v1_0::cs_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< CS_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ CS_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CS") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CS: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (B side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (bit 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 60
+///
+fapi2::ReturnCode decoder_v1_0::b_side_clk_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< B_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ B_SIDE_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y0,Y2)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (A side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (bit 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 60
+///
+fapi2::ReturnCode decoder_v1_0::a_side_clk_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< A_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ A_SIDE_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y1,Y3)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes data buffer revision number
+/// @param[out] o_output revision number
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 139 (Bits 7~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 60
+///
+fapi2::ReturnCode decoder_v1_0::data_buffer_rev(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 139;
+ const uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX];
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ // This checks JEDEC range is met
+ constexpr size_t UNDEFINED = 0xFF;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_raw_byte != UNDEFINED,
+ BYTE_INDEX,
+ l_raw_byte,
+ "Failed bounds check for data buffer revision number") );
+
+ // Update output only if check passes
+ o_output = l_raw_byte;
+
+ FAPI_INF("%s. Data buffer rev: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes DRAM VrefDQ for Package Rank 0
+/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 140 (Bits 5~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 61
+///
+fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank0(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK0 >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // JESD79-4 specification
+ constexpr size_t RESERVED = 0b110011;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ VREF_DQ_RANK0.iv_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM VrefDQ for Package Rank 0") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM VrefDQ for Package Rank 0: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM VrefDQ for Package Rank 1
+/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 141 (Bits 5~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 61
+///
+fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank1(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK1 >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // JESD79-4 specification
+ constexpr size_t RESERVED = 0b110011;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ VREF_DQ_RANK1.iv_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM VrefDQ for Package Rank 1") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM VrefDQ for Package Rank 1: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM VrefDQ for Package Rank 2
+/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 142 (Bits 5~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 61
+///
+fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank2(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK2 >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // JESD79-4 specification
+ constexpr size_t RESERVED = 0b110011;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ VREF_DQ_RANK2.iv_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM VrefDQ for Package Rank 2") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM VrefDQ for Package Rank 2: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM VrefDQ for Package Rank 3
+/// @param[out] o_output encoding of MR6 A5:A0 in JESD790-4 spec
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 143 (Bits 5~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.12.2 - 61
+///
+fapi2::ReturnCode decoder_v1_0::dram_vref_dq_rank3(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< VREF_DQ_RANK3 >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // JESD79-4 specification
+ constexpr size_t RESERVED = 0b110011;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ VREF_DQ_RANK3.iv_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM VrefDQ for Package Rank 3") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM VrefDQ for Package Rank 3: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes data buffer VrefDQ for DRAM interface
+/// @param[out] o_output encoding of F5BC6x in DDR4DB01 spec
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 144 (Bits 5~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 61
+///
+fapi2::ReturnCode decoder_v1_0::data_buffer_vref_dq(uint8_t& o_output)
+{
+ constexpr size_t BYTE_INDEX = 144;
+ uint8_t l_raw_data = iv_spd_data[BYTE_INDEX];
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_raw_data);
+
+ // DDR4DB01 spec
+ constexpr size_t RESERVED = 0b00110011;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_raw_data < RESERVED,
+ BYTE_INDEX,
+ l_raw_data,
+ "Failed bounds check for data buffer VrefDQ for DRAM interface") );
+
+ // Update output only if check passes
+ o_output = l_raw_data;
+
+ FAPI_INF("%s. Data buffer VrefDQ for DRAM interface: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM interface MDQ Drive Strenth
+/// of the data buffer component for a particular dimm speed
+/// @param[in] i_dimm_speed the dimm speed in MT/s
+/// @param[out] o_output encoding of F5BC6x in
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 145 - 147 (Bits 6~4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 62
+///
+fapi2::ReturnCode decoder_v1_0::data_buffer_mdq_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output)
+{
+ uint8_t l_byte = 0;
+ uint8_t l_field_bits = 0;
+
+ FAPI_TRY( mdq_helper(i_dimm_speed, l_byte) );
+
+ {
+ constexpr size_t START = 1;
+ constexpr size_t LEN = 3;
+ const field_t MDQ_DRIVE_STRENGTH(l_byte, START, LEN);
+
+ l_field_bits = extract_spd_field( iv_target, MDQ_DRIVE_STRENGTH, iv_spd_data );
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // Lets make sure we aren't being set to a reserved field
+ bool is_reserved_bit = false;
+
+ switch(l_field_bits)
+ {
+ case 0b011:
+ case 0b100:
+ case 0b110:
+ case 0b111:
+ is_reserved_bit = true;
+ break;
+
+ default:
+ is_reserved_bit = false;
+ break;
+ }
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 7;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits <= MAX_VALID_VALUE) &&
+ (is_reserved_bit != true),
+ l_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM interface MDQ Drive Strenth") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM interface MDQ Drive Strenth: %d",
+ mss::c_str(iv_target),
+ o_output);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM interface MDQ read termination strength
+/// of the data buffer component for a particular dimm speed
+/// @param[in] i_dimm_speed the dimm speed in MT/s
+/// @param[out] o_output encoding of F5BC6x in
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 145 - 147 (Bits 2~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 62
+///
+fapi2::ReturnCode decoder_v1_0::data_buffer_mdq_rtt(const uint64_t i_dimm_speed, uint8_t& o_output)
+{
+ uint8_t l_byte = 0;
+ uint8_t l_field_bits = 0;
+
+ FAPI_TRY( mdq_helper(i_dimm_speed, l_byte) );
+
+ {
+ constexpr size_t START = 1;
+ constexpr size_t LEN = 3;
+ const field_t DATA_BUFFER_MDQ_RTT(l_byte, START, LEN);
+
+ l_field_bits = extract_spd_field( iv_target, DATA_BUFFER_MDQ_RTT, iv_spd_data );
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 7;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ l_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM interface MDQ RTT:") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM interface MDQ RTT: %d",
+ mss::c_str(iv_target),
+ o_output);
+ }
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM drive strenth
+/// for a particular dimm speed
+/// @param[in] i_dimm_speed the dimm speed in MT/s
+/// @param[out] o_output DRAM drive strength (encoding)
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 148 (Bits 5~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 63
+///
+fapi2::ReturnCode decoder_v1_0::dram_drive_strength(const uint64_t i_dimm_speed, uint8_t& o_output)
+{
+ size_t l_start = 0;
+ FAPI_TRY( drive_strength_start_bit_finder(i_dimm_speed, l_start) );
+
+ {
+ constexpr size_t BYTE_INDEX = 148;
+ constexpr size_t LEN = 2;
+ const field_t DRAM_DRIVE_STRENGTH(BYTE_INDEX, l_start, LEN);
+
+ uint8_t l_field_bits = extract_spd_field( iv_target, DRAM_DRIVE_STRENGTH, iv_spd_data );
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // SPD JEDEC specification
+ constexpr size_t RESERVED = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bounds check for DRAM VrefDQ for Package Rank 3") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM drive strenth: %d",
+ mss::c_str(iv_target),
+ o_output);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM ODT for RTT_NOM
+/// for a particular dimm speed
+/// @param[in] i_dimm_speed the dimm speed in MT/s
+/// @param[out] o_output ODT termination strength (encoding)
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 149 - 151 (Bits 2~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - (64 - 65)
+///
+fapi2::ReturnCode decoder_v1_0::dram_rtt_nom(const uint64_t i_dimm_speed, uint8_t& o_output)
+{
+ size_t l_byte = 0;
+ FAPI_TRY( rtt_wr_and_nom_byte_finder(i_dimm_speed, l_byte) );
+
+ {
+ constexpr size_t START = 5;
+ constexpr size_t LEN = 3;
+ const field_t DRAM_RTT_NOM(l_byte, START, LEN);
+
+ uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_NOM, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 7;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ l_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM RTT_NOM") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM RTT_NOM: %d",
+ mss::c_str(iv_target),
+ o_output);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM ODT for RTT_WR
+/// for a particular dimm speed
+/// @param[in] i_dimm_speed the dimm speed in MT/s
+/// @param[out] o_output ODT termination strength (encoding)
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 149 - 151 (Bits 5~3)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - (64 - 65)
+///
+fapi2::ReturnCode decoder_v1_0::dram_rtt_wr(const uint64_t i_dimm_speed, uint8_t& o_output)
+{
+ size_t l_byte = 0;
+ FAPI_TRY( rtt_wr_and_nom_byte_finder(i_dimm_speed, l_byte) );
+
+ {
+ constexpr size_t START = 2;
+ constexpr size_t LEN = 3;
+ const field_t DRAM_RTT_WR(l_byte, START, LEN);
+
+ uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_WR, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // Lets make sure we aren't being set to a reserved field
+ bool is_reserved_bit = false;
+
+ switch(l_field_bits)
+ {
+ case 0b101:
+ case 0b110:
+ case 0b111:
+ is_reserved_bit = true;
+ break;
+
+ default:
+ is_reserved_bit = false;
+ break;
+ }
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 7;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits <= MAX_VALID_VALUE) &&
+ (is_reserved_bit != true),
+ l_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM RTT_WR") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM_RTT_WR: %d",
+ mss::c_str(iv_target),
+ o_output);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM ODT for RTT_PARK, package ranks 0 & 1
+/// for a particular dimm speed
+/// @param[in] i_dimm_speed the dimm speed in MT/s
+/// @param[out] o_output ODT termination strength (encoding)
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 152 - 154 (Bits 2~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 65
+///
+fapi2::ReturnCode decoder_v1_0::dram_rtt_park_ranks0_1(const uint64_t i_dimm_speed, uint8_t& o_output)
+{
+ size_t l_byte = 0;
+ FAPI_TRY( rtt_park_byte_finder(i_dimm_speed, l_byte) );
+
+ {
+ constexpr size_t START = 5;
+ constexpr size_t LEN = 3;
+ const field_t DRAM_RTT_PARK(l_byte, START, LEN);
+
+ uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_PARK, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 7;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ l_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM RTT_PARK (package ranks 0,1)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM RTT_PARK (package ranks 0,1): %d",
+ mss::c_str(iv_target),
+ o_output);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes DRAM ODT for RTT_PARK, package ranks 2 & 3
+/// for a particular dimm speed
+/// @param[in] i_dimm_speed the dimm speed in MT/s
+/// @param[out] o_output ODT termination strength (encoding)
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 152 - 154 (Bits 5~3)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12.2 - 65
+///
+fapi2::ReturnCode decoder_v1_0::dram_rtt_park_ranks2_3(const uint64_t i_dimm_speed, uint8_t& o_output)
+{
+ size_t l_byte = 0;
+ FAPI_TRY( rtt_park_byte_finder(i_dimm_speed, l_byte) );
+
+ {
+ constexpr size_t START = 2;
+ constexpr size_t LEN = 3;
+ const field_t DRAM_RTT_PARK(l_byte, START, LEN);
+
+ uint8_t l_field_bits = extract_spd_field(iv_target, DRAM_RTT_PARK, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 7;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ l_byte,
+ l_field_bits,
+ "Failed bounds check for DRAM RTT_PARK (package ranks 2,3)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. DRAM RTT_PARK (package ranks 2,3): %d",
+ mss::c_str(iv_target),
+ o_output);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}// lrdimm
+}//spd
+}// mss
diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C
new file mode 100644
index 000000000..32bc97940
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C
@@ -0,0 +1,273 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_1.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file lrdimm_decoder_v1_1.C
+/// @brief LRDIMM module SPD decoder definitions for revision 1.1
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H>
+#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
+#include <generic/memory/lib/spd/spd_checker.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/find.H>
+
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+namespace mss
+{
+namespace spd
+{
+namespace lrdimm
+{
+
+///
+/// @brief Decodes register and data buffer types
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 131 (Bits 7~4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12.3 - 63
+///
+fapi2::ReturnCode decoder_v1_1::register_and_buffer_type(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< REGISTER_TYPE >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ REGISTER_TYPE.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register and Data Buffer Types") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register and Data Buffer Types: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes register output drive strength for CKE signal
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (Bits 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12.3 - 65
+///
+fapi2::ReturnCode decoder_v1_1::cke_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< CKE_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ CKE_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CKE") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CKE: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for ODT signal
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (Bits 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12.3 - 65
+///
+fapi2::ReturnCode decoder_v1_1::odt_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< ODT_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ ODT_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for ODT") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for ODT: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for control signal (CS) signal
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (Bits 6~7)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12.3 - 65
+///
+fapi2::ReturnCode decoder_v1_1::cs_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< CS_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ CS_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CS") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CS: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (B side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (Bits 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12.3 - 66
+///
+fapi2::ReturnCode decoder_v1_1::b_side_clk_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< B_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ B_SIDE_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y0,Y2)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (A side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (Bits 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12.3 - 66
+///
+fapi2::ReturnCode decoder_v1_1::a_side_clk_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< A_SIDE_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL,
+ A_SIDE_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y1,Y3)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}// lrdimm
+}// spd
+}// mss
diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C
new file mode 100644
index 000000000..4e223cb19
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C
@@ -0,0 +1,306 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4_v1_2.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file lrdimm_decoder_v1_2.C
+/// @brief LRDIMM module SPD decoder definitions for revision 1.2
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H>
+#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
+#include <generic/memory/lib/spd/spd_checker.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/find.H>
+
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+namespace mss
+{
+namespace spd
+{
+namespace lrdimm
+{
+///
+/// @brief Decodes register output drive strength for data buffer control (BCOM, BODT, BKCE)
+/// @param[out] o_output encoded drive strength
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (Bit 4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.12.3 - 76
+///
+fapi2::ReturnCode decoder_v1_2::bcom_bcke_bodt_drive_strength(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< BCOM_BODT_BCKE_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL,
+ BCOM_BODT_BCKE_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for data buffer control (BCOM, BODT, BCKE)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for data buffer control (BCOM, BODT, BCKE): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for data buffer control (BCK)
+/// @param[out] o_output encoded drive strength
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (Bit 5)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.12.3 - 76
+///
+fapi2::ReturnCode decoder_v1_2::bck_output_drive_strength(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< BCK_DRIVE_STRENGTH >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL,
+ BCK_DRIVE_STRENGTH.iv_byte,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for data buffer control (BCK)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for data buffer control (BCK): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes RCD output slew rate control
+/// @param[out] o_output encoded drive strength
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (Bit 6)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.L-4 - 76
+///
+fapi2::ReturnCode decoder_v1_2::slew_rate_control(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< RCD_SLEW_CNTRL >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 0b1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ RCD_SLEW_CNTRL.iv_byte,
+ l_field_bits,
+ "Failed bound check for RCD output slew rate control") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. RCD output slew rate control: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes VrefDQ range for DRAM interface range
+/// @param[out] o_output spd encoding
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 155 (Bits 3~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.L-4 - 76
+///
+fapi2::ReturnCode decoder_v1_2::dram_vref_dq_range(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< DRAM_VREF_DQ_RANGE >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 0b1111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ DRAM_VREF_DQ_RANGE.iv_byte,
+ l_field_bits,
+ "Failed bound check for VrefDQ range for DRAM interface range ") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. VrefDQ range for DRAM interface range: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes data buffer VrefDQ range for DRAM interface range
+/// @param[out] o_output spd encoding
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 155 (Bit 4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.L-4 - 76
+///
+fapi2::ReturnCode decoder_v1_2::data_buffer_vref_dq_range(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_VREF_DQ >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ DATA_BUFFER_VREF_DQ.iv_byte,
+ l_field_bits,
+ "Failed bound check for data buffer VrefDQ range for DRAM interface range") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Data buffer VrefDQ range for DRAM interface range: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes data buffer gain adjustment
+/// @param[out] o_output spd encoding
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 156 (Bit 0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.L-4 - 77
+///
+fapi2::ReturnCode decoder_v1_2::data_buffer_gain_adjustment(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_GAIN_ADJUST >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ DATA_BUFFER_GAIN_ADJUST.iv_byte,
+ l_field_bits,
+ "Failed bound check for data buffer gain adjustment") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Data buffer gain adjustment: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes data buffer Decision Feedback Equalization (DFE)
+/// @param[out] o_output spd encoding
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 156 (Bit 1)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 4
+/// @note Page 4.1.2.L-4 - 77
+///
+fapi2::ReturnCode decoder_v1_2::data_buffer_dfe(uint8_t& o_output)
+{
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field< DATA_BUFFER_DFE >(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VAL = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VAL, // extract sanity check
+ DATA_BUFFER_DFE.iv_byte,
+ l_field_bits,
+ "Failed bound check for data buffer Decision Feedback Equalization (DFE)") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Data buffer Decision Feedback Equalization (DFE): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}// lrdimm
+}// spd
+}// mss
diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C
new file mode 100644
index 000000000..f4b943b2c
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C
@@ -0,0 +1,84 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file raw_cards.C
+/// @brief LRDIMM raw card data structure
+/// Contains RCW settings per raw card rev
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: FSP:HB
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H>
+
+namespace mss
+{
+
+///
+/// @brief raw card B0 settings
+///
+// TODO RTC:160116 Fill in valid RCD data for LRDIMM
+rcw_settings lrdimm_rc_b0( 0x00, // RC00
+ 0x00, // RC01 (C might be the right answer)
+ 0x00, // RC02
+ 0x1F, // RC06_7
+ 0x00, // RC09
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6C
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAx
+ 0x07);// RCBX
+
+namespace lrdimm
+{
+
+// TODO - RTC:160121 Catch all for adding raw card data for DIMMs
+const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
+{
+ // I expect this to grow as Warren M. expects us to have
+ // settings for every raw card that JEDEC puts out. Openpower
+ // can't break due to a missing raw card...
+ {raw_card_rev::B0, lrdimm_rc_b0},
+};
+
+}// lrdimm
+}// mss
diff --git a/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H
new file mode 100644
index 000000000..e3a99698d
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H
@@ -0,0 +1,68 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file raw_cards.H
+/// @brief Raw card data structure
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_LRDIMM_RAW_CARDS_H_
+#define _MSS_LRDIMM_RAW_CARDS_H_
+
+#include <fapi2.H>
+#include <cstdint>
+#include <vector>
+#include <generic/memory/lib/spd/common/rcw_settings.H>
+
+namespace mss
+{
+namespace lrdimm
+{
+
+// In the order of the vector below which needs to be sorted by enum value
+enum raw_card_rev : uint8_t
+{
+ // TODO RTC:160116 Fill in valid RCD data for LRDIMM
+ B0 = 0x01,
+};
+
+// Raw cards can share the same raw card # between RDIMM and LRDIMMs so
+// we track them independently. Since all of these don't come from SPD for DDR4,
+// we have to set some RCWs (we want limit these and derive as many as possible)
+extern const std::vector< std::pair< uint8_t, rcw_settings> > RAW_CARDS;
+
+}// lrdimm
+
+// Exposed so we can test them.
+extern rcw_settings lrdimm_rc_b0;
+
+}// mss
+
+#endif //_MSS_LRDIMM_RAW_CARDS_H_
diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H
new file mode 100644
index 000000000..effc7f983
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H
@@ -0,0 +1,431 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file rdimm_decoder.H
+/// @brief RDIMM module SPD decoder declarations
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_RDIMM_DECODER_H_
+#define _MSS_RDIMM_DECODER_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/spd/common/dimm_module_decoder.H>
+
+namespace mss
+{
+namespace spd
+{
+
+///
+/// @class decoder
+/// @brief RDIMM module SPD DRAM decoder for rev 1.0
+///
+class rdimm_decoder_v1_0 : public dimm_module_decoder
+{
+ protected:
+ enum
+ {
+ // Byte 128
+ MODULE_NOM_HEIGHT_START = 3,
+ MODULE_NOM_HEIGHT_LEN = 5,
+ RAW_CARD_EXT_START = 0,
+ RAW_CARD_EXT_LEN = 3,
+
+ // Byte 129
+ FRONT_MODULE_THICKNESS_START = 4,
+ FRONT_MODULE_THICKNESS_LEN = 4,
+ BACK_MODULE_THICKNESS_START = 0,
+ BACK_MODULE_THICKNESS_LEN = 4,
+
+ // Byte 130
+ REF_RAW_CARD_START = 3,
+ REF_RAW_CARD_LEN = 5,
+ REF_RAW_CARD_REV_START = 1,
+ REF_RAW_CARD_REV_LEN = 2,
+ REF_RAW_CARD_EXT_START = 0,
+ REF_RAW_CARD_EXT_LEN = 1,
+
+ // Byte 131
+ REGS_USED_START = 6,
+ REGS_USED_LEN = 2,
+ ROWS_OF_DRAMS_START = 4,
+ ROWS_OF_DRAMS_LEN = 2,
+ REGISTER_TYPE_START = 0,
+ REGISTER_TYPE_LEN = 4,
+
+ // Byte 132
+ HEAT_SPREADER_CHAR_START = 1,
+ HEAT_SPREADER_CHAR_LEN = 7,
+ HEAT_SPREADER_SOL_START = 0,
+ HEAT_SPREADER_SOL_LEN = 1,
+
+ // Byte 133
+ CONTINUATION_CODES_START = 1,
+ CONTINUATION_CODES_LEN = 7,
+
+ // Byte 134 - whole byte taken
+ // Byte 135 - whole byte taken
+
+ // Byte 136
+ ADDR_MAPPING_START = 7,
+ ADDR_MAPPING_LEN = 1,
+
+ // Byte 137
+ CKE_DRIVER_START = 6,
+ CKE_DRIVER_LEN = 2,
+ ODT_DRIVER_START = 4,
+ ODT_DRIVER_LEN = 2,
+ CA_DRIVER_START = 2,
+ CA_DRIVER_LEN = 2,
+ CS_DRIVER_START = 0,
+ CS_DRIVER_LEN = 2,
+
+ // Byte 138
+ YO_Y2_DRIVER_START = 6,
+ YO_Y2_DRIVER_LEN = 2,
+ Y1_Y3_DRIVER_START = 4,
+ Y1_Y3_DRIVER_LEN = 2,
+ };
+
+ enum addr_mapping
+ {
+ STANDARD = 0,
+ MIRRORED = 1,
+ };
+
+ public:
+ // deleted default ctor
+ rdimm_decoder_v1_0() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data vector DIMM SPD data
+ ///
+ rdimm_decoder_v1_0(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data): iv_target(i_target), iv_spd_data(i_spd_data)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ virtual ~rdimm_decoder_v1_0() = default;
+
+ ///
+ /// @brief Decodes module nominal height max, in mm
+ /// @param[out] o_output height range encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 128 (Bits 4~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 48
+ ///
+ virtual fapi2::ReturnCode max_module_nominal_height(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes front module maximum thickness max, in mm
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 129 (Bits 3~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 48
+ ///
+ virtual fapi2::ReturnCode front_module_max_thickness(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes back module maximum thickness max, in mm
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 129 (Bits 7~4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 48
+ ///
+ virtual fapi2::ReturnCode back_module_max_thickness(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes number of registers used on RDIMM
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 131 (Bits 1~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 50
+ ///
+ virtual fapi2::ReturnCode num_registers_used(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes number of rows of DRAMs on RDIMM
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 131 (Bits 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 50
+ ///
+ virtual fapi2::ReturnCode num_rows_of_drams(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes heat spreader thermal characteristics
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCEawSS if okay
+ /// @note SPD Byte 132 (Bits 6~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 51
+ ///
+ virtual fapi2::ReturnCode heat_spreader_thermal_char(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes heat spreader solution
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 132 (Bit 7)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 51
+ ///
+ virtual fapi2::ReturnCode heat_spreader_solution(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes number of continuation codes
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 133 (bit 6~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 51
+ ///
+ virtual fapi2::ReturnCode num_continuation_codes(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register manufacturer ID code
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 133 (bit 6~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 51
+ ///
+ virtual fapi2::ReturnCode reg_manufacturer_id_code(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register revision number
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 136 (bit 7~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 51
+ ///
+ virtual fapi2::ReturnCode register_rev_num(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes address mapping from register to dram
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 136 (bit 0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 52
+ ///
+ virtual fapi2::ReturnCode register_to_dram_addr_mapping(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for CKE signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (bit 1~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 53
+ ///
+ virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for ODT signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (bit 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 53
+ ///
+ virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for command/address (CA) signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (bit 5~4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 53
+ ///
+ virtual fapi2::ReturnCode ca_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for control signal (CS) signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (bit 6~7)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 53
+ ///
+ virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (B side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (bit 1~0)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 53
+ ///
+ virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (A side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (bit 3~2)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 2
+ /// @note Page 4.1.2.12 - 53
+ ///
+ virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override;
+
+ protected:
+ const fapi2::Target<fapi2::TARGET_TYPE_DIMM> iv_target;
+ const std::vector<uint8_t> iv_spd_data;
+
+};// rdimm_decoder_v1_0
+
+///
+/// @class decoder
+/// @brief RDIMM module SPD DRAM decoder for rev 1.1
+///
+class rdimm_decoder_v1_1 : public rdimm_decoder_v1_0
+{
+ public:
+
+ // deleted default ctor
+ rdimm_decoder_v1_1() = delete;
+
+ ///
+ /// @brief ctor
+ /// @param[in] i_target dimm target
+ /// @param[in] i_spd_data vector DIMM SPD data
+ ///
+ rdimm_decoder_v1_1(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::vector<uint8_t>& i_spd_data): rdimm_decoder_v1_0(i_target, i_spd_data)
+ {}
+
+ ///
+ /// @brief default dtor
+ ///
+ virtual ~rdimm_decoder_v1_1() = default;
+
+ ///
+ /// @brief Decodes register types
+ /// @param[out] o_output encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 131 (Bits 7~4)
+ /// @note Item JEDEC Standard No. 21-C
+ /// @note DDR4 SPD Document Release 3
+ /// @note Page 4.1.2.12.3 - 63
+ ///
+ virtual fapi2::ReturnCode register_and_buffer_type(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for CKE signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (bit 1~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 76
+ /// @note DDR4 SPD Document Release 4
+ ///
+ virtual fapi2::ReturnCode cke_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for ODT signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (bit 3~2)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 76
+ /// @note DDR4 SPD Document Release 4
+ ///
+ virtual fapi2::ReturnCode odt_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for control signal (CS) signal
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 137 (bit 6~7)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 76
+ /// @note DDR4 SPD Document Release 4
+ ///
+ virtual fapi2::ReturnCode cs_signal_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (B side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (bit 1~0)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 76
+ /// @note DDR4 SPD Document Release 4
+ ///
+ virtual fapi2::ReturnCode b_side_clk_output_driver(uint8_t& o_output) override;
+
+ ///
+ /// @brief Decodes register output drive strength for clock (A side)
+ /// @param[out] o_output drive strength encoding from SPD
+ /// @return FAPI2_RC_SUCCESS if okay
+ /// @note SPD Byte 138 (bit 3~2)
+ /// @note Item JC-45-2220.01x
+ /// @note Page 76
+ /// @note DDR4 SPD Document Release 4
+ ///
+ virtual fapi2::ReturnCode a_side_clk_output_driver(uint8_t& o_output) override;
+
+};//rdimm_decoder_v1_1
+
+}// spd
+}// mss
+
+#endif //_MSS_RDIMM_DECODER_H_
diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C
new file mode 100644
index 000000000..43eb08c51
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C
@@ -0,0 +1,672 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_0.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+///
+/// @file rdimm_decoder.C
+/// @brief RDIMM module specific SPD decoder definitions
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H>
+#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
+#include <generic/memory/lib/spd/spd_checker.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/find.H>
+
+using fapi2::TARGET_TYPE_MCBIST;
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+
+namespace mss
+{
+namespace spd
+{
+
+/////////////////////////
+// Member Method implementation
+// For RDIMM module rev 1.0
+/////////////////////////
+
+///
+/// @brief Decodes module nominal height max, in mm
+/// @param[out] o_output height range encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 128 (Bits 4~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 48
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::max_module_nominal_height(uint8_t& o_output)
+{
+ constexpr size_t BYTE_INDEX = 128;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, MODULE_NOM_HEIGHT_START, MODULE_NOM_HEIGHT_LEN>(iv_target,
+ iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b11111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for module nominal height max") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Max module nominal height: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes front module maximum thickness max, in mm
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 129 (Bits 3~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 48
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::front_module_max_thickness(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 129;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, FRONT_MODULE_THICKNESS_START, FRONT_MODULE_THICKNESS_LEN>
+ (iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b1111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for front module max thickness") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Front module max thickness: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes back module maximum thickness max, in mm
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 129 (Bits 7~4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 48
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::back_module_max_thickness(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 129;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, BACK_MODULE_THICKNESS_START, BACK_MODULE_THICKNESS_LEN>(iv_target,
+ iv_spd_data);
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b1111;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for back module max thickness") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Back module max thickness: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes number of registers used on RDIMM
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 131 (Bits 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 50
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::num_registers_used(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 131;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, REGS_USED_START, REGS_USED_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for number of registers used on RDIMM ") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Number of registers used on RDIMM : %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes number of rows of DRAMs on RDIMM
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 131 (Bits 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 50
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::num_rows_of_drams(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 131;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, ROWS_OF_DRAMS_START, ROWS_OF_DRAMS_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for number of rows of DRAMs on RDIMM ") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Number of rows of DRAMs on RDIMM : %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes heat spreader thermal characteristics
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCEawSS if okay
+/// @note SPD Byte 132 (Bits 6~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 51
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::heat_spreader_thermal_char(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 132;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, HEAT_SPREADER_CHAR_START, HEAT_SPREADER_CHAR_LEN>(iv_target,
+ iv_spd_data);
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for heat spreader thermal characteristics") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Heat spreader thermal characteristics: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes heat spreader solution
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 132 (Bit 7)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 51
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::heat_spreader_solution(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 132;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, HEAT_SPREADER_SOL_START, HEAT_SPREADER_SOL_LEN>(iv_target,
+ iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 1;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for heat spreader solution") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Heat spreader solution: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Decodes number of continuation codes
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 133 (bit 6~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 51
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::num_continuation_codes(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 133;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, CONTINUATION_CODES_START, CONTINUATION_CODES_LEN>(iv_target,
+ iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t MAX_VALID_VALUE = 10; // JEP106AS
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits <= MAX_VALID_VALUE,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for number of continuation codes") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Number of continuation codes: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes register manufacturer ID code
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 134 (bit 7~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 51
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::reg_manufacturer_id_code(uint8_t& o_output)
+{
+ constexpr size_t BYTE_INDEX = 134;
+ uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX];
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ o_output = l_raw_byte;
+
+ FAPI_INF("%s. Manufacturer ID code: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes register revision number
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 135 (bit 7~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 51
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::register_rev_num(uint8_t& o_output)
+{
+ constexpr size_t BYTE_INDEX = 135;
+ uint8_t l_raw_byte = iv_spd_data[BYTE_INDEX];
+
+ // Trace in the front assists w/ debug
+ FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
+ mss::c_str(iv_target),
+ BYTE_INDEX,
+ l_raw_byte);
+
+ o_output = l_raw_byte;
+
+ FAPI_INF("%s. Register revision number: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Decodes address mapping from register to dram
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 136 (bit 0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 52
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::register_to_dram_addr_mapping(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 136;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, ADDR_MAPPING_START, ADDR_MAPPING_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bound check for to register to dram addr mapping") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Address mapping from register to dram: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for CKE signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 53
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::cke_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 137;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, CKE_DRIVER_START, CKE_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CKE") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CKE: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for ODT signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 53
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::odt_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 137;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, ODT_DRIVER_START, ODT_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for ODT") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for ODT: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for command/address (CA) signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 5~4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 53
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::ca_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 137;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, CA_DRIVER_START, CA_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t INVALID_VAL = 3;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < INVALID_VAL, // extract sanity check
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CA") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CA: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for control signal (CS) signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 6~7)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 53
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::cs_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 137;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, CS_DRIVER_START, CS_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CS") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CS: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (B side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (bit 1~0)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 53
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::b_side_clk_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE_INDEX = 138;
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, YO_Y2_DRIVER_START, YO_Y2_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED, // extract sanity check
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y0,Y2)") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (A side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (bit 3~2)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 2
+/// @note Page 4.1.2.12 - 53
+///
+fapi2::ReturnCode rdimm_decoder_v1_0::a_side_clk_output_driver(uint8_t& o_output)
+{
+ // Trace in the front assists w/ debug
+ constexpr size_t BYTE_INDEX = 138;
+
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field<BYTE_INDEX, Y1_Y3_DRIVER_START, Y1_Y3_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ l_field_bits < RESERVED,
+ BYTE_INDEX,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y1,Y3)") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}//spd namespace
+}// mss namespace
diff --git a/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C
new file mode 100644
index 000000000..4517de0a7
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C
@@ -0,0 +1,273 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4_v1_1.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H>
+#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
+#include <generic/memory/lib/spd/spd_checker.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/find.H>
+
+using fapi2::TARGET_TYPE_MCBIST;
+using fapi2::TARGET_TYPE_MCA;
+using fapi2::TARGET_TYPE_MCS;
+using fapi2::TARGET_TYPE_DIMM;
+
+
+namespace mss
+{
+namespace spd
+{
+
+/////////////////////////
+// Member Method implementation
+// For RDIMM module rev 1.1
+/////////////////////////
+
+///
+/// @brief Decodes register type
+/// @param[out] o_output encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 131 (Bits 7~4)
+/// @note Item JEDEC Standard No. 21-C
+/// @note DDR4 SPD Document Release 3
+/// @note Page 4.1.2.12.3 - 63
+///
+fapi2::ReturnCode rdimm_decoder_v1_1::register_and_buffer_type(uint8_t& o_output)
+{
+ constexpr size_t BYTE = 131;
+ // Extracting desired bits
+ uint8_t l_field_bits = extract_spd_field<BYTE, REGISTER_TYPE_START, REGISTER_TYPE_LEN>(iv_target, iv_spd_data);
+ FAPI_INF("Field Bits value: %d", l_field_bits);
+
+ // This checks my extracting params returns a value within bound
+ constexpr size_t RESERVED = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits < RESERVED), // extract sanity check
+ BYTE,
+ l_field_bits,
+ "Failed bounds check for Register and Data Buffer Types") );
+
+ // Update output only if check passes
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Types: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Decodes register output drive strength for CKE signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 76
+/// @note DDR4 SPD Document Release 4
+///
+fapi2::ReturnCode rdimm_decoder_v1_1::cke_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE = 137;
+ uint8_t l_field_bits = extract_spd_field<BYTE, CKE_DRIVER_START, CKE_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This really just checks my extract gives me a valid value
+ constexpr size_t MAX_VALID_VALUE = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits <= MAX_VALID_VALUE), // extract sanity check
+ BYTE,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for CKE") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CKE: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for ODT signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 3~2)
+/// @note Item JC-45-2220.01x
+/// @note Page 76
+/// @note DDR4 SPD Document Release 4
+///
+fapi2::ReturnCode rdimm_decoder_v1_1::odt_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE = 137;
+ uint8_t l_field_bits = extract_spd_field<BYTE, ODT_DRIVER_START, ODT_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This really just checks my extract gives me a valid value
+ constexpr size_t MAX_VALID_VALUE = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits <= MAX_VALID_VALUE), // extract sanity check
+ BYTE,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for ODT") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for ODT: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for control signal (CS) signal
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 137 (bit 6~7)
+/// @note Item JC-45-2220.01x
+/// @note Page 76
+/// @note DDR4 SPD Document Release 4
+///
+fapi2::ReturnCode rdimm_decoder_v1_1::cs_signal_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE = 137;
+ uint8_t l_field_bits = extract_spd_field<BYTE, CS_DRIVER_START, CS_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This really just checks my extract gives me a valid value
+ constexpr size_t MAX_VALID_VALUE = 0b11;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits <= MAX_VALID_VALUE), // extract sanity check
+ BYTE,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for chip select") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for CS: %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (B side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (bit 1~0)
+/// @note Item JC-45-2220.01x
+/// @note Page 76
+/// @note DDR4 SPD Document Release 4
+///
+fapi2::ReturnCode rdimm_decoder_v1_1::b_side_clk_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE = 138;
+ uint8_t l_field_bits = extract_spd_field<BYTE, YO_Y2_DRIVER_START, YO_Y2_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This really just checks my extract gives me a valid value
+ constexpr size_t MAX_VALID_VAL = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits <= MAX_VALID_VAL), // extract sanity check
+ BYTE,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y0,Y2)") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y0,Y2): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Decodes register output drive strength for clock (A side)
+/// @param[out] o_output drive strength encoding from SPD
+/// @return FAPI2_RC_SUCCESS if okay
+/// @note SPD Byte 138 (bit 3~2)
+/// @note Item JC-45-2220.01x
+/// @note Page 76
+/// @note DDR4 SPD Document Release 4
+///
+fapi2::ReturnCode rdimm_decoder_v1_1::a_side_clk_output_driver(uint8_t& o_output)
+{
+ // Extracting desired bits
+ constexpr size_t BYTE = 138;
+ uint8_t l_field_bits = extract_spd_field<BYTE, Y1_Y3_DRIVER_START, Y1_Y3_DRIVER_LEN>(iv_target, iv_spd_data);
+
+ FAPI_INF("Field_Bits value: %d", l_field_bits);
+
+ // This really just checks my extract gives me a valid value
+ constexpr size_t MAX_VALID_VAL = 2;
+
+ FAPI_TRY( mss::check::spd::fail_for_invalid_value(iv_target,
+ (l_field_bits <= MAX_VALID_VAL), // extract sanity check
+ BYTE,
+ l_field_bits,
+ "Failed bounds check for Register Output Driver for clock (Y1,Y3)") );
+
+ o_output = l_field_bits;
+
+ FAPI_INF("%s. Register Output Driver for clock (Y1,Y3): %d",
+ mss::c_str(iv_target),
+ o_output);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+}//spd
+}// mss
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
new file mode 100644
index 000000000..0b4e50f02
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C
@@ -0,0 +1,216 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file raw_cards.C
+/// @brief RDIMM raw card data structure
+/// Contains RCW settings per raw card rev
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: FSP:HB
+
+// std lib
+#include <vector>
+
+// fapi2
+#include <fapi2.H>
+
+// mss lib
+#include <generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H>
+
+namespace mss
+{
+
+///
+/// @brief raw card C1 settings
+///
+rcw_settings rdimm_rc_c1( 0x00, // RC00
+ 0x00, // RC01 (C might be the right answer?)
+ 0x00, // RC02
+ 0x0F, // RC06_07
+ 0x00, // RC09
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6X
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAX
+ 0x07);// RCBX
+
+///
+/// @brief raw card C2 settings
+/// @note same settings as C1
+///
+rcw_settings rdimm_rc_c2( 0x00, // RC00
+ 0x00, // RC01 (C might be the right answer?)
+ 0x00, // RC02
+ 0x0F, // RC06_07
+ 0x00, // RC09
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6X
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAX
+ 0x07);// RCBX
+
+///
+/// @brief raw card A1 settings
+///
+rcw_settings rdimm_rc_a1( 0x00, // RC00
+ 0x00, // RC01 (C might be the right answer?)
+ 0x00, // RC02
+ 0x0F, // RC06_07
+ 0x00, // RC09
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6X
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAX
+ 0x07);// RCBX
+
+///
+/// @brief raw card B1 settings
+/// @note need to verify, copy from b2, need to verify with b1 annex
+///
+rcw_settings rdimm_rc_b1( 0x00, // RC00
+ 0x00, // RC01 (C might be the right answer?)
+ 0x00, // RC02
+ 0x0F, // RC06_07
+ 0x00, // RC09 //Should be set in eff_config for CKE power DOWN modep:q
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6X
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAX
+ 0x07);// RCBX
+
+///
+/// @brief raw card B2 settings
+///
+rcw_settings rdimm_rc_b2( 0x00, // RC00
+ 0x00, // RC01 (C might be the right answer?)
+ 0x00, // RC02
+ 0x0F, // RC06_07
+ 0x00, // RC09
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6X
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAX
+ 0x07);// RCBX
+
+////
+/// @brief raw card for custom dimms
+///
+rcw_settings rdimm_rc_custom ( 0x00, // RC00
+ 0x00, // RC01 (C might be the right answer?)
+ 0x00, // RC02
+ 0x0F, // RC06_07
+ 0x00, // RC09
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6X
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAX
+ 0x07);// RCBX
+
+//
+/// @brief raw card VBU settings
+///
+rcw_settings rdimm_rc_vbu( 0x00, // RC00
+ 0x00, // RC01
+ 0x00, // RC02
+ 0x0F, // RC06_07
+ 0x00, // RC09
+ 0x0E, // RC0B
+ 0x00, // RC0C
+ 0x00, // RC0F
+ 0x00, // RC1X
+ 0x00, // RC2X
+ 0x00, // RC4X
+ 0x00, // RC5X
+ 0x00, // RC6X
+ 0x00, // RC8X
+ 0x00, // RC9X
+ 0x00, // RCAX
+ 0x07);// RCBX
+
+namespace rdimm
+{
+
+const std::vector< std::pair< uint8_t , rcw_settings> > RAW_CARDS =
+{
+ // I expect this to grow as Warren M. expects us to have
+ // settings for every raw card that JEDEC puts out. Openpower
+ // can't break due to a missing raw card...
+ {raw_card_rev::A1, rdimm_rc_a1},
+ {raw_card_rev::B1, rdimm_rc_b1},
+ {raw_card_rev::C1, rdimm_rc_c1},
+ {raw_card_rev::VBU, rdimm_rc_vbu},
+ {raw_card_rev::B2, rdimm_rc_b2},
+ {raw_card_rev::C2, rdimm_rc_c2},
+ {raw_card_rev::CUSTOM, rdimm_rc_custom},
+};
+
+}// rdimm
+}// mss
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
new file mode 100644
index 000000000..02c30ba79
--- /dev/null
+++ b/src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H
@@ -0,0 +1,86 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/import/generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+///
+/// @file raw_cards.H
+/// @brief Raw card data structure
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_RDIMM_RAW_CARDS_H_
+#define _MSS_RDIMM_RAW_CARDS_H_
+
+#include <fapi2.H>
+#include <cstdint>
+#include <vector>
+#include <generic/memory/lib/spd/common/rcw_settings.H>
+
+namespace mss
+{
+namespace rdimm
+{
+
+// In the order of the vector below which needs to be sorted by enum value
+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,
+
+ B2 = 0x41,
+ C2 = 0x42,
+
+ // Default settings used for DIMMs that do not use a JEDEC raw card reference
+ CUSTOM = 0xFF,
+};
+
+// Raw cards can share the same raw card # between RDIMM and LRDIMMs so
+// we track them independently. Since all of these don't come from SPD for DDR4,
+// we have to set some RCWs (we want limit these and derive as many as possible)
+extern const std::vector< std::pair< uint8_t, rcw_settings> > RAW_CARDS;
+
+}// rdimm
+
+// Exposed so we can test them.
+extern rcw_settings rdimm_rc_c1;
+extern rcw_settings rdimm_rc_c2;
+extern rcw_settings rdimm_rc_a1;
+extern rcw_settings rdimm_rc_b1;
+extern rcw_settings rdimm_rc_b2;
+extern rcw_settings rdimm_rc_custom;
+extern rcw_settings rdimm_rc_vbu;
+
+}// mss
+
+#endif //_MSS_RDIMM_RAW_CARDS_H_
diff --git a/src/import/generic/memory/lib/spd/spd_checker.H b/src/import/generic/memory/lib/spd/spd_checker.H
index 77cc902f3..d3a85aaa4 100644
--- a/src/import/generic/memory/lib/spd/spd_checker.H
+++ b/src/import/generic/memory/lib/spd/spd_checker.H
@@ -22,3 +22,115 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+#ifndef _SPD_CHECKER_H_
+#define _SPD_CHECKER_H_
+
+#include <fapi2.H>
+
+namespace mss
+{
+namespace check
+{
+namespace spd
+{
+
+///
+/// @brief Checks conditional passes and implements traces & exits if it fails
+/// @tparam T input data of any size
+/// @param[in] i_target fapi2 dimm target
+/// @param[in] i_conditional conditional that we are testing against
+/// @param[in] i_spd_byte_index current SPD byte
+/// @param[in] i_spd_data debug data
+/// @param[in] i_err_str error string to print out when conditional fails
+/// @return ReturnCode
+///
+template< typename T >
+inline fapi2::ReturnCode fail_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const bool i_conditional,
+ const size_t i_spd_byte_index,
+ const T i_spd_data,
+ const char* i_err_str)
+{
+ FAPI_ASSERT(i_conditional,
+ fapi2::MSS_BAD_SPD().
+ set_VALUE(i_spd_data).
+ set_BYTE(i_spd_byte_index).
+ set_DIMM_TARGET(i_target),
+ "%s %s Byte %d, Data returned: %d.",
+ c_str(i_target),
+ i_err_str,
+ i_spd_byte_index,
+ i_spd_data);
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+
+} // fail_for_invalid_value()
+
+///
+/// @brief Checks conditional passes and implements traces if it fails. No FFDC collected.
+/// @tparam T input data of any size
+/// @param[in] i_target fapi2 dimm target
+/// @param[in] i_conditional that we are testing against
+/// @param[in] i_spd_byte_index
+/// @param[in] i_spd_data debug data
+/// @param[in] i_err_str string to print out when conditional fails
+/// @return void
+///
+template< typename T >
+inline void warn_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const bool i_conditional,
+ const size_t i_spd_byte_index,
+ const T i_spd_data,
+ const char* i_err_str)
+{
+ // Don't print warning conditional if true
+ if(!i_conditional)
+ {
+ FAPI_IMP("%s. %s. Byte %d, Data returned: %d.",
+ c_str(i_target),
+ i_err_str,
+ i_spd_byte_index,
+ i_spd_data );
+ }
+}// warn_for_invalid_value
+
+///
+/// @brief Checks if valid factory parameters are given
+/// @param[in] i_target fapi2 dimm target
+/// @param[in] i_dimm_type DIMM type enumeration
+/// @param[in] i_encoding_rev SPD encoding level rev number
+/// @param[in] i_additions_rev SPD additions level rev number
+/// @param[in] i_err_str string to print out when conditional fails
+/// @return fapi2::ReturnCode
+///
+inline fapi2::ReturnCode invalid_factory_sel(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_dimm_type,
+ const uint8_t i_encoding_rev,
+ const uint8_t i_additions_rev,
+ const char* i_err_str)
+{
+ FAPI_ASSERT(false,
+ fapi2::MSS_INVALID_DIMM_REV_COMBO().
+ set_DIMM_TYPE(i_dimm_type).
+ set_ENCODING_REV(i_encoding_rev).
+ set_ADDITIONS_REV(i_additions_rev).
+ set_DIMM_TARGET(i_target),
+ "%s. %s. Invalid combination for dimm type: %d, rev: %d.%d",
+ c_str(i_target),
+ i_err_str,
+ i_dimm_type,
+ i_encoding_rev,
+ i_additions_rev);
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ return fapi2::current_err;
+}// invalid_factory_sel
+
+}// spd
+}// check
+}// mss
+
+#endif
OpenPOWER on IntegriCloud