diff options
Diffstat (limited to 'src/import/chips/p9/procedures/hwp')
21 files changed, 1103 insertions, 1649 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 f8d7cfc7c..4e52d5083 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 @@ -22,8 +22,8 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com> -// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com> +// *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: FSP:HB @@ -37,8 +37,6 @@ // mss lib #include <lib/utils/fake_vpd.H> #include <lib/mss_vpd_decoder.H> -#include <lib/spd/spd_factory.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> #include <generic/memory/lib/spd/common/rcw_settings.H> #include <lib/eff_config/timing.H> #include <lib/dimm/ddr4/mrs_load_ddr4.H> @@ -48,9 +46,9 @@ #include <lib/dimm/eff_dimm.H> #include <lib/dimm/mrs_load.H> #include <lib/shared/mss_kind.H> -#include <generic/memory/lib/spd/common/dimm_module_decoder.H> #include <lib/phy/dp16.H> #include <lib/mss_attribute_accessors_manual.H> +#include <endian.h> namespace mss { @@ -60,6 +58,147 @@ using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCBIST; +// +// Note SPD mappings included are settings only supported by Nimbus. +// We purposely omit certain settings that exist in the JEDEC SPD spec +// if they are not supported in HW. This simplifies error catching and +// explicitly depicts supported mappings. +// + +// ========================================================= +// Byte 4 maps +// Item JC-45-2220.01x +// Page 18 +// DDR4 SPD Document Release 3 +// Byte 4 (0x004): SDRAM Density and Banks +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::SDRAM_DENSITY_MAP = +{ + // {key byte, capacity in GBs} + {4, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_4G}, + {5, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_8G}, + {6, fapi2::ENUM_ATTR_EFF_DRAM_DENSITY_16G}, +}; + +// ========================================================= +// Byte 4 maps +// Item JC-45-2220.01x +// Page 18 +// DDR4 SPD Document Release 3 +// Byte 4 (0x004): SDRAM Density and Banks +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > eff_dimm::BANK_ADDR_BITS_MAP = +{ + // {key byte, number of bank address bits} + {0, 2}, + {1, 3} +}; + +// ========================================================= +// Byte 5 maps +// Item JC-45-2220.01x +// Page 18 +// DDR4 SPD Document Release 3 +// Byte 5 (0x005): SDRAM Addressing +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::ROW_ADDRESS_BITS_MAP = +{ + //{key byte,row address bits} + {2, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM14}, + {3, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM15}, + {4, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM16}, + {5, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM17}, + {6, fapi2::ENUM_ATTR_EFF_DRAM_ROW_BITS_NUM18} +}; + +// ========================================================= +// Byte 6 maps +// Item JC-45-2220.01x +// Page 19 +// DDR4 SPD Document Release 3 +// Byte 6 (0x006): Primary SDRAM Package Type +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::PRIM_DIE_COUNT_MAP = +{ + // {key byte, number of die} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + {5, 6}, + {6, 7}, + {7, 8} +}; + +// ========================================================= +// Byte 9 maps +// Item JC-45-2220.01x +// Page 21 +// DDR4 SPD Document Release 3 +// Byte 9 (0x009): Other SDRAM Optional Features +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::SOFT_PPR_MAP = +{ + // {key byte, value } + {0, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED}, + {1, fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED} +}; + +// ========================================================= +// Byte 10 maps +// Item JC-45-2220.01x +// Page 21-22 +// DDR4 SPD Document Release 3 +// Byte 10 (0x00A): Secondary SDRAM Package Type +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::SEC_DIE_COUNT_MAP = +{ + // {key byte, number of die} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + {5, 6}, + {6, 7}, + {7, 8} +}; + +// ========================================================= +// Byte 12 maps +// Item JC-45-2220.01x +// Page 23 +// DDR4 SPD Document Release 3 +// Byte 12 (0x00C): Module Organization +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::DEVICE_WIDTH_MAP = +{ + // {key byte, device width (bits)} + {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 +}; + +// ========================================================= +// Byte 13 maps +// Item JC-45-2220.01x +// Page 27 +// DDR4 SPD Document Release 3 +// Byte 13 (0x00D): Module Memory Bus Width +// ========================================================= +const std::vector<std::pair<uint8_t, uint8_t> > eff_dimm::BUS_WIDTH_MAP = +{ + // {key byte, bus width (in bits) + {0, 8}, + {1, 16}, + {2, 32}, + {3, 64} + // All others reserved +}; + /// /// @brief bit encodings for RC02 /// From DDR4 Register v1.0 @@ -141,7 +280,7 @@ enum rc0d_encode : uint8_t /// @brief bit encodings for RC0E /// From DDR4 Register v1.0 /// -enum rc0e_encode +enum rc0e_encode : uint8_t { RC0E_PARITY_ENABLE_BIT = 7, RC0E_PARITY_ENABLE = 1, @@ -204,7 +343,7 @@ enum lrdimm_databuffers /// /// @brief encoding for MSS_INVALID_FREQ so we can look up functions based on encoding /// -enum invalid_freq_function_encoding +enum invalid_freq_function_encoding : uint8_t { RC0A = 0x0a, RC3X = 0x30, @@ -214,17 +353,124 @@ enum invalid_freq_function_encoding /// /// @brief encoding for MSS_INVALID_TIMING so we can look up functions based on encoding /// -enum invalid_timing_function_encoding +enum invalid_timing_function_encoding : uint8_t { TRRD_S = 0, TRRD_L = 1, TFAW = 2, }; + ///////////////////////// // Non-member function implementations ///////////////////////// /// +/// @brief Helper function to calculate logical ranks +/// @param[in] i_signal_loading signal loading from SPD +/// @param[in] i_dram_die_count DRAM die count from SPD +/// @param[in] i_master_ranks number of master ranks from SPD +/// +static uint8_t calc_logical_ranks(const uint8_t i_signal_loading, + const uint8_t i_dram_die_count, + const uint8_t i_master_ranks) +{ + // For single-load-stack(3DS) the logical ranks per package ends up being the same as the die count. + // For MONOLITHIC & MULTI_LOAD_STACK + // The die count isn't guaranteed to be 1 (e.g. SDP - 1 die package, DDP - 2 die package). + // Value of 1 has no meaning and is used for calculation purposes as defined by the SPD spec. + const uint8_t l_multiplier = (i_signal_loading == spd::SINGLE_LOAD_STACK) ? i_dram_die_count : 1; + + return (i_master_ranks * l_multiplier); +} + +/// +/// @brief Returns logical ranks in Primary SDRAM type +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::prim_sdram_logical_ranks( uint8_t& o_logical_ranks ) const +{ + uint8_t l_signal_loading = 0; + uint8_t l_master_ranks = 0; + + // Number of master ranks taken from attribute since we need mapped value + // and not the encoded raw value from SPD. + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(iv_dimm, l_master_ranks) ); + FAPI_TRY( iv_spd_decoder.prim_sdram_signal_loading(l_signal_loading) ); + + o_logical_ranks = calc_logical_ranks(l_signal_loading, iv_dram_die_count, l_master_ranks); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function that returns logical ranks in SDRAM type +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::sec_sdram_logical_ranks( uint8_t& o_logical_ranks ) const +{ + uint8_t l_signal_loading = 0; + uint8_t l_master_ranks = 0; + uint8_t l_spd_die_count = 0; + uint8_t l_die_count = 0; + + // Grabbing signal loading + FAPI_TRY( iv_spd_decoder.sec_sdram_signal_loading(l_signal_loading) ); + + // Number of master ranks taken from attribute since we need mapped value + // and not the encoded raw value from SPD. + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(iv_dimm, l_master_ranks) ); + + // Getting die count + FAPI_TRY( iv_spd_decoder.sec_sdram_die_count(l_spd_die_count) ); + + FAPI_ASSERT( mss::find_value_from_key(SEC_DIE_COUNT_MAP, l_spd_die_count, l_die_count), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_die_count) + .set_DATA(l_die_count) + .set_TARGET(iv_dimm), + "Could not a mapped value that matched the key (%d) for %s", + l_spd_die_count, mss::c_str(iv_dimm) ); + + o_logical_ranks = calc_logical_ranks(l_signal_loading, l_die_count, l_master_ranks); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Returns logical ranks per DIMM +/// @param[out] o_logical_ranks number of logical ranks +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const +{ + uint8_t l_prim_logical_rank_per_dimm = 0; + uint8_t l_rank_mix = 0; + + FAPI_TRY( iv_spd_decoder.rank_mix(l_rank_mix) ); + FAPI_TRY( prim_sdram_logical_ranks(l_prim_logical_rank_per_dimm) ); + + if(l_rank_mix == fapi2::ENUM_ATTR_EFF_DRAM_RANK_MIX_SYMMETRICAL) + { + o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm; + } + else + { + // Rank mix is ASYMMETRICAL + uint8_t l_sec_logical_rank_per_dimm = 0; + FAPI_TRY( sec_sdram_logical_ranks(l_sec_logical_rank_per_dimm) ); + + o_logical_rank_per_dimm = l_prim_logical_rank_per_dimm + l_sec_logical_rank_per_dimm; + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// /// @brief Gets the JEDEC train and range values from the encoded VPD value /// @param[in] i_target - the DIMM target on which to operate /// @param[out] o_range - the JEDEC VREFDQ range @@ -293,28 +539,105 @@ static uint64_t ibt_helper(const uint8_t i_ibt) } /// +/// @brief Helper function to set dram width instance variable +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::set_dram_width_instance() +{ + uint8_t l_spd_device_width = 0; + FAPI_TRY( iv_spd_decoder.device_width(l_spd_device_width), + "Failed accessing device width from SPD %s", mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(DEVICE_WIDTH_MAP, l_spd_device_width, iv_dram_width), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_device_width) + .set_DATA(iv_dram_width) + .set_FUNCTION(SET_DRAM_WIDTH_INSTANCE) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_device_width, mss::c_str(iv_dimm) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to set dram density instance variable +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::set_dram_density_instance() +{ + uint8_t l_spd_dram_density = 0; + FAPI_TRY( iv_spd_decoder.sdram_density(l_spd_dram_density), "Failed to get dram_density from SPD %s", + mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(SDRAM_DENSITY_MAP, l_spd_dram_density, iv_dram_density), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_dram_density) + .set_DATA(iv_dram_density) + .set_FUNCTION(SET_DRAM_DENSITY_INSTANCE) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_dram_density, mss::c_str(iv_dimm) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Helper function to set dram density instance variable +/// @return fapi2::FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode eff_dimm::set_prim_dram_die_count_instance() +{ + uint8_t l_decoder_val = 0; + FAPI_TRY( iv_spd_decoder.prim_sdram_die_count(l_decoder_val), + "Failed to get the die count for the dimm %s", mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(PRIM_DIE_COUNT_MAP, l_decoder_val, iv_dram_die_count), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_decoder_val) + .set_DATA(iv_dram_die_count) + .set_FUNCTION(PRIM_DIE_COUNT) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_decoder_val, mss::c_str(iv_dimm) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} +/// /// @brief factory to make an eff_config DIMM object based on dimm kind (type, gen, and revision number) -/// @param[in] i_pDecoder the spd::decoder for the dimm target +/// @param[in] i_spd_decoder the spd::decoder for the dimm target /// @param[out] o_fact_obj a shared pointer of the eff_dimm type /// -fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decoder>& i_pDecoder, - std::shared_ptr<eff_dimm>& o_fact_obj ) +fapi2::ReturnCode eff_dimm::factory ( const spd::facade& i_spd_decoder, + std::shared_ptr<eff_dimm>& o_fact_obj ) { uint8_t l_type = 0; uint8_t l_gen = 0; uint8_t l_buffer_type = 0; kind_t l_dimm_kind = DEFAULT_KIND; + rcw_settings l_raw_card; fapi2::ReturnCode l_rc; - const auto& l_dimm = i_pDecoder->iv_target; + const auto l_dimm = i_spd_decoder.get_dimm_target(); // Now time to get the three attributes to tell which dimm we're working with. - // Dram_gen and dimm_type are set in the SPD factory and we'll call the SPD decoder to get the reg and buff type - FAPI_TRY( eff_dram_gen(l_dimm, l_gen), "Failed eff_dram_gen() accessor for %s", l_dimm ); - FAPI_TRY( eff_dimm_type(l_dimm, l_type), "Failed eff_dimm_type() accessor for %s", - l_dimm ); - FAPI_TRY( i_pDecoder->iv_module_decoder->register_and_buffer_type(l_buffer_type), - "Failed decoding register and buffer type from SPD for %s", l_dimm ); + // Dram_gen and dimm_type are set in mss_freq and we'll call the SPD decoder to get the reg and buff type + FAPI_TRY( eff_dram_gen(l_dimm, l_gen), "Failed eff_dram_gen() accessor for %s", mss::c_str(l_dimm) ); + FAPI_TRY( eff_dimm_type(l_dimm, l_type), "Failed eff_dimm_type() accessor for %s", mss::c_str(l_dimm) ); + + FAPI_TRY( i_spd_decoder.register_and_buffer_type(l_buffer_type), + "Failed decoding register and buffer type from SPD for %s", mss::c_str(l_dimm) ); + + FAPI_TRY(raw_card_factory(l_dimm, i_spd_decoder, l_raw_card)); l_dimm_kind = mss::dimm_kind(l_type, l_gen); @@ -324,7 +647,7 @@ fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decode switch (l_buffer_type) { case LRDIMM_DB01: - o_fact_obj = std::make_shared<eff_lrdimm_db01>( i_pDecoder, l_rc ); + o_fact_obj = std::make_shared<eff_lrdimm_db01>( i_spd_decoder, l_raw_card, l_rc ); // Assert that l_rc is good and o_fact_object isn't null FAPI_ASSERT( ((l_rc == fapi2::FAPI2_RC_SUCCESS) && (o_fact_obj != nullptr)), @@ -339,7 +662,7 @@ fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decode break; case LRDIMM_DB02: - o_fact_obj = std::make_shared<eff_lrdimm_db02>( i_pDecoder, l_rc ); + o_fact_obj = std::make_shared<eff_lrdimm_db02>( i_spd_decoder, l_raw_card, l_rc ); // Assert that l_rc is good and o_fact_object isn't null FAPI_ASSERT( ((l_rc == fapi2::FAPI2_RC_SUCCESS) && (o_fact_obj != nullptr)), @@ -367,7 +690,7 @@ fapi2::ReturnCode eff_dimm::eff_dimm_factory ( const std::shared_ptr<spd::decode break; case KIND_RDIMM_DDR4: - o_fact_obj = std::make_shared<eff_rdimm>( i_pDecoder, l_rc ); + o_fact_obj = std::make_shared<eff_rdimm>( i_spd_decoder, l_raw_card, l_rc ); // Assert that l_rc is good and o_fact_object isn't null FAPI_ASSERT( ((l_rc == fapi2::FAPI2_RC_SUCCESS) && (o_fact_obj != nullptr)), fapi2::MSS_ERROR_CREATING_EFF_CONFIG_DIMM_OBJECT(). @@ -410,7 +733,8 @@ fapi2::ReturnCode eff_dimm::rcd_mfg_id() // Get & update MCS attribute FAPI_TRY( eff_rcd_mfg_id(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_EFF_RCD_MFG_ID" ); - FAPI_TRY( iv_pDecoder->reg_manufacturer_id_code(l_decoder_val), "Failed getting rcd id code from SPD %s", + FAPI_TRY( iv_spd_decoder.reg_manufacturer_id_code(l_decoder_val), + "Failed getting rcd id code from SPD %s", mss::c_str(iv_dimm) ); switch (l_decoder_val) @@ -451,7 +775,7 @@ fapi2::ReturnCode eff_dimm::register_type() // Get & update MCS attribute FAPI_TRY( eff_register_type(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_REGISTER_TYPE" ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->register_and_buffer_type(l_decoder_val), + FAPI_TRY( iv_spd_decoder.register_and_buffer_type(l_decoder_val), "Failed getting register_type code from SPD %s", mss::c_str(iv_dimm) ); @@ -475,7 +799,8 @@ fapi2::ReturnCode eff_dimm::register_rev() // Get & update MCS attribute FAPI_TRY( eff_register_rev(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_REGISTER_REV" ); - FAPI_TRY( iv_pDecoder->register_rev_num(l_decoder_val), "Failed getting register_rev code from SPD %s", + FAPI_TRY( iv_spd_decoder.register_rev_num(l_decoder_val), + "Failed getting register_rev code from SPD %s", mss::c_str(iv_dimm) ); FAPI_INF("%s Register rev is 0x%02x", mss::c_str(iv_dimm), l_decoder_val); @@ -498,9 +823,11 @@ fapi2::ReturnCode eff_dimm::dram_mfg_id() // Get & update MCS attribute FAPI_TRY( eff_dram_mfg_id(iv_mcs, &l_mcs_attrs[0][0]), "Failed accessing ATTR_MSS_EFF_DRAM_MFG_ID" ); - FAPI_TRY( iv_pDecoder->dram_manufacturer_id_code(l_decoder_val), "Failed getting dram id code from SPD %s", + FAPI_TRY( iv_spd_decoder.dram_manufacturer_id_code(l_decoder_val), "Failed getting dram id code from SPD %s", mss::c_str(iv_dimm) ); + endian_swap(l_decoder_val); + switch (l_decoder_val) { case fapi2::ENUM_ATTR_EFF_DRAM_MFG_ID_MICRON: @@ -534,24 +861,12 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dram_width() { - uint8_t l_decoder_val = 0; uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; // Get & update MCS attribute - FAPI_TRY( iv_pDecoder->device_width(l_decoder_val), "Failed accessing device width from SPD %s", mss::c_str(iv_dimm) ); FAPI_TRY( eff_dram_width(iv_mcs, &l_mcs_attrs[0][0]), "Failed getting EFF_DRAM_WIDTH" ); - // Enforcing NIMBUS restrictions - FAPI_ASSERT( (l_decoder_val == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) || - (l_decoder_val == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4), - fapi2::MSS_INVALID_DRAM_WIDTH() - .set_DRAM_WIDTH(l_decoder_val) - .set_DIMM_TARGET(iv_dimm), - "Unsupported DRAM width with %d for target %s", - l_decoder_val, - mss::c_str(iv_dimm)); - - l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; + l_mcs_attrs[iv_port_index][iv_dimm_index] = iv_dram_width; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WIDTH, iv_mcs, l_mcs_attrs), "Failed setting ATTR_EFF_DRAM_WIDTH" ); fapi_try_exit: @@ -564,17 +879,12 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dram_density() { - uint8_t l_decoder_val = 0; - FAPI_TRY( iv_pDecoder->sdram_density(l_decoder_val), "Failed to get dram_density from SPD %s", mss::c_str(iv_dimm) ); - // Get & update MCS attribute - { - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dram_density(iv_mcs, &l_mcs_attrs[0][0]), "Failed to get ATTR_MSS_EFF_DRAM_DENSITY" ); + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dram_density(iv_mcs, &l_mcs_attrs[0][0]), "Failed to get ATTR_MSS_EFF_DRAM_DENSITY" ); - l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DENSITY, iv_mcs, l_mcs_attrs), "Failed to set ATTR_EFF_DRAM_DENSITY" ); - } + l_mcs_attrs[iv_port_index][iv_dimm_index] = iv_dram_density; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DENSITY, iv_mcs, l_mcs_attrs), "Failed to set ATTR_EFF_DRAM_DENSITY" ); fapi_try_exit: return fapi2::current_err; @@ -591,8 +901,8 @@ fapi2::ReturnCode eff_dimm::ranks_per_dimm() // Get & update MCS attribute FAPI_TRY( eff_num_ranks_per_dimm(iv_mcs, &l_attrs_ranks_per_dimm[0][0]), "Failed to get EFF_NUM_RANKS_PER_DIMM" ); - FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(l_ranks_per_dimm), - "Failed to get logical_ranks_per_dimm from SPD %s", mss::c_str(iv_dimm) ); + FAPI_TRY( logical_ranks_per_dimm(l_ranks_per_dimm), + "Failed to get logical_ranks_per_dimm %s", mss::c_str(iv_dimm) ); l_attrs_ranks_per_dimm[iv_port_index][iv_dimm_index] = l_ranks_per_dimm; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_RANKS_PER_DIMM, iv_mcs, l_attrs_ranks_per_dimm), @@ -608,15 +918,12 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::prim_die_count() { - uint8_t l_die_count = 0; uint8_t l_attr[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; // Get & update MCS attribute FAPI_TRY( eff_prim_die_count(iv_mcs, &l_attr[0][0]), "Failed to get EFF_PRIM_DIE_COUNT" ); - FAPI_TRY( iv_pDecoder->prim_sdram_die_count(l_die_count), - "Failed to get the die count for the dimm %s", mss::c_str(iv_dimm) ); - l_attr[iv_port_index][iv_dimm_index] = l_die_count; + l_attr[iv_port_index][iv_dimm_index] = iv_dram_die_count; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PRIM_DIE_COUNT, iv_mcs, l_attr), "Failed to set ATTR_EFF_PRIM_DIE_COUNT" ); @@ -633,9 +940,9 @@ fapi2::ReturnCode eff_dimm::primary_stack_type() uint8_t l_stack_type = 0; uint8_t l_package_type = 0; - FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(l_stack_type), + FAPI_TRY( iv_spd_decoder.prim_sdram_signal_loading(l_stack_type), "Failed to get dram_signal_loading from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->prim_sdram_package_type(l_package_type), + FAPI_TRY( iv_spd_decoder.prim_sdram_package_type(l_package_type), "Failed to get prim_sdram_package_type from SPD %s", mss::c_str(iv_dimm) ); // Check to see if monolithic DRAM/ SDP @@ -700,14 +1007,24 @@ fapi2::ReturnCode eff_dimm::dimm_size() // Retrieve values needed to calculate dimm size uint8_t l_bus_width = 0; - uint8_t l_sdram_width = 0; - uint8_t l_sdram_density = 0; uint8_t l_logical_rank_per_dimm = 0; - FAPI_TRY( iv_pDecoder->device_width(l_sdram_width), "Failed to get device width from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->prim_bus_width(l_bus_width), "Failed to get prim bus width from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->sdram_density(l_sdram_density), "Failed to get dram density from SPD %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(l_logical_rank_per_dimm), + { + uint8_t l_spd_bus_width = 0; + FAPI_TRY( iv_spd_decoder.prim_bus_width(l_spd_bus_width), "Failed to get prim bus width from SPD %s", + mss::c_str(iv_dimm) ); + + FAPI_ASSERT( mss::find_value_from_key(BUS_WIDTH_MAP, l_spd_bus_width, l_bus_width), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_spd_bus_width) + .set_DATA(l_bus_width) + .set_FUNCTION(DIMM_SIZE) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_spd_bus_width, mss::c_str(iv_dimm) ); + } + + FAPI_TRY( logical_ranks_per_dimm(l_logical_rank_per_dimm), "Failed to get logical ranks from SPD %s", mss::c_str(iv_dimm) ); // Let's sort the dimm size vector just to be super duper safe @@ -716,9 +1033,9 @@ fapi2::ReturnCode eff_dimm::dimm_size() // Double checking to avoid divide by zero errors // If this fails, there was a problem with the check in SPD function - FAPI_ASSERT( l_sdram_density != 0, + FAPI_ASSERT( iv_dram_density != 0, fapi2::MSS_BAD_SDRAM_DENSITY_DECODER() - .set_DRAM_DENSITY(l_sdram_density) + .set_DRAM_DENSITY(iv_dram_density) .set_DIMM_TARGET(iv_dimm), "SPD decoder messed up and returned a 0. Should have been caught already %s", mss::c_str(iv_dimm)); @@ -726,23 +1043,23 @@ fapi2::ReturnCode eff_dimm::dimm_size() // Calculate dimm size // Formula from SPD Spec (seriously, they don't have parenthesis in the spec) // Total = SDRAM Capacity / 8 * Primary Bus Width / SDRAM Width * Logical Ranks per DIMM - const uint32_t l_dimm_size = (l_sdram_density * l_bus_width * l_logical_rank_per_dimm) / (8 * l_sdram_width); + const uint32_t l_dimm_size = (iv_dram_density * l_bus_width * l_logical_rank_per_dimm) / (8 * iv_dram_width); FAPI_ASSERT( (std::binary_search(l_dimm_sizes.begin(), l_dimm_sizes.end(), l_dimm_size) == true), fapi2::MSS_INVALID_CALCULATED_DIMM_SIZE() .set_CALCULATED_SIZE(l_dimm_size) - .set_SDRAM_WIDTH(l_sdram_width) + .set_SDRAM_WIDTH(iv_dram_width) .set_BUS_WIDTH(l_bus_width) - .set_DRAM_DENSITY(l_sdram_density) + .set_DRAM_DENSITY(iv_dram_density) .set_LOGICAL_RANKS(l_logical_rank_per_dimm) .set_DIMM_TARGET(iv_dimm), "Recieved an invalid dimm size (%d) for calculated DIMM_SIZE for target %s" - "(l_sdram_density %d * l_bus_width %d * l_logical_rank_per_dimm %d) / (8 * l_sdram_width %d", + "(iv_dram_density %d * l_bus_width %d * l_logical_rank_per_dimm %d) / (8 * iv_dram_width %d", l_dimm_size, mss::c_str(iv_dimm), - l_sdram_width, + iv_dram_width, l_bus_width, - l_sdram_density, + iv_dram_density, l_logical_rank_per_dimm); // Get & update MCS attribute @@ -820,7 +1137,7 @@ fapi2::ReturnCode eff_dimm::dram_trefi() // Calculate nck FAPI_TRY( spd::calc_nck( l_trefi_in_ps, static_cast<uint64_t>(iv_tCK_in_ps), - INVERSE_DDR4_CORRECTION_FACTOR, + spd::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(iv_dimm), l_trefi_in_ps); @@ -866,19 +1183,19 @@ fapi2::ReturnCode eff_dimm::dram_trfc() switch(iv_refresh_mode) { case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL: - FAPI_TRY( iv_pDecoder->min_trfc1(l_trfc_mtb), + FAPI_TRY( iv_spd_decoder.min_trfc1(l_trfc_mtb), "Failed to decode SPD for tRFC1" ); 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( iv_pDecoder->min_trfc2(l_trfc_mtb), + FAPI_TRY( iv_spd_decoder.min_trfc2(l_trfc_mtb), "Failed to decode SPD for tRFC2" ); break; case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_4X: case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_4X: - FAPI_TRY( iv_pDecoder->min_trfc4(l_trfc_mtb), + FAPI_TRY( iv_spd_decoder.min_trfc4(l_trfc_mtb), "Failed to decode SPD for tRFC4" ); break; @@ -916,7 +1233,7 @@ fapi2::ReturnCode eff_dimm::dram_trfc() "Failed to retrieve tRFC attribute" ); // Calculate nck - FAPI_TRY( spd::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, spd::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(iv_dimm), l_trfc_in_ps); FAPI_INF("tCK (ps): %d, tRFC (ps): %d, tRFC (nck): %d", @@ -943,27 +1260,23 @@ fapi_try_exit: fapi2::ReturnCode eff_dimm::dram_trfc_dlr() { - uint8_t l_density = 0; uint64_t l_tCK_in_ps = 0; uint64_t l_trfc_dlr_in_ps = 0; uint8_t l_trfc_dlr_in_nck = 0; std::vector<uint8_t> l_mcs_attrs_trfc_dlr(PORTS_PER_MCS, 0); // Retrieve map params - FAPI_TRY( iv_pDecoder->sdram_density(l_density), "Failed to get sdram density"); - 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, iv_refresh_mode); + iv_dram_density, iv_refresh_mode); // Calculate refresh cycle time in ps - FAPI_TRY( calc_trfc_dlr(iv_dimm, iv_refresh_mode, l_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" ); + FAPI_TRY( calc_trfc_dlr(iv_dimm, iv_refresh_mode, iv_dram_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" ); // Calculate clock period (tCK) from selected freq from mss_freq FAPI_TRY( clock_period(iv_dimm, l_tCK_in_ps), "Failed to calculate clock period (tCK)"); // Calculate refresh cycle time 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_TRY( spd::calc_nck(l_trfc_dlr_in_ps, l_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trfc_dlr_in_nck)); 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); @@ -996,7 +1309,7 @@ fapi2::ReturnCode eff_dimm::rcd_mirror_mode() FAPI_TRY( eff_dimm_rcd_mirror_mode(iv_mcs, &l_attrs_mirror_mode[0][0]) ); // Update MCS attribute - FAPI_TRY( iv_pDecoder->iv_module_decoder->register_to_dram_addr_mapping(l_mirror_mode) ); + FAPI_TRY( iv_spd_decoder.register_to_dram_addr_mapping(l_mirror_mode) ); l_attrs_mirror_mode[iv_port_index][iv_dimm_index] = l_mirror_mode; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RCD_MIRROR_MODE, iv_mcs, l_attrs_mirror_mode) ); @@ -1012,10 +1325,20 @@ fapi_try_exit: fapi2::ReturnCode eff_dimm::dram_bank_bits() { uint8_t l_bank_bits = 0; + uint8_t l_decoder_val = 0; uint8_t l_attrs_bank_bits[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; FAPI_TRY( eff_dram_bank_bits(iv_mcs, &l_attrs_bank_bits[0][0]) ); - FAPI_TRY( iv_pDecoder->bank_bits(l_bank_bits) ); + FAPI_TRY( iv_spd_decoder.bank_bits(l_decoder_val) ); + + FAPI_ASSERT( mss::find_value_from_key(BANK_ADDR_BITS_MAP, l_decoder_val, l_bank_bits), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_decoder_val) + .set_DATA(l_bank_bits) + .set_FUNCTION(DRAM_BANK_BITS) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_decoder_val, mss::c_str(iv_dimm) ); l_attrs_bank_bits[iv_port_index][iv_dimm_index] = l_bank_bits; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANK_BITS, iv_mcs, l_attrs_bank_bits) ); @@ -1030,11 +1353,21 @@ fapi_try_exit: /// fapi2::ReturnCode eff_dimm::dram_row_bits() { + uint8_t l_decoder_val = 0; uint8_t l_row_bits = 0; uint8_t l_attrs_row_bits[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; FAPI_TRY( eff_dram_row_bits(iv_mcs, &l_attrs_row_bits[0][0]) ); - FAPI_TRY( iv_pDecoder->row_address_bits(l_row_bits) ); + FAPI_TRY( iv_spd_decoder.row_address_bits(l_decoder_val) ); + + FAPI_ASSERT( mss::find_value_from_key(ROW_ADDRESS_BITS_MAP, l_decoder_val, l_row_bits), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_decoder_val) + .set_DATA(l_row_bits) + .set_FUNCTION(DRAM_ROW_BITS) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_decoder_val, mss::c_str(iv_dimm) ); l_attrs_row_bits[iv_port_index][iv_dimm_index] = l_row_bits; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_ROW_BITS, iv_mcs, l_attrs_row_bits) ); @@ -1051,27 +1384,13 @@ fapi_try_exit: fapi2::ReturnCode eff_dimm::dram_dqs_time() { uint8_t l_attrs_dqs_time[PORTS_PER_MCS] = {}; - uint8_t l_dram_width = 0; - - // Get the DRAM width - FAPI_TRY( iv_pDecoder->device_width(l_dram_width) ); // Get & update MCS attribute FAPI_TRY( eff_dram_tdqs(iv_mcs, &l_attrs_dqs_time[0]) ); - FAPI_INF("SDRAM width: %d for target %s", l_dram_width, mss::c_str(iv_dimm)); - - // Enforcing current NIMBUS standards. - FAPI_ASSERT( (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) || - (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4), - fapi2::MSS_INVALID_DRAM_WIDTH() - .set_DRAM_WIDTH(l_dram_width) - .set_DIMM_TARGET(iv_dimm), - "Invalid DRAM width with %d for target %s", - l_dram_width, - mss::c_str(iv_dimm)); + FAPI_INF("SDRAM width: %d for target %s", iv_dram_width, mss::c_str(iv_dimm)); // Only possible dram width are x4, x8. If x8, tdqs is available, else not available - l_attrs_dqs_time[iv_port_index] = (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? + l_attrs_dqs_time[iv_port_index] = (iv_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? fapi2::ENUM_ATTR_EFF_DRAM_TDQS_ENABLE : fapi2::ENUM_ATTR_EFF_DRAM_TDQS_DISABLE; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TDQS, iv_mcs, l_attrs_dqs_time) ); @@ -1098,9 +1417,9 @@ fapi2::ReturnCode eff_dimm::dram_tccd_l() int64_t l_tccd_mtb = 0; int64_t l_tccd_ftb = 0; - FAPI_TRY( iv_pDecoder->min_tccd_l(l_tccd_mtb), + FAPI_TRY( iv_spd_decoder.min_tccd_l(l_tccd_mtb), "Failed min_tccd_l() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_tccd_l(l_tccd_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_tccd_l(l_tccd_ftb), "Failed fine_offset_min_tccd_l() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tCCD_L (MTB): %ld, tCCD_L(FTB): %ld", @@ -1119,7 +1438,7 @@ fapi2::ReturnCode eff_dimm::dram_tccd_l() "Failed to retrieve tCCD attribute" ); // Calculate nck - FAPI_TRY( spd::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, spd::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(iv_dimm), l_tccd_in_ps); FAPI_INF("tCK (ps): %d, tCCD_L (ps): %d, tCCD_L (nck): %d", @@ -1151,7 +1470,7 @@ fapi2::ReturnCode eff_dimm::dimm_rc00() FAPI_TRY( eff_dimm_ddr4_rc00(iv_mcs, &l_attrs_dimm_rc00[0][0]) ); // Update MCS attribute - l_attrs_dimm_rc00[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc00; + l_attrs_dimm_rc00[iv_port_index][iv_dimm_index] = iv_raw_card.iv_rc00; FAPI_INF("%s: RC00 settting: 0x%02x", mss::c_str(iv_dimm), l_attrs_dimm_rc00[iv_port_index][iv_dimm_index] ); FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC00, iv_mcs, l_attrs_dimm_rc00) ); @@ -1172,7 +1491,7 @@ fapi2::ReturnCode eff_dimm::dimm_rc01() FAPI_TRY( eff_dimm_ddr4_rc01(iv_mcs, &l_attrs_dimm_rc01[0][0]) ); // Update MCS attribute - l_attrs_dimm_rc01[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc01; + l_attrs_dimm_rc01[iv_port_index][iv_dimm_index] = iv_raw_card.iv_rc01; FAPI_INF("%s: RC01 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc01[iv_port_index][iv_dimm_index] ); FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC01, iv_mcs, l_attrs_dimm_rc01) ); @@ -1218,8 +1537,8 @@ fapi2::ReturnCode eff_dimm::dimm_rc03() uint8_t l_cs_output_drive = 0; uint8_t l_ca_output_drive = 0; - FAPI_TRY( iv_pDecoder->iv_module_decoder->cs_signal_output_driver(l_cs_output_drive) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->ca_signal_output_driver(l_ca_output_drive) ); + FAPI_TRY( iv_spd_decoder.cs_signal_output_driver(l_cs_output_drive) ); + FAPI_TRY( iv_spd_decoder.ca_signal_output_driver(l_ca_output_drive) ); FAPI_INF( "%s: Retrieved register output drive, for CA: %d, CS: %d", mss::c_str(iv_dimm), l_ca_output_drive, l_cs_output_drive ); @@ -1259,8 +1578,8 @@ fapi2::ReturnCode eff_dimm::dimm_rc04() fapi2::buffer<uint8_t> l_buffer; - FAPI_TRY( iv_pDecoder->iv_module_decoder->odt_signal_output_driver(l_odt_output_drive) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->cke_signal_output_driver(l_cke_output_drive) ); + FAPI_TRY( iv_spd_decoder.odt_signal_output_driver(l_odt_output_drive) ); + FAPI_TRY( iv_spd_decoder.cke_signal_output_driver(l_cke_output_drive) ); FAPI_INF( "%s: Retrieved signal driver output, for CKE: %d, ODT: %d", mss::c_str(iv_dimm), l_cke_output_drive, l_odt_output_drive ); @@ -1301,8 +1620,8 @@ fapi2::ReturnCode eff_dimm::dimm_rc05() fapi2::buffer<uint8_t> l_buffer; - FAPI_TRY( iv_pDecoder->iv_module_decoder->a_side_clk_output_driver(l_a_side_output_drive) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->b_side_clk_output_driver(l_b_side_output_drive) ); + FAPI_TRY( iv_spd_decoder.a_side_clk_output_driver(l_a_side_output_drive) ); + FAPI_TRY( iv_spd_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", mss::c_str(iv_dimm), l_b_side_output_drive, l_a_side_output_drive ); @@ -1718,15 +2037,15 @@ fapi2::ReturnCode eff_dimm::dimm_rc0d() constexpr uint8_t l_cs_mode = rc0d_encode::DIRECT_CS_MODE; uint8_t l_mirror_mode = 0; uint8_t l_dimm_type = 0; - uint8_t l_module_type = 0; + uint8_t l_rc0d_dimm_type = 0; - FAPI_TRY( spd::base_module_type(iv_dimm, iv_pDecoder->iv_spd_data, l_module_type) ); + FAPI_TRY(mss::eff_dimm_type(iv_dimm, l_dimm_type)); - l_dimm_type = (l_module_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? - rc0d_encode::RDIMM : - rc0d_encode::LRDIMM; + l_rc0d_dimm_type = (l_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? + rc0d_encode::RDIMM : + rc0d_encode::LRDIMM; - FAPI_TRY( iv_pDecoder->iv_module_decoder->register_to_dram_addr_mapping(l_mirror_mode) ); + FAPI_TRY( iv_spd_decoder.register_to_dram_addr_mapping(l_mirror_mode) ); // Lets construct encoding byte for RCD setting { @@ -1743,7 +2062,7 @@ fapi2::ReturnCode eff_dimm::dimm_rc0d() constexpr size_t MIRROR_LEN = 1; l_buffer.insertFromRight<CS_START, CS_LEN>(l_cs_mode) - .insertFromRight<DIMM_TYPE_START, DIMM_TYPE_LEN>(l_dimm_type) + .insertFromRight<DIMM_TYPE_START, DIMM_TYPE_LEN>(l_rc0d_dimm_type) .insertFromRight<MIRROR_START, MIRROR_LEN>(l_mirror_mode); } @@ -1751,7 +2070,6 @@ fapi2::ReturnCode eff_dimm::dimm_rc0d() FAPI_TRY( eff_dimm_ddr4_rc0d(iv_mcs, &l_attrs_dimm_rc0d[0][0]) ); // Update MCS attribute - FAPI_TRY( spd::base_module_type(iv_dimm, iv_pDecoder->iv_spd_data, l_dimm_type) ); l_attrs_dimm_rc0d[iv_port_index][iv_dimm_index] = l_buffer; FAPI_INF( "%s: RC0D setting: 0x%02x", mss::c_str(iv_dimm), l_attrs_dimm_rc0d[iv_port_index][iv_dimm_index] ); @@ -2183,7 +2501,7 @@ fapi2::ReturnCode eff_dimm::dram_twr() constexpr int64_t l_twr_ftb = 0; int64_t l_twr_mtb = 0; - FAPI_TRY( iv_pDecoder->min_twr(l_twr_mtb), + FAPI_TRY( iv_spd_decoder.min_twr(l_twr_mtb), "Failed min_twr() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWR (MTB): %ld, tWR(FTB): %ld", @@ -2198,7 +2516,7 @@ fapi2::ReturnCode eff_dimm::dram_twr() uint8_t l_twr_in_nck = 0; // Calculate tNCK - FAPI_TRY( spd::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, spd::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(iv_dimm), l_twr_in_ps); FAPI_INF( "tCK (ps): %d, tWR (ps): %d, tWR (nck): %d for target: %s", @@ -2269,20 +2587,18 @@ fapi2::ReturnCode eff_dimm::dram_cwl() // Taken from DDR4 JEDEC spec 1716.78C // Proposed DDR4 Full spec update(79-4A) // Page 26, Table 7 - static std::pair<uint64_t, uint8_t> CWL_TABLE_1 [6] = + static constexpr std::pair<uint64_t, uint8_t> CWL_TABLE_1 [] = { - {1600, 9}, - {1866, 10}, - {2133, 11}, - {2400, 12}, - {2666, 14}, - {3200, 16}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT1866, 10}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2133, 11}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2400, 12}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2666, 14}, }; - static std::pair<uint64_t, uint8_t> CWL_TABLE_2 [3] = + + static constexpr std::pair<uint64_t, uint8_t> CWL_TABLE_2 [] = { - {2400, 14}, - {2666, 16}, - {3200, 18}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2400, 14}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2666, 16}, }; std::vector<uint8_t> l_attrs_cwl(PORTS_PER_MCS, 0); @@ -2744,7 +3060,7 @@ fapi2::ReturnCode eff_dimm::post_package_repair() uint8_t l_attrs_dram_ppr[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; FAPI_TRY( eff_dram_ppr(iv_mcs, &l_attrs_dram_ppr[0][0]) ); - FAPI_TRY( iv_pDecoder->post_package_repair(l_decoder_val) ); + FAPI_TRY( iv_spd_decoder.post_package_repair(l_decoder_val) ); l_attrs_dram_ppr[iv_port_index][iv_dimm_index] = l_decoder_val; FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_PPR, iv_mcs, l_attrs_dram_ppr), @@ -2755,6 +3071,53 @@ fapi_try_exit: } /// +/// @brief Determines & sets effective config for soft post package repair +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::soft_post_package_repair() +{ + uint8_t l_sppr_decoder_val = 0; + uint8_t l_rev_decoder_val = 0; + + uint8_t l_sppr = 0; + uint8_t l_attrs_dram_soft_ppr[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( eff_dram_soft_ppr(iv_mcs, &l_attrs_dram_soft_ppr[0][0]) ); + + FAPI_TRY( iv_spd_decoder.soft_post_package_repair(l_sppr_decoder_val) ); + FAPI_TRY( iv_spd_decoder.revision(l_rev_decoder_val) ); + + if(l_rev_decoder_val == spd::rev::V1_0 && + l_sppr_decoder_val == fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_SUPPORTED) + { + // Lab observes DIMMs that are SPD rev 1.0 but have sPPR enabled that is considered + // invalid per the SPD spec. For backward compatability of those DIMMs (known past vendor issue) + // we set it to a valid value. + FAPI_INF("Invalid sPPR (0x%02x) for SPD rev 0x%02x on %s. Setting sPPR to 0x%02x", + l_sppr_decoder_val, l_rev_decoder_val, mss::c_str(iv_dimm), + fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED); + + l_sppr_decoder_val = fapi2::ENUM_ATTR_EFF_DRAM_SOFT_PPR_NOT_SUPPORTED; + } + + FAPI_ASSERT( mss::find_value_from_key(SOFT_PPR_MAP, l_sppr_decoder_val, l_sppr), + fapi2::MSS_LOOKUP_FAILED() + .set_KEY(l_sppr_decoder_val) + .set_DATA(l_sppr) + .set_FUNCTION(SOFT_POST_PACKAGE_REPAIR) + .set_TARGET(iv_dimm), + "Could not find a mapped value that matched the key (%d) for %s", + l_sppr_decoder_val, mss::c_str(iv_dimm) ); + + l_attrs_dram_soft_ppr[iv_port_index][iv_dimm_index] = l_sppr; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_SOFT_PPR, iv_mcs, l_attrs_dram_soft_ppr), + "Failed setting attribute for DRAM_SOFT_PPR"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// /// @brief Determines & sets effective config for rd_preamble_train /// @return fapi2::FAPI2_RC_SUCCESS if okay /// @@ -3197,10 +3560,10 @@ fapi2::ReturnCode eff_dimm::dram_trp() int64_t l_trp_mtb = 0; int64_t l_trp_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trp(l_trp_mtb), + FAPI_TRY( iv_spd_decoder.min_trp(l_trp_mtb), "Failed min_trp() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trp(l_trp_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trp(l_trp_ftb), "Failed fine_offset_min_trp() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tRP (MTB): %ld, tRP(FTB): %ld", @@ -3221,7 +3584,7 @@ fapi2::ReturnCode eff_dimm::dram_trp() uint8_t l_trp_in_nck = 0; // Calculate nck - FAPI_TRY( spd::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, spd::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(iv_dimm), l_trp_in_ps); FAPI_INF( "tCK (ps): %d, tRP (ps): %d, tRP (nck): %d for target: %s", @@ -3259,10 +3622,10 @@ fapi2::ReturnCode eff_dimm::dram_trcd() int64_t l_trcd_mtb = 0; int64_t l_trcd_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trcd(l_trcd_mtb), + FAPI_TRY( iv_spd_decoder.min_trcd(l_trcd_mtb), "Failed min_trcd() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trcd(l_trcd_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trcd(l_trcd_ftb), "Failed fine_offset_min_trcd() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCD (MTB): %ld, tRCD (FTB): %ld", @@ -3276,7 +3639,7 @@ fapi2::ReturnCode eff_dimm::dram_trcd() uint8_t l_trcd_in_nck = 0; // Calculate nck - FAPI_TRY( spd::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, spd::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(iv_dimm), l_trcd_in_ps); FAPI_INF("tCK (ps): %d, tRCD (ps): %d, tRCD (nck): %d for target: %s", @@ -3309,10 +3672,10 @@ fapi2::ReturnCode eff_dimm::dram_trc() int64_t l_trc_mtb = 0; int64_t l_trc_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trc(l_trc_mtb), + FAPI_TRY( iv_spd_decoder.min_trc(l_trc_mtb), "Failed min_trc() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trc(l_trc_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trc(l_trc_ftb), "Failed fine_offset_min_trc() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCmin (MTB): %ld, tRCmin(FTB): %ld", @@ -3326,7 +3689,7 @@ fapi2::ReturnCode eff_dimm::dram_trc() 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), + FAPI_TRY( spd::calc_nck(l_trc_in_ps, iv_tCK_in_ps, spd::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(iv_dimm), l_trc_in_ps ); @@ -3360,7 +3723,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_l() constexpr int64_t l_twtr_l_ftb = 0; int64_t l_twtr_l_mtb = 0; - FAPI_TRY( iv_pDecoder->min_twtr_l(l_twtr_l_mtb) ); + FAPI_TRY( iv_spd_decoder.min_twtr_l(l_twtr_l_mtb) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", mss::c_str(iv_dimm), iv_mtb, iv_ftb, l_twtr_l_mtb, l_twtr_l_ftb ); @@ -3374,7 +3737,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_l() int8_t l_twtr_l_in_nck = 0; // 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), + FAPI_TRY( spd::calc_nck(l_twtr_l_in_ps, iv_tCK_in_ps, spd::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(iv_dimm), l_twtr_l_in_ps ); FAPI_INF( "tCK (ps): %d, tWTR_L (ps): %d, tWTR_L (nck): %d for target: %s", @@ -3407,7 +3770,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_s() constexpr int64_t l_twtr_s_ftb = 0; int64_t l_twtr_s_mtb = 0; - FAPI_TRY( iv_pDecoder->min_twtr_s(l_twtr_s_mtb) ); + FAPI_TRY( iv_spd_decoder.min_twtr_s(l_twtr_s_mtb) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", mss::c_str(iv_dimm), iv_mtb, iv_ftb, l_twtr_s_mtb, l_twtr_s_ftb ); @@ -3420,7 +3783,7 @@ fapi2::ReturnCode eff_dimm::dram_twtr_s() uint8_t l_twtr_s_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_twtr_s_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_twtr_s_in_nck), + FAPI_TRY( spd::calc_nck(l_twtr_s_in_ps, iv_tCK_in_ps, spd::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(iv_dimm), l_twtr_s_in_ps); FAPI_INF("tCK (ps): %d, tWTR_S (ps): %d, tWTR_S (nck): %d for target: %s", @@ -3449,7 +3812,7 @@ fapi2::ReturnCode eff_dimm::nibble_map() uint8_t l_attr[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_DQ_NIBBLES] = {}; std::vector<uint8_t> l_nibble_bitmap; - FAPI_TRY( iv_pDecoder->nibble_map(l_nibble_bitmap) ); + FAPI_TRY( iv_spd_decoder.nibble_map(l_nibble_bitmap) ); // Sanity check we retrieved a vector w/the right size FAPI_ASSERT( l_nibble_bitmap.size() == MAX_DQ_NIBBLES, @@ -3482,7 +3845,7 @@ fapi2::ReturnCode eff_dimm::package_rank_map() uint8_t l_attr[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_DQ_NIBBLES] = {}; std::vector<uint8_t> l_package_rank_map; - FAPI_TRY( iv_pDecoder->package_rank_map(l_package_rank_map) ); + FAPI_TRY( iv_spd_decoder.package_rank_map(l_package_rank_map) ); // Sanity check we retrieved a vector w/the right size FAPI_ASSERT( l_package_rank_map.size() == MAX_DQ_NIBBLES, @@ -3540,17 +3903,16 @@ fapi2::ReturnCode eff_dimm::dram_trrd_s() uint64_t l_trrd_s_in_nck = 0; int64_t l_trrd_s_in_ps = 0; uint64_t l_jedec_trrd = 0; - uint8_t l_dram_width = 0; // Calculate tRRD_S { int64_t l_trrd_s_mtb = 0; int64_t l_trrd_s_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trrd_s(l_trrd_s_mtb), + FAPI_TRY( iv_spd_decoder.min_trrd_s(l_trrd_s_mtb), "Failed min_trrd_s() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trrd_s(l_trrd_s_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trrd_s(l_trrd_s_ftb), "Failed fine_offset_min_trrd_s() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, trrd_s (MTB): %ld", @@ -3569,16 +3931,13 @@ fapi2::ReturnCode eff_dimm::dram_trrd_s() FAPI_DBG("TRRD_S in ps is %d", l_trrd_s_in_ps); - FAPI_TRY( spd::calc_nck(l_trrd_s_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_s_in_nck), + FAPI_TRY( spd::calc_nck(l_trrd_s_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_s_in_nck), "Error in calculating l_tFAW for target %s, with value of l_trrd_s_in_ps: %d", mss::c_str(iv_dimm), l_trrd_s_in_nck); } - FAPI_TRY( iv_pDecoder->device_width(l_dram_width), - "Failed device_width()"); - - FAPI_TRY( trrd_s( iv_dimm, l_dram_width, l_jedec_trrd) ); + FAPI_TRY( trrd_s( iv_dimm, iv_dram_width, 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) @@ -3587,14 +3946,14 @@ fapi2::ReturnCode eff_dimm::dram_trrd_s() mss::c_str(iv_dimm), l_jedec_trrd, l_trrd_s_in_nck, - l_dram_width, + iv_dram_width, iv_freq); l_trrd_s_in_nck = std::max( l_jedec_trrd, l_trrd_s_in_nck); } FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", - l_dram_width, l_trrd_s_in_nck, mss::c_str(iv_dimm)); + iv_dram_width, l_trrd_s_in_nck, mss::c_str(iv_dimm)); // Get & update MCS attribute FAPI_TRY( eff_dram_trrd_s(iv_mcs, l_attrs_dram_trrd_s.data()) ); @@ -3619,17 +3978,16 @@ fapi2::ReturnCode eff_dimm::dram_trrd_l() std::vector<uint8_t> l_attrs_dram_trrd_l(PORTS_PER_MCS, 0); uint64_t l_trrd_l_in_nck = 0; int64_t l_trrd_l_in_ps = 0; - uint8_t l_dram_width = 0; uint64_t l_jedec_trrd = 0; // Calculate tRRD_L { int64_t l_trrd_l_mtb = 0; int64_t l_trrd_l_ftb = 0; - FAPI_TRY( iv_pDecoder->min_trrd_l(l_trrd_l_mtb), + FAPI_TRY( iv_spd_decoder.min_trrd_l(l_trrd_l_mtb), "Failed min_trrd_l() for %s", mss::c_str(iv_dimm) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trrd_l(l_trrd_l_ftb), + FAPI_TRY( iv_spd_decoder.fine_offset_min_trrd_l(l_trrd_l_ftb), "Failed fine_offset_min_trrd_l() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, trrd_l (MTB): %ld", @@ -3649,16 +4007,13 @@ fapi2::ReturnCode eff_dimm::dram_trrd_l() FAPI_DBG("TRRD_L in ps is %d", l_trrd_l_in_ps); - FAPI_TRY( spd::calc_nck(l_trrd_l_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_l_in_nck), + FAPI_TRY( spd::calc_nck(l_trrd_l_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_trrd_l_in_nck), "Error in calculating l_tFAW for target %s, with value of l_trrd_l_in_ps: %d", mss::c_str(iv_dimm), l_trrd_l_in_nck); } - FAPI_TRY( iv_pDecoder->device_width(l_dram_width), - "Failed device_width()"); - - FAPI_TRY( trrd_l( iv_dimm, l_dram_width, l_jedec_trrd) ); + FAPI_TRY( trrd_l( iv_dimm, iv_dram_width, 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) @@ -3667,14 +4022,14 @@ fapi2::ReturnCode eff_dimm::dram_trrd_l() mss::c_str(iv_dimm), l_jedec_trrd, l_trrd_l_in_nck, - l_dram_width, + iv_dram_width, iv_freq); l_trrd_l_in_nck = std::max( l_jedec_trrd, l_trrd_l_in_nck); } FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", - l_dram_width, l_trrd_l_in_nck, mss::c_str(iv_dimm)); + iv_dram_width, l_trrd_l_in_nck, mss::c_str(iv_dimm)); // Get & update MCS attribute FAPI_TRY( eff_dram_trrd_l(iv_mcs, l_attrs_dram_trrd_l.data()) ); @@ -3726,14 +4081,13 @@ fapi2::ReturnCode eff_dimm::dram_tfaw() uint64_t l_tfaw_in_nck = 0; uint64_t l_jedec_tfaw_in_nck = 0; int64_t l_tfaw_in_ps = 0; - uint8_t l_dram_width = 0; int64_t l_tfaw_ftb = 0; // Calculate tFAW { int64_t l_tfaw_mtb = 0; - FAPI_TRY( iv_pDecoder->min_tfaw(l_tfaw_mtb), + FAPI_TRY( iv_spd_decoder.min_tfaw(l_tfaw_mtb), "Failed min_tfaw() for %s", mss::c_str(iv_dimm) ); FAPI_INF("%s medium timebase (ps): %ld, fine timebase (ps): %ld, tfaw (MTB): %ld", @@ -3752,16 +4106,13 @@ fapi2::ReturnCode eff_dimm::dram_tfaw() FAPI_DBG("%s TFAW in ps is %d", mss::c_str(iv_dimm), l_tfaw_in_ps); - FAPI_TRY( spd::calc_nck(l_tfaw_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_tfaw_in_nck), + FAPI_TRY( spd::calc_nck(l_tfaw_in_ps, iv_tCK_in_ps, spd::INVERSE_DDR4_CORRECTION_FACTOR, l_tfaw_in_nck), "Error in calculating l_tFAW for target %s, with value of l_tfaw_in_ps: %d", mss::c_str(iv_dimm), l_tfaw_in_nck); } - FAPI_TRY( iv_pDecoder->device_width(l_dram_width), - "Failed device_width()"); - - FAPI_TRY( mss::tfaw(iv_dimm, l_dram_width, l_jedec_tfaw_in_nck), "Failed tfaw()" ); + FAPI_TRY( mss::tfaw(iv_dimm, iv_dram_width, 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) @@ -3770,14 +4121,14 @@ fapi2::ReturnCode eff_dimm::dram_tfaw() mss::c_str(iv_dimm), l_jedec_tfaw_in_nck, l_tfaw_in_nck, - l_dram_width, + iv_dram_width, iv_freq); l_tfaw_in_nck = std::max(l_jedec_tfaw_in_nck, l_tfaw_in_nck); } FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", - l_dram_width, l_tfaw_in_nck, mss::c_str(iv_dimm)); + iv_dram_width, l_tfaw_in_nck, mss::c_str(iv_dimm)); // Get & update MCS attribute FAPI_TRY( eff_dram_tfaw(iv_mcs, l_attrs_dram_tfaw.data()) ); @@ -3842,7 +4193,7 @@ fapi2::ReturnCode eff_dimm::dram_tras() // 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, + spd::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(iv_dimm), l_tras_in_ps); @@ -3878,7 +4229,7 @@ fapi2::ReturnCode eff_dimm::dram_trtp() uint8_t l_calc_trtp_in_nck = 0; // Calculate nck - FAPI_TRY( spd::calc_nck(l_max_trtp_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_calc_trtp_in_nck), + FAPI_TRY( spd::calc_nck(l_max_trtp_in_ps, iv_tCK_in_ps, spd::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(iv_dimm), l_max_trtp_in_ps); @@ -3974,7 +4325,7 @@ fapi2::ReturnCode eff_lrdimm::dram_rtt_nom() FAPI_TRY( eff_dram_rtt_nom(iv_mcs, &l_mcs_attrs[0][0][0]) ); // Get the value from the LRDIMM SPD - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_nom(iv_freq, l_decoder_val)); + FAPI_TRY( iv_spd_decoder.dram_rtt_nom(iv_freq, l_decoder_val)); // Plug into every rank position for the attribute so it'll fit the same style as the RDIMM value // Same value for every rank for LRDIMMs @@ -4057,7 +4408,7 @@ fapi2::ReturnCode eff_lrdimm::dram_rtt_wr() uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; // Get the value from the LRDIMM SPD - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_wr(iv_freq, l_decoder_val)); + FAPI_TRY( iv_spd_decoder.dram_rtt_wr(iv_freq, l_decoder_val)); // Plug into every rank position for the attribute so it'll fit the same style as the RDIMM value // Same value for every rank for LRDIMMs @@ -4090,10 +4441,10 @@ fapi2::ReturnCode eff_rdimm::dram_rtt_park() // for mss::index 1. So this doesn't correspond directly with the table in the JEDEC spec, // as that's not in "denominator order." constexpr uint64_t RTT_PARK_COUNT = 8; - // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 - constexpr uint8_t rtt_park_map[RTT_PARK_COUNT] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; + // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 + constexpr uint8_t const rtt_park_map[RTT_PARK_COUNT] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; - uint8_t l_rtt_park[MAX_RANK_PER_DIMM]; + uint8_t l_rtt_park[MAX_RANK_PER_DIMM] = {}; FAPI_TRY( mss::vpd_mt_dram_rtt_park(iv_dimm, &(l_rtt_park[0])) ); FAPI_TRY( eff_dram_rtt_park(iv_mcs, &l_mcs_attrs[0][0][0]) ); @@ -4133,8 +4484,8 @@ fapi2::ReturnCode eff_lrdimm::dram_rtt_park() FAPI_TRY( eff_dram_rtt_park(iv_mcs, &l_mcs_attrs[0][0][0]) ); // Get the value from the LRDIMM SPD - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_park_ranks0_1(iv_freq, l_decoder_val_01) ); - FAPI_TRY( iv_pDecoder->iv_module_decoder->dram_rtt_park_ranks2_3(iv_freq, l_decoder_val_23) ); + FAPI_TRY( iv_spd_decoder.dram_rtt_park_ranks0_1(iv_freq, l_decoder_val_01) ); + FAPI_TRY( iv_spd_decoder.dram_rtt_park_ranks2_3(iv_freq, l_decoder_val_23) ); // Setting the four rank values for this dimm // Rank 0 and 1 have the same value, l_decoder_val_01 @@ -4457,7 +4808,7 @@ fapi2::ReturnCode eff_lrdimm::dimm_bc04() // So the encoding from the SPD is the same as the encoding for the buffer control encoding // Simple grab and insert // Value is checked in decoder function for validity - FAPI_TRY( iv_pDecoder->iv_module_decoder->data_buffer_mdq_rtt(iv_freq, l_decoder_val) ); + FAPI_TRY( iv_spd_decoder.data_buffer_mdq_rtt(iv_freq, l_decoder_val) ); // Update MCS attribute @@ -4485,7 +4836,7 @@ fapi2::ReturnCode eff_lrdimm::dimm_bc05() FAPI_TRY( eff_dimm_ddr4_bc05(iv_mcs, &l_attrs_dimm_bc05[0][0]) ); // Same as BC04, grab from SPD and put into BC - FAPI_TRY( iv_pDecoder->iv_module_decoder->data_buffer_mdq_drive_strength(iv_freq, l_decoder_val) ); + FAPI_TRY( iv_spd_decoder.data_buffer_mdq_drive_strength(iv_freq, l_decoder_val) ); l_attrs_dimm_bc05[iv_port_index][iv_dimm_index] = l_decoder_val; FAPI_INF("%s: BC05 settting (MDQ Drive Strenght): %d", mss::c_str(iv_dimm), @@ -4509,15 +4860,14 @@ fapi2::ReturnCode eff_lrdimm::dimm_bc07() // Map for the bc07 attribute, Each bit and its position represents one rank // 0b0 == enabled, 0b1 == disabled // 1 rank 2 rank 3 rank 4 rank - constexpr uint8_t dram_map [MAX_RANK_PER_DIMM] = {0b1110, 0b1100, 0b1000, 0b0000}; - + constexpr uint8_t const dram_map [MAX_RANK_PER_DIMM] = {0b1110, 0b1100, 0b1000, 0b0000}; uint8_t l_ranks_per_dimm = 0; // Retrieve MCS attribute data uint8_t l_attrs_dimm_bc07[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( iv_pDecoder->num_package_ranks_per_dimm(l_ranks_per_dimm) ); - + // It is safe to use the attribute accessor directly since it is set in mss_freq + FAPI_TRY( eff_num_master_ranks_per_dimm(iv_dimm, l_ranks_per_dimm) ); FAPI_TRY( eff_dimm_ddr4_bc07(iv_mcs, &l_attrs_dimm_bc07[0][0]) ); // Subtract so 1 rank == 0, 2 rank == 1, etc. For array mss::indexing diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H index 85d36d904..7e33c0bdb 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/eff_dimm.H @@ -28,14 +28,19 @@ // *HWP Level: 3 // *HWP Consumed by: FSP:HB - #ifndef _MSS_EFF_DIMM_H_ #define _MSS_EFF_DIMM_H_ #include <fapi2.H> #include <lib/shared/mss_kind.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <lib/shared/mss_const.H> +#include <generic/memory/lib/spd/spd_facade.H> +#include <generic/memory/lib/spd/common/rcw_settings.H> +#include <lib/spd/spd_factory.H> #include <lib/eff_config/timing.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> +#include <generic/memory/lib/spd/spd_utils.H> + namespace mss { @@ -65,11 +70,15 @@ class eff_dimm size_t iv_dimm_index; int64_t iv_ftb; // fine timebase int64_t iv_mtb; // medium timebase + rcw_settings iv_raw_card; + uint8_t iv_dram_width; + uint8_t iv_dram_die_count; public: uint64_t iv_freq; int64_t iv_tCK_in_ps; - const std::shared_ptr<spd::decoder> iv_pDecoder; + spd::facade iv_spd_decoder; + uint8_t iv_dram_density; // Assists testing with write ability on these MRW // settings that are normally NOT writable @@ -91,34 +100,48 @@ class eff_dimm }; + // eff_config SPD raw values to attribute mappings + static const std::vector<std::pair<uint8_t, uint8_t> > DEVICE_WIDTH_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > SDRAM_DENSITY_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > SOFT_PPR_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > BUS_WIDTH_MAP; + static const std::vector< std::pair<uint8_t, uint8_t> > BANK_ADDR_BITS_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > ROW_ADDRESS_BITS_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > PRIM_DIE_COUNT_MAP; + static const std::vector<std::pair<uint8_t, uint8_t> > SEC_DIE_COUNT_MAP; + //Delete the default eff_dimm () = delete; /// /// @brief constructor for the base eff_dimm class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// - eff_dimm( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_dimm( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ): - iv_pDecoder(i_pDecoder) + iv_raw_card(i_rcw), + iv_spd_decoder(i_spd_decoder) { - FAPI_DBG("Constructing eff_dimm object"); - iv_dimm = iv_pDecoder->iv_target; + // Targeting and index info + iv_dimm = i_spd_decoder.get_dimm_target(); + FAPI_DBG("Constructing eff_dimm object for %s", mss::c_str(iv_dimm)); + iv_mca = find_target<fapi2::TARGET_TYPE_MCA>(iv_dimm); iv_mcs = find_target<fapi2::TARGET_TYPE_MCS>(iv_dimm); iv_port_index = mss::index(iv_mca); iv_dimm_index = mss::index(iv_dimm); - FAPI_TRY( iv_pDecoder->medium_timebase(iv_mtb), "Failed medium timebase in eff_dimm()" ); - FAPI_TRY( iv_pDecoder->fine_timebase(iv_ftb), "Failed medium timebase in eff_dimm()" ); - + // Set widely used parameters + FAPI_TRY( spd::get_timebases(iv_spd_decoder, iv_mtb, iv_ftb) ); + FAPI_TRY( set_dram_width_instance() ); + FAPI_TRY( set_prim_dram_die_count_instance() ); + FAPI_TRY( set_dram_density_instance() ); FAPI_TRY( clock_period(iv_dimm, iv_tCK_in_ps), "Failed to calculate clock period (tCK)" ); - FAPI_TRY( mss::mrw_refresh_rate_request(iv_refresh_rate_request), "Failed mrw_temp_refresh_rate_request()" ); FAPI_TRY( mss::mrw_fine_refresh_mode(iv_refresh_mode), "Failed mrw_fine_refresh_mode()" ); - FAPI_TRY( mss::freq(find_target<fapi2::TARGET_TYPE_MCBIST>(iv_dimm), iv_freq), "Failed accessing mss::freq in eff_dimm"); @@ -139,20 +162,20 @@ class eff_dimm /// /// @brief factory to make an eff_config DIMM object based on dimm kind (type, gen, and revision number) - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_fact_obj a shared pointer of the eff_dimm type /// - static fapi2::ReturnCode eff_dimm_factory ( const std::shared_ptr<spd::decoder>& i_pDecoder, - std::shared_ptr<eff_dimm>& o_fact_obj); + static fapi2::ReturnCode factory ( const spd::facade& i_spd_decoder, + std::shared_ptr<eff_dimm>& o_fact_obj); /// - /// @brief Determines & sets effective config for buffer and rev density + /// @brief Determines & sets effective config for buffer and rev type /// @param[in] i_target FAPI2 target - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @return fapi2::FAPI2_RC_SUCCESS if okay /// static fapi2::ReturnCode register_and_buffer_type( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::shared_ptr<spd::decoder>& i_pDecoder ); + const spd::facade& i_spd_decoder ); /// /// @brief Default destructor @@ -567,6 +590,12 @@ class eff_dimm fapi2::ReturnCode post_package_repair(); /// + /// @brief Determines & sets effective config for Soft Post Package Repair + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode soft_post_package_repair(); + + /// /// @brief Determines & sets effective config for rd_preamble_train /// @return fapi2::FAPI2_RC_SUCCESS if okay /// @@ -916,6 +945,46 @@ class eff_dimm /// virtual fapi2::ReturnCode dimm_bc0f() = 0; + private: + + /// + /// @brief Returns Logical ranks in Primary SDRAM type + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode prim_sdram_logical_ranks( uint8_t& o_logical_ranks ) const; + + /// + /// @brief Helper function that returns Logical ranks in SDRAM type + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode sec_sdram_logical_ranks( uint8_t& o_logical_ranks ) const; + + /// + /// @brief Returns Logical ranks per DIMM + /// @param[out] o_logical_ranks number of logical ranks + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode logical_ranks_per_dimm( uint8_t& o_logical_rank_per_dimm ) const; + + /// + /// @brief Helper function to set dram width instance variable + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode set_dram_width_instance(); + + /// + /// @brief Helper function to set dram density instance variable + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode set_dram_density_instance(); + + /// + /// @brief Helper function to set dram density instance variable + /// @return fapi2::FAPI2_RC_SUCCESS iff okay + /// + fapi2::ReturnCode set_prim_dram_die_count_instance(); }; /// @@ -928,16 +997,17 @@ class eff_lrdimm : public eff_dimm public: /// /// @brief constructor for the eff_lrdimm class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_lrdimm( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_lrdimm( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ): - eff_dimm ( i_pDecoder, o_rc ) + eff_dimm ( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing LRDIMM"); + FAPI_DBG("Constructing LRDIMM for %s", mss::c_str(iv_dimm)); } /// @@ -1070,16 +1140,17 @@ class eff_lrdimm_db01 : public eff_lrdimm /// /// @brief constructor for the eff_lrdimm_db01 (LRDIMM DataBuffer 1) class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_lrdimm_db01( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_lrdimm_db01( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ) : - eff_lrdimm( i_pDecoder, o_rc ) + eff_lrdimm( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing LRDIMM_DB01"); + FAPI_DBG("Constructing LRDIMM_DB01 for %s", mss::c_str(iv_dimm)) } /// @@ -1126,16 +1197,17 @@ class eff_lrdimm_db02 : public eff_lrdimm /// /// @brief constructor for the eff_lrdimm_db02 (LRDIMM DataBuffer 2) class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_lrdimm_db02( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_lrdimm_db02( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ) : - eff_lrdimm( i_pDecoder, o_rc ) + eff_lrdimm( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing LRDIMM_DB02"); + FAPI_DBG("Constructing LRDIMM_DB02 for %s", mss::c_str(iv_dimm)); } /// @@ -1179,16 +1251,17 @@ class eff_rdimm : public eff_dimm /// /// @brief constructor for the eff_rdimm_db01 (LRDIMM DataBuffer 1) class - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_rc fapi2::ReturnCode /// @note also sets class variables for parent MCA/ MCS and for freqs /// @note calls eff_dimm ctor /// - eff_rdimm( const std::shared_ptr<spd::decoder>& i_pDecoder, + eff_rdimm( const spd::facade& i_spd_decoder, + const rcw_settings& i_rcw, fapi2::ReturnCode& o_rc ) : - eff_dimm( i_pDecoder, o_rc ) + eff_dimm( i_spd_decoder, i_rcw, o_rc ) { - FAPI_DBG("Constructing RDIMM"); + FAPI_DBG("Constructing RDIMM for %s", mss::c_str(iv_dimm)); } /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C index ef49471e9..aeb61f126 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -25,9 +25,8 @@ /// @file attr_setters.C /// @brief Create setter functions for mss attributes /// -// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com> +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP HWP Backup: Andre A. Marin <aamarin@us.ibm.com> -// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: HB:FSP @@ -35,27 +34,62 @@ #include <fapi2.H> #include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> namespace mss { + /// /// @brief Set ATTR_MSS_VOLT_VDDR and ATTR_MSS_VOLT_VPP /// @param[in] i_target_mcs the MCS target -/// @param[in] l_selected_dram_voltage the voltage in millivolts for nominal voltage -/// @param[in] l_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @param[in] i_selected_dram_voltage the voltage in millivolts for nominal voltage +/// @param[in] i_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @note dram_voltage and dram_voltage_vpp are not const due to FAPI_ATTR_SET template deduction /// @return FAPI2_RC_SUCCESS iff ok /// - fapi2::ReturnCode set_voltage_attributes(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs, - uint32_t l_selected_dram_voltage, - uint32_t l_selected_dram_voltage_vpp) + uint32_t i_selected_dram_voltage, + uint32_t i_selected_dram_voltage_vpp) { const auto l_target_mcbist = find_target<fapi2::TARGET_TYPE_MCBIST>(i_target_mcs); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VDDR, l_target_mcbist, l_selected_dram_voltage) ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VPP, l_target_mcbist, l_selected_dram_voltage_vpp) ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VDDR, l_target_mcbist, i_selected_dram_voltage) ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_VOLT_VPP, l_target_mcbist, i_selected_dram_voltage_vpp) ); fapi_try_exit: return fapi2::current_err; } + +/// +/// @brief Sets pre_eff_config attributes +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_decoder SPD decoder +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const spd::facade& i_spd_decoder ) +{ + fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); + mss::pre_data_engine<mss::NIMBUS> l_data_engine(i_target, i_spd_decoder, l_rc); + FAPI_TRY(l_rc, "Failed to instantiate pre_data_engine object for %s", spd::c_str(i_target)); + + // Set attributes needed before eff_config + // DIMM type and DRAM gen are needed for c_str to aid debugging + FAPI_TRY(l_data_engine.set_dimm_type(), "Failed to set DIMM type %s", spd::c_str(i_target) ); + FAPI_TRY(l_data_engine.set_dram_gen(), "Failed to set DRAM gen %s", spd::c_str(i_target) ); + + // Hybrid and hybrid media help detect hybrid modules, specifically NVDIMMs for Nimbus + FAPI_TRY(l_data_engine.set_hybrid(), "Failed to set Hybrid %s", spd::c_str(i_target) ); + FAPI_TRY(l_data_engine.set_hybrid_media(), "Failed to set Hybrid Media %s", spd::c_str(i_target) ); + + // Number of master ranks needed for VPD decoding + // and dimm_ranks_configured is a PRD attr... + FAPI_TRY(l_data_engine.set_master_ranks(), "Failed to set Master ranks %s", spd::c_str(i_target) ); + FAPI_TRY(l_data_engine.set_dimm_ranks_configured(), "Failed to set DIMM ranks configured %s", spd::c_str(i_target) ); + +fapi_try_exit: + return fapi2::current_err; +} + } // mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H index 793d92fc9..976c1077d 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -27,37 +27,41 @@ /// @file attr_setters.H /// @brief Create setter functions for mss attributes /// -// *HWP HWP Owner: Jacob Harvey <jlharvey@us.ibm.com> +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP HWP Backup: Andre A. Marin <aamarin@us.ibm.com> -// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> // *HWP Team: Memory // *HWP Level: 3 // *HWP Consumed by: HB:FSP - - - #ifndef _MSS_ATTR_SETTERS_H_ #define _MSS_ATTR_SETTERS_H_ #include <fapi2.H> - - +#include <generic/memory/lib/spd/spd_facade.H> namespace mss { + /// /// @brief Set ATTR_MSS_VOLT_VDDR and ATTR_MSS_VOLT_VPP /// @param[in] i_target_mcs the MCS target -/// @param[in] l_selected_dram_voltage the voltage in millivolts for nominal voltage -/// @param[in] l_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @param[in] i_selected_dram_voltage the voltage in millivolts for nominal voltage +/// @param[in] i_selected_dram_voltage_vpp voltage in millivolts for the VPP +/// @note dram_voltage and dram_voltage_vpp are not const due to FAPI_ATTR_SET template deduction /// @return FAPI2_RC_SUCCESS iff ok /// - fapi2::ReturnCode set_voltage_attributes(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs, - uint32_t l_selected_dram_voltage, - uint32_t l_selected_dram_voltage_vpp); + uint32_t i_selected_dram_voltage, + uint32_t i_selected_dram_voltage_vpp); +/// +/// @brief Sets pre_eff_config attributes +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_decoder SPD decoder +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const spd::facade& i_spd_decoder ); } // mss #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C new file mode 100644 index 000000000..7cf3b7b3d --- /dev/null +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C @@ -0,0 +1,239 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2018 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/// +/// @file nimbus_pre_data_engine.C +/// @brief pre_data_engine implimentation for Nimbus +/// +// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> +// *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: CI + +#include <generic/memory/lib/utils/index.H> +#include <lib/mss_attribute_accessors.H> +#include <lib/eff_config/attr_setters.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> +#include <generic/memory/lib/utils/find.H> + +namespace mss +{ + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 2 (0x002): Key Byte / DRAM Device Type +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::DRAM_GEN_MAP = +{ + //{key value, dram gen} + {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4} + // Other key bytes reserved or not supported +}; + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 3 (0x003): Key Byte / Module Type - Hybrid +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID_MAP = +{ + //{key byte, dimm type} + {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID}, + {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID}, + // All others reserved or not supported +}; + + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 3 (0x003): Key Byte / Module Type - Hybrid +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID_MEMORY_TYPE_MAP = +{ + + //{key byte, dimm type} + {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE}, + {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM}, + // All others reserved or not supported +}; + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 3 (0x003): Key Byte / Module Type +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::BASE_MODULE_TYPE_MAP = +{ + //{key byte, dimm type} + {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM}, + {2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM}, + {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM}, + // All others reserved or not supported +}; + +// ========================================================= +// DDR4 SPD Document Release 4 +// Byte 12 (0x00C): Module Organization +// ========================================================= +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::NUM_PACKAGE_RANKS_MAP = +{ + // {key byte, num of package ranks per DIMM (package ranks)} + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 5}, + {5, 6}, + {6, 7}, + {7, 8}, +}; + +/// +/// @brief ctor +/// @param[in] i_target the DIMM target +/// @param[in] i_spd_data SPD data +/// @param[out] o_rc ReturnCode for failure to init object +/// +pre_data_engine<NIMBUS>::pre_data_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, + const spd::facade& i_spd_data, + fapi2::ReturnCode& o_rc): + iv_dimm(i_target), + iv_spd_data(i_spd_data) +{ + // Sets up commonly used member variables + uint8_t l_master_ranks = 0; + FAPI_TRY(iv_spd_data.num_package_ranks_per_dimm(l_master_ranks)); + FAPI_TRY(lookup_table_check(i_target, NUM_PACKAGE_RANKS_MAP, PRE_DATA_ENGINE_CTOR, l_master_ranks, iv_master_ranks)); + + o_rc = fapi2::FAPI2_RC_SUCCESS; + return; + +fapi_try_exit: + o_rc = fapi2::current_err; + return; +} + +/// +/// @brief Set ATTR_EFF_DIMM_TYPE +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dimm_type() +{ + uint8_t l_base_module_type = 0; + uint8_t l_dimm_type = 0; + + FAPI_TRY(iv_spd_data.base_module(l_base_module_type)); + FAPI_TRY(lookup_table_check(iv_dimm, BASE_MODULE_TYPE_MAP, SET_ATTR_DIMM_TYPE, l_base_module_type, l_dimm_type)); + FAPI_TRY( (set_field<NIMBUS, DIMM_TYPE>(iv_dimm, l_dimm_type)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_DRAM_GEN +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dram_gen() +{ + uint8_t l_device_type = 0; + uint8_t l_dram_gen = 0; + + FAPI_TRY(iv_spd_data.device_type(l_device_type)); + FAPI_TRY(lookup_table_check(iv_dimm, DRAM_GEN_MAP, SET_ATTR_DRAM_GEN, l_device_type, l_dram_gen)); + + FAPI_TRY( (set_field<NIMBUS, DRAM_GEN>(iv_dimm, l_dram_gen)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_HYBRID +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid() +{ + uint8_t l_spd_hybrid_type = 0; + uint8_t l_hybrid = 0; + + FAPI_TRY(iv_spd_data.hybrid(l_spd_hybrid_type)); + FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_type, l_hybrid)); + + FAPI_TRY( (set_field<NIMBUS, HYBRID>(iv_dimm, l_hybrid)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_HYBRID_MEMORY_TYPE +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid_media() +{ + uint8_t l_hybrid_media = 0; + uint8_t l_spd_hybrid_media = 0; + + FAPI_TRY(iv_spd_data.hybrid_media(l_spd_hybrid_media)); + FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_media, l_hybrid_media)); + + FAPI_TRY( (set_field<NIMBUS, HYBRID_MEDIA>(iv_dimm, l_hybrid_media)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Set ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM +/// @return FAPI2_RC_SUCCESS iff ok +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_master_ranks() +{ + FAPI_TRY( (set_field<NIMBUS, MRANKS>(iv_dimm, iv_master_ranks)) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Sets ATTR_EFF_DIMM_RANKS_CONFIGED +/// @return FAPI2_RC_SUCCESS iff okay +/// +fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dimm_ranks_configured() +{ + // Set configed ranks. Set the bit representing the master rank configured (0 being left most.) So, + // a 4R DIMM would be 0b11110000 (0xF0). This is used by PRD. + fapi2::buffer<uint8_t> l_ranks_configed; + + FAPI_TRY( l_ranks_configed.setBit(0, iv_master_ranks), + "%s. Failed to setBit", spd::c_str(iv_dimm) ); + + FAPI_TRY( (set_field<NIMBUS, DIMM_RANKS_CNFG>(iv_dimm, uint8_t(l_ranks_configed))) ); + +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 cb500c798..b4a715fb7 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 @@ -38,6 +38,7 @@ #include <cstdint> #include <fapi2.H> #include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> #include <lib/utils/conversions.H> namespace mss @@ -62,17 +63,6 @@ enum functions TDLLK = 11, }; -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) - // when doing integer math, we add-in the inverse correction factor - // Formula used for derivation: - // Guardband = 1000 * (1000* correction_factor) - 1 - INVERSE_DDR3_CORRECTION_FACTOR = 989, ///< DDR3 correction factor - INVERSE_DDR4_CORRECTION_FACTOR = 974, ///< DDR4 correction factor -}; - enum refresh_rate : uint8_t { REF1X = 1, ///< Refresh rate 1X @@ -84,96 +74,6 @@ namespace spd { /// -/// @brief Calculates timing value -/// @param[in] i_timing_mtb timing value in MTB units -/// @param[in] i_mtb_multiplier SPD medium timebase -/// @param[in] i_timing_ftb fine offset of timing value -/// @param[in] i_ftb_multiplier SPD fine timebase -/// @return the timing value in picoseconds -/// -inline int64_t calc_timing_from_timebase(const int64_t i_timing_mtb, - const int64_t i_mtb_multiplier, - const int64_t i_timing_ftb, - const int64_t i_ftb_multiplier) -{ - // JEDEC algorithm - const int64_t l_timing_val = i_timing_mtb * i_mtb_multiplier; - const int64_t l_fine_offset = i_timing_ftb * i_ftb_multiplier; - - return l_timing_val + l_fine_offset; -} - -/// -/// @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 true if overflow didn't occur, false otherwise -/// @note DDR4 SPD Contents Rounding Algorithm -/// @note Item 2220.46 -/// -template<typename T, typename OT> -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 * 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 / CONVERT_PS_IN_A_NS; - - // 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_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); - - // If we don't assert, we don't know what's in current_err ... - return fapi2::FAPI2_RC_SUCCESS; - -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 @@ -201,7 +101,7 @@ inline OT ps_to_nck( const fapi2::Target<T>& i_target, const OT& i_timing_in_ps) 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), + 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; 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 b81796771..1e1494560 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 @@ -42,8 +42,9 @@ // mss lib #include <lib/freq/cas_latency.H> -#include <lib/spd/spd_factory.H> +#include <generic/memory/lib/data_engine/pre_data_init.H> #include <lib/eff_config/timing.H> +#include <generic/memory/lib/spd/spd_utils.H> #include <generic/memory/lib/utils/find.H> #include <lib/utils/checker.H> @@ -66,7 +67,7 @@ namespace mss /// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully /// cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, - const std::vector< std::shared_ptr<spd::decoder> >& i_caches, + const std::vector< spd::facade >& i_caches, const std::vector<uint32_t>& i_supported_freqs, fapi2::ReturnCode& o_rc): iv_dimm_list_empty(false), @@ -88,16 +89,16 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, for ( const auto& l_cache : i_caches ) { // Retrieve timing values from the SPD - const auto l_target = l_cache->iv_target; + const auto l_target = l_cache.get_dimm_target(); 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_cache, l_taa_min_in_ps), "%s. Failed to get tAAmin", mss::c_str(l_target) ); - FAPI_TRY( get_tckmax(l_cache, l_tckmax_in_ps), + FAPI_TRY( spd::get_tckmax(l_cache, l_tckmax_in_ps), "%s. Failed to get tCKmax", mss::c_str(l_target) ); - FAPI_TRY( get_tckmin(l_cache, l_tck_min_in_ps), + FAPI_TRY( spd::get_tckmin(l_cache, l_tck_min_in_ps), "%s. Failed to get tCKmin", mss::c_str(l_target) ); // Determine largest tAAmin value @@ -114,7 +115,7 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, if( iv_is_3ds != loading::IS_3DS) { uint8_t l_stack_type = 0; - FAPI_TRY( l_cache->prim_sdram_signal_loading(l_stack_type) ); + FAPI_TRY( l_cache.prim_sdram_signal_loading(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) ? @@ -124,7 +125,7 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, { // Retrieve dimm supported cas latencies from SPD uint64_t l_dimm_supported_cl = 0; - FAPI_TRY( l_cache->supported_cas_latencies(l_dimm_supported_cl), + FAPI_TRY( l_cache.supported_cas_latencies(l_dimm_supported_cl), "%s. Failed to get supported CAS latency", mss::c_str(l_target) ); // Bitwise ANDING the bitmap from all modules creates a bitmap w/a common CL @@ -312,11 +313,11 @@ fapi_try_exit: /// /// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD -/// @param[in] i_pDecoder the SPD decoder +/// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_value tCKmin value in ps /// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode cas_latency::get_taamin( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, +fapi2::ReturnCode cas_latency::get_taamin( const mss::spd::facade& i_spd_decoder, uint64_t& o_value ) { int64_t l_timing_ftb = 0; @@ -326,15 +327,14 @@ fapi2::ReturnCode cas_latency::get_taamin( const std::shared_ptr<mss::spd::decod int64_t l_temp = 0; // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; + const auto l_target = i_spd_decoder.get_dimm_target(); - FAPI_TRY( i_pDecoder->medium_timebase(l_medium_timebase), - "%s. Failed medium_timebase()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_timebase(l_fine_timebase), - "%s. Failed fine_timebase()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->min_taa(l_timing_mtb), + FAPI_TRY( get_timebases(i_spd_decoder, l_medium_timebase, l_fine_timebase), + "%s. Failed Failed get_timebases", mss::c_str(l_target) ); + + FAPI_TRY( i_spd_decoder.min_taa(l_timing_mtb), "%s. Failed min_taa()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_offset_min_taa(l_timing_ftb), + FAPI_TRY( i_spd_decoder.fine_offset_min_taa(l_timing_ftb), "%s. Failed fine_offset_min_taa()", mss::c_str(l_target) ); // Calculate timing value @@ -409,7 +409,7 @@ inline fapi2::ReturnCode cas_latency::calc_cas_latency(const uint64_t i_taa, const uint64_t i_tck, uint64_t& o_cas_latency) const { - FAPI_TRY( spd::calc_nck(i_taa, i_tck, INVERSE_DDR4_CORRECTION_FACTOR, o_cas_latency) ); + FAPI_TRY( spd::calc_nck(i_taa, i_tck, spd::INVERSE_DDR4_CORRECTION_FACTOR, o_cas_latency) ); FAPI_INF("%s. tAA (ps): %d, tCK (ps): %d, CL (nck): %d", mss::c_str(iv_target), 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 6c9ad087c..bd01e5dc9 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 @@ -45,7 +45,7 @@ #include <fapi2.H> // mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <lib/utils/conversions.H> #include <lib/freq/sync.H> @@ -132,7 +132,7 @@ class cas_latency /// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully /// cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target_mcs, - const std::vector< std::shared_ptr<spd::decoder> >& i_caches, + const std::vector< spd::facade >& i_caches, const std::vector<uint32_t>& i_supported_freqs, fapi2::ReturnCode& o_rc); @@ -277,11 +277,11 @@ class cas_latency /// /// @brief Retrieves SDRAM Minimum CAS Latency Time (tAAmin) from SPD - /// @param[in] i_pDecoder the SPD decoder + /// @param[in] i_spd_decoder the SPD decoder /// @param[out] o_value tCKmin value in ps /// @return FAPI2_RC_SUCCESS iff ok /// - fapi2::ReturnCode get_taamin(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, + fapi2::ReturnCode get_taamin(const mss::spd::facade& i_spd_decoder, uint64_t& o_value); /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C index 35f6daa10..0d9d4c0f8 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C @@ -42,8 +42,9 @@ #include <lib/freq/sync.H> #include <generic/memory/lib/utils/find.H> #include <lib/utils/assert_noexit.H> -#include <lib/spd/spd_factory.H> #include <generic/memory/lib/utils/count_dimm.H> +#include <generic/memory/lib/spd/spd_facade.H> +#include <generic/memory/lib/spd/spd_utils.H> using fapi2::TARGET_TYPE_DIMM; using fapi2::TARGET_TYPE_MCS; @@ -445,25 +446,23 @@ fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TARGET_TYPE_MCBIST>& i_ o_supported_freqs = std::vector<uint32_t>(PORTS_PER_MCBIST, ~(0)); // Get cached decoder - std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches; - - FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches), - "%s. Failed to populate decoder cache", mss::c_str(i_target) ); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(i_target, l_spd_facades) ); // Looking for the biggest application period on an MC. // This will further reduce supported frequencies the system can run on. - for ( const auto& l_cache : l_factory_caches ) + for ( const auto& l_cache : l_spd_facades ) { - const auto l_dimm = l_cache->iv_target; + const auto l_dimm = l_cache.get_dimm_target(); const auto l_mca = mss::find_target<TARGET_TYPE_MCA>(l_dimm); const auto l_port_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(l_mca); uint64_t l_tckmax_in_ps = 0; uint64_t l_tck_min_in_ps = 0; uint32_t l_dimm_freq = 0; - FAPI_TRY( get_tckmax(l_cache, l_tckmax_in_ps), + FAPI_TRY( spd::get_tckmax(l_cache, l_tckmax_in_ps), "%s. Failed to get tCKmax", mss::c_str(l_dimm) ); - FAPI_TRY( get_tckmin(l_cache, l_tck_min_in_ps), + FAPI_TRY( spd::get_tckmin(l_cache, l_tck_min_in_ps), "%s. Failed to get tCKmin", mss::c_str(l_dimm) ); // Determine a proposed tCK value that is greater than or equal tCKmin diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C index 0589d11ae..a0622f929 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C @@ -39,7 +39,7 @@ // mss lib #include <lib/power_thermal/throttle.H> #include <generic/memory/lib/utils/count_dimm.H> -#include <mss.H> + using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_DIMM; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H index 768917bcf..189583cfa 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H @@ -37,7 +37,9 @@ #define _MSS_POWER_THROTTLE_ #include <fapi2.H> -#include <mss.H> +#include <lib/shared/mss_const.H> +#include <lib/mss_attribute_accessors.H> + namespace mss { namespace power_thermal diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H index 63ab07aa1..6535cab1e 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H @@ -37,6 +37,7 @@ #define _MSS_CONST_H_ #include <cstdint> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> #include <generic/memory/lib/utils/mss_math.H> namespace mss @@ -51,9 +52,6 @@ enum sizes MCBIST_PER_MC = 1, MAX_DIMM_PER_PORT = 2, MAX_RANK_PER_DIMM = 4, - NIBBLES_PER_BYTE = 2, - BITS_PER_NIBBLE = 4, - BITS_PER_BYTE = 8, BITS_PER_DP = 16, NIBBLES_PER_DP = BITS_PER_DP / BITS_PER_NIBBLE, BYTES_PER_DP = BITS_PER_DP / BITS_PER_BYTE, @@ -122,9 +120,6 @@ enum sizes enum times { - CONVERT_PS_IN_A_NS = 1000, ///< 1000 pico in an nano - CONVERT_PS_IN_A_US = 1000000, ///< 1000000 picos in a micro - DELAY_1NS = 1, DELAY_10NS = 10 , ///< general purpose 10 ns delay for HW mode DELAY_100NS = 100, ///< general purpose 100 ns delay for HW mode @@ -134,9 +129,6 @@ enum times DELAY_1MS = 1000000, ///< general purpose 1 ms delay for HW mode // Not *exactly* a time but go with it. - MHZ_TO_KHZ = 1000, - - SEC_IN_HOUR = 60 * 60, ///< seconds in an hour, used for scrub times BG_SCRUB_IN_HOURS = 12, CMD_TIMEBASE = 8192, ///< Represents the timebase multiplier for the MCBIST inter cmd gap @@ -145,13 +137,34 @@ enum times }; /// -/// @brief ID codes so we can lookup which function triggered the ffdc fail +/// @brief function ID codes for FFDC functions +/// @note If we get a fail in HB, we can trace back to the function that failed /// enum ffdc_function_codes { + // Following are used in rank.H + RANK_PAIR_TO_PHY = 0, + RANK_PAIR_FROM_PHY = 1, + SET_RANKS_IN_PAIR = 2, + GET_RANKS_IN_PAIR = 3, + GET_RANK_FIELD = 4, + GET_PAIR_VALID = 5, + SET_RANK_FIELD = 6, + RD_CTR_WORKAROUND_READ_DATA = 7, + OVERRIDE_ODT_WR_CONFIG = 8, + RECORD_BAD_BITS_HELPER = 9, + SET_PAIR_VALID = 10, + // Used in eff_dimm.C + SET_DRAM_DENSITY_INSTANCE = 19, NIBBLE_MAP_FUNC = 20, PACKAGE_RANK_MAP_FUNC = 21, + SET_DRAM_WIDTH_INSTANCE = 22, + PRIM_DIE_COUNT = 23, + DIMM_SIZE = 24, + DRAM_BANK_BITS = 25, + DRAM_ROW_BITS = 26, + SOFT_POST_PACKAGE_REPAIR = 27, // Used in fw_mark_store.H for MSS_INVALID_RANK_PASSED FWMS_READ = 30, @@ -186,10 +199,6 @@ enum ffdc_function_codes GET_DRAM_DISABLE_REG_AND_POS = 94, GET_STARTING_WR_DQ_DELAY_VALUE = 95, - GET_TAAMIN = 96, - GET_TCKMIN = 97, - GET_TCKMAX = 98, - SUPPORTED_FREQS = 99, SELECT_SUPPORTED_FREQ = 100, @@ -228,25 +237,6 @@ enum states NO_CHIP_SELECT_ACTIVE = 0xFF, }; -/// -/// @brief function ID codes for FFDC functions -/// @note If we get a fail in HB, we can trace back to the function that failed -/// -enum ffdc_functions -{ - // Following are used in rank.H - RANK_PAIR_TO_PHY = 0, - RANK_PAIR_FROM_PHY = 1, - SET_RANKS_IN_PAIR = 2, - GET_RANKS_IN_PAIR = 3, - GET_RANK_FIELD = 4, - GET_PAIR_VALID = 5, - SET_RANK_FIELD = 6, - RD_CTR_WORKAROUND_READ_DATA = 7, - OVERRIDE_ODT_WR_CONFIG = 8, - RECORD_BAD_BITS_HELPER = 9, - SET_PAIR_VALID = 10, -}; // Static consts describing the bits used in the cal_step_enable attribute // These are bit positions. 0 is the left most bit. enum cal_steps : uint64_t diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H index 6ffea0585..c1b07f643 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_kind.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -62,18 +62,18 @@ enum kind_t FORCE_DISPATCH = 4 + 1, }; -inline mss::kind_t dimm_kind( const uint64_t l_type, const uint64_t l_gen ) +inline mss::kind_t dimm_kind( const uint64_t i_type, const uint64_t i_gen ) { // This is the conditional needed to differentiate dimm type/generation - switch (l_type) + switch (i_type) { case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM: - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) { return KIND_RDIMM_EMPTY; } - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { return KIND_RDIMM_DDR4; } @@ -82,12 +82,12 @@ inline mss::kind_t dimm_kind( const uint64_t l_type, const uint64_t l_gen ) break; case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM: - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY) { return KIND_LRDIMM_EMPTY; } - if (l_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) + if (i_gen == fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4) { return KIND_LRDIMM_DDR4; } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C index 10e23a6f2..1dd9cb759 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C @@ -46,10 +46,11 @@ #include <generic/memory/lib/spd/rdimm/ddr4/rdimm_decoder_ddr4.H> #include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_decoder_ddr4.H> #include <generic/memory/lib/spd/common/rcw_settings.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <generic/memory/lib/spd/rdimm/ddr4/rdimm_raw_cards.H> #include <generic/memory/lib/spd/lrdimm/ddr4/lrdimm_raw_cards.H> #include <generic/memory/lib/spd/spd_checker.H> -#include <generic/memory/lib/utils/c_str.H> +#include <generic/memory/lib/spd/spd_utils.H> #include <lib/utils/conversions.H> #include <generic/memory/lib/utils/find.H> #include <lib/eff_config/timing.H> @@ -62,883 +63,39 @@ using fapi2::FAPI2_RC_SUCCESS; namespace mss { - -/// -/// @brief Helper function to retrieves medium and fine timebase values -/// @param[in] i_pDecoder the SPD decoder -/// @param[out] o_mtb the medium timebase (MTB) from SPD -/// @param[out] o_ftb the fine timebase (FTB) from SPD -/// @return FAPI2_RC_SUCCESS iff ok -/// -static fapi2::ReturnCode get_timebases( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - int64_t& o_mtb, - int64_t& o_ftb ) -{ - // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; - - FAPI_TRY( i_pDecoder->medium_timebase(o_mtb), - "%s. Failed medium_timebase()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_timebase(o_ftb), - "%s. Failed fine_timebase()", mss::c_str(l_target) ); - - FAPI_INF("MTB: %d, FTB: %d for %s", o_mtb, o_ftb, mss::c_str(l_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD -/// @param[in] i_pDecoder the SPD decoder -/// @param[out] o_value tCKmin value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmin( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value ) -{ - int64_t l_timing_ftb = 0; - int64_t l_timing_mtb = 0; - int64_t l_medium_timebase = 0; - int64_t l_fine_timebase = 0; - int64_t l_temp = 0; - - // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; - - FAPI_TRY( get_timebases(i_pDecoder, l_medium_timebase, l_fine_timebase), - "%s. Failed get_timebases", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->min_tck(l_timing_mtb), - "%s. Failed min_tck()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_offset_min_tck(l_timing_ftb), - "%s. Failed fine_offset_min_tck()", mss::c_str(l_target) ); - - // Calculate timing value - l_temp = spd::calc_timing_from_timebase(l_timing_mtb, - l_medium_timebase, - l_timing_ftb, - l_fine_timebase); - - // Sanity check - FAPI_ASSERT(l_temp > 0, - fapi2::MSS_INVALID_TIMING_VALUE(). - set_VALUE(l_temp). - set_FUNCTION(GET_TCKMIN). - set_DIMM_TARGET(l_target), - "%s. tCKmin invalid (<= 0) : %d", - mss::c_str(l_target), - l_temp); - - o_value = l_temp; - - FAPI_INF("%s. tCKmin (ps): %d", - mss::c_str(l_target), - o_value ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD -/// @param[in] i_pDecoder SPD decoder -/// @param[out] o_value tCKmax value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmax( const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value ) -{ - int64_t l_timing_ftb = 0; - int64_t l_timing_mtb = 0; - int64_t l_medium_timebase = 0; - int64_t l_fine_timebase = 0; - int64_t l_temp = 0; - - // Retrieve timing parameters - const auto l_target = i_pDecoder->iv_target; - - FAPI_TRY( get_timebases(i_pDecoder, l_medium_timebase, l_fine_timebase), - "%s. Failed get_timebases", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->max_tck(l_timing_mtb), - "%s. Failed max_tck()", mss::c_str(l_target) ); - FAPI_TRY( i_pDecoder->fine_offset_max_tck(l_timing_ftb), - "%s. Failed fine_offset_max_tck()", mss::c_str(l_target) ); - - // Calculate timing value - l_temp = spd::calc_timing_from_timebase(l_timing_mtb, - l_medium_timebase, - l_timing_ftb, - l_fine_timebase); - - // Sanity check - FAPI_ASSERT(l_temp > 0, - fapi2::MSS_INVALID_TIMING_VALUE(). - set_VALUE(l_temp). - set_FUNCTION(GET_TCKMAX). - set_DIMM_TARGET(l_target), - "%s. tCKmax invalid (<= 0) : %d", - mss::c_str(l_target), - l_temp); - - o_value = l_temp; - - FAPI_INF( "%s. tCKmax (ps): %d", - mss::c_str(l_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - namespace spd { -enum factory_byte_extract -{ - // Byte 1 - ENCODING_LEVEL_START = 0, ///< SPD encoding level start bit - ENCODING_LEVEL_LEN = 4, ///< SPD encoding level bit length - - ADDITIONS_LEVEL_START = 4, ///< SPD additions level start bit - ADDITIONS_LEVEL_LEN = 4, ///< SPD additions level bit length - - // Byte 3 - HYBRID_START = 0, ///< SPD hybrid start bit - HYBRID_LEN = 1, ///< SPD hybrid bit length - HYBRID_TYPE_START = 1, ///< SPD hybrid type start bit - HYBRID_TYPE_LEN = 3, ///< SPD hybrid type bit length - BASE_MODULE_START = 4, ///< SPD base module start bit - BASE_MODULE_LEN = 4, ///< SPD base module bit length -}; - -/// -/// @brief Decodes SPD Revision encoding level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value encoding revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (3~0). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_encoding_level(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - constexpr size_t BYTE_INDEX = 1; - constexpr field_t ENCODING_LEVEL{BYTE_INDEX, ENCODING_LEVEL_START, ENCODING_LEVEL_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, ENCODING_LEVEL, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - (l_field_bits != UNDEFINED), - ENCODING_LEVEL.iv_byte, - l_field_bits, - "Failed check on SPD rev encoding level") ); - - // Update output only after check passes - o_value = l_field_bits; - - // Print decoded info - FAPI_INF("%s. Rev - Encoding Level : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes SPD Revision additions level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value additions revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (bits 7~4). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_additions_level(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - constexpr size_t BYTE_INDEX = 1; - constexpr field_t ADDITIONS_LEVEL{BYTE_INDEX, ADDITIONS_LEVEL_START, ADDITIONS_LEVEL_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, ADDITIONS_LEVEL, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - constexpr size_t UNDEFINED = 0xF; // per JEDEC spec this value is undefined - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - (l_field_bits != UNDEFINED), - ADDITIONS_LEVEL.iv_byte, - l_field_bits, - "Failed check on SPD rev encoding level") ); - - // Update output only after check passes - o_value = l_field_bits; - - // Print decoded info - FAPI_INF("%s. Rev - Additions Level : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes hybrid type (whether or not the DIMM is a hybrid) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 3 maps - // Item JC-45-2220.01x - // Page 17 - // DDR4 SPD Document Release 3 - // Byte 3 (0x003): Key Byte / Module Type - Hybrid - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_MAP = - { - //{key byte, dimm type} - {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID}, - {1, fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID}, - // All others reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 3; - constexpr field_t HYBRID{BYTE_INDEX, HYBRID_START, HYBRID_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, HYBRID, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - const bool l_is_val_found = find_value_from_key(HYBRID_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - HYBRID.iv_byte, - l_field_bits, - "Failed check on Hybrid") ); - - FAPI_INF("%s. Hybrid Media: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes hybrid type (hybrid DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 3 maps - // Item JC-45-2220.01x - // Page 17 - // DDR4 SPD Document Release 3 - // Byte 3 (0x003): Key Byte / Module Type - Hybrid - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > HYBRID_TYPE_MAP = - { - //{key byte, dimm type} - {0, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE}, - {1, fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NVDIMM}, - // All others reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 3; - constexpr field_t HYBRID_TYPE{BYTE_INDEX, HYBRID_TYPE_START, HYBRID_TYPE_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, HYBRID_TYPE, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - const bool l_is_val_found = find_value_from_key(HYBRID_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - HYBRID_TYPE.iv_byte, - l_field_bits, - "Failed check on Hybrid Memory Type") ); - - FAPI_INF("%s. Hybrid Memory Type: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes base module type (DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value base module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode base_module_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 3 maps - // Item JC-45-2220.01x - // Page 17 - // DDR4 SPD Document Release 3 - // Byte 3 (0x003): Key Byte / Module Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > BASE_MODULE_TYPE_MAP = - { - //{key byte, dimm type} - {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM}, - {2, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM}, - {4, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM}, - // All others reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 3; - constexpr field_t BASE_MODULE{BYTE_INDEX, BASE_MODULE_START, BASE_MODULE_LEN}; - - // Extracting desired bits - const uint8_t l_field_bits = extract_spd_field(i_target, BASE_MODULE, i_spd_data); - FAPI_DBG("%s. Field Bits value: %d", mss::c_str(i_target), l_field_bits); - - // Check that value is valid - const bool l_is_val_found = find_value_from_key(BASE_MODULE_TYPE_MAP, l_field_bits, o_value); - - FAPI_TRY( mss::check::spd::fail_for_invalid_value(i_target, - l_is_val_found, - BASE_MODULE.iv_byte, - l_field_bits, - "Failed check on Base Module Type") ); - - FAPI_INF("%s. Base Module Type: %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes DRAM Device Type -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value dram device type enumeration -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 2 -/// @note Item JC-45-2220.01x -/// @note Page 16 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode dram_device_type(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value) -{ - // ========================================================= - // Byte 2 maps - // Item JC-45-2220.01x - // Page 16 - // DDR4 SPD Document Release 3 - // Byte 2 (0x002): Key Byte / DRAM Device Type - // ========================================================= - static const std::vector<std::pair<uint8_t, uint8_t> > DRAM_GEN_MAP = - { - //{key value, dram gen} - {0x0B, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3}, - {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4} - // Other key bytes reserved or not supported - }; - - constexpr size_t BYTE_INDEX = 2; - const uint8_t l_raw_byte = i_spd_data[BYTE_INDEX]; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - l_raw_byte); - - // Find map value - const bool l_is_val_found = mss::find_value_from_key(DRAM_GEN_MAP, l_raw_byte, o_value); - - FAPI_TRY( mss::check::spd:: fail_for_invalid_value(i_target, - l_is_val_found, - BYTE_INDEX, - l_raw_byte, - "Failed check on SPD dram device type") ); - - // Print decoded info - FAPI_INF("%s Device type : %d", - mss::c_str(i_target), - o_value); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Decodes reference raw card -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 130 (Bits 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @Note Page 4.1.2.12 - 49 -/// -fapi2::ReturnCode reference_raw_card(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_output) -{ - // Extracting desired bits - constexpr size_t BYTE_INDEX = 130; - - // Trace in the front assists w/ debug - FAPI_INF("%s SPD data at Byte %d: 0x%llX.", - mss::c_str(i_target), - BYTE_INDEX, - i_spd_data[BYTE_INDEX]); - - // Byte taken directly, all bits are an encoding value so no fail check - o_output = i_spd_data[BYTE_INDEX]; - - FAPI_INF("%s. Reference raw card: %d", - mss::c_str(i_target), - o_output); - - return fapi2::FAPI2_RC_SUCCESS; -} - -/// -/// @brief Helper function to set dimm type attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_dimm_type dimm type encoding needed by factory -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode dimm_type_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_dimm_type) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dimm type & set attribute (needed by c_str) - uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( base_module_type(i_target, i_spd_data, o_dimm_type), - "%s. Failed to find base module type", mss::c_str(i_target) ); - FAPI_TRY( eff_dimm_type(l_mcs, &l_dimm_types_mcs[0][0]), - "%s. Failed to invoke DIMM type accessor", mss::c_str(i_target)); - - l_dimm_types_mcs[l_port_num][l_dimm_num] = o_dimm_type; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, l_mcs, l_dimm_types_mcs), - "%s. Failed to set ATTR_EFF_DIMM_TYPE", mss::c_str(i_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to set hybrid attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_hybrid dimm type encoding needed by factory -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode hybrid_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_hybrid) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dimm type & set attribute (needed by c_str) - uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( hybrid(i_target, i_spd_data, o_hybrid), - "%s. Failed to find hybrid", mss::c_str(i_target) ); - FAPI_TRY( eff_hybrid(l_mcs, &l_dimm_types_mcs[0][0]), - "%s. Failed to invoke hybrid accessor", mss::c_str(i_target)); - - l_dimm_types_mcs[l_port_num][l_dimm_num] = o_hybrid; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID, l_mcs, l_dimm_types_mcs), - "%s. Failed to set ATTR_EFF_HYBRID", mss::c_str(i_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to set hybrid_type attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_hybrid_type dimm type encoding needed by factory -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode hybrid_type_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_hybrid_type) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dimm type & set attribute (needed by c_str) - uint8_t l_dimm_types_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( hybrid_type(i_target, i_spd_data, o_hybrid_type), - "%s. Failed to find hybrid_memory_type", mss::c_str(i_target) ); - FAPI_TRY( eff_hybrid_memory_type(l_mcs, &l_dimm_types_mcs[0][0]), - "%s. Failed to invoke hybrid_memory_type accessor", mss::c_str(i_target)); - - l_dimm_types_mcs[l_port_num][l_dimm_num] = o_hybrid_type; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, l_mcs, l_dimm_types_mcs), - "%s. Failed to set ATTR_EFF_HYBRID_MEMORY", mss::c_str(i_target)); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to set dram gen attribute -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @return FAPI2_RC_SUCCESS if okay -/// -static fapi2::ReturnCode dram_gen_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data) -{ - const auto l_port_num = index( find_target<TARGET_TYPE_MCA>(i_target) ); - const auto l_dimm_num = index(i_target); - const auto l_mcs = mss::find_target<TARGET_TYPE_MCS>(i_target); - - // Get dram generation & set attribute (needed by c_str) - uint8_t l_dram_gen = 0; - uint8_t l_dram_gen_mcs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( eff_dram_gen(l_mcs, &l_dram_gen_mcs[0][0]), - "%s. Failed to inboke DRAM gen accesssor", mss::c_str(i_target) ); - FAPI_TRY( dram_device_type(i_target, i_spd_data, l_dram_gen), - "%s. Failed to find base module type", mss::c_str(i_target) ); - - l_dram_gen_mcs[l_port_num][l_dimm_num] = l_dram_gen; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_mcs, l_dram_gen_mcs), - "%s. Failed to set ATTR_EFF_DRAM_GEN", mss::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for number of master ranks per dimm -/// @param[in] i_target FAPI2 target -/// @param[in] the SPD cache -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note This is done after the SPD cache is configured so that it can reflect the results of the -/// factory and we don't need to worry about SPD versions. This is expressly different than the dram and dimm setters -/// -fapi2::ReturnCode master_ranks_per_dimm_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::shared_ptr<decoder>& i_pDecoder) -{ - const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target); - const auto l_mca = find_target<TARGET_TYPE_MCA>(i_target); - - uint8_t l_decoder_val = 0; - fapi2::buffer<uint8_t> l_ranks_configed; - uint8_t l_attrs_master_ranks_per_dimm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - uint8_t l_attrs_dimm_ranks_configed[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Get & update MCS attribute - FAPI_TRY( i_pDecoder->num_package_ranks_per_dimm(l_decoder_val), - "%s. Failed num_package_ranks_per_dimm()", mss::c_str(i_target) ); - FAPI_TRY(eff_num_master_ranks_per_dimm(l_mcs, &l_attrs_master_ranks_per_dimm[0][0]), - "%s. Failed eff_num_master_ranks_per_dimm()", mss::c_str(i_target) ); - FAPI_TRY(eff_dimm_ranks_configed(l_mcs, &l_attrs_dimm_ranks_configed[0][0]), - "%s. Failed eff_dimm_ranks_configed()", mss::c_str(i_target) ); - - l_attrs_master_ranks_per_dimm[index(l_mca)][index(i_target)] = l_decoder_val; - - // Set configed ranks. Set the bit representing the master rank configured (0 being left most.) So, - // a 4R DIMM would be 0b11110000 (0xF0). This is used by PRD. - FAPI_TRY( l_ranks_configed.setBit(0, l_decoder_val), - "%s. Failed to setBit", mss::c_str(i_target) ); - - l_attrs_dimm_ranks_configed[index(l_mca)][index(i_target)] = l_ranks_configed; - - FAPI_INF( "%s Num Master Ranks %d, DIMM Ranks Configed 0x%x", - mss::c_str(i_target), - l_attrs_master_ranks_per_dimm[index(l_mca)][index(i_target)], - l_attrs_dimm_ranks_configed[index(l_mca)][index(i_target)] ); - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, l_mcs, l_attrs_master_ranks_per_dimm), - "%s. Failed to set ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM", mss::c_str(i_target) ); - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, l_mcs, l_attrs_dimm_ranks_configed), - "%s. Failed to set ATTR_EFF_DIMM_RANKS_CONFIGED", mss::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to return RDIMM decoder -/// @param[in] i_target dimm target -/// @param[in] i_encoding_rev encoding revision -/// @param[in] i_additions_rev additions revision -/// @param[in] i_raw_card raw card reference revision -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -static fapi2::ReturnCode rdimm_rev_helper(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const uint8_t i_encoding_rev, - const uint8_t i_additions_rev, - const rcw_settings i_raw_card, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj) -{ - // This needs to be updated for added revisions - constexpr uint64_t HIGHEST_ENCODING_LEVEL = 1; - constexpr uint64_t HIGHEST_ADDITIONS_LEVEL = 1; - - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - std::shared_ptr<dimm_module_decoder> l_module_decoder; - - // SPD Revision format #.# - // 1st # = encoding level - // 2nd # = additions level - switch(i_encoding_rev) - { - // Skipping case 0 since we shouldn't be using pre-production revisions - case 1: - switch(i_additions_rev) - { - // Rev 1.0 - case 0: - // Life starts out at base revision level - FAPI_INF( "%s. Creating decoder for RDIMM SPD revision 1.0", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::rdimm::decoder_v1_0>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_0>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - case 1: - // Rev 1.1 - // Changes to both the general section & rdimm section occured - FAPI_INF( "%s. Creating decoder for RDIMM SPD revision 1.1", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::rdimm::decoder_v1_1>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - default: - // For additions level retrieved from SPD higher than highest decoded revision level, - // we default to be highest decoded additions level because they are backward compatable. - // This will need to be updated for every new additions level that is decoded. - FAPI_INF( "%s. Unable to create decoder for retrieved SPD RDIMM revision %d.%d", - mss::c_str(i_target), i_encoding_rev, i_additions_rev ); - - FAPI_INF("%s. Falling back to highest supported, backward-comptable decoder, " - "for SPD RDIMM revision %d.%d", - mss::c_str(i_target), HIGHEST_ENCODING_LEVEL, HIGHEST_ADDITIONS_LEVEL ); - - l_module_decoder = std::make_shared<ddr4::rdimm::decoder_v1_1>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - }//end additions - - break; - - default: - // For encodings level retrieved from SPD higher than highest decoded revision level, - // we error out because encoding level changes are NOT backward comptable. - // Current this means Rev 2.0+ is no supported - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, - i_encoding_rev, - i_additions_rev, - "Encoding Level unsupported!"), - "%s. Invalid encoding level received: %d", - mss::c_str(i_target), i_encoding_rev); - - break; - }// end encodings - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Helper function to return LRDIMM decoder -/// @param[in] i_target dimm target -/// @param[in] i_encoding_rev encoding revision -/// @param[in] i_additions_rev additions revision -/// @param[in] i_raw_card raw card reference revision -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -static fapi2::ReturnCode lrdimm_rev_helper(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const uint8_t i_encoding_rev, - const uint8_t i_additions_rev, - const rcw_settings i_raw_card, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - std::shared_ptr<dimm_module_decoder> l_module_decoder; - - // This needs to be updated for added revisions - constexpr uint64_t HIGHEST_ENCODING_LEVEL = 2; - constexpr uint64_t HIGHEST_ADDITIONS_LEVEL = 1; - - // SPD Revision format #.# - // 1st # = encoding level - // 2nd # = additions level - switch(i_encoding_rev) - { - // Skipping case 0 since we shouldn't be using pre-production revisions - case 1: - switch(i_additions_rev) - { - // Rev 1.0 - case 0: - // Life starts out at base revision level - FAPI_INF( "%s. Creating decoder for LRDIMM SPD revision 1.0", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_0>(i_target, i_spd_data); - o_fact_obj = std::make_shared<decoder>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - case 1: - // Rev 1.1 - // Changes to both the general section & lrdimm section occured - FAPI_INF( "%s. Creating decoder for LRDIMM SPD revision 1.1", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_1>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - case 2: - // Rev 1.2 - // Changes lrdimm section occured - // General section remained the same - FAPI_INF( "%s. Creating decoder for LRDIMM SPD revision 1.2", mss::c_str(i_target) ); - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_2>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - default: - // For additions level retrieved from SPD higher than highest decoded revision level, - // we default to be highest decoded additions level because they are backward compatable. - // This will need to be updated for every new additions level that is decoded. - FAPI_INF( "%s. Unable to create decoder for retrieved SPD LRDIMM revision %d.%d", - mss::c_str(i_target), i_encoding_rev, i_additions_rev ); - - FAPI_INF("%s. Falling back to highest supported, backward-comptable decoder, " - "for SPD LRDIMM revision %d.%d", - mss::c_str(i_target), HIGHEST_ENCODING_LEVEL, HIGHEST_ADDITIONS_LEVEL ); - - l_module_decoder = std::make_shared<ddr4::lrdimm::decoder_v1_2>(i_target, i_spd_data); - o_fact_obj = std::make_shared<ddr4::decoder_v1_1>( i_target, i_spd_data, l_module_decoder, i_raw_card ); - break; - - }//end additions - - break; - - default: - // For encodings level retrieved from SPD higher than highest decoded revision level, - // we error out because encoding level changes are NOT backward comptable. - // Currently this means Rev 2.0+ is not supported - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM, - i_encoding_rev, - i_additions_rev, - "Encoding Level unsupported!"), - "%s. Invalid encoding level received: %d", - mss::c_str(i_target), i_encoding_rev); - break; - }// end encodings - -fapi_try_exit: - return fapi2::current_err; -} - /// /// @brief Retrieve current raw card settings /// based on dimm type and raw card reference rev /// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data +/// @param[in] i_data SPD data /// @param[out] o_raw_card raw card settings /// @return FAPI2_RC_SUCCESS if okay /// fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, + const facade& i_data, rcw_settings& o_raw_card) { + // Lets find out what raw card we are and grab the right + // raw card settings uint8_t l_dimm_type = 0; uint8_t l_hybrid = 0; uint8_t l_hybrid_type = 0; uint8_t l_ref_raw_card_rev = 0; - // Lets find out what raw card we are and grab the right - // raw card settings - FAPI_TRY( mss::eff_dimm_type(i_target, l_dimm_type) ); - FAPI_TRY( mss::eff_hybrid(i_target, l_hybrid) ); - FAPI_TRY( mss::eff_hybrid_memory_type(i_target, l_hybrid_type) ); - FAPI_TRY( reference_raw_card(i_target, i_spd_data, l_ref_raw_card_rev) ); + FAPI_TRY(i_data.base_module(l_dimm_type) ); + FAPI_TRY(i_data.hybrid(l_hybrid)); + FAPI_TRY(i_data.hybrid_media(l_hybrid_type)); + FAPI_TRY(i_data.reference_raw_card(l_ref_raw_card_rev)); - FAPI_INF( "Retrieved dimm_type: %d, raw card reference: 0x%lx from SPD", - l_dimm_type, l_ref_raw_card_rev); + FAPI_INF("Retrieved dimm_type: %d, raw card reference: 0x%lx from SPD for %s", + l_dimm_type, l_ref_raw_card_rev, spd::c_str(i_target)); switch(l_dimm_type) { - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM: + case RDIMM: // TODO:RTC178807 - Update how NVDIMMs are handled once more are up and running in the lab // NVDIMM is currently considered differently than all other rdimm raw cards, due to settings differences @@ -947,20 +104,20 @@ fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_targ { l_ref_raw_card_rev = mss::rdimm::raw_card_rev::NVDIMM; FAPI_INF("%s is an NVDIMM, overwrote l_ref_raw_card_rev to be 0x%02x", - mss::c_str(i_target), + mss::spd::c_str(i_target), l_ref_raw_card_rev); } FAPI_TRY( find_raw_card( i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, + RDIMM, l_ref_raw_card_rev, mss::rdimm::RAW_CARDS, o_raw_card) ); break; - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM: + case LRDIMM: FAPI_TRY( find_raw_card( i_target, - fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM, + LRDIMM, l_ref_raw_card_rev, mss::lrdimm::RAW_CARDS, o_raw_card) ); @@ -972,7 +129,7 @@ fapi2::ReturnCode raw_card_factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_targ .set_DIMM_TYPE(l_dimm_type) .set_DIMM_TARGET(i_target), "Recieved invalid dimm type: %d for %s", - l_dimm_type, mss::c_str(i_target) ); + l_dimm_type, mss::spd::c_str(i_target) ); break; } @@ -981,100 +138,6 @@ fapi_try_exit: } /// -/// @brief Object factory to select correct decoder -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -fapi2::ReturnCode factory(const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj) -{ - if( i_spd_data.empty() ) - { - // This won't work with no data - FAPI_ERR( "%s. SPD vector of data is empty! Factory requires valid SPD data.", mss::c_str(i_target) ); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - uint8_t l_dimm_type = 0; - uint8_t l_hybrid = 0; - uint8_t l_hybrid_type = 0; - uint8_t l_encoding_rev = 0; - uint8_t l_additions_rev = 0; - rcw_settings l_raw_card; - - // Attribute setting needed by mss::c_str() which is used in - // the SPD decoder for debugging help - FAPI_TRY( dimm_type_setter(i_target, i_spd_data, l_dimm_type), - "%s. Failed to set DIMM type", mss::c_str(i_target) ); - FAPI_TRY( hybrid_setter(i_target, i_spd_data, l_hybrid), - "%s. Failed to set hybrid", mss::c_str(i_target) ); - FAPI_TRY( hybrid_type_setter(i_target, i_spd_data, l_hybrid_type), - "%s. Failed to set hybrid_type", mss::c_str(i_target) ); - FAPI_TRY( dram_gen_setter(i_target, i_spd_data), - "%s. Failed to set DRAM generation", mss::c_str(i_target) ); - FAPI_TRY( raw_card_factory(i_target, i_spd_data, l_raw_card), - "%s. Failed raw_card_factory()", mss::c_str(i_target) ); - - // Get revision levels to figure out what SPD version we are - FAPI_TRY( rev_encoding_level(i_target, i_spd_data, l_encoding_rev), - "%s. Failed to decode encoding level", mss::c_str(i_target) ); - FAPI_TRY( rev_additions_level(i_target, i_spd_data, l_additions_rev), - "%s. Failed to decode additons level", mss::c_str(i_target) ); - - // Get decoder object needed for current dimm type and spd rev - switch(l_dimm_type) - { - // Each dimm type rev is independent - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM: - FAPI_TRY( rdimm_rev_helper(i_target, - l_encoding_rev, - l_additions_rev, - l_raw_card, - i_spd_data, - o_fact_obj), - "%s. Failed to decode SPD revision for RDIMM, " - "encoding rev: %d, additions rev: %d", - mss::c_str(i_target), l_encoding_rev, l_additions_rev ); - break; - - // Each dimm type rev is independent - case fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM: - FAPI_TRY( lrdimm_rev_helper(i_target, - l_encoding_rev, - l_additions_rev, - l_raw_card, - i_spd_data, - o_fact_obj), - "%s. Failed to decode SPD revision for LRDIMM, " - "encoding rev: %d, additions rev: %d", - mss::c_str(i_target), l_encoding_rev, l_additions_rev); - break; - - default: - FAPI_TRY( mss::check::spd::invalid_factory_sel(i_target, - l_dimm_type, - l_encoding_rev, - l_additions_rev, - "DIMM Type unsupported!") ); - break; - - } // end dimm type - - FAPI_INF( "%s: Decoder created for DIMM type: %d, SPD revision %d.%d", - mss::c_str(i_target), - l_dimm_type, - l_encoding_rev, - l_additions_rev ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// /// @brief Wrapper function for finding the raw card -- helper for testing /// @param[in] i_target the dimm target /// @param[in] i_dimm_type @@ -1100,7 +163,7 @@ fapi2::ReturnCode find_raw_card_helper( const fapi2::Target<TARGET_TYPE_DIMM>& i FAPI_INF("Unsupported raw cards %s allowed for %s", i_mrw_supported_rc ? "are" : "are NOT", - mss::c_str(i_target)); + mss::spd::c_str(i_target)); FAPI_ASSERT(find_value_from_key( i_map, i_ref_raw_card_rev, o_raw_card), fapi2::MSS_INVALID_RAW_CARD(fapi2::FAPI2_ERRL_SEV_RECOVERED, l_rc) @@ -1109,9 +172,9 @@ fapi2::ReturnCode find_raw_card_helper( const fapi2::Target<TARGET_TYPE_DIMM>& i .set_DIMM_TARGET(i_target) .set_MCA_TARGET(l_mca), "Invalid reference raw card received for %s: %d for %s", - (i_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? "RDIMM" : "LRDIMM", + (i_dimm_type == RDIMM) ? "RDIMM" : "LRDIMM", i_ref_raw_card_rev, - mss::c_str(i_target)); + mss::spd::c_str(i_target)); return fapi2::FAPI2_RC_SUCCESS; @@ -1124,7 +187,7 @@ fapi_try_exit: { fapi2::logError(l_rc, fapi2::FAPI2_ERRL_SEV_RECOVERED); l_rc = fapi2::FAPI2_RC_SUCCESS; - o_raw_card = (i_dimm_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? rdimm_rc_default : lrdimm_rc_default; + o_raw_card = (i_dimm_type == RDIMM) ? rdimm_rc_default : lrdimm_rc_default; } return l_rc; @@ -1151,41 +214,7 @@ fapi2::ReturnCode find_raw_card( const fapi2::Target<TARGET_TYPE_DIMM>& i_target FAPI_TRY( mrw_allow_unsupported_rcw(l_allow_unsupported_rcw) ); FAPI_TRY( find_raw_card_helper(i_target, i_dimm_type, i_ref_raw_card_rev, l_allow_unsupported_rcw, i_map, o_raw_card), - "Failed find_raw_card_helper for %s", mss::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Creates factory object & SPD data caches -/// @param[in] i_target the dimm target -/// @param[out] o_factory_caches vector of factory objects -/// @param[in] i_pDecoder custom decoder to populate cache (nullptr default) -/// @return FAPI2_RC_SUCCESS if okay -/// @note This specialization is suited for creating a cache with custom -/// SPD data (e.g. testing custom SPD). -/// -template<> -fapi2::ReturnCode populate_decoder_caches( const fapi2::Target<TARGET_TYPE_DIMM>& i_target, - std::vector< std::shared_ptr<decoder> >& o_factory_caches, - const std::shared_ptr<decoder>& i_pDecoder) -{ - if(i_pDecoder == nullptr) - { - // This won't work w/a null parameter - FAPI_ERR("%s. Received decoder is NULL!", mss::c_str(i_target) ); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - } - - // Custom decoder provided (usually done for testing) - // Populate custom spd caches maps one dimm at a time - o_factory_caches.push_back( i_pDecoder ); - - // Populate some of the DIMM attributes early. This allows the following code to make - // decisions based on DIMM information. Expressly done after the factory has decided on the SPD version - FAPI_TRY( master_ranks_per_dimm_setter(i_target, i_pDecoder), - "%s. Failed master_ranks_per_dimm_setter()", mss::c_str(i_target) ); + "Failed find_raw_card_helper for %s", mss::spd::c_str(i_target) ); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H index ab9872ca6..9d8786452 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H @@ -45,8 +45,8 @@ #include <fapi2_spd_access.H> // mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <generic/memory/lib/utils/find.H> +#include <generic/memory/lib/spd/spd_facade.H> +#include <generic/memory/lib/spd/common/rcw_settings.H> namespace mss { @@ -54,93 +54,6 @@ namespace spd { /// -/// @brief Decodes SPD Revision encoding level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value encoding revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (3~0). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_encoding_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); -/// -/// @brief Decodes SPD Revision additions level -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD blob -/// @param[out] o_value additions revision num -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 1 (bits 7~4). -/// @note Item JC-45-2220.01x -/// @note Page 14-15 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode rev_additions_level(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Decodes hybrid type (whether or not the DIMM is a hybrid) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bit 7) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Decodes hybrid type (hybrid DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value hybrid module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 6~4) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode hybrid_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// -/// @brief Decodes base module type (DIMM type) from SPD -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_value base module type -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 3 (bits 3~0) -/// @note Item JC-45-2220.01x -/// @note Page 17 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode base_module_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); -/// -/// @brief Decodes DRAM Device Type -/// @param[in] i_target dimm target -/// @param[out] o_value dram device type enumeration -/// @return FAPI2_RC_SUCCESS if okay -/// @note Decodes SPD Byte 2 -/// @note Item JC-45-2220.01x -/// @note Page 16 -/// @note DDR4 SPD Document Release 3 -/// -fapi2::ReturnCode dram_device_type(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_value); - -/// /// @brief Wrapper function for finding the raw card -- helper for testing /// @param[in] i_target the dimm target /// @param[in] i_dimm_type @@ -179,126 +92,18 @@ fapi2::ReturnCode find_raw_card( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i rcw_settings& o_raw_card); /// -/// @brief Decodes reference raw card -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_output encoding from SPD -/// @return FAPI2_RC_SUCCESS if okay -/// @note SPD Byte 130 (Bits 7~0) -/// @note Item JEDEC Standard No. 21-C -/// @note DDR4 SPD Document Release 2 -/// @Note Page 4.1.2.12 - 49 -/// -fapi2::ReturnCode reference_raw_card(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - uint8_t& o_output); - -/// /// @brief Retrieve current raw card settings /// based on dimm type and raw card reference rev /// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data +/// @param[in] i_data SPD data /// @param[out] o_raw_card raw card settings /// @return FAPI2_RC_SUCCESS if okay /// fapi2::ReturnCode raw_card_factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, + const facade& i_data, rcw_settings& o_raw_card); -/// -/// @brief Object factory to select correct decoder -/// @param[in] i_target dimm target -/// @param[in] i_spd_data SPD data -/// @param[out] o_fact_obj shared pointer to the factory object -/// @return FAPI2_RC_SUCCESS if okay -/// @note Factory dependent on SPD revision & dimm type -/// -fapi2::ReturnCode factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::vector<uint8_t>& i_spd_data, - std::shared_ptr<decoder>& o_fact_obj); - - -/// -/// @brief Determines & sets effective config for number of master ranks per dimm -/// @param[in] i_target DIMM fapi2::Target -/// @param[in] i_pDecoder shared_ptr to SPD decoder -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note This is done after the SPD cache is configured so that it can reflect the results of the -/// factory and we don't need to worry about SPD versions. This is expressly different than the dram and dimm setters -/// -fapi2::ReturnCode master_ranks_per_dimm_setter(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const std::shared_ptr<decoder>& i_pDecoder); - -/// -/// @brief Creates factory object & SPD data caches -/// @tparam T fapi2::TargetType, MCA, MCS, MCBIST, PROC_CHIP are possible TargetTypes -/// @param[in] i_target the fapi2 target to find DIMMs on -/// @param[out] o_factory_caches vector of factory objects -/// @param[in] i_pDecoder optional input decoder to insert custom decoder (nullptr default) -/// @return FAPI2_RC_SUCCESS if okay -/// -template<fapi2::TargetType T> -fapi2::ReturnCode populate_decoder_caches(const fapi2::Target<T>& i_target, - std::vector< std::shared_ptr<decoder> >& o_factory_caches, - const std::shared_ptr<decoder>& i_pDecoder = nullptr) -{ - // Input decoder for this version of populating cache would get overriden - // so I don't bother with it in this specialization - std::shared_ptr<decoder> l_pDecoder; - - for( const auto& l_dimm : find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) ) - { - size_t l_size = 0; - FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size), - "%s. Failed to retrieve SPD blob size", mss::c_str(i_target) ); - - { - // "Container" for SPD data - std::vector<uint8_t> l_spd(l_size); - - // Retrieve SPD data - FAPI_TRY( fapi2::getSPD(l_dimm, l_spd.data(), l_size), - "%s. Failed to retrieve SPD data", mss::c_str(i_target) ); - - // Retrieve factory object instance & populate spd data for that instance - FAPI_TRY( factory(l_dimm, l_spd, l_pDecoder), - "%s. Failed SPD factory, could not instantiate decoder object", mss::c_str(i_target) ); - - // Populate spd caches - o_factory_caches.push_back( l_pDecoder ); - } - - // Populate some of the DIMM attributes early. This allows the following code to make - // decisions based on DIMM information. Expressly done after the factory has decided on the SPD version - FAPI_TRY( master_ranks_per_dimm_setter(l_dimm, l_pDecoder), - "%s. Failed master_ranks_per_dimm_setter()", mss::c_str(i_target) ); - - }// end dimm - -fapi_try_exit: - return fapi2::current_err; -} - }// spd - -/// -/// @brief Retrieves SDRAM Minimum Cycle Time (tCKmin) from SPD -/// @param[in] i_pDecoder the SPD decoder -/// @param[out] o_value tCKmin value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmin(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value); - -/// -/// @brief Retrieves SDRAM Maximum Cycle Time (tCKmax) from SPD -/// @param[in] i_pDecoder SPD decoder -/// @param[out] o_value tCKmax value in ps -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode get_tckmax(const std::shared_ptr<mss::spd::decoder>& i_pDecoder, - uint64_t& o_value); - }// mss #endif //_MSS_SPD_FACTORY_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H index 260197a66..57523f5bd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/swizzle.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,27 @@ namespace mss { /// +/// @brief Endian swapping +/// @tparam T input type +/// @param[in,out] io_input integral input +/// @note https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c +/// +template < typename T > +void endian_swap(T& io_input) +{ + constexpr size_t MIN_BYTES = 2; + static_assert(sizeof(T) >= MIN_BYTES, "Byte swapping requires at least 2 bytes of data"); + + uint8_t* l_varArray = reinterpret_cast<uint8_t*>(&io_input); + + for(size_t i = 0; i < sizeof(io_input) / 2; i++) + { + const size_t BYTE_SWAP_INDEX = sizeof(io_input) - 1 - i; + std::swap(l_varArray[BYTE_SWAP_INDEX], l_varArray[i]); + } +} + +/// /// @brief Swap two bits in a buffer /// @tparam TB the bit in the buffer to move to SB /// @tparam SB the bit in the buffer to move to TB diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C index 17ebcba7e..57b40397b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C @@ -34,7 +34,6 @@ // *HWP Consumed by: FSP:HB #include <vector> -#include <mss.H> #include <fapi2.H> #include <p9_mss_bulk_pwr_throttles.H> #include <generic/memory/lib/utils/find.H> 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 711eca0ad..c05c51992 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 @@ -43,7 +43,6 @@ // mss lib #include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <lib/spd/spd_factory.H> #include <generic/memory/lib/utils/pos.H> #include <lib/utils/checker.H> #include <generic/memory/lib/utils/find.H> @@ -67,12 +66,8 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS> return fapi2::FAPI2_RC_SUCCESS; } - fapi2::ReturnCode l_rc; - std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches; - - // Caches - FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches), - "Failed populate_decoder_caches for %s", mss::c_str(i_target)); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(i_target, l_spd_facades) ); // Need to check dead load before we get the VPD. // MR and MT VPD depends on DIMM ranks and freaks out if it receives 0 ranks from DIMM 0 and 1 or more ranks for DIMM 1 @@ -93,13 +88,13 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS> "Unable to decode VPD for %s", mss::c_str(i_target) ); } - for( const auto& l_cache : l_factory_caches ) + for( const auto& l_spd : l_spd_facades ) { - const auto l_dimm = l_cache->iv_target; + const auto l_dimm = l_spd.get_dimm_target(); std::shared_ptr<mss::eff_dimm> l_eff_dimm; - FAPI_TRY( mss::eff_dimm::eff_dimm_factory( l_cache, l_eff_dimm), - "Failed eff_dimm_factory for %s", mss::c_str(l_dimm)); + FAPI_TRY( mss::eff_dimm::factory( l_spd, l_eff_dimm), + "Failed factory for %s", mss::c_str(l_dimm)); FAPI_INF("Running eff_config on %s", mss::c_str(l_dimm) ); @@ -225,6 +220,8 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS> "Failed odt_input_buffer for %s", mss::c_str(l_dimm) ); FAPI_TRY( l_eff_dimm->post_package_repair(), "Failed post_package_repair for %s", mss::c_str(l_dimm) ); + FAPI_TRY( l_eff_dimm->soft_post_package_repair(), + "Failed soft_post_package_repair for %s", mss::c_str(l_dimm) ); FAPI_TRY( l_eff_dimm->read_preamble_train(), "Failed read_preamble_train for %s", mss::c_str(l_dimm) ); FAPI_TRY( l_eff_dimm->read_preamble(), 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 c767e87b7..e01918cd7 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 @@ -45,8 +45,7 @@ #include <fapi2.H> // mss lib -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> -#include <lib/spd/spd_factory.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <lib/freq/cas_latency.H> #include <lib/freq/sync.H> #include <lib/workarounds/freq_workarounds.H> @@ -55,6 +54,7 @@ #include <generic/memory/lib/utils/count_dimm.H> #include <generic/memory/lib/utils/index.H> #include <lib/shared/mss_const.H> +#include <lib/eff_config/attr_setters.H> using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_MCA; @@ -79,7 +79,7 @@ extern "C" // So for now, iterate over all the MCBIST. This isn't great as we do this work // twice for every MC. However, attribute access is cheap so this will suffice for // the time being. - const auto& l_mcbist = mss::find_target<TARGET_TYPE_MCBIST>(i_target); + const auto l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target); std::vector< std::vector<uint64_t> > l_min_dimm_freq(mss::MCS_PER_MC, std::vector<uint64_t> (mss::PORTS_PER_MCS, 0) ); std::vector<uint32_t> l_supported_freqs; @@ -93,6 +93,21 @@ extern "C" return FAPI2_RC_SUCCESS; } + // We will first set pre-eff_config attributes + for( const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_mcbist)) + { + std::vector<uint8_t> l_raw_spd; + FAPI_TRY(mss::spd::get_raw_data(d, l_raw_spd)); + + { + fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); + mss::spd::facade l_spd_decoder(d, l_raw_spd, l_rc); + + FAPI_TRY(l_rc, "Failed to initialize SPD facade for %s", mss::spd::c_str(d)); + FAPI_TRY(mss::set_pre_init_attrs(d, l_spd_decoder)); + } + } + // Get supported freqs for this MCBIST FAPI_TRY( mss::supported_freqs(l_mcbist, l_supported_freqs) ); @@ -105,15 +120,14 @@ extern "C" for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs) ) { const auto l_mca_index = mss::index(l_mca); - std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches; fapi2::ReturnCode l_rc; // Get cached decoder - FAPI_TRY( mss::spd::populate_decoder_caches(l_mca, l_factory_caches), - "%s. Failed to populate decoder cache", mss::c_str(l_mca) ); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(l_mca, l_spd_facades) ); // Instantiation of class that calculates CL algorithm - mss::cas_latency l_cas_latency( l_mca, l_factory_caches, l_supported_freqs, l_rc ); + mss::cas_latency l_cas_latency( l_mca, l_spd_facades, l_supported_freqs, l_rc ); FAPI_TRY( l_rc, "%s. Failed to initialize cas_latency ctor", mss::c_str(l_mca) ); diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C index d8bf63b9c..487824835 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C @@ -47,7 +47,6 @@ #include <generic/memory/lib/utils/index.H> #include <generic/memory/lib/utils/find.H> #include <lib/utils/conversions.H> -#include <lib/power_thermal/throttle.H> #include <lib/mss_attribute_accessors.H> #include <generic/memory/lib/utils/count_dimm.H> #include <lib/shared/mss_const.H> diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C index 04a6c0b34..0c8f9d98a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_volt.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,8 +42,7 @@ #include <fapi2.H> // mss lib -#include <lib/spd/spd_factory.H> -#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H> +#include <generic/memory/lib/spd/spd_facade.H> #include <lib/eff_config/attr_setters.H> #include <generic/memory/lib/utils/c_str.H> #include <generic/memory/lib/utils/pos.H> @@ -72,19 +71,19 @@ extern "C" FAPI_INF("Populating decoder cache for %s", mss::c_str(l_mcs)); //Factory cache is per MCS - std::vector< 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 for %s", l_mcs); + std::vector< mss::spd::facade > l_spd_facades; + FAPI_TRY( get_spd_decoder_list(l_mcs, l_spd_facades) ); // Get dimms for each MCS - for ( const auto& l_cache : l_factory_caches ) + for ( const auto& l_cache : l_spd_facades ) { + const auto l_dimm = l_cache.get_dimm_target(); uint8_t l_dimm_nominal = 0; uint8_t l_dimm_endurant = 0; // Read nominal and endurant bits from SPD, 0 = 1.2V is not operable and endurant, 1 = 1.2 is valid - FAPI_TRY( l_cache->operable_nominal_voltage(l_dimm_nominal) ); - FAPI_TRY( l_cache->endurant_nominal_voltage(l_dimm_endurant) ); + FAPI_TRY( l_cache.operable_nominal_voltage(l_dimm_nominal) ); + FAPI_TRY( l_cache.endurant_nominal_voltage(l_dimm_endurant) ); //Check to make sure 1.2 V is both operable and endurant, fail if it is not FAPI_ASSERT ( (l_dimm_nominal == mss::spd::OPERABLE) && (l_dimm_endurant == mss::spd::ENDURANT), @@ -93,10 +92,10 @@ extern "C" set_ACTUAL_ENDURANT(l_dimm_endurant). set_EXPECTED_OPERABLE(mss::spd::OPERABLE). set_EXPECTED_ENDURANT(mss::spd::ENDURANT). - set_DIMM_TARGET(l_cache->iv_target), + set_DIMM_TARGET(l_dimm), "%s: DIMM is not operable (%d) expected (%d)" " and/or endurant (%d) expected (%d) at 1.2V", - mss::c_str(l_cache->iv_target), + mss::c_str(l_dimm), l_dimm_nominal, mss::spd::OPERABLE, l_dimm_endurant, |