diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2017-01-23 10:25:55 -0600 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2017-01-30 11:40:56 -0500 |
commit | ef02e47839d9c312606cd7b51be614ec695d76ba (patch) | |
tree | eeb83dd18200717156386a29e3fbee07767476ef /src/import/chips/p9 | |
parent | 3933a5cbfc15fc4184b4c1045e558da232a83e5b (diff) | |
download | talos-hostboot-ef02e47839d9c312606cd7b51be614ec695d76ba.tar.gz talos-hostboot-ef02e47839d9c312606cd7b51be614ec695d76ba.zip |
Added periodic cal fix - fixes bad delays
Change-Id: I8c55c2947dd85cc9ada45aaa9225ce641633f259
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35239
Reviewed-by: Brian R. Silver <bsilver@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com>
Dev-Ready: STEPHEN GLANCY <sglancy@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Matt K. Light <mklight@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35335
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9')
9 files changed, 348 insertions, 2 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H index ee9205500..87e3e52c9 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors_manual.H @@ -31,7 +31,7 @@ /// a work-around they'd be burdened with updating this file. /// // *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com> -// *HWP HWP Backup: Steven Glancy <sglancy@usi.ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: Memory @@ -253,6 +253,31 @@ fapi_try_exit: return false; } +/// +/// @brief ATTR_CHIP_EC_FEATURE_MSS_BLUE_WATERFALL_ADJUST getter +/// @tparam T the fapi2 target type of the target +/// @param[in] const ref to the target +/// @return bool true iff feature is enabled +/// +template< fapi2::TargetType T > +inline bool chip_ec_feature_blue_waterfall_adjust(const fapi2::Target<T>& i_target) +{ + const auto l_chip = mss::find_target<fapi2::TARGET_TYPE_PROC_CHIP>(i_target); + uint8_t l_value = 0; + uint8_t l_do_value = 0; + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_MSS_BLUE_WATERFALL_ADJUST, l_chip, l_value) ); + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_DO_BLUE_WATERFALL_ADJUST, l_chip, l_do_value) ); + + return (l_value != 0) && (l_do_value == fapi2::ENUM_ATTR_DO_BLUE_WATERFALL_ADJUST_YES); + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_CHIP_EC_FEATURE_MSS_WR_VREF or ATTR_DO_MSS_WR_VREF: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + fapi2::Assert(false); + return false; +} + } // close mss namespace #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C index fab3712cd..968944ddc 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C @@ -468,6 +468,10 @@ const std::vector< std::vector<std::pair<uint64_t, uint64_t>> > dp16Traits<TARGE }, }; +// we need these declarations here in order for the linker to see the definitions +constexpr const uint64_t dp16Traits<fapi2::TARGET_TYPE_MCA>::GATE_DELAY_BIT_POS[]; +constexpr const uint64_t dp16Traits<fapi2::TARGET_TYPE_MCA>::BLUE_WATERFALL_BIT_POS[]; + /// /// @brief Given a RD_VREF value, create a PHY 'standard' bit field for that percentage. /// @tparam T fapi2 Target Type - derived diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H index 9fb1b1ae3..597d5047e 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H @@ -123,6 +123,9 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA> // Maximum number of DRAM's per DP static constexpr uint64_t MAX_DRAM_PER_DP = 4; + // Number of quads per DP16 + static constexpr uint64_t NUM_QUAD_PER_DP16 = 4; + // Number of instances of the DLL per DP16. Used for checking parameters, the rest of the // code assumes 2 DLL per DP16. There are no DLL in Centaur so we don't need to worry about // any of this for some time. @@ -164,7 +167,7 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA> static const std::vector<std::vector<std::pair<uint64_t, uint64_t>>> BIT_DISABLE_REG; - //WR VREF registers + // WR VREF registers static const std::vector< uint64_t > WR_VREF_CONFIG0_REG; static const std::vector< uint64_t > WR_VREF_CONFIG1_REG; static const std::vector< uint64_t > WR_VREF_STATUS0_REG; @@ -176,6 +179,22 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA> static const std::vector< std::pair<uint64_t, uint64_t> > WR_VREF_VALUE_RP2_REG; static const std::vector< std::pair<uint64_t, uint64_t> > WR_VREF_VALUE_RP3_REG; + // Definitions of the gate delay and waterfall bits' locations + constexpr static const uint64_t GATE_DELAY_BIT_POS[NUM_QUAD_PER_DP16] = + { + MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_0_01_N0, + MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_0_01_N1, + MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_0_01_N2, + MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_0_01_N3, + }; + constexpr static const uint64_t BLUE_WATERFALL_BIT_POS[NUM_QUAD_PER_DP16] = + { + MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_0_01_RDCLK_SELECT0, + MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_0_01_RDCLK_SELECT1, + MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_0_01_RDCLK_SELECT2, + MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_0_01_RDCLK_SELECT3, + }; + enum { DLL_CNTL_INIT_RXDLL_CAL_RESET = MCA_DDRPHY_DP16_DLL_CNTL0_P0_0_01_INIT_RXDLL_CAL_RESET, @@ -224,6 +243,10 @@ class dp16Traits<fapi2::TARGET_TYPE_MCA> IO_TX_PFET_TERM_EN_P_WR = MCA_DDRPHY_DP16_IO_TX_PFET_TERM_P0_0_01_EN_P_WR, IO_TX_PFET_TERM_EN_P_WR_LEN = MCA_DDRPHY_DP16_IO_TX_PFET_TERM_P0_0_01_EN_P_WR_LEN, + GATE_DELAY_LEN = MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_0_01_N0_LEN, + // Both blue and red waterfalls are the same number of bits + WATERFALL_LEN = MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_0_01_RDCLK_SELECT0_LEN, + //////////////////////////////////////// // WR VREF register field information // //////////////////////////////////////// @@ -1773,6 +1796,74 @@ template< fapi2::TargetType T, typename TT = dp16Traits<T> > fapi2::ReturnCode write_force_fifo_capture( const fapi2::Target<T>& i_target, const mss::states i_state); +/// +/// @brief Get the blue waterfall for the given quad +/// @tparam uint64_t QUAD - which quad to access +/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCA +/// @tparam TT traits type defaults to dp16Traits<T> +/// @param[in] i_data the value of the register +/// @return value of the blue waterfall +/// +template< uint64_t QUAD, fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> > +inline uint64_t get_blue_waterfall( const fapi2::buffer<uint64_t>& i_data ) +{ + + static_assert(QUAD < TT::NUM_QUAD_PER_DP16, "Inserted quad value is not less than the maximum value"); + uint64_t l_waterfall = 0; + i_data.extractToRight<TT::BLUE_WATERFALL_BIT_POS[QUAD], TT::WATERFALL_LEN>(l_waterfall); + return l_waterfall; +} + +/// +/// @brief Get the gate delay for the given quad +/// @tparam uint64_t QUAD - which quad to access +/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCA +/// @tparam TT traits type defaults to dp16Traits<T> +/// @param[in] i_data the value of the register +/// @return value of the gate delay +/// +template< uint64_t QUAD, fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> > +inline uint64_t get_gate_delay( const fapi2::buffer<uint64_t>& i_data ) +{ + + static_assert(QUAD < TT::NUM_QUAD_PER_DP16, "Inserted quad value is not less than the maximum value"); + uint64_t l_gate_delay = 0; + i_data.extractToRight<TT::GATE_DELAY_BIT_POS[QUAD], TT::GATE_DELAY_LEN>(l_gate_delay); + return l_gate_delay; +} + +/// +/// @brief Set the blue waterfall for the given quad +/// @tparam uint64_t QUAD - which quad to access +/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCA +/// @tparam TT traits type defaults to dp16Traits<T> +/// @param[in,out] io_data the value of the register +/// @param[in] value of the blue waterfall +/// +template< uint64_t QUAD, fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> > +inline void set_blue_waterfall( fapi2::buffer<uint64_t>& io_data, const uint64_t i_waterfall ) +{ + + static_assert(QUAD < TT::NUM_QUAD_PER_DP16, "QUAD value is not less than the maximum value"); + io_data.insertFromRight<TT::BLUE_WATERFALL_BIT_POS[QUAD], TT::WATERFALL_LEN>(i_waterfall); +} + +/// +/// @brief Set the gate delay for the given quad +/// @tparam uint64_t QUAD - which quad to access +/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCA +/// @tparam TT traits type defaults to dp16Traits<T> +/// @param[in,out] io_data the value of the register +/// @param[in] value of the gate delay +/// +template< uint64_t QUAD, fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> > +inline void set_gate_delay( fapi2::buffer<uint64_t>& io_data, const uint64_t i_gate_delay ) +{ + + static_assert(QUAD < TT::NUM_QUAD_PER_DP16, "QUAD value is not less than the maximum value"); + io_data.insertFromRight<TT::GATE_DELAY_BIT_POS[QUAD], TT::GATE_DELAY_LEN>(i_gate_delay); +} + } // close namespace dp16 } // close namespace mss 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 67a152547..78ca353a7 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 @@ -192,6 +192,128 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Fixes blue waterfall values in a port +/// @param[in] i_target - the target to operate on +/// @param[in] i_always_run - ignores the attribute and always run - default = false +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode fix_blue_waterfall_gate( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const bool i_always_run ) +{ + // Checks if the workaround needs to be run + const bool l_attr_value = mss::chip_ec_feature_blue_waterfall_adjust(i_target); + + if(!l_attr_value && !i_always_run) + { + FAPI_DBG("Skipping running fix_blue_waterfall_gate i_always_run %s attr %s", i_always_run ? "true" : "false", + l_attr_value ? "true" : "false" ); + return fapi2::FAPI2_RC_SUCCESS; + } + + // Loops through the first 4 DP's as the last DP is a DP08 so we only need to do 2 quads + // TK update to hit all rank pairs + const std::vector<std::vector<std::pair<uint64_t, uint64_t>>> l_dp16_registers = + { + { + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_0, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_0}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_1, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_1}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_2, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_2}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_3, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_3}, + }, + { + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_0, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP1_P0_0}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_1, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP1_P0_1}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_2, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP1_P0_2}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_3, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP1_P0_3}, + }, + { + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_0, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP2_P0_0}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_1, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP2_P0_1}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_2, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP2_P0_2}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_3, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP2_P0_3}, + }, + { + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_0, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP3_P0_0}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_1, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP3_P0_1}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_2, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP3_P0_2}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_3, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP3_P0_3}, + }, + }; + const std::vector<std::pair<uint64_t, uint64_t>> l_dp08_registers = + { + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR0_P0_4, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP0_P0_4}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR1_P0_4, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP1_P0_4}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR2_P0_4, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP2_P0_4}, + {MCA_DDRPHY_DP16_DQS_RD_PHASE_SELECT_RANK_PAIR3_P0_4, MCA_DDRPHY_DP16_DQS_GATE_DELAY_RP3_P0_4}, + }; + + // Gets the number of primary ranks to loop through + std::vector<uint64_t> l_primary_ranks; + FAPI_TRY(mss::rank::primary_ranks(i_target, l_primary_ranks)); + + // Loops through all configured rank pairs + for(uint64_t l_rp = 0; l_rp < l_primary_ranks.size(); ++l_rp) + { + // Loops through all DP16s + for(const auto& l_reg : l_dp16_registers[l_rp]) + { + fapi2::buffer<uint64_t> l_waterfall; + fapi2::buffer<uint64_t> l_gate_delay; + + // Getscoms + FAPI_TRY(mss::getScom(i_target, l_reg.first, l_waterfall), "Failed to getScom from 0x%016lx", l_reg.first); + FAPI_TRY(mss::getScom(i_target, l_reg.second, l_gate_delay), "Failed to getScom from 0x%016lx", l_reg.second); + + // Updates the data for all quads + update_blue_waterfall_gate_delay_for_quad<0>(l_waterfall, l_gate_delay); + update_blue_waterfall_gate_delay_for_quad<1>(l_waterfall, l_gate_delay); + update_blue_waterfall_gate_delay_for_quad<2>(l_waterfall, l_gate_delay); + update_blue_waterfall_gate_delay_for_quad<3>(l_waterfall, l_gate_delay); + + // Putscoms + FAPI_TRY(mss::putScom(i_target, l_reg.first, l_waterfall), "Failed to putScom to 0x%016lx", l_reg.first); + FAPI_TRY(mss::putScom(i_target, l_reg.second, l_gate_delay), "Failed to putScom to 0x%016lx", l_reg.second); + } + + // Now for the odd man out - the DP08, as it only has two quads. + // Note: We are not modifying the non-existant quads, as changing values in the non-existant DP08 has caused FIRs + { + fapi2::buffer<uint64_t> l_waterfall; + fapi2::buffer<uint64_t> l_gate_delay; + + // Getscoms + FAPI_TRY(mss::getScom(i_target, l_dp08_registers[l_rp].first, l_waterfall), "Failed to getScom from 0x%016lx", + l_dp08_registers[l_rp].first); + FAPI_TRY(mss::getScom(i_target, l_dp08_registers[l_rp].second, l_gate_delay), "Failed to getScom from 0x%016lx", + l_dp08_registers[l_rp].second); + + // Updates the data for all quads + update_blue_waterfall_gate_delay_for_quad<0>(l_waterfall, l_gate_delay); + update_blue_waterfall_gate_delay_for_quad<1>(l_waterfall, l_gate_delay); + + // Putscoms + FAPI_TRY(mss::putScom(i_target, l_dp08_registers[l_rp].first, l_waterfall), "Failed to putScom to 0x%016lx", + l_dp08_registers[l_rp].first); + FAPI_TRY(mss::putScom(i_target, l_dp08_registers[l_rp].second, l_gate_delay), "Failed to putScom to 0x%016lx", + l_dp08_registers[l_rp].second); + } + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Modifies HW calibration results based upon workarounds +/// @param[in] i_target - the target to operate on +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode modify_calibration_results( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ) +{ + return fix_blue_waterfall_gate( i_target ); +} + namespace wr_vref { 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 c7fc99d96..25e6efc97 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 @@ -42,6 +42,7 @@ #include <p9_mc_scom_addresses.H> #include <p9_mc_scom_addresses_fld.H> #include <mss_attribute_accessors.H> +#include <lib/phy/dp16.H> namespace mss { @@ -185,6 +186,72 @@ fapi_try_exit: /// fapi2::ReturnCode after_phy_reset( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target ); +/// +/// @brief Updates gate delay and blue waterfall (aka RDCLK phase select) values based upon blue waterfall values +/// @param[in,out] io_blue_waterfall - the blue waterfall value +/// @param[in,out] io_gate_delay - the gate delay value +/// +inline void update_blue_waterfall_gate_delay(uint64_t& io_blue_waterfall, uint64_t& io_gate_delay) +{ + // The PHY should never have a blue waterfall value of a 0 - if so, change it to a 3, and decrease one off the gate delay + // The blue waterfall is a quarter clock cycle delay - the current thinking is that a value of a 0 is a value of a 4 + // In this case the delay was large enough, so that a value of a 3 rolled over to another clock cycle. + // The value of a 0 is considered to be incorrect but can be passable, as the gate delay calibrates in an extra cycle of delay + // So, if there is a 0 value in the blue waterfall, change it to the max, a 3, and subtract one off the gate delay to have correct timing + constexpr uint64_t BW_INCORRECT = 0; + constexpr uint64_t BW_MAX = 3; + + // Check if a correction is needed + if(io_blue_waterfall == BW_INCORRECT) + { + io_blue_waterfall = BW_MAX; + // Does a check to make sure the value doesn't underflow + io_gate_delay = ((io_gate_delay == 0) ? 0 : (io_gate_delay - 1)); + } +} + +/// +/// @brief Gets the blue waterfall and gate delay values for a given DP quad +/// @tparam uint64_t QUAD - which quad to access +/// @param[in,out] io_waterfall_reg - waterfall register data +/// @param[in,out] io_gate_reg - gate delay register information +/// +template< uint64_t QUAD> +void update_blue_waterfall_gate_delay_for_quad(fapi2::buffer<uint64_t>& io_waterfall_reg, + fapi2::buffer<uint64_t>& io_gate_reg) +{ + constexpr uint64_t NUM_QUAD = 4; + // Valid quad values are from 0-3, exit if the requested value is greater + static_assert(QUAD < NUM_QUAD, "Inserted quad value is greater than or equal to 4"); + + // Gets the data for this Quad + auto l_blue_waterfall = mss::dp16::get_blue_waterfall<QUAD>(io_waterfall_reg); + auto l_gate_delay = mss::dp16::get_gate_delay<QUAD>(io_gate_reg); + + // Updates the waterfall and gate delay + update_blue_waterfall_gate_delay(l_blue_waterfall, l_gate_delay); + + // Sets the data back into the register + mss::dp16::set_blue_waterfall<QUAD>(io_waterfall_reg, l_blue_waterfall); + mss::dp16::set_gate_delay<QUAD>(io_gate_reg, l_gate_delay); +} + +/// +/// @brief Fixes blue waterfall values in a port +/// @param[in] i_target - the target to operate on +/// @param[in] i_always_run - ignores the attribute and always run - default = false - this is used in lab code to force the workaround to be run +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode fix_blue_waterfall_gate( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const bool i_always_run = false ); + +/// +/// @brief Modifies HW calibration results based upon workarounds +/// @param[in] i_target - the target to operate on +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +fapi2::ReturnCode modify_calibration_results( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target ); + namespace wr_vref { 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 b8cdf227a..635ccc0cd 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 @@ -38,6 +38,7 @@ #include <p9_mss_draminit_training.H> #include <lib/utils/count_dimm.H> +#include <lib/workarounds/dp16_workarounds.H> #include <lib/fir/unmask.H> using fapi2::TARGET_TYPE_MCBIST; @@ -191,6 +192,9 @@ extern "C" // 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(i_target, l_program, p) ); + // Modifies the training steps, based upon workarounds - adding this here so it always gets run + FAPI_TRY( mss::workarounds::dp16::modify_calibration_results( p ) ); + // If we're aborting on error we can just FAPI_TRY. If we're not, we don't want to exit if there's // an error but we want to log the error and keep on keeping on. if ((fapi2::current_err = mss::process_initial_cal_errors(p)) != fapi2::FAPI2_RC_SUCCESS) diff --git a/src/import/chips/p9/procedures/hwp/perv/p9_getecid.C b/src/import/chips/p9/procedures/hwp/perv/p9_getecid.C index df69deb21..753d323d6 100644 --- a/src/import/chips/p9/procedures/hwp/perv/p9_getecid.C +++ b/src/import/chips/p9/procedures/hwp/perv/p9_getecid.C @@ -123,6 +123,7 @@ static fapi2::ReturnCode setup_memory_work_around_attributes( // All these attributes have 1 as their 'YES' enum value uint8_t l_value = 1; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_DO_MSS_TRAINING_BAD_BITS, i_target, l_value) ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_DO_BLUE_WATERFALL_ADJUST, i_target, l_value) ); } return fapi2::FAPI2_RC_SUCCESS; diff --git a/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml index 163fa1c2d..c1a351a8a 100644 --- a/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/chip_ec_attributes.xml @@ -2061,6 +2061,24 @@ </chipEcFeature> </attribute> + <attribute> + <id>ATTR_CHIP_EC_FEATURE_MSS_BLUE_WATERFALL_ADJUST</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description> + In DD1.** Nimbus, the blue waterfall can calibrate to an incorrect value. In DD2 Nimbus, + This isn't the case as the HW will not allow this calibration value + </description> + <chipEcFeature> + <chip> + <name>ENUM_ATTR_NAME_NIMBUS</name> + <ec> + <value>0x20</value> + <test>LESS_THAN</test> + </ec> + </chip> + </chipEcFeature> + </attribute> + <!-- ******************************************************************** --> <!-- End Memory Section --> <!-- ******************************************************************** --> diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_workarounds_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_workarounds_attributes.xml index 1d40c3ced..02b9915c5 100644 --- a/src/import/chips/p9/procedures/xml/attribute_info/memory_workarounds_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_workarounds_attributes.xml @@ -69,4 +69,18 @@ <writeable/> </attribute> + <attribute> + <id>ATTR_DO_BLUE_WATERFALL_ADJUST</id> + <targetType>TARGET_TYPE_PROC_CHIP</targetType> + <description> + For Nimbus pre DD1.** we want to adjust the blue waterfall values + and their associated gate delays if the blue waterfalls are 0. + Post DD1.** will have a hardware enabled fix for this. + </description> + <initToZero></initToZero> + <valueType>uint8</valueType> + <enum>NO = 0, YES = 1</enum> + <writeable/> + </attribute> + </attributes> |