summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C')
-rw-r--r--src/import/generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4_v1_1.C850
1 files changed, 850 insertions, 0 deletions
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
OpenPOWER on IntegriCloud