summaryrefslogtreecommitdiffstats
path: root/src/import
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2016-10-11 20:54:09 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2016-10-31 10:36:30 -0400
commitc7cf0b2d56200537be4227b246fa5c4754cc7306 (patch)
tree1d00ece50c9f5a6e582e431ebc2e1b174edbb319 /src/import
parenta0575efc0dae3b41ee95e55d5a5e7acb12418c90 (diff)
downloadtalos-hostboot-c7cf0b2d56200537be4227b246fa5c4754cc7306.tar.gz
talos-hostboot-c7cf0b2d56200537be4227b246fa5c4754cc7306.zip
Fixed CL and timing bugs, unit test augmentations
Fix 3DS timing params for SLR and DLR and add unit tests. Fix CL setting for non-configured ports and add unit CL tests Fixed SPD timing errors, CL, MR, and ddr_phy UT bugs Change-Id: Icc7efcc6f5a01ceee168a10ca8236cb656ba013c Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31066 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Matt K. Light <mklight@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Reviewed-by: Brian R. Silver <bsilver@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31484 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/import')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C3
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C653
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H56
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.C14
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H952
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C441
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H170
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H38
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H151
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.C22
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C25
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C10
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C31
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H39
-rw-r--r--src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml45
-rw-r--r--src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml4
16 files changed, 1883 insertions, 771 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C
index 71a51e7bb..9f2aafc01 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/mrs00.C
@@ -122,7 +122,7 @@ fapi2::ReturnCode mrs00(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
constexpr uint8_t wr_map[WR_COUNT] =
{
// 10 12 14 16 18 20 22 24 26
- 0b0000, 0, 0b0001, 0, 0b0001, 0, 0b0011, 0, 0b0100, 0, 0b0101, 0, 0b0111, 0, 0b0110, 0, 0b1000
+ 0b0000, 0, 0b0001, 0, 0b0010, 0, 0b0011, 0, 0b0100, 0, 0b0101, 0, 0b0111, 0, 0b0110, 0, 0b1000
};
// Map from the CAS Latency attribute to the bits in the MRS
@@ -241,4 +241,3 @@ fapi2::ReturnCode (*mrs00_data::decode)(const ccs::instruction_t<fapi2::TARGET_T
} // ns ddr4
} // ns mss
-
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C
index 5aa4830aa..2feba70b5 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C
@@ -48,6 +48,7 @@
#include <lib/dimm/rank.H>
#include <lib/utils/conversions.H>
#include <lib/utils/find.H>
+#include <math.h>
using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
@@ -387,31 +388,26 @@ fapi_try_exit:
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
-fapi2::ReturnCode eff_config::refresh_interval_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+fapi2::ReturnCode eff_config::dram_trefi(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
{
- uint8_t l_temp_refresh_range = 0;
- uint8_t l_refresh_mode = 0;
- int64_t l_trefi_in_ps = 0;
-
- FAPI_TRY( mss::mrw_temp_refresh_range(l_temp_refresh_range), "Failed mrw_temp_refresh_range()" );
- FAPI_TRY( mss::mrw_fine_refresh_mode(l_refresh_mode), "Failed mrw_fine_refresh_mode()" );
+ uint64_t l_trefi_in_ps = 0;
// Calculates appropriate tREFI based on fine refresh mode
- switch(l_refresh_mode)
+ switch(iv_refresh_mode)
{
case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL:
FAPI_TRY( calc_trefi( mss::refresh_rate::REF1X,
- l_temp_refresh_range,
+ iv_temp_refresh_range,
l_trefi_in_ps),
- "Failed to calculate tREF1 in refresh_interval_time for target %s", mss::c_str(i_target) );
+ "Failed to calculate tREF1 for target %s", mss::c_str(i_target) );
break;
case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X:
case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X:
FAPI_TRY( calc_trefi( mss::refresh_rate::REF2X,
- l_temp_refresh_range,
+ iv_temp_refresh_range,
l_trefi_in_ps),
"Failed to calculate tREF2 for target %s", mss::c_str(i_target) );
break;
@@ -420,7 +416,7 @@ fapi2::ReturnCode eff_config::refresh_interval_time(const fapi2::Target<TARGET_T
case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_4X:
FAPI_TRY( calc_trefi( mss::refresh_rate::REF4X,
- l_temp_refresh_range,
+ iv_temp_refresh_range,
l_trefi_in_ps),
"Failed to calculate tREF4 for target %s", mss::c_str(i_target) );
break;
@@ -431,10 +427,10 @@ fapi2::ReturnCode eff_config::refresh_interval_time(const fapi2::Target<TARGET_T
// if openpower messes this up we can at least catch it
FAPI_ASSERT(false,
fapi2::MSS_INVALID_FINE_REFRESH_MODE().
- set_FINE_REF_MODE(l_refresh_mode),
+ set_FINE_REF_MODE(iv_refresh_mode),
"%s Incorrect Fine Refresh Mode received: %d ",
mss::c_str(i_target),
- l_refresh_mode);
+ iv_refresh_mode);
break;
}
@@ -444,17 +440,18 @@ fapi2::ReturnCode eff_config::refresh_interval_time(const fapi2::Target<TARGET_T
const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) );
std::vector<uint16_t> l_mcs_attrs_trefi(PORTS_PER_MCS, 0);
- uint16_t l_trefi_in_nck = 0;
+ uint64_t l_trefi_in_nck = 0;
// Retrieve MCS attribute data
FAPI_TRY( eff_dram_trefi(l_mcs, l_mcs_attrs_trefi.data()) );
// Calculate nck
- // iv_tCK-in_ps will always be positive
- FAPI_TRY( calc_nck(l_trefi_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trefi_in_nck),
+ FAPI_TRY( spd::calc_nck(l_trefi_in_ps, static_cast<uint64_t>(iv_tCK_in_ps), INVERSE_DDR4_CORRECTION_FACTOR,
+ l_trefi_in_nck),
"Error in calculating tREFI for target %s, with value of l_trefi_in_ps: %d", mss::c_str(i_target), l_trefi_in_ps);
- FAPI_INF("Calculated tREFI (ps): %d, tREFI (nck): %d", l_trefi_in_ps, l_trefi_in_nck);
+ FAPI_INF("tCK (ps): %d, tREFI (ps): %d, tREFI (nck): %d",
+ iv_tCK_in_ps, l_trefi_in_ps, l_trefi_in_nck);
// Update MCS attribute
l_mcs_attrs_trefi[l_port_num] = l_trefi_in_nck;
@@ -476,17 +473,13 @@ fapi_try_exit:
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
-fapi2::ReturnCode eff_config::refresh_cycle_time(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+fapi2::ReturnCode eff_config::dram_trfc(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
{
- uint8_t l_refresh_mode = 0;
int64_t l_trfc_mtb = 0;
int64_t l_trfc_in_ps = 0;
- FAPI_TRY ( mss::mrw_fine_refresh_mode(l_refresh_mode),
- "Failed to get MRW attribute for fine refresh mode" );
-
// Selects appropriate tRFC based on fine refresh mode
- switch(l_refresh_mode)
+ switch(iv_refresh_mode)
{
case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL:
FAPI_TRY( iv_pDecoder->min_refresh_recovery_delay_time_1(i_target, l_trfc_mtb),
@@ -511,11 +504,10 @@ fapi2::ReturnCode eff_config::refresh_cycle_time(const fapi2::Target<TARGET_TYPE
// if openpower messes this up we can at least catch it
FAPI_ASSERT(false,
fapi2::MSS_INVALID_FINE_REFRESH_MODE().
- set_FINE_REF_MODE(l_refresh_mode),
+ set_FINE_REF_MODE(iv_refresh_mode),
"%s Incorrect Fine Refresh Mode received: %d ",
mss::c_str(i_target),
- l_refresh_mode);
-
+ iv_refresh_mode);
break;
}// switch
@@ -529,7 +521,10 @@ fapi2::ReturnCode eff_config::refresh_cycle_time(const fapi2::Target<TARGET_TYPE
FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- l_trfc_in_ps = calc_timing_from_timebase(l_trfc_mtb, l_mtb, l_trfc_ftb, l_ftb);
+ FAPI_INF( "medium timebase (ps): %ld, fine timebase (ps): %ld, tRFC (MTB): %ld, tRFC(FTB): %ld",
+ l_mtb, l_ftb, l_trfc_mtb, l_trfc_ftb );
+
+ l_trfc_in_ps = spd::calc_timing_from_timebase(l_trfc_mtb, l_mtb, l_trfc_ftb, l_ftb);
}
{
@@ -545,9 +540,11 @@ fapi2::ReturnCode eff_config::refresh_cycle_time(const fapi2::Target<TARGET_TYPE
"Failed to retrieve tRFC attribute" );
// Calculate nck
- FAPI_TRY( calc_nck(l_trfc_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_in_nck),
+ FAPI_TRY( spd::calc_nck(l_trfc_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_in_nck),
"Error in calculating l_tRFC for target %s, with value of l_trfc_in_ps: %d", mss::c_str(i_target), l_trfc_in_ps);
- FAPI_INF("Calculated tRFC (ps): %d, tRFC (nck): %d", l_trfc_in_ps, l_trfc_in_nck);
+
+ FAPI_INF("tCK (ps): %d, tRFC (ps): %d, tRFC (nck): %d",
+ iv_tCK_in_ps, l_trfc_in_ps, l_trfc_in_nck);
// Update MCS attribute
l_mcs_attrs_trfc[l_port_num] = l_trfc_in_nck;
@@ -568,12 +565,11 @@ fapi_try_exit:
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
-fapi2::ReturnCode eff_config::refresh_cycle_time_dlr(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+fapi2::ReturnCode eff_config::dram_trfc_dlr(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
{
const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) );
- uint8_t l_refresh_mode = 0;
uint8_t l_density = 0;
uint64_t l_tCK_in_ps = 0;
uint64_t l_trfc_dlr_in_ps = 0;
@@ -582,21 +578,21 @@ fapi2::ReturnCode eff_config::refresh_cycle_time_dlr(const fapi2::Target<TARGET_
// Retrieve map params
FAPI_TRY( iv_pDecoder->sdram_density(i_target, l_density), "Failed to get sdram density");
- FAPI_TRY ( mss::mrw_fine_refresh_mode(l_refresh_mode), "Failed to get MRW attribute for fine refresh mode" );
+ FAPI_TRY ( mss::mrw_fine_refresh_mode(iv_refresh_mode), "Failed to get MRW attribute for fine refresh mode" );
FAPI_INF("Retrieved SDRAM density: %d, fine refresh mode: %d",
- l_density, l_refresh_mode);
+ l_density, iv_refresh_mode);
// Calculate refresh cycle time in ps
- FAPI_TRY( calc_trfc_dlr(l_refresh_mode, l_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" );
+ FAPI_TRY( calc_trfc_dlr(iv_refresh_mode, l_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" );
// Calculate clock period (tCK) from selected freq from mss_freq
FAPI_TRY( clock_period(i_target, l_tCK_in_ps), "Failed to calculate clock period (tCK)");
// Calculate refresh cycle time in nck
- FAPI_TRY( calc_nck(l_trfc_dlr_in_ps, l_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_dlr_in_nck));
+ FAPI_TRY( spd::calc_nck(l_trfc_dlr_in_ps, l_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_dlr_in_nck));
- FAPI_INF("Calculated clock period (tCK): %d, tRFC_DLR (ps): %d, tRFC_DLR (nck): %d",
+ FAPI_INF("tCK (ps): %d, tRFC_DLR (ps): %d, tRFC_DLR (nck): %d",
l_tCK_in_ps, l_trfc_dlr_in_ps, l_trfc_dlr_in_nck);
// Retrieve MCS attribute data
@@ -716,7 +712,7 @@ fapi2::ReturnCode eff_config::dram_dqs_time(const fapi2::Target<TARGET_TYPE_DIMM
// Get & update MCS attribute
FAPI_TRY( eff_dram_tdqs(l_mcs, &l_attrs_dqs_time[0]) );
- FAPI_INF("Dram width is %ld for target %s", l_dram_width, mss::c_str(i_target));
+ FAPI_INF("SDRAM width: %d for target %s", l_dram_width, mss::c_str(i_target));
//Only possible dram width are x4, x8. If x8, tdqs is available, else not available
l_attrs_dqs_time[l_port_num] = (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ?
@@ -735,26 +731,36 @@ fapi_try_exit:
///
fapi2::ReturnCode eff_config::dram_tccd_l(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
{
- int64_t l_tccd_mtb = 0;
- int64_t l_tccd_ftb = 0;
int64_t l_tccd_in_ps = 0;
- //Get the tCCD timing values
- FAPI_TRY( iv_pDecoder->min_tccd_l(i_target, l_tccd_mtb), "failed to get min_tccd_l" );
- FAPI_TRY( iv_pDecoder->fine_offset_min_tccd_l(i_target, l_tccd_ftb) );
+ // Get the tCCD_L timing values
+ // tCCD_L is speed bin independent and is
+ // the same for all bins within a speed grade.
+ // It is safe to read this from SPD because the correct nck
+ // value will be calulated based on our dimm speed.
- //Calculate tccd in ps
+ // TODO: RTC 163150 Clean up eff_config timing boilerplate
{
int64_t l_ftb = 0;
int64_t l_mtb = 0;
-
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
-
- l_tccd_in_ps = calc_timing_from_timebase(l_tccd_mtb, l_mtb, l_tccd_ftb, l_ftb);
+ int64_t l_tccd_mtb = 0;
+ int64_t l_tccd_ftb = 0;
+
+ FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb),
+ "Failed medium_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb),
+ "Failed fine_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->min_tccd_l(i_target, l_tccd_mtb),
+ "Failed min_tccd_l() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_offset_min_tccd_l(i_target, l_tccd_ftb),
+ "Failed fine_offset_min_tccd_l() for %s", mss::c_str(i_target) );
+
+ FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tCCD_L (MTB): %ld, tCCD_L(FTB): %ld",
+ l_mtb, l_ftb, l_tccd_mtb, l_tccd_ftb );
+
+ l_tccd_in_ps = spd::calc_timing_from_timebase(l_tccd_mtb, l_mtb, l_tccd_ftb, l_ftb);
}
-
{
// Calculate refresh cycle time in nCK & set attribute
const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
@@ -768,9 +774,11 @@ fapi2::ReturnCode eff_config::dram_tccd_l(const fapi2::Target<TARGET_TYPE_DIMM>&
"Failed to retrieve tCCD attribute" );
// Calculate nck
- FAPI_TRY ( calc_nck(l_tccd_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_tccd_in_nck),
+ FAPI_TRY ( spd::calc_nck(l_tccd_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_tccd_in_nck),
"Error in calculating tccd for target %s, with value of l_tccd_in_ps: %d", mss::c_str(i_target), l_tccd_in_ps);
- FAPI_INF("Calculated tCCD (ps): %d, tCCD (nck): %d", l_tccd_in_ps, l_tccd_in_nck);
+
+ FAPI_INF("tCK (ps): %d, tCCD_L (ps): %d, tCCD_L (nck): %d",
+ iv_tCK_in_ps, l_tccd_in_ps, l_tccd_in_nck);
// Update MCS attribute
l_mcs_attrs_tccd[l_port_num] = l_tccd_in_nck;
@@ -808,7 +816,7 @@ fapi2::ReturnCode eff_config::dimm_rc00(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc00[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc00;
- FAPI_INF("%s: RC00 settting: %d", c_str(i_target), l_attrs_dimm_rc00[l_port_num][l_dimm_num] );
+ FAPI_INF("%s: RC00 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc00[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC00, l_mcs, l_attrs_dimm_rc00) );
fapi_try_exit:
@@ -837,7 +845,7 @@ fapi2::ReturnCode eff_config::dimm_rc01(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc01[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc01;
- FAPI_INF("%s: RC01 settting: %d", c_str(i_target), l_attrs_dimm_rc01[l_port_num][l_dimm_num] );
+ FAPI_INF("%s: RC01 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc01[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC01, l_mcs, l_attrs_dimm_rc01) );
fapi_try_exit:
@@ -866,7 +874,7 @@ fapi2::ReturnCode eff_config::dimm_rc02(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc02[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc02;
- FAPI_INF("%s: RC02 settting: %d", c_str(i_target), l_attrs_dimm_rc02[l_port_num][l_dimm_num] );
+ FAPI_INF("%s: RC02 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc02[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC02, l_mcs, l_attrs_dimm_rc02) );
fapi_try_exit:
@@ -898,7 +906,7 @@ fapi2::ReturnCode eff_config::dimm_rc03(const fapi2::Target<TARGET_TYPE_DIMM>& i
FAPI_TRY( iv_pDecoder->iv_module_decoder->ca_signal_output_driver(l_ca_output_drive) );
FAPI_INF( "%s: Retrieved register output drive, for CA: %d, CS: %d",
- c_str(i_target), l_ca_output_drive, l_cs_output_drive );
+ mss::c_str(i_target), l_ca_output_drive, l_cs_output_drive );
// Lets construct encoding byte for RCD setting
{
@@ -916,7 +924,7 @@ fapi2::ReturnCode eff_config::dimm_rc03(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc03[l_port_num][l_dimm_num] = l_buffer;
- FAPI_INF("%s: RC03 settting: %d", c_str(i_target), l_attrs_dimm_rc03[l_port_num][l_dimm_num] );
+ FAPI_INF("%s: RC03 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc03[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC03, l_mcs, l_attrs_dimm_rc03) );
fapi_try_exit:
@@ -948,7 +956,7 @@ fapi2::ReturnCode eff_config::dimm_rc04(const fapi2::Target<TARGET_TYPE_DIMM>& i
FAPI_TRY( iv_pDecoder->iv_module_decoder->cke_signal_output_driver(l_cke_output_drive) );
FAPI_INF( "%s: Retrieved signal driver output, for CKE: %d, ODT: %d",
- c_str(i_target), l_cke_output_drive, l_odt_output_drive );
+ mss::c_str(i_target), l_cke_output_drive, l_odt_output_drive );
// Lets construct encoding byte for RCD setting
{
@@ -967,7 +975,7 @@ fapi2::ReturnCode eff_config::dimm_rc04(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc04[l_port_num][l_dimm_num] = l_buffer;
- FAPI_INF("%s: RC04 setting: %d", c_str(i_target), l_attrs_dimm_rc04[l_port_num][l_dimm_num] );
+ FAPI_INF("%s: RC04 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc04[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC04, l_mcs, l_attrs_dimm_rc04) );
fapi_try_exit:
@@ -999,7 +1007,7 @@ fapi2::ReturnCode eff_config::dimm_rc05(const fapi2::Target<TARGET_TYPE_DIMM>& i
FAPI_TRY( iv_pDecoder->iv_module_decoder->b_side_clk_output_driver(l_b_side_output_drive) );
FAPI_INF( "%s: Retrieved register output drive for clock, b-side (Y0,Y2): %d, a-side (Y1,Y3): %d",
- c_str(i_target), l_b_side_output_drive, l_a_side_output_drive );
+ mss::c_str(i_target), l_b_side_output_drive, l_a_side_output_drive );
{
// Buffer insert constants for ODT and CKE output drive
@@ -1018,7 +1026,7 @@ fapi2::ReturnCode eff_config::dimm_rc05(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc05[l_port_num][l_dimm_num] = l_buffer;
- FAPI_INF( "%s: RC05 setting: %d", c_str(i_target), l_attrs_dimm_rc05[l_port_num][l_dimm_num] )
+ FAPI_INF( "%s: RC05 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc05[l_port_num][l_dimm_num] )
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC05, l_mcs, l_attrs_dimm_rc05) );
fapi_try_exit:
@@ -1047,7 +1055,7 @@ fapi2::ReturnCode eff_config::dimm_rc06_07(const fapi2::Target<TARGET_TYPE_DIMM>
// Update MCS attribute
l_attrs_dimm_rc06_07[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc06_07;
- FAPI_INF( "%s: RC06_07 setting: %d", c_str(i_target), l_attrs_dimm_rc06_07[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC06_07 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc06_07[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC06_07, l_mcs, l_attrs_dimm_rc06_07) );
fapi_try_exit:
@@ -1076,7 +1084,7 @@ fapi2::ReturnCode eff_config::dimm_rc08(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc08[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc08;
- FAPI_INF( "%s: RC08 setting: %d", c_str(i_target), l_attrs_dimm_rc08[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC08 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc08[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC08, l_mcs, l_attrs_dimm_rc08) );
fapi_try_exit:
@@ -1107,7 +1115,7 @@ fapi2::ReturnCode eff_config::dimm_rc09(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc09[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc09;
- FAPI_INF( "%s: RC09 setting: %d", c_str(i_target), l_attrs_dimm_rc09[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC09 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc09[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC09, l_mcs, l_attrs_dimm_rc09) );
fapi_try_exit:
@@ -1162,7 +1170,7 @@ fapi2::ReturnCode eff_config::dimm_rc10(const fapi2::Target<TARGET_TYPE_DIMM>& i
break;
}
- FAPI_INF( "%s: RC10 setting: %d", c_str(i_target), l_attrs_dimm_rc10[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC10 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc10[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC10, l_mcs, l_attrs_dimm_rc10) );
fapi_try_exit:
@@ -1191,7 +1199,7 @@ fapi2::ReturnCode eff_config::dimm_rc11(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc11[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0b;
- FAPI_INF( "%s: RC11 setting: %d", c_str(i_target), l_attrs_dimm_rc11[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC11 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc11[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC11, l_mcs, l_attrs_dimm_rc11) );
fapi_try_exit:
@@ -1220,7 +1228,7 @@ fapi2::ReturnCode eff_config::dimm_rc12(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc12[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0c;
- FAPI_INF( "%s: R12 setting: %d", c_str(i_target), l_attrs_dimm_rc12[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: R12 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc12[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC12, l_mcs, l_attrs_dimm_rc12) );
fapi_try_exit:
@@ -1285,7 +1293,7 @@ fapi2::ReturnCode eff_config::dimm_rc13(const fapi2::Target<TARGET_TYPE_DIMM>& i
FAPI_TRY( spd::base_module_type(i_target, iv_pDecoder->iv_spd_data, l_dimm_type) );
l_attrs_dimm_rc13[l_port_num][l_dimm_num] = l_buffer;
- FAPI_INF( "%s: RC13 setting: %d", c_str(i_target), l_attrs_dimm_rc13[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC13 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc13[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC13, l_mcs, l_attrs_dimm_rc13) );
fapi_try_exit:
@@ -1314,7 +1322,7 @@ fapi2::ReturnCode eff_config::dimm_rc14(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc14[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0e;
- FAPI_INF( "%s: RC14 setting: 0x%0x", c_str(i_target), l_attrs_dimm_rc14[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC14 setting: 0x%0x", mss::c_str(i_target), l_attrs_dimm_rc14[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC14, l_mcs, l_attrs_dimm_rc14) );
fapi_try_exit:
@@ -1343,7 +1351,7 @@ fapi2::ReturnCode eff_config::dimm_rc15(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc15[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0f;
- FAPI_INF( "%s: RC15 setting: %d", c_str(i_target), l_attrs_dimm_rc15[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC15 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc15[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC15, l_mcs, l_attrs_dimm_rc15) );
fapi_try_exit:
@@ -1372,7 +1380,7 @@ fapi2::ReturnCode eff_config::dimm_rc1x(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_1x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc1x;
- FAPI_INF( "%s: RC1X setting: %d", c_str(i_target), l_attrs_dimm_rc_1x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC1X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_1x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_1x, l_mcs, l_attrs_dimm_rc_1x) );
fapi_try_exit:
@@ -1401,7 +1409,7 @@ fapi2::ReturnCode eff_config::dimm_rc2x(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_2x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc2x;
- FAPI_INF( "%s: RC2X setting: %d", c_str(i_target), l_attrs_dimm_rc_2x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC2X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_2x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_2x, l_mcs, l_attrs_dimm_rc_2x) );
fapi_try_exit:
@@ -1456,7 +1464,7 @@ fapi2::ReturnCode eff_config::dimm_rc3x(const fapi2::Target<TARGET_TYPE_DIMM>& i
break;
}
- FAPI_INF( "%s: RC3X setting: %d", c_str(i_target), l_attrs_dimm_rc_3x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC3X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_3x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_3x, l_mcs, l_attrs_dimm_rc_3x) );
@@ -1486,7 +1494,7 @@ fapi2::ReturnCode eff_config::dimm_rc4x(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_4x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc4x;
- FAPI_INF( "%s: RC4X setting: %d", c_str(i_target), l_attrs_dimm_rc_4x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC4X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_4x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_4x, l_mcs, l_attrs_dimm_rc_4x) );
fapi_try_exit:
@@ -1515,7 +1523,7 @@ fapi2::ReturnCode eff_config::dimm_rc5x(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_5x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc5x;
- FAPI_INF( "%s: RC5X setting: %d", c_str(i_target), l_attrs_dimm_rc_5x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC5X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_5x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_5x, l_mcs, l_attrs_dimm_rc_5x) );
fapi_try_exit:
@@ -1544,7 +1552,7 @@ fapi2::ReturnCode eff_config::dimm_rc6x(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_6x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc6x;
- FAPI_INF( "%s: RC6X setting: %d", c_str(i_target), l_attrs_dimm_rc_6x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC6X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_6x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_6x, l_mcs, l_attrs_dimm_rc_6x) );
fapi_try_exit:
@@ -1631,7 +1639,7 @@ fapi2::ReturnCode eff_config::dimm_rc8x(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_8x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc8x;
- FAPI_INF( "%s: RC8X setting: %d", c_str(i_target), l_attrs_dimm_rc_8x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC8X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_8x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_8x, l_mcs, l_attrs_dimm_rc_8x) );
fapi_try_exit:
@@ -1660,7 +1668,7 @@ fapi2::ReturnCode eff_config::dimm_rc9x(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_9x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc9x;
- FAPI_INF( "%s: RC9X setting: %d", c_str(i_target), l_attrs_dimm_rc_9x[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RC9X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_9x[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_9x, l_mcs, l_attrs_dimm_rc_9x) );
fapi_try_exit:
@@ -1689,7 +1697,7 @@ fapi2::ReturnCode eff_config::dimm_rcax(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_ax[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rcax;
- FAPI_INF( "%s: RCAX setting: %d", c_str(i_target), l_attrs_dimm_rc_ax[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RCAX setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_ax[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_Ax, l_mcs, l_attrs_dimm_rc_ax) );
fapi_try_exit:
@@ -1718,7 +1726,7 @@ fapi2::ReturnCode eff_config::dimm_rcbx(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Update MCS attribute
l_attrs_dimm_rc_bx[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rcbx;
- FAPI_INF( "%s: RCBX setting: %d", c_str(i_target), l_attrs_dimm_rc_bx[l_port_num][l_dimm_num] );
+ FAPI_INF( "%s: RCBX setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_bx[l_port_num][l_dimm_num] );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_Bx, l_mcs, l_attrs_dimm_rc_bx) );
fapi_try_exit:
@@ -1736,31 +1744,41 @@ fapi2::ReturnCode eff_config::dram_twr(const fapi2::Target<TARGET_TYPE_DIMM>& i_
const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
int64_t l_twr_in_ps = 0;
- // Calculate twr (in ps)
+ // Get the tWR timing values
+ // tWR is speed bin independent and is
+ // the same for all bins within a speed grade.
+ // It is safe to read this from SPD because the correct nck
+ // value will be calulated based on our dimm speed.
{
constexpr int64_t l_twr_ftb = 0;
int64_t l_twr_mtb = 0;
int64_t l_ftb = 0;
int64_t l_mtb = 0;
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- FAPI_TRY( iv_pDecoder->min_write_recovery_time(i_target, l_twr_mtb) );
- FAPI_INF("Values for write_recovery (twr) in MTB units: medium timebase: %ld, fine timebase: %ld, and min write: %ld",
- l_mtb, l_ftb, l_twr_mtb);
- l_twr_in_ps = calc_timing_from_timebase(l_twr_mtb, l_mtb, l_twr_ftb, l_ftb);
+ FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb),
+ "Failed medium_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb),
+ "Failed fine_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->min_write_recovery_time(i_target, l_twr_mtb),
+ "Failed min_write_recovery_time() for %s", mss::c_str(i_target) );
+
+ FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWR (MTB): %ld, tWR(FTB): %ld",
+ l_mtb, l_ftb, l_twr_mtb, l_twr_ftb);
+
+ // Calculate twr (in ps)
+ l_twr_in_ps = spd::calc_timing_from_timebase(l_twr_mtb, l_mtb, l_twr_ftb, l_ftb);
}
{
std::vector<uint8_t> l_attrs_dram_twr(PORTS_PER_MCS, 0);
uint8_t l_twr_in_nck = 0;
- FAPI_INF("iv tck is %d", iv_tCK_in_ps);
// Calculate tNCK
- FAPI_TRY( calc_nck(l_twr_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twr_in_nck),
+ FAPI_TRY( spd::calc_nck(l_twr_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twr_in_nck),
"Error in calculating l_twr_in_nck for target %s, with value of l_twr_in_ps: %d", mss::c_str(i_target), l_twr_in_ps);
- FAPI_INF("Calculated tWR (ps): %d, tWR (nck): %d for target: %s", l_twr_in_ps, l_twr_in_nck, mss::c_str(i_target));
+ FAPI_INF( "tCK (ps): %d, tWR (ps): %d, tWR (nck): %d for target: %s",
+ iv_tCK_in_ps, l_twr_in_ps, l_twr_in_nck, mss::c_str(i_target) );
// Get & update MCS attribute
FAPI_TRY( eff_dram_twr(l_mcs, l_attrs_dram_twr.data()) );
@@ -1885,7 +1903,7 @@ fapi2::ReturnCode eff_config::dram_cwl(const fapi2::Target<TARGET_TYPE_DIMM>& i_
.set_VALUE(l_preamble)
.set_DIMM_TARGET(i_target),
"Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d",
- c_str(i_target),
+ mss::c_str(i_target),
l_preamble );
FAPI_TRY( mss::freq(l_mcbist, l_freq) );
@@ -1942,7 +1960,7 @@ fapi2::ReturnCode eff_config::dram_lpasr(const fapi2::Target<TARGET_TYPE_DIMM>&
FAPI_TRY( eff_dram_lpasr(l_mcs, l_attrs_lpasr.data()) );
- l_attrs_lpasr[l_port_num] = fapi2::ENUM_ATTR_EFF_DRAM_LPASR_ASR;
+ l_attrs_lpasr[l_port_num] = fapi2::ENUM_ATTR_EFF_DRAM_LPASR_MANUAL_EXTENDED;
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_LPASR,
l_mcs,
@@ -2262,7 +2280,7 @@ fapi2::ReturnCode eff_config::crc_error_clear(const fapi2::Target<TARGET_TYPE_DI
FAPI_TRY( eff_crc_error_clear(l_mcs, l_attrs_crc_error_clear.data()) );
- l_attrs_crc_error_clear[l_port_num] = fapi2::ENUM_ATTR_EFF_CRC_ERROR_CLEAR_ERROR;
+ l_attrs_crc_error_clear[l_port_num] = fapi2::ENUM_ATTR_EFF_CRC_ERROR_CLEAR_CLEAR;
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CRC_ERROR_CLEAR,
l_mcs,
@@ -2530,7 +2548,7 @@ fapi2::ReturnCode eff_config::read_preamble(const fapi2::Target<TARGET_TYPE_DIMM
.set_VALUE(l_preamble)
.set_DIMM_TARGET(i_target),
"Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d",
- c_str(i_target),
+ mss::c_str(i_target),
l_preamble );
FAPI_TRY( eff_rd_preamble(l_mcs, l_attrs_rd_preamble.data()) );
@@ -2571,7 +2589,7 @@ fapi2::ReturnCode eff_config::write_preamble(const fapi2::Target<TARGET_TYPE_DIM
.set_VALUE(l_preamble)
.set_DIMM_TARGET(i_target),
"Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d",
- c_str(i_target),
+ mss::c_str(i_target),
l_preamble );
FAPI_TRY( eff_wr_preamble(l_mcs, l_attrs_wr_preamble.data()) );
@@ -3064,12 +3082,26 @@ fapi2::ReturnCode eff_config::dram_trp(const fapi2::Target<TARGET_TYPE_DIMM>& i_
int64_t l_ftb = 0;
int64_t l_mtb = 0;
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- FAPI_TRY( iv_pDecoder->min_row_precharge_delay_time(i_target, l_trp_mtb) );
- FAPI_TRY( iv_pDecoder->fine_offset_min_trp(i_target, l_trp_ftb) );
+ FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb),
+ "Failed medium_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb),
+ "Failed fine_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->min_row_precharge_delay_time(i_target, l_trp_mtb),
+ "Failed min_row_precharge_delay_time() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_offset_min_trp(i_target, l_trp_ftb),
+ "Failed fine_offset_min_trp() for %s", mss::c_str(i_target) );
+
+ FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tRP (MTB): %ld, tRP(FTB): %ld",
+ l_mtb, l_ftb, l_trp_mtb, l_trp_ftb);
- l_trp_in_ps = calc_timing_from_timebase(l_trp_mtb, l_mtb, l_trp_ftb, l_ftb);
+ l_trp_in_ps = spd::calc_timing_from_timebase(l_trp_mtb, l_mtb, l_trp_ftb, l_ftb);
+ }
+
+ // SPD spec gives us the minimum... compute our worstcase (maximum) from JEDEC
+ {
+ // Declaring as int64_t to fix std::max compile
+ const int64_t l_trp = mss::ps_to_cycles(i_target, mss::trtp());
+ l_trp_in_ps = std::max( l_trp_in_ps , l_trp );
}
{
@@ -3077,10 +3109,11 @@ fapi2::ReturnCode eff_config::dram_trp(const fapi2::Target<TARGET_TYPE_DIMM>& i_
uint8_t l_trp_in_nck = 0;
// Calculate nck
- FAPI_TRY( calc_nck(l_trp_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trp_in_nck),
+ FAPI_TRY( spd::calc_nck(l_trp_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trp_in_nck),
"Error in calculating dram_tRP nck for target %s, with value of l_trp_in_ps: %d", mss::c_str(i_target), l_trp_in_ps);
- FAPI_INF("Calculated trp (ps): %d, trp (nck): %d for target: %s", l_trp_in_ps, l_trp_in_nck, mss::c_str(i_target));
+ FAPI_INF( "tCK (ps): %d, tRP (ps): %d, tRP (nck): %d for target: %s",
+ iv_tCK_in_ps, l_trp_in_ps, l_trp_in_nck, mss::c_str(i_target) );
// Get & update MCS attribute
FAPI_TRY( eff_dram_trp(l_mcs, l_attrs_dram_trp.data()) );
@@ -3107,31 +3140,43 @@ fapi2::ReturnCode eff_config::dram_trcd(const fapi2::Target<TARGET_TYPE_DIMM>& i
const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
int64_t l_trcd_in_ps = 0;
- // Calculate trcd (in ps)
+ // Calculate tRCD (in ps)
+ // Get the tRCD timing values
+ // tRCD is speed bin dependent and has a unique
+ // value for each speed bin so it is safe to
+ // read from SPD because the correct nck
+ // value will be calulated based on our dimm speed.
{
int64_t l_trcd_mtb = 0;
int64_t l_trcd_ftb = 0;
int64_t l_ftb = 0;
int64_t l_mtb = 0;
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- FAPI_TRY( iv_pDecoder->min_ras_to_cas_delay_time(i_target, l_trcd_mtb) );
- FAPI_TRY( iv_pDecoder->fine_offset_min_trcd(i_target, l_trcd_ftb) );
- FAPI_INF( "trcd values are: min_trcd %d, fine offset is %d", l_trcd_mtb, l_trcd_ftb);
- l_trcd_in_ps = calc_timing_from_timebase(l_trcd_mtb, l_mtb, l_trcd_ftb, l_ftb);
- }
+ FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb),
+ "Failed medium_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb),
+ "Failed fine_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->min_ras_to_cas_delay_time(i_target, l_trcd_mtb),
+ "Failed min_ras_to_cas_delay_time() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_offset_min_trcd(i_target, l_trcd_ftb),
+ "Failed fine_offset_min_trcd() for %s", mss::c_str(i_target) );
+ FAPI_INF("medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCD (MTB): %ld, tRCD (FTB): %ld",
+ l_mtb, l_ftb, l_trcd_mtb, l_trcd_ftb);
+
+ l_trcd_in_ps = spd::calc_timing_from_timebase(l_trcd_mtb, l_mtb, l_trcd_ftb, l_ftb);
+ }
{
std::vector<uint8_t> l_attrs_dram_trcd(PORTS_PER_MCS, 0);
uint8_t l_trcd_in_nck = 0;
// Calculate nck
- FAPI_TRY( calc_nck(l_trcd_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trcd_in_nck),
+ FAPI_TRY( spd::calc_nck(l_trcd_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trcd_in_nck),
"Error in calculating trcd for target %s, with value of l_trcd_in_ps: %d", mss::c_str(i_target), l_trcd_in_ps);
- FAPI_INF("Calculated trcd (ps): %d, trcd (nck): %d for target: %s", l_trcd_in_ps, l_trcd_in_nck, mss::c_str(i_target));
+ FAPI_INF("tCK (ps): %d, tRCD (ps): %d, tRCD (nck): %d for target: %s",
+ iv_tCK_in_ps, l_trcd_in_ps, l_trcd_in_nck, mss::c_str(i_target));
// Get & update MCS attribute
FAPI_TRY( eff_dram_trcd(l_mcs, l_attrs_dram_trcd.data()) );
@@ -3148,6 +3193,65 @@ fapi_try_exit:
}
///
+/// @brief Determines & sets effective config for tRC
+/// @param[in] i_target FAPI2 target
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+///
+fapi2::ReturnCode eff_config::dram_trc(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+{
+ const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
+ int64_t l_trc_in_ps = 0;
+
+ // Calculate trc (in ps)
+ {
+ int64_t l_trc_mtb = 0;
+ int64_t l_trc_ftb = 0;
+ int64_t l_ftb = 0;
+ int64_t l_mtb = 0;
+
+ FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb),
+ "Failed medium_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb),
+ "Failed fine_timebase() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->min_active_to_active_refresh_delay_time(i_target, l_trc_mtb),
+ "Failed min_active_to_active_refresh_delay_time() for %s", mss::c_str(i_target) );
+ FAPI_TRY( iv_pDecoder->fine_offset_min_trc(i_target, l_trc_ftb),
+ "Failed fine_offset_min_trc() for %s", mss::c_str(i_target) );
+
+ FAPI_INF("medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCmin (MTB): %ld, tRCmin(FTB): %ld",
+ l_mtb, l_ftb, l_trc_mtb, l_trc_ftb);
+
+ l_trc_in_ps = spd::calc_timing_from_timebase(l_trc_mtb, l_mtb, l_trc_ftb, l_ftb);
+ }
+
+ {
+ std::vector<uint8_t> l_attrs_dram_trc(PORTS_PER_MCS, 0);
+ uint8_t l_trc_in_nck = 0;
+
+ // Calculate nck
+ FAPI_TRY( spd::calc_nck(l_trc_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trc_in_nck),
+ "Error in calculating trc for target %s, with value of l_trc_in_ps: %d",
+ mss::c_str(i_target), l_trc_in_ps );
+
+ FAPI_INF( "tCK (ps): %d, tRC (ps): %d, tRC (nck): %d for target: %s",
+ iv_tCK_in_ps, l_trc_in_ps, l_trc_in_nck, mss::c_str(i_target) );
+
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_trc(l_mcs, l_attrs_dram_trc.data()) );
+
+ l_attrs_dram_trc[l_port_num] = l_trc_in_nck;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRC,
+ l_mcs,
+ UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trc, PORTS_PER_MCS)),
+ "Failed setting attribute for DRAM_TRC");
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
/// @brief Determines & sets effective config for tWTR_L
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
@@ -3169,7 +3273,10 @@ fapi2::ReturnCode eff_config::dram_twtr_l(const fapi2::Target<TARGET_TYPE_DIMM>&
FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
FAPI_TRY( iv_pDecoder->min_twtr_l(i_target, l_twtr_l_mtb) );
- l_twtr_l_in_ps = calc_timing_from_timebase(l_twtr_l_mtb, l_mtb, l_twtr_l_ftb, l_ftb);
+ FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld",
+ l_mtb, l_ftb, l_twtr_l_mtb, l_twtr_l_ftb );
+
+ l_twtr_l_in_ps = spd::calc_timing_from_timebase(l_twtr_l_mtb, l_mtb, l_twtr_l_ftb, l_ftb);
}
@@ -3177,12 +3284,12 @@ fapi2::ReturnCode eff_config::dram_twtr_l(const fapi2::Target<TARGET_TYPE_DIMM>&
std::vector<uint8_t> l_attrs_dram_twtr_l(PORTS_PER_MCS, 0);
int8_t l_twtr_l_in_nck = 0;
- // Calculate tNCK
- FAPI_TRY( calc_nck(l_twtr_l_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_l_in_nck),
- "Error in calculating twtr_l for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_twtr_l_in_ps );
+ // Calculate nck
+ FAPI_TRY( spd::calc_nck(l_twtr_l_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_l_in_nck),
+ "Error in calculating tWTR_L for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_twtr_l_in_ps );
- FAPI_INF("Calculated twtr_l (ps): %d, twtr_l (nck): %d for target: %s", l_twtr_l_in_ps, l_twtr_l_in_nck,
- mss::c_str(i_target));
+ FAPI_INF( "tCK (ps): %d, tWTR_L (ps): %d, tWTR_L (nck): %d for target: %s",
+ iv_tCK_in_ps, l_twtr_l_in_ps, l_twtr_l_in_nck, mss::c_str(i_target) );
// Get & update MCS attribute
FAPI_TRY( eff_dram_twtr_l(l_mcs, l_attrs_dram_twtr_l.data()) );
@@ -3220,7 +3327,10 @@ fapi2::ReturnCode eff_config::dram_twtr_s(const fapi2::Target<TARGET_TYPE_DIMM>&
FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
FAPI_TRY( iv_pDecoder->min_twtr_s(i_target, l_twtr_s_mtb) );
- l_twtr_s_in_ps = calc_timing_from_timebase(l_twtr_s_mtb, l_mtb, l_twtr_s_ftb, l_ftb);
+ FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld",
+ l_mtb, l_ftb, l_twtr_s_mtb, l_twtr_s_ftb );
+
+ l_twtr_s_in_ps = spd::calc_timing_from_timebase(l_twtr_s_mtb, l_mtb, l_twtr_s_ftb, l_ftb);
}
{
@@ -3228,11 +3338,11 @@ fapi2::ReturnCode eff_config::dram_twtr_s(const fapi2::Target<TARGET_TYPE_DIMM>&
uint8_t l_twtr_s_in_nck = 0;
// Calculate nck
- FAPI_TRY( calc_nck(l_twtr_s_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_s_in_nck),
- "Error in calculating l_twtr_s for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_twtr_s_in_ps);
+ FAPI_TRY( spd::calc_nck(l_twtr_s_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_s_in_nck),
+ "Error in calculating tWTR_S for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_twtr_s_in_ps);
- FAPI_INF("Calculated twtr_s (ps): %d, twtr_s (nck): %d for target: %s", l_twtr_s_in_ps, l_twtr_s_in_nck,
- mss::c_str(i_target));
+ FAPI_INF("tCK (ps): %d, tWTR_S (ps): %d, tWTR_S (nck): %d for target: %s",
+ iv_tCK_in_ps, l_twtr_s_in_ps, l_twtr_s_in_nck, mss::c_str(i_target) );
// Get & update MCS attribute
FAPI_TRY( eff_dram_twtr_s(l_mcs, l_attrs_dram_twtr_s.data()) );
@@ -3257,42 +3367,44 @@ fapi2::ReturnCode eff_config::dram_trrd_s(const fapi2::Target<TARGET_TYPE_DIMM>&
{
const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
- int64_t l_trrd_s_in_ps = 0;
- // Calculate trrd_s (in ps)
- {
- int64_t l_trrd_s_mtb = 0;
- int64_t l_trrd_s_ftb = 0;
- int64_t l_ftb = 0;
- int64_t l_mtb = 0;
+ std::vector<uint8_t> l_attrs_dram_trrd_s(PORTS_PER_MCS, 0);
+ uint64_t l_trrd_s_in_nck = 0;
+ uint8_t l_stack_type = 0;
+ uint8_t l_dram_width = 0;
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- FAPI_TRY( iv_pDecoder->min_trrd_s(i_target, l_trrd_s_mtb) );
- FAPI_TRY( iv_pDecoder->fine_offset_min_trrd_s(i_target, l_trrd_s_ftb) );
+ FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(i_target, l_stack_type) );
+ FAPI_TRY( iv_pDecoder->device_width(i_target, l_dram_width),
+ "Failed to access device_width()");
- l_trrd_s_in_ps = calc_timing_from_timebase(l_trrd_s_mtb, l_mtb, l_trrd_s_ftb, l_ftb);
- }
+ // From the SPD Spec:
+ // At some frequencies, a minimum number of clocks may be required resulting
+ // in a larger tRRD_Smin value than indicated in the SPD.
+ // tRRD_S (3DS) is speed bin independent.
+ // So we won't read this from SPD and choose the correct value based on mss_freq
+ if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS)
{
- std::vector<uint8_t> l_attrs_dram_trrd_s(PORTS_PER_MCS, 0);
- uint8_t l_trrd_s_in_nck = 0;
+ FAPI_TRY( trrd_s_slr(i_target, l_trrd_s_in_nck) );
+ }
+ else
+ {
+ // Non-3DS
+ FAPI_TRY( mss::trrd_s(i_target, l_dram_width, l_trrd_s_in_nck) );
+ }
- // Calculate nck
- FAPI_TRY( calc_nck(l_trrd_s_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_s_in_nck),
- "Error in calculating trrd_s for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_trrd_s_in_ps);
+ FAPI_INF("SDRAM width: %d, tRRD_S (nck): %d for target: %s",
+ l_dram_width, l_trrd_s_in_nck, mss::c_str(i_target));
- FAPI_INF("Calculated trrd_s (ps): %d, trrd_s (nck): %d for target: %s", l_trrd_s_in_ps, l_trrd_s_in_nck,
- mss::c_str(i_target));
- // Get & update MCS attribute
- FAPI_TRY( eff_dram_trrd_s(l_mcs, l_attrs_dram_trrd_s.data()) );
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_trrd_s(l_mcs, l_attrs_dram_trrd_s.data()) );
- l_attrs_dram_trrd_s[l_port_num] = l_trrd_s_in_nck;
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_S,
- l_mcs,
- UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_s, PORTS_PER_MCS)),
- "Failed setting attribute for DRAM_TRRD_S");
- }
+ l_attrs_dram_trrd_s[l_port_num] = l_trrd_s_in_nck;
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_S,
+ l_mcs,
+ UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_s, PORTS_PER_MCS)),
+ "Failed setting attribute for DRAM_TRRD_S");
fapi_try_exit:
return fapi2::current_err;
@@ -3307,43 +3419,72 @@ fapi2::ReturnCode eff_config::dram_trrd_l(const fapi2::Target<TARGET_TYPE_DIMM>&
{
const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
- int64_t l_trrd_l_in_ps = 0;
- // Calculate trrd_l (in ps)
- {
- int64_t l_trrd_l_mtb = 0;
- int64_t l_trrd_l_ftb = 0;
- int64_t l_ftb = 0;
- int64_t l_mtb = 0;
+ std::vector<uint8_t> l_attrs_dram_trrd_l(PORTS_PER_MCS, 0);
+ uint64_t l_trrd_l_in_nck = 0;
+ uint8_t l_stack_type = 0;
+ uint8_t l_dram_width = 0;
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- FAPI_TRY( iv_pDecoder->min_trrd_l(i_target, l_trrd_l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_offset_min_trrd_l(i_target, l_trrd_l_ftb) );
+ FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(i_target, l_stack_type),
+ "Failed prim_sdram_signal_loading()" );
+ FAPI_TRY( iv_pDecoder->device_width(i_target, l_dram_width),
+ "Failed to access device_width()");
- l_trrd_l_in_ps = calc_timing_from_timebase(l_trrd_l_mtb, l_mtb, l_trrd_l_ftb, l_ftb);
- }
+ // From the SPD Spec:
+ // At some frequencies, a minimum number of clocks may be required resulting
+ // in a larger tRRD_Smin value than indicated in the SPD.
+ // tRRD_S (3DS) is speed bin independent.
+ // So we won't read this from SPD and choose the correct value based on mss_freq
+ if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS)
+ {
+ FAPI_TRY( trrd_l_slr(i_target, l_trrd_l_in_nck) );
+ }
+ else
{
- std::vector<uint8_t> l_attrs_dram_trrd_l(PORTS_PER_MCS, 0);
- uint8_t l_trrd_l_in_nck = 0;
+ FAPI_TRY( mss::trrd_l(i_target, l_dram_width, l_trrd_l_in_nck), "Failed trrd_l()" );
+ }
- // Calculate nck
- FAPI_TRY( calc_nck(l_trrd_l_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_l_in_nck),
- "Error in calculating trrd_l for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_trrd_l_in_ps);
+ FAPI_INF("SDRAM width: %d, tRRD_L (nck): %d for target: %s",
+ l_dram_width, l_trrd_l_in_nck, mss::c_str(i_target));
- FAPI_INF("Calculated trrd_l (ps): %d, trrd_l (nck): %d for target: %s", l_trrd_l_in_ps, l_trrd_l_in_nck,
- mss::c_str(i_target));
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_trrd_l(l_mcs, l_attrs_dram_trrd_l.data()) );
- // Get & update MCS attribute
- FAPI_TRY( eff_dram_trrd_l(l_mcs, l_attrs_dram_trrd_l.data()) );
+ l_attrs_dram_trrd_l[l_port_num] = l_trrd_l_in_nck;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_L,
+ l_mcs,
+ UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_l, PORTS_PER_MCS)),
+ "Failed setting attribute for DRAM_TRRD_L");
- l_attrs_dram_trrd_l[l_port_num] = l_trrd_l_in_nck;
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_L,
- l_mcs,
- UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_l, PORTS_PER_MCS)),
- "Failed setting attribute for DRAM_TRRD_L");
- }
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Determines & sets effective config for tRRD_dlr
+/// @param[in] i_target FAPI2 target
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+///
+fapi2::ReturnCode eff_config::dram_trrd_dlr(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+{
+ const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
+
+ std::vector<uint8_t> l_attrs_dram_trrd_dlr(PORTS_PER_MCS, 0);
+ constexpr uint64_t l_trrd_dlr_in_nck = trrd_dlr();
+
+ FAPI_INF("tRRD_dlr (nck): %d for target: %s", l_trrd_dlr_in_nck, mss::c_str(i_target));
+
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_trrd_dlr(l_mcs, l_attrs_dram_trrd_dlr.data()) );
+
+ l_attrs_dram_trrd_dlr[l_port_num] = l_trrd_dlr_in_nck;
+
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_DLR,
+ l_mcs,
+ UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_dlr, PORTS_PER_MCS)),
+ "Failed setting attribute for DRAM_TRRD_DLR");
fapi_try_exit:
return fapi2::current_err;
@@ -3358,90 +3499,114 @@ fapi2::ReturnCode eff_config::dram_tfaw(const fapi2::Target<TARGET_TYPE_DIMM>& i
{
const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
- int64_t l_tfaw_in_ps = 0;
- // Calculate tfaw (in ps)
- {
- constexpr int64_t l_tfaw_ftb = 0;
- int64_t l_tfaw_mtb = 0;
- int64_t l_ftb = 0;
- int64_t l_mtb = 0;
+ std::vector<uint8_t> l_attrs_dram_tfaw(PORTS_PER_MCS, 0);
+ uint64_t l_tfaw_in_nck = 0;
+ uint8_t l_stack_type = 0;
+ uint8_t l_dram_width = 0;
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- FAPI_TRY( iv_pDecoder->min_tfaw(i_target, l_tfaw_mtb) );
+ FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(i_target, l_stack_type),
+ "Failed prim_sdram_signal_loading()");
+ FAPI_TRY( iv_pDecoder->device_width(i_target, l_dram_width),
+ "Failed device_width()");
- l_tfaw_in_ps = calc_timing_from_timebase(l_tfaw_mtb, l_mtb, l_tfaw_ftb, l_ftb);
+ if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS)
+ {
+ FAPI_TRY( tfaw_slr(i_target, l_dram_width, l_tfaw_in_nck), "Failed tfaw_slr()");
}
-
+ else
{
- std::vector<uint8_t> l_attrs_dram_tfaw(PORTS_PER_MCS, 0);
- uint8_t l_tfaw_in_nck = 0;
+ FAPI_TRY( mss::tfaw(i_target, l_dram_width, l_tfaw_in_nck), "Failed tfaw()" );
+ }
- // Calculate nck
- FAPI_TRY ( calc_nck(l_tfaw_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_tfaw_in_nck),
- "Error in calculating tfaw_l for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_tfaw_in_ps );
+ FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s",
+ l_dram_width, l_tfaw_in_nck, mss::c_str(i_target));
- FAPI_INF("Calculated tFAW (ps): %d, tFAW (nck): %d for target: %s", l_tfaw_in_ps, l_tfaw_in_nck, mss::c_str(i_target));
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_tfaw(l_mcs, l_attrs_dram_tfaw.data()) );
- // Get & update MCS attribute
- FAPI_TRY( eff_dram_tfaw(l_mcs, l_attrs_dram_tfaw.data()) );
+ l_attrs_dram_tfaw[l_port_num] = l_tfaw_in_nck;
- l_attrs_dram_tfaw[l_port_num] = l_tfaw_in_nck;
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TFAW,
- l_mcs,
- UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tfaw, PORTS_PER_MCS)),
- "Failed setting attribute for DRAM_TFAW");
- }
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TFAW,
+ l_mcs,
+ UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tfaw, PORTS_PER_MCS)),
+ "Failed setting attribute for DRAM_TFAW");
fapi_try_exit:
return fapi2::current_err;
}
///
-/// @brief Determines & sets effective config for tRAS
+/// @brief Determines & sets effective config for tFAW_DLR
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
-fapi2::ReturnCode eff_config::dram_tras(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+fapi2::ReturnCode eff_config::dram_tfaw_dlr(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
{
const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
- int64_t l_tras_in_ps = 0;
- // Calculate tras (in ps)
- {
- constexpr int64_t l_tras_ftb = 0;
- int64_t l_tras_mtb = 0;
- int64_t l_ftb = 0;
- int64_t l_mtb = 0;
+ std::vector<uint8_t> l_attrs_dram_tfaw_dlr(PORTS_PER_MCS, 0);
+ constexpr uint64_t l_tfaw_dlr_in_nck = tfaw_dlr();
- FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) );
- FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) );
- FAPI_TRY( iv_pDecoder->min_active_to_precharge_delay_time(i_target, l_tras_mtb) );
+ FAPI_INF("tFAW_dlr (nck): %d for target: %s", l_tfaw_dlr_in_nck, mss::c_str(i_target));
- l_tras_in_ps = calc_timing_from_timebase(l_tras_mtb, l_mtb, l_tras_ftb, l_ftb);
- }
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_tfaw_dlr(l_mcs, l_attrs_dram_tfaw_dlr.data()) );
- {
- std::vector<uint8_t> l_attrs_dram_tras(PORTS_PER_MCS, 0);
- int8_t l_tras_in_nck = 0;
+ l_attrs_dram_tfaw_dlr[l_port_num] = l_tfaw_dlr_in_nck;
- // Calculate nck
- FAPI_TRY( calc_nck(l_tras_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_tras_in_nck),
- "Error in calculating tras_l for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_tras_in_ps);
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TFAW_DLR,
+ l_mcs,
+ UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tfaw_dlr, PORTS_PER_MCS)),
+ "Failed setting attribute for DRAM_TFAW_DLR");
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Determines & sets effective config for tRAS
+/// @param[in] i_target FAPI2 target
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+///
+fapi2::ReturnCode eff_config::dram_tras(const fapi2::Target<TARGET_TYPE_DIMM>& i_target)
+{
+ const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
+ const auto l_port_num = index(find_target<TARGET_TYPE_MCA>(i_target));
- FAPI_INF("Calculated tRAS (ps): %d, tRAS (nck): %d for target: %s", l_tras_in_ps, l_tras_in_nck, mss::c_str(i_target));
+ // tRAS is bin independent so we don't read this from SPD
+ // which will give the best timing value for the dimm
+ // (like 2400 MT/s) which may be different than the system
+ // speed (if we were being limited by VPD or MRW restrictions)
+ const uint64_t l_tras_in_ps = mss::tras(i_target);
- // Get & update MCS attribute
- FAPI_TRY( eff_dram_tras(l_mcs, l_attrs_dram_tras.data()) );
+ // Calculate nck
+ std::vector<uint8_t> l_attrs_dram_tras(PORTS_PER_MCS, 0);
+ uint8_t l_tras_in_nck = 0;
+
+ // Cast needed for calculations to be done on the same integral type
+ // as required by template deduction. We have iv_tCK_in_ps as a signed
+ // integer because we have other timing values that calculations do
+ // addition with negative integers.
+ FAPI_TRY( spd::calc_nck(l_tras_in_ps,
+ static_cast<uint64_t>(iv_tCK_in_ps),
+ INVERSE_DDR4_CORRECTION_FACTOR,
+ l_tras_in_nck),
+ "Error in calculating tras_l for target %s, with value of l_twtr_in_ps: %d",
+ mss::c_str(i_target), l_tras_in_ps);
+
+ FAPI_INF("tCK (ps): %d, tRAS (ps): %d, tRAS (nck): %d for target: %s",
+ iv_tCK_in_ps, l_tras_in_ps, l_tras_in_nck, mss::c_str(i_target));
- l_attrs_dram_tras[l_port_num] = l_tras_in_nck;
- FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRAS,
- l_mcs,
- UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tras, PORTS_PER_MCS)),
- "Failed setting attribute for tRAS");
- }
+ // Get & update MCS attribute
+ FAPI_TRY( eff_dram_tras(l_mcs, l_attrs_dram_tras.data()) );
+
+ l_attrs_dram_tras[l_port_num] = l_tras_in_nck;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRAS,
+ l_mcs,
+ UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tras, PORTS_PER_MCS)),
+ "Failed setting attribute for tRAS");
fapi_try_exit:
return fapi2::current_err;
@@ -3460,22 +3625,24 @@ fapi2::ReturnCode eff_config::dram_trtp(const fapi2::Target<TARGET_TYPE_DIMM>& i
// Values from proposed DDR4 Full spec update(79-4A)
// Item No. 1716.78C
// Page 241 & 246
- constexpr int64_t l_max_trtp_in_ps = 7500;
- constexpr int64_t l_min_trtp_in_nck = 4;
+ int64_t constexpr l_max_trtp_in_ps = trtp();
std::vector<uint8_t> l_attrs_dram_trtp(PORTS_PER_MCS, 0);
- int64_t l_calc_trtp_in_nck = 0;
+ uint8_t l_calc_trtp_in_nck = 0;
// Calculate nck
- FAPI_TRY( calc_nck(l_max_trtp_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_calc_trtp_in_nck),
- "Error in calculating trtp for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_max_trtp_in_ps);
+ FAPI_TRY( spd::calc_nck(l_max_trtp_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_calc_trtp_in_nck),
+ "Error in calculating trtp for target %s, with value of l_twtr_in_ps: %d",
+ mss::c_str(i_target), l_max_trtp_in_ps);
- FAPI_INF("Calculated trtp (nck): %d", l_calc_trtp_in_nck);
+ FAPI_INF("tCK (ps): %d, tRTP (ps): %d, tRTP (nck): %d",
+ iv_tCK_in_ps, l_max_trtp_in_ps, l_calc_trtp_in_nck);
// Get & update MCS attribute
FAPI_TRY( eff_dram_trtp(l_mcs, l_attrs_dram_trtp.data()) );
- l_attrs_dram_trtp[l_port_num] = uint8_t( std::max(l_min_trtp_in_nck, l_calc_trtp_in_nck) );
+ l_attrs_dram_trtp[l_port_num] = l_calc_trtp_in_nck;
+
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRTP,
l_mcs,
UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trtp, PORTS_PER_MCS)),
@@ -3505,7 +3672,7 @@ fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target<TARGET_TYPE_MCS>& i
// We need to set up all VPD info before calling getVPD, the API assumes this
// For MR we need to tell the VPDInfo the frequency (err ... mt/s - why is this mhz?)
FAPI_TRY( mss::freq(find_target<TARGET_TYPE_MCBIST>(i_target), l_vpd_info.iv_freq_mhz) );
- FAPI_INF("%s. VPD info - dimm data rate: %d MT/s", c_str(i_target), l_vpd_info.iv_freq_mhz);
+ FAPI_INF("%s. VPD info - dimm data rate: %d MT/s", mss::c_str(i_target), l_vpd_info.iv_freq_mhz);
// Make sure to create 0 filled blobs for all the possible blobs, not just for the
// chiplets which are configured. This prevents the decoder from accessing nullptrs
@@ -3542,7 +3709,7 @@ fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target<TARGET_TYPE_MCS>& i
l_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1];
FAPI_INF("%s. VPD info - rank count for dimm_0: %d, dimm_1: %d",
- c_str(i_target), l_vpd_info.iv_rank_count_dimm_0, l_vpd_info.iv_rank_count_dimm_1);
+ mss::c_str(i_target), l_vpd_info.iv_rank_count_dimm_0, l_vpd_info.iv_rank_count_dimm_1);
// Get the MCS blob for this specific rank combination *only if* we have DIMM. Remember,
// Cronus can give us functional MCA which have no DIMM - and we'd puke getting the VPD.
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H
index e3613c20b..a85ed96d3 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H
@@ -56,20 +56,24 @@ namespace mss
///
class eff_config
{
- private:
-
- int64_t iv_tCK_in_ps;
-
public:
//TK - Make this constructor take this as param - AAM
std::shared_ptr<spd::decoder> iv_pDecoder;
+ int64_t iv_tCK_in_ps;
+
+ // Assists testing with write ability on these MRW
+ // settings that are normally NOT writable
+ // using attribute accessors
+ // Could create getters & setters...
+ uint8_t iv_refresh_mode;
+ uint8_t iv_temp_refresh_range;
//TODO: RTC 159777: Change eff_config class to use iv's for mcs, port and dimm position
///
/// @brief Constructor
- /// @param[in] i_target, the fapi2::Target which we're configuring (DIMM)
- /// @param[out] o_rc, a return code which determines the success of the constructor
+ /// @param[in] i_target the fapi2::Target which we're configuring (DIMM)
+ /// @param[out] o_rc a return code which determines the success of the constructor
///
eff_config( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, fapi2::ReturnCode& o_rc )
{
@@ -84,12 +88,15 @@ class eff_config
///
/// @brief Constructor
/// @param[in] i_target the fapi2::Target which we're configuring (MCS)
- /// @param[out] o_rc, a return code which determines the success of the constructor
+ /// @param[out] o_rc a return code which determines the success of the constructor
///
eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, fapi2::ReturnCode& o_rc )
{
FAPI_TRY( clock_period(i_target, iv_tCK_in_ps), "Failed to calculate clock period (tCK)" );
- FAPI_INF("Calculated clock period (tCK): %d on DIMM %s", iv_tCK_in_ps, mss::c_str(i_target));
+ FAPI_TRY( mss::mrw_temp_refresh_range(iv_temp_refresh_range), "Failed mrw_temp_refresh_range()" );
+ FAPI_TRY( mss::mrw_fine_refresh_mode(iv_refresh_mode), "Failed mrw_fine_refresh_mode()" );
+
+ FAPI_INF( "Calculated clock period - tCK (ps): %d for %s", iv_tCK_in_ps, mss::c_str(i_target) );
fapi_try_exit:
o_rc = fapi2::current_err;
@@ -147,21 +154,21 @@ class eff_config
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode refresh_interval_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+ fapi2::ReturnCode dram_trefi(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
/// @brief Determines & sets effective config for refresh cycle time (tRFC)
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode refresh_cycle_time(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+ fapi2::ReturnCode dram_trfc(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
/// @brief Determines & sets effective config for refresh cycle time (logical ranks) (tRFC_DLR)
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
- fapi2::ReturnCode refresh_cycle_time_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+ fapi2::ReturnCode dram_trfc_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
/// @brief Determines & sets effective config for dram density
@@ -705,6 +712,13 @@ class eff_config
fapi2::ReturnCode dram_trcd(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
+ /// @brief Determines & sets effective config for tRC
+ /// @param[in] i_target FAPI2 target
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode dram_trc(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+
+ ///
/// @brief Determines & sets effective config for tWTR_L
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
@@ -719,27 +733,41 @@ class eff_config
fapi2::ReturnCode dram_twtr_s(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
- /// @brief Determines & sets effective config for tRRD_S
+ /// @brief Determines & sets effective config for tRRD_S (tRRD_S_slr)
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode dram_trrd_s(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
- /// @brief Determines & sets effective config for tRRD_L
+ /// @brief Determines & sets effective config for tRRD_L (or tRRD_L_slr)
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode dram_trrd_l(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
- /// @brief Determines & sets effective config for tfaw
+ /// @brief Determines & sets effective config for tRRD_DLR
+ /// @param[in] i_target FAPI2 target
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode dram_trrd_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+
+ ///
+ /// @brief Determines & sets effective config for tFAW (or tFAW_slr)
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode dram_tfaw(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
///
+ /// @brief Determines & sets effective config for tFAW_DLR
+ /// @param[in] i_target FAPI2 target
+ /// @return fapi2::FAPI2_RC_SUCCESS if okay
+ ///
+ fapi2::ReturnCode dram_tfaw_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target);
+
+ ///
/// @brief Determines & sets effective config for tRAS
/// @param[in] i_target FAPI2 target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.C
index e87a0457e..82ef939d1 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.C
@@ -30,6 +30,12 @@
namespace mss
{
+enum temp_mode : uint8_t
+{
+ NORMAL = 1,
+ EXTENDED = 2,
+};
+
// Proposed DDR4 Full spec update(79-4B)
// Item No. 1716.78C
// pg.46
@@ -81,9 +87,9 @@ static const std::vector<std::pair<uint8_t, uint64_t> > TRFC_DLR4 =
///
fapi2::ReturnCode calc_trefi( const refresh_rate i_mode,
const uint8_t i_temp_refresh_range,
- int64_t& o_timing )
+ uint64_t& o_timing )
{
- int64_t l_multiplier = 0;
+ uint64_t l_multiplier = 0;
switch(i_temp_refresh_range)
{
@@ -104,8 +110,8 @@ fapi2::ReturnCode calc_trefi( const refresh_rate i_mode,
break;
}
- const int64_t l_quotient = TREFI_BASE / ( int64_t(i_mode) * l_multiplier );
- const int64_t l_remainder = TREFI_BASE % ( int64_t(i_mode) * l_multiplier );
+ const uint64_t l_quotient = TREFI_BASE / ( int64_t(i_mode) * l_multiplier );
+ const uint64_t l_remainder = TREFI_BASE % ( int64_t(i_mode) * l_multiplier );
o_timing = l_quotient + (l_remainder == 0 ? 0 : 1);
FAPI_INF( "tREFI: %d, quotient: %d, remainder: %d, tREFI_base: %d",
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 6dfb94227..9180aaa9c 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
@@ -43,7 +43,7 @@
namespace mss
{
-enum GUARD_BAND : uint16_t
+enum guard_band : uint16_t
{
// Used for caclulating spd timing values - from JEDEC rounding algorithm
// Correction factor is 1% (for DDR3) or 2.5% (for DDR4)
@@ -61,11 +61,8 @@ enum class refresh_rate : uint8_t
REF4X = 4,
};
-enum temp_mode : uint8_t
+namespace spd
{
- NORMAL = 1,
- EXTENDED = 2,
-};
///
/// @brief Calculates timing value
@@ -88,50 +85,142 @@ inline int64_t calc_timing_from_timebase(const int64_t i_timing_mtb,
}
///
-/// @brief Returns clock cycles
-/// @tparam T input
-/// @tparam OT output
-/// @param[in] timing_in_ps timing parameter in ps
-/// @param[in] tck_in_ps clock period in ps
-/// @param[in] inverse_corr_factor inverse correction factor (defined by JEDEC)
+/// @brief Helper to compute JEDEC's SPD rounding algorithm
+/// to convert ps to nCK
+/// @tparam T input type
+/// @tparam OT output type
+/// @param[in] i_timing_in_ps timing parameter in ps
+/// @param[in] i_tck_in_ps clock period in ps
+/// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC)
/// @param[out] o_value_nck the end calculation in nck
-/// @return the clock cycles of timing parameter (provided in ps)
+/// @return true if overflow didn't occur, false otherwise
/// @note DDR4 SPD Contents Rounding Algorithm
/// @note Item 2220.46
///
template<typename T, typename OT>
-inline fapi2::ReturnCode calc_nck(const T& i_timing_in_ps,
- const T& i_tck_in_ps,
- GUARD_BAND i_inverse_corr_factor,
- OT& o_val_nck)
+static inline bool jedec_spd_rounding_alg(const T& i_timing_in_ps,
+ const T& i_tck_in_ps,
+ const guard_band i_inverse_corr_factor,
+ OT& o_val_nck)
{
// Preliminary nCK calculation, scaled by 1000 per JDEC algorithm
- T l_temp_nck = (i_timing_in_ps * 1000) / (i_tck_in_ps == 0 ? 1 : i_tck_in_ps);
+ T l_temp_nck = (i_timing_in_ps * CONVERT_PS_IN_A_NS) / (i_tck_in_ps == 0 ? 1 : i_tck_in_ps);
l_temp_nck += i_inverse_corr_factor;
- l_temp_nck = l_temp_nck / 1000;
+ l_temp_nck = l_temp_nck / CONVERT_PS_IN_A_NS;
- //Check for overflow.
+ // Check for overflow
+ // static_cast needed for HB compiler that complains about
+ // comparision of two different integral types
o_val_nck = l_temp_nck;
- FAPI_ASSERT(o_val_nck == l_temp_nck,
- fapi2::MSS_INVALID_CAST_CALC_NCK().
- set_TIMING_PS(i_timing_in_ps).
- set_NCK_NS(i_tck_in_ps).
- set_CORRECTION_FACTOR(i_inverse_corr_factor),
- "Bad cast for calc_nck. Output is: %d, after cast is %d", l_temp_nck, l_temp_nck);
- return fapi2::FAPI2_RC_SUCCESS;
+ FAPI_DBG("Input timing (ps) %d, tCK (ps) %d, temp output %d, output (nCK) %d",
+ i_timing_in_ps, i_tck_in_ps, l_temp_nck, o_val_nck);
+
+ return (static_cast<T>(o_val_nck) == l_temp_nck);
+}
+
+///
+/// @brief Returns clock cycles based on input application period
+/// @tparam T input type
+/// @tparam OT output type
+/// @param[in] i_timing_in_ps timing parameter in ps
+/// @param[in] i_tck_in_ps clock period in ps
+/// @param[in] i_inverse_corr_factor inverse correction factor (defined by JEDEC)
+/// @param[out] o_value_nck the end calculation in nck
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note DDR4 SPD Contents Rounding Algorithm
+/// @note Item 2220.46
+///
+template<typename T, typename OT>
+inline fapi2::ReturnCode calc_nck(const T& i_timing_in_ps,
+ const T& i_tck_in_ps,
+ const guard_band i_inverse_corr_factor,
+ OT& o_val_nck)
+{
+ FAPI_ASSERT( jedec_spd_rounding_alg(i_timing_in_ps,
+ i_tck_in_ps,
+ i_inverse_corr_factor,
+ o_val_nck),
+ fapi2::MSS_INVALID_CAST_CALC_NCK().
+ set_TIMING_PS(i_timing_in_ps).
+ set_NCK_NS(i_tck_in_ps).
+ set_CORRECTION_FACTOR(i_inverse_corr_factor),
+ "Overflow occured. Returned data is %d", o_val_nck);
fapi_try_exit:
return fapi2::current_err;
}
///
+/// @brief Returns clock cycles form picoseconds based on speed bin
+/// Uses SPD rounding algorithm for DDR4
+/// @tparam T the target type from which to get the mt/s
+/// @tparam OT the output type, derrived from the parameters
+/// @param[in] i_target target for the frequency attribute
+/// @param[in] timing_in_ps timing parameter in ps
+/// @return the clock cycles of timing parameter (provided in ps)
+/// @note Uses DDR4 SPD Contents Rounding Algorithm
+/// @note Item 2220.46
+///
+template<fapi2::TargetType T, typename OT>
+inline OT ps_to_nck( const fapi2::Target<T>& i_target, const OT& i_timing_in_ps)
+{
+ uint64_t l_freq = 0;
+ OT l_tck_in_ps = 0;
+ OT l_temp_nck = 0;
+
+ 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;
+ }
+
+ FAPI_TRY( freq_to_ps(l_freq, l_tck_in_ps),
+ "Failed freq() accessor" );
+ FAPI_TRY( calc_nck(i_timing_in_ps, l_tck_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_temp_nck),
+ "Failed calc_nck()" );
+
+ return l_temp_nck;
+
+fapi_try_exit:
+ // We simply can't work if we can't get the frequency or
+ // if we get an unsupported value that can't be converted to a valid tCK (clock period)
+ // ...so this should be ok
+ FAPI_ERR("Can't get MSS_FREQ, obtained an invalid MSS_FREQ (%d), or overflow occurred - stopping", l_freq);
+ fapi2::Assert(false);
+
+ // Keeps compiler happy
+ return 0;
+}
+
+///
+/// @brief Returns clock cycles from nanoseconds
+/// Uses SPD rounding algorithm for DDR4
+/// @tparam T the target type from which to get the mt/s
+/// @tparam OT the output type, derrived from the parameters
+/// @param[in] timing_in_ps timing parameter in ps
+/// @param[out] o_value_nck the end calculation in nck
+/// @return the clock cycles of timing parameter (provided in ps)
+/// @note Uses DDR4 SPD Contents Rounding Algorithm
+/// @note Item 2220.46
+///
+template<fapi2::TargetType T, typename OT>
+inline OT ns_to_nck( const fapi2::Target<T>& i_target, const OT& i_timing_in_ns)
+{
+ return ps_to_nck(i_target, i_timing_in_ns * CONVERT_PS_IN_A_NS);
+}
+
+}// spd
+
+///
/// @brief Returns application clock period (tCK) based on dimm transfer rate
/// @tparam T the fapi2 target
/// @tparam OT output type
/// @param[in] i_target FAPI2 target
/// @param[out] o_tCK_in_ps application period in ps
-/// @return fapi2::FAPI2_RC_SUCCESS if okay
+/// @return fapi2::FAPI2_RC_SUCCESS iff okay
///
template<fapi2::TargetType T, typename OT>
inline fapi2::ReturnCode clock_period(const fapi2::Target<T>& i_target,
@@ -155,7 +244,7 @@ fapi_try_exit:
///
fapi2::ReturnCode calc_trefi( const refresh_rate i_mode,
const uint8_t i_temp_refresh_range,
- int64_t& o_timing );
+ uint64_t& o_timing );
///
/// @brief Calculates Minimum Refresh Recovery Delay Time (different logical rank)
@@ -318,37 +407,6 @@ fapi_try_exit:
}
///
-/// @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*
@@ -465,5 +523,781 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief tRTP *in ps*
+/// @return constexpr value of RTP = 7500 ps
+///
+constexpr uint64_t trtp()
+{
+ // Per JEDEC spec, defaults to 7500 ps for all frequencies.
+ // (technically max of 7.5 ns or 4 nclk, which is always 7.5ns for DDR4)
+ return 7500;
+}
+
+///
+/// @brief Return the minimum allowable tRAS in picoseconds
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @return value in picoseconds
+///
+template< fapi2::TargetType T >
+inline uint64_t tras(const fapi2::Target<T>& i_target)
+{
+ uint64_t l_freq = 0;
+ uint64_t l_tras = 0;
+
+ // Frequency is used to determine tRAS
+ FAPI_TRY( freq(mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq) );
+
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ l_tras = 34000;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ l_tras = 33000;
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ l_tras = 32000;
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ }
+
+ return l_tras;
+
+fapi_try_exit:
+
+ // We simply can't work if we can't get the frequency or
+ // if we get an unsupported value that can't be converted to a valid tCK (clock period)
+ // ...so this should be ok
+ FAPI_ERR("Can't get MSS_FREQ or obtained an invalid MSS_FREQ (%d) - stopping", l_freq);
+ fapi2::Assert(false);
+
+ // Keeps compiler happy
+ return 0;
+}
+
+///
+/// @brief Helper function to find tFAW based speed (MT/s) for 1/2 KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_half_kb_page_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ // static_cast is needed for template deduction of std::max API
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_output = std::max( 16, spd::ns_to_nck(i_target, 17) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ o_output = std::max( 16, spd::ns_to_nck(i_target, 15) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_output = std::max( 16, spd::ns_to_nck(i_target, 13) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_output = std::max( 16, spd::ns_to_nck(i_target, 12) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tFAW based speed (MT/s) for 1KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_1kb_page_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_output = std::max( 20, spd::ns_to_nck(i_target, 23) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_output = std::max( 20, spd::ns_to_nck(i_target, 21) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tFAW based speed (MT/s) for 2KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_2kb_page_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_output = std::max( 28, spd::ns_to_nck(i_target, 30) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return the minimum allowable tFAW in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_dram_width the page size
+/// @param[out] o_tFAW timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+//
+template< fapi2::TargetType T >
+fapi2::ReturnCode tfaw( const fapi2::Target<T>& i_target,
+ const uint8_t i_dram_width,
+ uint64_t& o_tFAW )
+{
+ switch(i_dram_width)
+ {
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4:
+ FAPI_TRY( tfaw_half_kb_page_helper(i_target, o_tFAW) );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8:
+ FAPI_TRY( tfaw_1kb_page_helper(i_target, o_tFAW) );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
+ FAPI_TRY( tfaw_2kb_page_helper(i_target, o_tFAW) );
+ break;
+
+ default:
+ FAPI_ERR("%s Recieved an invalid page size: %lu", mss::c_str(i_target), i_dram_width);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tFAW_slr_x4 based on speed (MT/s)
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for 3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_slr_x4_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_output = spd::ns_to_nck(i_target, 17);
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ o_output = spd::ns_to_nck(i_target, 15);
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_output = spd::ns_to_nck(i_target, 13);
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ FAPI_ERR("2666 MT/s is TBD from the DDR3 3DS spec");
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+
+ default:
+ FAPI_ERR( "%s: Invalid frequency received (%d)", c_str(i_target), l_freq );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tFAW_slr_x8 based on speed (MT/s)
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for 3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode tfaw_slr_x8_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+ FAPI_INF("Fetching timing value for %d MT/s");
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_output = spd::ns_to_nck(i_target, 23);
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_output = spd::ns_to_nck(i_target, 21);
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ FAPI_ERR("2666 MT/s is TBD from the DDR3 3DS spec");
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+
+ default:
+ FAPI_ERR( "%s: Invalid frequency received (%d)", c_str(i_target), l_freq );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return the minimum allowable tFAW in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_page_size the page size
+/// @param[out] o_tFAW timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+//
+template< fapi2::TargetType T >
+fapi2::ReturnCode tfaw_slr( const fapi2::Target<T>& i_target,
+ const uint8_t i_dram_width,
+ uint64_t& o_tFAW )
+{
+ if( i_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4 )
+ {
+ FAPI_TRY( tfaw_slr_x4_helper(i_target, o_tFAW) );
+ }
+ else
+ {
+ FAPI_TRY( tfaw_slr_x8_helper(i_target, o_tFAW) );
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief tFAW_dlr *in nck*
+/// @return 16nck
+/// @note From DDR4 3DS Spec
+/// 12.2 Timing Parameters by Speed Grade
+///
+constexpr uint64_t tfaw_dlr()
+{
+ return 16;
+}
+
+///
+/// @brief tRRD_dlr *in nck*
+/// @return 4nck
+/// @note From DDR4 3DS Spec
+/// 12.2 Timing Parameters by Speed Grade
+///
+constexpr uint64_t trrd_dlr()
+{
+ return 4;
+}
+
+///
+/// @brief Find tRRD_S_slr in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for 3DS DIMM
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode trrd_s_slr(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+
+ // Values derived from DDR4 3DS Spec
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 4200) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 3700) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 3300) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ FAPI_ERR("2666 MT/s is TBD from the DDR3 3DS spec");
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+
+ default:
+ FAPI_ERR( "%s: Invalid frequency received (%d)", c_str(i_target), l_freq );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Find tRRD_L_slr in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for 3DS DIMM
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode trrd_l_slr(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+
+ // Values derived from DDR4 3DS Spec
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability.
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 5300) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 4900) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ FAPI_ERR("2666 MT/s is TBD from the DDR4 SPD spec");
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+
+ default:
+ FAPI_ERR( "%s: Invalid frequency received (%d)", c_str(i_target), l_freq );
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tRRD_L based speed (MT/s) for 1KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_l_half_and_1kb_page_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ // From the spec: Max(4nCK,5.3ns)
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 5300) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ // Max(4nCK,4.9ns)
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 4900) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tRRD_L based speed (MT/s) for 2KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_l_2kb_page_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 6400) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return the minimum allowable tRRD_L in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_dram_width the page size
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode trrd_l( const fapi2::Target<T>& i_target,
+ const uint8_t i_dram_width,
+ uint64_t& o_tRRD_L )
+{
+ switch(i_dram_width)
+ {
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4:
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8:
+ FAPI_TRY( trrd_l_half_and_1kb_page_helper(i_target, o_tRRD_L) );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
+ FAPI_TRY( trrd_l_2kb_page_helper(i_target, o_tRRD_L) );
+ break;
+
+ default:
+ FAPI_ERR("%s Recieved an invalid page size: %lu", mss::c_str(i_target), i_dram_width);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tRRD_S based speed (MT/s) for 1KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_s_half_and_1kb_page_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ o_output = std::max( 4, spd::ns_to_nck(i_target, 4200) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ o_output = std::max( 4, spd::ns_to_nck(i_target, 3700) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ o_output = std::max( 4, spd::ns_to_nck(i_target, 3300) );
+ break;
+
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_output = std::max( 4, spd::ns_to_nck(i_target, 3000) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to find tRRD_S based speed (MT/s) for 2KB page
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[out] o_output timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+static fapi2::ReturnCode trrd_s_2kb_page_helper(const fapi2::Target<T>& i_target,
+ uint64_t& o_output)
+{
+ // Values derived from DDR4 Spec (79-4A)
+ // 13.3 Timing Parameters by Speed Grade
+ // Table 132. Pg 240
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+
+ uint64_t l_freq = 0;
+ FAPI_TRY( freq(find_target<fapi2::TARGET_TYPE_MCBIST>(i_target), l_freq),
+ "Failed to invoke freq accessor" );
+
+ // It could have been more "efficient" to hand-calculate the answer and
+ // use compile time constants to return the answer. To avoid magic
+ // numbers and to align (more closely) with the DDR4 JEDEC spec,
+ // we let the std library do the work for us for maintainability (and ease of debug?).
+ // Could have used compile-time constants to denote the numbers below
+ // but they are "random" and vary.
+ switch(l_freq)
+ {
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT1866:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2133:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2400:
+ case fapi2::ENUM_ATTR_MSS_FREQ_MT2666:
+ o_output = std::max( 4, spd::ps_to_nck(i_target, 5300) );
+ break;
+
+ default:
+ FAPI_TRY(fapi2::FAPI2_RC_INVALID_PARAMETER, "%s Invalid frequency %lu", mss::c_str(i_target), l_freq);
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Return the minimum allowable tRRD_S in nck
+/// @tparam T the fapi2::TargetType of a type from which we can get MT/s
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_dram_width the page size
+/// @param[out] o_tRRD_S timing in clocks (nck)
+/// @return FAPI2_RC_SUCCESS iff okay
+/// @note this is only for non-3DS DIMM
+///
+template< fapi2::TargetType T >
+fapi2::ReturnCode trrd_s( const fapi2::Target<T>& i_target,
+ const uint8_t i_dram_width,
+ uint64_t& o_tRRD_S )
+{
+ switch(i_dram_width)
+ {
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4:
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8:
+ FAPI_TRY( trrd_s_half_and_1kb_page_helper(i_target, o_tRRD_S) );
+ break;
+
+ case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
+ FAPI_TRY( trrd_s_2kb_page_helper(i_target, o_tRRD_S) );
+ break;
+
+ default:
+ FAPI_ERR("%s Recieved an invalid page size: %lu", mss::c_str(i_target), i_dram_width);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ break;
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
} // mss
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C
index 07e4ca4d2..c275c1e0d 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C
@@ -44,6 +44,7 @@
#include <lib/spd/common/spd_decoder.H>
#include <lib/freq/cas_latency.H>
#include <lib/freq/cycle_time.H>
+#include <lib/freq/sync.H>
#include <lib/utils/conversions.H>
#include <lib/eff_config/timing.H>
#include <lib/utils/find.H>
@@ -66,17 +67,19 @@ namespace mss
/// @param[in] i_caches decoder caches
///
cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches):
+ const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches,
+ fapi2::ReturnCode& o_rc):
iv_dimm_list_empty(false),
+ iv_target(i_target),
iv_largest_taamin(0),
iv_proposed_tck(0),
- iv_common_CL(UINT64_MAX) // Masks out supported CLs
+ iv_common_cl(UINT64_MAX) // Masks out supported CLs
{
- const auto l_dimm_list = find_targets<TARGET_TYPE_DIMM>(i_target);
+ const auto l_dimm_list = find_targets<TARGET_TYPE_DIMM>(iv_target);
if(l_dimm_list.empty())
{
- FAPI_INF("cas latency ctor seeing no DIMM on %s", mss::c_str(i_target));
+ FAPI_INF("cas latency ctor seeing no DIMM on %s", mss::c_str(iv_target));
iv_dimm_list_empty = true;
return;
}
@@ -86,105 +89,169 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
const auto l_dimm_pos = pos(l_dimm);
// Find decoder factory for this dimm position
+ // Can't be const auto because HB needs to implement
+ // something - AAM
auto l_it = i_caches.find(l_dimm_pos);
FAPI_TRY( check::spd::invalid_cache(l_dimm,
l_it != i_caches.end(),
l_dimm_pos),
- "Failed to get valid cache");
+ "%s. Failed to get valid cache", mss::c_str(iv_target) );
{
// Retrive timing values from the SPD
- uint64_t l_tAAmin_in_ps = 0;
- uint64_t l_tCKmax_in_ps = 0;
- uint64_t l_tCKmin_in_ps = 0;
+ uint64_t l_taa_min_in_ps = 0;
+ uint64_t l_tckmax_in_ps = 0;
+ uint64_t l_tck_min_in_ps = 0;
- FAPI_TRY( get_taamin(l_dimm, l_it->second, l_tAAmin_in_ps),
- "Failed to get tAAmin");
- FAPI_TRY( get_tckmax(l_dimm, l_it->second, l_tCKmax_in_ps),
- "Failed to get tCKmax" );
- FAPI_TRY( get_tckmin(l_dimm, l_it->second, l_tCKmin_in_ps),
- "Failed to get tCKmin");
+ FAPI_TRY( get_taamin(l_dimm, l_it->second, l_taa_min_in_ps),
+ "%s. Failed to get tAAmin", mss::c_str(iv_target) );
+ FAPI_TRY( get_tckmax(l_dimm, l_it->second, l_tckmax_in_ps),
+ "%s. Failed to get tCKmax", mss::c_str(iv_target) );
+ FAPI_TRY( get_tckmin(l_dimm, l_it->second, l_tck_min_in_ps),
+ "%s. Failed to get tCKmin", mss::c_str(iv_target) );
// Determine largest tAAmin value
- iv_largest_taamin = std::max(iv_largest_taamin, l_tAAmin_in_ps);
+ iv_largest_taamin = std::max(iv_largest_taamin, l_taa_min_in_ps);
// Determine a proposed tCK value that is greater than or equal tCKmin
// But less than tCKmax
- iv_proposed_tck = std::max(iv_proposed_tck, l_tCKmin_in_ps);
- iv_proposed_tck = std::min(iv_proposed_tck, l_tCKmax_in_ps);
+ iv_proposed_tck = std::max(iv_proposed_tck, l_tck_min_in_ps);
+ iv_proposed_tck = std::min(iv_proposed_tck, l_tckmax_in_ps);
+ }
+
+ // Collecting stack type
+ // If I have at least one 3DS DIMM connected I have
+ // to use 3DS tAAmax of 21.5 ps versus 18 ps for non-3DS DDR4
+ if( iv_is_3ds != loading::IS_3DS)
+ {
+ uint8_t l_stack_type = 0;
+ FAPI_TRY( l_it->second->prim_sdram_signal_loading(l_dimm, l_stack_type) );
+
+ // Is there a more algorithmic efficient approach? - AAM
+ iv_is_3ds = (l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) ?
+ loading::IS_3DS : loading::NOT_3DS;
}
{
// Retrieve dimm supported cas latencies from SPD
- uint64_t l_dimm_supported_CL = 0;
+ uint64_t l_dimm_supported_cl = 0;
FAPI_TRY( l_it->second->supported_cas_latencies(l_dimm,
- l_dimm_supported_CL),
- "Failed to get supported CAS latency");
+ l_dimm_supported_cl),
+ "%s. Failed to get supported CAS latency", mss::c_str(iv_target) );
- // ANDing bitmap from all modules creates a bitmap w/a common CL
- iv_common_CL &= l_dimm_supported_CL;
+ // Bitwise ANDING the bitmap from all modules creates a bitmap w/a common CL
+ iv_common_cl &= l_dimm_supported_cl;
}
}// dimm
+ // Limit tCK from the max supported dimm speed in the system
+ // So that this is taken into account when calculating CL
+ {
+ // Defaulting to non-zero speed
+ uint64_t l_freq_override = fapi2::ENUM_ATTR_MSS_FREQ_MT2666;
+ uint64_t l_tck_override_in_ps = 0;
+
+ FAPI_TRY( select_supported_freq(iv_target, l_freq_override),
+ "%s. Failed select_supported_freq()", mss::c_str(iv_target) );
+ FAPI_TRY( freq_to_ps(l_freq_override, l_tck_override_in_ps),
+ "%s. Failed freq_to_ps()", mss::c_str(iv_target) );
+
+ FAPI_INF("%s. Selected supported dimm speed %d MT/s (Clock period %d in ps)",
+ mss::c_str(iv_target), l_freq_override, l_tck_override_in_ps);
+
+ iv_proposed_tck = std::max( l_tck_override_in_ps, iv_proposed_tck );
+ FAPI_INF("%s. Initial proposed tCK in ps: %d", mss::c_str(iv_target), iv_proposed_tck);
+ }
+
// Why didn't I encapsulate common CL operations and checking in a function
// like the timing params? Well, I want to check the "final" common CL and
- // the creation of common CLs (ANDing bits) is dimm level operation
- FAPI_ASSERT(iv_common_CL != 0,
+ // the creation of common CLs (bitwise ANDING) is at the dimm level operation
+ FAPI_ASSERT(iv_common_cl != 0,
fapi2::MSS_NO_COMMON_SUPPORTED_CL().
- set_CL_SUPPORTED(iv_common_CL).
- set_MCS_TARGET(i_target),
- "No common CAS latencies (CL bitmap = 0)");
+ set_CL_SUPPORTED(iv_common_cl).
+ set_MCS_TARGET(iv_target),
+ "%s. No common CAS latencies (CL bitmap = 0)",
+ mss::c_str(iv_target) );
- FAPI_DBG("Supported CL bitmap 0x%llX", iv_common_CL);
+ FAPI_INF("%s. Supported CL bitmap 0x%llX", mss::c_str(iv_target), iv_common_cl);
- // If we reach here al instance vars should have successfully initialized
+ // If we reach here all member vars should have successfully initialized
+ o_rc = fapi2::FAPI2_RC_SUCCESS;
return;
// If we reach here something failed above.
fapi_try_exit:
- FAPI_ERR("Something went wrong retreiving dimm info");
+ o_rc = fapi2::FAPI2_RC_FALSE;
+ FAPI_ERR("%s. Something went wrong retrieving DIMM info", mss::c_str(iv_target) );
}// ctor
///
-/// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec.
+/// @brief Constructor that allows the user to set desired data in lieu of SPD
/// @param[in] i_target the controller target
+/// @param[in] i_taa_min largest tAAmin we want to set in picoseconds
+/// @param[in] i_tck_min proposed tCKmin in picoseconds
+/// @param[in] i_common_cl_mask common CAS latency mask we want to force (bitmap)
+/// @param[in] i_is_3ds boolean for whether this is a 3DS SDRAM, 3DS is true, false otherwise (default)
+///
+cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const uint64_t i_taa_min,
+ const uint64_t i_tck_min,
+ const uint64_t i_common_cl_mask,
+ const loading i_is_3ds):
+ iv_dimm_list_empty(false),
+ iv_target(i_target),
+ iv_largest_taamin(i_taa_min),
+ iv_proposed_tck(i_tck_min),
+ iv_common_cl(i_common_cl_mask),
+ iv_is_3ds(i_is_3ds)
+{
+ const auto l_dimm_list = find_targets<TARGET_TYPE_DIMM>(iv_target);
+
+ if(l_dimm_list.empty())
+ {
+ FAPI_INF("cas latency ctor seeing no DIMM on %s", mss::c_str(iv_target));
+ iv_dimm_list_empty = true;
+ }
+}
+
+///
+/// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec.
/// @param[out] o_cas_latency selected CAS latency
-/// @param[out] o_tCK cycle time corresponding to seleted CAS latency
+/// @param[out] o_tck cycle time corresponding to selected CAS latency
/// @return fapi2::FAPI2_RC_SUCCESS if ok
///
-fapi2::ReturnCode cas_latency::find_CL(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- uint64_t& o_cas_latency,
- uint64_t& o_tCK)
+fapi2::ReturnCode cas_latency::find_cl(uint64_t& o_cas_latency,
+ uint64_t& o_tck)
{
uint64_t l_desired_cas_latency = 0;
if(!iv_dimm_list_empty)
{
// Create a vector filled with common CLs from buffer
- std::vector<uint64_t> l_supported_CLs = create_common_cl_vector(iv_common_CL);
+ std::vector<uint64_t> l_supported_cls = integral_bitmap_to_vector(iv_common_cl);
//For a proposed tCK value between tCKmin(all) and tCKmax, determine the desired CAS Latency.
- l_desired_cas_latency = calc_cas_latency(iv_largest_taamin, iv_proposed_tck);
+ FAPI_TRY( calc_cas_latency(iv_largest_taamin, iv_proposed_tck, l_desired_cas_latency),
+ "%s. Failed to calculate CAS latency", mss::c_str(iv_target) );
//Chose an actual CAS Latency (CLactual) that is greater than or equal to CLdesired
//and is supported by all modules on the memory channel
- FAPI_TRY( choose_actual_CL(l_supported_CLs, iv_largest_taamin, iv_proposed_tck, l_desired_cas_latency),
- "Failed choose_actual_CL()");
+ FAPI_TRY( is_cl_supported_in_common(l_supported_cls, l_desired_cas_latency),
+ "%s. Failed to find a common CAS latency supported among all modules", mss::c_str(iv_target) );
- // Once the calculation of CLactual is completed, the BIOS must also
+ // Once the calculation of CLactual is completed
// verify that this CAS Latency value does not exceed tAAmax.
- //If not, choose a lower CL value and repeat until a solution is found.
- FAPI_TRY( validate_valid_CL(l_supported_CLs, iv_largest_taamin, iv_proposed_tck, l_desired_cas_latency),
- "Failed validate_valid_CL()");
+ FAPI_TRY( is_cl_exceeding_taa_max (l_desired_cas_latency, iv_proposed_tck),
+ "%s. Failed to find a CL value that doesn't exceed tAAmax", mss::c_str(iv_target) );
}
// Update output values after all criteria is met
// If the MCS has no dimm configured than both
// l_desired_latency & iv_proposed_tck is 0 by initialization
o_cas_latency = l_desired_cas_latency;
- o_tCK = iv_proposed_tck;
+ o_tck = iv_proposed_tck;
fapi_try_exit:
return fapi2::current_err;
@@ -207,27 +274,32 @@ fapi2::ReturnCode cas_latency::get_taamin(const fapi2::Target<TARGET_TYPE_DIMM>&
int64_t l_fine_timebase = 0;
// Retrieve timing parameters
- FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase) );
- FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase) );
- FAPI_TRY( i_pDecoder->min_cas_latency_time(i_target, l_timing_mtb) );
- FAPI_TRY( i_pDecoder->fine_offset_min_taa(i_target, l_timing_ftb) );
+ FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase),
+ "%s. Failed medium_timebase()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase),
+ "%s. Failed fine_timebase()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->min_cas_latency_time(i_target, l_timing_mtb),
+ "%s. Failed min_cas_latency_time()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->fine_offset_min_taa(i_target, l_timing_ftb),
+ "%s. Failed fine_offset_min_taa()", mss::c_str(iv_target) );
// Calculate timing value
- o_value = uint64_t(calc_timing_from_timebase(l_timing_mtb,
- l_medium_timebase,
- l_timing_ftb,
- l_fine_timebase));
+ o_value = spd::calc_timing_from_timebase(l_timing_mtb,
+ l_medium_timebase,
+ l_timing_ftb,
+ l_fine_timebase);
// Sanity check
FAPI_ASSERT(o_value > 0,
fapi2::MSS_INVALID_TIMING_VALUE().
set_VALUE(o_value).
set_DIMM_TARGET(i_target),
- "tAAmin invalid (<= 0) : %d",
+ "%s. tAAmin invalid (<= 0) : %d",
+ mss::c_str(iv_target),
o_value);
- FAPI_DBG( "%s. tAAmin (ps): %d",
- c_str(i_target),
+ FAPI_INF( "%s. tAAmin (ps): %d",
+ mss::c_str(iv_target),
o_value);
fapi_try_exit:
@@ -252,34 +324,38 @@ fapi2::ReturnCode cas_latency::get_tckmin(const fapi2::Target<TARGET_TYPE_DIMM>&
int64_t l_fine_timebase = 0;
// Retrieve timing parameters
- FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase) );
- FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase) );
- FAPI_TRY( i_pDecoder->min_cycle_time(i_target, l_timing_mtb) );
- FAPI_TRY( i_pDecoder->fine_offset_min_tck(i_target, l_timing_ftb) );
+ FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase),
+ "%s. Failed medium_timebase()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase),
+ "%s. Failed fine_timebase()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->min_cycle_time(i_target, l_timing_mtb),
+ "%s. Failed min_cycle_time()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->fine_offset_min_tck(i_target, l_timing_ftb),
+ "%s. Failed fine_offset_min_tck()", mss::c_str(iv_target) );
// Calculate timing value
- o_value = uint64_t( calc_timing_from_timebase(l_timing_mtb,
- l_medium_timebase,
- l_timing_ftb,
- l_fine_timebase) );
+ o_value = spd::calc_timing_from_timebase(l_timing_mtb,
+ l_medium_timebase,
+ l_timing_ftb,
+ l_fine_timebase);
// Sanity check
FAPI_ASSERT(o_value > 0,
fapi2::MSS_INVALID_TIMING_VALUE().
set_VALUE(o_value).
set_DIMM_TARGET(i_target),
- "tCKmin invalid (<= 0) : %d",
+ "%s. tCKmin invalid (<= 0) : %d",
+ mss::c_str(iv_target),
o_value);
- FAPI_DBG("%s. tCKmin (ps): %d",
- c_str(i_target),
+ FAPI_INF("%s. tCKmin (ps): %d",
+ mss::c_str(iv_target),
o_value );
fapi_try_exit:
return fapi2::current_err;
}
-
///
/// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD
/// @param[in] i_target the dimm target
@@ -297,27 +373,32 @@ fapi2::ReturnCode cas_latency::get_tckmax(const fapi2::Target<TARGET_TYPE_DIMM>&
int64_t l_fine_timebase = 0;
// Retrieve timing parameters
- FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase) );
- FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase) );
- FAPI_TRY( i_pDecoder->max_cycle_time(i_target, l_timing_mtb) );
- FAPI_TRY( i_pDecoder->fine_offset_max_tck(i_target, l_timing_ftb) );
+ FAPI_TRY( i_pDecoder->medium_timebase(i_target, l_medium_timebase),
+ "%s. Failed medium_timebase()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->fine_timebase(i_target, l_fine_timebase),
+ "%s. Failed fine_timebase()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->max_cycle_time(i_target, l_timing_mtb),
+ "%s. Failed max_cycle_time()", mss::c_str(iv_target) );
+ FAPI_TRY( i_pDecoder->fine_offset_max_tck(i_target, l_timing_ftb),
+ "%s. Failed fine_offset_max_tck()", mss::c_str(iv_target) );
// Calculate timing value
- o_value = uint64_t(calc_timing_from_timebase(l_timing_mtb,
- l_medium_timebase,
- l_timing_ftb,
- l_fine_timebase) );
+ o_value = spd::calc_timing_from_timebase(l_timing_mtb,
+ l_medium_timebase,
+ l_timing_ftb,
+ l_fine_timebase);
// Sanity check
FAPI_ASSERT(o_value > 0,
fapi2::MSS_INVALID_TIMING_VALUE().
set_VALUE(o_value).
set_DIMM_TARGET(i_target),
- "tCKmax invalid (<= 0) : %d",
+ "%s. tCKmax invalid (<= 0) : %d",
+ mss::c_str(iv_target),
o_value);
- FAPI_DBG( "%s. tCKmax (ps): %d",
- c_str(i_target),
+ FAPI_INF( "%s. tCKmax (ps): %d",
+ mss::c_str(iv_target),
o_value);
fapi_try_exit:
@@ -326,231 +407,133 @@ fapi_try_exit:
///
/// @brief Gets max CAS latency (CL) for the appropriate High/Low Range
-/// @param[in] i_supported_CL
+/// @param[in] i_supported_cl
/// @return the maximum supported CL
/// @note Depends on bit 7 of byte 23 from the DDR4 SPD
///
-inline uint64_t cas_latency::get_max_CL(const fapi2::buffer<uint64_t> i_supported_CL) const
+inline uint64_t cas_latency::get_max_cl(const fapi2::buffer<uint64_t> i_supported_cl) const
{
- constexpr uint64_t CAS_LAT_RANGE_BIT = 31;
-
// If the last of Byte 23 of the SPD is 1, this selects CL values
// in the High CL range (23 to 52)
// If the last bit of Byte 23 of the SPD is 0, this selects CL values
// in the Low CL range (7 to 36)
//Assuming bitmap is right aligned
- return i_supported_CL.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MAX_CL_DDR4 : LOW_RANGE_MAX_CL_DDR4;
+ return i_supported_cl.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MAX_CL_DDR4 : LOW_RANGE_MAX_CL_DDR4;
}
///
/// @brief Gets min CAS latency (CL) for the appropriate High/Low Range
-/// @param[in] i_supported_CL
+/// @param[in] i_supported_cl
/// @return the minimum supported CL
/// @note Depends on bit 7 of byte 23 from the DDR4 SPD
///
-inline uint64_t cas_latency::get_min_CL(const fapi2::buffer<uint64_t>& i_supported_CL) const
+inline uint64_t cas_latency::get_min_cl(const fapi2::buffer<uint64_t>& i_supported_cl) const
{
// If the last of Byte 23 of the SPD is 1, this selects CL values
// in the High CL range (23 to 52)
// If the last bit of Byte 23 of the SPD is 0, this selects CL values
// in the Low CL range (7 to 36)
- constexpr uint64_t CAS_LAT_RANGE_BIT = 31;
-
- return i_supported_CL.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MIN_CL_DDR4 : LOW_RANGE_MIN_CL_DDR4;
+ return i_supported_cl.getBit<CAS_LAT_RANGE_BIT>() ? HIGH_RANGE_MIN_CL_DDR4 : LOW_RANGE_MIN_CL_DDR4;
}
///
/// @brief Calculates CAS latency time from tCK and tAA
-/// @param[in] i_tAA cas latency time
-/// @param[in] i_tCK min cycle time
-/// @return o_cas_latency calculated CAS latency
+/// @param[in] i_taa cas latency time
+/// @param[in] i_tck min cycle time
+/// @param[out] o_cas_latency calculated CAS latency
+/// @return FAPI2_RC_SUCCESS iff okay
///
-inline uint64_t cas_latency::calc_cas_latency(const uint64_t i_tAA, const uint64_t i_tCK) const
+inline fapi2::ReturnCode cas_latency::calc_cas_latency(const uint64_t i_taa,
+ const uint64_t i_tck,
+ uint64_t& o_cas_latency) const
{
- uint64_t l_quotient = i_tAA / i_tCK;
- uint64_t l_remainder = i_tAA % i_tCK;
- uint64_t o_cas_latency = l_quotient + (l_remainder == 0 ? 0 : 1);
+ FAPI_TRY( spd::calc_nck(i_taa, i_tck, INVERSE_DDR4_CORRECTION_FACTOR, o_cas_latency) );
- FAPI_DBG("Calculated CL = tAA / tCK : %d / %d = %d",
- i_tAA,
- i_tCK,
+ FAPI_INF("%s. tAA (ps): %d, tCK (ps): %d, CL (nck): %d",
+ mss::c_str(iv_target),
+ i_taa,
+ i_tck,
o_cas_latency);
- return o_cas_latency;
+fapi_try_exit:
+ return fapi2::current_err;
}
///
/// @brief Helper function to create a vector of supported CAS latencies from a bitmap
-/// @param[in] i_common_CL common CAS latency bitmap
+/// @param[in] i_common_cl common CAS latency bitmap
/// @return vector of supported CAS latencies
///
-std::vector<uint64_t> cas_latency::create_common_cl_vector(const uint64_t i_common_CL) const
+std::vector<uint64_t> cas_latency::integral_bitmap_to_vector(const uint64_t i_common_cl) const
{
std::vector<uint64_t> l_vector;
- fapi2::buffer<uint64_t> l_CL_mask(i_common_CL);
+ fapi2::buffer<uint64_t> l_cl_mask(i_common_cl);
- uint64_t min_CL = get_min_CL(l_CL_mask);
- uint64_t max_CL = get_max_CL(l_CL_mask);
+ uint64_t min_cl = get_min_cl(l_cl_mask);
+ uint64_t max_cl = get_max_cl(l_cl_mask);
- FAPI_DBG("min CL %lu", min_CL);
- FAPI_DBG("max CL %lu", max_CL);
+ FAPI_INF("%s. min CL %lu", mss::c_str(iv_target), min_cl);
+ FAPI_INF("%s. max CL %lu", mss::c_str(iv_target), max_cl);
- for(uint64_t cas_latency = min_CL; cas_latency <= max_CL; ++cas_latency)
+ for(uint64_t l_cas_latency = min_cl; l_cas_latency <= max_cl; ++l_cas_latency)
{
// 64 bit is buffer length - indexed at 0 - 63
constexpr uint64_t l_buffer_length = 64 - 1;
- uint64_t l_bit_pos = l_buffer_length - (cas_latency - min_CL);
+ uint64_t l_bit_pos = l_buffer_length - (l_cas_latency - min_cl);
// Traversing through buffer one bit at a time
// 0 means unsupported CAS latency
// 1 means supported CAS latency
// We are pushing supported CAS latencies into a vector for direct use
- if( l_CL_mask.getBit(l_bit_pos) )
+ if( l_cl_mask.getBit(l_bit_pos) )
{
- l_vector.push_back(cas_latency);
+ // I want don't this to print all the time, DBG is fine
+ FAPI_DBG( "%s. Supported CL (%d) from common CL mask",
+ mss::c_str(iv_target), l_cas_latency );
+
+ l_vector.push_back(l_cas_latency);
}
}
return l_vector;
}
-
///
/// @brief Determines if a requested CAS latency (CL) is supported in the bin of common CLs
-/// @param[in] i_common_CLs vector of common CAS latencies
+/// @param[in] i_common_cls vector of common CAS latencies
/// @param[in] i_cas_latency CAS latency we are comparing against
-/// @return true if CAS latency is supported
+/// @return FAPI2_RC_SUCCESS iff ok
///
-inline bool cas_latency::is_CL_supported_in_common(const std::vector<uint64_t>& i_common_CLs,
+inline fapi2::ReturnCode cas_latency::is_cl_supported_in_common(const std::vector<uint64_t>& i_common_cls,
const uint64_t i_cas_latency) const
{
- return std::binary_search(i_common_CLs.begin(), i_common_CLs.end(), i_cas_latency);
+ return std::binary_search(i_common_cls.begin(), i_common_cls.end(), i_cas_latency) == true ?
+ fapi2::FAPI2_RC_SUCCESS : fapi2::FAPI2_RC_FALSE;
}
///
/// @brief Checks that CAS latency doesn't exceed largest CAS latency time
/// @param[in] i_cas_latency cas latency
-/// @param[in] i_tCK cycle time
-/// @return bool true if CAS latency exceeds the largest CAS latency time
-/// false otherwise
-///
-inline bool cas_latency::is_CL_exceeding_tAAmax(const uint64_t i_cas_latency,
- const uint64_t i_tCK) const
-{
- // JEDEC spec requirement
- return (i_cas_latency * i_tCK > TAA_MAX_DDR4);
-}
-
-
-///
-/// @brief Helper function to determines next lowest CAS latency (CL)
-/// @param[in] i_common_CLs vector of common CAS latencies
-/// @param[in] i_desired_cas_latency current CAS latency
-/// @return the next lowest CL
-///
-inline uint64_t cas_latency::next_lowest_CL(const std::vector<uint64_t>& i_common_CLs,
- const uint64_t i_desired_cas_latency)
-{
- auto iterator = std::lower_bound(i_common_CLs.begin(), i_common_CLs.end(), i_desired_cas_latency);
- return *(--iterator);
-}
-
-///
-/// @brief Checks that CAS latency (CL) is supported among all dimms
-/// and if it isn't we try to find a CL that is.
-/// @param[in] i_common_CLs vector of common CAS latencies
-/// @param[in] i_tAA CAS latency time
-/// @param[in,out] io_tCK cycle time that corresponds to cas latency
-/// @param[in,out] io_desired_cas_lat cas latency supported for all dimms
-/// @return fapi2::FAPI2_RC_SUCCESS if we find a valid CL also common among all dimms
-///
-fapi2::ReturnCode cas_latency::choose_actual_CL (const std::vector<uint64_t>& i_common_CLs,
- const uint64_t i_tAA,
- uint64_t& io_tCK,
- uint64_t& io_desired_cas_lat)
-{
- if( i_common_CLs.empty() )
- {
- FAPI_ERR("Common CAS latency vector is empty!");
- return fapi2::FAPI2_RC_INVALID_PARAMETER;
- }
-
- //check if the desired CL is supported in the common CAS latency bin
- bool l_is_CL_supported = is_CL_supported_in_common(i_common_CLs, io_desired_cas_lat);
-
- while( !l_is_CL_supported )
- {
- // If CL is not supported...
- // Choose a higher tCKproposed value and recalculate CL
- // Check recalculated CL is supported in common CL
- // Repeat until a solution is found
- FAPI_TRY( select_higher_tck(io_tCK), "Failed select_higher_tck()");
- FAPI_DBG("Next higher tCK: %d", io_tCK);
-
- io_desired_cas_lat = calc_cas_latency(i_tAA, io_tCK);
- l_is_CL_supported = is_CL_supported_in_common(i_common_CLs, io_desired_cas_lat);
- }
-
- // If we reach here everything is okay
- return fapi2::FAPI2_RC_SUCCESS;
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Checks that CAS latency (CL) doesn't exceed max CAS latency time (tAAmax)
-/// and if it does it tries to find a valid CL that doesn't exceed tAAmax.
-/// @param[in] i_common_CLs vector of common CAS latencies
-/// @param[in] i_tAA CAS latency time
-/// @param[in,out] io_tCK cycle time that corresponds to cas latency
-/// @param[in,out] io_desired_cas_lat cas latency supported for all dimms
-/// @return fapi2::FAPI2_RC_SUCCESS if CL doesn't exceed tAAmax
+/// @param[in] i_tck cycle time
+/// @return FAPI2_RC_SUCCESS iff ok
///
-fapi2::ReturnCode cas_latency::validate_valid_CL (const std::vector<uint64_t>& i_common_CLs,
- const uint64_t i_tAA,
- uint64_t& io_tCK,
- uint64_t& io_desired_cas_lat)
+inline fapi2::ReturnCode cas_latency::is_cl_exceeding_taa_max(const uint64_t i_cas_latency,
+ const uint64_t i_tck) const
{
- if( i_common_CLs.empty() )
- {
- FAPI_ERR("Common CAS latency vector is empty!");
- return fapi2::FAPI2_RC_INVALID_PARAMETER;
- }
+ // JEDEC SPD spec requirement
+ const size_t l_taa_max = (iv_is_3ds == loading::NOT_3DS) ? TAA_MAX_DDR4 : TAA_MAX_DDR4_3DS;
- // Check that selected CL is less than tAAmax
- bool l_is_CL_violating_spec = is_CL_exceeding_tAAmax (io_desired_cas_lat, io_tCK);
+ FAPI_INF("%s. CL (%d) * tCK (%d) = %d > %d",
+ mss::c_str(iv_target),
+ i_cas_latency,
+ i_tck,
+ i_cas_latency * i_tck,
+ l_taa_max);
- while(l_is_CL_violating_spec)
- {
- // If it is not....
- // Decrement CL to next lowest supported CL
- // And try again
- io_desired_cas_lat = next_lowest_CL(i_common_CLs, io_desired_cas_lat);
- FAPI_DBG("Next lowest CAS latency %d", io_desired_cas_lat);
-
- FAPI_TRY( choose_actual_CL(i_common_CLs, i_tAA, io_tCK, io_desired_cas_lat),
- "Failed choose_actual_CL()");
-
- l_is_CL_violating_spec = is_CL_exceeding_tAAmax (io_desired_cas_lat, io_tCK);
- }
-
- //If we reach this point that we are not violationg tAAmax spec anymore
- return fapi2::FAPI2_RC_SUCCESS;
-
-fapi_try_exit:
- // Since a fail here could mean a fail due to choose_actual_cl and
- // due to violation of taamax specification, this error will help
- // distinguish error reason
- FAPI_ASSERT(false,
- fapi2::MSS_EXCEED_TAA_MAX_NO_CL().
- set_CL(io_desired_cas_lat),
- "Exceeded tAAmax");
-
- return fapi2::current_err;
+ return (i_cas_latency * i_tck) > l_taa_max ? fapi2::FAPI2_RC_FALSE : fapi2::FAPI2_RC_SUCCESS;
}
}// mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H
index b52c6b16c..d1c11510c 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H
@@ -50,23 +50,16 @@
namespace mss
{
-enum constants : std::uint64_t
+
+// I choose enumerations over boolean because I feel
+// it makes the interface clearer than could be depicted
+// by 'true' and 'false' alone.
+enum class loading : size_t
{
- // From JEDEC Standard No. 79-4A
- // Speed Bins pg. 164
- /// Time in picoseconds
- TAA_MAX_DDR4 = 18000,
-
- // Low range CAS latency from SPD
- LOW_RANGE_MIN_CL_DDR4 = 7,
- LOW_RANGE_MAX_CL_DDR4 = 36,
-
- // High range CAS latency SPD
- HIGH_RANGE_MIN_CL_DDR4 = 23,
- HIGH_RANGE_MAX_CL_DDR4 = 52,
+ NOT_3DS,
+ IS_3DS,
};
-
///
/// @class decoder
/// @brief CAS latency class that encapsulates JEDEC calculation algorithm
@@ -89,23 +82,73 @@ class cas_latency
/// @brief Class constructor that retrieves required SPD data held by internal state
/// @param[in] i_target the controller target
/// @param[in] i_caches decoder caches
+ /// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully
///
cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs,
- const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches);
+ const std::map<uint32_t, std::shared_ptr<spd::decoder> >& i_caches,
+ fapi2::ReturnCode& o_rc);
+
+ /// @brief Constructor that allows the user to set desired data in lieu of SPD
+ /// @param[in] i_target the controller target
+ /// @param[in] i_taa_min largest tAAmin we want to set in picoseconds
+ /// @param[in] i_tck_min proposed tCKmin in picoseconds
+ /// @param[in] i_common_cl_mask common CAS latency mask we want to use (bitmap)
+ /// @param[in] i_is_3ds loading::IS_3DS if this is for 3DS,
+ /// loading::NOT_3DS otherwise (default)
+ ///
+ cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ const uint64_t i_taa_min,
+ const uint64_t i_tck_min,
+ const uint64_t i_common_cl_mask,
+ const loading i_is_3ds = loading::NOT_3DS);
- // Default destructor
+ ///
+ /// @brief Default destructor
+ ///
~cas_latency() = default;
///
/// @brief Calculates CAS latency and checks if it is supported and within JEDEC spec.
- /// @param[in] i_target the controller target
/// @param[out] o_cas_latency selected CAS latency
- /// @param[out] o_tCK cycle time corresponding to seleted CAS latency
+ /// @param[out] o_tck cycle time corresponding to seleted CAS latency
/// @return fapi2::FAPI2_RC_SUCCESS if ok
///
- fapi2::ReturnCode find_CL(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs,
- uint64_t& o_cas_latency,
- uint64_t& o_tCK);
+ fapi2::ReturnCode find_cl(uint64_t& o_cas_latency,
+ uint64_t& o_tck);
+
+ private:
+
+ enum
+ {
+ // From JEDEC Standard No. 79-4A
+ // Speed Bins pg. 164
+ /// Time in picoseconds
+ TAA_MAX_DDR4 = 18000,
+
+ // From JEDEC Standard No. 79-4 3DS
+ // Speed Bins pg. 135
+ /// Time in picoseconds
+ TAA_MAX_DDR4_3DS = 21500,
+
+ // Low range CAS latency from SPD
+ LOW_RANGE_MIN_CL_DDR4 = 7,
+ LOW_RANGE_MAX_CL_DDR4 = 36,
+
+ // High range CAS latency SPD
+ HIGH_RANGE_MIN_CL_DDR4 = 23,
+ HIGH_RANGE_MAX_CL_DDR4 = 52,
+
+ CAS_LAT_RANGE_BIT = 31,
+ };
+
+ /////////////////////////
+ // Private variables
+ /////////////////////////
+ fapi2::Target<fapi2::TARGET_TYPE_MCS> iv_target;
+ uint64_t iv_largest_taamin;// cas latency time
+ uint64_t iv_proposed_tck;// cycle time
+ uint64_t iv_common_cl; // common cas latency
+ loading iv_is_3ds;
///
/// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD
@@ -141,99 +184,56 @@ class cas_latency
///
/// @brief Gets max CAS latency (CL) for the appropriate High/Low Range
- /// @param[in] i_supported_CL
+ /// @param[in] i_supported_cl
/// @return the maximum supported CL
/// @note Depends on bit 7 of byte 23 from the DDR4 SPD
///
- inline uint64_t get_max_CL(const fapi2::buffer<uint64_t> i_supported_CL) const;
+ inline uint64_t get_max_cl(const fapi2::buffer<uint64_t> i_supported_cl) const;
///
/// @brief Gets min CAS latency (CL) for the appropriate High/Low Range
- /// @param[in] i_supported_CL
+ /// @param[in] i_supported_cl
/// @return the minimum supported CL
/// @note Depends on bit 7 of byte 23 from the DDR4 SPD
///
- inline uint64_t get_min_CL(const fapi2::buffer<uint64_t>& i_supported_CL) const;
+ inline uint64_t get_min_cl(const fapi2::buffer<uint64_t>& i_supported_cl) const;
///
/// @brief Calculates CAS latency time from tCK and tAA
- /// @param[in] i_tAA cas latency time
- /// @param[in] i_tCK min cycle time
- /// @return o_cas_latency calculated CAS latency
+ /// @param[in] i_taa cas latency time
+ /// @param[in] i_tck min cycle time
+ /// @param[out] o_cas_latency calculated CAS latency
+ /// @return FAPI2_RC_SUCCESS iff okay
///
- inline uint64_t calc_cas_latency(const uint64_t i_tAA, const uint64_t i_tCK) const;
+ inline fapi2::ReturnCode calc_cas_latency(const uint64_t i_taa,
+ const uint64_t i_tck,
+ uint64_t& o_cas_latency) const;
///
/// @brief Helper function to create a vector of supported CAS latencies from a bitmap
- /// @param[in] i_common_CL common CAS latency bitmap
+ /// @param[in] i_common_cl common CAS latency bitmap
/// @return vector of supported CAS latencies
///
- std::vector<uint64_t> create_common_cl_vector(const uint64_t i_common_CL) const;
+ std::vector<uint64_t> integral_bitmap_to_vector(const uint64_t i_bitmap) const;
///
/// @brief Determines if a requested CAS latency (CL) is supported in the bin of common CLs
- /// @param[in] i_common_CLs vector of common CAS latencies
+ /// @param[in] i_common_cls vector of common CAS latencies
/// @param[in] i_cas_latency CAS latency we are comparing against
- /// @return true if CAS latency is supported
+ /// @return fapi2::FAPI2_RC_SUCCESS if ok
///
- inline bool is_CL_supported_in_common(const std::vector<uint64_t>& i_common_CLs,
- const uint64_t i_cas_latency) const;
+ inline fapi2::ReturnCode is_cl_supported_in_common(const std::vector<uint64_t>& i_common_cls,
+ const uint64_t i_cas_latency) const;
///
/// @brief Checks that CAS latency doesn't exceed largest CAS latency time
/// @param[in] i_cas_latency cas latency
- /// @param[in] i_tCK cycle time
- /// @return bool true if CAS latency exceeds the largest CAS latency time
- /// false otherwise
- ///
- inline bool is_CL_exceeding_tAAmax(const uint64_t i_cas_latency,
- const uint64_t i_tCK) const;
-
- ///
- /// @brief Helper function to determines next lowest CAS latency (CL)
- /// @param[in] i_common_CLs vector of common CAS latencies
- /// @param[in] i_desired_cas_latency current CAS latency
- /// @return the next lowest CL
- ///
- inline uint64_t next_lowest_CL(const std::vector<uint64_t>& i_common_CLs,
- const uint64_t i_desired_cas_latency);
-
- ///
- /// @brief Checks that CAS latency (CL) is supported among all dimms
- /// and if it isn't we try to find a CL that is.
- /// @param[in] i_common_CLs vector of common CAS latencies
- /// @param[in] i_tAA CAS latency time
- /// @param[in,out] io_tCK cycle time that corresponds to cas latency
- /// @param[in,out] io_desired_cas_lat cas latency supported for all dimms
- /// @return fapi2::FAPI2_RC_SUCCESS if we find a valid CL also common among all dimms
- ///
- fapi2::ReturnCode choose_actual_CL (const std::vector<uint64_t>& i_common_CLs,
- const uint64_t i_tAA,
- uint64_t& io_tCK,
- uint64_t& io_desired_cas_lat);
- ///
- /// @brief Checks that CAS latency (CL) doesn't exceed max CAS latency time (tAAmax)
- /// and if it does it tries to find a valid CL that doesn't exceed tAAmax.
- /// @param[in] i_common_CLs vector of common CAS latencies
- /// @param[in] i_tAA CAS latency time
- /// @param[in,out] io_tCK cycle time that corresponds to cas latency
- /// @param[in,out] io_desired_cas_lat cas latency supported for all dimms
- /// @return fapi2::FAPI2_RC_SUCCESS if CL doesn't exceed tAAmax
+ /// @param[in] i_tck cycle time
+ /// @return fapi2::FAPI2_RC_SUCCESS if ok
///
- fapi2::ReturnCode validate_valid_CL (const std::vector<uint64_t>& i_common_CLs,
- const uint64_t i_tAA,
- uint64_t& io_tCK,
- uint64_t& io_desired_cas_lat);
-
- private:
-
- /////////////////////////
- // Private variables
- /////////////////////////
- uint64_t iv_largest_taamin;// cas latency time
- uint64_t iv_proposed_tck;// cycle time
- uint64_t iv_common_CL; // common cas latency
+ inline fapi2::ReturnCode is_cl_exceeding_taa_max(const uint64_t i_cas_latency,
+ const uint64_t i_tck) const;
};// cas_latency
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H
index 2352d14df..39ff8d401 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cycle_time.H
@@ -52,22 +52,6 @@ enum FREQ_MARGIN : std::uint64_t
MAX_FREQ_MARGIN = 2799,
};
-// Proposed DDR4 Full spec update(79-4A)
-// Item No. 1716.78C
-// Page 217
-// 10.1 Item No. 1716.78C
-// Speed Bin Table Note
-static const std::vector<uint64_t> tckmin_avg_ddr4
-{
-
- // Timing in picoseconds | Application bin speed
- 750, // 2666 MT/s
- 833, // 2400 MT/s
- 937, // 2133 MT/s
- 1071, // 1866 MT/s
- /* 1250, // 1600 MT/s - don't think we support this one - AAM */
-};
-
///
/// @brief Selects DIMM frequency to run based on supported system frequencies
/// @tparam T the fapi2::TargetType for which the DIMM information exists.
@@ -127,28 +111,6 @@ fapi_try_exit:
return fapi2::current_err;
}
-///
-/// @brief Determines next highest min cycle time (tCK)
-/// @param[in,out] io_tCK_in_ps min cycle time in ps
-/// @return fapi2::FAPI2_RC_SUCCESS if ok
-///
-inline fapi2::ReturnCode select_higher_tck(uint64_t& io_tCK)
-{
- auto iterator = std::upper_bound(tckmin_avg_ddr4.begin(),
- tckmin_avg_ddr4.end(),
- io_tCK);
-
- // Did we find a greater than value?
- FAPI_ASSERT(iterator != tckmin_avg_ddr4.end(),
- fapi2::MSS_REACHED_HIGHEST_TCK().
- set_TCK(io_tCK),
- "Reached highest valid tCK");
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-
}// mss
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H
index 5d99d8caf..0a1b3c896 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H
@@ -15854,8 +15854,11 @@ fapi_try_exit:
/// @param[out] ref to the value uint16_t
/// @note Generated by gen_accessors.pl generateParameters (D)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Average Refresh Interval (tREFI) in nck (number of clock cycles). creator:
-/// mss_eff_config consumer: various firmware notes:
+/// @note Average Refresh Interval (tREFI) in nck (number of clock cycles). This depends
+/// on MRW attribute that selects fine refresh mode (x1, x2, x4). From DDR4 spec
+/// (79-4A). For 3DS, the tREFI time to the same logical rank is defined as
+/// tRFC_slr1, tRFC_slr2, or tRFC_slr4. creator: mss_eff_config consumer: various
+/// firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trefi(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint16_t& o_value)
@@ -15878,8 +15881,11 @@ fapi_try_exit:
/// @param[out] ref to the value uint16_t
/// @note Generated by gen_accessors.pl generateParameters (D.1)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Average Refresh Interval (tREFI) in nck (number of clock cycles). creator:
-/// mss_eff_config consumer: various firmware notes:
+/// @note Average Refresh Interval (tREFI) in nck (number of clock cycles). This depends
+/// on MRW attribute that selects fine refresh mode (x1, x2, x4). From DDR4 spec
+/// (79-4A). For 3DS, the tREFI time to the same logical rank is defined as
+/// tRFC_slr1, tRFC_slr2, or tRFC_slr4. creator: mss_eff_config consumer: various
+/// firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trefi(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint16_t& o_value)
@@ -15903,8 +15909,11 @@ fapi_try_exit:
/// @param[out] uint16_t* memory to store the value
/// @note Generated by gen_accessors.pl generateParameters (E)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Average Refresh Interval (tREFI) in nck (number of clock cycles). creator:
-/// mss_eff_config consumer: various firmware notes:
+/// @note Average Refresh Interval (tREFI) in nck (number of clock cycles). This depends
+/// on MRW attribute that selects fine refresh mode (x1, x2, x4). From DDR4 spec
+/// (79-4A). For 3DS, the tREFI time to the same logical rank is defined as
+/// tRFC_slr1, tRFC_slr2, or tRFC_slr4. creator: mss_eff_config consumer: various
+/// firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trefi(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, uint16_t* o_array)
@@ -15933,8 +15942,9 @@ fapi_try_exit:
/// @param[out] ref to the value uint8_t
/// @note Generated by gen_accessors.pl generateParameters (D)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Internal Read to Precharge Delay. Each memory channel will have a value.
-/// creator: mss_eff_cnfg_timing consumer: various firmware notes:
+/// @note Internal Read to Precharge Delay. From the DDR4 spec (79-4A). Each memory
+/// channel will have a value. creator: mss_eff_cnfg_timing consumer: various
+/// firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trtp(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint8_t& o_value)
@@ -15957,8 +15967,9 @@ fapi_try_exit:
/// @param[out] ref to the value uint8_t
/// @note Generated by gen_accessors.pl generateParameters (D.1)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Internal Read to Precharge Delay. Each memory channel will have a value.
-/// creator: mss_eff_cnfg_timing consumer: various firmware notes:
+/// @note Internal Read to Precharge Delay. From the DDR4 spec (79-4A). Each memory
+/// channel will have a value. creator: mss_eff_cnfg_timing consumer: various
+/// firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trtp(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_value)
@@ -15982,8 +15993,9 @@ fapi_try_exit:
/// @param[out] uint8_t* memory to store the value
/// @note Generated by gen_accessors.pl generateParameters (E)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Internal Read to Precharge Delay. Each memory channel will have a value.
-/// creator: mss_eff_cnfg_timing consumer: various firmware notes:
+/// @note Internal Read to Precharge Delay. From the DDR4 spec (79-4A). Each memory
+/// channel will have a value. creator: mss_eff_cnfg_timing consumer: various
+/// firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trtp(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, uint8_t* o_array)
@@ -16012,11 +16024,11 @@ fapi_try_exit:
/// @param[out] ref to the value uint8_t
/// @note Generated by gen_accessors.pl generateParameters (D)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Minimum Refresh Recovery Delay Time in nck (number of clock cyles). Selected
-/// tRFC value (tRFC_dl1, tRFC_dl2, or tRFC_dl4) depends on MRW attribute that
-/// selects fine refresh mode (x1, x2, x4). For 3DS, The tRFC time to different
-/// logical ranks are defined as tRFC_dlr creator: eff_config consumer: various
-/// firmware notes:
+/// @note Minimum Refresh Recovery Delay Time (different logical ranks) in nck (number of
+/// clock cyles). Selected tRFC value (tRFC_dlr1, tRFC_dlr2, or tRFC_dlr4) depends
+/// on MRW attribute that selects fine refresh mode (x1, x2, x4). For 3DS, The tRFC
+/// time to different logical ranks are defined as tRFC_dlr creator: eff_config
+/// consumer: various firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trfc_dlr(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint8_t& o_value)
@@ -16039,11 +16051,11 @@ fapi_try_exit:
/// @param[out] ref to the value uint8_t
/// @note Generated by gen_accessors.pl generateParameters (D.1)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Minimum Refresh Recovery Delay Time in nck (number of clock cyles). Selected
-/// tRFC value (tRFC_dl1, tRFC_dl2, or tRFC_dl4) depends on MRW attribute that
-/// selects fine refresh mode (x1, x2, x4). For 3DS, The tRFC time to different
-/// logical ranks are defined as tRFC_dlr creator: eff_config consumer: various
-/// firmware notes:
+/// @note Minimum Refresh Recovery Delay Time (different logical ranks) in nck (number of
+/// clock cyles). Selected tRFC value (tRFC_dlr1, tRFC_dlr2, or tRFC_dlr4) depends
+/// on MRW attribute that selects fine refresh mode (x1, x2, x4). For 3DS, The tRFC
+/// time to different logical ranks are defined as tRFC_dlr creator: eff_config
+/// consumer: various firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trfc_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_value)
@@ -16067,11 +16079,11 @@ fapi_try_exit:
/// @param[out] uint8_t* memory to store the value
/// @note Generated by gen_accessors.pl generateParameters (E)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Minimum Refresh Recovery Delay Time in nck (number of clock cyles). Selected
-/// tRFC value (tRFC_dl1, tRFC_dl2, or tRFC_dl4) depends on MRW attribute that
-/// selects fine refresh mode (x1, x2, x4). For 3DS, The tRFC time to different
-/// logical ranks are defined as tRFC_dlr creator: eff_config consumer: various
-/// firmware notes:
+/// @note Minimum Refresh Recovery Delay Time (different logical ranks) in nck (number of
+/// clock cyles). Selected tRFC value (tRFC_dlr1, tRFC_dlr2, or tRFC_dlr4) depends
+/// on MRW attribute that selects fine refresh mode (x1, x2, x4). For 3DS, The tRFC
+/// time to different logical ranks are defined as tRFC_dlr creator: eff_config
+/// consumer: various firmware notes:
/// none
///
inline fapi2::ReturnCode eff_dram_trfc_dlr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, uint8_t* o_array)
@@ -16180,6 +16192,91 @@ fapi_try_exit:
}
///
+/// @brief ATTR_EFF_DRAM_TRRD_DLR getter
+/// @param[in] const ref to the fapi2::Target<fapi2::TARGET_TYPE_MCA>
+/// @param[out] ref to the value uint8_t
+/// @note Generated by gen_accessors.pl generateParameters (D)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Minimum Activate to Activate Delay Time (different logical ranks) in nck (number
+/// of clock cycles). For 3DS, The tRRD_S time to a different logical rank is
+/// defined as tRRD_dlr. Each memory channel will have a value. creator: eff_confg
+/// consumer: various firmware notes:
+/// none
+///
+inline fapi2::ReturnCode eff_dram_trrd_dlr(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint8_t& o_value)
+{
+ uint8_t l_value[2];
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_TRRD_DLR, i_target.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ o_value = l_value[mss::index(i_target)];
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_EFF_DRAM_TRRD_DLR: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_EFF_DRAM_TRRD_DLR getter
+/// @param[in] const ref to the fapi2::Target<fapi2::TARGET_TYPE_DIMM>
+/// @param[out] ref to the value uint8_t
+/// @note Generated by gen_accessors.pl generateParameters (D.1)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Minimum Activate to Activate Delay Time (different logical ranks) in nck (number
+/// of clock cycles). For 3DS, The tRRD_S time to a different logical rank is
+/// defined as tRRD_dlr. Each memory channel will have a value. creator: eff_confg
+/// consumer: various firmware notes:
+/// none
+///
+inline fapi2::ReturnCode eff_dram_trrd_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint8_t& o_value)
+{
+ uint8_t l_value[2];
+ auto l_mca = i_target.getParent<fapi2::TARGET_TYPE_MCA>();
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_TRRD_DLR, l_mca.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ o_value = l_value[mss::index(l_mca)];
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_EFF_DRAM_TRRD_DLR: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_EFF_DRAM_TRRD_DLR getter
+/// @param[in] const ref to the fapi2::Target<fapi2::TARGET_TYPE_MCS>
+/// @param[out] uint8_t* memory to store the value
+/// @note Generated by gen_accessors.pl generateParameters (E)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Minimum Activate to Activate Delay Time (different logical ranks) in nck (number
+/// of clock cycles). For 3DS, The tRRD_S time to a different logical rank is
+/// defined as tRRD_dlr. Each memory channel will have a value. creator: eff_confg
+/// consumer: various firmware notes:
+/// none
+///
+inline fapi2::ReturnCode eff_dram_trrd_dlr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, uint8_t* o_array)
+{
+ if (o_array == nullptr)
+ {
+ FAPI_ERR("nullptr passed to attribute accessor %s", __func__);
+ return fapi2::FAPI2_RC_INVALID_PARAMETER;
+ }
+
+ uint8_t l_value[2];
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_TRRD_DLR, i_target, l_value) );
+ memcpy(o_array, &l_value, 2);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_EFF_DRAM_TRRD_DLR: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
/// @brief ATTR_EFF_DRAM_TXS getter
/// @param[in] const ref to the fapi2::Target<fapi2::TARGET_TYPE_MCA>
/// @param[out] ref to the value uint8_t
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.C
index c7583f58c..61f6b5ee4 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/seq.C
@@ -116,13 +116,28 @@ fapi2::ReturnCode reset_timing0( const fapi2::Target<TARGET_TYPE_MCA>& i_target
l_data.insertFromRight<TT::TRP_CYCLES, TT::TRP_CYCLES_LEN>( exp_helper(l_trp) );
// It's not really clear what to put here. We can have DIMM with different tRFC as they
- // don't have to be the same (3DS v. SPD for example.) So we'll take the maximum trfc we
+ // don't have to be the same (3DS v. SDP for example.) So we'll take the maximum trfc we
// find on the DIMM connected to this port.
for (const auto& d : mss::find_targets<TARGET_TYPE_DIMM>(i_target))
{
+ // tRFC is for non-3DS, tRFC_slr for 3DS is to the same logical rank,
+ // and tRFC_dlr is to different logical ranks. Unclear which to use.
uint16_t l_trfc = 0;
- FAPI_TRY( mss::trfc(d, l_trfc) );
- l_trfc_max = std::max(l_trfc_max, l_trfc);
+ uint8_t l_trfc_dlr = 0;
+
+ // tRFC (or tRFC_slr) will retrieve a value for 3DS or non-3DS
+ // tRFC_dlr is only set for 3DS (should be 0 otherwise)
+ // so we opt to take the more aggressive timing,
+ // means less chance of data being corrupted
+ FAPI_TRY( mss::eff_dram_trfc(d, l_trfc) );
+ FAPI_TRY( mss::eff_dram_trfc_dlr(d, l_trfc_dlr) );
+
+ {
+ // cast needed for template deduction of std::max()
+ // HB doesn't support using std::min() with initializer lists
+ const uint16_t l_trfc_3ds_min = std::min(l_trfc, static_cast<uint16_t>(l_trfc_dlr));
+ l_trfc_max = std::min( l_trfc_3ds_min, l_trfc_max);
+ }
}
l_data.insertFromRight<TT::TRFC_CYCLES, TT::TRFC_CYCLES_LEN>( exp_helper(l_trfc_max) );
@@ -194,4 +209,3 @@ fapi_try_exit:
} // close namespace seq
} // close namespace mss
-
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C
index 1e71de864..864805541 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/spd_decoder.C
@@ -1037,10 +1037,10 @@ fapi2::ReturnCode decoder::device_width(const fapi2::Target<TARGET_TYPE_DIMM>& i
static const std::vector<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP =
{
// {key byte, device width (bits)}
- {0, 4},
- {1, 8},
- {2, 16},
- {3, 32},
+ {0, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4},
+ {1, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8},
+ {2, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16},
+ {3, fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X32},
// All others reserved
};
@@ -1544,28 +1544,28 @@ fapi2::ReturnCode decoder::supported_cas_latencies(const fapi2::Target<TARGET_TY
constexpr size_t FIRST_BYTE = 20;
uint8_t first_raw_byte = iv_spd_data[FIRST_BYTE];
FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
- c_str(i_target),
+ mss::c_str(i_target),
FIRST_BYTE,
first_raw_byte);
constexpr size_t SEC_BYTE = 21;
uint8_t sec_raw_byte = iv_spd_data[SEC_BYTE];
FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
- c_str(i_target),
+ mss::c_str(i_target),
SEC_BYTE,
sec_raw_byte);
constexpr size_t THIRD_BYTE = 22;
uint8_t third_raw_byte = iv_spd_data[THIRD_BYTE];
FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
- c_str(i_target),
+ mss::c_str(i_target),
THIRD_BYTE,
third_raw_byte);
constexpr size_t FOURTH_BYTE = 23;
uint8_t fourth_raw_byte = iv_spd_data[FOURTH_BYTE];
FAPI_INF("%s SPD data at Byte %d: 0x%llX.",
- c_str(i_target),
+ mss::c_str(i_target),
FOURTH_BYTE,
fourth_raw_byte);
@@ -1766,9 +1766,11 @@ fapi2::ReturnCode decoder::min_active_to_precharge_delay_time(const fapi2::Targe
{
constexpr size_t BYTE_INDEX_MSN = 27;
uint8_t tRASmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TRASMIN_MSN_START, TRASMIN_MSN_LEN >(i_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tRASmin_MSN);
constexpr size_t BYTE_INDEX_LSB = 28;
uint8_t tRASmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TRASMIN_LSB_START, TRASMIN_LSB_LEN >(i_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tRASmin_LSB);
// Combining bits to create timing value (in a buffer)
constexpr size_t MSN_START = 52;
@@ -1831,9 +1833,11 @@ fapi2::ReturnCode decoder::min_active_to_active_refresh_delay_time(const fapi2::
{
constexpr size_t BYTE_INDEX_MSN = 27;
uint8_t tRCmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TRCMIN_MSN_START, TRCMIN_MSN_LEN >(i_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tRCmin_MSN);
constexpr size_t BYTE_INDEX_LSB = 29;
uint8_t tRCmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TRCMIN_LSB_START, TRCMIN_LSB_LEN >(i_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tRCmin_LSB);
// Combining bits to create timing value (in a buffer)
constexpr size_t MSN_START = 52;
@@ -1842,7 +1846,6 @@ fapi2::ReturnCode decoder::min_active_to_active_refresh_delay_time(const fapi2::
constexpr size_t LSB_LEN = 8;
fapi2::buffer<int64_t> l_buffer;
-
l_buffer.insertFromRight<MSN_START, MSN_LEN>( tRCmin_MSN )
.insertFromRight<LSB_START, LSB_LEN>( tRCmin_LSB );
@@ -2072,9 +2075,11 @@ fapi2::ReturnCode decoder::min_tfaw(const fapi2::Target<TARGET_TYPE_DIMM>& i_tar
{
constexpr size_t BYTE_INDEX_MSN = 36;
uint8_t tFAWmin_MSN = extract_spd_field< BYTE_INDEX_MSN, TFAWMIN_MSN_START, TFAWMIN_MSN_LEN >(i_target, iv_spd_data);
+ FAPI_INF("MSN Field Bits value: %lu", tFAWmin_MSN);
constexpr size_t BYTE_INDEX_LSB = 37;
uint8_t tFAWmin_LSB = extract_spd_field< BYTE_INDEX_LSB, TFAWMIN_LSB_START, TFAWMIN_LSB_LEN >(i_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", tFAWmin_LSB);
// Combining bits to create timing value (in a buffer)
constexpr size_t MSN_START = 52;
@@ -2789,9 +2794,11 @@ fapi2::ReturnCode decoder::cyclical_redundancy_code(const fapi2::Target<fapi2::T
{
constexpr size_t BYTE_INDEX_MSB = 127;
uint8_t crc_MSB = extract_spd_field< BYTE_INDEX_MSB, CRC_MSB_START, CRC_MSB_LEN >(i_target, iv_spd_data);
+ FAPI_INF("MSB Field Bits value: %lu", crc_MSB);
constexpr size_t BYTE_INDEX_LSB = 126;
uint8_t crc_LSB = extract_spd_field< BYTE_INDEX_LSB, CRC_LSB_START, CRC_LSB_LEN >(i_target, iv_spd_data);
+ FAPI_INF("LSB Field Bits value: %lu", crc_LSB);
// Combining bits to create timing value (in a buffer)
constexpr size_t MSN_START = 0;
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
index 46a4dd765..8306dc750 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
@@ -93,13 +93,12 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS>
FAPI_TRY( l_eff_config.dram_width(l_dimm) );
FAPI_TRY( l_eff_config.dram_density(l_dimm) );
FAPI_TRY( l_eff_config.ranks_per_dimm(l_dimm) );
- // Master ranks done above
FAPI_TRY( l_eff_config.primary_stack_type(l_dimm) );
FAPI_TRY( l_eff_config.dimm_size(l_dimm) );
FAPI_TRY( l_eff_config.hybrid_memory_type(l_dimm) );
- FAPI_TRY( l_eff_config.refresh_interval_time(l_dimm) );
- FAPI_TRY( l_eff_config.refresh_cycle_time(l_dimm) );
- FAPI_TRY( l_eff_config.refresh_cycle_time_dlr(l_dimm) );
+ FAPI_TRY( l_eff_config.dram_trefi(l_dimm) );
+ FAPI_TRY( l_eff_config.dram_trfc(l_dimm) );
+ FAPI_TRY( l_eff_config.dram_trfc_dlr(l_dimm) );
FAPI_TRY( l_eff_config.rcd_mirror_mode(l_dimm) );
FAPI_TRY( l_eff_config.dram_bank_bits(l_dimm) );
FAPI_TRY( l_eff_config.dram_row_bits(l_dimm) );
@@ -168,11 +167,14 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS>
FAPI_TRY( l_eff_config.memcal_interval(l_dimm) );
FAPI_TRY( l_eff_config.dram_trp(l_dimm) );
FAPI_TRY( l_eff_config.dram_trcd(l_dimm) );
+ FAPI_TRY( l_eff_config.dram_trc(l_dimm) );
FAPI_TRY( l_eff_config.dram_twtr_l(l_dimm) );
FAPI_TRY( l_eff_config.dram_twtr_s(l_dimm) );
FAPI_TRY( l_eff_config.dram_trrd_s(l_dimm) );
FAPI_TRY( l_eff_config.dram_trrd_l(l_dimm) );
+ FAPI_TRY( l_eff_config.dram_trrd_dlr(l_dimm) );
FAPI_TRY( l_eff_config.dram_tfaw(l_dimm) );
+ FAPI_TRY( l_eff_config.dram_tfaw_dlr(l_dimm) );
FAPI_TRY( l_eff_config.dram_tras(l_dimm) );
FAPI_TRY( l_eff_config.dram_trtp(l_dimm) );
FAPI_TRY( l_eff_config.read_dbi(l_dimm) );
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C
index 953626b16..646885e34 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C
@@ -99,16 +99,19 @@ extern "C"
// Get cached decoder
std::map<uint32_t, std::shared_ptr<mss::spd::decoder> > l_factory_caches;
FAPI_TRY( mss::spd::populate_decoder_caches(l_mcs, l_factory_caches),
- "Failed to populate decoder cache");
+ "%s. Failed to populate decoder cache", mss::c_str(i_target) );
{
// instantiation of class that calculates CL algorithm
- mss::cas_latency l_cas_latency(l_mcs, l_factory_caches);
+ fapi2::ReturnCode l_rc;
+ mss::cas_latency l_cas_latency(l_mcs, l_factory_caches, l_rc);
+ FAPI_TRY( l_rc, "%s. Failed to initialize cas_latency ctor", mss::c_str(i_target) );
if(l_cas_latency.iv_dimm_list_empty)
{
// Cannot fail out for an empty DIMM configuration, so default values are set
- FAPI_INF("DIMM list is empty! Setting default values for CAS latency and DIMM speed.");
+ FAPI_INF("%s. DIMM list is empty! Setting default values for CAS latency and DIMM speed.",
+ mss::c_str(i_target) );
}
else
{
@@ -121,33 +124,35 @@ extern "C"
uint64_t l_tCKmin = 0;
// Find CAS latency using JEDEC algorithm
- l_cas_latency.find_CL(l_mcs,
- l_desired_cas_latency[l_index],
- l_tCKmin);
+ FAPI_TRY( l_cas_latency.find_cl(l_desired_cas_latency[l_index],
+ l_tCKmin) );
+
+ FAPI_INF("%s. Result from CL algorithm, CL (nck): %d, tCK (ps): %d",
+ mss::c_str(i_target), l_desired_cas_latency[l_index], l_tCKmin);
// Find dimm transfer speed from selected tCK
FAPI_TRY( mss::ps_to_freq(l_tCKmin, l_min_dimm_freq[l_index]),
- "Failed ps_to_freq()");
+ "%s. Failed ps_to_freq()", mss::c_str(i_target) );
- FAPI_INF("DIMM speed from selected tCK: %d (%s)", l_min_dimm_freq[l_index], mss::c_str(l_mcs));
+ FAPI_INF("DIMM speed from selected tCK (ps): %d for %s", l_min_dimm_freq[l_index], mss::c_str(l_mcs));
FAPI_TRY(mss::select_supported_freq(l_mcs, l_min_dimm_freq[l_index]),
- "Failed select_supported_freq() %s", mss::c_str(l_mcs));
+ "Failed select_supported_freq() for %s", mss::c_str(l_mcs));
- FAPI_INF("Selected DIMM speed from supported speeds: %d", l_min_dimm_freq[l_index]);
+ FAPI_INF("%s. Selected DIMM speed from supported speeds: %d",
+ mss::c_str(i_target), l_min_dimm_freq[l_index]);
}// end else
} // close scope
FAPI_TRY(mss::set_CL_attr(l_mcs, l_desired_cas_latency[l_index] ),
- "Failed set_CL_attr()");
+ "%s. Failed set_CL_attr()", mss::c_str(i_target) );
- FAPI_INF( "Final Chosen CL: %d (%s)", l_desired_cas_latency[l_index], mss::c_str(l_mcs));
} // close for each mcs
FAPI_TRY(mss::set_freq_attrs(l_mcbist, l_min_dimm_freq),
- "Failed set_freq_attrs()");
+ "%s. Failed set_freq_attrs()", mss::c_str(i_target) );
fapi_try_exit:
return fapi2::current_err;
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H
index 4050b06c2..3f24856bf 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H
@@ -46,32 +46,6 @@ namespace mss
{
///
-/// @brief Checks for frequency override and sets dimm frequency and timing values
-/// @param[in] i_target mcbist fapi2 target
-/// @param[out] o_tCK new cycle time if there is a freq override
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-inline fapi2::ReturnCode check_for_freq_override(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
- uint64_t& o_tCK)
-{
- uint64_t l_freq_override = 0;
-
- FAPI_TRY(freq_override(i_target, l_freq_override),
- "Failed to override frequency!");
-
- // If there is no override, don't change anything
- if ( l_freq_override != fapi2::ENUM_ATTR_MSS_FREQ_OVERRIDE_AUTO)
- {
- FAPI_TRY( mss::freq_to_ps(l_freq_override, o_tCK), "Failed freq_to_ps()");
- FAPI_DBG( "Override Frequency Detected: %d", l_freq_override);
- }
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-
-///
/// @brief Sets DRAM CAS latency attributes
/// @param[in] i_target the controller target
/// @param[in] i_cas_latency final selected CAS ltency
@@ -80,15 +54,20 @@ fapi_try_exit:
inline fapi2::ReturnCode set_CL_attr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
uint64_t i_cas_latency)
{
- // Declaration of the vector correctly initializes it to the right size
- // in the case the enum for PORTS_PER_MCS changes
- std::vector<uint8_t> l_cls_vect(PORTS_PER_MCS, uint8_t(i_cas_latency) );
+ std::vector<uint8_t> l_cls(PORTS_PER_MCS, 0);
+
+ // Set configured ports
+ for( const auto& p : find_targets<fapi2::TARGET_TYPE_MCA>(i_target) )
+ {
+ l_cls[mss::index(p)] = i_cas_latency;
+ FAPI_INF( "Final Chosen CL: %d for %s", i_cas_latency, mss::c_str(p));
+ }
// set CAS latency attribute
// casts vector into the type FAPI_ATTR_SET is expecting by deduction
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_CL,
i_target,
- UINT8_VECTOR_TO_1D_ARRAY(l_cls_vect, PORTS_PER_MCS)) ,
+ UINT8_VECTOR_TO_1D_ARRAY(l_cls, PORTS_PER_MCS)) ,
"Failed to set CAS latency attribute");
fapi_try_exit:
diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml
index 8d5776543..b0353804e 100644
--- a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml
+++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml
@@ -2865,7 +2865,14 @@
<id>ATTR_EFF_DRAM_TREFI</id>
<targetType>TARGET_TYPE_MCS</targetType>
<description>
- Average Refresh Interval (tREFI) in nck (number of clock cycles).
+ Average Refresh Interval (tREFI)
+ in nck (number of clock cycles).
+ This depends on MRW attribute that selects fine refresh mode (x1, x2, x4).
+ From DDR4 spec (79-4A).
+
+ For 3DS, the tREFI time to the same logical rank is defined as
+ tRFC_slr1, tRFC_slr2, or tRFC_slr4.
+
creator: mss_eff_config
consumer: various
firmware notes: none
@@ -2881,14 +2888,14 @@
<attribute>
<id>ATTR_EFF_DRAM_TRTP</id>
- <!-- Not an SPD byte - how to find this?? -AM -->
<targetType>TARGET_TYPE_MCS</targetType>
<description>
- Internal Read to Precharge Delay.
- Each memory channel will have a value.
- creator: mss_eff_cnfg_timing
- consumer: various
- firmware notes: none
+ Internal Read to Precharge Delay.
+ From the DDR4 spec (79-4A).
+ Each memory channel will have a value.
+ creator: mss_eff_cnfg_timing
+ consumer: various
+ firmware notes: none
</description>
<initToZero></initToZero>
<valueType>uint8</valueType>
@@ -2901,9 +2908,9 @@
<id>ATTR_EFF_DRAM_TRFC_DLR</id>
<targetType>TARGET_TYPE_MCS</targetType>
<description>
- Minimum Refresh Recovery Delay Time
+ Minimum Refresh Recovery Delay Time (different logical ranks)
in nck (number of clock cyles).
- Selected tRFC value (tRFC_dl1, tRFC_dl2, or tRFC_dl4)
+ Selected tRFC value (tRFC_dlr1, tRFC_dlr2, or tRFC_dlr4)
depends on MRW attribute that selects fine refresh mode (x1, x2, x4).
For 3DS, The tRFC time to different logical ranks are defined as tRFC_dlr
creator: eff_config
@@ -2938,6 +2945,26 @@
</attribute>
<attribute>
+ <id>ATTR_EFF_DRAM_TRRD_DLR</id>
+ <targetType>TARGET_TYPE_MCS</targetType>
+ <description>
+ Minimum Activate to Activate Delay Time (different logical ranks)
+ in nck (number of clock cycles).
+ For 3DS, The tRRD_S time to a different logical rank is defined as tRRD_dlr.
+ Each memory channel will have a value.
+ creator: eff_confg
+ consumer: various
+ firmware notes: none
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint8</valueType>
+ <writeable/>
+ <array> 2 </array>
+ <mssUnits> nck </mssUnits>
+ <mssAccessorName>eff_dram_trrd_dlr</mssAccessorName>
+ </attribute>
+
+ <attribute>
<id>ATTR_EFF_DRAM_TXS</id>
<targetType>TARGET_TYPE_MCS</targetType>
<description>
diff --git a/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml b/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml
index 79fe18a1d..6aee20e1b 100644
--- a/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml
+++ b/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml
@@ -212,7 +212,9 @@
<attribute>
<id>ATTR_SYSTEM_RESCLK_ENABLE</id>
</attribute>
-
+ <attribute>
+ <id>ATTR_EFF_DRAM_TRRD_DLR</id>
+ </attribute>
<!-- =====================================================================
End of temporary definitions
================================================================= -->
OpenPOWER on IntegriCloud