summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/phy
diff options
context:
space:
mode:
authorTsung Yeung <tyeung@us.ibm.com>2018-01-24 15:28:06 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2018-02-18 13:13:31 -0500
commitd1e10cd97287451d40838a40a1097177ab429514 (patch)
tree64de054b7303794f9346a614b353ce29aeaf9054 /src/import/chips/p9/procedures/hwp/memory/lib/phy
parentfb663d7186c1b2e9120c6ad3449f27555b716784 (diff)
downloadtalos-hostboot-d1e10cd97287451d40838a40a1097177ab429514.tar.gz
talos-hostboot-d1e10cd97287451d40838a40a1097177ab429514.zip
Adds read wr_vref function to support P9 NVDIMM post restore
Change-Id: I235e2ff3931dfbbf74cda05df45f2a02d45351c9 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/52560 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@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/52592 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/phy')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C112
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H103
2 files changed, 215 insertions, 0 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C
index b7fceab3b..87fea9fa6 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C
@@ -4629,6 +4629,118 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Checks that the rank pair and DRAM are in bounds
+/// @param[in] i_target - the MCA target on which to operate
+/// @param[in] i_rp - the rank pair on which to operate
+/// @param[in] i_dram - the DRAM that needs to have the workaround applied to it
+/// @param[in] i_function - the calling function to callout in FFDC
+///
+fapi2::ReturnCode check_rp_and_dram( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ const uint64_t i_dram,
+ const ffdc_function_codes i_function )
+{
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // Checks inputs
+ uint8_t l_width[MAX_DIMM_PER_PORT] = {};
+ FAPI_TRY( mss::eff_dram_width(i_target, l_width) );
+
+ // Checks for DRAM in bounds
+ {
+ const uint64_t MAX_NUM_DRAM = l_width[0] == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8 ? MAX_DRAMS_X8 : MAX_DRAMS_X4;
+ FAPI_ASSERT(i_dram < MAX_NUM_DRAM,
+ fapi2::MSS_INVALID_INDEX_PASSED()
+ .set_INDEX(i_dram)
+ .set_FUNCTION(i_function),
+ "%s Invalid DRAM index passed to check_for_dram_disabled (%d)",
+ mss::c_str(i_target),
+ i_dram);
+ }
+
+ // Checks for i_rp in bounds
+ FAPI_ASSERT(i_rp < MAX_RANK_PAIRS,
+ fapi2::MSS_INVALID_RANK().
+ set_MCA_TARGET(i_target).
+ set_RANK(i_rp).
+ set_FUNCTION(i_function),
+ "%s rank pair is out of bounds %lu", mss::c_str(i_target), i_rp);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Determine the dp and reg number to the give DRAM
+/// @param[in] i_target - the fapi2 target type MCA
+/// @param[in] i_dram - the DRAM
+/// @param[out] o_dp - the dp number for the given DRAM
+/// @param[out] o_reg_num - the register number for the given DRAM
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode dram_to_dp_reg(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_dram,
+ uint64_t& o_dp,
+ uint64_t& o_reg_num)
+{
+ uint8_t l_widths[mss::PORTS_PER_MCS] = {0};
+ typedef dp16Traits<fapi2::TARGET_TYPE_MCA> TT;
+
+ FAPI_TRY( mss::eff_dram_width(i_target, l_widths) );
+
+ // Calculate the address
+ // The assumption here is that the i_dram is within bound. Therefore, the calculated dp and reg_num should also be within bound.
+ {
+ const auto l_dram_per_dp = (l_widths[0] == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? BYTES_PER_DP : NIBBLES_PER_DP;
+ o_dp = i_dram / l_dram_per_dp;
+ o_reg_num = (i_dram % l_dram_per_dp) / TT::NUM_DRAM_PER_REG;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Gets the write vref register
+/// @param[in] i_target - the fapi2 target type MCA
+/// @param[in] i_rp - rank pair, to make sure the dram and rp are within bounds
+/// @param[in] i_dram - the DRAM
+/// @param[out] o_reg - the dp16 wr_vref register for the rank pair and dram
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode get_wr_vref_rp_reg(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ const uint64_t i_dram,
+ uint64_t& o_reg)
+{
+
+ uint64_t l_dp = 0;
+ uint64_t l_reg_num = 0;
+
+ // TODO: RTC187141 Clean up WR_VREF register traits
+ typedef dp16Traits<fapi2::TARGET_TYPE_MCA> TT;
+ const std::vector<std::vector< std::pair<uint64_t, uint64_t> >> REGS =
+ {
+ TT::WR_VREF_VALUE_RP0_REG,
+ TT::WR_VREF_VALUE_RP1_REG,
+ TT::WR_VREF_VALUE_RP2_REG,
+ TT::WR_VREF_VALUE_RP3_REG,
+ };
+
+ // Make sure the rank pair and dram are within bounds
+ FAPI_TRY( check_rp_and_dram(i_target, i_rp, i_dram,
+ ffdc_function_codes::DRAM_TO_RP_REG));
+
+ // If the dram is within bound, compute the vector address
+ FAPI_TRY(dram_to_dp_reg(i_target, i_dram, l_dp, l_reg_num));
+
+ o_reg = (l_reg_num == 0) ? REGS[i_rp][l_dp].first : REGS[i_rp][l_dp].second;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
} // close namespace wr_vref
} // close namespace dp16
} // close namespace mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H
index 40924bc20..10651793d 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H
@@ -154,6 +154,9 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA>
static constexpr uint64_t RD_VREF_DVDD = 12;
static constexpr uint64_t RD_VREF_DAC_STEP = 6500;
+ // Number of DRAM per register
+ static constexpr uint64_t NUM_DRAM_PER_REG = 2;
+
// Vectors of DP16 registers. The pair represents the two DLL in per DP16
static const std::vector< uint64_t > DLL_CNFG_REG;
static const std::vector< uint64_t > RD_VREF_CAL_ENABLE_REG;
@@ -2404,6 +2407,106 @@ uint64_t compute_composite_value(const uint64_t i_range, const uint64_t i_value)
fapi2::ReturnCode offset_values( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
uint8_t& io_train_range,
uint8_t& io_train_value );
+
+///
+/// @brief Checks that the rank pair and DRAM are in bounds
+/// @param[in] i_target - the MCA target on which to operate
+/// @param[in] i_rp - the rank pair on which to operate
+/// @param[in] i_dram - the DRAM that needs to have the workaround applied to it
+/// @param[in] i_function - the calling function to callout in FFDC
+///
+fapi2::ReturnCode check_rp_and_dram( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ const uint64_t i_dram,
+ const ffdc_function_codes i_function );
+
+///
+/// @brief Determine the dp and reg number to the give DRAM
+/// @param[in] i_target - the fapi2 target type MCA
+/// @param[in] i_dram - the DRAM
+/// @param[out] o_dp - the dp number for the given DRAM
+/// @param[out] o_reg_num - the register number for the given DRAM
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode dram_to_dp_reg(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_dram,
+ uint64_t& o_dp,
+ uint64_t& o_reg_num);
+
+///
+/// @brief Gets the write vref register
+/// @param[in] i_target - the fapi2 target type MCA
+/// @param[in] i_rp - rank pair, to make sure the dram and rp are within bounds
+/// @param[in] i_dram - the DRAM
+/// @param[out] o_reg - the dp16 wr_vref register for the rank pair and dram
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+fapi2::ReturnCode get_wr_vref_rp_reg(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ const uint64_t i_dram,
+ uint64_t& o_reg);
+
+///
+/// @brief Get the nominal WR VREF value and range of a dram
+/// @param[in] i_target - the fapi2 target type MCA
+/// @param[in] i_rp - rank pair to check and modify
+/// @param[in] i_dram - the DRAM
+/// @param[out] o_data - scom data containing wr vref value and range
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+inline fapi2::ReturnCode read_wr_vref_register( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const uint64_t i_rp,
+ const uint64_t i_dram,
+ fapi2::buffer<uint64_t>& o_data )
+{
+ // TK: Create similar function for write
+ uint64_t l_reg = 0;
+ FAPI_TRY( get_wr_vref_rp_reg(i_target, i_rp, i_dram, l_reg));
+
+ // Get the vref value and range from scom
+ FAPI_TRY(mss::getScom(i_target, l_reg, o_data));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Extract the write vref range from scom data
+/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCA
+/// @tparam TT traits type defaults to dp16Traits<T>
+/// @param[in] i_data - scom data containing the wr_vref data
+/// @param[in] i_dram - the DRAM
+/// @param[out] o_range - wr_vref range extracted from scom data
+///
+template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> >
+inline void get_wr_vref_range( const fapi2::buffer<uint64_t> i_data,
+ const uint64_t i_dram,
+ bool& o_range )
+{
+ const auto l_dram_pos = i_dram % TT::NUM_DRAM_PER_REG;
+ const auto l_range_pos = (l_dram_pos == 0) ? TT::WR_VREF_VALUE_RANGE_DRAM_EVEN : TT::WR_VREF_VALUE_RANGE_DRAM_ODD;
+
+ o_range = i_data.getBit(l_range_pos);
+}
+
+///
+/// @brief Extract the write vref value from scom data
+/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCA
+/// @tparam TT traits type defaults to dp16Traits<T>
+/// @param[in] i_data - scom data containing the wr_vref data
+/// @param[in] i_dram - the DRAM
+/// @param[out] o_value - wr_vref value extracted from scom data
+///
+template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> >
+inline void get_wr_vref_value( const fapi2::buffer<uint64_t> i_data,
+ const uint64_t i_dram,
+ uint64_t& o_value )
+{
+ const auto l_dram_pos = i_dram % TT::NUM_DRAM_PER_REG;
+ const auto l_value_pos = (l_dram_pos == 0) ? TT::WR_VREF_VALUE_VALUE_DRAM_EVEN : TT::WR_VREF_VALUE_VALUE_DRAM_ODD;
+ i_data.extractToRight(o_value, l_value_pos, TT::WR_VREF_VALUE_VALUE_DRAM_EVEN_LEN);
+}
+
} // close namespace wr_vref
} // close namespace dp16
} // close namespace mss
OpenPOWER on IntegriCloud