From 04e2dd7b90abd697b61a956a56d76a5fb7121df6 Mon Sep 17 00:00:00 2001 From: Andre Marin Date: Fri, 28 Apr 2017 17:15:31 -0500 Subject: Add DLL workaround and unit tests Change-Id: I142ecd417abb92f4f8ec7d3748563b30359c486d Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39673 Tested-by: Jenkins Server Reviewed-by: STEPHEN GLANCY Tested-by: PPE CI Dev-Ready: ANDRE A. MARIN Tested-by: Hostboot CI Reviewed-by: Matt K. Light Reviewed-by: Thi N. Tran Reviewed-by: Louis Stermole Reviewed-by: Jennifer A. Stofer Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/39677 Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins Reviewed-by: Christian R. Geddes --- .../memory/lib/mss_attribute_accessors_manual.H | 22 ++ .../p9/procedures/hwp/memory/lib/phy/ddr_phy.C | 57 ++- .../chips/p9/procedures/hwp/memory/lib/phy/dp16.H | 17 + .../p9/procedures/hwp/memory/lib/phy/phy_cntrl.H | 64 +++- .../procedures/hwp/memory/lib/shared/mss_const.H | 1 + .../hwp/memory/lib/workarounds/dll_workarounds.C | 426 +++++++++++++++++++++ .../hwp/memory/lib/workarounds/dll_workarounds.H | 131 +++++++ .../procedures/hwp/memory/p9_mss_ddr_phy_reset.C | 17 +- .../xml/attribute_info/chip_ec_attributes.xml | 127 +++--- 9 files changed, 780 insertions(+), 82 deletions(-) (limited to 'src/import/chips/p9/procedures') 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 385fdcb40..abdceefb2 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 @@ -390,6 +390,28 @@ fapi_try_exit: return false; } +/// +/// @brief ATTR_CHIP_EC_FEATURE_MSS_DLL_WORKAROUND getter +/// @tparam T the fapi2 target type of the target +/// @param[in] const ref to the target +/// @return bool true iff we're on a Nimbus < EC 2.0 +/// +template< fapi2::TargetType T > +inline bool chip_ec_feature_mss_dll_workaround(const fapi2::Target& i_target) +{ + const auto l_chip = mss::find_target(i_target); + uint8_t l_value = 0; + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_MSS_DLL_WORKAROUND, l_chip, l_value) ); + return l_value != 0; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_CHIP_EC_FEATURE_MSS_DLL_WORKAROUND: 0x%lx (target: %s)", + uint64_t(fapi2::current_err), mss::c_str(i_target)); + fapi2::Assert(false); + return false; +} + /// /// @brief ATTR_CHIP_EC_FEATURE_MSS_RUN_DQS_LOOP getter /// @tparam T the fapi2 target type of the target 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 7a3d7affc..240b3a259 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 @@ -1514,35 +1514,38 @@ fapi2::ReturnCode dll_calibration( const fapi2::Target> i_read; + typedef adr32sTraits TT; - FAPI_TRY(mss::scom_suckah(p, adr32sTraits::DLL_CNFG_REG, i_read)); - std::for_each( i_read.begin(), i_read.end(), - [](fapi2::buffer& b) + std::vector> l_read; + FAPI_TRY(mss::scom_suckah(p, TT::DLL_CNFG_REG, l_read)); + + std::for_each( l_read.begin(), l_read.end(), [](fapi2::buffer& b) { adr32s::set_dll_cal_reset(b); } ); - FAPI_TRY(mss::scom_blastah(p, adr32sTraits::DLL_CNFG_REG, i_read)); + + FAPI_TRY(mss::scom_blastah(p, TT::DLL_CNFG_REG, l_read)); } // Read, modify, write the DLL_RESET in the DP16_DLL registers { - std::vector< std::pair, fapi2::buffer > > i_read; + typedef dp16Traits TT; - FAPI_TRY(mss::scom_suckah(p, dp16Traits::DLL_CNTRL_REG, i_read)); + std::vector< std::pair, fapi2::buffer > > l_read; + FAPI_TRY(mss::scom_suckah(p, TT::DLL_CNTRL_REG, l_read)); size_t l_index = 0; - for (const auto& r : dp16Traits::DLL_CNTRL_REG) + for (const auto& r : TT::DLL_CNTRL_REG) { mss::states l_state = (r.second == MCA_DDRPHY_DP16_DLL_CNTL1_P0_4) ? mss::HIGH : mss::LOW; - dp16::set_dll_cal_reset(i_read[l_index].first, mss::LOW); - dp16::set_dll_cal_reset(i_read[l_index].second, l_state); + dp16::set_dll_cal_reset(l_read[l_index].first, mss::LOW); + dp16::set_dll_cal_reset(l_read[l_index].second, l_state); l_index += 1; } - FAPI_TRY(mss::scom_blastah(p, dp16Traits::DLL_CNTRL_REG, i_read)); + FAPI_TRY(mss::scom_blastah(p, TT::DLL_CNTRL_REG, l_read)); } } @@ -1552,7 +1555,7 @@ fapi2::ReturnCode dll_calibration( const fapi2::Target l_read; FAPI_TRY( mss::getScom(p, l_dll_status_reg, l_read) ); - FAPI_ASSERT(mss::pc::get_dll_cal_status(l_read) == mss::YES, - fapi2::MSS_DLL_FAILED_TO_CALIBRATE().set_MCA_IN_ERROR(p), - "dll fapiled to calibrate: %s", mss::c_str(p)); - } + + if( mss::pc::get_dll_cal_status(l_read) != mss::YES ) + { + // For < DD2.0 parts we want to run DLL workaround so + // Instead of using FAPI_ASSERT and logging FFDC we will + // return a "bad" ReturnCode to trigger a workaround that + // will be run after DLL Calibration for all failing DLLs. + // FFDC will be collected there if it doesn't pass. + if( mss::chip_ec_feature_mss_dll_workaround(p) ) + { + FAPI_INF("%s DLL failed to calibrate", mss::c_str(p)); + return fapi2::FAPI2_RC_FALSE; + } + + // If we are here than we are not running DLL workaround + // because this part is not < DD2.0, so we want to fail out here + // and log FFDC + FAPI_ASSERT( false, + fapi2::MSS_DLL_FAILED_TO_CALIBRATE() + .set_MCA_IN_ERROR(p), + "%s DLL failed to calibrate", + mss::c_str(i_target) ); + + }// endif + + }// mca fapi_try_exit: return fapi2::current_err; 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 0e75b19cf..32cefd760 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 @@ -203,6 +203,8 @@ class dp16Traits enum { DLL_CNTL_INIT_RXDLL_CAL_RESET = MCA_DDRPHY_DP16_DLL_CNTL0_P0_0_01_INIT_RXDLL_CAL_RESET, + DLL_CNTL_INIT_RXDLL_CAL_SKIP = MCA_DDRPHY_DP16_DLL_CNTL0_P0_1_01_REGS_RXDLL_CAL_SKIP, + DLL_CNTL_INIT_RXDLL_CAL_SKIP_LEN = MCA_DDRPHY_DP16_DLL_CNTL0_P0_1_01_REGS_RXDLL_CAL_SKIP_LEN, FLUSH = MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_0_01_FLUSH, INIT_IO = MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_0_01_INIT_IO, ADV_PP = MCA_DDRPHY_DP16_DATA_BIT_DIR1_P0_0_01_ADVANCE_PING_PONG, @@ -696,6 +698,21 @@ inline void set_dll_cal_reset( fapi2::buffer& o_data, const states i_s o_data.writeBit(i_state); } +/// +/// @brief Set the DLL cal skip reset +/// @tparam T fapi2 Target Type - defaults to TARGET_TYPE_MCA +/// @tparam TT traits type defaults to dp16Traits +/// @param[in,out] io_data the value of the register +/// @param[in] i_value the value to write +/// +template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits > +inline void set_dll_cal_skip( fapi2::buffer& io_data, const uint64_t i_value ) +{ + FAPI_INF("set_dll_cal_skip to %d", i_value); + io_data.insertFromRight(i_value); +} + /// /// @brief Read DATA_BIT_DIR1 /// @tparam I DP16 instance diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H index a2e5b0b87..0fcc81dbb 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H @@ -389,6 +389,44 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Get DP DLL Cal Status +/// @param[in] l_good DLL CAL good status of DP or ADR +/// @param[in] l_error DLL CAL error status of DP or ADR +/// @param[in] l_error_fine DLL CAL error fine status of DP or ADR +/// @return mss::states; YES == success, NO == fail, INVALID == still running +/// @note Since the these indicators are a summary of all DLLs, all must be started to make +/// them valid. +/// +static mss::states dll_cal_status_helper( const bool l_good, + const bool l_error, + const bool l_error_fine ) +{ + // Full calibration is still going on in at least 1 DLL while all 3 signals are 0. + if ((l_good == mss::LOW) && (l_error == mss::LOW) && (l_error_fine == mss::LOW)) + { + return mss::INVALID; + } + + // Full calibration was successful in all DLLs if CAL_GOOD = 1 and both CAL_ERROR and CAL_ERROR_FINE are 0. + if ((l_good == mss::HIGH) && (l_error == mss::LOW) && (l_error_fine == mss::LOW)) + { + return mss::YES; + } + + // Full calibration failed in at least 1 DLL if either CAL_ERROR or CAL_ERROR_FINE are 1. + if ((l_error == mss::HIGH) || (l_error_fine == mss::HIGH)) + { + return mss::NO; + } + + // All cases shoud be covered above + // we shouldn't reach here so we add + // a saftey net. + fapi2::Assert(false); + return mss::NO; +} + /// /// @brief Get DP DLL Cal Status /// @tparam T fapi2 Target Type - derived @@ -402,32 +440,38 @@ fapi_try_exit: template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = pcTraits > inline mss::states get_dll_cal_status( fapi2::buffer& i_data ) { + // Lets check the cal status of the DPs first const bool l_dp_good = i_data.getBit(); const bool l_dp_error = i_data.getBit(); const bool l_dp_error_fine = i_data.getBit(); + const mss::states l_dp_status = dll_cal_status_helper(l_dp_good, l_dp_error, l_dp_error_fine); + + // Lets check the cal status of the ADRs second + const bool l_adr_good = i_data.getBit(); + const bool l_adr_error = i_data.getBit(); + const bool l_adr_error_fine = i_data.getBit(); + + const mss::states l_adr_status = dll_cal_status_helper(l_adr_good, l_adr_error, l_adr_error_fine); FAPI_INF("pc_dll_status: 0x%016llx", i_data); - // Full calibration is still going on in at least 1 DLL while all 3 signals are 0. - if ((l_dp_good == mss::LOW) && (l_dp_error == mss::LOW) && (l_dp_error_fine == mss::LOW)) + + if( l_dp_status == mss::INVALID || l_adr_status == mss::INVALID ) { return mss::INVALID; } - // Full calibration was successful in all DLLs if CAL_GOOD = 1 and both CAL_ERROR and CAL_ERROR_FINE are 0. - if ((l_dp_good == mss::HIGH) && (l_dp_error == mss::LOW) && (l_dp_error_fine == mss::LOW)) + if( l_dp_status == mss::NO || l_adr_status == mss::NO ) { - return mss::YES; + return mss::NO; } - // Full calibration failed in at least 1 DLL if either CAL_ERROR or CAL_ERROR_FINE are 1. - // Full calibration was successful in all DLLs if CAL_GOOD = 1 and both CAL_ERROR and CAL_ERROR_FINE are 0. - if ((l_dp_error == mss::HIGH) || (l_dp_error_fine == mss::HIGH)) + if( l_dp_status == mss::YES && l_adr_status == mss::YES ) { - return mss::NO; + return mss::YES; } - // Not reached ... right? + // Shouldn't get here, so we put some belt and suspenders FAPI_ERR("pc_dll_cal_status: 0x%016llx unable to calculate state", i_data); fapi2::Assert(false); return mss::NO; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H index 6fb449f8e..fe9ef2680 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H @@ -120,6 +120,7 @@ enum times BG_SCRUB_IN_HOURS = 12, CMD_TIMEBASE = 8192, ///< Represents the timebase multiplier for the MCBIST inter cmd gap + FULL_DLL_CAL_DELAY = 37382, ///< Full DLL calibration (in ddphy_nck cycles) }; enum states diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.C index c44e79560..78b981343 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.C @@ -22,3 +22,429 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Stephen Glancy +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mss +{ + +static const std::vector< mss::dll_map > DLL_REGS = +{ + // ADR DLL 0 + { + MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0, + MCA_DDRPHY_ADR_DLL_VREG_COARSE_P0_ADR32S0, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_2, + MCA_DDRPHY_ADR_DLL_DAC_LOWER_P0_ADR32S0, + MCA_DDRPHY_ADR_DLL_DAC_UPPER_P0_ADR32S0 + }, + + // DP0 DLL0 + { + MCA_DDRPHY_DP16_DLL_CNTL0_P0_0, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_0, + MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_0, + MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_0, + }, + + // DP1 DLL0 + { + MCA_DDRPHY_DP16_DLL_CNTL0_P0_1, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_1, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_1, + MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_1, + MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_1, + }, + + // DP2 DLL0 + { + MCA_DDRPHY_DP16_DLL_CNTL0_P0_2, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_2, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_2, + MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_2, + MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_2, + }, + + // DP3 DLL0 + { + MCA_DDRPHY_DP16_DLL_CNTL0_P0_3, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_3, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_3, + MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_3, + MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_3, + }, + + // DP4 DLL0 + { + MCA_DDRPHY_DP16_DLL_CNTL0_P0_4, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_4, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_3, + MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_4, + MCA_DDRPHY_DP16_DLL_DAC_UPPER0_P0_4, + }, + + // DP0 DLL1 + { + MCA_DDRPHY_DP16_DLL_CNTL1_P0_0, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_0, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0, + MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_0, + MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_0, + }, + + // DP1 DLL1 + { + MCA_DDRPHY_DP16_DLL_CNTL1_P0_1, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_1, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_1, + MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_1, + MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_1, + }, + + // DP2 DLL1 + { + MCA_DDRPHY_DP16_DLL_CNTL1_P0_2, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_2, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_2, + MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_2, + MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_2, + }, + + // DP3 DLL1 + { + MCA_DDRPHY_DP16_DLL_CNTL1_P0_3, + MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_3, + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_3, + MCA_DDRPHY_DP16_DLL_DAC_LOWER1_P0_3, + MCA_DDRPHY_DP16_DLL_DAC_UPPER1_P0_3, + }, +}; + +namespace workarounds +{ +namespace dll +{ + +/// +/// @brief Checks if CAL_ERROR and CAL_ERROR_FINE bits are set +/// @param[in] i_dll_cntrl_data DLL CNTRL data +/// @return true if DLL cal failed, false otherwiae +/// +bool did_cal_fail( const fapi2::buffer& i_dll_cntrl_data ) +{ + FAPI_DBG("DLL_CNTL data 0x%016llx, CAL_ERROR %d, CAL_ERROR_FINE %d", + i_dll_cntrl_data, + i_dll_cntrl_data.getBit(), + i_dll_cntrl_data.getBit()); + + return i_dll_cntrl_data.getBit() || + i_dll_cntrl_data.getBit(); +} + +/// +/// @brief Logs DLL error mappings from failed DLLs +/// @param[in] i_target the fapi2 target +/// @param[in] i_map dll map of DLLs to log errors from +/// @param[in,out] io_failed_dll_cntrl failed list of DLL CNTRL regs +/// @param[in,out] io_failed_dll_vreg_coarse map of VREG COARSE from failed DLLs +/// @param[in,out] io_failed_dll_dac map of DLL DAC from failed DLLs +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode log_fails(const fapi2::Target& i_target, + const mss::dll_map& i_map, + std::vector< uint64_t >& io_failed_dll_cntrl, + std::map< fapi2::buffer, fapi2::buffer >& io_failed_dll_vreg_coarse, + std::map< fapi2::buffer, fapi2::buffer >& io_failed_dll_dac) +{ + fapi2::buffer l_dll_cntrl_data; + FAPI_TRY( mss::getScom(i_target, i_map.iv_cntrl, l_dll_cntrl_data), + "Failed getScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), i_map.iv_cntrl); + + FAPI_DBG("%s Read DLL_CNTRL reg 0x%016llx, with data 0x%016llx", + mss::c_str(i_target), i_map.iv_cntrl, l_dll_cntrl_data); + + if( did_cal_fail(l_dll_cntrl_data) ) + { + fapi2::buffer l_dll_dac_data; + uint64_t l_neighbor_dac_coarse = 0; + + // Read DAC coarse from neighboring DLL + FAPI_TRY( mss::getScom(i_target, i_map.iv_vreg_coarse_neighbor_dll, l_dll_dac_data), + "Failed getScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), i_map.iv_vreg_coarse_neighbor_dll ); + + FAPI_DBG( "%s Read neighboring DLL VREG COARSE reg 0x%016llx with data 0x%016llx", + mss::c_str(i_target), i_map.iv_vreg_coarse_neighbor_dll, l_dll_dac_data ); + + // Pair VREG coarse from failing DLL w/data from the DAC coarse from the neighboring DLL + l_dll_dac_data.extractToRight< dll_map::REGS_RXDLL_DAC_COARSE, dll_map::REGS_RXDLL_DAC_COARSE_LEN > + (l_neighbor_dac_coarse); + + FAPI_DBG( "%s Saving failing DLL VREG COARSE reg 0x%016llx, value extracted 0x%llx", + mss::c_str(i_target), i_map.iv_vreg_coarse_same_dll, l_neighbor_dac_coarse); + + io_failed_dll_vreg_coarse.emplace( std::make_pair(i_map.iv_vreg_coarse_same_dll, l_neighbor_dac_coarse) ); + + // Create a list DAC Lower and Upper pairs for failing DLLs + FAPI_DBG( "%s Saving off pair of failling DLL regs for DAC LOWER 0x%016llx, DAC UPPER 0x%016llx", + mss::c_str(i_target), i_map.iv_dll_dac_lower, i_map.iv_dll_dac_upper ); + + io_failed_dll_dac.emplace( std::make_pair(i_map.iv_dll_dac_lower, i_map.iv_dll_dac_upper) ); + + // Store a list of all failing DLL CNTRL registers + FAPI_INF( "%s Saving off failed DLL_CNTRL 0x%016llx", + mss::c_str(i_target), i_map.iv_cntrl ); + + io_failed_dll_cntrl.push_back(i_map.iv_cntrl); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Checks for DLL error status +/// @param[in] i_target the fapi2 target +/// @param[in] i_failed_dll_cntrl vector of failed DLLs +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode check_status(const fapi2::Target& i_target, + const std::vector< uint64_t >& i_failed_dll_cntrl) +{ + for( const auto& reg : i_failed_dll_cntrl ) + { + fapi2::buffer l_dll_cntrl_data; + + FAPI_TRY( mss::getScom(i_target, reg, l_dll_cntrl_data), + "Failed getScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), reg ); + + FAPI_DBG("Checking status on %s, DLL CNTRL reg 0x%016llx", mss::c_str(i_target), reg); + + FAPI_ASSERT( did_cal_fail(l_dll_cntrl_data) == false, + fapi2::MSS_DLL_FAILED_TO_CALIBRATE() + .set_MCA_IN_ERROR(i_target), + "%s DLL failed to calibrate", + mss::c_str(i_target) ) + } + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Change VREG_COARSE for failed DLLs +/// @param[in] i_target the fapi2 target +/// @param[in] i_failed_dll_map failed DLL VREG COARSE map +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode change_vreg_coarse(const fapi2::Target& i_target, + const std::map< fapi2::buffer, fapi2::buffer >& i_failed_dll_map) +{ + for( const auto& map : i_failed_dll_map) + { + // Little renaming to help clarify map fields + const auto FAILING_COARSE_REG = map.first; + const auto NEIGHBOR_DATA = map.second; + + fapi2::buffer l_data; + + // Read DAC coarse from failed DLL + FAPI_TRY( mss::getScom(i_target, FAILING_COARSE_REG, l_data), + "Failed getScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), FAILING_COARSE_REG ); + + + FAPI_DBG("%s Read DLL_VREG_COARSE reg 0x%016llx, data 0x%016llx", + mss::c_str(i_target), FAILING_COARSE_REG, l_data); + + l_data.insertFromRight< dll_map::REGS_RXDLL_DAC_COARSE, + dll_map::REGS_RXDLL_DAC_COARSE_LEN>(NEIGHBOR_DATA); + + FAPI_INF("%s Writing to DLL_VREG_COARSE reg 0x%016llx, data 0x%016llx, value 0x%llx", + mss::c_str(i_target), FAILING_COARSE_REG, l_data, NEIGHBOR_DATA); + + // Write DAC coarse from failed DLL with DAC coarse from neighboring DLL + FAPI_TRY( mss::putScom(i_target, FAILING_COARSE_REG, l_data), + "Failed putScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), FAILING_COARSE_REG ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to set DAC_COARSE reg +/// @param[in] i_target the fapi2 target +/// @param[in] i_failed_dll_dac failed DLL VREG COARSE +/// @param[in] i_value the value to set +/// @return FAPI2_RC_SUCCESS iff ok +/// +static fapi2::ReturnCode dll_dac_helper(const fapi2::Target& i_target, + const fapi2::buffer& i_failed_dll_dac, + const uint64_t i_value) +{ + constexpr uint64_t SOURCE_START = dll_map::REGS_RXDLL_VREG; + + // Read DAC coarse from failed DLL + fapi2::buffer l_data; + + FAPI_TRY( mss::getScom(i_target, i_failed_dll_dac, l_data), + "Failed getScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), i_failed_dll_dac ); + + + l_data.insert(i_value); + + FAPI_INF("%s Writing to DAC_REG 0x%016llx, data 0x%016llx, value 0x%llx", + mss::c_str(i_target), i_failed_dll_dac, l_data, i_value); + + // Write DAC coarse from failed DLL with DAC coarse from neighboring DLL + FAPI_TRY( mss::putScom(i_target, i_failed_dll_dac, l_data), + "Failed putScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), i_failed_dll_dac ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Change DLL DAC for failled DLLs map +/// @param[in] i_target the fapi2 target +/// @param[in] i_failed_dll_dac_map failed DLL DAC map +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode change_dac(const fapi2::Target& i_target, + const std::map< fapi2::buffer, fapi2::buffer >& i_failed_dll_dac_map) +{ + // Hard coded default values per Steve Wyatt for this workaround + constexpr uint64_t DAC_LOWER_DEFAULT = 0x8000; + constexpr uint64_t DAC_UPPER_DEFAULT = 0xFFE0; + + for( const auto& map : i_failed_dll_dac_map) + { + const auto DAC_LOWER_REG = map.first; + const auto DAC_UPPER_REG = map.second; + + FAPI_TRY( dll_dac_helper(i_target, DAC_UPPER_REG, DAC_UPPER_DEFAULT) ); + FAPI_TRY( dll_dac_helper(i_target, DAC_LOWER_REG, DAC_LOWER_DEFAULT) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief DLL Workaround algorithm to fax bad voltage settings +/// @param[in] i_target the fapi2 target +/// @return FAPI2_RC_SUCCESS iff ok +/// +template< > +fapi2::ReturnCode fix_bad_voltage_settings(const fapi2::Target& i_target) +{ + constexpr uint64_t SKIP_VREG = 0b10; + + for( const auto& p : mss::find_targets(i_target) ) + { + std::vector l_failing_dll_cntrl; + std::map< fapi2::buffer, fapi2::buffer > l_failing_dll_vreg_coarse; + std::map< fapi2::buffer, fapi2::buffer > l_failing_dll_dac; + + // Find failing DLL + for( const auto& map : DLL_REGS ) + { + FAPI_TRY( log_fails(p, map, l_failing_dll_cntrl, l_failing_dll_vreg_coarse, l_failing_dll_dac), + "%s Failed log_fails()", mss::c_str(p)); + } + + // Set DLL reset bit and skip VREG bit on failed DLLs + { + fapi2::buffer l_read; + + for( const auto& d : l_failing_dll_cntrl ) + { + FAPI_TRY(mss::getScom(p, d, l_read), + "Failed getScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), d ); + + + mss::dp16::set_dll_cal_reset(l_read, mss::HIGH); + mss::dp16::set_dll_cal_skip(l_read, SKIP_VREG); + + FAPI_TRY(mss::putScom(p, d, l_read), + "Failed putScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), d ); + + } + + } + + // Write the VREG DAC value found in log_fails to the failing DLL VREG DAC + FAPI_TRY( change_vreg_coarse(p, l_failing_dll_vreg_coarse), + "%s Failed change_vreg_coarse()", mss::c_str(p) ); + + // Reset the upper and lower fine calibration bits back to defaults + // since the earlier initial full calibration will have disturbed these. + FAPI_TRY( change_dac(p, l_failing_dll_dac), + "Failed change_dac on %s", mss::c_str(p) ); + + // Run DLL Calibration again on failed DLLs + { + fapi2::buffer l_read; + + for( const auto& d : l_failing_dll_cntrl ) + { + FAPI_TRY(mss::getScom(p, d, l_read), + "Failed getScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), d ); + + mss::dp16::set_dll_cal_reset(l_read, mss::LOW); + + FAPI_INF("%s DLL_CNTRL_REG 0x%016llx, data 0x%016llx", + mss::c_str(p), d, l_read); + + FAPI_TRY(mss::putScom(p, d, l_read), + "Failed putScom() operation on %s reg 0x%016llx", + mss::c_str(i_target), d ); + } + } + + // The [delay value] gives software a reasonable amount of time to wait for an individual + // DLL to calibrate starting from when it is taken out of reset. As some internal state machine transitions + // between steps may not have been counted, software should add some margin. + // 32,772 dphy_nclk cycles from Reset=0 to VREG Calibration to exhaust all values + // 37,382 dphy_nclk cycles for full calibration to start and fail (“worst case”) + // More or less a fake value for sim delay as this isn't executed in sim. + fapi2::delay(mss::cycles_to_ns(i_target, mss::FULL_DLL_CAL_DELAY), DELAY_1US); + + FAPI_TRY( check_status(p, l_failing_dll_cntrl), + "%s check_status() failed", mss::c_str(p)); + }// mca + +fapi_try_exit: + return fapi2::current_err; +} + +} // close namespace dll +} // close namespace workarounds +} // close namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.H b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.H index ab673f919..f7dd7b711 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.H @@ -22,3 +22,134 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Stephen Glancy +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + +#ifndef _MSS_WORKAROUNDS_DLL_H_ +#define _MSS_WORKAROUNDS_DLL_H_ + +#include +#include +#include +#include + +namespace mss +{ + +/// +/// @brief class to keep trace of DLL info for workaround +/// +struct dll_map +{ + // Same values for DP16 and ADR enumerations + // Used DP16 enumerations...just because + static constexpr uint64_t REGS_RXDLL_DAC_COARSE = MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_1_01_REGS_RXDLL_DAC_COARSE; + static constexpr uint64_t REGS_RXDLL_DAC_COARSE_LEN = + MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_1_01_REGS_RXDLL_DAC_COARSE_LEN; + static constexpr uint64_t DLL_CNTL_CAL_ERROR = MCA_DDRPHY_DP16_DLL_CNTL0_P0_1_01_CAL_ERROR; + static constexpr uint64_t DLL_CNTL_CAL_ERROR_FINE = MCA_DDRPHY_DP16_DLL_CNTL0_P0_1_01_CAL_ERROR_FINE; + + // Value for UPPER and LOWER DAC are the same + // Used LOWER DAC enumeration...just because + static constexpr uint64_t REGS_RXDLL_VREG = MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_0_01_REGS_RXDLL_VREG_LOWER; + static constexpr uint64_t REGS_RXDLL_VREG_LEN = MCA_DDRPHY_DP16_DLL_DAC_LOWER0_P0_0_01_REGS_RXDLL_VREG_LOWER_LEN; + + /// + /// @brief Checks for DLL error status + /// @param[in] i_cntrl_reg + /// @param[in] i_vreg_coarse_same_dll + /// @param[in] i_vreg_coarse_neighbor_dll + /// @param[in] i_dll_dac_upper + /// @param[in] i_dll_dac_lower + /// + constexpr dll_map(const uint64_t i_cntrl_reg, + const uint64_t i_vreg_coarse_same_dll, + const uint64_t i_vreg_coarse_neighbor_dll, + const uint64_t i_dll_dac_lower, + const uint64_t i_dll_dac_upper) + : iv_cntrl(i_cntrl_reg), + iv_vreg_coarse_same_dll(i_vreg_coarse_same_dll), + iv_vreg_coarse_neighbor_dll(i_vreg_coarse_neighbor_dll), + iv_dll_dac_lower(i_dll_dac_lower), + iv_dll_dac_upper(i_dll_dac_upper) + {} + + const uint64_t iv_cntrl; // DP16 or ADR CNTRL register + const uint64_t iv_vreg_coarse_same_dll; // VREG_COARSE register for same DLL as iv_cntrl_reg + const uint64_t iv_vreg_coarse_neighbor_dll; // VREG_COARSE register for DLL neighbor for this workaround + const uint64_t iv_dll_dac_lower; // DLL DAC Upper register + const uint64_t iv_dll_dac_upper; // DLL DAC Lower register +}; + +namespace workarounds +{ +namespace dll +{ + +/// +/// @brief Checks if CAL_ERROR and CAL_ERROR_FINE bits are set +/// @param[in] i_dll_cntrl_data DLL CNTRL data +/// @return bool +/// +bool did_cal_fail( const fapi2::buffer& i_dll_cntrl_data ); + +/// +/// @brief Logs DLL error mappings from failed DLLs +/// @param[in] i_target the fapi2 target +/// @param[in] i_map dll map of DLLs to log errors from +/// @param[in,out] io_failed_dll_cntrl failed list of DLL CNTRL regs +/// @param[in,out] io_failed_dll_vreg_coarse map of VREG COARSE from failed DLLs +/// @param[in,out] io_failed_dll_dac map of DLL DAC from failed DLLs +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode log_fails(const fapi2::Target& i_target, + const mss::dll_map& i_map, + std::vector< uint64_t >& io_failed_dll_cntrl, + std::map< fapi2::buffer, fapi2::buffer >& io_failed_dll_vreg_coarse, + std::map< fapi2::buffer, fapi2::buffer >& io_failed_dll_dac); + +/// +/// @brief Checks for DLL error status +/// @param[in] i_target the fapi2 target +/// @param[in] i_failed_dll_cntrl vector of failed DLLs +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode check_status(const fapi2::Target& i_target, + const std::vector< uint64_t >& i_failed_dll_cntrl); + +/// +/// @brief Change VREG_COARSE for failed DLLs +/// @param[in] i_target the fapi2 target +/// @param[in] i_failed_dll_map failed DLL VREG COARSE map +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode change_vreg_coarse(const fapi2::Target& i_target, + const std::map< fapi2::buffer, fapi2::buffer >& i_failed_dll_map); + +/// +/// @brief Change DLL DAC for failled DLLs map +/// @param[in] i_target the fapi2 target +/// @param[in] i_failed_dll_dac_map failed DLL DAC map +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode change_dac(const fapi2::Target& i_target, + const std::map< fapi2::buffer, fapi2::buffer >& i_failed_dll_dac_map); + +/// +/// @brief DLL Workaround algorithm to fax bad voltage settings +/// @tparam T fapi2 Target Type - derived +/// @param[in] i_target the fapi2 target +/// @return FAPI2_RC_SUCCESS iff ok +/// +template< fapi2::TargetType T > +fapi2::ReturnCode fix_bad_voltage_settings(const fapi2::Target& i_target); + +} // close namespace dll +} // close namespace workarounds +} // close namespace mss + +#endif diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C index 22ae9b1ba..ab6dc8548 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -109,8 +110,20 @@ extern "C" // and DDRPHY_ADR_DLL_CNTL registers // 15. Monitor the DDRPHY_PC_DLL_ZCAL_CAL_STATUS register to determine when calibration is // complete. One of the 3 bits will be asserted for ADR and DP16. - FAPI_INF( "starting DLL calibration %s", mss::c_str(i_target) ); - FAPI_TRY( mss::dll_calibration(i_target) ); + { + FAPI_INF( "starting DLL calibration %s", mss::c_str(i_target) ); + fapi2::ReturnCode l_rc = mss::dll_calibration(i_target); + + // Only run DLL workaround if we fail DLL cal and we are a < DD2.0 part + if( l_rc != fapi2::FAPI2_RC_SUCCESS && + mss::chip_ec_feature_mss_dll_workaround(i_target) ) + { + FAPI_INF( "%s Applying DLL workaround", mss::c_str(i_target) ); + l_rc = mss::workarounds::dll::fix_bad_voltage_settings(i_target); + } + + FAPI_TRY( l_rc, "Failed DLL calibration" ); + } // // Start bang-bang-lock 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 296a301e8..4bdcb1362 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 @@ -2632,15 +2632,11 @@ - - - - ATTR_CHIP_EC_FEATURE_MSS_UT_EC_NIMBUS_LESS_THAN_TWO_OH + ATTR_CHIP_EC_FEATURE_MSS_HW392781_RDARRAY_CLKGATE TARGET_TYPE_PROC_CHIP - Attribute used only for memory subsystem unit tests. Tells us whether - the chip EC we're running on is less than 2.0 and we're on a Nimbus + Data integrity issue requires us to disable clockgate in read array for Nimbus DD1.0 @@ -2654,11 +2650,10 @@ - ATTR_CHIP_EC_FEATURE_MCBIST_END_OF_RANK + ATTR_CHIP_EC_FEATURE_HW400075 TARGET_TYPE_PROC_CHIP - MCBIST has a bug where it won't detect the end of a rank properly for - a 1R DIMM during super-fast read. + Addresses issue where MDI bit was getting wrong values with threadmill and transactional data resulting in coherency issues. @@ -2672,10 +2667,10 @@ - ATTR_CHIP_EC_FEATURE_MSS_WR_VREF + ATTR_CHIP_EC_FEATURE_HW398139 TARGET_TYPE_PROC_CHIP - In DD1 Nimbus in the WR VREF algorithm, certain work-arounds are needed + Avoid powerbus early hangs by enabling prefetch drops to break out of fairness issue with prefetch ops @@ -2689,10 +2684,10 @@ - ATTR_CHIP_EC_FEATURE_MSS_DQS_POLARITY + ATTR_CHIP_EC_FEATURE_HW400932 TARGET_TYPE_PROC_CHIP - For Monza DDR port 2, one pair of DQS P/N is swapped polarity. + ATAG info corruption on presp issue requires us to disable clockgate for Nimbus DD1.0 @@ -2706,10 +2701,10 @@ - ATTR_CHIP_EC_FEATURE_MSS_VREF_DAC + ATTR_CHIP_EC_FEATURE_HW401780 TARGET_TYPE_PROC_CHIP - VREF DAC work-around for Nimbus DD1.0 + Need AMO caching disabled for multiple defects until Nimbus DD2.0 @@ -2723,10 +2718,10 @@ - ATTR_CHIP_EC_FEATURE_MSS_WAT_DEBUG_ATTN + ATTR_CHIP_EC_FEATURE_HW406577 TARGET_TYPE_PROC_CHIP - WAT Debug Attention work-around for Nimbus DD1.0 + Noise window disabled in DD1 because continually reocurring intermittent UE's can cause us to hang on refreshes. @@ -2739,11 +2734,15 @@ + + + - ATTR_CHIP_EC_FEATURE_MSS_HW392781_RDARRAY_CLKGATE + ATTR_CHIP_EC_FEATURE_MCBIST_END_OF_RANK TARGET_TYPE_PROC_CHIP - Data integrity issue requires us to disable clockgate in read array for Nimbus DD1.0 + MCBIST has a bug where it won't detect the end of a rank properly for + a 1R DIMM during super-fast read. @@ -2757,10 +2756,10 @@ - ATTR_CHIP_EC_FEATURE_HW400075 + ATTR_CHIP_EC_FEATURE_MSS_WAT_DEBUG_ATTN TARGET_TYPE_PROC_CHIP - Addresses issue where MDI bit was getting wrong values with threadmill and transactional data resulting in coherency issues. + WAT Debug Attention work-around for Nimbus DD1.0 @@ -2774,10 +2773,11 @@ - ATTR_CHIP_EC_FEATURE_HW398139 + ATTR_CHIP_EC_FEATURE_MSS_UT_EC_NIMBUS_LESS_THAN_TWO_OH TARGET_TYPE_PROC_CHIP - Avoid powerbus early hangs by enabling prefetch drops to break out of fairness issue with prefetch ops + Attribute used only for memory subsystem unit tests. Tells us whether + the chip EC we're running on is less than 2.0 and we're on a Nimbus @@ -2791,10 +2791,10 @@ - ATTR_CHIP_EC_FEATURE_HW384794 + ATTR_CHIP_EC_FEATURE_MSS_WR_VREF TARGET_TYPE_PROC_CHIP - Workaround for defect where clock enables to PHY were incorrectly driven + In DD1 Nimbus in the WR VREF algorithm, certain work-arounds are needed @@ -2808,10 +2808,10 @@ - ATTR_CHIP_EC_FEATURE_HW375732 + ATTR_CHIP_EC_FEATURE_MSS_DQS_POLARITY TARGET_TYPE_PROC_CHIP - Workaround for Data mismatch discovered by Geyzer at certain async frequency ratios + For Monza DDR port 2, one pair of DQS P/N is swapped polarity. @@ -2825,12 +2825,10 @@ - ATTR_CHIP_EC_FEATURE_MSS_TRAINING_BAD_BITS + ATTR_CHIP_EC_FEATURE_MSS_VREF_DAC TARGET_TYPE_PROC_CHIP - For Nimbus pre DD1.02 we want to pass DDR training if we see 'correctable' - errors. This isn't the case for post-DD1.02 where we want to pass/fail - training based on the results from the PHY itself + VREF DAC work-around for Nimbus DD1.0 @@ -2844,10 +2842,12 @@ - ATTR_CHIP_EC_FEATURE_HW400932 + ATTR_CHIP_EC_FEATURE_MSS_TRAINING_BAD_BITS TARGET_TYPE_PROC_CHIP - ATAG info corruption on presp issue requires us to disable clockgate for Nimbus DD1.0 + For Nimbus pre DD1.02 we want to pass DDR training if we see 'correctable' + errors. This isn't the case for post-DD1.02 where we want to pass/fail + training based on the results from the PHY itself @@ -2861,10 +2861,10 @@ - ATTR_CHIP_EC_FEATURE_HW401780 + ATTR_CHIP_EC_FEATURE_MSS_CHECK_DISABLE_HW_VREF_CAL TARGET_TYPE_PROC_CHIP - Need AMO caching disabled for multiple defects until Nimbus DD2.0 + In below DD2 Nimbus, the HW VREF calibration needs to be checked against the chip subversion to see if it can be run. @@ -2878,10 +2878,10 @@ - ATTR_CHIP_EC_FEATURE_HW406577 + ATTR_CHIP_EC_FEATURE_MSS_RUN_RD_CTR_WORKAROUND TARGET_TYPE_PROC_CHIP - Noise window disabled in DD1 because continually reocurring intermittent UE's can cause us to hang on refreshes. + In below DD2 Nimbus, a workaround after read centering might need to be run. @@ -2895,10 +2895,12 @@ - ATTR_CHIP_EC_FEATURE_MSS_CHECK_DISABLE_HW_VREF_CAL + ATTR_CHIP_EC_FEATURE_MSS_ODT_CONFIG TARGET_TYPE_PROC_CHIP - In below DD2 Nimbus, the HW VREF calibration needs to be checked against the chip subversion to see if it can be run. + For Nimbus pre DD2.** we need to swap ODT2 and ODT3 values in the + DDRPHY_SEQ_ODT_RD/WR_CONFIG registers due to a PHY erratum. + Post DD2.** will have a hardware enabled fix for this (HW389360). @@ -2912,10 +2914,11 @@ - ATTR_CHIP_EC_FEATURE_MSS_RUN_RD_CTR_WORKAROUND + ATTR_CHIP_EC_FEATURE_MSS_BLUE_WATERFALL_ADJUST TARGET_TYPE_PROC_CHIP - In below DD2 Nimbus, a workaround after read centering might need to be run. + 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 @@ -2929,12 +2932,10 @@ - ATTR_CHIP_EC_FEATURE_MSS_ODT_CONFIG + ATTR_CHIP_EC_FEATURE_MSS_CHECK_DIABLE_RD_VREF_CAL_VREFSENSE TARGET_TYPE_PROC_CHIP - For Nimbus pre DD2.** we need to swap ODT2 and ODT3 values in the - DDRPHY_SEQ_ODT_RD/WR_CONFIG registers due to a PHY erratum. - Post DD2.** will have a hardware enabled fix for this (HW389360). + In below DD2 Nimbus, the RD VREF cal VREF sense needs to be checked against the chip subversion to see if it should be run. @@ -2948,11 +2949,10 @@ - ATTR_CHIP_EC_FEATURE_MSS_BLUE_WATERFALL_ADJUST + ATTR_CHIP_EC_FEATURE_MSS_DLL_WORKAROUND TARGET_TYPE_PROC_CHIP - 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 + Run DLL workaround algorithm to fix bad voltage settings pre DD2.0 @@ -2983,12 +2983,32 @@ + + + - ATTR_CHIP_EC_FEATURE_MSS_CHECK_DIABLE_RD_VREF_CAL_VREFSENSE + ATTR_CHIP_EC_FEATURE_HW384794 TARGET_TYPE_PROC_CHIP - In below DD2 Nimbus, the RD VREF cal VREF sense needs to be checked against the chip subversion to see if it should be run. + Workaround for defect where clock enables to PHY were incorrectly driven + + + + ENUM_ATTR_NAME_NIMBUS + + 0x20 + LESS_THAN + + + + + + + ATTR_CHIP_EC_FEATURE_HW375732 + TARGET_TYPE_PROC_CHIP + + Workaround for Data mismatch discovered by Geyzer at certain async frequency ratios @@ -3155,6 +3175,7 @@ + ATTR_CHIP_EC_FEATURE_HW399466 TARGET_TYPE_PROC_CHIP @@ -3172,6 +3193,7 @@ + ATTR_CHIP_EC_FEATURE_HW355538 TARGET_TYPE_PROC_CHIP @@ -3189,6 +3211,7 @@ + ATTR_CHIP_EC_FEATURE_NEW_MC_DD2_SETTINGS TARGET_TYPE_PROC_CHIP @@ -3206,10 +3229,6 @@ - - - - ATTR_CHIP_EC_FEATURE_DD1_ANALOG -- cgit v1.2.1