summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs.H13
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C17
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.H12
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.C198
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/ccs_workarounds.H79
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
OpenPOWER on IntegriCloud