summaryrefslogtreecommitdiffstats
path: root/src/import
diff options
context:
space:
mode:
authorBrian Silver <bsilver@us.ibm.com>2016-08-07 12:47:05 -0500
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2016-08-09 11:23:44 -0400
commit481d34db3c9cb6fcc016daf5f70f9f8f63791256 (patch)
tree9a964acdf1a0042f62e40a2d738b3ab302641c3f /src/import
parenta813cd37381b61b4021a012b0ceb8612b64f6790 (diff)
downloadtalos-hostboot-481d34db3c9cb6fcc016daf5f70f9f8f63791256.tar.gz
talos-hostboot-481d34db3c9cb6fcc016daf5f70f9f8f63791256.zip
Change VPD decoding to account for MCA VPD spread over MCS blobs
Update formatting of eff_config error xml Change eff_config ctor to decode VPD to ensure ordering Change-Id: I29f4fe7b73cdc9c25fc524e84a1e8dc9d85bd5cb Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/27964 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/27965 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/import')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C68
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H18
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mss_vpd_decoder.H1375
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C10
-rw-r--r--src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml16
5 files changed, 868 insertions, 619 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C
index 0fcc69039..97601d088 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C
@@ -3398,8 +3398,11 @@ fapi_try_exit:
///
fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target<TARGET_TYPE_MCS>& i_target)
{
- uint8_t l_mt_blob[mss::VPD_KEYWORD_MAX];
- uint8_t l_mr_blob[mss::VPD_KEYWORD_MAX];
+ uint8_t l_mr_blob[mss::VPD_KEYWORD_MAX] = {0};
+ std::vector<uint8_t*> l_mt_blobs(PORTS_PER_MCS, nullptr);
+
+ // For sanity. Not sure this will break us, but we're certainly making assumptions below.
+ static_assert(MAX_DIMM_PER_PORT == 2, "Max DIMM per port isn't 2");
// Get MT data
{
@@ -3415,8 +3418,41 @@ fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target<TARGET_TYPE_MCS>& i
}
// For MT we need to fill in the rank information
- // TODO RTC:157758 Seems the interface is incorrect, but we're just returning fake VPD here anyway
- FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_mt_blob[0])) );
+ // But, of course, the rank information can differ per port. However, the vpd interface doesn't
+ // allow this in a straight-forward way. So, we have to get VPD blobs for MCS which contain
+ // ports which have the rank configuration in question. This means, basically, we pass a MCS MT
+ // blob to the decoder for each MCA, regardless of whether the port configurations are the same.
+ for (const auto& p : find_targets<TARGET_TYPE_MCA>(i_target))
+ {
+ uint8_t* l_mt_blob = new uint8_t[mss::VPD_KEYWORD_MAX];
+ uint64_t l_rank_count_dimm[MAX_DIMM_PER_PORT] = {0};
+
+ // Make sure the mt blob is all 0's. In the event that we get an MCA who has 0 ranks (no DIMM)
+ // we don't want to get the VPD (that will fail) but we can't give up. Cronus will
+ // give us MCA with 0 DIMM, so we'll just use a 0-filled VPD for those MCA.
+ memset(l_mt_blob, 0, mss::VPD_KEYWORD_MAX);
+
+ for (const auto& d : find_targets<TARGET_TYPE_DIMM>(p))
+ {
+ uint8_t l_num_master_ranks = 0;
+ FAPI_TRY( mss::eff_num_master_ranks_per_dimm(d, l_num_master_ranks) );
+ l_rank_count_dimm[mss::index(d)] = l_num_master_ranks;
+ }
+
+ // This value will, of course, be 0 if there is no DIMM in the port.
+ l_vpd_info.iv_rank_count_dimm_0 = l_rank_count_dimm[0];
+ l_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1];
+
+ // Get the MCS blob for this specific rank combination *only if* we have DIMM. Remember,
+ // Cronus can give us functional MCA which have no DIMM - and we'd puke getting the VPD.
+ if ((l_vpd_info.iv_rank_count_dimm_0 != 0) || (l_vpd_info.iv_rank_count_dimm_1 != 0))
+ {
+ FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_mt_blob[0])) );
+ }
+
+ // Put it in the vector in the right place.
+ l_mt_blobs[mss::index(p)] = l_mt_blob;
+ }
}
// Get MR data
@@ -3433,13 +3469,31 @@ fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target<TARGET_TYPE_MCS>& i
}
// For MR we need to tell the VPDInfo the frequency (err ... mt/s - why is this mhz?)
- FAPI_TRY( mss::freq(mss::find_target<TARGET_TYPE_MCBIST>(i_target), l_vpd_info.iv_freq_mhz) );
- FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_mr_blob[0])) );
+ FAPI_TRY( mss::freq(find_target<TARGET_TYPE_MCBIST>(i_target), l_vpd_info.iv_freq_mhz) );
+
+ // Only get the MR blob if we have a freq. It's possible for Cronus to give us an MCS which
+ // is connected to a controller which has 0 DIMM installed. In this case, we won't have
+ // a frequency, and thus we'd fail getting the VPD. So we initiaized the VPD to 0's and if
+ // there's no freq, we us a 0 filled VPD.
+ if (l_vpd_info.iv_freq_mhz != 0)
+ {
+ FAPI_TRY( mss::getVPD(i_target, l_vpd_info, &(l_mr_blob[0])) );
+ }
}
- FAPI_TRY( mss::eff_decode(i_target, l_mt_blob, l_mr_blob) );
+ FAPI_TRY( mss::eff_decode(i_target, l_mt_blobs, l_mr_blob) );
fapi_try_exit:
+
+ // delete the mt blobs
+ for (auto p : l_mt_blobs)
+ {
+ if (p != nullptr)
+ {
+ delete[] p;
+ }
+ }
+
return fapi2::current_err;
}
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H
index d4d6c874a..98ec81ddc 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H
@@ -56,10 +56,19 @@ class eff_config
// state of decoder timebases, target, fapi2 positions,
// and clock period eliminate code duplication.
- //
- // @brief Constructor
- //
- eff_config() = default;
+ ///
+ /// @brief Constructor
+ /// @tparam T, the fapi2::TargetType of the target
+ /// @param[in] i_target, the fapi2::Target which we're configuring
+ /// @param[out] o_rc, a return code which determines the success of the constructor
+ ///
+ template< fapi2::TargetType T >
+ eff_config( const fapi2::Target<T>& i_target, fapi2::ReturnCode& o_rc )
+ {
+ // Decode the VPD for this MCS and stick it in the attributes.
+ o_rc = decode_vpd(i_target);
+ return;
+ }
//
// @brief Destructor
@@ -768,6 +777,7 @@ class eff_config
///
fapi2::ReturnCode dram_trtp(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+ private:
///
/// @brief Grab the VPD blobs and decode into attributes
/// @param[in] i_target FAPI2 target (MCS)
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_vpd_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_vpd_decoder.H
index db3f2a30a..ede76118a 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_vpd_decoder.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_vpd_decoder.H
@@ -38,6 +38,759 @@ namespace decoder
// VPD Keyword Version Byte: 00
///
+/// @brief ATTR_MSS_VPD_MT_0_VERSION_LAYOUT decode and set
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note MT Keyword Layout Version Number. Increases when attributes are added, removed, or redefined. Does not reset.
+///
+inline fapi2::ReturnCode vpd_mt_0_version_layout(const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value;
+
+ memcpy(&l_value, i_blobs[0] + 0, 1);
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_0_VERSION_LAYOUT, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_0_VERSION_LAYOUT start: 0, len: 1");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_1_VERSION_DATA decode and set
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note MT Keyword Data Version Number. Increases when data changes with the above layout version. Resets when layout version number increments.
+///
+inline fapi2::ReturnCode vpd_mt_1_version_data(const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value;
+
+ memcpy(&l_value, i_blobs[0] + 1, 1);
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_1_VERSION_DATA, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_1_VERSION_DATA start: 1, len: 1");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_2_SIGNATURE_HASH decode and set
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Hash Signature for the MT Keyword. The hash signature is 32bits for 256 bytes of data.
+///
+inline fapi2::ReturnCode vpd_mt_2_signature_hash(const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint32_t l_value;
+
+ memcpy(&l_value, i_blobs[0] + 2, 4);
+ l_value = be32toh(l_value);
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_2_SIGNATURE_HASH, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_2_SIGNATURE_HASH start: 2, len: 4");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_DIMM_RCD_IBT decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Register Clock Driver, Input Bus Termination in tens of Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_dimm_rcd_ibt(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2][2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 4 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 6 + (l_index * l_length);
+ memcpy(&(l_value[l_index][0]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DIMM_RCD_IBT, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_DIMM_RCD_IBT start: 6, len: 4");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note DQ and DQS Drive Impedance for [Port][DIMM][RANK].
+///
+inline fapi2::ReturnCode vpd_mt_dram_drv_imp_dq_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2][2][2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 10 + (l_index * l_length);
+ memcpy(&(l_value[l_index][0][0]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS start: 10, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_DRAM_RTT_NOM decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note DRAM side Nominal Termination Resistance in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_dram_rtt_nom(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2][2][2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 18 + (l_index * l_length);
+ memcpy(&(l_value[l_index][0][0]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_RTT_NOM, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_RTT_NOM start: 18, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_DRAM_RTT_PARK decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note DRAM side Park Termination Resistance in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_dram_rtt_park(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2][2][2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 26 + (l_index * l_length);
+ memcpy(&(l_value[l_index][0][0]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_RTT_PARK, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_RTT_PARK start: 26, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_DRAM_RTT_WR decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note DRAM side Write Termination Resistance in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_dram_rtt_wr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2][2][2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 34 + (l_index * l_length);
+ memcpy(&(l_value[l_index][0][0]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_RTT_WR, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_RTT_WR start: 34, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_RD_UP decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Selects the number of enabled pullup branches during READ mode. ONLY set range 0-7. Eg. 0x02 = b010 (1 branch selected), 0x06 = b110 (2 branches selected)
+/// Bit 0-2 = DP16 Block 0 (DQ Bits 0-7)
+/// Bit 3-5 = DP16 Block 0 (DQ Bits 8-15)
+/// Bit 6-8 = DP16 Block 1 (DQ Bits 0-7)
+/// Bit 9-11 = DP16 Block 1 (DQ Bits 8-15)
+/// Bit 12-14 = DP16 Block 2 (DQ Bits 0-7)
+/// Bit 15-17 = DP16 Block 2 (DQ Bits 8-15)
+/// Bit 18-20 = DP16 Block 3 (DQ Bits 0-7)
+/// Bit 21-23 = DP16 Block 3 (DQ Bits 8-15)
+/// Bit 24-26 = DP16 Block 4 (DQ Bits 0-7)
+/// Bit 27-29 = DP16 Block 4 (DQ Bits 8-15)
+///
+inline fapi2::ReturnCode vpd_mt_mc_dq_acboost_rd_up(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint32_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 42 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ l_value[i] = be32toh(l_value[i]);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_RD_UP, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_RD_UP start: 42, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_DOWN decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Selects the number of enabled pulldown branches during WRITE mode. ONLY set range 0-7. Eg. 0x02 = b010 (1 branch selected), 0x06 = b110 (2 branches selected)
+/// Bit 0-2 = DP16 Block 0 (DQ Bits 0-7)
+/// Bit 3-5 = DP16 Block 0 (DQ Bits 8-15)
+/// Bit 6-8 = DP16 Block 1 (DQ Bits 0-7)
+/// Bit 9-11 = DP16 Block 1 (DQ Bits 8-15)
+/// Bit 12-14 = DP16 Block 2 (DQ Bits 0-7)
+/// Bit 15-17 = DP16 Block 2 (DQ Bits 8-15)
+/// Bit 18-20 = DP16 Block 3 (DQ Bits 0-7)
+/// Bit 21-23 = DP16 Block 3 (DQ Bits 8-15)
+/// Bit 24-26 = DP16 Block 4 (DQ Bits 0-7)
+/// Bit 27-29 = DP16 Block 4 (DQ Bits 8-15)
+///
+inline fapi2::ReturnCode vpd_mt_mc_dq_acboost_wr_down(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint32_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 50 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ l_value[i] = be32toh(l_value[i]);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_DOWN, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_DOWN start: 50, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_UP decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Selects the number of enabled pullup branches during WRITE mode. ONLY set range 0-7. Eg. 0x02 = b010 (1 branch selected), 0x06 = b110 (2 branches selected)
+/// Bit 0-2 = DP16 Block 0 (DQ Bits 0-7)
+/// Bit 3-5 = DP16 Block 0 (DQ Bits 8-15)
+/// Bit 6-8 = DP16 Block 1 (DQ Bits 0-7)
+/// Bit 9-11 = DP16 Block 1 (DQ Bits 8-15)
+/// Bit 12-14 = DP16 Block 2 (DQ Bits 0-7)
+/// Bit 15-17 = DP16 Block 2 (DQ Bits 8-15)
+/// Bit 18-20 = DP16 Block 3 (DQ Bits 0-7)
+/// Bit 21-23 = DP16 Block 3 (DQ Bits 8-15)
+/// Bit 24-26 = DP16 Block 4 (DQ Bits 0-7)
+/// Bit 27-29 = DP16 Block 4 (DQ Bits 8-15)
+///
+inline fapi2::ReturnCode vpd_mt_mc_dq_acboost_wr_up(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint32_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 58 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ l_value[i] = be32toh(l_value[i]);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_UP, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_UP start: 58, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DQ_CTLE_CAP decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Sets the capacitance value in the RC source degeneration. ONLY set range 0-3. (b00 = No capacitor selected, b01 = more caps selected, b10 = even more caps selected, b11 = maximum capacitors selected)
+/// Bit 0-1 = DP16 Block 0 Nibble 0 Bit 16-17 = DP16 Block 2 Nibble 0 Bit 32-33 = DP16 Block 4 Nibble 0
+/// Bit 2-3 = DP16 Block 0 Nibble 1 Bit 18-19 = DP16 Block 2 Nibble 1 Bit 34-35 = DP16 Block 4 Nibble 1
+/// Bit 4-5 = DP16 Block 0 Nibble 2 Bit 20-21 = DP16 Block 2 Nibble 2 Bit 36-37 = DP16 Block 4 Nibble 2
+/// Bit 6-7 = DP16 Block 0 Nibble 3 Bit 22-23 = DP16 Block 2 Nibble 3 Bit 38-39 = DP16 Block 4 Nibble 3
+/// Bit 8-9 = DP16 Block 1 Nibble 0 Bit 24-25 = DP16 Block 3 Nibble 0
+/// Bit 10-11 = DP16 Block 1 Nibble 1 Bit 26-27 = DP16 Block 3 Nibble 1
+/// Bit 12-13 = DP16 Block 1 Nibble 2 Bit 28-29 = DP16 Block 3 Nibble 2
+/// Bit 14-15 = DP16 Block 1 Nibble 3 Bit 30-31 = DP16 Block 3 Nibble 3
+///
+inline fapi2::ReturnCode vpd_mt_mc_dq_ctle_cap(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint64_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 16 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 66 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ l_value[i] = be64toh(l_value[i]);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_CTLE_CAP, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_CTLE_CAP start: 66, len: 16");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DQ_CTLE_RES decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Sets the resistance value in the RC source degeneration. Also defines the CTLE's DC Gain. ONLY set range 0-7. (b000 = max resistance, b001 to b110 = decreasing resistance, b111 = min resistance)
+/// Bit 0-2 = DP16 Block 0 Nibble 0 Bit 24-26 = DP16 Block 2 Nibble 0 Bit 48-50 = DP16 Block 4 Nibble 0
+/// Bit 3-5 = DP16 Block 0 Nibble 1 Bit 27-29 = DP16 Block 2 Nibble 1 Bit 51-53 = DP16 Block 4 Nibble 1
+/// Bit 6-8 = DP16 Block 0 Nibble 2 Bit 30-32 = DP16 Block 2 Nibble 2 Bit 54-56 = DP16 Block 4 Nibble 2
+/// Bit 9-11 = DP16 Block 0 Nibble 3 Bit 33-35 = DP16 Block 2 Nibble 3 Bit 57-59 = DP16 Block 4 Nibble 3
+/// Bit 12-14 = DP16 Block 1 Nibble 0 Bit 36-38 = DP16 Block 3 Nibble 0
+/// Bit 15-17 = DP16 Block 1 Nibble 1 Bit 39-41 = DP16 Block 3 Nibble 1
+/// Bit 18-20 = DP16 Block 1 Nibble 2 Bit 42-44 = DP16 Block 3 Nibble 2
+/// Bit 21-23 = DP16 Block 1 Nibble 3 Bit 45-47 = DP16 Block 3 Nibble 3
+///
+inline fapi2::ReturnCode vpd_mt_mc_dq_ctle_res(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint64_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 16 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 82 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ l_value[i] = be64toh(l_value[i]);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_CTLE_RES, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_CTLE_RES start: 82, len: 16");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_ADDR decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Memory Controller side Drive Impedance for Address Lines in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_mc_drv_imp_addr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 2 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 98 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_ADDR, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_ADDR start: 98, len: 2");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_CLK decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Memory Controller side Drive Impedance for Clock in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_mc_drv_imp_clk(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 2 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 100 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_CLK, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_CLK start: 100, len: 2");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_CNTL decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Memory Controller side Drive Impedance for Control Lines in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_mc_drv_imp_cntl(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 2 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 102 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_CNTL, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_CNTL start: 102, len: 2");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Memory Controller side Drive Impedance for Data and Data Strobe Lines in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_mc_drv_imp_dq_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 2 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 104 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS start: 104, len: 2");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_SPCKE decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Memory Controller side Drive Impedance for Clock Enable Spare Line in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_mc_drv_imp_spcke(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 2 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 106 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_SPCKE, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_SPCKE start: 106, len: 2");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Memory Controller side Receiver Impedance for Data and Data Strobe Lines in Ohms.
+///
+inline fapi2::ReturnCode vpd_mt_mc_rcv_imp_dq_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 2 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 108 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS start: 108, len: 2");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_ODT_RD decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note READ, On Die Termination triggering bitmap.
+///
+inline fapi2::ReturnCode vpd_mt_odt_rd(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2][2][2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 110 + (l_index * l_length);
+ memcpy(&(l_value[l_index][0][0]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_ODT_RD, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_ODT_RD start: 110, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_ODT_WR decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note WRITE, On Die Termination triggering bitmap.
+///
+inline fapi2::ReturnCode vpd_mt_odt_wr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2][2][2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 118 + (l_index * l_length);
+ memcpy(&(l_value[l_index][0][0]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_ODT_WR, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_ODT_WR start: 118, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_VREF_DRAM_WR decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note DRAM side Write Vref setting for DDR4. Bit encode is 01234567. Bit 0 is unused. Bit 1 is the Range. Bits 2-7 is the Value. Refer to the VrefDQ Training Table in JEDEC.
+///
+inline fapi2::ReturnCode vpd_mt_vref_dram_wr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint8_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 2 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 126 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_VREF_DRAM_WR, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_VREF_DRAM_WR start: 126, len: 2");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_VREF_MC_RD decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Memory Controller side Read Vref setting. Dividing by 1000 gives you percentage of Vdd
+///
+inline fapi2::ReturnCode vpd_mt_vref_mc_rd(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint32_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 8 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 128 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ l_value[i] = be32toh(l_value[i]);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_VREF_MC_RD, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_VREF_MC_RD start: 128, len: 8");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_VPD_MT_WINDAGE_RD_CTR decode and set (array)
+/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[in] i_blobs a std::vector of pointers to VPD blobs for this MCS's MCAs
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Derived from calibration/characterization of read centering. Number of windage offset in units of pico-seconds[ps] with sign bit0 (0b0=positive, 0b1=negative) and value in bits1..31, so 0x8023 for example would mean "-35ps". If this is enabled, disable periodic rd_ctr in draminit_mc. Default
+///
+inline fapi2::ReturnCode vpd_mt_windage_rd_ctr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_blobs)
+{
+ uint16_t l_value[2];
+ const auto& l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target);
+ const uint64_t l_length = 4 / l_mcas.size();
+
+ for (const auto& l_mca : l_mcas)
+ {
+ const uint64_t l_index = mss::index(l_mca);
+ const uint8_t* l_blob = i_blobs[l_index];
+ const uint64_t l_start = 136 + (l_index * l_length);
+ memcpy(&(l_value[l_index]), l_blob + l_start, l_length);
+ }
+
+ for (size_t i = 0; i < 2; ++i)
+ {
+ l_value[i] = be16toh(l_value[i]);
+ }
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_WINDAGE_RD_CTR, i_target, l_value),
+ "Unable to decode and set ATTR_MSS_VPD_MT_WINDAGE_RD_CTR start: 136, len: 4");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+// VPD Keyword Version Byte: 00
+///
/// @brief ATTR_MSS_VPD_MR_0_VERSION_LAYOUT decode and set
/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>
/// @param[in] i_blob the VPD blob for this MCS
@@ -978,587 +1731,43 @@ fapi_try_exit:
return fapi2::current_err;
}
-
-// VPD Keyword Version Byte: 00
-///
-/// @brief ATTR_MSS_VPD_MT_0_VERSION_LAYOUT decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note MT Keyword Layout Version Number. Increases when attributes are added, removed, or redefined. Does not reset.
-///
-inline fapi2::ReturnCode vpd_mt_0_version_layout(const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value;
-
- memcpy(&l_value, i_blob + 0, 1);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_0_VERSION_LAYOUT, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_0_VERSION_LAYOUT start: 0, len: 1");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_1_VERSION_DATA decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note MT Keyword Data Version Number. Increases when data changes with the above layout version. Resets when layout version number increments.
-///
-inline fapi2::ReturnCode vpd_mt_1_version_data(const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value;
-
- memcpy(&l_value, i_blob + 1, 1);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_1_VERSION_DATA, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_1_VERSION_DATA start: 1, len: 1");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_2_SIGNATURE_HASH decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Hash Signature for the MT Keyword. The hash signature is 32bits for 256 bytes of data.
-///
-inline fapi2::ReturnCode vpd_mt_2_signature_hash(const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>& i_target,
- const uint8_t* i_blob)
-{
- uint32_t l_value;
-
- memcpy(&l_value, i_blob + 2, 4);
- l_value = be32toh(l_value);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_2_SIGNATURE_HASH, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_2_SIGNATURE_HASH start: 2, len: 4");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_DIMM_RCD_IBT decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Register Clock Driver, Input Bus Termination in tens of Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_dimm_rcd_ibt(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2][2];
-
- memcpy(&l_value, i_blob + 6, 4);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DIMM_RCD_IBT, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_DIMM_RCD_IBT start: 6, len: 4");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note DQ and DQS Drive Impedance for [Port][DIMM][RANK].
-///
-inline fapi2::ReturnCode vpd_mt_dram_drv_imp_dq_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2][2][2];
-
- memcpy(&l_value, i_blob + 10, 8);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS start: 10, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_DRAM_RTT_NOM decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note DRAM side Nominal Termination Resistance in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_dram_rtt_nom(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2][2][2];
-
- memcpy(&l_value, i_blob + 18, 8);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_RTT_NOM, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_RTT_NOM start: 18, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_DRAM_RTT_PARK decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note DRAM side Park Termination Resistance in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_dram_rtt_park(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2][2][2];
-
- memcpy(&l_value, i_blob + 26, 8);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_RTT_PARK, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_RTT_PARK start: 26, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_DRAM_RTT_WR decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note DRAM side Write Termination Resistance in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_dram_rtt_wr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2][2][2];
-
- memcpy(&l_value, i_blob + 34, 8);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_DRAM_RTT_WR, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_DRAM_RTT_WR start: 34, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_RD_UP decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Selects the number of enabled pullup branches during READ mode. ONLY set range 0-7. Eg. 0x02 = b010 (1 branch selected), 0x06 = b110 (2 branches selected)
-/// Bit 0-2 = DP16 Block 0 (DQ Bits 0-7)
-/// Bit 3-5 = DP16 Block 0 (DQ Bits 8-15)
-/// Bit 6-8 = DP16 Block 1 (DQ Bits 0-7)
-/// Bit 9-11 = DP16 Block 1 (DQ Bits 8-15)
-/// Bit 12-14 = DP16 Block 2 (DQ Bits 0-7)
-/// Bit 15-17 = DP16 Block 2 (DQ Bits 8-15)
-/// Bit 18-20 = DP16 Block 3 (DQ Bits 0-7)
-/// Bit 21-23 = DP16 Block 3 (DQ Bits 8-15)
-/// Bit 24-26 = DP16 Block 4 (DQ Bits 0-7)
-/// Bit 27-29 = DP16 Block 4 (DQ Bits 8-15)
-///
-inline fapi2::ReturnCode vpd_mt_mc_dq_acboost_rd_up(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint32_t l_value[2];
-
- memcpy(&l_value, i_blob + 42, 8);
-
- for (size_t i = 0; i < 2; ++i)
- {
- l_value[i] = be32toh(l_value[i]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_RD_UP, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_RD_UP start: 42, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_DOWN decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Selects the number of enabled pulldown branches during WRITE mode. ONLY set range 0-7. Eg. 0x02 = b010 (1 branch selected), 0x06 = b110 (2 branches selected)
-/// Bit 0-2 = DP16 Block 0 (DQ Bits 0-7)
-/// Bit 3-5 = DP16 Block 0 (DQ Bits 8-15)
-/// Bit 6-8 = DP16 Block 1 (DQ Bits 0-7)
-/// Bit 9-11 = DP16 Block 1 (DQ Bits 8-15)
-/// Bit 12-14 = DP16 Block 2 (DQ Bits 0-7)
-/// Bit 15-17 = DP16 Block 2 (DQ Bits 8-15)
-/// Bit 18-20 = DP16 Block 3 (DQ Bits 0-7)
-/// Bit 21-23 = DP16 Block 3 (DQ Bits 8-15)
-/// Bit 24-26 = DP16 Block 4 (DQ Bits 0-7)
-/// Bit 27-29 = DP16 Block 4 (DQ Bits 8-15)
-///
-inline fapi2::ReturnCode vpd_mt_mc_dq_acboost_wr_down(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint32_t l_value[2];
-
- memcpy(&l_value, i_blob + 50, 8);
-
- for (size_t i = 0; i < 2; ++i)
- {
- l_value[i] = be32toh(l_value[i]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_DOWN, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_DOWN start: 50, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_UP decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Selects the number of enabled pullup branches during WRITE mode. ONLY set range 0-7. Eg. 0x02 = b010 (1 branch selected), 0x06 = b110 (2 branches selected)
-/// Bit 0-2 = DP16 Block 0 (DQ Bits 0-7)
-/// Bit 3-5 = DP16 Block 0 (DQ Bits 8-15)
-/// Bit 6-8 = DP16 Block 1 (DQ Bits 0-7)
-/// Bit 9-11 = DP16 Block 1 (DQ Bits 8-15)
-/// Bit 12-14 = DP16 Block 2 (DQ Bits 0-7)
-/// Bit 15-17 = DP16 Block 2 (DQ Bits 8-15)
-/// Bit 18-20 = DP16 Block 3 (DQ Bits 0-7)
-/// Bit 21-23 = DP16 Block 3 (DQ Bits 8-15)
-/// Bit 24-26 = DP16 Block 4 (DQ Bits 0-7)
-/// Bit 27-29 = DP16 Block 4 (DQ Bits 8-15)
-///
-inline fapi2::ReturnCode vpd_mt_mc_dq_acboost_wr_up(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint32_t l_value[2];
-
- memcpy(&l_value, i_blob + 58, 8);
-
- for (size_t i = 0; i < 2; ++i)
- {
- l_value[i] = be32toh(l_value[i]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_UP, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_ACBOOST_WR_UP start: 58, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DQ_CTLE_CAP decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Sets the capacitance value in the RC source degeneration. ONLY set range 0-3. (b00 = No capacitor selected, b01 = more caps selected, b10 = even more caps selected, b11 = maximum capacitors selected)
-/// Bit 0-1 = DP16 Block 0 Nibble 0 Bit 16-17 = DP16 Block 2 Nibble 0 Bit 32-33 = DP16 Block 4 Nibble 0
-/// Bit 2-3 = DP16 Block 0 Nibble 1 Bit 18-19 = DP16 Block 2 Nibble 1 Bit 34-35 = DP16 Block 4 Nibble 1
-/// Bit 4-5 = DP16 Block 0 Nibble 2 Bit 20-21 = DP16 Block 2 Nibble 2 Bit 36-37 = DP16 Block 4 Nibble 2
-/// Bit 6-7 = DP16 Block 0 Nibble 3 Bit 22-23 = DP16 Block 2 Nibble 3 Bit 38-39 = DP16 Block 4 Nibble 3
-/// Bit 8-9 = DP16 Block 1 Nibble 0 Bit 24-25 = DP16 Block 3 Nibble 0
-/// Bit 10-11 = DP16 Block 1 Nibble 1 Bit 26-27 = DP16 Block 3 Nibble 1
-/// Bit 12-13 = DP16 Block 1 Nibble 2 Bit 28-29 = DP16 Block 3 Nibble 2
-/// Bit 14-15 = DP16 Block 1 Nibble 3 Bit 30-31 = DP16 Block 3 Nibble 3
-///
-inline fapi2::ReturnCode vpd_mt_mc_dq_ctle_cap(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint64_t l_value[2];
-
- memcpy(&l_value, i_blob + 66, 16);
-
- for (size_t i = 0; i < 2; ++i)
- {
- l_value[i] = be64toh(l_value[i]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_CTLE_CAP, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_CTLE_CAP start: 66, len: 16");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DQ_CTLE_RES decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Sets the resistance value in the RC source degeneration. Also defines the CTLE's DC Gain. ONLY set range 0-7. (b000 = max resistance, b001 to b110 = decreasing resistance, b111 = min resistance)
-/// Bit 0-2 = DP16 Block 0 Nibble 0 Bit 24-26 = DP16 Block 2 Nibble 0 Bit 48-50 = DP16 Block 4 Nibble 0
-/// Bit 3-5 = DP16 Block 0 Nibble 1 Bit 27-29 = DP16 Block 2 Nibble 1 Bit 51-53 = DP16 Block 4 Nibble 1
-/// Bit 6-8 = DP16 Block 0 Nibble 2 Bit 30-32 = DP16 Block 2 Nibble 2 Bit 54-56 = DP16 Block 4 Nibble 2
-/// Bit 9-11 = DP16 Block 0 Nibble 3 Bit 33-35 = DP16 Block 2 Nibble 3 Bit 57-59 = DP16 Block 4 Nibble 3
-/// Bit 12-14 = DP16 Block 1 Nibble 0 Bit 36-38 = DP16 Block 3 Nibble 0
-/// Bit 15-17 = DP16 Block 1 Nibble 1 Bit 39-41 = DP16 Block 3 Nibble 1
-/// Bit 18-20 = DP16 Block 1 Nibble 2 Bit 42-44 = DP16 Block 3 Nibble 2
-/// Bit 21-23 = DP16 Block 1 Nibble 3 Bit 45-47 = DP16 Block 3 Nibble 3
-///
-inline fapi2::ReturnCode vpd_mt_mc_dq_ctle_res(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint64_t l_value[2];
-
- memcpy(&l_value, i_blob + 82, 16);
-
- for (size_t i = 0; i < 2; ++i)
- {
- l_value[i] = be64toh(l_value[i]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DQ_CTLE_RES, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DQ_CTLE_RES start: 82, len: 16");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_ADDR decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Memory Controller side Drive Impedance for Address Lines in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_mc_drv_imp_addr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2];
-
- memcpy(&l_value, i_blob + 98, 2);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_ADDR, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_ADDR start: 98, len: 2");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_CLK decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Memory Controller side Drive Impedance for Clock in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_mc_drv_imp_clk(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2];
-
- memcpy(&l_value, i_blob + 100, 2);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_CLK, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_CLK start: 100, len: 2");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_CNTL decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Memory Controller side Drive Impedance for Control Lines in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_mc_drv_imp_cntl(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2];
-
- memcpy(&l_value, i_blob + 102, 2);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_CNTL, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_CNTL start: 102, len: 2");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Memory Controller side Drive Impedance for Data and Data Strobe Lines in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_mc_drv_imp_dq_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2];
-
- memcpy(&l_value, i_blob + 104, 2);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_DQ_DQS start: 104, len: 2");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_DRV_IMP_SPCKE decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Memory Controller side Drive Impedance for Clock Enable Spare Line in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_mc_drv_imp_spcke(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2];
-
- memcpy(&l_value, i_blob + 106, 2);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_DRV_IMP_SPCKE, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_DRV_IMP_SPCKE start: 106, len: 2");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Memory Controller side Receiver Impedance for Data and Data Strobe Lines in Ohms.
-///
-inline fapi2::ReturnCode vpd_mt_mc_rcv_imp_dq_dqs(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2];
-
- memcpy(&l_value, i_blob + 108, 2);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_MC_RCV_IMP_DQ_DQS start: 108, len: 2");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_ODT_RD decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note READ, On Die Termination triggering bitmap.
-///
-inline fapi2::ReturnCode vpd_mt_odt_rd(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, const uint8_t* i_blob)
-{
- uint8_t l_value[2][2][2];
-
- memcpy(&l_value, i_blob + 110, 8);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_ODT_RD, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_ODT_RD start: 110, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_ODT_WR decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note WRITE, On Die Termination triggering bitmap.
-///
-inline fapi2::ReturnCode vpd_mt_odt_wr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, const uint8_t* i_blob)
-{
- uint8_t l_value[2][2][2];
-
- memcpy(&l_value, i_blob + 118, 8);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_ODT_WR, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_ODT_WR start: 118, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_VREF_DRAM_WR decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note DRAM side Write Vref setting for DDR4. Bit encode is 01234567. Bit 0 is unused. Bit 1 is the Range. Bits 2-7 is the Value. Refer to the VrefDQ Training Table in JEDEC.
-///
-inline fapi2::ReturnCode vpd_mt_vref_dram_wr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint8_t l_value[2];
-
- memcpy(&l_value, i_blob + 126, 2);
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_VREF_DRAM_WR, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_VREF_DRAM_WR start: 126, len: 2");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_VREF_MC_RD decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Memory Controller side Read Vref setting. Dividing by 1000 gives you percentage of Vdd
-///
-inline fapi2::ReturnCode vpd_mt_vref_mc_rd(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, const uint8_t* i_blob)
-{
- uint32_t l_value[2];
-
- memcpy(&l_value, i_blob + 128, 8);
-
- for (size_t i = 0; i < 2; ++i)
- {
- l_value[i] = be32toh(l_value[i]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_VREF_MC_RD, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_VREF_MC_RD start: 128, len: 8");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief ATTR_MSS_VPD_MT_WINDAGE_RD_CTR decode and set
-/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_blob the VPD blob for this MCS
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
-/// @note Derived from calibration/characterization of read centering. Number of windage offset in units of pico-seconds[ps] with sign bit0 (0b0=positive, 0b1=negative) and value in bits1..31, so 0x8023 for example would mean "-35ps". If this is enabled, disable periodic rd_ctr in draminit_mc. Default
-///
-inline fapi2::ReturnCode vpd_mt_windage_rd_ctr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const uint8_t* i_blob)
-{
- uint16_t l_value[2];
-
- memcpy(&l_value, i_blob + 136, 4);
-
- for (size_t i = 0; i < 2; ++i)
- {
- l_value[i] = be16toh(l_value[i]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VPD_MT_WINDAGE_RD_CTR, i_target, l_value),
- "Unable to decode and set ATTR_MSS_VPD_MT_WINDAGE_RD_CTR start: 136, len: 4");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
}; // close decoder ns
///
/// @brief eff_decode
/// @param[in] i_target fapi2::Target<fapi2::TARGET_TYPE_MCS>
-/// @param[in] i_mt_blob the MT VPD blob for this MCS
+/// @param[in] i_mt_blobs std::vector of pointers to the the MT VPD blobs for this MCS's MCA
/// @param[in] i_mr_blob the MR VPD blob for this MCS
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
/// @note Decodes the blobs and sets all the attributes.
///
-inline fapi2::ReturnCode eff_decode(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, const uint8_t* i_mt_blob,
- const uint8_t* i_mr_blob)
+inline fapi2::ReturnCode eff_decode(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const std::vector<uint8_t*>& i_mt_blob, const uint8_t* i_mr_blob)
{
+ FAPI_TRY (decoder::vpd_mt_0_version_layout(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_1_version_data(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_2_signature_hash(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_dimm_rcd_ibt(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_dram_drv_imp_dq_dqs(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_dram_rtt_nom(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_dram_rtt_park(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_dram_rtt_wr(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_dq_acboost_rd_up(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_dq_acboost_wr_down(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_dq_acboost_wr_up(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_dq_ctle_cap(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_dq_ctle_res(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_drv_imp_addr(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_drv_imp_clk(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_drv_imp_cntl(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_drv_imp_dq_dqs(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_drv_imp_spcke(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_mc_rcv_imp_dq_dqs(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_odt_rd(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_odt_wr(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_vref_dram_wr(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_vref_mc_rd(i_target, i_mt_blob) );
+ FAPI_TRY (decoder::vpd_mt_windage_rd_ctr(i_target, i_mt_blob) );
FAPI_TRY (decoder::vpd_mr_0_version_layout(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mr_blob) );
FAPI_TRY (decoder::vpd_mr_1_version_data(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mr_blob) );
FAPI_TRY (decoder::vpd_mr_2_signature_hash(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mr_blob) );
@@ -1606,30 +1815,6 @@ inline fapi2::ReturnCode eff_decode(const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
FAPI_TRY (decoder::vpd_mr_mc_phase_rot_cntl_d1_odt0(i_target, i_mr_blob) );
FAPI_TRY (decoder::vpd_mr_mc_phase_rot_cntl_d1_odt1(i_target, i_mr_blob) );
FAPI_TRY (decoder::vpd_mr_mc_2n_mode_autoset(i_target, i_mr_blob) );
- FAPI_TRY (decoder::vpd_mt_0_version_layout(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_1_version_data(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_2_signature_hash(fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_dimm_rcd_ibt(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_dram_drv_imp_dq_dqs(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_dram_rtt_nom(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_dram_rtt_park(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_dram_rtt_wr(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_dq_acboost_rd_up(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_dq_acboost_wr_down(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_dq_acboost_wr_up(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_dq_ctle_cap(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_dq_ctle_res(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_drv_imp_addr(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_drv_imp_clk(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_drv_imp_cntl(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_drv_imp_dq_dqs(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_drv_imp_spcke(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_mc_rcv_imp_dq_dqs(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_odt_rd(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_odt_wr(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_vref_dram_wr(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_vref_mc_rd(i_target, i_mt_blob) );
- FAPI_TRY (decoder::vpd_mt_windage_rd_ctr(i_target, i_mt_blob) );
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
index 181995b20..25b2869af 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
@@ -50,15 +50,15 @@
///
fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target )
{
- mss::eff_config l_eff_config;
+ fapi2::ReturnCode l_rc;
+ std::map<uint32_t, std::shared_ptr<mss::spd::decoder> > l_factory_caches;
+
+ mss::eff_config l_eff_config(i_target, l_rc);
+ FAPI_TRY(l_rc, "Unable to decode VPD for %s", mss::c_str(i_target) );
// Caches
- std::map<uint32_t, std::shared_ptr<mss::spd::decoder> > l_factory_caches;
FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches) );
- // Decode the VPD for this MCS and stick it in the attributes.
- FAPI_TRY( l_eff_config.decode_vpd(i_target) );
-
for( const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) )
{
const auto l_dimm_pos = mss::pos(l_dimm);
diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml
index 4bb33c98c..e43dedb89 100644
--- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml
+++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml
@@ -36,7 +36,7 @@
<hwpErrors>
- <hwpError>
+ <hwpError>
<rc>RC_MSS_INVALID_TEMP_REF_RANGE</rc>
<description>
Invalid Temperature refresh range recieved
@@ -50,9 +50,9 @@
<deconfigure>
<target>DIMM_TARGET</target>
</deconfigure>
- </hwpError>
+ </hwpError>
- <hwpError>
+ <hwpError>
<rc>RC_MSS_INVALID_FINE_REFRESH_MODE</rc>
<description>
Invalid fine refresh mode recieved
@@ -66,9 +66,9 @@
<deconfigure>
<target>DIMM_TARGET</target>
</deconfigure>
- </hwpError>
+ </hwpError>
- <hwpError>
+ <hwpError>
<rc>RC_MSS_INVALID_KEY</rc>
<description>
Conditional that tests whether a certain key value is located in a map.
@@ -82,9 +82,9 @@
<deconfigure>
<target>DIMM_TARGET</target>
</deconfigure>
- </hwpError>
+ </hwpError>
- <hwpError>
+ <hwpError>
<rc>RC_MSS_INVALID_VPD_VREF_DRAM_WR_RANGE</rc>
<description>
Value in the VPD for VREF dram WR range is outside of the JEDEC spec's range.
@@ -98,6 +98,6 @@
<deconfigure>
<target>DIMM_TARGET</target>
</deconfigure>
- </hwpError>
+ </hwpError>
</hwpErrors>
OpenPOWER on IntegriCloud