diff options
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/phy')
3 files changed, 112 insertions, 26 deletions
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<fapi2::TARGET_TYPE_MCBIST // Note: Keep INIT_RXDLL_CAL_UPDATE at 0 to ensure PC CAL_GOOD indicator is accurate. // Read, modify, write the DLL_RESET in the ADR_DLL registers { - std::vector<fapi2::buffer<uint64_t>> i_read; + typedef adr32sTraits<TARGET_TYPE_MCA> TT; - FAPI_TRY(mss::scom_suckah(p, adr32sTraits<TARGET_TYPE_MCA>::DLL_CNFG_REG, i_read)); - std::for_each( i_read.begin(), i_read.end(), - [](fapi2::buffer<uint64_t>& b) + std::vector<fapi2::buffer<uint64_t>> 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<uint64_t>& b) { adr32s::set_dll_cal_reset(b); } ); - FAPI_TRY(mss::scom_blastah(p, adr32sTraits<TARGET_TYPE_MCA>::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<uint64_t>, fapi2::buffer<uint64_t> > > i_read; + typedef dp16Traits<TARGET_TYPE_MCA> TT; - FAPI_TRY(mss::scom_suckah(p, dp16Traits<TARGET_TYPE_MCA>::DLL_CNTRL_REG, i_read)); + std::vector< std::pair<fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > > l_read; + FAPI_TRY(mss::scom_suckah(p, TT::DLL_CNTRL_REG, l_read)); size_t l_index = 0; - for (const auto& r : dp16Traits<TARGET_TYPE_MCA>::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<TARGET_TYPE_MCA>::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<fapi2::TARGET_TYPE_MCBIST // 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, 37382), DELAY_1US); + fapi2::delay(mss::cycles_to_ns(i_target, mss::FULL_DLL_CAL_DELAY), DELAY_1US); // 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. @@ -1570,10 +1573,32 @@ fapi2::ReturnCode dll_calibration( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST { fapi2::buffer<uint64_t> 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<fapi2::TARGET_TYPE_MCA> 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, @@ -697,6 +699,21 @@ inline void set_dll_cal_reset( fapi2::buffer<uint64_t>& o_data, const states i_s } /// +/// @brief Set the DLL cal skip reset +/// @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] i_value the value to write +/// +template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> > +inline void set_dll_cal_skip( fapi2::buffer<uint64_t>& io_data, const uint64_t i_value ) +{ + FAPI_INF("set_dll_cal_skip to %d", i_value); + io_data.insertFromRight<TT::DLL_CNTL_INIT_RXDLL_CAL_SKIP, + TT::DLL_CNTL_INIT_RXDLL_CAL_SKIP_LEN>(i_value); +} + +/// /// @brief Read DATA_BIT_DIR1 /// @tparam I DP16 instance /// @tparam T fapi2 Target Type - derived 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 @@ -391,6 +391,44 @@ fapi_try_exit: /// /// @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 /// @tparam TT traits type defaults to dp16Traits<T> /// Combine the processing of Good, Error and Error Fine into one functional interface @@ -402,32 +440,38 @@ fapi_try_exit: template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = pcTraits<T> > inline mss::states get_dll_cal_status( fapi2::buffer<uint64_t>& i_data ) { + // Lets check the cal status of the DPs first const bool l_dp_good = i_data.getBit<TT::DLL_CAL_STATUS_DP_GOOD>(); const bool l_dp_error = i_data.getBit<TT::DLL_CAL_STATUS_DP_ERROR>(); const bool l_dp_error_fine = i_data.getBit<TT::DLL_CAL_STATUS_DP_ERROR_FINE>(); + 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<TT::DLL_CAL_STATUS_ADR_GOOD>(); + const bool l_adr_error = i_data.getBit<TT::DLL_CAL_STATUS_ADR_ERROR>(); + const bool l_adr_error_fine = i_data.getBit<TT::DLL_CAL_STATUS_ADR_ERROR_FINE>(); + + 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; |