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 da0bc9e10d5..3488fad5058 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 @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -22,3 +22,4195 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// *HWP HWP Owner: Jacob Harvey +// *HWP HWP Backup: Andre Marin +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB +#include + +// fapi2 +#include +#include +#include + +// mss lib +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mss +{ + +using fapi2::TARGET_TYPE_DIMM; +using fapi2::TARGET_TYPE_MCS; +using fapi2::TARGET_TYPE_MCA; +using fapi2::TARGET_TYPE_MCBIST; + +/// +/// @brief bit encodings for Frequencies RC0A (RC10) +/// @note valid frequency values for Nimbus systems +/// From DDR4 Register v1.0 +/// More encodings available but they won't be used due to system constrains +/// +// TODO: RTC 167542 +//Do we need to implement v2.0? It would be easy with the new structure - JLH +enum rc10_encode : uint8_t +{ + DDR4_1866 = 0b001, + DDR4_2133 = 0b010, + DDR4_2400 = 0b011, + DDR4_2666 = 0b100, +}; + +/// +/// @brief bit encodings for RC0D (RC10 here) - DIMM Configuration Control Word RC0D (RC10 here) +/// From DDR4 Register v1.0 +/// +enum rc13_encode : uint8_t +{ + DIRECT_CS_MODE = 0, ///< Direct DualCS mode: Register uses two DCS_n inputes + LRDIMM = 0, + RDIMM = 1, +}; + +/// +/// @brief bit encodings for RC3x - Fine Granularity RDIMM Operating Speed +/// @note Only limited encodings here, more available +/// From DDR4 Register v1.0 +/// +enum rc3x_encode : uint8_t +{ + MT1860_TO_MT1880 = 0x1F, + MT2120_TO_MT2140 = 0x2C, + MT2380_TO_MT2400 = 0x39, + MT2660_TO_MT2680 = 0x47, +}; + +/// +/// @brief bc03_encode enums for Host Interface DQ Driver Control Word +/// From DDR4 Databuffer 01 rev 1.0 and same for DDR4 DataBuffer 02 rev 0.95 +/// +enum bc03_encode : uint8_t +{ + // Bit position of the BC03 bit to enable/ disable DQ/ DQS drivers + BC03_DQ_DISABLE_POS = 4, + BC03_DQ_DISABLE = 1, + BC03_DQ_ENABLE = 0, +}; + + +/// +/// @brief bc09_encode enums Power Saving Settings Control Word +/// +//Used for hard coding currently +enum bc09_encode : uint8_t +{ + BC09_CKE_POWER_DOWN_DISABLE = 0, + BC09_CKE_POWER_DOWN_ENABLE = 1, + BC09_CKE_POWER_DOWN_ENABLE_POS = 4, + BC09_CKE_POWER_ODT_OFF = 1, + BC09_CKE_POWER_ODT_ON = 0, +}; + +/// +/// @brief encoding for DB01 and DB02 as seen from SPD +/// +enum lrdimm_databuffers +{ + LRDIMM_DB01 = 0b0000, + LRDIMM_DB02 = 0b0001 +}; + +///////////////////////// +// Non-member function implementations +///////////////////////// + +/// +/// @brief IBT helper - maps from VPD definition of IBT to the RCD control word bit fields +/// @param[in] i_ibt the IBT from VPD (e.g., 10, 15, ...), stored as 10% of original val (10 in VPD == 100 Ohms) +/// @return the IBT bit field e.g., 00, 01 ... (right aligned) +/// @note Unrecognized IBT values will force an assertion. +/// +static uint64_t ibt_helper(const uint8_t i_ibt) +{ + switch(i_ibt) + { + // Off + case 0: + return 0b11; + break; + + // 100 Ohm + case 10: + return 0b00; + break; + + // 150 Ohm + case 15: + return 0b01; + break; + + // 300 Ohm + case 30: + return 0b10; + break; + + default: + FAPI_ERR("unknown IBT value %d", i_ibt); + fapi2::Assert(false); + }; + + // Not reached, but 'return' off ... + return 0b11; +} + +/// +/// @brief factory to make an eff_config DIMM object based on dimm kind (type, gen, and revision number) +/// @param[in] i_target dimm target +/// @param[in] i_pDecoder 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 fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder, + std::shared_ptr& 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; + + fapi2::ReturnCode l_rc; + + // 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(i_target, l_gen), "Failed accessing the ATTR_MSS_EFF_DRAM_GEN" ); + FAPI_TRY( eff_dimm_type(i_target, l_type), "Failed accessing the ATTR_MSS_EFF_DIMM_TYPE" ); + FAPI_TRY( i_pDecoder->iv_module_decoder->register_and_buffer_type(l_buffer_type), + "Failed decoding register and buffer type" ); + + l_dimm_kind = mss::dimm_kind(l_type, l_gen); + + switch (l_dimm_kind) + { + case KIND_LRDIMM_DDR4: + switch (l_buffer_type) + { + case LRDIMM_DB01: + o_fact_obj = std::make_shared (i_target, i_pDecoder, 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(). + set_DIMM_TYPE(l_type). + set_DRAM_GEN(l_gen). + set_REG_AND_BUFF_TYPE(l_buffer_type). + set_DIMM_TARGET(i_target), + "Failure creating an eff_dimm object for an LRDIMM DB01 for target %s buff_type %d", + mss::c_str(i_target), + l_buffer_type); + break; + + case LRDIMM_DB02: + o_fact_obj = std::make_shared (i_target, i_pDecoder, 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(). + set_DIMM_TYPE(l_type). + set_DRAM_GEN(l_gen). + set_REG_AND_BUFF_TYPE(l_buffer_type). + set_DIMM_TARGET(i_target), + "Failure creating an eff_dimm object for an LRDIMM DB02 for target %s buff_type %d", + mss::c_str(i_target), + l_buffer_type); + break; + + default: + FAPI_ASSERT(false, + fapi2::MSS_INVALID_LRDIMM_DB(). + set_DATA_BUFFER_GEN(l_buffer_type). + set_DIMM_TARGET(i_target), + "Error when creating a LRDIMM dimm object due to invalid databuffer type (%d) for target %s", + l_buffer_type, + mss::c_str(i_target)); + return fapi2::FAPI2_RC_INVALID_PARAMETER; + } + + break; + + case KIND_RDIMM_DDR4: + o_fact_obj = std::make_shared (i_target, i_pDecoder, 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(). + set_DIMM_TYPE(l_type). + set_DRAM_GEN(l_gen). + set_REG_AND_BUFF_TYPE(l_buffer_type). + set_DIMM_TARGET(i_target), + "Failure creating an eff_dimm object for an RDIMM for target %s register type %d", + mss::c_str(i_target), + l_buffer_type); + break; + + default: + FAPI_ERR("Wrong kind of DIMM plugged in (not DDR4 LRDIMM or RDIMM for target %s", mss::c_str(i_target)); + FAPI_ASSERT(false, + fapi2::MSS_UNSUPPORTED_DIMM_KIND(). + set_DIMM_KIND(l_dimm_kind). + set_DIMM_TYPE(l_type). + set_DRAM_GEN(l_gen). + set_DIMM_TARGET(i_target), + "Invalid dimm target when passed into eff_config: kind %d, type %d, gen %d for target %s", + l_dimm_kind, + l_type, + l_gen, + mss::c_str(i_target)); + } + +fapi_try_exit: + return fapi2::current_err; +} + + +///////////////////////// +// Member Method implementation +///////////////////////// + +/// +/// @brief Determines & sets effective config for eff_dram_mfg_id type from SPD +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_mfg_id() +{ + uint16_t l_decoder_val = 0; + uint16_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // 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(iv_dimm, l_decoder_val), "Failed getting dram id code from SPD" ); + + l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_MFG_ID, iv_mcs, l_mcs_attrs), "Failed to set ATTR_EFF_DRAM_MFG_ID" ); + +fapi_try_exit: + return fapi2::current_err; + +}// dimm_type + +/// +/// @brief Determines & sets effective config for dram width +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +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(iv_dimm, l_decoder_val), "Failed accessing device width from SPD" ); + FAPI_TRY( eff_dram_width(iv_mcs, &l_mcs_attrs[0][0]), "Failed getting EFF_DRAM_WIDTH" ); + + l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WIDTH, iv_mcs, l_mcs_attrs), "Failed setting ATTR_EFF_DRAM_WIDTH" ); + +fapi_try_exit: + return fapi2::current_err; + +} + +/// +/// @brief Determines & sets effective config for dram density +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_density() +{ + + uint8_t l_decoder_val = 0; + FAPI_TRY( iv_pDecoder->sdram_density(iv_dimm, l_decoder_val), "Failed to get dram_density from SPD" ); + + // 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" ); + + 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" ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for number of ranks per dimm +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::ranks_per_dimm() +{ + uint8_t l_ranks_per_dimm = 0; + uint8_t l_attrs_ranks_per_dimm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // 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(iv_dimm, l_ranks_per_dimm), + "Failed to get logical_ranks_per_dimm from SPD" ); + + 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), + "Failed to set ATTR_EFF_NUM_RANKS_PER_DIMM" ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for stack type +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::primary_stack_type() +{ + uint8_t l_decoder_val = 0; + FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(iv_dimm, l_decoder_val), + "Failed to get dram_signal_loading from SPD" ); + + // Get & update MCS attribute + { + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_prim_stack_type(iv_mcs, &l_mcs_attrs[0][0]), "Failed to get ATTR_MSS_EFF_PRIM_STACK_TYPE" ); + + l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PRIM_STACK_TYPE, iv_mcs, l_mcs_attrs), "Failed to set EFF_PRIM_STACK_TYPE" ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for dimm size +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @warn Dependent on the following attributes already set: +/// @warn eff_dram_density, eff_sdram_width, eff_ranks_per_dimm +/// +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(iv_dimm, l_sdram_width), "Failed to get device width from SPD" ); + FAPI_TRY( iv_pDecoder->prim_bus_width(iv_dimm, l_bus_width), "Failed to get prim bus width from SPD" ); + FAPI_TRY( iv_pDecoder->sdram_density(iv_dimm, l_sdram_density), "Failed to get dram density from SPD" ); + FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(iv_dimm, l_logical_rank_per_dimm), + "Failed to get logical ranks from SPD" ); + + { + // Calculate dimm size + // Formula from SPD Spec + // Total = SDRAM Capacity 8 * Primary Bus Width SDRAM Width * Logical Ranks per DIMM + uint32_t l_dimm_size = 0; + l_dimm_size = (l_sdram_density * l_bus_width * l_logical_rank_per_dimm) / (8 * l_sdram_width); + + // Get & update MCS attribute + uint32_t l_attrs_dimm_size[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_size(iv_mcs, &l_attrs_dimm_size[0][0]), "Failed to get ATTR_MSS_EFF_DIMM_SIZE" ); + + l_attrs_dimm_size[iv_port_index][iv_dimm_index] = l_dimm_size; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_SIZE, iv_mcs, l_attrs_dimm_size), "Failed to get ATTR_MSS_EFF_DIMM_SIZE" ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for Hybrid memory type from SPD +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::hybrid_memory_type() +{ + uint8_t l_decoder_val = 0; + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // Get & update MCS attribute + FAPI_TRY( eff_hybrid_memory_type(iv_mcs, &l_mcs_attrs[0][0]), "Failed to get ATTR_MSS_HYBRID_MEMORY_TYPE" ); + FAPI_TRY(iv_pDecoder->hybrid_media(iv_dimm, l_decoder_val), "Failed to get Hybrid_media from SPD"); + + l_mcs_attrs[iv_port_index][iv_dimm_index] = l_decoder_val; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, iv_mcs, l_mcs_attrs), + "Failed to set ATTR_EFF_HYBRID_MEMORY_TYPE" ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for temperature controlled refresh mode +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note from DDR4 Spec (79-4B) 4.9.4 page 48 +/// +fapi2::ReturnCode eff_dimm::temp_refresh_mode() +{ + uint8_t l_mcs_attrs [mss::PORTS_PER_MCS] = {}; + + FAPI_TRY(mss::eff_temp_refresh_mode (iv_mcs, &l_mcs_attrs[0])); + + // If fine refresh mode is normal, enable temperature control refresh mode + // Otherwise disable the temperature control refresh + l_mcs_attrs[iv_port_index] = (iv_refresh_mode == fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL) ? + fapi2::ENUM_ATTR_EFF_TEMP_REFRESH_MODE_ENABLE : + fapi2::ENUM_ATTR_EFF_TEMP_REFRESH_MODE_DISABLE; + FAPI_INF("%s: temperature control refresh mode is %d", mss::c_str(iv_dimm), l_mcs_attrs[iv_port_index]); + FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_EFF_TEMP_REFRESH_MODE, iv_mcs, l_mcs_attrs ) ); + +fapi_try_exit: + return fapi2::current_err; +}; + + + +/// +/// @brief Determines & sets effective config for refresh interval time (tREFI) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trefi() +{ + uint64_t l_trefi_in_ps = 0; + + // Calculates appropriate tREFI based on fine refresh mode + switch(iv_refresh_mode) + { + case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL: + + FAPI_TRY( calc_trefi( mss::refresh_rate::REF1X, + iv_temp_refresh_range, + l_trefi_in_ps), + "Failed to calculate tREF1 for target %s", mss::c_str(iv_dimm) ); + break; + + case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X: + case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X: + + FAPI_TRY( calc_trefi( mss::refresh_rate::REF2X, + iv_temp_refresh_range, + l_trefi_in_ps), + "Failed to calculate tREF2 for target %s", mss::c_str(iv_dimm) ); + 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( calc_trefi( mss::refresh_rate::REF4X, + iv_temp_refresh_range, + l_trefi_in_ps), + "Failed to calculate tREF4 for target %s", mss::c_str(iv_dimm) ); + break; + + default: + // Fine Refresh Mode will be a platform attribute set by the MRW, + // which they "shouldn't" mess up as long as use "attribute" enums. + // if openpower messes this up we can at least catch it + FAPI_ASSERT(false, + fapi2::MSS_INVALID_FINE_REFRESH_MODE(). + set_FINE_REF_MODE(iv_refresh_mode), + "%s Incorrect Fine Refresh Mode received: %d ", + mss::c_str(iv_dimm), + iv_refresh_mode); + break; + } + + { + // Calculate refresh cycle time in nCK & set attribute + + std::vector l_mcs_attrs_trefi(PORTS_PER_MCS, 0); + uint64_t l_trefi_in_nck = 0; + + // Retrieve MCS attribute data + FAPI_TRY( eff_dram_trefi(iv_mcs, l_mcs_attrs_trefi.data()) ); + + // Calculate nck + FAPI_TRY( spd::calc_nck( l_trefi_in_ps, + static_cast(iv_tCK_in_ps), + INVERSE_DDR4_CORRECTION_FACTOR, + l_trefi_in_nck), + "Error in calculating tREFI for target %s, with value of l_trefi_in_ps: %d", mss::c_str(iv_dimm), l_trefi_in_ps); + + FAPI_INF("tCK (ps): %d, tREFI (ps): %d, tREFI (nck): %d", + iv_tCK_in_ps, l_trefi_in_ps, l_trefi_in_nck); + + // Update MCS attribute + l_mcs_attrs_trefi[iv_port_index] = l_trefi_in_nck; + + // casts vector into the type FAPI_ATTR_SET is expecting by deduction + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TREFI, + iv_mcs, + UINT16_VECTOR_TO_1D_ARRAY(l_mcs_attrs_trefi, PORTS_PER_MCS)), + "Failed to set tREFI attribute"); + } + +fapi_try_exit: + return fapi2::current_err; + +}// refresh_interval + +/// +/// @brief Determines & sets effective config for refresh cycle time (tRFC) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trfc() +{ + int64_t l_trfc_mtb = 0; + int64_t l_trfc_in_ps = 0; + + // Selects appropriate tRFC based on fine refresh mode + switch(iv_refresh_mode) + { + case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL: + FAPI_TRY( iv_pDecoder->min_refresh_recovery_delay_time_1(iv_dimm, 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_refresh_recovery_delay_time_2(iv_dimm, 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_refresh_recovery_delay_time_4(iv_dimm, l_trfc_mtb), + "Failed to decode SPD for tRFC4" ); + break; + + default: + // Fine Refresh Mode will be a platform attribute set by the MRW, + // which they "shouldn't" mess up as long as use "attribute" enums. + // if openpower messes this up we can at least catch it + FAPI_ASSERT(false, + fapi2::MSS_INVALID_FINE_REFRESH_MODE(). + set_FINE_REF_MODE(iv_refresh_mode), + "%s Incorrect Fine Refresh Mode received: %d ", + mss::c_str(iv_dimm), + iv_refresh_mode); + break; + + }// switch + + // Calculate trfc (in ps) + { + constexpr int64_t l_trfc_ftb = 0; + int64_t l_ftb = 0; + int64_t l_mtb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb) ); + + FAPI_INF( "medium timebase (ps): %ld, fine timebase (ps): %ld, tRFC (MTB): %ld, tRFC(FTB): %ld", + l_mtb, l_ftb, l_trfc_mtb, l_trfc_ftb ); + + l_trfc_in_ps = spd::calc_timing_from_timebase(l_trfc_mtb, l_mtb, l_trfc_ftb, l_ftb); + } + + { + // Calculate refresh cycle time in nCK & set attribute + + uint16_t l_trfc_in_nck = 0; + std::vector l_mcs_attrs_trfc(PORTS_PER_MCS, 0); + + // Retrieve MCS attribute data + FAPI_TRY( eff_dram_trfc(iv_mcs, l_mcs_attrs_trfc.data()), + "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), + "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", + iv_tCK_in_ps, l_trfc_in_ps, l_trfc_in_nck); + + // Update MCS attribute + l_mcs_attrs_trfc[iv_port_index] = l_trfc_in_nck; + + // casts vector into the type FAPI_ATTR_SET is expecting by deduction + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRFC, + iv_mcs, + UINT16_VECTOR_TO_1D_ARRAY(l_mcs_attrs_trfc, PORTS_PER_MCS) ), + "Failed to set tRFC attribute" ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for refresh cycle time (different logical ranks - tRFC_DLR) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +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 l_mcs_attrs_trfc_dlr(PORTS_PER_MCS, 0); + + // Retrieve map params + FAPI_TRY( iv_pDecoder->sdram_density(iv_dimm, 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); + + // Calculate refresh cycle time in ps + FAPI_TRY( calc_trfc_dlr(iv_refresh_mode, l_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" ); + + // Calculate clock period (tCK) from selected freq from mss_freq + FAPI_TRY( clock_period(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_INF("tCK (ps): %d, tRFC_DLR (ps): %d, tRFC_DLR (nck): %d", + l_tCK_in_ps, l_trfc_dlr_in_ps, l_trfc_dlr_in_nck); + + // Retrieve MCS attribute data + FAPI_TRY( eff_dram_trfc_dlr(iv_mcs, l_mcs_attrs_trfc_dlr.data()), "Failed to retrieve tRFC_DLR attribute" ); + + // Update MCS attribute + l_mcs_attrs_trfc_dlr[iv_port_index] = l_trfc_dlr_in_nck; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRFC_DLR, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_mcs_attrs_trfc_dlr, PORTS_PER_MCS) ), + "Failed to set tRFC_DLR attribute" ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for dimm rcd mirror mode +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::rcd_mirror_mode() +{ + // Retrieve MCS attribute data + uint8_t l_mirror_mode = 0; + uint8_t l_attrs_mirror_mode[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + 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) ); + 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) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for dram bank bits +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_bank_bits() +{ + uint8_t l_bank_bits = 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(iv_dimm, l_bank_bits) ); + + 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) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for dram row bits +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_row_bits() +{ + 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(iv_dimm, l_row_bits) ); + + 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) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tDQS +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Sets TDQS to off for x4, sets to on for x8 +/// +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(iv_dimm, 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)); + + // 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) ? + 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) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tCCD_L +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_tccd_l() +{ + int64_t l_tccd_in_ps = 0; + + // Get the tCCD_L timing values + // tCCD_L is speed bin independent and is + // the same for all bins within a speed grade. + // It is safe to read this from SPD because the correct nck + // value will be calulated based on our dimm speed. + + // TODO: RTC 163150 Clean up eff_config timing boilerplate + { + int64_t l_ftb = 0; + int64_t l_mtb = 0; + int64_t l_tccd_mtb = 0; + int64_t l_tccd_ftb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb), + "Failed medium_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb), + "Failed fine_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->min_tccd_l(iv_dimm, l_tccd_mtb), + "Failed min_tccd_l() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_offset_min_tccd_l(iv_dimm, l_tccd_ftb), + "Failed fine_offset_min_tccd_l() for %s", mss::c_str(iv_dimm) ); + + FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tCCD_L (MTB): %ld, tCCD_L(FTB): %ld", + l_mtb, l_ftb, l_tccd_mtb, l_tccd_ftb ); + + l_tccd_in_ps = spd::calc_timing_from_timebase(l_tccd_mtb, l_mtb, l_tccd_ftb, l_ftb); + } + + { + // Calculate refresh cycle time in nCK & set attribute + uint8_t l_tccd_in_nck = 0; + std::vector l_mcs_attrs_tccd(PORTS_PER_MCS, 0); + + // Retrieve MCS attribute data + FAPI_TRY( eff_dram_tccd_l(iv_mcs, l_mcs_attrs_tccd.data()), + "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), + "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", + iv_tCK_in_ps, l_tccd_in_ps, l_tccd_in_nck); + + // Update MCS attribute + l_mcs_attrs_tccd[iv_port_index] = l_tccd_in_nck; + + // casts vector into the type FAPI_ATTR_SET is expecting by deduction + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TCCD_L, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_mcs_attrs_tccd, PORTS_PER_MCS) ), + "Failed to set tCCD_L attribute" ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC00 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc00() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc00[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + 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; + + FAPI_INF("%s: RC00 settting: %d", 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) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC01 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc01() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc01[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + 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; + + 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) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC02 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc02() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc02[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc02(iv_mcs, &l_attrs_dimm_rc02[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc02[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc02; + + FAPI_INF("%s: RC02 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc02[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC02, iv_mcs, l_attrs_dimm_rc02) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC03 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc03() +{ + fapi2::buffer l_buffer; + + uint8_t l_attrs_dimm_rc03[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + 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_INF( "%s: Retrieved register output drive, for CA: %d, CS: %d", + mss::c_str(iv_dimm), l_ca_output_drive, l_cs_output_drive ); + + // Lets construct encoding byte for RCD setting + { + // Buffer insert constants for CS and CA output drive + constexpr size_t CS_START = 4; + constexpr size_t CA_START = 6; + constexpr size_t LEN = 2; + + l_buffer.insertFromRight(l_ca_output_drive) + .insertFromRight(l_cs_output_drive); + } + // Retrieve MCS attribute data + FAPI_TRY( eff_dimm_ddr4_rc03(iv_mcs, &l_attrs_dimm_rc03[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc03[iv_port_index][iv_dimm_index] = l_buffer; + + FAPI_INF("%s: RC03 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc03[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC03, iv_mcs, l_attrs_dimm_rc03) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC04 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc04() +{ + uint8_t l_attrs_dimm_rc04[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + uint8_t l_odt_output_drive = 0; + uint8_t l_cke_output_drive = 0; + + fapi2::buffer 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_INF( "%s: Retrieved signal driver output, for CKE: %d, ODT: %d", + mss::c_str(iv_dimm), l_cke_output_drive, l_odt_output_drive ); + + // Lets construct encoding byte for RCD setting + { + // Buffer insert constants for ODT and CKE output drive + constexpr size_t CKE_START = 6; + constexpr size_t ODT_START = 4; + constexpr size_t LEN = 2; + + l_buffer.insertFromRight(l_cke_output_drive) + .insertFromRight(l_odt_output_drive); + } + + // Retrieve MCS attribute data + FAPI_TRY( eff_dimm_ddr4_rc04(iv_mcs, &l_attrs_dimm_rc04[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc04[iv_port_index][iv_dimm_index] = l_buffer; + + FAPI_INF("%s: RC04 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc04[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC04, iv_mcs, l_attrs_dimm_rc04) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC05 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc05() +{ + uint8_t l_attrs_dimm_rc05[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + uint8_t l_a_side_output_drive = 0; + uint8_t l_b_side_output_drive = 0; + + fapi2::buffer 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_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 ); + + { + // Buffer insert constants for ODT and CKE output drive + constexpr size_t B_START = 6; + constexpr size_t A_START = 4; + constexpr size_t LEN = 2; + + // Lets construct encoding byte for RCD setting + l_buffer.insertFromRight(l_b_side_output_drive) + .insertFromRight(l_a_side_output_drive); + } + + // Retrieve MCS attribute data + FAPI_TRY( eff_dimm_ddr4_rc05(iv_mcs, &l_attrs_dimm_rc05[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc05[iv_port_index][iv_dimm_index] = l_buffer; + + FAPI_INF( "%s: RC05 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc05[iv_port_index][iv_dimm_index] ) + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC05, iv_mcs, l_attrs_dimm_rc05) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC06_07 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc06_07() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc06_07[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc06_07(iv_mcs, &l_attrs_dimm_rc06_07[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc06_07[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc06_07; + + FAPI_INF( "%s: RC06_07 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc06_07[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC06_07, iv_mcs, l_attrs_dimm_rc06_07) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC08 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc08() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc08[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc08(iv_mcs, &l_attrs_dimm_rc08[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc08[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc08; + + FAPI_INF( "%s: RC08 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc08[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC08, iv_mcs, l_attrs_dimm_rc08) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC09 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc09() +{ + // TODO - RTC 160118: Clean up eff_config boiler plate that can moved into helper functions + + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc09[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc09(iv_mcs, &l_attrs_dimm_rc09[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc09[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc09; + + FAPI_INF( "%s: RC09 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc09[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC09, iv_mcs, l_attrs_dimm_rc09) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC10 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc10() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc10[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc10(iv_mcs, &l_attrs_dimm_rc10[0][0]) ); + + + switch(iv_freq) + { + case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: + l_attrs_dimm_rc10[iv_port_index][iv_dimm_index] = rc10_encode::DDR4_1866; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: + l_attrs_dimm_rc10[iv_port_index][iv_dimm_index] = rc10_encode::DDR4_2133; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: + l_attrs_dimm_rc10[iv_port_index][iv_dimm_index] = rc10_encode::DDR4_2400; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: + l_attrs_dimm_rc10[iv_port_index][iv_dimm_index] = rc10_encode::DDR4_2666; + break; + + default: + FAPI_ERR("Invalid frequency for rc10 encoding received: %d", iv_freq); + return fapi2::FAPI2_RC_FALSE; + break; + } + + FAPI_INF( "%s: RC10 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc10[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC10, iv_mcs, l_attrs_dimm_rc10) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC11 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc11() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc11[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc11(iv_mcs, &l_attrs_dimm_rc11[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc11[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc0b; + + FAPI_INF( "%s: RC11 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc11[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC11, iv_mcs, l_attrs_dimm_rc11) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC12 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc12() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc12[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc12(iv_mcs, &l_attrs_dimm_rc12[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc12[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc0c; + + FAPI_INF( "%s: R12 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc12[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC12, iv_mcs, l_attrs_dimm_rc12) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC13 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc13() +{ + uint8_t l_attrs_dimm_rc13[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + fapi2::buffer l_buffer; + + // TODO - RTC 160116: Fix RC0D chip select setting for LRDIMMs + constexpr uint8_t l_cs_mode = rc13_encode::DIRECT_CS_MODE; + uint8_t l_mirror_mode = 0; + uint8_t l_dimm_type = 0; + uint8_t l_module_type = 0; + + FAPI_TRY( spd::base_module_type(iv_dimm, iv_pDecoder->iv_spd_data, l_module_type) ); + + l_dimm_type = (l_module_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? + rc13_encode::RDIMM : + rc13_encode::LRDIMM; + + FAPI_TRY( iv_pDecoder->iv_module_decoder->register_to_dram_addr_mapping(l_mirror_mode) ); + + // Lets construct encoding byte for RCD setting + { + // CS + constexpr size_t CS_START = 6; + constexpr size_t CS_LEN = 2; + + // DIMM TYPE + constexpr size_t DIMM_TYPE_START = 5; + constexpr size_t DIMM_TYPE_LEN = 1; + + // MIRROR mode + constexpr size_t MIRROR_START = 4; + constexpr size_t MIRROR_LEN = 1; + + l_buffer.insertFromRight(l_cs_mode) + .insertFromRight(l_dimm_type) + .insertFromRight(l_mirror_mode); + } + + // Retrieve MCS attribute data + FAPI_TRY( eff_dimm_ddr4_rc13(iv_mcs, &l_attrs_dimm_rc13[0][0]) ); + + // Update MCS attribute + FAPI_TRY( spd::base_module_type(iv_dimm, iv_pDecoder->iv_spd_data, l_dimm_type) ); + l_attrs_dimm_rc13[iv_port_index][iv_dimm_index] = l_buffer; + + FAPI_INF( "%s: RC13 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc13[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC13, iv_mcs, l_attrs_dimm_rc13) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC14 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc14() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc14[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc14(iv_mcs, &l_attrs_dimm_rc14[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc14[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc0e; + + FAPI_INF( "%s: RC14 setting: 0x%0x", mss::c_str(iv_dimm), l_attrs_dimm_rc14[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC14, iv_mcs, l_attrs_dimm_rc14) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC15 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc15() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc15[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc15(iv_mcs, &l_attrs_dimm_rc15[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc15[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc0f; + + FAPI_INF( "%s: RC15 setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc15[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC15, iv_mcs, l_attrs_dimm_rc15) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_1x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc1x() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_1x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_1x(iv_mcs, &l_attrs_dimm_rc_1x[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_1x[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc1x; + + FAPI_INF( "%s: RC1X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_1x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_1x, iv_mcs, l_attrs_dimm_rc_1x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_2x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc2x() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_2x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_2x(iv_mcs, &l_attrs_dimm_rc_2x[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_2x[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc2x; + + FAPI_INF( "%s: RC2X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_2x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_2x, iv_mcs, l_attrs_dimm_rc_2x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_3x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc3x() +{ + uint8_t l_attrs_dimm_rc_3x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // Retrieve MCS attribute data + FAPI_TRY( eff_dimm_ddr4_rc_3x(iv_mcs, &l_attrs_dimm_rc_3x[0][0]) ); + + switch(iv_freq) + { + case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: + l_attrs_dimm_rc_3x[iv_port_index][iv_dimm_index] = rc3x_encode::MT1860_TO_MT1880; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: + l_attrs_dimm_rc_3x[iv_port_index][iv_dimm_index] = rc3x_encode::MT2120_TO_MT2140; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: + l_attrs_dimm_rc_3x[iv_port_index][iv_dimm_index] = rc3x_encode::MT2380_TO_MT2400; + break; + + case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: + l_attrs_dimm_rc_3x[iv_port_index][iv_dimm_index] = rc3x_encode::MT2660_TO_MT2680; + break; + + default: + FAPI_ERR("Invalid frequency for rc_3x encoding received: %d", iv_freq); + return fapi2::FAPI2_RC_FALSE; + break; + } + + FAPI_INF( "%s: RC3X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_3x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_3x, iv_mcs, l_attrs_dimm_rc_3x) ); + + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_4x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc4x() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_4x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_4x(iv_mcs, &l_attrs_dimm_rc_4x[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_4x[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc4x; + + FAPI_INF( "%s: RC4X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_4x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_4x, iv_mcs, l_attrs_dimm_rc_4x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_5x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc5x() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_5x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_5x(iv_mcs, &l_attrs_dimm_rc_5x[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_5x[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc5x; + + FAPI_INF( "%s: RC5X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_5x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_5x, iv_mcs, l_attrs_dimm_rc_5x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_6x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc6x() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_6x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_6x(iv_mcs, &l_attrs_dimm_rc_6x[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_6x[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc6x; + + FAPI_INF( "%s: RC6X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_6x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_6x, iv_mcs, l_attrs_dimm_rc_6x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_7x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc7x() +{ + uint8_t l_attrs_dimm_rc_7x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + fapi2::buffer l_rcd7x = 0; + + // All the IBT bit fields in the RCD control word are 2 bits long. + constexpr uint64_t LEN = 2; + + // CA starts at bit 6, others are the same. So the field runs from START for LEN bits, + // for example CA field is bits 6:7 + constexpr uint64_t CA_START = 6; + uint8_t l_ibt_ca = 0; + + constexpr uint64_t CKE_START = 2; + uint8_t l_ibt_cke = 0; + + constexpr uint64_t CS_START = 4; + uint8_t l_ibt_cs = 0; + + constexpr uint64_t ODT_START = 0; + uint8_t l_ibt_odt = 0; + + // Pull the individual settings from VPD, and shuffle them into RCD7x + FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_ca(iv_dimm, l_ibt_ca) ); + FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_cke(iv_dimm, l_ibt_cke) ); + FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_cs(iv_dimm, l_ibt_cs) ); + FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_odt(iv_dimm, l_ibt_odt) ); + + l_rcd7x.insertFromRight( ibt_helper(l_ibt_ca) ); + l_rcd7x.insertFromRight( ibt_helper(l_ibt_cke) ); + l_rcd7x.insertFromRight( ibt_helper(l_ibt_cs) ); + l_rcd7x.insertFromRight( ibt_helper(l_ibt_odt) ); + + // Now write RCD7x out to the effective attribute + FAPI_TRY( eff_dimm_ddr4_rc_7x(iv_mcs, &l_attrs_dimm_rc_7x[0][0]) ); + l_attrs_dimm_rc_7x[iv_port_index][iv_dimm_index] = l_rcd7x; + + FAPI_INF( "%s: RC7X setting is 0x%x", mss::c_str(iv_dimm), l_attrs_dimm_rc_7x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_7x, iv_mcs, l_attrs_dimm_rc_7x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_8x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc8x() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_8x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_8x(iv_mcs, &l_attrs_dimm_rc_8x[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_8x[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc8x; + + FAPI_INF( "%s: RC8X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_8x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_8x, iv_mcs, l_attrs_dimm_rc_8x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_9x +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rc9x() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_9x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_9x(iv_mcs, &l_attrs_dimm_rc_9x[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_9x[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rc9x; + + FAPI_INF( "%s: RC9X setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_9x[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_9x, iv_mcs, l_attrs_dimm_rc_9x) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_AX +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rcax() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_ax[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_ax(iv_mcs, &l_attrs_dimm_rc_ax[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_ax[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rcax; + + FAPI_INF( "%s: RCAX setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_ax[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_Ax, iv_mcs, l_attrs_dimm_rc_ax) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM RC_BX +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dimm_rcbx() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_rc_bx[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_rc_bx(iv_mcs, &l_attrs_dimm_rc_bx[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_rc_bx[iv_port_index][iv_dimm_index] = iv_pDecoder->iv_raw_card.iv_rcbx; + + FAPI_INF( "%s: RCBX setting: %d", mss::c_str(iv_dimm), l_attrs_dimm_rc_bx[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_Bx, iv_mcs, l_attrs_dimm_rc_bx) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tWR +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_twr() +{ + int64_t l_twr_in_ps = 0; + + // Get the tWR timing values + // tWR is speed bin independent and is + // the same for all bins within a speed grade. + // It is safe to read this from SPD because the correct nck + // value will be calulated based on our dimm speed. + { + constexpr int64_t l_twr_ftb = 0; + int64_t l_twr_mtb = 0; + int64_t l_ftb = 0; + int64_t l_mtb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb), + "Failed medium_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb), + "Failed fine_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->min_write_recovery_time(iv_dimm, l_twr_mtb), + "Failed min_write_recovery_time() for %s", mss::c_str(iv_dimm) ); + + FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWR (MTB): %ld, tWR(FTB): %ld", + l_mtb, l_ftb, l_twr_mtb, l_twr_ftb); + + // Calculate twr (in ps) + l_twr_in_ps = spd::calc_timing_from_timebase(l_twr_mtb, l_mtb, l_twr_ftb, l_ftb); + } + + { + std::vector l_attrs_dram_twr(PORTS_PER_MCS, 0); + 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), + "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", + iv_tCK_in_ps, l_twr_in_ps, l_twr_in_nck, mss::c_str(iv_dimm) ); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_twr(iv_mcs, l_attrs_dram_twr.data()) ); + + l_attrs_dram_twr[iv_port_index] = l_twr_in_nck; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TWR, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_twr, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TWR"); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for RBT +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::read_burst_type() +{ + uint8_t l_attrs_rbt[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( eff_dram_rbt(iv_mcs, &l_attrs_rbt[0][0]) ); + + l_attrs_rbt[iv_port_index][iv_dimm_index] = fapi2::ENUM_ATTR_EFF_DRAM_RBT_SEQUENTIAL; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RBT, iv_mcs, l_attrs_rbt), + "Failed setting attribute for RTB"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for TM +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note dram testing mode +/// @note always disabled +/// +fapi2::ReturnCode eff_dimm::dram_tm() +{ + uint8_t l_attrs_tm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( eff_dram_tm(iv_mcs, &l_attrs_tm[0][0]) ); + + l_attrs_tm[iv_port_index][iv_dimm_index] = fapi2::ENUM_ATTR_EFF_DRAM_TM_NORMAL; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TM, iv_mcs, l_attrs_tm), + "Failed setting attribute for BL"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for cwl +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Sets CAS Write Latency, depending on frequency and ATTR_MSS_MT_PREAMBLE +/// +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 CWL_TABLE_1 [6] = + { + {1600, 9}, + {1866, 10}, + {2133, 11}, + {2400, 12}, + {2666, 14}, + {3200, 16}, + }; + static std::pair CWL_TABLE_2 [3] = + { + {2400, 14}, + {2666, 16}, + {3200, 18}, + }; + + std::vector l_attrs_cwl(PORTS_PER_MCS, 0); + uint8_t l_cwl = 0; + uint8_t l_preamble = 0; + + FAPI_TRY( vpd_mt_preamble (iv_mca, l_preamble) ); + + // get the first nibble as according to vpd. 4-7 is read, 0-3 for write + l_preamble = l_preamble & 0x0F; + + FAPI_ASSERT( ((l_preamble == 0) || (l_preamble == 1)), + fapi2::MSS_INVALID_VPD_MT_PREAMBLE() + .set_VALUE(l_preamble) + .set_DIMM_TARGET(iv_dimm), + "Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d", + mss::c_str(iv_dimm), + l_preamble ); + + // Using an if branch because a ternary conditional wasn't working with params for find_value_from_key + if (l_preamble == 0) + { + FAPI_TRY( mss::find_value_from_key( CWL_TABLE_1, + iv_freq, l_cwl), + "Failed finding CAS Write Latency (cwl), freq: %d, preamble %d", + iv_freq, + l_preamble); + } + else + { + FAPI_TRY( mss::find_value_from_key( CWL_TABLE_2, + iv_freq, l_cwl), + "Failed finding CAS Write Latency (cwl), freq: %d, preamble %d", + iv_freq, + l_preamble); + + } + + FAPI_TRY( eff_dram_cwl(iv_mcs, l_attrs_cwl.data()) ); + l_attrs_cwl[iv_port_index] = l_cwl; + + FAPI_INF("Calculated CAS Write Latency is %d", l_cwl); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_CWL, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_cwl, PORTS_PER_MCS)), + "Failed setting attribute for cwl"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for lpasr +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note from JEDEC DDR4 DRAM MR2 page 26 +/// @note All DDR4 supports auto refresh, setting to default +/// +fapi2::ReturnCode eff_dimm::dram_lpasr() +{ + std::vector l_attrs_lpasr(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_dram_lpasr(iv_mcs, l_attrs_lpasr.data()) ); + + l_attrs_lpasr[iv_port_index] = fapi2::ENUM_ATTR_EFF_DRAM_LPASR_MANUAL_EXTENDED; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_LPASR, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_lpasr, PORTS_PER_MCS)), + "Failed setting attribute for LPASR"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for additive latency +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::additive_latency() +{ + std::vector l_attrs_dram_al(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_dram_al(iv_mcs, l_attrs_dram_al.data()) ); + + l_attrs_dram_al[iv_port_index] = fapi2::ENUM_ATTR_EFF_DRAM_AL_DISABLE; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_AL, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_al, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_AL"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DLL Reset +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dll_reset() +{ + uint8_t l_attrs_dll_reset[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( eff_dram_dll_reset(iv_mcs, &l_attrs_dll_reset[0][0]) ); + + // Default is to reset DLLs during IPL. + l_attrs_dll_reset[iv_port_index][iv_dimm_index] = fapi2::ENUM_ATTR_EFF_DRAM_DLL_RESET_YES; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DLL_RESET, iv_mcs, l_attrs_dll_reset), + "Failed setting attribute for BL"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DLL Enable +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dll_enable() +{ + uint8_t l_attrs_dll_enable[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + FAPI_TRY( eff_dram_dll_enable(iv_mcs, &l_attrs_dll_enable[0][0]) ); + + // Enable DLLs by default. + l_attrs_dll_enable[iv_port_index][iv_dimm_index] = fapi2::ENUM_ATTR_EFF_DRAM_DLL_ENABLE_YES; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DLL_ENABLE, iv_mcs, l_attrs_dll_enable), + "Failed setting attribute for BL"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for Write Level Enable +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::write_level_enable() +{ + std::vector l_attrs_wr_lvl_enable(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_dram_wr_lvl_enable(iv_mcs, l_attrs_wr_lvl_enable.data()) ); + + l_attrs_wr_lvl_enable[iv_port_index] = fapi2::ENUM_ATTR_EFF_DRAM_WR_LVL_ENABLE_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WR_LVL_ENABLE, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_wr_lvl_enable, PORTS_PER_MCS)), + "Failed setting attribute for WR_LVL_ENABLE"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for Output Buffer +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::output_buffer() +{ + std::vector l_attrs_output_buffer(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_dram_output_buffer(iv_mcs, l_attrs_output_buffer.data()) ); + + l_attrs_output_buffer[iv_port_index] = fapi2::ENUM_ATTR_EFF_DRAM_OUTPUT_BUFFER_ENABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_OUTPUT_BUFFER, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_output_buffer, PORTS_PER_MCS)), + "Failed setting attribute for OUTPUT_BUFFER"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for Vref DQ Train Value +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::vref_dq_train_value() +{ + + uint8_t l_attrs_vref_dq_train_val[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + std::vector< uint64_t > l_ranks; + + // value to set. + fapi2::buffer l_vpd_value; + fapi2::buffer l_train_value; + constexpr uint64_t VPD_TRAIN_VALUE_START = 2; + constexpr uint64_t VPD_TRAIN_VALUE_LEN = 6; + // Taken from DDR4 (this attribute is DDR4 only) spec MRS6 section VrefDQ training: values table + constexpr uint8_t JEDEC_MAX_TRAIN_VALUE = 0b00110010; + + FAPI_TRY(mss::vpd_mt_vref_dram_wr(iv_dimm, l_vpd_value)); + l_vpd_value.extractToRight(l_train_value); + + FAPI_ASSERT(l_train_value <= JEDEC_MAX_TRAIN_VALUE, + fapi2::MSS_INVALID_VPD_VREF_DRAM_WR_RANGE() + .set_MAX(JEDEC_MAX_TRAIN_VALUE) + .set_VALUE(l_train_value) + .set_DIMM_TARGET(iv_dimm), + "%s VPD DRAM VREF value out of range max 0x%02x value 0x%02x", mss::c_str(iv_dimm), + JEDEC_MAX_TRAIN_VALUE, l_train_value ); + + // Attribute to set num dimm ranks is a pre-requisite + FAPI_TRY( eff_vref_dq_train_value(iv_mcs, &l_attrs_vref_dq_train_val[0][0][0]) ); + FAPI_TRY( mss::rank::ranks(iv_dimm, l_ranks) ); + + for(const auto& l_rank : l_ranks) + { + l_attrs_vref_dq_train_val[iv_port_index][iv_dimm_index][index(l_rank)] = l_train_value; + } + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_VREF_DQ_TRAIN_VALUE, iv_mcs, l_attrs_vref_dq_train_val), + "Failed setting attribute for ATTR_EFF_VREF_DQ_TRAIN_VALUE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for Vref DQ Train Enable +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::vref_dq_train_enable() +{ + // Default mode for train enable should be normal operation mode - 0x00 + + uint8_t l_attrs_vref_dq_train_enable[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + std::vector< uint64_t > l_ranks; + + // Attribute to set num dimm ranks is a pre-requisite + FAPI_TRY( eff_vref_dq_train_enable(iv_mcs, &l_attrs_vref_dq_train_enable[0][0][0]) ); + FAPI_TRY( mss::rank::ranks(iv_dimm, l_ranks) ); + + for(const auto& l_rank : l_ranks) + { + l_attrs_vref_dq_train_enable[iv_port_index][iv_dimm_index][index(l_rank)] = 0x00; + } + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_VREF_DQ_TRAIN_ENABLE, iv_mcs, l_attrs_vref_dq_train_enable), + "Failed setting attribute for ATTR_EFF_VREF_DQ_TRAIN_ENABLE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for Vref DQ Train Range +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::vref_dq_train_range() +{ + + // Attribute to set num dimm ranks is a pre-requisite + uint8_t l_attrs_vref_dq_train_range[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + std::vector< uint64_t > l_ranks; + + // value to set. + fapi2::buffer l_vpd_value; + fapi2::buffer l_train_range; + constexpr uint64_t VPD_TRAIN_RANGE_START = 1; + FAPI_TRY(mss::vpd_mt_vref_dram_wr(iv_dimm, l_vpd_value)); + l_train_range = l_vpd_value.getBit(); + + // gets the current value of train_range + FAPI_TRY( eff_vref_dq_train_range(iv_mcs, &l_attrs_vref_dq_train_range[0][0][0]) ); + FAPI_TRY( mss::rank::ranks(iv_dimm, l_ranks) ); + + for(const auto& l_rank : l_ranks) + { + l_attrs_vref_dq_train_range[iv_port_index][iv_dimm_index][index(l_rank)] = l_train_range; + } + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_VREF_DQ_TRAIN_RANGE, iv_mcs, l_attrs_vref_dq_train_range), + "Failed setting attribute for ATTR_EFF_VREF_DQ_TRAIN_RANGE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for CA Parity Latency +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::ca_parity_latency() +{ + // TODO: RTC 159554 Update RAS related attributes + std::vector l_attrs_ca_parity_latency(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_ca_parity_latency(iv_mcs, l_attrs_ca_parity_latency.data()) ); + l_attrs_ca_parity_latency[iv_port_index] = fapi2::ENUM_ATTR_EFF_CA_PARITY_LATENCY_DISABLE; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CA_PARITY_LATENCY, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_ca_parity_latency, PORTS_PER_MCS)), + "Failed setting attribute for CA_PARITY_LATENCY"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for CRC Error Clear +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::crc_error_clear() +{ + // TODO: RTC 159554 Update RAS related attributes + std::vector l_attrs_crc_error_clear(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_crc_error_clear(iv_mcs, l_attrs_crc_error_clear.data()) ); + + l_attrs_crc_error_clear[iv_port_index] = fapi2::ENUM_ATTR_EFF_CRC_ERROR_CLEAR_CLEAR; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CRC_ERROR_CLEAR, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_crc_error_clear, PORTS_PER_MCS)), + "Failed setting attribute for CRC_ERROR_CLEAR"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for CA Parity Error Status +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::ca_parity_error_status() +{ + // TODO: RTC 159554 Update RAS related attributes + std::vector l_attrs_ca_parity_error_status(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_ca_parity_error_status(iv_mcs, l_attrs_ca_parity_error_status.data()) ); + + l_attrs_ca_parity_error_status[iv_port_index] = fapi2::ENUM_ATTR_EFF_CA_PARITY_ERROR_STATUS_CLEAR; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CA_PARITY_ERROR_STATUS, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_ca_parity_error_status, PORTS_PER_MCS)), + "Failed setting attribute for CA_PARITY_ERROR_STATUS"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for CA Parity +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::ca_parity() +{ + // TODO: RTC 159554 Update RAS related attributes + std::vector l_attrs_ca_parity(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_ca_parity(iv_mcs, l_attrs_ca_parity.data()) ); + + l_attrs_ca_parity[iv_port_index] = fapi2::ENUM_ATTR_EFF_CA_PARITY_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CA_PARITY, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_ca_parity, PORTS_PER_MCS)), + "Failed setting attribute for CA_PARITY"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for ODT Input Buffer +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::odt_input_buffer() +{ + // keeping this value as 0x01, given that we know that that works in sim + constexpr uint8_t SIM_VALUE = 0x01; + std::vector l_attrs_odt_input_buffer(PORTS_PER_MCS, 0); + + // Targets + + // keep simulation to values we know work + uint8_t is_sim = 0; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), is_sim) ); + + + FAPI_TRY( eff_odt_input_buff(iv_mcs, l_attrs_odt_input_buffer.data()) ); + + // sim vs actual hardware value + l_attrs_odt_input_buffer[iv_port_index] = is_sim ? SIM_VALUE : fapi2::ENUM_ATTR_EFF_ODT_INPUT_BUFF_ACTIVATED; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_ODT_INPUT_BUFF, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_odt_input_buffer, PORTS_PER_MCS)), + "Failed setting attribute for ODT_INPUT_BUFF"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for data_mask +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Datamask is unnused and not needed because no DBI. +/// @note Defaulted to 0 +/// +fapi2::ReturnCode eff_dimm::data_mask() +{ + std::vector l_attrs_data_mask(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_data_mask(iv_mcs, l_attrs_data_mask.data()) ); + + l_attrs_data_mask[iv_port_index] = fapi2::ENUM_ATTR_EFF_DATA_MASK_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DATA_MASK, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_data_mask, PORTS_PER_MCS)), + "Failed setting attribute for DATA_MASK"); +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for write_dbi +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note DBI is not supported +/// +fapi2::ReturnCode eff_dimm::write_dbi() +{ + std::vector l_attrs_write_dbi(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_write_dbi(iv_mcs, l_attrs_write_dbi.data()) ); + + l_attrs_write_dbi[iv_port_index] = fapi2::ENUM_ATTR_EFF_WRITE_DBI_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_WRITE_DBI, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_write_dbi, PORTS_PER_MCS)), + "Failed setting attribute for WRITE_DBI"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for read_dbi +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note read_dbi is not supported, so set to DISABLED (0) +/// @note No logic for DBI +/// +fapi2::ReturnCode eff_dimm::read_dbi() +{ + + std::vector l_attrs_read_dbi(PORTS_PER_MCS, 0); + FAPI_TRY( eff_read_dbi(iv_mcs, l_attrs_read_dbi.data()) ); + + l_attrs_read_dbi[iv_port_index] = fapi2::ENUM_ATTR_EFF_READ_DBI_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_READ_DBI, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_read_dbi, PORTS_PER_MCS)), + "Failed setting attribute for READ_DBI"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for Post Package Repair +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note write_dbi is not supported, so set to DISABLED (0) +/// @note no logic for DBI +/// +fapi2::ReturnCode eff_dimm::post_package_repair() +{ + + uint8_t l_decoder_val = 0; + 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(iv_dimm, 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), + "Failed setting attribute for DRAM_PPR"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for rd_preamble_train +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::read_preamble_train() +{ + std::vector l_attrs_rd_preamble_train(PORTS_PER_MCS, 0); + FAPI_TRY( eff_rd_preamble_train(iv_mcs, l_attrs_rd_preamble_train.data()) ); + + l_attrs_rd_preamble_train[iv_port_index] = fapi2::ENUM_ATTR_EFF_RD_PREAMBLE_TRAIN_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_RD_PREAMBLE_TRAIN, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_rd_preamble_train, PORTS_PER_MCS)), + "Failed setting attribute for RD_PREAMBLE_TRAIN"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for rd_preamble +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::read_preamble() +{ + std::vector l_attrs_rd_preamble(PORTS_PER_MCS, 0); + uint8_t l_preamble = 0; + + FAPI_TRY( vpd_mt_preamble (iv_mca, l_preamble) ) ; + l_preamble = l_preamble & 0xF0; + l_preamble = l_preamble >> 4; + + + FAPI_ASSERT( ((l_preamble == 0) || (l_preamble == 1)), + fapi2::MSS_INVALID_VPD_MT_PREAMBLE() + .set_VALUE(l_preamble) + .set_DIMM_TARGET(iv_dimm), + "Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d", + mss::c_str(iv_dimm), + l_preamble ); + + FAPI_TRY( eff_rd_preamble(iv_mcs, l_attrs_rd_preamble.data()) ); + + l_attrs_rd_preamble[iv_port_index] = l_preamble; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_RD_PREAMBLE, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_rd_preamble, PORTS_PER_MCS)), + "Failed setting attribute for RD_PREAMBLE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for wr_preamble +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::write_preamble() +{ + std::vector l_attrs_wr_preamble(PORTS_PER_MCS, 0); + uint8_t l_preamble = 0; + + FAPI_TRY( vpd_mt_preamble (iv_mca, l_preamble) ) ; + l_preamble = l_preamble & 0x0F; + FAPI_INF("WR preamble is %d", l_preamble); + + FAPI_ASSERT( ((l_preamble == 0) || (l_preamble == 1)), + fapi2::MSS_INVALID_VPD_MT_PREAMBLE() + .set_VALUE(l_preamble) + .set_DIMM_TARGET(iv_dimm), + "Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d", + mss::c_str(iv_dimm), + l_preamble ); + + FAPI_TRY( eff_wr_preamble(iv_mcs, l_attrs_wr_preamble.data()) ); + + l_attrs_wr_preamble[iv_port_index] = l_preamble; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_WR_PREAMBLE, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_wr_preamble, PORTS_PER_MCS)), + "Failed setting attribute for RD_PREAMBLE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for self_ref_abort +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::self_refresh_abort() +{ + std::vector l_attrs_self_ref_abort(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_self_ref_abort(iv_mcs, l_attrs_self_ref_abort.data()) ); + + l_attrs_self_ref_abort[iv_port_index] = fapi2::ENUM_ATTR_EFF_SELF_REF_ABORT_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_SELF_REF_ABORT, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_self_ref_abort, PORTS_PER_MCS)), + "Failed setting attribute for SELF_REF_ABORT"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for cs_cmd_latency +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::cs_to_cmd_addr_latency() +{ + std::vector l_attrs_cs_cmd_latency(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_cs_cmd_latency(iv_mcs, l_attrs_cs_cmd_latency.data()) ); + + l_attrs_cs_cmd_latency[iv_port_index] = fapi2::ENUM_ATTR_EFF_CS_CMD_LATENCY_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CS_CMD_LATENCY, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_cs_cmd_latency, PORTS_PER_MCS)), + "Failed setting attribute for CS_CMD_LATENCY"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for int_vref_mon +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::internal_vref_monitor() +{ + std::vector l_attrs_int_vref_mon(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_internal_vref_monitor(iv_mcs, l_attrs_int_vref_mon.data()) ); + + l_attrs_int_vref_mon[iv_port_index] = fapi2::ENUM_ATTR_EFF_INTERNAL_VREF_MONITOR_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_INTERNAL_VREF_MONITOR, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_int_vref_mon, PORTS_PER_MCS)), + "Failed setting attribute for INT_VREF_MON"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for powerdown_mode +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::max_powerdown_mode() +{ + std::vector l_attrs_powerdown_mode(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_max_powerdown_mode(iv_mcs, l_attrs_powerdown_mode.data()) ); + + l_attrs_powerdown_mode[iv_port_index] = fapi2::ENUM_ATTR_EFF_MAX_POWERDOWN_MODE_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MAX_POWERDOWN_MODE, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_powerdown_mode, PORTS_PER_MCS)), + "Failed setting attribute for POWERDOWN_MODE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for mpr_rd_format +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::mpr_read_format() +{ + std::vector l_attrs_mpr_rd_format(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_mpr_rd_format(iv_mcs, l_attrs_mpr_rd_format.data()) ); + + // Serial format is standard for Nimbus and needed for PHY calibration (draminit_training) + l_attrs_mpr_rd_format[iv_port_index] = fapi2::ENUM_ATTR_EFF_MPR_RD_FORMAT_SERIAL; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MPR_RD_FORMAT, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_mpr_rd_format, PORTS_PER_MCS)), + "Failed setting attribute for MPR_RD_FORMAT"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for CRC write latency +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::crc_wr_latency() +{ + std::vector l_attrs_crc_wr_latency(PORTS_PER_MCS, 0); + + // keep simulation to values we know work + uint8_t is_sim = 0; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), is_sim) ); + + FAPI_TRY( eff_crc_wr_latency(iv_mcs, l_attrs_crc_wr_latency.data()) ); + + // keep simulation to values we know work + if(is_sim) + { + l_attrs_crc_wr_latency[iv_port_index] = 0x05; + } + // set the attribute according to frequency + else + { + // TODO RTC:159481 - update CRC write latency to include 2667 + // currently, JEDEC defines the following + // crc wr latency - freq + // 4 - 1600 + // 5 - 1866, 2133, 2400 + // 6 - TBD + // Nimbus only supports 1866->2400 on the current list + // 2667 is not noted. We will set crc_wr_latency to 0x05 until JEDEC value is updated + // When JEDEC defines the 2667 value we can change this, but leave the sim value as 0x05 + l_attrs_crc_wr_latency[iv_port_index] = 0x05; + } + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CRC_WR_LATENCY, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_crc_wr_latency, PORTS_PER_MCS)), + "Failed setting attribute for CRC WRITE LATENCY"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for temperature readout +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::temp_readout() +{ + std::vector l_attrs_temp_readout(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_temp_readout(iv_mcs, l_attrs_temp_readout.data()) ); + + // Disabled for mainline mode + l_attrs_temp_readout[iv_port_index] = fapi2::ENUM_ATTR_EFF_TEMP_READOUT_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_TEMP_READOUT, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_temp_readout, PORTS_PER_MCS)), + "Failed setting attribute for TEMP_READOUT"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for per DRAM addressability +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::per_dram_addressability() +{ + std::vector l_attrs_per_dram_access(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_per_dram_access(iv_mcs, l_attrs_per_dram_access.data()) ); + + // PDA is disabled in mainline functionality + l_attrs_per_dram_access[iv_port_index] = fapi2::ENUM_ATTR_EFF_PER_DRAM_ACCESS_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PER_DRAM_ACCESS, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_per_dram_access, PORTS_PER_MCS)), + "Failed setting attribute for PER_DRAM_ACCESS"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for geardown mode +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::geardown_mode() +{ + std::vector l_attrs_geardown_mode(PORTS_PER_MCS, 0); + + // Geardown maps directly to autoset = 0 gets 1/2 rate, 1 get 1/4 rate. + FAPI_TRY( eff_geardown_mode(iv_mcs, l_attrs_geardown_mode.data()) ); + + // If the MRW states 'auto' we use what's in VPD, otherwise we use what's in the MRW. + // We remove 1 from the value as that matches the expectations in the MR perfectly. + l_attrs_geardown_mode[iv_port_index] = mss::two_n_mode_helper(iv_dimm); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_GEARDOWN_MODE, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_geardown_mode, PORTS_PER_MCS)), + "Failed setting attribute for GEARDOWN_MODE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for MPR page +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::mpr_page() +{ + std::vector l_attrs_mpr_page(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_mpr_page(iv_mcs, l_attrs_mpr_page.data()) ); + + // page0 is needed for PHY calibration algorithm (run in draminit_training) + l_attrs_mpr_page[iv_port_index] = fapi2::ENUM_ATTR_EFF_MPR_PAGE_PG0; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MPR_PAGE, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_mpr_page, PORTS_PER_MCS)), + "Failed setting attribute for MPR_PAGE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for MPR mode +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::mpr_mode() +{ + std::vector l_attrs_mpr_mode(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_mpr_mode(iv_mcs, l_attrs_mpr_mode.data()) ); + + // MPR mode is disabled for mainline functionality + l_attrs_mpr_mode[iv_port_index] = fapi2::ENUM_ATTR_EFF_MPR_MODE_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MPR_MODE, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_mpr_mode, PORTS_PER_MCS)), + "Failed setting attribute for MPR_MODE"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for write CRC +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::write_crc() +{ + // TODO: RTC 159554 Update RAS related attributes + std::vector l_attrs_write_crc(PORTS_PER_MCS, 0); + + uint8_t l_mrw = 0; + + FAPI_TRY( eff_write_crc(iv_mcs, l_attrs_write_crc.data()) ); + FAPI_TRY( mrw_dram_write_crc(l_mrw) ); + + l_attrs_write_crc[iv_port_index] = (l_mrw == fapi2::ENUM_ATTR_MSS_MRW_DRAM_WRITE_CRC_ENABLE) ? + fapi2::ENUM_ATTR_EFF_WRITE_CRC_ENABLE : + fapi2::ENUM_ATTR_EFF_WRITE_CRC_DISABLE; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_WRITE_CRC, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_write_crc, PORTS_PER_MCS)), + "Failed setting attribute for WRITE_CRC"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for ZQ Calibration +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::zqcal_interval() +{ + std::vector l_attrs_zqcal_interval(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_zqcal_interval(iv_mcs, l_attrs_zqcal_interval.data()) ); + + // Calculate ZQCAL Interval based on the following equation from Ken: + // 0.5 + // ------------------------------ = 13.333ms + // (1.5 * 10) + (0.15 * 150) + // (13333 * ATTR_MSS_FREQ) / 2 + + l_attrs_zqcal_interval[iv_port_index] = 13333 * iv_freq / 2; + + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_ZQCAL_INTERVAL, + iv_mcs, + UINT32_VECTOR_TO_1D_ARRAY(l_attrs_zqcal_interval, PORTS_PER_MCS)), + "Failed setting attribute for ZQCAL_INTERVAL"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for MEMCAL Calibration +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::memcal_interval() +{ + std::vector l_attrs_memcal_interval(PORTS_PER_MCS, 0); + + FAPI_TRY( eff_memcal_interval(iv_mcs, l_attrs_memcal_interval.data()) ); + + // Calculate MEMCAL Interval based on 1sec interval across all bits per DP16 + // (62500 * ATTR_MSS_FREQ) / 2 + l_attrs_memcal_interval[iv_port_index] = 62500 * iv_freq / 2; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MEMCAL_INTERVAL, + iv_mcs, + UINT32_VECTOR_TO_1D_ARRAY(l_attrs_memcal_interval, PORTS_PER_MCS)), + "Failed setting attribute for MEMCAL_INTERVAL"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRP +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trp() +{ + + int64_t l_trp_in_ps = 0; + + // Calculate tRP (in ps) + { + int64_t l_trp_mtb = 0; + int64_t l_trp_ftb = 0; + int64_t l_ftb = 0; + int64_t l_mtb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb), + "Failed medium_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb), + "Failed fine_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->min_row_precharge_delay_time(iv_dimm, l_trp_mtb), + "Failed min_row_precharge_delay_time() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_offset_min_trp(iv_dimm, l_trp_ftb), + "Failed fine_offset_min_trp() for %s", mss::c_str(iv_dimm) ); + + FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tRP (MTB): %ld, tRP(FTB): %ld", + l_mtb, l_ftb, l_trp_mtb, l_trp_ftb); + + l_trp_in_ps = spd::calc_timing_from_timebase(l_trp_mtb, l_mtb, l_trp_ftb, l_ftb); + } + + // SPD spec gives us the minimum... compute our worstcase (maximum) from JEDEC + { + // Declaring as int64_t to fix std::max compile + const int64_t l_trp = mss::ps_to_cycles(iv_dimm, mss::trtp()); + l_trp_in_ps = std::max( l_trp_in_ps , l_trp ); + } + + { + std::vector l_attrs_dram_trp(PORTS_PER_MCS, 0); + 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), + "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", + iv_tCK_in_ps, l_trp_in_ps, l_trp_in_nck, mss::c_str(iv_dimm) ); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_trp(iv_mcs, l_attrs_dram_trp.data()) ); + + l_attrs_dram_trp[iv_port_index] = l_trp_in_nck ; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRP, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trp, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TRP"); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRCD +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trcd() +{ + int64_t l_trcd_in_ps = 0; + + // Calculate tRCD (in ps) + // Get the tRCD timing values + // tRCD is speed bin dependent and has a unique + // value for each speed bin so it is safe to + // read from SPD because the correct nck + // value will be calulated based on our dimm speed. + { + int64_t l_trcd_mtb = 0; + int64_t l_trcd_ftb = 0; + int64_t l_ftb = 0; + int64_t l_mtb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb), + "Failed medium_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb), + "Failed fine_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->min_ras_to_cas_delay_time(iv_dimm, l_trcd_mtb), + "Failed min_ras_to_cas_delay_time() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_offset_min_trcd(iv_dimm, l_trcd_ftb), + "Failed fine_offset_min_trcd() for %s", mss::c_str(iv_dimm) ); + + FAPI_INF("medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCD (MTB): %ld, tRCD (FTB): %ld", + l_mtb, l_ftb, l_trcd_mtb, l_trcd_ftb); + + l_trcd_in_ps = spd::calc_timing_from_timebase(l_trcd_mtb, l_mtb, l_trcd_ftb, l_ftb); + } + + { + std::vector l_attrs_dram_trcd(PORTS_PER_MCS, 0); + 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), + "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", + iv_tCK_in_ps, l_trcd_in_ps, l_trcd_in_nck, mss::c_str(iv_dimm)); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_trcd(iv_mcs, l_attrs_dram_trcd.data()) ); + + l_attrs_dram_trcd[iv_port_index] = l_trcd_in_nck; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRCD, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trcd, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TRCD"); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRC +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trc() +{ + int64_t l_trc_in_ps = 0; + + // Calculate trc (in ps) + { + int64_t l_trc_mtb = 0; + int64_t l_trc_ftb = 0; + int64_t l_ftb = 0; + int64_t l_mtb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb), + "Failed medium_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb), + "Failed fine_timebase() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->min_active_to_active_refresh_delay_time(iv_dimm, l_trc_mtb), + "Failed min_active_to_active_refresh_delay_time() for %s", mss::c_str(iv_dimm) ); + FAPI_TRY( iv_pDecoder->fine_offset_min_trc(iv_dimm, l_trc_ftb), + "Failed fine_offset_min_trc() for %s", mss::c_str(iv_dimm) ); + + FAPI_INF("medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCmin (MTB): %ld, tRCmin(FTB): %ld", + l_mtb, l_ftb, l_trc_mtb, l_trc_ftb); + + l_trc_in_ps = spd::calc_timing_from_timebase(l_trc_mtb, l_mtb, l_trc_ftb, l_ftb); + } + + { + std::vector l_attrs_dram_trc(PORTS_PER_MCS, 0); + uint8_t l_trc_in_nck = 0; + + // Calculate nck + FAPI_TRY( spd::calc_nck(l_trc_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trc_in_nck), + "Error in calculating trc for target %s, with value of l_trc_in_ps: %d", + mss::c_str(iv_dimm), l_trc_in_ps ); + + FAPI_INF( "tCK (ps): %d, tRC (ps): %d, tRC (nck): %d for target: %s", + iv_tCK_in_ps, l_trc_in_ps, l_trc_in_nck, mss::c_str(iv_dimm) ); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_trc(iv_mcs, l_attrs_dram_trc.data()) ); + + l_attrs_dram_trc[iv_port_index] = l_trc_in_nck; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRC, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trc, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TRC"); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tWTR_L +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_twtr_l() +{ + int64_t l_twtr_l_in_ps = 0; + + // Calculate twtr_l (in ps) + { + constexpr int64_t l_twtr_l_ftb = 0; + int64_t l_twtr_l_mtb = 0; + int64_t l_ftb = 0; + int64_t l_mtb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb) ); + FAPI_TRY( iv_pDecoder->min_twtr_l(iv_dimm, l_twtr_l_mtb) ); + + FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", + l_mtb, l_ftb, l_twtr_l_mtb, l_twtr_l_ftb ); + + l_twtr_l_in_ps = spd::calc_timing_from_timebase(l_twtr_l_mtb, l_mtb, l_twtr_l_ftb, l_ftb); + } + + + { + std::vector l_attrs_dram_twtr_l(PORTS_PER_MCS, 0); + 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), + "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", + iv_tCK_in_ps, l_twtr_l_in_ps, l_twtr_l_in_nck, mss::c_str(iv_dimm) ); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_twtr_l(iv_mcs, l_attrs_dram_twtr_l.data()) ); + + l_attrs_dram_twtr_l[iv_port_index] = l_twtr_l_in_nck; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TWTR_L, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_twtr_l, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TWTR_L"); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tWTR_S +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_twtr_s() +{ + int64_t l_twtr_s_in_ps = 0; + + // Calculate twtr_s (in ps) + { + constexpr int64_t l_twtr_s_ftb = 0; + int64_t l_twtr_s_mtb = 0; + int64_t l_ftb = 0; + int64_t l_mtb = 0; + + FAPI_TRY( iv_pDecoder->medium_timebase(iv_dimm, l_mtb) ); + FAPI_TRY( iv_pDecoder->fine_timebase(iv_dimm, l_ftb) ); + FAPI_TRY( iv_pDecoder->min_twtr_s(iv_dimm, l_twtr_s_mtb) ); + + FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", + l_mtb, l_ftb, l_twtr_s_mtb, l_twtr_s_ftb ); + + l_twtr_s_in_ps = spd::calc_timing_from_timebase(l_twtr_s_mtb, l_mtb, l_twtr_s_ftb, l_ftb); + } + + { + std::vector l_attrs_dram_twtr_s(PORTS_PER_MCS, 0); + 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), + "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", + iv_tCK_in_ps, l_twtr_s_in_ps, l_twtr_s_in_nck, mss::c_str(iv_dimm) ); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_twtr_s(iv_mcs, l_attrs_dram_twtr_s.data()) ); + + l_attrs_dram_twtr_s[iv_port_index] = l_twtr_s_in_nck; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TWTR_S, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_twtr_s, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TWTR_S"); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRRD_S +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trrd_s() +{ + + std::vector l_attrs_dram_trrd_s(PORTS_PER_MCS, 0); + uint64_t l_trrd_s_in_nck = 0; + uint8_t l_stack_type = 0; + uint8_t l_dram_width = 0; + + FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(iv_dimm, l_stack_type) ); + FAPI_TRY( iv_pDecoder->device_width(iv_dimm, l_dram_width), + "Failed to access device_width()"); + + // From the SPD Spec: + // At some frequencies, a minimum number of clocks may be required resulting + // in a larger tRRD_Smin value than indicated in the SPD. + // tRRD_S (3DS) is speed bin independent. + // So we won't read this from SPD and choose the correct value based on mss_freq + + if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) + { + FAPI_TRY( trrd_s_slr(iv_dimm, l_trrd_s_in_nck) ); + } + else + { + // Non-3DS + FAPI_TRY( mss::trrd_s(iv_dimm, l_dram_width, l_trrd_s_in_nck) ); + } + + FAPI_INF("SDRAM width: %d, tRRD_S (nck): %d for target: %s", + l_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()) ); + + l_attrs_dram_trrd_s[iv_port_index] = l_trrd_s_in_nck; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_S, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_s, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TRRD_S"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRRD_L +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trrd_l() +{ + + std::vector l_attrs_dram_trrd_l(PORTS_PER_MCS, 0); + uint64_t l_trrd_l_in_nck = 0; + uint8_t l_stack_type = 0; + uint8_t l_dram_width = 0; + + FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(iv_dimm, l_stack_type), + "Failed prim_sdram_signal_loading()" ); + FAPI_TRY( iv_pDecoder->device_width(iv_dimm, l_dram_width), + "Failed to access device_width()"); + + // From the SPD Spec: + // At some frequencies, a minimum number of clocks may be required resulting + // in a larger tRRD_Smin value than indicated in the SPD. + // tRRD_S (3DS) is speed bin independent. + // So we won't read this from SPD and choose the correct value based on mss_freq + + if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) + { + FAPI_TRY( trrd_l_slr(iv_dimm, l_trrd_l_in_nck) ); + } + else + { + FAPI_TRY( mss::trrd_l(iv_dimm, l_dram_width, l_trrd_l_in_nck), "Failed trrd_l()" ); + } + + FAPI_INF("SDRAM width: %d, tRRD_L (nck): %d for target: %s", + l_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()) ); + + l_attrs_dram_trrd_l[iv_port_index] = l_trrd_l_in_nck; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_L, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_l, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TRRD_L"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRRD_dlr +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trrd_dlr() +{ + + std::vector l_attrs_dram_trrd_dlr(PORTS_PER_MCS, 0); + constexpr uint64_t l_trrd_dlr_in_nck = trrd_dlr(); + + FAPI_INF("tRRD_dlr (nck): %d for target: %s", l_trrd_dlr_in_nck, mss::c_str(iv_dimm)); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_trrd_dlr(iv_mcs, l_attrs_dram_trrd_dlr.data()) ); + + l_attrs_dram_trrd_dlr[iv_port_index] = l_trrd_dlr_in_nck; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_DLR, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_dlr, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TRRD_DLR"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tfaw +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_tfaw() +{ + + std::vector l_attrs_dram_tfaw(PORTS_PER_MCS, 0); + uint64_t l_tfaw_in_nck = 0; + uint8_t l_stack_type = 0; + uint8_t l_dram_width = 0; + + FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(iv_dimm, l_stack_type), + "Failed prim_sdram_signal_loading()"); + FAPI_TRY( iv_pDecoder->device_width(iv_dimm, l_dram_width), + "Failed device_width()"); + + if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) + { + FAPI_TRY( tfaw_slr(iv_dimm, l_dram_width, l_tfaw_in_nck), "Failed tfaw_slr()"); + } + else + { + FAPI_TRY( mss::tfaw(iv_dimm, l_dram_width, l_tfaw_in_nck), "Failed tfaw()" ); + } + + FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", + l_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()) ); + + l_attrs_dram_tfaw[iv_port_index] = l_tfaw_in_nck; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TFAW, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tfaw, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TFAW"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tFAW_DLR +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_tfaw_dlr() +{ + + std::vector l_attrs_dram_tfaw_dlr(PORTS_PER_MCS, 0); + constexpr uint64_t l_tfaw_dlr_in_nck = tfaw_dlr(); + + FAPI_INF("tFAW_dlr (nck): %d for target: %s", l_tfaw_dlr_in_nck, mss::c_str(iv_dimm)); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_tfaw_dlr(iv_mcs, l_attrs_dram_tfaw_dlr.data()) ); + + l_attrs_dram_tfaw_dlr[iv_port_index] = l_tfaw_dlr_in_nck; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TFAW_DLR, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tfaw_dlr, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TFAW_DLR"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRAS +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_tras() +{ + + // tRAS is bin independent so we don't read this from SPD + // which will give the best timing value for the dimm + // (like 2400 MT/s) which may be different than the system + // speed (if we were being limited by VPD or MRW restrictions) + const uint64_t l_tras_in_ps = mss::tras(iv_dimm); + + // Calculate nck + std::vector l_attrs_dram_tras(PORTS_PER_MCS, 0); + uint8_t l_tras_in_nck = 0; + + // Cast needed for calculations to be done on the same integral type + // as required by template deduction. We have iv_tCK_in_ps as a signed + // integer because we have other timing values that calculations do + // addition with negative integers. + FAPI_TRY( spd::calc_nck(l_tras_in_ps, + static_cast(iv_tCK_in_ps), + INVERSE_DDR4_CORRECTION_FACTOR, + l_tras_in_nck), + "Error in calculating tras_l for target %s, with value of l_twtr_in_ps: %d", + mss::c_str(iv_dimm), l_tras_in_ps); + + FAPI_INF("tCK (ps): %d, tRAS (ps): %d, tRAS (nck): %d for target: %s", + iv_tCK_in_ps, l_tras_in_ps, l_tras_in_nck, mss::c_str(iv_dimm)); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_tras(iv_mcs, l_attrs_dram_tras.data()) ); + + l_attrs_dram_tras[iv_port_index] = l_tras_in_nck; + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRAS, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tras, PORTS_PER_MCS)), + "Failed setting attribute for tRAS"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for tRTP +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::dram_trtp() +{ + // Values from proposed DDR4 Full spec update(79-4A) + // Item No. 1716.78C + // Page 241 & 246 + int64_t constexpr l_max_trtp_in_ps = trtp(); + + std::vector l_attrs_dram_trtp(PORTS_PER_MCS, 0); + 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), + "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); + + FAPI_INF("tCK (ps): %d, tRTP (ps): %d, tRTP (nck): %d", + iv_tCK_in_ps, l_max_trtp_in_ps, l_calc_trtp_in_nck); + + // Get & update MCS attribute + FAPI_TRY( eff_dram_trtp(iv_mcs, l_attrs_dram_trtp.data()) ); + + l_attrs_dram_trtp[iv_port_index] = l_calc_trtp_in_nck; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRTP, + iv_mcs, + UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trtp, PORTS_PER_MCS)), + "Failed setting attribute for DRAM_TRTP"); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets the RTT_NOM value for the eff_dimm +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note used for MRS01 +/// +fapi2::ReturnCode eff_rdimm::dram_rtt_nom() +{ + constexpr size_t RTT_NOM_MAP_SIZE = 8; + uint8_t l_decoder_val = 0; + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + + // Temp holders to grab attributes to then parse into value for this dimm and rank + uint8_t l_rtt_nom[MAX_RANK_PER_DIMM] {}; + // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking + // for mss::index 1. So this doesn't correspond directly with the table in the JEDEC spec, + // as that's not in "denominator order." + // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 + constexpr uint8_t rtt_nom_map[RTT_NOM_MAP_SIZE] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; + + size_t l_rtt_nom_index = 0; + std::vector< uint64_t > l_ranks; + + FAPI_TRY( mss::vpd_mt_dram_rtt_nom(iv_dimm, &(l_rtt_nom[0])) ); + FAPI_TRY( eff_dram_rtt_nom(iv_mcs, &l_mcs_attrs[0][0][0]) ); + + // Calculate the value for each rank and store in attribute + + FAPI_TRY(mss::rank::ranks(iv_dimm, l_ranks)); + + for (const auto& l_rank : l_ranks) + { + // We have to be careful about 0 + l_rtt_nom_index = (l_rtt_nom[mss::index(l_rank)] == 0) ? + 0 : fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_NOM_OHM240 / l_rtt_nom[mss::index(l_rank)]; + + // Make sure it's a valid mss::index + fapi2::Assert( l_rtt_nom_index < RTT_NOM_MAP_SIZE); + + // Map from RTT_NOM array to the value in the map + l_decoder_val = rtt_nom_map[l_rtt_nom_index]; + + // Store value and move to next rank + l_mcs_attrs[iv_port_index][iv_dimm_index][mss::index(l_rank)] = l_decoder_val; + } + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_NOM, iv_mcs, l_mcs_attrs) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for the RTT_NOM value +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note used for MRS01 +/// +fapi2::ReturnCode eff_lrdimm::dram_rtt_nom() +{ + std::vector< uint64_t > l_ranks; + + uint8_t l_decoder_val = 0; + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + 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)); + + // 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 + FAPI_TRY(mss::rank::ranks(iv_dimm, l_ranks)); + + for (const auto& l_rank : l_ranks) + { + l_mcs_attrs[iv_port_index][iv_dimm_index][mss::index(l_rank)] = l_decoder_val; + } + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_NOM, iv_mcs, l_mcs_attrs) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for the RTT_WR value from SPD +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note used for MRS02 +/// +fapi2::ReturnCode eff_rdimm::dram_rtt_wr() +{ + std::vector< uint64_t > l_ranks; + uint8_t l_encoding = 0; + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + + FAPI_TRY( eff_dram_rtt_wr(iv_mcs, &l_mcs_attrs[0][0][0]) ); + + // Get RTT_WR from VPD + uint8_t l_dram_rtt_wr[MAX_RANK_PER_DIMM]; + FAPI_TRY( mss::vpd_mt_dram_rtt_wr(iv_dimm, &(l_dram_rtt_wr[0])) ); + + // Calculate the value for each rank and store in attribute + FAPI_TRY(mss::rank::ranks(iv_dimm, l_ranks)); + static const std::vector< std::pair > l_rtt_wr_map = + { + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_DISABLE, 0b000}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_HIGHZ, 0b011}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM80, 0b100}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM120, 0b001}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM240, 0b010} + }; + + for (const auto& l_rank : l_ranks) + { + FAPI_ASSERT( mss::find_value_from_key(l_rtt_wr_map, l_dram_rtt_wr[mss::index(l_rank)], l_encoding), + fapi2::MSS_INVALID_RTT_WR() + .set_RTT_WR(l_dram_rtt_wr[l_rank]) + .set_RANK(mss::index(l_rank)) + .set_DIMM_TARGET(iv_dimm), + "unknown RTT_WR 0x%x (%s rank %d), dynamic odt off", + l_dram_rtt_wr[mss::index(l_rank)], + mss::c_str(iv_dimm), + mss::index(l_rank)); + + // Store value and move to next rank + l_mcs_attrs[iv_port_index][iv_dimm_index][mss::index(l_rank)] = l_encoding; + } + + // Set the attribute + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_WR, iv_mcs, l_mcs_attrs) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for the RTT_WR value from SPD +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note used for MRS02 +/// +fapi2::ReturnCode eff_lrdimm::dram_rtt_wr() +{ + std::vector< uint64_t > l_ranks; + + uint8_t l_decoder_val = 0; + 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)); + + // 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 + FAPI_TRY(mss::rank::ranks(iv_dimm, l_ranks)); + + for (const auto& l_rank : l_ranks) + { + l_mcs_attrs[iv_port_index][iv_dimm_index][mss::index(l_rank)] = l_decoder_val; + } + + // Set the attribute + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_WR, iv_mcs, l_mcs_attrs) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for the RTT_PARK value from SPD +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note used for MRS05 +/// +fapi2::ReturnCode eff_rdimm::dram_rtt_park() +{ + std::vector< uint64_t > l_ranks; + + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + + // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking + // 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 }; + + 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]) ); + + // Calculate the value for each rank and store in attribute + FAPI_TRY(mss::rank::ranks(iv_dimm, l_ranks)); + + for (const auto& l_rank : l_ranks) + { + uint8_t l_rtt_park_index = 0; + + // We have to be careful about 0 + l_rtt_park_index = (l_rtt_park[mss::index(l_rank)] == 0) ? + 0 : fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_PARK_240OHM / l_rtt_park[mss::index(l_rank)]; + + // Map from RTT_PARK array to the value in the map + l_mcs_attrs[iv_port_index][iv_dimm_index][mss::index(l_rank)] = rtt_park_map[l_rtt_park_index]; + } + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_PARK, iv_mcs, l_mcs_attrs) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for the RTT_PARK value from SPD +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note used for MRS05 +/// +fapi2::ReturnCode eff_lrdimm::dram_rtt_park() +{ + uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; + uint8_t l_decoder_val_01 = 0; + uint8_t l_decoder_val_23 = 0; + + 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));; + + // Setting the four rank values for this dimm + // Rank 0 and 1 have the same value, l_decoder_val_01 + // Rank 2 and 3 have the same value, l_decoder_val_23 + l_mcs_attrs[iv_port_index][iv_dimm_index][0] = l_decoder_val_01; + l_mcs_attrs[iv_port_index][iv_dimm_index][1] = l_decoder_val_01; + l_mcs_attrs[iv_port_index][iv_dimm_index][2] = l_decoder_val_23; + l_mcs_attrs[iv_port_index][iv_dimm_index][3] = l_decoder_val_23; + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_PARK, iv_mcs, l_mcs_attrs) ); + +fapi_try_exit: + return fapi2::current_err; +} + + +/// +/// @brief Determines & sets effective config for DIMM BC00 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Host Interface DQ RTT_NOM Control +/// From DDR4DB02 Spec Rev 0.95 +/// Page 56 table 23 +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc00() +{ + uint8_t l_decoder_val; + constexpr size_t RTT_NOM_MAP_SIZE = 8; + + // All LRDIMMS in the eyes of the MC are 1 rank, so say it's rank 0 for calculations + uint8_t l_rank = 0; + // value to mss::index into rtt_nom_map using rtt_nom attribute + size_t l_rtt_nom_index = 0; + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc00[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking + // for mss::index 1. So this doesn't correspond directly with the table in the JEDEC spec, + // as that's not in "denominator order." + // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 + constexpr uint8_t rtt_nom_map[RTT_NOM_MAP_SIZE] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; + + // Temp holders to grab attributes to then parse into value for this dimm and rank + uint8_t l_rtt_nom[MAX_RANK_PER_DIMM] = {}; + + FAPI_TRY( mss::vpd_mt_dram_rtt_nom(iv_dimm, &(l_rtt_nom[0])) ); + + // Calculate the value for each rank and store in attribute + + // We have to be careful about 0 + l_rtt_nom_index = (l_rtt_nom[l_rank] == 0) ? + 0 : fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_NOM_OHM240 / l_rtt_nom[l_rank]; + + // Make sure it's a valid mss::index + // + fapi2::Assert( l_rtt_nom_index < RTT_NOM_MAP_SIZE); + + // Map from RTT_NOM array to the value in the map + l_decoder_val = rtt_nom_map[l_rtt_nom_index]; + // Store value and move to next rank + + // Read, modify, write + FAPI_TRY( eff_dimm_ddr4_bc00(iv_mcs, &l_attrs_dimm_bc00[0][0]) ); + l_attrs_dimm_bc00[iv_port_index][iv_dimm_index] = l_decoder_val; + + FAPI_INF("%s: BC00 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc00[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC00, iv_mcs, l_attrs_dimm_bc00) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC01 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Host Interface DQ RTT_WR Control +/// From DDR4DB02 Spec Rev 0.95 +/// Page 56 Table 24 +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc01() +{ + // All LRDIMMS are treated as 1 rank DIMMS from the MC point of view + uint8_t l_rank = 0; + uint8_t l_encoding = 0; + uint8_t l_attrs_dimm_bc01[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // Get RTT_WR from VPD + uint8_t l_dram_rtt_wr[MAX_RANK_PER_DIMM]; + FAPI_TRY( mss::vpd_mt_dram_rtt_wr(iv_dimm, &(l_dram_rtt_wr[0])) ); + + static const std::vector< std::pair > l_rtt_wr_map = + { + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_DISABLE, 0b000}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_HIGHZ, 0b011}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM80, 0b100}, // RZQ/3 + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM120, 0b001}, // RZQ/2 + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM240, 0b010} + }; + + FAPI_ASSERT( mss::find_value_from_key(l_rtt_wr_map, l_dram_rtt_wr[l_rank], l_encoding), + fapi2::MSS_INVALID_RTT_WR() + .set_RTT_WR(l_dram_rtt_wr[l_rank]) + .set_RANK(mss::index(l_rank)) + .set_DIMM_TARGET(iv_dimm), + "unknown RTT_WR 0x%x (%s rank %d), dynamic odt off", + l_dram_rtt_wr[mss::index(l_rank)], + mss::c_str(iv_dimm), + l_rank); + + // Read, modify, write + FAPI_TRY( eff_dimm_ddr4_bc01(iv_mcs, &l_attrs_dimm_bc01[0][0]) ); + + l_attrs_dimm_bc01[iv_port_index][iv_dimm_index] = l_encoding; + + FAPI_INF("%s: BC01 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc01[iv_port_index][iv_dimm_index] ); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC01, iv_mcs, l_attrs_dimm_bc01) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC02 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Host Interface DQ RTT_PARK Control +/// From DDR4DB02 Spec Rev 0.95 +/// Page 56 Table 25 +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc02() +{ + uint8_t l_decoder_val = 0; + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc02[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + { + uint8_t l_rank = 0; + // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking + // 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 }; + + uint8_t l_rtt_park[MAX_RANK_PER_DIMM]; + + FAPI_TRY( mss::vpd_mt_dram_rtt_park(iv_dimm, &(l_rtt_park[0])) ); + + // Calculate the value for each rank and store in attribute + uint8_t l_rtt_park_index = 0; + + // We have to be careful about 0 + l_rtt_park_index = (l_rtt_park[l_rank] == 0) ? + 0 : fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_PARK_240OHM / l_rtt_park[l_rank]; + + // Map from RTT_PARK array to the value in the map + l_decoder_val = rtt_park_map[l_rtt_park_index]; + } + + FAPI_TRY( eff_dimm_ddr4_bc02(iv_mcs, &l_attrs_dimm_bc02[0][0]) ); + l_attrs_dimm_bc02[iv_port_index][iv_dimm_index] = l_decoder_val; + + FAPI_INF("%s: BC02 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc02[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC02, iv_mcs, l_attrs_dimm_bc02) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC03 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Host Interface DQ Driver Control Word +/// From DDR4DB01 Spec Rev 1.0 +/// 2.5.5 Page 57 table 36 +/// +fapi2::ReturnCode eff_lrdimm_db01::dimm_bc03() +{ + uint8_t l_attrs_dimm_bc03[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // constants + // Little table to map Output Driver Imepdance Control according to DDR4DB02 4.5 + static const std::vector< std::pair > l_odic_map = + { + // Yes, this is the encoding listed in the JEDEC spec... + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM34, 0b001}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM40, 0b000}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM48, 0b010}, + }; + + // Treat buffer as 0th rank. LRDIMM in memory controller's eyes only have 1 rank + constexpr size_t l_rank = 0; + fapi2::buffer l_result = 0; + uint64_t l_ohm_value = 0; + uint8_t l_encoding = 0; + // attributes + uint8_t l_odic[MAX_RANK_PER_DIMM] = {}; + FAPI_TRY( mss::vpd_mt_dram_drv_imp_dq_dqs(iv_dimm, &(l_odic[0])) ); + // Get the Ohm value for rank 0 + l_ohm_value = l_odic[l_rank]; + + // Now get the proper encoding for that value. Fail if not found + // Change for rev level + FAPI_ASSERT( mss::find_value_from_key(l_odic_map, l_ohm_value, l_encoding), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(1) + .set_PARAMETER(OUTPUT_IMPEDANCE) + .set_PARAMETER_VALUE(l_odic[mss::index(l_rank)]) + .set_DIMM_IN_ERROR(iv_dimm), + "Bad value for output driver impedance: %d (%s)", + l_odic[mss::index(l_rank)], mss::c_str(iv_dimm)); + + l_result = l_encoding; + + // Using a writeBit for clarity sake + // Enabling Host interface DQ/DQS driver + l_result.writeBit(BC03_DQ_ENABLE); + + FAPI_TRY( eff_dimm_ddr4_bc03(iv_mcs, &l_attrs_dimm_bc03[0][0]) ); + l_attrs_dimm_bc03[iv_port_index][iv_dimm_index] = l_result; + + FAPI_INF("%s: BC03 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc03[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC03, iv_mcs, l_attrs_dimm_bc03) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC03 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Host Interface DQ Driver Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 57 Table 26 +/// +fapi2::ReturnCode eff_lrdimm_db02::dimm_bc03() +{ + uint8_t l_attrs_dimm_bc03[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // constants + // Little table to map Output Driver Imepdance Control according to DDR4DB02 4.5 + static const std::vector< std::pair > l_odic_map = + { + // Yes, this is the order and encoding listed in the JEDEC spec... + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM30, 0b011}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM34, 0b001}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM40, 0b000}, + {fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_DRV_IMP_DQ_DQS_OHM48, 0b010} + }; + + // Treat buffer as 0th rank. LRDIMM in our eyes only have 1 rank + constexpr size_t l_rank = 0; + fapi2::buffer l_result = 0; + uint64_t l_ohm_value = 0; + uint8_t l_encoding = 0; + // attributes + uint8_t l_odic[MAX_RANK_PER_DIMM] = {}; + FAPI_TRY( mss::vpd_mt_dram_drv_imp_dq_dqs(iv_dimm, &(l_odic[0])) ); + // Get the Ohm value for rank 0 + l_ohm_value = l_odic[l_rank]; + + // Now get the proper encoding for that value. Fail if not found + // Change for rev level + FAPI_ASSERT( mss::find_value_from_key(l_odic_map, l_ohm_value, l_encoding), + fapi2::MSS_BAD_MR_PARAMETER() + .set_MR_NUMBER(1) + .set_PARAMETER(OUTPUT_IMPEDANCE) + .set_PARAMETER_VALUE(l_odic[mss::index(l_rank)]) + .set_DIMM_IN_ERROR(iv_dimm), + "Bad value for output driver impedance: %d (%s)", + l_odic[mss::index(l_rank)], mss::c_str(iv_dimm)); + + l_result = l_encoding; + + // Using a writeBit for clarity sake + // Enabling DQ/DQS drivers + l_result.writeBit(BC03_DQ_ENABLE); + + // Retrieve MCS attribute data + FAPI_TRY( eff_dimm_ddr4_bc03(iv_mcs, &l_attrs_dimm_bc03[0][0]) ); + l_attrs_dimm_bc03[iv_port_index][iv_dimm_index] = l_result; + + FAPI_INF("%s: BC03 settting: %d, vpd_drv_dram_imp is %d", + mss::c_str(iv_dimm), + l_attrs_dimm_bc03[iv_port_index][iv_dimm_index], + l_ohm_value); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC03, iv_mcs, l_attrs_dimm_bc03) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC04 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note DRAM Interface MDQ RTT Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// @note Uses MDQ Read Termination Strength (RTT) +/// From DDR4DB02 Spec Rev 0.95 +/// Page 57 Table 27 +/// DRAM Interface MDQ/MDQS ODT Strength for Data Buffer +/// Comes from SPD +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc04() +{ + uint8_t l_decoder_val = 0; + + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc04[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc04(iv_mcs, &l_attrs_dimm_bc04[0][0]) ); + // Update MCS attribute + + // 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)); + + // Update MCS attribute + + FAPI_INF("%s: BC04 settting (MDQ_RTT): %d", mss::c_str(iv_dimm), l_attrs_dimm_bc04[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC04, iv_mcs, l_attrs_dimm_bc04) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC05 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note DRAM Interface MDQ Driver Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 57 Table 28 +/// @note DRAM Interface MDQ/MDQS Output Driver Impedance control +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc05() +{ + uint8_t l_decoder_val; + + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc05[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + 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)); + 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), + l_attrs_dimm_bc05[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC05, iv_mcs, l_attrs_dimm_bc05) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC07 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Rank Presence Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// 2.5.9 Page 58 Table 30 +/// Tells the buffer which drams are enabled +/// +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}; + + 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(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 + --l_ranks_per_dimm; + // Make sure we didn't overflow or screw up somehow + fapi2::Assert (l_ranks_per_dimm < MAX_RANK_PER_DIMM); + + l_attrs_dimm_bc07[iv_port_index][iv_dimm_index] = dram_map[l_ranks_per_dimm]; + + FAPI_INF("%s: BC07 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc07[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC07, iv_mcs, l_attrs_dimm_bc07) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC08 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Power Saving Settings Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc08() +{ + // Some constants made for changing code in the future + // Hard coding values for now until characterization can be done. + // Not sure if info needs to be added to VPD or MRW or what + + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc08[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + // Update MCS attribute + FAPI_TRY( eff_dimm_ddr4_bc08(iv_mcs, &l_attrs_dimm_bc08[0][0]) ); + // BC08 is used to set the rank for Write Leveling training modes + // Defaulting to 0 because every dimm should have a rank 0, right? + // This attribute should be set in training... + l_attrs_dimm_bc08[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC08 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc08[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC08, iv_mcs, l_attrs_dimm_bc08) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC09 +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Power Saving Settings Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc09() +{ + // Some constants made for changing code in the future + // Hard coding values for now until characterization can be done. + // Not sure if info needs to be added to VPD or MRW or what + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc09[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + + fapi2::buffer l_setting = 0; + + // Disabling for now until characterization can be done + // Power/ performance setting + l_setting.writeBit (BC09_CKE_POWER_DOWN_DISABLE); + + // Update MCS attribute + FAPI_TRY( eff_dimm_ddr4_bc09(iv_mcs, &l_attrs_dimm_bc09[0][0]) ); + l_attrs_dimm_bc09[iv_port_index][iv_dimm_index] = l_setting; + + FAPI_INF("%s: BC09 settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc09[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC09, iv_mcs, l_attrs_dimm_bc09) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets config for DIMM BC0a +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note LRDIMM Operating Speed +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc0a() +{ + uint8_t l_encoding = 0; + + static const std::vector< std::pair > l_freq_map = + { + // There's also 1600, 2933, and 3200 but Nimbus can't support those... + {fapi2::ENUM_ATTR_MSS_FREQ_MT1866, 0b001}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2133, 0b010}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2400, 0b011}, + {fapi2::ENUM_ATTR_MSS_FREQ_MT2666, 0b100}, + }; + + uint8_t l_attrs_dimm_bc0a[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_INF(" FREQ is %d enum is %d", iv_freq, fapi2::ENUM_ATTR_MSS_FREQ_MT2400); + FAPI_INF("%d", (iv_freq == fapi2::ENUM_ATTR_MSS_FREQ_MT2400)); + // Find the correct mapping from freq to encoding + FAPI_ASSERT( mss::find_value_from_key(l_freq_map, uint64_t(iv_freq), l_encoding), + fapi2::MSS_INVALID_FREQ() + .set_FREQ(iv_freq), + "unknown FREQ %d for %s", + iv_freq, + mss::c_str(iv_dimm)); + + // Retrieve MCS attribute data + FAPI_TRY( eff_dimm_ddr4_bc0a(iv_mcs, &l_attrs_dimm_bc0a[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_bc0a[iv_port_index][iv_dimm_index] = l_encoding; + + FAPI_INF("%s: BC0a settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0a[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0A, iv_mcs, l_attrs_dimm_bc0a) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0b +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// From DDR4DB01 Spec Rev 1.0 +/// 2.5.13 Page 60 table 34 +/// @note Operating Voltage +/// +fapi2::ReturnCode eff_lrdimm_db01::dimm_bc0b() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0b[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0b(iv_mcs, &l_attrs_dimm_bc0b[0][0]) ); + + // Update MCS attribute + // Only option is to set it to 0 to signify 1.2 operating Voltage, everything else is reserved + l_attrs_dimm_bc0b[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC0b settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0b[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0B, iv_mcs, l_attrs_dimm_bc0b) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0b +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Operating Voltage and Host Side Output Slew Rate Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// +fapi2::ReturnCode eff_lrdimm_db02::dimm_bc0b() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0b[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0b(iv_mcs, &l_attrs_dimm_bc0b[0][0]) ); + + // Update MCS attribute + // Bits 0~1 (IBM numbering) are for slew rate + // Bit 3 is reserved, Bit 4 has to be 0 to signal 1.2 V Buffer Vdd Voltage + // Hard coding values to 0, sets slew rate to Moderate (according to Dan Phipps, this is fine) + l_attrs_dimm_bc0b[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC0b settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0b[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0B, iv_mcs, l_attrs_dimm_bc0b) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0c +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note LDQ Operation Control Word +/// From DDR4DB01 Spec Rev 1.0 +/// Page 60 Table 24 +/// +fapi2::ReturnCode eff_lrdimm_db01::dimm_bc0c() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0c[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0c(iv_mcs, &l_attrs_dimm_bc0c[0][0]) ); + + // Update MCS attribute + // This attribute is used to set the training mode + // Setting it to 0 to signal default normal mode + l_attrs_dimm_bc0c[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC0c settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0c[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0D, iv_mcs, l_attrs_dimm_bc0c) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0c +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note LDQ Operation Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// +fapi2::ReturnCode eff_lrdimm_db02::dimm_bc0c() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0c[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0c(iv_mcs, &l_attrs_dimm_bc0c[0][0]) ); + + // Update MCS attribute + // Setting it to 0 to signal default normal mode + // This attribute is used to set the training mode + l_attrs_dimm_bc0c[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC0c settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0c[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0D, iv_mcs, l_attrs_dimm_bc0c) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0d +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note LDQ Operation Control Word +/// From DDR4DB01 Spec Rev 1.0 +/// Page 61 Table 25 +/// All values are reserved for DB01, setting to 0 +/// +fapi2::ReturnCode eff_lrdimm_db01::dimm_bc0d() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0d[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0d(iv_mcs, &l_attrs_dimm_bc0d[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_bc0d[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC0d settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0d[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0D, iv_mcs, l_attrs_dimm_bc0d) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0d +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note LDQ Operation Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// @note This register is used by the Non Volatile controller (NVC) to change the mode of operation of the DDR4DB02 +/// Setting to 0 (LDQ port disabled, normal operation) +/// +fapi2::ReturnCode eff_lrdimm_db02::dimm_bc0d() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0d[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0d(iv_mcs, &l_attrs_dimm_bc0d[0][0]) ); + + // Update MCS attribute + l_attrs_dimm_bc0d[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC0d settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0d[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0D, iv_mcs, l_attrs_dimm_bc0d) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0e +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Parity Control Word +/// From DDR4DB02 Spec Rev 0.95 +/// Page 60 Table 24 +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc0e() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0e[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0e(iv_mcs, &l_attrs_dimm_bc0e[0][0]) ); + + // Update MCS attribute + // Disabling parity checking for the BCOM bus (interal DRAM to buffer on dimm) and sequence checking by the data buffer + l_attrs_dimm_bc0e[iv_port_index][iv_dimm_index] = 0; + + + FAPI_INF("%s: BC0e settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0e[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0E, iv_mcs, l_attrs_dimm_bc0e) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Determines & sets effective config for DIMM BC0f +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Error Status Word for parity and sequence error +/// +fapi2::ReturnCode eff_lrdimm::dimm_bc0f() +{ + // Retrieve MCS attribute data + uint8_t l_attrs_dimm_bc0f[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; + FAPI_TRY( eff_dimm_ddr4_bc0f(iv_mcs, &l_attrs_dimm_bc0f[0][0]) ); + + // Update MCS attribute + // BC0F is an error register so setting to 0 and it will change as reads as performed + l_attrs_dimm_bc0f[iv_port_index][iv_dimm_index] = 0; + + FAPI_INF("%s: BC0f settting: %d", mss::c_str(iv_dimm), l_attrs_dimm_bc0f[iv_port_index][iv_dimm_index] ); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_BC0E, iv_mcs, l_attrs_dimm_bc0f) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Grab the VPD blobs and decode into attributes +/// @param[in] i_target FAPI2 target (MCS) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// +fapi2::ReturnCode eff_dimm::decode_vpd(const fapi2::Target& i_target) +{ + uint8_t l_mr_blob[mss::VPD_KEYWORD_MAX] = {0}; + uint8_t l_cke_blob[mss::VPD_KEYWORD_MAX] = {0}; + uint8_t l_dq_blob[mss::VPD_KEYWORD_MAX] = {0}; + uint64_t l_freq = 0; + + std::vector l_mt_blobs(PORTS_PER_MCS, nullptr); + fapi2::VPDInfo l_vpd_info(fapi2::MemVpdData::MT); + + // For sanity. Not sure this will break us, but we're certainly making assumptions below. + static_assert(MAX_DIMM_PER_PORT == 2, "Max DIMM per port isn't 2"); + FAPI_TRY( mss::freq(find_target(i_target), l_freq)); + // We need to set up all VPD info before calling getVPD, the API assumes this + // For MR we need to tell the VPDInfo the frequency (err ... mt/s - why is this mhz?) + l_vpd_info.iv_freq_mhz = l_freq; + FAPI_INF("%s. VPD info - dimm data rate: %d MT/s", mss::c_str(i_target), l_vpd_info.iv_freq_mhz); + + // Make sure to create 0 filled blobs for all the possible blobs, not just for the + // chiplets which are configured. This prevents the decoder from accessing nullptrs + // but the code which uses the VPD will only access the information for the chiplets + // which exist - so the 0's are meaningless + for (auto& b : l_mt_blobs) + { + b = new uint8_t[mss::VPD_KEYWORD_MAX]; + memset(b, 0, mss::VPD_KEYWORD_MAX); + } + + // For MT we need to fill in the rank information + // But, of course, the rank information can differ per port. However, the vpd interface doesn't + // allow this in a straight-forward way. So, we have to get VPD blobs for MCS which contain + // ports which have the rank configuration in question. This means, basically, we pass a MCS MT + // blob to the decoder for each MCA, regardless of whether the port configurations are the same. + for (const auto& p : find_targets(i_target)) + { + // Find our blob in the vector of blob pointers + uint8_t* l_mt_blob = l_mt_blobs[mss::index(p)]; + uint64_t l_rank_count_dimm[MAX_DIMM_PER_PORT] = {0}; + + // If we don't have any DIMM, don't worry about it. This will just drop the blob full of 0's into our index. + // This will fill the VPD attributes with 0's which is perfectly ok. + for (const auto& d : mss::find_targets(p)) + { + uint8_t l_num_master_ranks = 0; + FAPI_TRY( mss::eff_num_master_ranks_per_dimm(d, l_num_master_ranks) ); + l_rank_count_dimm[mss::index(d)] = l_num_master_ranks; + } + + // This value will, of course, be 0 if there is no DIMM in the port. + l_vpd_info.iv_rank_count_dimm_0 = l_rank_count_dimm[0]; + l_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1]; + + FAPI_INF("%s. VPD info - rank count for dimm_0: %d, dimm_1: %d", + mss::c_str(i_target), l_vpd_info.iv_rank_count_dimm_0, l_vpd_info.iv_rank_count_dimm_1); + + // Get the MCS blob for this specific rank combination *only if* we have DIMM. Remember, + // Cronus can give us functional MCA which have no DIMM - and we'd puke getting the VPD. + if ((l_vpd_info.iv_rank_count_dimm_0 != 0) || (l_vpd_info.iv_rank_count_dimm_1 != 0)) + { + // If getVPD returns us an error, then we don't have VPD for the DIMM configuration. + // This is the root of our plug-rules: if you want a configuration of DIMM to be + // supported, it needs to have VPD defined. Likewise, if you don't want a configuration + // of DIMM supported be sure to leave it out of the VPD. Note that we don't return a specific + // plug-rule error as f/w (Dan) suggested this would duplicate errors leading to confusion. + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::MT; + + // Check the max for giggles. Programming bug so we should assert. + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve MT size from VPD"); + + if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) + { + FAPI_ERR("VPD MT keyword is too big for our array"); + fapi2::Assert(false); + } + + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_mt_blob[0])), + "Failed to retrieve MT VPD"); + } + }// mca + + // Only get the MR blob if we have a freq. It's possible for Cronus to give us an MCS which + // is connected to a controller which has 0 DIMM installed. In this case, we won't have + // a frequency, and thus we'd fail getting the VPD. So we initiaized the VPD to 0's and if + // there's no freq, we us a 0 filled VPD. + if (l_vpd_info.iv_freq_mhz != 0) + { + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::MR; + + // Check the max for giggles. Programming bug so we should assert. + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve MR size from VPD"); + + if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) + { + FAPI_ERR("VPD MR keyword is too big for our array"); + fapi2::Assert(false); + } + + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_mr_blob[0])), + "Failed to retrieve MR VPD"); + } + + // Get CKE data + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::CK; + + // Check the max for giggles. Programming bug so we should assert. + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve CK size from VPD"); + + if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) + { + FAPI_ERR("VPD CK keyword is too big for our array"); + fapi2::Assert(false); + } + + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_cke_blob[0])), + "Failed to retrieve DQ VPD"); + + // Get DQ data + l_vpd_info.iv_vpd_type = fapi2::MemVpdData::DQ; + + // Check the max for giggles. Programming bug so we should assert. + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), + "Failed to retrieve DQ size from VPD"); + + if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) + { + FAPI_ERR("VPD DQ keyword is too big for our array"); + fapi2::Assert(false); + } + + FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_dq_blob[0])), + "Failed to retrieve DQ VPD"); + + FAPI_TRY( mss::eff_decode(i_target, l_mt_blobs, l_mr_blob, l_cke_blob, l_dq_blob) ); + +fapi_try_exit: + + // delete the mt blobs + for (auto p : l_mt_blobs) + { + if (p != nullptr) + { + delete[] p; + } + } + + return fapi2::current_err; +} + + + +}//mss 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 e5f8c6d91d1..63abcb320c7 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 @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -22,3 +22,1239 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ +// *HWP HWP Owner: Jacob Harvey +// *HWP HWP Backup: Aandre Marin +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: FSP:HB + + +#ifndef _MSS_EFF_DIMM_H_ +#define _MSS_EFF_DIMM_H_ + +#include +#include +#include +#include +namespace mss +{ + +/// +/// @class mss::dimm::eff_dimm +/// @brief A class made to perform eff_config functions based on the different dimm kinds (gen, type, buffer type) +/// @note this is a base class +/// +class eff_dimm +{ + protected: + const fapi2::Target iv_dimm; + fapi2::Target iv_mca; + fapi2::Target iv_mcs; + uint64_t iv_port_index; + uint64_t iv_dimm_index; + + public: + uint64_t iv_freq; + int64_t iv_tCK_in_ps; + const std::shared_ptr iv_pDecoder; + + // Assists testing with write ability on these MRW + // settings that are normally NOT writable + // using attribute accessors + // Could create getters & setters... + uint8_t iv_refresh_mode; + uint8_t iv_temp_refresh_range; + + //Delete the default + eff_dimm () = delete; + + /// + /// @brief constructor for the base eff_dimm class + /// @param[in] i_target the dimm target + /// @param[in] i_pDecoder the SPD decoder + /// @param[out] o_rc fapi2::ReturnCode + /// @note also sets class variables for parent MCA/ MCS and for freqs + /// + eff_dimm (const fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder, + fapi2::ReturnCode& o_rc) : + iv_dimm (i_target), + iv_pDecoder(i_pDecoder) + { + FAPI_DBG("Constructing EFF_DIMM Object"); + iv_mca = find_target(iv_dimm); + iv_mcs = find_target(iv_dimm); + iv_port_index = mss::index(iv_mca); + iv_dimm_index = mss::index(iv_dimm); + + FAPI_TRY( clock_period(i_target, iv_tCK_in_ps), "Failed to calculate clock period (tCK)" ); + + FAPI_TRY( mss::mrw_temp_refresh_range(iv_temp_refresh_range), "Failed mrw_temp_refresh_range()" ); + FAPI_TRY( mss::mrw_fine_refresh_mode(iv_refresh_mode), "Failed mrw_fine_refresh_mode()" ); + + FAPI_TRY( mss::freq(find_target(i_target), iv_freq)); + + FAPI_INF("Calculated clock period - tCK (ps): %d for %s", iv_tCK_in_ps, mss::c_str(i_target)); + FAPI_INF("Calculated frequency (ps): %d for %s", iv_freq, mss::c_str(i_target)); + + fapi_try_exit: + o_rc = fapi2::current_err; + return; + } + + /// + /// @brief Grab the VPD blobs and decode into attributes + /// @param[in] i_target FAPI2 target (MCS) + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + static fapi2::ReturnCode decode_vpd(const fapi2::Target& i_target); + + /// + /// @brief factory to make an eff_config DIMM object based on dimm kind (type, gen, and revision number) + /// @param[in] i_target the dimm target + /// @param[in] i_pDecoder the SPD decoder + /// @param[out] o_fact_obj a shared pointer of the eff_dimm type + /// + static fapi2::ReturnCode eff_dimm_factory (const fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder, + std::shared_ptr& o_fact_obj); + + /// + /// @brief Determines & sets effective config for buffer and rev density + /// @param[in] i_target FAPI2 target + /// @param[in] i_pDecoder the SPD decoder + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + static fapi2::ReturnCode register_and_buffer_type( const fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder ); + + /// + /// @brief Default destructor + /// + virtual ~eff_dimm() = default; + + /// + /// @brief Determines & sets effective config for eff_dram_mfg_id type from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_mfg_id(); + + /// + /// @brief Determines & sets effective config for primary stack type + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode primary_stack_type(); + + /// + /// @brief Determines & sets effective config for Hybrid memory type from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode hybrid_memory_type(); + + /// + /// @brief Determines & sets effective config for temperature controlled refresh mode + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode temp_refresh_mode(); + + /// + /// @brief Determines & sets effective config for refresh interval time (tREFI) + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trefi(); + + /// + /// @brief Determines & sets effective config for refresh cycle time (tRFC) + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trfc(); + + /// + /// @brief Determines & sets effective config for refresh cycle time (logical ranks) (tRFC_DLR) + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trfc_dlr(); + + /// + /// @brief Determines & sets effective config for dram density + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_density(); + + /// + + /// @brief Determines & sets effective config for dram width + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_width(); + /// + /// @brief Determines & sets effective config for dimm rcd mirror mode + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode rcd_mirror_mode(); + + /// + /// @brief Determines & sets effective config for dimm size + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_size(); + + /// + /// @brief Determines & sets effective config for dram bank bits + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_bank_bits(); + + /// + /// @brief Determines & sets effective config for dram row bits + /// @param[in] i_target FAPI2 target + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_row_bits(); + + /// + /// @brief Determines & sets effective config for number of ranks per dimm + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode ranks_per_dimm(); + + /// + /// @brief Determines & sets effective config for number of master ranks per dimm + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode master_ranks_per_dimm(); + + /// + /// @brief Determines & sets effective config for tDQS + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_dqs_time(); + + /// + /// @brief Determines & sets effective config for tCCD_L + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_tccd_l(); + + /// + /// @brief Determines & sets effective config for DIMM RC00 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc00(); + + /// + /// @brief Determines & sets effective config for DIMM RC01 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc01(); + + /// + /// @brief Determines & sets effective config for DIMM RC02 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc02(); + + /// + /// @brief Determines & sets effective config for DIMM RC03 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc03(); + + /// + /// @brief Determines & sets effective config for DIMM RC04 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc04(); + + /// + /// @brief Determines & sets effective config for DIMM RC05 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc05(); + + /// + /// @brief Determines & sets effective config for DIMM RC06_07 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc06_07(); + + /// + /// @brief Determines & sets effective config for DIMM RC08 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc08(); + + /// + /// @brief Determines & sets effective config for DIMM RC09 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc09(); + + /// + /// @brief Determines & sets effective config for DIMM RC10 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc10(); + + /// + /// @brief Determines & sets effective config for DIMM RC11 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc11(); + + /// + /// @brief Determines & sets effective config for DIMM RC12 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc12(); + + /// + /// @brief Determines & sets effective config for DIMM RC13 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc13(); + + /// + /// @brief Determines & sets effective config for DIMM RC14 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc14(); + + /// + /// @brief Determines & sets effective config for DIMM RC15 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc15(); + + /// + /// @brief Determines & sets effective config for DIMM RC_1x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc1x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_2x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc2x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_3x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc3x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_4x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc4x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_5x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc5x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_6x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc6x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_7x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc7x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_8x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc8x(); + + /// + /// @brief Determines & sets effective config for DIMM RC_9x + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rc9x(); + + + /// + /// @brief Determines & sets effective config for DIMM RC_AX + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rcax(); + + + /// + /// @brief Determines & sets effective config for DIMM RC_BX + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_rcbx(); + + /// + /// @brief Determines & sets effective config for tWR + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_twr(); + + /// + /// @brief Determines & sets effective config for RBT + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode read_burst_type(); + + /// + /// @brief Determines & sets effective config for TM + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_tm(); + + /// + /// @brief Determines & sets effective config for cwl + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_cwl(); + + /// + /// @brief Determines & sets effective config for lpasr + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_lpasr(); + + /// + /// @brief Determines & sets effective config for additive latency + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode additive_latency(); + + /// + /// @brief Determines & sets effective config for DLL Reset + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dll_reset(); + + /// + /// @brief Determines & sets effective config for DLL Enable + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dll_enable(); + + /// + /// @brief Determines & sets effective config for Write Level Enable + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode write_level_enable(); + + /// + /// @brief Determines & sets effective config for Output Buffer + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode output_buffer(); + + + /// + /// @brief Determines & sets effective config for Vref DQ Train Value + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode vref_dq_train_value(); + + /// + /// @brief Determines & sets effective config for Vref DQ Train Enable + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode vref_dq_train_enable(); + + /// + /// @brief Determines & sets effective config for Vref DQ Train Range + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode vref_dq_train_range(); + + /// + /// @brief Determines & sets effective config for CA Parity Latency + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode ca_parity_latency(); + + /// + /// @brief Determines & sets effective config for CA Parity + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode ca_parity(); + + /// + /// @brief Determines & sets effective config for CRC Error Clear + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode crc_error_clear(); + + /// + /// @brief Determines & sets effective config for CA Parity Error Status + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode ca_parity_error_status(); + + /// + /// @brief Determines & sets effective config for ODT Input Buffer + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode odt_input_buffer(); + /// + /// @brief Determines & sets effective config for data_mask + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode data_mask(); + + /// + /// @brief Determines & sets effective config for write_dbi + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode write_dbi(); + + /// + /// @brief Determines & sets effective config for read_dbi + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode read_dbi(); + + /// + /// @brief Determines & sets effective config for Post Package Repair + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode post_package_repair(); + + /// + /// @brief Determines & sets effective config for rd_preamble_train + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode read_preamble_train(); + + /// + /// @brief Determines & sets effective config for rd_preamble + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode read_preamble(); + + /// + /// @brief Determines & sets effective config for wr_preamble + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode write_preamble(); + + /// + /// @brief Determines & sets effective config for self_ref_abort + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode self_refresh_abort(); + + /// + /// @brief Determines & sets effective config for cs_cmd_latency + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode cs_to_cmd_addr_latency(); + + /// + /// @brief Determines & sets effective config for int_vref_mon + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode internal_vref_monitor(); + + /// + /// @brief Determines & sets effective config for powerdown_mode + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode max_powerdown_mode(); + + /// + /// @brief Determines & sets effective config for mpr_rd_format + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode mpr_read_format(); + + /// + /// @brief Determines & sets effective config for CRC write latency + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode crc_wr_latency(); + + /// + /// @brief Determines & sets effective config for temperature readout + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode temp_readout(); + + /// + /// @brief Determines & sets effective config for per DRAM addressability + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode per_dram_addressability(); + + /// + /// @brief Determines & sets effective config for geardown mode + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode geardown_mode(); + + /// + /// @brief Determines & sets effective config for geardown mode + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode mpr_page(); + + /// + /// @brief Determines & sets effective config for MPR mode + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode mpr_mode(); + + /// + /// @brief Determines & sets effective config for write CRC + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode write_crc(); + + /// + /// @brief Determines & sets effective config for ZQ Calibration + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode zqcal_interval(); + + /// + /// @brief Determines & sets effective config for MEMCAL Calibration + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode memcal_interval(); + + /// + /// @brief Determines & sets effective config for tRP + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trp(); + + /// + /// @brief Determines & sets effective config for tRCD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trcd(); + + /// + /// @brief Determines & sets effective config for tRC + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trc(); + + /// + /// @brief Determines & sets effective config for tWTR_L + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_twtr_l(); + + /// + /// @brief Determines & sets effective config for tWTR_S + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_twtr_s(); + + /// + /// @brief Determines & sets effective config for tRRD_S (tRRD_S_slr) + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trrd_s(); + + /// + /// @brief Determines & sets effective config for tRRD_L (or tRRD_L_slr) + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trrd_l(); + + /// + /// @brief Determines & sets effective config for tRRD_DLR + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trrd_dlr(); + + /// + /// @brief Determines & sets effective config for tFAW (or tFAW_slr) + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_tfaw(); + + /// + /// @brief Determines & sets effective config for tFAW_DLR + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_tfaw_dlr(); + + /// + /// @brief Determines & sets effective config for tRAS + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_tras(); + + /// + /// @brief Determines & sets effective config for tRTP + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dram_trtp(); + + /// + /// @brief Sets the RTT_NOM value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS01 + /// + virtual fapi2::ReturnCode dram_rtt_nom() = 0; + + /// + /// @brief Sets the RTT_NOM value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS02 + /// + virtual fapi2::ReturnCode dram_rtt_wr() = 0; + + /// + /// @brief Sets the RTT_PARK value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS05 + /// + virtual fapi2::ReturnCode dram_rtt_park() = 0; + + /// + /// @brief Determines and sets DIMM BC00 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc00() = 0; + + /// + /// @brief Determines and sets DIMM BC01 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc01() = 0; + + /// + /// @brief Determines and sets DIMM BC02 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc02() = 0; + + /// + /// @brief Determines and sets DIMM BC03 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc03() = 0; + + /// + /// @brief Determines and sets DIMM BC04 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc04() = 0; + + /// + /// @brief Determines and sets DIMM BC05 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc05() = 0; + + /// + /// @brief Determines and sets DIMM BC07 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc07() = 0; + + /// + /// @brief Determines and sets DIMM BC08 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc08() = 0; + + + /// + /// @brief Determines and sets DIMM BC09 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc09() = 0; + + /// + /// @brief Determines and sets DIMM BC0a + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0a() = 0; + + /// + /// @brief Determines and sets DIMM BC0b + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0b() = 0; + + /// + /// @brief Determines and sets DIMM BC0c + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0c() = 0; + + /// + /// @brief Determines and sets DIMM BC0d + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0d() = 0; + + /// + /// @brief Determines and sets DIMM BC0e + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0e() = 0; + + /// + /// @brief Determines and sets DIMM BC0f + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0f() = 0; + +}; + +/// +/// @class mss::dimm::eff_lrdimm : eff_dimm +/// @brief A class made to perform eff_config functions for DDR4 LRDIMMS +/// @note this is a subclass of eff_dimm and parent class to eff_lrdimm_db01 and eff_lrdimm_db02 +/// +class eff_lrdimm : public eff_dimm +{ + public: + /// + /// @brief constructor for the eff_lrdimm class + /// @param[in] i_target the dimm target + /// @param[in] i_pDecoder 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 fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder, + fapi2::ReturnCode& o_rc): + eff_dimm (i_target, i_pDecoder, o_rc) + { + FAPI_DBG("Constructing LRDIMM"); + } + + /// + /// @brief default destructor + /// + virtual ~eff_lrdimm() = default; + + /// + /// @brief Sets the RTT_NOM value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS01 + /// + virtual fapi2::ReturnCode dram_rtt_nom() final; + + /// + /// @brief Sets the RTT_NOM value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS02 + /// + virtual fapi2::ReturnCode dram_rtt_wr() final; + + /// + /// @brief Sets the RTT_PARK value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS05 + /// + virtual fapi2::ReturnCode dram_rtt_park() final; + + /// + /// @brief Determines and sets DIMM BC00 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc00() final; + + /// + /// @brief Determines and sets DIMM BC01 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc01() final; + + /// + /// @brief Determines and sets DIMM BC02 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc02() final; + + /// + /// @brief Determines and sets DIMM BC03 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc03() = 0; + + /// + /// @brief Determines and sets DIMM BC04 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc04() final; + + /// + /// @brief Determines and sets DIMM BC05 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc05() final; + + /// + /// @brief Determines and sets DIMM BC07 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc07() final; + + /// + /// @brief Determines and sets DIMM BC08 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc08() final; + + /// + /// @brief Determines and sets DIMM BC09 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc09() final; + + /// + /// @brief Determines and sets DIMM BC0a + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0a() final; + + /// + /// @brief Determines and sets DIMM BC0b + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0b() = 0; + + /// + /// @brief Determines and sets DIMM BC0c + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0c() = 0; + + /// + /// @brief Determines and sets DIMM BC0d + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0d() = 0; + + /// + /// @brief Determines and sets DIMM BC0e + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0e() final; + + /// + /// @brief Determines and sets DIMM BC0f + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0f() final; +}; + +/// +/// @class mss::dimm::eff_lrdimm_db01 : eff_lrdimm +/// @brief A class made to perform eff_config functions for DDR4 LRDIMMS with Databuffer type 01 +/// +class eff_lrdimm_db01 : public eff_lrdimm +{ + protected: + public: + //Delete default + eff_lrdimm_db01 () = delete; + + /// + /// @brief constructor for the eff_lrdimm_db01 (LRDIMM DataBuffer 1) class + /// @param[in] i_target the dimm target + /// @param[in] i_pDecoder 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 fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder, + fapi2::ReturnCode& o_rc) : + eff_lrdimm(i_target, i_pDecoder, o_rc) + { + FAPI_DBG("Constructing LRDIMM_DB01"); + } + /// + /// @brief default destructor + /// + ~eff_lrdimm_db01() = default; + + /// + /// @brief Determines and sets DIMM BC03 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc03(); + + /// + /// @brief Determines and sets DIMM BC0b + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0b(); + + + /// + /// @brief Determines and sets DIMM BC0c + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0c(); + + /// + /// @brief Determines and sets DIMM BC0d + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0d(); +}; + +/// +/// @class mss::dimm::eff_lrdimm_db02 : eff_lrdimm +/// @brief A class made to perform eff_config functions for DDR4 LRDIMMS with Databuffer type 02 +/// +class eff_lrdimm_db02 : public eff_lrdimm +{ + protected: + public: + //Delete default + eff_lrdimm_db02() = delete; + + /// + /// @brief constructor for the eff_lrdimm_db02 (LRDIMM DataBuffer 2) class + /// @param[in] i_target the dimm target + /// @param[in] i_pDecoder 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 fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder, + fapi2::ReturnCode& o_rc) : + eff_lrdimm(i_target, i_pDecoder, o_rc) + { + FAPI_DBG("Constructing LRDIMM_DB02"); + } + + /// + /// @brief default destructor + /// + ~eff_lrdimm_db02() = default; + + /// + /// @brief Determines and sets DIMM BC03 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc03(); + + /// + /// @brief Determines and sets DIMM BC0b + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0b(); + + /// + /// @brief Determines and sets DIMM BC0c + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0c(); + + /// + /// @brief Determines and sets DIMM BC0d + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + virtual fapi2::ReturnCode dimm_bc0d(); +}; + +/// +/// @class mss::dimm::eff_rdimm : eff_dimm +/// @brief A class made to perform eff_config functions for DDR4 RDIMMS +/// +class eff_rdimm : public eff_dimm +{ + public: + eff_rdimm() = delete; + + /// + /// @brief constructor for the eff_rdimm_db01 (LRDIMM DataBuffer 1) class + /// @param[in] i_target the dimm target + /// @param[in] i_pDecoder 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 fapi2::Target& i_target, + const std::shared_ptr& i_pDecoder, + fapi2::ReturnCode& o_rc) : + eff_dimm(i_target, i_pDecoder, o_rc) + { + FAPI_DBG("Constructing RDIMM"); + } + + /// + /// @brief default destructor + /// + ~eff_rdimm() = default; + + /// + /// @brief Sets the RTT_NOM value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS01 + /// + fapi2::ReturnCode dram_rtt_nom() final; + + /// + /// @brief Sets the RTT_NOM value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS02 + /// + fapi2::ReturnCode dram_rtt_wr() final; + + /// + /// @brief Sets the RTT_PARK value from SPD + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// @note used for MRS05 + /// + fapi2::ReturnCode dram_rtt_park() final; + + /// + /// @brief Determines and sets DIMM BC00 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc00() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC01 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc01() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC02 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc02() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC03 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc03() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC04 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc04() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC05 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc05() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC07 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc07() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC08 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc08() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC09 + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc09() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC0a + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc0a() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC0b + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc0b() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC0c + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc0c() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC0d + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc0d() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC0e + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc0e() final + { + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Determines and sets DIMM BC0f + /// @return fapi2::FAPI2_RC_SUCCESS if okay + /// + fapi2::ReturnCode dimm_bc0f() final + { + return fapi2::FAPI2_RC_SUCCESS; + } +}; +}//mss + +#endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C deleted file mode 100644 index 6f14f4acd49..00000000000 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C +++ /dev/null @@ -1,4100 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ -/* [+] 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 eff_config.C -/// @brief Determine effective config for mss settings -/// -// *HWP HWP Owner: Andre Marin -// *HWP HWP Backup: Brian Silver -// *HWP Team: Memory -// *HWP Level: 2 -// *HWP Consumed by: FSP:HB -//utils -#include - -// fapi2 -#include -#include -#include - -// mss lib -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_MCS; -using fapi2::TARGET_TYPE_DIMM; -using fapi2::TARGET_TYPE_MCBIST; - -namespace mss -{ - -enum rc10_encode : uint8_t -{ - DDR4_1866 = 0x01, - DDR4_2133 = 0x02, - DDR4_2400 = 0x03, - DDR4_2666 = 0x04, -}; - -enum rc13_encode : uint8_t -{ - DIRECT_CS_MODE = 0, - LRDIMM = 0, - RDIMM = 1, -}; - -enum rc3x_encode : uint8_t -{ - MT1860_TO_MT1880 = 0x1F, - MT2120_TO_MT2140 = 0x2C, - MT2380_TO_MT2400 = 0x39, - MT2660_TO_MT2680 = 0x47, -}; - -///////////////////////// -// Non-member function implementations -///////////////////////// - -/// -/// @brief IBT helper - maps from VPD definition of IBT to the RCD control word bit fields -/// @param[in] i_ibt the IBT from VPD (e.g., 10, 15, ...) -/// @return the IBT bit field e.g., 00, 01 ... (right aligned) -/// @note Unrecognized IBT values will force an assertion. -/// -static uint64_t ibt_helper(const uint8_t i_ibt) -{ - switch(i_ibt) - { - // Off - case 0: - return 0b11; - break; - - // 100Ohm - case 10: - return 0b00; - break; - - // 150Ohm - case 15: - return 0b01; - break; - - // 300Ohm - case 30: - return 0b10; - break; - - default: - FAPI_ERR("unknown IBT value %d", i_ibt); - fapi2::Assert(false); - }; - - // Not reached, but 'return' off ... - return 0b11; -} - -///////////////////////// -// Member Method implementation -///////////////////////// - -/// -/// @brief Determines & sets effective config for DRAM generation from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_gen(const fapi2::Target& i_target, - const std::vector& i_spd_data ) -{ - //TODO: RTC 159777: Change eff_config class to use iv's for mcs, port and dimm position - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_decoder_val = 0; - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Get & update MCS attribute - FAPI_TRY( eff_dram_gen(l_mcs, &l_mcs_attrs[0][0]) ); - FAPI_TRY( spd::dram_device_type(i_target, i_spd_data, l_decoder_val) ); - - l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; - -}// dram_gen - -/// -/// @brief Determines & sets effective config for DIMM type from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_type(const fapi2::Target& i_target, - const std::vector& i_spd_data ) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_decoder_val = 0; - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Get & update MCS attribute - FAPI_TRY( eff_dimm_type(l_mcs, &l_mcs_attrs[0][0]) ); - FAPI_TRY( spd::base_module_type(i_target, i_spd_data, l_decoder_val) ); - - l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; - -}// dimm_type - -/// -/// @brief Determines & sets effective config for eff_dram_mfg_id type from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_mfg_id(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint16_t l_decoder_val = 0; - uint16_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Get & update MCS attribute - FAPI_TRY( eff_dram_mfg_id(l_mcs, &l_mcs_attrs[0][0]) ); - FAPI_TRY( iv_pDecoder->dram_manufacturer_id_code(i_target, l_decoder_val) ); - - l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_MFG_ID, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; - -}// dimm_type - -/// -/// @brief Determines & sets effective config for dram width -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_width(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - 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(i_target, l_decoder_val) ); - FAPI_TRY( eff_dram_width(l_mcs, &l_mcs_attrs[0][0]) ); - - l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WIDTH, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief Determines & sets effective config for the RTT_NOM value -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note used for MRS01 -/// -template<> -fapi2::ReturnCode eff_config::dram_rtt_nom(const fapi2::Target& i_target) -{ - //Indexing info - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_decoder_val = 0; - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - - //Temp holders to grab attributes to then parse into value for this dimm and rank - uint8_t l_rtt_nom[MAX_RANK_PER_DIMM] = {}; - - //Size per JEDEC spec - constexpr size_t RTT_NOM_SIZE = 8; - // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking - // for index 1. So this doesn't correspond directly with the table in the JEDEC spec, - // as that's not in "denominator order." - // 0 RQZ/1 RQZ/2 RQZ/3 RQZ/4 RQZ/5 RQZ/6 RQZ/7 - constexpr uint8_t rtt_nom_map[] = { 0, 0b100, 0b010, 0b110, 0b001, 0b101, 0b011, 0b111 }; - - size_t l_rtt_nom_index = 0; - std::vector< uint64_t > l_ranks; - - FAPI_TRY( mss::vpd_mt_dram_rtt_nom(i_target, &(l_rtt_nom[0])) ); - FAPI_TRY( eff_dram_rtt_nom(l_mcs, &l_mcs_attrs[0][0][0]) ); - - //Calculate the value for each rank and store in attribute - - FAPI_TRY(mss::rank::ranks(i_target, l_ranks)); - - for (const auto& l_rank : l_ranks) - { - // We have to be careful about 0 - l_rtt_nom_index = (l_rtt_nom[mss::index(l_rank)] == 0) ? - 0 : fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_NOM_OHM240 / l_rtt_nom[mss::index(l_rank)]; - - //Make sure it's a valid index - FAPI_ASSERT( (l_rtt_nom_index < RTT_NOM_SIZE), - fapi2::MSS_BAD_MR_PARAMETER() - .set_MR_NUMBER(5) - .set_PARAMETER(RTT_NOM) - .set_PARAMETER_VALUE(l_rtt_nom_index) - .set_DIMM_IN_ERROR(i_target), - "Bad value for RTT NOM: %d (%s)", l_rank, mss::c_str(i_target)); - - - // Map from RTT_NOM array to the value in the map - l_decoder_val = rtt_nom_map[l_rtt_nom_index]; - - //Store value and move to next rank - l_mcs_attrs[l_port_num][l_dimm_num][mss::index(l_rank)] = l_decoder_val; - } - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_NOM, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for the RTT_NOM value -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note used for MRS01 -/// -template<> -fapi2::ReturnCode eff_config::dram_rtt_nom(const fapi2::Target& i_target) -{ - //Indexing info - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - std::vector< uint64_t > l_ranks; - - - uint8_t l_decoder_val = 0; - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - FAPI_TRY( eff_dram_rtt_nom(l_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)); - - //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 - FAPI_TRY(mss::rank::ranks(i_target, l_ranks)); - - for (const auto& l_rank : l_ranks) - { - l_mcs_attrs[l_port_num][l_dimm_num][mss::index(l_rank)] = l_decoder_val; - } - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_NOM, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; - -} -/// -/// @brief Determines & sets effective config for the RTT_WR value from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note used for MRS02 -/// -template<> -fapi2::ReturnCode eff_config::dram_rtt_wr(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - std::vector< uint64_t > l_ranks; - - - uint8_t l_decoder_val = 0; - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - - FAPI_TRY( eff_dram_rtt_wr(l_mcs, &l_mcs_attrs[0][0][0]) ); - - //Get RTT_WR from VPD - uint8_t l_dram_rtt_wr[MAX_RANK_PER_DIMM]; - FAPI_TRY( mss::vpd_mt_dram_rtt_wr(i_target, &(l_dram_rtt_wr[0])) ); - - //Calculate the value for each rank and store in attribute - FAPI_TRY(mss::rank::ranks(i_target, l_ranks)); - - for (const auto& l_rank : l_ranks) - { - const auto l_index = mss::index(l_rank); - - switch (l_dram_rtt_wr[l_index]) - { - case fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_DISABLE: - l_decoder_val = 0b000; - break; - - case fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_HIGHZ: - l_decoder_val = 0b011; - break; - - case fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM240: - l_decoder_val = 0b010; - break; - - case fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM80: - l_decoder_val = 0b100; - break; - - case fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_WR_OHM120: - l_decoder_val = 0b001; - break; - - default: - FAPI_ERR("unknown RTT_WR 0x%x (%s rank %d), dynamic odt off", - l_dram_rtt_wr[l_index], mss::c_str(i_target), l_rank); - l_decoder_val = 0b000; - break; - }; - - //Store value and move to next rank - l_mcs_attrs[l_port_num][l_dimm_num][mss::index(l_rank)] = l_decoder_val; - } - - //Set the attribute - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_WR, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for the RTT_WR value from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note used for MRS02 -/// -template<> -fapi2::ReturnCode eff_config::dram_rtt_wr(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - std::vector< uint64_t > l_ranks; - - - uint8_t l_decoder_val = 0; - 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)); - - //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 - FAPI_TRY(mss::rank::ranks(i_target, l_ranks)); - - for (const auto& l_rank : l_ranks) - { - l_mcs_attrs[l_port_num][l_dimm_num][mss::index(l_rank)] = l_decoder_val; - } - - //Set the attribute - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_WR, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for the RTT_PARK value from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note used for MRS05 -/// -template <> -fapi2::ReturnCode eff_config::dram_rtt_park(const fapi2::Target& i_target) -{ - //Indexing info - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - std::vector< uint64_t > l_ranks; - - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - - // Indexed by denominator. So, if RQZ is 240, and you have OHM240, then you're looking - // for 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 }; - - uint8_t l_rtt_park[MAX_RANK_PER_DIMM]; - - FAPI_TRY( mss::vpd_mt_dram_rtt_park(i_target, &(l_rtt_park[0])) ); - FAPI_TRY( eff_dram_rtt_park(l_mcs, &l_mcs_attrs[0][0][0]) ); - - //Calculate the value for each rank and store in attribute - FAPI_TRY(mss::rank::ranks(i_target, l_ranks)); - - - for (const auto& l_rank : l_ranks) - { - const auto l_index = mss::index(l_rank); - - // We have to be careful about 0 - uint8_t l_rtt_park_index = (l_rtt_park[l_index] == 0) ? - 0 : fapi2::ENUM_ATTR_MSS_VPD_MT_DRAM_RTT_PARK_240OHM / l_rtt_park[l_index]; - - FAPI_ASSERT( (l_rtt_park_index < RTT_PARK_COUNT), - fapi2::MSS_BAD_MR_PARAMETER() - .set_MR_NUMBER(5) - .set_PARAMETER(RTT_PARK) - .set_PARAMETER_VALUE(l_rank) - .set_DIMM_IN_ERROR(i_target), - "Bad value for RTT park: %d (%s)", l_rank, mss::c_str(i_target)); - - // Map from RTT_PARK array to the value in the map - l_mcs_attrs[l_port_num][l_dimm_num][l_index] = rtt_park_map[l_rtt_park_index]; - } - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_PARK, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for the RTT_PARK value from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note used for MRS05 -/// -template <> -fapi2::ReturnCode eff_config::dram_rtt_park(const fapi2::Target& i_target) -{ -//Indexing info - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - uint8_t l_decoder_val_01 = 0; - uint8_t l_decoder_val_23 = 0; - - FAPI_TRY( eff_dram_rtt_park(l_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));; - - l_mcs_attrs[l_port_num][l_dimm_num][0] = l_decoder_val_01; - l_mcs_attrs[l_port_num][l_dimm_num][1] = l_decoder_val_01; - l_mcs_attrs[l_port_num][l_dimm_num][2] = l_decoder_val_23; - l_mcs_attrs[l_port_num][l_dimm_num][3] = l_decoder_val_23; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RTT_PARK, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for dram density -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_density(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - - uint8_t l_decoder_val = 0; - FAPI_TRY( iv_pDecoder->sdram_density(i_target, l_decoder_val) ); - - // Get & update MCS attribute - { - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dram_density(l_mcs, &l_mcs_attrs[0][0]) ); - - l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DENSITY, l_mcs, l_mcs_attrs) ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for number of ranks per dimm -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::ranks_per_dimm(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_ranks_per_dimm = 0; - uint8_t l_attrs_ranks_per_dimm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Get & update MCS attribute - FAPI_TRY( eff_num_ranks_per_dimm(l_mcs, &l_attrs_ranks_per_dimm[0][0]) ); - FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(i_target, l_ranks_per_dimm) ); - - l_attrs_ranks_per_dimm[l_port_num][l_dimm_num] = l_ranks_per_dimm; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_RANKS_PER_DIMM, l_mcs, l_attrs_ranks_per_dimm) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for stack type -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::primary_stack_type(const fapi2::Target& i_target) -{ - uint8_t l_decoder_val = 0; - FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(i_target, l_decoder_val) ); - - // Get & update MCS attribute - { - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_prim_stack_type(l_mcs, &l_mcs_attrs[0][0]) ); - - l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PRIM_STACK_TYPE, l_mcs, l_mcs_attrs) ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for dimm size -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @warn Dependent on the following attributes already set: -/// @warn eff_dram_density, eff_sdram_width, eff_ranks_per_dimm -/// -fapi2::ReturnCode eff_config::dimm_size(const fapi2::Target& i_target) -{ - // 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(i_target, l_sdram_width) ); - FAPI_TRY( iv_pDecoder->prim_bus_width(i_target, l_bus_width) ); - FAPI_TRY( iv_pDecoder->sdram_density(i_target, l_sdram_density) ); - FAPI_TRY( iv_pDecoder->logical_ranks_per_dimm(i_target, l_logical_rank_per_dimm) ); - - { - // Calculate dimm size - // Formula from SPD Spec - // Total = SDRAM Capacity 8 * Primary Bus Width SDRAM Width * Logical Ranks per DIMM - uint32_t l_dimm_size = 0; - l_dimm_size = (l_sdram_density / 8.0) * (l_bus_width / l_sdram_width) * l_logical_rank_per_dimm; - - // Get & update MCS attribute - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint32_t l_attrs_dimm_size[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_size(l_mcs, &l_attrs_dimm_size[0][0]) ); - - l_attrs_dimm_size[l_port_num][l_dimm_num] = l_dimm_size; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_SIZE, l_mcs, l_attrs_dimm_size) ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for Hybrid memory type from SPD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::hybrid_memory_type(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_decoder_val = 0; - uint8_t l_mcs_attrs[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Get & update MCS attribute - FAPI_TRY( eff_hybrid_memory_type(l_mcs, &l_mcs_attrs[0][0]) ); - FAPI_TRY(iv_pDecoder->hybrid_media(i_target, l_decoder_val)); - - l_mcs_attrs[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, l_mcs, l_mcs_attrs) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for refresh interval time (tREFI) -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trefi(const fapi2::Target& i_target) -{ - uint64_t l_trefi_in_ps = 0; - - // Calculates appropriate tREFI based on fine refresh mode - switch(iv_refresh_mode) - { - case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL: - - FAPI_TRY( calc_trefi( mss::refresh_rate::REF1X, - iv_temp_refresh_range, - l_trefi_in_ps), - "Failed to calculate tREF1 for target %s", mss::c_str(i_target) ); - break; - - case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FIXED_2X: - case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_FLY_2X: - - FAPI_TRY( calc_trefi( mss::refresh_rate::REF2X, - iv_temp_refresh_range, - l_trefi_in_ps), - "Failed to calculate tREF2 for target %s", mss::c_str(i_target) ); - 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( calc_trefi( mss::refresh_rate::REF4X, - iv_temp_refresh_range, - l_trefi_in_ps), - "Failed to calculate tREF4 for target %s", mss::c_str(i_target) ); - break; - - default: - // Fine Refresh Mode will be a platform attribute set by the MRW, - // which they "shouldn't" mess up as long as use "attribute" enums. - // if openpower messes this up we can at least catch it - FAPI_ASSERT(false, - fapi2::MSS_INVALID_FINE_REFRESH_MODE(). - set_FINE_REF_MODE(iv_refresh_mode), - "%s Incorrect Fine Refresh Mode received: %d ", - mss::c_str(i_target), - iv_refresh_mode); - break; - } - - { - // Calculate refresh cycle time in nCK & set attribute - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - - std::vector l_mcs_attrs_trefi(PORTS_PER_MCS, 0); - uint64_t l_trefi_in_nck = 0; - - // Retrieve MCS attribute data - FAPI_TRY( eff_dram_trefi(l_mcs, l_mcs_attrs_trefi.data()) ); - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_trefi_in_ps, static_cast(iv_tCK_in_ps), INVERSE_DDR4_CORRECTION_FACTOR, - l_trefi_in_nck), - "Error in calculating tREFI for target %s, with value of l_trefi_in_ps: %d", mss::c_str(i_target), l_trefi_in_ps); - - FAPI_INF("tCK (ps): %d, tREFI (ps): %d, tREFI (nck): %d", - iv_tCK_in_ps, l_trefi_in_ps, l_trefi_in_nck); - - // Update MCS attribute - l_mcs_attrs_trefi[l_port_num] = l_trefi_in_nck; - - // casts vector into the type FAPI_ATTR_SET is expecting by deduction - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TREFI, - l_mcs, - UINT16_VECTOR_TO_1D_ARRAY(l_mcs_attrs_trefi, PORTS_PER_MCS)), - "Failed to set tREFI attribute"); - } - -fapi_try_exit: - return fapi2::current_err; - -}// refresh_interval - -/// -/// @brief Determines & sets effective config for refresh cycle time (tRFC) -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trfc(const fapi2::Target& i_target) -{ - int64_t l_trfc_mtb = 0; - int64_t l_trfc_in_ps = 0; - - // Selects appropriate tRFC based on fine refresh mode - switch(iv_refresh_mode) - { - case fapi2::ENUM_ATTR_MSS_MRW_FINE_REFRESH_MODE_NORMAL: - FAPI_TRY( iv_pDecoder->min_refresh_recovery_delay_time_1(i_target, l_trfc_mtb), - "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_refresh_recovery_delay_time_2(i_target, 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_refresh_recovery_delay_time_4(i_target, l_trfc_mtb), - "Failed to decode SPD for tRFC4" ); - break; - - default: - // Fine Refresh Mode will be a platform attribute set by the MRW, - // which they "shouldn't" mess up as long as use "attribute" enums. - // if openpower messes this up we can at least catch it - FAPI_ASSERT(false, - fapi2::MSS_INVALID_FINE_REFRESH_MODE(). - set_FINE_REF_MODE(iv_refresh_mode), - "%s Incorrect Fine Refresh Mode received: %d ", - mss::c_str(i_target), - iv_refresh_mode); - break; - - }// switch - - // Calculate trfc (in ps) - { - constexpr int64_t l_trfc_ftb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) ); - - FAPI_INF( "medium timebase (ps): %ld, fine timebase (ps): %ld, tRFC (MTB): %ld, tRFC(FTB): %ld", - l_mtb, l_ftb, l_trfc_mtb, l_trfc_ftb ); - - l_trfc_in_ps = spd::calc_timing_from_timebase(l_trfc_mtb, l_mtb, l_trfc_ftb, l_ftb); - } - - { - // Calculate refresh cycle time in nCK & set attribute - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - - uint16_t l_trfc_in_nck = 0; - std::vector l_mcs_attrs_trfc(PORTS_PER_MCS, 0); - - // Retrieve MCS attribute data - FAPI_TRY( eff_dram_trfc(l_mcs, l_mcs_attrs_trfc.data()), - "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), - "Error in calculating l_tRFC for target %s, with value of l_trfc_in_ps: %d", mss::c_str(i_target), l_trfc_in_ps); - - FAPI_INF("tCK (ps): %d, tRFC (ps): %d, tRFC (nck): %d", - iv_tCK_in_ps, l_trfc_in_ps, l_trfc_in_nck); - - // Update MCS attribute - l_mcs_attrs_trfc[l_port_num] = l_trfc_in_nck; - - // casts vector into the type FAPI_ATTR_SET is expecting by deduction - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRFC, - l_mcs, - UINT16_VECTOR_TO_1D_ARRAY(l_mcs_attrs_trfc, PORTS_PER_MCS) ), - "Failed to set tRFC attribute" ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for refresh cycle time (different logical ranks - tRFC_DLR) -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trfc_dlr(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - - 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 l_mcs_attrs_trfc_dlr(PORTS_PER_MCS, 0); - - // Retrieve map params - FAPI_TRY( iv_pDecoder->sdram_density(i_target, l_density), "Failed to get sdram density"); - FAPI_TRY ( mss::mrw_fine_refresh_mode(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); - - // Calculate refresh cycle time in ps - FAPI_TRY( calc_trfc_dlr(iv_refresh_mode, l_density, l_trfc_dlr_in_ps), "Failed calc_trfc_dlr()" ); - - // Calculate clock period (tCK) from selected freq from mss_freq - FAPI_TRY( clock_period(i_target, l_tCK_in_ps), "Failed to calculate clock period (tCK)"); - - // Calculate refresh cycle time in nck - FAPI_TRY( spd::calc_nck(l_trfc_dlr_in_ps, l_tCK_in_ps, 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); - - // Retrieve MCS attribute data - FAPI_TRY( eff_dram_trfc_dlr(l_mcs, l_mcs_attrs_trfc_dlr.data()), "Failed to retrieve tRFC_DLR attribute" ); - - // Update MCS attribute - l_mcs_attrs_trfc_dlr[l_port_num] = l_trfc_dlr_in_nck; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRFC_DLR, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_mcs_attrs_trfc_dlr, PORTS_PER_MCS) ), - "Failed to set tRFC_DLR attribute" ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for dimm rcd mirror mode -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::rcd_mirror_mode(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_mirror_mode = 0; - uint8_t l_attrs_mirror_mode[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( eff_dimm_rcd_mirror_mode(l_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) ); - l_attrs_mirror_mode[l_port_num][l_dimm_num] = l_mirror_mode; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RCD_MIRROR_MODE, l_mcs, l_attrs_mirror_mode) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for dram bank bits -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_bank_bits(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_bank_bits = 0; - uint8_t l_attrs_bank_bits[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( eff_dram_bank_bits(l_mcs, &l_attrs_bank_bits[0][0]) ); - FAPI_TRY( iv_pDecoder->bank_bits(i_target, l_bank_bits) ); - - l_attrs_bank_bits[l_port_num][l_dimm_num] = l_bank_bits; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_BANK_BITS, l_mcs, l_attrs_bank_bits) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for dram row bits -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_row_bits(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - 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(l_mcs, &l_attrs_row_bits[0][0]) ); - FAPI_TRY( iv_pDecoder->row_address_bits(i_target, l_row_bits) ); - - l_attrs_row_bits[l_port_num][l_dimm_num] = l_row_bits; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_ROW_BITS, l_mcs, l_attrs_row_bits) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tDQS -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note Sets TDQS to off for x4, sets to on for x8 -/// -fapi2::ReturnCode eff_config::dram_dqs_time(const fapi2::Target& i_target) -{ - uint8_t l_attrs_dqs_time[PORTS_PER_MCS] = {}; - uint8_t l_dram_width = 0; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - //Get the DRAM width - FAPI_TRY( iv_pDecoder->device_width(i_target, l_dram_width) ); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_tdqs(l_mcs, &l_attrs_dqs_time[0]) ); - FAPI_INF("SDRAM width: %d for target %s", l_dram_width, mss::c_str(i_target)); - - //Only possible dram width are x4, x8. If x8, tdqs is available, else not available - l_attrs_dqs_time[l_port_num] = (l_dram_width == fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8) ? - fapi2::ENUM_ATTR_EFF_DRAM_TDQS_ENABLE : fapi2::ENUM_ATTR_EFF_DRAM_TDQS_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TDQS, l_mcs, l_attrs_dqs_time) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tCCD_L -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_tccd_l(const fapi2::Target& i_target) -{ - int64_t l_tccd_in_ps = 0; - - // Get the tCCD_L timing values - // tCCD_L is speed bin independent and is - // the same for all bins within a speed grade. - // It is safe to read this from SPD because the correct nck - // value will be calulated based on our dimm speed. - - // TODO: RTC 163150 Clean up eff_config timing boilerplate - { - int64_t l_ftb = 0; - int64_t l_mtb = 0; - int64_t l_tccd_mtb = 0; - int64_t l_tccd_ftb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb), - "Failed medium_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb), - "Failed fine_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->min_tccd_l(i_target, l_tccd_mtb), - "Failed min_tccd_l() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_tccd_l(i_target, l_tccd_ftb), - "Failed fine_offset_min_tccd_l() for %s", mss::c_str(i_target) ); - - FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tCCD_L (MTB): %ld, tCCD_L(FTB): %ld", - l_mtb, l_ftb, l_tccd_mtb, l_tccd_ftb ); - - l_tccd_in_ps = spd::calc_timing_from_timebase(l_tccd_mtb, l_mtb, l_tccd_ftb, l_ftb); - } - - { - // Calculate refresh cycle time in nCK & set attribute - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - - uint8_t l_tccd_in_nck = 0; - std::vector l_mcs_attrs_tccd(PORTS_PER_MCS, 0); - - // Retrieve MCS attribute data - FAPI_TRY( eff_dram_tccd_l(l_mcs, l_mcs_attrs_tccd.data()), - "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), - "Error in calculating tccd for target %s, with value of l_tccd_in_ps: %d", mss::c_str(i_target), l_tccd_in_ps); - - FAPI_INF("tCK (ps): %d, tCCD_L (ps): %d, tCCD_L (nck): %d", - iv_tCK_in_ps, l_tccd_in_ps, l_tccd_in_nck); - - // Update MCS attribute - l_mcs_attrs_tccd[l_port_num] = l_tccd_in_nck; - - // casts vector into the type FAPI_ATTR_SET is expecting by deduction - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TCCD_L, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_mcs_attrs_tccd, PORTS_PER_MCS) ), - "Failed to set tCCD_L attribute" ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC00 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc00(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc00[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc00(l_mcs, &l_attrs_dimm_rc00[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc00[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc00; - - FAPI_INF("%s: RC00 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc00[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC00, l_mcs, l_attrs_dimm_rc00) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC01 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc01(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc01[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc01(l_mcs, &l_attrs_dimm_rc01[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc01[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc01; - - FAPI_INF("%s: RC01 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc01[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC01, l_mcs, l_attrs_dimm_rc01) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC02 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc02(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc02[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc02(l_mcs, &l_attrs_dimm_rc02[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc02[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc02; - - FAPI_INF("%s: RC02 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc02[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC02, l_mcs, l_attrs_dimm_rc02) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC03 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc03(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - fapi2::buffer l_buffer; - - uint8_t l_attrs_dimm_rc03[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - 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_INF( "%s: Retrieved register output drive, for CA: %d, CS: %d", - mss::c_str(i_target), l_ca_output_drive, l_cs_output_drive ); - - // Lets construct encoding byte for RCD setting - { - // Buffer insert constants for CS and CA output drive - constexpr size_t CS_START = 4; - constexpr size_t CA_START = 6; - constexpr size_t LEN = 2; - - l_buffer.insertFromRight(l_ca_output_drive) - .insertFromRight(l_cs_output_drive); - } - // Retrieve MCS attribute data - FAPI_TRY( eff_dimm_ddr4_rc03(l_mcs, &l_attrs_dimm_rc03[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc03[l_port_num][l_dimm_num] = l_buffer; - - FAPI_INF("%s: RC03 settting: %d", mss::c_str(i_target), l_attrs_dimm_rc03[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC03, l_mcs, l_attrs_dimm_rc03) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC04 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc04(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - uint8_t l_attrs_dimm_rc04[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - uint8_t l_odt_output_drive = 0; - uint8_t l_cke_output_drive = 0; - - fapi2::buffer 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_INF( "%s: Retrieved signal driver output, for CKE: %d, ODT: %d", - mss::c_str(i_target), l_cke_output_drive, l_odt_output_drive ); - - // Lets construct encoding byte for RCD setting - { - // Buffer insert constants for ODT and CKE output drive - constexpr size_t CKE_START = 6; - constexpr size_t ODT_START = 4; - constexpr size_t LEN = 2; - - l_buffer.insertFromRight(l_cke_output_drive) - .insertFromRight(l_odt_output_drive); - } - - // Retrieve MCS attribute data - FAPI_TRY( eff_dimm_ddr4_rc04(l_mcs, &l_attrs_dimm_rc04[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc04[l_port_num][l_dimm_num] = l_buffer; - - FAPI_INF("%s: RC04 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc04[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC04, l_mcs, l_attrs_dimm_rc04) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC05 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc05(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - uint8_t l_attrs_dimm_rc05[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - uint8_t l_a_side_output_drive = 0; - uint8_t l_b_side_output_drive = 0; - - fapi2::buffer 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_INF( "%s: Retrieved register output drive for clock, b-side (Y0,Y2): %d, a-side (Y1,Y3): %d", - mss::c_str(i_target), l_b_side_output_drive, l_a_side_output_drive ); - - { - // Buffer insert constants for ODT and CKE output drive - constexpr size_t B_START = 6; - constexpr size_t A_START = 4; - constexpr size_t LEN = 2; - - // Lets construct encoding byte for RCD setting - l_buffer.insertFromRight(l_b_side_output_drive) - .insertFromRight(l_a_side_output_drive); - } - - // Retrieve MCS attribute data - FAPI_TRY( eff_dimm_ddr4_rc05(l_mcs, &l_attrs_dimm_rc05[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc05[l_port_num][l_dimm_num] = l_buffer; - - FAPI_INF( "%s: RC05 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc05[l_port_num][l_dimm_num] ) - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC05, l_mcs, l_attrs_dimm_rc05) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC06_07 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc06_07(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc06_07[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc06_07(l_mcs, &l_attrs_dimm_rc06_07[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc06_07[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc06_07; - - FAPI_INF( "%s: RC06_07 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc06_07[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC06_07, l_mcs, l_attrs_dimm_rc06_07) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC08 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc08(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc08[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc08(l_mcs, &l_attrs_dimm_rc08[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc08[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc08; - - FAPI_INF( "%s: RC08 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc08[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC08, l_mcs, l_attrs_dimm_rc08) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC09 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc09(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // TODO - RTC 160118: Clean up eff_config boiler plate that can moved into helper functions - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc09[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc09(l_mcs, &l_attrs_dimm_rc09[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc09[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc09; - - FAPI_INF( "%s: RC09 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc09[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC09, l_mcs, l_attrs_dimm_rc09) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC10 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc10(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc10[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc10(l_mcs, &l_attrs_dimm_rc10[0][0]) ); - - - switch(iv_freq) - { - case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: - l_attrs_dimm_rc10[l_port_num][l_dimm_num] = rc10_encode::DDR4_1866; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: - l_attrs_dimm_rc10[l_port_num][l_dimm_num] = rc10_encode::DDR4_2133; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: - l_attrs_dimm_rc10[l_port_num][l_dimm_num] = rc10_encode::DDR4_2400; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: - l_attrs_dimm_rc10[l_port_num][l_dimm_num] = rc10_encode::DDR4_2666; - break; - - default: - FAPI_ERR("Invalid frequency for rc10 encoding received: %d", iv_freq); - return fapi2::FAPI2_RC_FALSE; - break; - } - - FAPI_INF( "%s: RC10 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc10[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC10, l_mcs, l_attrs_dimm_rc10) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC11 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc11(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc11[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc11(l_mcs, &l_attrs_dimm_rc11[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc11[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0b; - - FAPI_INF( "%s: RC11 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc11[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC11, l_mcs, l_attrs_dimm_rc11) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC12 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc12(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc12[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc12(l_mcs, &l_attrs_dimm_rc12[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc12[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0c; - - FAPI_INF( "%s: R12 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc12[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC12, l_mcs, l_attrs_dimm_rc12) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC13 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc13(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - uint8_t l_attrs_dimm_rc13[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - fapi2::buffer l_buffer; - - // TODO - RTC 160116: Fix RC0D chip select setting for LRDIMMs - constexpr uint8_t l_cs_mode = rc13_encode::DIRECT_CS_MODE; - uint8_t l_mirror_mode = 0; - uint8_t l_dimm_type = 0; - uint8_t l_module_type = 0; - - FAPI_TRY( spd::base_module_type(i_target, iv_pDecoder->iv_spd_data, l_module_type) ); - - l_dimm_type = (l_module_type == fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) ? - rc13_encode::RDIMM : - rc13_encode::LRDIMM; - - FAPI_TRY( iv_pDecoder->iv_module_decoder->register_to_dram_addr_mapping(l_mirror_mode) ); - - // Lets construct encoding byte for RCD setting - { - // CS - constexpr size_t CS_START = 6; - constexpr size_t CS_LEN = 2; - - // DIMM TYPE - constexpr size_t DIMM_TYPE_START = 5; - constexpr size_t DIMM_TYPE_LEN = 1; - - // MIRROR mode - constexpr size_t MIRROR_START = 4; - constexpr size_t MIRROR_LEN = 1; - - l_buffer.insertFromRight(l_cs_mode) - .insertFromRight(l_dimm_type) - .insertFromRight(l_mirror_mode); - } - - // Retrieve MCS attribute data - FAPI_TRY( eff_dimm_ddr4_rc13(l_mcs, &l_attrs_dimm_rc13[0][0]) ); - - // Update MCS attribute - FAPI_TRY( spd::base_module_type(i_target, iv_pDecoder->iv_spd_data, l_dimm_type) ); - l_attrs_dimm_rc13[l_port_num][l_dimm_num] = l_buffer; - - FAPI_INF( "%s: RC13 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc13[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC13, l_mcs, l_attrs_dimm_rc13) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC14 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc14(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc14[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc14(l_mcs, &l_attrs_dimm_rc14[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc14[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0e; - - FAPI_INF( "%s: RC14 setting: 0x%0x", mss::c_str(i_target), l_attrs_dimm_rc14[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC14, l_mcs, l_attrs_dimm_rc14) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC15 -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc15(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc15[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc15(l_mcs, &l_attrs_dimm_rc15[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc15[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc0f; - - FAPI_INF( "%s: RC15 setting: %d", mss::c_str(i_target), l_attrs_dimm_rc15[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC15, l_mcs, l_attrs_dimm_rc15) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_1x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc1x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_1x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_1x(l_mcs, &l_attrs_dimm_rc_1x[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_1x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc1x; - - FAPI_INF( "%s: RC1X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_1x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_1x, l_mcs, l_attrs_dimm_rc_1x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_2x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc2x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_2x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_2x(l_mcs, &l_attrs_dimm_rc_2x[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_2x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc2x; - - FAPI_INF( "%s: RC2X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_2x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_2x, l_mcs, l_attrs_dimm_rc_2x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_3x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc3x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - uint8_t l_attrs_dimm_rc_3x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Retrieve MCS attribute data - FAPI_TRY( eff_dimm_ddr4_rc_3x(l_mcs, &l_attrs_dimm_rc_3x[0][0]) ); - - switch(iv_freq) - { - case fapi2::ENUM_ATTR_MSS_FREQ_MT1866: - l_attrs_dimm_rc_3x[l_port_num][l_dimm_num] = rc3x_encode::MT1860_TO_MT1880; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2133: - l_attrs_dimm_rc_3x[l_port_num][l_dimm_num] = rc3x_encode::MT2120_TO_MT2140; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2400: - l_attrs_dimm_rc_3x[l_port_num][l_dimm_num] = rc3x_encode::MT2380_TO_MT2400; - break; - - case fapi2::ENUM_ATTR_MSS_FREQ_MT2666: - l_attrs_dimm_rc_3x[l_port_num][l_dimm_num] = rc3x_encode::MT2660_TO_MT2680; - break; - - default: - FAPI_ERR("Invalid frequency for rc_3x encoding received: %d", iv_freq); - return fapi2::FAPI2_RC_FALSE; - break; - } - - FAPI_INF( "%s: RC3X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_3x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_3x, l_mcs, l_attrs_dimm_rc_3x) ); - - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_4x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc4x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_4x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_4x(l_mcs, &l_attrs_dimm_rc_4x[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_4x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc4x; - - FAPI_INF( "%s: RC4X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_4x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_4x, l_mcs, l_attrs_dimm_rc_4x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_5x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc5x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_5x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_5x(l_mcs, &l_attrs_dimm_rc_5x[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_5x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc5x; - - FAPI_INF( "%s: RC5X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_5x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_5x, l_mcs, l_attrs_dimm_rc_5x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_6x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc6x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_6x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_6x(l_mcs, &l_attrs_dimm_rc_6x[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_6x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc6x; - - FAPI_INF( "%s: RC6X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_6x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_6x, l_mcs, l_attrs_dimm_rc_6x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_7x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc7x(const fapi2::Target& i_target) -{ - uint8_t l_attrs_dimm_rc_7x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - fapi2::buffer l_rcd7x = 0; - - // All the IBT bit fields in the RCD control word are 2 bits long. - constexpr uint64_t LEN = 2; - - // CA starts at bit 6, others are the same. So the field runs from START for LEN bits, - // for example CA field is bits 6:7 - constexpr uint64_t CA_START = 6; - uint8_t l_ibt_ca = 0; - - constexpr uint64_t CKE_START = 2; - uint8_t l_ibt_cke = 0; - - constexpr uint64_t CS_START = 4; - uint8_t l_ibt_cs = 0; - - constexpr uint64_t ODT_START = 0; - uint8_t l_ibt_odt = 0; - - // Pull the individual settings from VPD, and shuffle them into RCD7x - FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_ca(i_target, l_ibt_ca) ); - FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_cke(i_target, l_ibt_cke) ); - FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_cs(i_target, l_ibt_cs) ); - FAPI_TRY( mss::vpd_mt_dimm_rcd_ibt_odt(i_target, l_ibt_odt) ); - - l_rcd7x.insertFromRight( ibt_helper(l_ibt_ca) ); - l_rcd7x.insertFromRight( ibt_helper(l_ibt_cke) ); - l_rcd7x.insertFromRight( ibt_helper(l_ibt_cs) ); - l_rcd7x.insertFromRight( ibt_helper(l_ibt_odt) ); - - // Now write RCD7x out to the effective attribute - FAPI_TRY( eff_dimm_ddr4_rc_7x(l_mcs, &l_attrs_dimm_rc_7x[0][0]) ); - l_attrs_dimm_rc_7x[l_port_num][l_dimm_num] = l_rcd7x; - - FAPI_INF( "%s: RC7X setting is 0x%x", mss::c_str(i_target), l_attrs_dimm_rc_7x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_7x, l_mcs, l_attrs_dimm_rc_7x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_8x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc8x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_8x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_8x(l_mcs, &l_attrs_dimm_rc_8x[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_8x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc8x; - - FAPI_INF( "%s: RC8X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_8x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_8x, l_mcs, l_attrs_dimm_rc_8x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_9x -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rc9x(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_9x[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_9x(l_mcs, &l_attrs_dimm_rc_9x[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_9x[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rc9x; - - FAPI_INF( "%s: RC9X setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_9x[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_9x, l_mcs, l_attrs_dimm_rc_9x) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_AX -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rcax(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_ax[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_ax(l_mcs, &l_attrs_dimm_rc_ax[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_ax[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rcax; - - FAPI_INF( "%s: RCAX setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_ax[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_Ax, l_mcs, l_attrs_dimm_rc_ax) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DIMM RC_BX -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dimm_rcbx(const fapi2::Target& i_target) -{ - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - // Retrieve MCS attribute data - uint8_t l_attrs_dimm_rc_bx[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - FAPI_TRY( eff_dimm_ddr4_rc_bx(l_mcs, &l_attrs_dimm_rc_bx[0][0]) ); - - // Update MCS attribute - l_attrs_dimm_rc_bx[l_port_num][l_dimm_num] = iv_pDecoder->iv_raw_card.iv_rcbx; - - FAPI_INF( "%s: RCBX setting: %d", mss::c_str(i_target), l_attrs_dimm_rc_bx[l_port_num][l_dimm_num] ); - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_DDR4_RC_Bx, l_mcs, l_attrs_dimm_rc_bx) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tWR -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_twr(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - int64_t l_twr_in_ps = 0; - - // Get the tWR timing values - // tWR is speed bin independent and is - // the same for all bins within a speed grade. - // It is safe to read this from SPD because the correct nck - // value will be calulated based on our dimm speed. - { - constexpr int64_t l_twr_ftb = 0; - int64_t l_twr_mtb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb), - "Failed medium_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb), - "Failed fine_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->min_write_recovery_time(i_target, l_twr_mtb), - "Failed min_write_recovery_time() for %s", mss::c_str(i_target) ); - - FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWR (MTB): %ld, tWR(FTB): %ld", - l_mtb, l_ftb, l_twr_mtb, l_twr_ftb); - - // Calculate twr (in ps) - l_twr_in_ps = spd::calc_timing_from_timebase(l_twr_mtb, l_mtb, l_twr_ftb, l_ftb); - } - - { - std::vector l_attrs_dram_twr(PORTS_PER_MCS, 0); - 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), - "Error in calculating l_twr_in_nck for target %s, with value of l_twr_in_ps: %d", mss::c_str(i_target), l_twr_in_ps); - - FAPI_INF( "tCK (ps): %d, tWR (ps): %d, tWR (nck): %d for target: %s", - iv_tCK_in_ps, l_twr_in_ps, l_twr_in_nck, mss::c_str(i_target) ); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_twr(l_mcs, l_attrs_dram_twr.data()) ); - - l_attrs_dram_twr[l_port_num] = l_twr_in_nck; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TWR, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_twr, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TWR"); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for RBT -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::read_burst_type(const fapi2::Target& i_target) -{ - uint8_t l_attrs_rbt[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - FAPI_TRY( eff_dram_rbt(l_mcs, &l_attrs_rbt[0][0]) ); - - l_attrs_rbt[l_port_num][l_dimm_num] = fapi2::ENUM_ATTR_EFF_DRAM_RBT_SEQUENTIAL; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_RBT, l_mcs, l_attrs_rbt), - "Failed setting attribute for RTB"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for TM -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note dram testing mode -/// @note always disabled -/// -fapi2::ReturnCode eff_config::dram_tm(const fapi2::Target& i_target) -{ - uint8_t l_attrs_tm[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - FAPI_TRY( eff_dram_tm(l_mcs, &l_attrs_tm[0][0]) ); - - l_attrs_tm[l_port_num][l_dimm_num] = fapi2::ENUM_ATTR_EFF_DRAM_TM_NORMAL; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TM, l_mcs, l_attrs_tm), - "Failed setting attribute for BL"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for cwl -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note Sets CAS Write Latency, depending on frequency and ATTR_MSS_MT_PREAMBLE -/// -fapi2::ReturnCode eff_config::dram_cwl(const fapi2::Target& i_target) -{ - - // Taken from DDR4 JEDEC spec 1716.78C - // Proposed DDR4 Full spec update(79-4A) - // Page 26, Table 7 - static std::pair CWL_TABLE_1 [6] = - { - {1600, 9}, - {1866, 10}, - {2133, 11}, - {2400, 12}, - {2666, 14}, - {3200, 16}, - }; - static std::pair CWL_TABLE_2 [3] = - { - {2400, 14}, - {2666, 16}, - {3200, 18}, - }; - - std::vector l_attrs_cwl(PORTS_PER_MCS, 0); - uint8_t l_cwl = 0; - uint8_t l_preamble = 0; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - // Current index - const auto l_port_num = index(l_mca); - - - FAPI_TRY (vpd_mt_preamble (l_mca, l_preamble) ); - - //get the first nibble as according to vpd. 4-7 is read, 0-3 for write - l_preamble = l_preamble & 0x0F; - - FAPI_ASSERT( ((l_preamble == 0) || (l_preamble == 1)), - fapi2::MSS_INVALID_VPD_MT_PREAMBLE() - .set_VALUE(l_preamble) - .set_DIMM_TARGET(i_target), - "Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d", - mss::c_str(i_target), - l_preamble ); - - // Using an if branch because a ternary conditional wasn't working with params for find_value_from_key - if (l_preamble == 0) - { - FAPI_TRY( mss::find_value_from_key( CWL_TABLE_1, - iv_freq, l_cwl), - "Failed finding CAS Write Latency (cwl), freq: %d, preamble %d", - iv_freq, - l_preamble); - } - else - { - FAPI_TRY( mss::find_value_from_key( CWL_TABLE_2, - iv_freq, l_cwl), - "Failed finding CAS Write Latency (cwl), freq: %d, preamble %d", - iv_freq, - l_preamble); - - } - - FAPI_TRY( eff_dram_cwl(l_mcs, l_attrs_cwl.data()) ); - l_attrs_cwl[l_port_num] = l_cwl; - - FAPI_INF("Calculated CAS Write Latency is %d", l_cwl); - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_CWL, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_cwl, PORTS_PER_MCS)), - "Failed setting attribute for cwl"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for lpasr -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note from JEDEC DDR4 DRAM MR2 page 26 -/// @note All DDR4 supports auto refresh, setting to default -/// -fapi2::ReturnCode eff_config::dram_lpasr(const fapi2::Target& i_target) -{ - std::vector l_attrs_lpasr(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_dram_lpasr(l_mcs, l_attrs_lpasr.data()) ); - - l_attrs_lpasr[l_port_num] = fapi2::ENUM_ATTR_EFF_DRAM_LPASR_MANUAL_EXTENDED; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_LPASR, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_lpasr, PORTS_PER_MCS)), - "Failed setting attribute for LPASR"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for additive latency -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::additive_latency(const fapi2::Target& i_target) -{ - std::vector l_attrs_dram_al(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_dram_al(l_mcs, l_attrs_dram_al.data()) ); - - l_attrs_dram_al[l_port_num] = fapi2::ENUM_ATTR_EFF_DRAM_AL_DISABLE; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_AL, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_al, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_AL"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DLL Reset -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dll_reset(const fapi2::Target& i_target) -{ - uint8_t l_attrs_dll_reset[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - FAPI_TRY( eff_dram_dll_reset(l_mcs, &l_attrs_dll_reset[0][0]) ); - - // Default is to reset DLLs during IPL. - l_attrs_dll_reset[l_port_num][l_dimm_num] = fapi2::ENUM_ATTR_EFF_DRAM_DLL_RESET_YES; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DLL_RESET, l_mcs, l_attrs_dll_reset), - "Failed setting attribute for BL"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for DLL Enable -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dll_enable(const fapi2::Target& i_target) -{ - uint8_t l_attrs_dll_enable[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - const auto l_dimm_num = index(i_target); - - FAPI_TRY( eff_dram_dll_enable(l_mcs, &l_attrs_dll_enable[0][0]) ); - - // Enable DLLs by default. - l_attrs_dll_enable[l_port_num][l_dimm_num] = fapi2::ENUM_ATTR_EFF_DRAM_DLL_ENABLE_YES; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_DLL_ENABLE, l_mcs, l_attrs_dll_enable), - "Failed setting attribute for BL"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for Write Level Enable -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::write_level_enable(const fapi2::Target& i_target) -{ - std::vector l_attrs_wr_lvl_enable(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_dram_wr_lvl_enable(l_mcs, l_attrs_wr_lvl_enable.data()) ); - - l_attrs_wr_lvl_enable[l_port_num] = fapi2::ENUM_ATTR_EFF_DRAM_WR_LVL_ENABLE_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_WR_LVL_ENABLE, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_wr_lvl_enable, PORTS_PER_MCS)), - "Failed setting attribute for WR_LVL_ENABLE"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for Output Buffer -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::output_buffer(const fapi2::Target& i_target) -{ - std::vector l_attrs_output_buffer(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_dram_output_buffer(l_mcs, l_attrs_output_buffer.data()) ); - - l_attrs_output_buffer[l_port_num] = fapi2::ENUM_ATTR_EFF_DRAM_OUTPUT_BUFFER_ENABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_OUTPUT_BUFFER, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_output_buffer, PORTS_PER_MCS)), - "Failed setting attribute for OUTPUT_BUFFER"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for Vref DQ Train Value -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::vref_dq_train_value(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - - uint8_t l_attrs_vref_dq_train_val[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - std::vector< uint64_t > l_ranks; - - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - //value to set. - fapi2::buffer l_vpd_value; - fapi2::buffer l_train_value; - constexpr uint64_t VPD_TRAIN_VALUE_START = 2; - constexpr uint64_t VPD_TRAIN_VALUE_LEN = 6; - //Taken from DDR4 (this attribute is DDR4 only) spec MRS6 section VrefDQ training: values table - constexpr uint8_t JEDEC_MAX_TRAIN_VALUE = 0b00110010; - - FAPI_TRY(mss::vpd_mt_vref_dram_wr(i_target, l_vpd_value)); - l_vpd_value.extractToRight(l_train_value); - - FAPI_ASSERT(l_train_value <= JEDEC_MAX_TRAIN_VALUE, - fapi2::MSS_INVALID_VPD_VREF_DRAM_WR_RANGE() - .set_MAX(JEDEC_MAX_TRAIN_VALUE) - .set_VALUE(l_train_value) - .set_DIMM_TARGET(i_target), - "%s VPD DRAM VREF value out of range max 0x%02x value 0x%02x", mss::c_str(i_target), - JEDEC_MAX_TRAIN_VALUE, l_train_value ); - - // Attribute to set num dimm ranks is a pre-requisite - FAPI_TRY( eff_vref_dq_train_value(l_mcs, &l_attrs_vref_dq_train_val[0][0][0]) ); - FAPI_TRY( mss::rank::ranks(i_target, l_ranks) ); - - for(const auto& l_rank : l_ranks) - { - l_attrs_vref_dq_train_val[l_port_num][l_dimm_num][index(l_rank)] = l_train_value; - } - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_VREF_DQ_TRAIN_VALUE, l_mcs, l_attrs_vref_dq_train_val), - "Failed setting attribute for ATTR_EFF_VREF_DQ_TRAIN_VALUE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for Vref DQ Train Enable -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::vref_dq_train_enable(const fapi2::Target& i_target) -{ - //Default mode for train enable should be normal operation mode - 0x00 - const auto l_mcs = find_target(i_target); - - uint8_t l_attrs_vref_dq_train_enable[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - std::vector< uint64_t > l_ranks; - - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - // Attribute to set num dimm ranks is a pre-requisite - FAPI_TRY( eff_vref_dq_train_enable(l_mcs, &l_attrs_vref_dq_train_enable[0][0][0]) ); - FAPI_TRY( mss::rank::ranks(i_target, l_ranks) ); - - for(const auto& l_rank : l_ranks) - { - l_attrs_vref_dq_train_enable[l_port_num][l_dimm_num][index(l_rank)] = 0x00; - } - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_VREF_DQ_TRAIN_ENABLE, l_mcs, l_attrs_vref_dq_train_enable), - "Failed setting attribute for ATTR_EFF_VREF_DQ_TRAIN_ENABLE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for Vref DQ Train Range -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::vref_dq_train_range(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - - // Attribute to set num dimm ranks is a pre-requisite - uint8_t l_attrs_vref_dq_train_range[PORTS_PER_MCS][MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] = {}; - std::vector< uint64_t > l_ranks; - - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - //value to set. - fapi2::buffer l_vpd_value; - fapi2::buffer l_train_range; - constexpr uint64_t VPD_TRAIN_RANGE_START = 1; - FAPI_TRY(mss::vpd_mt_vref_dram_wr(i_target, l_vpd_value)); - l_train_range = l_vpd_value.getBit(); - - //gets the current value of train_range - FAPI_TRY( eff_vref_dq_train_range(l_mcs, &l_attrs_vref_dq_train_range[0][0][0]) ); - FAPI_TRY( mss::rank::ranks(i_target, l_ranks) ); - - for(const auto& l_rank : l_ranks) - { - l_attrs_vref_dq_train_range[l_port_num][l_dimm_num][index(l_rank)] = l_train_range; - } - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_VREF_DQ_TRAIN_RANGE, l_mcs, l_attrs_vref_dq_train_range), - "Failed setting attribute for ATTR_EFF_VREF_DQ_TRAIN_RANGE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for CA Parity Latency -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::ca_parity_latency(const fapi2::Target& i_target) -{ - //TODO: RTC 159554 Update RAS related attributes - std::vector l_attrs_ca_parity_latency(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_ca_parity_latency(l_mcs, l_attrs_ca_parity_latency.data()) ); - l_attrs_ca_parity_latency[l_port_num] = fapi2::ENUM_ATTR_EFF_CA_PARITY_LATENCY_DISABLE; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CA_PARITY_LATENCY, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_ca_parity_latency, PORTS_PER_MCS)), - "Failed setting attribute for CA_PARITY_LATENCY"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for CRC Error Clear -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::crc_error_clear(const fapi2::Target& i_target) -{ - //TODO: RTC 159554 Update RAS related attributes - std::vector l_attrs_crc_error_clear(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_crc_error_clear(l_mcs, l_attrs_crc_error_clear.data()) ); - - l_attrs_crc_error_clear[l_port_num] = fapi2::ENUM_ATTR_EFF_CRC_ERROR_CLEAR_CLEAR; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CRC_ERROR_CLEAR, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_crc_error_clear, PORTS_PER_MCS)), - "Failed setting attribute for CRC_ERROR_CLEAR"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for CA Parity Error Status -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::ca_parity_error_status(const fapi2::Target& i_target) -{ - //TODO: RTC 159554 Update RAS related attributes - std::vector l_attrs_ca_parity_error_status(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_ca_parity_error_status(l_mcs, l_attrs_ca_parity_error_status.data()) ); - - l_attrs_ca_parity_error_status[l_port_num] = fapi2::ENUM_ATTR_EFF_CA_PARITY_ERROR_STATUS_CLEAR; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CA_PARITY_ERROR_STATUS, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_ca_parity_error_status, PORTS_PER_MCS)), - "Failed setting attribute for CA_PARITY_ERROR_STATUS"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for CA Parity -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::ca_parity(const fapi2::Target& i_target) -{ - //TODO: RTC 159554 Update RAS related attributes - std::vector l_attrs_ca_parity(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_ca_parity(l_mcs, l_attrs_ca_parity.data()) ); - - l_attrs_ca_parity[l_port_num] = fapi2::ENUM_ATTR_EFF_CA_PARITY_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CA_PARITY, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_ca_parity, PORTS_PER_MCS)), - "Failed setting attribute for CA_PARITY"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for ODT Input Buffer -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::odt_input_buffer(const fapi2::Target& i_target) -{ - // keeping this value as 0x01, given that we know that that works in sim - constexpr uint8_t SIM_VALUE = 0x01; - std::vector l_attrs_odt_input_buffer(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - //keep simulation to values we know work - uint8_t is_sim = 0; - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), is_sim) ); - - - FAPI_TRY( eff_odt_input_buff(l_mcs, l_attrs_odt_input_buffer.data()) ); - - //sim vs actual hardware value - l_attrs_odt_input_buffer[l_port_num] = is_sim ? SIM_VALUE : fapi2::ENUM_ATTR_EFF_ODT_INPUT_BUFF_ACTIVATED; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_ODT_INPUT_BUFF, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_odt_input_buffer, PORTS_PER_MCS)), - "Failed setting attribute for ODT_INPUT_BUFF"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for data_mask -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note Datamask is unnused and not needed because no DBI. -/// @note Defaulted to 0 -/// -fapi2::ReturnCode eff_config::data_mask(const fapi2::Target& i_target) -{ - std::vector l_attrs_data_mask(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_data_mask(l_mcs, l_attrs_data_mask.data()) ); - - l_attrs_data_mask[l_port_num] = fapi2::ENUM_ATTR_EFF_DATA_MASK_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DATA_MASK, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_data_mask, PORTS_PER_MCS)), - "Failed setting attribute for DATA_MASK"); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for write_dbi -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note DBI is not supported -/// -fapi2::ReturnCode eff_config::write_dbi(const fapi2::Target& i_target) -{ - std::vector l_attrs_write_dbi(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_write_dbi(l_mcs, l_attrs_write_dbi.data()) ); - - l_attrs_write_dbi[l_port_num] = fapi2::ENUM_ATTR_EFF_WRITE_DBI_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_WRITE_DBI, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_write_dbi, PORTS_PER_MCS)), - "Failed setting attribute for WRITE_DBI"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for read_dbi -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note read_dbi is not supported, so set to DISABLED (0) -/// @note No logic for DBI -/// -fapi2::ReturnCode eff_config::read_dbi(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - - std::vector l_attrs_read_dbi(PORTS_PER_MCS, 0); - FAPI_TRY( eff_read_dbi(l_mcs, l_attrs_read_dbi.data()) ); - - l_attrs_read_dbi[l_port_num] = fapi2::ENUM_ATTR_EFF_READ_DBI_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_READ_DBI, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_read_dbi, PORTS_PER_MCS)), - "Failed setting attribute for READ_DBI"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for Post Package Repair -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// @note write_dbi is not supported, so set to DISABLED (0) -/// @note no logic for DBI -/// -fapi2::ReturnCode eff_config::post_package_repair(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - const auto l_dimm_num = index(i_target); - - uint8_t l_decoder_val = 0; - uint8_t l_attrs_dram_ppr[PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {}; - - FAPI_TRY( eff_dram_ppr(l_mcs, &l_attrs_dram_ppr[0][0]) ); - FAPI_TRY( iv_pDecoder->post_package_repair(i_target, l_decoder_val) ); - - l_attrs_dram_ppr[l_port_num][l_dimm_num] = l_decoder_val; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_PPR, l_mcs, l_attrs_dram_ppr), - "Failed setting attribute for DRAM_PPR"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for rd_preamble_train -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::read_preamble_train(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index( find_target(i_target) ); - - std::vector l_attrs_rd_preamble_train(PORTS_PER_MCS, 0); - FAPI_TRY( eff_rd_preamble_train(l_mcs, l_attrs_rd_preamble_train.data()) ); - - l_attrs_rd_preamble_train[l_port_num] = fapi2::ENUM_ATTR_EFF_RD_PREAMBLE_TRAIN_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_RD_PREAMBLE_TRAIN, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_rd_preamble_train, PORTS_PER_MCS)), - "Failed setting attribute for RD_PREAMBLE_TRAIN"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for rd_preamble -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::read_preamble(const fapi2::Target& i_target) -{ - std::vector l_attrs_rd_preamble(PORTS_PER_MCS, 0); - uint8_t l_preamble = 0; - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY (vpd_mt_preamble (l_mca, l_preamble) ) ; - l_preamble = l_preamble & 0xF0; - l_preamble = l_preamble >> 4; - - - FAPI_ASSERT( ((l_preamble == 0) || (l_preamble == 1)), - fapi2::MSS_INVALID_VPD_MT_PREAMBLE() - .set_VALUE(l_preamble) - .set_DIMM_TARGET(i_target), - "Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d", - mss::c_str(i_target), - l_preamble ); - - FAPI_TRY( eff_rd_preamble(l_mcs, l_attrs_rd_preamble.data()) ); - - l_attrs_rd_preamble[l_port_num] = l_preamble; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_RD_PREAMBLE, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_rd_preamble, PORTS_PER_MCS)), - "Failed setting attribute for RD_PREAMBLE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for wr_preamble -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::write_preamble(const fapi2::Target& i_target) -{ - std::vector l_attrs_wr_preamble(PORTS_PER_MCS, 0); - uint8_t l_preamble = 0; - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY (vpd_mt_preamble (l_mca, l_preamble) ) ; - l_preamble = l_preamble & 0x0F; - FAPI_INF("WR preamble is %d", l_preamble); - - FAPI_ASSERT( ((l_preamble == 0) || (l_preamble == 1)), - fapi2::MSS_INVALID_VPD_MT_PREAMBLE() - .set_VALUE(l_preamble) - .set_DIMM_TARGET(i_target), - "Target %s VPD_MT_PREAMBLE is invalid (not 1 or 0), value is %d", - mss::c_str(i_target), - l_preamble ); - - FAPI_TRY( eff_wr_preamble(l_mcs, l_attrs_wr_preamble.data()) ); - - l_attrs_wr_preamble[l_port_num] = l_preamble; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_WR_PREAMBLE, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_wr_preamble, PORTS_PER_MCS)), - "Failed setting attribute for RD_PREAMBLE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for self_ref_abort -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::self_refresh_abort(const fapi2::Target& i_target) -{ - std::vector l_attrs_self_ref_abort(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_self_ref_abort(l_mcs, l_attrs_self_ref_abort.data()) ); - - l_attrs_self_ref_abort[l_port_num] = fapi2::ENUM_ATTR_EFF_SELF_REF_ABORT_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_SELF_REF_ABORT, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_self_ref_abort, PORTS_PER_MCS)), - "Failed setting attribute for SELF_REF_ABORT"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for cs_cmd_latency -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::cs_to_cmd_addr_latency(const fapi2::Target& i_target) -{ - std::vector l_attrs_cs_cmd_latency(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_cs_cmd_latency(l_mcs, l_attrs_cs_cmd_latency.data()) ); - - l_attrs_cs_cmd_latency[l_port_num] = fapi2::ENUM_ATTR_EFF_CS_CMD_LATENCY_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CS_CMD_LATENCY, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_cs_cmd_latency, PORTS_PER_MCS)), - "Failed setting attribute for CS_CMD_LATENCY"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for int_vref_mon -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::internal_vref_monitor(const fapi2::Target& i_target) -{ - std::vector l_attrs_int_vref_mon(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_internal_vref_monitor(l_mcs, l_attrs_int_vref_mon.data()) ); - - l_attrs_int_vref_mon[l_port_num] = fapi2::ENUM_ATTR_EFF_INTERNAL_VREF_MONITOR_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_INTERNAL_VREF_MONITOR, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_int_vref_mon, PORTS_PER_MCS)), - "Failed setting attribute for INT_VREF_MON"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for powerdown_mode -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::max_powerdown_mode(const fapi2::Target& i_target) -{ - std::vector l_attrs_powerdown_mode(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_max_powerdown_mode(l_mcs, l_attrs_powerdown_mode.data()) ); - - l_attrs_powerdown_mode[l_port_num] = fapi2::ENUM_ATTR_EFF_MAX_POWERDOWN_MODE_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MAX_POWERDOWN_MODE, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_powerdown_mode, PORTS_PER_MCS)), - "Failed setting attribute for POWERDOWN_MODE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for mpr_rd_format -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::mpr_read_format(const fapi2::Target& i_target) -{ - std::vector l_attrs_mpr_rd_format(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_mpr_rd_format(l_mcs, l_attrs_mpr_rd_format.data()) ); - - //Serial format is standard for Nimbus and needed for PHY calibration (draminit_training) - l_attrs_mpr_rd_format[l_port_num] = fapi2::ENUM_ATTR_EFF_MPR_RD_FORMAT_SERIAL; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MPR_RD_FORMAT, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_mpr_rd_format, PORTS_PER_MCS)), - "Failed setting attribute for MPR_RD_FORMAT"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for CRC write latency -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::crc_wr_latency(const fapi2::Target& i_target) -{ - std::vector l_attrs_crc_wr_latency(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - //keep simulation to values we know work - uint8_t is_sim = 0; - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_IS_SIMULATION, fapi2::Target(), is_sim) ); - - FAPI_TRY( eff_crc_wr_latency(l_mcs, l_attrs_crc_wr_latency.data()) ); - - //keep simulation to values we know work - if(is_sim) - { - l_attrs_crc_wr_latency[l_port_num] = 0x05; - } - //set the attribute according to frequency - else - { - //TODO RTC:159481 - update CRC write latency to include 2667 - //currently, JEDEC defines the following - //crc wr latency - freq - //4 - 1600 - //5 - 1866, 2133, 2400 - //6 - TBD - //Nimbus only supports 1866->2400 on the current list - //2667 is not noted. We will set crc_wr_latency to 0x05 until JEDEC value is updated - //When JEDEC defines the 2667 value we can change this, but leave the sim value as 0x05 - l_attrs_crc_wr_latency[l_port_num] = 0x05; - } - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_CRC_WR_LATENCY, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_crc_wr_latency, PORTS_PER_MCS)), - "Failed setting attribute for CRC WRITE LATENCY"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for temperature readout -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::temp_readout(const fapi2::Target& i_target) -{ - std::vector l_attrs_temp_readout(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_temp_readout(l_mcs, l_attrs_temp_readout.data()) ); - - //Disabled for mainline mode - l_attrs_temp_readout[l_port_num] = fapi2::ENUM_ATTR_EFF_TEMP_READOUT_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_TEMP_READOUT, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_temp_readout, PORTS_PER_MCS)), - "Failed setting attribute for TEMP_READOUT"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for per DRAM addressability -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::per_dram_addressability(const fapi2::Target& i_target) -{ - std::vector l_attrs_per_dram_access(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_per_dram_access(l_mcs, l_attrs_per_dram_access.data()) ); - - //PDA is disabled in mainline functionality - l_attrs_per_dram_access[l_port_num] = fapi2::ENUM_ATTR_EFF_PER_DRAM_ACCESS_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_PER_DRAM_ACCESS, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_per_dram_access, PORTS_PER_MCS)), - "Failed setting attribute for PER_DRAM_ACCESS"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for geardown mode -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::geardown_mode(const fapi2::Target& i_target) -{ - std::vector l_attrs_geardown_mode(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - // Geardown maps directly to autoset = 0 gets 1/2 rate, 1 get 1/4 rate. - FAPI_TRY( eff_geardown_mode(l_mcs, l_attrs_geardown_mode.data()) ); - - // If the MRW states 'auto' we use what's in VPD, otherwise we use what's in the MRW. - // We remove 1 from the value as that matches the expectations in the MR perfectly. - l_attrs_geardown_mode[l_port_num] = mss::two_n_mode_helper(i_target); - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_GEARDOWN_MODE, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_geardown_mode, PORTS_PER_MCS)), - "Failed setting attribute for GEARDOWN_MODE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for MPR page -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::mpr_page(const fapi2::Target& i_target) -{ - std::vector l_attrs_mpr_page(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_mpr_page(l_mcs, l_attrs_mpr_page.data()) ); - - //page0 is needed for PHY calibration algorithm (run in draminit_training) - l_attrs_mpr_page[l_port_num] = fapi2::ENUM_ATTR_EFF_MPR_PAGE_PG0; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MPR_PAGE, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_mpr_page, PORTS_PER_MCS)), - "Failed setting attribute for MPR_PAGE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for MPR mode -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::mpr_mode(const fapi2::Target& i_target) -{ - std::vector l_attrs_mpr_mode(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_mpr_mode(l_mcs, l_attrs_mpr_mode.data()) ); - - //MPR mode is disabled for mainline functionality - l_attrs_mpr_mode[l_port_num] = fapi2::ENUM_ATTR_EFF_MPR_MODE_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MPR_MODE, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_mpr_mode, PORTS_PER_MCS)), - "Failed setting attribute for MPR_MODE"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for write CRC -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::write_crc(const fapi2::Target& i_target) -{ - //TODO: RTC 159554 Update RAS related attributes - std::vector l_attrs_write_crc(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_write_crc(l_mcs, l_attrs_write_crc.data()) ); - - l_attrs_write_crc[l_port_num] = fapi2::ENUM_ATTR_EFF_WRITE_CRC_DISABLE; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_WRITE_CRC, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_write_crc, PORTS_PER_MCS)), - "Failed setting attribute for WRITE_CRC"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for ZQ Calibration -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::zqcal_interval(const fapi2::Target& i_target) -{ - std::vector l_attrs_zqcal_interval(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_zqcal_interval(l_mcs, l_attrs_zqcal_interval.data()) ); - - // Calculate ZQCAL Interval based on the following equation from Ken: - // 0.5 - // ------------------------------ = 13.333ms - // (1.5 * 10) + (0.15 * 150) - // (13333 * ATTR_MSS_FREQ) / 2 - - l_attrs_zqcal_interval[l_port_num] = 13333 * iv_freq / 2; - - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_ZQCAL_INTERVAL, - l_mcs, - UINT32_VECTOR_TO_1D_ARRAY(l_attrs_zqcal_interval, PORTS_PER_MCS)), - "Failed setting attribute for ZQCAL_INTERVAL"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for MEMCAL Calibration -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::memcal_interval(const fapi2::Target& i_target) -{ - std::vector l_attrs_memcal_interval(PORTS_PER_MCS, 0); - - // Targets - const auto l_mcs = find_target(i_target); - const auto l_mca = find_target(i_target); - - // Current index - const auto l_port_num = index(l_mca); - - FAPI_TRY( eff_memcal_interval(l_mcs, l_attrs_memcal_interval.data()) ); - - // Calculate MEMCAL Interval based on 1sec interval across all bits per DP16 - // (62500 * ATTR_MSS_FREQ) / 2 - l_attrs_memcal_interval[l_port_num] = 62500 * iv_freq / 2; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_MEMCAL_INTERVAL, - l_mcs, - UINT32_VECTOR_TO_1D_ARRAY(l_attrs_memcal_interval, PORTS_PER_MCS)), - "Failed setting attribute for MEMCAL_INTERVAL"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRP -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trp(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - int64_t l_trp_in_ps = 0; - - // Calculate tRP (in ps) - { - int64_t l_trp_mtb = 0; - int64_t l_trp_ftb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb), - "Failed medium_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb), - "Failed fine_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->min_row_precharge_delay_time(i_target, l_trp_mtb), - "Failed min_row_precharge_delay_time() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trp(i_target, l_trp_ftb), - "Failed fine_offset_min_trp() for %s", mss::c_str(i_target) ); - - FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tRP (MTB): %ld, tRP(FTB): %ld", - l_mtb, l_ftb, l_trp_mtb, l_trp_ftb); - - l_trp_in_ps = spd::calc_timing_from_timebase(l_trp_mtb, l_mtb, l_trp_ftb, l_ftb); - } - - // SPD spec gives us the minimum... compute our worstcase (maximum) from JEDEC - { - // Declaring as int64_t to fix std::max compile - const int64_t l_trp = mss::ps_to_cycles(i_target, mss::trtp()); - l_trp_in_ps = std::max( l_trp_in_ps , l_trp ); - } - - { - std::vector l_attrs_dram_trp(PORTS_PER_MCS, 0); - 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), - "Error in calculating dram_tRP nck for target %s, with value of l_trp_in_ps: %d", mss::c_str(i_target), l_trp_in_ps); - - FAPI_INF( "tCK (ps): %d, tRP (ps): %d, tRP (nck): %d for target: %s", - iv_tCK_in_ps, l_trp_in_ps, l_trp_in_nck, mss::c_str(i_target) ); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_trp(l_mcs, l_attrs_dram_trp.data()) ); - - l_attrs_dram_trp[l_port_num] = l_trp_in_nck ; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRP, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trp, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TRP"); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRCD -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trcd(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - int64_t l_trcd_in_ps = 0; - - // Calculate tRCD (in ps) - // Get the tRCD timing values - // tRCD is speed bin dependent and has a unique - // value for each speed bin so it is safe to - // read from SPD because the correct nck - // value will be calulated based on our dimm speed. - { - int64_t l_trcd_mtb = 0; - int64_t l_trcd_ftb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb), - "Failed medium_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb), - "Failed fine_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->min_ras_to_cas_delay_time(i_target, l_trcd_mtb), - "Failed min_ras_to_cas_delay_time() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trcd(i_target, l_trcd_ftb), - "Failed fine_offset_min_trcd() for %s", mss::c_str(i_target) ); - - FAPI_INF("medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCD (MTB): %ld, tRCD (FTB): %ld", - l_mtb, l_ftb, l_trcd_mtb, l_trcd_ftb); - - l_trcd_in_ps = spd::calc_timing_from_timebase(l_trcd_mtb, l_mtb, l_trcd_ftb, l_ftb); - } - - { - std::vector l_attrs_dram_trcd(PORTS_PER_MCS, 0); - 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), - "Error in calculating trcd for target %s, with value of l_trcd_in_ps: %d", mss::c_str(i_target), l_trcd_in_ps); - - FAPI_INF("tCK (ps): %d, tRCD (ps): %d, tRCD (nck): %d for target: %s", - iv_tCK_in_ps, l_trcd_in_ps, l_trcd_in_nck, mss::c_str(i_target)); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_trcd(l_mcs, l_attrs_dram_trcd.data()) ); - - l_attrs_dram_trcd[l_port_num] = l_trcd_in_nck; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRCD, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trcd, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TRCD"); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRC -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trc(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - int64_t l_trc_in_ps = 0; - - // Calculate trc (in ps) - { - int64_t l_trc_mtb = 0; - int64_t l_trc_ftb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb), - "Failed medium_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb), - "Failed fine_timebase() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->min_active_to_active_refresh_delay_time(i_target, l_trc_mtb), - "Failed min_active_to_active_refresh_delay_time() for %s", mss::c_str(i_target) ); - FAPI_TRY( iv_pDecoder->fine_offset_min_trc(i_target, l_trc_ftb), - "Failed fine_offset_min_trc() for %s", mss::c_str(i_target) ); - - FAPI_INF("medium timebase MTB (ps): %ld, fine timebase FTB (ps): %ld, tRCmin (MTB): %ld, tRCmin(FTB): %ld", - l_mtb, l_ftb, l_trc_mtb, l_trc_ftb); - - l_trc_in_ps = spd::calc_timing_from_timebase(l_trc_mtb, l_mtb, l_trc_ftb, l_ftb); - } - - { - std::vector l_attrs_dram_trc(PORTS_PER_MCS, 0); - uint8_t l_trc_in_nck = 0; - - // Calculate nck - FAPI_TRY( spd::calc_nck(l_trc_in_ps, iv_tCK_in_ps, INVERSE_DDR4_CORRECTION_FACTOR, l_trc_in_nck), - "Error in calculating trc for target %s, with value of l_trc_in_ps: %d", - mss::c_str(i_target), l_trc_in_ps ); - - FAPI_INF( "tCK (ps): %d, tRC (ps): %d, tRC (nck): %d for target: %s", - iv_tCK_in_ps, l_trc_in_ps, l_trc_in_nck, mss::c_str(i_target) ); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_trc(l_mcs, l_attrs_dram_trc.data()) ); - - l_attrs_dram_trc[l_port_num] = l_trc_in_nck; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRC, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trc, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TRC"); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tWTR_L -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_twtr_l(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - int64_t l_twtr_l_in_ps = 0; - - // Calculate twtr_l (in ps) - { - constexpr int64_t l_twtr_l_ftb = 0; - int64_t l_twtr_l_mtb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) ); - FAPI_TRY( iv_pDecoder->min_twtr_l(i_target, l_twtr_l_mtb) ); - - FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", - l_mtb, l_ftb, l_twtr_l_mtb, l_twtr_l_ftb ); - - l_twtr_l_in_ps = spd::calc_timing_from_timebase(l_twtr_l_mtb, l_mtb, l_twtr_l_ftb, l_ftb); - } - - - { - std::vector l_attrs_dram_twtr_l(PORTS_PER_MCS, 0); - 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), - "Error in calculating tWTR_L for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_twtr_l_in_ps ); - - FAPI_INF( "tCK (ps): %d, tWTR_L (ps): %d, tWTR_L (nck): %d for target: %s", - iv_tCK_in_ps, l_twtr_l_in_ps, l_twtr_l_in_nck, mss::c_str(i_target) ); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_twtr_l(l_mcs, l_attrs_dram_twtr_l.data()) ); - - l_attrs_dram_twtr_l[l_port_num] = l_twtr_l_in_nck; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TWTR_L, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_twtr_l, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TWTR_L"); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tWTR_S -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_twtr_s(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - int64_t l_twtr_s_in_ps = 0; - - // Calculate twtr_s (in ps) - { - constexpr int64_t l_twtr_s_ftb = 0; - int64_t l_twtr_s_mtb = 0; - int64_t l_ftb = 0; - int64_t l_mtb = 0; - - FAPI_TRY( iv_pDecoder->medium_timebase(i_target, l_mtb) ); - FAPI_TRY( iv_pDecoder->fine_timebase(i_target, l_ftb) ); - FAPI_TRY( iv_pDecoder->min_twtr_s(i_target, l_twtr_s_mtb) ); - - FAPI_INF("medium timebase (ps): %ld, fine timebase (ps): %ld, tWTR_S (MTB): %ld, tWTR_S (FTB): %ld", - l_mtb, l_ftb, l_twtr_s_mtb, l_twtr_s_ftb ); - - l_twtr_s_in_ps = spd::calc_timing_from_timebase(l_twtr_s_mtb, l_mtb, l_twtr_s_ftb, l_ftb); - } - - { - std::vector l_attrs_dram_twtr_s(PORTS_PER_MCS, 0); - 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), - "Error in calculating tWTR_S for target %s, with value of l_twtr_in_ps: %d", mss::c_str(i_target), l_twtr_s_in_ps); - - FAPI_INF("tCK (ps): %d, tWTR_S (ps): %d, tWTR_S (nck): %d for target: %s", - iv_tCK_in_ps, l_twtr_s_in_ps, l_twtr_s_in_nck, mss::c_str(i_target) ); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_twtr_s(l_mcs, l_attrs_dram_twtr_s.data()) ); - - l_attrs_dram_twtr_s[l_port_num] = l_twtr_s_in_nck; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TWTR_S, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_twtr_s, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TWTR_S"); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRRD_S -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trrd_s(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - std::vector l_attrs_dram_trrd_s(PORTS_PER_MCS, 0); - uint64_t l_trrd_s_in_nck = 0; - uint8_t l_stack_type = 0; - uint8_t l_dram_width = 0; - - FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(i_target, l_stack_type) ); - FAPI_TRY( iv_pDecoder->device_width(i_target, l_dram_width), - "Failed to access device_width()"); - - // From the SPD Spec: - // At some frequencies, a minimum number of clocks may be required resulting - // in a larger tRRD_Smin value than indicated in the SPD. - // tRRD_S (3DS) is speed bin independent. - // So we won't read this from SPD and choose the correct value based on mss_freq - - if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) - { - FAPI_TRY( trrd_s_slr(i_target, l_trrd_s_in_nck) ); - } - else - { - // Non-3DS - FAPI_TRY( mss::trrd_s(i_target, l_dram_width, l_trrd_s_in_nck) ); - } - - FAPI_INF("SDRAM width: %d, tRRD_S (nck): %d for target: %s", - l_dram_width, l_trrd_s_in_nck, mss::c_str(i_target)); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_trrd_s(l_mcs, l_attrs_dram_trrd_s.data()) ); - - l_attrs_dram_trrd_s[l_port_num] = l_trrd_s_in_nck; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_S, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_s, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TRRD_S"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRRD_L -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trrd_l(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - std::vector l_attrs_dram_trrd_l(PORTS_PER_MCS, 0); - uint64_t l_trrd_l_in_nck = 0; - uint8_t l_stack_type = 0; - uint8_t l_dram_width = 0; - - FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(i_target, l_stack_type), - "Failed prim_sdram_signal_loading()" ); - FAPI_TRY( iv_pDecoder->device_width(i_target, l_dram_width), - "Failed to access device_width()"); - - // From the SPD Spec: - // At some frequencies, a minimum number of clocks may be required resulting - // in a larger tRRD_Smin value than indicated in the SPD. - // tRRD_S (3DS) is speed bin independent. - // So we won't read this from SPD and choose the correct value based on mss_freq - - if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) - { - FAPI_TRY( trrd_l_slr(i_target, l_trrd_l_in_nck) ); - } - else - { - FAPI_TRY( mss::trrd_l(i_target, l_dram_width, l_trrd_l_in_nck), "Failed trrd_l()" ); - } - - FAPI_INF("SDRAM width: %d, tRRD_L (nck): %d for target: %s", - l_dram_width, l_trrd_l_in_nck, mss::c_str(i_target)); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_trrd_l(l_mcs, l_attrs_dram_trrd_l.data()) ); - - l_attrs_dram_trrd_l[l_port_num] = l_trrd_l_in_nck; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_L, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_l, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TRRD_L"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRRD_dlr -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trrd_dlr(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - std::vector l_attrs_dram_trrd_dlr(PORTS_PER_MCS, 0); - constexpr uint64_t l_trrd_dlr_in_nck = trrd_dlr(); - - FAPI_INF("tRRD_dlr (nck): %d for target: %s", l_trrd_dlr_in_nck, mss::c_str(i_target)); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_trrd_dlr(l_mcs, l_attrs_dram_trrd_dlr.data()) ); - - l_attrs_dram_trrd_dlr[l_port_num] = l_trrd_dlr_in_nck; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRRD_DLR, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trrd_dlr, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TRRD_DLR"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tfaw -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_tfaw(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - std::vector l_attrs_dram_tfaw(PORTS_PER_MCS, 0); - uint64_t l_tfaw_in_nck = 0; - uint8_t l_stack_type = 0; - uint8_t l_dram_width = 0; - - FAPI_TRY( iv_pDecoder->prim_sdram_signal_loading(i_target, l_stack_type), - "Failed prim_sdram_signal_loading()"); - FAPI_TRY( iv_pDecoder->device_width(i_target, l_dram_width), - "Failed device_width()"); - - if( l_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) - { - FAPI_TRY( tfaw_slr(i_target, l_dram_width, l_tfaw_in_nck), "Failed tfaw_slr()"); - } - else - { - FAPI_TRY( mss::tfaw(i_target, l_dram_width, l_tfaw_in_nck), "Failed tfaw()" ); - } - - FAPI_INF("SDRAM width: %d, tFAW (nck): %d for target: %s", - l_dram_width, l_tfaw_in_nck, mss::c_str(i_target)); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_tfaw(l_mcs, l_attrs_dram_tfaw.data()) ); - - l_attrs_dram_tfaw[l_port_num] = l_tfaw_in_nck; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TFAW, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tfaw, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TFAW"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tFAW_DLR -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_tfaw_dlr(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - std::vector l_attrs_dram_tfaw_dlr(PORTS_PER_MCS, 0); - constexpr uint64_t l_tfaw_dlr_in_nck = tfaw_dlr(); - - FAPI_INF("tFAW_dlr (nck): %d for target: %s", l_tfaw_dlr_in_nck, mss::c_str(i_target)); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_tfaw_dlr(l_mcs, l_attrs_dram_tfaw_dlr.data()) ); - - l_attrs_dram_tfaw_dlr[l_port_num] = l_tfaw_dlr_in_nck; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TFAW_DLR, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tfaw_dlr, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TFAW_DLR"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRAS -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_tras(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - // tRAS is bin independent so we don't read this from SPD - // which will give the best timing value for the dimm - // (like 2400 MT/s) which may be different than the system - // speed (if we were being limited by VPD or MRW restrictions) - const uint64_t l_tras_in_ps = mss::tras(i_target); - - // Calculate nck - std::vector l_attrs_dram_tras(PORTS_PER_MCS, 0); - uint8_t l_tras_in_nck = 0; - - // Cast needed for calculations to be done on the same integral type - // as required by template deduction. We have iv_tCK_in_ps as a signed - // integer because we have other timing values that calculations do - // addition with negative integers. - FAPI_TRY( spd::calc_nck(l_tras_in_ps, - static_cast(iv_tCK_in_ps), - INVERSE_DDR4_CORRECTION_FACTOR, - l_tras_in_nck), - "Error in calculating tras_l for target %s, with value of l_twtr_in_ps: %d", - mss::c_str(i_target), l_tras_in_ps); - - FAPI_INF("tCK (ps): %d, tRAS (ps): %d, tRAS (nck): %d for target: %s", - iv_tCK_in_ps, l_tras_in_ps, l_tras_in_nck, mss::c_str(i_target)); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_tras(l_mcs, l_attrs_dram_tras.data()) ); - - l_attrs_dram_tras[l_port_num] = l_tras_in_nck; - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRAS, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_tras, PORTS_PER_MCS)), - "Failed setting attribute for tRAS"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Determines & sets effective config for tRTP -/// @param[in] i_target FAPI2 target -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::dram_trtp(const fapi2::Target& i_target) -{ - const auto l_mcs = find_target(i_target); - const auto l_port_num = index(find_target(i_target)); - - // Values from proposed DDR4 Full spec update(79-4A) - // Item No. 1716.78C - // Page 241 & 246 - int64_t constexpr l_max_trtp_in_ps = trtp(); - - std::vector l_attrs_dram_trtp(PORTS_PER_MCS, 0); - 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), - "Error in calculating trtp for target %s, with value of l_twtr_in_ps: %d", - mss::c_str(i_target), l_max_trtp_in_ps); - - FAPI_INF("tCK (ps): %d, tRTP (ps): %d, tRTP (nck): %d", - iv_tCK_in_ps, l_max_trtp_in_ps, l_calc_trtp_in_nck); - - // Get & update MCS attribute - FAPI_TRY( eff_dram_trtp(l_mcs, l_attrs_dram_trtp.data()) ); - - l_attrs_dram_trtp[l_port_num] = l_calc_trtp_in_nck; - - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_TRTP, - l_mcs, - UINT8_VECTOR_TO_1D_ARRAY(l_attrs_dram_trtp, PORTS_PER_MCS)), - "Failed setting attribute for DRAM_TRTP"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Grab the VPD blobs and decode into attributes -/// @param[in] i_target FAPI2 target (MCS) -/// @return fapi2::FAPI2_RC_SUCCESS if okay -/// -fapi2::ReturnCode eff_config::decode_vpd(const fapi2::Target& i_target) -{ - uint8_t l_mr_blob[mss::VPD_KEYWORD_MAX] = {0}; - uint8_t l_cke_blob[mss::VPD_KEYWORD_MAX] = {0}; - uint8_t l_dq_blob[mss::VPD_KEYWORD_MAX] = {0}; - - std::vector l_mt_blobs(PORTS_PER_MCS, nullptr); - fapi2::VPDInfo l_vpd_info(fapi2::MemVpdData::MT); - - // For sanity. Not sure this will break us, but we're certainly making assumptions below. - static_assert(MAX_DIMM_PER_PORT == 2, "Max DIMM per port isn't 2"); - - // We need to set up all VPD info before calling getVPD, the API assumes this - // For MR we need to tell the VPDInfo the frequency (err ... mt/s - why is this mhz?) - l_vpd_info.iv_freq_mhz = iv_freq; - FAPI_INF("%s. VPD info - dimm data rate: %d MT/s", mss::c_str(i_target), l_vpd_info.iv_freq_mhz); - - // Make sure to create 0 filled blobs for all the possible blobs, not just for the - // chiplets which are configured. This prevents the decoder from accessing nullptrs - // but the code which uses the VPD will only access the information for the chiplets - // which exist - so the 0's are meaningless - for (auto& b : l_mt_blobs) - { - b = new uint8_t[mss::VPD_KEYWORD_MAX]; - memset(b, 0, mss::VPD_KEYWORD_MAX); - } - - // For MT we need to fill in the rank information - // But, of course, the rank information can differ per port. However, the vpd interface doesn't - // allow this in a straight-forward way. So, we have to get VPD blobs for MCS which contain - // ports which have the rank configuration in question. This means, basically, we pass a MCS MT - // blob to the decoder for each MCA, regardless of whether the port configurations are the same. - for (const auto& p : find_targets(i_target)) - { - // Find our blob in the vector of blob pointers - uint8_t* l_mt_blob = l_mt_blobs[mss::index(p)]; - uint64_t l_rank_count_dimm[MAX_DIMM_PER_PORT] = {0}; - - // If we don't have any DIMM, don't worry about it. This will just drop the blob full of 0's into our index. - // This will fill the VPD attributes with 0's which is perfectly ok. - for (const auto& d : mss::find_targets(p)) - { - uint8_t l_num_master_ranks = 0; - FAPI_TRY( mss::eff_num_master_ranks_per_dimm(d, l_num_master_ranks) ); - l_rank_count_dimm[mss::index(d)] = l_num_master_ranks; - } - - // This value will, of course, be 0 if there is no DIMM in the port. - l_vpd_info.iv_rank_count_dimm_0 = l_rank_count_dimm[0]; - l_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1]; - - FAPI_INF("%s. VPD info - rank count for dimm_0: %d, dimm_1: %d", - mss::c_str(i_target), l_vpd_info.iv_rank_count_dimm_0, l_vpd_info.iv_rank_count_dimm_1); - - // Get the MCS blob for this specific rank combination *only if* we have DIMM. Remember, - // Cronus can give us functional MCA which have no DIMM - and we'd puke getting the VPD. - if ((l_vpd_info.iv_rank_count_dimm_0 != 0) || (l_vpd_info.iv_rank_count_dimm_1 != 0)) - { - // If getVPD returns us an error, then we don't have VPD for the DIMM configuration. - // This is the root of our plug-rules: if you want a configuration of DIMM to be - // supported, it needs to have VPD defined. Likewise, if you don't want a configuration - // of DIMM supported be sure to leave it out of the VPD. Note that we don't return a specific - // plug-rule error as f/w (Dan) suggested this would duplicate errors leading to confusion. - l_vpd_info.iv_vpd_type = fapi2::MemVpdData::MT; - - // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), - "Failed to retrieve MT size from VPD"); - - if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) - { - FAPI_ERR("VPD MT keyword is too big for our array"); - fapi2::Assert(false); - } - - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_mt_blob[0])), - "Failed to retrieve MT VPD"); - } - }// mca - - // Only get the MR blob if we have a freq. It's possible for Cronus to give us an MCS which - // is connected to a controller which has 0 DIMM installed. In this case, we won't have - // a frequency, and thus we'd fail getting the VPD. So we initiaized the VPD to 0's and if - // there's no freq, we us a 0 filled VPD. - if (l_vpd_info.iv_freq_mhz != 0) - { - l_vpd_info.iv_vpd_type = fapi2::MemVpdData::MR; - - // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), - "Failed to retrieve MR size from VPD"); - - if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) - { - FAPI_ERR("VPD MR keyword is too big for our array"); - fapi2::Assert(false); - } - - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_mr_blob[0])), - "Failed to retrieve MR VPD"); - } - - // Until CK/DQ integration is working, we differentiate getting our fake_vpd for those ids. - // This gives us an extended API we can use for testing which won't be seen by HB because we'd use this to limit it -#ifndef __HOSTBOOT_MODULE - - // Get CKE data - l_vpd_info.iv_vpd_type = fapi2::MemVpdData::CK; - - // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), - "Failed to retrieve CK size from VPD"); - - if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) - { - FAPI_ERR("VPD CK keyword is too big for our array"); - fapi2::Assert(false); - } - - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_cke_blob[0])), - "Failed to retrieve DQ VPD"); - - // Get DQ data - l_vpd_info.iv_vpd_type = fapi2::MemVpdData::DQ; - - // Check the max for giggles. Programming bug so we should assert. - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, nullptr), - "Failed to retrieve DQ size from VPD"); - - if (l_vpd_info.iv_size > mss::VPD_KEYWORD_MAX) - { - FAPI_ERR("VPD DQ keyword is too big for our array"); - fapi2::Assert(false); - } - - FAPI_TRY( fapi2::getVPD(i_target, l_vpd_info, &(l_dq_blob[0])), - "Failed to retrieve DQ VPD"); - -#endif - - FAPI_TRY( mss::eff_decode(i_target, l_mt_blobs, l_mr_blob, l_cke_blob, l_dq_blob) ); - -fapi_try_exit: - - // delete the mt blobs - for (auto p : l_mt_blobs) - { - if (p != nullptr) - { - delete[] p; - } - } - - return fapi2::current_err; -} - -}// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H deleted file mode 100644 index 47128b68d11..00000000000 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H +++ /dev/null @@ -1,825 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/eff_config/eff_config.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ -/* [+] 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 eff_config.H -/// @brief Determine effective config for mss settings -/// -// *HWP HWP Owner: Andre Marin -// *HWP FW Owner: Brian Silver -// *HWP Team: Memory -// *HWP Level: 2 -// *HWP Consumed by: HB:FSP - -#ifndef _MSS_EFF_CONFIG_H_ -#define _MSS_EFF_CONFIG_H_ - -// std lib -#include - -// fapi2 -#include - -// mss lib -#include - -#include -#include -#include -#include -namespace mss -{ - -/// -/// @class eff_config -/// @brief Determine effective config for mss settings -/// -class eff_config -{ - public: - //TK - Make this constructor take this as param - AAM - std::shared_ptr iv_pDecoder; - int64_t iv_tCK_in_ps; - uint64_t iv_freq; - // Assists testing with write ability on these MRW - // settings that are normally NOT writable - // using attribute accessors - // Could create getters & setters... - uint8_t iv_refresh_mode; - uint8_t iv_temp_refresh_range; - - /// - /// @brief Constructor - /// @param[in] i_target the fapi2::Target which we're configuring (MCS) - /// @param[out] o_rc a return code which determines the success of the constructor - /// - eff_config( const fapi2::Target& i_target, fapi2::ReturnCode& o_rc ) - { - FAPI_TRY( clock_period(i_target, iv_tCK_in_ps), "Failed to calculate clock period (tCK)" ); - FAPI_TRY( mss::freq(find_target(i_target), iv_freq)); - FAPI_TRY( mss::mrw_temp_refresh_range(iv_temp_refresh_range), "Failed mrw_temp_refresh_range()" ); - FAPI_TRY( mss::mrw_fine_refresh_mode(iv_refresh_mode), "Failed mrw_fine_refresh_mode()" ); - - FAPI_INF( "Calculated clock period - tCK (ps): %d for %s", iv_tCK_in_ps, mss::c_str(i_target) ); - FAPI_INF("Calculated frequency: %d on DIMM %s", iv_freq, mss::c_str(i_target)); - - - fapi_try_exit: - o_rc = fapi2::current_err; - return; - } - - // - // @brief Destructor - // - ~eff_config() = default; - - //////////////////////// - // Methods - /////////////////////// - - /// - /// @brief Determines & sets effective config for DRAM generation from SPD - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_gen(const fapi2::Target& i_target, - const std::vector& i_spd_data); - - /// - /// @brief Determines & sets effective config for DIMM type - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_type(const fapi2::Target& i_target, - const std::vector& i_spd_data); - - /// - /// @brief Determines & sets effective config for eff_dram_mfg_id type from SPD - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_mfg_id(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for primary stack type - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode primary_stack_type(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for Hybrid memory type from SPD - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode hybrid_memory_type(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for refresh interval time (tREFI) - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trefi(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for refresh cycle time (tRFC) - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trfc(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for refresh cycle time (logical ranks) (tRFC_DLR) - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trfc_dlr(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for dram density - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_density(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for dram width - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_width(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for the RTT_NOM value from SPD - /// @tparam kind_t dimm_kind value - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// @note used for MRS01 - /// - template - fapi2::ReturnCode dram_rtt_nom(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for the RTT_NOM value from SPD - /// @tparam kind_t dimm_kind value - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// @note used for MRS02 - /// - template - fapi2::ReturnCode dram_rtt_wr(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for the RTT_PARK value from SPD - /// @tparam kind_t dimm_kind value - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// @note used for MRS05 - /// - template - fapi2::ReturnCode dram_rtt_park(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for dimm rcd mirror mode - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode rcd_mirror_mode(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for dimm size - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_size(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for dram bank bits - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_bank_bits(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for dram row bits - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_row_bits(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for number of ranks per dimm - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode ranks_per_dimm(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for number of master ranks per dimm - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode master_ranks_per_dimm(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tDQS - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_dqs_time(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tCCD_L - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_tccd_l(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC00 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc00(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC01 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc01(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC02 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc02(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC03 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc03(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC04 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc04(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC05 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc05(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC06_07 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc06_07(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC08 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc08(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC09 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc09(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC10 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc10(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC11 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc11(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC12 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc12(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC13 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc13(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC14 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc14(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC15 - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc15(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_1x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc1x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_2x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc2x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_3x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc3x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_4x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc4x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_5x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc5x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_6x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc6x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_7x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc7x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_8x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc8x(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DIMM RC_9x - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rc9x(const fapi2::Target& i_target); - - - /// - /// @brief Determines & sets effective config for DIMM RC_AX - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rcax(const fapi2::Target& i_target); - - - /// - /// @brief Determines & sets effective config for DIMM RC_BX - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dimm_rcbx(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tWR - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_twr(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for RBT - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode read_burst_type(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for TM - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_tm(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for cwl - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_cwl(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for lpasr - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_lpasr(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for additive latency - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode additive_latency(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DLL Reset - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dll_reset(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for DLL Enable - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dll_enable(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for Write Level Enable - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode write_level_enable(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for Output Buffer - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode output_buffer(const fapi2::Target& i_target); - - - /// - /// @brief Determines & sets effective config for Vref DQ Train Value - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode vref_dq_train_value(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for Vref DQ Train Enable - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode vref_dq_train_enable(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for Vref DQ Train Range - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode vref_dq_train_range(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for CA Parity Latency - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode ca_parity_latency(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for CA Parity - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode ca_parity(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for CRC Error Clear - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode crc_error_clear(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for CA Parity Error Status - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode ca_parity_error_status(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for ODT Input Buffer - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode odt_input_buffer(const fapi2::Target& i_target); - /// - /// @brief Determines & sets effective config for data_mask - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode data_mask(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for write_dbi - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode write_dbi(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for read_dbi - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode read_dbi(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for Post Package Repair - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode post_package_repair(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for rd_preamble_train - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode read_preamble_train(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for rd_preamble - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode read_preamble(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for wr_preamble - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode write_preamble(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for self_ref_abort - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode self_refresh_abort(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for cs_cmd_latency - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode cs_to_cmd_addr_latency(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for int_vref_mon - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode internal_vref_monitor(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for powerdown_mode - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode max_powerdown_mode(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for mpr_rd_format - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode mpr_read_format(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for CRC write latency - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode crc_wr_latency(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for temperature readout - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode temp_readout(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for per DRAM addressability - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode per_dram_addressability(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for geardown mode - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode geardown_mode(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for geardown mode - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode mpr_page(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for MPR mode - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode mpr_mode(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for write CRC - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode write_crc(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for ZQ Calibration - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode zqcal_interval(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for MEMCAL Calibration - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode memcal_interval(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRP - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trp(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRCD - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trcd(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRC - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trc(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tWTR_L - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_twtr_l(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tWTR_S - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_twtr_s(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRRD_S (tRRD_S_slr) - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trrd_s(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRRD_L (or tRRD_L_slr) - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trrd_l(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRRD_DLR - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trrd_dlr(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tFAW (or tFAW_slr) - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_tfaw(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tFAW_DLR - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_tfaw_dlr(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRAS - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_tras(const fapi2::Target& i_target); - - /// - /// @brief Determines & sets effective config for tRTP - /// @param[in] i_target FAPI2 target - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode dram_trtp(const fapi2::Target& i_target); - - /// - /// @brief Grab the VPD blobs and decode into attributes - /// @param[in] i_target FAPI2 target (MCS) - /// @return fapi2::FAPI2_RC_SUCCESS if okay - /// - fapi2::ReturnCode decode_vpd(const fapi2::Target& i_target); - - /// - /// @brief Enforce the plug-rules per MCS - /// @param[in] i_target FAPI2 target (MCS) - /// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code - /// - fapi2::ReturnCode enforce_plug_rules(const fapi2::Target& i_target); - - /// - /// @brief Enforce the plug-rules per MCA - /// @param[in] i_target FAPI2 target (MCA) - /// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code - /// - fapi2::ReturnCode enforce_plug_rules(const fapi2::Target& i_target); - -}; // eff_config - -} // mss -#endif // _MSS_EFF_CONFIG_H_ diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C index d0cecee5911..6f3e2f6feeb 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,9 +38,9 @@ #include #include -#include #include #include +#include using fapi2::TARGET_TYPE_MCA; using fapi2::TARGET_TYPE_MCS; @@ -358,7 +358,7 @@ fapi_try_exit: /// @param[in] i_target FAPI2 target (MCS) /// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code /// -fapi2::ReturnCode eff_config::enforce_plug_rules(const fapi2::Target& i_target) +fapi2::ReturnCode plug_rule::enforce_plug_rules(const fapi2::Target& i_target) { // Check per-MCS plug rules. If those all pass, check each of our MCA @@ -410,7 +410,7 @@ fapi_try_exit: /// @param[in] i_target FAPI2 target (MCA) /// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code /// -fapi2::ReturnCode eff_config::enforce_plug_rules(const fapi2::Target& i_target) +fapi2::ReturnCode plug_rule::enforce_plug_rules(const fapi2::Target& i_target) { const auto l_dimms = mss::find_targets(i_target); diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H index 928fdcf087a..7d0ad15d069 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,6 +46,21 @@ namespace mss namespace plug_rule { + +/// +/// @brief Enforce the plug-rules per MCS +/// @param[in] i_target FAPI2 target (MCS) +/// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code +/// +fapi2::ReturnCode enforce_plug_rules(const fapi2::Target& i_target); + +/// +/// @brief Enforce the plug-rules per MCA +/// @param[in] i_target FAPI2 target (MCA) +/// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code +/// +fapi2::ReturnCode enforce_plug_rules(const fapi2::Target& i_target); + /// /// @brief Helper to evaluate the unsupported rank config override attribute /// @param[in] i_dimm0_ranks count of the ranks on DIMM in slot 0 diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H index cd331558c85..d53ddb8efbe 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H @@ -20266,6 +20266,26 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief ATTR_MSS_MRW_DRAM_WRITE_CRC getter +/// @param[out] uint8_t& reference to store the value +/// @note Generated by gen_accessors.pl generateParameters (SYSTEM) +/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK +/// @note Enables DRAM Write +/// CRC +/// +inline fapi2::ReturnCode mrw_dram_write_crc(uint8_t& o_value) +{ + + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_DRAM_WRITE_CRC, fapi2::Target(), o_value) ); + return fapi2::current_err; + +fapi_try_exit: + FAPI_ERR("failed accessing ATTR_MSS_MRW_DRAM_WRITE_CRC: 0x%lx (system target)", + uint64_t(fapi2::current_err)); + return fapi2::current_err; +} + /// /// @brief ATTR_MSS_VPD_MR_0_VERSION_LAYOUT getter diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H index e8b5716e271..f5d8660ae99 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/common/dimm_module_decoder.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -143,7 +143,7 @@ class dimm_module_decoder } /// - /// @brief Decodes number of rows of DRAMs on RDIMM + /// @brief Decodes register and buffer type for LRDIMMs /// @param[out] o_output encoding from SPD /// @return FAPI2_RC_SUCCESS if okay /// @note SPD Byte 131 (Bits 7~4) 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 316d817b275..d49c277a982 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 @@ -44,14 +44,13 @@ // mss lib #include #include -#include #include #include #include #include #include - - +#include +#include /// /// @brief Configure the attributes for each controller /// @param[in] i_target the controller (e.g., MCS) @@ -63,10 +62,6 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target { fapi2::ReturnCode l_rc; std::map > l_factory_caches; - - mss::eff_config l_eff_config(i_target, l_rc); - FAPI_TRY(l_rc, "Unable to construct eff_config object for for %s", mss::c_str(i_target) ); - // Caches FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches) ); @@ -78,16 +73,15 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target { // Always set VPD attributes unless we enable the SPD_ONLY flag // Enables skipping VPD decoder when a valid VPD template isn't available - FAPI_TRY( l_eff_config.decode_vpd(i_target), + FAPI_TRY( mss::eff_dimm::decode_vpd(i_target), "Unable to decode VPD for %s", mss::c_str(i_target) ); } for( const auto& l_dimm : mss::find_targets(i_target) ) { + std::shared_ptr l_eff_dimm; + const auto l_dimm_pos = mss::pos(l_dimm); - uint8_t l_type = 0; - uint8_t l_gen = 0; - uint64_t l_kind = 0; // TODO RTC:152390 Create function to do map checking on cached values // Find decoder factory for this dimm position @@ -98,131 +92,119 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target l_dimm_pos), "Failed to get valid cache (main decoder)"); - l_eff_config.iv_pDecoder = l_it->second; - - // DRAM Gen and DIMM type not needed here since set in spd_factory... - // but it doesn't hurt to do it twice - FAPI_TRY( l_eff_config.dimm_type(l_dimm, l_it->second->iv_spd_data) ); - FAPI_TRY( l_eff_config.dram_gen(l_dimm, l_it->second->iv_spd_data) ); - - FAPI_TRY( l_eff_config.dram_mfg_id(l_dimm) ); - FAPI_TRY( l_eff_config.dram_width(l_dimm) ); - FAPI_TRY( l_eff_config.dram_density(l_dimm) ); - FAPI_TRY( l_eff_config.ranks_per_dimm(l_dimm) ); - FAPI_TRY( l_eff_config.primary_stack_type(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_size(l_dimm) ); - FAPI_TRY( l_eff_config.hybrid_memory_type(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trefi(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trfc(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trfc_dlr(l_dimm) ); - FAPI_TRY( l_eff_config.rcd_mirror_mode(l_dimm) ); - FAPI_TRY( l_eff_config.dram_bank_bits(l_dimm) ); - FAPI_TRY( l_eff_config.dram_row_bits(l_dimm) ); - FAPI_TRY( l_eff_config.dram_dqs_time(l_dimm) ); - FAPI_TRY( l_eff_config.dram_tccd_l(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc00(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc01(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc02(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc03(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc04(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc05(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc06_07(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc08(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc09(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc10(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc11(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc12(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc13(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc14(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc15(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc1x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc2x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc3x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc4x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc5x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc6x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc7x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc8x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rc9x(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rcax(l_dimm) ); - FAPI_TRY( l_eff_config.dimm_rcbx(l_dimm) ); - FAPI_TRY( l_eff_config.dram_twr(l_dimm) ); - FAPI_TRY( l_eff_config.read_burst_type(l_dimm) ); - FAPI_TRY( l_eff_config.dram_tm(l_dimm) ); - FAPI_TRY( l_eff_config.dram_cwl(l_dimm) ); - FAPI_TRY( l_eff_config.dram_lpasr(l_dimm) ); - FAPI_TRY( l_eff_config.dll_enable(l_dimm) ); - FAPI_TRY( l_eff_config.dll_reset(l_dimm) ); - FAPI_TRY( l_eff_config.write_level_enable(l_dimm) ); - FAPI_TRY( l_eff_config.output_buffer(l_dimm) ); - FAPI_TRY( l_eff_config.vref_dq_train_value(l_dimm) ); - FAPI_TRY( l_eff_config.vref_dq_train_range(l_dimm) ); - FAPI_TRY( l_eff_config.vref_dq_train_enable(l_dimm) ); - FAPI_TRY( l_eff_config.ca_parity_latency(l_dimm) ); - FAPI_TRY( l_eff_config.ca_parity_error_status(l_dimm) ); - FAPI_TRY( l_eff_config.ca_parity(l_dimm) ); - FAPI_TRY( l_eff_config.crc_error_clear(l_dimm) ); - FAPI_TRY( l_eff_config.odt_input_buffer(l_dimm) ); - FAPI_TRY( l_eff_config.post_package_repair(l_dimm) ); - FAPI_TRY( l_eff_config.read_preamble_train(l_dimm) ); - FAPI_TRY( l_eff_config.read_preamble(l_dimm) ); - FAPI_TRY( l_eff_config.write_preamble(l_dimm) ); - FAPI_TRY( l_eff_config.self_refresh_abort(l_dimm) ); - FAPI_TRY( l_eff_config.cs_to_cmd_addr_latency(l_dimm) ); - FAPI_TRY( l_eff_config.internal_vref_monitor(l_dimm) ); - FAPI_TRY( l_eff_config.max_powerdown_mode(l_dimm) ); - FAPI_TRY( l_eff_config.mpr_read_format(l_dimm) ); - FAPI_TRY( l_eff_config.temp_readout(l_dimm) ); - FAPI_TRY( l_eff_config.crc_wr_latency(l_dimm) ); - FAPI_TRY( l_eff_config.per_dram_addressability(l_dimm) ); - FAPI_TRY( l_eff_config.geardown_mode(l_dimm) ); - FAPI_TRY( l_eff_config.mpr_page(l_dimm) ); - FAPI_TRY( l_eff_config.mpr_mode(l_dimm) ); - FAPI_TRY( l_eff_config.write_crc(l_dimm) ); - FAPI_TRY( l_eff_config.zqcal_interval(l_dimm) ); - FAPI_TRY( l_eff_config.memcal_interval(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trp(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trcd(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trc(l_dimm) ); - FAPI_TRY( l_eff_config.dram_twtr_l(l_dimm) ); - FAPI_TRY( l_eff_config.dram_twtr_s(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trrd_s(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trrd_l(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trrd_dlr(l_dimm) ); - FAPI_TRY( l_eff_config.dram_tfaw(l_dimm) ); - FAPI_TRY( l_eff_config.dram_tfaw_dlr(l_dimm) ); - FAPI_TRY( l_eff_config.dram_tras(l_dimm) ); - FAPI_TRY( l_eff_config.dram_trtp(l_dimm) ); - FAPI_TRY( l_eff_config.read_dbi(l_dimm) ); - FAPI_TRY( l_eff_config.write_dbi(l_dimm) ); - FAPI_TRY( l_eff_config.additive_latency(l_dimm) ); - FAPI_TRY( l_eff_config.data_mask(l_dimm) ); - - FAPI_TRY( mss::eff_dram_gen(l_dimm, l_gen) ); - FAPI_TRY( mss::eff_dimm_type(l_dimm, l_type) ); - l_kind = mss::dimm_kind (l_type, l_gen); - - //One day we won't need this switch case, we can just specialize the methods via passed in target type - //Till then, we have a story - //TODO RTC: 166453 - switch (l_kind) - { - case mss::KIND_LRDIMM_DDR4: - FAPI_TRY( l_eff_config.dram_rtt_nom(l_dimm) ); - FAPI_TRY( l_eff_config.dram_rtt_wr(l_dimm) ); - FAPI_TRY( l_eff_config.dram_rtt_park(l_dimm) ); - break; - - case mss::KIND_RDIMM_DDR4: - FAPI_TRY( l_eff_config.dram_rtt_nom(l_dimm) ); - FAPI_TRY( l_eff_config.dram_rtt_wr(l_dimm) ); - FAPI_TRY( l_eff_config.dram_rtt_park(l_dimm) ); - break; - - default: - FAPI_ERR("Invalid DIMM type and or gen"); - return fapi2::FAPI2_RC_INVALID_PARAMETER; - }; + FAPI_TRY( mss::eff_dimm::eff_dimm_factory( l_dimm, l_it->second, l_eff_dimm)); + + FAPI_TRY( l_eff_dimm->dram_mfg_id() ); + FAPI_TRY( l_eff_dimm->dram_width() ); + FAPI_TRY( l_eff_dimm->dram_density() ); + FAPI_TRY( l_eff_dimm->ranks_per_dimm() ); + FAPI_TRY( l_eff_dimm->primary_stack_type() ); + FAPI_TRY( l_eff_dimm->dimm_size() ); + FAPI_TRY( l_eff_dimm->hybrid_memory_type() ); + FAPI_TRY( l_eff_dimm->temp_refresh_mode() ); + FAPI_TRY( l_eff_dimm->dram_trefi() ); + FAPI_TRY( l_eff_dimm->dram_trfc() ); + FAPI_TRY( l_eff_dimm->dram_trfc_dlr() ); + FAPI_TRY( l_eff_dimm->rcd_mirror_mode() ); + FAPI_TRY( l_eff_dimm->dram_bank_bits() ); + FAPI_TRY( l_eff_dimm->dram_row_bits() ); + FAPI_TRY( l_eff_dimm->dram_dqs_time() ); + FAPI_TRY( l_eff_dimm->dram_tccd_l() ); + FAPI_TRY( l_eff_dimm->dimm_rc00() ); + FAPI_TRY( l_eff_dimm->dimm_rc01() ); + FAPI_TRY( l_eff_dimm->dimm_rc02() ); + FAPI_TRY( l_eff_dimm->dimm_rc03() ); + FAPI_TRY( l_eff_dimm->dimm_rc04() ); + FAPI_TRY( l_eff_dimm->dimm_rc05() ); + FAPI_TRY( l_eff_dimm->dimm_rc06_07() ); + FAPI_TRY( l_eff_dimm->dimm_rc08() ); + FAPI_TRY( l_eff_dimm->dimm_rc09() ); + FAPI_TRY( l_eff_dimm->dimm_rc10() ); + FAPI_TRY( l_eff_dimm->dimm_rc11() ); + FAPI_TRY( l_eff_dimm->dimm_rc12() ); + FAPI_TRY( l_eff_dimm->dimm_rc13() ); + FAPI_TRY( l_eff_dimm->dimm_rc14() ); + FAPI_TRY( l_eff_dimm->dimm_rc15() ); + FAPI_TRY( l_eff_dimm->dimm_rc1x() ); + FAPI_TRY( l_eff_dimm->dimm_rc2x() ); + FAPI_TRY( l_eff_dimm->dimm_rc3x() ); + FAPI_TRY( l_eff_dimm->dimm_rc4x() ); + FAPI_TRY( l_eff_dimm->dimm_rc5x() ); + FAPI_TRY( l_eff_dimm->dimm_rc6x() ); + FAPI_TRY( l_eff_dimm->dimm_rc7x() ); + FAPI_TRY( l_eff_dimm->dimm_rc8x() ); + FAPI_TRY( l_eff_dimm->dimm_rc9x() ); + FAPI_TRY( l_eff_dimm->dimm_rcax() ); + FAPI_TRY( l_eff_dimm->dimm_rcbx() ); + FAPI_TRY( l_eff_dimm->dram_twr() ); + FAPI_TRY( l_eff_dimm->read_burst_type() ); + FAPI_TRY( l_eff_dimm->dram_tm() ); + FAPI_TRY( l_eff_dimm->dram_cwl() ); + FAPI_TRY( l_eff_dimm->dram_lpasr() ); + FAPI_TRY( l_eff_dimm->dll_enable() ); + FAPI_TRY( l_eff_dimm->dll_reset() ); + FAPI_TRY( l_eff_dimm->write_level_enable() ); + FAPI_TRY( l_eff_dimm->output_buffer() ); + FAPI_TRY( l_eff_dimm->vref_dq_train_value() ); + FAPI_TRY( l_eff_dimm->vref_dq_train_range() ); + FAPI_TRY( l_eff_dimm->vref_dq_train_enable() ); + FAPI_TRY( l_eff_dimm->ca_parity_latency() ); + FAPI_TRY( l_eff_dimm->ca_parity_error_status() ); + FAPI_TRY( l_eff_dimm->ca_parity() ); + FAPI_TRY( l_eff_dimm->crc_error_clear() ); + FAPI_TRY( l_eff_dimm->odt_input_buffer() ); + FAPI_TRY( l_eff_dimm->post_package_repair() ); + FAPI_TRY( l_eff_dimm->read_preamble_train() ); + FAPI_TRY( l_eff_dimm->read_preamble() ); + FAPI_TRY( l_eff_dimm->write_preamble() ); + FAPI_TRY( l_eff_dimm->self_refresh_abort() ); + FAPI_TRY( l_eff_dimm->cs_to_cmd_addr_latency() ); + FAPI_TRY( l_eff_dimm->internal_vref_monitor() ); + FAPI_TRY( l_eff_dimm->max_powerdown_mode() ); + FAPI_TRY( l_eff_dimm->mpr_read_format() ); + FAPI_TRY( l_eff_dimm->temp_readout() ); + FAPI_TRY( l_eff_dimm->crc_wr_latency() ); + FAPI_TRY( l_eff_dimm->per_dram_addressability() ); + FAPI_TRY( l_eff_dimm->geardown_mode() ); + FAPI_TRY( l_eff_dimm->mpr_page() ); + FAPI_TRY( l_eff_dimm->mpr_mode() ); + FAPI_TRY( l_eff_dimm->write_crc() ); + FAPI_TRY( l_eff_dimm->zqcal_interval() ); + FAPI_TRY( l_eff_dimm->memcal_interval() ); + FAPI_TRY( l_eff_dimm->dram_trp() ); + FAPI_TRY( l_eff_dimm->dram_trcd() ); + FAPI_TRY( l_eff_dimm->dram_trc() ); + FAPI_TRY( l_eff_dimm->dram_twtr_l() ); + FAPI_TRY( l_eff_dimm->dram_twtr_s() ); + FAPI_TRY( l_eff_dimm->dram_trrd_s() ); + FAPI_TRY( l_eff_dimm->dram_trrd_l() ); + FAPI_TRY( l_eff_dimm->dram_trrd_dlr() ); + FAPI_TRY( l_eff_dimm->dram_tfaw() ); + FAPI_TRY( l_eff_dimm->dram_tfaw_dlr() ); + FAPI_TRY( l_eff_dimm->dram_tras() ); + FAPI_TRY( l_eff_dimm->dram_trtp() ); + FAPI_TRY( l_eff_dimm->read_dbi() ); + FAPI_TRY( l_eff_dimm->write_dbi() ); + FAPI_TRY( l_eff_dimm->additive_latency() ); + FAPI_TRY( l_eff_dimm->data_mask() ); + FAPI_TRY( l_eff_dimm->dimm_bc00()); + FAPI_TRY( l_eff_dimm->dimm_bc01()); + FAPI_TRY( l_eff_dimm->dimm_bc02()); + FAPI_TRY( l_eff_dimm->dimm_bc03()); + FAPI_TRY( l_eff_dimm->dimm_bc04()); + FAPI_TRY( l_eff_dimm->dimm_bc05()); + FAPI_TRY( l_eff_dimm->dimm_bc07()); + FAPI_TRY( l_eff_dimm->dimm_bc08()); + FAPI_TRY( l_eff_dimm->dimm_bc09()); + FAPI_TRY( l_eff_dimm->dimm_bc0a()); + FAPI_TRY( l_eff_dimm->dimm_bc0b()); + FAPI_TRY( l_eff_dimm->dimm_bc0c()); + FAPI_TRY( l_eff_dimm->dimm_bc0d()); + FAPI_TRY( l_eff_dimm->dimm_bc0e()); + FAPI_TRY( l_eff_dimm->dimm_bc0f()); + FAPI_TRY( l_eff_dimm->dram_rtt_nom () ); + FAPI_TRY( l_eff_dimm->dram_rtt_wr () ); + FAPI_TRY( l_eff_dimm->dram_rtt_park() ); }// dimm // TODO RTC:160060 Clean up hard coded values at bottom of eff_config @@ -233,15 +215,8 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_CAL_STEP_ENABLE, i_target, l_cal_step) ); } - { - // TODO RTC:162080 Logically link ATTR_MSS_MRW_TEMP_REFRESH_RANGE and MODE - uint8_t l_temp_refresh_mode[mss::PORTS_PER_MCS] = - {fapi2::ENUM_ATTR_EFF_TEMP_REFRESH_MODE_DISABLE, fapi2::ENUM_ATTR_EFF_TEMP_REFRESH_MODE_DISABLE}; - FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_EFF_TEMP_REFRESH_MODE, i_target, l_temp_refresh_mode ) ); - } - // Check plug rules. We check the MCS, and this will iterate down to children as needed. - FAPI_TRY( l_eff_config.enforce_plug_rules(i_target) ); + FAPI_TRY( mss::plug_rule::enforce_plug_rules(i_target) ); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml index 7f1619a9fff..ed50f6d0c7e 100755 --- a/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_mrw_attributes.xml @@ -5,7 +5,7 @@ - + @@ -598,4 +598,15 @@ mrw_unsupported_rank_config + + ATTR_MSS_MRW_DRAM_WRITE_CRC + TARGET_TYPE_SYSTEM + Enables DRAM Write CRC + uint8 + + DISABLE = 0, ENABLE = 1 + 0 + mrw_dram_write_crc + + diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_mt_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_mt_attributes.xml index bfa10c00397..49cc606e9a2 100644 --- a/src/import/chips/p9/procedures/xml/attribute_info/memory_mt_attributes.xml +++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_mt_attributes.xml @@ -145,7 +145,7 @@ uint8 - OHM34 = 34, OHM48 = 48 + OHM30 = 30, OHM34 = 34, OHM40 = 40, OHM48 = 48 ohm 22 16 diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml index 07def393145..51d7a8e8c55 100644 --- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml @@ -5,7 +5,7 @@ - + @@ -239,5 +239,89 @@ + + RC_MSS_INVALID_LRDIMM_DB + + Error with the LRDIMM databuffer type + + DATA_BUFFER_GEN + + DIMM_TARGET + HIGH + + + DIMM_TARGET + + + + + RC_MSS_UNSUPPORTED_DIMM_KIND + + DIMM plugged in is not supported + + DIMM_KIND + DIMM_TYPE + DRAM_GEN + + DIMM_TARGET + HIGH + + + DIMM_TARGET + + + + + RC_MSS_INVALID_RTT_WR + + An invalid encoding recieved from VPD for RTT_WR/dynamic ODT value + + RTT_WR + RANK + + DIMM_TARGET + HIGH + + + DIMM_TARGET + + + + + RC_MSS_INVALID_FREQ + + An invalid Freq value has been set + + FREQ + + DIMM_TARGET + HIGH + + + DIMM_TARGET + + + + + RC_MSS_ERROR_CREATING_EFF_CONFIG_DIMM_OBJECT + + Failed to create a dimm object, probably due to bad attribute settings + + DIMM_TYPE + DRAM_GEN + REG_AND_BUFF_TYPE + + DIMM_TARGET + HIGH + + + DIMM_TARGET + + + + + + + diff --git a/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml b/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml index 96d33905aa0..e785c6de4a7 100644 --- a/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml +++ b/src/import/hwpf/fapi2/xml/attribute_info/hb_temp_defaults.xml @@ -247,7 +247,10 @@ ATTR_MAX_SBE_SEEPROM_SIZE 0x40000 - + + ATTR_MSS_MRW_DRAM_WRITE_CRC + 0x0 + diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index c1f9a7a101f..c2d135f819e 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -32735,4 +32735,22 @@ Measured in GB + + MSS_MRW_DRAM_WRITE_CRC + + Enables DRAM Write CRC + + + + + + volatile-zeroed + + + ATTR_MSS_MRW_DRAM_WRITE_CRC + DIRECT + + + + diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index 5dc34fccc19..d16b87f7965 100755 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -900,6 +900,7 @@ MSS_MEM_PORT_POS_OF_FAIL_THROTTLE SYSTEM_RING_DBG_MODE NEST_LEAKAGE_PERCENT + MSS_MRW_DRAM_WRITE_CRC