diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2017-10-03 14:03:46 -0500 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2017-11-10 10:57:07 -0500 |
commit | 0f5f2625adad6e82f56abe7a5a4db0930dcb4f93 (patch) | |
tree | 822376a7992817ea8e50a06a2ebb12595f50af4b /src/import/chips/p9/procedures/hwp/memory | |
parent | c0d7d47a554fb9187b0411ca6eca47a40e6daf84 (diff) | |
download | talos-hostboot-0f5f2625adad6e82f56abe7a5a4db0930dcb4f93.tar.gz talos-hostboot-0f5f2625adad6e82f56abe7a5a4db0930dcb4f93.zip |
Updates dramint training structure
Creates a class to contain workaround and cal steps to execute
Change-Id: Ife1a3a451dbc92b46eec15131a6ad3f68968c1f7
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/47092
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Dev-Ready: STEPHEN GLANCY <sglancy@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/47096
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: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory')
20 files changed, 1526 insertions, 615 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H index e901055e8..1f52142f7 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H @@ -41,218 +41,28 @@ #include <lib/eff_config/timing.H> #include <lib/utils/poll.H> #include <lib/phy/read_cntrl.H> +#include <lib/phy/mss_training.H> namespace mss { /// -/// @brief Return the cycles taken for write leveling on a single rank -/// @tparam T the target type used to get attributes -/// @param[in] i_target used to get attributes -/// @return uint64_t, the cycles taken for write leveling on a single rank -/// -template<fapi2::TargetType T> -uint64_t wr_lvl_cycles(const fapi2::Target<T>& i_target ) -{ - const uint64_t TWLO_TWLOE = mss::twlo_twloe(i_target); - - // This step runs for approximately (80 + TWLO_TWLOE) x NUM_VALID_SAMPLES x (384/(BIG_STEP + 1) + - // (2 x (BIG_STEP + 1))/(SMALL_STEP + 1)) + 20 memory clock cycles per rank. - - const uint64_t l_wr_lvl_cycles = (80 + TWLO_TWLOE) * WR_LVL_NUM_VALID_SAMPLES * (384 / (WR_LVL_BIG_STEP + 1) + - (2 * (WR_LVL_BIG_STEP + 1)) / (WR_LVL_SMALL_STEP + 1)) + 20; - FAPI_DBG("%s wr_lvl_cycles: %llu(%lluns) (%llu, %llu, %llu, %llu)", - mss::c_str(i_target), - l_wr_lvl_cycles, - mss::cycles_to_ns(i_target, - l_wr_lvl_cycles), - TWLO_TWLOE, WR_LVL_NUM_VALID_SAMPLES, WR_LVL_BIG_STEP, WR_LVL_SMALL_STEP); - - return l_wr_lvl_cycles; -} - -/// -/// @brief Return the cycles taken for DQS align on a single rank -/// @tparam T the target type used to get attributes -/// @param[in] i_target used to get attributes -/// @return uint64_t, the cycles taken for DQS align on a single rank -/// -template<fapi2::TargetType T> -uint64_t dqs_align_cycles(const fapi2::Target<T>& i_target ) -{ - // This step runs for approximately 6 x 600 x 4 DRAM clocks per rank pair. - const uint64_t l_dqs_align_cycles = 6 * 600 * 4; - - FAPI_DBG("%s dqs_align_cycles: %llu(%lluns)", mss::c_str(i_target), l_dqs_align_cycles, mss::cycles_to_ns(i_target, - l_dqs_align_cycles)); - return l_dqs_align_cycles; -} - -/// -/// @brief Return the cycles taken for RD clock align on a single rank -/// @tparam T the target type used to get attributes -/// @param[in] i_target used to get attributes -/// @return uint64_t, the cycles taken for RD clock align on a single rank -/// -template<fapi2::TargetType T> -uint64_t rdclk_align_cycles(const fapi2::Target<T>& i_target ) -{ - // This step runs for approximately 24 x ((1024/COARSE_CAL_STEP_SIZE + 4 x COARSE_CAL_STEP_SIZE) x 4 + 32) DRAM - // clocks per rank pair - const uint64_t l_rdclk_align_cycles = 24 * ((1024 / COARSE_CAL_STEP_SIZE + 4 * COARSE_CAL_STEP_SIZE) * 4 + 32); - FAPI_DBG("%s rdclk_align_cycles: %llu(%lluns) (%llu)", mss::c_str(i_target), l_rdclk_align_cycles, - mss::cycles_to_ns(i_target, l_rdclk_align_cycles), COARSE_CAL_STEP_SIZE); - return l_rdclk_align_cycles; -} - -/// -/// @brief Return the cycles taken for read centering on a single rank -/// @tparam T the target type used to get attributes -/// @param[in] i_target used to get attributes -/// @return uint64_t, the cycles taken for read centering on a single rank -/// -template<fapi2::TargetType T> -uint64_t read_ctr_cycles(const fapi2::Target<T>& i_target ) -{ - // This step runs for approximately 6 x (512/COARSE_CAL_STEP_SIZE + 4 x (COARSE_CAL_STEP_SIZE + - // 4 x CONSEQ_PASS)) x 24 DRAM clocks per rank pair. - - const uint64_t l_read_ctr_cycles = 6 * (512 / COARSE_CAL_STEP_SIZE + 4 * (COARSE_CAL_STEP_SIZE + 4 * CONSEQ_PASS)) * 24; - FAPI_DBG("%s read_ctr_cycles %llu(%lluns) (%llu, %llu)", - mss::c_str(i_target), - l_read_ctr_cycles, - mss::cycles_to_ns(i_target, l_read_ctr_cycles), - COARSE_CAL_STEP_SIZE, - CONSEQ_PASS); - return l_read_ctr_cycles; -} - -/// -/// @brief Return the cycles taken for write centering on a single rank -/// @tparam T the target type used to get attributes -/// @param[in] i_target used to get attributes -/// @param[out] o_cycles the cycles taken for write centering on a single rank -/// @return FAPI2_RC_SUCCESS iff ok -/// -template<fapi2::TargetType T> -fapi2::ReturnCode write_ctr_cycles(const fapi2::Target<T>& i_target, uint64_t& o_cycles) -{ - // 1000 + (NUM_VALID_SAMPLES * (FW_WR_RD + FW_RD_WR + 16) * - // (1024/(SMALL_STEP +1) + 128/(BIG_STEP +1)) + 2 * (BIG_STEP+1)/(SMALL_STEP+1)) x 24 DRAM - // clocks per rank pair. - constexpr uint64_t WR_CNTR_FW_WR_RD = mss::fw_wr_rd(); - uint8_t l_fw_rd_wr = 0; - - FAPI_TRY( mss::fw_rd_wr(i_target, l_fw_rd_wr) ); - - o_cycles = 1000 + (WR_LVL_NUM_VALID_SAMPLES * (WR_CNTR_FW_WR_RD + l_fw_rd_wr + 16) * - (1024 / (WR_LVL_SMALL_STEP + 1) + 128 / (WR_LVL_BIG_STEP + 1)) + 2 * - (WR_LVL_BIG_STEP + 1) / (WR_LVL_SMALL_STEP + 1)) * 24; - - FAPI_DBG("%s write_ctr_cycles: %lu(%luns) (%u, %u, %u, %u, %u)", - mss::c_str(i_target), - o_cycles, - mss::cycles_to_ns(i_target, o_cycles), - WR_LVL_NUM_VALID_SAMPLES, - WR_CNTR_FW_WR_RD, - l_fw_rd_wr, - WR_LVL_BIG_STEP, - WR_LVL_SMALL_STEP); - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Return the cycles taken for coarse write on a single rank -/// @tparam T the target type used to get attributes -/// @param[in] i_target used to get attributes -/// @return uint64_t, the cycles taken for coarse write on a single rank -/// -template<fapi2::TargetType T> -uint64_t coarse_wr_cycles(const fapi2::Target<T>& i_target ) -{ - // The run length given here is the maximum run length for this calibration algorithm. - // This step runs for approximately 40 DRAM clocks per rank pair. - static const uint64_t l_coarse_wr_cycles = 40; - FAPI_DBG("%s coarse_wr_cycles: %llu(%lluns)", - mss::c_str(i_target), - l_coarse_wr_cycles, - mss::cycles_to_ns(i_target, l_coarse_wr_cycles)); - return l_coarse_wr_cycles; -} - -/// -/// @brief Return the cycles taken for coarse read on a single rank -/// @tparam T the target type used to get attributes -/// @param[in] i_target used to get attributes -/// @return uint64_t, the cycles taken for coarse rd on a single rank -/// -template<fapi2::TargetType T> -uint64_t coarse_rd_cycles(const fapi2::Target<T>& i_target ) -{ - // The run length given here is the maximum run length for this calibration algorithm. - // This step runs for approximately 32 DRAM clocks per rank pair. - static const uint64_t l_coarse_rd_cycles = 32; - FAPI_DBG("%s coarse_rd_cycles: %llu(%lluns)", - mss::c_str(i_target), - l_coarse_rd_cycles, - mss::cycles_to_ns(i_target, l_coarse_rd_cycles)); - return l_coarse_rd_cycles; -} - -/// /// @brief Configure the polling intervals with the proper timeings based on the cal steps enabled /// @tparam T the fapi2::TargetType of the port /// @param[in] i_target the port target +/// @param[in] i_total_cycles the number of cycles a cal step takes /// @param[in,out] io_poll the poll_parameters to update -/// @param[in] i_cal_steps_enabled a fapi2::buffer<uint8_t> representing the cal steps enabled /// @return FAPI2_RC_SUCCESS iff everything is OK /// template<fapi2::TargetType T> inline fapi2::ReturnCode cal_timer_setup(const fapi2::Target<T>& i_target, - poll_parameters& io_poll, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled) + const uint64_t i_total_cycles, + poll_parameters& io_poll) { // This should equal half of the minimum poll count of the quickest cal segment when in sim // i.e. DQS_ALIGN + INITIAL_PAT_WR = 3 polls, so this should be 2 constexpr uint64_t MINIMUM_POLL_COUNT = 2; - uint64_t l_write_cntr_cycles = 0; - uint64_t l_total_cycles = 0; - int64_t l_ns_left = 0; - uint8_t cal_abort_on_error = 0; - uint16_t l_vref_cal_enable = 0; - - FAPI_TRY( mss::write_ctr_cycles(i_target, l_write_cntr_cycles), "%s Failed calling write_ctr_cycles", - mss::c_str(i_target) ); - FAPI_TRY( mss::cal_abort_on_error(cal_abort_on_error), "%s Failed calling cal_abort_on_errorp", mss::c_str(i_target) ); - FAPI_TRY( mss::rdvref_cal_enable(i_target, l_vref_cal_enable), "%s Failed calling rdvref_cal_enable", - mss::c_str(i_target) ); - - // First, calculate the total number of cycles this cal should take if everything - // runs to completion - l_total_cycles = i_cal_steps_enabled.getBit<WR_LEVEL>() ? wr_lvl_cycles(i_target) : 0; - l_total_cycles += i_cal_steps_enabled.getBit<DQS_ALIGN>() ? dqs_align_cycles(i_target) : 0; - l_total_cycles += i_cal_steps_enabled.getBit<RDCLK_ALIGN>() ? rdclk_align_cycles(i_target) : 0; - - // We run either read centering during normal draminit_training and also during draminit_training_advance, - // can't be run twice in one cal though - l_total_cycles += ( i_cal_steps_enabled.getBit<READ_CTR>() || i_cal_steps_enabled.getBit<TRAINING_ADV>()) - ? read_ctr_cycles(i_target) : 0; - l_total_cycles += i_cal_steps_enabled.getBit<WRITE_CTR>() ? l_write_cntr_cycles : 0; - l_total_cycles += i_cal_steps_enabled.getBit<COARSE_WR>() ? coarse_wr_cycles(i_target) : 0; - l_total_cycles += i_cal_steps_enabled.getBit<COARSE_RD>() ? coarse_rd_cycles(i_target) : 0; - l_total_cycles += ((l_vref_cal_enable != 0) - && i_cal_steps_enabled.getBit<READ_CTR_2D_VREF>()) ? rc::vref_guess_time(i_target) : 0; - - // Now we have to decide if we're going to abort on an error or keep going. If we keep going, - // then we want our initial delay to be the expected time to completion - we don't have much - // of a choice. If we abort on error then we want to have a small initial delay, and poll more - // times with longer durations between the polling. - // Sometimes when running in sim, particularly Mesa, it is helpful to not delay a bunch // when training starts - makes it simpler to get an AET for, say, write leveling. So // this is here to allow the simple removal of the initial delay for those situations. @@ -261,18 +71,18 @@ inline fapi2::ReturnCode cal_timer_setup(const fapi2::Target<T>& i_target, io_poll.iv_initial_sim_delay = mss::cycles_to_simcycles(1); #else // We don't want to wait too long for the initial check, just some hueristics here - io_poll.iv_initial_delay = mss::cycles_to_ns(i_target, l_total_cycles / 8); - io_poll.iv_initial_sim_delay = mss::cycles_to_simcycles(l_total_cycles / 8); + io_poll.iv_initial_delay = mss::cycles_to_ns(i_target, i_total_cycles / 8); + io_poll.iv_initial_sim_delay = mss::cycles_to_simcycles(i_total_cycles / 8); #endif // Delay 10us between polls, and setup the poll count so - // iv_initial_delay + (iv_delay * iv_poll_count) == l_total_cycles + some fudge; + // iv_initial_delay + (iv_delay * iv_poll_count) == i_total_cycles + some fudge; io_poll.iv_delay = DELAY_10US; io_poll.iv_sim_delay = mss::cycles_to_simcycles(mss::ns_to_cycles(i_target, io_poll.iv_delay)); // Round up to the cycles left after the initial delay - l_ns_left = std::max(int64_t(0), (int64_t(mss::cycles_to_ns(i_target, - l_total_cycles)) - int64_t(io_poll.iv_initial_delay))); + const uint64_t l_ns_left = std::max(int64_t(0), (int64_t(mss::cycles_to_ns(i_target, + i_total_cycles)) - int64_t(io_poll.iv_initial_delay))); io_poll.iv_poll_count = l_ns_left / io_poll.iv_delay; io_poll.iv_poll_count += l_ns_left % io_poll.iv_delay ? 0 : 1; @@ -285,10 +95,9 @@ inline fapi2::ReturnCode cal_timer_setup(const fapi2::Target<T>& i_target, // HB is failing, bump it out 4x for the polling io_poll.iv_poll_count *= 4; - FAPI_INF("%s cal abort on error? %s. tc: %luc, id: %luns(%lusc), d: %lu(%lusc), pc: %lu", + FAPI_INF("%s tc: %luc, id: %luns(%lusc), d: %lu(%lusc), pc: %lu", mss::c_str(i_target), - (cal_abort_on_error ? "yup" : "nope"), - l_total_cycles, + i_total_cycles, io_poll.iv_initial_delay, io_poll.iv_initial_sim_delay, io_poll.iv_delay, @@ -296,9 +105,6 @@ inline fapi2::ReturnCode cal_timer_setup(const fapi2::Target<T>& i_target, io_poll.iv_poll_count); return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; } } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C index 45e36dd95..da960bac9 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C @@ -38,6 +38,7 @@ #include <fapi2.H> #include <mss.H> +#include <lib/mss_attribute_accessors.H> #include <lib/phy/ddr_phy.H> #include <lib/phy/read_cntrl.H> @@ -52,6 +53,7 @@ #include <lib/dimm/ddr4/latch_wr_vref.H> #include <lib/workarounds/seq_workarounds.H> #include <lib/workarounds/dqs_align_workarounds.H> +#include <lib/phy/mss_training.H> #include <lib/utils/bit_count.H> #include <generic/memory/lib/utils/find.H> @@ -937,11 +939,13 @@ fapi_try_exit: /// /// @brief Write the READ_VREF register to enable and or to skip the read centering cal /// @param[in] i_target the MCA target associated with this cal setup -/// @param[in] i_cal_steps_enabled fapi2::buffer<uint8_t> representing the cal steps to enable +/// @param[in] i_rd_ctr - run RD CTR if set to true +/// @param[in] i_rd_vref - run RD VREF is set to true /// @return FAPI2_RC_SUCCESS iff setup was successful /// fapi2::ReturnCode setup_read_vref_config1( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled) + const bool i_rd_ctr, + const bool i_rd_vref) { fapi2::buffer<uint64_t> l_data; typedef rcTraits<fapi2::TARGET_TYPE_MCA> TT; @@ -951,16 +955,15 @@ fapi2::ReturnCode setup_read_vref_config1( const fapi2::Target<fapi2::TARGET_TYP FAPI_TRY( mss::rc::read_vref_config1(i_target, l_data), "%s Failed read_vref_config1", mss::c_str(i_target) ); // Enable is based off of the RDVREF attribute - l_data.writeBit<TT::RDVREF_CALIBRATION_ENABLE>( i_cal_steps_enabled.getBit<READ_CTR_2D_VREF>() ); + l_data.writeBit<TT::RDVREF_CALIBRATION_ENABLE>( i_rd_vref ); // Check to see if READ_CENTERING is disabled, if so, set the bit - l_data.writeBit<TT::SKIP_RDCENTERING>( !(i_cal_steps_enabled.getBit<READ_CTR>() - || i_cal_steps_enabled.getBit<TRAINING_ADV>()) ); + l_data.writeBit<TT::SKIP_RDCENTERING>( !i_rd_ctr ); FAPI_INF("%s %s read VREF cal, read centering is %s", mss::c_str(i_target), - i_cal_steps_enabled.getBit<READ_CTR_2D_VREF>() ? "Enabling" : "Disabling", - i_cal_steps_enabled.getBit<READ_CTR>() ? "yup" : "nope"); + i_rd_vref ? "Enabling" : "Disabling", + i_rd_ctr ? "yup" : "nope"); FAPI_TRY( mss::rc::write_vref_config1(i_target, l_data), "%s Failed write_vref_config1", mss::c_str(i_target) ); fapi_try_exit: @@ -969,199 +972,61 @@ fapi_try_exit: /// /// @brief Setup all the cal config register -/// @param[in] i_target the MCA target associated with this cal setup -/// @param[in] i_rank_pairs the vector of currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer<uint8_t> representing the cal steps to enable +/// @param[in] i_target the target associated with this cal setup +/// @param[in] i_rank_pair the rank pair to calibrate +/// @param[in] i_cal_config the calibration config register +/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override /// @return FAPI2_RC_SUCCESS iff setup was successful /// -template<> fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const std::vector<uint64_t>& i_rank_pairs, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled) + const uint64_t i_rank_pair, + const fapi2::buffer<uint64_t>& i_cal_config, + const uint8_t i_abort_on_error) { - fapi2::buffer<uint64_t> l_cal_config; - uint8_t l_sim = 0; - uint8_t l_cal_abort_on_error = 0; - - FAPI_TRY( mss::cal_abort_on_error(l_cal_abort_on_error) ); - FAPI_TRY( mss::is_simulation(l_sim) ); - - // This is the buffer which will be written to CAL_CONFIG0. It starts - // life assuming no cal sequences, no rank pairs - - - // Sadly, the bits in the register don't align directly with the bits in the attribute. - // So, arrange the bits accordingly and write the config register. - { - // Skip DRAM_ZQCAL as it's not in the config register - we do it outside. - // Loop (unrolled because static) over the remaining bits. - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_WR_LEVEL>( - i_cal_steps_enabled.getBit<WR_LEVEL>()); - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_DQS_ALIGN>( - i_cal_steps_enabled.getBit<DQS_ALIGN>()); - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_RDCLK_ALIGN>( - i_cal_steps_enabled.getBit<RDCLK_ALIGN>()); - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_READ_CTR>( - i_cal_steps_enabled.getBit<READ_CTR>() || i_cal_steps_enabled.getBit<READ_CTR_2D_VREF>()); - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_WRITE_CTR>( - i_cal_steps_enabled.getBit<WRITE_CTR>() || i_cal_steps_enabled.getBit<WRITE_CTR_2D_VREF>()); - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_INITIAL_COARSE_WR>( - i_cal_steps_enabled.getBit<COARSE_WR>()); - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_COARSE_RD>( - i_cal_steps_enabled.getBit<COARSE_RD>()); - - // Turn on initial pattern write only in h/w, never for sim (makes the DIMM behavioral lose it's mind) - if (!l_sim) - { - // If we are running training advance, none of the steps above can be enabled. - // If they are, we have a code bug and should fapi2:Assert. - // This isn't dependent on system or attributes but code structure - if ( l_cal_config != 0 && i_cal_steps_enabled.getBit<TRAINING_ADV>()) - { - FAPI_ERR("Error setting up draminit training advance. Set CUSTOM_RD with other cal steps"); - fapi2::Assert( false ); - } - - // Enable CUSTOM_RD for training ADV. If this bit is set, only TRAINING_ADV and INIT_PAT_WR can be set - // We assert this above. - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_CUSTOM_RD>( - i_cal_steps_enabled.getBit<TRAINING_ADV>()); - - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_INITIAL_PAT_WR>( - i_cal_steps_enabled.getBit<INITIAL_PAT_WR>()); - } - - // Moved this down here so we can make the training advance check above - l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ABORT_ON_ERROR>(l_cal_abort_on_error); - } - - // Blast the VREF config with the proper setting for these cal bits if there were any enable bits set - if (i_cal_steps_enabled.getBit<READ_CTR_2D_VREF>()) - { - uint16_t l_vref_cal_enable = 0; - - // Blast the VREF_CAL_ENABLE to the registers that control which dp16's to use for rdvref - FAPI_TRY( mss::rdvref_cal_enable(i_target, l_vref_cal_enable) ); - FAPI_TRY( mss::scom_blastah(i_target, dp16Traits<TARGET_TYPE_MCA>::RD_VREF_CAL_ENABLE_REG, l_vref_cal_enable) ); - } - - // Now lets set the actual read_vref_config. We want to write/ clear this every time we run so seperate function - FAPI_TRY( setup_read_vref_config1(i_target, i_cal_steps_enabled), - "%s Failed setting the read_vref_config1", mss::c_str(i_target) ); - - { - typedef mss::dp16Traits<fapi2::TARGET_TYPE_MCA> TT; - std::vector<fapi2::buffer<uint64_t>> l_wr_vref_config; - FAPI_TRY( mss::scom_suckah(i_target, TT::WR_VREF_CONFIG0_REG, l_wr_vref_config) ); - - // Loops and sets or clears the 2D VREF bit on all DPs - for(auto& l_data : l_wr_vref_config) - { - // 0: Run only the VREF (2D) write centering algorithm - // 1: Run only the 1D - l_data.writeBit<TT::WR_VREF_CONFIG0_1D_ONLY_SWITCH>(!i_cal_steps_enabled.getBit<WRITE_CTR_2D_VREF>()); - } - - FAPI_TRY(mss::scom_blastah(i_target, TT::WR_VREF_CONFIG0_REG, l_wr_vref_config)); - } + auto l_cal_config = i_cal_config; - // loops through all RP's running workarounds and latching the VREF's as need be - for(const auto& l_rp : i_rank_pairs) - { - // Latches in the WR VREF values - // Overrides will be set by mss::workarounds::wr_vref::execute. - // If the execute code is skipped, then it will read from the attributes - uint8_t l_vrefdq_train_range_override = mss::ddr4::USE_DEFAULT_WR_VREF_SETTINGS; - uint8_t l_vrefdq_train_value_override = mss::ddr4::USE_DEFAULT_WR_VREF_SETTINGS; - - // Runs WR VREF workarounds if needed - // it will check and see if it needs to run, if not it will return success - FAPI_TRY( mss::workarounds::wr_vref::execute(i_target, - l_rp, - i_cal_steps_enabled, - l_vrefdq_train_range_override, - l_vrefdq_train_value_override) ); - - // Latches the VREF's, if and only if the latching bit is set - if(i_cal_steps_enabled.getBit<WR_VREF_LATCH>()) - { - FAPI_TRY( mss::ddr4::latch_wr_vref_commands_by_rank_pair(i_target, - l_rp, - l_vrefdq_train_range_override, - l_vrefdq_train_value_override) ); - } - } + // Sets up abort on error + l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ABORT_ON_ERROR>(i_abort_on_error); // Note: This rank encoding isn't used if the cal is initiated from the CCS engine - // as they use the recal inteface. + // as they use the recal interface. // Configure the rank pairs - for (const auto& rp : i_rank_pairs) - { - FAPI_TRY( l_cal_config.setBit(MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_RANK_PAIR + rp) ); - } + FAPI_TRY( l_cal_config.setBit(MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_RANK_PAIR + i_rank_pair) ); - FAPI_INF("cal_config for %s: 0x%04lx (steps: 0x%08x)", - mss::c_str(i_target), uint16_t(l_cal_config), i_cal_steps_enabled); + FAPI_INF("cal_config for %s: 0x%016lx", mss::c_str(i_target), l_cal_config); FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0, l_cal_config) ); - // Sets up the workarounds - FAPI_TRY( mss::workarounds::dp16::rd_vref_vref_sense_setup(i_target) ); - fapi_try_exit: return fapi2::current_err; } /// -/// @brief Setup all the cal config register -/// @param[in] i_target the target associated with this cal setup -/// @param[in] i_rank one currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable -/// @return FAPI2_RC_SUCCESS iff setup was successful -/// -fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const uint64_t i_rank, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled) -{ - std::vector< uint64_t > l_ranks({i_rank}); - return setup_cal_config(i_target, l_ranks, i_cal_steps_enabled); -} - -/// /// @brief Execute a set of PHY cal steps -/// Specializaton for TARGET_TYPE_MCA -/// @param[in] i_target the target associated with this cal +/// @param[in] i_target the target associated with this cal - MCA specialization /// @param[in] i_rp one of the currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable +/// @param[in] i_cal_config fapi2::buffer representing the calibration configuration register /// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override +/// @param[in] i_total_cycles how long the calibration will take in cycles /// @return FAPI2_RC_SUCCESS iff setup was successful /// @note This is a helper function. Library users are required to call setup_and_execute_cal /// -template<> -fapi2::ReturnCode execute_cal_steps_helper( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, +template< > +fapi2::ReturnCode execute_cal_steps_helper( const fapi2::Target<TARGET_TYPE_MCA>& i_target, const uint64_t i_rp, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled, - const uint8_t i_abort_on_error) + const fapi2::buffer<uint64_t>& i_cal_config, + const uint8_t i_abort_on_error, + const uint64_t i_total_cycles) { const auto& l_mcbist = mss::find_target<TARGET_TYPE_MCBIST>(i_target); auto l_cal_inst = mss::ccs::initial_cal_command<TARGET_TYPE_MCBIST>(i_rp); mss::ccs::program<TARGET_TYPE_MCBIST, TARGET_TYPE_MCA> l_program; - // Sanity check due to WR_LEVEL termination requirement - if ((i_cal_steps_enabled.getBit<mss::cal_steps::WR_LEVEL>()) && - (mss::bit_count(uint32_t(i_cal_steps_enabled)) != 1)) - { - FAPI_ERR("WR_LEVEL cal step requires special terminations, so must be run separately from other cal steps (0x%08llx)", - i_cal_steps_enabled ); - - fapi2::Assert(false); - } - - FAPI_DBG("%s executing training CCS instruction: 0x%llx, 0x%llx for cal steps 0x%08x", + FAPI_DBG("%s executing training CCS instruction: 0x%016llx, 0x%016llx for cal config 0x%16x", mss::c_str(i_target), l_cal_inst.arr0, l_cal_inst.arr1, - i_cal_steps_enabled); + i_cal_config); // Delays in the CCS instruction ARR1 for training are supposed to be 0xFFFF, // and we're supposed to poll for the done or timeout bit. But we don't want @@ -1176,196 +1041,23 @@ fapi2::ReturnCode execute_cal_steps_helper( const fapi2::Target<fapi2::TARGET_TY // We need to figure out how long to wait before we start polling. Each cal step has an expected // duration, so for each cal step which was enabled, we update the CCS program. - FAPI_TRY( mss::cal_timer_setup(i_target, l_program.iv_poll, i_cal_steps_enabled) ); - FAPI_TRY( mss::setup_cal_config(i_target, i_rp, i_cal_steps_enabled) ); + FAPI_TRY( mss::cal_timer_setup(i_target, i_total_cycles, l_program.iv_poll) ); + FAPI_TRY( mss::setup_cal_config( i_target, i_rp, i_cal_config, i_abort_on_error) ); - // In the event of an init cal hang, CCS_STATQ(2) will assert and CCS_STATQ(3:5) = “001” to indicate a + // In the event of an init cal hang, CCS_STATQ(2) will assert and CCS_STATQ(3:5) = "001" to indicate a // timeout. Otherwise, if calibration completes, FW should inspect DDRPHY_FIR_REG bits (50) and (58) // for signs of a calibration error. If either bit is on, then the DDRPHY_PC_INIT_CAL_ERROR register // should be polled to determine which calibration step failed. // If we got a cal timeout, or another CCS error just leave now. If we got success, check the error // bits for a cal failure. We'll return the proper ReturnCode so all we need to do is FAPI_TRY. - FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target), "%s failed to execute CCS program for cal steps 0x%08x", - mss::c_str(i_target), i_cal_steps_enabled ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Perform necessary termination setup and execute a set of PHY cal steps -/// Specializaton for TARGET_TYPE_MCA -/// @param[in] i_target the target associated with this cal -/// @param[in] i_rp one of the currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable -/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override -/// @return FAPI2_RC_SUCCESS iff setup was successful -/// -template<> -fapi2::ReturnCode setup_and_execute_cal( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const uint64_t i_rp, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled, - const uint8_t i_abort_on_error) -{ - const auto& l_mcbist = mss::find_target<TARGET_TYPE_MCBIST>(i_target); - FAPI_INF("ABORT_ON_ERROR is %d", i_abort_on_error); - - // We run the cal steps in three chunks: pre-write-leveling, write-leveling, post-wirte-leveling. - // This is because write-leveling requires a special set of termination values. - - // Run WR_LEVEL step (with overridden termination values) if selected - if (i_cal_steps_enabled.getBit<mss::cal_steps::WR_LEVEL>()) - { - mss::ccs::program<TARGET_TYPE_MCBIST, TARGET_TYPE_MCA> l_program; - std::vector< ccs::instruction_t<TARGET_TYPE_MCBIST> > l_rtt_inst; - - FAPI_DBG("%s Running WR_LEVEL step on RP%d", mss::c_str(i_target), i_rp); - fapi2::buffer<uint32_t> l_steps_to_execute; - l_steps_to_execute.setBit<mss::cal_steps::WR_LEVEL>(); - - // Setup WR_LEVEL specific terminations - // JEDEC spec requires disabling RTT_WR during WR_LEVEL, and enabling equivalent terminations - FAPI_TRY( setup_wr_level_terminations(i_target, i_rp, l_rtt_inst) ); - - if (!l_rtt_inst.empty()) - { - l_program.iv_instructions.insert(l_program.iv_instructions.end(), l_rtt_inst.begin(), l_rtt_inst.end() ); - FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); - l_program.iv_instructions.clear(); - } - - // Execute WR_LEVEL - FAPI_TRY( execute_cal_steps_helper(i_target, - i_rp, - l_steps_to_execute, - i_abort_on_error) ); - - // Restore normal terminations - l_rtt_inst.clear(); - FAPI_TRY( restore_mainline_terminations(i_target, i_rp, l_rtt_inst) ); - - if (!l_rtt_inst.empty()) - { - l_program.iv_instructions.insert(l_program.iv_instructions.end(), - l_rtt_inst.begin(), - l_rtt_inst.end() ); - FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); - } - } - - // run Initial Pattern Write and custom read centering if enabled - if(i_cal_steps_enabled.getBit<mss::cal_steps::INITIAL_PAT_WR>()) - { - // Sets up the cal steps in the buffer - fapi2::buffer<uint32_t> l_steps_to_execute; - l_steps_to_execute.writeBit<mss::cal_steps::INITIAL_PAT_WR> - (i_cal_steps_enabled.getBit<mss::cal_steps::INITIAL_PAT_WR>()); - l_steps_to_execute.writeBit<mss::cal_steps::TRAINING_ADV> - (i_cal_steps_enabled.getBit<mss::cal_steps::TRAINING_ADV>()); - - FAPI_INF("%s Running Initial Pattern Write and TRAINING_ADV(%s) on RP%d 0x%08x", - mss::c_str(i_target), - (i_cal_steps_enabled.getBit<mss::cal_steps::TRAINING_ADV>() ? "yes" : "no"), - i_rp, - l_steps_to_execute); - - // Undertake the calibration steps - FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); - } - - // Lets run DQS - if(i_cal_steps_enabled.getBit<mss::cal_steps::DQS_ALIGN>()) - { - // Sets up the cal steps in the buffer - fapi2::buffer<uint32_t> l_steps_to_execute; - l_steps_to_execute.setBit<mss::cal_steps::DQS_ALIGN>(); - - FAPI_INF("%s Running DQS align on RP%d 0x%08x", - mss::c_str(i_target), i_rp, l_steps_to_execute); - - // Undertake the calibration steps - FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); - - // Now run the DQS align workaround - FAPI_TRY(mss::workarounds::dp16::dqs_align::dqs_align_workaround(i_target, i_rp, i_abort_on_error), - "%s Failed to run dqs align workaround on rp %d", mss::c_str(i_target), i_rp); - } - - // Run cal step READ CLOCK ALIGN - if (i_cal_steps_enabled.getBit<mss::cal_steps::RDCLK_ALIGN>()) - { - // Turn off refresh - FAPI_TRY( mss::workarounds::dqs_align::turn_off_refresh(i_target) ); - - // Sets up the cal steps in the buffer - fapi2::buffer<uint32_t> l_steps_to_execute; - - l_steps_to_execute.setBit<mss::cal_steps::RDCLK_ALIGN>(); - - FAPI_INF("%s Running rd_clk align on RP%d 0x%08x", mss::c_str(i_target), i_rp, - l_steps_to_execute); - - // Undertake the calibration steps - FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); - - // Run the red_waterfall workaround for low VDN sensitivity - // Increments the waterfall forward by one - FAPI_TRY( mss::workarounds::dp16::fix_red_waterfall_gate( i_target, i_rp) ); - - // Turn refresh back on - FAPI_TRY( mss::workarounds::dqs_align::turn_on_refresh(i_target) ); - } - - if(i_cal_steps_enabled.getBit<mss::cal_steps::READ_CTR_2D_VREF, mss::cal_steps::READ_VREF_TO_READ_CTR_LEN>()) - { - // Turn off refresh - FAPI_TRY( mss::workarounds::dqs_align::turn_off_refresh(i_target) ); - - // Sets up the cal steps in the buffer - fapi2::buffer<uint32_t> l_steps_to_execute; - - l_steps_to_execute.writeBit<mss::cal_steps::READ_CTR_2D_VREF> - (i_cal_steps_enabled.getBit<mss::cal_steps::READ_CTR_2D_VREF>()); - l_steps_to_execute.writeBit<mss::cal_steps::READ_CTR>(i_cal_steps_enabled.getBit<mss::cal_steps::READ_CTR>()); - - FAPI_INF("%s Running read centering vref through read centering on RP%d 0x%08x", mss::c_str(i_target), i_rp, - l_steps_to_execute); - - // Undertake the calibration steps - FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); - - // Now run the read centering workaround - if(l_steps_to_execute.getBit<READ_CTR>()) - { - FAPI_TRY(mss::workarounds::dp16::rd_dq::fix_delay_values(i_target, i_rp), - "%s Failed to run read centering workaround on rp %d", mss::c_str(i_target), i_rp); - } - - // Turn refresh back on - FAPI_TRY( mss::workarounds::dqs_align::turn_on_refresh(i_target) ); - } - - // Run cal steps after RD_CTR if any are selected - note: WRITE_CTR takes place after RD_CTR - if (i_cal_steps_enabled.getBit<mss::cal_steps::WRITE_CTR_2D_VREF, mss::cal_steps::WR_VREF_TO_COARSE_RD_LEN>()) - { - fapi2::buffer<uint32_t> l_steps_to_execute( i_cal_steps_enabled ); - l_steps_to_execute.clearBit<mss::cal_steps::DRAM_ZQCAL, mss::cal_steps::DRAM_ZQCAL_UP_TO_WRITE_CTR_2D_VREF>(); - - // Setting the WR_VREF_LATCH bit to run the WR_VREF workaround after wr_vref runs - // Gets set iff the bit is set in i_steps_to_execute - l_steps_to_execute.writeBit<WR_VREF_LATCH>( i_cal_steps_enabled.getBit<WR_VREF_LATCH>() ); - - FAPI_DBG("%s Running remaining cal steps on RP%d 0x%08x", mss::c_str(i_target), i_rp, l_steps_to_execute); - - FAPI_TRY( execute_cal_steps_helper(i_target, i_rp, l_steps_to_execute, i_abort_on_error) ); - } + FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target), "%s failed to execute CCS program for calibration", + mss::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; } - // TODO RTC:167929 Can ODT VPD processing be shared between RD and WR? /// /// @brief Setup odt_rd_config diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H index 37f763846..d56af96cd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H @@ -37,7 +37,6 @@ #define _MSS_DDR_PHY_H_ #include <fapi2.H> -#include <lib/mss_attribute_accessors.H> #include <lib/ccs/ccs.H> namespace mss @@ -107,11 +106,13 @@ fapi2::ReturnCode check_bang_bang_lock( const fapi2::Target<fapi2::TARGET_TYPE_M /// /// @brief Write the READ_VREF register to enable and or to skip the read centering cal /// @param[in] i_target the MCA target associated with this cal setup -/// @param[in] i_cal_steps_enabled fapi2::buffer<uint8_t> representing the cal steps to enable +/// @param[in] i_rd_ctr - run RD CTR if set to true +/// @param[in] i_rd_vref - run RD VREF is set to true /// @return FAPI2_RC_SUCCESS iff setup was successful /// fapi2::ReturnCode setup_read_vref_config1( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled); + const bool i_rd_ctr, + const bool i_rd_vref); /// /// @brief Configure the DP16 sysclk @@ -140,58 +141,34 @@ fapi2::ReturnCode clear_initial_cal_errors( const fapi2::Target<T>& i_target ); /// /// @brief Setup all the cal config register -/// @tparam T, the target type of the MCA/MBA /// @param[in] i_target the target associated with this cal setup -/// @param[in] i_rank_pairs the vector of currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer<uint32_t> representing the cal steps to enable -/// @return FAPI2_RC_SUCCESS iff setup was successful -/// -template< fapi2::TargetType T > -fapi2::ReturnCode setup_cal_config( const fapi2::Target<T>& i_target, - const std::vector<uint64_t>& i_rank_pairs, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled); - -/// -/// @brief Setup all the cal config register -/// @param[in] i_target the target associated with this cal setup -/// @param[in] i_rank one currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable +/// @param[in] i_rank_pair the rank pair to calibrate +/// @param[in] i_cal_config the calibration config register +/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override /// @return FAPI2_RC_SUCCESS iff setup was successful /// fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const uint64_t i_rank, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled); + const uint64_t i_rank_pair, + const fapi2::buffer<uint64_t>& i_cal_config, + const uint8_t i_abort_on_error); /// /// @brief Execute a set of PHY cal steps /// @tparam T the target type associated with this cal /// @param[in] i_target the target associated with this cal /// @param[in] i_rp one of the currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable +/// @param[in] i_cal_config fapi2::buffer representing the calibration configuration register /// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override +/// @param[in] i_total_cycles how long the calibration will take in cycles /// @return FAPI2_RC_SUCCESS iff setup was successful /// @note This is a helper function. Library users are required to call setup_and_execute_cal /// template< fapi2::TargetType T > fapi2::ReturnCode execute_cal_steps_helper( const fapi2::Target<T>& i_target, const uint64_t i_rp, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled, - const uint8_t i_abort_on_error); - -/// -/// @brief Perform necessary termination setup and execute a set of PHY cal steps -/// @tparam T, the target type of the MCA/MBA -/// @param[in] i_target the target associated with this cal -/// @param[in] i_rp one of the currently configured rank pairs -/// @param[in] i_cal_steps_enabled fapi2::buffer representing the cal steps to enable -/// @param[in] i_abort_on_error CAL_ABORT_ON_ERROR override -/// @return FAPI2_RC_SUCCESS iff setup was successful -/// -template< fapi2::TargetType T > -fapi2::ReturnCode setup_and_execute_cal( const fapi2::Target<T>& i_target, - const uint64_t i_rp, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled, - const uint8_t i_abort_on_error); + const fapi2::buffer<uint64_t>& i_cal_config, + const uint8_t i_abort_on_error, + const uint64_t i_total_cycles); // TODO RTC:167929 Can ODT VPD processing be shared between RD and WR? // TODO RTC:157753 tparams P and R can be pulled from an MCA trait once we have it 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 4c191f105..9c7060c26 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 @@ -22,3 +22,725 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file workarounds/mss_training_workarounds.C +/// @brief High level workarounds for training +/// Workarounds are very device specific, so there is no attempt to generalize +/// this code in any way. +/// +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include <vector> +#include <initializer_list> + +#include <fapi2.H> +#include <mss.H> +#include <lib/phy/ddr_phy.H> +#include <lib/phy/mss_training.H> + +#include <lib/workarounds/dp16_workarounds.H> +#include <lib/workarounds/wr_vref_workarounds.H> +#include <lib/dimm/ddr4/latch_wr_vref.H> +#include <lib/workarounds/seq_workarounds.H> +#include <lib/workarounds/dqs_align_workarounds.H> + +#include <generic/memory/lib/utils/scom.H> +#include <lib/utils/count_dimm.H> +#include <lib/dimm/rank.H> +#include <lib/shared/mss_const.H> + +namespace mss +{ + +namespace training +{ + +/// +/// @brief Executes a cal step with workarounds +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode step::execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + // First, pre-workaround + FAPI_TRY(pre_workaround(i_target, i_rp, i_abort_on_error)); + + // Second, setup/run + FAPI_TRY(run(i_target, i_rp, i_abort_on_error)); + + // Finally, post workaround + FAPI_TRY(post_workaround(i_target, i_rp, i_abort_on_error)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes the pre-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode wr_vref_latch::pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + FAPI_INF("%s RP%d WR VREF latch workaround", mss::c_str(i_target), i_rp); + + // DD1 chip bugs require the WR VREF workarounds below + // This DD1 chip bug might override the VREF values, as such + // Runs WR VREF workarounds if needed + // it will check and see if it needs to run, if not it will return success + // Overrides will be set by mss::workarounds::wr_vref::execute. + // If the execute code is skipped, then it will read from the attributes + FAPI_TRY( mss::workarounds::wr_vref::execute(i_target, + i_rp, + iv_wr_vref, + iv_vrefdq_train_range_override, + iv_vrefdq_train_value_override) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Sets up and runs the calibration step +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode wr_vref_latch::run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + // Latches the WR VREF's on this rank pair, if required + // Note: the VREF latching should be done before write centering + // The latching is not a workaround (but is required by JEDEC), so we do not execute it in the workarounds steps + // It's not a training step per-se but is part of the setup and is included in the cal step enable + FAPI_INF("%s RP%d latching WR VREF values below", mss::c_str(i_target), i_rp); + + // Latches the VREF's + FAPI_TRY( mss::ddr4::latch_wr_vref_commands_by_rank_pair(i_target, + i_rp, + iv_vrefdq_train_range_override, + iv_vrefdq_train_value_override) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t wr_vref_latch::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // The latch code figures out it's own cycles, so just return 1 + return 1; +} + +/// +/// @brief Sets up and runs the calibration step +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode phy_step::run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + // Execute this cal step + FAPI_INF("%s RP%d running cal step '%s'", mss::c_str(i_target), i_rp, get_name()); + FAPI_TRY(mss::execute_cal_steps_helper( i_target, + i_rp, + iv_init_cal_config, + i_abort_on_error, + calculate_cycles(i_target))); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes the pre-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode wr_lvl::pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> > l_rtt_inst; + + FAPI_DBG("%s Running Pre-WR_LEVEL workaround steps on RP%d", mss::c_str(i_target), i_rp); + // Setup WR_LEVEL specific terminations + // JEDEC spec requires disabling RTT_WR during WR_LEVEL, and enabling equivalent terminations + FAPI_TRY( setup_wr_level_terminations(i_target, i_rp, l_rtt_inst) ); + + if (!l_rtt_inst.empty()) + { + const auto& l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target); + mss::ccs::program<fapi2::TARGET_TYPE_MCBIST, fapi2::TARGET_TYPE_MCA> l_program; + l_program.iv_instructions.insert(l_program.iv_instructions.end(), l_rtt_inst.begin(), l_rtt_inst.end() ); + FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); + l_program.iv_instructions.clear(); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t wr_lvl::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + const uint64_t TWLO_TWLOE = mss::twlo_twloe(i_target); + + // This step runs for approximately (80 + TWLO_TWLOE) x NUM_VALID_SAMPLES x (384/(BIG_STEP + 1) + + // (2 x (BIG_STEP + 1))/(SMALL_STEP + 1)) + 20 memory clock cycles per rank. + + const uint64_t l_wr_lvl_cycles = (80 + TWLO_TWLOE) * WR_LVL_NUM_VALID_SAMPLES * (384 / (WR_LVL_BIG_STEP + 1) + + (2 * (WR_LVL_BIG_STEP + 1)) / (WR_LVL_SMALL_STEP + 1)) + 20; + FAPI_DBG("%s wr_lvl_cycles: %llu(%lluns) (%llu, %llu, %llu, %llu)", + mss::c_str(i_target), + l_wr_lvl_cycles, + mss::cycles_to_ns(i_target, + l_wr_lvl_cycles), + TWLO_TWLOE, WR_LVL_NUM_VALID_SAMPLES, WR_LVL_BIG_STEP, WR_LVL_SMALL_STEP); + + return l_wr_lvl_cycles; +} + +/// +/// @brief Executes the post-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode wr_lvl::post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + std::vector< ccs::instruction_t<fapi2::TARGET_TYPE_MCBIST> > l_rtt_inst; + + FAPI_DBG("%s Running Post-WR_LEVEL workaround steps on RP%d", mss::c_str(i_target), i_rp); + + FAPI_TRY( restore_mainline_terminations(i_target, i_rp, l_rtt_inst) ); + + if (!l_rtt_inst.empty()) + { + const auto& l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target); + mss::ccs::program<fapi2::TARGET_TYPE_MCBIST, fapi2::TARGET_TYPE_MCA> l_program; + l_program.iv_instructions.insert(l_program.iv_instructions.end(), + l_rtt_inst.begin(), + l_rtt_inst.end() ); + FAPI_TRY( mss::ccs::execute(l_mcbist, l_program, i_target) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t initial_pattern_write::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // Not sure how long this should take, so we're gonna use 1 to make sure we get at least one polling loop + return 1; +} + +/// +/// @brief Executes the post-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode dqs_align::post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + + FAPI_DBG("%s Running Post-DQS_ALIGN workaround steps on RP%d", mss::c_str(i_target), i_rp); + + FAPI_TRY(mss::workarounds::dp16::dqs_align::dqs_align_workaround(i_target, i_rp, i_abort_on_error), + "%s Failed to run dqs align workaround on rp %d", mss::c_str(i_target), i_rp); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t dqs_align::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // This step runs for approximately 6 x 600 x 4 DRAM clocks per rank pair. + const uint64_t l_dqs_align_cycles = 6 * 600 * 4; + + FAPI_DBG("%s dqs_align_cycles: %llu(%lluns)", mss::c_str(i_target), l_dqs_align_cycles, mss::cycles_to_ns(i_target, + l_dqs_align_cycles)); + return l_dqs_align_cycles; +} + +/// +/// @brief Executes the pre-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode rdclk_align::pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + FAPI_DBG("%s Running Pre-RDCLK_ALIGN workaround steps on RP%d", mss::c_str(i_target), i_rp); + // Turn off refresh + FAPI_TRY( mss::workarounds::dqs_align::turn_off_refresh(i_target) ); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes the post-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode rdclk_align::post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + FAPI_DBG("%s Running Post-RDCLK_ALIGN workaround steps on RP%d", mss::c_str(i_target), i_rp); + + // Run the red_waterfall workaround for low VDN sensitivity + // Increments the waterfall forward by one + FAPI_TRY( mss::workarounds::dp16::fix_red_waterfall_gate( i_target, i_rp) ); + + // Turn refresh back on + FAPI_TRY( mss::workarounds::dqs_align::turn_on_refresh(i_target) ); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t rdclk_align::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // This step runs for approximately 24 x ((1024/COARSE_CAL_STEP_SIZE + 4 x COARSE_CAL_STEP_SIZE) x 4 + 32) DRAM + // clocks per rank pair + const uint64_t l_rdclk_align_cycles = 24 * ((1024 / COARSE_CAL_STEP_SIZE + 4 * COARSE_CAL_STEP_SIZE) * 4 + 32); + FAPI_DBG("%s rdclk_align_cycles: %llu(%lluns) (%llu)", mss::c_str(i_target), l_rdclk_align_cycles, + mss::cycles_to_ns(i_target, l_rdclk_align_cycles), COARSE_CAL_STEP_SIZE); + return l_rdclk_align_cycles; +} + +/// +/// @brief Executes the pre-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode read_ctr::pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + FAPI_DBG("%s Running Pre-RD_CTR workaround steps on RP%d", mss::c_str(i_target), i_rp); + // Turn off refresh + FAPI_TRY( mss::workarounds::dqs_align::turn_off_refresh(i_target) ); + + // Sets up the RD VREF sense workaround + FAPI_TRY( mss::workarounds::dp16::rd_vref_vref_sense_setup(i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Sets up and runs the calibration step +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode read_ctr::run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + // Blast the VREF config with the proper setting for these cal bits if there were any enable bits set + if (iv_rd_vref) + { + uint16_t l_vref_cal_enable = 0; + + // Blast the VREF_CAL_ENABLE to the registers that control which dp16's to use for rdvref + FAPI_TRY( mss::rdvref_cal_enable(i_target, l_vref_cal_enable) ); + FAPI_TRY( mss::scom_blastah(i_target, dp16Traits<fapi2::TARGET_TYPE_MCA>::RD_VREF_CAL_ENABLE_REG, l_vref_cal_enable) ); + } + + // Now lets set the actual read_vref_config. We want to write/ clear this every time we run so seperate function + FAPI_TRY( setup_read_vref_config1(i_target, iv_rd_ctr, iv_rd_vref), + "%s Failed setting the read_vref_config1", mss::c_str(i_target) ); + + // Now run the actual calibration + FAPI_TRY(phy_step::run(i_target, i_rp, i_abort_on_error)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes the post-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode read_ctr::post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + FAPI_DBG("%s Running Post-RD_CTR workaround steps on RP%d", mss::c_str(i_target), i_rp); + + // Now run the read centering workaround + if(iv_rd_ctr) + { + FAPI_TRY(mss::workarounds::dp16::rd_dq::fix_delay_values(i_target, i_rp), + "%s Failed to run read centering workaround on rp %d", mss::c_str(i_target), i_rp); + } + + // Turn refresh back on + FAPI_TRY( mss::workarounds::dqs_align::turn_on_refresh(i_target) ); + + // Sets up the RD VREF sense workaround + FAPI_TRY( mss::workarounds::dp16::rd_vref_vref_sense_cleanup( i_target ) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t read_ctr::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // This step runs for approximately 6 x (512/COARSE_CAL_STEP_SIZE + 4 x (COARSE_CAL_STEP_SIZE + + // 4 x CONSEQ_PASS)) x 24 DRAM clocks per rank pair. + + const uint64_t l_read_ctr_cycles = 6 * (512 / COARSE_CAL_STEP_SIZE + 4 * (COARSE_CAL_STEP_SIZE + 4 * CONSEQ_PASS)) * 24; + FAPI_DBG("%s read_ctr_cycles %llu(%lluns) (%llu, %llu)", + mss::c_str(i_target), + l_read_ctr_cycles, + mss::cycles_to_ns(i_target, l_read_ctr_cycles), + COARSE_CAL_STEP_SIZE, + CONSEQ_PASS); + + // This calibration step could take up to read centering + RD VREF time, so let's just output that to make the math simpler + return l_read_ctr_cycles + rc::vref_guess_time(i_target); +} + + +/// +/// @brief Sets up and runs the calibration step +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode write_ctr::run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + typedef mss::dp16Traits<fapi2::TARGET_TYPE_MCA> TT; + std::vector<fapi2::buffer<uint64_t>> l_wr_vref_config; + FAPI_TRY( mss::scom_suckah(i_target, TT::WR_VREF_CONFIG0_REG, l_wr_vref_config) ); + + // Loops and sets or clears the 2D VREF bit on all DPs + for(auto& l_data : l_wr_vref_config) + { + // 0: Run only the VREF (2D) write centering algorithm + // 1: Run only the 1D + l_data.writeBit<TT::WR_VREF_CONFIG0_1D_ONLY_SWITCH>(!iv_wr_vref); + } + + FAPI_TRY(mss::scom_blastah(i_target, TT::WR_VREF_CONFIG0_REG, l_wr_vref_config)); + + FAPI_TRY(phy_step::run(i_target, i_rp, i_abort_on_error)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t write_ctr::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // 1000 + (NUM_VALID_SAMPLES * (FW_WR_RD + FW_RD_WR + 16) * + // (1024/(SMALL_STEP +1) + 128/(BIG_STEP +1)) + 2 * (BIG_STEP+1)/(SMALL_STEP+1)) x 24 DRAM + // clocks per rank pair. + constexpr uint64_t WR_CNTR_FW_WR_RD = mss::fw_wr_rd(); + uint8_t l_fw_rd_wr = 0; + uint64_t l_cycles = 1; + + FAPI_TRY( mss::fw_rd_wr(i_target, l_fw_rd_wr) ); + + l_cycles = 1000 + (WR_LVL_NUM_VALID_SAMPLES * (WR_CNTR_FW_WR_RD + l_fw_rd_wr + 16) * + (1024 / (WR_LVL_SMALL_STEP + 1) + 128 / (WR_LVL_BIG_STEP + 1)) + 2 * + (WR_LVL_BIG_STEP + 1) / (WR_LVL_SMALL_STEP + 1)) * 24; + + FAPI_DBG("%s write_ctr_cycles: %lu(%luns) (%u, %u, %u, %u, %u)", + mss::c_str(i_target), + l_cycles, + mss::cycles_to_ns(i_target, l_cycles), + WR_LVL_NUM_VALID_SAMPLES, + WR_CNTR_FW_WR_RD, + l_fw_rd_wr, + WR_LVL_BIG_STEP, + WR_LVL_SMALL_STEP); + + return l_cycles; + +fapi_try_exit: + // We had an error, let's exit + FAPI_ERR("%s had an error and is going to exit", mss::c_str(i_target)); + fapi2::Assert(false); + + // Error case, the return is to make the compiler happy + return l_cycles; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t coarse_wr_rd::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // The run length given here is the maximum run length for this calibration algorithm. + // This step runs for approximately 40 DRAM clocks per rank pair. + constexpr uint64_t COARSE_WR_CYCLES = 40; + + // The run length given here is the maximum run length for this calibration algorithm. + // This step runs for approximately 32 DRAM clocks per rank pair. + constexpr uint64_t COARSE_RD_CYCLES = 32; + + // Total coarse cycles + constexpr uint64_t COARSE_WR_RD_CYCLES = COARSE_WR_CYCLES + COARSE_RD_CYCLES; + + FAPI_DBG("%s coarse_wr_cycles: %llu(%lluns) coarse_rd_cycles %llu(%lluns) coarse wr/rd cycles %llu(%lluns)", + mss::c_str(i_target), + COARSE_WR_CYCLES, + mss::cycles_to_ns(i_target, COARSE_WR_CYCLES), + COARSE_RD_CYCLES, + mss::cycles_to_ns(i_target, COARSE_RD_CYCLES), + COARSE_WR_RD_CYCLES, + mss::cycles_to_ns(i_target, COARSE_WR_RD_CYCLES)); + return COARSE_WR_RD_CYCLES; +} + +/// +/// @brief Executes the pre-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode custom_read_ctr::pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + FAPI_DBG("%s Running Pre-Custom RD CTR workaround steps on RP%d", mss::c_str(i_target), i_rp); + // Turn off refresh + FAPI_TRY( mss::workarounds::dqs_align::turn_off_refresh(i_target) ); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes a cal step with workarounds +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode custom_read_ctr::run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + constexpr bool RUN_RD_CTR = true; + constexpr bool SKIP_RD_VREF = false; + // Now lets set the actual read_vref_config. We want to write/ clear this every time we run so seperate function + FAPI_TRY( setup_read_vref_config1(i_target, RUN_RD_CTR, SKIP_RD_VREF), + "%s Failed setting the read_vref_config1", mss::c_str(i_target) ); + + FAPI_TRY(phy_step::run(i_target, i_rp, i_abort_on_error)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Executes the post-cal step workaround +/// @param[in] i_target - the MCA target on which to operate +/// @param[in] i_rp - the rank pair +/// @param[in] i_abort_on_error - whether or not we are aborting on cal error +/// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode custom_read_ctr::post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const +{ + FAPI_DBG("%s Running Post-Custom RD CTR workaround steps on RP%d", mss::c_str(i_target), i_rp); + // Turn refresh back on + FAPI_TRY( mss::workarounds::dqs_align::turn_on_refresh(i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calculates the number of cycles a given calibration step will take +/// @param[in] i_target - the MCA target on which to operate +/// @return l_cycles - the number of cycles a given calibration step wil take +/// +uint64_t custom_read_ctr::calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const +{ + // This step runs for approximately 6 x (512/COARSE_CAL_STEP_SIZE + 4 x (COARSE_CAL_STEP_SIZE + + // 4 x CONSEQ_PASS)) x 24 DRAM clocks per rank pair. + + const uint64_t l_read_ctr_cycles = 6 * (512 / COARSE_CAL_STEP_SIZE + 4 * (COARSE_CAL_STEP_SIZE + 4 * CONSEQ_PASS)) * 24; + FAPI_DBG("%s read_ctr_cycles %llu(%lluns) (%llu, %llu)", + mss::c_str(i_target), + l_read_ctr_cycles, + mss::cycles_to_ns(i_target, l_read_ctr_cycles), + COARSE_CAL_STEP_SIZE, + CONSEQ_PASS); + + // This calibration step could take up to read centering + RD VREF time, so let's just output that to make the math simpler + return l_read_ctr_cycles; +} + +/// +/// @brief Creates the vector of training steps to loop over +/// @param[in] i_cal_steps - the bit mask of calibration steps +/// @return a vector of the calibration steps to run +/// +std::vector<std::shared_ptr<step>> steps_factory(const fapi2::buffer<uint32_t>& i_cal_steps) +{ + std::vector<std::shared_ptr<step>> l_steps; + + // WR LVL + 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>()); + } + + // INITIAL_PAT_WR + if(i_cal_steps.getBit<mss::cal_steps::INITIAL_PAT_WR>()) + { + FAPI_INF("Initial pattern write is enabled"); + l_steps.push_back(std::make_shared<initial_pattern_write>()); + } + + // DQS_ALIGN + if(i_cal_steps.getBit<mss::cal_steps::DQS_ALIGN>()) + { + FAPI_INF("DQS align is enabled"); + l_steps.push_back(std::make_shared<dqs_align>()); + } + + // RDCLK_ALIGN + if(i_cal_steps.getBit<mss::cal_steps::RDCLK_ALIGN>()) + { + FAPI_INF("RDCLK align is enabled"); + l_steps.push_back(std::make_shared<rdclk_align>()); + } + + // READ_CTR_2D_VREF or READ_CTR + const bool RD_VREF = i_cal_steps.getBit<mss::cal_steps::READ_CTR_2D_VREF>(); + const bool RD_CTR = i_cal_steps.getBit<mss::cal_steps::READ_CTR>(); + + if(RD_VREF || RD_CTR) + { + FAPI_INF("Read centering %s enabled read VREF %s enabled", + RD_CTR ? "is" : "isn't", + RD_VREF ? "is" : "isn't"); + l_steps.push_back(std::make_shared<read_ctr>(RD_VREF, RD_CTR)); + } + + // WR_VREF_LATCH additionally WRITE_CTR_2D_VREF is needed + const bool WR_LATCH = i_cal_steps.getBit<mss::cal_steps::WR_VREF_LATCH>(); + const bool WR_VREF = i_cal_steps.getBit<mss::cal_steps::WRITE_CTR_2D_VREF>(); + const bool WRITE_CTR = i_cal_steps.getBit<mss::cal_steps::WRITE_CTR>(); + + if(WR_LATCH) + { + FAPI_INF("Write VREF latching is enabled %s WR VREF", + WR_VREF ? "with" : "without"); + + l_steps.push_back(std::make_shared<wr_vref_latch>( WR_VREF )); + } + + + // WRITE_CTR_2D_VREF or WRITE_CTR + if(WR_VREF || WRITE_CTR) + { + FAPI_INF("Write centering is enabled %s WR VREF", + WR_VREF ? "with" : "without"); + + l_steps.push_back(std::make_shared<write_ctr>( WR_VREF )); + } + + // COARSE WR/RD + if(i_cal_steps.getBit<mss::cal_steps::COARSE_WR>() || i_cal_steps.getBit<mss::cal_steps::COARSE_RD>()) + { + FAPI_INF("Coarse WR/RD is enabled"); + l_steps.push_back(std::make_shared<coarse_wr_rd>()); + } + + // Training Advanced - aka custom pattern RD CTR + if(i_cal_steps.getBit<mss::cal_steps::TRAINING_ADV>()) + { + FAPI_INF("Custom RD_CTR is enabled"); + l_steps.push_back(std::make_shared<custom_read_ctr>()); + } + + return l_steps; +} + +} // ns training + +} // ns mss 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 ba82528db..24ebc0e71 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 @@ -22,3 +22,680 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file workarounds/mss_training_workarounds.H +/// @brief High level workarounds for training +/// Workarounds are very device specific, so there is no attempt to generalize +/// this code in any way. +/// +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#ifndef MSS_WORKAROUNDS_TRAINING_H +#define MSS_WORKAROUNDS_TRAINING_H + +#include <fapi2.H> +#include <lib/eff_config/timing.H> +#include <lib/phy/read_cntrl.H> +#include <lib/dimm/ddr4/latch_wr_vref.H> + +namespace mss +{ + +namespace training +{ + +/// +/// @brief Training step class - contains all information to run a calibration step +/// @note step is an abstract class +/// +class step +{ + public: + // Delete base constructor + step() = delete; + + /// + /// @brief Default virtual destructor + /// + virtual ~step() = default; + + /// + /// @brief Constructor for step class + /// @param[in] i_name - calibration step name + /// + step( const char* i_name) : + iv_name(i_name) + {} + + /// + /// @brief Executes the pre-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + virtual fapi2::ReturnCode pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const + { + FAPI_INF("%s RP%d cal step '%s' has no pre-cal step workaround.", mss::c_str(i_target), i_rp, iv_name); + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Sets up and runs the calibration step + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + virtual fapi2::ReturnCode run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const = 0; + + /// + /// @brief Executes the post-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + virtual fapi2::ReturnCode post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const + { + FAPI_INF("%s RP%d cal step '%s' has no post-cal step workaround.", mss::c_str(i_target), i_rp, iv_name); + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Executes a cal step with workarounds + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @return l_cycles - the number of cycles a given calibration step wil take + /// + virtual uint64_t calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const = 0; + + /// + /// @brief Gets the name of this calibration step + /// @return name of this calibration step + /// + const char* get_name() const + { + return iv_name; + } + + private: + // Contains the human readable name for this calibration step + const char* iv_name; +}; + +/// +/// @brief Latches the WR VREF data into the hardware +/// +class wr_vref_latch : public step +{ + public: + // Delete base constructor + wr_vref_latch() = delete; + + /// + /// @brief Default destructor + /// + ~wr_vref_latch() override = default; + + /// + /// @brief Constructor for step class + /// @param[in] i_wr_vref - true if WR VREF will be run during the calibration + /// + wr_vref_latch( const bool i_wr_vref ) : + step("WR_VREF_LATCH"), + iv_wr_vref(i_wr_vref), + iv_vrefdq_train_range_override(mss::ddr4::USE_DEFAULT_WR_VREF_SETTINGS), + iv_vrefdq_train_value_override(mss::ddr4::USE_DEFAULT_WR_VREF_SETTINGS) + {} + + /// + /// @brief Executes the pre-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Sets up and runs the calibration step + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; + + /// + /// @brief Getter for WR VREF + /// @return bool iv_wr_vref + /// + bool get_wr_vref() const + { + return iv_wr_vref; + } + + /// + /// @brief Getter for WR VREF + /// @return uint64_t iv_vrefdq_train_range_override + /// + uint64_t get_vrefdq_range() const + { + return iv_vrefdq_train_range_override; + } + + /// + /// @brief Getter for WR VREF + /// @return uint64_t iv_vrefdq_train_value_override + /// + uint64_t get_vrefdq_value() const + { + return iv_vrefdq_train_value_override; + } + + private: + // Notes whether the WR VREF calibration workaround needs to be run or not + bool iv_wr_vref; + + // WR VREF values to latch + // Note: these are mutable as they might need to be modified for a workaround related to Nimbus DD1 WR VREF HW calibration + mutable uint8_t iv_vrefdq_train_range_override; + mutable uint8_t iv_vrefdq_train_value_override; +}; + +/// +/// @brief A PHY hardware accelerated calibration step +/// @note phy_step is an abstract class +/// +class phy_step : public step +{ + public: + // Delete base constructor + phy_step() = delete; + + /// + /// @brief Default destructor + /// + virtual ~phy_step() = default; + + /// + /// @brief Constructor for step class + /// @param[in] i_init_cal_config - calibration step name + /// @param[in] i_name - calibration step name + /// + phy_step( const fapi2::buffer<uint64_t> i_init_cal_config, const char* i_name) : + step(i_name), + iv_init_cal_config(i_init_cal_config) + {} + + /// + /// @brief Sets up and runs the calibration step + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + virtual fapi2::ReturnCode run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @return l_cycles - the number of cycles a given calibration step wil take + /// + virtual uint64_t calculate_cycles( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) const = 0; + + /// + /// @brief Gets the init cal config register's starting + /// @return fapi2::buffer<uint64_t> iv_init_cal_config - init cal config's starting value + /// + const fapi2::buffer<uint64_t> get_init_cal_config() const + { + return iv_init_cal_config; + } + + private: + // Contains all of the base information for the init cal configuration register + fapi2::buffer<uint64_t> iv_init_cal_config; +}; + +/// +/// @brief Write leveling calibration step class +/// +class wr_lvl : public phy_step +{ + public: + /// + /// @brief Base constructor + /// + wr_lvl() : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_WR_LEVEL>(), "WR_LVL") + {} + + /// + /// @brief Default destructor + /// + ~wr_lvl() override = default; + + /// + /// @brief Executes the pre-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Executes the post-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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; +}; + +/// +/// @brief Initial pattern write +/// +class initial_pattern_write : public phy_step +{ + public: + /// + /// @brief Base constructor + /// + initial_pattern_write() : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_INITIAL_PAT_WR>(), + "INITIAL_PATTERN_WRITE") + {} + + /// + /// @brief Default destructor + /// + ~initial_pattern_write() override = default; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; +}; + +/// +/// @brief DQS align +/// +class dqs_align : public phy_step +{ + public: + /// + /// @brief Base constructor + /// + dqs_align() : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_DQS_ALIGN>(), + "DQS_ALIGN") + {} + + /// + /// @brief Default destructor + /// + ~dqs_align() override = default; + + /// + /// @brief Executes the post-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; +}; + +/// +/// @brief Read clock align +/// +class rdclk_align : public phy_step +{ + public: + /// + /// @brief Base constructor + /// + rdclk_align() : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_RDCLK_ALIGN>(), + "RDCLK_ALIGN") + {} + + /// + /// @brief Default destructor + /// + ~rdclk_align() override = default; + + /// + /// @brief Executes the pre-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Executes the post-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; +}; + +/// +/// @brief Read centering (and potentially RD VREF) +/// +class read_ctr : public phy_step +{ + public: + // No default constructor + read_ctr() = delete; + + /// + /// @brief Base constructor + /// @param[in] i_rd_vref - true IFF RD VREF is enabled + /// @param[in] i_rd_ctr - true IFF RD CTR is enabled + /// + read_ctr(const bool i_rd_vref, const bool i_rd_ctr) : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_READ_CTR>(), + "READ_CTR"), + iv_rd_vref(i_rd_vref), + iv_rd_ctr(i_rd_ctr) + {} + + /// + /// @brief Default destructor + /// + ~read_ctr() override = default; + + /// + /// @brief Executes the pre-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Sets up and runs the calibration step + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Executes the post-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; + + /// + /// @brief Getter for RD VREF + /// @return bool iv_rd_vref + /// + bool get_rd_vref() const + { + return iv_rd_vref; + } + + /// + /// @brief Getter for RD centering + /// @return bool iv_rd_ctr + /// + bool get_rd_ctr() const + { + return iv_rd_ctr; + } + + private: + bool iv_rd_vref; + bool iv_rd_ctr; +}; + +/// +/// @brief Write centering (and potentially WR VREF) +/// +class write_ctr : public phy_step +{ + public: + // No default constructor + write_ctr() = delete; + + /// + /// @brief Base constructor + /// @param[in] i_wr_vref - true IFF WR VREF is enabled + /// + write_ctr(const bool i_wr_vref) : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_WRITE_CTR>(), + "write_ctr"), + iv_wr_vref(i_wr_vref) + {} + + /// + /// @brief Default destructor + /// + ~write_ctr() override = default; + + /// + /// @brief Sets up and runs the calibration step + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; + + /// + /// @brief Getter for WR VREF + /// @return bool iv_wr_vref + /// + bool get_wr_vref() const + { + return iv_wr_vref; + } + + private: + bool iv_wr_vref; +}; + +/// +/// @brief Coarse WR/RD calibration +/// +class coarse_wr_rd : public phy_step +{ + public: + /// + /// @brief Base constructor + /// + static constexpr uint64_t COARSE_WR_RD_LEN = 2; + coarse_wr_rd() : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_INITIAL_COARSE_WR, COARSE_WR_RD_LEN>(), + "COARSE_WR/RD") + {} + + /// + /// @brief Default destructor + /// + ~coarse_wr_rd() override = default; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; +}; + +/// +/// @brief Custom read centering - can include initial pattern write +/// +class custom_read_ctr : public phy_step +{ + public: + /// + /// @brief Base constructor + /// + custom_read_ctr() : + phy_step( fapi2::buffer<uint64_t>().setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_CUSTOM_RD>(), + "CUSTOM_READ_CTR") + {} + + /// + /// @brief Default destructor + /// + ~custom_read_ctr() override = default; + + /// + /// @brief Sets up and runs the calibration step + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode run( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Executes the pre-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode pre_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Executes the post-cal step workaround + /// @param[in] i_target - the MCA target on which to operate + /// @param[in] i_rp - the rank pair + /// @param[in] i_abort_on_error - whether or not we are aborting on cal error + /// @return fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ok + /// + fapi2::ReturnCode post_workaround( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_rp, + const uint8_t i_abort_on_error ) const override; + + /// + /// @brief Calculates the number of cycles a given calibration step will take + /// @param[in] i_target - the MCA target on which to operate + /// @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 override; +}; + +/// +/// @brief Creates the vector of training steps to loop over +/// @param[in] i_cal_steps - the bit mask of calibration steps +/// @return a vector of the calibration steps to run +/// +std::vector<std::shared_ptr<step>> steps_factory(const fapi2::buffer<uint32_t>& i_cal_steps); + +} // ns training + +} // ns mss + +#endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H index 797588274..9f71d1655 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.H @@ -283,6 +283,21 @@ inline void set_trfc_cycles( fapi2::buffer<uint64_t>& io_data, const uint64_t i_ } /// +/// @brief Get SEQ_MEM_TIMING_PARAM0_TRFC_CYCLES +/// @tparam T fapi2 Target Type - derived +/// @tparam TT traits type defaults to seqTraits<T> +/// @param[in] i_data the value of the register +/// @param[out] o_value value representing trfc value in cycles +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = seqTraits<T> > +inline void get_trfc_cycles( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_value ) +{ + i_data.extractToRight<TT::TRFC_CYCLES, TT::TRFC_CYCLES_LEN>(o_value); + FAPI_DBG("seq_timing0 trfc_cycles: 0x%llx", o_value); +} + +/// /// @brief Read SEQ_MEM_TIMING_PARAM1 /// @tparam T fapi2 Target Type - derived /// @tparam TT traits type defaults to seqTraits<T> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.C index 7e2f52ae9..4b877b47f 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.C @@ -26,7 +26,7 @@ /// /// @file workarounds/adr32s_workarounds.C /// @brief Workarounds for the ADR32s logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.H index 713a9505f..a4e02cafe 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/adr32s_workarounds.H @@ -26,7 +26,7 @@ /// /// @file workarounds/adr32s_workarounds.H /// @brief Workarounds for the ADR32s logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C index 98e6a4479..1ed664574 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C @@ -26,7 +26,7 @@ /// /// @file workarounds/dp16.C /// @brief Workarounds for the DP16 logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> @@ -45,6 +45,7 @@ #include <lib/phy/dp16.H> #include <lib/phy/ddr_phy.H> #include <lib/phy/phy_cntrl.H> +#include <lib/phy/mss_training.H> #include <lib/dimm/rank.H> #include <lib/utils/bit_count.H> #include <lib/fir/check.H> @@ -190,7 +191,6 @@ fapi2::ReturnCode post_training_workarounds( const fapi2::Target<fapi2::TARGET_T i_cal_steps_enabled.getBit<mss::cal_steps::COARSE_WR>()) { FAPI_TRY( mss::workarounds::dp16::modify_calibration_results( i_target ) ); - FAPI_TRY( mss::workarounds::dp16::rd_vref_vref_sense_cleanup( i_target ) ); } // Returns success, as we might not have run these workarounds, depending upon cal step enable @@ -555,6 +555,9 @@ fapi2::ReturnCode dqs_align_workaround(const fapi2::Target<fapi2::TARGET_TYPE_MC // Boolean to keep track of if a fail was calibration related, or scom related bool l_cal_fail = false; + // Create a DQS align calibration step, as it might need to be used in the loop below + const auto l_dqs_align_step = mss::training::dqs_align(); + FAPI_TRY( eff_dram_width( i_target, l_dram_width) ); l_is_x8 = ((l_dram_width[0] == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) || @@ -590,11 +593,7 @@ fapi2::ReturnCode dqs_align_workaround(const fapi2::Target<fapi2::TARGET_TYPE_MC FAPI_TRY(mss::workarounds::dp16::dqs_align::reset_disables(i_target, i_rp)); // Hit calibration one more time - { - const auto l_dqs_align_cal = fapi2::buffer<uint32_t>().setBit<mss::cal_steps::DQS_ALIGN>(); - - FAPI_TRY(mss::execute_cal_steps_helper( i_target, i_rp, l_dqs_align_cal, i_abort_on_error)); - } + FAPI_TRY(l_dqs_align_step.execute(i_target, i_rp, i_abort_on_error)); // Get the current passing states // We override any states that were passing previously and are still passing 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 586d5419d..fd5cdb7e6 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 @@ -26,7 +26,7 @@ /// /// @file workarounds/dp16.H /// @brief Workarounds for the DP16 logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.C index 3a1c039a4..27202d57a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.C @@ -26,7 +26,7 @@ /// /// @file workarounds/mca_workarounds.C /// @brief Workarounds for the MCA logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.H index 82ab4db42..56e98e72c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mca_workarounds.H @@ -26,7 +26,7 @@ /// /// @file workarounds/mca_workarounds.H /// @brief Workarounds for the MCA logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C index de06e36a4..3b6009f42 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.C @@ -26,7 +26,7 @@ /// /// @file mcbist_workarounds.C /// @brief Workarounds for the MCBISt engine -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H index e9d978be3..1f1aa5dbe 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/mcbist_workarounds.H @@ -26,7 +26,7 @@ /// /// @file mcbist_workarounds.H /// @brief Workarounds for the MCBISt engine -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.C index 383dc5114..8ec8165e1 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.C @@ -26,7 +26,7 @@ /// /// @file workarounds/seq_workarounds.C /// @brief Workarounds for the SEQ logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.H index 6ff7fc925..08ef94879 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/seq_workarounds.H @@ -26,7 +26,7 @@ /// /// @file workarounds/seq_workarounds.H /// @brief Workarounds for the SEQ logic blocks -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com> diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C index e14ef0964..b9426fe94 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.C @@ -26,7 +26,7 @@ /// /// @file wr_vref_workarounds.C /// @brief Workarounds for the WR VREF calibration logic -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> @@ -52,21 +52,22 @@ namespace wr_vref /// @brief Executes WR VREF workarounds /// @param[in] i_target the fapi2 target of the port /// @param[in] i_rp - the rank pair to execute the override on -/// @param[in] i_cal_steps_enabled - cal steps to exectue, used to see if WR VREF needs to be exectued +/// @param[in] i_wr_vref_enabled - true if WR VREF is enabled /// @param[out] o_vrefdq_train_range - training range value /// @param[out] o_vrefdq_train_value - training value value /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok /// +// TODO RTC:166422 update training code to set cal step enable and consume it everywhere locally fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, const uint64_t i_rp, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled, + const bool i_wr_vref_enabled, uint8_t& o_vrefdq_train_range, uint8_t& o_vrefdq_train_value ) { // Skip running WR VREF workarounds if: // 1) the chip does not need to have the workaround run // 2) WR VREF has not been requested in the calibration steps - if ((! mss::chip_ec_feature_mss_wr_vref(i_target)) || (!i_cal_steps_enabled.getBit<WRITE_CTR_2D_VREF>())) + if ((! mss::chip_ec_feature_mss_wr_vref(i_target)) || (!i_wr_vref_enabled)) { return fapi2::FAPI2_RC_SUCCESS; } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H index 4350a8da7..82761e08d 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/wr_vref_workarounds.H @@ -26,7 +26,7 @@ /// /// @file wr_vref_workarounds.H /// @brief Workarounds for the WR VREF calibration logic -/// Workarounds are very deivce specific, so there is no attempt to generalize +/// Workarounds are very device specific, so there is no attempt to generalize /// this code in any way. /// // *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> @@ -53,7 +53,7 @@ namespace wr_vref /// @brief Executes WR VREF workarounds /// @param[in] i_target the fapi2 target of the port /// @param[in] i_rp - the rank pair to execute the override on -/// @param[in] i_cal_steps_enabled - cal steps to exectue, used to see if WR VREF needs to be exectued +/// @param[in] i_wr_vref_enabled - true if WR VREF is enabled /// @param[out] o_vrefdq_train_range - training range value /// @param[out] o_vrefdq_train_value - training value value /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok @@ -61,7 +61,7 @@ namespace wr_vref // TODO RTC:166422 update training code to set cal step enable and consume it everywhere locally fapi2::ReturnCode execute( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, const uint64_t i_rp, - const fapi2::buffer<uint32_t>& i_cal_steps_enabled, + const bool i_wr_vref_enabled, uint8_t& o_vrefdq_train_range, uint8_t& o_vrefdq_train_value ); diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C index fdd8b7ce0..c354bc86b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training.C @@ -42,6 +42,7 @@ #include <lib/shared/mss_const.H> #include <lib/workarounds/dp16_workarounds.H> #include <lib/workarounds/dqs_align_workarounds.H> +#include <lib/phy/mss_training.H> #include <lib/fir/unmask.H> #include <lib/dimm/ddr4/zqcal.H> @@ -61,6 +62,7 @@ extern "C" const uint32_t i_special_training, const uint8_t i_abort_on_error) { + // Keep track of the last error seen by a port fapi2::ReturnCode l_port_error ( fapi2::FAPI2_RC_SUCCESS ); @@ -177,7 +179,11 @@ extern "C" bool l_cal_fail = false; FAPI_INF("Execute cal on rp %d %s", rp, mss::c_str(p)); - FAPI_TRY( mss::setup_and_execute_cal(p, rp, l_cal_steps_enabled, l_cal_abort_on_error) ); + for(const auto& l_step : mss::training::steps_factory(l_cal_steps_enabled)) + { + FAPI_TRY( l_step->execute( p, rp, l_cal_abort_on_error) ); + } + FAPI_TRY( mss::find_and_log_cal_errors(p, rp, l_cal_abort_on_error, l_cal_fail, l_fails) ); }// rank pairs diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training_adv.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training_adv.C index 35ccf81fb..0a33fe947 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training_adv.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_draminit_training_adv.C @@ -42,6 +42,7 @@ #include <lib/phy/dp16.H> #include <lib/phy/seq.H> #include <lib/phy/ddr_phy.H> +#include <lib/phy/mss_training.H> using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_MCA; @@ -88,6 +89,7 @@ extern "C" for( const auto& p : mss::find_targets<TARGET_TYPE_MCA>(i_target)) { fapi2::buffer<uint32_t> l_cal_steps_enabled; + std::vector<std::shared_ptr<mss::training::step>> l_steps; FAPI_TRY( mss::cal_step_enable(p, l_cal_steps_enabled), "Error in p9_mss_draminit_training %s", mss::c_str(i_target) ); if (!l_cal_steps_enabled.getBit<mss::TRAINING_ADV>()) @@ -103,6 +105,9 @@ extern "C" l_cal_steps_enabled = 0; l_cal_steps_enabled.setBit<mss::INITIAL_PAT_WR>().setBit<mss::TRAINING_ADV>(); + // Gets the training steps to calibrate + l_steps = mss::training::steps_factory(l_cal_steps_enabled); + // Keep track of the last error seen by a rank pair fapi2::ReturnCode l_rank_pair_error(fapi2::FAPI2_RC_SUCCESS); @@ -138,7 +143,13 @@ extern "C" FAPI_TRY( l_original_settings.save() ); std::vector<fapi2::ReturnCode> l_fails_on_rp; - FAPI_TRY( mss::setup_and_execute_cal(p, rp, l_cal_steps_enabled, l_cal_abort_on_error) ); + + // Loop through all of the steps (should just be initial pattern write and custom read centering) + for(const auto l_step : l_steps) + { + FAPI_TRY( l_step->execute(p, rp, l_cal_abort_on_error) ); + } + FAPI_TRY( mss::find_and_log_cal_errors(p, rp, l_cal_abort_on_error, l_cal_fail, l_fails_on_rp) ); // If we got a fail, let's ignore the previous fails and run backup pattern @@ -164,7 +175,12 @@ extern "C" FAPI_TRY( mss::seq::setup_rd_wr_data( p, l_backup) ); // Rerun the training for this rp - FAPI_TRY( mss::setup_and_execute_cal(p, rp, l_cal_steps_enabled, l_cal_abort_on_error) ); + // Loop through all of the steps (should just be initial pattern write and custom read centering) + for(const auto l_step : l_steps) + { + FAPI_TRY( l_step->execute(p, rp, l_cal_abort_on_error) ); + } + FAPI_TRY( mss::find_and_log_cal_errors(p, rp, l_cal_abort_on_error, l_cal_fail, l_fails_on_rp) ); // If we got fails from the backup pattern, restore the pre-adv training settings for this rank pair |