summaryrefslogtreecommitdiffstats
path: root/src/import/chips
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/chips')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C32
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C31
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H201
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H2
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C36
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/read_cntrl.H8
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H2
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/termination/slew_cal.C503
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H31
9 files changed, 278 insertions, 568 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C
index b4ce1a6b7..540ae5b8c 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs_load_ddr4.C
@@ -37,6 +37,7 @@
#include <mss.H>
#include <lib/dimm/ddr4/mrs_load_ddr4.H>
+#include <lib/eff_config/timing.H>
using fapi2::TARGET_TYPE_MCBIST;
using fapi2::TARGET_TYPE_DIMM;
@@ -60,31 +61,26 @@ fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
{
FAPI_INF("ddr4::mrs_load %s", mss::c_str(i_target));
- // Per DDR4 Full spec update (79-4A) - timing requirements
- constexpr uint64_t tMRD = 8;
- constexpr uint64_t tZQinit = 1024;
- uint64_t l_freq = 0;
- uint64_t tDLLK = 0;
fapi2::buffer<uint16_t> l_cal_steps;
+ uint64_t tDLLK = 0;
static std::vector< mrs_data<TARGET_TYPE_MCBIST> > l_mrs_data =
{
// JEDEC ordering of MRS per DDR4 power on sequence
- { 3, mrs03, mrs03_decode, tMRD },
- { 6, mrs06, mrs06_decode, tMRD },
- { 5, mrs05, mrs05_decode, tMRD },
- { 4, mrs04, mrs04_decode, tMRD },
- { 2, mrs02, mrs02_decode, tMRD },
- { 1, mrs01, mrs01_decode, tMRD },
- { 0, mrs00, mrs00_decode, tMRD },
+ { 3, mrs03, mrs03_decode, mss::tmrd() },
+ { 6, mrs06, mrs06_decode, mss::tmrd() },
+ { 5, mrs05, mrs05_decode, mss::tmrd() },
+ { 4, mrs04, mrs04_decode, mss::tmrd() },
+ { 2, mrs02, mrs02_decode, mss::tmrd() },
+ { 1, mrs01, mrs01_decode, mss::tmrd() },
+
+ // We need to wait either tmod or tmrd before zqcl.
+ { 0, mrs00, mrs00_decode, std::max(mss::tmrd(), mss::tmod(i_target)) },
};
std::vector< uint64_t > l_ranks;
FAPI_TRY( mss::ranks(i_target, l_ranks) );
-
- // Calculate tDLLK from our frequency. Magic numbers (in clocks) from the DDR4 spec
- FAPI_TRY( mss::freq(mss::find_target<TARGET_TYPE_MCBIST>(i_target), l_freq) );
- tDLLK = (l_freq < fapi2::ENUM_ATTR_MSS_FREQ_MT2133) ? 597 : 768;
+ FAPI_TRY( mss::tdllk(i_target, tDLLK) );
// Load MRS
for (const auto& d : l_mrs_data)
@@ -141,9 +137,9 @@ fapi2::ReturnCode mrs_load( const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
l_inst_b_side = mss::address_invert(l_inst_a_side);
l_inst_a_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
- MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + tZQinit);
+ MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + mss::tzqinit());
l_inst_b_side.arr1.insertFromRight<MCBIST_CCS_INST_ARR1_00_IDLES,
- MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + tZQinit);
+ MCBIST_CCS_INST_ARR1_00_IDLES_LEN>(tDLLK + mss::tzqinit());
// There's nothing to decode here.
FAPI_INF("ZQCL 0x%016llx:0x%016llx %s:rank %d a-side",
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C
index ef7f77392..a1f57e489 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rcd_load_ddr4.C
@@ -59,28 +59,29 @@ fapi2::ReturnCode rcd_load_ddr4( const fapi2::Target<TARGET_TYPE_DIMM>& i_target
{
FAPI_INF("rcd_load_ddr4 %s", mss::c_str(i_target));
- // Per DDR4RCD02 table 104 - timing requirements
- static const uint64_t tMRD = 8;
- static const uint64_t tMRD_L = 16;
-
- // Per DDR4RCD02, tSTAB is 5us. We want this in cycles for the CCS.
- const uint64_t tSTAB = mss::us_to_cycles(i_target, 5);
+ // Per DDR4RCD02, tSTAB is us. We want this in cycles for the CCS.
+ const uint64_t tSTAB = mss::us_to_cycles(i_target, mss::tstab());
static std::vector< rcd_data > l_rcd_4bit_data =
{
- { 0, eff_dimm_ddr4_rc00, tMRD }, { 1, eff_dimm_ddr4_rc01, tMRD }, { 2, eff_dimm_ddr4_rc02, tSTAB },
- { 3, eff_dimm_ddr4_rc03, tMRD_L}, { 4, eff_dimm_ddr4_rc04, tMRD_L}, { 5, eff_dimm_ddr4_rc05, tMRD_L},
- { 6, eff_dimm_ddr4_rc06_07, tMRD }, { 8, eff_dimm_ddr4_rc08, tMRD }, { 9, eff_dimm_ddr4_rc09, tMRD },
- { 10, eff_dimm_ddr4_rc10, tSTAB }, { 11, eff_dimm_ddr4_rc11, tMRD }, { 12, eff_dimm_ddr4_rc12, tMRD },
- { 13, eff_dimm_ddr4_rc13, tMRD }, { 14, eff_dimm_ddr4_rc14, tMRD }, { 15, eff_dimm_ddr4_rc15, tMRD },
+ { 0, eff_dimm_ddr4_rc00, mss::tmrd() }, { 1, eff_dimm_ddr4_rc01, mss::tmrd() },
+ { 2, eff_dimm_ddr4_rc02, tSTAB }, { 3, eff_dimm_ddr4_rc03, mss::tmrd_l() },
+ { 4, eff_dimm_ddr4_rc04, mss::tmrd_l() }, { 5, eff_dimm_ddr4_rc05, mss::tmrd_l() },
+ { 6, eff_dimm_ddr4_rc06_07, mss::tmrd() }, { 8, eff_dimm_ddr4_rc08, mss::tmrd() },
+ { 9, eff_dimm_ddr4_rc09, mss::tmrd() }, { 10, eff_dimm_ddr4_rc10, tSTAB },
+ { 11, eff_dimm_ddr4_rc11, mss::tmrd() }, { 12, eff_dimm_ddr4_rc12, mss::tmrd() },
+ { 13, eff_dimm_ddr4_rc13, mss::tmrd() }, { 14, eff_dimm_ddr4_rc14, mss::tmrd() },
+ { 15, eff_dimm_ddr4_rc15, mss::tmrd() },
};
static std::vector< rcd_data > l_rcd_8bit_data =
{
- { 1, eff_dimm_ddr4_rc_1x, tMRD }, { 2, eff_dimm_ddr4_rc_2x, tMRD }, { 3, eff_dimm_ddr4_rc_3x, tSTAB },
- { 4, eff_dimm_ddr4_rc_4x, tMRD }, { 5, eff_dimm_ddr4_rc_5x, tMRD }, { 6, eff_dimm_ddr4_rc_6x, tMRD },
- { 7, eff_dimm_ddr4_rc_7x, tMRD }, { 8, eff_dimm_ddr4_rc_8x, tMRD }, { 9, eff_dimm_ddr4_rc_9x, tMRD },
- { 10, eff_dimm_ddr4_rc_ax, tMRD }, { 11, eff_dimm_ddr4_rc_bx, tMRD_L}
+ { 1, eff_dimm_ddr4_rc_1x, mss::tmrd() }, { 2, eff_dimm_ddr4_rc_2x, mss::tmrd() },
+ { 3, eff_dimm_ddr4_rc_3x, tSTAB }, { 4, eff_dimm_ddr4_rc_4x, mss::tmrd() },
+ { 5, eff_dimm_ddr4_rc_5x, mss::tmrd() }, { 6, eff_dimm_ddr4_rc_6x, mss::tmrd() },
+ { 7, eff_dimm_ddr4_rc_7x, mss::tmrd() }, { 8, eff_dimm_ddr4_rc_8x, mss::tmrd() },
+ { 9, eff_dimm_ddr4_rc_9x, mss::tmrd() }, { 10, eff_dimm_ddr4_rc_ax, mss::tmrd() },
+ { 11, eff_dimm_ddr4_rc_bx, mss::tmrd_l() }
};
fapi2::buffer<uint8_t> l_value;
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
index 894205480..88024e7a0 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H
@@ -145,6 +145,7 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
/// @brief Calculates refresh interval time
/// @param[in] i_mode fine refresh rate mode
/// @param[in] i_temp_refresh_range temperature refresh range
@@ -155,6 +156,7 @@ fapi2::ReturnCode calc_trefi( const refresh_rate i_mode,
const uint8_t i_temp_refresh_range,
int64_t& o_timing );
+///
/// @brief Calculates Minimum Refresh Recovery Delay Time (different logical rank)
/// @param[in] i_mode fine refresh rate mode
/// @param[in] i_density SDRAM density
@@ -165,5 +167,204 @@ fapi2::ReturnCode calc_trfc_dlr( const uint8_t i_refresh_mode,
const uint8_t i_density,
uint64_t& o_trfc_in_ps );
+///
+/// @brief DLL locking time
+/// @tparam T the fapi2::TargetType of i_target
+/// @tparam OT the type of the output location
+/// @param[in] i_target a target for attributes
+/// @param[out] o_value reference to space into which to store the output
+/// @return fapi2::FAPI2_RC_SUCCESS iff okay
+///
+template< fapi2::TargetType T, typename OT = uint64_t >
+inline fapi2::ReturnCode tdllk( const fapi2::Target<T>& i_target, OT& o_value )
+{
+ uint64_t l_freq = 0;
+
+ // Calculate tDLLK from our MT/s. Magic numbers (in clocks) from the DDR4 spec
+ FAPI_TRY( mss::freq(mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq) );
+ o_value = (l_freq < fapi2::ENUM_ATTR_MSS_FREQ_MT2133) ? 597 : 768;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Mode Register Set Command Cycle Time
+/// @return constexpr value of 8 clocks
+///
+constexpr uint64_t tmrd()
+{
+ // Per DDR4 Full spec update (79-4A) - timing requirements
+ return 8;
+}
+
+///
+/// @brief Control word to control word delay
+/// @return constexpr value of 16 clocks
+///
+constexpr uint64_t tmrd_l()
+{
+ // Per DDR4RCD02 Spec Rev 0.85
+ return 16;
+}
+
+///
+/// @brief Stabilization time
+/// @return constexpr value of 5 us
+///
+constexpr uint64_t tstab()
+{
+ // Per DDR4RCD02 Spec Rev 0.85 CK_t stable
+ return 5;
+}
+
+///
+/// @brief Power-up and RESET calibration time
+/// @return constexpr value of 1024 clocks
+///
+constexpr uint64_t tzqinit()
+{
+ // Per DDR4 Full spec update (79-4A) - timing requirements
+ return 1024;
+}
+
+///
+/// @brief Normal operation Full calibration time
+/// @return constexpr value of 512 clocks
+///
+constexpr uint64_t tzqoper()
+{
+ // Per DDR4 Full spec update (79-4A) - timing requirements
+ return 512;
+}
+
+///
+/// @brief Normal operation Short calibration time
+/// @return constexpr value of 128 clocks
+///
+constexpr uint64_t tzqcs()
+{
+ // Per DDR4 Full spec update (79-4A) - timing requirements
+ return 128;
+}
+
+///
+/// @brief DQS_t/DQS_n delay after write leveling mode is programmed
+/// @return constexpr value of 25 clocks
+///
+constexpr uint64_t twldqsen()
+{
+ // Per DDR4 Full spec update (79-4A) - timing requirements
+ return 25;
+}
+
+///
+/// @brief First DQS_t/DQS_n rising edge after write leveling mode is programmed
+/// @return constexpr value of 40 clocks
+///
+constexpr uint64_t twlmrd()
+{
+ // Per DDR4 Full spec update (79-4A) - timing requirements
+ return 40;
+}
+
+///
+/// @brief Calculate TWLO_TWLOE
+/// @tparam T fapi2::TargetType of the target used to calculate cycles from ns
+/// @param[in] i_target the target used to get DIMM clocks
+/// @return uint64_t, TWLO_TWLOE in cycles
+///
+template< fapi2::TargetType T >
+inline uint64_t twlo_twloe(const fapi2::Target<T>& i_target)
+{
+ return 12 + mss::ns_to_cycles(i_target, tWLO - tWLOE);
+}
+
+///
+/// @brief Mode Register Set command update delay
+/// @tparam T fapi2::TargetType of the target used to calculate cycles from ns
+/// @param[in] i_target the target used to get clocks
+/// @return max(24nCK,15ns) in clocks
+///
+template< fapi2::TargetType T >
+inline uint64_t tmod( const fapi2::Target<T>& i_target )
+{
+ // Per DDR4 Full spec update (79-4A) - timing requirements
+ return mss::max_ck_ns( i_target, 24, 15 );
+}
+
+///
+/// @brief Refresh cycle time
+/// @param[in] i_target the DIMM target used to get clocks (needed to know the stack type)
+/// @param[out] o_trfc the trfc *in clocks*
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+inline fapi2::ReturnCode trfc( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint16_t& o_trfc )
+{
+ // Pull down the 3DS attribute. If we have a stack we need to use
+ // tRFC_DLR if not we pull down TRFC and use that.
+ uint8_t l_stack = 0;
+
+ FAPI_TRY( mss::eff_prim_stack_type(i_target, l_stack) );
+
+ if (l_stack == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS)
+ {
+ uint8_t l_value = 0;
+ FAPI_TRY( mss::eff_dram_trfc_dlr(i_target, l_value) );
+ o_trfc = l_value;
+ }
+ else
+ {
+ FAPI_TRY( mss::eff_dram_trfc(i_target, o_trfc) );
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Direct ODT turn on Latency
+/// @param[in] i_target the DIMM target used to get attributes
+/// @param[out] o_dodt *in clocks*
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+inline fapi2::ReturnCode dodt_on( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_dodt )
+{
+ // CWL + AL + PL - 2.0 per DDR4 Full spec update(79-4B)
+
+ uint8_t l_ca_parity_latency = 0;
+ uint8_t l_al = 0;
+ uint8_t l_cwl = 0;
+
+ FAPI_TRY( mss::eff_ca_parity_latency(i_target, l_ca_parity_latency) );
+ FAPI_TRY( mss::eff_dram_al(i_target, l_al) );
+ FAPI_TRY( mss::eff_dram_cwl(i_target, l_cwl) );
+
+ o_dodt = l_cwl + l_al + l_ca_parity_latency - 2;
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Direct ODT turn off Latency
+/// @param[in] i_target the DIMM target used to get attributes
+/// @param[out] o_dodt *in clocks*
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+inline fapi2::ReturnCode dodt_off( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_dodt )
+{
+ // Same for all frequencies of DDR4; DDR4 Full spec update(79-4B)
+ return dodt_on(i_target, o_dodt);
+}
+
+// TK RODTon - The use would be for the ODT in the PHY, but the max RODT is equal to or less than
+// the max DODTon/off so it would really never be used anyway there anyway. We can implement it if
+// we find another need for it.
+
} // mss
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H
index e2b2e316a..898154c93 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/cal_timers.H
@@ -38,7 +38,7 @@
#include <fapi2.H>
#include <lib/shared/mss_const.H>
-#include <lib/utils/conversions.H>
+#include <lib/eff_config/timing.H>
#include <lib/utils/poll.H>
namespace mss
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 0333ed464..78dbc776e 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
@@ -188,15 +188,14 @@ fapi_try_exit:
fapi2::ReturnCode setup_phase_rotator_control_registers( const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
const states i_state )
{
- uint8_t is_sim = 0;
+ // From the DDR PHY workbook
+ constexpr uint64_t CONTINUOUS_UPDATE = 0x8004;
+ constexpr uint64_t SIM_OVERRIDE = 0x8080;
+ constexpr uint64_t PHASE_CNTL_EN = 0x8020;
- // Per Bialas, we don't want to do true alignment in the cycle sim as we have
- // a chance of being off one-tick (which is detrimental.) Per his recomendations,
- // we write 0's to the control registers and then configure them with 0x8080. We'll
- // over write l_update's values with a getScom to the correct h/w initiialized values
- // if we're not in sim
+ uint8_t is_sim = 0;
- fapi2::buffer<uint64_t> l_update( i_state == mss::ON ? 0x0 : 0x8080 );
+ fapi2::buffer<uint64_t> l_update( i_state == mss::ON ? CONTINUOUS_UPDATE : PHASE_CNTL_EN );
const auto l_mca = find_targets<TARGET_TYPE_MCA>(i_target);
std::vector<uint64_t> addrs(
@@ -212,15 +211,17 @@ fapi2::ReturnCode setup_phase_rotator_control_registers( const fapi2::Target<TAR
FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<TARGET_TYPE_SYSTEM>(), is_sim) );
- if (! is_sim)
+ if (is_sim)
{
- // All the MCA (and both registers) will be in the same state, so we can get the first and use it to create the
- // values for the others.
- FAPI_TRY( mss::getScom(l_mca[0], MCA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0, l_update) );
- l_update.setBit<MCA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0_ADR0_PHASE_EN>();
- l_update.writeBit<MCA_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0_ADR0_CONTINUOUS_UPDATE>(i_state);
+ // Per Bialas, we don't want to do true alignment in the cycle sim as we have
+ // a chance of being off one-tick (which is detrimental.) Per his recomendations,
+ // we write 0's to the control registers and then configure them with 0x8080.
+ l_update = (i_state == mss::ON) ? 0x0 : SIM_OVERRIDE;
}
+ // All the MCA (and both registers) will be in the same state, so we can get the first and use it to create the
+ // values for the others.
+
FAPI_INF("Write 0x%lx into the ADR SysClk Phase Rotator Control Regs", l_update);
// WRCLK Phase rotators are taken care of in the phy initfile. BRS 6/16.
@@ -734,6 +735,7 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
{
fapi2::buffer<uint64_t> l_cal_config;
fapi2::buffer<uint64_t> l_vref_config;
+ uint8_t is_sim = 0;
// This is the buffer which will be written to CAL_CONFIG0. It starts
// life assuming no cal sequences, no rank pairs - but we set the abort-on-error
@@ -747,6 +749,8 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
i_cal_steps_enabled.clearBit<WRITE_CTR>();
}
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<TARGET_TYPE_SYSTEM>(), is_sim) );
+
// Sadly, the bits in the register don't align directly with the bits in the attribute.
// So, arrange the bits accordingly and write the config register.
{
@@ -766,6 +770,12 @@ fapi2::ReturnCode setup_cal_config( const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
i_cal_steps_enabled.getBit<COARSE_WR>());
l_cal_config.writeBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_COARSE_RD>(
i_cal_steps_enabled.getBit<COARSE_RD>());
+
+ // Always turn on initial pattern write in h/w, never for sim (makes the DIMM behavioral lose it's mind)
+ if (!is_sim)
+ {
+ l_cal_config.setBit<MCA_DDRPHY_PC_INIT_CAL_CONFIG0_P0_ENA_INITIAL_PAT_WR>();
+ }
}
// Blast the VREF config with the proper setting for these cal bits.
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/read_cntrl.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/read_cntrl.H
index cadca6a20..58e638ae7 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/read_cntrl.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/read_cntrl.H
@@ -390,12 +390,10 @@ template< fapi2::TargetType T, typename TT = rcTraits<T> >
inline fapi2::ReturnCode reset_config3( const fapi2::Target<T>& i_target )
{
fapi2::buffer<uint64_t> l_data;
- uint8_t is_sim = 0;
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), is_sim) );
- // 51:54, 0b1010, (def_is_sim); # COARSE_CAL_STEP_SIZE» # old=4=5/128 (5/18)
- // 51:54, 0b0000, any; # COARSE_CAL_STEP_SIZE = 1/128
- l_data.insertFromRight<TT::COARSE_CAL_STEP_SIZE, TT::COARSE_CAL_STEP_SIZE_LEN>(is_sim ? 0b1010 : 0b0000);
+ // Per S. Wyatt 8/16: COARSE_CAL_STEP_SIZE='1010'b [Centaur sim value] is reserved.
+ // Change to COARSE_CAL_STEP_SIZE='0100'
+ l_data.insertFromRight<TT::COARSE_CAL_STEP_SIZE, TT::COARSE_CAL_STEP_SIZE_LEN>(0b0100);
FAPI_TRY( write_config3(i_target, l_data) );
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H b/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H
index 2b1a9084e..26cc5e564 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/write_cntrl.H
@@ -39,7 +39,7 @@
#include <fapi2.H>
#include <p9_mc_scom_addresses.H>
#include <lib/utils/scom.H>
-#include <lib/utils/conversions.H>
+#include <lib/eff_config/timing.H>
namespace mss
{
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/termination/slew_cal.C b/src/import/chips/p9/procedures/hwp/memory/lib/termination/slew_cal.C
deleted file mode 100644
index f62f8b920..000000000
--- a/src/import/chips/p9/procedures/hwp/memory/lib/termination/slew_cal.C
+++ /dev/null
@@ -1,503 +0,0 @@
-/* IBM_PROLOG_BEGIN_TAG */
-/* This is an automatically generated prolog. */
-/* */
-/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/termination/slew_cal.C $ */
-/* */
-/* OpenPOWER HostBoot Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2016 */
-/* [+] International Business Machines Corp. */
-/* */
-/* */
-/* Licensed under the Apache License, Version 2.0 (the "License"); */
-/* you may not use this file except in compliance with the License. */
-/* You may obtain a copy of the License at */
-/* */
-/* http://www.apache.org/licenses/LICENSE-2.0 */
-/* */
-/* Unless required by applicable law or agreed to in writing, software */
-/* distributed under the License is distributed on an "AS IS" BASIS, */
-/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
-/* implied. See the License for the specific language governing */
-/* permissions and limitations under the License. */
-/* */
-/* IBM_PROLOG_END_TAG */
-///
-/// @file slew_cal.C
-/// @brief * This function runs the slew calibration engine to configure MSS_SLEW_DATA/ADR
-/// attributes and calls config_slew_rate to set the slew rate in the 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 <mss.H>
-#include <lib/termination/slew_cal.H>
-
-using fapi2::TARGET_TYPE_MCBIST;
-using fapi2::TARGET_TYPE_MCA;
-using fapi2::TARGET_TYPE_MCS;
-using fapi2::TARGET_TYPE_SYSTEM;
-
-using fapi2::TARGET_STATE_FUNCTIONAL;
-
-using fapi2::FAPI2_RC_SUCCESS;
-
-// slew calibration control register
-
-static const uint64_t slew_cal_cntl[] =
-{
- MCA_0_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0,
- MCA_1_DDRPHY_ADR_SLEW_CAL_CNTL_P1_ADR32S0,
- MCA_2_DDRPHY_ADR_SLEW_CAL_CNTL_P2_ADR32S0,
- MCA_3_DDRPHY_ADR_SLEW_CAL_CNTL_P3_ADR32S0,
-};
-// slew calibration status registers
-static const uint64_t ENABLE_BIT = 48;
-static const uint64_t slew_cal_stat[] =
-{
- MCA_0_DDRPHY_ADR_SYSCLK_CNTL_PR_P0_ADR32S0,
- MCA_1_DDRPHY_ADR_SYSCLK_CNTL_PR_P1_ADR32S0,
- MCA_2_DDRPHY_ADR_SYSCLK_CNTL_PR_P2_ADR32S0,
- MCA_3_DDRPHY_ADR_SYSCLK_CNTL_PR_P3_ADR32S0,
-};
-
-// big bang lock bit register
-static const uint64_t bb_lock_stat[] =
-{
- MCA_0_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0,
- MCA_1_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P1_ADR32S0,
- MCA_2_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P2_ADR32S0,
- MCA_3_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P3_ADR32S0,
-};
-
-namespace mss
-{
-
-///
-/// @brief perform the slew calibration, store the result.
-/// @tparam T the type of the slew table
-/// @param[in] i_target MCA (port) target
-/// @param[in] l_table a vector of the steps which came before me
-/// @param[in] o_cal_slew the slew table to be operated on
-/// @param[out] the array holding the results
-/// @return FAPI2_RC_SUCCESS, iff ok
-///
-template<typename T>
-fapi2::ReturnCode perform_slew_cal(
- const fapi2::Target<TARGET_TYPE_MCA>& i_target,
- std::vector<tags_t>& i_where_am_i, T& l_table,
- uint8_t (&o_cal_slew)[2][PORTS_PER_MCS][MAX_NUM_IMP][MAX_NUM_CAL_SLEW_RATES])
-{
- i_where_am_i.push_back(l_table.first);
-
- for (auto e : l_table.second)
- {
- FAPI_TRY( perform_slew_cal(i_target, i_where_am_i, e, o_cal_slew) );
- }
-
- i_where_am_i.pop_back();
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief perform the slew calibration, store the result.
-/// @param[in] i_target MCA (port) target
-/// @param[in] i_where_am_i a vector of the steps which came before me
-/// @param[in] a slew_table_t
-/// @param[out] the array holding the results
-/// @bote Prunes recursion based on frequency.
-/// @return FAPI2_RC_SUCCESS, iff ok
-///
-template<>
-fapi2::ReturnCode perform_slew_cal(
- const fapi2::Target<TARGET_TYPE_MCA>& i_target,
- std::vector<tags_t>& i_where_am_i,
- std::pair<tags_t, slew_per_imp_t>& l_table,
- uint8_t (&o_cal_slew)[2][PORTS_PER_MCS][MAX_NUM_IMP][MAX_NUM_CAL_SLEW_RATES])
-{
- uint64_t ddr_freq = 0;
- const char* l_type = i_where_am_i[0] == TAG_ADR ? "adr" : "data";
-
- // Check our speed. If this isn't our speed, we can get out of here.
- FAPI_TRY( mss::freq(i_target.getParent<TARGET_TYPE_MCBIST>(), ddr_freq),
- "Unable to get ddr freq for %s", mss::c_str(i_target) );
-
- if (ddr_freq != l_table.first)
- {
- FAPI_DBG("Skipping slew %s for %s: invalid speed %d(%d)",
- l_type, mss::c_str(i_target), l_table.first, ddr_freq);
- return FAPI2_RC_SUCCESS;
- }
-
- i_where_am_i.push_back(l_table.first);
-
- for (auto e : l_table.second)
- {
- FAPI_TRY( perform_slew_cal(i_target, i_where_am_i, e, o_cal_slew) );
- }
-
- i_where_am_i.pop_back();
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief perform the slew calibration, store the result.
-/// @param[in] i_target MCA (port) target
-/// @param[in] i_where_am_i a vector of the steps which came before me
-/// @param[in] l_slew_rate the slew rate to be calculated
-/// @param[out] the array holding the results
-/// @return FAPI2_RC_SUCCESS, iff ok
-///
-template<>
-fapi2::ReturnCode perform_slew_cal<slew_rate_t>(
- const fapi2::Target<TARGET_TYPE_MCA>& i_target,
- std::vector<tags_t>& i_where_am_i,
- slew_rate_t& l_slew_rate,
- uint8_t (&o_cal_slew)[2][PORTS_PER_MCS][MAX_NUM_IMP][MAX_NUM_CAL_SLEW_RATES])
-{
- i_where_am_i.push_back(l_slew_rate.first);
-
- fapi2::buffer<uint64_t> l_data;
-
- // Some short-hand for this calibration
- const char* l_type = i_where_am_i[0] == TAG_ADR ? "adr" : "data";
- const uint64_t& l_speed = i_where_am_i[1];
- const uint64_t& l_ohm = i_where_am_i[2];
- const uint64_t& l_vns = i_where_am_i[3];
-
- uint64_t cal_status = 0;
- fapi2::buffer<uint64_t> status_register;
- uint64_t calculated_slew = 0;
-
- FAPI_INF("Processing slew %s, %dmhz %dohm %dV/ns: %d", l_type, l_speed, l_ohm, l_vns, l_slew_rate.second);
-
-#ifdef NOT_TESTING_WITH_SUET
- // Get out of here if we're in the simulator. Calibration fails in sim since bb_lock not possible in cycle
- // simulator, putting initial to be cal'd value in output table
- uint8_t is_sim = 0;
- FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target<TARGET_TYPE_SYSTEM>(), is_sim) );
-
- if (is_sim)
- {
- FAPI_INF("In SIM setting input slew value in array");
- calculated_slew = l_slew_rate.second;
- goto perform_slew_cal_exit;
- }
-
-#endif
-
- // This doesn't look right. There are 5 bits, but some of our values (134) are 8 bits. So, the
- // left-most bits are truncated. Note this is the same in P8, it seems - this needs to be looked at BRS
- l_data.insertFromRight<MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0_ADR0_TARGET_PR_OFFSET,
- MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0_ADR0_TARGET_PR_OFFSET_LEN>(l_slew_rate.second);
- l_data.setBit<MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0_ADR0_START>();
-
- FAPI_TRY( mss::putScom(i_target, MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0, l_data) );
-
- mss::poll( i_target, MCA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0, mss::poll_parameters(DELAY_100NS),
- [&](const size_t poll_remaining, const fapi2::buffer<uint64_t>& stat_reg) -> bool
- {
- // Save off our claibration status
- status_register = stat_reg;
- stat_reg.extractToRight<MCA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0_ADR0_SLEW_DONE_STATUS,
- MCA_DDRPHY_ADR_SYSCLK_PR_VALUE_RO_P0_ADR32S0_ADR0_SLEW_DONE_STATUS_LEN>(cal_status);
- FAPI_DBG("slew calibration status 0x%llx, remaining: %d", cal_status, poll_remaining);
- return cal_status != SLEW_CAL_NOT_DONE;
- });
-
- // This will kick us out if there's no further processing we can do.
- FAPI_TRY( slew_cal_status(i_target, i_where_am_i, l_slew_rate.second, cal_status, status_register) );
-
- // Get our calculated slew rate and process.
- FAPI_TRY( mss::getScom(i_target, MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0, l_data) );
- l_data.extractToRight<MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0_ADR0_TARGET_PR_OFFSET,
- MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0_ADR0_TARGET_PR_OFFSET_LEN>(calculated_slew);
-
-#ifdef NOT_TESTING_WITH_SUET
-perform_slew_cal_exit:
-#endif
- FAPI_DBG("MSS_SLEW_RATE %s port %d %dohm slew 0x%lx(0x%lx)",
- l_type, mss::pos(i_target), l_ohm, calculated_slew, uint64_t(status_register));
-
- o_cal_slew[i_where_am_i[0]] // adr/data
- [mss::index(i_target)] // port
- [mss::index(i_where_am_i[0], i_where_am_i[2])] // imp
- [mss::index(i_where_am_i[0], i_where_am_i[3])] = calculated_slew;
-
- i_where_am_i.pop_back();
-
- return FAPI2_RC_SUCCESS;
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-
-///
-/// @brief Run the slew calibration engine
-/// @param[in] i_target the MCBIST
-/// @return FAPI2_RC_SUCCESS iff OK
-///
-fapi2::ReturnCode slew_cal(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target)
-{
- // freq index into lookup table. Fixed at 3 right now as we don't support
- // dimm slower than 1866 - without more work below.
- static const uint8_t freq_idx = 3;
-
- // current ddr freq
- uint64_t ddr_freq = 0;
-
- // ddr type index into lookup table
- // We only have one entry in the table right now, so this is fixed.
- static const uint8_t ddr_idx = 0;
-
- // ATTR_EFF_DRAM_GEN{0=invalid, 1=ddr3, 2=ddr4}
- // p9n only supprts ddr4 right now. So, fixed
- static const uint8_t ddr_type = 2;
-
- fapi2::buffer<uint64_t> ctl_reg;
- fapi2::buffer<uint64_t> stat_reg;
-
- // DD level 1.0-1.1, Version 1.0
- // [ddr3/4][dq/adr][speed][impedance][slew_rate]
- // note: Assumes standard voltage for DDR3(1.35V), DDR4(1.2V),
- // little endian, if >=128, lab only debug.
- //
- // ddr_type(1), ddr4=0
- // data/adr(2)data(dq/dqs)=0, adr(cmd/cntl)=1
- // speed(4)1066=0, 1333=1, 1600=2, 1866=3
- // imped(4)24ohms=0, 30ohms=1, 34ohms=2, 40ohms=3 for DQ/DQS
- // imped(4)15ohms=0, 20ohms=1, 30ohms=2, 40ohms=3 for ADR driver
- // slew(3)3V/ns=0, 4V/ns=1, 5V/ns=2, 6V/ns=3
-
- // Too many in here for real-world. But this allows us to test out the
- // logic to make sure we're in good shape as we add to this table. We
- // can redice this table before flight BRS.
- std::vector< std::pair< tags_t, slew_table_t> > slew_table =
- {
- {
- TAG_ADR, {
- {
- TAG_1066MHZ,
- {
- { TAG_15OHM, {{TAG_3VNS, 142}, {TAG_4VNS, 139}, {TAG_5VNS, 136}, {TAG_6VNS, 134}} },
- { TAG_20OHM, {{TAG_3VNS, 140}, {TAG_4VNS, 136}, {TAG_5VNS, 134}, {TAG_6VNS, 133}} },
- { TAG_30OHM, {{TAG_3VNS, 138}, {TAG_4VNS, 134}, {TAG_5VNS, 131}, {TAG_6VNS, 131}} },
- { TAG_40OHM, {{TAG_3VNS, 133}, {TAG_4VNS, 131}, {TAG_5VNS, 131}, {TAG_6VNS, 131}} },
- }
- },
-
-
- {
- TAG_1333MHZ,
- {
- { TAG_15OHM, {{TAG_3VNS, 145}, {TAG_4VNS, 142}, {TAG_5VNS, 139}, {TAG_6VNS, 136}} },
- { TAG_20OHM, {{TAG_3VNS, 143}, {TAG_4VNS, 138}, {TAG_5VNS, 135}, {TAG_6VNS, 134}} },
- { TAG_30OHM, {{TAG_3VNS, 140}, {TAG_4VNS, 135}, {TAG_5VNS, 132}, {TAG_6VNS, 132}} },
- { TAG_40OHM, {{TAG_3VNS, 134}, {TAG_4VNS, 132}, {TAG_5VNS, 132}, {TAG_6VNS, 132}} },
- }
- },
-
-
- {
- TAG_1600MHZ,
- {
- { TAG_15OHM, {{TAG_3VNS, 21}, {TAG_4VNS, 16}, {TAG_5VNS, 13}, {TAG_6VNS, 10}} },
- { TAG_20OHM, {{TAG_3VNS, 18}, {TAG_4VNS, 12}, {TAG_5VNS, 9}, {TAG_6VNS, 135}} },
- { TAG_30OHM, {{TAG_3VNS, 15}, {TAG_4VNS, 8}, {TAG_5VNS, 133}, {TAG_6VNS, 133}} },
- { TAG_40OHM, {{TAG_3VNS, 7}, {TAG_4VNS, 133}, {TAG_5VNS, 133}, {TAG_6VNS, 133}} },
- }
- },
-
-
- {
- TAG_1866MHZ,
- {
- { TAG_15OHM, {{TAG_3VNS, 24}, {TAG_4VNS, 19}, {TAG_5VNS, 15}, {TAG_6VNS, 11}} },
- { TAG_20OHM, {{TAG_3VNS, 21}, {TAG_4VNS, 14}, {TAG_5VNS, 10}, {TAG_6VNS, 136}} },
- { TAG_30OHM, {{TAG_3VNS, 17}, {TAG_4VNS, 10}, {TAG_5VNS, 134}, {TAG_6VNS, 134}} },
- { TAG_40OHM, {{TAG_3VNS, 9}, {TAG_4VNS, 134}, {TAG_5VNS, 134}, {TAG_6VNS, 134}} },
- }
- },
-
- {
- TAG_2400MHZ,
- {
- { TAG_15OHM, {{TAG_3VNS, 24}, {TAG_4VNS, 19}, {TAG_5VNS, 15}, {TAG_6VNS, 11}} },
- { TAG_20OHM, {{TAG_3VNS, 21}, {TAG_4VNS, 14}, {TAG_5VNS, 10}, {TAG_6VNS, 136}} },
- { TAG_30OHM, {{TAG_3VNS, 17}, {TAG_4VNS, 10}, {TAG_5VNS, 134}, {TAG_6VNS, 134}} },
- { TAG_40OHM, {{TAG_3VNS, 9}, {TAG_4VNS, 134}, {TAG_5VNS, 134}, {TAG_6VNS, 134}} },
- }
- },
-
- },
- },
-
- {
- TAG_DATA, {
- {
- TAG_1066MHZ,
- {
- { TAG_24OHM, {{TAG_3VNS, 138}, {TAG_4VNS, 135}, {TAG_5VNS, 134}, {TAG_6VNS, 133}} },
- { TAG_30OHM, {{TAG_3VNS, 139}, {TAG_4VNS, 136}, {TAG_5VNS, 134}, {TAG_6VNS, 132}} },
- { TAG_34OHM, {{TAG_3VNS, 140}, {TAG_4VNS, 136}, {TAG_5VNS, 135}, {TAG_6VNS, 133}} },
- { TAG_40OHM, {{TAG_3VNS, 140}, {TAG_4VNS, 136}, {TAG_5VNS, 132}, {TAG_6VNS, 132}} },
- }
- },
-
- {
- TAG_1333MHZ,
- {
- { TAG_24OHM, {{TAG_3VNS, 139}, {TAG_4VNS, 137}, {TAG_5VNS, 135}, {TAG_6VNS, 134}} },
- { TAG_30OHM, {{TAG_3VNS, 142}, {TAG_4VNS, 138}, {TAG_5VNS, 135}, {TAG_6VNS, 133}} },
- { TAG_34OHM, {{TAG_3VNS, 143}, {TAG_4VNS, 138}, {TAG_5VNS, 135}, {TAG_6VNS, 133}} },
- { TAG_40OHM, {{TAG_3VNS, 143}, {TAG_4VNS, 138}, {TAG_5VNS, 133}, {TAG_6VNS, 132}} },
- }
- },
-
- {
- TAG_1600MHZ,
- {
- { TAG_24OHM, {{TAG_3VNS, 15}, {TAG_4VNS, 11}, {TAG_5VNS, 9}, {TAG_6VNS, 135}} },
- { TAG_30OHM, {{TAG_3VNS, 17}, {TAG_4VNS, 11}, {TAG_5VNS, 9}, {TAG_6VNS, 135}} },
- { TAG_34OHM, {{TAG_3VNS, 18}, {TAG_4VNS, 13}, {TAG_5VNS, 9}, {TAG_6VNS, 134}} },
- { TAG_40OHM, {{TAG_3VNS, 18}, {TAG_4VNS, 11}, {TAG_5VNS, 6}, {TAG_6VNS, 133}} },
- }
- },
-
-
- {
- TAG_1866MHZ,
- {
- { TAG_24OHM, {{TAG_3VNS, 18}, {TAG_4VNS, 13}, {TAG_5VNS, 10}, {TAG_6VNS, 137}} },
- { TAG_30OHM, {{TAG_3VNS, 19}, {TAG_4VNS, 13}, {TAG_5VNS, 10}, {TAG_6VNS, 136}} },
- { TAG_34OHM, {{TAG_3VNS, 21}, {TAG_4VNS, 15}, {TAG_5VNS, 10}, {TAG_6VNS, 135}} },
- { TAG_40OHM, {{TAG_3VNS, 21}, {TAG_4VNS, 13}, {TAG_5VNS, 8}, {TAG_6VNS, 134}} },
- }
- },
-
- {
- TAG_2400MHZ,
- {
- { TAG_24OHM, {{TAG_3VNS, 18}, {TAG_4VNS, 13}, {TAG_5VNS, 10}, {TAG_6VNS, 137}} },
- { TAG_30OHM, {{TAG_3VNS, 19}, {TAG_4VNS, 13}, {TAG_5VNS, 10}, {TAG_6VNS, 136}} },
- { TAG_34OHM, {{TAG_3VNS, 21}, {TAG_4VNS, 15}, {TAG_5VNS, 10}, {TAG_6VNS, 135}} },
- { TAG_40OHM, {{TAG_3VNS, 21}, {TAG_4VNS, 13}, {TAG_5VNS, 8}, {TAG_6VNS, 134}} },
- }
- },
-
- }
- }
- };
-
- // Get the vector of ports. Note that we presently think there's a bit in the CCS_MODE
- // register which needs to be twiddled during slew cal. That means our caller can't
- // put each port's slew cal on a thread and do them in parallel. So, we interleave.
- // If that requirement for that MCBIST register goes away, then these functions can turn
- // in to per-port functions and the caller can decide to loop or thread as appropriate.
- // Or maybe per MCS given the attribute work we need to do at the end ...
- auto l_ports = i_target.getChildren<TARGET_TYPE_MCA>(TARGET_STATE_FUNCTIONAL);
-
- // Cache the name of our target. We can't just keep the pointer from c_str as
- // it points to thread-local space and anything we call might change the string.
- char l_name[fapi2::MAX_ECMD_STRING_LEN];
- strncpy(l_name, mss::c_str(i_target), fapi2::MAX_ECMD_STRING_LEN);
-
- // p9n is ddr4 only for now, so skip checking the dimm generation (effective config
- // should have raised a rukus if this isn't a DDR4 dimm ...
-
- FAPI_TRY( mss::freq(i_target, ddr_freq),
- "Unable to get ddr freq for %s", l_name );
-
- // Note: this catches two cases. One where ddr_freq is 0 and the other
- // where we put something slow in we don't (yet?) support
- FAPI_ASSERT( ddr_freq > 1732,
- fapi2::MSS_SLEW_CAL_INVALID_FREQ(),
- "Invalid ATTR_MSS_FREQ (%d) on %s", ddr_freq, l_name );
-
- // Get a list of functional ports.
- // Note: If we need to use the functional vector to figure this out,
- // change this to an mss call, and bury the attribute manipluation
- // in that function so it can be shared and tests. BRS
-
- //
- // This doesn't match teh Centaur workbook algorithm, but it matches the P8 code so
- // I'm leaving it this way. The algorithm according to the Centaur book would be to
- // configure ADR/MCLK detect and then wait for BB_LOCK. Then, enable the cal engine and
- // wait 2K clocks. So to "fix" you'd move the polling for BB_LOCK above the putScom. BRS
- //
-
- // Sanity check the DRAM generation
- for (auto c : i_target.getChildren<TARGET_TYPE_MCS>())
- {
- FAPI_TRY( check::dram_type(c) );
- }
-
- // Step A: Configure ADR registers and MCLK detect (done in ddr_phy_reset)
- {
- for (auto p : l_ports)
- {
- FAPI_INF("Enabling slew calibration engine on port %i: DDR%i(%u) %u(%u) in %s",
- mss::pos(p), (ddr_type + 2), ddr_idx, ddr_freq, freq_idx, l_name);
-
- // Note: This is wrong. Cant' find the SLEW_CAL enable bit in n10_e9024, so leaving this here for now BRS
- FAPI_TRY( mss::putScom(p, MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0,
- fapi2::buffer<uint64_t>().setBit<ENABLE_BIT>()),
- "Error enabling slew calibration engine in DDRPHY_ADR_SLEW_CAL_CNTL register.");
- }
- }
-
- // Note: must be 2000 nclks+ after setting enable bit
- // normally 2000, but since cal doesn't work in SIM, setting to 1
- FAPI_TRY( fapi2::delay(cycles_to_ns(i_target, 2000), cycles_to_simcycles(1)) );
-
- // Create calibrated slew settings, per MCS. We do this as the attributes are written per MCS,
- // and this makes it easier to keep track of what's going where, etc.
- for (auto c : i_target.getChildren<TARGET_TYPE_MCS>())
- {
- // [adr or data][port on mcs][imp][slew]
- uint8_t calibrated_slew[2][PORTS_PER_MCS][MAX_NUM_IMP][MAX_NUM_CAL_SLEW_RATES] = {0};
-
- auto l_mcs_ports = c.getChildren<TARGET_TYPE_MCA>();
-
- for (auto p : l_mcs_ports)
- {
- for (auto e : slew_table)
- {
- FAPI_INF("Starting %s, port %d slew calibration", (e.first == TAG_ADR ? "adr" : "data"), mss::pos(p));
-
- for (auto this_table : e.second)
- {
- std::vector<tags_t> l_where_am_i;
- l_where_am_i.push_back(e.first);
- FAPI_TRY( perform_slew_cal(p, l_where_am_i, this_table, calibrated_slew) );
- }
- }
- }
-
- // We have the calibrated slew settings, disable the calibration engine and do the
- // attribute dance.
- for (auto p : l_mcs_ports)
- {
- // Note: This is wrong. Cant' find the SLEW_CAL enable bit in n10_e9024, so leaving this here for now BRS
- FAPI_TRY( mss::putScom(p, MCA_DDRPHY_ADR_SLEW_CAL_CNTL_P0_ADR32S0,
- fapi2::buffer<uint64_t>().clearBit<ENABLE_BIT>()),
- "Error disabling slew calibration engine in DDRPHY_ADR_SLEW_CAL_CNTL register.");
- }
-
-// FAPI_TRY( slew_cal_attributes() );
- }
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-} // namespace
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
index 9076f97ee..c7a3589b7 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/conversions.H
@@ -186,6 +186,12 @@ inline uint64_t ps_to_cycles(const fapi2::Target<T>& i_target, const uint64_t i_
FAPI_TRY( mss::freq( find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq) );
+ // No time if MT/s is 0 (well, infinite really but shut up)
+ if (l_freq == 0)
+ {
+ return 0;
+ }
+
// Hoping the compiler figures out how to do these together.
FAPI_TRY( freq_to_ps(l_freq, l_divisor) );
l_quotient = i_ps / ((l_divisor == 0) ? 1 : l_divisor);
@@ -312,18 +318,6 @@ inline uint64_t cycles_to_us(const fapi2::Target<T>& i_target, const uint64_t i_
}
///
-/// @brief Calculate TWLO_TWLOE - this needs to go in to eff_config and be an attribute
-/// @tparam T fapi2::TargetType of the target used to calculate cycles from ns
-/// @param[in] i_target the target used to get DIMM clocks
-/// @return uint64_t, TWLO_TWLOE in cycles
-///
-template< fapi2::TargetType T >
-inline uint64_t twlo_twloe(const fapi2::Target<T>& i_target)
-{
- return 12 + mss::ns_to_cycles(i_target, tWLO - tWLOE);
-}
-
-///
/// @brief Convert nanoseconds to picoseconds
/// @tparam T input and output type
/// @param[in] i_time_in_ns time in nanoseconds
@@ -352,6 +346,19 @@ inline T ps_to_ns(const T i_time_in_ps)
return l_time_in_ns + ( remainder == 0 ? 0 : 1 );
}
+///
+/// @brief Return the maximum of two values *in clocks*, the first in clocks the second in ns
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_clocks a value in clocks
+/// @param[in] i_time a value in nanoseconds
+/// @return max( iclocks nCK, i_time ) in clocks
+///
+template< fapi2::TargetType T >
+inline uint64_t max_ck_ns(const fapi2::Target<T>& i_target, const uint64_t i_clocks, const uint64_t i_time)
+{
+ return std::max( i_clocks, ns_to_cycles(i_target, i_time) );
+}
+
};// mss namespace
OpenPOWER on IntegriCloud