diff options
5 files changed, 310 insertions, 9 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H index fe7e62806..49da3db73 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -300,6 +300,17 @@ class instruction_t TT::ARR0_DDR_CSN_2_3_LEN>(CS_N[l_effective_rank].first); } } + + /// + /// @brief Equals comparison operator + /// @param[in] i_rhs - the instruction to compare to + /// @return True if both instructions are equal + /// + inline bool operator==( const instruction_t<T>& i_rhs ) const + { + return arr0 == i_rhs.arr0 && + arr1 == i_rhs.arr1; + } }; /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C index 06131bd61..6f0ba4e72 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C @@ -48,6 +48,7 @@ #include <lib/dimm/ddr4/latch_wr_vref.H> #include <lib/workarounds/seq_workarounds.H> #include <lib/workarounds/dqs_align_workarounds.H> +#include <lib/workarounds/ccs_workarounds.H> #include <generic/memory/lib/utils/scom.H> #include <lib/utils/count_dimm.H> @@ -201,6 +202,13 @@ fapi2::ReturnCode wr_lvl::pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE l_program.iv_instructions.clear(); } + FAPI_INF("%s RP%lu %s WR_LVL workaround setup", mss::c_str(i_target), i_rp, iv_sim ? "skipping" : "running"); + + if(!iv_sim) + { + FAPI_TRY( mss::ccs::workarounds::wr_lvl::configure_non_calibrating_ranks(i_target, i_rp, mss::states::OFF_N) ); + } + fapi_try_exit: return fapi2::current_err; } @@ -256,6 +264,13 @@ fapi2::ReturnCode wr_lvl::post_workaround( const fapi2::Target<fapi2::TARGET_TYP FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); } + FAPI_INF("%s RP%lu %s WR_LVL workaround cleanup", mss::c_str(i_target), i_rp, iv_sim ? "skipping" : "running"); + + if(!iv_sim) + { + FAPI_TRY( mss::ccs::workarounds::wr_lvl::configure_non_calibrating_ranks(i_target, i_rp, mss::states::ON_N) ); + } + fapi_try_exit: return fapi2::current_err; } @@ -893,7 +908,7 @@ std::vector<std::shared_ptr<step>> steps_factory(const fapi2::buffer<uint32_t>& if(i_cal_steps.getBit<mss::cal_steps::WR_LEVEL>()) { FAPI_INF("Write leveling is enabled"); - l_steps.push_back(std::make_shared<wr_lvl>()); + l_steps.push_back(std::make_shared<wr_lvl>(i_sim)); } // INITIAL_PAT_WR diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.H index 69372ef85..3ae5e3365 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.H @@ -301,11 +301,16 @@ class wr_lvl : public phy_step public: /// /// @brief Base constructor + /// @param[in] i_sim - true if in simulation mode /// - wr_lvl() : - phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_WR_LEVEL>(), "WR_LVL") + wr_lvl(const bool i_sim) : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_WR_LEVEL>(), "WR_LVL"), + iv_sim(i_sim) {} + // Delete the default constructor + wr_lvl() = delete; + /// /// @brief Default destructor /// @@ -339,6 +344,9 @@ class wr_lvl : public phy_step /// @return l_cycles - the number of cycles a given calibration step wil take /// uint64_t calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const; + + private: + bool iv_sim; }; /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C index bc4b791b7..e7ceb2b0b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017 */ +/* Contributors Listed Below - COPYRIGHT 2017,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -37,6 +37,7 @@ #include <lib/dimm/rank.H> #include <p9_mc_scom_addresses.H> #include <generic/memory/lib/utils/scom.H> +#include <lib/eff_config/timing.H> namespace mss { @@ -75,13 +76,13 @@ fapi2::ReturnCode enable_pda_shadow_reg( const fapi2::Target<fapi2::TARGET_TYPE_ fapi2::buffer<uint64_t> l_data; // Read - FAPI_TRY(mss::getScom(i_target, RP_TO_REG[l_rp], l_data)); + FAPI_TRY( mss::getScom(i_target, RP_TO_REG[l_rp], l_data) ); // Modify l_data.setBit<PDA_BIT>(); // Write - FAPI_TRY(mss::putScom(i_target, RP_TO_REG[l_rp], l_data)); + FAPI_TRY( mss::putScom(i_target, RP_TO_REG[l_rp], l_data) ); } fapi_try_exit: @@ -119,7 +120,7 @@ fapi2::ReturnCode exit( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, // Re-enable PDA mode in the PHY { - FAPI_TRY(enable_pda_shadow_reg(l_mca, i_rank)); + FAPI_TRY( enable_pda_shadow_reg(l_mca, i_rank) ); } // Sets up the B-side MRS - the outside code will issue it @@ -135,6 +136,195 @@ fapi_try_exit: return fapi2::current_err; } +namespace wr_lvl +{ + +/// +/// @brief Updates an MRS to have the desired Qoff value +/// @param[in,out] io_mrs - the MRS to update +/// @param[in] i_state - the state for the qoff in the MRS +/// +void update_mrs(mss::ddr4::mrs01_data& io_mrs, const mss::states i_state) +{ + io_mrs.iv_qoff = i_state; + io_mrs.iv_wl_enable = i_state; +} + +/// +/// @brief Adds in an MRS on a per-rank basis based upon qoff +/// @param[in] i_target - the target on which to operate +/// @param[in] i_rank - the rank on which to operate +/// @param[in] i_state - the state of qoff +/// @param[in,out] io_inst the instruction to fixup +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode add_mrs(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rank, + const mss::states& i_state, + std::vector<ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>>& io_inst) +{ + // First, get the DIMM target + // Note: the target is setup below based upon the rank + fapi2::Target<fapi2::TARGET_TYPE_DIMM> l_dimm(0); + FAPI_TRY( mss::rank::get_dimm_target_from_rank(i_target, i_rank, l_dimm) ); + + // Updates and adds in the MRS information + { + // Get the MRS data + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + mss::ddr4::mrs01_data l_mrs(l_dimm, l_rc); + FAPI_TRY( l_rc, "%s failed to create MRS for rank %lu", mss::c_str(l_dimm), i_rank); + + // Update the MRS data for qoff + update_mrs(l_mrs, i_state); + + // Add the MRS data to the ccs instructions + FAPI_TRY( mrs_engine(l_dimm, l_mrs, i_rank, mss::tmod(i_target), io_inst) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Gets a vector of ranks that are not going to be calibrated in the given rank pair +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[out] o_ranks - the vector of ranks that are not being calibrated +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode get_non_calibrating_ranks(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + std::vector<uint64_t>& o_ranks) +{ + o_ranks.clear(); + std::vector<uint64_t> l_pairs; + + // Get our rank pairs + FAPI_TRY( mss::rank::get_rank_pairs(i_target, l_pairs) ); + + // Loops through all of the rank pairs + for(const auto l_rp : l_pairs) + { + // If this is our current rank pair, add in all non-primary ranks + if(l_rp == i_rp) + { + FAPI_TRY( add_non_primary_ranks(i_target, l_rp, o_ranks) ); + } + else + { + FAPI_TRY( add_ranks_from_pair(i_target, l_rp, o_ranks) ); + } + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Adds the non-primary ranks from a rank pair to a ranks vector +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[in,out] io_ranks - the vector of ranks that are not being calibrated +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode add_non_primary_ranks(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + std::vector<uint64_t>& io_ranks) +{ + std::vector<uint64_t> l_ranks_in_pair; + FAPI_TRY( mss::rank::get_ranks_in_pair(i_target, i_rp, l_ranks_in_pair) ); + + // Loops through the ranks and adds them as need be + { + // Primary rank is first, so we skip that one + const auto l_begin = l_ranks_in_pair.begin() + 1; + const auto l_end = l_ranks_in_pair.end(); + + // Loops through the ranks + for(auto l_it = l_begin; l_it < l_end; ++l_it) + { + const auto l_rank = *l_it; + add_rank_to_vector(l_rank, io_ranks); + } + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Adds all ranks from a rank pair to a ranks vector +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[in,out] io_ranks - the vector of ranks that are not being calibrated +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode add_ranks_from_pair(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + std::vector<uint64_t>& io_ranks) +{ + std::vector<uint64_t> l_ranks_in_pair; + FAPI_TRY( mss::rank::get_ranks_in_pair(i_target, i_rp, l_ranks_in_pair) ); + + // Loops through the ranks + for(const auto l_rank : l_ranks_in_pair) + { + add_rank_to_vector(l_rank, io_ranks); + } + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Adds a rank to the ranks vector if it is valid +/// @param[in] i_rank - the rank to add to the vector +/// @param[in,out] io_ranks - the vector of ranks that are not being calibrated +/// +void add_rank_to_vector(const uint64_t i_rank, std::vector<uint64_t>& io_ranks) +{ + if(i_rank != mss::NO_RANK) + { + io_ranks.push_back(i_rank); + } +} + +/// +/// @brief Enables or disables the DQ outputs on all non-calibrating ranks +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[in] i_state - the state of qoff +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode configure_non_calibrating_ranks(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const mss::states& i_state) +{ + // Declares variables + mss::ccs::program<fapi2::TARGET_TYPE_MCBIST, fapi2::TARGET_TYPE_MCA> l_program; + std::vector<uint64_t> l_ranks; + const auto& l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target); + + // Gets the ranks to configure + FAPI_TRY( get_non_calibrating_ranks(i_target, i_rp, l_ranks) ); + + // Adds in the MRS instructions to configure qoff + for(const auto l_rank : l_ranks) + { + FAPI_TRY( add_mrs(i_target, l_rank, i_state, l_program.iv_instructions) ); + } + + // Executes the CCS instructions + FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + +} // ns wr_lvl + } // ns workarounds } // ns ccs diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H index c39187b37..ded4f9891 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017 */ +/* Contributors Listed Below - COPYRIGHT 2017,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,7 @@ #include <generic/memory/lib/utils/c_str.H> #include <generic/memory/lib/utils/find.H> #include <lib/ccs/ccs.H> +#include <lib/dimm/ddr4/mrs_load_ddr4.H> namespace mss { @@ -76,6 +77,82 @@ fapi2::ReturnCode exit( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode enable_pda_shadow_reg( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, const uint64_t i_rank ); +namespace wr_lvl +{ + +/// +/// @brief Updates an MRS to have the desired Qoff value +/// @param[in,out] io_mrs - the MRS to update +/// @param[in] i_state - the state for the qoff in the MRS +/// +void update_mrs(mss::ddr4::mrs01_data& io_mrs, const mss::states i_state); + +/// +/// @brief Adds in an MRS on a per-rank basis based upon qoff +/// @param[in] i_target - the target on which to operate +/// @param[in] i_rank - the rank on which to operate +/// @param[in] i_state - the state of qoff +/// @param[in,out] io_inst the instruction to fixup +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode add_mrs(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rank, + const mss::states& i_state, + std::vector<ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST>>& io_inst); + +/// +/// @brief Gets a vector of ranks that are not going to be calibrated in the given rank pair +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[out] o_ranks - the vector of ranks that are not being calibrated +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode get_non_calibrating_ranks(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + std::vector<uint64_t>& o_ranks); + +/// +/// @brief Adds the non-primary ranks from a rank pair to a ranks vector +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[in,out] io_ranks - the vector of ranks that are not being calibrated +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode add_non_primary_ranks(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + std::vector<uint64_t>& io_ranks); + +/// +/// @brief Adds all ranks from a rank pair to a ranks vector +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[in,out] io_ranks - the vector of ranks that are not being calibrated +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode add_ranks_from_pair(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + std::vector<uint64_t>& io_ranks); + +/// +/// @brief Adds a rank to the ranks vector if it is valid +/// @param[in] i_rank - the rank to add to the vector +/// @param[in,out] io_ranks - the vector of ranks that are not being calibrated +/// +void add_rank_to_vector(const uint64_t i_rank, std::vector<uint64_t>& io_ranks); + +/// +/// @brief Enables or disables the DQ outputs on all non-calibrating ranks +/// @param[in] i_target - the MCA target on which to oparate +/// @param[in] i_rp - the rank pair that is currently being calibrated +/// @param[in] i_state - the state of qoff +/// @return FAPI2_RC_SUCCESS iff OK +/// +fapi2::ReturnCode configure_non_calibrating_ranks(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const mss::states& i_state); + +} // ns wr_lvl + } // ns workarounds } // ns ccs |