From d1e10cd97287451d40838a40a1097177ab429514 Mon Sep 17 00:00:00 2001 From: Tsung Yeung Date: Wed, 24 Jan 2018 15:28:06 -0500 Subject: 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 Tested-by: Jenkins Server Tested-by: HWSV CI Tested-by: Hostboot CI Reviewed-by: STEPHEN GLANCY Reviewed-by: Louis Stermole Reviewed-by: ANDRE A. MARIN Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/52592 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Daniel M. Crowell --- .../chips/p9/procedures/hwp/memory/lib/phy/dp16.C | 112 +++++++++++++++++++++ .../chips/p9/procedures/hwp/memory/lib/phy/dp16.H | 103 +++++++++++++++++++ 2 files changed, 215 insertions(+) (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/phy') 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& 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& 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 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& 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 TT; + const std::vector >> 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 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& 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& 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& 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& 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& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + fapi2::buffer& 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 +/// @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 > +inline void get_wr_vref_range( const fapi2::buffer 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 +/// @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 > +inline void get_wr_vref_value( const fapi2::buffer 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 -- cgit v1.2.1