summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/phy
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/phy')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C57
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H17
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H64
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;
OpenPOWER on IntegriCloud