diff options
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H')
-rw-r--r-- | src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H | 236 |
1 files changed, 235 insertions, 1 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H index fd5cdb7e6..ac5a73f48 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -44,6 +44,7 @@ #include <p9_mc_scom_addresses_fld.H> #include <mss_attribute_accessors.H> #include <lib/phy/dp16.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> namespace mss { @@ -497,6 +498,42 @@ fapi2::ReturnCode get_delay_data(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_ /// /// @brief Finds the median and sorts the vector +/// @tparam T the type of data to sort +/// @param[in] i_data the data to find a median for +/// @param[out] o_median the median value +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +template < typename T > +fapi2::ReturnCode find_median(const std::vector<T>& i_data, T& o_median) +{ + + // The fapi_try is in an if statement, this ensures we have a good value + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Bomb out if the vector is empty to avoid accessing a non-existant element + FAPI_ASSERT(!i_data.empty(), + fapi2::MSS_RD_CTR_WORKAROUND_EMPTY_VECTOR(), + "Empty vector passed in to find_median_and_sort" + ); + { + // Copies the data to make finding the median easier + auto l_data = i_data; + + // Sorts first + std::sort(l_data.begin(), l_data.end()); + + // The only way to find the median, is to sort and find the mid point + const auto l_median_it = l_data.begin() + (l_data.size() / 2); + o_median = *l_median_it; + } + + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Finds the median and sorts the vector /// @param[in,out] io_reg_data register data /// @param[out] o_median the median value /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok @@ -603,6 +640,203 @@ fapi2::ReturnCode setup_values( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_t uint8_t& o_train_range, uint8_t& o_train_value); +/// +/// @brief Gets the disable register and bit position for the DRAM +/// @param[in] i_target the fapi2 target type MCA of the port +/// @param[in] i_rp - rank pair to check and modify +/// @param[in] i_dram - the DRAM to be checked +/// @param[out] o_reg - the register to access from +/// @param[out] o_bit_pos - the bit position in the register to access from +/// @param[out] o_bit_len - the bit length to access +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode get_disable_reg_and_pos_for_dram( 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& o_bit_pos, + uint64_t& o_bit_len); + +/// +/// @brief Gets the disables for a specific DRAM +/// @param[in] i_target the fapi2 target type MCA of the port +/// @param[in] i_rp - rank pair to check and modify +/// @param[in] i_dram - the DRAM to be checked +/// @param[out] o_disables - true if the whole DRAM is disabled +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode get_disables_for_dram( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + uint64_t& o_disables); + +/// +/// @brief Identifies if an inputted DRAM is wholely disabled +/// @param[in] i_target the fapi2 target type MCA of the port +/// @param[in] i_rp - rank pair to check and modify +/// @param[in] i_dram - the DRAM to be checked +/// @param[out] o_disabled - true if the whole DRAM is disabled +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode is_dram_disabled( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + bool& o_disabled); + +/// +/// @brief Identifies if an inputted DRAM has any disables +/// @param[in] i_target the fapi2 target type MCA of the port +/// @param[in] i_rp - rank pair to check and modify +/// @param[in] i_dram - the DRAM to be checked +/// @param[out] o_has_disables - true if the whole DRAM has any disables +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode dram_has_disables( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + bool& o_has_disables); + +/// +/// @brief Disables bits based upon RD VREF values that differ from the median significantly +/// @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 +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// @note The differing values can cause WR VREF fail, so the bit(s) that differ are disabled temporarily +/// +fapi2::ReturnCode disable_bits( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram ); + +/// +/// @brief Clears all disable bits for a recovered DRAM +/// @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 +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode clear_dram_disable_bits( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram ); + +/// +/// @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 Configures the WR VREF value of a DRAM to be the nominal values +/// @param[in] i_target the fapi2 target type DIMM +/// @param[in] i_rp - rank pair to check and modify +/// @param[in] i_dram - the DRAM +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode configure_wr_vref_to_nominal( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const uint64_t i_rp, + const uint64_t i_dram); + +/// +/// @brief Configures the skip bits to be 0x7 for an entire port for the workaround +/// @param[in] i_target the fapi2 target type DIMM +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode configure_skip_bits( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target); + +/// +/// @brief Modifies the WR VREF value in an MRS06 to have the VPD, not eff_config attribute values +/// @param[in] i_target - the DIMM target on which to operate +/// @param[in,out] io_mrs06 - the MRS data class to modify +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// @note The differing values can cause WR VREF fail, so the bit(s) that differ are disabled temporarily +/// +fapi2::ReturnCode modify_mrs_vref_to_vpd( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + mss::ddr4::mrs06_data& io_mrs06 ); + +/// +/// @brief Resets the WR DQ delays for a given DRAM to be a quarter clock before the DQS +/// @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_delay - the write DQ delay value +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// @note The differing values can cause WR VREF fail, so the bit(s) that differ are disabled temporarily +/// +fapi2::ReturnCode reset_wr_dq_delay( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + const uint64_t i_delay ); + +/// +/// @brief Reads out the RD VREF values for a given DRAM +/// @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[out] o_rd_vref_values - the RD VREF values for a given DRAM +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// @note The differing values can cause WR VREF fail, so the bit(s) that differ are disabled temporarily +/// +fapi2::ReturnCode read_rd_vref_for_dram( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + std::vector<uint64_t>& o_rd_vref_values ); + +/// +/// @brief Identifies the first good RD VREF bit +/// @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_rd_vref_values - the RD VREF values for a given DRAM +/// @param[out] o_bit - the bit for the first good RD VREF +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// @note The differing values can cause WR VREF fail, so the bit(s) that differ are disabled temporarily +/// +fapi2::ReturnCode identify_first_good_rd_vref( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + const std::vector<uint64_t>& i_rd_vref_values, + uint64_t& o_bit ); + +/// +/// @brief Reads out the WR DQ delay value for a given DRAM +/// @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[out] o_wr_dq_delay - the WR DQ delay value for a given DRAM +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// @note At this point, WR CTR hasn't been run, so all WR DQ delays should be the same on the DRAM +/// +fapi2::ReturnCode get_starting_wr_dq_delay( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + uint64_t& o_wr_dq_delay ); + +/// +/// @brief Logs an informational callout detailing if we were able to recover +/// @param[in] i_target - the MCA target under calibration +/// @param[in] i_rp - the rank pair under calibration +/// @param[in] i_dram - the DRAM in question +/// @param[in] i_bad - true iff the DRAM failed to recover +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode log_dram_results( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint64_t i_dram, + const bool i_bad ); + +/// +/// @brief Clears the PHY training FIRs for a given port +/// @param[in] i_target - the MCA target under calibration +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode clear_training_firs( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ); + } // close namespace wr_vref } // close namespace dp16 } // close namespace workarounds |