summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory
diff options
context:
space:
mode:
authorBrian Silver <bsilver@us.ibm.com>2016-06-22 11:14:04 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-07-13 14:21:12 -0400
commitf6f43282388298e9e2f6398b40c7fecbc99c62ff (patch)
treeae626b2ed5b6a6ec806bb515e6d615902a16c7fc /src/import/chips/p9/procedures/hwp/memory
parent1be7eab90246335fa2293ab5376643d5ec6873ce (diff)
downloadtalos-hostboot-f6f43282388298e9e2f6398b40c7fecbc99c62ff.tar.gz
talos-hostboot-f6f43282388298e9e2f6398b40c7fecbc99c62ff.zip
Add DLL Calibration
Add ADRS32{0,1} register API Add per-procedure ipl test (phy reset) Fix blastah, don't return current_err unchanged Change-Id: I4a76f74f8b7401af15ba1ae0b1823f61ad2ec050 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/26306 Tested-by: Jenkins Server Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Tested-by: Hostboot CI Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/26307 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.C26
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.H146
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C176
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H25
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C17
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.H91
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/phy_cntrl.H77
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/scom.H203
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_ddr_phy_reset.C11
9 files changed, 679 insertions, 93 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.C
index f49ad482b..ed7a10b07 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.C
@@ -16,3 +16,29 @@
/* deposited with the U.S. Copyright Office. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file adr32s.C
+/// @brief Subroutines for the PHY ADR32S registers
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: FSP:HB
+
+#include <fapi2.H>
+#include <lib/phy/adr32s.H>
+
+namespace mss
+{
+
+// Definition of the ADR32S DLL Config registers
+const std::vector<uint64_t> adr32sTraits<fapi2::TARGET_TYPE_MCA>::DLL_CNFG_REG =
+{
+ MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0,
+ MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S1
+};
+
+}
+
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.H
index e41a5a094..2294db408 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/adr32s.H
@@ -16,3 +16,149 @@
/* deposited with the U.S. Copyright Office. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file adr32s.H
+/// @brief Subroutines for the PHY ADR32S registers
+///
+// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 2
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_ADR32S_H_
+#define _MSS_ADR32S_H_
+
+#include <fapi2.H>
+#include <p9_mc_scom_addresses.H>
+#include <p9_mc_scom_addresses_fld.H>
+
+#include <lib/shared/mss_const.H>
+#include <lib/utils/scom.H>
+
+namespace mss
+{
+
+// I have a dream that the PHY code can be shared among controllers. So, I drive the
+// engine from a set of traits. This might be folly. Allow me to dream. BRS
+
+///
+/// @class adr32sTraits
+/// @brief a collection of traits associated with the PHY ADR32S interface
+/// @tparam T fapi2::TargetType representing the PHY
+///
+template< fapi2::TargetType T >
+class adr32sTraits;
+
+///
+/// @class adr32sTraits
+/// @brief a collection of traits associated with the Centaur PHY ADR32S interface
+///
+template<>
+class adr32sTraits<fapi2::TARGET_TYPE_MBA>
+{
+};
+
+///
+/// @class adr32sTraits
+/// @brief a collection of traits associated with the Nimbus PHY ADR32S
+///
+template<>
+class adr32sTraits<fapi2::TARGET_TYPE_MCA>
+{
+ public:
+
+ // Number of ADR32S units
+ static constexpr uint64_t ADR32S_COUNT = 2;
+
+ // MCA ADR32S control registers all come in pairs.
+ static const std::vector<uint64_t> DLL_CNFG_REG;
+
+ enum
+ {
+ DLL_CNTL_INIT_RXDLL_CAL_RESET = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_INIT_RXDLL_CAL_RESET,
+ DLL_CNTL_INIT_RXDLL_CAL_UPDATE = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_INIT_RXDLL_CAL_UPDATE,
+ DLL_CNTL_REGS_RXDLL_CAL_SKIP = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_REGS_RXDLL_CAL_SKIP,
+ DLL_CNTL_REGS_RXDLL_CAL_SKIP_LEN = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_REGS_RXDLL_CAL_SKIP_LEN,
+ DLL_CNTL_REGS_RXDLL_COARSE_ADJ_BY2 = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_REGS_RXDLL_COARSE_ADJ_BY2,
+ DLL_CNTL_RXREG_FILTER_LENGTH_DC = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_RXREG_FILTER_LENGTH_DC,
+ DLL_CNTL_RXREG_FILTER_LENGTH_DC_LEN = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_RXREG_FILTER_LENGTH_DC_LEN,
+ DLL_CNTL_RXREG_LEAD_LAG_SEPARATION_DC = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_RXREG_LEAD_LAG_SEPARATION_DC,
+ DLL_CNTL_RXREG_LEAD_LAG_SEPARATION_DC_LEN =
+ MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_RXREG_LEAD_LAG_SEPARATION_DC_LEN,
+ DLL_CNTL_EN_DRIVER_INVFB_DC = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_EN_DRIVER_INVFB_DC,
+ DLL_CNTL_RXREG_FINECAL_2XILSB_DC = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_RXREG_FINECAL_2XILSB_DC,
+ DLL_CNTL_CAL_GOOD = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_CAL_GOOD,
+ DLL_CNTL_CAL_ERROR = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_CAL_ERROR,
+ DLL_CNTL_CAL_ERROR_FINE = MCA_DDRPHY_ADR_DLL_CNTL_P0_ADR32S0_ADR0_CAL_ERROR_FINE,
+
+ };
+
+};
+
+namespace adr32s
+{
+
+///
+/// @brief Read DLL_CNTL
+/// @tparam I ADR32S instance e.g., 0 or 1 for a 64 bit implementation of the PHY
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to adr32sTraits<T>
+/// @param[in] i_target the fapi2 target of the port
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t I, fapi2::TargetType T, typename TT = adr32sTraits<T> >
+inline fapi2::ReturnCode read_dll_cntl( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ static_assert( I < TT::ADR32S_COUNT, "adr32s instance out of range");
+ FAPI_TRY( mss::getScom(i_target, TT::DLL_CNFG_REG[I], o_data) );
+ FAPI_INF("dll_cntl adrs32%d: 0x%016lx", I, o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Write DLL_CNTL_ADR32S0
+/// @tparam I ADR32S instance e.g., 0 or 1 for a 64 bit implementation of the PHY
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to adr32sTraits<T>
+/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t I, fapi2::TargetType T, typename TT = adr32sTraits<T> >
+inline fapi2::ReturnCode write_dll_cntl( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ static_assert( I < TT::ADR32S_COUNT, "adr32s instance out of range");
+ FAPI_INF("dll_cntl adr32s%d: 0x%016lx", I, i_data);
+ FAPI_TRY( mss::putScom(i_target, TT::DLL_CNFG_REG[I], i_data) );
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+//
+// Reseting the DLL registers TODO RTC:156518
+//
+
+///
+/// @brief Set the DLL cal reset (begins DLL cal operations)
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to adr32sTraits<T>
+/// @param[in] o_data the value of the register
+/// @param[in] i_state mss::LOW or mss::HIGH representing the state of the bit
+/// @note Default state is 'low' as writing a 0 forces the cal to begin.
+///
+template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = adr32sTraits<T> >
+inline void set_dll_cal_reset( fapi2::buffer<uint64_t>& o_data, const states i_state = mss::LOW )
+{
+ FAPI_INF("set_dll_cal_reset %s", (i_state == mss::LOW ? "low" : "high"));
+ o_data.writeBit<TT::DLL_CNTL_INIT_RXDLL_CAL_RESET>(i_state);
+}
+
+} // close namespace adr
+
+} // close namespace mss
+
+#endif
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 62c711f26..f0d5da547 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
@@ -37,8 +37,10 @@
#include <lib/phy/read_cntrl.H>
#include <lib/phy/phy_cntrl.H>
#include <lib/phy/apb.H>
+#include <lib/phy/adr32s.H>
#include <lib/utils/bit_count.H>
+#include <lib/utils/find.H>
#include <lib/utils/dump_regs.H>
#include <lib/utils/scom.H>
@@ -48,6 +50,7 @@ using fapi2::TARGET_TYPE_SYSTEM;
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;
+using fapi2::FAPI2_RC_SUCCESS;
namespace mss
{
@@ -176,91 +179,15 @@ fapi2::ReturnCode deassert_pll_reset( const fapi2::Target<TARGET_TYPE_MCBIST>& i
{
fapi2::buffer<uint64_t> l_data;
-#ifdef KNOW_ADR_DLL_PROCESS
- static const uint64_t dp16_lock_mask = 0x000000000000FFFE;
- static const uint64_t ad_lock_mask = fapi2::buffer<uint64_t>().setBit<48>().setBit<49>();
-#endif
-
//
// Write 0x4000 into the PC Resets Registers. This deasserts the PLL_RESET and leaves the SYSCLK_RESET bit active
- // (SCOM Addr: 0x8000C00E0301143F, 0x8001C00E0301143F, 0x8000C00E0301183F, 0x8001C00E0301183F)
+ //
+ // TODO RTC:156693 Do we need to do this on Nimbus? BRS
FAPI_DBG("Write 0x4000 into the PC Resets Regs. This deasserts the PLL_RESET and leaves the SYSCLK_RESET bit active");
l_data.setBit<MCA_DDRPHY_PC_RESETS_P0_SYSCLK_RESET>();
FAPI_TRY( mss::scom_blastah(mss::find_targets<TARGET_TYPE_MCA>(i_target), MCA_DDRPHY_PC_RESETS_P0, l_data) );
- //
- // Wait at least 1 millisecond to allow the PLLs to lock. Otherwise, poll the PC DP18 PLL Lock Status
- // and the PC AD32S PLL Lock Status to determine if all PLLs have locked.
- // PC DP18 PLL Lock Status should be 0xF800: (SCOM Addr: 0x8000C0000301143F, 0x8001C0000301143F, 0x8000C0000301183F, 0x8001C0000301183F)
- // PC AD32S PLL Lock Status should be 0xC000: (SCOM Addr: 0x8000C0010301143F, 0x8001C0010301143F, 0x8000C0010301183F, 0x8001C0010301183F)
-
-#ifdef KNOW_ADR_DLL_PROCESS
- // Poll for lock bits
- FAPI_DBG("Poll until DP18 and AD32S PLLs have locked");
-
- do
- {
- // Set in the CHECK_PLL macro
- done_polling = true;
-
- fapi2::delay(DELAY_1US, cycles_to_simcycles(us_to_cycles(i_target, 1)));
-
- // Note: in the latest scomdef this is DP16 BRS
- // Note: Not sure what the proper registers here are. I took the following old addresses from Ed's
- // version of the code and mapped the addresses to the latests mc_scom_addresses.H. This needs to
- // be fixed up when the extended addressing is fixed up. BRS
-
- // CONST_UINT64_T(DDRPHY_PC_DP18_PLL_LOCK_STATUS_P0_0x8000C0000701143F, ULL(0x8000C0000701143F) );
- CHECK_PLL( l_target_proc, MCA_0_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P0, l_data, dp16_lock_mask );
-
- // CONST_UINT64_T(DDRPHY_PC_DP18_PLL_LOCK_STATUS_P1_0x8001C0000701143F, ULL(0x8001C0000701143F) );
- CHECK_PLL( l_target_proc, MCA_1_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P1, l_data, dp16_lock_mask );
-
- // CONST_UINT64_T(DDRPHY_PC_DP18_PLL_LOCK_STATUS_P2_0x8000C0000701183F, ULL(0x8000C0000701183F) );
- CHECK_PLL( l_target_proc, MCA_2_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P2, l_data, dp16_lock_mask );
-
- // CONST_UINT64_T(DDRPHY_PC_DP18_PLL_LOCK_STATUS_P3_0x8001C0000701183F, ULL(0x8001C0000701183F) );
- CHECK_PLL( l_target_proc, MCA_3_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P3, l_data, dp16_lock_mask );
-
- // CONST_UINT64_T( DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P0_0x8000C0010701143F, ULL(0x8000C0010701143F) );
- CHECK_PLL( l_target_proc, MCA_0_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P0, l_data, ad_lock_mask );
-
- // CONST_UINT64_T( DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P1_0x8001C0010701143F, ULL(0x8001C0010701143F) );
- CHECK_PLL( l_target_proc, MCA_1_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P1, l_data, ad_lock_mask );
-
- // CONST_UINT64_T( DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P2_0x8000C0010701183F, ULL(0x8000C0010701183F) );
- CHECK_PLL( l_target_proc, MCA_2_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P2, l_data, ad_lock_mask );
-
- // CONST_UINT64_T( DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P3_0x8001C0010701183F, ULL(0x8001C0010701183F) );
- CHECK_PLL( l_target_proc, MCA_3_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P3, l_data, ad_lock_mask );
- }
- while (!done_polling && --max_poll_loops);
-
- // If we ran out of iterations, report we have a pll lock failure.
- if (max_poll_loops == 0)
- {
- FAPI_ERR("DDR PHY PLL failed to lock for %s", mss::c_str(i_target));
- FFDC_PLL( l_target_proc, MCA_0_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P0, l_data, dp16_lock_mask,
- fapi2::MSS_DP16_PLL_FAILED_TO_LOCK() );
- FFDC_PLL( l_target_proc, MCA_1_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P1, l_data, dp16_lock_mask,
- fapi2::MSS_DP16_PLL_FAILED_TO_LOCK() );
- FFDC_PLL( l_target_proc, MCA_2_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P2, l_data, dp16_lock_mask,
- fapi2::MSS_DP16_PLL_FAILED_TO_LOCK() );
- FFDC_PLL( l_target_proc, MCA_3_DDRPHY_PC_DP18_PLL_LOCK_STATUS_P3, l_data, dp16_lock_mask,
- fapi2::MSS_DP16_PLL_FAILED_TO_LOCK() );
-
- FFDC_PLL( l_target_proc, MCA_0_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P0, l_data, ad_lock_mask,
- fapi2::MSS_AD32S_PLL_FAILED_TO_LOCK() );
- FFDC_PLL( l_target_proc, MCA_1_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P1, l_data, ad_lock_mask,
- fapi2::MSS_AD32S_PLL_FAILED_TO_LOCK() );
- FFDC_PLL( l_target_proc, MCA_2_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P2, l_data, ad_lock_mask,
- fapi2::MSS_AD32S_PLL_FAILED_TO_LOCK() );
- FFDC_PLL( l_target_proc, MCA_3_DDRPHY_PC_AD32S_PLL_LOCK_STATUS_P3, l_data, ad_lock_mask,
- fapi2::MSS_AD32S_PLL_FAILED_TO_LOCK() );
- }
-
-#endif
fapi_try_exit:
return fapi2::current_err;
@@ -1107,5 +1034,98 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief Start the DLL calibration, monitor for fails.
+/// @param[in] i_target the target associated with this DLL cal
+/// @return FAPI2_RC_SUCCESS iff setup was successful
+///
+template<>
+fapi2::ReturnCode dll_calibration( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target )
+{
+ uint8_t is_sim = 0;
+ fapi2::buffer<uint64_t> l_status;
+ constexpr uint64_t l_dll_status_reg = pcTraits<TARGET_TYPE_MCA>::PC_DLL_ZCAL_CAL_STATUS_REG;
+ const auto& l_mca = mss::find_targets<TARGET_TYPE_MCA>(i_target);
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<TARGET_TYPE_SYSTEM>(), is_sim) );
+
+ // Nothing works here in cycle sim ...
+ if (is_sim)
+ {
+ return FAPI2_RC_SUCCESS;
+ }
+
+ // If we don't have any MCA, we can go
+ if (l_mca.size() == 0)
+ {
+ return FAPI2_RC_SUCCESS;
+ }
+
+ // 14. Begin DLL calibrations by setting INIT_RXDLL_CAL_RESET=0 in the DDRPHY_DP16_DLL_CNTL{0:1} registers
+ // and DDRPHY_ADR_DLL_CNTL registers
+ for (const auto& p : l_mca)
+ {
+ // 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;
+
+ 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)
+ {
+ adr32s::set_dll_cal_reset(b);
+ } );
+ FAPI_TRY(mss::scom_blastah(p, adr32sTraits<TARGET_TYPE_MCA>::DLL_CNFG_REG, i_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;
+
+ FAPI_TRY(mss::scom_suckah(p, dp16Traits<TARGET_TYPE_MCA>::DLL_CNFG_REG, i_read));
+ std::for_each( i_read.begin(), i_read.end(),
+ [](std::pair< fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> >& b)
+ {
+ dp16::set_dll_cal_reset(b.first);
+ dp16::set_dll_cal_reset(b.second);
+ } );
+ FAPI_TRY(mss::scom_blastah(p, dp16Traits<TARGET_TYPE_MCA>::DLL_CNFG_REG, i_read));
+ }
+ }
+
+ // 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, 37382), 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.
+ // To keep things simple, we'll poll for the change in one of the bits. Once that's completed, we'll
+ // check the others. If any one has failed, or isn't notifying complete, we'll pop out an error
+ mss::poll(l_mca[0], l_dll_status_reg, poll_parameters(),
+ [&l_status](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
+ {
+ FAPI_INF("phy control dll/zcal stat 0x%llx, remaining: %d", stat_reg, poll_remaining);
+ l_status = stat_reg;
+ return mss::pc::get_dll_cal_status(l_status) == mss::YES;
+ });
+
+ for (const auto& p : l_mca)
+ {
+ 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));
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
}
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H
index a1256cd6b..6b9010976 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.H
@@ -223,6 +223,31 @@ template<>
fapi2::ReturnCode reset_seq_rd_wr_data( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );
///
+/// @brief Perform the DLL calibration
+/// @tparam T the target type of the MCBIST
+/// @param[in] i_target the target associated with this DLL cal
+/// @return FAPI2_RC_SUCCESS iff setup was successful
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode dll_calibration( const fapi2::Target<T>& i_target );
+
+///
+/// @brief Perform the DLL calibration
+/// @param[in] i_target the target associated with this DLL cal
+/// @return FAPI2_RC_SUCCESS iff setup was successful
+///
+template<>
+fapi2::ReturnCode dll_calibration( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target );
+
+///
+/// @brief Setup seq_rd_wr_data
+/// @param[in] i_target the MCA target associated with this cal setup
+/// @return FAPI2_RC_SUCCESS iff setup was successful
+///
+template<>
+fapi2::ReturnCode reset_seq_rd_wr_data( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target );
+
+///
/// @brief Setup the PC CONFIG0 register
/// @tparam T the fapi2::TargetType
/// @param[in] i_target the target (MCA or MBA?)
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 180631291..803e9bdea 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
@@ -49,6 +49,20 @@ using fapi2::TARGET_TYPE_SYSTEM;
namespace mss
{
+// Definition of the DP16 DLL Config registers
+// DP16 DLL registers all come in pairs - DLL per 8 bits
+// 5 DLL per MCA gives us 10 DLL Config Registers.
+// All-caps (as opposed to the others) as it's really in the dp16Traits class which is app caps <shrug>)
+const std::vector< std::pair<uint64_t, uint64_t> > dp16Traits<TARGET_TYPE_MCA>::DLL_CNFG_REG =
+{
+ { MCA_DDRPHY_DP16_DLL_CNTL0_P0_0, MCA_DDRPHY_DP16_DLL_CNTL1_P0_0 },
+ { MCA_DDRPHY_DP16_DLL_CNTL0_P0_1, MCA_DDRPHY_DP16_DLL_CNTL1_P0_1 },
+ { MCA_DDRPHY_DP16_DLL_CNTL0_P0_2, MCA_DDRPHY_DP16_DLL_CNTL1_P0_2 },
+ { MCA_DDRPHY_DP16_DLL_CNTL0_P0_3, MCA_DDRPHY_DP16_DLL_CNTL1_P0_3 },
+ { MCA_DDRPHY_DP16_DLL_CNTL0_P0_4, MCA_DDRPHY_DP16_DLL_CNTL1_P0_4 },
+};
+
+
namespace dp16
{
@@ -288,7 +302,7 @@ fapi_try_exit:
///
fapi2::ReturnCode reset_sysclk( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target )
{
- std::vector< std::pair<uint64_t, uint64_t> > l_addrs(
+ static const std::vector< std::pair<uint64_t, uint64_t> > l_addrs(
{
{MCA_DDRPHY_DP16_SYSCLK_PR0_P0_0, MCA_DDRPHY_DP16_SYSCLK_PR1_P0_0},
{MCA_DDRPHY_DP16_SYSCLK_PR0_P0_1, MCA_DDRPHY_DP16_SYSCLK_PR1_P0_1},
@@ -393,6 +407,5 @@ fapi_try_exit:
return fapi2::current_err;
}
-
} // close namespace dp16
} // close namespace mss
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 754e4c16e..04ccb0a38 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
@@ -35,6 +35,7 @@
#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>
+#include <lib/utils/scom.H>
namespace mss
{
@@ -106,11 +107,101 @@ class dp16Traits<fapi2::TARGET_TYPE_MBA>
template<>
class dp16Traits<fapi2::TARGET_TYPE_MCA>
{
+
+ public:
+ // Number of DP instances
+ static constexpr uint64_t DP_COUNT = 5;
+
+ // 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.
+ static constexpr uint64_t DLL_PER_DP16 = 2;
+
+ // Vector of the DLL configuration registers. The pair represents the two DLL in per DP16
+ static const std::vector< std::pair<uint64_t, uint64_t> > DLL_CNFG_REG;
+
+ enum
+ {
+ DLL_CNTL_INIT_RXDLL_CAL_RESET = MCA_DDRPHY_DP16_DLL_CNTL0_P0_0_01_INIT_RXDLL_CAL_RESET,
+ };
};
namespace dp16
{
+///
+/// @brief Read DLL_CNTL
+/// @tparam I DP16 instance
+/// @tparam D DLL instance in the specified DP16
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to dp16Traits<T>
+/// @param[in] i_target the fapi2 target of the port
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t I, uint64_t D, fapi2::TargetType T, typename TT = dp16Traits<T> >
+inline fapi2::ReturnCode read_dll_cntl( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ static_assert( I < TT::DP_COUNT, "dp16 instance out of range");
+ static_assert( D < TT::DLL_PER_DP16, "dll instance out of range");
+
+ // The pair represents the upper and lower bytes of the DP16 - each has its own DLL regiters
+ const uint64_t& l_addr = (D == 0) ? TT::DLL_CNFG_REG[I].first : TT::DLL_CNFG_REG[I].second;
+
+ FAPI_TRY( mss::getScom(i_target, l_addr, o_data) );
+ FAPI_INF("dll_cntl dp16<%d, %d>: 0x%016lx", I, D, o_data);
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+///
+/// @brief Write DLL_CNTL
+/// @tparam I DP16 instance
+/// @tparam D DLL instance in the specified DP16
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to dp16Traits<T>
+/// @param[in] i_target the fapi2 target of the port
+/// @param[in] i_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< uint64_t I, uint64_t D, fapi2::TargetType T, typename TT = dp16Traits<T> >
+inline fapi2::ReturnCode write_dll_cntl( const fapi2::Target<T>& i_target, const fapi2::buffer<uint64_t>& i_data )
+{
+ static_assert( I < TT::DP_COUNT, "dp16 instance out of range");
+ static_assert( D < TT::DLL_PER_DP16, "dll instance out of range");
+
+ // The pair represents the upper and lower bytes of the DP16 - each has its own DLL regiters
+ const uint64_t& l_addr = (D == 0) ? TT::DLL_CNFG_REG[I].first : TT::DLL_CNFG_REG[I].second;
+
+ FAPI_INF("dll_cntl dp16<%d,%d>: 0x%016lx", I, D, i_data);
+ FAPI_TRY( mss::putScom(i_target, l_addr, i_data) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+
+}
+
+//
+// Reseting the DLL registers TODO RTC:156518
+//
+
+///
+/// @brief Set the DLL cal reset (begins DLL cal operations)
+/// @tparam T fapi2 Target Type - derived
+/// @tparam TT traits type defaults to dp16Traits<T>
+/// @param[in] o_data the value of the register
+/// @param[in] i_state mss::LOW or mss::HIGH representing the state of the bit
+/// @note Default state is 'low' as writing a 0 forces the cal to begin.
+///
+template< fapi2::TargetType T = fapi2::TARGET_TYPE_MCA, typename TT = dp16Traits<T> >
+inline void set_dll_cal_reset( fapi2::buffer<uint64_t>& o_data, const states i_state = mss::LOW )
+{
+ FAPI_INF("set_dll_cal_reset %s", (i_state == mss::LOW ? "low" : "high"));
+ o_data.writeBit<TT::DLL_CNTL_INIT_RXDLL_CAL_RESET>(i_state);
+}
+
///
/// @brief Configure the DP16 sysclk
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 3c6df4529..978eee23a 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
@@ -67,6 +67,7 @@ class pcTraits<fapi2::TARGET_TYPE_MCA>
// MCA phy control registers
static const uint64_t PC_ERROR_STATUS0_REG = MCA_DDRPHY_PC_ERROR_STATUS0_P0;
static const uint64_t PC_INIT_CAL_ERROR_REG = MCA_DDRPHY_PC_INIT_CAL_ERROR_P0;
+ static const uint64_t PC_DLL_ZCAL_CAL_STATUS_REG = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0;
enum
{
@@ -88,6 +89,15 @@ class pcTraits<fapi2::TARGET_TYPE_MCA>
// How many bits are in the field running from INIT_CAL_ERROR_WR_LEVEL to INIT_CAL_ERROR_VREF
// Needed to pull the entire field out of the register.
CAL_ERROR_FIELD_LEN = 11,
+
+ DLL_CAL_STATUS_DP_GOOD = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0_DP_GOOD,
+ DLL_CAL_STATUS_DP_ERROR = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0_DP_ERROR,
+ DLL_CAL_STATUS_DP_ERROR_FINE = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0_DP_ERROR_FINE,
+ DLL_CAL_STATUS_ADR_GOOD = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0_ADR_GOOD,
+ DLL_CAL_STATUS_ADR_ERROR = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0_ADR_ERROR,
+ DLL_CAL_STATUS_ADR_ERROR_FINE = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0_ADR_ERROR_FINE,
+ ZCAL_CAL_STATUS_DONE = MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS_P0_DONE,
+
};
};
@@ -97,6 +107,65 @@ namespace pc
///
+/// @brief read MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS
+/// @param[in] i_target the fapi2 target of the port
+/// @param[out] o_data the value of the register
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok
+///
+template< fapi2::TargetType T, typename TT = pcTraits<T> >
+inline fapi2::ReturnCode read_dll_zcal_status( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
+{
+ FAPI_TRY( mss::getScom(i_target, TT::PC_DLL_ZCAL_CAL_STATUS_REG, o_data) );
+ FAPI_INF("pc_dll_zcal_status: 0x%016llx", o_data);
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Get DP DLL Cal Status
+/// Combine the processing of Good, Error and Error Fine into one functional interface
+/// @param[in] fapi2::buffer representing the status register to interrogate
+/// @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.
+///
+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 )
+{
+ 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>();
+
+ 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))
+ {
+ 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))
+ {
+ return mss::YES;
+ }
+
+ // 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))
+ {
+ return mss::NO;
+ }
+
+ // Not reached ... right?
+ FAPI_ERR("pc_dll_cal_status: 0x%016llx unable to calculate state", i_data);
+ fapi2::Assert(false);
+ return mss::NO;
+}
+
+// MCA_DDRPHY_PC_DLL_ZCAL_CAL_STATUS is read-only
+
+///
/// @brief read PC_ERROR_STATUS0
/// @param[in] i_target the fapi2 target of the port
/// @param[out] o_data the value of the register
@@ -106,7 +175,7 @@ template< fapi2::TargetType T, typename TT = pcTraits<T> >
inline fapi2::ReturnCode read_error_status0( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
{
FAPI_TRY( mss::getScom(i_target, TT::PC_ERROR_STATUS0_REG, o_data) );
- FAPI_DBG("pc_error_status0: 0x%016llx", o_data);
+ FAPI_INF("pc_error_status0: 0x%016llx", o_data);
fapi_try_exit:
return fapi2::current_err;
}
@@ -121,7 +190,7 @@ template< fapi2::TargetType T, typename TT = pcTraits<T> >
inline fapi2::ReturnCode write_error_status0( const fapi2::Target<T>& i_target,
const fapi2::buffer<uint64_t>& i_data )
{
- FAPI_DBG("pc_error_status0: 0x%016llx", i_data);
+ FAPI_INF("pc_error_status0: 0x%016llx", i_data);
FAPI_TRY( mss::putScom(i_target, TT::PC_ERROR_STATUS0_REG, i_data) );
fapi_try_exit:
return fapi2::current_err;
@@ -151,7 +220,7 @@ template< fapi2::TargetType T, typename TT = pcTraits<T> >
inline fapi2::ReturnCode read_init_cal_error( const fapi2::Target<T>& i_target, fapi2::buffer<uint64_t>& o_data )
{
FAPI_TRY( mss::getScom(i_target, TT::PC_INIT_CAL_ERROR_REG, o_data) );
- FAPI_DBG("pc_init_cal_error: 0x%016llx", o_data);
+ FAPI_INF("pc_init_cal_error: 0x%016llx", o_data);
fapi_try_exit:
return fapi2::current_err;
}
@@ -166,7 +235,7 @@ template< fapi2::TargetType T, typename TT = pcTraits<T> >
inline fapi2::ReturnCode write_init_cal_error( const fapi2::Target<T>& i_target,
const fapi2::buffer<uint64_t>& i_data )
{
- FAPI_DBG("pc_init_cal_error: 0x%016llx", i_data);
+ FAPI_INF("pc_init_cal_error: 0x%016llx", i_data);
FAPI_TRY( mss::putScom(i_target, TT::PC_INIT_CAL_ERROR_REG, i_data) );
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/scom.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/scom.H
index 109a9a414..324bd9884 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/scom.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/scom.H
@@ -54,7 +54,8 @@ namespace mss
/// @note We wrap scom operations in the mss library so that we can hook
/// into them in the lab. For IPL firmware, this should compile out.
template< fapi2::TargetType K >
-inline fapi2::ReturnCode getScom(const fapi2::Target<K>& i_target, const uint64_t i_address,
+inline fapi2::ReturnCode getScom(const fapi2::Target<K>& i_target,
+ const uint64_t i_address,
fapi2::buffer<uint64_t>& o_data)
{
#ifdef PSYSTEMS_MSS_LAB_ONLY
@@ -74,7 +75,8 @@ inline fapi2::ReturnCode getScom(const fapi2::Target<K>& i_target, const uint64_
/// @note We wrap scom operations in the mss library so that we can hook
/// into them in the lab. For IPL firmware, this should compile out.
template< fapi2::TargetType K >
-inline fapi2::ReturnCode putScom(const fapi2::Target<K>& i_target, const uint64_t i_address,
+inline fapi2::ReturnCode putScom(const fapi2::Target<K>& i_target,
+ const uint64_t i_address,
const fapi2::buffer<uint64_t> i_data)
{
#ifdef PSYSTEMS_MSS_LAB_ONLY
@@ -120,7 +122,8 @@ inline fapi2::ReturnCode putScomUnderMask(const fapi2::Target<K>& i_target,
/// and the FAPI_TRY mechanism, this is the simplest.
///
template< fapi2::TargetType T >
-fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_target, const std::vector<uint64_t>& i_addrs,
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_target,
+ const std::vector<uint64_t>& i_addrs,
const fapi2::buffer<uint64_t>& i_data )
{
size_t count(0);
@@ -131,7 +134,8 @@ fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_target, const std::vec
++count;
}
- return fapi2::current_err;
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
FAPI_ERR( "scom_blastah failed: %d of %d executed against %s", count, i_addrs.size(), mss::c_str(i_target));
@@ -140,13 +144,14 @@ fapi_try_exit:
///
/// @brief Blast one peice of data across a vector of targets
-/// @param[in]i_targets the vector of targets for the scom
+/// @param[in] i_targets the vector of targets for the scom
/// @param[in] i_addr the address
/// @param[in] i_data const fapi2::buffer<uint64_t>& the data to blast
/// @return FAPI2_RC_SUCCESS iff ok
///
template< fapi2::TargetType T >
-fapi2::ReturnCode scom_blastah( const std::vector<fapi2::Target<T> >& i_targets, const uint64_t i_addr,
+fapi2::ReturnCode scom_blastah( const std::vector<fapi2::Target<T> >& i_targets,
+ const uint64_t i_addr,
const fapi2::buffer<uint64_t>& i_data )
{
size_t count(0);
@@ -157,7 +162,8 @@ fapi2::ReturnCode scom_blastah( const std::vector<fapi2::Target<T> >& i_targets,
++count;
}
- return fapi2::current_err;
+ // Don't return current_err, if there are no targets in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
FAPI_ERR( "scom_blastah failed: %d of %d written to 0x%llx", count, i_targets.size(), i_addr);
@@ -166,7 +172,7 @@ fapi_try_exit:
///
/// @brief Blast one peice of data across a vector of targets
-/// @param[in]i_targets the vector of targets for the scom
+/// @param[in] i_targets the vector of targets for the scom
/// @param[in] i_addrs the vector of addresses
/// @param[in] i_data const fapi2::buffer<uint64_t>& the data to blast
/// @return FAPI2_RC_SUCCESS iff ok
@@ -184,13 +190,192 @@ fapi2::ReturnCode scom_blastah( const std::vector<fapi2::Target<T> >& i_targets,
++count;
}
- return fapi2::current_err;
+ // Don't return current_err, if there are no targets in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
FAPI_ERR( "scom_blastah failed: %d of %dx%d", count, i_targets.size(), i_addrs.size() );
return fapi2::current_err;
}
+///
+/// @brief Blast parallel vectors of data and addresses to a single target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addrs const std::vector<uint64_t>& addresses
+/// @param[in] i_data std:vector<fapi2::buffer<uint64_t>>& the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_targets,
+ const std::vector<uint64_t>& i_addrs,
+ const std::vector<fapi2::buffer<uint64_t>>& i_data )
+{
+ size_t count(0);
+
+ // Little sanity check
+ if (i_data.size() != i_addrs.size())
+ {
+ FAPI_ERR("Passed bad vectors in to scom_blastah: %d and %d in size", i_data.size(), i_addrs.size() );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ }
+
+ auto l_address = i_addrs.begin();
+ auto l_data = i_data.begin();
+
+ for ( ; l_address != i_addrs.end(); ++l_address, ++l_data )
+ {
+ FAPI_TRY( mss::putScom(i_targets, *l_address, *l_data) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "parallel scom_blastah failed: %d of %d", count, i_addrs.size() );
+ return fapi2::current_err;
+}
+
+///
+/// @brief Blast parallel vectors of data and address pairs to a single target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addrs const std::vector<uint64_t>& of address pairs
+/// @param[in] i_data std::vector< std::pair<uint64_t, uint64_t>> the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_targets,
+ const std::vector< std::pair< uint64_t, uint64_t> >& i_addrs,
+ const std::vector< std::pair<fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > >& i_data )
+{
+ size_t count(0);
+
+ // Little sanity check
+ if (i_data.size() != i_addrs.size())
+ {
+ FAPI_ERR("Passed bad vectors of pairs in to scom_blastah: %d and %d in size", i_data.size(), i_addrs.size() );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ }
+
+ auto l_address = i_addrs.begin();
+ auto l_data = i_data.begin();
+
+ for ( ; l_address != i_addrs.end(); ++l_address, ++l_data )
+ {
+ FAPI_TRY( mss::putScom(i_targets, l_address->first, l_data->first) );
+ FAPI_TRY( mss::putScom(i_targets, l_address->second, l_data->second) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "parallel pairs scom_blastah failed: %d of %d", count, i_addrs.size() );
+ return fapi2::current_err;
+}
+
+///
+/// @brief Blast single data data to a vector of address pairs to a single target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addrs const std::vector< std::pair<uint64_t, uint64_t> >& of address pairs
+/// @param[in] i_data uint64_t the data to blast
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_blastah( const fapi2::Target<T>& i_targets,
+ const std::vector< std::pair< uint64_t, uint64_t> >& i_addr,
+ const fapi2::buffer<uint64_t>& i_data )
+{
+ size_t count(0);
+
+ for (auto a = i_addr.begin(); a != i_addr.end(); ++a)
+ {
+ FAPI_TRY( mss::putScom(i_targets, a->first, i_data) );
+ FAPI_TRY( mss::putScom(i_targets, a->second, i_data) );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "pairs scom_blastah failed: %d of %d", count, i_addr.size() );
+ return fapi2::current_err;
+}
+
+///
+/// @brief Suck one peice of data from a vector of addresses
+/// @tparam T the fapi2::TargetType of the target
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addr the vector of addresses
+/// @param[in] o_data std::vector<uint64_t> the resulting data
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Author is originally from Boston (Pahk mah cah in Havahd Yahd)
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_suckah( const fapi2::Target<T>& i_target,
+ const std::vector<uint64_t>& i_addr,
+ std::vector< fapi2::buffer<uint64_t> >& o_data )
+{
+ size_t count(0);
+ fapi2::buffer<uint64_t> l_read;
+
+ o_data.clear();
+
+ for (const auto& a : i_addr)
+ {
+ FAPI_TRY( mss::getScom(i_target, a, l_read) );
+ o_data.push_back(l_read);
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "scom_suckah failed: %d of %d executed against %s", count, i_addr.size(), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Suck one peice of data from a vector of address pairs
+/// @tparam T the fapi2::TargetType of the target
+/// @tparam B a begin iterator
+/// @tparam E an end iterator
+/// @param[in] i_target the target for the scom
+/// @param[in] i_addr a vector of address pairs
+/// @param[in] o_data std::vector< std::pair<uint64_t, uint64_t>> the resulting data
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note Author is originally from Boston (Pahk mah cah in Havahd Yahd)
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode scom_suckah( const fapi2::Target<T>& i_target,
+ const std::vector< std::pair< uint64_t, uint64_t> >& i_addr,
+ std::vector< std::pair<fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > >& o_data )
+{
+ size_t count(0);
+ std::pair< fapi2::buffer<uint64_t>, fapi2::buffer<uint64_t> > l_read;
+
+ o_data.clear();
+
+ for (const auto& a : i_addr)
+ {
+ FAPI_TRY( mss::getScom(i_target, a.first, l_read.first) );
+ FAPI_TRY( mss::getScom(i_target, a.second, l_read.second) );
+ o_data.push_back( l_read );
+ ++count;
+ }
+
+ // Don't return current_err, if there are no registers in the vector we don't set it.
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ FAPI_ERR( "scom_suckah failed: %d of %d executed against %s", count, i_addr.size(), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
}
#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 7d1821b4c..57607a8ea 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
@@ -77,6 +77,17 @@ extern "C"
FAPI_TRY( mss::deassert_pll_reset(i_target) );
//
+ // DLL calibration
+ //
+
+ // 14. Begin DLL calibrations by setting INIT_RXDLL_CAL_RESET=0 in the DDRPHY_DP16_DLL_CNTL{0:1} registers
+ // 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) );
+
+ //
// Start bang-bang-lock
//
OpenPOWER on IntegriCloud