summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib
diff options
context:
space:
mode:
authorLouis Stermole <stermole@us.ibm.com>2019-06-07 15:44:22 -0400
committerChristian R. Geddes <crgeddes@us.ibm.com>2019-07-09 10:18:24 -0500
commitd9bbcfabbc2f041ba85095ac70dc27c37cb87755 (patch)
tree7d1270c8dc0939956034a7ab1f6cddb45a33ac72 /src/import/chips/p9/procedures/hwp/memory/lib
parent491995a6a3ed6062169c2818c89db7a85da9e448 (diff)
downloadtalos-hostboot-d9bbcfabbc2f041ba85095ac70dc27c37cb87755.tar.gz
talos-hostboot-d9bbcfabbc2f041ba85095ac70dc27c37cb87755.zip
Add missing timing attrs to p9a_eff_config
Change-Id: I0270bec76fa1146c3c74cc125f838f5602b8a5b8 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/78564 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Mark Pizzutillo <mark.pizzutillo@ibm.com> Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/78576 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C24
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.C165
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/timing.H733
3 files changed, 11 insertions, 911 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C
index baac38c30..74e3182ee 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.C
@@ -366,16 +366,6 @@ enum invalid_freq_function_encoding : uint8_t
F0BC6X = 0x60,
};
-///
-/// @brief encoding for MSS_INVALID_TIMING so we can look up functions based on encoding
-///
-enum invalid_timing_function_encoding : uint8_t
-{
- TRRD_S = 0,
- TRRD_L = 1,
- TFAW = 2,
-};
-
/////////////////////////
// Non-member function implementations
/////////////////////////
@@ -4098,7 +4088,7 @@ fapi2::ReturnCode eff_dimm::dram_trrd_s()
l_trrd_s_in_nck);
}
- FAPI_TRY( trrd_s( iv_dimm, iv_dram_width, l_jedec_trrd) );
+ FAPI_TRY( trrd_s( iv_dimm, iv_dram_width, iv_freq, l_jedec_trrd) );
// Taking the worst case between the required minimum JEDEC value and the proposed value from SPD
if (l_jedec_trrd != l_trrd_s_in_nck)
@@ -4174,7 +4164,7 @@ fapi2::ReturnCode eff_dimm::dram_trrd_l()
l_trrd_l_in_nck);
}
- FAPI_TRY( trrd_l( iv_dimm, iv_dram_width, l_jedec_trrd) );
+ FAPI_TRY( trrd_l( iv_dimm, iv_dram_width, iv_freq, l_jedec_trrd) );
// Taking the worst case between the required minimum JEDEC value and the proposed value from SPD
if (l_jedec_trrd != l_trrd_l_in_nck)
@@ -4273,7 +4263,7 @@ fapi2::ReturnCode eff_dimm::dram_tfaw()
l_tfaw_in_nck);
}
- FAPI_TRY( mss::tfaw(iv_dimm, iv_dram_width, l_jedec_tfaw_in_nck), "Failed tfaw()" );
+ FAPI_TRY( mss::tfaw(iv_dimm, iv_dram_width, iv_freq, l_jedec_tfaw_in_nck), "Failed tfaw()" );
// Taking the worst case between the required minimum JEDEC value and the proposed value from SPD
if (l_jedec_tfaw_in_nck != l_tfaw_in_nck)
@@ -4342,11 +4332,15 @@ fapi2::ReturnCode eff_dimm::dram_tras()
// 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(iv_dimm);
+ uint64_t l_tras_in_ps;
+ uint64_t l_freq = 0;
+ uint8_t l_tras_in_nck = 0;
// Calculate nck
std::vector<uint8_t> l_attrs_dram_tras(PORTS_PER_MCS, 0);
- uint8_t l_tras_in_nck = 0;
+
+ FAPI_TRY( freq(mss::find_target<fapi2::TARGET_TYPE_MCBIST>(iv_dimm), l_freq) );
+ l_tras_in_ps = mss::tras(iv_dimm, l_freq);
// 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
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 ebc203f2e..1f2920c7b 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
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -37,167 +37,4 @@
namespace mss
{
-enum temp_mode : uint8_t
-{
- NORMAL = 1,
- EXTENDED = 2,
-};
-
-// Proposed DDR4 Full spec update(79-4B)
-// Item No. 1716.78C
-// pg.46
-// Table 24 - tREFI and tRFC parameters (in ps)
-constexpr uint64_t TREFI_BASE = 7800000;
-
-// Proposed DDR4 3DS Addendum
-// Item No. 1727.58A
-// pg. 69 - 71
-// Table 42 - Refresh parameters by logical rank density
-static const std::vector<std::pair<uint8_t, uint64_t> > TRFC_DLR1 =
-{
- // { density in GBs, tRFC4(min) in picoseconds }
- {4, 90000},
- {8, 120000},
- {16, 185000},
-};
-
-// Proposed DDR4 3DS Addendum
-// Item No. 1727.58A
-// pg. 69 - 71
-// Table 42 - Refresh parameters by logical rank density
-static const std::vector<std::pair<uint8_t, uint64_t> > TRFC_DLR2 =
-{
- // { density in GBs, tRFC4(min) in picoseconds }
- {4, 55000},
- {8, 90000},
- {16, 120000},
-};
-
-// Proposed DDR4 3DS Addendum
-// Item No. 1727.58A
-// pg. 69 - 71
-// Table 42 - Refresh parameters by logical rank density
-static const std::vector<std::pair<uint8_t, uint64_t> > TRFC_DLR4 =
-{
- // { density in GBs, tRFC4(min) in picoseconds }
- {4, 40000},
- {8, 55000},
- {16, 90000},
-};
-
-///
-/// @brief Calculates refresh interval time
-/// @param[in] i_mode fine refresh rate mode
-/// @param[in] i_refresh_request_rate refresh rate
-/// @param[out] o_value timing val in ps
-/// @return fapi2::ReturnCode
-///
-fapi2::ReturnCode calc_trefi( const refresh_rate i_mode,
- const uint8_t i_refresh_request_rate,
- uint64_t& o_timing )
-{
- uint64_t l_refresh_request = 0;
- constexpr double TEN_PERCENT_FASTER = 0.90;
-
- switch(i_refresh_request_rate)
- {
- case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_SINGLE:
- l_refresh_request = TREFI_BASE;
- break;
-
- case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_DOUBLE:
- // We are truncating but there is no remainder with TREFI_BASE, so we are okay
- l_refresh_request = TREFI_BASE / 2;
- break;
-
- case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_SINGLE_10_PERCENT_FASTER:
- // We are truncating but there is no remainder with TREFI_BASE, so we are okay
- // 10% faster so 100% - 10% = 90%
- l_refresh_request = TREFI_BASE * TEN_PERCENT_FASTER;
- break;
-
- case fapi2::ENUM_ATTR_MSS_MRW_REFRESH_RATE_REQUEST_DOUBLE_10_PERCENT_FASTER:
- // We are truncating but there is no remainder with TREFI_BASE, so we are okay
- // 10% faster so 100% - 10% = 90%
- l_refresh_request = (TREFI_BASE / 2) * TEN_PERCENT_FASTER;
- break;
-
- default:
- // Will catch incorrect MRW value set
- FAPI_ASSERT(false,
- fapi2::MSS_INVALID_REFRESH_RATE_REQUEST().set_REFRESH_RATE_REQUEST(i_refresh_request_rate),
- "Incorrect refresh request rate received: %d ", i_refresh_request_rate);
- break;
- }
-
- o_timing = (l_refresh_request / i_mode);
-
- FAPI_INF( "tREFI (ps): %d, refresh request (ps): %d, tREFI_base (ps): %d, REF%dX",
- o_timing, l_refresh_request, TREFI_BASE, i_mode );
-
- // FAPI_ASSERT doesn't set current_err as good
- return fapi2::FAPI2_RC_SUCCESS;
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-/// @brief Calculates Minimum Refresh Recovery Delay Time (different logical rank)
-/// @param[in] i_mode fine refresh rate mode
-/// @param[in] i_density SDRAM density
-/// @param[out] o_trfc_in_ps timing val in ps
-/// @return fapi2::FAPI2_RC_SUCCESS iff okay
-///
-fapi2::ReturnCode calc_trfc_dlr(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const uint8_t i_refresh_mode,
- const uint8_t i_density,
- uint64_t& o_trfc_in_ps)
-{
- bool l_is_val_found = 0;
-
- // Selects appropriate tRFC based on fine refresh mode
- switch(i_refresh_mode)
- {
- case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL:
- l_is_val_found = find_value_from_key(TRFC_DLR1, i_density, o_trfc_in_ps);
- break;
-
- case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X:
- case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X:
- l_is_val_found = find_value_from_key(TRFC_DLR2, i_density, o_trfc_in_ps);
- break;
-
- case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_4X:
- case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_4X:
- l_is_val_found = find_value_from_key(TRFC_DLR4, i_density, o_trfc_in_ps);
- break;
-
- default:
- // Fine Refresh Mode will be a platform attribute set by the MRW,
- // which they "shouldn't" mess up as long as use "attribute" enums.
- // if openpower messes this up we can at least catch it
- FAPI_ASSERT( false,
- fapi2::MSS_INVALID_FINE_REFRESH()
- .set_REFRESH_MODE(i_refresh_mode),
- "Incorrect Fine Refresh Mode received: %d ",
- i_refresh_mode);
- break;
- }// switch
-
- FAPI_ASSERT( l_is_val_found,
- fapi2::MSS_FAILED_TO_FIND_TRFC()
- .set_SDRAM_DENSITY(i_density)
- .set_REFRESH_MODE(i_refresh_mode)
- .set_DIMM_TARGET(i_target),
- "%s: Unable to find tRFC (ps) from map with SDRAM density key %d with %d refresh mode",
- mss::c_str(i_target),
- i_density,
- i_refresh_mode);
-
- // Again, FAPI_ASSERT doesn't set current_err to good, only to bad
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- return fapi2::current_err;
-}
-
}// mss
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 8b8215b96..d748400cb 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
@@ -40,104 +40,13 @@
#include <lib/mss_attribute_accessors.H>
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/dimm/mss_timing.H>
#include <lib/utils/mss_nimbus_conversions.H>
namespace mss
{
///
-/// @brief Enums for ffdc error callout so we know which function had the error
-///
-enum functions
-{
- TRAS = 0,
- TFAW_HALF_KB_PAGE_HELPER = 1,
- TFAW_ONE_KB_PAGE_HELPER = 2,
- TFAW_TW_KB_PAGE_HELPER = 3,
- TFAW_SLR_X4_HELPER = 4,
- TFAW_SLR_X8_HELPER = 5,
- TRRD_S_SLR = 6,
- TRRD_L_SLR = 7,
- TRRD_L_HALF_AND_1KB_PAGE_HELPER = 8,
- TRRD_S_HALF_AND_1KB_PAGE_HELPER = 9,
- TRRD_S_2KB_PAGE_HELPER = 10,
- TDLLK = 11,
-};
-
-enum refresh_rate : uint8_t
-{
- REF1X = 1, ///< Refresh rate 1X
- REF2X = 2, ///< Refresh rate 2X
- REF4X = 4, ///< Refresh rate 4X
-};
-
-namespace spd
-{
-
-///
-/// @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, spd::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)F
-/// @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
@@ -159,30 +68,6 @@ fapi_try_exit:
}
///
-/// @brief Calculates refresh interval time
-/// @param[in] i_mode fine refresh rate mode
-/// @param[in] i_temp_refresh_range temperature refresh range
-/// @param[out] o_value timing val in ps
-/// @return fapi2::ReturnCode
-///
-fapi2::ReturnCode calc_trefi( const refresh_rate i_mode,
- const uint8_t i_temp_refresh_range,
- uint64_t& o_timing );
-
-///
-/// @brief Calculates Minimum Refresh Recovery Delay Time (different logical rank)
-/// @param[in] i_target a target for attributes
-/// @param[in] i_mode fine refresh rate mode
-/// @param[in] i_density SDRAM density
-/// @param[out] o_trfc_in_ps timing val in ps
-/// @return fapi2::FAPI2_RC_SUCCESS iff okay
-///
-fapi2::ReturnCode calc_trfc_dlr( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const uint8_t i_refresh_mode,
- const uint8_t i_density,
- uint64_t& o_trfc_in_ps );
-
-///
/// @brief DLL locking time *in clocks*
/// @tparam T the fapi2::TargetType of i_target
/// @tparam OT the type of the output location
@@ -582,602 +467,6 @@ fapi_try_exit:
}
///
-/// @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
-/// @param[in] i_target the fapi2 target
-/// @return value in picoseconds
-///
-inline uint64_t tras(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& 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_ASSERT( false,
- fapi2::MSS_INVALID_FREQ_PASSED_IN()
- .set_FREQ(l_freq)
- .set_FUNCTION(TRAS)
- .set_DIMM_TARGET(i_target),
- "%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_ASSERT( false,
- fapi2::MSS_INVALID_FREQ_PASSED_IN()
- .set_FREQ(l_freq)
- .set_FUNCTION(TFAW_HALF_KB_PAGE_HELPER)
- .set_DIMM_TARGET(i_target),
- "%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_ASSERT( false,
- fapi2::MSS_INVALID_FREQ_PASSED_IN()
- .set_FREQ(l_freq)
- .set_FUNCTION(TFAW_ONE_KB_PAGE_HELPER)
- .set_DIMM_TARGET(i_target),
- "%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_ASSERT( false,
- fapi2::MSS_INVALID_FREQ_PASSED_IN()
- .set_FREQ(l_freq)
- .set_FUNCTION(TFAW_TW_KB_PAGE_HELPER)
- .set_DIMM_TARGET(i_target),
- "%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_ASSERT( false,
- fapi2::MSS_INVALID_DRAM_WIDTH()
- .set_DRAM_WIDTH(i_dram_width)
- .set_DIMM_TARGET(i_target),
- "Invalid DRAM width with %d for target %s",
- i_dram_width,
- mss::c_str(i_target));
- break;
- }
-
-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 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_ASSERT( false,
- fapi2::MSS_INVALID_FREQ_PASSED_IN()
- .set_FREQ(l_freq)
- .set_FUNCTION(TRRD_L_HALF_AND_1KB_PAGE_HELPER)
- .set_DIMM_TARGET(i_target),
- "%s Invalid frequency %lu",
- mss::c_str(i_target),
- l_freq);
- }
-
- return fapi2::FAPI2_RC_SUCCESS;
-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), "Error calculating trrd l for half and 1kb page" );
- break;
-
- case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
- FAPI_TRY( trrd_l_2kb_page_helper(i_target, o_tRRD_L) );
- break;
-
- default:
- FAPI_ASSERT( false,
- fapi2::MSS_INVALID_PAGE_SIZE()
- .set_DRAM_WIDTH(i_dram_width)
- .set_DIMM_TARGET(i_target),
- "%s Recieved an invalid page size: %lu",
- mss::c_str(i_target),
- i_dram_width);
- break;
- }
-
- return fapi2::FAPI2_RC_SUCCESS;
-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::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:
- o_output = std::max( 4, spd::ps_to_nck(i_target, 3000) );
- break;
-
- default:
- FAPI_ASSERT( false,
- fapi2::MSS_INVALID_FREQ_PASSED_IN()
- .set_FREQ(l_freq)
- .set_FUNCTION(TRRD_S_HALF_AND_1KB_PAGE_HELPER)
- .set_DIMM_TARGET(i_target),
- "%s Invalid frequency %lu",
- mss::c_str(i_target),
- l_freq);
- }
-
- return fapi2::FAPI2_RC_SUCCESS;
-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_ASSERT( false,
- fapi2::MSS_INVALID_FREQ_PASSED_IN()
- .set_FREQ(l_freq)
- .set_FUNCTION(TRRD_S_2KB_PAGE_HELPER)
- .set_DIMM_TARGET(i_target),
- "%s Invalid frequency %lu",
- mss::c_str(i_target),
- l_freq);
- break;
- }
-
- return fapi2::FAPI2_RC_SUCCESS;
-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), "Error calculating trrd_s for half and 1kb page" );
- break;
-
- case fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16:
- FAPI_TRY( trrd_s_2kb_page_helper(i_target, o_tRRD_S) );
- break;
-
- default:
- FAPI_ASSERT( false,
- fapi2::MSS_INVALID_PAGE_SIZE()
- .set_DRAM_WIDTH(i_dram_width)
- .set_DIMM_TARGET(i_target),
- "%s Recieved an invalid page size: %lu",
- mss::c_str(i_target),
- i_dram_width);
- break;
- }
-
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
/// @brief VREF DQ Enter time *in clocks*
/// @tparam T the fapi2::TargetType of i_target
/// @param[in] i_target a target for attributes
@@ -1215,25 +504,5 @@ constexpr uint64_t tccd_s()
return 4;
}
-namespace lrdimm
-{
-
-///
-/// @brief Return the VREF to VREF change time long
-/// @tparam fapi2::TargetType T - type of the target on which to operate
-/// @param[in] i_target the fapi2 target
-/// @return value in clocks
-/// @note VREF time change long is used for changing by more than one VREF tick
-///
-template< fapi2::TargetType T >
-inline uint64_t vref_time_long(const fapi2::Target<T>& i_target)
-{
- // Taken from the LRDIMM spec
- constexpr uint64_t VREF_TIME_LONG_NS = 500;
- return mss::spd::ns_to_nck(i_target, VREF_TIME_LONG_NS);
-}
-
-} // ns lrdimm
-
} // mss
#endif
OpenPOWER on IntegriCloud