summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/spd/spd_checker.H
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/generic/memory/lib/spd/spd_checker.H')
-rw-r--r--src/import/generic/memory/lib/spd/spd_checker.H282
1 files changed, 218 insertions, 64 deletions
diff --git a/src/import/generic/memory/lib/spd/spd_checker.H b/src/import/generic/memory/lib/spd/spd_checker.H
index d3a85aaa4..a26ac4741 100644
--- a/src/import/generic/memory/lib/spd/spd_checker.H
+++ b/src/import/generic/memory/lib/spd/spd_checker.H
@@ -23,42 +23,130 @@
/* */
/* IBM_PROLOG_END_TAG */
+///
+/// @file spd_checker.H
+/// @brief SPD functions to check boundaries
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
#ifndef _SPD_CHECKER_H_
#define _SPD_CHECKER_H_
#include <fapi2.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
namespace mss
{
-namespace check
+
+///
+/// @brief Selectors for timing limits
+/// @note BITS12 stands for a 12 bit range
+/// @note BITS16 stands for a 16 bit range
+///
+enum bit_len
+{
+ BITS12 = 12,
+ BITS16 = 16,
+};
+
+///
+/// @class bitRangeTraits
+/// @brief Traits class to select
+/// @tparam T bit_len selector
+///
+template <bit_len T>
+struct bitRangeTraits;
+
+///
+/// @class bitRangeTraits
+/// @brief Traits class to select - BITS12 specialization
+///
+template<>
+struct bitRangeTraits<BITS12>
+{
+ enum
+ {
+ LOWER_BOUND = 0x1,
+ UPPER_BOUND = 0xfff,
+ };
+};
+
+///
+/// @class bitRangeTraits
+/// @brief Traits class to select - BITS16 specialization
+///
+template<>
+struct bitRangeTraits<BITS16>
{
+ enum
+ {
+ LOWER_BOUND = 0x1,
+ UPPER_BOUND = 0xffff,
+ };
+};
+
namespace spd
{
+namespace check
+{
+
+///
+/// @brief SPD timing boundary check
+/// @tparam BL bit_len selector
+/// @tparam T the TargetType
+/// @tparam TT defaulted to bitRangeTraits<TB>
+/// @param[in] i_target fapi2 target
+/// @param[in] i_timing the timing value
+/// @param[in] i_ffdc ffdc function code
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < bit_len BL, fapi2::TargetType T, typename TT = bitRangeTraits<BL> >
+fapi2::ReturnCode max_timing_range(const fapi2::Target<T>& i_target,
+ const int64_t i_timing,
+ const generic_ffdc_codes i_ffdc)
+{
+ FAPI_ASSERT( (i_timing <= TT::UPPER_BOUND) &&
+ (i_timing >= TT::LOWER_BOUND),
+ fapi2::MSS_SPD_TIMING_FAIL()
+ .set_FUNCTION_CODE(i_ffdc)
+ .set_TARGET(i_target),
+ "Failed timing parameter check for %s",
+ spd::c_str(i_target));
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
///
-/// @brief Checks conditional passes and implements traces & exits if it fails
-/// @tparam T input data of any size
-/// @param[in] i_target fapi2 dimm target
-/// @param[in] i_conditional conditional that we are testing against
-/// @param[in] i_spd_byte_index current SPD byte
-/// @param[in] i_spd_data debug data
-/// @param[in] i_err_str error string to print out when conditional fails
-/// @return ReturnCode
+/// @brief Checks conditional passes and implements traces & exits if it fails
+/// @tparam T input data of any size
+/// @param[in] i_target fapi2 dimm target
+/// @param[in] i_conditional conditional that we are testing against
+/// @param[in] i_spd_byte_index current SPD byte
+/// @param[in] i_spd_data debug data
+/// @param[in] i_err_str error string to print out when conditional fails
+/// @return FAPI2_RC_SUCCESS iff okay
///
template< typename T >
inline fapi2::ReturnCode fail_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
const bool i_conditional,
const size_t i_spd_byte_index,
const T i_spd_data,
- const char* i_err_str)
+ const char* i_err_str = "")
{
FAPI_ASSERT(i_conditional,
fapi2::MSS_BAD_SPD().
set_VALUE(i_spd_data).
set_BYTE(i_spd_byte_index).
set_DIMM_TARGET(i_target),
- "%s %s Byte %d, Data returned: %d.",
- c_str(i_target),
+ "%s %s Byte %d, data 0x%02x, extracted value: 0x%02x.",
+ spd::c_str(i_target),
i_err_str,
i_spd_byte_index,
i_spd_data);
@@ -67,70 +155,136 @@ inline fapi2::ReturnCode fail_for_invalid_value(const fapi2::Target<fapi2::TARGE
fapi_try_exit:
return fapi2::current_err;
-} // fail_for_invalid_value()
+} // fail_for_invalid_value
///
-/// @brief Checks conditional passes and implements traces if it fails. No FFDC collected.
-/// @tparam T input data of any size
-/// @param[in] i_target fapi2 dimm target
-/// @param[in] i_conditional that we are testing against
-/// @param[in] i_spd_byte_index
-/// @param[in] i_spd_data debug data
-/// @param[in] i_err_str string to print out when conditional fails
-/// @return void
+/// @brief Helper function to test if a DRAM generation is valid
+/// @param[in] i_dram_gen the DRAM gen from SPD
+/// @return true if this DRAM gen is valid, else false
///
-template< typename T >
-inline void warn_for_invalid_value(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const bool i_conditional,
- const size_t i_spd_byte_index,
- const T i_spd_data,
- const char* i_err_str)
+static inline bool is_dram_gen_valid(const uint8_t i_dram_gen)
+{
+ bool l_result = false;
+
+ switch(i_dram_gen)
+ {
+ case DDR4:
+ l_result = true;
+ break;
+
+ default:
+ l_result = false;
+ break;
+ }
+
+ return l_result;
+}
+
+///
+/// @brief Checks for valid DRAM generation
+/// @param[in] i_target the DIMM target
+/// @param[in] i_dram_gen the DRAM gen from SPD
+/// @param[in] i_func_code mss ffdc code
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+inline fapi2::ReturnCode dram_gen(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_dram_gen,
+ const generic_ffdc_codes i_func_code)
+{
+ FAPI_ASSERT(is_dram_gen_valid(i_dram_gen),
+ fapi2::MSS_INVALID_DRAM_GEN()
+ .set_DRAM_GEN(i_dram_gen)
+ .set_FUNCTION(i_func_code)
+ .set_DIMM_TARGET(i_target),
+ "Invalid DRAM gen recieved (%d) for %s",
+ i_dram_gen, spd::c_str(i_target));
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to test if a DIMM type is valid
+/// @param[in] i_dimm_type the DIMM type from SPD
+/// @return true if this DIMM type is valid, else false
+///
+static inline bool is_dimm_type_valid(const uint8_t i_dimm_type)
{
- // Don't print warning conditional if true
- if(!i_conditional)
+ bool l_result = false;
+
+ switch(i_dimm_type)
{
- FAPI_IMP("%s. %s. Byte %d, Data returned: %d.",
- c_str(i_target),
- i_err_str,
- i_spd_byte_index,
- i_spd_data );
+ case RDIMM:
+ case LRDIMM:
+ l_result = true;
+ break;
+
+ default:
+ l_result = false;
+ break;
}
-}// warn_for_invalid_value
-
-///
-/// @brief Checks if valid factory parameters are given
-/// @param[in] i_target fapi2 dimm target
-/// @param[in] i_dimm_type DIMM type enumeration
-/// @param[in] i_encoding_rev SPD encoding level rev number
-/// @param[in] i_additions_rev SPD additions level rev number
-/// @param[in] i_err_str string to print out when conditional fails
-/// @return fapi2::ReturnCode
-///
-inline fapi2::ReturnCode invalid_factory_sel(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const uint8_t i_dimm_type,
- const uint8_t i_encoding_rev,
- const uint8_t i_additions_rev,
- const char* i_err_str)
+
+ return l_result;
+}
+
+///
+/// @brief Checks for valid DIMM type
+/// @param[in] i_target the DIMM target
+/// @param[in] i_dram_gen the DIMM type from SPD
+/// @param[in] i_func_code mss ffdc code
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+inline fapi2::ReturnCode dimm_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const uint8_t i_dimm_type,
+ const generic_ffdc_codes i_func_code)
{
- FAPI_ASSERT(false,
- fapi2::MSS_INVALID_DIMM_REV_COMBO().
- set_DIMM_TYPE(i_dimm_type).
- set_ENCODING_REV(i_encoding_rev).
- set_ADDITIONS_REV(i_additions_rev).
- set_DIMM_TARGET(i_target),
- "%s. %s. Invalid combination for dimm type: %d, rev: %d.%d",
- c_str(i_target),
- i_err_str,
- i_dimm_type,
- i_encoding_rev,
- i_additions_rev);
+ FAPI_ASSERT(is_dimm_type_valid(i_dimm_type),
+ fapi2::MSS_INVALID_DIMM_TYPE()
+ .set_DIMM_TYPE(i_dimm_type)
+ .set_FUNCTION(i_func_code)
+ .set_DIMM_TARGET(i_target),
+ "Invalid DIMM type recieved (%d) for %s",
+ i_dimm_type, spd::c_str(i_target));
+
return fapi2::FAPI2_RC_SUCCESS;
+
fapi_try_exit:
return fapi2::current_err;
-}// invalid_factory_sel
+}
+
+///
+/// @brief Helper function to check for reserved values
+/// @tparam TT FAPI2 target type
+/// @param[in] i_target the fapi2 target
+/// @param[in] i_reserved_bits vector of SORTED reserved bits to sort through
+/// @param[in] i_ffdc ffdc function code
+/// @param[in] i_input value to check
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < fapi2::TargetType TT >
+inline fapi2::ReturnCode reserved_values(const fapi2::Target<TT>& i_target,
+ const std::vector<uint8_t>& i_reserved_bits,
+ const generic_ffdc_codes i_ffdc,
+ const uint8_t i_input)
+{
+ // Lets make an additional check that we aren't being set to a reserved field
+ FAPI_ASSERT( !std::binary_search(i_reserved_bits.begin(), i_reserved_bits.end(), i_input),
+ fapi2::MSS_INVALID_SPD_RESERVED_BITS()
+ .set_FUNCTION_CODE(i_ffdc)
+ .set_TARGET(i_target),
+ "Reserved bits seen on %s",
+ spd::c_str(i_target) );
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
-}// spd
}// check
+}// spd
}// mss
#endif
OpenPOWER on IntegriCloud