summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C10
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.C115
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dll_workarounds.H20
-rw-r--r--src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml2
4 files changed, 124 insertions, 23 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 da960bac9..66c1e9af5 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
@@ -52,6 +52,7 @@
#include <lib/workarounds/wr_vref_workarounds.H>
#include <lib/dimm/ddr4/latch_wr_vref.H>
#include <lib/workarounds/seq_workarounds.H>
+#include <lib/workarounds/dll_workarounds.H>
#include <lib/workarounds/dqs_align_workarounds.H>
#include <lib/phy/mss_training.H>
@@ -1515,14 +1516,7 @@ fapi2::ReturnCode dll_calibration( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST
for (const auto& p : l_mca)
{
- fapi2::buffer<uint64_t> l_read;
- FAPI_TRY( mss::getScom(p, l_dll_status_reg, l_read) );
-
- // For all Nimbus parts we want to run DLL workaround so
- // Instead of using FAPI_ASSERT or returning an error
- // We'll use a bool to tell if we need to run the workaround
- o_run_workaround |= (mss::pc::get_dll_cal_status(l_read) != mss::YES);
-
+ FAPI_TRY( mss::workarounds::dll::needed(p, o_run_workaround) );
}// mca
fapi_try_exit:
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 647ec0a36..73c9c3516 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
@@ -37,6 +37,7 @@
#include <generic/memory/lib/utils/scom.H>
#include <lib/phy/dp16.H>
#include <lib/fir/fir.H>
+#include <lib/phy/phy_cntrl.H>
#include <lib/shared/mss_const.H>
#include <lib/utils/conversions.H>
@@ -142,12 +143,68 @@ namespace dll
{
///
+/// @brief Check if workaround is needed
+/// @param[in] i_target the MCA target
+/// @param[in,out] io_run_workaround set to true if workaround is needed
+/// @return FAPI2_RC_SUCCESS if the scoms don't fail
+///
+fapi2::ReturnCode needed( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ bool& io_run_workaround )
+{
+ constexpr uint64_t l_dll_status_reg = mss::pcTraits<fapi2::TARGET_TYPE_MCA>::PC_DLL_ZCAL_CAL_STATUS_REG;
+ constexpr uint64_t BAD_VREG_VALUE = 1;
+
+ // VREG_COARSE registers. If any of these have a value of '1' after calibration, the workaround
+ // will need to be triggered, since Vreg=1 is not a good value for any process window.
+ // Note these are the same registers that are used in the workaround.
+ static const std::vector<uint64_t> DLL_VREG =
+ {
+ MCA_DDRPHY_ADR_DLL_VREG_COARSE_P0_ADR32S0,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_1,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_2,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_3,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_4,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_0,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_1,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_2,
+ MCA_DDRPHY_DP16_DLL_VREG_COARSE1_P0_3,
+ };
+
+ fapi2::buffer<uint64_t> l_cal_status;
+ std::vector<fapi2::buffer<uint64_t>> l_vreg_values;
+
+ // For all Nimbus parts we want to run DLL workaround so
+ // Instead of using FAPI_ASSERT or returning an error
+ // We'll use a bool to tell if we need to run the workaround
+ // First check the DLL cal status - if it failed, we run the workaround
+ FAPI_TRY( mss::getScom(i_target, l_dll_status_reg, l_cal_status) );
+ io_run_workaround |= (mss::pc::get_dll_cal_status(l_cal_status) != mss::YES);
+
+ // Next check if any Vreg got set to the value '1' - if we see any, run the workaround
+ FAPI_TRY( mss::scom_suckah(i_target, DLL_VREG, l_vreg_values) );
+
+ for (const auto l_buf : l_vreg_values)
+ {
+ uint64_t l_vreg_value = 0;
+
+ // Note that the fields are the same for the ADR and DP16 registers
+ l_buf.extractToRight< MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0_01_REGS_RXDLL_DAC_COARSE, MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0_01_REGS_RXDLL_DAC_COARSE_LEN >
+ (l_vreg_value);
+ io_run_workaround |= (l_vreg_value == BAD_VREG_VALUE);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
/// @brief Clears the DLL firs
/// @param[in] i_target the MCA target
/// @return FAPI2_RC_SUCCESS if the scoms don't fail
/// @note Need to clear the DLL firs when we notice a DLL fail for workarounds
///
-fapi2::ReturnCode clear_dll_fir( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target )
+fapi2::ReturnCode clear_dll_fir( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target )
{
fapi2::buffer<uint64_t> l_phyfir_data;
@@ -169,19 +226,41 @@ fapi_try_exit:
}
///
-/// @brief Checks if CAL_ERROR and CAL_ERROR_FINE bits are set
+/// @brief Checks if CAL_ERROR and CAL_ERROR_FINE bits are set, or if VREG is '1'
+/// @param[in] i_target the fapi2 target
/// @param[in] i_dll_cntrl_data DLL CNTRL data
-/// @return true if DLL cal failed, false otherwiae
+/// @param[in] i_map dll map of DLLs to log errors from
+/// @param[out] o_failed set to true if DLL cal failed
///
-bool did_cal_fail( const fapi2::buffer<uint64_t>& i_dll_cntrl_data )
+fapi2::ReturnCode did_cal_fail( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const mss::dll_map& i_map,
+ const fapi2::buffer<uint64_t>& i_dll_cntrl_data,
+ bool& o_failed )
{
+ constexpr uint64_t BAD_VREG_VALUE = 1;
+
+ fapi2::buffer<uint64_t> l_dll_dac_data;
+ uint64_t l_dac_coarse = 0;
+
FAPI_DBG("DLL_CNTL data 0x%016llx, CAL_ERROR %d, CAL_ERROR_FINE %d",
i_dll_cntrl_data,
i_dll_cntrl_data.getBit<mss::dll_map::DLL_CNTL_CAL_ERROR>(),
i_dll_cntrl_data.getBit<mss::dll_map::DLL_CNTL_CAL_ERROR_FINE>());
- return i_dll_cntrl_data.getBit<mss::dll_map::DLL_CNTL_CAL_ERROR>() ||
- i_dll_cntrl_data.getBit<mss::dll_map::DLL_CNTL_CAL_ERROR_FINE>();
+ o_failed = i_dll_cntrl_data.getBit<mss::dll_map::DLL_CNTL_CAL_ERROR>() ||
+ i_dll_cntrl_data.getBit<mss::dll_map::DLL_CNTL_CAL_ERROR_FINE>();
+
+ // Read DAC coarse from DLL, and set failed if value is '1'
+ FAPI_TRY( mss::getScom(i_target, i_map.iv_vreg_coarse_same_dll, l_dll_dac_data),
+ "Failed getScom() operation on %s reg 0x%016llx",
+ mss::c_str(i_target), i_map.iv_vreg_coarse_same_dll );
+
+ l_dll_dac_data.extractToRight< MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0_01_REGS_RXDLL_DAC_COARSE, MCA_DDRPHY_DP16_DLL_VREG_COARSE0_P0_0_01_REGS_RXDLL_DAC_COARSE_LEN >
+ (l_dac_coarse);
+ o_failed |= (l_dac_coarse == BAD_VREG_VALUE);
+
+fapi_try_exit:
+ return fapi2::current_err;
}
///
@@ -200,6 +279,8 @@ fapi2::ReturnCode log_fails(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_targe
std::map< fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> >& io_failed_dll_dac)
{
fapi2::buffer<uint64_t> l_dll_cntrl_data;
+ bool l_failed = false;
+
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);
@@ -207,7 +288,9 @@ fapi2::ReturnCode log_fails(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_targe
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) )
+ FAPI_TRY( did_cal_fail(i_target, i_map, l_dll_cntrl_data, l_failed) );
+
+ if( l_failed )
{
fapi2::buffer<uint64_t> l_dll_dac_data;
uint64_t l_neighbor_dac_coarse = 0;
@@ -265,11 +348,19 @@ fapi2::ReturnCode check_status(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_ta
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) )
+ for( const auto& map : DLL_REGS )
+ {
+ bool l_failed = false;
+ FAPI_TRY( did_cal_fail(i_target, map, l_dll_cntrl_data, l_failed) );
+
+ FAPI_ASSERT( l_failed == false,
+ fapi2::MSS_DLL_FAILED_TO_CALIBRATE()
+ .set_MCA_IN_ERROR(i_target)
+ .set_CNTRL_REG(map.iv_cntrl)
+ .set_VREG_COARSE_REG(map.iv_vreg_coarse_same_dll),
+ "%s DLL failed to calibrate",
+ mss::c_str(i_target) );
+ }
}
return fapi2::FAPI2_RC_SUCCESS;
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 cc82cd4d4..d1911143a 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
@@ -92,6 +92,15 @@ namespace dll
{
///
+/// @brief Check if workaround is needed
+/// @param[in] i_target the MCA target
+/// @param[in,out] io_run_workaround set to true if workaround is needed
+/// @return FAPI2_RC_SUCCESS if the scoms don't fail
+///
+fapi2::ReturnCode needed( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ bool& io_run_workaround );
+
+///
/// @brief Clears the DLL firs
/// @param[in] i_target the MCA target
/// @return returns true unless if scom errors
@@ -99,11 +108,16 @@ namespace dll
fapi2::ReturnCode clear_dll_fir( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );
///
-/// @brief Checks if CAL_ERROR and CAL_ERROR_FINE bits are set
+/// @brief Checks if CAL_ERROR and CAL_ERROR_FINE bits are set, or if VREG is '1'
+/// @param[in] i_target the fapi2 target
/// @param[in] i_dll_cntrl_data DLL CNTRL data
-/// @return bool
+/// @param[in] i_map dll map of DLLs to log errors from
+/// @param[out] o_failed set to true if DLL cal failed
///
-bool did_cal_fail( const fapi2::buffer<uint64_t>& i_dll_cntrl_data );
+fapi2::ReturnCode did_cal_fail( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ const mss::dll_map& i_map,
+ const fapi2::buffer<uint64_t>& i_dll_cntrl_data,
+ bool& o_failed );
///
/// @brief Logs DLL error mappings from failed DLLs
diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml
index 78491442e..a64dfde9f 100644
--- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml
+++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_ddr_phy_reset.xml
@@ -267,6 +267,8 @@
<description>
DLL failed to calibrate
</description>
+ <ffdc>CNTRL_REG</ffdc>
+ <ffdc>VREG_COARSE_REG</ffdc>
<collectRegisterFfdc>
<id>REG_FFDC_DLL_REGS</id>
<target>MCA_IN_ERROR</target>
OpenPOWER on IntegriCloud